Files
2026-08-24 20:12:26 +02:00

190 lines
6.5 KiB
JavaScript

/* =========================================================
Apex Turf — Landing Page Interactions
========================================================= */
(function () {
"use strict";
var prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
/* ---------- Sticky header ---------- */
var header = document.getElementById("siteHeader");
function onScroll() {
if (window.scrollY > 40) {
header.classList.add("is-scrolled");
} else {
header.classList.remove("is-scrolled");
}
toggleBackToTop();
}
window.addEventListener("scroll", onScroll, { passive: true });
onScroll();
/* ---------- Mobile nav toggle ---------- */
var navToggle = document.getElementById("navToggle");
var mainNav = document.getElementById("mainNav");
navToggle.addEventListener("click", function () {
var isOpen = document.body.classList.toggle("nav-open");
navToggle.setAttribute("aria-expanded", isOpen ? "true" : "false");
});
mainNav.querySelectorAll("a").forEach(function (link) {
link.addEventListener("click", function () {
document.body.classList.remove("nav-open");
navToggle.setAttribute("aria-expanded", "false");
});
});
/* ---------- Active nav link on scroll ---------- */
var navLinks = Array.prototype.slice.call(mainNav.querySelectorAll("a"));
var sections = navLinks
.map(function (link) {
var id = link.getAttribute("href");
return id && id.charAt(0) === "#" ? document.querySelector(id) : null;
})
.filter(Boolean);
if ("IntersectionObserver" in window && sections.length) {
var navObserver = new IntersectionObserver(
function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
var id = "#" + entry.target.id;
navLinks.forEach(function (link) {
link.classList.toggle("is-active", link.getAttribute("href") === id);
});
}
});
},
{ rootMargin: "-45% 0px -50% 0px", threshold: 0 }
);
sections.forEach(function (section) { navObserver.observe(section); });
}
/* ---------- Scroll reveal (with fallbacks so content never stays stuck hidden) ---------- */
var revealEls = document.querySelectorAll(".reveal");
function revealAll() {
revealEls.forEach(function (el) { el.classList.add("is-visible"); });
}
try {
if ("IntersectionObserver" in window && !prefersReducedMotion) {
var revealObserver = new IntersectionObserver(
function (entries, obs) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
entry.target.classList.add("is-visible");
obs.unobserve(entry.target);
}
});
},
{ threshold: 0.15 }
);
revealEls.forEach(function (el) { revealObserver.observe(el); });
// Safety net: if the observer never fires (paint quirks, fragment-jump
// navigation, etc.) don't leave content permanently invisible.
setTimeout(revealAll, 2500);
} else {
revealAll();
}
} catch (err) {
revealAll();
}
/* ---------- Hero right-pane tabs (Pádel / Football / Golf) ---------- */
var tabButtons = document.querySelectorAll("#heroTabs button");
var scenes = document.querySelectorAll(".right-scene");
var sceneOrder = ["padel", "football", "golf"];
var currentIndex = 0;
var rotateTimer = null;
var rightPane = document.querySelector(".pane-right");
function showScene(name) {
tabButtons.forEach(function (btn) {
var active = btn.getAttribute("data-scene") === name;
btn.classList.toggle("is-active", active);
btn.setAttribute("aria-selected", active ? "true" : "false");
});
scenes.forEach(function (scene) {
scene.classList.toggle("is-active", scene.getAttribute("data-scene") === name);
});
currentIndex = sceneOrder.indexOf(name);
}
function nextScene() {
currentIndex = (currentIndex + 1) % sceneOrder.length;
showScene(sceneOrder[currentIndex]);
}
function startRotation() {
stopRotation();
if (!prefersReducedMotion) {
rotateTimer = setInterval(nextScene, 6000);
}
}
function stopRotation() {
if (rotateTimer) { clearInterval(rotateTimer); rotateTimer = null; }
}
tabButtons.forEach(function (btn) {
btn.addEventListener("click", function () {
showScene(btn.getAttribute("data-scene"));
startRotation();
});
});
if (rightPane) {
rightPane.addEventListener("mouseenter", stopRotation);
rightPane.addEventListener("mouseleave", startRotation);
rightPane.addEventListener("focusin", stopRotation);
rightPane.addEventListener("focusout", startRotation);
}
startRotation();
/* ---------- Smooth scroll with header offset ---------- */
var headerOffset = function () {
return header.offsetHeight + 12;
};
document.querySelectorAll('a[href^="#"]').forEach(function (link) {
link.addEventListener("click", function (e) {
var targetId = link.getAttribute("href");
if (targetId.length < 2) return;
var target = document.querySelector(targetId);
if (!target) return;
e.preventDefault();
var top = target.getBoundingClientRect().top + window.pageYOffset - headerOffset();
window.scrollTo({ top: top, behavior: prefersReducedMotion ? "auto" : "smooth" });
history.pushState(null, "", targetId);
});
});
/* ---------- Quote form (front-end only) ---------- */
var form = document.getElementById("quoteForm");
var successBox = document.getElementById("formSuccess");
if (form) {
form.addEventListener("submit", function (e) {
e.preventDefault();
if (!form.checkValidity()) {
form.reportValidity();
return;
}
successBox.classList.add("show");
form.reset();
successBox.scrollIntoView({ behavior: prefersReducedMotion ? "auto" : "smooth", block: "center" });
setTimeout(function () { successBox.classList.remove("show"); }, 8000);
});
}
/* ---------- Back to top ---------- */
var backToTop = document.getElementById("backToTop");
function toggleBackToTop() {
if (!backToTop) return;
backToTop.classList.toggle("show", window.scrollY > 700);
}
backToTop.addEventListener("click", function () {
window.scrollTo({ top: 0, behavior: prefersReducedMotion ? "auto" : "smooth" });
});
/* ---------- Footer year ---------- */
var yearEl = document.getElementById("year");
if (yearEl) { yearEl.textContent = new Date().getFullYear(); }
})();