263 lines
5.7 KiB
JavaScript
263 lines
5.7 KiB
JavaScript
/* =====================================================
|
|
GLOBAL STATE
|
|
===================================================== */
|
|
|
|
let index = 0;
|
|
let track;
|
|
let dots = [];
|
|
|
|
|
|
/* =====================================================
|
|
DOM CONTENT LOADED
|
|
===================================================== */
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
initServices();
|
|
initNavigation();
|
|
initNewsSlider();
|
|
});
|
|
|
|
|
|
/* =====================================================
|
|
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; // 8 sec
|
|
|
|
/* -------------------------
|
|
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++;
|
|
|
|
if (index >= slides.length) {
|
|
index = 0; // LOOP BACK
|
|
}
|
|
|
|
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();
|
|
});
|
|
|
|
/* -------------------------
|
|
INIT
|
|
------------------------- */
|
|
|
|
updateSlider();
|
|
startAutoSlide();
|
|
} |