diff --git a/Minecraft-Modern-Theme/js/assistant-widget.js b/Minecraft-Modern-Theme/js/assistant-widget.js new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Minecraft-Modern-Theme/js/assistant-widget.js @@ -0,0 +1 @@ + diff --git a/Minecraft-Modern-Theme/js/header-scroll.js b/Minecraft-Modern-Theme/js/header-scroll.js index 90b98d9..41ccbee 100644 --- a/Minecraft-Modern-Theme/js/header-scroll.js +++ b/Minecraft-Modern-Theme/js/header-scroll.js @@ -1,4 +1,4 @@ -// header-scroll.js – ergänzt um Header-Suche Toggle +// header-scroll.js – kompakter Header beim Scrollen + Suche Toggle document.addEventListener('DOMContentLoaded', function () { // ── Customizer Guard ────────────────────────────────────────────────── @@ -9,12 +9,79 @@ document.addEventListener('DOMContentLoaded', function () { return; } - // ── Scroll-Effekt ───────────────────────────────────────────────────── + // ── Scroll-Effekt + kompakter Header ───────────────────────────────── const header = document.querySelector('.site-header'); + const brandingRow = header ? header.querySelector('.header-row-branding') : null; + if (header) { - window.addEventListener('scroll', function () { - header.classList.toggle('scrolled', window.scrollY > 50); - }, { passive: true }); + let lastScrollY = Math.max(window.scrollY, 0); + let directionAnchorY = lastScrollY; + let isCompact = header.classList.contains('header-compact'); + let lastStateChangeAt = 0; + let ticking = false; + + const compactEnterThreshold = 110; + const compactExitThreshold = 24; + const directionThreshold = 10; + const expandDelta = 120; + const stateChangeCooldown = 260; + + const setCompactState = function (nextCompact, now) { + if (isCompact === nextCompact) { + return; + } + + isCompact = nextCompact; + lastStateChangeAt = now; + directionAnchorY = Math.max(window.scrollY, 0); + + header.classList.toggle('header-compact', nextCompact); + + if (brandingRow) { + brandingRow.classList.toggle('branding-hidden', nextCompact); + } + }; + + const updateHeaderState = function () { + ticking = false; + + const now = window.performance && typeof window.performance.now === 'function' + ? window.performance.now() + : Date.now(); + const currentScrollY = Math.max(window.scrollY, 0); + const delta = currentScrollY - lastScrollY; + const canChangeState = now - lastStateChangeAt >= stateChangeCooldown; + + header.classList.toggle('scrolled', currentScrollY > 50); + + if (currentScrollY <= compactExitThreshold) { + setCompactState(false, now); + } else if (canChangeState && delta > directionThreshold) { + directionAnchorY = currentScrollY; + + if (currentScrollY > compactEnterThreshold) { + setCompactState(true, now); + } + } else if (canChangeState && delta < -directionThreshold) { + if (directionAnchorY - currentScrollY >= expandDelta) { + setCompactState(false, now); + } + } + + lastScrollY = currentScrollY; + }; + + const onScroll = function () { + if (ticking) { + return; + } + + ticking = true; + window.requestAnimationFrame(updateHeaderState); + }; + + updateHeaderState(); + window.addEventListener('scroll', onScroll, { passive: true }); } // ── Suche Toggle ────────────────────────────────────────────────────── diff --git a/Minecraft-Modern-Theme/js/minecraft-avatar-skinview.js b/Minecraft-Modern-Theme/js/minecraft-avatar-skinview.js new file mode 100644 index 0000000..1d098c6 --- /dev/null +++ b/Minecraft-Modern-Theme/js/minecraft-avatar-skinview.js @@ -0,0 +1,63 @@ +// Lädt skinview3d von CDN +(function(){ + if(document.getElementById('skinview3d-cdn')) return; + var s = document.createElement('script'); + s.id = 'skinview3d-cdn'; + s.src = 'https://unpkg.com/skinview3d@4.1.1/bundles/skinview3d.min.js'; + s.onload = function() { + window.skinview3dReady = true; + }; + document.head.appendChild(s); +})(); + +window.showMinecraftSkinModal = function(uuid) { + if(document.getElementById('minecraft-skin-modal')) return; + var modal = document.createElement('div'); + modal.id = 'minecraft-skin-modal'; + modal.innerHTML = ` +
+ + `; + document.body.appendChild(modal); + document.querySelector('.sv3d-modal-close').onclick = function(){ modal.remove(); }; + document.querySelector('.sv3d-modal-bg').onclick = function(){ modal.remove(); }; + + function renderSkin() { + var skinUrl = `https://crafatar.com/skins/${uuid}`; + var canvas = document.createElement('canvas'); + canvas.width = 320; canvas.height = 320; + document.getElementById('sv3d-canvas-wrap').appendChild(canvas); + var viewer = new skinview3d.SkinViewer({ + canvas: canvas, + width: 320, + height: 320, + skin: skinUrl + }); + viewer.controls.enableZoom = false; + viewer.animation = new skinview3d.WalkingAnimation(); + viewer.animation.speed = 1.2; + viewer.animation.play(); + } + if(window.skinview3dReady) renderSkin(); + else { + var check = setInterval(function(){ + if(window.skinview3dReady) { clearInterval(check); renderSkin(); } + }, 100); + } +}; + +// Avatar-Widget-Click-Handler +window.addEventListener('DOMContentLoaded', function(){ + var widget = document.getElementById('minecraft-avatar-widget'); + if(widget) { + widget.style.cursor = 'pointer'; + widget.title = 'Klicke für 3D Skin-Ansicht'; + widget.onclick = function(){ + var uuid = widget.getAttribute('data-uuid'); + if(uuid) window.showMinecraftSkinModal(uuid); + }; + } +}); diff --git a/Minecraft-Modern-Theme/js/navigation.js b/Minecraft-Modern-Theme/js/navigation.js index 7f058f2..ce31855 100644 --- a/Minecraft-Modern-Theme/js/navigation.js +++ b/Minecraft-Modern-Theme/js/navigation.js @@ -1,61 +1,174 @@ -( function() { - // FIX: Null-Check – Script bricht auf Login-Seite & Seiten ohne Nav nicht mehr ab - const siteNavigation = document.getElementById( 'site-navigation' ); - if ( ! siteNavigation ) { +( function () { + 'use strict'; + + var isSidebarLayout = document.querySelector( '.site-header--sidebar' ) !== null; + + if ( isSidebarLayout ) { + + // --- Panel öffnen / schließen --- + var panel = document.getElementById( 'header-sidebar' ); + var overlay = document.getElementById( 'sidebar-overlay' ); + var openBtn = document.querySelector( '.sidebar-menu-toggle' ); + var closeBtn = document.querySelector( '.sidebar-menu-close' ); + + function openPanel() { + if ( ! panel ) return; + panel.classList.add( 'is-open' ); + panel.setAttribute( 'aria-hidden', 'false' ); + if ( openBtn ) openBtn.setAttribute( 'aria-expanded', 'true' ); + if ( overlay ) overlay.classList.add( 'is-visible' ); + document.body.classList.add( 'sidebar-nav-open' ); + } + + function closePanel() { + if ( ! panel ) return; + panel.classList.remove( 'is-open' ); + panel.setAttribute( 'aria-hidden', 'true' ); + if ( openBtn ) openBtn.setAttribute( 'aria-expanded', 'false' ); + if ( overlay ) overlay.classList.remove( 'is-visible' ); + document.body.classList.remove( 'sidebar-nav-open' ); + } + + if ( openBtn ) openBtn.addEventListener( 'click', openPanel ); + if ( closeBtn ) closeBtn.addEventListener( 'click', closePanel ); + if ( overlay ) overlay.addEventListener( 'click', closePanel ); + document.addEventListener( 'keydown', function ( e ) { + if ( e.key === 'Escape' ) closePanel(); + } ); + + // --- Submenu Flyout --- + var sidebarNav = document.getElementById( 'site-navigation' ); + if ( sidebarNav ) { + sidebarNav.querySelectorAll( '.menu-item-has-children' ).forEach( function ( item ) { + var subMenu = item.querySelector( ':scope > .sub-menu' ); + if ( ! subMenu ) return; + + var isOpen = false; + var moveHdlr = null; + + function showFlyout() { + if ( isOpen ) return; + isOpen = true; + subMenu.style.top = item.getBoundingClientRect().top + 'px'; + item.classList.add( 'flyout-open' ); + + // Erkennungszone berechnen: + // - vertikal: Höhe des li-Elements + // - horizontal: von linkem Rand der Sidebar (0) bis + // rechtem Rand des Flyout-Panels + // → voller horizontaler Streifen für diesen Menüpunkt + moveHdlr = function ( e ) { + var ir = item.getBoundingClientRect(); + var sr = subMenu.getBoundingClientRect(); + + var zoneLeft = 0; // Bildschirmrand links + var zoneRight = Math.max( ir.right, sr.right ); // bis Ende Flyout + var zoneTop = ir.top; // oberer Rand des li + var zoneBottom = ir.bottom; // unterer Rand des li + + var inZone = e.clientX >= zoneLeft && + e.clientX <= zoneRight && + e.clientY >= zoneTop && + e.clientY <= zoneBottom; + + if ( ! inZone ) hideFlyout(); + }; + + document.addEventListener( 'mousemove', moveHdlr ); + } + + function hideFlyout() { + if ( ! isOpen ) return; + isOpen = false; + item.classList.remove( 'flyout-open' ); + if ( moveHdlr ) { + document.removeEventListener( 'mousemove', moveHdlr ); + moveHdlr = null; + } + } + + item.addEventListener( 'mouseenter', showFlyout ); + + // Klick-Toggle für Touch / Tastatur + var btn = document.createElement( 'button' ); + btn.className = 'submenu-toggle'; + btn.setAttribute( 'aria-expanded', 'false' ); + btn.innerHTML = ''; + var link = item.querySelector( ':scope > a' ); + if ( link ) link.insertAdjacentElement( 'afterend', btn ); + + btn.addEventListener( 'click', function ( e ) { + e.stopPropagation(); + var open = item.classList.toggle( 'active' ); + btn.setAttribute( 'aria-expanded', open ? 'true' : 'false' ); + if ( open ) { + subMenu.style.top = item.getBoundingClientRect().top + 'px'; + item.classList.add( 'flyout-open' ); + isOpen = true; + } else { + hideFlyout(); + } + } ); + } ); + } + return; } - const menuToggle = siteNavigation.querySelector( '.menu-toggle' ); - if ( ! menuToggle ) { - return; - } + // ========================================================================= + // CLASSIC / CENTERED / MEGA + // ========================================================================= + var siteNavigation = document.getElementById( 'site-navigation' ); + if ( ! siteNavigation ) return; - // Toggle Klassen hinzufügen (Menü öffnen/schließen) - menuToggle.addEventListener( 'click', function() { - siteNavigation.classList.toggle( 'toggled' ); + var menuToggle = siteNavigation.querySelector( '.menu-toggle' ); + var subMenuParents = siteNavigation.querySelectorAll( '.menu-item-has-children' ); - if ( menuToggle.getAttribute( 'aria-expanded' ) === 'true' ) { - menuToggle.setAttribute( 'aria-expanded', 'false' ); - menuToggle.innerHTML = ''; - } else { - menuToggle.setAttribute( 'aria-expanded', 'true' ); - menuToggle.innerHTML = ''; - } - } ); - - // 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 ) { - // FIX: Eigenen Toggle-Button erzeugen statt gesamtes