mt_dom/node/
element.rs

1use crate::node::{Attribute, Node};
2use alloc::vec;
3use alloc::vec::Vec;
4use core::fmt::Debug;
5
6/// Represents an element of the virtual node
7/// An element has a generic tag, this tag could be a static str tag, such as usage in html dom.
8///     Example of which are `div`, `a`, `input`, `img`, etc.
9///
10/// Tag is a generic type, which can represent a different DOM tree other than the html dom
11/// such as widgets in native platform such as gtk, example of which are `Hpane`, `Vbox`, `Image`,
12///
13/// An element can have an optional namespace, such in the case for html dom where namespace like
14/// HTML and SVG, which needs to specified in order to create the DOM element to work on the
15/// browser.
16///
17/// The namespace is also needed in attributes where namespace are necessary such as `xlink:href`
18/// where the namespace `xlink` is needed in order for the linked element in an svg image to work.
19#[derive(Clone, Debug, PartialEq, Default)]
20pub struct Element<Ns, Tag, Leaf, Att, Val>
21where
22    Ns: PartialEq + Clone + Debug,
23    Tag: PartialEq + Debug,
24    Leaf: PartialEq + Clone + Debug,
25    Att: PartialEq + Clone + Debug,
26    Val: PartialEq + Clone + Debug,
27{
28    /// namespace of this element,
29    /// svg elements requires namespace to render correcly in the browser
30    pub namespace: Option<Ns>,
31    /// the element tag, such as div, a, button
32    pub tag: Tag,
33    /// attributes for this element
34    pub attrs: Vec<Attribute<Ns, Att, Val>>,
35    /// children elements of this element
36    pub children: Vec<Node<Ns, Tag, Leaf, Att, Val>>,
37    /// is the element has a self closing tag
38    pub self_closing: bool,
39}
40
41impl<Ns, Tag, Leaf, Att, Val> Element<Ns, Tag, Leaf, Att, Val>
42where
43    Ns: PartialEq + Clone + Debug,
44    Tag: PartialEq + Debug,
45    Leaf: PartialEq + Clone + Debug,
46    Att: PartialEq + Clone + Debug,
47    Val: PartialEq + Clone + Debug,
48{
49    /// create a new instance of an element
50    pub fn new(
51        namespace: Option<Ns>,
52        tag: Tag,
53        attrs: impl IntoIterator<Item = Attribute<Ns, Att, Val>>,
54        children: impl IntoIterator<Item = Node<Ns, Tag, Leaf, Att, Val>>,
55        self_closing: bool,
56    ) -> Self {
57        //unroll the nodelist
58        let children = children
59            .into_iter()
60            .flat_map(|child| match child {
61                Node::NodeList(node_list) => node_list,
62                _ => vec![child],
63            })
64            .collect();
65        Self {
66            namespace,
67            tag,
68            attrs: attrs.into_iter().collect(),
69            children,
70            self_closing,
71        }
72    }
73
74    /// add attributes to this element
75    pub fn add_attributes(
76        &mut self,
77        attrs: impl IntoIterator<Item = Attribute<Ns, Att, Val>>,
78    ) {
79        self.attrs.extend(attrs)
80    }
81
82    /// add children virtual node to this element
83    pub fn add_children(
84        &mut self,
85        children: impl IntoIterator<Item = Node<Ns, Tag, Leaf, Att, Val>>,
86    ) {
87        self.children.extend(children.into_iter());
88    }
89
90    /// returns a refernce to the children of this node
91    pub fn children(&self) -> &[Node<Ns, Tag, Leaf, Att, Val>] {
92        &self.children
93    }
94
95    /// returns a mutable reference to the children of this node
96    pub fn children_mut(&mut self) -> &mut [Node<Ns, Tag, Leaf, Att, Val>] {
97        &mut self.children
98    }
99
100    /// Removes an child node  from this element and returns it.
101    ///
102    /// The removed child is replaced by the last child of the element's children.
103    ///
104    /// # Panics
105    /// Panics if index is out of bounds in children
106    ///
107    pub fn swap_remove_child(
108        &mut self,
109        index: usize,
110    ) -> Node<Ns, Tag, Leaf, Att, Val> {
111        self.children.swap_remove(index)
112    }
113
114    /// Swaps the 2 child node in this element
115    ///
116    /// # Arguments
117    /// * a - The index of the first child node
118    /// * b - The index of the second child node
119    ///
120    /// # Panics
121    /// Panics if both `a` and `b` are out of bounds
122    ///
123    pub fn swap_children(&mut self, a: usize, b: usize) {
124        self.children.swap(a, b)
125    }
126
127    /// consume self and return the children
128    pub fn take_children(self) -> Vec<Node<Ns, Tag, Leaf, Att, Val>> {
129        self.children
130    }
131
132    /// return a reference to the attribute of this element
133    pub fn attributes(&self) -> &[Attribute<Ns, Att, Val>] {
134        &self.attrs
135    }
136
137    /// consume self and return the attributes
138    pub fn take_attributes(self) -> Vec<Attribute<Ns, Att, Val>> {
139        self.attrs
140    }
141
142    /// return the namespace of this element
143    pub fn namespace(&self) -> Option<&Ns> {
144        self.namespace.as_ref()
145    }
146
147    /// return the tag of this element
148    pub fn tag(&self) -> &Tag {
149        &self.tag
150    }
151
152    /// consume self and return the tag of this element
153    pub fn take_tag(self) -> Tag {
154        self.tag
155    }
156
157    /// change the tag of this element
158    pub fn set_tag(&mut self, tag: Tag) {
159        self.tag = tag;
160    }
161
162    /// remove the attributes with this key
163    pub fn remove_attribute(&mut self, key: &Att) {
164        self.attrs.retain(|att| att.name != *key)
165    }
166
167    /// remove the existing values of this attribute
168    /// and add the new values
169    pub fn set_attributes(
170        &mut self,
171        attrs: impl IntoIterator<Item = Attribute<Ns, Att, Val>>,
172    ) {
173        for attr in attrs {
174            self.remove_attribute(&attr.name);
175            self.attrs.push(attr);
176        }
177    }
178
179    /// merge to existing attributes if it exist
180    pub fn merge_attributes(
181        &mut self,
182        new_attrs: impl IntoIterator<Item = Attribute<Ns, Att, Val>>,
183    ) {
184        for new_att in new_attrs {
185            if let Some(existing_attr) =
186                self.attrs.iter_mut().find(|att| att.name == new_att.name)
187            {
188                existing_attr.value.extend(new_att.value);
189            } else {
190                self.attrs.push(new_att);
191            }
192        }
193    }
194
195    /// return all the attribute values which the name &Att
196    pub fn attribute_value(&self, name: &Att) -> Option<Vec<&Val>> {
197        let result: Vec<&Val> = self
198            .attrs
199            .iter()
200            .filter(|att| att.name == *name)
201            .flat_map(|att| att.value())
202            .collect();
203
204        if result.is_empty() {
205            None
206        } else {
207            Some(result)
208        }
209    }
210}