Skip to main content

virtual_node/
velement.rs

1use crate::event::{Events, RealDom};
2use crate::VirtualNode;
3use std::collections::HashMap;
4use std::fmt;
5
6pub use self::attribute_value::*;
7pub use self::special_attributes::*;
8
9mod attribute_value;
10mod special_attributes;
11
12pub struct VirtualElement<Handle: RealDom> {
13    /// The HTML tag, such as "div"
14    pub tag: String,
15    /// HTML attributes such as id, class, style, etc
16    pub attrs: HashMap<String, AttributeValue>,
17    /// Events that will get added to your real DOM element via `.addEventListener`
18    ///
19    /// Events natively handled in HTML such as onclick, onchange, oninput and others
20    /// can be found in [`VElement.known_events`]
21    pub events: Events<Handle>,
22    /// The children of this `VirtualNode`. So a <div> <em></em> </div> structure would
23    /// have a parent div and one child, em.
24    pub children: Vec<VirtualNode<Handle>>,
25    /// See [`SpecialAttributes`]
26    pub special_attributes: SpecialAttributes,
27}
28
29impl<Handle: RealDom> PartialEq for VirtualElement<Handle> {
30    fn eq(&self, other: &Self) -> bool {
31        let VirtualElement {
32            tag: lhs_tag,
33            attrs: lhs_attrs,
34            events: lhs_events,
35            children: lhs_children,
36            special_attributes: lhs_special_attributes,
37        } = self;
38        let VirtualElement {
39            tag: rhs_tag,
40            attrs: rhs_attrs,
41            events: rhs_events,
42            children: rhs_children,
43            special_attributes: rhs_special_attributes,
44        } = other;
45
46        lhs_tag == rhs_tag
47            && lhs_attrs == rhs_attrs
48            && lhs_events == rhs_events
49            && lhs_children == rhs_children
50            && lhs_special_attributes == rhs_special_attributes
51    }
52}
53
54impl<Handle: RealDom> VirtualElement<Handle> {
55    pub fn new(tag: impl Into<String>) -> VirtualElement<Handle> {
56        VirtualElement {
57            tag: tag.into(),
58            attrs: HashMap::new(),
59            events: Events::new(),
60            children: vec![],
61            special_attributes: SpecialAttributes::default(),
62        }
63    }
64}
65
66impl<Handle: RealDom> fmt::Debug for VirtualElement<Handle> {
67    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68        write!(
69            f,
70            "Element(<{}>, attrs: {:?}, children: {:?})",
71            self.tag, self.attrs, self.children,
72        )
73    }
74}
75
76impl<Handle: RealDom> fmt::Display for VirtualElement<Handle> {
77    // Turn a VElement and all of it's children (recursively) into an HTML string
78    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79        write!(f, "<{}", self.tag).unwrap();
80
81        for (attr, value) in self.attrs.iter() {
82            match value {
83                AttributeValue::String(value_str) => {
84                    write!(f, r#" {}="{}""#, attr, value_str)?;
85                }
86                AttributeValue::Bool(value_bool) => {
87                    if *value_bool {
88                        write!(f, " {}", attr)?;
89                    }
90                }
91            }
92        }
93
94        write!(f, ">")?;
95
96        for child in self.children.iter() {
97            write!(f, "{}", child.to_string())?;
98        }
99
100        if !html_validation::is_self_closing(&self.tag) {
101            write!(f, "</{}>", self.tag)?;
102        }
103
104        Ok(())
105    }
106}