use futures::{future::FutureExt, pin_mut, select}; use web_sys::{Element, HtmlDialogElement, Node}; use crate::{ on_click, utils::{SelectorExt, by_id, selector_and_clone}, }; /// Show a modal dialog with a copy of the given HTML element as content. pub async fn show(element_selector: &str) -> bool { show_and_initialize(element_selector, async |_| Some(())) .await .is_some() } /// Show a modal dialog with a copy of the given HTML element as content and execute an initilizer /// to modify the given content. pub async fn show_and_initialize(element_selector: &str, initializer: T) -> Option where T: AsyncFn(Element) -> U, { show_and_initialize_with_ok(element_selector, initializer, |_, result| result).await } /// Show a modal dialog with a copy of the given HTML element as content and execute an initilizer /// to modify the given content. /// Call the given function when OK is pressed. pub async fn show_and_initialize_with_ok( element_selector: &str, initializer: FInit, ok: FOk, ) -> Option where FInit: AsyncFn(Element) -> TInit, FOk: Fn(Element, TInit) -> TOk, { let dialog: HtmlDialogElement = by_id("modal-dialog"); let content_element = dialog.selector::(".content"); let element: Element = selector_and_clone(element_selector); content_element.set_inner_html(""); content_element.append_child(&element).unwrap(); let init_result = initializer(element.clone()).await; let input_ok: Element = dialog.selector(".ok"); let input_cancel: Element = dialog.selector(".cancel"); dialog.show_modal().unwrap(); let click_ok = on_click::OnClick::new(&input_ok).fuse(); let click_cancel = on_click::OnClick::new(&input_cancel).fuse(); let dialog_cloned = dialog.clone(); let click_dialog = on_click::OnClick::new_with_filter(&dialog, move |node| node == &dialog_cloned as &Node) .fuse(); pin_mut!(click_ok, click_cancel, click_dialog); let result = select! { () = click_ok => Some(ok(element, init_result)), () = click_cancel => None, () = click_dialog => None, }; dialog.close(); result }