use wasm_bindgen::JsCast;
use crate::dom_types;
use crate::dom_types::El;
fn set_attr_shim(el_ws: &web_sys::Node, at: &dom_types::At, val: &str) {
let mut set_special = false;
let at = at.as_str();
if at == "checked" {
let input_el = el_ws.dyn_ref::<web_sys::HtmlInputElement>();
if let Some(el) = input_el {
match val {
"true" => {
el.set_checked(true);
}
"false" => {
el.set_checked(false);
}
_ => (),
}
set_special = true;
}
}
else if at == "autofocus" {
if let Some(input) = el_ws.dyn_ref::<web_sys::HtmlInputElement>() {
match val {
"true" => {
input.set_autofocus(true);
}
"false" => {
input.set_autofocus(false);
}
_ => (),
}
set_special = true;
}
if let Some(input) = el_ws.dyn_ref::<web_sys::HtmlTextAreaElement>() {
match val {
"true" => {
input.set_autofocus(true);
}
"false" => {
input.set_autofocus(false);
}
_ => (),
}
set_special = true;
}
if let Some(input) = el_ws.dyn_ref::<web_sys::HtmlSelectElement>() {
match val {
"true" => {
input.set_autofocus(true);
}
"false" => {
input.set_autofocus(false);
}
_ => (),
}
set_special = true;
}
if let Some(input) = el_ws.dyn_ref::<web_sys::HtmlButtonElement>() {
match val {
"true" => {
input.set_autofocus(true);
}
"false" => {
input.set_autofocus(false);
}
_ => (),
}
set_special = true;
}
}
if !set_special {
match el_ws.node_type() {
1 => el_ws
.dyn_ref::<web_sys::Element>()
.expect("Problem casting Node as Element while setting an attribute")
.set_attribute(at, val)
.expect("Problem setting an atrribute."),
3 => crate::log("Trying to set attr on text node. Bug?"),
_ => crate::log("Found non el/text node."),
}
}
}
fn set_style(el_ws: &web_sys::Node, style: &dom_types::Style) {
el_ws
.dyn_ref::<web_sys::Element>()
.expect("Problem casting Node as Element while setting style")
.set_attribute("style", &style.to_string())
.expect("Problem setting style");
}
pub fn make_websys_el<Ms: Clone>(
el_vdom: &mut El<Ms>,
document: &web_sys::Document,
) -> web_sys::Node {
if let Some(text) = &el_vdom.text {
return document.create_text_node(&text).into();
}
let tag = el_vdom.tag.as_str();
let el_ws = match el_vdom.namespace {
Some(ref ns) => document
.create_element_ns(Some(ns.as_str()), tag)
.expect("Problem creating web-sys El"),
None => document
.create_element(tag)
.expect("Problem creating web-sys El"),
};
for (at, val) in &el_vdom.attrs.vals {
set_attr_shim(&el_ws, at, val);
}
if let Some(ns) = &el_vdom.namespace {
el_ws
.dyn_ref::<web_sys::Element>()
.expect("Problem casting Node as Element while setting an attribute")
.set_attribute("xmlns", ns.as_str())
.expect("Problem setting xlmns attribute");
}
if el_vdom.style.vals.keys().len() > 0 {
set_style(&el_ws, &el_vdom.style)
}
el_ws.into()
}
pub fn attach_children<Ms: Clone>(el_vdom: &mut El<Ms>) {
let el_ws = el_vdom
.el_ws
.take()
.expect("Missing websys el in attach children");
for child in &mut el_vdom.children {
attach_el_and_children(child, &el_ws)
}
el_vdom.el_ws.replace(el_ws);
}
pub fn attach_el_and_children<Ms: Clone>(el_vdom: &mut El<Ms>, parent: &web_sys::Node) {
if el_vdom.empty {
return;
}
let el_ws = el_vdom.el_ws.take().expect("Missing websys el");
match parent.append_child(&el_ws) {
Ok(_) => {}
Err(_) => {
crate::log("Minor problem with html element (append)");
}
}
for child in &mut el_vdom.children {
attach_el_and_children(child, &el_ws)
}
if let Some(mount_actions) = &mut el_vdom.hooks.did_mount {
mount_actions(&el_ws)
}
el_vdom.el_ws.replace(el_ws);
}
pub fn _remove_children(el: &web_sys::Node) {
while let Some(child) = el.last_child() {
el.remove_child(&child).expect("Problem removing child");
}
}
pub fn patch_el_details<Ms: Clone>(old: &mut El<Ms>, new: &mut El<Ms>, old_el_ws: &web_sys::Node) {
if let Some(update_actions) = &mut old.hooks.did_update {
update_actions(old_el_ws)
}
if old.attrs != new.attrs {
for (key, new_val) in &new.attrs.vals {
match old.attrs.vals.get(key) {
Some(old_val) => {
if old_val != new_val {
set_attr_shim(&old_el_ws, key, new_val);
}
}
None => set_attr_shim(&old_el_ws, key, new_val),
}
}
for name in old.attrs.vals.keys() {
if new.attrs.vals.get(name).is_none() {
match old_el_ws.dyn_ref::<web_sys::Element>() {
Some(el) => el
.remove_attribute(name.as_str())
.expect("Removing an attribute"),
None => crate::log("Minor error on html element (setting attrs)"),
}
}
}
}
if old.style != new.style {
set_style(&old_el_ws, &new.style)
}
if old.text != new.text {
match new.text.clone() {
Some(text) => old_el_ws.set_text_content(Some(&text)),
None => old_el_ws.set_text_content(None),
}
}
}
pub fn to_input(target: &web_sys::EventTarget) -> &web_sys::HtmlInputElement {
target
.dyn_ref::<web_sys::HtmlInputElement>()
.expect("Unable to cast as an input element")
}
pub fn to_textarea(target: &web_sys::EventTarget) -> &web_sys::HtmlTextAreaElement {
target
.dyn_ref::<web_sys::HtmlTextAreaElement>()
.expect("Unable to cast as a textarea element")
}
pub fn to_select(target: &web_sys::EventTarget) -> &web_sys::HtmlSelectElement {
target
.dyn_ref::<web_sys::HtmlSelectElement>()
.expect("Unable to cast as a select element")
}
pub fn to_html_el(target: &web_sys::EventTarget) -> &web_sys::HtmlElement {
target
.dyn_ref::<web_sys::HtmlElement>()
.expect("Unable to cast as an HTML element")
}
pub fn to_kbevent(event: &web_sys::Event) -> &web_sys::KeyboardEvent {
event
.dyn_ref::<web_sys::KeyboardEvent>()
.expect("Unable to cast as a keyboard event")
}
pub fn to_mouse_event(event: &web_sys::Event) -> &web_sys::MouseEvent {
event
.dyn_ref::<web_sys::MouseEvent>()
.expect("Unable to cast as a mouse event")
}
pub fn el_from_ws<Ms>(node: &web_sys::Node) -> Option<El<Ms>> {
match node.node_type() {
1 => {
let el_ws = node
.dyn_ref::<web_sys::Element>()
.expect("Problem casting Node as Element");
let mut result = match el_ws.tag_name().to_lowercase().as_ref() {
"svg" => El::empty_svg(el_ws.tag_name().to_lowercase().into()),
_ => El::empty(el_ws.tag_name().to_lowercase().into()),
};
let mut attrs = dom_types::Attrs::empty();
el_ws
.get_attribute_names()
.for_each(&mut |attr_name, _, _| {
let attr_name2 = attr_name
.as_string()
.expect("problem converting attr to string");
if let Some(attr_val) = el_ws.get_attribute(&attr_name2) {
attrs.add(attr_name2.into(), &attr_val);
}
});
result.attrs = attrs;
if let Some(ns) = el_ws.namespace_uri() {
result.namespace = Some(ns.into());
}
let children = el_ws.child_nodes();
for i in 0..children.length() {
let child = children
.get(i)
.expect("Can't find child in raw html element.");
if let Some(child_vdom) = el_from_ws(&child) {
result.children.push(child_vdom);
}
}
Some(result)
}
3 => {
Some(El::new_text(&node.text_content().expect("Can't find text")))
}
_ => {
crate::log("Unexpected node type found from raw html");
None
}
}
}