virtual_node/
create_element.rs1use js_sys::Reflect;
2use std::cell::RefCell;
3use std::rc::Rc;
4use wasm_bindgen::JsValue;
5use web_sys::{Document, Element};
6
7use crate::event::{VirtualEventElement, VirtualEvents};
8use crate::{AttributeValue, VElement, VirtualEventNode, VirtualNode};
9
10mod add_events;
11
12#[doc(hidden)]
14pub const VIRTUAL_NODE_MARKER_PROPERTY: &'static str = "__v__";
15
16impl VElement {
17 pub(crate) fn create_element_node(
20 &self,
21 events: &mut VirtualEvents,
22 ) -> (Element, VirtualEventNode) {
23 let document = web_sys::window().unwrap().document().unwrap();
24
25 let element = if html_validation::is_svg_namespace(&self.tag) {
26 document
27 .create_element_ns(Some("http://www.w3.org/2000/svg"), &self.tag)
28 .unwrap()
29 } else {
30 document.create_element(&self.tag).unwrap()
31 };
32 set_virtual_node_marker(&element);
33
34 self.attrs.iter().for_each(|(name, value)| {
35 match value {
36 AttributeValue::String(s) => {
37 element.set_attribute(name, s).unwrap();
38 }
39 AttributeValue::Bool(b) => {
40 if *b {
41 element.set_attribute(name, "").unwrap();
42 }
43 }
44 };
45 });
46
47 let mut event_elem = events.create_element_node();
48 self.add_events(
49 &element,
50 events,
51 event_elem.as_element().unwrap().events_id(),
52 );
53
54 self.append_children_to_dom(
55 &element,
56 &document,
57 event_elem.as_element_mut().unwrap(),
58 events,
59 );
60
61 self.special_attributes
62 .maybe_call_on_create_element(&element);
63
64 if let Some(inner_html) = &self.special_attributes.dangerous_inner_html {
65 element.set_inner_html(inner_html);
66 }
67
68 (element, event_elem)
69 }
70}
71
72impl VElement {
73 fn append_children_to_dom(
74 &self,
75 element: &Element,
76 document: &Document,
77 event_node: &mut VirtualEventElement,
78 events: &mut VirtualEvents,
79 ) {
80 let mut previous_node_was_text = false;
81
82 self.children.iter().for_each(|child| {
83 let child_events_node = match child {
84 VirtualNode::Text(text_node) => {
85 let current_node = element.as_ref() as &web_sys::Node;
86
87 if previous_node_was_text {
94 let separator = document.create_comment("ptns");
95 set_virtual_node_marker(&separator);
96 current_node
97 .append_child(separator.as_ref() as &web_sys::Node)
98 .unwrap();
99 }
100
101 current_node
102 .append_child(&text_node.create_text_node())
103 .unwrap();
104
105 previous_node_was_text = true;
106
107 events.create_text_node()
108 }
109 VirtualNode::Element(element_node) => {
110 previous_node_was_text = false;
111
112 let (child, child_events) = element_node.create_element_node(events);
113 let child_elem: Element = child;
114
115 element.append_child(&child_elem).unwrap();
116
117 child_events
118 }
119 };
120
121 let child_events_node = Rc::new(RefCell::new(child_events_node));
122 event_node.append_child(child_events_node.clone());
123 });
124 }
125}
126
127pub(crate) fn set_virtual_node_marker(node: &JsValue) {
129 let unused_data = 123;
130
131 Reflect::set(
132 &node.into(),
133 &VIRTUAL_NODE_MARKER_PROPERTY.into(),
134 &unused_data.into(),
135 )
136 .unwrap();
137}