306 lines
11 KiB
JavaScript
306 lines
11 KiB
JavaScript
/**
|
|
* MYP Platform Dark Mode Handler
|
|
* Version: 6.0.0
|
|
*/
|
|
|
|
// Sofort ausführen, um FOUC zu vermeiden (Flash of Unstyled Content)
|
|
(function() {
|
|
"use strict";
|
|
|
|
// Speicherort für Dark Mode-Einstellung
|
|
const STORAGE_KEY = 'myp-dark-mode';
|
|
|
|
// DOM-Elemente
|
|
let darkModeToggle;
|
|
const html = document.documentElement;
|
|
|
|
// Initialisierung beim Laden der Seite
|
|
document.addEventListener('DOMContentLoaded', initialize);
|
|
|
|
// Prüft System-Präferenz und gespeicherte Einstellung
|
|
function shouldUseDarkMode() {
|
|
// Lokale Speichereinstellung prüfen
|
|
const savedMode = localStorage.getItem(STORAGE_KEY);
|
|
|
|
// Prüfen ob es eine gespeicherte Einstellung gibt
|
|
if (savedMode !== null) {
|
|
return savedMode === 'true';
|
|
}
|
|
|
|
// Ansonsten Systemeinstellung verwenden
|
|
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
}
|
|
|
|
// Setzt Dark/Light Mode
|
|
function setDarkMode(enable) {
|
|
// Deaktiviere Übergänge temporär, um Flackern zu vermeiden
|
|
html.classList.add('disable-transitions');
|
|
|
|
// Dark Mode Klasse am HTML-Element setzen
|
|
if (enable) {
|
|
html.classList.add('dark');
|
|
html.setAttribute('data-theme', 'dark');
|
|
html.style.colorScheme = 'dark';
|
|
} else {
|
|
html.classList.remove('dark');
|
|
html.setAttribute('data-theme', 'light');
|
|
html.style.colorScheme = 'light';
|
|
}
|
|
|
|
// Speichern in LocalStorage
|
|
localStorage.setItem(STORAGE_KEY, enable);
|
|
|
|
// Update ThemeColor Meta-Tag
|
|
updateMetaThemeColor(enable);
|
|
|
|
// Wenn Toggle existiert, aktualisiere Icon
|
|
if (darkModeToggle) {
|
|
updateDarkModeToggle(enable);
|
|
}
|
|
|
|
// Event für andere Komponenten
|
|
window.dispatchEvent(new CustomEvent('darkModeChanged', {
|
|
detail: {
|
|
isDark: enable,
|
|
source: 'dark-mode-toggle',
|
|
timestamp: new Date().toISOString()
|
|
}
|
|
}));
|
|
|
|
// Event auch als eigenen Event-Typ versenden (rückwärtskompatibel)
|
|
const eventName = enable ? 'darkModeEnabled' : 'darkModeDisabled';
|
|
window.dispatchEvent(new CustomEvent(eventName, {
|
|
detail: { timestamp: new Date().toISOString() }
|
|
}));
|
|
|
|
// Übergänge nach kurzer Verzögerung wieder aktivieren
|
|
setTimeout(function() {
|
|
html.classList.remove('disable-transitions');
|
|
}, 100);
|
|
|
|
// Erfolgsmeldung in die Konsole
|
|
console.log(`${enable ? '🌙' : '☀️'} ${enable ? 'Dark Mode aktiviert - Augenschonender Modus aktiv' : 'Light Mode aktiviert - Heller Modus aktiv'}`);
|
|
}
|
|
|
|
// Aktualisiert das Theme-Color Meta-Tag
|
|
function updateMetaThemeColor(isDark) {
|
|
// Alle Theme-Color Meta-Tags aktualisieren
|
|
const metaTags = [
|
|
document.getElementById('metaThemeColor'),
|
|
document.querySelector('meta[name="theme-color"]'),
|
|
document.querySelector('meta[name="theme-color"][media="(prefers-color-scheme: light)"]'),
|
|
document.querySelector('meta[name="theme-color"][media="(prefers-color-scheme: dark)"]')
|
|
];
|
|
|
|
// CSS-Variablen für konsistente Farben verwenden
|
|
const darkColor = getComputedStyle(document.documentElement).getPropertyValue('--color-bg') || '#0f172a';
|
|
const lightColor = getComputedStyle(document.documentElement).getPropertyValue('--color-bg') || '#ffffff';
|
|
|
|
metaTags.forEach(tag => {
|
|
if (tag) {
|
|
// Für Media-spezifische Tags die entsprechende Farbe setzen
|
|
if (tag.getAttribute('media') === '(prefers-color-scheme: dark)') {
|
|
tag.setAttribute('content', darkColor);
|
|
} else if (tag.getAttribute('media') === '(prefers-color-scheme: light)') {
|
|
tag.setAttribute('content', lightColor);
|
|
} else {
|
|
// Für nicht-Media-spezifische Tags die aktuelle Farbe setzen
|
|
tag.setAttribute('content', isDark ? darkColor : lightColor);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Aktualisiert das Aussehen des Toggle-Buttons
|
|
function updateDarkModeToggle(isDark) {
|
|
// Aria-Attribute für Barrierefreiheit
|
|
darkModeToggle.setAttribute('aria-pressed', isDark.toString());
|
|
darkModeToggle.title = isDark ? "Light Mode aktivieren" : "Dark Mode aktivieren";
|
|
|
|
// Icons aktualisieren
|
|
const sunIcon = darkModeToggle.querySelector('.sun-icon');
|
|
const moonIcon = darkModeToggle.querySelector('.moon-icon');
|
|
|
|
if (sunIcon && moonIcon) {
|
|
if (isDark) {
|
|
sunIcon.classList.add('hidden');
|
|
moonIcon.classList.remove('hidden');
|
|
} else {
|
|
sunIcon.classList.remove('hidden');
|
|
moonIcon.classList.add('hidden');
|
|
}
|
|
} else {
|
|
// Fallback für ältere Implementierung mit einem Icon
|
|
const icon = darkModeToggle.querySelector('svg');
|
|
if (icon) {
|
|
// Animationsklasse hinzufügen
|
|
icon.classList.add('animate-spin-once');
|
|
|
|
// Nach Animation wieder entfernen
|
|
setTimeout(() => {
|
|
icon.classList.remove('animate-spin-once');
|
|
}, 300);
|
|
|
|
const pathElement = icon.querySelector('path');
|
|
if (pathElement) {
|
|
// Sonnen- oder Mond-Symbol
|
|
if (isDark) {
|
|
pathElement.setAttribute("d", "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z");
|
|
} else {
|
|
pathElement.setAttribute("d", "M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialisierungsfunktion
|
|
function initialize() {
|
|
// Toggle-Button finden
|
|
darkModeToggle = document.getElementById('darkModeToggle');
|
|
|
|
// Wenn kein Toggle existiert, erstelle einen
|
|
if (!darkModeToggle) {
|
|
console.log('🔧 Dark Mode Toggle nicht gefunden - erstelle automatisch einen neuen Button');
|
|
createDarkModeToggle();
|
|
}
|
|
|
|
// Event-Listener für Dark Mode Toggle
|
|
if (darkModeToggle) {
|
|
darkModeToggle.addEventListener('click', function() {
|
|
const isDark = !shouldUseDarkMode();
|
|
console.log(`👆 Dark Mode Toggle: Wechsel zu ${isDark ? '🌙 dunkel' : '☀️ hell'} angefordert`);
|
|
setDarkMode(isDark);
|
|
});
|
|
}
|
|
|
|
// Tastenkombination: Strg+Shift+D
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.ctrlKey && e.shiftKey && e.key === 'D') {
|
|
const isDark = !shouldUseDarkMode();
|
|
console.log(`⌨️ Tastenkombination STRG+SHIFT+D erkannt: Wechsel zu ${isDark ? '🌙 dunkel' : '☀️ hell'}`);
|
|
setDarkMode(isDark);
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
|
|
// Auf Systemeinstellungsänderungen reagieren
|
|
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
|
|
// Moderne Event-API verwenden
|
|
try {
|
|
darkModeMediaQuery.addEventListener('change', function(e) {
|
|
// Nur anwenden, wenn keine benutzerdefinierte Einstellung gespeichert ist
|
|
if (localStorage.getItem(STORAGE_KEY) === null) {
|
|
console.log(`🖥️ Systemeinstellung geändert: ${e.matches ? '🌙 dunkel' : '☀️ hell'}`);
|
|
setDarkMode(e.matches);
|
|
}
|
|
});
|
|
} catch (error) {
|
|
// Fallback für ältere Browser
|
|
darkModeMediaQuery.addListener(function(e) {
|
|
if (localStorage.getItem(STORAGE_KEY) === null) {
|
|
console.log(`🖥️ Systemeinstellung geändert (Legacy-Browser): ${e.matches ? '🌙 dunkel' : '☀️ hell'}`);
|
|
setDarkMode(e.matches);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Initialer Zustand
|
|
const initialState = shouldUseDarkMode();
|
|
console.log(`🔍 Ermittelter Ausgangszustand: ${initialState ? '🌙 Dark Mode' : '☀️ Light Mode'}`);
|
|
setDarkMode(initialState);
|
|
|
|
// Animation für den korrekten Modus hinzufügen
|
|
const animClass = initialState ? 'dark-mode-transition' : 'light-mode-transition';
|
|
document.body.classList.add(animClass);
|
|
|
|
// Animation entfernen nach Abschluss
|
|
setTimeout(() => {
|
|
document.body.classList.remove(animClass);
|
|
}, 300);
|
|
|
|
console.log('🚀 Dark Mode Handler erfolgreich initialisiert');
|
|
}
|
|
|
|
// Erstellt ein Toggle-Element, falls keines existiert
|
|
function createDarkModeToggle() {
|
|
// Bestehende Header-Elemente finden
|
|
const header = document.querySelector('header');
|
|
const nav = document.querySelector('nav');
|
|
const container = document.querySelector('.dark-mode-container') || header || nav;
|
|
|
|
if (!container) {
|
|
console.error('⚠️ Kein geeigneter Container für Dark Mode Toggle gefunden');
|
|
return;
|
|
}
|
|
|
|
// Toggle-Button erstellen
|
|
darkModeToggle = document.createElement('button');
|
|
darkModeToggle.id = 'darkModeToggle';
|
|
darkModeToggle.className = 'dark-mode-toggle-new';
|
|
darkModeToggle.setAttribute('aria-label', 'Dark Mode umschalten');
|
|
darkModeToggle.setAttribute('title', 'Dark Mode aktivieren');
|
|
darkModeToggle.setAttribute('data-action', 'toggle-dark-mode');
|
|
|
|
// Sonnen-Icon erstellen
|
|
const sunIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
sunIcon.setAttribute("class", "w-5 h-5 sm:w-5 sm:h-5 sun-icon");
|
|
sunIcon.setAttribute("fill", "none");
|
|
sunIcon.setAttribute("stroke", "currentColor");
|
|
sunIcon.setAttribute("viewBox", "0 0 24 24");
|
|
sunIcon.setAttribute("aria-hidden", "true");
|
|
|
|
const sunPath = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
sunPath.setAttribute("stroke-linecap", "round");
|
|
sunPath.setAttribute("stroke-linejoin", "round");
|
|
sunPath.setAttribute("stroke-width", "2");
|
|
sunPath.setAttribute("d", "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z");
|
|
|
|
// Mond-Icon erstellen
|
|
const moonIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
moonIcon.setAttribute("class", "w-5 h-5 sm:w-5 sm:h-5 moon-icon hidden");
|
|
moonIcon.setAttribute("fill", "none");
|
|
moonIcon.setAttribute("stroke", "currentColor");
|
|
moonIcon.setAttribute("viewBox", "0 0 24 24");
|
|
moonIcon.setAttribute("aria-hidden", "true");
|
|
|
|
const moonPath = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
moonPath.setAttribute("stroke-linecap", "round");
|
|
moonPath.setAttribute("stroke-linejoin", "round");
|
|
moonPath.setAttribute("stroke-width", "2");
|
|
moonPath.setAttribute("d", "M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z");
|
|
|
|
// Elemente zusammenfügen
|
|
sunIcon.appendChild(sunPath);
|
|
moonIcon.appendChild(moonPath);
|
|
darkModeToggle.appendChild(sunIcon);
|
|
darkModeToggle.appendChild(moonIcon);
|
|
|
|
// Zum Container hinzufügen
|
|
container.appendChild(darkModeToggle);
|
|
console.log('✅ Dark Mode Toggle Button erfolgreich erstellt und zur Benutzeroberfläche hinzugefügt');
|
|
}
|
|
|
|
// Sofort Dark/Light Mode anwenden (vor DOMContentLoaded)
|
|
const isDark = shouldUseDarkMode();
|
|
console.log(`🏃♂️ Sofortige Anwendung: ${isDark ? '🌙 Dark Mode' : '☀️ Light Mode'} (vor DOM-Ladung)`);
|
|
setDarkMode(isDark);
|
|
})();
|
|
|
|
// Animationen für Spin-Effekt
|
|
if (!document.querySelector('style#dark-mode-animations')) {
|
|
const styleTag = document.createElement('style');
|
|
styleTag.id = 'dark-mode-animations';
|
|
styleTag.textContent = `
|
|
@keyframes spin-once {
|
|
from { transform: rotate(0deg); }
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
.animate-spin-once {
|
|
animation: spin-once 0.3s ease-in-out;
|
|
}
|
|
`;
|
|
document.head.appendChild(styleTag);
|
|
console.log('💫 Animations-Styles für Dark Mode Toggle hinzugefügt');
|
|
}
|