plaster/virtual_dom/mod.rs
1//! This module contains the implementation of reactive virtual dom concept.
2
3pub mod vcomp;
4pub mod vlist;
5pub mod vnode;
6pub mod vtag;
7pub mod vtext;
8
9use std::collections::{HashMap, HashSet};
10use std::fmt;
11use web_sys::{Element, Node};
12
13pub use self::vcomp::VComp;
14pub use self::vlist::VList;
15pub use self::vnode::VNode;
16pub use self::vtag::VTag;
17pub use self::vtext::VText;
18use html::{Component, EventListenerHandle, Scope};
19
20/// `Listener` trait is an universal implementation of an event listener
21/// which helps to bind Rust-listener to JS-listener (DOM).
22pub trait Listener<COMP: Component> {
23 /// Returns standard name of DOM's event.
24 fn kind(&self) -> &'static str;
25 /// Attaches listener to the element and uses scope instance to send
26 /// prepaired event back to the yew main loop.
27 fn attach(&mut self, element: &Element, scope: Scope<COMP>) -> EventListenerHandle;
28}
29
30impl<COMP: Component> fmt::Debug for dyn Listener<COMP> {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 write!(f, "Listener {{ kind: {} }}", self.kind())
33 }
34}
35
36/// A list of event listeners.
37type Listeners<COMP> = Vec<Box<dyn Listener<COMP>>>;
38
39/// A map of attributes.
40type Attributes = HashMap<String, String>;
41
42/// A set of classes.
43type Classes = HashSet<String>;
44
45/// Patch for DOM node modification.
46enum Patch<ID, T> {
47 Add(ID, T),
48 Replace(ID, T),
49 Remove(ID),
50}
51
52/// Reform of a node.
53enum Reform {
54 /// Don't create a NEW reference (js Node).
55 ///
56 /// The reference _may still be mutated_.
57 Keep,
58
59 /// Create a new reference (js Node).
60 ///
61 /// The optional `Node` is used to insert the
62 /// new node in the correct slot of the parent.
63 ///
64 /// If it does not exist, a `precursor` must be
65 /// speccified (see `VDiff::apply()`).
66 Before(Option<Node>),
67}
68
69// TODO What about to implement `VDiff` for `Element`?
70// In makes possible to include ANY element into the tree.
71// `Ace` editor embedding for example?
72
73/// This trait provides features to update a tree by other tree comparsion.
74pub trait VDiff {
75 /// The component which this instance put into.
76 type Component: Component;
77
78 /// Remove itself from parent and return the next sibling.
79 fn detach(&mut self, parent: &Node) -> Option<Node>;
80
81 /// Scoped diff apply to other tree.
82 ///
83 /// Virtual rendering for the node. It uses parent node and existing children (virtual and DOM)
84 /// to check the difference and apply patches to the actual DOM represenatation.
85 ///
86 /// Parameters:
87 /// - `parent`: the parent node in the DOM.
88 /// - `precursor`: the "previous node" in a list of nodes, used to efficiently
89 /// find where to put the node.
90 /// - `ancestor`: the node that this node will be replacing in the DOM.
91 /// This method will _always_ remove the `ancestor` from the `parent`.
92 /// - `env`: the `Env`.
93 ///
94 /// ### Internal Behavior Notice:
95 ///
96 /// Note that these modify the DOM by modifying the reference that _already_ exists
97 /// on the `ancestor`. If `self.reference` exists (which it _shouldn't_) this method
98 /// will panic.
99 ///
100 /// The exception to this is obviously `VRef` which simply uses the inner `Node` directly
101 /// (always removes the `Node` that exists).
102 fn apply(
103 &mut self,
104 parent: &Node,
105 precursor: Option<&Node>,
106 ancestor: Option<VNode<Self::Component>>,
107 scope: &Scope<Self::Component>,
108 ) -> Option<Node>;
109}