Oops! Sorry!!


This site doesn't support Internet Explorer. Please use a modern browser like Chrome, Firefox or Edge.

// Enhanced Mobile Navigation Class class MobileNavigation { constructor() { this.navbar = document.querySelector('.navbar'); this.mobileToggle = document.querySelector('#mobileMenuToggle'); this.navbarNav = document.querySelector('#navbarNav'); this.isAnimating = false; this.init(); } init() { if (!this.mobileToggle || !this.navbarNav) { console.warn('Mobile navigation elements not found'); return; } console.log('Initializing mobile navigation...'); this.setupEventListeners(); this.setupScrollEffect(); } setupEventListeners() { // Mobile menu toggle this.mobileToggle.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); console.log('Mobile toggle clicked'); this.toggleMobileMenu(); }); // Keyboard support for toggle this.mobileToggle.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); this.toggleMobileMenu(); } }); // Close menu when clicking outside navbar document.addEventListener('click', (e) => { if (!e.target.closest('.navbar') && this.isMobileMenuOpen()) { console.log('Clicking outside - closing menu'); this.closeMobileMenu(); } }); // Close menu on escape key document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && this.isMobileMenuOpen()) { console.log('Escape pressed - closing menu'); this.closeMobileMenu(); this.mobileToggle.focus(); } }); // Close menu on window resize to desktop window.addEventListener('resize', () => { if (window.innerWidth > 768 && this.isMobileMenuOpen()) { console.log('Resized to desktop - closing menu'); this.closeMobileMenu(); } }); // Close menu when clicking navigation links const navLinks = this.navbarNav.querySelectorAll('.dropdown-item, .nav-link'); navLinks.forEach(link => { link.addEventListener('click', (e) => { // Only close if it's an actual navigation link (has href that's not just "#") const href = link.getAttribute('href'); if (href && href !== '#' && href.length > 1) { if (this.isMobileMenuOpen()) { console.log('Nav link clicked - closing menu'); setTimeout(() => this.closeMobileMenu(), 150); } } }); }); } setupScrollEffect() { if (!this.navbar) return; let ticking = false; const handleScroll = () => { if (!ticking) { requestAnimationFrame(() => { const scrolled = window.scrollY > 100; this.navbar.classList.toggle('scrolled', scrolled); ticking = false; }); ticking = true; } }; window.addEventListener('scroll', handleScroll, { passive: true }); } toggleMobileMenu() { if (this.isAnimating) { console.log('Animation in progress - ignoring toggle'); return; } if (this.isMobileMenuOpen()) { this.closeMobileMenu(); } else { this.openMobileMenu(); } } openMobileMenu() { console.log('Opening mobile menu'); this.isAnimating = true; // Add active classes this.mobileToggle.classList.add('active'); this.navbarNav.classList.add('mobile-open'); document.body.classList.add('mobile-menu-open'); // Update ARIA attributes this.mobileToggle.setAttribute('aria-expanded', 'true'); this.navbarNav.setAttribute('aria-hidden', 'false'); // Focus management setTimeout(() => { const firstLink = this.navbarNav.querySelector('.nav-link'); if (firstLink) { firstLink.focus(); } this.isAnimating = false; console.log('Mobile menu opened'); }, 300); } closeMobileMenu() { console.log('Closing mobile menu'); this.isAnimating = true; // Remove active classes this.mobileToggle.classList.remove('active'); this.navbarNav.classList.remove('mobile-open'); document.body.classList.remove('mobile-menu-open'); // Update ARIA attributes this.mobileToggle.setAttribute('aria-expanded', 'false'); this.navbarNav.setAttribute('aria-hidden', 'true'); setTimeout(() => { this.isAnimating = false; console.log('Mobile menu closed'); }, 300); } isMobileMenuOpen() { return this.navbarNav && this.navbarNav.classList.contains('mobile-open'); } } // Update your existing Navigation class or replace the mobile menu section class Navigation { constructor() { this.navbar = Utils.querySelector('.navbar'); this.mobileToggle = Utils.querySelector('#mobileMenuToggle'); this.navbarNav = Utils.querySelector('#navbarNav'); this.backToTop = Utils.querySelector('#backToTop'); this.mobileNav = new MobileNavigation(); // Use the new mobile navigation this.init(); } init() { try { this.setupBackToTop(); this.setupSmoothScrolling(); // Mobile navigation is now handled by MobileNavigation class } catch (error) { console.error('Error initializing Navigation:', error); } } // Keep your existing setupBackToTop and setupSmoothScrolling methods... setupBackToTop() { if (!this.backToTop) return; if (Utils.hasFeature('intersectionObserver')) { const heroSection = Utils.querySelector('.hero'); if (heroSection) { const observer = new IntersectionObserver( (entries) => { entries.forEach(entry => { const isVisible = !entry.isIntersecting; this.backToTop.style.opacity = isVisible ? '1' : '0'; this.backToTop.style.visibility = isVisible ? 'visible' : 'hidden'; this.backToTop.setAttribute('aria-hidden', !isVisible); }); }, { threshold: 0.1 } ); observer.observe(heroSection); } } this.backToTop.addEventListener('click', (e) => { e.preventDefault(); this.smoothScrollToTop(); }); } setupSmoothScrolling() { const anchorLinks = document.querySelectorAll('a[href^="#"]'); anchorLinks.forEach(anchor => { anchor.addEventListener('click', (e) => { const targetId = anchor.getAttribute('href'); if (targetId === '#' || targetId.length <= 1) { return; } e.preventDefault(); const target = Utils.querySelector(targetId); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); // Close mobile menu if open if (this.mobileNav && this.mobileNav.isMobileMenuOpen()) { this.mobileNav.closeMobileMenu(); } target.setAttribute('tabindex', '-1'); target.focus(); setTimeout(() => target.removeAttribute('tabindex'), 1000); } }); }); } smoothScrollToTop() { if ('scrollBehavior' in document.documentElement.style) { window.scrollTo({ top: 0, behavior: 'smooth' }); } else { const scrollToTop = () => { const scrollTop = window.pageYOffset || document.documentElement.scrollTop; if (scrollTop > 0) { window.requestAnimationFrame(scrollToTop); window.scrollTo(0, scrollTop - scrollTop / 8); } }; scrollToTop(); } } }