use crate::element::Element;
use crate::props::ClosureProp;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{HtmlElement, Node};
#[doc(hidden)]
pub fn render(rust_fel_element: Element, container: &Node, is_update: bool) {
let window = web_sys::window().expect("no global `window` exists");
let document = window.document().expect("should have a document on window");
if rust_fel_element.html_type == "TEXT_ELEMENT" {
match rust_fel_element.props.text {
Some(text) => {
container
.append_child(&document.create_text_node(&text))
.expect("couldn't append text node");
}
None => (),
};
} else {
let dom_el = document
.create_element(&rust_fel_element.html_type)
.unwrap();
match rust_fel_element.props.text {
Some(text) => {
dom_el
.append_child(&document.create_text_node(&text))
.expect("couldn't append text node");
}
None => (),
};
match rust_fel_element.props.class_name {
Some(class_name) => {
dom_el.set_class_name(&class_name);
}
None => (),
}
match rust_fel_element.props.href {
Some(href) => {
dom_el
.set_attribute("href", &href)
.expect("could not set href");
}
None => (),
}
match rust_fel_element.props.src {
Some(src) => {
dom_el
.set_attribute("src", &src)
.expect("could not set src");
}
None => (),
}
match rust_fel_element.props.type_attr {
Some(type_attr) => {
dom_el
.set_attribute("type", &type_attr)
.expect("could not set type");
}
None => (),
}
match rust_fel_element.props.data_cy {
Some(data_cy) => {
dom_el
.set_attribute("data-cy", &data_cy)
.expect("could not set data-cy");
}
None => (),
}
match rust_fel_element.props.role {
Some(role) => {
dom_el
.set_attribute("role", &role)
.expect("could not set role");
}
None => (),
}
match rust_fel_element.props.on_click {
Some(mut on_click) => {
let closure = Closure::wrap(Box::new(move || on_click()) as ClosureProp);
dom_el
.dyn_ref::<HtmlElement>()
.expect("should be an `HtmlElement`")
.set_onclick(Some(closure.as_ref().unchecked_ref()));
closure.forget();
}
None => (),
}
match rust_fel_element.props.mouse {
Some(mut mouse) => {
let closure = Closure::wrap(Box::new(move || mouse()) as ClosureProp);
dom_el
.dyn_ref::<HtmlElement>()
.expect("should be an `HtmlElement`")
.add_event_listener_with_callback("mouseout", closure.as_ref().unchecked_ref())
.expect("could not add event listener");
closure.forget();
}
None => (),
}
let mut id_copy = None;
match rust_fel_element.props.id {
Some(id) => {
dom_el.set_id(&id);
id_copy = Some(id);
}
None => (),
}
let dom: Node;
if is_update {
let id = &id_copy.unwrap();
let old_child = document
.get_element_by_id(&id)
.unwrap_or_else(|| panic!("Unable to get element by id {}", id));
container
.replace_child(&dom_el, &old_child)
.expect("Unable to replace child");
let new_child: Node = Node::from(
document
.get_element_by_id(&id)
.unwrap_or_else(|| panic!("Unable to get element by id {}", id)),
);
dom = new_child;
} else {
dom = container
.append_child(&dom_el)
.expect("Unable to append child to the container node");
};
match rust_fel_element.props.children {
Some(children) => {
for child in children {
render(child, &dom, false)
}
}
None => (),
}
}
}
pub fn re_render(rust_fel_element: Element, id: Option<String>) {
let window = web_sys::window().expect("no global `window` exists");
let document = window.document().expect("should have a document on window");
if let Some(i) = id {
let child = document
.get_element_by_id(&i)
.expect("should have a root div");
let parent = child.parent_node().unwrap();
render(rust_fel_element, &parent, true);
} else {
panic!("Components that initalize re-renders must have a Id");
}
}