1// ======================================== 2// MODERN HEADER FUNCTIONALITY 3// ======================================== 4 5document.addEventListener('DOMContentLoaded', function() { 6 7 // Elements 8 const header = document.querySelector('header'); 9 const navToggle = document.querySelector('.header__nav-toggle'); 10 const nav = document.querySelector('.header__nav'); 11 const dropdownToggles = document.querySelectorAll('.header__dropdown-toggle'); 12 13 // Create mobile overlay 14 const overlay = document.createElement('div'); 15 overlay.className = 'mobile-overlay'; 16 document.body.appendChild(overlay); 17 18 // ======================================== 19 // Scroll Effect 20 // ======================================== 21 let lastScroll = 0; 22 window.addEventListener('scroll', function() { 23 const currentScroll = window.pageYOffset; 24 25 if (currentScroll > 100) { 26 header.classList.add('scrolled'); 27 } else { 28 header.classList.remove('scrolled'); 29 } 30 31 lastScroll = currentScroll; 32 }); 33 34 // ======================================== 35 // Mobile Menu Toggle 36 // ======================================== 37 function toggleMobileMenu() { 38 navToggle.classList.toggle('active'); 39 nav.classList.toggle('active'); 40 overlay.classList.toggle('active'); 41 document.body.style.overflow = nav.classList.contains('active') ? 'hidden' : ''; 42 } 43 44 function closeMobileMenu() { 45 navToggle.classList.remove('active'); 46 nav.classList.remove('active'); 47 overlay.classList.remove('active'); 48 document.body.style.overflow = ''; 49 50 // Close all dropdowns 51 dropdownToggles.forEach(toggle => { 52 toggle.classList.remove('active'); 53 }); 54 } 55 56 // Toggle button click 57 if (navToggle) { 58 navToggle.addEventListener('click', function(e) { 59 e.preventDefault(); 60 e.stopPropagation(); 61 toggleMobileMenu(); 62 }); 63 } 64 65 // Overlay click 66 overlay.addEventListener('click', closeMobileMenu); 67 68 // ======================================== 69 // Mobile Dropdown Functionality 70 // ======================================== 71 dropdownToggles.forEach(function(toggle) { 72 // Create arrow element for mobile 73 const arrow = document.createElement('span'); 74 arrow.className = 'mobile-dropdown-arrow'; 75 76 const link = toggle.querySelector('a'); 77 78 // Add arrow to link only on mobile 79 function updateArrow() { 80 if (window.innerWidth <= 992) { 81 if (!link.querySelector('.mobile-dropdown-arrow')) { 82 link.appendChild(arrow); 83 } 84 } else { 85 if (link.querySelector('.mobile-dropdown-arrow')) { 86 arrow.remove(); 87 } 88 } 89 } 90 91 updateArrow(); 92 93 // Arrow click handler 94 arrow.addEventListener('click', function(e) { 95 e.preventDefault(); 96 e.stopPropagation(); 97 98 // Close other dropdowns 99 dropdownToggles.forEach(function(otherToggle) { 100 if (otherToggle !== toggle) { 101 otherToggle.classList.remove('active'); 102 } 103 }); 104 105 // Toggle current dropdown 106 toggle.classList.toggle('active'); 107 }); 108 109 // Link click - should navigate normally 110 link.addEventListener('click', function(e) { 111 if (window.innerWidth <= 992) { 112 // Check if click was on arrow 113 if (e.target.closest('.mobile-dropdown-arrow')) { 114 e.preventDefault(); 115 e.stopPropagation(); 116 } 117 // Otherwise allow normal navigation 118 } 119 }); 120 121 // Update on resize 122 window.addEventListener('resize', updateArrow); 123 });
124 125 // ======================================== 126 // Close menu on window resize 127 // ======================================== 128 let resizeTimer; 129 window.addEventListener('resize', function() { 130 clearTimeout(resizeTimer); 131 resizeTimer = setTimeout(function() { 132 if (window.innerWidth > 992) { 133 closeMobileMenu(); 134 } 135 }, 250); 136 }); 137 138 // ======================================== 139 // Prevent body scroll when menu is open 140 // ======================================== 141 document.addEventListener('touchmove', function(e) { 142 if (nav.classList.contains('active') && !nav.contains(e.target)) { 143 e.preventDefault(); 144 } 145 }, { passive: false }); 146 147 // ======================================== 148 // Keyboard Navigation 149 // ======================================== 150 document.addEventListener('keydown', function(e) { 151 // Close menu on Escape 152 if (e.key === 'Escape' && nav.classList.contains('active')) { 153 closeMobileMenu(); 154 } 155 }); 156 157 // ======================================== 158 // Smooth Scroll for Anchor Links 159 // ======================================== 160 document.querySelectorAll('a[href^="#"]').forEach(anchor => { 161 anchor.addEventListener('click', function(e) { 162 const href = this.getAttribute('href'); 163 if (href !== '#' && document.querySelector(href)) { 164 e.preventDefault(); 165 closeMobileMenu(); 166 167 setTimeout(() => { 168 document.querySelector(href).scrollIntoView({ 169 behavior: 'smooth', 170 block: 'start' 171 }); 172 }, 300); 173 } 174 }); 175 }); 176 177 // ======================================== 178 // Add animation to dropdown items 179 // ======================================== 180 dropdownToggles.forEach(toggle => { 181 const dropdown = toggle.querySelector('.header__dropdown'); 182 if (dropdown) { 183 const items = dropdown.querySelectorAll('li'); 184 185 toggle.addEventListener('mouseenter', function() { 186 if (window.innerWidth > 992) { 187 items.forEach((item, index) => { 188 item.style.opacity = '0'; 189 item.style.transform = 'translateY(-10px)'; 190 191 setTimeout(() => { 192 item.style.transition = 'all 0.3s ease'; 193 item.style.opacity = '1'; 194 item.style.transform = 'translateY(0)'; 195 }, index * 50); 196 }); 197 } 198 }); 199 } 200 }); 201 202 // ======================================== 203 // Console log for debugging 204 // ======================================== 205 console.log('Modern Header Script Loaded Successfully! ð'); 206});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.