document.addEventListener('DOMContentLoaded', function() { // --- Mobile menu functionality --- const mobileMenuBtn = document.getElementById('mobile-menu-btn'); const mobileMenu = document.getElementById('mobile-menu'); if (mobileMenuBtn && mobileMenu) { mobileMenuBtn.addEventListener('click', function() { mobileMenu.classList.toggle('hidden'); // Update icon const icon = mobileMenuBtn.querySelector('i'); if (mobileMenu.classList.contains('hidden')) { icon.classList.remove('fa-times'); icon.classList.add('fa-bars'); } else { icon.classList.remove('fa-bars'); icon.classList.add('fa-times'); } }); } // Close mobile menu when clicking on a link const mobileMenuLinks = mobileMenu?.querySelectorAll('a'); mobileMenuLinks?.forEach(link => { link.addEventListener('click', function() { mobileMenu.classList.add('hidden'); const icon = mobileMenuBtn.querySelector('i'); icon.classList.remove('fa-times'); icon.classList.add('fa-bars'); }); }); // Close mobile menu when clicking outside document.addEventListener('click', function(event) { if (mobileMenu && !mobileMenu.contains(event.target) && !mobileMenuBtn.contains(event.target)) { mobileMenu.classList.add('hidden'); const icon = mobileMenuBtn.querySelector('i'); icon.classList.remove('fa-times'); icon.classList.add('fa-bars'); } }); // --- Smooth scrolling for anchor links --- document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function(e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); // --- Add scroll to top button if needed --- document.addEventListener('scroll', function() { const scrollBtn = document.getElementById('scroll-to-top'); if (scrollBtn) { if (window.scrollY > 300) { scrollBtn.classList.remove('hidden'); } else { scrollBtn.classList.add('hidden'); } } }); // --- Intersection Observer for animations --- const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('animate-fade-in'); } }); }, observerOptions); const animateElements = document.querySelectorAll('.animate-on-scroll'); animateElements.forEach(element => { observer.observe(element); }); // --- Handle CTA button clicks --- const ctaButtons = document.querySelectorAll('button'); ctaButtons.forEach(button => { // Skip the contact form submit button if (button.type === 'submit' && button.closest('#contact-form')) { return; } if (button.textContent.includes('Get Started') || button.textContent.includes('Free Estimate') || button.textContent.includes('Get Quote')) { button.addEventListener('click', function() { showNotification('Thank you for your interest! Please call us at (555) 123-4567 or email info@kellygreen.com to get started.', 'info'); }); } }); // --- Contact Form Handling --- const contactForm = document.getElementById('contact-form'); if (contactForm) { console.log('Contact form found, adding event listener'); // Debug log // Primary form submit handler contactForm.addEventListener('submit', handleContactForm); // Safari backup: also add submit handler with different approach contactForm.onsubmit = function(event) { return handleContactForm(event) === false ? false : false; }; // Also add a click handler to the submit button as backup for Safari const submitButton = contactForm.querySelector('button[type="submit"]'); if (submitButton) { console.log('Submit button found, adding backup click handler'); // Debug log submitButton.addEventListener('click', function(event) { console.log('Submit button clicked'); // Debug log // Safari sometimes needs explicit handling on button click setTimeout(function() { if (validateForm(contactForm)) { event.preventDefault(); handleContactForm(event); } }, 50); }); } } else { console.error('Contact form not found!'); // Debug log } // --- Gallery & Buzz Carousel --- const buzzContent = document.getElementById('buzz-content'); if (buzzContent) { const buzzSlides = Array.from(buzzContent.querySelectorAll('.buzz-slide')); const swiper = new Swiper('.swiper-container', { loop: true, effect: 'coverflow', grabCursor: true, centeredSlides: true, slidesPerView: 'auto', coverflowEffect: { rotate: 0, stretch: 80, depth: 200, modifier: 1, slideShadows: false, }, navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }, on: { slideChange: function () { buzzSlides.forEach((slide, i) => { slide.classList.toggle('hidden', i !== this.realIndex); }); }, }, }); } }); // --- Utility Functions (can be outside DOMContentLoaded) --- // Form validation with specific error messages function validateForm(form) { const fields = [ { id: 'first-name', errorId: 'first-name-error', message: 'First name is required.' }, { id: 'last-name', errorId: 'last-name-error', message: 'Last name is required.' }, { id: 'email', errorId: 'email-error', message: 'Please enter a valid email address.' }, { id: 'phone', errorId: 'phone-error', message: 'Phone number is required.' }, { id: 'message', errorId: 'message-error', message: 'Message is required.' }, { id: 'terms', errorId: 'terms-error', message: 'You must agree to the terms and privacy policy.' } ]; let isValid = true; // Clear all previous errors fields.forEach(field => { const fieldElement = document.getElementById(field.id); const errorElement = document.getElementById(field.errorId); if (fieldElement && errorElement) { fieldElement.classList.remove('border-red-500'); errorElement.classList.add('hidden'); } }); // Validate each field fields.forEach(field => { const fieldElement = document.getElementById(field.id); const errorElement = document.getElementById(field.errorId); if (fieldElement && errorElement) { let fieldIsValid = true; if (field.id === 'email') { // Special validation for email - Safari compatible regex const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; fieldIsValid = fieldElement.value.trim() !== '' && emailPattern.test(fieldElement.value.trim()); } else if (field.id === 'terms') { // Special validation for checkbox fieldIsValid = fieldElement.checked; } else { // Standard validation for text fields fieldIsValid = fieldElement.value.trim() !== ''; } if (!fieldIsValid) { isValid = false; fieldElement.classList.add('border-red-500'); errorElement.classList.remove('hidden'); } } }); return isValid; } // Contact form submission function handleContactForm(event) { // Safari compatibility: ensure preventDefault works if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; // IE fallback } if (event.stopPropagation) { event.stopPropagation(); } console.log('Form submission intercepted'); // Debug log const form = event.target; if (validateForm(form)) { console.log('Form validation passed'); // Debug log // Hide the form and show thank you message form.style.display = 'none'; // Also hide the title and subtitle const contactTitle = form.parentElement.querySelector('h2'); const contactSubtitle = form.parentElement.querySelector('p'); if (contactTitle) contactTitle.style.display = 'none'; if (contactSubtitle) contactSubtitle.style.display = 'none'; const thankYouMessage = document.getElementById('thank-you-message'); if (thankYouMessage) { thankYouMessage.classList.remove('hidden'); // Safari-compatible scrolling setTimeout(function() { if (thankYouMessage.scrollIntoView) { // Check if Safari supports smooth scrolling if ('scrollBehavior' in document.documentElement.style) { thankYouMessage.scrollIntoView({ behavior: 'smooth', block: 'center' }); } else { // Fallback for older Safari versions thankYouMessage.scrollIntoView(true); } } else { // Even older browser fallback window.scrollTo(0, thankYouMessage.offsetTop - 100); } }, 100); console.log('Thank you message shown'); // Debug log } else { console.error('Thank you message element not found'); // Debug log } } else { console.log('Form validation failed'); // Debug log } // Extra Safari protection return false; } // Notification system function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `fixed top-20 right-4 z-50 p-4 rounded-lg shadow-lg max-w-sm transition-all duration-300 transform translate-x-full ${ type === 'success' ? 'bg-green-500 text-white' : type === 'error' ? 'bg-red-500 text-white' : 'bg-blue-500 text-white' }`; notification.textContent = message; document.body.appendChild(notification); setTimeout(() => { notification.classList.remove('translate-x-full'); }, 100); setTimeout(() => { notification.classList.add('translate-x-full'); setTimeout(() => { document.body.removeChild(notification); }, 300); }, 5000); } // Scroll to top functionality function scrollToTop() { window.scrollTo({ top: 0, behavior: 'smooth' }); } // Loading animation for buttons function addLoadingState(button, originalText = 'Loading...') { button.disabled = true; button.innerHTML = `${originalText}`; } function removeLoadingState(button, originalText) { button.disabled = false; button.innerHTML = originalText; } // Utility functions function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; }