1document.addEventListener('DOMContentLoaded', () => { 2 // Current Year Update 3 const yearSpan = document.getElementById('year'); 4 if (yearSpan) { 5 yearSpan.textContent = new Date().getFullYear(); 6 } 7 8 // Navbar Scroll Effect 9 const navbar = document.getElementById('navbar'); 10 window.addEventListener('scroll', () => { 11 if (window.scrollY > 50) { 12 navbar.classList.add('scrolled'); 13 } else { 14 navbar.classList.remove('scrolled'); 15 } 16 }); 17 18 // Mobile Menu Toggle 19 const mobileMenu = document.getElementById('mobile-menu'); 20 const navMenu = document.querySelector('.nav-menu'); 21 const navLinks = document.querySelectorAll('.nav-link'); 22 23 mobileMenu.addEventListener('click', () => { 24 mobileMenu.classList.toggle('active'); 25 navMenu.classList.toggle('active'); 26 }); 27 28 navLinks.forEach(link => { 29 link.addEventListener('click', () => { 30 mobileMenu.classList.remove('active'); 31 navMenu.classList.remove('active'); 32 }); 33 }); 34 35 // Active Link Highlighting 36 const sections = document.querySelectorAll('section, header'); 37 38 window.addEventListener('scroll', () => { 39 let current = ''; 40 sections.forEach(section => { 41 const sectionTop = section.offsetTop; 42 const sectionHeight = section.clientHeight; 43 if (scrollY >= (sectionTop - 200)) { 44 current = section.getAttribute('id'); 45 } 46 }); 47 48 navLinks.forEach(link => { 49 link.classList.remove('active'); 50 if (link.getAttribute('href').includes(current)) { 51 link.classList.add('active'); 52 } 53 }); 54 }); 55 56 // Scroll Reveal Animation (Intersection Observer) 57 const revealElements = document.querySelectorAll('.scroll-reveal'); 58 59 const revealOptions = { 60 threshold: 0.15, 61 rootMargin: "0px 0px -50px 0px" 62 }; 63 64 const revealOnScroll = new IntersectionObserver(function(entries, observer) { 65 entries.forEach(entry => { 66 if (!entry.isIntersecting) { 67 return; 68 } else { 69 entry.target.classList.add('visible'); 70 observer.unobserve(entry.target); 71 } 72 }); 73 }, revealOptions); 74 75 revealElements.forEach(el => { 76 revealOnScroll.observe(el); 77 }); 78 79 // Handle Subscribe Form Submission (Dummy Action) 80 const form = document.getElementById('subscribe-form'); 81 if (form) { 82 form.addEventListener('submit', (e) => { 83 e.preventDefault(); 84 const btn = form.querySelector('.submit-btn'); 85 const msg = form.querySelector('.success-msg'); 86 const input = form.querySelector('.form-input'); 87 88 btn.textContent = 'Subscribing...'; 89 btn.disabled = true; 90 91 setTimeout(() => { 92 btn.textContent = 'Subscribe'; 93 btn.disabled = false; 94 input.value = ''; 95 msg.style.display = 'block'; 96 97 setTimeout(() => { 98 msg.style.display = 'none'; 99 }, 4000); 100 }, 1000); 101 }); 102 } 103});
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.