perspective_viewer/utils/browser/
selection.rs1use perspective_js::utils::global;
14use wasm_bindgen::JsCast;
15
16use crate::*;
17
18pub trait CaretPosition {
22 fn select_all(&self) -> ApiResult<()>;
23 fn set_caret_position(&self, offset: usize) -> ApiResult<()>;
24 fn get_caret_position(&self) -> Option<u32>;
25}
26
27impl CaretPosition for web_sys::HtmlElement {
28 fn select_all(&self) -> ApiResult<()> {
29 let range = global::document().create_range()?;
30 let selection = global::window().get_selection()?.into_apierror()?;
31 range.set_start(self, 0_u32)?;
32 range.set_end(self, 10000000_u32)?;
33 selection.remove_all_ranges()?;
34 selection.add_range(&range)?;
35 Ok(())
36 }
37
38 fn set_caret_position(&self, offset: usize) -> ApiResult<()> {
39 let range = global::document().create_range()?;
40 let selection = global::window().get_selection()?.into_apierror()?;
41 range.set_start(self, offset as u32)?;
42 range.collapse_with_to_start(true);
43 selection.remove_all_ranges()?;
44 selection.add_range(&range)?;
45 Ok(())
46 }
47
48 fn get_caret_position(&self) -> Option<u32> {
49 maybe! {
50 let root = self.get_root_node().unchecked_into::<web_sys::Document>();
51 let selection = root.get_selection()?.into_apierror()?;
52 if selection.range_count() > 0 {
53 let range = selection.get_range_at(0)?;
54 range.end_offset()
55 } else {
56 Err(wasm_bindgen::JsValue::UNDEFINED)
57 }
58 }
59 .ok()
60 }
61}
62
63impl CaretPosition for web_sys::HtmlTextAreaElement {
64 fn select_all(&self) -> ApiResult<()> {
65 self.set_selection_start(Some(0_u32))?;
66 self.set_selection_end(Some(1000000000_u32))?;
67 Ok(())
68 }
69
70 fn set_caret_position(&self, offset: usize) -> ApiResult<()> {
71 self.set_selection_end(Some(offset as u32))?;
72 self.set_selection_start(Some(offset as u32))?;
73 Ok(())
74 }
75
76 fn get_caret_position(&self) -> Option<u32> {
77 self.selection_end().ok()?
78 }
79}