Molodetz blogrol volgens DPP-template
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
export class ModalManager {
|
||||
constructor() {
|
||||
this.stack = [];
|
||||
document.addEventListener("click", (event) => this.onClick(event));
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Escape" && this.stack.length) {
|
||||
this.close(this.stack[this.stack.length - 1]);
|
||||
}
|
||||
});
|
||||
window.addEventListener("popstate", () => {
|
||||
if (this.stack.length) {
|
||||
this.close(this.stack[this.stack.length - 1], false);
|
||||
}
|
||||
});
|
||||
new MutationObserver(() => this.wire()).observe(document.body, { childList: true, subtree: true });
|
||||
this.wire();
|
||||
}
|
||||
|
||||
wire() {
|
||||
document.querySelectorAll(".modal-overlay:not([data-wired])").forEach((overlay) => {
|
||||
overlay.dataset.wired = "1";
|
||||
overlay.setAttribute("role", overlay.getAttribute("role") || "dialog");
|
||||
overlay.setAttribute("aria-modal", "true");
|
||||
overlay.addEventListener("keydown", (event) => this.trap(event, overlay));
|
||||
});
|
||||
}
|
||||
|
||||
onClick(event) {
|
||||
const trigger = event.target.closest("[data-modal]");
|
||||
if (trigger) {
|
||||
event.preventDefault();
|
||||
this.open(document.getElementById(trigger.dataset.modal));
|
||||
return;
|
||||
}
|
||||
if (event.target.closest(".modal-close")) {
|
||||
this.close(event.target.closest(".modal-overlay"));
|
||||
return;
|
||||
}
|
||||
if (event.target.classList?.contains("modal-overlay")) {
|
||||
this.close(event.target);
|
||||
}
|
||||
}
|
||||
|
||||
open(overlay) {
|
||||
if (!overlay) {
|
||||
return;
|
||||
}
|
||||
overlay.classList.add("visible");
|
||||
this.stack.push(overlay);
|
||||
history.pushState({ modal: overlay.id }, "");
|
||||
overlay.querySelector("button, a, input, select, textarea")?.focus();
|
||||
}
|
||||
|
||||
close(overlay, popHistory = true) {
|
||||
if (!overlay) {
|
||||
return;
|
||||
}
|
||||
overlay.classList.remove("visible");
|
||||
this.stack = this.stack.filter((item) => item !== overlay);
|
||||
if (popHistory && history.state?.modal === overlay.id) {
|
||||
history.back();
|
||||
}
|
||||
}
|
||||
|
||||
trap(event, overlay) {
|
||||
if (event.key !== "Tab") {
|
||||
return;
|
||||
}
|
||||
const focusable = [...overlay.querySelectorAll("button, a[href], input, select, textarea")].filter((el) => !el.disabled);
|
||||
if (!focusable.length) {
|
||||
return;
|
||||
}
|
||||
const first = focusable[0];
|
||||
const last = focusable[focusable.length - 1];
|
||||
if (event.shiftKey && document.activeElement === first) {
|
||||
event.preventDefault();
|
||||
last.focus();
|
||||
} else if (!event.shiftKey && document.activeElement === last) {
|
||||
event.preventDefault();
|
||||
first.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user