Correct default selectionStart and selectionEnd

This commit is contained in:
paavininanda 2018-02-21 01:29:33 +05:30
parent b517410a34
commit 87e7b1ee7a
7 changed files with 58 additions and 26 deletions

View file

@ -550,18 +550,24 @@ impl HTMLInputElementMethods for HTMLInputElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-input-value // https://html.spec.whatwg.org/multipage/#dom-input-value
fn SetValue(&self, value: DOMString) -> ErrorResult { fn SetValue(&self, mut value: DOMString) -> ErrorResult {
match self.value_mode() { match self.value_mode() {
ValueMode::Value => { ValueMode::Value => {
// Steps 1-2.
let old_value = mem::replace(self.textinput.borrow_mut().single_line_content_mut(), value);
// Step 3. // Step 3.
self.value_dirty.set(true); self.value_dirty.set(true);
// Step 4. // Step 4.
self.sanitize_value(); self.sanitize_value(&mut value);
let mut textinput = self.textinput.borrow_mut();
// Step 5. // Step 5.
if *self.textinput.borrow().single_line_content() != old_value { if *textinput.single_line_content() != value {
self.textinput.borrow_mut().clear_selection_to_limit(Direction::Forward); // Steps 1-2
textinput.set_content(value);
// Step 5.
textinput.clear_selection_to_limit(Direction::Forward);
} }
} }
ValueMode::Default | ValueMode::Default |
@ -935,8 +941,7 @@ impl HTMLInputElement {
InputType::Image => (), InputType::Image => (),
_ => () _ => ()
} }
self.SetValue(self.DefaultValue()) self.textinput.borrow_mut().set_content(self.DefaultValue());
.expect("Failed to reset input value to default.");
self.value_dirty.set(false); self.value_dirty.set(false);
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
} }
@ -1093,7 +1098,6 @@ impl VirtualMethods for HTMLInputElement {
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation); self.super_type().unwrap().attribute_mutated(attr, mutation);
match attr.local_name() { match attr.local_name() {
&local_name!("disabled") => { &local_name!("disabled") => {
let disabled_state = match mutation { let disabled_state = match mutation {
@ -1194,11 +1198,11 @@ impl VirtualMethods for HTMLInputElement {
let mut textinput = self.textinput.borrow_mut(); let mut textinput = self.textinput.borrow_mut();
let mut value = textinput.single_line_content().clone(); let mut value = textinput.single_line_content().clone();
self.sanitize_value(&mut value); self.sanitize_value(&mut value);
textinput.set_content(value, true); textinput.set_content(value);
// Steps 7-9 // Steps 7-9
if !previously_selectable && self.selection_api_applies() { if !previously_selectable && self.selection_api_applies() {
self.textinput.borrow_mut().clear_selection_to_limit(Direction::Backward); textinput.clear_selection_to_limit(Direction::Backward);
} }
}, },
AttributeMutation::Removed => { AttributeMutation::Removed => {
@ -1222,9 +1226,7 @@ impl VirtualMethods for HTMLInputElement {
let mut value = value.map_or(DOMString::new(), DOMString::from); let mut value = value.map_or(DOMString::new(), DOMString::from);
self.sanitize_value(&mut value); self.sanitize_value(&mut value);
self.textinput.borrow_mut().set_content(value);
self.textinput.borrow_mut().set_content(
value.map_or(DOMString::new(), DOMString::from));
self.update_placeholder_shown_state(); self.update_placeholder_shown_state();
}, },
&local_name!("name") if self.input_type() == InputType::Radio => { &local_name!("name") if self.input_type() == InputType::Radio => {

View file

@ -248,7 +248,6 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
// Step 1 // Step 1
let old_value = textinput.get_content(); let old_value = textinput.get_content();
let old_selection = textinput.selection_origin;
// Step 2 // Step 2
textinput.set_content(value); textinput.set_content(value);
@ -259,8 +258,6 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
if old_value != textinput.get_content() { if old_value != textinput.get_content() {
// Step 4 // Step 4
textinput.clear_selection_to_limit(Direction::Forward); textinput.clear_selection_to_limit(Direction::Forward);
} else {
textinput.selection_origin = old_selection;
} }
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
@ -327,7 +324,8 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
impl HTMLTextAreaElement { impl HTMLTextAreaElement {
pub fn reset(&self) { pub fn reset(&self) {
// https://html.spec.whatwg.org/multipage/#the-textarea-element:concept-form-reset-control // https://html.spec.whatwg.org/multipage/#the-textarea-element:concept-form-reset-control
self.SetValue(self.DefaultValue()); let mut textinput = self.textinput.borrow_mut();
textinput.set_content(self.DefaultValue());
self.value_dirty.set(false); self.value_dirty.set(false);
} }

View file

@ -448,9 +448,7 @@ impl<T: ClipboardProvider> TextInput<T> {
return; return;
} }
let col = self.lines[self.edit_point.line][..self.edit_point.index].chars().count(); let col = self.lines[self.edit_point.line][..self.edit_point.index].chars().count();
self.edit_point.line = target_line as usize; self.edit_point.line = target_line as usize;
self.edit_point.index = len_of_first_n_chars(&self.lines[self.edit_point.line], col); self.edit_point.index = len_of_first_n_chars(&self.lines[self.edit_point.line], col);
self.assert_ok_selection(); self.assert_ok_selection();
@ -887,7 +885,6 @@ impl<T: ClipboardProvider> TextInput<T> {
if let Some(origin) = self.selection_origin { if let Some(origin) = self.selection_origin {
self.selection_origin = Some(origin.constrain_to(&self.lines)); self.selection_origin = Some(origin.constrain_to(&self.lines));
} }
self.assert_ok_selection(); self.assert_ok_selection();
} }

View file

@ -494,10 +494,11 @@ fn test_textinput_set_content() {
assert_eq!(textinput.edit_point().line, 0); assert_eq!(textinput.edit_point().line, 0);
assert_eq!(textinput.edit_point().index, 0); assert_eq!(textinput.edit_point().index, 0);
textinput.adjust_horizontal(3, Selection::Selected); textinput.adjust_horizontal(3, Selection::Selected);
assert_eq!(textinput.edit_point().line, 0); assert_eq!(textinput.edit_point().line, 0);
assert_eq!(textinput.edit_point().index, 3); assert_eq!(textinput.edit_point().index, 3);
textinput.set_content(DOMString::from("de"), true); textinput.set_content(DOMString::from("de"));
assert_eq!(textinput.get_content(), "de"); assert_eq!(textinput.get_content(), "de");
assert_eq!(textinput.edit_point().line, 0); assert_eq!(textinput.edit_point().line, 0);
assert_eq!(textinput.edit_point().index, 2); assert_eq!(textinput.edit_point().index, 2);
@ -634,6 +635,10 @@ fn test_textinput_unicode_handling() {
fn test_selection_bounds() { fn test_selection_bounds() {
let mut textinput = text_input(Lines::Single, "abcdef"); let mut textinput = text_input(Lines::Single, "abcdef");
assert_eq!(TextPoint { line: 0, index: 0 }, textinput.selection_origin_or_edit_point());
assert_eq!(TextPoint { line: 0, index: 0 }, textinput.selection_start());
assert_eq!(TextPoint { line: 0, index: 0 }, textinput.selection_end());
textinput.set_selection_range(2, 5, SelectionDirection::Forward); textinput.set_selection_range(2, 5, SelectionDirection::Forward);
assert_eq!(TextPoint { line: 0, index: 2 }, textinput.selection_origin_or_edit_point()); assert_eq!(TextPoint { line: 0, index: 2 }, textinput.selection_origin_or_edit_point());
assert_eq!(TextPoint { line: 0, index: 2 }, textinput.selection_start()); assert_eq!(TextPoint { line: 0, index: 2 }, textinput.selection_start());

View file

@ -330871,6 +330871,12 @@
{} {}
] ]
], ],
"html/semantics/forms/textfieldselection/defaultSelection.html": [
[
"/html/semantics/forms/textfieldselection/defaultSelection.html",
{}
]
],
"html/semantics/forms/textfieldselection/select-event.html": [ "html/semantics/forms/textfieldselection/select-event.html": [
[ [
"/html/semantics/forms/textfieldselection/select-event.html", "/html/semantics/forms/textfieldselection/select-event.html",

View file

@ -1,4 +0,0 @@
[setSelectionRange.html]
[setSelectionRange on line boundaries]
expected: FAIL

View file

@ -0,0 +1,28 @@
<!doctype html>
<meta charset="utf-8">
<title></title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<textarea>foo</textarea>
<input type="text" value="foo"></input>
<script>
for (let el of [document.querySelector("textarea"), document.querySelector("input")]) {
test(function() {
assert_equals(el.selectionStart, 0);
assert_equals(el.selectionEnd, 0);
}, `Default selectionStart and selectionEnd for ${el}`);
test(function() {
el.value="foo";
assert_equals(el.selectionStart, 0);
assert_equals(el.selectionEnd, 0);
}, `selectionStart and selectionEnd do not change when same value set again for ${el}`);
test(function() {
el.value="Foo";
assert_equals(el.selectionStart, 3);
assert_equals(el.selectionEnd, 3);
}, `selectionStart and selectionEnd change when value changed to upper case for ${el}`);
}
</script>