Files
landingpage-haus-schleusingen/public/js/haus-schleusingen.js
Claw (KI-Assistent) a170afa7c0
All checks were successful
Lint / PHP Syntax Check (pull_request) Manual approval
Lint / CSS Lint (stylelint) (pull_request) Manual approval
Lint / HTML Lint (htmlhint) (pull_request) Manual approval
Deploy Feature Branch to Test / deploy (push) Manual approval
Lint / PHP Syntax Check (push) Manual approval
Lint / CSS Lint (stylelint) (push) Manual approval
Lint / HTML Lint (htmlhint) (push) Successful in 1m12s
fix: remove mailto handler and fix formSuccess element ID (refs #57, #58)
2026-05-22 13:57:21 +00:00

228 lines
7.1 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

document.addEventListener("DOMContentLoaded", function () {
// Navbar scroll
var navbar = document.getElementById("navbar");
window.addEventListener("scroll", function () {
if (window.scrollY > 60) navbar.classList.add("scrolled");
else navbar.classList.remove("scrolled");
});
// Hero animation on load
setTimeout(function () {
document.getElementById("heroContent").classList.add("visible");
document.getElementById("heroBg").classList.add("loaded");
}, 200);
// Scroll animations via IntersectionObserver
var animElements = document.querySelectorAll(".fact, [data-animate]");
animElements.forEach(function (el) {
el.style.opacity = "0";
el.style.transform = "translateY(30px)";
el.style.transition = "opacity 0.8s ease, transform 0.8s ease";
});
if ("IntersectionObserver" in window) {
var observer = new IntersectionObserver(
function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
entry.target.style.opacity = "1";
entry.target.style.transform = "translateY(0)";
observer.unobserve(entry.target);
}
});
},
{ rootMargin: "0px 0px -60px 0px" }
);
animElements.forEach(function (el) {
observer.observe(el);
});
} else {
// Fallback: show all immediately
animElements.forEach(function (el) {
el.classList.add("visible");
el.style.opacity = "1";
el.style.transform = "translateY(0)";
});
}
// Floor accordion
// Floor accordion (vanilla JS + a11y)
document.querySelectorAll(".floor-header").forEach(function (header) {
header.addEventListener("click", function () {
var item = this.closest(".floor-item");
var isOpen = item.classList.contains("open");
var allItems = document.querySelectorAll(".floor-item");
// Close all
allItems.forEach(function (fi) {
fi.classList.remove("open");
var hdr = fi.querySelector(".floor-header");
if (hdr) hdr.setAttribute("aria-expanded", "false");
var body = fi.querySelector(".floor-body");
if (body) body.style.display = "none";
});
// Open clicked if it was closed
if (!isOpen) {
item.classList.add("open");
this.setAttribute("aria-expanded", "true");
var body = item.querySelector(".floor-body");
if (body) body.style.display = "block";
}
});
});
// Accordion keyboard handler (Enter/Space)
document.querySelectorAll(".floor-header").forEach(function (header) {
header.addEventListener("keydown", function (e) {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
this.click();
}
});
});
// Lightbox track last focused element for focus return
var lightboxTrigger = null;
function openLightbox(src) {
lightboxTrigger = document.activeElement;
var img = document.getElementById("lightboxImg");
// WebP fallback: if .webp fails, try original format
img.onerror = function () {
if (img.getAttribute('src').endsWith('.webp')) {
img.setAttribute('src', src.replace(/\.webp$/, '.png'));
}
};
img.setAttribute("src", src);
img.setAttribute("alt", "");
document.getElementById("lightbox").classList.add("open");
document.body.style.overflow = "hidden";
// Set focus to close button
setTimeout(function () {
document.getElementById("lightboxClose").focus();
}, 50);
}
function closeLightbox() {
document.getElementById("lightbox").classList.remove("open");
document.body.style.overflow = "";
// Return focus to trigger
if (lightboxTrigger) {
lightboxTrigger.focus();
lightboxTrigger = null;
}
}
// Lightbox gallery grid items
document.querySelectorAll(".grid-item").forEach(function (item) {
item.addEventListener("click", function () {
var src = this.dataset.img || this.querySelector("img").getAttribute("src");
openLightbox(src);
});
});
// Gallery keyboard handler (Enter/Space)
document.querySelectorAll(".grid-item").forEach(function (item) {
item.setAttribute("tabindex", "0");
item.addEventListener("keydown", function (e) {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
this.click();
}
});
});
// Lightbox floor plan images in Raumaufteilung
document.querySelectorAll(".floor-plan img[data-img]").forEach(function (img) {
img.addEventListener("click", function () {
openLightbox(this.dataset.img);
});
});
document.getElementById("lightboxClose").addEventListener("click", closeLightbox);
document.getElementById("lightbox").addEventListener("click", function (e) {
if (e.target === this) closeLightbox();
});
document.addEventListener("keydown", function (e) {
if (e.key === "Escape") closeLightbox();
});
// Focus trap for lightbox
document.getElementById("lightbox").addEventListener("keydown", function (e) {
if (e.key !== "Tab") return;
var focusable = this.querySelectorAll("button, [href], input, select, textarea, [tabindex]:not([tabindex='-1'])");
focusable = Array.from(focusable).filter(function (el) { return el.offsetParent !== null; });
if (focusable.length === 0) return;
var first = focusable[0];
var last = focusable[focusable.length - 1];
if (e.shiftKey) {
if (document.activeElement === first) {
e.preventDefault();
last.focus();
}
} else {
if (document.activeElement === last) {
e.preventDefault();
first.focus();
}
}
});
// Form submit is handled server-side by PHP no JS intervention needed.
// Form submit opens email client with pre-filled mailto: link
document.getElementById("contactForm")
});
});
// Mobile hamburger menu (vanilla JS)
(function () {
var hamburger = document.querySelector(".nav-hamburger");
var nav = document.getElementById("navbar");
var overlay = document.querySelector(".nav-mobile-overlay");
var links = nav ? nav.querySelectorAll(".nav-links a") : [];
function toggleMenu() {
var isOpen = hamburger.classList.toggle("active");
nav.classList.toggle("mobile-open", isOpen);
if (overlay) overlay.classList.toggle("active", isOpen);
hamburger.setAttribute("aria-expanded", isOpen);
document.body.style.overflow = isOpen ? "hidden" : "";
}
function closeMenu() {
hamburger.classList.remove("active");
nav.classList.remove("mobile-open");
if (overlay) overlay.classList.remove("active");
hamburger.setAttribute("aria-expanded", "false");
document.body.style.overflow = "";
}
if (hamburger) {
hamburger.addEventListener("click", toggleMenu);
}
if (overlay) {
overlay.addEventListener("click", closeMenu);
}
links.forEach(function (link) {
link.addEventListener("click", closeMenu);
});
document.addEventListener("keydown", function (e) {
if (e.key === "Escape") closeMenu();
});
// Close on resize to desktop
window.addEventListener("resize", function () {
if (window.innerWidth > 900) closeMenu();
});
})();