/** * Main JavaScript * Handles modals, navigation, scroll behavior, guest selector, and general interactions */ document.addEventListener('DOMContentLoaded', function() { initSectionNav(); initModals(); initGuestSelector(); initMobileBookingBar(); initSmoothScroll(); initReadMore(); }); /* ---- Section Navigation (sticky sub-nav) ---- */ function initSectionNav() { const sectionNav = document.querySelector('.section-nav'); const gallery = document.querySelector('.photo-gallery'); if (!sectionNav || !gallery) return; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (!entry.isIntersecting) { sectionNav.classList.add('visible'); } else { sectionNav.classList.remove('visible'); } }); }, { threshold: 0, rootMargin: '-80px 0px 0px 0px' }); observer.observe(gallery); // Active section tracking const sections = document.querySelectorAll('[data-section]'); const navLinks = sectionNav.querySelectorAll('a'); const sectionObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const sectionId = entry.target.dataset.section; navLinks.forEach(link => { link.classList.toggle('active', link.getAttribute('href') === `#${sectionId}`); }); } }); }, { threshold: 0.3, rootMargin: '-100px 0px -50% 0px' }); sections.forEach(section => sectionObserver.observe(section)); } /* ---- Smooth Scroll ---- */ function initSmoothScroll() { document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function(e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { const offset = 100; // Account for sticky header const top = target.getBoundingClientRect().top + window.pageYOffset - offset; window.scrollTo({ top, behavior: 'smooth' }); } }); }); } /* ---- Modals ---- */ function initModals() { // Description modal const readMoreBtn = document.querySelector('.read-more-btn'); const descriptionModal = document.getElementById('description-modal'); if (readMoreBtn && descriptionModal) { readMoreBtn.addEventListener('click', () => openModal(descriptionModal)); } // Amenities modal const amenitiesBtn = document.querySelector('.show-amenities-btn'); const amenitiesModal = document.getElementById('amenities-modal'); if (amenitiesBtn && amenitiesModal) { amenitiesBtn.addEventListener('click', () => openModal(amenitiesModal)); } // Close buttons document.querySelectorAll('.modal-close').forEach(btn => { btn.addEventListener('click', () => { const modal = btn.closest('.modal-overlay'); if (modal) closeModal(modal); }); }); // Click outside to close document.querySelectorAll('.modal-overlay').forEach(modal => { modal.addEventListener('click', (e) => { if (e.target === modal) closeModal(modal); }); }); // Escape key to close document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { const activeModal = document.querySelector('.modal-overlay.active'); if (activeModal) closeModal(activeModal); } }); } function openModal(modal) { modal.classList.add('active'); document.body.style.overflow = 'hidden'; } function closeModal(modal) { modal.classList.remove('active'); // Only restore scroll if no other modals are open if (!document.querySelector('.modal-overlay.active') && !document.querySelector('.lightbox-overlay.active')) { document.body.style.overflow = ''; } } /* ---- Read More (Description) ---- */ function initReadMore() { const truncated = document.querySelector('.description-text .truncated'); const readMoreBtn = document.querySelector('.read-more-btn'); if (!truncated || !readMoreBtn) return; // Check if text is actually truncated if (truncated.scrollHeight <= truncated.clientHeight) { readMoreBtn.style.display = 'none'; } } /* ---- Guest Selector ---- */ function initGuestSelector() { const guestBtn = document.querySelector('.booking-guests'); const dropdown = document.querySelector('.guest-dropdown'); if (!guestBtn || !dropdown) return; let guests = { adults: 1, children: 0, infants: 0 }; guestBtn.addEventListener('click', (e) => { e.stopPropagation(); dropdown.classList.toggle('active'); }); // Close dropdown when clicking outside document.addEventListener('click', (e) => { if (!dropdown.contains(e.target) && !guestBtn.contains(e.target)) { dropdown.classList.remove('active'); } }); // Counter buttons dropdown.querySelectorAll('.guest-counter button').forEach(btn => { btn.addEventListener('click', (e) => { e.stopPropagation(); const type = btn.dataset.type; const action = btn.dataset.action; if (action === 'increment') { guests[type]++; } else if (action === 'decrement' && guests[type] > 0) { if (type === 'adults' && guests[type] <= 1) return; guests[type]--; } updateGuestDisplay(guests); }); }); function updateGuestDisplay(guests) { const total = guests.adults + guests.children; const guestText = document.querySelector('.guest-count'); if (guestText) { let text = `${total} voyageur${total > 1 ? 's' : ''}`; if (guests.infants > 0) { text += `, ${guests.infants} bébé${guests.infants > 1 ? 's' : ''}`; } guestText.textContent = text; } // Update counter displays dropdown.querySelectorAll('.guest-counter').forEach(counter => { const type = counter.dataset.guestType; const display = counter.querySelector('span'); const decrementBtn = counter.querySelector('[data-action="decrement"]'); if (display) display.textContent = guests[type]; if (decrementBtn) { const min = type === 'adults' ? 1 : 0; decrementBtn.disabled = guests[type] <= min; } }); } } /* ---- Mobile Booking Bar ---- */ function initMobileBookingBar() { const mobileBar = document.querySelector('.mobile-booking-bar'); if (!mobileBar) return; const ctaBtn = mobileBar.querySelector('.booking-cta'); if (ctaBtn) { ctaBtn.addEventListener('click', () => { const calendarSection = document.querySelector('.calendar-section'); if (calendarSection) { calendarSection.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); } } /* ---- Booking Widget Date Click ---- */ document.addEventListener('DOMContentLoaded', function() { const arrivalField = document.querySelector('.booking-date-field:first-child'); const departureField = document.querySelector('.booking-date-field:last-child'); if (arrivalField) { arrivalField.addEventListener('click', () => { const calendarSection = document.querySelector('.calendar-section'); if (calendarSection) { calendarSection.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); } if (departureField) { departureField.addEventListener('click', () => { const calendarSection = document.querySelector('.calendar-section'); if (calendarSection) { calendarSection.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); } });