diff options
author | Jon Leighton <j@jonathanleighton.com> | 2017-11-17 21:34:35 +0100 |
---|---|---|
committer | Jon Leighton <j@jonathanleighton.com> | 2017-11-18 22:33:05 +0100 |
commit | 6beda3c76103ee8391b961b457f3e3e364e5f8fe (patch) | |
tree | bb8bd3bd1751adda249d04271dd1d7332b53cde3 /components/script/dom/textcontrol.rs | |
parent | f290cacccddb1a8fd2eaf13c364f08a5ee7afe88 (diff) | |
download | servo-6beda3c76103ee8391b961b457f3e3e364e5f8fe.tar.gz servo-6beda3c76103ee8391b961b457f3e3e364e5f8fe.zip |
Extract common text control selection code
The API for text control selection is the same for both <input> and
<textarea>:
https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#textFieldSelection
Before this change, they had similar but not identical implementations
with duplicate code. Now there is a common TextControl trait which
contains the implementation used by both. As a result, some previously
failing tests now pass.
Diffstat (limited to 'components/script/dom/textcontrol.rs')
-rw-r--r-- | components/script/dom/textcontrol.rs | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/components/script/dom/textcontrol.rs b/components/script/dom/textcontrol.rs new file mode 100644 index 00000000000..0b8870b1996 --- /dev/null +++ b/components/script/dom/textcontrol.rs @@ -0,0 +1,78 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::cell::DomRefCell; +use dom::bindings::conversions::DerivedFrom; +use dom::bindings::str::DOMString; +use dom::event::{EventBubbles, EventCancelable}; +use dom::eventtarget::EventTarget; +use dom::node::{Node, NodeDamage, window_from_node}; +use script_traits::ScriptToConstellationChan; +use textinput::{SelectionDirection, TextInput}; + +pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> { + fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>>; + + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart + fn dom_selection_start(&self) -> u32 { + self.textinput().borrow().get_selection_start() + } + + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart + fn set_dom_selection_start(&self, start: u32) { + self.set_selection_range(start, self.dom_selection_end(), self.selection_direction()); + } + + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend + fn dom_selection_end(&self) -> u32 { + self.textinput().borrow().get_absolute_insertion_point() as u32 + } + + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend + fn set_dom_selection_end(&self, end: u32) { + self.set_selection_range(self.dom_selection_start(), end, self.selection_direction()); + } + + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection + fn dom_selection_direction(&self) -> DOMString { + DOMString::from(self.selection_direction()) + } + + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection + fn set_dom_selection_direction(&self, direction: DOMString) { + self.textinput().borrow_mut().selection_direction = SelectionDirection::from(direction); + } + + // https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange + fn set_dom_selection_range(&self, start: u32, end: u32, direction: Option<DOMString>) { + // Step 4 + let direction = direction.map_or(SelectionDirection::None, |d| SelectionDirection::from(d)); + + self.set_selection_range(start, end, direction); + } + + fn selection_direction(&self) -> SelectionDirection { + self.textinput().borrow().selection_direction + } + + // https://html.spec.whatwg.org/multipage/#set-the-selection-range + fn set_selection_range(&self, start: u32, end: u32, direction: SelectionDirection) { + // Step 5 + self.textinput().borrow_mut().selection_direction = direction; + + // Step 3 + self.textinput().borrow_mut().set_selection_range(start, end); + + // Step 6 + let window = window_from_node(self); + let _ = window.user_interaction_task_source().queue_event( + &self.upcast::<EventTarget>(), + atom!("select"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable, + &window); + + self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); + } +} |