1use wasm_bindgen::UnwrapThrowExt;
2
3pub mod window {
4 use js_sys::Function;
5 use wasm_bindgen::{JsValue, UnwrapThrowExt};
6
7 use super::WINDOW;
8
9 pub fn request_animation_frame(callback: &::js_sys::Function) {
10 WINDOW.with(|win| win.request_animation_frame(callback).unwrap_throw());
11 }
12
13 pub fn history() -> web_sys::History {
14 WINDOW.with(|win| win.history().unwrap_throw())
15 }
16
17 pub fn location() -> web_sys::Location {
18 WINDOW.with(|win| win.location())
19 }
20
21 pub fn set_onpopstate(value: Option<&Function>) {
22 WINDOW.with(|win| win.set_onpopstate(value));
23 }
24
25 pub fn local_storage() -> Result<web_sys::Storage, JsValue> {
26 WINDOW.with(|w| w.local_storage().map(|w| w.unwrap_throw()))
27 }
28
29 pub fn session_storage() -> Result<web_sys::Storage, JsValue> {
30 WINDOW.with(|w| w.session_storage().map(|w| w.unwrap_throw()))
31 }
32
33 pub fn performance() -> Option<web_sys::Performance> {
34 WINDOW.with(|w| w.performance())
35 }
36}
37
38pub mod document {
39 use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt};
40 use web_sys::HtmlBaseElement;
41
42 use super::DOCUMENT;
43
44 pub fn get_element_by_id(id: &str) -> Option<web_sys::Element> {
45 DOCUMENT.with(|doc| doc.get_element_by_id(id))
46 }
47
48 pub fn create_element(tag: &str) -> web_sys::Element {
49 DOCUMENT.with(|doc| doc.create_element(tag).unwrap_throw())
50 }
51
52 pub fn create_element_ns(namespace: &str, tag: &str) -> web_sys::Element {
53 DOCUMENT.with(|doc| doc.create_element_ns(Some(namespace), tag).unwrap_throw())
54 }
55
56 pub fn create_text_node(text: &str) -> web_sys::Text {
57 DOCUMENT.with(|doc| doc.create_text_node(text))
58 }
59
60 pub fn base_uri() -> Option<String> {
61 DOCUMENT
62 .with(|doc| doc.query_selector("base[href]"))
63 .unwrap_throw()
64 .map(|base_elem| {
65 base_elem
66 .dyn_into::<HtmlBaseElement>()
67 .unwrap_throw()
68 .href()
69 })
70 }
71
72 pub fn query_selector(selectors: &str) -> Result<Option<web_sys::Element>, JsValue> {
73 DOCUMENT.with(|doc| doc.query_selector(selectors))
74 }
75
76 pub fn head() -> Option<web_sys::HtmlHeadElement> {
77 DOCUMENT.with(|doc| doc.head())
78 }
79
80 pub fn body() -> Option<web_sys::HtmlElement> {
81 DOCUMENT.with(|doc| doc.body())
82 }
83}
84
85pub trait GlobalEventTarget {
86 fn add_event_listener_with_callback(name: &'static str, listener: &::js_sys::Function);
87
88 fn remove_event_listener_with_callback(name: &'static str, listener: &::js_sys::Function);
89}
90
91pub struct Document;
92
93impl GlobalEventTarget for Document {
94 fn add_event_listener_with_callback(name: &'static str, listener: &::js_sys::Function) {
95 DOCUMENT.with(|doc| {
96 doc.add_event_listener_with_callback(name, listener)
97 .unwrap_throw()
98 })
99 }
100
101 fn remove_event_listener_with_callback(name: &'static str, listener: &::js_sys::Function) {
102 DOCUMENT.with(|doc| {
103 doc.remove_event_listener_with_callback(name, listener)
104 .unwrap_throw()
105 })
106 }
107}
108
109pub struct Window;
110
111impl GlobalEventTarget for Window {
112 fn add_event_listener_with_callback(name: &'static str, listener: &::js_sys::Function) {
113 WINDOW.with(|win| {
114 win.add_event_listener_with_callback(name, listener)
115 .unwrap_throw()
116 })
117 }
118
119 fn remove_event_listener_with_callback(name: &'static str, listener: &::js_sys::Function) {
120 WINDOW.with(|win| {
121 win.remove_event_listener_with_callback(name, listener)
122 .unwrap_throw()
123 })
124 }
125}
126
127thread_local!(
128 static WINDOW: web_sys::Window = web_sys::window().expect_throw("Window must be available");
129 static DOCUMENT: web_sys::Document = WINDOW.with(|win| {
130 win.document()
131 .expect_throw("Window must contain a document")
132 });
133);