diff --git a/Minecraft-Modern-Theme/js/announcement.js b/Minecraft-Modern-Theme/js/announcement.js index 27b5fa9..5836d1f 100644 --- a/Minecraft-Modern-Theme/js/announcement.js +++ b/Minecraft-Modern-Theme/js/announcement.js @@ -7,8 +7,7 @@ document.addEventListener("DOMContentLoaded", function () { if (position === "top") { document.body.insertAdjacentElement('afterbegin', bar); - } - else if (position === "below-slider") { + } else if (position === "below-slider") { const anchor = document.getElementById("mm-announcement-anchor"); if (anchor) { anchor.replaceWith(bar); @@ -16,69 +15,62 @@ document.addEventListener("DOMContentLoaded", function () { const header = document.getElementById("masthead"); if (header) header.insertAdjacentElement('afterend', bar); } - } - else if (position === "below-header") { - const header = document.getElementById("masthead"); - if (header) header.insertAdjacentElement('afterend', bar); - } - else { + } else { + // "below-header" und alle anderen Positionen const header = document.getElementById("masthead"); if (header) header.insertAdjacentElement('afterend', bar); } + // --- 2. Schließen-Button --- const closeBtn = bar.querySelector(".mm-announcement-close"); if (closeBtn) { closeBtn.addEventListener("click", function () { - bar.style.display = "none"; + bar.style.transition = 'opacity 0.3s ease'; + bar.style.opacity = '0'; + setTimeout(function() { bar.style.display = "none"; }, 300); }); } - // --- 2. Countdown Timer Logik --- + // --- 3. Countdown Timer --- const timerElement = document.querySelector('.mm-countdown-timer'); - + if (timerElement) { const targetDateString = timerElement.getAttribute('data-date'); - const expiredMessage = timerElement.getAttribute('data-expired'); - - // Prüfen ob Datum gesetzt ist - if (targetDateString) { - const countDownDate = new Date(targetDateString).getTime(); + const expiredMessage = timerElement.getAttribute('data-expired') || 'Abgelaufen'; - const updateTimer = setInterval(function() { - const now = new Date().getTime(); - const distance = countDownDate - now; - - if (distance < 0) { - clearInterval(updateTimer); - timerElement.innerHTML = expiredMessage; - // Optional: Rot einfärben wenn abgelaufen - timerElement.style.color = '#ff3333'; - return; - } - - // Zeitberechnung - const days = Math.floor(distance / (1000 * 60 * 60 * 24)); - const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); - const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); - const seconds = Math.floor((distance % (1000 * 60)) / 1000); - - // Formatierung (z.B. 05 statt 5) - const fDays = days > 0 ? days + "d " : ""; - const fHours = hours < 10 ? "0" + hours : hours; - const fMinutes = minutes < 10 ? "0" + minutes : minutes; - const fSeconds = seconds < 10 ? "0" + seconds : seconds; - - timerElement.innerHTML = fDays + fHours + ":" + fMinutes + ":" + fSeconds; - }, 1000); - - // Sofort einmal ausführen, um Ladezeit zu vermeiden - // Wir lösen das Interval manuell für den ersten Durchlauf aus, - // indem wir den Code kopieren oder den Timeout kurz setzen. - // Für diesen Fall reicht der erste Tick nach 1 Sekunde, - // aber wir können es direkt aufrufen: - // (Hier nutzen wir einfach den ersten Tick des Intervals) - } else { + if (!targetDateString) { timerElement.style.display = 'none'; + return; } + + const countDownDate = new Date(targetDateString).getTime(); + + // FIX: Tick-Funktion auslagern und SOFORT aufrufen – kein 1s-Flackern beim Laden + function tick() { + const now = new Date().getTime(); + const distance = countDownDate - now; + + if (distance < 0) { + clearInterval(timerInterval); + timerElement.innerHTML = expiredMessage; + timerElement.style.color = '#ff3333'; + return; + } + + const days = Math.floor(distance / (1000 * 60 * 60 * 24)); + const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((distance % (1000 * 60)) / 1000); + + const fDays = days > 0 ? days + 'd ' : ''; + const fHours = String(hours).padStart(2, '0'); + const fMinutes = String(minutes).padStart(2, '0'); + const fSeconds = String(seconds).padStart(2, '0'); + + timerElement.innerHTML = fDays + fHours + ':' + fMinutes + ':' + fSeconds; + } + + tick(); // Sofort ausführen + const timerInterval = setInterval(tick, 1000); } }); \ No newline at end of file diff --git a/Minecraft-Modern-Theme/js/header-scroll.js b/Minecraft-Modern-Theme/js/header-scroll.js index 48dc990..90b98d9 100644 --- a/Minecraft-Modern-Theme/js/header-scroll.js +++ b/Minecraft-Modern-Theme/js/header-scroll.js @@ -1,17 +1,57 @@ -// /js/header-scroll.js -document.addEventListener('DOMContentLoaded', function() { - // WICHTIG: Das Skript nur ausführen, wenn wir NICHT im Customizer sind. - // Diese Prüfung ist robuster und funktioniert ohne PHP. - if ( window.location.href.includes('/wp-admin/customize.php') || ( window.parent && window.parent.wp && window.parent.wp.customize ) ) { - return; // Skript hier beenden, wenn wir im Customizer sind. +// header-scroll.js – ergänzt um Header-Suche Toggle +document.addEventListener('DOMContentLoaded', function () { + + // ── Customizer Guard ────────────────────────────────────────────────── + if ( + window.location.href.includes('/wp-admin/customize.php') || + (window.parent && window.parent.wp && window.parent.wp.customize) + ) { + return; } + // ── Scroll-Effekt ───────────────────────────────────────────────────── const header = document.querySelector('.site-header'); - window.addEventListener('scroll', function() { - if (window.scrollY > 50) { - header.classList.add('scrolled'); - } else { - header.classList.remove('scrolled'); - } - }); + if (header) { + window.addEventListener('scroll', function () { + header.classList.toggle('scrolled', window.scrollY > 50); + }, { passive: true }); + } + + // ── Suche Toggle ────────────────────────────────────────────────────── + const searchToggle = document.querySelector('.header-search-toggle'); + const searchDropdown = document.querySelector('.header-search-dropdown'); + + if (searchToggle && searchDropdown) { + searchToggle.addEventListener('click', function (e) { + e.stopPropagation(); + const isOpen = searchDropdown.classList.toggle('open'); + searchToggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false'); + searchDropdown.setAttribute('aria-hidden', isOpen ? 'false' : 'true'); + + if (isOpen) { + // Fokus ins Suchfeld setzen + const field = searchDropdown.querySelector('.search-field'); + if (field) setTimeout(function () { field.focus(); }, 50); + } + }); + + // Schließen bei Außenklick + document.addEventListener('click', function (e) { + if (!searchDropdown.contains(e.target) && !searchToggle.contains(e.target)) { + searchDropdown.classList.remove('open'); + searchToggle.setAttribute('aria-expanded', 'false'); + searchDropdown.setAttribute('aria-hidden', 'true'); + } + }); + + // Schließen mit Escape + document.addEventListener('keydown', function (e) { + if (e.key === 'Escape' && searchDropdown.classList.contains('open')) { + searchDropdown.classList.remove('open'); + searchToggle.setAttribute('aria-expanded', 'false'); + searchDropdown.setAttribute('aria-hidden', 'true'); + searchToggle.focus(); + } + }); + } }); \ No newline at end of file diff --git a/Minecraft-Modern-Theme/js/login-slider.js b/Minecraft-Modern-Theme/js/login-slider.js index 26c649d..aa93882 100644 --- a/Minecraft-Modern-Theme/js/login-slider.js +++ b/Minecraft-Modern-Theme/js/login-slider.js @@ -1,25 +1,30 @@ jQuery(document).ready(function($) { const slider = $('#minecraft-avatar-slider'); const slides = slider.find('.avatar-slide'); - - // Nur starten, wenn es mehr als einen Slide gibt - if (slides.length > 1) { - let currentIndex = 0; - function showSlide(index) { - slides.removeClass('avatar-slide-active'); - slides.eq(index).addClass('avatar-slide-active'); - } + if ( slides.length === 0 ) return; + let currentIndex = 0; + + function showSlide(index) { + slides.removeClass('avatar-slide-active'); + slides.eq(index).addClass('avatar-slide-active'); + } + + // FIX: Ersten Slide sofort anzeigen, nicht erst nach dem ersten Interval-Tick + showSlide(0); + + // Nur Interval starten wenn es mehr als einen Slide gibt + if ( slides.length > 1 ) { function nextSlide() { currentIndex = (currentIndex + 1) % slides.length; showSlide(currentIndex); } - // Geschwindigkeit aus den WordPress-Einstellungen holen - const speed = avatarSliderSettings.speed || 4000; + const speed = ( typeof avatarSliderSettings !== 'undefined' && avatarSliderSettings.speed ) + ? avatarSliderSettings.speed + : 4000; - // Den Slider alle X Sekunden wechseln setInterval(nextSlide, speed); } }); \ No newline at end of file diff --git a/Minecraft-Modern-Theme/js/navigation.js b/Minecraft-Modern-Theme/js/navigation.js index 6e47dc4..7f058f2 100644 --- a/Minecraft-Modern-Theme/js/navigation.js +++ b/Minecraft-Modern-Theme/js/navigation.js @@ -1,8 +1,11 @@ ( function() { + // FIX: Null-Check – Script bricht auf Login-Seite & Seiten ohne Nav nicht mehr ab const siteNavigation = document.getElementById( 'site-navigation' ); - const menuToggle = siteNavigation.querySelector( '.menu-toggle' ); + if ( ! siteNavigation ) { + return; + } - // Early exit wenn kein Toggle da ist + const menuToggle = siteNavigation.querySelector( '.menu-toggle' ); if ( ! menuToggle ) { return; } @@ -10,8 +13,7 @@ // Toggle Klassen hinzufügen (Menü öffnen/schließen) menuToggle.addEventListener( 'click', function() { siteNavigation.classList.toggle( 'toggled' ); - - // Aria States aktualisieren + if ( menuToggle.getAttribute( 'aria-expanded' ) === 'true' ) { menuToggle.setAttribute( 'aria-expanded', 'false' ); menuToggle.innerHTML = ''; @@ -21,18 +23,37 @@ } } ); - // Mobile Submenu Toggle (Klick auf Parent-Item öffnet Untermenü) + // FIX: Menü bei Klick außerhalb schließen + document.addEventListener( 'click', function( e ) { + if ( siteNavigation.classList.contains( 'toggled' ) && ! siteNavigation.contains( e.target ) ) { + siteNavigation.classList.remove( 'toggled' ); + menuToggle.setAttribute( 'aria-expanded', 'false' ); + menuToggle.innerHTML = ''; + } + } ); + + // Mobile Submenu Toggle const subMenuParents = siteNavigation.querySelectorAll( '.menu-item-has-children' ); subMenuParents.forEach( function( subMenuParent ) { - subMenuParent.addEventListener( 'click', function( e ) { - // Nur auf Mobil aktivieren (Media Query Check) - if ( window.innerWidth <= 992 ) { - // Optional: Verhindern, dass der Link geklickt wird, wenn man nur das Menü öffnen will - // e.preventDefault(); + // FIX: Eigenen Toggle-Button erzeugen statt gesamtes
  • klickbar zu machen + const toggleBtn = document.createElement( 'button' ); + toggleBtn.classList.add( 'submenu-toggle' ); + toggleBtn.setAttribute( 'aria-expanded', 'false' ); + toggleBtn.innerHTML = ''; - // Klasse 'active' umschalten für das CSS Display - this.classList.toggle( 'active' ); + const parentLink = subMenuParent.querySelector( 'a' ); + if ( parentLink ) { + parentLink.insertAdjacentElement( 'afterend', toggleBtn ); + } + + toggleBtn.addEventListener( 'click', function( e ) { + e.stopPropagation(); + if ( window.innerWidth <= 992 ) { + const isOpen = subMenuParent.classList.toggle( 'active' ); + toggleBtn.setAttribute( 'aria-expanded', isOpen ? 'true' : 'false' ); + // Icon drehen + toggleBtn.querySelector('i').style.transform = isOpen ? 'rotate(180deg)' : 'rotate(0deg)'; } } ); } ); diff --git a/Minecraft-Modern-Theme/js/theme-toggle.js b/Minecraft-Modern-Theme/js/theme-toggle.js index 869f8e8..8a271b4 100644 --- a/Minecraft-Modern-Theme/js/theme-toggle.js +++ b/Minecraft-Modern-Theme/js/theme-toggle.js @@ -1,32 +1,55 @@ document.addEventListener('DOMContentLoaded', function () { - const html = document.documentElement; - const toggle = document.querySelector('.theme-toggle'); - const iconMoon = toggle.querySelector('.icon-moon'); - const iconSun = toggle.querySelector('.icon-sun'); + // FIX: Null-Check – Login-Seite hat keinen Toggle-Button + const toggle = document.querySelector('.theme-toggle'); + if ( ! toggle ) { + return; + } - const defaultMode = typeof sliderSettings !== 'undefined' ? sliderSettings.defaultMode : 'dark'; - const saved = localStorage.getItem('themeMode') || defaultMode; + const html = document.documentElement; + const iconMoon = toggle.querySelector('.icon-moon'); + const iconSun = toggle.querySelector('.icon-sun'); - if (saved === 'light') { - html.classList.add('light-mode'); - iconMoon.style.display = 'none'; - iconSun.style.display = 'block'; - } else { - iconMoon.style.display = 'block'; - iconSun.style.display = 'none'; - } + const defaultMode = typeof sliderSettings !== 'undefined' ? sliderSettings.defaultMode : 'dark'; - toggle.addEventListener('click', function () { - html.classList.toggle('light-mode'); + // FIX: Systemschema respektieren wenn kein gespeicherter Wert vorhanden + let saved = localStorage.getItem('themeMode'); + if ( ! saved ) { + // Prüfe OS-Einstellung, falle sonst auf Theme-Default zurück + if ( window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches ) { + saved = 'light'; + } else { + saved = defaultMode; + } + } - if (html.classList.contains('light-mode')) { - iconMoon.style.display = 'none'; - iconSun.style.display = 'block'; - localStorage.setItem('themeMode', 'light'); - } else { - iconMoon.style.display = 'block'; - iconSun.style.display = 'none'; - localStorage.setItem('themeMode', 'dark'); - } - }); + function applyMode( mode ) { + if ( mode === 'light' ) { + html.classList.add('light-mode'); + if ( iconMoon ) iconMoon.style.display = 'none'; + if ( iconSun ) iconSun.style.display = 'block'; + } else { + html.classList.remove('light-mode'); + if ( iconMoon ) iconMoon.style.display = 'block'; + if ( iconSun ) iconSun.style.display = 'none'; + } + } + + applyMode( saved ); + + toggle.addEventListener('click', function () { + const isLight = html.classList.toggle('light-mode'); + const newMode = isLight ? 'light' : 'dark'; + applyMode( newMode ); + localStorage.setItem('themeMode', newMode); + }); + + // Live-Reaktion auf OS-Umschalten (optional aber nice-to-have) + if ( window.matchMedia ) { + window.matchMedia('(prefers-color-scheme: light)').addEventListener('change', function( e ) { + // Nur reagieren wenn der User noch keine manuelle Auswahl getroffen hat + if ( ! localStorage.getItem('themeMode') ) { + applyMode( e.matches ? 'light' : 'dark' ); + } + }); + } }); \ No newline at end of file