401 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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');
})();