1 use std::fmt; 2 3 use webcore::value::Reference; 4 use webcore::try_from::TryInto; 5 use webapi::event::{ConcreteEvent, IEvent}; 6 7 pub struct EventListenerHandle { 8 event_type: &'static str, 9 reference: Reference, 10 listener_reference: Reference 11 } 12 13 impl fmt::Debug for EventListenerHandle { fmt( &self, formatter: &mut fmt::Formatter ) -> fmt::Result14 fn fmt( &self, formatter: &mut fmt::Formatter ) -> fmt::Result { 15 write!( formatter, "EventListenerHandle {{ event_type: {}, reference: {:?} }}", self.event_type, self.reference ) 16 } 17 } 18 19 impl EventListenerHandle { 20 /// Removes the handler from the [IEventTarget](trait.IEventTarget.html) on 21 /// which it was previously registered. 22 /// 23 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener) remove( self )24 pub fn remove( self ) { 25 js! { @(no_return) 26 var self = @{self.reference}; 27 var event_type = @{self.event_type}; 28 var listener = @{self.listener_reference}; 29 listener.drop(); 30 self.removeEventListener( event_type, listener ); 31 } 32 } 33 } 34 35 /// `IEventTarget` is an interface implemented by objects that 36 /// can receive events and may have listeners for them. 37 /// 38 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) 39 pub trait IEventTarget: AsRef< Reference > { 40 /// Adds given event handler to the list the list of event listeners for 41 /// the specified `EventTarget` on which it's called. 42 /// 43 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) add_event_listener< T, F >( &self, listener: F ) -> EventListenerHandle where T: ConcreteEvent, F: FnMut( T ) + 'static44 fn add_event_listener< T, F >( &self, listener: F ) -> EventListenerHandle 45 where T: ConcreteEvent, F: FnMut( T ) + 'static 46 { 47 let reference = self.as_ref(); 48 let listener_reference = js! { 49 var listener = @{listener}; 50 @{reference}.addEventListener( @{T::EVENT_TYPE}, listener ); 51 return listener; 52 }.try_into().unwrap(); 53 54 EventListenerHandle { 55 event_type: T::EVENT_TYPE, 56 reference: reference.clone(), 57 listener_reference: listener_reference 58 } 59 } 60 61 /// Dispatches an `Event` at this `EventTarget`, invoking the affected event listeners in the 62 /// appropriate order. 63 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent) dispatch_event< T: IEvent >( &self, event: &T ) -> bool64 fn dispatch_event< T: IEvent >( &self, event: &T ) -> bool { 65 js! ( 66 return @{self.as_ref()}.dispatchEvent( @{event.as_ref()} ); 67 ).try_into().unwrap() 68 } 69 } 70 71 /// A reference to a JavaScript object which implements the [IEventTarget](trait.IEventTarget.html) 72 /// interface. 73 /// 74 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) 75 pub struct EventTarget( Reference ); 76 77 impl IEventTarget for EventTarget {} 78 79 reference_boilerplate! { 80 EventTarget, 81 instanceof EventTarget 82 } 83