Bug 1437641 - Remove numberbox binding and convert usages to input[type=number]. r=bgrins,dao
authorTim Nguyen <ntim.bugs@gmail.com>
Wed, 09 Jan 2019 08:51:32 +0000
changeset 453021 00d33e7058c1261b31ddd3b8df31e39c98212c3e
parent 453020 f06b57684ee92fcfcd0e7e491e1d13ecc9d32975
child 453022 ded030d641a2fd955e72236a39e8df127694193a
push id35340
push usercsabou@mozilla.com
push dateWed, 09 Jan 2019 16:04:56 +0000
treeherdermozilla-central@e28e5537e369 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins, dao
bugs1437641
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1437641 - Remove numberbox binding and convert usages to input[type=number]. r=bgrins,dao Differential Revision: https://phabricator.services.mozilla.com/D15882
accessible/tests/mochitest/name/test_general.xul
browser/components/preferences/connection.xul
browser/installer/allowed-dupes.mn
browser/themes/shared/incontentprefs/preferences.inc.css
editor/reftests/xul/emptytextbox-3.xul
editor/reftests/xul/number-1.xul
editor/reftests/xul/number-2.xul
editor/reftests/xul/number-3.xul
editor/reftests/xul/number-4.xul
editor/reftests/xul/number-5.xul
editor/reftests/xul/number-ref.xul
editor/reftests/xul/numberwithvalue-1.xul
editor/reftests/xul/numberwithvalue-ref.xul
editor/reftests/xul/reftest.list
mobile/android/installer/allowed-dupes.mn
toolkit/components/printing/content/printPreviewToolbar.js
toolkit/content/customElements.js
toolkit/content/jar.mn
toolkit/content/tests/chrome/chrome.ini
toolkit/content/tests/chrome/test_textbox_number.xul
toolkit/content/widgets.css
toolkit/content/widgets/numberbox.xml
toolkit/content/widgets/textbox.xml
toolkit/content/xul.css
toolkit/themes/linux/global/global.css
toolkit/themes/linux/global/in-content/common.css
toolkit/themes/mobile/jar.mn
toolkit/themes/osx/global/in-content/common.css
toolkit/themes/shared/in-content/common.inc.css
toolkit/themes/shared/jar.inc.mn
toolkit/themes/shared/numberbox.css
toolkit/themes/shared/numberinput.css
toolkit/themes/windows/global/global.css
--- a/accessible/tests/mochitest/name/test_general.xul
+++ b/accessible/tests/mochitest/name/test_general.xul
@@ -233,17 +233,17 @@
 
   <!-- aria-labelledby, multiple relations -->
   <box class="third" id="labelledby_box_anon" role="group" />
 
   <!-- trick aria-labelledby -->
   <checkbox id="rememberHistoryDays"
             label="Remember "
             aria-labelledby="rememberHistoryDays historyDays rememberAfter"/>
-  <textbox id="historyDays" type="number" value="3"
+  <textbox id="historyDays" value="3"
            aria-labelledby="rememberHistoryDays historyDays rememberAfter"/>
   <label id="rememberAfter">days</label>
 
   <!-- the name from subtree, mixed content -->
   <description id="labelledby_mixed">
     no<description>more text</description>
   </description>
   <button id="btn_labelledby_mixed"
--- a/browser/components/preferences/connection.xul
+++ b/browser/components/preferences/connection.xul
@@ -63,18 +63,18 @@
           <row align="center">
             <hbox pack="end">
               <label data-l10n-id="connection-proxy-http" control="networkProxyHTTP" />
             </hbox>
             <hbox align="center">
               <textbox id="networkProxyHTTP" flex="1"
                        preference="network.proxy.http" onsyncfrompreference="return gConnectionsDialog.readHTTPProxyServer();"/>
               <label data-l10n-id="connection-proxy-http-port" control="networkProxyHTTP_Port" />
-              <textbox id="networkProxyHTTP_Port" class="proxy-port-input" type="number" max="65535" hidespinbuttons="true"
-                       preference="network.proxy.http_port" onsyncfrompreference="return gConnectionsDialog.readHTTPProxyPort();"/>
+              <html:input id="networkProxyHTTP_Port" class="proxy-port-input" hidespinbuttons="true" type="number" min="0" max="65535"
+                          preference="network.proxy.http_port" onsyncfrompreference="return gConnectionsDialog.readHTTPProxyPort();"/>
             </hbox>
           </row>
           <row>
             <hbox/>
             <hbox>
               <checkbox id="shareAllProxies" data-l10n-id="connection-proxy-http-share"
                         preference="network.proxy.share_proxy_settings"
                         onsyncfrompreference="return gConnectionsDialog.updateProtocolPrefs();"/>
@@ -83,42 +83,42 @@
           <row align="center">
             <hbox pack="end">
               <label data-l10n-id="connection-proxy-ssl" control="networkProxySSL"/>
             </hbox>
             <hbox align="center">
               <textbox id="networkProxySSL" flex="1" preference="network.proxy.ssl"
                        onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ssl', false);"/>
               <label data-l10n-id="connection-proxy-ssl-port" control="networkProxySSL_Port" />
-              <textbox id="networkProxySSL_Port" class="proxy-port-input" type="number" max="65535" size="5" preference="network.proxy.ssl_port"
-                       hidespinbuttons="true" onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ssl', true);"/>
+              <html:input id="networkProxySSL_Port" class="proxy-port-input" hidespinbuttons="true" type="number" min="0" max="65535" size="5"
+                          preference="network.proxy.ssl_port" onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ssl', true);"/>
             </hbox>
           </row>
           <row align="center">
             <hbox pack="end">
               <label data-l10n-id="connection-proxy-ftp" control="networkProxyFTP"/>
             </hbox>
             <hbox align="center">
               <textbox id="networkProxyFTP" flex="1" preference="network.proxy.ftp"
                        onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ftp', false);"/>
               <label data-l10n-id="connection-proxy-ftp-port" control="networkProxyFTP_Port"/>
-              <textbox id="networkProxyFTP_Port" class="proxy-port-input" type="number" max="65535" size="5" preference="network.proxy.ftp_port"
-                       hidespinbuttons="true" onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ftp', true);"/>
+              <html:input id="networkProxyFTP_Port" class="proxy-port-input" hidespinbuttons="true" type="number" min="0" max="65535" size="5"
+                          preference="network.proxy.ftp_port" onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('ftp', true);"/>
             </hbox>
           </row>
           <row align="center">
             <hbox pack="end">
               <label data-l10n-id="connection-proxy-socks" control="networkProxySOCKS"/>
             </hbox>
             <hbox align="center">
               <textbox id="networkProxySOCKS" flex="1" preference="network.proxy.socks"
                        onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('socks', false);"/>
               <label data-l10n-id="connection-proxy-socks-port" control="networkProxySOCKS_Port"/>
