blob: 3499297fa16b04a4aa5506c017708675f98f023d [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../resources/accessibility-helper.js"></script>
<script src="../resources/js-test.js"></script>
</head>
<body>
<input type="text" id="textfield" value="Text field.">
<p id="bgContent">Other page content with <a id="background-link" tabindex="0" href="#">a dummy focusable element</a></p>
<p><a onclick="toggleDialog(document.getElementById('dialog1'), 'show'); return false;" href="#" role="button" id="displayBtn">Display a dialog</a></p>
<div role="dialog" aria-labelledby="description1" id="dialog1" style="display: none" tabindex="-1">
<h3 id="description1">Just an example.</h3>
<a id="dialog1-link" tabindex="0" href="#">Link present to ensure we have a focusable element</a>
<button id="ok" onclick="toggleDialog(document.getElementById('dialog1'), 'hide');">OK</button>
<button onclick="toggleDialog(document.getElementById('dialog2'), 'show');" id="new">New</button>
</div>
<div role="dialog" aria-labelledby="description2" id="dialog2" style="display: none" tabindex="-1">
<h3 id="description2">Another dialog.</h3>
<a id="dialog2-link" tabindex="0" href="#">Link present to ensure we have a focusable element</a>
<button id="close" onclick="toggleDialog(document.getElementById('dialog2'), 'hide');">Close</button>
</div>
<script>
var testOutput = "This tests that aria-modal works correctly on multiple dialogs\n\n";
if (window.accessibilityController) {
window.jsTestIsAsync = true;
setTimeout(async () => {
testOutput += "\nVerifying the background is accessible on page load.\n\n";
await backgroundAccessible(true);
testOutput += "\nClicking the display button to open #dialog1.\n\n";
document.getElementById("displayBtn").click();
await backgroundAccessible(false);
await dialog1Accessible(true);
testOutput += "\nClicking the new button to open #dialog2 without closing #dialog1.\n\n";
document.getElementById("new").click();
await backgroundAccessible(false);
await dialog1Accessible(false);
await dialog2Accessible(true);
// With both modals active, and focus currently in #dialog2, moving focus to #dialog1 should cause it to become the active modal.
testOutput += "\nFocusing first descendant of #dialog1.\n\n";
focusFirstDescendant(document.getElementById("dialog1"));
await backgroundAccessible(false);
await dialog1Accessible(true);
await dialog2Accessible(false);
testOutput += "\nMoving focus back to first descendant of #dialog2.\n\n";
focusFirstDescendant(document.getElementById("dialog2"));
await backgroundAccessible(false);
await dialog1Accessible(false);
await dialog2Accessible(true);
testOutput += "\nClosing dialog2.\n\n";
document.getElementById("close").click();
await backgroundAccessible(false);
await dialog1Accessible(true);
testOutput += "\nClosing dialog1.\n\n";
document.getElementById("ok").click();
await backgroundAccessible(true);
debug(testOutput);
finishJSTest();
});
}
async function backgroundAccessible(shouldBeAccessible) {
await waitFor(() => {
const displayBtn = accessibilityController.accessibleElementById("displayBtn");
const bgContent = accessibilityController.accessibleElementById("bgContent");
if (!displayBtn || !bgContent)
return !shouldBeAccessible;
return (!displayBtn.isIgnored && !bgContent.isIgnored) === shouldBeAccessible;
});
testOutput += `PASS: background accessible: ${shouldBeAccessible}\n`
}
async function dialog1Accessible(shouldBeAccessible) {
await waitFor(() => {
const okBtn = accessibilityController.accessibleElementById("ok");
const newBtn = accessibilityController.accessibleElementById("new");
if (!okBtn || !newBtn)
return !shouldBeAccessible;
return (!okBtn.isIgnored && !newBtn.isIgnored) === shouldBeAccessible;
});
testOutput += `PASS: #dialog1 accessible: ${shouldBeAccessible}\n`
}
async function dialog2Accessible(shouldBeAccessible) {
await waitFor(() => {
const closeButton = accessibilityController.accessibleElementById("close");
if (!closeButton)
return !shouldBeAccessible;
return closeButton.isIgnored !== shouldBeAccessible;
});
testOutput += `PASS: #dialog2 accessible: ${shouldBeAccessible}\n`
}
function toggleDialog(dialog, sh) {
if (sh == "show") {
dialog.style.display = "block";
dialog.setAttribute("aria-modal", "true");
// Put focus inside the new dialog so it takes precedence over other dialogs (even if they come later in DOM order).
focusFirstDescendant(dialog);
} else {
dialog.style.display = "none";
dialog.setAttribute("aria-modal", "false");
}
}
function focusFirstDescendant(element) {
for (let i = 0; i < element.childNodes.length; i++) {
const child = element.childNodes[i];
if (!attemptFocus(child))
focusFirstDescendant(child)
}
};
function attemptFocus(element) {
try { element.focus() } catch (e) {}
return document.activeElement === element;
}
</script>
</body>
</html>