homepage
This commit is contained in:
161
js/main.js
Normal file
161
js/main.js
Normal file
@@ -0,0 +1,161 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var header = document.getElementById('siteHeader');
|
||||
var nav = document.getElementById('primaryNav');
|
||||
var burger = document.getElementById('burger');
|
||||
var navToggle = nav && nav.querySelector('.nav__toggle');
|
||||
var mqDesktop = window.matchMedia('(min-width: 60.0625rem)');
|
||||
|
||||
/* ---------- mobile menu ---------- */
|
||||
function closeMenu() {
|
||||
if (!nav || !burger) return;
|
||||
nav.classList.remove('is-open');
|
||||
burger.setAttribute('aria-expanded', 'false');
|
||||
burger.setAttribute('aria-label', 'Open menu');
|
||||
}
|
||||
|
||||
if (burger && nav) {
|
||||
burger.addEventListener('click', function () {
|
||||
var open = nav.classList.toggle('is-open');
|
||||
burger.setAttribute('aria-expanded', String(open));
|
||||
burger.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
|
||||
});
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
if (mqDesktop.matches) return;
|
||||
if (!nav.contains(e.target) && !burger.contains(e.target)) closeMenu();
|
||||
});
|
||||
|
||||
nav.addEventListener('click', function (e) {
|
||||
if (!mqDesktop.matches && e.target.closest('a')) closeMenu();
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (e.key !== 'Escape') return;
|
||||
closeMenu();
|
||||
if (navToggle) navToggle.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
|
||||
mqDesktop.addEventListener('change', function (e) {
|
||||
if (e.matches) closeMenu();
|
||||
});
|
||||
|
||||
/* ---------- Tours submenu ---------- */
|
||||
if (navToggle) {
|
||||
navToggle.addEventListener('click', function () {
|
||||
var open = navToggle.getAttribute('aria-expanded') === 'true';
|
||||
navToggle.setAttribute('aria-expanded', String(!open));
|
||||
});
|
||||
}
|
||||
|
||||
/* ---------- mobile "Book now" inside the menu ---------- */
|
||||
var desktopCta = document.querySelector('.header__cta');
|
||||
var navList = nav && nav.querySelector('.nav__list');
|
||||
if (desktopCta && navList) {
|
||||
var li = document.createElement('li');
|
||||
li.className = 'nav__mobile-cta';
|
||||
var clone = desktopCta.cloneNode(true);
|
||||
clone.classList.remove('header__cta');
|
||||
clone.classList.add('nav__cta');
|
||||
li.appendChild(clone);
|
||||
navList.appendChild(li);
|
||||
}
|
||||
|
||||
/* ---------- sticky header past the hero ---------- */
|
||||
var hero = document.querySelector('.hero');
|
||||
if (header && hero && 'IntersectionObserver' in window) {
|
||||
var sentinel = document.createElement('div');
|
||||
sentinel.setAttribute('aria-hidden', 'true');
|
||||
sentinel.style.cssText = 'position:absolute;top:0;left:0;width:1px;height:60vh;pointer-events:none';
|
||||
hero.appendChild(sentinel);
|
||||
|
||||
new IntersectionObserver(function (entries) {
|
||||
header.classList.toggle('is-stuck', !entries[0].isIntersecting);
|
||||
}, { threshold: 0 }).observe(sentinel);
|
||||
}
|
||||
|
||||
/* ---------- card rails (prev / next) ---------- */
|
||||
function railStep(rail) {
|
||||
var card = rail.firstElementChild;
|
||||
if (!card) return rail.clientWidth;
|
||||
var gap = parseFloat(getComputedStyle(rail).columnGap) || 0;
|
||||
return card.getBoundingClientRect().width + gap;
|
||||
}
|
||||
|
||||
function syncRailButtons(rail, prev, next) {
|
||||
var max = rail.scrollWidth - rail.clientWidth - 1;
|
||||
if (prev) prev.disabled = rail.scrollLeft <= 0;
|
||||
if (next) next.disabled = rail.scrollLeft >= max;
|
||||
}
|
||||
|
||||
Array.prototype.forEach.call(document.querySelectorAll('.rail'), function (rail) {
|
||||
var prev = document.querySelector('[data-rail-prev="' + rail.id + '"]');
|
||||
var next = document.querySelector('[data-rail-next="' + rail.id + '"]');
|
||||
|
||||
if (prev) prev.addEventListener('click', function () {
|
||||
rail.scrollBy({ left: -railStep(rail), behavior: 'smooth' });
|
||||
});
|
||||
if (next) next.addEventListener('click', function () {
|
||||
rail.scrollBy({ left: railStep(rail), behavior: 'smooth' });
|
||||
});
|
||||
|
||||
rail.addEventListener('scroll', function () {
|
||||
syncRailButtons(rail, prev, next);
|
||||
}, { passive: true });
|
||||
window.addEventListener('resize', function () {
|
||||
syncRailButtons(rail, prev, next);
|
||||
});
|
||||
syncRailButtons(rail, prev, next);
|
||||
});
|
||||
|
||||
/* ---------- testimonials marquee: duplicate for a seamless loop ---------- */
|
||||
var marquee = document.querySelector('[data-marquee] .marquee__track');
|
||||
if (marquee) {
|
||||
var originals = Array.prototype.slice.call(marquee.children);
|
||||
originals.forEach(function (node) {
|
||||
var copy = node.cloneNode(true);
|
||||
copy.setAttribute('aria-hidden', 'true');
|
||||
marquee.appendChild(copy);
|
||||
});
|
||||
}
|
||||
|
||||
/* ---------- FAQ accordion ---------- */
|
||||
var accordion = document.querySelector('[data-accordion]');
|
||||
if (accordion) {
|
||||
accordion.addEventListener('click', function (e) {
|
||||
var btn = e.target.closest('.acc__q');
|
||||
if (!btn) return;
|
||||
var open = btn.getAttribute('aria-expanded') === 'true';
|
||||
Array.prototype.forEach.call(accordion.querySelectorAll('.acc__q'), function (other) {
|
||||
other.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
btn.setAttribute('aria-expanded', String(!open));
|
||||
});
|
||||
}
|
||||
|
||||
/* ---------- date field: text placeholder, native picker on focus ---------- */
|
||||
var dateField = document.querySelector('[data-datefield]');
|
||||
if (dateField) {
|
||||
dateField.addEventListener('focus', function () {
|
||||
dateField.type = 'date';
|
||||
if (typeof dateField.showPicker === 'function') {
|
||||
try { dateField.showPicker(); } catch (err) { /* not user-activated */ }
|
||||
}
|
||||
});
|
||||
dateField.addEventListener('blur', function () {
|
||||
if (!dateField.value) dateField.type = 'text';
|
||||
});
|
||||
}
|
||||
|
||||
/* ---------- booking form ---------- */
|
||||
var form = document.getElementById('booking');
|
||||
if (form) {
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var data = Object.fromEntries(new FormData(form).entries());
|
||||
console.log('Booking request', data);
|
||||
});
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user