diff options
author | Jon Leighton <j@jonathanleighton.com> | 2017-12-02 10:53:50 +0100 |
---|---|---|
committer | Jon Leighton <j@jonathanleighton.com> | 2017-12-08 21:07:05 +0100 |
commit | 71a013dd5018294f507c7047ca0d4fd700b555f1 (patch) | |
tree | 86bdd1d4f1a1676b1e973d2c047abd2b7c519c5b /components/script/dom/textcontrol.rs | |
parent | e64647188879b8269b62c1d5c8aa05732ab9d96d (diff) | |
download | servo-71a013dd5018294f507c7047ca0d4fd700b555f1.tar.gz servo-71a013dd5018294f507c7047ca0d4fd700b555f1.zip |
Handle cases where selection API doesn't apply
The selection API only applies to certain <input> types:
https://html.spec.whatwg.org/multipage/#do-not-apply
This commit ensures that we handle that correctly.
Some notes:
1. TextControl::set_dom_selection_direction now calls
set_selection_range(), which means that setting selectionDirection will
now fire a selection event, as it should per the spec.
2. There is a test for the firing of the select event in
tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/select-event.html,
however the test did not run due to this syntax error:
(pid:26017) "ERROR:script::dom::bindings::error: Error at http://web-platform.test:8000/html/semantics/forms/textfieldselection/select-event.html:50:11 missing = in const declaration"
This happens due to the us of the "for (const foo of ...)" construct.
Per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
this should actually work, so it's somewhat unsatisfying to have to
change the test.
4. If an <input>'s type is unset, it defaults to a text, and the
selection API applies. Also, if an <input>'s type is set to an
invalid value, it defaults to a text too. I've expanded the tests
to account for this second case.
Diffstat (limited to 'components/script/dom/textcontrol.rs')
-rw-r--r-- | components/script/dom/textcontrol.rs | 108 |
1 files changed, 84 insertions, 24 deletions
diff --git a/components/script/dom/textcontrol.rs b/components/script/dom/textcontrol.rs index 2b47fcd00a4..9143c2bda23 100644 --- a/components/script/dom/textcontrol.rs +++ b/components/script/dom/textcontrol.rs @@ -4,6 +4,7 @@ use dom::bindings::cell::DomRefCell; use dom::bindings::conversions::DerivedFrom; +use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::str::DOMString; use dom::event::{EventBubbles, EventCancelable}; use dom::eventtarget::EventTarget; @@ -13,52 +14,108 @@ use textinput::{SelectionDirection, TextInput}; pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> { fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>>; + fn selection_api_applies(&self) -> bool; // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart - fn dom_selection_start(&self) -> u32 { - self.textinput().borrow().get_selection_start() + fn get_dom_selection_start(&self) -> Option<u32> { + // Step 1 + if !self.selection_api_applies() { + return None; + } + + // Steps 2-3 + Some(self.selection_start()) } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart - fn set_dom_selection_start(&self, start: u32) { + fn set_dom_selection_start(&self, start: Option<u32>) -> ErrorResult { + // Step 1 + if !self.selection_api_applies() { + return Err(Error::InvalidState); + } + // Step 2 - let mut end = self.dom_selection_end(); + let mut end = self.selection_end(); // Step 3 - if end < start { - end = start; + if let Some(s) = start { + if end < s { + end = s; + } } // Step 4 - self.set_selection_range(start, end, self.selection_direction()); + self.set_selection_range(start, Some(end), Some(self.selection_direction())); + Ok(()) } // 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 + fn get_dom_selection_end(&self) -> Option<u32> { + // Step 1 + if !self.selection_api_applies() { + return None; + } + + // Steps 2-3 + Some(self.selection_end()) } // 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()); + fn set_dom_selection_end(&self, end: Option<u32>) -> ErrorResult { + // Step 1 + if !self.selection_api_applies() { + return Err(Error::InvalidState); + } + + // Step 2 + self.set_selection_range(Some(self.selection_start()), end, Some(self.selection_direction())); + Ok(()) } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection - fn dom_selection_direction(&self) -> DOMString { - DOMString::from(self.selection_direction()) + fn get_dom_selection_direction(&self) -> Option<DOMString> { + // Step 1 + if !self.selection_api_applies() { + return None; + } + + Some(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); + fn set_dom_selection_direction(&self, direction: Option<DOMString>) -> ErrorResult { + // Step 1 + if !self.selection_api_applies() { + return Err(Error::InvalidState); + } + + // Step 2 + self.set_selection_range( + Some(self.selection_start()), + Some(self.selection_end()), + direction.map(|d| SelectionDirection::from(d)) + ); + Ok(()) } // 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)); + fn set_dom_selection_range(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult { + // Step 1 + if !self.selection_api_applies() { + return Err(Error::InvalidState); + } + + // Step 2 + self.set_selection_range(Some(start), Some(end), direction.map(|d| SelectionDirection::from(d))); + Ok(()) + } - self.set_selection_range(start, end, direction); + fn selection_start(&self) -> u32 { + self.textinput().borrow().get_selection_start() + } + + fn selection_end(&self) -> u32 { + self.textinput().borrow().get_absolute_insertion_point() as u32 } fn selection_direction(&self) -> SelectionDirection { @@ -66,12 +123,15 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> { } // 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; + fn set_selection_range(&self, start: Option<u32>, end: Option<u32>, direction: Option<SelectionDirection>) { + // Step 1 + let start = start.unwrap_or(0); - // Step 3 - self.textinput().borrow_mut().set_selection_range(start, end); + // Step 2 + let end = end.unwrap_or(0); + + // Steps 3-5 + self.textinput().borrow_mut().set_selection_range(start, end, direction.unwrap_or(SelectionDirection::None)); // Step 6 let window = window_from_node(self); |