/** * Mercedes-Benz MYP Platform - Zentrale Event Handler * CSP-konforme Event-Handler ohne Inline-JavaScript */ class GlobalEventManager { constructor() { this.init(); } init() { // Event-Delegation für bessere Performance und CSP-Konformität document.addEventListener('click', this.handleClick.bind(this)); document.addEventListener('DOMContentLoaded', this.setupEventListeners.bind(this)); // Falls DOM bereits geladen if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', this.setupEventListeners.bind(this)); } else { this.setupEventListeners(); } } /** * Zentrale Click-Handler mit Event-Delegation */ handleClick(event) { const target = event.target.closest('[data-action]'); if (!target) return; const action = target.getAttribute('data-action'); const params = this.parseActionParams(target); event.preventDefault(); this.executeAction(action, params, target); } /** * Action-Parameter aus data-Attributen parsen */ parseActionParams(element) { const params = {}; // Alle data-action-* Attribute sammeln for (const attr of element.attributes) { if (attr.name.startsWith('data-action-')) { const key = attr.name.replace('data-action-', ''); params[key] = attr.value; } } return params; } /** * Action ausführen basierend auf dem Action-Namen */ executeAction(action, params, element) { console.log(`🎯 Führe Action aus: ${action}`, params); switch (action) { // Dashboard Actions case 'refresh-dashboard': if (typeof refreshDashboard === 'function') refreshDashboard(); break; // Navigation Actions case 'logout': if (typeof handleLogout === 'function') handleLogout(); break; case 'go-back': window.history.back(); break; case 'reload-page': window.location.reload(); break; case 'print-page': window.print(); break; // Job Management Actions case 'refresh-jobs': if (typeof refreshJobs === 'function') refreshJobs(); break; case 'toggle-batch-mode': if (typeof toggleBatchMode === 'function') toggleBatchMode(); break; case 'start-job': if (typeof jobManager !== 'undefined' && params.id) { jobManager.startJob(params.id); } break; case 'pause-job': if (typeof jobManager !== 'undefined' && params.id) { jobManager.pauseJob(params.id); } break; case 'resume-job': if (typeof jobManager !== 'undefined' && params.id) { jobManager.resumeJob(params.id); } break; case 'delete-job': if (typeof jobManager !== 'undefined' && params.id) { jobManager.deleteJob(params.id); } break; case 'open-job-details': if (typeof jobManager !== 'undefined' && params.id) { jobManager.openJobDetails(params.id); } break; // Printer Management Actions case 'refresh-printers': if (typeof refreshPrinters === 'function') refreshPrinters(); break; case 'toggle-maintenance-mode': if (typeof toggleMaintenanceMode === 'function') toggleMaintenanceMode(); break; case 'open-add-printer-modal': if (typeof openAddPrinterModal === 'function') openAddPrinterModal(); break; case 'toggle-auto-refresh': if (typeof toggleAutoRefresh === 'function') toggleAutoRefresh(); break; case 'clear-all-filters': if (typeof clearAllFilters === 'function') clearAllFilters(); break; case 'test-printer-connection': if (typeof testPrinterConnection === 'function') testPrinterConnection(); break; case 'delete-printer': if (typeof deletePrinter === 'function') deletePrinter(); break; case 'edit-printer': if (typeof printerManager !== 'undefined' && params.id) { printerManager.editPrinter(params.id); } break; case 'connect-printer': if (typeof printerManager !== 'undefined' && params.id) { printerManager.connectPrinter(params.id); } break; // Calendar Actions case 'refresh-calendar': if (typeof refreshCalendar === 'function') refreshCalendar(); break; case 'toggle-auto-optimization': if (typeof toggleAutoOptimization === 'function') toggleAutoOptimization(); break; case 'export-calendar': if (typeof exportCalendar === 'function') exportCalendar(); break; case 'open-create-event-modal': if (typeof openCreateEventModal === 'function') openCreateEventModal(); break; // Modal Actions case 'close-modal': this.closeModal(params.target || element.closest('.fixed')); break; case 'close-printer-modal': if (typeof closePrinterModal === 'function') closePrinterModal(); break; case 'close-job-modal': if (typeof closeJobModal === 'function') closeJobModal(); break; case 'close-event-modal': if (typeof closeEventModal === 'function') closeEventModal(); break; // Form Actions case 'reset-form': if (typeof resetForm === 'function') resetForm(); else this.resetNearestForm(element); break; case 'clear-file': if (typeof clearFile === 'function') clearFile(); break; // Guest Request Actions case 'check-status': if (typeof checkStatus === 'function') checkStatus(); break; case 'copy-code': if (typeof copyCode === 'function') copyCode(); break; case 'refresh-status': if (typeof refreshStatus === 'function') refreshStatus(); break; case 'show-status-check': if (typeof showStatusCheck === 'function') showStatusCheck(); break; // Admin Actions case 'perform-bulk-action': if (typeof performBulkAction === 'function' && params.type) { performBulkAction(params.type); } break; case 'close-bulk-modal': if (typeof closeBulkModal === 'function') closeBulkModal(); break; case 'clear-cache': if (typeof clearCache === 'function') clearCache(); break; case 'optimize-database': if (typeof optimizeDatabase === 'function') optimizeDatabase(); break; case 'create-backup': if (typeof createBackup === 'function') createBackup(); break; case 'download-logs': if (typeof downloadLogs === 'function') downloadLogs(); break; case 'run-maintenance': if (typeof runMaintenance === 'function') runMaintenance(); break; case 'save-settings': if (typeof saveSettings === 'function') saveSettings(); break; // Profile Actions case 'toggle-edit-mode': if (typeof toggleEditMode === 'function') toggleEditMode(); break; case 'trigger-avatar-upload': if (typeof triggerAvatarUpload === 'function') triggerAvatarUpload(); break; case 'cancel-edit': if (typeof cancelEdit === 'function') cancelEdit(); break; case 'download-user-data': if (typeof downloadUserData === 'function') downloadUserData(); break; // Stats Actions case 'refresh-stats': if (typeof refreshStats === 'function') refreshStats(); break; case 'export-stats': if (typeof exportStats === 'function') exportStats(); break; // Generic Actions case 'remove-element': const targetElement = params.target ? document.querySelector(params.target) : element.closest(params.selector || '.removable'); if (targetElement) { targetElement.remove(); } break; case 'toggle-element': const toggleTarget = params.target ? document.querySelector(params.target) : element.nextElementSibling; if (toggleTarget) { toggleTarget.classList.toggle('hidden'); } break; case 'show-element': const showTarget = document.querySelector(params.target); if (showTarget) { showTarget.classList.remove('hidden'); } break; case 'hide-element': const hideTarget = document.querySelector(params.target); if (hideTarget) { hideTarget.classList.add('hidden'); } break; default: console.warn(`⚠️ Unbekannte Action: ${action}`); // Versuche globale Funktion zu finden if (typeof window[action] === 'function') { window[action](params); } break; } } /** * Generische Modal-Schließfunktion */ closeModal(modalElement) { if (modalElement) { modalElement.classList.add('hidden'); modalElement.remove(); } } /** * Nächstes Formular zurücksetzen */ resetNearestForm(element) { const form = element.closest('form'); if (form) { form.reset(); } } /** * Spezifische Event-Listener einrichten */ setupEventListeners() { // Auto-Refresh für bestimmte Seiten this.setupAutoRefresh(); // Keyboard Shortcuts this.setupKeyboardShortcuts(); // Form Validierung this.setupFormValidation(); console.log('🔧 Globale Event-Handler initialisiert'); } /** * Auto-Refresh für Dashboard/Jobs einrichten */ setupAutoRefresh() { const currentPath = window.location.pathname; // Auto-refresh für Dashboard alle 30 Sekunden if (currentPath.includes('/dashboard')) { setInterval(() => { if (typeof refreshDashboard === 'function') { refreshDashboard(); } }, 30000); } // Auto-refresh für Jobs alle 15 Sekunden if (currentPath.includes('/jobs')) { setInterval(() => { if (typeof refreshJobs === 'function') { refreshJobs(); } }, 15000); } } /** * Keyboard Shortcuts einrichten */ setupKeyboardShortcuts() { document.addEventListener('keydown', (event) => { // ESC zum Schließen von Modals if (event.key === 'Escape') { const openModal = document.querySelector('.fixed:not(.hidden)'); if (openModal) { this.closeModal(openModal); } } // Ctrl+R für Refresh (überschreiben für spezifische Funktionen) if (event.ctrlKey && event.key === 'r') { event.preventDefault(); const currentPath = window.location.pathname; if (currentPath.includes('/dashboard') && typeof refreshDashboard === 'function') { refreshDashboard(); } else if (currentPath.includes('/jobs') && typeof refreshJobs === 'function') { refreshJobs(); } else if (currentPath.includes('/printers') && typeof refreshPrinters === 'function') { refreshPrinters(); } else { window.location.reload(); } } }); } /** * Form-Validierung einrichten */ setupFormValidation() { // Alle Formulare finden und Validierung hinzufügen const forms = document.querySelectorAll('form[data-validate]'); forms.forEach(form => { form.addEventListener('submit', this.validateForm.bind(this)); }); } /** * Formular validieren */ validateForm(event) { const form = event.target; const requiredFields = form.querySelectorAll('[required]'); let isValid = true; requiredFields.forEach(field => { if (!field.value.trim()) { isValid = false; field.classList.add('border-red-500'); // Fehlermeldung anzeigen const errorId = `${field.id}-error`; let errorElement = document.getElementById(errorId); if (!errorElement) { errorElement = document.createElement('div'); errorElement.id = errorId; errorElement.className = 'text-red-500 text-sm mt-1'; field.parentNode.appendChild(errorElement); } errorElement.textContent = `${field.getAttribute('data-label') || 'Dieses Feld'} ist erforderlich.`; } else { field.classList.remove('border-red-500'); const errorElement = document.getElementById(`${field.id}-error`); if (errorElement) { errorElement.remove(); } } }); if (!isValid) { event.preventDefault(); } return isValid; } } // Globale Instanz erstellen const globalEventManager = new GlobalEventManager(); // Export für Module if (typeof module !== 'undefined' && module.exports) { module.exports = GlobalEventManager; } console.log('🌍 Globaler Event Manager geladen');