/* ===================================================== GLOBAL STATE ===================================================== */ let index = 0; let track; let dots = []; let currentLang = "de"; /* ===================================================== DOM CONTENT LOADED ===================================================== */ document.addEventListener("DOMContentLoaded", () => { const saved = localStorage.getItem("lang") || "de"; setLang(saved, false); initServices(); initNavigation(); initNewsSlider(); }); /* ===================================================== i18n – LANGUAGE SWITCHING ===================================================== */ async function setLang(lang, save = true) { try { const res = await fetch(`locales/${lang}.json`); const translations = await res.json(); currentLang = lang; document.documentElement.lang = lang; if (save) localStorage.setItem("lang", lang); /* Plain text nodes */ document.querySelectorAll("[data-i18n]").forEach(el => { const key = el.getAttribute("data-i18n"); if (translations[key] !== undefined) { el.textContent = translations[key]; } }); /* HTML nodes (for content with ,
etc.) */ document.querySelectorAll("[data-i18n-html]").forEach(el => { const key = el.getAttribute("data-i18n-html"); if (translations[key] !== undefined) { el.innerHTML = translations[key]; } }); /* Update active button */ document.getElementById("lang-de").classList.toggle("active", lang === "de"); document.getElementById("lang-en").classList.toggle("active", lang === "en"); } catch (err) { console.error("Language file could not be loaded:", err); } } /* Attribute handling (for [src], [alt], etc.) */ document.querySelectorAll("[data-i18n-attr]").forEach(el => { const attrMap = el.getAttribute("data-i18n-attr"); // Example: "src:logo_path,alt:logo_alt" const mappings = attrMap.split(';'); mappings.forEach(mapping => { const [attr, key] = mapping.split(':'); if (translations[key] !== undefined) { el.setAttribute(attr, translations[key]); } }); }); /* ===================================================== SERVICES EXPAND / COLLAPSE ===================================================== */ function initServices() { const boxes = document.querySelectorAll(".service-box"); boxes.forEach(box => { const arrow = box.querySelector(".service-arrow"); const text = box.querySelector(".service-text"); let closeTimeout; arrow.addEventListener("click", () => { boxes.forEach(b => { if (b !== box) b.classList.remove("open"); if (b.closeTimeout) clearTimeout(b.closeTimeout); }); box.classList.toggle("open"); }); /* AUTO CLOSE */ box.addEventListener("mouseleave", () => { if (box.classList.contains("open")) { box.classList.add("closing"); closeTimeout = setTimeout(() => { box.classList.remove("open"); }, 600); box.closeTimeout = closeTimeout; } }); /* CANCEL CLOSE */ box.addEventListener("mouseenter", () => { if (closeTimeout) clearTimeout(closeTimeout); box.classList.remove("closing"); }); /* CLEANUP CLASS */ text.addEventListener("transitionend", e => { if (e.propertyName === "max-height" && box.classList.contains("closing")) { box.classList.remove("closing"); } }); }); } /* ===================================================== SCROLL TO TOP ===================================================== */ function scrollToTop() { window.scrollTo({ top: 0, behavior: "smooth" }); } /* ===================================================== MOBILE BURGER MENU ===================================================== */ function toggleBurger() { document.querySelector(".nav").classList.toggle("open"); } /* ===================================================== ACTIVE NAVIGATION SCROLL ===================================================== */ function initNavigation() { const sections = document.querySelectorAll("section"); const navLinks = document.querySelectorAll(".nav-links a"); window.addEventListener("scroll", () => { let current = ""; sections.forEach(section => { const top = section.offsetTop - 120; if (window.scrollY >= top) current = section.getAttribute("id"); }); navLinks.forEach(link => { link.classList.remove("active"); if (link.getAttribute("href") === "#" + current) link.classList.add("active"); }); }); } /* ===================================================== NEWS SLIDER ===================================================== */ function initNewsSlider() { track = document.querySelector(".news-track"); const slider = document.querySelector(".news-slider"); const dotsContainer = document.querySelector(".news-dots"); const slides = document.querySelectorAll(".news-slide"); if (!track || !dotsContainer || slides.length === 0) return; let autoSlide; const INTERVAL = 8000; /* CREATE DOTS */ dotsContainer.innerHTML = ""; dots = []; slides.forEach((slide, i) => { const dot = document.createElement("div"); dot.classList.add("news-dot"); if (i === 0) dot.classList.add("active"); dot.addEventListener("click", () => { index = i; updateSlider(); restartAutoSlide(); }); dotsContainer.appendChild(dot); dots.push(dot); }); /* UPDATE SLIDER */ function updateSlider() { track.style.transform = `translateX(-${index * 100}%)`; dots.forEach((dot, i) => dot.classList.toggle("active", i === index)); } /* AUTO LOOP */ function startAutoSlide() { autoSlide = setInterval(() => { index = (index + 1) >= slides.length ? 0 : index + 1; updateSlider(); }, INTERVAL); } function stopAutoSlide() { clearInterval(autoSlide); } function restartAutoSlide() { stopAutoSlide(); startAutoSlide(); } /* PAUSE ON HOVER */ const newsSection = document.querySelector("#news"); newsSection.addEventListener("mouseenter", stopAutoSlide); newsSection.addEventListener("mouseleave", startAutoSlide); /* TOUCH SUPPORT */ let startX = 0; let isDragging = false; track.addEventListener("touchstart", e => { startX = e.touches[0].clientX; isDragging = true; stopAutoSlide(); }); track.addEventListener("touchmove", e => { if (!isDragging) return; const delta = e.touches[0].clientX - startX; track.style.transition = "none"; track.style.transform = `translateX(calc(-${index * 100}% + ${delta}px))`; }); track.addEventListener("touchend", e => { isDragging = false; track.style.transition = "transform 0.6s ease"; const delta = e.changedTouches[0].clientX - startX; if (delta > 50 && index > 0) index--; else if (delta < -50 && index < slides.length - 1) index++; updateSlider(); restartAutoSlide(); }); updateSlider(); startAutoSlide(); }