stdweb/webapi/event.rs
1use webcore::value::Reference;
2use webcore::try_from::TryInto;
3use webcore::reference_type::ReferenceType;
4use webapi::event_target::EventTarget;
5use webapi::window::Window;
6
7/// The `IEvent` interface represents any event which takes place in the DOM; some
8/// are user-generated (such as mouse or keyboard events), while others are
9/// generated by APIs (such as events that indicate an animation has finished
10/// running, a video has been paused, and so forth). There are many types of event,
11/// some of which useĀ other interfaces based on the main `IEvent` interface. `IEvent`
12/// itself contains the properties and methods which are common to all events.
13///
14/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event)
15// https://dom.spec.whatwg.org/#event
16pub trait IEvent: ReferenceType {
17 /// Indicates whether this event bubbles upward through the DOM.
18 ///
19 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event)
20 // https://dom.spec.whatwg.org/#ref-for-dom-event-bubbles%E2%91%A0
21 #[inline]
22 fn bubbles( &self ) -> bool {
23 js!(
24 return @{self.as_ref()}.bubbles;
25 ).try_into().unwrap()
26 }
27
28 /// A historical alias to `Event.stopPropagation()`.
29 ///
30 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/cancelBubble)
31 // https://dom.spec.whatwg.org/#ref-for-dom-event-cancelbubble
32 #[inline]
33 fn cancel_bubble( &self ) -> bool {
34 js!(
35 return @{self.as_ref()}.cancelBubble;
36 ).try_into().unwrap()
37 }
38
39 /// A historical alias to `Event.stopPropagation()`.
40 /// Setting this to `true` before returning from an event handler will stop propagation
41 /// of the event.
42 ///
43 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/cancelBubble)
44 // https://dom.spec.whatwg.org/#ref-for-dom-event-cancelbubble
45 #[inline]
46 fn set_cancel_bubble( &self, value: bool ) {
47 js! { @(no_return)
48 @{self.as_ref()}.cancelBubble = @{value};
49 }
50 }
51
52 /// Indicates whether the event is cancelable.
53 ///
54 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/cancelable)
55 // https://dom.spec.whatwg.org/#ref-for-dom-event-cancelable
56 #[inline]
57 fn cancelable( &self ) -> bool {
58 js!(
59 return @{self.as_ref()}.cancelable;
60 ).try_into().unwrap()
61 }
62
63 /// A reference to the currently registered target of this event.
64 ///
65 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget)
66 // https://dom.spec.whatwg.org/#ref-for-dom-event-currenttarget%E2%91%A0
67 #[inline]
68 fn current_target( &self ) -> Option< EventTarget > {
69 js!(
70 return @{self.as_ref()}.currentTarget;
71 ).try_into().ok()
72 }
73
74 /// Indicates whether `preventDefault` has been called on this event.
75 ///
76 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/defaultPrevented)
77 // https://dom.spec.whatwg.org/#ref-for-dom-event-defaultprevented
78 #[inline]
79 fn default_prevented( &self ) -> bool {
80 js!(
81 return @{self.as_ref()}.defaultPrevented;
82 ).try_into().unwrap()
83 }
84
85 /// Indicates which phase of event flow is currently being evaluated.
86 ///
87 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/eventPhase)
88 // https://dom.spec.whatwg.org/#ref-for-dom-event-eventphase%E2%91%A1
89 fn event_phase( &self ) -> EventPhase {
90 match js!(
91 return @{self.as_ref()}.eventPhase;
92 ).try_into().unwrap() {
93 0 => EventPhase::None,
94 1 => EventPhase::Capturing,
95 2 => EventPhase::AtTarget,
96 3 => EventPhase::Bubbling,
97 _ => unreachable!("Unexpected EventPhase type"),
98 }
99 }
100
101 /// Prevents any further listeners from being called for this event.
102 ///
103 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/stopImmediatePropagation)
104 #[inline]
105 fn stop_immediate_propagation( &self ) {
106 js! { @(no_return)
107 @{self.as_ref()}.stopImmediatePropagation();
108 }
109 }
110
111 /// Stops the propagation of this event to descendants in the DOM.
112 ///
113 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation)
114 // https://dom.spec.whatwg.org/#ref-for-dom-event-stopimmediatepropagation
115 #[inline]
116 fn stop_propagation( &self ) {
117 js! { @(no_return)
118 @{self.as_ref()}.stopPropagation();
119 }
120 }
121
122
123 /// Returns a reference to the target to which this event was originally registered.
124 ///
125 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/target)
126 // https://dom.spec.whatwg.org/#ref-for-dom-event-target%E2%91%A1
127 #[inline]
128 fn target( &self ) -> Option< EventTarget > {
129 js!(
130 return @{self.as_ref()}.target;
131 ).try_into().ok()
132 }
133
134 /// Returns the time in milliseconds at which this event was created.
135 ///
136 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/timeStamp)
137 // https://dom.spec.whatwg.org/#ref-for-dom-event-timestamp
138 #[inline]
139 fn time_stamp( &self ) -> Option< f64 > {
140 js!(
141 return @{self.as_ref()}.timeStamp;
142 ).try_into().ok()
143 }
144
145 /// Indicates whether the event was generated by a user action.
146 // https://dom.spec.whatwg.org/#ref-for-dom-event-istrusted
147 #[inline]
148 fn is_trusted( &self ) -> bool {
149 js!(
150 return @{self.as_ref()}.isTrusted;
151 ).try_into().unwrap()
152 }
153
154 /// ReturnsĀ a string containing the type of event. It is set when
155 /// the event is constructed and is the name commonly used to refer
156 /// to the specific event.
157 ///
158 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/type)
159 // https://dom.spec.whatwg.org/#ref-for-dom-event-type%E2%91%A1
160 #[inline]
161 fn event_type( &self ) -> String {
162 js!(
163 return @{self.as_ref()}.type;
164 ).try_into().unwrap()
165 }
166
167 /// Cancels the event if it is cancelable, without
168 /// stopping further propagation of the event.
169 ///
170 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault)
171 // https://dom.spec.whatwg.org/#ref-for-dom-event-preventdefault%E2%91%A0
172 #[inline]
173 fn prevent_default( &self ) {
174 js! { @(no_return)
175 @{self.as_ref()}.preventDefault();
176 }
177 }
178}
179
180/// Indicates the phase of event flow during event proessing.
181// https://dom.spec.whatwg.org/#dom-event-eventphase
182#[derive(Clone, Copy, Debug, Eq, PartialEq)]
183pub enum EventPhase {
184 /// No event is currently being processed.
185 None,
186 /// The event is being propagated down through the target's ancestors.
187 Capturing,
188 /// The target is currently processing the event.
189 AtTarget,
190 /// The event is propagating back up through the target's ancestors.
191 Bubbling,
192}
193
194/// A trait representing a concrete event type.
195pub trait ConcreteEvent: IEvent {
196 /// A string representing the event type.
197 ///
198 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event/type)
199 const EVENT_TYPE: &'static str;
200}
201
202/// A reference to a JavaScript object which implements the [IEvent](trait.IEvent.html)
203/// interface.
204///
205/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Event)
206// https://dom.spec.whatwg.org/#event
207#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
208#[reference(instance_of = "Event")]
209pub struct Event( Reference );
210
211impl IEvent for Event {}
212
213/// The `BeforeUnload` event fires when the window is about to be unloaded (to close the page or
214/// follow a link). If the event propagation is cancelled, the browser will present the user with
215/// a confirmation dialog allowing them to stay on the page or continue.
216///
217/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event)
218// https://html.spec.whatwg.org/multipage/indices.html#event-beforeunload
219#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
220#[reference(instance_of = "BeforeUnloadEvent")]
221#[reference(event = "beforeunload")]
222pub struct BeforeUnloadEvent( Reference );
223
224impl IEvent for BeforeUnloadEvent {}
225
226
227/// The `Unload` event fires when the window has been unloaded and is no longer visible. This event
228/// can't be cancelled.
229///
230/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event)
231// https://html.spec.whatwg.org/multipage/indices.html#event-unload
232#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
233#[reference(instance_of = "UnloadEvent")]
234#[reference(event = "unload")]
235pub struct UnloadEvent( Reference );
236
237impl IEvent for UnloadEvent {}
238
239/// The 'FullscreenChange' event fires when an element enters or exits fullscreen
240///
241/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Document/fullscreenchange_event)
242// https://fullscreen.spec.whatwg.org/#handler-document-onfullscreenchange
243#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
244#[reference(instance_of = "Event")]
245#[reference(event = "fullscreenchange")]
246pub struct FullscreenChangeEvent( Reference );
247
248impl IEvent for FullscreenChangeEvent {}
249
250/// The `IUiEvent` interface represents simple user interface events.
251///
252/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent)
253// https://w3c.github.io/uievents/#uievent
254pub trait IUiEvent: IEvent {
255 /// Provides the current click count for this event, if applicable.
256 ///
257 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail)
258 // https://w3c.github.io/uievents/#dom-uievent-detail
259 #[inline]
260 fn detail( &self ) -> i32 {
261 js!(
262 return @{self.as_ref()}.detail;
263 ).try_into().unwrap()
264 }
265
266 /// Returns the `WindowProxy` that generated the event.
267 ///
268 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/view)
269 // https://w3c.github.io/uievents/#dom-uievent-view
270 #[inline]
271 fn view( &self ) -> Option< Window > {
272 js!(
273 return @{self.as_ref()}.view;
274 ).try_into().ok()
275 }
276}
277
278/// A reference to a JavaScript object which implements the [IUiEvent](trait.IUiEvent.html)
279/// interface.
280///
281/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent)
282// https://w3c.github.io/uievents/#uievent
283#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
284#[reference(instance_of = "UIEvent")]
285#[reference(subclass_of(Event))]
286pub struct UiEvent( Reference );
287
288impl IEvent for UiEvent {}
289impl IUiEvent for UiEvent {}
290
291#[cfg(all(test, feature = "web_test"))]
292mod tests {
293 use super::*;
294
295 #[test]
296 fn test_event() {
297 let event: Event = js!(
298 return new Event("dummy")
299 ).try_into().unwrap();
300
301 assert_eq!( event.event_type(), "dummy" );
302 assert_eq!( event.bubbles(), false );
303 assert!( !event.cancel_bubble() );
304 assert!( !event.cancelable(), false );
305 assert!( event.current_target().is_none() );
306 assert!( !event.default_prevented() );
307 assert_eq!( event.event_phase(), EventPhase::None );
308 assert!( event.target().is_none() );
309 assert!( event.time_stamp().is_some() );
310 assert!( !event.is_trusted() );
311
312 event.stop_immediate_propagation();
313 event.stop_propagation();
314 }
315
316 #[test]
317 fn test_ui_event() {
318 use webapi::events::mouse::ClickEvent;
319
320 let event: UiEvent = js!(
321 return new UIEvent(
322 @{ClickEvent::EVENT_TYPE},
323 {
324 detail: 1,
325 }
326 )
327 ).try_into().unwrap();
328 assert_eq!( event.event_type(), ClickEvent::EVENT_TYPE );
329 assert_eq!( event.detail(), 1 );
330 assert!( event.view().is_none() );
331 }
332}