401 lines
13 KiB
JavaScript
401 lines
13 KiB
JavaScript
/**
|
||
* MYP Platform - UI Debug & Diagnostic Tool
|
||
* Diagnostiziert und behebt UI-Probleme in Echtzeit
|
||
*/
|
||
|
||
(function() {
|
||
'use strict';
|
||
|
||
console.log('🔍 UI-Debug-Tool wird geladen...');
|
||
|
||
// Debug-Konfiguration
|
||
const DEBUG_CONFIG = {
|
||
logClicks: true,
|
||
logErrors: true,
|
||
logNavigation: true,
|
||
showVisualFeedback: true,
|
||
autoFix: true
|
||
};
|
||
|
||
/**
|
||
* Hauptinitialisierung des Debug-Tools
|
||
*/
|
||
function initDebugTool() {
|
||
console.log('🚀 UI-Debug-Tool gestartet');
|
||
|
||
// 1. Click-Tracking
|
||
setupClickTracking();
|
||
|
||
// 2. Error-Tracking
|
||
setupErrorTracking();
|
||
|
||
// 3. Navigation-Tracking
|
||
setupNavigationTracking();
|
||
|
||
// 4. Element-Diagnostik
|
||
diagnoseElements();
|
||
|
||
// 5. Auto-Fix aktivieren
|
||
if (DEBUG_CONFIG.autoFix) {
|
||
setupAutoFix();
|
||
}
|
||
|
||
// 6. Debug-Panel erstellen
|
||
createDebugPanel();
|
||
|
||
console.log('✅ UI-Debug-Tool vollständig initialisiert');
|
||
}
|
||
|
||
/**
|
||
* Click-Tracking einrichten
|
||
*/
|
||
function setupClickTracking() {
|
||
if (!DEBUG_CONFIG.logClicks) return;
|
||
|
||
document.addEventListener('click', function(event) {
|
||
const target = event.target;
|
||
const info = {
|
||
element: target.tagName,
|
||
id: target.id || 'keine ID',
|
||
classes: target.className || 'keine Klassen',
|
||
href: target.href || 'kein href',
|
||
type: target.type || 'kein type',
|
||
dataAction: target.getAttribute('data-action') || 'keine data-action',
|
||
clickable: isElementClickable(target),
|
||
hasEventListeners: hasEventListeners(target)
|
||
};
|
||
|
||
console.log('👆 KLICK ERKANNT:', info);
|
||
|
||
// Visuelles Feedback
|
||
if (DEBUG_CONFIG.showVisualFeedback) {
|
||
showClickFeedback(target);
|
||
}
|
||
|
||
// Auto-Fix für nicht-klickbare Elemente
|
||
if (!info.clickable && DEBUG_CONFIG.autoFix) {
|
||
makeElementClickable(target);
|
||
}
|
||
}, true);
|
||
}
|
||
|
||
/**
|
||
* Error-Tracking einrichten
|
||
*/
|
||
function setupErrorTracking() {
|
||
if (!DEBUG_CONFIG.logErrors) return;
|
||
|
||
window.addEventListener('error', function(event) {
|
||
console.error('🚨 JAVASCRIPT-FEHLER:', {
|
||
message: event.message,
|
||
filename: event.filename,
|
||
lineno: event.lineno,
|
||
colno: event.colno,
|
||
error: event.error
|
||
});
|
||
});
|
||
|
||
window.addEventListener('unhandledrejection', function(event) {
|
||
console.error('🚨 UNHANDLED PROMISE REJECTION:', event.reason);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Navigation-Tracking einrichten
|
||
*/
|
||
function setupNavigationTracking() {
|
||
if (!DEBUG_CONFIG.logNavigation) return;
|
||
|
||
// Link-Klicks verfolgen
|
||
document.addEventListener('click', function(event) {
|
||
const link = event.target.closest('a');
|
||
if (link) {
|
||
console.log('🔗 NAVIGATION:', {
|
||
href: link.href,
|
||
text: link.textContent.trim(),
|
||
target: link.target,
|
||
internal: isInternalLink(link.href)
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Element-Diagnostik durchführen
|
||
*/
|
||
function diagnoseElements() {
|
||
console.log('🔍 Starte Element-Diagnostik...');
|
||
|
||
// Alle potentiell klickbaren Elemente finden
|
||
const clickableSelectors = [
|
||
'a', 'button', '[role="button"]', '[data-action]',
|
||
'.btn', '.clickable', '.nav-item', '.menu-item'
|
||
];
|
||
|
||
clickableSelectors.forEach(selector => {
|
||
const elements = document.querySelectorAll(selector);
|
||
console.log(`📊 ${selector}: ${elements.length} Elemente gefunden`);
|
||
|
||
elements.forEach((element, index) => {
|
||
const diagnosis = diagnoseElement(element);
|
||
if (diagnosis.issues.length > 0) {
|
||
console.warn(`⚠️ ${selector}[${index}] hat Probleme:`, diagnosis);
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Einzelnes Element diagnostizieren
|
||
*/
|
||
function diagnoseElement(element) {
|
||
const issues = [];
|
||
const info = {
|
||
tag: element.tagName,
|
||
id: element.id,
|
||
classes: element.className,
|
||
href: element.href,
|
||
type: element.type,
|
||
disabled: element.disabled,
|
||
hidden: element.hidden || element.style.display === 'none',
|
||
hasEventListeners: hasEventListeners(element),
|
||
clickable: isElementClickable(element)
|
||
};
|
||
|
||
// Probleme identifizieren
|
||
if (element.tagName === 'A' && (!element.href || element.href === '#')) {
|
||
issues.push('Link ohne gültiges href-Attribut');
|
||
}
|
||
|
||
if (element.tagName === 'BUTTON' && element.disabled) {
|
||
issues.push('Button ist deaktiviert');
|
||
}
|
||
|
||
if (!info.hasEventListeners && !element.href && !element.onclick) {
|
||
issues.push('Keine Event-Listener oder onclick-Handler gefunden');
|
||
}
|
||
|
||
if (info.hidden) {
|
||
issues.push('Element ist versteckt');
|
||
}
|
||
|
||
return { info, issues };
|
||
}
|
||
|
||
/**
|
||
* Auto-Fix einrichten
|
||
*/
|
||
function setupAutoFix() {
|
||
console.log('🔧 Auto-Fix aktiviert');
|
||
|
||
// Alle problematischen Elemente finden und reparieren
|
||
const problematicElements = document.querySelectorAll('a[href="#"], button:disabled, [data-action]:not([onclick])');
|
||
|
||
problematicElements.forEach(element => {
|
||
fixElement(element);
|
||
});
|
||
|
||
// Mutation Observer für dynamisch hinzugefügte Elemente
|
||
const observer = new MutationObserver(function(mutations) {
|
||
mutations.forEach(function(mutation) {
|
||
mutation.addedNodes.forEach(function(node) {
|
||
if (node.nodeType === Node.ELEMENT_NODE) {
|
||
const problematic = node.querySelectorAll('a[href="#"], button:disabled, [data-action]:not([onclick])');
|
||
problematic.forEach(fixElement);
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
observer.observe(document.body, { childList: true, subtree: true });
|
||
}
|
||
|
||
/**
|
||
* Element reparieren
|
||
*/
|
||
function fixElement(element) {
|
||
console.log('🔧 Repariere Element:', element);
|
||
|
||
if (element.tagName === 'A' && (!element.href || element.href === '#')) {
|
||
// Link ohne href reparieren
|
||
element.style.cursor = 'pointer';
|
||
element.addEventListener('click', function(e) {
|
||
e.preventDefault();
|
||
console.log('🔗 Reparierter Link geklickt:', this);
|
||
});
|
||
}
|
||
|
||
if (element.tagName === 'BUTTON' && element.disabled) {
|
||
// Deaktivierten Button aktivieren (falls sicher)
|
||
if (!element.hasAttribute('data-keep-disabled')) {
|
||
element.disabled = false;
|
||
console.log('🔘 Button aktiviert:', element);
|
||
}
|
||
}
|
||
|
||
if (element.hasAttribute('data-action') && !hasEventListeners(element)) {
|
||
// Data-Action-Element ohne Event-Listener reparieren
|
||
element.addEventListener('click', function(e) {
|
||
e.preventDefault();
|
||
const action = this.getAttribute('data-action');
|
||
console.log('⚡ Data-Action ausgeführt:', action);
|
||
|
||
// Versuche globale Handler zu finden
|
||
if (window.MYP_UI_FIXES && window.MYP_UI_FIXES[action]) {
|
||
window.MYP_UI_FIXES[action]();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Debug-Panel erstellen
|
||
*/
|
||
function createDebugPanel() {
|
||
const panel = document.createElement('div');
|
||
panel.id = 'debug-panel';
|
||
panel.style.cssText = `
|
||
position: fixed;
|
||
top: 10px;
|
||
right: 10px;
|
||
width: 300px;
|
||
background: rgba(0, 0, 0, 0.9);
|
||
color: white;
|
||
padding: 10px;
|
||
border-radius: 5px;
|
||
font-family: monospace;
|
||
font-size: 12px;
|
||
z-index: 10000;
|
||
max-height: 400px;
|
||
overflow-y: auto;
|
||
display: none;
|
||
`;
|
||
|
||
panel.innerHTML = `
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
||
<strong>🔍 UI Debug Panel</strong>
|
||
<button onclick="this.parentElement.parentElement.style.display='none'" style="background: red; color: white; border: none; padding: 2px 6px; border-radius: 3px; cursor: pointer;">×</button>
|
||
</div>
|
||
<div id="debug-content">
|
||
<div>✅ Debug-Tool aktiv</div>
|
||
<div>👆 Klicks werden verfolgt</div>
|
||
<div>🔧 Auto-Fix aktiviert</div>
|
||
</div>
|
||
`;
|
||
|
||
document.body.appendChild(panel);
|
||
|
||
// Toggle-Button für Debug-Panel
|
||
const toggleButton = document.createElement('button');
|
||
toggleButton.textContent = '🔍';
|
||
toggleButton.style.cssText = `
|
||
position: fixed;
|
||
bottom: 20px;
|
||
right: 20px;
|
||
width: 50px;
|
||
height: 50px;
|
||
border-radius: 50%;
|
||
background: #007bff;
|
||
color: white;
|
||
border: none;
|
||
font-size: 20px;
|
||
cursor: pointer;
|
||
z-index: 10001;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
|
||
`;
|
||
|
||
toggleButton.addEventListener('click', function() {
|
||
const panel = document.getElementById('debug-panel');
|
||
panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
|
||
});
|
||
|
||
document.body.appendChild(toggleButton);
|
||
}
|
||
|
||
/**
|
||
* Hilfsfunktionen
|
||
*/
|
||
function isElementClickable(element) {
|
||
const style = window.getComputedStyle(element);
|
||
return style.pointerEvents !== 'none' &&
|
||
style.display !== 'none' &&
|
||
style.visibility !== 'hidden' &&
|
||
!element.disabled;
|
||
}
|
||
|
||
function hasEventListeners(element) {
|
||
// Vereinfachte Prüfung - in der Realität schwer zu detektieren
|
||
return element.onclick !== null ||
|
||
element.getAttribute('onclick') !== null ||
|
||
element.hasAttribute('data-action');
|
||
}
|
||
|
||
function isInternalLink(href) {
|
||
if (!href) return false;
|
||
return href.startsWith('/') ||
|
||
href.startsWith('./') ||
|
||
href.startsWith('../') ||
|
||
href.includes(window.location.hostname);
|
||
}
|
||
|
||
function makeElementClickable(element) {
|
||
if (!isElementClickable(element)) {
|
||
element.style.cursor = 'pointer';
|
||
element.style.pointerEvents = 'auto';
|
||
|
||
if (!hasEventListeners(element)) {
|
||
element.addEventListener('click', function(e) {
|
||
console.log('🔧 Auto-Fix Klick auf:', this);
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
function showClickFeedback(element) {
|
||
const feedback = document.createElement('div');
|
||
feedback.style.cssText = `
|
||
position: absolute;
|
||
background: rgba(0, 255, 0, 0.3);
|
||
border: 2px solid #00ff00;
|
||
pointer-events: none;
|
||
z-index: 9999;
|
||
border-radius: 3px;
|
||
`;
|
||
|
||
const rect = element.getBoundingClientRect();
|
||
feedback.style.left = rect.left + 'px';
|
||
feedback.style.top = rect.top + 'px';
|
||
feedback.style.width = rect.width + 'px';
|
||
feedback.style.height = rect.height + 'px';
|
||
|
||
document.body.appendChild(feedback);
|
||
|
||
setTimeout(() => {
|
||
feedback.remove();
|
||
}, 500);
|
||
}
|
||
|
||
/**
|
||
* Initialisierung
|
||
*/
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', initDebugTool);
|
||
} else {
|
||
initDebugTool();
|
||
}
|
||
|
||
// Globale Debug-Funktionen
|
||
window.DEBUG_UI = {
|
||
diagnose: diagnoseElements,
|
||
fix: setupAutoFix,
|
||
toggle: function() {
|
||
const panel = document.getElementById('debug-panel');
|
||
if (panel) {
|
||
panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
|
||
}
|
||
}
|
||
};
|
||
|
||
console.log('✅ UI-Debug-Tool geladen');
|
||
|
||
})();
|