-              <textbox id="networkProxySOCKS_Port" class="proxy-port-input" type="number" max="65535" size="5" preference="network.proxy.socks_port"
-                       hidespinbuttons="true" onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('socks', true);"/>
+              <html:input id="networkProxySOCKS_Port" class="proxy-port-input" hidespinbuttons="true" type="number" min="0" max="65535" size="5"
+                          preference="network.proxy.socks_port" onsyncfrompreference="return gConnectionsDialog.readProxyProtocolPref('socks', true);"/>
             </hbox>
           </row>
           <row>
             <spacer/>
             <box pack="start">
             <radiogroup id="networkProxySOCKSVersion" orient="horizontal"
                         preference="network.proxy.socks_version">
               <radio id="networkProxySOCKSVersion4" value="4" data-l10n-id="connection-proxy-socks4" />
--- a/browser/installer/allowed-dupes.mn
+++ b/browser/installer/allowed-dupes.mn
@@ -90,17 +90,17 @@ chrome/toolkit/skin/classic/global/autoc
 chrome/toolkit/skin/classic/global/button.css
 chrome/toolkit/skin/classic/global/checkbox.css
 chrome/toolkit/skin/classic/global/dialog.css
 chrome/toolkit/skin/classic/global/dropmarker.css
 chrome/toolkit/skin/classic/global/global.css
 chrome/toolkit/skin/classic/global/icons/close-win7.png
 chrome/toolkit/skin/classic/global/menu.css
 chrome/toolkit/skin/classic/global/menulist.css
-chrome/toolkit/skin/classic/global/numberbox.css
+chrome/toolkit/skin/classic/global/numberinput.css
 chrome/toolkit/skin/classic/global/popup.css
 chrome/toolkit/skin/classic/global/preferences.css
 chrome/toolkit/skin/classic/global/radio.css
 chrome/toolkit/skin/classic/global/richlistbox.css
 chrome/toolkit/skin/classic/global/scrollbars.css
 chrome/toolkit/skin/classic/global/scrollbox.css
 chrome/toolkit/skin/classic/global/splitter.css
 chrome/toolkit/skin/classic/global/tabbox.css
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -844,17 +844,18 @@ menulist[indicator=true] > menupopup men
 
 #no-results-message[query*=🔥🦊] > .no-results-container {
   visibility: hidden;
 }
 
 /* Proxy port input */
 
 .proxy-port-input {
-  width: calc(5ch + 22px); /* 5 chars + 11px padding on both sides */
+  width: calc(5ch + 18px); /* 5 chars + (8px padding + 1px border) on both sides */
+  margin-inline-start: 4px;
 }
 
 #defaultBrowserLanguage {
   margin-inline-start: 0;
   min-width: 20em;
 }
 
 #selectedLocales {
deleted file mode 100644
--- a/editor/reftests/xul/emptytextbox-3.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:html="http://www.w3.org/1999/xhtml"
-        title="Textbox tests">
-
-  <script type="text/javascript" src="platform.js"/>
-
-  <textbox type="number"/>
-      
-</window>
deleted file mode 100644
--- a/editor/reftests/xul/number-1.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:html="http://www.w3.org/1999/xhtml"
-        title="Textbox tests">
-
-  <script type="text/javascript" src="platform.js"/>
-
-  <textbox type="number"/>
-      
-</window>
deleted file mode 100644
--- a/editor/reftests/xul/number-2.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:html="http://www.w3.org/1999/xhtml"
-        title="Textbox tests">
-
-  <script type="text/javascript" src="platform.js"/>
-
-  <textbox type="number" hidespinbuttons="false"/>
-      
-</window>
deleted file mode 100644
--- a/editor/reftests/xul/number-3.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:html="http://www.w3.org/1999/xhtml"
-        title="Textbox tests">
-
-  <script type="text/javascript" src="platform.js"/>
-
-  <textbox type="number" hidespinbuttons="true"/>
-      
-</window>
deleted file mode 100644
--- a/editor/reftests/xul/number-4.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:html="http://www.w3.org/1999/xhtml"
-        title="Textbox tests">
-
-  <script type="text/javascript" src="platform.js"/>
-
-  <textbox type="number" value="1" hidespinbuttons="true"/>
-      
-</window>
deleted file mode 100644
--- a/editor/reftests/xul/number-5.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:html="http://www.w3.org/1999/xhtml"
-        title="Textbox tests">
-
-  <script type="text/javascript" src="platform.js"/>
-
-  <textbox type="number" value="test" hidespinbuttons="true"/>
-      
-</window>
deleted file mode 100644
--- a/editor/reftests/xul/number-ref.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="resource://reftest/input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:html="http://www.w3.org/1999/xhtml"
-        title="Textbox tests">
-
-  <script type="text/javascript" src="platform.js"/>
-
-  <html:input value="0" class="num"/>
-      
-</window>
deleted file mode 100644
--- a/editor/reftests/xul/numberwithvalue-1.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:html="http://www.w3.org/1999/xhtml"
-        title="Textbox tests">
-
-  <script type="text/javascript" src="platform.js"/>
-
-  <textbox type="number" value="123" hidespinbuttons="true"/>
-      
-</window>
deleted file mode 100644
--- a/editor/reftests/xul/numberwithvalue-ref.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="resource://reftest/input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:html="http://www.w3.org/1999/xhtml"
-        title="Textbox tests">
-
-  <script type="text/javascript" src="platform.js"/>
-
-  <html:input value="123" class="num"/>
-      
-</window>
--- a/editor/reftests/xul/reftest.list
+++ b/editor/reftests/xul/reftest.list
@@ -3,26 +3,17 @@ fails-if(Android) skip-if(winWidget) == 
 # There is no way to simulate an autocomplete textbox in windows XP/Vista/7/8/10 default theme using CSS.
 # Therefore, the equlity tests below should be marked as failing.
 fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == autocomplete-1.xul autocomplete-ref.xul # bug 783658
 fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == emptyautocomplete-1.xul emptyautocomplete-ref.xul # bug 783658
 != emptymultiline-1.xul emptymultiline-ref.xul
 fails-if(Android) == emptymultiline-2.xul emptymultiline-ref.xul # bug 783658
 fails-if(Android) skip-if(winWidget) == emptytextbox-1.xul emptytextbox-ref.xul # Windows: bug 1239170
 fails-if(Android) skip-if(winWidget) == emptytextbox-2.xul emptytextbox-ref.xul # Windows: bug 1239170
