573 lines
17 KiB
JavaScript
573 lines
17 KiB
JavaScript
/**
|
|
* MYP Platform - UI Issues Fix
|
|
* Behebt alle Klickbarkeits- und Interaktivitätsprobleme
|
|
* Version: 1.0.0
|
|
*/
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
console.log('🔧 UI-Fix wird geladen...');
|
|
|
|
// Globale Variablen für bessere Kompatibilität
|
|
window.MYP_UI_FIXED = false;
|
|
|
|
/**
|
|
* Hauptinitialisierung
|
|
*/
|
|
function initializeUIFixes() {
|
|
if (window.MYP_UI_FIXED) {
|
|
console.log('✅ UI bereits gefixt');
|
|
return;
|
|
}
|
|
|
|
console.log('🚀 Starte UI-Fixes...');
|
|
|
|
// 1. Event-Delegation für alle Klicks
|
|
setupGlobalClickHandlers();
|
|
|
|
// 2. Navigation-Fixes
|
|
fixNavigationClicks();
|
|
|
|
// 3. Button-Fixes
|
|
fixButtonClicks();
|
|
|
|
// 4. Form-Fixes
|
|
fixFormSubmissions();
|
|
|
|
// 5. Modal-Fixes
|
|
fixModalInteractions();
|
|
|
|
// 6. Dark Mode Fix
|
|
fixDarkModeToggle();
|
|
|
|
// 7. Mobile Menu Fix
|
|
fixMobileMenu();
|
|
|
|
// 8. Dropdown-Fixes
|
|
fixDropdowns();
|
|
|
|
// 9. CSRF-Token-Fixes
|
|
fixCSRFTokens();
|
|
|
|
// 10. Auto-Refresh-Fixes
|
|
setupAutoRefresh();
|
|
|
|
window.MYP_UI_FIXED = true;
|
|
console.log('✅ Alle UI-Fixes erfolgreich angewendet!');
|
|
}
|
|
|
|
/**
|
|
* 1. Globale Click-Handler mit Event-Delegation
|
|
*/
|
|
function setupGlobalClickHandlers() {
|
|
console.log('🎯 Richte globale Click-Handler ein...');
|
|
|
|
// Entferne alte Event-Listener
|
|
document.removeEventListener('click', handleGlobalClick);
|
|
|
|
// Füge neuen Event-Listener hinzu
|
|
document.addEventListener('click', handleGlobalClick, true);
|
|
|
|
function handleGlobalClick(event) {
|
|
const target = event.target;
|
|
const closest = target.closest('a, button, [role="button"], [data-action], .clickable');
|
|
|
|
if (!closest) return;
|
|
|
|
// Verhindere doppelte Events
|
|
if (event.defaultPrevented) return;
|
|
|
|
console.log('👆 Klick erkannt auf:', closest);
|
|
|
|
// Spezielle Handler für verschiedene Elemente
|
|
if (closest.matches('a[href]')) {
|
|
handleLinkClick(event, closest);
|
|
} else if (closest.matches('button, [role="button"]')) {
|
|
handleButtonClick(event, closest);
|
|
} else if (closest.hasAttribute('data-action')) {
|
|
handleDataActionClick(event, closest);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Link-Klicks behandeln
|
|
*/
|
|
function handleLinkClick(event, link) {
|
|
const href = link.getAttribute('href');
|
|
|
|
if (!href || href === '#') {
|
|
event.preventDefault();
|
|
return;
|
|
}
|
|
|
|
// Externe Links in neuem Tab öffnen
|
|
if (href.startsWith('http') && !href.includes(window.location.hostname)) {
|
|
event.preventDefault();
|
|
window.open(href, '_blank', 'noopener,noreferrer');
|
|
return;
|
|
}
|
|
|
|
// Interne Navigation
|
|
if (href.startsWith('/') || href.startsWith('./') || href.startsWith('../')) {
|
|
console.log('🔗 Navigiere zu:', href);
|
|
// Lass den Browser die Navigation normal handhaben
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Button-Klicks behandeln
|
|
*/
|
|
function handleButtonClick(event, button) {
|
|
// Verhindere doppelte Klicks
|
|
if (button.disabled || button.classList.contains('loading')) {
|
|
event.preventDefault();
|
|
return;
|
|
}
|
|
|
|
// Spezielle Button-Typen
|
|
const buttonType = button.getAttribute('data-type') || button.type;
|
|
|
|
switch (buttonType) {
|
|
case 'logout':
|
|
event.preventDefault();
|
|
handleLogoutClick();
|
|
break;
|
|
|
|
case 'dark-mode-toggle':
|
|
event.preventDefault();
|
|
handleDarkModeToggle();
|
|
break;
|
|
|
|
case 'mobile-menu-toggle':
|
|
event.preventDefault();
|
|
handleMobileMenuToggle();
|
|
break;
|
|
|
|
case 'refresh':
|
|
event.preventDefault();
|
|
handleRefreshClick(button);
|
|
break;
|
|
|
|
default:
|
|
// Normale Button-Behandlung
|
|
console.log('🔘 Button geklickt:', button);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Data-Action-Klicks behandeln
|
|
*/
|
|
function handleDataActionClick(event, element) {
|
|
event.preventDefault();
|
|
|
|
const action = element.getAttribute('data-action');
|
|
const params = getDataActionParams(element);
|
|
|
|
console.log('⚡ Data-Action ausgeführt:', action, params);
|
|
|
|
switch (action) {
|
|
case 'logout':
|
|
handleLogoutClick();
|
|
break;
|
|
|
|
case 'toggle-dark-mode':
|
|
handleDarkModeToggle();
|
|
break;
|
|
|
|
case 'toggle-mobile-menu':
|
|
handleMobileMenuToggle();
|
|
break;
|
|
|
|
case 'refresh-page':
|
|
window.location.reload();
|
|
break;
|
|
|
|
case 'go-back':
|
|
window.history.back();
|
|
break;
|
|
|
|
case 'close-modal':
|
|
closeModal(params.target);
|
|
break;
|
|
|
|
default:
|
|
console.warn('⚠️ Unbekannte Data-Action:', action);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Data-Action-Parameter extrahieren
|
|
*/
|
|
function getDataActionParams(element) {
|
|
const params = {};
|
|
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* 2. Navigation-Fixes
|
|
*/
|
|
function fixNavigationClicks() {
|
|
console.log('🧭 Fixe Navigation...');
|
|
|
|
// Alle Navigations-Links finden und reparieren
|
|
const navLinks = document.querySelectorAll('nav a, .navbar a, .nav-item');
|
|
|
|
navLinks.forEach(link => {
|
|
if (!link.href || link.href === '#') {
|
|
link.style.cursor = 'pointer';
|
|
link.addEventListener('click', function(e) {
|
|
e.preventDefault();
|
|
console.log('🔗 Navigation-Link geklickt:', this);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 3. Button-Fixes
|
|
*/
|
|
function fixButtonClicks() {
|
|
console.log('🔘 Fixe Buttons...');
|
|
|
|
// Alle Buttons finden und Event-Listener hinzufügen
|
|
const buttons = document.querySelectorAll('button, [role="button"], .btn');
|
|
|
|
buttons.forEach(button => {
|
|
// Entferne alte Event-Listener
|
|
button.removeEventListener('click', handleButtonClickFix);
|
|
|
|
// Füge neuen Event-Listener hinzu
|
|
button.addEventListener('click', handleButtonClickFix);
|
|
});
|
|
|
|
function handleButtonClickFix(event) {
|
|
console.log('🔘 Button-Fix aktiviert für:', this);
|
|
|
|
// Verhindere doppelte Klicks
|
|
if (this.disabled) {
|
|
event.preventDefault();
|
|
return;
|
|
}
|
|
|
|
// Visuelles Feedback
|
|
this.style.transform = 'scale(0.95)';
|
|
setTimeout(() => {
|
|
this.style.transform = '';
|
|
}, 150);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 4. Form-Fixes
|
|
*/
|
|
function fixFormSubmissions() {
|
|
console.log('📝 Fixe Formulare...');
|
|
|
|
const forms = document.querySelectorAll('form');
|
|
|
|
forms.forEach(form => {
|
|
form.addEventListener('submit', function(event) {
|
|
console.log('📤 Formular wird abgesendet:', this);
|
|
|
|
// CSRF-Token prüfen
|
|
const csrfToken = this.querySelector('input[name="csrf_token"]');
|
|
if (!csrfToken) {
|
|
console.warn('⚠️ CSRF-Token fehlt in Formular');
|
|
addCSRFTokenToForm(this);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 5. Modal-Fixes
|
|
*/
|
|
function fixModalInteractions() {
|
|
console.log('🪟 Fixe Modals...');
|
|
|
|
// Modal-Close-Buttons
|
|
const closeButtons = document.querySelectorAll('[data-modal-close], .modal-close');
|
|
|
|
closeButtons.forEach(button => {
|
|
button.addEventListener('click', function(event) {
|
|
event.preventDefault();
|
|
const modal = this.closest('.modal, .fixed');
|
|
if (modal) {
|
|
closeModal(modal);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Modal-Backdrop-Klicks
|
|
const modals = document.querySelectorAll('.modal, .fixed');
|
|
|
|
modals.forEach(modal => {
|
|
modal.addEventListener('click', function(event) {
|
|
if (event.target === this) {
|
|
closeModal(this);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 6. Dark Mode Fix
|
|
*/
|
|
function fixDarkModeToggle() {
|
|
console.log('🌙 Fixe Dark Mode...');
|
|
|
|
const darkModeToggle = document.getElementById('darkModeToggle') ||
|
|
document.querySelector('[data-action="toggle-dark-mode"]');
|
|
|
|
if (darkModeToggle) {
|
|
darkModeToggle.addEventListener('click', handleDarkModeToggle);
|
|
}
|
|
}
|
|
|
|
function handleDarkModeToggle() {
|
|
console.log('🌙 Dark Mode Toggle aktiviert');
|
|
|
|
const html = document.documentElement;
|
|
const isDark = html.classList.contains('dark');
|
|
|
|
if (isDark) {
|
|
html.classList.remove('dark');
|
|
localStorage.setItem('myp-dark-mode', 'false');
|
|
} else {
|
|
html.classList.add('dark');
|
|
localStorage.setItem('myp-dark-mode', 'true');
|
|
}
|
|
|
|
// Icons aktualisieren
|
|
updateDarkModeIcons(!isDark);
|
|
}
|
|
|
|
function updateDarkModeIcons(isDark) {
|
|
const sunIcons = document.querySelectorAll('.sun-icon');
|
|
const moonIcons = document.querySelectorAll('.moon-icon');
|
|
|
|
sunIcons.forEach(icon => {
|
|
icon.classList.toggle('hidden', isDark);
|
|
});
|
|
|
|
moonIcons.forEach(icon => {
|
|
icon.classList.toggle('hidden', !isDark);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 7. Mobile Menu Fix
|
|
*/
|
|
function fixMobileMenu() {
|
|
console.log('📱 Fixe Mobile Menu...');
|
|
|
|
const mobileMenuToggle = document.getElementById('mobileMenuToggle') ||
|
|
document.querySelector('[data-action="toggle-mobile-menu"]');
|
|
const mobileMenu = document.getElementById('mobileMenu');
|
|
|
|
if (mobileMenuToggle && mobileMenu) {
|
|
mobileMenuToggle.addEventListener('click', handleMobileMenuToggle);
|
|
}
|
|
}
|
|
|
|
function handleMobileMenuToggle() {
|
|
console.log('📱 Mobile Menu Toggle aktiviert');
|
|
|
|
const mobileMenu = document.getElementById('mobileMenu');
|
|
if (mobileMenu) {
|
|
mobileMenu.classList.toggle('hidden');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 8. Dropdown-Fixes
|
|
*/
|
|
function fixDropdowns() {
|
|
console.log('📋 Fixe Dropdowns...');
|
|
|
|
const dropdownToggles = document.querySelectorAll('[data-dropdown-toggle]');
|
|
|
|
dropdownToggles.forEach(toggle => {
|
|
toggle.addEventListener('click', function(event) {
|
|
event.preventDefault();
|
|
const targetId = this.getAttribute('data-dropdown-toggle');
|
|
const dropdown = document.getElementById(targetId);
|
|
|
|
if (dropdown) {
|
|
dropdown.classList.toggle('hidden');
|
|
}
|
|
});
|
|
});
|
|
|
|
// Schließe Dropdowns bei Klick außerhalb
|
|
document.addEventListener('click', function(event) {
|
|
const dropdowns = document.querySelectorAll('[data-dropdown-menu]');
|
|
|
|
dropdowns.forEach(dropdown => {
|
|
if (!dropdown.contains(event.target) &&
|
|
!event.target.matches('[data-dropdown-toggle]')) {
|
|
dropdown.classList.add('hidden');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 9. CSRF-Token-Fixes
|
|
*/
|
|
function fixCSRFTokens() {
|
|
console.log('🔒 Fixe CSRF-Tokens...');
|
|
|
|
const csrfToken = document.querySelector('meta[name="csrf-token"]');
|
|
if (!csrfToken) {
|
|
console.warn('⚠️ CSRF-Token Meta-Tag fehlt');
|
|
return;
|
|
}
|
|
|
|
const tokenValue = csrfToken.getAttribute('content');
|
|
|
|
// Füge CSRF-Token zu allen Formularen hinzu
|
|
const forms = document.querySelectorAll('form');
|
|
forms.forEach(form => {
|
|
if (!form.querySelector('input[name="csrf_token"]')) {
|
|
addCSRFTokenToForm(form, tokenValue);
|
|
}
|
|
});
|
|
}
|
|
|
|
function addCSRFTokenToForm(form, tokenValue = null) {
|
|
if (!tokenValue) {
|
|
const csrfMeta = document.querySelector('meta[name="csrf-token"]');
|
|
tokenValue = csrfMeta ? csrfMeta.getAttribute('content') : '';
|
|
}
|
|
|
|
if (tokenValue) {
|
|
const input = document.createElement('input');
|
|
input.type = 'hidden';
|
|
input.name = 'csrf_token';
|
|
input.value = tokenValue;
|
|
form.appendChild(input);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 10. Auto-Refresh-Setup
|
|
*/
|
|
function setupAutoRefresh() {
|
|
console.log('🔄 Richte Auto-Refresh ein...');
|
|
|
|
// Auto-Refresh für bestimmte Seiten
|
|
const refreshInterval = 30000; // 30 Sekunden
|
|
|
|
if (window.location.pathname.includes('/dashboard') ||
|
|
window.location.pathname.includes('/printers') ||
|
|
window.location.pathname.includes('/jobs')) {
|
|
|
|
setInterval(() => {
|
|
refreshPageData();
|
|
}, refreshInterval);
|
|
}
|
|
}
|
|
|
|
function refreshPageData() {
|
|
// Implementierung für spezifische Seiten-Refreshs
|
|
console.log('🔄 Aktualisiere Seitendaten...');
|
|
}
|
|
|
|
/**
|
|
* Logout-Handler
|
|
*/
|
|
function handleLogoutClick() {
|
|
console.log('👋 Logout-Prozess gestartet');
|
|
|
|
if (confirm('Möchten Sie sich wirklich abmelden?')) {
|
|
// CSRF-Token holen
|
|
const csrfToken = document.querySelector('meta[name="csrf-token"]');
|
|
|
|
// Logout-Form erstellen
|
|
const form = document.createElement('form');
|
|
form.method = 'POST';
|
|
form.action = '/auth/logout';
|
|
form.style.display = 'none';
|
|
|
|
if (csrfToken) {
|
|
const input = document.createElement('input');
|
|
input.type = 'hidden';
|
|
input.name = 'csrf_token';
|
|
input.value = csrfToken.getAttribute('content');
|
|
form.appendChild(input);
|
|
}
|
|
|
|
document.body.appendChild(form);
|
|
form.submit();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Refresh-Handler
|
|
*/
|
|
function handleRefreshClick(button) {
|
|
console.log('🔄 Refresh-Button geklickt');
|
|
|
|
// Button-State ändern
|
|
const originalText = button.textContent;
|
|
button.textContent = 'Wird aktualisiert...';
|
|
button.disabled = true;
|
|
|
|
// Seite neu laden
|
|
setTimeout(() => {
|
|
window.location.reload();
|
|
}, 500);
|
|
}
|
|
|
|
/**
|
|
* Modal schließen
|
|
*/
|
|
function closeModal(modal) {
|
|
if (typeof modal === 'string') {
|
|
modal = document.getElementById(modal) || document.querySelector(modal);
|
|
}
|
|
|
|
if (modal) {
|
|
modal.classList.add('hidden');
|
|
modal.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialisierung bei DOM-Ready
|
|
*/
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', initializeUIFixes);
|
|
} else {
|
|
initializeUIFixes();
|
|
}
|
|
|
|
// Backup-Initialisierung nach 1 Sekunde
|
|
setTimeout(initializeUIFixes, 1000);
|
|
|
|
// Globale Funktionen für Kompatibilität
|
|
window.MYP_UI_FIXES = {
|
|
init: initializeUIFixes,
|
|
handleLogout: handleLogoutClick,
|
|
handleDarkMode: handleDarkModeToggle,
|
|
handleMobileMenu: handleMobileMenuToggle,
|
|
closeModal: closeModal
|
|
};
|
|
|
|
console.log('✅ UI-Fix-Script geladen');
|
|
|
|
})();
|