1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use wasm_bindgen::UnwrapThrowExt;

mod attributes;
mod element;
mod node;
mod nodes;
mod text;

pub use attributes::*;
pub use element::*;
pub use node::*;
pub use nodes::*;
pub use text::*;

#[cfg(feature = "keyed-list")]
mod keyed_list;
#[cfg(feature = "keyed-list")]
pub use keyed_list::*;

pub trait ElementTag: Copy {
    const NAMESPACE: &'static str;
    fn tag_name(&self) -> &str;
}

pub enum TagName {
    Html(crate::render::html::HtmlTag),
    #[cfg(feature = "svg")]
    Svg(crate::render::svg::SvgTag),
}

pub trait AChildNode {
    fn ws_node(&self) -> &web_sys::Node;

    fn append_to(&self, parent: &web_sys::Node) {
        parent
            .append_child(self.ws_node())
            .expect_throw("AChildNode::append_to");
    }

    fn insert_before_a_sibling(
        &self,
        parent: &web_sys::Node,
        next_sibling: Option<&web_sys::Node>,
    ) {
        parent
            .insert_before(self.ws_node(), next_sibling)
            .expect_throw("AChildNode::insert_before");
    }

    fn remove_from(&self, parent: &web_sys::Node) {
        parent
            .remove_child(self.ws_node())
            .expect_throw("AChildNode::remove_from");
    }
}

impl AChildNode for web_sys::Node {
    fn ws_node(&self) -> &web_sys::Node {
        self
    }
}

pub trait MaybeAChildNode {
    fn ws_node(&self) -> Option<&web_sys::Node>;

    fn append_to(&self, parent: &web_sys::Node) {
        if let Some(node) = self.ws_node() {
            node.append_to(parent);
        }
    }

    fn insert_before_a_sibling(
        &self,
        parent: &web_sys::Node,
        next_sibling: Option<&web_sys::Node>,
    ) {
        if let Some(node) = self.ws_node() {
            node.insert_before_a_sibling(parent, next_sibling);
        }
    }

    fn remove_from(&self, parent: &web_sys::Node) {
        if let Some(node) = self.ws_node() {
            node.remove_from(parent);
        }
    }
}

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum ElementStatus {
    JustCreated,
    Existing,
    JustCloned,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ElementType {
    Select,
    Input,
    Option,
    TextArea,
    Other,
}

impl From<&str> for ElementType {
    fn from(tag: &str) -> Self {
        match tag {
            "select" => Self::Select,
            "input" => Self::Input,
            "option" => Self::Option,
            "textarea" => Self::TextArea,
            _ => Self::Other,
        }
    }
}