1// Navigation scroll effect 2document.addEventListener('DOMContentLoaded', function() { 3 // Add scroll event for navigation 4 const header = document.querySelector('.main-navigation'); 5 let lastScroll = 0; 6 7 window.addEventListener('scroll', () => { 8 const currentScroll = window.pageYOffset; 9 10 if (currentScroll <= 0) { 11 header.classList.remove('scrolled'); 12 return; 13 } 14 15 if (currentScroll > lastScroll && !header.classList.contains('scroll-down')) { 16 // Scroll down 17 header.classList.remove('scrolled-up'); 18 header.classList.add('scrolled', 'scroll-down'); 19 } else if (currentScroll < lastScroll && header.classList.contains('scroll-down')) { 20 // Scroll up 21 header.classList.remove('scroll-down'); 22 header.classList.add('scrolled-up'); 23 } 24 25 lastScroll = currentScroll; 26 }); 27 28 // Smooth scrolling for anchor links 29 document.querySelectorAll('a[href^="#"]').forEach(anchor => { 30 anchor.addEventListener('click', function(e) { 31 e.preventDefault(); 32 33 const targetId = this.getAttribute('href'); 34 if (targetId === '#') return; 35 36 const targetElement = document.querySelector(targetId); 37 if (targetElement) { 38 window.scrollTo({ 39 top: targetElement.offsetTop - 100, 40 behavior: 'smooth' 41 }); 42 43 // Close mobile menu if open 44 const mobileMenu = document.getElementById('mobile-navigation'); 45 const mobileMenuBtn = document.querySelector('.mobile-menu-btn'); 46 if (mobileMenu && mobileMenu.getAttribute('aria-hidden') === 'false') { 47 mobileMenu.setAttribute('aria-hidden', 'true'); 48 mobileMenuBtn.setAttribute('aria-expanded', 'false'); 49 document.body.classList.remove('menu-open'); 50 } 51 } 52 }); 53 }); 54 // Tab functionality 55 const tabButtons = document.querySelectorAll('.tab-btn'); 56 const tabPanes = document.querySelectorAll('.tab-pane'); 57 58 // Set initial active tab 59 let activeTab = localStorage.getItem('activeTab') || 'superfast'; 60 61 // Function to activate a tab 62 function activateTab(tabId) { 63 // Hide all tab panes 64 tabPanes.forEach(pane => { 65 pane.classList.remove('active'); 66 }); 67 68 // Deactivate all tab buttons 69 tabButtons.forEach(btn => { 70 btn.classList.remove('active'); 71 }); 72 73 // Show the selected tab pane 74 const activePane = document.getElementById(tabId); 75 if (activePane) { 76 activePane.classList.add('active'); 77 } 78 79 // Activate the clicked button 80 const activeButton = document.querySelector(`.tab-btn[data-tab="${tabId}"]`); 81 if (activeButton) { 82 activeButton.classList.add('active'); 83 } 84 85 // Save active tab to localStorage 86 localStorage.setItem('activeTab', tabId); 87 } 88 89 // Add click event listeners to tab buttons 90 tabButtons.forEach(button => { 91 button.addEventListener('click', () => { 92 const tabId = button.getAttribute('data-tab'); 93 activateTab(tabId); 94 }); 95 }); 96 97 // Initialize with the active tab 98 activateTab(activeTab); 99 100 // Handle window resize for responsive behavior 101 let resizeTimer; 102 window.addEventListener('resize', () => { 103 clearTimeout(resizeTimer); 104 resizeTimer = setTimeout(() => { 105 // Update tab heights on resize 106 updateTabHeights(); 107 }, 250); 108 }); 109 110 // Function to update tab heights for consistent height 111 function updateTabHeights() { 112 let maxHeight = 0; 113 tabPanes.forEach(pane => { 114 pane.style.height = 'auto'; 115 const height = pane.offsetHeight; 116 if (height > maxHeight) { 117 maxHeight = height; 118 } 119 }); 120 121 // Set all tab panes to the height of the tallest one
122 tabPanes.forEach(pane => { 123 pane.style.minHeight = `${maxHeight}px`; 124 }); 125 } 126 127 // Initialize tab heights 128 updateTabHeights(); 129 130 // Add animation class to elements when they come into view 131 const animateOnScroll = () => { 132 const elements = document.querySelectorAll('.animate-on-scroll'); 133 elements.forEach(element => { 134 const elementPosition = element.getBoundingClientRect().top; 135 const windowHeight = window.innerHeight; 136 137 if (elementPosition < windowHeight - 50) { 138 element.classList.add('animate'); 139 } 140 }); 141 }; 142 143 // Initial check 144 animateOnScroll(); 145 146 // Check on scroll 147 window.addEventListener('scroll', animateOnScroll); 148 149 // Add animation to hero content 150 const heroContent = document.querySelector('.hero-content'); 151 if (heroContent) { 152 heroContent.classList.add('animate-on-scroll'); 153 } 154});
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.