use webcore::value::Reference;
use webcore::try_from::TryInto;
use webcore::reference_type::ReferenceType;
use webapi::event_target::EventTarget;
use webapi::window::Window;
pub trait IEvent: ReferenceType {
#[inline]
fn bubbles( &self ) -> bool {
js!(
return @{self.as_ref()}.bubbles;
).try_into().unwrap()
}
#[inline]
fn cancel_bubble( &self ) -> bool {
js!(
return @{self.as_ref()}.cancelBubble;
).try_into().unwrap()
}
#[inline]
fn set_cancel_bubble( &self, value: bool ) {
js! { @(no_return)
@{self.as_ref()}.cancelBubble = @{value};
}
}
#[inline]
fn cancelable( &self ) -> bool {
js!(
return @{self.as_ref()}.cancelable;
).try_into().unwrap()
}
#[inline]
fn current_target( &self ) -> Option< EventTarget > {
js!(
return @{self.as_ref()}.currentTarget;
).try_into().ok()
}
#[inline]
fn default_prevented( &self ) -> bool {
js!(
return @{self.as_ref()}.defaultPrevented;
).try_into().unwrap()
}
fn event_phase( &self ) -> EventPhase {
match js!(
return @{self.as_ref()}.eventPhase;
).try_into().unwrap() {
0 => EventPhase::None,
1 => EventPhase::Capturing,
2 => EventPhase::AtTarget,
3 => EventPhase::Bubbling,
_ => unreachable!("Unexpected EventPhase type"),
}
}
#[inline]
fn stop_immediate_propagation( &self ) {
js! { @(no_return)
@{self.as_ref()}.stopImmediatePropagation();
}
}
#[inline]
fn stop_propagation( &self ) {
js! { @(no_return)
@{self.as_ref()}.stopPropagation();
}
}
#[inline]
fn target( &self ) -> Option< EventTarget > {
js!(
return @{self.as_ref()}.target;
).try_into().ok()
}
#[inline]
fn time_stamp( &self ) -> Option< f64 > {
js!(
return @{self.as_ref()}.timeStamp;
).try_into().ok()
}
#[inline]
fn is_trusted( &self ) -> bool {
js!(
return @{self.as_ref()}.isTrusted;
).try_into().unwrap()
}
#[inline]
fn event_type( &self ) -> String {
js!(
return @{self.as_ref()}.type;
).try_into().unwrap()
}
#[inline]
fn prevent_default( &self ) {
js! { @(no_return)
@{self.as_ref()}.preventDefault();
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum EventPhase {
None,
Capturing,
AtTarget,
Bubbling,
}
pub trait ConcreteEvent: IEvent {
const EVENT_TYPE: &'static str;
}
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "Event")]
pub struct Event( Reference );
impl IEvent for Event {}
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "BeforeUnloadEvent")]
#[reference(event = "beforeunload")]
pub struct BeforeUnloadEvent( Reference );
impl IEvent for BeforeUnloadEvent {}
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "UnloadEvent")]
#[reference(event = "unload")]
pub struct UnloadEvent( Reference );
impl IEvent for UnloadEvent {}
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "Event")]
#[reference(event = "fullscreenchange")]
pub struct FullscreenChangeEvent( Reference );
impl IEvent for FullscreenChangeEvent {}
pub trait IUiEvent: IEvent {
#[inline]
fn detail( &self ) -> i32 {
js!(
return @{self.as_ref()}.detail;
).try_into().unwrap()
}
#[inline]
fn view( &self ) -> Option< Window > {
js!(
return @{self.as_ref()}.view;
).try_into().ok()
}
}
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "UIEvent")]
#[reference(subclass_of(Event))]
pub struct UiEvent( Reference );
impl IEvent for UiEvent {}
impl IUiEvent for UiEvent {}
#[cfg(all(test, feature = "web_test"))]
mod tests {
use super::*;
#[test]
fn test_event() {
let event: Event = js!(
return new Event("dummy")
).try_into().unwrap();
assert_eq!( event.event_type(), "dummy" );
assert_eq!( event.bubbles(), false );
assert!( !event.cancel_bubble() );
assert!( !event.cancelable(), false );
assert!( event.current_target().is_none() );
assert!( !event.default_prevented() );
assert_eq!( event.event_phase(), EventPhase::None );
assert!( event.target().is_none() );
assert!( event.time_stamp().is_some() );
assert!( !event.is_trusted() );
event.stop_immediate_propagation();
event.stop_propagation();
}
#[test]
fn test_ui_event() {
use webapi::events::mouse::ClickEvent;
let event: UiEvent = js!(
return new UIEvent(
@{ClickEvent::EVENT_TYPE},
{
detail: 1,
}
)
).try_into().unwrap();
assert_eq!( event.event_type(), ClickEvent::EVENT_TYPE );
assert_eq!( event.detail(), 1 );
assert!( event.view().is_none() );
}
}