Unify dialog infrastructure

This commit is contained in:
2026-03-20 07:56:41 +01:00
parent 96cc82db9e
commit a3f021e5e1
6 changed files with 2047 additions and 1150 deletions

95
js/dialog.js Normal file
View File

@@ -0,0 +1,95 @@
/* global window, document */
/**
* Unified Dialog Infrastructure
*
* Provides a shared modal overlay and dialog container that all other
* client-side modules (event popups, cache purge, etc.) can use.
*
* Usage:
* Luxtools.Dialog.show(htmlString) render content and open
* Luxtools.Dialog.close() close the dialog
* Luxtools.Dialog.getContainer() return the dialog DOM element
*/
(function () {
'use strict';
var Luxtools = window.Luxtools || (window.Luxtools = {});
var Dialog = (function () {
var overlay = null;
var container = null;
/**
* Lazily create the overlay + dialog container and attach them to
* the document body. Wires up click-outside-to-close and Escape.
*/
function ensureElements() {
if (overlay) return;
overlay = document.createElement('div');
overlay.className = 'luxtools-dialog-overlay';
overlay.style.display = 'none';
container = document.createElement('div');
container.className = 'luxtools-dialog';
container.setAttribute('role', 'dialog');
container.setAttribute('aria-modal', 'true');
overlay.appendChild(container);
document.body.appendChild(overlay);
// Close when clicking the backdrop (but not the dialog itself)
overlay.addEventListener('click', function (e) {
if (e.target === overlay) close();
});
// Close on Escape
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && overlay && overlay.style.display !== 'none') {
close();
}
});
}
/**
* Show the dialog with the given HTML content.
*
* The HTML should include a close button with class
* `luxtools-dialog-close` it will be wired up automatically.
*
* @param {string} html - innerHTML for the dialog container
*/
function show(html) {
ensureElements();
container.innerHTML = html;
overlay.style.display = 'flex';
// Auto-wire the close button inside the rendered content
var closeBtn = container.querySelector('.luxtools-dialog-close');
if (closeBtn) closeBtn.addEventListener('click', close);
}
/**
* Close (hide) the dialog.
*/
function close() {
if (overlay) overlay.style.display = 'none';
}
/**
* Return the dialog container element (creates it if necessary).
* Useful for querying form inputs after `show()`.
*
* @returns {HTMLElement}
*/
function getContainer() {
ensureElements();
return container;
}
return { show: show, close: close, getContainer: getContainer };
})();
Luxtools.Dialog = Dialog;
})();