diff options
author | Jon Leighton <j@jonathanleighton.com> | 2017-12-11 21:30:47 +0100 |
---|---|---|
committer | Jon Leighton <j@jonathanleighton.com> | 2018-01-26 20:12:38 +0100 |
commit | a8b64aca2a9c5e6e3756145afc0dedb606947ef8 (patch) | |
tree | 2831b7d93caf3126bdb690c2373e3c34b232537c | |
parent | ce7bae8834c0e89c57072ec1ddfa43efa5fe6f4e (diff) | |
download | servo-a8b64aca2a9c5e6e3756145afc0dedb606947ef8.tar.gz servo-a8b64aca2a9c5e6e3756145afc0dedb606947ef8.zip |
Steps 7-9 of the input type change algorithm
Spec: https://html.spec.whatwg.org/multipage/input.html#input-type-change
In short, this resets the selection to the start of the field when the
type has changed from one which doesn't support the selection API to one
that does.
I couldn't see an existing WPT test covering this.
-rwxr-xr-x | components/script/dom/htmlinputelement.rs | 11 | ||||
-rwxr-xr-x | components/script/dom/htmltextareaelement.rs | 4 | ||||
-rw-r--r-- | components/script/textinput.rs | 4 | ||||
-rw-r--r-- | tests/wpt/metadata/MANIFEST.json | 2 | ||||
-rw-r--r-- | tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html | 26 |
5 files changed, 40 insertions, 7 deletions
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 4b417a2bfaa..e70afde60c2 100755 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -53,7 +53,7 @@ use std::ops::Range; use style::attr::AttrValue; use style::element_state::ElementState; use style::str::split_commas; -use textinput::{SelectionDirection, TextInput}; +use textinput::{Direction, SelectionDirection, TextInput}; use textinput::KeyReaction::{DispatchInput, Nothing, RedrawSelection, TriggerDefaultAction}; use textinput::Lines::Single; @@ -566,7 +566,7 @@ impl HTMLInputElementMethods for HTMLInputElement { self.sanitize_value(); // Step 5. if *self.textinput.borrow().single_line_content() != old_value { - self.textinput.borrow_mut().clear_selection_to_limit(); + self.textinput.borrow_mut().clear_selection_to_limit(Direction::Forward); } } ValueMode::Default | @@ -1159,6 +1159,8 @@ impl VirtualMethods for HTMLInputElement { // https://html.spec.whatwg.org/multipage/#input-type-change let (old_value_mode, old_idl_value) = (self.value_mode(), self.Value()); + let previously_selectable = self.selection_api_applies(); + self.input_type.set(new_type); if new_type.is_textual() { @@ -1210,6 +1212,11 @@ impl VirtualMethods for HTMLInputElement { // Step 6 self.sanitize_value(); + + // Steps 7-9 + if !previously_selectable && self.selection_api_applies() { + self.textinput.borrow_mut().clear_selection_to_limit(Direction::Backward); + } }, AttributeMutation::Removed => { if self.input_type() == InputType::Radio { diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index 90574c9967a..bdb0020c616 100755 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -36,7 +36,7 @@ use std::default::Default; use std::ops::Range; use style::attr::AttrValue; use style::element_state::ElementState; -use textinput::{KeyReaction, Lines, SelectionDirection, TextInput}; +use textinput::{Direction, KeyReaction, Lines, SelectionDirection, TextInput}; #[dom_struct] pub struct HTMLTextAreaElement { @@ -262,7 +262,7 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement { if old_value != textinput.get_content() { // Step 4 - textinput.clear_selection_to_limit(); + textinput.clear_selection_to_limit(Direction::Forward); } else { textinput.selection_origin = old_selection; } diff --git a/components/script/textinput.rs b/components/script/textinput.rs index bf165148f0f..937ab38ed5d 100644 --- a/components/script/textinput.rs +++ b/components/script/textinput.rs @@ -533,9 +533,9 @@ impl<T: ClipboardProvider> TextInput<T> { } /// Remove the current selection and set the edit point to the end of the content. - pub fn clear_selection_to_limit(&mut self) { + pub fn clear_selection_to_limit(&mut self, direction: Direction) { self.clear_selection(); - self.adjust_horizontal_to_limit(Direction::Forward, Selection::NotSelected); + self.adjust_horizontal_to_limit(direction, Selection::NotSelected); } pub fn adjust_horizontal_by_word(&mut self, direction: Direction, select: Selection) { diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index 04fd44f5dbd..f247ba70162 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -553459,7 +553459,7 @@ "testharness" ], "html/semantics/forms/the-input-element/type-change-state.html": [ - "d731573ee091b7e658ea0b1ded46a764e8165f6c", + "6ca94002609dae5548e5c832e4a84639c1094f69", "testharness" ], "html/semantics/forms/the-input-element/url.html": [ diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html index 82d36cda481..34cfd438cb6 100644 --- a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html +++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html @@ -31,6 +31,11 @@ { type: "reset" }, { type: "button" } ]; + + const selectionStart = 2; + const selectionEnd = 5; + const selectionDirection = "backward"; + for (var i = 0; i < types.length; i++) { for (var j = 0; j < types.length; j++) { if (types[i] != types[j]) { @@ -49,6 +54,13 @@ assert_equals(input.value, ""); } else { input.value = expected; + + const previouslySelectable = (input.selectionStart !== null); + + if (previouslySelectable) { + input.setSelectionRange(selectionStart, selectionEnd, selectionDirection); + } + input.type = types[j].type; // change state // type[i] sanitization @@ -69,6 +81,20 @@ } assert_equals(input.value, expected, "input.value should be '" + expected + "' after change of state"); + + const nowSelectable = (input.selectionStart !== null); + + if (nowSelectable) { + if (previouslySelectable) { + assert_equals(input.selectionStart, selectionStart, "selectionStart should be unchanged"); + assert_equals(input.selectionEnd, selectionEnd, "selectionEnd should be unchanged"); + assert_equals(input.selectionDirection, selectionDirection, "selectionDirection should be unchanged"); + } else { + assert_equals(input.selectionStart, 0, "selectionStart should be 0"); + assert_equals(input.selectionEnd, 0, "selectionEnd should be 0"); + assert_equals(input.selectionDirection, "none", "selectionDirection should be 'none'"); + } + } } }, "change state from " + types[i].type + " to " + types[j].type); } |