Files
landingpage-haus-schleusingen/public/js/haus-schleusingen.js
Claw (KI-Assistent) 3db7dc8971
All checks were successful
Deploy Feature Branch to Test / deploy (push) Successful in 26s
Lint / PHP Syntax Check (push) Successful in 35s
Lint / CSS Lint (stylelint) (push) Successful in 1m15s
Lint / HTML Lint (htmlhint) (push) Successful in 1m11s
Lint / PHP Syntax Check (pull_request) Successful in 39s
Lint / CSS Lint (stylelint) (pull_request) Successful in 1m13s
Lint / HTML Lint (htmlhint) (pull_request) Successful in 1m12s
fix(#58): remove broken getElementById('contactForm') stub
The JS had a dangling document.getElementById('contactForm') call that
did nothing - no event handler attached, no return value used.

Form handling is entirely server-side (PHP POST → redirect to #form-result).
No JS form intervention needed.

Closes #58
2026-05-22 14:14:23 +00:00

227 lines
7.0 KiB
JavaScript
Executable File
Raw Permalink 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.
// Success feedback is shown via #form-result after server redirect.
});
});
// 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();
});
})();