aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Leighton <j@jonathanleighton.com>2017-12-11 21:30:47 +0100
committerJon Leighton <j@jonathanleighton.com>2018-01-26 20:12:38 +0100
commita8b64aca2a9c5e6e3756145afc0dedb606947ef8 (patch)
tree2831b7d93caf3126bdb690c2373e3c34b232537c
parentce7bae8834c0e89c57072ec1ddfa43efa5fe6f4e (diff)
downloadservo-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-xcomponents/script/dom/htmlinputelement.rs11
-rwxr-xr-xcomponents/script/dom/htmltextareaelement.rs4
-rw-r--r--components/script/textinput.rs4
-rw-r--r--tests/wpt/metadata/MANIFEST.json2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html26
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);
}