Bug 1570852: Trap focus in delete confirmation dialog. r=jaws

Differential Revision: https://phabricator.services.mozilla.com/D43717

--HG--
extra : moz-landing-system : lando
This commit is contained in:
lesleynorton 2019-09-05 21:31:10 +00:00
parent 1c1704fdbb
commit 8f7faa78fb
2 changed files with 49 additions and 0 deletions

View File

@ -45,7 +45,28 @@ export default class ConfirmationDialog extends HTMLElement {
}
}
setKeyboardAccessForElementsExternalToDialog(enableTabbingOutsideDialog) {
const pageElements = document.querySelectorAll(
"login-item, login-list, menu-button, login-filter, fxaccounts-button, [tabindex]"
);
pageElements.forEach(el => {
if (!enableTabbingOutsideDialog) {
if (el.tabIndex > -1) {
el.dataset.oldTabIndex = el.tabIndex;
}
el.tabIndex = "-1";
} else if (el.dataset.oldTabIndex) {
el.tabIndex = el.dataset.oldTabIndex;
delete el.dataset.oldTabIndex;
} else {
el.removeAttribute("tabindex");
}
});
}
hide() {
this.setKeyboardAccessForElementsExternalToDialog(true);
this._cancelButton.removeEventListener("click", this);
this._confirmButton.removeEventListener("click", this);
this._dismissButton.removeEventListener("click", this);
@ -56,6 +77,7 @@ export default class ConfirmationDialog extends HTMLElement {
}
show({ title, message, confirmButtonLabel }) {
this.setKeyboardAccessForElementsExternalToDialog(false);
this.hidden = false;
document.l10n.setAttributes(this._title, title);

View File

@ -95,6 +95,33 @@ add_task(async function test_enter_key_to_confirm() {
ok(false, "The dialog Promise should not reject after hitting Return with the confirm button focused");
}
});
add_task(async function test_dialog_focus_trap() {
let displayEl = document.getElementById("display");
let displayElChildSpan = document.createElement("span");
displayElChildSpan.tabIndex = 0;
displayElChildSpan.id = "display-child";
displayEl.appendChild(displayElChildSpan);
gConfirmationDialog.show(options);
ok(!gConfirmationDialog.hidden, "The dialog should be visible");
ok(displayElChildSpan.tabIndex === -1, "The tabIndex value for elements with a hardcoded tabIndex attribute should be reset to '-1'.")
ok(displayElChildSpan.dataset.oldTabIndex === "0", "Existing tabIndex values should be stored in `dataset.oldTabIndex`.")
const isActiveElemDialogOrHTML = (elemTagName) => {
return (["HTML", "CONFIRMATION-DIALOG"].includes(elemTagName));
}
let iterator = 0;
while(iterator < 20) {
sendKey("TAB");
isnot(document.activeElement.id, "display-child", "The display-child element should not gain focus when the dialog is showing");
is(isActiveElemDialogOrHTML(document.activeElement.tagName), true, "The confirmation-dialog should always have focus when the dialog is showing");
iterator++;
}
});
</script>
</body>
</html>