1//! Utility functions. Intended for internal use only.
23use crate::*;
45/// Get all nodes between `start` and `end`.
6///
7/// If `end` is before `start`, all nodes after `start` will be returned.
8///
9/// The range is exclusive so `start` and `end` will not be included.
10#[must_use]
11pub fn get_nodes_between(start: &web_sys::Node, end: &web_sys::Node) -> Vec<web_sys::Node> {
12let parent = start.parent_node().unwrap();
13debug_assert_eq!(
14 parent,
15 end.parent_node().unwrap(),
16"parents of `start` and `end` do not match"
17);
1819let mut nodes = Vec::new();
2021let mut next = start.next_sibling();
22while let Some(current) = next {
23let tmp = current.next_sibling();
24if ¤t == end {
25break;
26 } else {
27 nodes.push(current);
28 }
29 next = tmp;
30 }
3132 nodes
33}
3435/// Wrap all the nodes in a [`View`] in a document fragment.
36///
37/// This is useful when the view is dynamically changed without being mounted since this will not
38/// update the DOM. Wrapping the nodes in a document fragment will allow you to dynamically update
39/// the view while it is detatched, and then insert it into the DOM later.
40///
41/// This only works on the client side.
42pub fn wrap_in_document_fragment(view: View) -> View {
43let fragment = web_sys::window()
44 .unwrap()
45 .document()
46 .unwrap()
47 .create_document_fragment();
4849for node in view.as_web_sys() {
50 fragment.append_child(&node).unwrap();
51 }
5253 View::from_node(HtmlNode::from_web_sys(fragment.into()))
54}
5556/// Unwraps all the nodes from a document fragment into a flat [`View`].
57///
58/// If the first node of the view is not a document fragment, returns the view.
59pub fn unwrap_from_document_fragment(view: View) -> View {
60if view.nodes.len() != 1 {
61return view;
62 }
63let node = view.nodes[0].as_web_sys();
64if node.node_type() != web_sys::Node::DOCUMENT_FRAGMENT_NODE {
65return view;
66 }
6768let fragment = node.unchecked_ref::<web_sys::DocumentFragment>();
6970let mut nodes = Vec::new();
71let mut next = fragment.first_child();
72while let Some(current) = next {
73 next = current.next_sibling();
74 nodes.push(current);
75 }
7677 View::from_nodes(nodes.into_iter().map(HtmlNode::from_web_sys).collect())
78}
7980/// Create a shallow copy of a view by converting the nodes to web-sys and then converting them
81/// back.
82pub fn clone_nodes_via_web_sys(view: &View) -> View {
83let nodes = view
84 .as_web_sys()
85 .into_iter()
86 .map(HtmlNode::from_web_sys)
87 .collect();
88 View::from_nodes(nodes)
89}