Website-Entwurf für HEB Bauelemente (normtor.de)

Akquise-Demo mit Startseite (Tor-Intro, 24-h-Renovierung mit Uhr,
Über uns, Fachbetrieb statt Discount), Galerie mit Filter und
Großansicht, Kontaktseite mit Anfrageformular sowie Impressum- und
Datenschutz-Entwürfen. Statisches HTML/CSS/JS, Seiten und Bilder
werden über tools/ erzeugt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
NotPika69andClaude Opus 5.5 committed 2026-10-04 22:52:10 +02:00
commit bec24e5bbc
148 files changed
+2261

No files matched your search

+215
View File
@@ -0,0 +1,215 @@
/* HEB Bauelemente: Intro-Tor, Navigation, Einblendungen, 24-h-Uhr, Galerie, Formular. Ohne Bibliotheken. */
(function () {
"use strict";
var root = document.documentElement;
root.classList.add("ready");
var reduced = matchMedia("(prefers-reduced-motion: reduce)").matches;
/* ---------- Intro: Sektionaltor fährt hoch (einmal pro Sitzung) ---------- */
var gate = document.querySelector(".gate");
if (gate && root.classList.contains("has-intro")) {
try { sessionStorage.setItem("heb-intro", "1"); } catch (e) {}
var started = false;
var open = function () {
if (started) return;
started = true;
gate.classList.add("is-moving");
requestAnimationFrame(function () {
gate.classList.add("is-open");
root.classList.add("intro-go");
});
};
gate.addEventListener("transitionend", function (e) {
if (e.target === gate && e.propertyName === "transform") gate.remove();
});
gate.addEventListener("click", open);
var img = document.querySelector(".hero__img img");
setTimeout(function () {
if (!img || img.complete) return open();
img.addEventListener("load", open);
setTimeout(open, 1200);
}, 650);
} else if (gate) {
gate.remove();
}
/* ---------- Header ---------- */
var header = document.querySelector(".site-header");
var onScroll = function () { header.classList.toggle("is-scrolled", scrollY > 8); };
addEventListener("scroll", onScroll, { passive: true });
onScroll();
var menuBtn = document.querySelector(".menu-btn");
var mobileNav = document.getElementById("mobile-nav");
if (menuBtn && mobileNav) {
var setMenu = function (open) {
menuBtn.setAttribute("aria-expanded", String(open));
menuBtn.setAttribute("aria-label", open ? "Menü schließen" : "Menü öffnen");
mobileNav.hidden = !open;
};
menuBtn.addEventListener("click", function () { setMenu(mobileNav.hidden); });
mobileNav.addEventListener("click", function (e) { if (e.target.closest("a")) setMenu(false); });
addEventListener("keydown", function (e) { if (e.key === "Escape" && !mobileNav.hidden) { setMenu(false); menuBtn.focus(); } });
}
document.querySelectorAll("[data-year]").forEach(function (el) { el.textContent = new Date().getFullYear(); });
/* ---------- Einblendungen ---------- */
var reveals = document.querySelectorAll(".reveal");
if ("IntersectionObserver" in window && !reduced) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) { en.target.classList.add("is-in"); io.unobserve(en.target); }
});
}, { threshold: 0.12, rootMargin: "0px 0px -40px 0px" });
reveals.forEach(function (el) { io.observe(el); });
} else {
reveals.forEach(function (el) { el.classList.add("is-in"); });
}
/* ---------- 24-h-Uhr: füllt sich mit den Arbeitsschritten ---------- */
var steps = Array.prototype.slice.call(document.querySelectorAll(".step[data-hours]"));
var bar = document.querySelector(".clock__bar");
var num = document.querySelector("[data-clock]");
if (steps.length && bar && num) {
var shown = 0, target = 0, tween = null;
var animateTo = function (h) {
target = h;
bar.style.strokeDashoffset = String(100 - (h / 24) * 100);
if (reduced) { shown = h; num.textContent = h; return; }
if (tween) return;
tween = setInterval(function () {
if (shown === target) { clearInterval(tween); tween = null; return; }
shown += shown < target ? 1 : -1;
num.textContent = shown;
}, 45);
};
var ticking = false;
var update = function () {
ticking = false;
var line = innerHeight * 0.6, active = -1;
steps.forEach(function (s, i) { if (s.getBoundingClientRect().top < line) active = i; });
steps.forEach(function (s, i) {
s.classList.toggle("is-active", i === active);
s.classList.toggle("is-done", i < active);
});
var h = active < 0 ? 0 : +steps[active].dataset.hours;
if (h !== target) animateTo(h);
};
addEventListener("scroll", function () { if (!ticking) { ticking = true; requestAnimationFrame(update); } }, { passive: true });
update();
}
/* ---------- Galerie: Filter ---------- */
var chips = document.querySelectorAll(".chip[data-filter]");
var items = Array.prototype.slice.call(document.querySelectorAll(".gallery__item"));
var count = document.querySelector("[data-count]");
chips.forEach(function (chip) {
chip.addEventListener("click", function () {
var f = chip.dataset.filter, n = 0;
chips.forEach(function (c) { c.setAttribute("aria-pressed", String(c === chip)); });
items.forEach(function (it) {
var show = f === "alle" || it.dataset.tags.split(" ").indexOf(f) > -1;
it.hidden = !show;
if (show) n++;
});
if (count) count.textContent = n;
});
});
if (location.hash && items.length) {
var hit = document.getElementById(location.hash.slice(1));
if (hit && hit.classList.contains("gallery__item")) hit.classList.add("is-target");
}
/* ---------- Galerie: Großansicht ---------- */
var box = document.querySelector(".lightbox");
if (box && typeof box.showModal === "function") {
var bImg = box.querySelector("img"), bTitle = box.querySelector("figcaption b"), bSub = box.querySelector("figcaption span");
var list = [], idx = 0, opener = null;
var show = function (i) {
idx = (i + list.length) % list.length;
var b = list[idx];
bImg.src = b.dataset.full;
bImg.alt = b.dataset.title + ", " + b.dataset.sub;
bTitle.textContent = b.dataset.title;
bSub.textContent = b.dataset.sub;
};
document.querySelectorAll(".gallery__btn").forEach(function (btn) {
btn.addEventListener("click", function () {
list = items.filter(function (it) { return !it.hidden; }).map(function (it) { return it.querySelector(".gallery__btn"); });
opener = btn;
show(list.indexOf(btn));
box.showModal();
});
});
box.querySelector(".lightbox__close").addEventListener("click", function () { box.close(); });
box.querySelector(".lightbox__prev").addEventListener("click", function () { show(idx - 1); });
box.querySelector(".lightbox__next").addEventListener("click", function () { show(idx + 1); });
box.addEventListener("click", function (e) { if (e.target === box) box.close(); });
box.addEventListener("close", function () { if (opener) opener.focus(); });
box.addEventListener("keydown", function (e) {
if (e.key === "ArrowLeft") show(idx - 1);
if (e.key === "ArrowRight") show(idx + 1);
});
var x0 = null;
box.addEventListener("touchstart", function (e) { x0 = e.touches[0].clientX; }, { passive: true });
box.addEventListener("touchend", function (e) {
if (x0 === null) return;
var dx = e.changedTouches[0].clientX - x0;
if (Math.abs(dx) > 50) show(idx + (dx < 0 ? 1 : -1));
x0 = null;
});
}
/* ---------- Anfrageformular ---------- */
var form = document.getElementById("anfrage");
if (form) {
var pre = new URLSearchParams(location.search).get("anliegen");
var preInput = pre && form.querySelector('input[name="anliegen"][value="' + pre.replace(/[^a-z]/g, "") + '"]');
if (preInput) preInput.checked = true;
var setError = function (input, msg) {
var wrap = input.closest(".field, .check");
var old = wrap.querySelector(".field__error");
if (old) old.remove();
wrap.classList.toggle("is-invalid", !!msg);
input.setAttribute("aria-invalid", msg ? "true" : "false");
if (msg && wrap.classList.contains("field")) {
var err = document.createElement("span");
err.className = "field__error";
err.id = "err-" + input.name;
err.textContent = msg;
wrap.appendChild(err);
input.setAttribute("aria-describedby", err.id);
} else {
input.removeAttribute("aria-describedby");
}
};
var check = function (input) {
var v = input.type === "checkbox" ? input.checked : input.value.trim();
var msg = "";
if (input.required && !v) msg = input.type === "checkbox" ? "Bitte bestätigen." : "Bitte ausfüllen.";
else if (input.name === "telefon" && v && v.replace(/\D/g, "").length < 6) msg = "Bitte eine gültige Telefonnummer angeben.";
else if (input.type === "email" && v && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(v)) msg = "Bitte eine gültige E-Mail-Adresse angeben.";
setError(input, msg);
return !msg;
};
var fields = form.querySelectorAll("input[required], input[type=email]");
fields.forEach(function (f) {
f.addEventListener(f.type === "checkbox" ? "change" : "blur", function () { check(f); });
});
form.addEventListener("submit", function (e) {
e.preventDefault();
var firstBad = null;
fields.forEach(function (f) { if (!check(f) && !firstBad) firstBad = f; });
if (firstBad) { firstBad.focus(); return; }
var done = form.querySelector(".form__done");
if (form.querySelector(".form__demo")) {
done.querySelector("[data-done-text]").textContent = "Im Entwurf wird nichts verschickt. Nach dem Launch landet die Anfrage direkt bei Wolfgang Haas.";
}
form.querySelector("button[type=submit]").hidden = true;
done.hidden = false;
done.focus();
});
}
})();