/** * Auto-Hide Navigation Script * Smoothly hides navigation when scrolling down and shows it when scrolling up */ (function() { 'use strict'; // Configuration const config = { scrollThreshold: 100, // Start hiding after this many pixels mouseRevealZone: 100, // Show header when mouse is within this many pixels from top animationDuration: 300, // Animation duration in ms debounceDelay: 10 // Scroll event debounce delay }; // State management let state = { lastScrollTop: 0, isVisible: true, headerHeight: 0, ticking: false }; // DOM elements let elements = {}; // Initialize when DOM is ready document.addEventListener('DOMContentLoaded', init); function init() { // Find header elements - Twenty Twenty-Five specific selectors elements.header = document.querySelector('header') || document.querySelector('.wp-site-header') || document.querySelector('.wp-block-template-part[data-area="header"]') || document.querySelector('.wp-block-group.is-layout-constrained') || document.querySelector('[class*="header"]'); elements.body = document.body; // Debug: Log found header element console.log('Auto-hide navigation: Header element found:', elements.header); if (!elements.header) { console.warn('Auto-hide navigation: No header element found'); // Try to find any element that might be the header const possibleHeaders = document.querySelectorAll('nav, [class*="nav"], [class*="header"], [class*="menu"]'); console.log('Possible header elements:', possibleHeaders); return; } // Add identifying class for our CSS elements.header.classList.add('srh-auto-hide-header'); // Setup calculateHeaderHeight(); bindEvents(); // Initial state updateHeaderState(); console.log('Auto-hide navigation initialized successfully'); } function calculateHeaderHeight() { if (!elements.header) return; state.headerHeight = elements.header.offsetHeight || 80; document.documentElement.style.setProperty('--header-height', state.headerHeight + 'px'); } function bindEvents() { // Scroll event with debouncing window.addEventListener('scroll', debounce(handleScroll, config.debounceDelay)); // Resize event window.addEventListener('resize', debounce(calculateHeaderHeight, 100)); // Mouse movement for revealing header document.addEventListener('mousemove', handleMouseMove); // Keyboard events for accessibility document.addEventListener('keydown', handleKeydown); // Focus events for accessibility if (elements.header) { const focusableElements = elements.header.querySelectorAll('a, button, input, textarea, select, [tabindex]'); focusableElements.forEach(el => { el.addEventListener('focus', showHeader); }); } // Smooth scroll for anchor links document.addEventListener('click', handleAnchorClick); } function handleScroll() { if (!state.ticking) { requestAnimationFrame(updateHeaderState); state.ticking = true; } } function updateHeaderState() { const scrollTop = window.pageYOffset || document.documentElement.scrollTop; // Add scrolled class for styling if (scrollTop > 50) { elements.body.classList.add('header-offset'); elements.header.classList.add('header-scrolled'); } else { elements.body.classList.remove('header-offset'); elements.header.classList.remove('header-scrolled'); } // Hide/show logic if (scrollTop > config.scrollThreshold) { if (scrollTop > state.lastScrollTop && state.isVisible) { // Scrolling down - hide header hideHeader(); } else if (scrollTop < state.lastScrollTop && !state.isVisible) { // Scrolling up - show header showHeader(); } } else if (!state.isVisible) { // Near top - always show header showHeader(); } state.lastScrollTop = scrollTop; state.ticking = false; } function hideHeader() { if (!state.isVisible) return; state.isVisible = false; elements.header.classList.remove('header-visible'); elements.header.classList.add('header-hidden'); // Dispatch custom event dispatchCustomEvent('headerHidden'); } function showHeader() { if (state.isVisible) return; state.isVisible = true; elements.header.classList.remove('header-hidden'); elements.header.classList.add('header-visible'); // Dispatch custom event dispatchCustomEvent('headerVisible'); } function handleMouseMove(e) { if (e.clientY < config.mouseRevealZone && window.pageYOffset > config.scrollThreshold && !state.isVisible) { showHeader(); } } function handleKeydown(e) { // Show header on Tab or Escape for accessibility if (e.key === 'Tab' || e.key === 'Escape') { showHeader(); } } function handleAnchorClick(e) { const link = e.target.closest('a[href^=\"#\"]'); if (!link) return; const targetId = link.getAttribute('href').substring(1); const target = document.getElementById(targetId); if (target) { e.preventDefault(); const offsetTop = target.getBoundingClientRect().top + window.pageYOffset - state.headerHeight; window.scrollTo({ top: offsetTop, behavior: 'smooth' }); } } function dispatchCustomEvent(eventName) { const event = new CustomEvent(eventName, { detail: { headerElement: elements.header, isVisible: state.isVisible, scrollTop: state.lastScrollTop } }); document.dispatchEvent(event); } function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // Public API window.SRHNavigation = { show: showHeader, hide: hideHeader, toggle: function() { state.isVisible ? hideHeader() : showHeader(); }, getState: function() { return { ...state }; }, updateConfig: function(newConfig) { Object.assign(config, newConfig); } }; })();