File size: 2,511 Bytes
b77c05a
 
 
 
 
 
 
 
f24a186
b77c05a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f24a186
b77c05a
f24a186
 
 
 
 
 
 
 
 
 
 
 
b77c05a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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();
    }
  });
}