Skip to main content

virtual_node/event/
virtual_events.rs

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