1use std::fmt;
4use std::rc::Rc;
5
6use wasm_bindgen::JsCast;
7use web_sys::{Node, Text};
8
9use crate::reactive::VecDiff;
10use crate::TemplateResult;
11use crate::{internal::*, TemplateList};
12
13pub trait Render {
15 fn render(&self) -> Node;
17
18 fn update_node(&self, parent: &Node, node: &Node) -> Node {
25 let new_node = self.render();
26 parent.replace_child(&new_node, &node).unwrap();
27 new_node
28 }
29}
30
31impl<T: fmt::Display + ?Sized> Render for T {
32 fn render(&self) -> Node {
33 web_sys::window()
34 .unwrap()
35 .document()
36 .unwrap()
37 .create_text_node(&format!("{}", self))
38 .into()
39 }
40
41 fn update_node(&self, _parent: &Node, node: &Node) -> Node {
42 node.clone()
44 .dyn_into::<Text>()
45 .unwrap()
46 .set_text_content(Some(&format!("{}", self)));
47
48 node.clone()
49 }
50}
51
52impl Render for TemplateList {
53 fn render(&self) -> Node {
54 let fragment = fragment();
55
56 for item in self
57 .templates
58 .inner_signal()
59 .get()
60 .borrow()
61 .clone()
62 .into_iter()
63 {
64 append_render(
65 &fragment,
66 Box::new(move || {
67 let item = item.clone();
68 Box::new(item)
69 }),
70 );
71 }
72
73 fragment.into()
74 }
75
76 fn update_node(&self, parent: &Node, node: &Node) -> Node {
77 let templates = self.templates.inner_signal().get(); let changes = Rc::clone(&self.templates.changes());
79
80 for change in changes.borrow().iter() {
81 match change {
82 VecDiff::Replace { values } => {
83 let first = templates.borrow().first().map(|x| x.node.clone());
84
85 for value in values {
86 parent.insert_before(&value.node, first.as_ref()).unwrap();
87 }
88
89 for template in templates.borrow().iter() {
90 parent.remove_child(&template.node).unwrap();
91 }
92 }
93 VecDiff::Insert { index, value } => {
94 parent
95 .insert_before(
96 &value.node,
97 templates
98 .borrow()
99 .get(*index)
100 .map(|template| template.node.next_sibling())
101 .flatten()
102 .as_ref(),
103 )
104 .unwrap();
105 }
106 VecDiff::Update { index, value } => {
107 parent
108 .replace_child(&templates.borrow()[*index].node, &value.node)
109 .unwrap();
110 }
111 VecDiff::Remove { index } => {
112 parent
113 .remove_child(&templates.borrow()[*index].node)
114 .unwrap();
115 }
116 VecDiff::Swap { index1, index2 } => {
117 let child1 = &templates.borrow()[*index1].node;
118 let child2 = &templates.borrow()[*index2].node;
119 parent.replace_child(child1, child2).unwrap();
120 parent.replace_child(child2, child1).unwrap();
121 }
122 VecDiff::Push { value } => {
123 parent
124 .insert_before(
125 &value.node,
126 templates
127 .borrow()
128 .last()
129 .map(|last| last.node.next_sibling())
130 .flatten()
131 .as_ref(),
132 )
133 .unwrap();
134 }
135 VecDiff::Pop => {
136 if let Some(last) = templates.borrow().last() {
137 parent.remove_child(&last.node).unwrap();
138 }
139 }
140 VecDiff::Clear => {
141 for template in templates.borrow().iter() {
142 parent.remove_child(&template.node).unwrap();
143 }
144 }
145 }
146 }
147
148 node.clone()
149 }
150}
151
152impl Render for TemplateResult {
153 fn render(&self) -> Node {
154 self.node.clone()
155 }
156}