1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use wasm_bindgen::closure::Closure;
use wasm_bindgen::{JsCast, UnwrapThrowExt};
pub trait Listener {}
macro_rules! create_events {
($($EventType:ident $EventListener:ident { $($EventName:ident => $event_name:literal,)+ })+) => {
$(
pub struct $EventListener {
event_name: &'static str,
event_target: web_sys::EventTarget,
closure: Closure<dyn Fn(web_sys::$EventType)>,
}
impl $EventListener {
fn new(event_name: &'static str, event_target: &web_sys::EventTarget, closure: Closure<dyn Fn(web_sys::$EventType)>) -> Self {
event_target.add_event_listener_with_callback(
event_name,
closure.as_ref().unchecked_ref()
).expect_throw("Expect event register to be successful");
Self {
event_name,
event_target: event_target.clone(),
closure,
}
}
}
impl Listener for $EventListener {}
impl Drop for $EventListener {
#[inline]
fn drop(&mut self) {
self.event_target
.remove_event_listener_with_callback(
self.event_name,
self.closure.as_ref().unchecked_ref()
).expect_throw("Expect event removal to be successful");
}
}
$(
#[doc = "Help creating "]
#[doc = $event_name]
#[doc = " event listener"]
pub trait $EventName {
fn on(self, node: &web_sys::EventTarget) -> Box<dyn Listener>;
fn on_window(self) -> Box<dyn Listener>;
}
impl<T> $EventName for T
where
T: 'static + Fn(web_sys::$EventType),
{
fn on(self, target: &web_sys::EventTarget) -> Box<dyn Listener> {
let closure = Closure::wrap(Box::new(self) as Box<dyn Fn(web_sys::$EventType)>);
Box::new($EventListener::new($event_name, target, closure))
}
fn on_window(self) -> Box<dyn Listener> {
$EventName::on(self, crate::utils::window().as_ref())
}
}
)+
)+
};
}
create_events! {
FocusEvent FocusEventListener {
Focus => "focus",
Blur => "blur",
}
MouseEvent MouseEventListener {
AuxClick => "auxclick",
Click => "click",
DblClick => "dblclick",
DoubleClick => "dblclick",
MouseEnter => "mouseenter",
MouseOver => "mouseover",
MouseMove => "mousemove",
MouseDown => "mousedown",
MouseUp => "mouseup",
MouseLeave => "mouseleave",
MouseOut => "mouseout",
ContextMenu => "contextmenu",
}
WheelEvent WheelEventListener {
Wheel => "wheel",
}
UiEvent UiEventListener {
UiSelect => "select",
}
InputEvent InputEventListener {
Input => "input",
}
KeyboardEvent KeyboardEventListener {
KeyDown => "keydown",
KeyPress => "keypress",
KeyUp => "keyup",
}
Event EventListener {
Change => "change",
Reset => "reset",
Submit => "submit",
PointerLockChange => "pointerlockchange",
PointerLockError => "pointerlockerror",
}
}