Bug 1283915: preserve input selection properties after type change; r?smaug
MozReview-Commit-ID: 7xJKc3vIpTY
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -4817,22 +4817,32 @@ HTMLInputElement::HandleTypeChange(uint8
ValueModeType aOldValueMode = GetValueMode();
uint8_t oldType = mType;
nsAutoString aOldValue;
if (aOldValueMode == VALUE_MODE_VALUE) {
GetValue(aOldValue);
}
+ nsTextEditorState::SelectionProperties sp;
+
+ if (GetEditorState()) {
+ sp = mInputData.mState->GetSelectionProperties();
+ }
+
// We already have a copy of the value, lets free it and changes the type.
FreeData();
mType = aNewType;
if (IsSingleLineTextControl()) {
+
mInputData.mState = new nsTextEditorState(this);
+ if (!sp.IsDefault()) {
+ mInputData.mState->SetSelectionProperties(sp);
+ }
}
/**
* The following code is trying to reproduce the algorithm described here:
* http://www.whatwg.org/specs/web-apps/current-work/complete.html#input-type-change
*/
switch (GetValueMode()) {
case VALUE_MODE_DEFAULT:
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -1531,16 +1531,29 @@ nsTextEditorState::GetSelectionPropertie
HTMLInputElement* number = GetParentNumberControl(mBoundFrame);
if (number) {
return number->GetSelectionProperties();
}
}
return mSelectionProperties;
}
+void
+nsTextEditorState::SetSelectionProperties(nsTextEditorState::SelectionProperties& aProps)
+{
+ if (mBoundFrame) {
+ mBoundFrame->SetSelectionRange(aProps.GetStart(),
+ aProps.GetEnd(),
+ aProps.GetDirection());
+ } else {
+ mSelectionProperties = aProps;
+ }
+}
+
+
HTMLInputElement*
nsTextEditorState::GetParentNumberControl(nsFrame* aFrame) const
{
MOZ_ASSERT(aFrame);
nsIContent* content = aFrame->GetContent();
MOZ_ASSERT(content);
nsIContent* parent = content->GetParent();
if (!parent) {
--- a/dom/html/nsTextEditorState.h
+++ b/dom/html/nsTextEditorState.h
@@ -255,16 +255,17 @@ public:
private:
int32_t mStart, mEnd;
bool mIsDirty = false;
nsITextControlFrame::SelectionDirection mDirection;
};
bool IsSelectionCached() const;
SelectionProperties& GetSelectionProperties();
+ void SetSelectionProperties(SelectionProperties& aProps);
void WillInitEagerly() { mSelectionRestoreEagerInit = true; }
bool HasNeverInitializedBefore() const { return !mEverInited; }
void UpdateEditableState(bool aNotify) {
if (mRootNode) {
mRootNode->UpdateEditableState(aNotify);
}
}
--- a/dom/html/test/forms/mochitest.ini
+++ b/dom/html/test/forms/mochitest.ini
@@ -1,15 +1,16 @@
[DEFAULT]
support-files =
save_restore_radio_groups.sjs
test_input_number_data.js
!/dom/html/test/reflect.js
[test_bug1039548.html]
+[test_bug1283915.html]
[test_bug1286509.html]
skip-if = os == "android" || appname == "b2g" # up/down arrow keys not supported on android/b2g
[test_button_attributes_reflection.html]
[test_input_radio_radiogroup.html]
[test_input_radio_required.html]
[test_change_event.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_datalist_element.html]
new file mode 100644
--- /dev/null
+++ b/dom/html/test/forms/test_bug1283915.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1283915
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1283915</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1283915 **/
+
+ SimpleTest.waitForExplicitFinish();
+
+ function isCursorAtEnd(field){
+ is(field.selectionStart, field.value.length);
+ is(field.selectionEnd, field.value.length);
+ }
+
+ function test() {
+ var tField = document.getElementById("textField");
+ tField.focus();
+
+ synthesizeKey("a", {});
+ is(tField.value, "a");
+ isCursorAtEnd(tField);
+ document.body.offsetWidth; // frame must be created after type change
+
+ synthesizeKey("b", {});
+ is(tField.value, "ab");
+ isCursorAtEnd(tField);
+
+ synthesizeKey("c", {});
+ is(tField.value, "abc");
+ isCursorAtEnd(tField);
+
+ var nField = document.getElementById("numField");
+ nField.focus();
+
+ synthesizeKey("1", {});
+ is(nField.value, "1");
+ isCursorAtEnd(nField);
+ document.body.offsetWidth;
+
+ synthesizeKey("2", {});
+ is(nField.value, "12");
+ isCursorAtEnd(nField);
+
+ synthesizeKey("3", {});
+ is(nField.value, "123");
+ isCursorAtEnd(nField);
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForFocus(test);
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1283915">Mozilla Bug 1283915</a>
+<p id="display"></p>
+<input id="textField" type="text" oninput="if (this.type !='password') this.type = 'password';">
+<input id="numField" type="text" oninput="if (this.type !='number') this.type = 'number';">
+<pre id="test">
+</pre>
+</body>
+</html>