Bug 1527691 - Disabled datetimebox inner elements shouldn't be tabbable. r=Gijs
authorEmilio Cobos Álvarez <emilio@crisal.io>
Mon, 23 May 2022 12:56:46 +0000
changeset 618539 8f2ec80adf9a3f1aa07258268473c940b3b7580e
parent 618538 3fb319df49c63d4dced1dc5b9a823fd36abe8f68
child 618540 9f66ea577c6bd9d51799ac01a2dcd490148bc457
push id163321
push userealvarez@mozilla.com
push dateMon, 23 May 2022 12:59:11 +0000
treeherderautoland@8f2ec80adf9a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1527691
milestone102.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 1527691 - Disabled datetimebox inner elements shouldn't be tabbable. r=Gijs They're not focusable with mouse already. Differential Revision: https://phabricator.services.mozilla.com/D147084
dom/html/test/forms/test_input_datetime_tabindex.html
toolkit/content/widgets/datetimebox.js
--- a/dom/html/test/forms/test_input_datetime_tabindex.html
+++ b/dom/html/test/forms/test_input_datetime_tabindex.html
@@ -11,26 +11,28 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1288591">Mozilla Bug 1288591</a>
 <p id="display"></p>
 <div id="content">
   <input id="time1" type="time" tabindex="0">
   <input id="time2" type="time" tabindex="-1">
   <input id="time3" type="time" tabindex="0">
+  <input id="time4" type="time" disabled>
   <input id="date1" type="date" tabindex="0">
   <input id="date2" type="date" tabindex="-1">
   <input id="date3" type="date" tabindex="0">
+  <input id="date4" type="date" disabled>
   <input id="datetime-local1" type="datetime-local" tabindex="0">
   <input id="datetime-local2" type="datetime-local" tabindex="-1">
   <input id="datetime-local3" type="datetime-local" tabindex="0">
+  <input id="datetime-local4" type="datetime-local" disabled>
 </div>
 <pre id="test">
-<script type="application/javascript">
-
+<script>
 /**
  * Test for Bug 1288591.
  * This test checks whether date/time input types tabindex attribute works
  * correctly.
  **/
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(function() {
   test();
@@ -45,16 +47,17 @@ function checkInnerTextboxTabindex(input
   }
 
 }
 
 function testTabindex(type) {
   let input1 = document.getElementById(type + "1");
   let input2 = document.getElementById(type + "2");
   let input3 = document.getElementById(type + "3");
+  let input4 = document.getElementById(type + "4");
 
   input1.focus();
   is(document.activeElement, input1,
      "input element with tabindex=0 is focusable");
 
   let fieldCount = type == "datetime-local" ? 6 : 3;
 
   // Advance through inner fields.
@@ -71,24 +74,30 @@ function testTabindex(type) {
 
   input2.focus();
   is(document.activeElement, input2,
      "input element with tabindex=-1 is still focusable");
 
   checkInnerTextboxTabindex(input1, 0);
   checkInnerTextboxTabindex(input2, -1);
   checkInnerTextboxTabindex(input3, 0);
+  checkInnerTextboxTabindex(input4, -1);
 
   // Changing the tabindex attribute dynamically.
   input3.setAttribute("tabindex", "-1");
+
   synthesizeKey("KEY_Tab"); // need only one TAB since input2 is not tabbable
+
   isnot(document.activeElement, input3,
         "element with tabindex changed to -1 should not be tabbable");
+  isnot(document.activeElement, input4,
+        "disabled element should not be tabbable");
 
   checkInnerTextboxTabindex(input3, -1);
+  checkInnerTextboxTabindex(input4, -1);
 }
 
 function test() {
   for (let inputType of ["time", "date", "datetime-local"]) {
     testTabindex(inputType);
   }
 }
 
--- a/toolkit/content/widgets/datetimebox.js
+++ b/toolkit/content/widgets/datetimebox.js
@@ -341,17 +341,17 @@ this.DateTimeBoxWidget = class {
     aPageUpDownInterval
   ) {
     let root = this.shadowRoot.getElementById("edit-wrapper");
     let field = this.shadowRoot.createElementAndAppendChildAt(root, "span");
     field.classList.add("datetime-edit-field");
     field.textContent = aPlaceHolder;
     field.placeholder = aPlaceHolder;
     field.setAttribute("aria-valuetext", "");
-    field.tabIndex = this.mInputElement.tabIndex;
+    field.tabIndex = this.editFieldTabIndex();
 
     field.setAttribute("readonly", this.mInputElement.readOnly);
     field.setAttribute("disabled", this.mInputElement.disabled);
     // Set property as well for convenience.
     field.disabled = this.mInputElement.disabled;
     field.readOnly = this.mInputElement.readOnly;
     field.setAttribute("aria-label", aLabel);
 
@@ -442,16 +442,23 @@ this.DateTimeBoxWidget = class {
     }
   }
 
   setPickerState(aIsOpen) {
     this.log("picker is now " + (aIsOpen ? "opened" : "closed"));
     this.mIsPickerOpen = aIsOpen;
   }
 
+  editFieldTabIndex() {
+    if (this.mInputElement.disabled) {
+      return -1;
+    }
+    return this.mInputElement.tabIndex;
+  }
+
   updateEditAttributes() {
     this.log("updateEditAttributes");
 
     let editRoot = this.shadowRoot.getElementById("edit-wrapper");
 
     for (let child of editRoot.querySelectorAll(
       ":scope > span.datetime-edit-field"
     )) {
@@ -460,18 +467,18 @@ this.DateTimeBoxWidget = class {
       // checks the literal string attribute values.
       child.setAttribute("disabled", this.mInputElement.disabled);
       child.setAttribute("readonly", this.mInputElement.readOnly);
 
       // Set property as well for convenience.
       child.disabled = this.mInputElement.disabled;
       child.readOnly = this.mInputElement.readOnly;
 
-      // tabIndex works on all elements
-      child.tabIndex = this.mInputElement.tabIndex;
+      // tabIndex as a property works on all relevant elements.
+      child.tabIndex = this.editFieldTabIndex();
     }
 
     this.mResetButton.disabled =
       this.mInputElement.disabled || this.mInputElement.readOnly;
     this.updateResetButtonVisibility();
   }
 
   isEmpty(aValue) {