199 lines
6.4 KiB
JavaScript
199 lines
6.4 KiB
JavaScript
// Dennis: Kontaktseite – Scroll-Reveal und Formular-Logik.
|
||
|
||
// ----- Scroll-Reveal -----
|
||
(function () {
|
||
const elements = document.querySelectorAll(".kontakt-seite .reveal");
|
||
if (!elements.length) return;
|
||
|
||
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||
|
||
if (reduceMotion || !("IntersectionObserver" in window)) {
|
||
elements.forEach(function (el) {
|
||
el.classList.add("visible");
|
||
});
|
||
return;
|
||
}
|
||
|
||
const observer = new IntersectionObserver(
|
||
function (entries) {
|
||
entries.forEach(function (entry) {
|
||
if (entry.isIntersecting) {
|
||
entry.target.classList.add("visible");
|
||
observer.unobserve(entry.target);
|
||
}
|
||
});
|
||
},
|
||
{ threshold: 0.12, rootMargin: "0px 0px -40px 0px" }
|
||
);
|
||
|
||
elements.forEach(function (el) {
|
||
observer.observe(el);
|
||
});
|
||
})();
|
||
|
||
// ----- Kontaktformular -----
|
||
(function () {
|
||
const form = document.getElementById("kontakt-formular");
|
||
if (!form) return;
|
||
|
||
const MIN_MESSAGE = 10;
|
||
const EMAIL_TARGET = "info@trihub.de";
|
||
|
||
const fields = {
|
||
name: form.querySelector("[name='name']"),
|
||
email: form.querySelector("[name='email']"),
|
||
phone: form.querySelector("[name='phone']"),
|
||
type: form.querySelector("[name='anfragetyp']"),
|
||
subject: form.querySelector("[name='betreff']"),
|
||
message: form.querySelector("[name='nachricht']")
|
||
};
|
||
|
||
const statusEl = document.getElementById("form-status");
|
||
|
||
function wrap(el) {
|
||
return el.closest(".field");
|
||
}
|
||
|
||
function setFieldState(el, state) {
|
||
const box = wrap(el);
|
||
if (!box) return;
|
||
box.classList.remove("has-error", "is-ok");
|
||
el.classList.remove("invalid", "valid");
|
||
if (state === "error") {
|
||
box.classList.add("has-error");
|
||
el.classList.add("invalid");
|
||
} else if (state === "ok") {
|
||
box.classList.add("is-ok");
|
||
el.classList.add("valid");
|
||
}
|
||
}
|
||
|
||
function validateName() {
|
||
const ok = fields.name.value.trim().length > 0;
|
||
setFieldState(fields.name, ok ? null : "error");
|
||
return ok;
|
||
}
|
||
|
||
function validateEmail() {
|
||
const value = fields.email.value.trim();
|
||
const ok = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(value);
|
||
setFieldState(fields.email, ok ? null : "error");
|
||
return ok;
|
||
}
|
||
|
||
function validateType() {
|
||
const ok = fields.type.value !== "";
|
||
setFieldState(fields.type, ok ? null : "error");
|
||
return ok;
|
||
}
|
||
|
||
function validateSubject() {
|
||
const ok = fields.subject.value.trim().length > 0;
|
||
setFieldState(fields.subject, ok ? null : "error");
|
||
return ok;
|
||
}
|
||
|
||
function validateMessage() {
|
||
const len = fields.message.value.trim().length;
|
||
if (len === 0) {
|
||
setFieldState(fields.message, "error");
|
||
return false;
|
||
}
|
||
if (len >= MIN_MESSAGE) {
|
||
setFieldState(fields.message, "ok");
|
||
return true;
|
||
}
|
||
// Zu kurz: erst bei Submit als Fehler markieren, live nur grün bei erfüllt.
|
||
setFieldState(fields.message, null);
|
||
return false;
|
||
}
|
||
|
||
function allValid() {
|
||
return (
|
||
fields.name.value.trim().length > 0 &&
|
||
/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(fields.email.value.trim()) &&
|
||
fields.type.value !== "" &&
|
||
fields.subject.value.trim().length > 0 &&
|
||
fields.message.value.trim().length >= MIN_MESSAGE
|
||
);
|
||
}
|
||
|
||
function updateSubmitState() {
|
||
const submit = form.querySelector("[type='submit']");
|
||
if (submit) {
|
||
submit.disabled = !allValid();
|
||
}
|
||
}
|
||
|
||
// Der Button bleibt unabhängig von der Eingabereihenfolge mit allen Feldern synchron.
|
||
form.addEventListener("input", updateSubmitState);
|
||
form.addEventListener("change", updateSubmitState);
|
||
|
||
// Live-Feedback: Nachricht wird bei 10+ Zeichen grün markiert.
|
||
fields.message.addEventListener("input", function () {
|
||
validateMessage();
|
||
});
|
||
|
||
["name", "email", "subject"].forEach(function (key) {
|
||
fields[key].addEventListener("blur", function () {
|
||
if (fields[key].value.trim() !== "" || form.dataset.touched === "true") {
|
||
({ name: validateName, email: validateEmail, subject: validateSubject })[key]();
|
||
}
|
||
});
|
||
});
|
||
|
||
fields.type.addEventListener("change", validateType);
|
||
|
||
form.addEventListener("submit", function (event) {
|
||
event.preventDefault();
|
||
form.dataset.touched = "true";
|
||
|
||
const okName = validateName();
|
||
const okEmail = validateEmail();
|
||
const okType = validateType();
|
||
const okSubject = validateSubject();
|
||
const okMessage = validateMessage();
|
||
|
||
if (!(okName && okEmail && okType && okSubject && okMessage)) {
|
||
showStatus("error", "Bitte überprüfe die markierten Felder und versuche es erneut.");
|
||
return;
|
||
}
|
||
|
||
const subject = fields.subject.value.trim();
|
||
const typeLabel = fields.type.options[fields.type.selectedIndex].text;
|
||
const body = [
|
||
"Name: " + fields.name.value.trim(),
|
||
"E-Mail: " + fields.email.value.trim(),
|
||
"Telefon: " + (fields.phone.value.trim() || "–"),
|
||
"Anfrage-Typ: " + typeLabel,
|
||
"",
|
||
fields.message.value.trim()
|
||
].join("\n");
|
||
|
||
// Statische Seite ohne Backend: E-Mail-Programm wird mit allen Angaben geöffnet.
|
||
window.location.href =
|
||
"mailto:" + EMAIL_TARGET +
|
||
"?subject=" + encodeURIComponent("Ernährungsberatung – " + subject) +
|
||
"&body=" + encodeURIComponent(body);
|
||
|
||
showStatus(
|
||
"ok",
|
||
"Danke! Dein E-Mail-Programm wurde geöffnet. Sende die Nachricht ab – wir melden uns zeitnah bei dir."
|
||
);
|
||
form.reset();
|
||
Object.values(fields).forEach(function (el) {
|
||
setFieldState(el, null);
|
||
});
|
||
updateSubmitState();
|
||
});
|
||
|
||
function showStatus(kind, text) {
|
||
if (!statusEl) return;
|
||
statusEl.textContent = kind === "ok" ? "✓ " + text : "✗ " + text;
|
||
statusEl.className =
|
||
"form-status is-visible " + (kind === "ok" ? "form-status--ok" : "form-status--error");
|
||
}
|
||
|
||
updateSubmitState();
|
||
})();
|