document.addEventListener('DOMContentLoaded', () => { const track = document.getElementById('sliderTrack'); if (!track) return; const dotsRow = document.getElementById('dotsRow'); const progFill = document.getElementById('progressFill'); const cards = Array.from(track.querySelectorAll('.stu-card')); const prevBtn = document.getElementById('prevBtn'); const nextBtn = document.getElementById('nextBtn'); const sliderSection = document.querySelector('.slider-outer'); const AUTO_INTERVAL = 4000; let current = 0; let autoTimer = null; let paused = false; let visible = 3; /* ═════════════ GET VISIBLE ═════════════ */ function getVisible() { const w = sliderSection.offsetWidth; if (w < 480) return 1; if (w < 720) return 2; return 3; } /* ═════════════ CARD WIDTH ═════════════ */ function cardWidth() { if (!cards.length) return 0; const style = window.getComputedStyle(track); const gap = parseInt(style.gap) || 0; return cards[0].offsetWidth + gap; } /* ═════════════ MAX INDEX ═════════════ */ function maxIndex() { return Math.max(0, cards.length - visible); } /* ═════════════ BUILD DOTS ═════════════ */ function buildDots() { dotsRow.innerHTML = ''; const total = maxIndex() + 1; for (let i = 0; i < total; i++) { const dot = document.createElement('div'); dot.className = 'dot'; if (i === current) { dot.classList.add('active'); } dot.addEventListener('click', () => { goTo(i); resetAuto(); }); dotsRow.appendChild(dot); } } /* ═════════════ UPDATE DOTS ═════════════ */ function updateDots() { const dots = dotsRow.querySelectorAll('.dot'); dots.forEach((dot, i) => { dot.classList.toggle('active', i === current); }); } /* ═════════════ GO TO SLIDE ═════════════ */ function goTo(index) { current = Math.max(0, Math.min(index, maxIndex())); const moveX = current * cardWidth(); track.style.transform = `translateX(-${moveX}px)`; updateDots(); } /* ═════════════ SLIDE ═════════════ */ function slide(direction) { if (direction === 1) { if (current >= maxIndex()) { current = 0; } else { current++; } } else { if (current <= 0) { current = maxIndex(); } else { current--; } } goTo(current); } /* ═════════════ AUTO SLIDE ═════════════ */ function startAuto() { clearInterval(autoTimer); autoTimer = setInterval(() => { if (!paused) { slide(1); startProgress(); } }, AUTO_INTERVAL); } /* ═════════════ RESET AUTO ═════════════ */ function resetAuto() { clearInterval(autoTimer); startAuto(); startProgress(); } /* ═════════════ PROGRESS BAR ═════════════ */ function startProgress() { if (!progFill) return; progFill.style.transition = 'none'; progFill.style.width = '0%'; setTimeout(() => { progFill.style.transition = `width ${AUTO_INTERVAL}ms linear`; progFill.style.width = '100%'; }, 50); } /* ═════════════ BUTTON EVENTS ═════════════ */ if (prevBtn) { prevBtn.addEventListener('click', () => { slide(-1); resetAuto(); }); } if (nextBtn) { nextBtn.addEventListener('click', () => { slide(1); resetAuto(); }); } /* ═════════════ HOVER PAUSE ═════════════ */ if (sliderSection) { sliderSection.addEventListener('mouseenter', () => { paused = true; }); sliderSection.addEventListener('mouseleave', () => { paused = false; }); } /* ═════════════ TOUCH SWIPE ═════════════ */ let startX = 0; if (sliderSection) { sliderSection.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; }); sliderSection.addEventListener('touchend', (e) => { const endX = e.changedTouches[0].clientX; const diff = startX - endX; if (Math.abs(diff) > 40) { if (diff > 0) { slide(1); } else { slide(-1); } resetAuto(); } }); } /* ═════════════ RESIZE ═════════════ */ window.addEventListener('resize', () => { visible = getVisible(); buildDots(); goTo(current); }); /* ═════════════ INIT ═════════════ */ function init() { visible = getVisible(); buildDots(); goTo(0); if (cards.length > visible) { startAuto(); startProgress(); } else { if (progFill && progFill.parentElement) { progFill.parentElement.style.display = 'none'; } } } init(); }); const tabButtons = document.querySelectorAll('.tab-btn'); tabButtons.forEach(button => { button.addEventListener('click', () => { // remove active from all tabButtons.forEach(btn => { btn.classList.remove('active'); }); // add active only clicked tab button.classList.add('active'); const filter = button.dataset.tab; const allCards = document.querySelectorAll('.stu-card'); allCards.forEach(card => { const isGov = card.dataset.gov === "1"; const isAward = card.dataset.award === "1"; let show = false; if(filter === 'all') { show = true; } else if(filter === 'gov') { show = isGov; } else if(filter === 'award') { show = isAward; } card.style.display = show ? 'block' : 'none'; }); }); });