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}