UNPKG

@ulu/frontend

Version:

A framework-agnostic frontend toolkit providing a modular, tree-shakable library of accessible components and utilities. Designed for seamless integration, it features a highly configurable SCSS system for any environment and vanilla JavaScript modules op

99 lines (90 loc) 3 kB
/** * @module ui/programmatic-modal */ import { getCoreEventName, dispatchCoreEvent } from "../core/events.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(getCoreEventName("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(); }); } dispatchCoreEvent("pageModified", modal); // Open the new modal for the first time modal.showModal(); return ctx; } }