// Main JavaScript for FBS Website document.addEventListener("DOMContentLoaded", function () { // Initialize all functionality initNavigation(); initScrollAnimations(); initSmoothScrolling(); initSlider(); initCustomCursor(); initScrollProgress(); initLoadingScreen(); initTextReveal(); initParallax(); }); // Navigation functionality - Updated to match current implementation function initNavigation() { const menuToggle = document.getElementById("menuToggle"); const navMenu = document.getElementById("navMenu"); const menuGrid = document.getElementById("menuGrid"); const navLinks = document.querySelectorAll(".nav-link"); // Only initialize if elements exist if (menuToggle && navMenu && menuGrid) { console.log("Navigation elements found:", { menuToggle, navMenu, menuGrid, }); let isMenuOpen = false; const menuPetal = document.getElementById("menuPetal"); console.log("menuPetal element:", menuPetal); const menuWrap = document.getElementById("menuWrap"); // Force a known initial state: closed menu shows closed petal if (menuWrap) menuWrap.classList.remove("open"); try { if (menuGrid) menuGrid.style.opacity = "1"; if (menuPetal) menuPetal.style.opacity = "0"; } catch (e) {} menuToggle.addEventListener("click", () => { console.log("Menu clicked! Current state:", isMenuOpen); console.log("menuPetal element:", menuPetal); console.log("navMenu element:", navMenu); if (isMenuOpen) { // Close menu console.log("Closing menu..."); navMenu.classList.add("hidden"); // Show closed petal, hide open petal if (menuPetal) { menuGrid.style.opacity = "1"; menuPetal.style.opacity = "0"; console.log("Showing closed petal, hiding open petal"); } isMenuOpen = false; } else { // Open menu console.log("Opening menu..."); navMenu.classList.remove("hidden"); // Hide closed petal, show open petal if (menuPetal) { menuGrid.style.opacity = "0"; menuPetal.style.opacity = "1"; console.log("Hiding closed petal, showing open petal"); } isMenuOpen = true; } }); // Close menu when clicking outside document.addEventListener("click", (e) => { if (!menuToggle.contains(e.target) && !navMenu.contains(e.target)) { navMenu.classList.add("hidden"); // Show closed petal, hide open petal if (menuPetal) { menuGrid.style.opacity = "1"; menuPetal.style.opacity = "0"; } isMenuOpen = false; } }); // Close navigation when clicking on a link navLinks.forEach((link) => { link.addEventListener("click", function () { navMenu.classList.add("hidden"); // Show closed petal, hide open petal if (menuPetal) { menuGrid.style.opacity = "1"; menuPetal.style.opacity = "0"; } isMenuOpen = false; }); }); // Close navigation with Escape key document.addEventListener("keydown", function (e) { if (e.key === "Escape" && !navMenu.classList.contains("hidden")) { navMenu.classList.add("hidden"); // Show closed petal, hide open petal if (menuPetal) { menuGrid.style.opacity = "1"; menuPetal.style.opacity = "0"; } isMenuOpen = false; } }); } } // Scroll-triggered animations function initScrollAnimations() { const observerOptions = { threshold: 0.1, rootMargin: "0px 0px -50px 0px", }; const observer = new IntersectionObserver(function (entries) { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add("animated"); } }); }, observerOptions); // Observe all elements with animation classes const animatedElements = document.querySelectorAll( ".animate-on-scroll, .animate-on-scroll-left, .animate-on-scroll-right, .animate-on-scroll-scale" ); animatedElements.forEach((el) => { observer.observe(el); }); } // Smooth scrolling for anchor links function initSmoothScrolling() { const links = document.querySelectorAll('a[href^="#"]'); links.forEach((link) => { link.addEventListener("click", function (e) { e.preventDefault(); const targetId = this.getAttribute("href"); const targetElement = document.querySelector(targetId); if (targetElement) { const offsetTop = targetElement.offsetTop; window.scrollTo({ top: offsetTop, behavior: "smooth", }); } }); }); } // Global scroll to section function function scrollToSection(sectionId) { const section = document.getElementById(sectionId); if (section) { section.scrollIntoView({ behavior: "smooth", block: "start", }); } } // Slider functionality function initSlider() { const sliderDots = document.querySelectorAll(".slider-dot"); let currentSlide = 0; sliderDots.forEach((dot, index) => { dot.addEventListener("click", function () { // Remove active class from all dots sliderDots.forEach((d) => d.classList.remove("active")); // Add active class to clicked dot this.classList.add("active"); // Update current slide currentSlide = index; // Here you would typically change the background image // For now, we'll just add a visual effect const heroImage = document.querySelector(".hero-image"); heroImage.style.transform = `scale(1.05)`; setTimeout(() => { heroImage.style.transform = "scale(1)"; }, 300); }); }); // Auto-slide functionality (optional) setInterval(() => { currentSlide = (currentSlide + 1) % sliderDots.length; sliderDots.forEach((dot, index) => { dot.classList.toggle("active", index === currentSlide); }); }, 5000); } // Custom cursor function initCustomCursor() { // Only enable on desktop if (window.innerWidth <= 768) return; const cursor = document.createElement("div"); cursor.className = "custom-cursor"; document.body.appendChild(cursor); document.addEventListener("mousemove", function (e) { cursor.style.left = e.clientX + "px"; cursor.style.top = e.clientY + "px"; }); // Add hover effect for interactive elements const interactiveElements = document.querySelectorAll( "a, button, .cta-button, .service-card" ); interactiveElements.forEach((el) => { el.addEventListener("mouseenter", function () { cursor.classList.add("hover"); }); el.addEventListener("mouseleave", function () { cursor.classList.remove("hover"); }); }); } // Scroll progress indicator function initScrollProgress() { const progressBar = document.createElement("div"); progressBar.className = "scroll-progress"; document.body.appendChild(progressBar); window.addEventListener("scroll", function () { const scrollTop = window.pageYOffset; const docHeight = document.body.scrollHeight - window.innerHeight; const scrollPercent = (scrollTop / docHeight) * 100; progressBar.style.width = scrollPercent + "%"; }); } // Loading screen function initLoadingScreen() { const loading = document.createElement("div"); loading.className = "loading"; loading.innerHTML = '
'; document.body.appendChild(loading); // Hide loading screen after page loads window.addEventListener("load", function () { setTimeout(() => { loading.classList.add("hidden"); setTimeout(() => { loading.remove(); }, 500); }, 1000); }); } // Text reveal animations function initTextReveal() { const textElements = document.querySelectorAll( ".main-headline, .section-title" ); textElements.forEach((element) => { const text = element.textContent; element.innerHTML = ""; element.classList.add("text-reveal"); text.split("").forEach((char) => { const span = document.createElement("span"); span.textContent = char === " " ? "\u00A0" : char; element.appendChild(span); }); }); // Trigger text reveal on scroll const textObserver = new IntersectionObserver( function (entries) { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add("revealed"); } }); }, { threshold: 0.5 } ); document.querySelectorAll(".text-reveal").forEach((el) => { textObserver.observe(el); }); } // Parallax effects function initParallax() { const parallaxElements = document.querySelectorAll( ".hero-image, .vertical-line" ); window.addEventListener("scroll", function () { const scrolled = window.pageYOffset; parallaxElements.forEach((element) => { const speed = element.dataset.speed || 0.5; const yPos = -(scrolled * speed); element.style.transform = `translateY(${yPos}px)`; }); }); } // Utility functions function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // Handle window resize window.addEventListener( "resize", debounce(function () { // Reinitialize cursor on resize const cursor = document.querySelector(".custom-cursor"); if (cursor && window.innerWidth <= 768) { cursor.remove(); } else if (!cursor && window.innerWidth > 768) { initCustomCursor(); } }, 250) ); // Add ripple effect to buttons document.addEventListener("click", function (e) { if ( e.target.classList.contains("cta-button") || e.target.closest(".cta-button") ) { const button = e.target.classList.contains("cta-button") ? e.target : e.target.closest(".cta-button"); button.classList.add("ripple"); setTimeout(() => { button.classList.remove("ripple"); }, 600); } }); // Form handling (for contact forms) function handleFormSubmit(form) { const formData = new FormData(form); const submitButton = form.querySelector('button[type="submit"]'); const originalText = submitButton.textContent; // Show loading state submitButton.textContent = "Sending..."; submitButton.disabled = true; // Simulate form submission (replace with actual endpoint) setTimeout(() => { submitButton.textContent = "Sent!"; submitButton.style.backgroundColor = "#B03037"; // kh3-red color setTimeout(() => { submitButton.textContent = originalText; submitButton.disabled = false; submitButton.style.backgroundColor = ""; form.reset(); }, 2000); }, 1500); } // Initialize form handlers document.addEventListener("DOMContentLoaded", function () { const forms = document.querySelectorAll("form"); forms.forEach((form) => { form.addEventListener("submit", function (e) { e.preventDefault(); handleFormSubmit(this); }); }); }); // Add some interactive effects to service cards document.addEventListener("DOMContentLoaded", function () { const serviceCards = document.querySelectorAll(".service-card"); serviceCards.forEach((card) => { card.addEventListener("mouseenter", function () { this.style.transform = "translateY(-10px) scale(1.02)"; }); card.addEventListener("mouseleave", function () { this.style.transform = "translateY(0) scale(1)"; }); }); }); // Keyboard navigation support document.addEventListener("keydown", function (e) { // Tab navigation for accessibility if (e.key === "Tab") { document.body.classList.add("keyboard-navigation"); } }); document.addEventListener("mousedown", function () { document.body.classList.remove("keyboard-navigation"); }); // Performance optimization: Lazy load images function initLazyLoading() { const images = document.querySelectorAll("img[data-src]"); const imageObserver = new IntersectionObserver(function (entries) { entries.forEach((entry) => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; img.classList.remove("lazy"); imageObserver.unobserve(img); } }); }); images.forEach((img) => imageObserver.observe(img)); } // Initialize lazy loading document.addEventListener("DOMContentLoaded", initLazyLoading);