Bug 1429573 - Use input[type=number] in textbox[type=number] implementation. r=Paolo,surkov

* The number is no longer selected on number input focus

MozReview-Commit-ID: EoXNqhXwK95

--HG--
extra : rebase_source : b5a522e11796ec42c87019f6c3955e6c40eb21d0
This commit is contained in:
Tim Nguyen 2018-02-09 19:23:56 +00:00
Родитель 962c6d6974
Коммит d2bb22650d
13 изменённых файлов: 68 добавлений и 292 удалений

Просмотреть файл

@ -75,10 +75,12 @@
accTree =
{ SECTION: [
{ ENTRY: [ { TEXT_LEAF: [] } ] },
{ SPINBUTTON: [
{ ENTRY: [ { TEXT_LEAF: [] } ] },
{ PUSHBUTTON: [ ] },
{ PUSHBUTTON: [ ] }
] },
{ MENUPOPUP: [] },
{ PUSHBUTTON: [] },
{ PUSHBUTTON: [] }
] };
testAccessibleTree("txc_number", accTree);

Просмотреть файл

@ -39,21 +39,7 @@ html|input.num {
text-align: end;
}
#mac html|input.num {
margin-inline-end: 8px;
}
#win html|input.num {
padding: 0 !important;
}
#linux html|input.num {
margin-inline-end: 3px;
padding: 3px 4px;
}
html|div.plainfield {
color: -moz-fieldtext;
white-space: pre;
}

Просмотреть файл

