${config.message}
/** * MicroModal Global Utilities * Provides helper functions for MicroModal management */ class ModalManager { constructor() { this.initialized = false; this.modals = new Map(); this.init(); } /** * Initialize MicroModal with default settings */ init() { if (typeof MicroModal === 'undefined') { console.warn('MicroModal is not loaded'); return; } if (this.initialized) { return; } MicroModal.init({ onShow: (modal) => { this.onModalShow(modal); }, onClose: (modal) => { this.onModalClose(modal); }, openTrigger: 'data-micromodal-trigger', closeTrigger: 'data-micromodal-close', openClass: 'is-open', disableScroll: true, disableFocus: false, awaitOpenAnimation: false, awaitCloseAnimation: false, debugMode: false }); this.initialized = true; console.log('MicroModal initialized'); } /** * Called when modal is shown */ onModalShow(modal) { // Re-initialize Lucide icons when modal opens if (typeof lucide !== 'undefined') { lucide.createIcons(); } // Add body class to prevent scrolling document.body.classList.add('modal-open'); // Execute custom show callback if exists if (modal && this.modals.has(modal.id)) { const config = this.modals.get(modal.id); if (config.onShow && typeof config.onShow === 'function') { config.onShow(modal); } } } /** * Called when modal is closed */ onModalClose(modal) { // Remove body class document.body.classList.remove('modal-open'); // Execute custom close callback if exists if (modal && this.modals.has(modal.id)) { const config = this.modals.get(modal.id); if (config.onClose && typeof config.onClose === 'function') { config.onClose(modal); } } } /** * Show modal with optional data */ show(modalId, data = {}) { if (typeof MicroModal === 'undefined') { console.error('MicroModal is not available'); return; } // Update modal content if data is provided if (Object.keys(data).length > 0) { this.updateModalContent(modalId, data); } MicroModal.show(modalId); } /** * Close modal */ close(modalId) { if (typeof MicroModal === 'undefined') { console.error('MicroModal is not available'); return; } MicroModal.close(modalId); } /** * Register a modal with custom configuration */ register(modalId, config = {}) { this.modals.set(modalId, config); } /** * Update modal content dynamically */ updateModalContent(modalId, data) { const modal = document.getElementById(modalId); if (!modal) { console.error(`Modal ${modalId} not found`); return; } // Update text content for elements with data-modal-* attributes Object.keys(data).forEach(key => { const element = modal.querySelector(`[data-modal-${key}]`); if (element) { if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') { element.value = data[key]; } else { element.textContent = data[key]; } } // Also support getElementById for backward compatibility const elementById = modal.querySelector(`#${key}`); if (elementById) { if (elementById.tagName === 'INPUT' || elementById.tagName === 'TEXTAREA') { elementById.value = data[key]; } else { elementById.textContent = data[key]; } } }); // Update form action if provided if (data.formAction) { const form = modal.querySelector('form'); if (form) { form.action = data.formAction; } } } /** * Create a confirmation modal dynamically */ showConfirmation(options = {}) { const defaults = { modalId: 'confirmationModal', title: 'Confirm Action', message: 'Are you sure?', confirmText: 'Confirm', cancelText: 'Cancel', confirmClass: 'btn btn-primary btn-sm', cancelClass: 'btn btn-outline-secondary btn-sm', onConfirm: null, onCancel: null }; const config = { ...defaults, ...options }; // Create modal HTML if it doesn't exist let modal = document.getElementById(config.modalId); if (!modal) { modal = this.createConfirmationModal(config); document.body.appendChild(modal); } else { // Update existing modal this.updateConfirmationModal(modal, config); } // Register callbacks this.register(config.modalId, { onShow: () => { const confirmBtn = modal.querySelector('.modal__confirm'); const cancelBtn = modal.querySelector('.modal__cancel'); // Remove existing event listeners confirmBtn.replaceWith(confirmBtn.cloneNode(true)); cancelBtn.replaceWith(cancelBtn.cloneNode(true)); // Add new event listeners modal.querySelector('.modal__confirm').addEventListener('click', (e) => { if (config.onConfirm && typeof config.onConfirm === 'function') { config.onConfirm(e); } this.close(config.modalId); }); modal.querySelector('.modal__cancel').addEventListener('click', (e) => { if (config.onCancel && typeof config.onCancel === 'function') { config.onCancel(e); } this.close(config.modalId); }); } }); this.show(config.modalId); } /** * Create confirmation modal HTML */ createConfirmationModal(config) { const modalHtml = `
`; const div = document.createElement('div'); div.innerHTML = modalHtml; return div.firstElementChild; } /** * Update existing confirmation modal */ updateConfirmationModal(modal, config) { modal.querySelector('.modal__title').textContent = config.title; modal.querySelector('.modal__content p').textContent = config.message; modal.querySelector('.modal__confirm').textContent = config.confirmText; modal.querySelector('.modal__cancel').textContent = config.cancelText; // Update button classes modal.querySelector('.modal__confirm').className = `modal__confirm ${config.confirmClass}`; modal.querySelector('.modal__cancel').className = `modal__cancel ${config.cancelClass}`; } } // Global instance window.ModalManager = new ModalManager(); // Helper functions for backward compatibility window.showModal = (modalId, data = {}) => { window.ModalManager.show(modalId, data); }; window.closeModal = (modalId) => { window.ModalManager.close(modalId); }; window.showConfirmation = (options) => { window.ModalManager.showConfirmation(options); }; // Auto-initialize when DOM is loaded document.addEventListener('DOMContentLoaded', function() { // Initialize Lucide icons if (typeof lucide !== 'undefined') { lucide.createIcons(); } console.log('Modal utilities loaded'); }); // Export for ES modules if (typeof module !== 'undefined' && module.exports) { module.exports = ModalManager; }