use std::sync::Mutex; use wasm_bindgen::prelude::*; use web_sys::{console, Event, HtmlElement, HtmlInputElement}; use anagrams::{AnagramDict, Dict}; static DICTIONNARY: Mutex> = Mutex::new(None); fn window() -> web_sys::Window { web_sys::window().expect("no global `window` exists") } fn document() -> web_sys::Document { window() .document() .expect("should have a document on window") } fn display_spinner() { let result = document() .get_element_by_id("spinner") .expect("#spinner not found"); let style = result .dyn_ref::() .expect("Failed to cast #spinner to HtmlElement") .style(); style .set_property("display", "inline-block") .expect("Failed to edit #spinner's CSS"); } fn hide_spinner() { let result = document() .get_element_by_id("spinner") .expect("#spinner not found"); let style = result .dyn_ref::() .expect("Failed to cast #spinner to HtmlElement") .style(); style .set_property("display", "none") .expect("Failed to edit #spinner's CSS"); } fn hide_ask_dict() { let result = document() .get_element_by_id("ask_dict") .expect("#ask_dic not found"); let style = result .dyn_ref::() .expect("Failed to cast #ask_dict to HtmlElement") .style(); console::log_1(&style); style .set_property("display", "none") .expect("Failed to edit #ask_dict's CSS"); } fn update_letters() { let el = document() .get_element_by_id("select_word") .expect("#select_word not found"); let val = el .dyn_ref::() .expect("Failed to dyn cast to HtmlInputElement") .value(); let result = document() .get_element_by_id("result") .expect("#result not found"); while let Some(child) = result.first_element_child() { child.remove(); } DICTIONNARY .lock() .expect("Failed to access DICTIONNARY") .as_ref() .map(|dict| dict.find(&val)) .flatten() .map(|anagrms| { for anagram in anagrms { let val = document().create_element("li").unwrap(); val.set_text_content(Some(&anagram)); result.append_child(&val).unwrap(); } }); } fn load_dict(text: JsValue) { display_spinner(); let text = text.as_string().expect("Failed to get content of the file"); let el = document() .get_element_by_id("nb_wild_card") .expect("#nb_wild_card not found"); let nb_wild_card = el .dyn_ref::() .expect("Failed to dyn cast #nb_wild_card to HtmlInputElement") .value(); console::log_1(&(&nb_wild_card).into()); let dict = Dict::load_from_str( &text, nb_wild_card .parse() .expect("#nb_wild_card should be an interger"), '?', ); *DICTIONNARY.lock().expect("Failed to access DICTIONNARY") = Some((&dict).into()); hide_spinner(); hide_ask_dict(); update_letters(); } // Called when the wasm module is instantiated #[wasm_bindgen(start)] fn main() -> Result<(), JsValue> { let load_dict_c1 = Closure::::new(move |text: JsValue| load_dict(text)); let load_dict_c2 = Closure::::new(move |text: JsValue| load_dict(text)); let update_dict = Closure::::new(move |event: Event| { display_spinner(); let target = event.target().expect("No target"); let _ = target .dyn_ref::() .expect("Failed to dyn cast to HtmlInputElement") .files() .expect("Failed to get files") .get(0) .expect("Failed to get first file") .text() .then(&load_dict_c1); }); let update_nb_wild_card = Closure::::new(move |_: Event| { let el = document() .get_element_by_id("upload_dict") .expect("#upload_dict not found"); let files = el .dyn_ref::() .expect("Failed to dyn cast to HtmlInputElement") .files() .expect("Failed to get files"); if files.length() > 0 { display_spinner(); let _ = files .get(0) .expect("Failed to get first file") .text() .then(&load_dict_c2); } }); let update_letters_closure = Closure::::new(|_: Event| update_letters()); let input_dict = document() .get_element_by_id("upload_dict") .expect("#upload_dict not found"); input_dict .dyn_ref::() .expect("#upload_dict must be an ") .add_event_listener_with_callback("change", update_dict.as_ref().unchecked_ref()) .expect("Failed to register event listener to #upload_dict"); let input_text = document() .get_element_by_id("select_word") .expect("#select_word not found"); input_text .dyn_ref::() .expect("#select_word must be an ") .add_event_listener_with_callback("input", update_letters_closure.as_ref().unchecked_ref()) .expect("Failed to register event listener to #select_word"); let nb_wild_card = document() .get_element_by_id("nb_wild_card") .expect("#nb_wild_card not found"); nb_wild_card .dyn_ref::() .expect("#nb_wild_card must be an ") .add_event_listener_with_callback("change", update_nb_wild_card.as_ref().unchecked_ref()) .expect("Failed to register event listener to #nb_wild_card"); update_dict.forget(); // The callback will invalidate when the closure is dropped, this prevent it, // at the cost of a "memory leak" update_letters_closure.forget(); update_nb_wild_card.forget(); Ok(()) }