Spaces:
Running
Running
| function runSequenceAnimation({ | |
| selectors, | |
| cyclePause = 2000, | |
| fadeOutOffset = 4000, | |
| initialDelay = 500, | |
| lastDelayOverride, | |
| onShow, | |
| scrollContainerSelector, | |
| useFadeOut = false, | |
| } = {}) { | |
| const groups = (selectors || []).flatMap((selector) => | |
| Array.from(document.querySelectorAll(selector)) | |
| ); | |
| if (groups.length === 0) { | |
| return; | |
| } | |
| const delays = groups.map((el) => parseInt(el.dataset.delay, 10) || 0); | |
| const maxDelay = Math.max(...delays, 0); | |
| const finalDelay = Math.max(maxDelay, lastDelayOverride || 0); | |
| const scrollContainer = scrollContainerSelector | |
| ? document.querySelector(scrollContainerSelector) | |
| : null; | |
| let timers = []; | |
| let runId = 0; | |
| function clearTimers() { | |
| timers.forEach((id) => clearTimeout(id)); | |
| timers = []; | |
| } | |
| function schedule(fn, delay) { | |
| const id = setTimeout(fn, delay); | |
| timers.push(id); | |
| return id; | |
| } | |
| function runAnimation(activeRunId) { | |
| if (activeRunId !== runId) { | |
| return; | |
| } | |
| clearTimers(); | |
| groups.forEach((el) => el.classList.remove('show', 'fade-out')); | |
| if (scrollContainer) { | |
| scrollContainer.scrollTop = 0; | |
| } | |
| // Force reflow to ensure class removal is processed before re-adding | |
| void document.body.offsetHeight; | |
| groups.forEach((el) => { | |
| const delay = parseInt(el.dataset.delay, 10) || 0; | |
| schedule(() => { | |
| if (activeRunId !== runId) { | |
| return; | |
| } | |
| el.classList.add('show'); | |
| if (onShow) { | |
| onShow(el); | |
| } | |
| if (scrollContainer) { | |
| scrollContainer.scrollTop = scrollContainer.scrollHeight; | |
| } | |
| }, delay); | |
| }); | |
| let restartDelay = finalDelay + cyclePause; | |
| if (useFadeOut) { | |
| const fadeOutTime = finalDelay + fadeOutOffset; | |
| schedule(() => { | |
| if (activeRunId !== runId) { | |
| return; | |
| } | |
| groups.forEach((el) => el.classList.add('fade-out')); | |
| }, fadeOutTime); | |
| restartDelay = fadeOutTime + 1000 + cyclePause; | |
| } | |
| schedule(() => runAnimation(activeRunId), restartDelay); | |
| } | |
| function start() { | |
| runId++; | |
| clearTimers(); | |
| schedule(() => runAnimation(runId), initialDelay); | |
| } | |
| if (document.readyState === 'complete') { | |
| start(); | |
| } else { | |
| window.addEventListener('load', start, { once: true }); | |
| } | |
| // Restart only on bfcache restores to avoid duplicate starts. | |
| window.addEventListener('pageshow', (event) => { | |
| if (event.persisted) { | |
| start(); | |
| } | |
| }); | |
| } | |