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