@ -6,8 +6,8 @@
-->
<window title="Textbox type='number' test" width="500" height="600"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<hbox>
<textbox id="n1" type="number" size="4"/>
@ -48,8 +48,6 @@ function doTests() {
testValsMinMax(n5, "initial n5", -10, -10, -3);
testValsMinMax(n6, "initial n6", 12, 12, 12);
ok(n1.spinButtons != null && n1.spinButtons.localName == "spinbuttons", "spinButtons set");
// test changing the value
n1.value = "1700";
testVals(n1, "set value,", 1700);
@ -93,67 +91,19 @@ function doTests() {
n1.max = 22;
testValsMinMax(n1, "set integer max,", 22, 8, 22);
// test increase and decrease via the keyboard and the spinbuttons
testIncreaseDecrease(n1, "integer", 1, 0, 8, 22);
// UI tests
n1.min = 5;
n1.max = 15;
n1.value = 5;
n1.focus();
var sb = n1.spinButtons;
var sbbottom = sb.getBoundingClientRect().bottom - sb.getBoundingClientRect().top - 2;
synthesizeKey("VK_UP", {});
testVals(n1, "key up", 6);
synthesizeKey("VK_DOWN", {});
testVals(n1, "key down", 5);
synthesizeMouse(sb, 2, 2, {});
testVals(n1, "spinbuttons up", 6);
synthesizeMouse(sb, 2, sbbottom, {});
testVals(n1, "spinbuttons down", 5);
n1.value = 15;
synthesizeKey("VK_UP", {});
testVals(n1, "key up at max", 15);
synthesizeMouse(sb, 2, 2, {});
testVals(n1, "spinbuttons up at max", 15);
n1.value = 5;
synthesizeKey("VK_DOWN", {});
testVals(n1, "key down at min", 5);
synthesizeMouse(sb, 2, sbbottom, {});
testVals(n1, "spinbuttons down at min", 5);
// check read only state
n1.readOnly = true;
n1.min = -10;
n1.max = 15;
n1.value = 12;
n1.inputField.focus();
// no events should fire and no changes should occur when the field is read only
synthesizeKeyExpectEvent("VK_UP", { }, n1, "!change", "key up read only");
is(n1.value, "12", "key up read only value");
synthesizeKeyExpectEvent("VK_DOWN", { }, n1, "!change", "key down read only");
is(n1.value, "12", "key down read only value");
synthesizeMouseExpectEvent(sb, 2, 2, { }, n1, "!change", "mouse up read only");
is(n1.value, "12", "mouse up read only value");
synthesizeMouseExpectEvent(sb, 2, sbbottom, { }, n1, "!change", "mouse down read only");
is(n1.value, "12", "mouse down read only value");
n1.readOnly = false;
n1.disabled = true;
synthesizeMouseExpectEvent(sb, 2, 2, { }, n1, "!change", "mouse up disabled");
is(n1.value, "12", "mouse up disabled value");
synthesizeMouseExpectEvent(sb, 2, sbbottom, { }, n1, "!change", "mouse down disabled");
is(n1.value, "12", "mouse down disabled value");
var nsbrect = $("n8").spinButtons.getBoundingClientRect();
ok(nsbrect.left == 0 && nsbrect.top == 0 && nsbrect.right == 0, nsbrect.bottom == 0,
"hidespinbuttons");
var n9 = $("n9");
is(n9.value, "0", "initial value");
@ -202,38 +152,6 @@ function testValsMinMax(nb, name, valueNumber, min, max, valueFieldNumber) {
SimpleTest.is(nb.max, max, name + " max is " + max);
}
function testIncreaseDecrease(nb, testid, increment, fixedCount, min, max) {
testid += " ";
nb.focus();
nb.value = min;
// pressing the cursor up and down keys should adjust the value
synthesizeKeyExpectEvent("VK_UP", { }, nb, "change", testid + "key up");
is(nb.value, String(min + increment), testid + "key up");
nb.value = max;
synthesizeKeyExpectEvent("VK_UP", { }, nb, "!change", testid + "key up at max");
is(nb.value, String(max), testid + "key up at max");
synthesizeKeyExpectEvent("VK_DOWN", { }, nb, "change", testid + "key down");
is(nb.value, String(max - increment), testid + "key down");
nb.value = min;
synthesizeKeyExpectEvent("VK_DOWN", { }, nb, "!change", testid + "key down at min");
is(nb.value, String(min), testid + "key down at min");
// check pressing the spinbutton arrows
var sb = nb.spinButtons;
var sbbottom = sb.getBoundingClientRect().bottom - sb.getBoundingClientRect().top - 2;
nb.value = min;
synthesizeMouseExpectEvent(sb, 2, 2, { }, nb, "change", testid + "mouse up");
is(nb.value, String(min + increment), testid + "mouse up");
nb.value = max;
synthesizeMouseExpectEvent(sb, 2, 2, { }, nb, "!change", testid + "mouse up at max");
synthesizeMouseExpectEvent(sb, 2, sbbottom, { }, nb, "change", testid + "mouse down");
is(nb.value, String(max - increment), testid + "mouse down");
nb.value = min;
synthesizeMouseExpectEvent(sb, 2, sbbottom, { }, nb, "!change", testid + "mouse down at min");
}
SimpleTest.waitForFocus(doTests);
]]></script>

Просмотреть файл

