update Felix
This commit is contained in:
159
js/script.js
159
js/script.js
@@ -5,6 +5,7 @@ GLOBAL STATE
|
||||
let index = 0;
|
||||
let track;
|
||||
let dots = [];
|
||||
let currentLang = "de";
|
||||
|
||||
|
||||
/* =====================================================
|
||||
@@ -12,12 +13,55 @@ 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 <strong>, <br> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* =====================================================
|
||||
SERVICES EXPAND / COLLAPSE
|
||||
===================================================== */
|
||||
@@ -29,17 +73,15 @@ function initServices() {
|
||||
boxes.forEach(box => {
|
||||
|
||||
const arrow = box.querySelector(".service-arrow");
|
||||
const text = box.querySelector(".service-text");
|
||||
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");
|
||||
});
|
||||
|
||||
@@ -47,11 +89,9 @@ function initServices() {
|
||||
box.addEventListener("mouseleave", () => {
|
||||
if (box.classList.contains("open")) {
|
||||
box.classList.add("closing");
|
||||
|
||||
closeTimeout = setTimeout(() => {
|
||||
box.classList.remove("open");
|
||||
}, 600);
|
||||
|
||||
box.closeTimeout = closeTimeout;
|
||||
}
|
||||
});
|
||||
@@ -64,10 +104,7 @@ function initServices() {
|
||||
|
||||
/* CLEANUP CLASS */
|
||||
text.addEventListener("transitionend", e => {
|
||||
if (
|
||||
e.propertyName === "max-height" &&
|
||||
box.classList.contains("closing")
|
||||
) {
|
||||
if (e.propertyName === "max-height" && box.classList.contains("closing")) {
|
||||
box.classList.remove("closing");
|
||||
}
|
||||
});
|
||||
@@ -80,10 +117,7 @@ SCROLL TO TOP
|
||||
===================================================== */
|
||||
|
||||
function scrollToTop() {
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: "smooth"
|
||||
});
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
}
|
||||
|
||||
|
||||
@@ -106,23 +140,14 @@ function initNavigation() {
|
||||
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");
|
||||
}
|
||||
if (window.scrollY >= top) current = section.getAttribute("id");
|
||||
});
|
||||
|
||||
navLinks.forEach(link => {
|
||||
link.classList.remove("active");
|
||||
|
||||
if (link.getAttribute("href") === "#" + current) {
|
||||
link.classList.add("active");
|
||||
}
|
||||
if (link.getAttribute("href") === "#" + current) link.classList.add("active");
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -135,19 +160,16 @@ NEWS SLIDER
|
||||
function initNewsSlider() {
|
||||
|
||||
track = document.querySelector(".news-track");
|
||||
const slider = document.querySelector(".news-slider");
|
||||
const slider = document.querySelector(".news-slider");
|
||||
const dotsContainer = document.querySelector(".news-dots");
|
||||
const slides = document.querySelectorAll(".news-slide");
|
||||
const slides = document.querySelectorAll(".news-slide");
|
||||
|
||||
if (!track || !dotsContainer || slides.length === 0) return;
|
||||
|
||||
let autoSlide;
|
||||
const INTERVAL = 8000; // 8 sec
|
||||
|
||||
/* -------------------------
|
||||
CREATE DOTS
|
||||
------------------------- */
|
||||
const INTERVAL = 8000;
|
||||
|
||||
/* CREATE DOTS */
|
||||
dotsContainer.innerHTML = "";
|
||||
dots = [];
|
||||
|
||||
@@ -155,73 +177,39 @@ function initNewsSlider() {
|
||||
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
|
||||
------------------------- */
|
||||
|
||||
/* UPDATE SLIDER */
|
||||
function updateSlider() {
|
||||
track.style.transform = `translateX(-${index * 100}%)`;
|
||||
|
||||
dots.forEach((dot, i) =>
|
||||
dot.classList.toggle("active", i === index)
|
||||
);
|
||||
dots.forEach((dot, i) => dot.classList.toggle("active", i === index));
|
||||
}
|
||||
|
||||
/* -------------------------
|
||||
AUTO LOOP
|
||||
------------------------- */
|
||||
|
||||
/* AUTO LOOP */
|
||||
function startAutoSlide() {
|
||||
autoSlide = setInterval(() => {
|
||||
index++;
|
||||
|
||||
if (index >= slides.length) {
|
||||
index = 0; // LOOP BACK
|
||||
}
|
||||
|
||||
index = (index + 1) >= slides.length ? 0 : index + 1;
|
||||
updateSlider();
|
||||
}, INTERVAL);
|
||||
}
|
||||
|
||||
function stopAutoSlide() {
|
||||
clearInterval(autoSlide);
|
||||
}
|
||||
function stopAutoSlide() { clearInterval(autoSlide); }
|
||||
function restartAutoSlide() { stopAutoSlide(); startAutoSlide(); }
|
||||
|
||||
function restartAutoSlide() {
|
||||
stopAutoSlide();
|
||||
startAutoSlide();
|
||||
}
|
||||
/* PAUSE ON HOVER */
|
||||
const newsSection = document.querySelector("#news");
|
||||
newsSection.addEventListener("mouseenter", stopAutoSlide);
|
||||
newsSection.addEventListener("mouseleave", startAutoSlide);
|
||||
|
||||
/* -------------------------
|
||||
PAUSE ON HOVER
|
||||
------------------------- */
|
||||
|
||||
const newsSection = document.querySelector("#news");
|
||||
|
||||
newsSection.addEventListener("mouseenter", () => {
|
||||
stopAutoSlide();
|
||||
});
|
||||
|
||||
newsSection.addEventListener("mouseleave", () => {
|
||||
startAutoSlide();
|
||||
});
|
||||
|
||||
/* -------------------------
|
||||
TOUCH SUPPORT
|
||||
------------------------- */
|
||||
|
||||
let startX = 0;
|
||||
/* TOUCH SUPPORT */
|
||||
let startX = 0;
|
||||
let isDragging = false;
|
||||
|
||||
track.addEventListener("touchstart", e => {
|
||||
@@ -232,32 +220,21 @@ newsSection.addEventListener("mouseleave", () => {
|
||||
|
||||
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.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--;
|
||||
if (delta > 50 && index > 0) index--;
|
||||
else if (delta < -50 && index < slides.length - 1) index++;
|
||||
|
||||
updateSlider();
|
||||
restartAutoSlide();
|
||||
});
|
||||
|
||||
/* -------------------------
|
||||
INIT
|
||||
------------------------- */
|
||||
|
||||
updateSlider();
|
||||
startAutoSlide();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user