-!= emptytextbox-3.xul emptytextbox-ref.xul
 != emptytextbox-4.xul emptytextbox-ref.xul
-# There is no way to simulate a number textbox in windows XP/Vista/7 default theme using CSS.
-# Therefore, the equlity tests below should be marked as failing.
-!= number-1.xul number-ref.xul
-!= number-2.xul number-ref.xul
-fuzzy-if(webrender,0-205,0-7) fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == number-3.xul number-ref.xul # bug 783658
-!= number-4.xul number-ref.xul
-fuzzy-if(webrender,0-205,0-7) fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == number-5.xul number-ref.xul # bug 783658
-fuzzy-if(webrender,0-255,0-7) fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == numberwithvalue-1.xul numberwithvalue-ref.xul # bug 783658
 fails-if(Android) skip-if(winWidget) == passwd-1.xul passwd-ref.xul # Windows: bug 1239170
 fails-if(Android) skip-if(winWidget) == passwd-2.xul passwd-ref.xul # Windows: bug 1239170
 != passwd-3.xul passwd-ref.xul
 fails-if(Android) == plain-1.xul plain-ref.xul # bug 783658
 fails-if(Android) skip-if(winWidget) == textbox-1.xul textbox-ref.xul # Windows: bug 1239170
 != textbox-disabled.xul textbox-ref.xul
 # Read-only textboxes look like normal textboxes in windows Vista/7 default theme
 fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(6\.[012]|10\.0)/.test(http.oscpu)) skip-if(winWidget) != textbox-readonly.xul textbox-ref.xul # Windows: bug 1239170
--- a/mobile/android/installer/allowed-dupes.mn
+++ b/mobile/android/installer/allowed-dupes.mn
@@ -9,17 +9,17 @@ chrome/toolkit/skin/classic/global/autoc
 chrome/toolkit/skin/classic/global/button.css
 chrome/toolkit/skin/classic/global/checkbox.css
 chrome/toolkit/skin/classic/global/dialog.css
 chrome/toolkit/skin/classic/global/dropmarker.css
 chrome/toolkit/skin/classic/global/global.css
 chrome/toolkit/skin/classic/global/listbox.css
 chrome/toolkit/skin/classic/global/menu.css
 chrome/toolkit/skin/classic/global/menulist.css
-chrome/toolkit/skin/classic/global/numberbox.css
+chrome/toolkit/skin/classic/global/numberinput.css
 chrome/toolkit/skin/classic/global/popup.css
 chrome/toolkit/skin/classic/global/preferences.css
 chrome/toolkit/skin/classic/global/radio.css
 chrome/toolkit/skin/classic/global/richlistbox.css
 chrome/toolkit/skin/classic/global/scrollbars.css
 chrome/toolkit/skin/classic/global/scrollbox.css
 chrome/toolkit/skin/classic/global/splitter.css
 chrome/toolkit/skin/classic/global/tabbox.css