@ -19,28 +19,16 @@
<content>
<xul:hbox class="textbox-input-box numberbox-input-box" flex="1" xbl:inherits="context,disabled,focused">
<html:input class="numberbox-input textbox-input" anonid="input"
xbl:inherits="value,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey"/>
<html:input class="numberbox-input textbox-input" type="number" anonid="input"
xbl:inherits="value,min,max,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey"/>
</xul:hbox>
<xul:spinbuttons anonid="buttons" xbl:inherits="disabled,hidden=hidespinbuttons"/>
</content>
<implementation>
<field name="_valueEntered">false</field>
<field name="_spinButtons">null</field>
<field name="_value">0</field>
<property name="spinButtons" readonly="true">
<getter>
<![CDATA[
if (!this._spinButtons)
this._spinButtons = document.getAnonymousElementByAttribute(this, "anonid", "buttons");
return this._spinButtons;
]]>
</getter>
</property>
<property name="value" onget="return '' + this.valueNumber"
<property name="value" onget="return String(this.valueNumber)"
onset="return this.valueNumber = val;"/>
<property name="valueNumber">
@ -93,47 +81,6 @@
</setter>
</property>
<method name="_modifyUp">
<body>
<![CDATA[
if (this.disabled || this.readOnly)
return;
var oldval = this.valueNumber;
var newval = this._validateValue(this.valueNumber + 1);
this.inputField.select();
if (oldval != newval)
this._fireChange();
]]>
</body>
</method>
<method name="_modifyDown">
<body>
<![CDATA[
if (this.disabled || this.readOnly)
return;
var oldval = this.valueNumber;
var newval = this._validateValue(this.valueNumber - 1);
this.inputField.select();
if (oldval != newval)
this._fireChange();
]]>
</body>
</method>
<method name="_enableDisableButtons">
<body>
<![CDATA[
var buttons = this.spinButtons;
if (this.disabled || this.readOnly) {
buttons.decreaseDisabled = buttons.increaseDisabled = true;
} else {
buttons.decreaseDisabled = (this.valueNumber <= this.min);
buttons.increaseDisabled = (this.valueNumber >= this.max);
}
]]>
</body>
</method>
<method name="_validateValue">
<parameter name="aValue"/>
<body>
@ -152,8 +99,6 @@
this._value = Number(aValue);
this.inputField.value = aValue;
this._enableDisableButtons();
return aValue;
]]>
</body>
@ -194,26 +139,9 @@
]]>
</handler>
<handler event="keypress" keycode="VK_UP">
this._modifyUp();
</handler>
<handler event="keypress" keycode="VK_DOWN">
this._modifyDown();
</handler>
<handler event="up" preventdefault="true">
this._modifyUp();
</handler>
<handler event="down" preventdefault="true">
this._modifyDown();
</handler>
<handler event="change">
if (event.originalTarget == this.inputField) {
var newval = this.inputField.value;
this._validateValue(newval);
this._validateValue(this.inputField.value);
}
</handler>
</handlers>

Просмотреть файл

