perspective_viewer/utils/browser/selection.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
// ┃ This file is part of the Perspective library, distributed under the terms ┃
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
use perspective_js::utils::global;
use wasm_bindgen::JsCast;
use crate::*;
/// Utilities for caret position. DOM elements have different APIs for this
/// but `Deref` makes them fall through, so it is important that this method
/// be called on the correct struct type!
pub trait CaretPosition {
fn select_all(&self) -> ApiResult<()>;
fn set_caret_position(&self, offset: usize) -> ApiResult<()>;
fn get_caret_position(&self) -> Option<u32>;
}
impl CaretPosition for web_sys::HtmlElement {
fn select_all(&self) -> ApiResult<()> {
let range = global::document().create_range()?;
let selection = global::window().get_selection()?.into_apierror()?;
range.set_start(self, 0_u32)?;
range.set_end(self, 10000000_u32)?;
selection.remove_all_ranges()?;
selection.add_range(&range)?;
Ok(())
}
fn set_caret_position(&self, offset: usize) -> ApiResult<()> {
let range = global::document().create_range()?;
let selection = global::window().get_selection()?.into_apierror()?;
range.set_start(self, offset as u32)?;
range.collapse_with_to_start(true);
selection.remove_all_ranges()?;
selection.add_range(&range)?;
Ok(())
}
fn get_caret_position(&self) -> Option<u32> {
maybe! {
let root = self.get_root_node().unchecked_into::<web_sys::Document>();
let selection = root.get_selection()?.into_apierror()?;
if selection.range_count() > 0 {
let range = selection.get_range_at(0)?;
range.end_offset()
} else {
Err(wasm_bindgen::JsValue::UNDEFINED)
}
}
.ok()
}
}
impl CaretPosition for web_sys::HtmlTextAreaElement {
fn select_all(&self) -> ApiResult<()> {
self.set_selection_start(Some(0_u32))?;
self.set_selection_end(Some(1000000000_u32))?;
Ok(())
}
fn set_caret_position(&self, offset: usize) -> ApiResult<()> {
self.set_selection_end(Some(offset as u32))?;
self.set_selection_start(Some(offset as u32))?;
Ok(())
}
fn get_caret_position(&self) -> Option<u32> {
self.selection_end().ok()?
}
}