--- a/toolkit/components/printing/content/printPreviewToolbar.js
+++ b/toolkit/components/printing/content/printPreviewToolbar.js
@@ -19,17 +19,17 @@ customElements.define("printpreview-tool
       <button id="print-preview-print" label="&print.label;" accesskey="&print.accesskey;" oncommand="this.parentNode.print();"/>
       <button id="print-preview-pageSetup" label="&pageSetup.label;" accesskey="&pageSetup.accesskey;" oncommand="this.parentNode.doPageSetup();"/>
       <vbox align="center" pack="center">
         <label value="&page.label;" accesskey="&page.accesskey;" control="print-preview-pageNumber"/>
       </vbox>
       <toolbarbutton id="print-preview-navigateHome" class="print-preview-navigate-button tabbable" oncommand="parentNode.navigate(0, 0, 'home');" tooltiptext="&homearrow.tooltip;"/>
       <toolbarbutton id="print-preview-navigatePrevious" class="print-preview-navigate-button tabbable" oncommand="parentNode.navigate(-1, 0, 0);" tooltiptext="&previousarrow.tooltip;"/>
       <hbox align="center" pack="center">
-        <textbox id="print-preview-pageNumber" value="1" min="1" type="number" hidespinbuttons="true" onchange="navigate(0, this.valueNumber, 0);"/>
+        <html:input id="print-preview-pageNumber" hidespinbuttons="true" type="number" value="1" min="1"/>
         <label value="&of.label;"/>
         <label id="print-preview-totalPages" value="1"/>
       </hbox>
       <toolbarbutton id="print-preview-navigateNext" class="print-preview-navigate-button tabbable" oncommand="parentNode.navigate(1, 0, 0);" tooltiptext="&nextarrow.tooltip;"/>
       <toolbarbutton id="print-preview-navigateEnd" class="print-preview-navigate-button tabbable" oncommand="parentNode.navigate(0, 0, 'end');" tooltiptext="&endarrow.tooltip;"/>
       <toolbarseparator class="toolbarseparator-primary"/>
       <vbox align="center" pack="center">
         <label id="print-preview-scale-label" value="&scale.label;" accesskey="&scale.accesskey;" control="print-preview-scale"/>
@@ -99,16 +99,21 @@ customElements.define("printpreview-tool
 
     this.mPrintPreviewObs = "";
 
     this.mWebProgress = "";
 
     this.mPPBrowser = null;
 
     this.mMessageManager = null;
+
+    this.mOnPageTextBoxChange = () => {
+      this.navigate(0, Number(this.mPageTextBox.value), 0);
+    };
+    this.mPageTextBox.addEventListener("change", this.mOnPageTextBoxChange);
   }
 
   initialize(aPPBrowser) {
     let { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm", {});
     if (!Services.prefs.getBoolPref("print.use_simplify_page")) {
       this.mSimplifyPageCheckbox.hidden = true;
       this.mSimplifyPageToolbarSeparator.hidden = true;
     }
@@ -135,16 +140,17 @@ customElements.define("printpreview-tool
       this.mMessageManager.removeMessageListener("Printing:Preview:UpdatePageCount", this);
       delete this.mMessageManager;
       delete this.mPPBrowser;
     }
   }
 
   disconnectedCallback() {
     window.removeEventListener("unload", this.disconnectedCallback);
+    this.mPageTextBox.removeEventListener("change", this.mOnPageTextBoxChange);
     this.destroy();
   }
 
   disableUpdateTriggers(aDisabled) {
     this.mPrintButton.disabled = aDisabled;
     this.mPageSetupButton.disabled = aDisabled;
     this.mNavigateHomeButton.disabled = aDisabled;
     this.mNavigatePreviousButton.disabled = aDisabled;
@@ -183,19 +189,19 @@ customElements.define("printpreview-tool
       } else {
         navType = nsIWebBrowserPrint.PRINTPREVIEW_END;
         this.mPageTextBox.value = this.mPageTextBox.max;
       }
       pageNum = 0;
     } else if (aDirection) {
       // aDirection is either +1 or -1, and allows us to increment
       // or decrement our currently viewed page.
-      this.mPageTextBox.valueNumber += aDirection;
+      this.mPageTextBox.value = Number(this.mPageTextBox.value) + aDirection;
       navType = nsIWebBrowserPrint.PRINTPREVIEW_GOTO_PAGENUM;
-      pageNum = this.mPageTextBox.value; // TODO: back to valueNumber?
+      pageNum = this.mPageTextBox.value;
     } else {
       // We're going to a specific page (aPageNum)
       navType = nsIWebBrowserPrint.PRINTPREVIEW_GOTO_PAGENUM;
       pageNum = aPageNum;
     }
 
     this.mMessageManager.sendAsyncMessage("Printing:Preview:Navigate", {
       navType,
--- a/toolkit/content/customElements.js
+++ b/toolkit/content/customElements.js
@@ -136,17 +136,18 @@ const MozElementMixin = Base => class Mo
     let doc = gXULDOMParser.parseFromString(`
       ${entities.length ? `<!DOCTYPE bindings [
         ${entities.reduce((preamble, url, index) => {
           return preamble + `<!ENTITY % _dtd-${index} SYSTEM "${url}">
             %_dtd-${index};
             `;
         }, "")}
       ]>` : ""}
-      <box xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+      <box xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+           xmlns:html="http://www.w3.org/1999/xhtml">
         ${str}
       </box>
     `, "application/xml");
     // The XUL/XBL parser is set to ignore all-whitespace nodes, whereas (X)HTML
     // does not do this. Most XUL code assumes that the whitespace has been
     // stripped out, so we simply remove all text nodes after using the parser.
     let nodeIterator = doc.createNodeIterator(doc, NodeFilter.SHOW_TEXT);
     let currentNode = nodeIterator.nextNode();
--- a/toolkit/content/jar.mn
+++ b/toolkit/content/jar.mn
@@ -70,17 +70,16 @@ toolkit.jar:
    content/global/bindings/datepicker.js       (widgets/datepicker.js)
    content/global/bindings/datetimebox.xml     (widgets/datetimebox.xml)
    content/global/bindings/datetimebox.css     (widgets/datetimebox.css)
 *  content/global/bindings/dialog.xml          (widgets/dialog.xml)
    content/global/bindings/general.xml         (widgets/general.xml)
    content/global/bindings/menu.xml            (widgets/menu.xml)
    content/global/bindings/menulist.xml        (widgets/menulist.xml)
    content/global/bindings/notification.xml    (widgets/notification.xml)
-   content/global/bindings/numberbox.xml       (widgets/numberbox.xml)
    content/global/bindings/popup.xml           (widgets/popup.xml)
    content/global/bindings/radio.xml           (widgets/radio.xml)
    content/global/bindings/richlistbox.xml     (widgets/richlistbox.xml)
    content/global/bindings/scrollbox.xml       (widgets/scrollbox.xml)
    content/global/bindings/spinner.js          (widgets/spinner.js)
 *  content/global/bindings/tabbox.xml          (widgets/tabbox.xml)
    content/global/bindings/text.xml            (widgets/text.xml)
 *  content/global/bindings/textbox.xml         (widgets/textbox.xml)
@@ -88,17 +87,17 @@ toolkit.jar:
    content/global/bindings/timepicker.js       (widgets/timepicker.js)
    content/global/bindings/toolbar.xml         (widgets/toolbar.xml)
    content/global/bindings/toolbarbutton.xml   (widgets/toolbarbutton.xml)
    content/global/bindings/tree.xml            (widgets/tree.xml)
    content/global/bindings/videocontrols.xml   (widgets/videocontrols.xml)
 *  content/global/bindings/wizard.xml          (widgets/wizard.xml)
    content/global/elements/datetimebox.js      (widgets/datetimebox.js)
    content/global/elements/findbar.js          (widgets/findbar.js)
-   content/global/elements/editor.js          (widgets/editor.js)
+   content/global/elements/editor.js           (widgets/editor.js)
    content/global/elements/general.js          (widgets/general.js)
    content/global/elements/notificationbox.js  (widgets/notificationbox.js)
    content/global/elements/pluginProblem.js    (widgets/pluginProblem.js)
    content/global/elements/radio.js            (widgets/radio.js)
    content/global/elements/richlistbox.js      (widgets/richlistbox.js)
    content/global/elements/marquee.css         (widgets/marquee.css)
    content/global/elements/marquee.js          (widgets/marquee.js)
    content/global/elements/stringbundle.js     (widgets/stringbundle.js)
--- a/toolkit/content/tests/chrome/chrome.ini
+++ b/toolkit/content/tests/chrome/chrome.ini
@@ -177,17 +177,16 @@ support-files = window_preferences_onsyn
 [test_screenPersistence.xul]
 [test_scrollbar.xul]
 [test_showcaret.xul]
 [test_subframe_origin.xul]
 [test_tabbox.xul]
 [test_tabindex.xul]
 [test_textbox_dictionary.xul]
 [test_textbox_emptytext.xul]
-[test_textbox_number.xul]
 [test_textbox_search.xul]
 [test_titlebar.xul]
 skip-if = os == "linux"
 [test_tooltip.xul]
 skip-if = (os == 'mac' && os_version == '10.10') || (os == 'win') # Bug 1141245, frequent timeouts on OSX 10.10, Windows
 [test_tooltip_noautohide.xul]
 [test_tree.xul]
 [test_tree_hier.xul]
deleted file mode 100644
--- a/toolkit/content/tests/chrome/test_textbox_number.xul
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
-<!--
-  XUL Widget Test for textbox type="number"
-  -->
-<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>
-
-<hbox>
-  <textbox id="n1" type="number"/>
-  <textbox id="n2" type="number" value="10" min="5" max="15"/>
-</hbox>
-<hbox>
-  <textbox id="n4" type="number" value="-2" min="-8" max="18"/>
-  <textbox id="n5" type="number" value="-17" min="-10" max="-3"/>
-</hbox>
-<hbox>
-  <textbox id="n6" type="number" value="9" min="12" max="8"/>
-  <textbox id="n8" type="number" hidespinbuttons="true"/>
-</hbox>
-<hbox>
-  <textbox id="n9" type="number" oninput="updateInputEventCount();"/>
-</hbox>
-
-  <!-- test results are displayed in the html:body -->
-  <body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
-
-  <!-- test code goes here -->
-  <script type="application/javascript"><![CDATA[
-SimpleTest.waitForExplicitFinish();
-
-// ---- NOTE: the numbers used in these tests are carefully chosen to avoid
-// ----       floating point rounding issues
-
-function doTests() {
-  var n1 = $("n1");
-  var n2 = $("n2");
-  var n4 = $("n4");
-  var n5 = $("n5");
-  var n6 = $("n6");
-
-  testValsMinMax(n1, "initial n1", 0, 0, Infinity);
-  testValsMinMax(n2, "initial n2", 10, 5, 15);
-  testValsMinMax(n4, "initial n4", -2, -8, 18);
-  testValsMinMax(n5, "initial n5", -10, -10, -3);
-  testValsMinMax(n6, "initial n6", 12, 12, 12);
-
-  // test changing the value
-  n1.value = "1700";
-  testVals(n1, "set value,", 1700);
-  n1.value = 1600;
-  testVals(n1, "set value int,", 1600);
-  n2.value = "2";
-  testVals(n2, "set value below min,", 5);
-  n2.value = 2;
-  testVals(n2, "set value below min int,", 5);
-  n2.value = 18;
-  testVals(n2, "set value above max,", 15);
-  n2.value = -6;
-  testVals(n2, "set value below min negative,", 5);
-  n5.value = -2;
-  testVals(n5, "set value above max positive,", -3);
-  n1.value = 4.75;
-  testVals(n1, "set value to decimal round,", 5);
-
-  // test changing the valueNumber
-  n1.valueNumber = 27;
-  testVals(n1, "set valueNumber,", 27);
-  n2.valueNumber = 1;
-  testVals(n2, "set valueNumber below min,", 5);
-  n2.valueNumber = 77;
-  testVals(n2, "set valueNumber above max,", 15);
-  n2.valueNumber = -5;
-  testVals(n2, "set valueNumber below min negative,", 5);
-  n5.valueNumber = -8;
-  n5.valueNumber = -1;
-  testVals(n5, "set valueNumber above max positive,", -3);
-  n1.value = 8.9;
-  testVals(n1, "set valueNumber to decimal round,", 9);
-
-  // test changing the min
-  n1.value = 6;
-  n1.min = 8;
-  testValsMinMax(n1, "set integer min,", 8, 8, Infinity);
-
-  // test changing the max
-  n1.value = 25;
-  n1.max = 22;
-  testValsMinMax(n1, "set integer max,", 22, 8, 22);
-
-  // 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("KEY_ArrowUp", {}, n1, "!change", "key up read only");
-  is(n1.value, "12", "key up read only value");
-  synthesizeKeyExpectEvent("KEY_ArrowDown", {}, n1, "!change", "key down read only");
-  is(n1.value, "12", "key down read only value");
-
-  n1.readOnly = false;
-
-  var n9 = $("n9");
-  is(n9.value, "0", "initial value");
-  n9.select();
-  sendString("4");
-  is(inputEventCount, 1, "input event count");
-  is(inputEventValue, "4", "input value");
-  is(n9.value, "4", "updated value");
-  sendString("2");
-  is(inputEventCount, 2, "input event count");
-  is(inputEventValue, "42", "input value");
-  is(n9.value, "42", "updated value");
-  synthesizeKey("KEY_Backspace");
-  is(inputEventCount, 3, "input event count");
-  is(inputEventValue, "4", "input value");
-  is(n9.value, "4", "updated value");
-  synthesizeKey("A", {accelKey: true});
-  synthesizeKey("KEY_Delete");
-  is(inputEventCount, 4, "input event count");
-  is(inputEventValue, "0", "input value");
-  is(n9.value, "0", "updated value");
-
-  SimpleTest.finish();
-}
-
-var inputEventCount = 0;
-var inputEventValue = null;
-function updateInputEventCount() {
-  inputEventValue = $("n9").value;
-  inputEventCount++;
-};
-
-function testVals(nb, name, valueNumber, valueFieldNumber) {
-  if (valueFieldNumber === undefined)
-    valueFieldNumber = "" + valueNumber;
-
-  SimpleTest.is(nb.value, "" + valueNumber, name + " value is '" + valueNumber + "'");
-  SimpleTest.is(nb.valueNumber, valueNumber, name + " valueNumber is " + valueNumber);
-  SimpleTest.is(nb.inputField.value, valueFieldNumber,
-      name + " inputField value is '" + valueFieldNumber + "'");
-}
-
-function testValsMinMax(nb, name, valueNumber, min, max, valueFieldNumber) {
-  testVals(nb, name, valueNumber, valueFieldNumber);
-  SimpleTest.is(nb.min, min, name + " min is " + min);
-  SimpleTest.is(nb.max, max, name + " max is " + max);
-}
-
-SimpleTest.waitForFocus(doTests);
-
-  ]]></script>
-
-</window>
--- a/toolkit/content/widgets.css
+++ b/toolkit/content/widgets.css
@@ -11,23 +11,20 @@
 @import url("chrome://global/skin/button.css");
 @import url("chrome://global/skin/checkbox.css");
 @import url("chrome://global/skin/dialog.css");
 @import url("chrome://global/skin/dropmarker.css");
 @import url("chrome://global/skin/findBar.css");
 @import url("chrome://global/skin/menu.css");
 @import url("chrome://global/skin/menulist.css");
 @import url("chrome://global/skin/notification.css");
+@import url("chrome://global/skin/numberinput.css");
 @import url("chrome://global/skin/popup.css");
 @import url("chrome://global/skin/radio.css");
 @import url("chrome://global/skin/richlistbox.css");
 @import url("chrome://global/skin/scrollbox.css");
 @import url("chrome://global/skin/splitter.css");
 @import url("chrome://global/skin/tabbox.css");
-
-/* numberbox.css needs to be loaded after textbox.css since it overrides it */
 @import url("chrome://global/skin/textbox.css");
-@import url("chrome://global/skin/numberbox.css");
-
 @import url("chrome://global/skin/toolbar.css");
 @import url("chrome://global/skin/toolbarbutton.css");
 @import url("chrome://global/skin/tree.css");
 @import url("chrome://global/skin/wizard.css");
deleted file mode 100644
--- a/toolkit/content/widgets/numberbox.xml
+++ /dev/null
@@ -1,146 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<bindings id="numberboxBindings"
-   xmlns="http://www.mozilla.org/xbl"
-   xmlns:html="http://www.w3.org/1999/xhtml"
-   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-   xmlns:xbl="http://www.mozilla.org/xbl">
-
-  <binding id="numberbox"
-           extends="chrome://global/content/bindings/textbox.xml#textbox">
-    <content>
-      <xul:moz-input-box anonid="moz-input-box" class="numberbox-input-box" flex="1" xbl:inherits="context,disabled,focused">
-        <html:input class="numberbox-input textbox-input" type="number" anonid="input"
-                    xbl:inherits="value,min,max,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey"/>
-      </xul:moz-input-box>
-    </content>
-
-    <implementation>
-      <field name="_valueEntered">false</field>
-      <field name="_value">0</field>
-
-      <property name="value" onget="return String(this.valueNumber)"
-                             onset="return this.valueNumber = val;"/>
-
-      <property name="valueNumber">
-        <getter>
-          if (this._valueEntered) {
-            var newval = this.inputField.value;
-            this._validateValue(newval);
-          }
-          return this._value;
-        </getter>
-        <setter>
-          this._validateValue(val);
-          return val;
-        </setter>
-      </property>
-      <property name="min">
-        <getter>
-          var min = this.getAttribute("min");
-          return min ? Number(min) : 0;
-        </getter>
-        <setter>
-        <![CDATA[
-          if (typeof val == "number") {
-            this.setAttribute("min", val);
-            if (this.valueNumber < val)
-              this._validateValue(val);
-          }
-          return val;
-        ]]>
-        </setter>
-      </property>
-
-      <property name="max">
-        <getter>
-          var max = this.getAttribute("max");
-          return max ? Number(max) : Infinity;
-        </getter>
-        <setter>
-        <![CDATA[
-          if (typeof val != "number")
-            return val;
-          var min = this.min;
-          if (val < min)
-            val = min;
-          this.setAttribute("max", val);
-          if (this.valueNumber > val)
-            this._validateValue(val);
-          return val;
-        ]]>
-        </setter>
-      </property>
-
-      <method name="_validateValue">
-        <parameter name="aValue"/>
-        <body>
-          <![CDATA[
-            aValue = Number(aValue) || 0;
-            aValue = Math.round(aValue);
-
-            var min = this.min;
-            var max = this.max;
-            if (aValue < min)
-              aValue = min;
-            else if (aValue > max)
-              aValue = max;
-
-            this._valueEntered = false;
-            this._value = Number(aValue);
-            this.inputField.value = aValue;
-
-            return aValue;
-          ]]>
-        </body>
-      </method>
-
-      <method name="_fireChange">
-        <body>
-          var evt = document.createEvent("Events");
-          evt.initEvent("change", true, true);
-          this.dispatchEvent(evt);
-        </body>
-      </method>
-
-      <constructor><![CDATA[
-        if (this.max < this.min)
-          this.max = this.min;
-
-        var value = this.inputField.value || 0;
-        this._validateValue(value);
-      ]]></constructor>
-
-    </implementation>
-
-    <handlers>
-      <handler event="input" phase="capturing">
-        this._valueEntered = true;
-      </handler>
-
-      <handler event="keypress">
-        <![CDATA[
-          if (!event.ctrlKey && !event.metaKey && !event.altKey && event.charCode) {
-            if (event.charCode == 45 && this.min < 0)
-              return;
-
-            if (event.charCode < 48 || event.charCode > 57)
-              event.preventDefault();
-          }
-        ]]>
-      </handler>
-
-      <handler event="change">
-        if (event.originalTarget == this.inputField) {
-          this._validateValue(this.inputField.value);
-        }
-      </handler>
-    </handlers>
-
-  </binding>
-
-</bindings>
--- a/toolkit/content/widgets/textbox.xml
+++ b/toolkit/content/widgets/textbox.xml
@@ -189,39 +189,37 @@
     </implementation>
 
     <handlers>
       <handler event="focus" phase="capturing">
         <![CDATA[
           if (this.hasAttribute("focused"))
             return;
 
-          let { originalTarget } = event;
-          if (originalTarget == this) {
-            // Forward focus to actual HTML input
-            this.inputField.focus();
-            this.setAttribute("focused", "true");
-            return;
+          switch (event.originalTarget) {
+            case this:
+              // Forward focus to actual HTML input
+              this.inputField.focus();
+              this.setAttribute("focused", "true");
+              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) {}
+              }
+              this.setAttribute("focused", "true");
+              break;
+            default:
+              // Otherwise, allow other children (e.g. URL bar buttons) to get focus
+              break;
           }
-
-          // 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>
 
       <handler event="blur" phase="capturing">
         <![CDATA[
           this.removeAttribute("focused");
 
           // don't trigger clickSelectsAll when switching application windows
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -557,20 +557,16 @@ html|textarea.textbox-textarea {
 textbox[resizable="true"] > moz-input-box > html|textarea.textbox-textarea {
   resize: both;
 }
 
 textbox[type="search"] {
   -moz-binding: url("chrome://global/content/bindings/textbox.xml#search-textbox");
 }
 
-textbox[type="number"] {
-  -moz-binding: url("chrome://global/content/bindings/numberbox.xml#numberbox");
-}
-
 @supports -moz-bool-pref("layout.css.emulate-moz-box-with-flex") {
   html|*.textbox-input,
   html|*.textbox-textarea {
     /* Be block-level, so that -moz-box-flex can take effect, when we are an item
        in a -moz-box being emulated by modified modern flex. */
     display: block;
   }
 }
--- a/toolkit/themes/linux/global/global.css
+++ b/toolkit/themes/linux/global/global.css
@@ -6,16 +6,17 @@
   == Styles that apply everywhere.
   ======================================================================= */
 
 /* all localizable skin settings shall live here */
 @import url("chrome://global/locale/intl.css");
 @import url("chrome://global/content/widgets.css");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+@namespace html url("http://www.w3.org/1999/xhtml");
 
 %include ../../shared/global.inc.css
 
 /* ::::: XBL bindings ::::: */
 
 menulist > menupopup {
   -moz-binding: url("chrome://global/content/bindings/popup.xml#popup-scrollbars");
 }
@@ -120,19 +121,20 @@ toolbar[mode="text"] .toolbarbutton-text
 #print-preview-portrait-button {
   list-style-image: url("moz-icon://stock/gtk-orientation-portrait?size=button");
 }
 
 #print-preview-landscape-button {
   list-style-image: url("moz-icon://stock/gtk-orientation-landscape?size=button");
 }
 
-#print-preview-pageNumber {
-  /* 3 chars + 4px padding left + 2px padding right + 2*6px border */
-  width: calc(18px + 3ch);
+html|*#print-preview-pageNumber {
+  /* 3 chars + (3px border + 1px padding) on both sides */
+  width: calc(8px + 3ch);
+  margin: 0 4px;
 }
 
 /* ::::: miscellaneous formatting ::::: */
 
 :root:-moz-lwtheme {
   -moz-appearance: none;
 }
 
@@ -256,9 +258,8 @@ notification > hbox > button {
   margin-bottom: 0;
 }
 
 popupnotificationcontent {
   margin-top: .5em;
 }
 
 %include ../../shared/notification-popup.inc.css
-
--- a/toolkit/themes/linux/global/in-content/common.css
+++ b/toolkit/themes/linux/global/in-content/common.css
@@ -38,21 +38,16 @@ xul|*.radio-check[selected] {
   background-color: -moz-field;
   fill: -moz-fieldText;
 }
 
 xul|*.radio-label-box {
   -moz-appearance: none;
 }
 
-xul|*.numberbox-input-box {
-  -moz-appearance: none;
-  border-width: 0;
-}
-
 xul|menulist:-moz-focusring > xul|*.menulist-label-box {
   outline: none;
 }
 
 html|input[type="checkbox"]:-moz-focusring + html|label:before {
   outline: 1px dotted;
 }
 
--- a/toolkit/themes/mobile/jar.mn
+++ b/toolkit/themes/mobile/jar.mn
@@ -8,17 +8,17 @@ toolkit.jar:
    skin/classic/global/autocomplete.css                    (global/empty.css)
    skin/classic/global/button.css                          (global/empty.css)
    skin/classic/global/checkbox.css                        (global/empty.css)
    skin/classic/global/dialog.css                          (global/empty.css)
    skin/classic/global/dropmarker.css                      (global/empty.css)
    skin/classic/global/global.css                          (global/empty.css)
    skin/classic/global/menu.css                            (global/empty.css)
    skin/classic/global/menulist.css                        (global/empty.css)
-   skin/classic/global/numberbox.css                       (global/empty.css)
+   skin/classic/global/numberinput.css                     (global/empty.css)
    skin/classic/global/popup.css                           (global/empty.css)
    skin/classic/global/radio.css                           (global/empty.css)
    skin/classic/global/richlistbox.css                     (global/empty.css)
    skin/classic/global/scrollbox.css                       (global/empty.css)
    skin/classic/global/splitter.css                        (global/empty.css)
    skin/classic/global/tabbox.css                          (global/empty.css)
    skin/classic/global/textbox.css                         (global/empty.css)
    skin/classic/global/toolbar.css                         (global/empty.css)
--- a/toolkit/themes/osx/global/in-content/common.css
+++ b/toolkit/themes/osx/global/in-content/common.css
@@ -65,24 +65,16 @@ xul|tab:-moz-focusring > .tab-middle > .
   outline-offset: 1px;
   -moz-outline-radius: 2px;
 }
 
 xul|radio[focused="true"] > .radio-check {
   -moz-outline-radius: 100%;
 }
 
-html|*.numberbox-input::-moz-number-spin-up {
-  border-radius: 4px 4px 0 0;
-}
-
-html|*.numberbox-input::-moz-number-spin-down  {
-  border-radius: 0 0 4px 4px;
-}
-
 textbox[type="search"] {
   -moz-appearance: none;
   padding-inline-start: 8px;
   padding-inline-end: 8px;
 }
 
 xul|textbox[type="search"] > moz-input-box > .textbox-search-sign {
   list-style-image: url(chrome://global/skin/icons/search-textbox.svg);
--- a/toolkit/themes/shared/in-content/common.inc.css
+++ b/toolkit/themes/shared/in-content/common.inc.css
@@ -160,19 +160,17 @@ html|button {
   padding: 3px;
 }
 
 /* xul buttons and menulists */
 
 *|button,
 html|select,
 html|input[type="color"],
-xul|menulist,
-html|*.numberbox-input::-moz-number-spin-up,
-html|*.numberbox-input::-moz-number-spin-down {
+xul|menulist {
   -moz-appearance: none;
   min-height: 32px;
   /* !important overrides button.css for disabled and default XUL buttons: */
   color: inherit !important;
   border: none;
   border-radius: 2px;
   background-color: var(--in-content-button-background);
   font-weight: 400;
@@ -194,19 +192,17 @@ html|button::-moz-focus-inner,
 html|select::-moz-focus-inner,
 html|input[type="color"]::-moz-focus-inner {
   border: none;
 }
 
 *|button:-moz-focusring,
 html|select:-moz-focusring,
 html|input[type="color"]:-moz-focusring,
-xul|menulist:-moz-focusring,
-html|input[type="number"]:-moz-focusring::-moz-number-spin-up,
-html|input[type="number"]:-moz-focusring::-moz-number-spin-down {
+xul|menulist:-moz-focusring {
   outline: none;
   box-shadow: 0 0 0 1px var(--in-content-border-active) inset,
     0 0 0 1px var(--in-content-border-active),
     0 0 0 4px var(--in-content-border-active-shadow);
 }
 
 html|select:not([size]):not([multiple]) {
   background-image: url("chrome://global/skin/in-content/dropdown.svg#dropdown");
@@ -220,37 +216,32 @@ html|select:not([size]):not([multiple]) 
 }
 
 html|select:not([size]):not([multiple]):dir(rtl) {
   background-position: left 3px center;
 }
 
 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,
 html|input[type="color"]:hover,
 xul|button:not([disabled="true"]):hover,
 xul|menulist:not([disabled="true"]):hover {
   background-color: var(--in-content-button-background-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,
 html|input[type="color"]:enabled:hover:active,
 xul|button:not([disabled="true"]):hover:active,
 xul|menulist[open="true"]:not([disabled="true"]) {
   background-color: var(--in-content-button-background-active);
 }
 
 html|button:disabled,
 html|select:disabled,
-html|*.numberbox-input:disabled::-moz-number-spin-box,
 html|input[type="color"]:disabled,
 xul|button[disabled="true"],
 xul|menulist[disabled="true"] {
   opacity: 0.4;
 }
 
 *|button.primary {
   background-color: var(--in-content-primary-button-background);
@@ -292,38 +283,16 @@ xul|button[type="menu"] > xul|*.button-b
 
 xul|*.close-icon > xul|*.button-box {
   padding-top: 0;
   padding-bottom: 0;
   padding-right: 0 !important;
   padding-left: 0 !important;
 }
 
-html|*.numberbox-input::-moz-number-spin-box {
-  margin-inline-end: 1px;
-}
-
-html|*.numberbox-input::-moz-number-spin-up,
-html|*.numberbox-input::-moz-number-spin-down {
-  padding: 5px 8px;
-  margin: 0;
-  min-height: initial;
-  background-position: center;
-}
-
-html|*.numberbox-input::-moz-number-spin-up {
-  border-radius: 1px 1px 0 0;
-  background-image: url("chrome://global/skin/arrow/arrow-up.gif");
-}
-
-html|*.numberbox-input::-moz-number-spin-down {
-  border-radius: 0 0 1px 1px;
-  background-image: url("chrome://global/skin/arrow/arrow-dn.gif");
-}
-
 xul|*.menulist-dropmarker {
   -moz-appearance: none;
   margin-inline-end: 4px;
   padding: 0;
   border: none;
   background-color: transparent;
   list-style-image: url("chrome://global/skin/in-content/dropdown.svg");
   -moz-context-properties: fill;
@@ -413,24 +382,16 @@ xul|textbox {
 }
 
 xul|textbox {
   min-height: 30px;
   padding-right: 8px;
   padding-left: 8px;
 }
 
-xul|textbox[type="number"] {
-  padding-inline-end: 0;
-}
-
-html|*.numberbox-input::-moz-number-text {
-  margin-inline-end: 10px;
-}
-
 /* Create a separate rule to unset these styles on .tree-input instead of
    using :not(.tree-input) so the selector specifity doesn't change. */
 xul|textbox.tree-input {
   min-height: unset;
   padding-right: unset;
   padding-left: unset;
 }
 
--- a/toolkit/themes/shared/jar.inc.mn
+++ b/toolkit/themes/shared/jar.inc.mn
@@ -17,17 +17,17 @@ toolkit.jar:
   skin/classic/global/aboutMemory.css                      (../../shared/aboutMemory.css)
 * skin/classic/global/aboutReader.css                      (../../shared/aboutReader.css)
   skin/classic/global/aboutRights.css                      (../../shared/aboutRights.css)
   skin/classic/global/aboutLicense.css                     (../../shared/aboutLicense.css)
   skin/classic/global/aboutSupport.css                     (../../shared/aboutSupport.css)
   skin/classic/global/appPicker.css                        (../../shared/appPicker.css)
   skin/classic/global/config.css                           (../../shared/config.css)
   skin/classic/global/datetimeinputpickers.css             (../../shared/datetimeinputpickers.css)
-  skin/classic/global/numberbox.css                        (../../shared/numberbox.css)
+  skin/classic/global/numberinput.css                      (../../shared/numberinput.css)
   skin/classic/global/passwordmgr.css                      (../../shared/passwordmgr.css)
   skin/classic/global/icons/autoscroll.svg                 (../../shared/icons/autoscroll.svg)
   skin/classic/global/icons/autoscroll-horizontal.svg      (../../shared/icons/autoscroll-horizontal.svg)
   skin/classic/global/icons/autoscroll-vertical.svg        (../../shared/icons/autoscroll-vertical.svg)
   skin/classic/global/icons/calendar-arrow-left.svg        (../../shared/icons/calendar-arrow-left.svg)
   skin/classic/global/icons/calendar-arrow-right.svg       (../../shared/icons/calendar-arrow-right.svg)
   skin/classic/global/icons/check.svg                      (../../shared/icons/check.svg)
   skin/classic/global/icons/check-partial.svg              (../../shared/icons/check-partial.svg)
rename from toolkit/themes/shared/numberbox.css
rename to toolkit/themes/shared/numberinput.css
--- a/toolkit/themes/shared/numberbox.css
+++ b/toolkit/themes/shared/numberinput.css
@@ -1,42 +1,35 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/* ===== numberbox.css ==================================================
-  == Styles used by the XUL textbox type="number" element.
+/* ===== numberinput.css ================================================
+  == Styles used by the input[type="number"] element.
   ======================================================================= */
 
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+@namespace xul url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 @namespace html url("http://www.w3.org/1999/xhtml");
 
-html|*.numberbox-input {
+html|input[type="number"] {
   text-align: right;
 }
 
-textbox[type="number"][hidespinbuttons="true"] html|*.numberbox-input {
-  -moz-appearance: textfield;
+html|input[type="number"][hidespinbuttons="true"] {
+  -moz-appearance: textfield !important;
 }
 
 /* input[type=number] uses display: flex; by default which is incompatible with XUL flexbox
    Forcing XUL flexbox allows changing the size of the input. */
-html|*.numberbox-input,
-html|*.numberbox-input::-moz-number-wrapper,
-html|*.numberbox-input::-moz-number-spin-box {
+xul|*:root html|input[type="number"],
+xul|*:root html|input[type="number"]::-moz-number-wrapper {
   display: -moz-box;
   -moz-box-align: center;
 }
 
-html|*.numberbox-input::-moz-number-spin-box {
-  -moz-box-orient: vertical;
-}
-
-html|*.numberbox-input::-moz-number-wrapper,
-html|*.numberbox-input::-moz-number-spin-up,
-html|*.numberbox-input::-moz-number-spin-down,
-html|*.numberbox-input::-moz-number-text {
+xul|*:root html|input[type="number"]::-moz-number-wrapper,
+xul|*:root html|input[type="number"]::-moz-number-text {
   -moz-box-flex: 1;
 }
 
-html|*.numberbox-input::-moz-number-wrapper {
+xul|*:root html|input[type="number"]::-moz-number-wrapper {
   width: 100%;
 }
--- a/toolkit/themes/windows/global/global.css
+++ b/toolkit/themes/windows/global/global.css
@@ -6,16 +6,17 @@
   == Styles that apply everywhere.
   ======================================================================= */
 
 /* all localizable skin settings shall live here */
 @import url("chrome://global/locale/intl.css");
 @import url("chrome://global/content/widgets.css");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+@namespace html url("http://www.w3.org/1999/xhtml");
 
 %include ../../shared/global.inc.css
 
 /* ::::: XBL bindings ::::: */
 
 menulist > menupopup {
   -moz-binding: url("chrome://global/content/bindings/popup.xml#popup-scrollbars");
 }
@@ -127,18 +128,20 @@ toolbar[mode="text"] .toolbarbutton-text
   -moz-image-region: rect(0px 16px 16px 0px);
 }
 
 #print-preview-landscape-button {
   list-style-image: url("chrome://global/skin/icons/Print-preview.png");
   -moz-image-region: rect(0px 32px 16px 16px);
 }
 
-#print-preview-pageNumber {
-  width: 3ch;
+html|*#print-preview-pageNumber {
+  /* 3 chars + (3px border + 1px padding) on both sides */
+  width: calc(8px + 3ch);
+  margin: 0 4px;
 }
 
 /* ::::: miscellaneous formatting ::::: */
 
 :root[lwtheme-image]:-moz-lwtheme-darktext {
   text-shadow: 0 -0.5px 1.5px white;
 }
 
@@ -261,9 +264,8 @@ label[disabled="true"] {
   outline: 1px dotted;
 }
 
 popupnotificationcontent {
   margin-top: .5em;
 }
 
 %include ../../shared/notification-popup.inc.css
-