Merge pull request #1748 from joachimesque/handle-modal-buttons-with-fallback

Handle modal component when already active at page load
This commit is contained in:
Mouse Reeve 2022-01-02 06:58:42 -08:00 committed by GitHub
commit f50294875f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 42 additions and 33 deletions

View File

@ -41,6 +41,7 @@ let BookWyrm = new (class {
document document
.querySelectorAll("[data-duplicate]") .querySelectorAll("[data-duplicate]")
.forEach((node) => node.addEventListener("click", this.duplicateInput.bind(this))); .forEach((node) => node.addEventListener("click", this.duplicateInput.bind(this)));
document document
.querySelectorAll("details.dropdown") .querySelectorAll("details.dropdown")
.forEach((node) => .forEach((node) =>
@ -60,6 +61,7 @@ let BookWyrm = new (class {
.querySelectorAll('input[type="file"]') .querySelectorAll('input[type="file"]')
.forEach(bookwyrm.disableIfTooLarge.bind(bookwyrm)); .forEach(bookwyrm.disableIfTooLarge.bind(bookwyrm));
document.querySelectorAll("[data-copytext]").forEach(bookwyrm.copyText.bind(bookwyrm)); document.querySelectorAll("[data-copytext]").forEach(bookwyrm.copyText.bind(bookwyrm));
document.querySelectorAll(".modal.is-active").forEach(bookwyrm.handleActiveModal.bind(bookwyrm));
}); });
} }
@ -405,7 +407,7 @@ let BookWyrm = new (class {
} }
/** /**
* Handle the modal component. * Handle the modal component with a button trigger.
* *
* @param {Event} event - Event fired by an element * @param {Event} event - Event fired by an element
* with the `data-modal-open` attribute * with the `data-modal-open` attribute
@ -416,6 +418,7 @@ let BookWyrm = new (class {
* for information about using the modal. * for information about using the modal.
*/ */
handleModalButton(event) { handleModalButton(event) {
const { handleFocusTrap } = this
const modalButton = event.currentTarget; const modalButton = event.currentTarget;
const targetModalId = modalButton.dataset.modalOpen; const targetModalId = modalButton.dataset.modalOpen;
const htmlElement = document.querySelector("html"); const htmlElement = document.querySelector("html");
@ -457,40 +460,46 @@ let BookWyrm = new (class {
modalButton.focus(); modalButton.focus();
} }
function handleFocusTrap(event) { // Open modal
if (event.key !== "Tab") { handleModalOpen(modal);
}
/**
* Handle the modal component when opened at page load.
*
* @param {Element} modalElement - Active modal element
* @return {undefined}
*
*/
handleActiveModal(modalElement) {
if (!modalElement) {
return; return;
} }
const focusableEls = event.currentTarget.querySelectorAll( const { handleFocusTrap } = this
[
"a[href]:not([disabled])",
"button:not([disabled])",
"textarea:not([disabled])",
'input:not([type="hidden"]):not([disabled])',
"select:not([disabled])",
"details:not([disabled])",
'[tabindex]:not([tabindex="-1"]):not([disabled])',
].join(",")
);
const firstFocusableEl = focusableEls[0];
const lastFocusableEl = focusableEls[focusableEls.length - 1];
if (event.shiftKey) { modalElement.getElementsByClassName("modal-card")[0].focus();
/* Shift + tab */ if (document.activeElement === firstFocusableEl) {
lastFocusableEl.focus();
event.preventDefault();
}
} /* Tab */ else {
if (document.activeElement === lastFocusableEl) {
firstFocusableEl.focus();
event.preventDefault();
}
}
}
// Open modal const closeButtons = modalElement.querySelectorAll("[data-modal-close]");
handleModalOpen(modal);
closeButtons.forEach((button) => {
button.addEventListener("click", function () {
handleModalClose(modalElement);
});
});
document.addEventListener("keydown", function (event) {
if (event.key === "Escape") {
handleModalClose(modalElement);
}
});
modalElement.addEventListener("keydown", handleFocusTrap);
function handleModalClose(modalElement) {
modalElement.removeEventListener("keydown", handleFocusTrap);
history.back();
}
} }
/** /**