@ -127,7 +127,12 @@
<parameter name="aSelectionStart"/>
<parameter name="aSelectionEnd"/>
<body>
this.inputField.setSelectionRange( aSelectionStart, aSelectionEnd );
// According to https://html.spec.whatwg.org/#do-not-apply,
// setSelectionRange() is only available on a limited set of input types.
if (this.inputField.type == "text" ||
this.inputField.tagName == "html:textarea") {
this.inputField.setSelectionRange( aSelectionStart, aSelectionEnd );
}
</body>
</method>
@ -188,26 +193,29 @@
if (this.hasAttribute("focused"))
return;
switch (event.originalTarget) {
case this:
// Forward focus to actual HTML input
this.inputField.focus();
break;
case this.inputField:
if (this.mIgnoreFocus) {
this.mIgnoreFocus = false;
} else if (this.clickSelectsAll) {
try {
if (!this.editor || !this.editor.composing)
this.editor.selectAll();
} catch (e) {}
}
break;
default:
// Allow other children (e.g. URL bar buttons) to get focus
return;
let { originalTarget } = event;
if (originalTarget == this) {
// Forward focus to actual HTML input
this.inputField.focus();
this.setAttribute("focused", "true");
return;
}
this.setAttribute("focused", "true");
// We check for the parent nodes to support input[type=number] where originalTarget may be an
// anonymous child input.
if (originalTarget == this.inputField ||
originalTarget.localName == "input" && originalTarget.parentNode.parentNode == this.inputField) {
if (this.mIgnoreFocus) {
this.mIgnoreFocus = false;
} else if (this.clickSelectsAll) {
try {
if (!this.editor || !this.editor.composing)
this.editor.selectAll();
} catch (e) {}
}
this.setAttribute("focused", "true");
}
// Otherwise, allow other children (e.g. URL bar buttons) to get focus
]]>
</handler>
@ -229,7 +237,7 @@
if (!this.mIgnoreClick) {
this.mIgnoreFocus = true;
this.inputField.setSelectionRange(0, 0);
this.setSelectionRange(0, 0);
if (event.originalTarget == this ||
event.originalTarget == this.inputField.parentNode)
this.inputField.focus();

Просмотреть файл

@ -81,10 +81,6 @@ html|input[type="checkbox"]:-moz-focusring + html|label:before {
outline: 1px dotted;
}
xul|spinbuttons {
-moz-appearance: none;
}
xul|treechildren::-moz-tree-row(multicol, odd) {
background-color: var(--in-content-box-background-odd);
}

Просмотреть файл

@ -9,25 +9,10 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
textbox[type="number"] {
-moz-appearance: none;
padding: 0 !important;
border: none;
cursor: default;
background-color: transparent;
}
html|*.numberbox-input {
text-align: right;
}
.numberbox-input-box {
-moz-box-align: center;
-moz-appearance: spinner-textfield;
margin-right: -1px;
padding: 3px;
}
textbox[hidespinbuttons="true"] > .numberbox-input-box {
-moz-appearance: textfield;
textbox[type="number"][hidespinbuttons="true"] html|*.numberbox-input {
-moz-appearance: textfield !important;
}

Просмотреть файл

@ -57,11 +57,6 @@ xul|*.radio-icon {
margin-inline-end: 0;
}
xul|*.numberbox-input-box {
-moz-appearance: none;
border-width: 0;
}
xul|*.text-link:-moz-focusring {
color: var(--in-content-link-highlight);
text-decoration: underline;
@ -83,29 +78,14 @@ xul|radio[focused="true"] > .radio-check {
-moz-outline-radius: 100%;
}
xul|spinbuttons {
-moz-appearance: none;
}
xul|*.spinbuttons-up {
margin-top: 0 !important;
html|*.numberbox-input::-moz-number-spin-up {
border-radius: 4px 4px 0 0;
}
xul|*.spinbuttons-down {
margin-bottom: 0 !important;
html|*.numberbox-input::-moz-number-spin-down {
border-radius: 0 0 4px 4px;
}
xul|*.spinbuttons-button > xul|*.button-box {
padding-inline-start: 2px !important;
padding-inline-end: 3px !important;
}
xul|*.spinbuttons-button > xul|*.button-box > xul|*.button-text {
display: none;
}
xul|textbox[type="search"]:not([searchbutton]) > .textbox-input-box > .textbox-search-sign {
list-style-image: url(chrome://global/skin/icons/search-textbox.svg);
margin-inline-end: 5px;

Просмотреть файл

@ -5,21 +5,11 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
textbox[type="number"] {
-moz-appearance: none;
-moz-box-align: center;
padding: 0 !important;
border: none;
background-color: transparent;
cursor: default;
}
html|*.numberbox-input {
text-align: right;
padding: 0 1px !important;
}
.numberbox-input-box {
-moz-appearance: textfield;
margin-right: 4px;
textbox[type="number"][hidespinbuttons="true"] html|*.numberbox-input {
-moz-appearance: textfield !important;
}

Просмотреть файл

@ -165,7 +165,9 @@ html|button {
*|button,
html|select,
xul|colorpicker[type="button"],
xul|menulist {
xul|menulist,
html|*.numberbox-input::-moz-number-spin-up,
html|*.numberbox-input::-moz-number-spin-down {
-moz-appearance: none;
min-height: 30px;
color: var(--in-content-text-color);
@ -201,6 +203,8 @@ html|select:not([size]):not([multiple]):dir(rtl){
html|button:enabled:hover,
html|select:not([size]):not([multiple]):enabled:hover,
html|*.numberbox-input::-moz-number-spin-up:hover,
html|*.numberbox-input::-moz-number-spin-down:hover,
xul|button:not([disabled="true"]):hover,
xul|colorpicker[type="button"]:not([disabled="true"]):hover,
xul|menulist:not([disabled="true"]):hover {
@ -209,6 +213,8 @@ xul|menulist:not([disabled="true"]):hover {
html|button:enabled:hover:active,
html|select:not([size]):not([multiple]):enabled:hover:active,
html|*.numberbox-input::-moz-number-spin-up:hover:active,
html|*.numberbox-input::-moz-number-spin-down:hover:active,
xul|button:not([disabled="true"]):hover:active,
xul|colorpicker[type="button"]:not([disabled="true"]):hover:active,
xul|menulist[open="true"]:not([disabled="true"]) {
@ -217,6 +223,7 @@ xul|menulist[open="true"]:not([disabled="true"]) {
html|button:disabled,
html|select:disabled,
html|*.numberbox-input:disabled::-moz-number-spin-box,
xul|button[disabled="true"],
xul|colorpicker[type="button"][disabled="true"],
xul|menulist[disabled="true"],
@ -347,40 +354,22 @@ html|*.help-button:hover:active {
background-color: var(--in-content-category-background-active);
}
xul|*.spinbuttons-button {
html|*.numberbox-input::-moz-number-spin-up,
html|*.numberbox-input::-moz-number-spin-down {
padding: 5px 8px;
margin: 1px;
margin-inline-start: 10px;
min-height: initial;
margin-inline-start: 10px !important;
margin-inline-end: 2px !important;
}
xul|*.spinbuttons-up {
margin-top: 2px !important;
html|*.numberbox-input::-moz-number-spin-up {
border-radius: 1px 1px 0 0;
background-image: url("chrome://global/skin/arrow/arrow-up.gif");
}
xul|*.spinbuttons-down {
margin-bottom: 2px !important;
html|*.numberbox-input::-moz-number-spin-down {
border-radius: 0 0 1px 1px;
}
xul|*.spinbuttons-button > xul|*.button-box {
padding: 1px 5px 2px !important;
}
xul|*.spinbuttons-up > xul|*.button-box > xul|*.button-icon {
list-style-image: url("chrome://global/skin/arrow/arrow-up.gif");
}
xul|*.spinbuttons-up[disabled="true"] > xul|*.button-box > xul|*.button-icon {
list-style-image: url("chrome://global/skin/arrow/arrow-up-dis.gif");
}
xul|*.spinbuttons-down > xul|*.button-box > xul|*.button-icon {
list-style-image: url("chrome://global/skin/arrow/arrow-dn.gif");
}
xul|*.spinbuttons-down[disabled="true"] > xul|*.button-box > xul|*.button-icon {
list-style-image: url("chrome://global/skin/arrow/arrow-dn-dis.gif");
background-image: url("chrome://global/skin/arrow/arrow-dn.gif");
}
xul|menulist:not([editable="true"]) > xul|*.menulist-dropmarker {

Просмотреть файл

@ -21,9 +21,7 @@
skin/classic/global/wizard.css (../../windows/global/wizard.css)
skin/classic/global/arrow/arrow-dn.gif (../../windows/global/arrow/arrow-dn.gif)
skin/classic/global/arrow/arrow-dn-dis.gif (../../windows/global/arrow/arrow-dn-dis.gif)
skin/classic/global/arrow/arrow-up.gif (../../windows/global/arrow/arrow-up.gif)
skin/classic/global/arrow/arrow-up-dis.gif (../../windows/global/arrow/arrow-up-dis.gif)
skin/classic/global/arrow/panelarrow-horizontal.svg (../../windows/global/arrow/panelarrow-horizontal.svg)
skin/classic/global/arrow/panelarrow-vertical.svg (../../windows/global/arrow/panelarrow-vertical.svg)

Просмотреть файл

@ -36,6 +36,8 @@ toolkit.jar:
skin/classic/global/arrow/arrow-lft-dis.gif (arrow/arrow-lft-dis.gif)
skin/classic/global/arrow/arrow-rit.gif (arrow/arrow-rit.gif)
skin/classic/global/arrow/arrow-rit-dis.gif (arrow/arrow-rit-dis.gif)
skin/classic/global/arrow/arrow-up-dis.gif (arrow/arrow-up-dis.gif)
skin/classic/global/arrow/arrow-dn-dis.gif (arrow/arrow-dn-dis.gif)
skin/classic/global/dirListing/folder.png (dirListing/folder.png)
skin/classic/global/dirListing/up.png (dirListing/up.png)
skin/classic/global/icons/blacklist_favicon.png (icons/blacklist_favicon.png)

Просмотреть файл

@ -9,16 +9,10 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
textbox[type="number"] {
padding: 0 !important;
cursor: default;
}
html|*.numberbox-input {
text-align: right;
}
.numberbox-input-box {
-moz-box-align: center;
textbox[type="number"][hidespinbuttons="true"] html|*.numberbox-input {
-moz-appearance: textfield !important;
}