@ulu/frontend
Version:
A versatile SCSS and JavaScript component library offering configurable, accessible components and flexible integration into any project, with SCSS modules suitable for modern JS frameworks.
99 lines (90 loc) • 2.97 kB
JavaScript
/**
* @module ui/programmatic-modal
*/
import { getName, dispatch } from "../events/index.js";
import { newId } from "../utils/id.js";
import { buildModal } from "./modal-builder.js";
import { getElement } from "@ulu/utils/browser/dom.js";
export class ProgrammaticModalManager {
static defaults = {
triggerSelector: "[data-ulu-programmatic-modal-trigger]",
triggerInitAttr: "data-ulu-programmatic-modal-init"
};
constructor(passedOptions) {
const options = Object.assign({}, ProgrammaticModalManager.defaults, passedOptions);
this.options = options;
this.triggers = null;
this.cachedTrigger = null;
this.triggerListener;
this.onTriggerClick = (event) => {
const trigger = event.target.closest(options.triggerSelector);
if (trigger) this.cachedTrigger = trigger;
};
this.onPageModified = () => {
this.setupTriggers();
};
document.addEventListener(getName("pageModified"), this.onPageModified);
this.setupTriggers();
}
setupTriggers() {
const { triggerSelector, triggerInitAttr } = this.options;
const triggers = document.querySelectorAll(`${ triggerSelector }:not([${ triggerInitAttr }])`);
triggers.forEach(trigger => {
trigger.addEventListener("click", this.onTriggerClick);
});
}
destroy() {
const { triggerSelector } = this.options;
const triggers = document.querySelectorAll(triggerSelector);
triggers.forEach(trigger => {
trigger.removeEventListener("click", this.onTriggerClick);
});
}
createAndOpen(config, afterCreate) {
const { noClickTrigger, removeOnClose, element, classes } = config;
const content = getElement(element);
if (!content.id) {
content.id = newId();
}
// Added to match original jquery module api
if (classes) {
content.classList.add(...classes);
}
let trigger;
if (!noClickTrigger) {
trigger = this.cachedTrigger;
// Remove cached trigger (since it no longer applies)
this.cachedTrigger = null;
}
if (!content) {
console.error("No element found from config.element. ", config);
return;
}
const { modal } = buildModal(content, config.modal);
const ctx = { trigger, modal, config };
if (afterCreate) {
afterCreate(ctx);
}
const onModalClose = () => {
if (removeOnClose) {
modal.remove();
}
if (trigger) {
trigger.focus();
}
};
// Add close event (to refocus the element that triggered)
modal.addEventListener("close", onModalClose, { once: true });
// Setup trigger to show this modal again and not do it's old behavior (if ajax link)
if (!removeOnClose && trigger) {
trigger.addEventListener("click", (event) => {
event.preventDefault();
modal.showModal();
});
}
dispatch("pageModified", modal);
// Open the new modal for the first time
modal.showModal();
return ctx;
}
}