This is unreleased documentation for Yew Next version.
For up-to-date documentation, see the latest version on docs.rs.

yew/virtual_dom/
listeners.rs

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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
use std::rc::Rc;

use crate::html::ImplicitClone;

/// The [Listener] trait is an universal implementation of an event listener
/// which is used to bind Rust-listener to JS-listener (DOM).
pub trait Listener {
    /// Returns the name of the event
    fn kind(&self) -> ListenerKind;

    /// Handles an event firing
    fn handle(&self, event: web_sys::Event);

    /// Makes the event listener passive. See
    /// [addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener).
    fn passive(&self) -> bool;
}

impl std::fmt::Debug for dyn Listener {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "Listener {{ kind: {}, passive: {:?} }}",
            self.kind().as_ref(),
            self.passive(),
        )
    }
}

macro_rules! gen_listener_kinds {
    ($($kind:ident)*) => {
        /// Supported kinds of DOM event listeners
        // Using instead of strings to optimise registry collection performance by simplifying
        // hashmap hash calculation.
        #[derive(Clone, PartialEq, Eq, Hash, Debug)]
        #[allow(non_camel_case_types)]
        #[allow(missing_docs)]
        pub enum ListenerKind {
            $( $kind, )*
            other(std::borrow::Cow<'static, str>),
        }

        impl ListenerKind {
            pub fn type_name(&self) -> std::borrow::Cow<'static, str> {
                match self {
                    Self::other(type_name) => type_name.clone(),
                    $( Self::$kind => stringify!($kind)[2..].into(), )*
                }
            }
        }

        impl AsRef<str> for ListenerKind {
            fn as_ref(&self) -> &str {
                match self {
                    $( Self::$kind => stringify!($kind), )*
                    Self::other(type_name) => type_name.as_ref(),
                }
            }
        }
    };
}

gen_listener_kinds! {
    onabort
    onauxclick
    onblur
    oncancel
    oncanplay
    oncanplaythrough
    onchange
    onclick
    onclose
    oncontextmenu
    oncuechange
    ondblclick
    ondrag
    ondragend
    ondragenter
    ondragexit
    ondragleave
    ondragover
    ondragstart
    ondrop
    ondurationchange
    onemptied
    onended
    onerror
    onfocus
    onfocusin
    onfocusout
    onformdata
    oninput
    oninvalid
    onkeydown
    onkeypress
    onkeyup
    onload
    onloadeddata
    onloadedmetadata
    onloadstart
    onmousedown
    onmouseenter
    onmouseleave
    onmousemove
    onmouseout
    onmouseover
    onmouseup
    onpause
    onplay
    onplaying
    onprogress
    onratechange
    onreset
    onresize
    onscroll
    onsecuritypolicyviolation
    onseeked
    onseeking
    onselect
    onslotchange
    onstalled
    onsubmit
    onsuspend
    ontimeupdate
    ontoggle
    onvolumechange
    onwaiting
    onwheel
    oncopy
    oncut
    onpaste
    onanimationcancel
    onanimationend
    onanimationiteration
    onanimationstart
    ongotpointercapture
    onloadend
    onlostpointercapture
    onpointercancel
    onpointerdown
    onpointerenter
    onpointerleave
    onpointerlockchange
    onpointerlockerror
    onpointermove
    onpointerout
    onpointerover
    onpointerup
    onselectionchange
    onselectstart
    onshow
    ontouchcancel
    ontouchend
    ontouchmove
    ontouchstart
    ontransitioncancel
    ontransitionend
    ontransitionrun
    ontransitionstart
}

/// A list of event listeners
#[derive(Debug)]
pub enum Listeners {
    /// No listeners registered or pending.
    /// Distinct from `Pending` with an empty slice to avoid an allocation.
    None,

    /// Not yet added to the element or registry
    Pending(Box<[Option<Rc<dyn Listener>>]>),
}

impl ImplicitClone for Listeners {}

impl PartialEq for Listeners {
    fn eq(&self, rhs: &Self) -> bool {
        use Listeners::*;

        match (self, rhs) {
            (None, None) => true,
            (Pending(lhs), Pending(rhs)) => {
                if lhs.len() != rhs.len() {
                    false
                } else {
                    use std::option::Option::None;

                    lhs.iter()
                        .zip(rhs.iter())
                        .all(|(lhs, rhs)| match (lhs, rhs) {
                            (Some(lhs), Some(rhs)) => {
                                // We are okay with comparisons from different compilation units to
                                // result in false not-equal results. This should only lead in the
                                // worst-case to some unneeded re-renders.
                                #[allow(ambiguous_wide_pointer_comparisons)]
                                Rc::ptr_eq(lhs, rhs)
                            }
                            (None, None) => true,
                            _ => false,
                        })
                }
            }
            (None, Pending(pending)) | (Pending(pending), None) => pending.len() == 0,
        }
    }
}

impl Clone for Listeners {
    fn clone(&self) -> Self {
        match self {
            Self::None => Self::None,
            Self::Pending(v) => Self::Pending(v.clone()),
        }
    }
}

impl Default for Listeners {
    fn default() -> Self {
        Self::None
    }
}