Skip to main content

virtual_node/event/
virtual_events.rs

1use crate::event::event_name::EventName;
2use crate::event::{EventHandler, RealDom};
3use std::cell::{Ref, RefCell, RefMut};
4use std::collections::HashMap;
5use std::rc::Rc;
6
7// Every real DOM element that we create gets a property set on it that can be used to look up
8// its events in [`crate::VirtualEvents`].
9#[doc(hidden)]
10pub const ELEMENT_EVENTS_ID_PROP: &'static str = "__events_id__";
11
12/// Uniquely identifies an element so that we can store it's events in [`VirtualEvents`].
13#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
14pub struct ElementEventsId(u32);
15
16impl ElementEventsId {
17    /// Create a new ElementEventsId.
18    pub fn new(id: u32) -> Self {
19        Self(id)
20    }
21
22    /// Get the inner u32 id.
23    pub fn get(&self) -> u32 {
24        self.0
25    }
26}
27
28/// A [`VirtualEvents`] that is compatible with [`web_sys`].
29#[cfg(feature = "web")]
30pub type VirtualEventsWebSys = VirtualEvents<web_sys::Window>;
31
32/// When we create a DOM node, we store all of it's closures and all of it's children's closures
33/// in VirtualEvents.
34///
35/// When an element gets interacted with in the DOM it's event handlers get looked up in
36/// VirtualEvents.
37///
38/// This helps power event delegation, where for many events kinds of events such as onclick we use
39/// a single event listener on the element that the application was mounted on and then as events
40/// occur we look up the event handlers in VirtualEvents.
41///
42/// This is faster since instead of needing to add and remove event listeners from the DOM after
43/// when applying patches we can simply overwrite the old closures in VirtualEvents with new ones.
44///
45/// ## Cloning
46///
47/// VirtualEvents can be cloned cheaply. Clones share the same inner data.
48#[derive(Clone)]
49pub struct VirtualEvents<Dom: RealDom> {
50    inner: Rc<RefCell<VirtualEventsInner<Dom>>>,
51    // Never changes after creation.
52    events_id_props_prefix: f64,
53}
54
55struct VirtualEventsInner<Dom: RealDom> {
56    root: Rc<RefCell<VirtualEventNode>>,
57    events: HashMap<ElementEventsId, Rc<RefCell<HashMap<EventName, EventHandler<Dom>>>>>,
58    /// For non delegated events an event listener is attached to the DOM element using
59    /// .add_event_listener();
60    /// That event listener is an `EventWrapper`, which in turn will find and call the
61    /// `EventHandler`.
62    /// This setup allows us to replace the `EventHandler` after every render without needing
63    /// to re-attach event listeners.
64    non_delegated_event_wrappers: HashMap<ElementEventsId, HashMap<EventName, Dom::EventCallback>>,
65    next_events_id: u32,
66}
67
68/// A tree where each entry holds the events for the corresponding entry in a
69/// [`crate::VirtualNode`] tree.
70#[derive(Debug)]
71pub struct VirtualEventNode {
72    variant: VirtualEventNodeVariant,
73    previous_sibling: Option<Rc<RefCell<VirtualEventNode>>>,
74    next_sibling: Option<Rc<RefCell<VirtualEventNode>>>,
75}
76
77#[derive(Debug)]
78enum VirtualEventNodeVariant {
79    Element(VirtualEventElement),
80    Text,
81}
82
83/// A virtual event element node.
84#[derive(Debug)]
85pub struct VirtualEventElement {
86    events_id: ElementEventsId,
87    children: Option<VirtualEventElementChildren>,
88}
89
90#[derive(Debug)]
91struct VirtualEventElementChildren {
92    first_child: Rc<RefCell<VirtualEventNode>>,
93    last_child: Rc<RefCell<VirtualEventNode>>,
94}
95
96impl<Dom: RealDom> VirtualEvents<Dom> {
97    /// Create a new EventsByNodeIdx.
98    #[cfg(feature = "web")]
99    pub fn new() -> Self {
100        VirtualEvents {
101            inner: Rc::new(RefCell::new(VirtualEventsInner::new())),
102            events_id_props_prefix: js_sys::Math::random(),
103        }
104    }
105
106    #[cfg(test)]
107    pub fn new_with_prefix(prefix: f64) -> Self {
108        VirtualEvents {
109            inner: Rc::new(RefCell::new(VirtualEventsInner::new())),
110            events_id_props_prefix: prefix,
111        }
112    }
113
114    /// Unique for every PercyDom so that if multiple instances of PercyDom are nested their
115    /// event delegation handlers don't collide.
116    pub fn events_id_props_prefix(&self) -> f64 {
117        self.events_id_props_prefix
118    }
119
120    /// Get the root event node.
121    pub fn root(&self) -> Rc<RefCell<VirtualEventNode>> {
122        self.borrow().root.clone()
123    }
124
125    /// Set the root event node.
126    pub fn set_root(&self, root: VirtualEventNode) {
127        *self.borrow_mut().root.borrow_mut() = root;
128    }
129
130    /// Insert a newly tracked event.
131    ///
132    /// # Panics
133    ///
134    /// Panics if the event_name is delegated and the event is not, or vice versa.
135    pub fn insert_event(
136        &self,
137        events_id: ElementEventsId,
138        event_name: EventName,
139        event: EventHandler<Dom>,
140        wrapper: Option<Dom::EventCallback>,
141    ) {
142        assert_eq!(event_name.is_delegated(), wrapper.is_none());
143
144        let mut borrow = self.borrow_mut();
145
146        borrow
147            .events
148            .entry(events_id)
149            .or_default()
150            .borrow_mut()
151            .insert(event_name.clone(), event);
152
153        if let Some(wrapper) = wrapper {
154            borrow
155                .non_delegated_event_wrappers
156                .entry(events_id)
157                .or_default()
158                .insert(event_name, wrapper);
159        }
160    }
161
162    /// Overwrite an event handler.
163    ///
164    /// # Panics
165    ///
166    /// Panics if there isn't an event attrib fn to overwrite.
167    pub fn overwrite_event_attrib_fn(
168        &self,
169        events_id: &ElementEventsId,
170        event_name: &EventName,
171        event: EventHandler<Dom>,
172    ) {
173        let mut borrow = self.borrow_mut();
174
175        let borrow = borrow.events.get_mut(events_id).unwrap();
176        let mut borrow = borrow.borrow_mut();
177        let func = borrow.get_mut(event_name).unwrap();
178
179        *func = event;
180    }
181
182    /// Remove a managed event.
183    pub fn remove_non_delegated_event_wrapper(
184        &mut self,
185        events_id: &ElementEventsId,
186        event_name: &EventName,
187    ) -> Dom::EventCallback {
188        let mut borrow = self.borrow_mut();
189        borrow
190            .non_delegated_event_wrappers
191            .get_mut(events_id)
192            .unwrap()
193            .remove(event_name)
194            .unwrap()
195    }
196
197    /// Get the event handler for a node.
198    pub fn get_event_handler(
199        &self,
200        events_id: &ElementEventsId,
201        event_name: &EventName,
202    ) -> Option<EventHandler<Dom>> {
203        let borrow = self.borrow();
204        let borrow = borrow.events.get(events_id)?;
205        let borrow = borrow.borrow();
206        borrow.get(event_name).cloned()
207    }
208
209    /// Remove an event handler.
210    pub fn remove_event_handler(
211        &self,
212        events_id: &ElementEventsId,
213        event_name: &EventName,
214    ) -> Option<EventHandler<Dom>> {
215        let mut borrow = self.borrow_mut();
216
217        let borrow = borrow.events.get_mut(events_id)?;
218        let mut borrow = borrow.borrow_mut();
219        borrow.remove(event_name)
220    }
221
222    /// Remove all event handlers for a node.
223    pub fn remove_node(&self, events_id: &ElementEventsId) {
224        let mut borrow = self.borrow_mut();
225        borrow.events.remove(events_id);
226        borrow.non_delegated_event_wrappers.remove(events_id);
227    }
228
229    /// Create a new element node.
230    pub fn create_element_node(&self) -> VirtualEventNode {
231        VirtualEventNode {
232            variant: VirtualEventNodeVariant::Element(VirtualEventElement::new(
233                self.unique_events_id(),
234            )),
235            previous_sibling: None,
236            next_sibling: None,
237        }
238    }
239
240    /// Create a new element node.
241    pub fn create_text_node(&self) -> VirtualEventNode {
242        VirtualEventNode {
243            variant: VirtualEventNodeVariant::Text,
244            previous_sibling: None,
245            next_sibling: None,
246        }
247    }
248
249    // Create an ElementEventsId that is unique to this VirtualEvents instance.
250    fn unique_events_id(&self) -> ElementEventsId {
251        let mut borrow = self.borrow_mut();
252        let counter = borrow.next_events_id;
253
254        borrow.next_events_id += 1;
255
256        ElementEventsId(counter)
257    }
258
259    fn borrow(&self) -> Ref<'_, VirtualEventsInner<Dom>> {
260        self.inner.borrow()
261    }
262    fn borrow_mut(&self) -> RefMut<'_, VirtualEventsInner<Dom>> {
263        self.inner.borrow_mut()
264    }
265}
266
267impl<Dom: RealDom> VirtualEventsInner<Dom> {
268    fn new() -> Self {
269        let root = VirtualEventNode {
270            // ::Text will get replaced with an element shortly after creating VirtualEvents.
271            variant: VirtualEventNodeVariant::Text,
272            previous_sibling: None,
273            next_sibling: None,
274        };
275
276        Self {
277            root: Rc::new(RefCell::new(root)),
278            events: HashMap::new(),
279            non_delegated_event_wrappers: HashMap::new(),
280            next_events_id: 0,
281        }
282    }
283}
284
285impl VirtualEventNode {
286    /// Get the [`VirtualEventNode::VirtualEventElement`] variant.
287    pub fn as_element(&self) -> Option<&VirtualEventElement> {
288        match &self.variant {
289            VirtualEventNodeVariant::Element(e) => Some(e),
290            _ => None,
291        }
292    }
293
294    /// Get a mutable reference to the [`VirtualEventNode::VirtualEventElement`] variant.
295    pub fn as_element_mut(&mut self) -> Option<&mut VirtualEventElement> {
296        match &mut self.variant {
297            VirtualEventNodeVariant::Element(e) => Some(e),
298            _ => None,
299        }
300    }
301
302    /// Get the previous sibling.
303    pub fn previous_sibling(&self) -> Option<&Rc<RefCell<VirtualEventNode>>> {
304        self.previous_sibling.as_ref()
305    }
306
307    /// Get the next sibling.
308    pub fn next_sibling(&self) -> Option<&Rc<RefCell<VirtualEventNode>>> {
309        self.next_sibling.as_ref()
310    }
311
312    /// Replace a node with another.
313    ///
314    /// The new node is given the same siblings as the old node.
315    pub fn replace_with_node(&mut self, mut new: VirtualEventNode) {
316        new.previous_sibling = self.previous_sibling.take();
317        new.next_sibling = self.next_sibling.take();
318
319        *self = new;
320    }
321
322    /// Remove a child node from it's siblings.
323    pub fn remove_node_from_siblings(&mut self, child: &Rc<RefCell<VirtualEventNode>>) {
324        let child = &mut *child.borrow_mut();
325        let is_first_sibling = child.previous_sibling.is_none();
326        let is_last_sibling = child.next_sibling.is_none();
327
328        let parent = self.as_element_mut().unwrap();
329        if is_first_sibling && is_last_sibling {
330            parent.children = None;
331        } else if is_first_sibling {
332            parent.children.as_mut().unwrap().first_child = child.next_sibling.clone().unwrap();
333        } else if is_last_sibling {
334            parent.children.as_mut().unwrap().last_child = child.previous_sibling.clone().unwrap();
335        }
336
337        match (child.previous_sibling.as_mut(), child.next_sibling.as_mut()) {
338            (Some(previous), Some(next)) => {
339                previous.borrow_mut().next_sibling = Some(next.clone());
340                next.borrow_mut().previous_sibling = Some(previous.clone());
341            }
342            (Some(previous), None) => {
343                previous.borrow_mut().next_sibling = None;
344            }
345            (None, Some(next)) => {
346                next.borrow_mut().previous_sibling = None;
347            }
348            (None, None) => {}
349        };
350
351        child.previous_sibling = None;
352        child.next_sibling = None;
353    }
354
355    /// Insert a node before another node.
356    pub fn insert_before(
357        &mut self,
358        new: Rc<RefCell<VirtualEventNode>>,
359        existing: Rc<RefCell<VirtualEventNode>>,
360    ) {
361        let parent = self.as_element_mut().unwrap();
362
363        {
364            let mut new_borrow = new.borrow_mut();
365            let mut existing_borrow = existing.borrow_mut();
366            match existing_borrow.previous_sibling.take() {
367                Some(previous) => {
368                    previous.borrow_mut().next_sibling = Some(new.clone());
369                    new_borrow.previous_sibling = Some(previous);
370                }
371                None => {
372                    parent.children.as_mut().unwrap().first_child = new.clone();
373                }
374            };
375        }
376
377        new.borrow_mut().next_sibling = Some(existing.clone());
378        existing.borrow_mut().previous_sibling = Some(new);
379    }
380}
381
382impl VirtualEventElement {
383    /// Create a new VirtualEventNode for the given events id.
384    fn new(events_id: ElementEventsId) -> Self {
385        VirtualEventElement {
386            events_id,
387            children: None,
388        }
389    }
390
391    /// Get this node's unique id for its events.
392    pub fn events_id(&self) -> ElementEventsId {
393        self.events_id
394    }
395
396    /// Get the element's first child.
397    pub fn first_child(&self) -> Option<Rc<RefCell<VirtualEventNode>>> {
398        self.children.as_ref().map(|c| c.first_child.clone())
399    }
400
401    /// Append a child to the end of the list of children.
402    pub fn append_child(&mut self, new_child: Rc<RefCell<VirtualEventNode>>) {
403        match self.children.as_mut() {
404            Some(children) => {
405                {
406                    children.last_child.borrow_mut().next_sibling = Some(new_child.clone());
407                    let mut new_child_borrow = new_child.borrow_mut();
408
409                    new_child_borrow.previous_sibling = Some(children.last_child.clone());
410                    new_child_borrow.next_sibling = None;
411                }
412
413                children.last_child = new_child;
414            }
415            None => {
416                self.set_first_and_last_child(new_child);
417            }
418        };
419    }
420
421    // Set this element's first and last child.
422    fn set_first_and_last_child(&mut self, child: Rc<RefCell<VirtualEventNode>>) {
423        self.children = Some(VirtualEventElementChildren {
424            first_child: child.clone(),
425            last_child: child.clone(),
426        })
427    }
428}
429
430#[cfg(feature = "web")]
431pub(crate) fn set_events_id<Dom: RealDom>(
432    node: &wasm_bindgen::JsValue,
433    events: &VirtualEvents<Dom>,
434    events_id: ElementEventsId,
435) {
436    use js_sys::Reflect;
437    Reflect::set(
438        &node.into(),
439        &ELEMENT_EVENTS_ID_PROP.into(),
440        &format!("{}{}", events.events_id_props_prefix(), events_id.get()).into(),
441    )
442    .unwrap();
443}
444
445#[cfg(test)]
446mod tests {
447    use super::*;
448
449    /// Verify that we can append children to a virtual event node.
450    #[test]
451    fn append_children() {
452        let events = VirtualEvents::new_with_prefix(1.);
453
454        let mut node = events.create_element_node();
455        let elem = node.as_element_mut().unwrap();
456
457        let children = create_element_nodes(&events, 3);
458        for child in &children {
459            elem.append_child(child.clone());
460        }
461
462        assert_elem_children_equal(elem, &children);
463    }
464
465    /// Verify that we can insert nodes before another node in the virtual event nodes.
466    #[test]
467    fn insert_before() {
468        let events = VirtualEvents::new_with_prefix(1.);
469
470        let children = create_element_nodes(&events, 3);
471
472        let mut node = events.create_element_node();
473
474        {
475            let elem = node.as_element_mut().unwrap();
476            elem.append_child(children[0].clone());
477        }
478
479        node.insert_before(children[1].clone(), children[0].clone());
480        node.insert_before(children[2].clone(), children[0].clone());
481
482        let expected_order = [
483            children[1].clone(),
484            children[2].clone(),
485            children[0].clone(),
486        ];
487        assert_elem_children_equal(node.as_element().unwrap(), &expected_order);
488    }
489
490    /// Verify that we can remove a node from its siblings.
491    #[test]
492    fn remove_node_from_siblings() {
493        let events = VirtualEvents::new_with_prefix(1.);
494
495        let children = create_element_nodes(&events, 3);
496
497        let mut node = events.create_element_node();
498
499        {
500            let elem = node.as_element_mut().unwrap();
501            for child in &children {
502                elem.append_child(child.clone());
503            }
504        }
505
506        node.remove_node_from_siblings(&children[1]);
507        assert_elem_children_equal(
508            node.as_element().unwrap(),
509            &[children[0].clone(), children[2].clone()],
510        );
511
512        node.remove_node_from_siblings(&children[0]);
513        assert_elem_children_equal(node.as_element().unwrap(), &[children[2].clone()]);
514
515        node.remove_node_from_siblings(&children[2]);
516        assert_elem_children_equal(node.as_element().unwrap(), &[]);
517    }
518
519    /// Verify that we can replace a node with another node.
520    #[test]
521    fn replace_node() {
522        let events = VirtualEvents::new_with_prefix(1.);
523
524        let children = create_element_nodes(&events, 3);
525
526        let mut node = events.create_element_node();
527
528        {
529            let elem = node.as_element_mut().unwrap();
530            for child in &children {
531                elem.append_child(child.clone());
532            }
533        }
534
535        let new_node = events.create_element_node();
536        let new_node_events_id = new_node.as_element().unwrap().events_id;
537
538        assert_eq!(node_events_id(&children[1]) == new_node_events_id, false);
539        children[1].borrow_mut().replace_with_node(new_node);
540        assert_eq!(node_events_id(&children[1]) == new_node_events_id, true);
541
542        assert_elem_children_equal(
543            node.as_element().unwrap(),
544            &[
545                children[0].clone(),
546                children[1].clone(),
547                children[2].clone(),
548            ],
549        );
550    }
551
552    fn create_element_nodes(
553        events: &VirtualEvents<web_sys::Window>,
554        count: usize,
555    ) -> Vec<Rc<RefCell<VirtualEventNode>>> {
556        (0..count)
557            .into_iter()
558            .map(|_| {
559                let child = events.create_element_node();
560                let child = Rc::new(RefCell::new(child));
561                child
562            })
563            .collect()
564    }
565
566    fn assert_elem_children_equal(
567        elem: &VirtualEventElement,
568        expected: &[Rc<RefCell<VirtualEventNode>>],
569    ) {
570        let mut idx = 0;
571
572        let mut next_child = elem.first_child().clone();
573
574        while let Some(child) = next_child {
575            let child = child.borrow();
576
577            if idx == 0 {
578                assert_eq!(child.previous_sibling.is_none(), true);
579            }
580
581            assert_eq!(
582                child.as_element().unwrap().events_id(),
583                expected[idx].borrow().as_element().unwrap().events_id,
584            );
585
586            next_child = child.next_sibling.clone();
587            idx += 1;
588
589            if idx == expected.len() {
590                assert_eq!(child.next_sibling.is_none(), true);
591            }
592        }
593
594        assert_eq!(idx, expected.len());
595
596        assert_elem_first_and_last_child(elem, expected);
597    }
598
599    fn assert_elem_first_and_last_child(
600        elem: &VirtualEventElement,
601        expected_children: &[Rc<RefCell<VirtualEventNode>>],
602    ) {
603        if expected_children.len() == 0 {
604            assert!(elem.children.is_none());
605            return;
606        }
607
608        let elem_children = elem.children.as_ref().unwrap();
609
610        assert_eq!(
611            node_events_id(&elem_children.first_child),
612            node_events_id(expected_children.first().unwrap()),
613        );
614
615        assert_eq!(
616            node_events_id(&elem_children.last_child),
617            node_events_id(expected_children.last().unwrap()),
618        );
619    }
620
621    fn node_events_id(node: &Rc<RefCell<VirtualEventNode>>) -> ElementEventsId {
622        node.borrow().as_element().unwrap().events_id
623    }
624}