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}