Files
linkding/bookmarks/frontend/behaviors/modal.js
2025-12-21 10:00:55 +01:00

91 lines
2.2 KiB
JavaScript

import { Behavior, registerBehavior } from "./index";
import { FocusTrapController } from "./focus-utils";
export class ModalBehavior extends Behavior {
constructor(element) {
super(element);
this.onClose = this.onClose.bind(this);
this.onKeyDown = this.onKeyDown.bind(this);
this.overlay = element.querySelector(".modal-overlay");
this.closeButton = element.querySelector(".modal-header .close");
this.overlay.addEventListener("click", this.onClose);
this.closeButton.addEventListener("click", this.onClose);
document.addEventListener("keydown", this.onKeyDown);
this.init();
}
destroy() {
this.overlay.removeEventListener("click", this.onClose);
this.closeButton.removeEventListener("click", this.onClose);
document.removeEventListener("keydown", this.onKeyDown);
this.removeScrollLock();
this.focusTrap.destroy();
}
init() {
this.setupScrollLock();
this.focusTrap = new FocusTrapController(
this.element.querySelector(".modal-container"),
);
}
setupScrollLock() {
document.body.classList.add("scroll-lock");
}
removeScrollLock() {
document.body.classList.remove("scroll-lock");
}
onKeyDown(event) {
// Skip if event occurred within an input element
const targetNodeName = event.target.nodeName;
const isInputTarget =
targetNodeName === "INPUT" ||
targetNodeName === "SELECT" ||
targetNodeName === "TEXTAREA";
if (isInputTarget) {
return;
}
if (event.key === "Escape") {
this.onClose(event);
}
}
onClose(event) {
event.preventDefault();
this.element.classList.add("closing");
this.element.addEventListener(
"animationend",
(event) => {
if (event.animationName === "fade-out") {
this.doClose();
}
},
{ once: true },
);
}
doClose() {
this.element.remove();
this.removeScrollLock();
this.element.dispatchEvent(new CustomEvent("modal:close"));
// Navigate to close URL
const closeUrl = this.element.dataset.closeUrl;
const frame = this.element.dataset.turboFrame;
if (closeUrl) {
Turbo.visit(closeUrl, { action: "replace", frame: frame });
}
}
}
registerBehavior("ld-modal", ModalBehavior);