PageSourceSearch

https://uxmag.com/wp-content/themes/genesis-sample/static/season-timeline.js

js uxmag.com collected 2026-09-24 08:23:51 UTC 5,086 bytes, 146 lines download raw bytes

1(function () {
2  'use strict';
3
4  function scrollportEl(track) {
5    if (!track) return null;
6    var parent = track.parentElement;
7    if (parent && parent.classList.contains('season-track-scroll')) return parent;
8    if (track.classList.contains('season-track') && track.scrollWidth > track.clientWidth) return track;
9    return track;
10  }
11
12  function scrollTarget(track, preferActive) {
13    if (preferActive) {
14      return (
15        track.querySelector('.season-ep.active') ||
16        track.querySelector('.season-ep[aria-pressed="true"]') ||
17        track.querySelector('[data-uxm-timeline-latest="true"]')
18      );
19    }
20    return (
21      track.querySelector('[data-uxm-timeline-latest="true"]') ||
22      track.querySelector('.season-ep.active') ||
23      track.querySelector('.season-ep[aria-pressed="true"]') ||
24      track.querySelector('.season-ep--nav:last-of-type, .season-ep--hub:last-of-type')
25    );
26  }
27
28  function centerStop(track, stop, behavior) {
29    var port = scrollportEl(track);
30    if (!port || !stop) return;
31    var max = port.scrollWidth - port.clientWidth;
32    if (max <= 0) return;
33    var left = stop.offsetLeft - port.clientWidth / 2 + stop.offsetWidth / 2;
34    port.scrollTo({ left: Math.max(0, Math.min(left, max)), behavior: behavior || 'auto' });
35  }
36
37  function dotCenterY(stop) {
38    var dot = stop.querySelector('.season-ep-dot');
39    if (!dot) return stop.offsetTop + stop.offsetHeight / 2;
40    return stop.offsetTop + dot.offsetTop + dot.offsetHeight / 2;
41  }
42
43  function layoutTimelineLine(track) {
44    var line = track.querySelector('.season-line');
45    if (!line) return;
46    var stops = track.querySelectorAll('.season-ep');
47    if (stops.length < 2) {
48      line.style.display = 'none';
49      return;
50    }
51    line.style.display = '';
52    var first = stops[0];
53    var last = stops[stops.length - 1];
54    var x1 = first.offsetLeft + first.offsetWidth / 2;
55    var x2 = last.offsetLeft + last.offsetWidth / 2;
56    var yCenter = dotCenterY(first);
57    line.style.left = x1 + 'px';
58    line.style.width = Math.max(0, x2 - x1) + 'px';
59    line.style.right = 'auto';
60    line.style.top = (yCenter - 1) + 'px';
61  }
62
63  function scheduleLineLayout(track) {
64    requestAnimationFrame(function () {
65      layoutTimelineLine(track);
66    });
67  }
68
69  function updateScrollDims(track) {
70    var port = scrollportEl(track);
71    if (!port) return;
72    var stops = track.querySelectorAll('.season-ep--nav, .season-ep--hub');
73    stops.forEach(function (stop) {
74      var r = stop.getBoundingClientRect();
75      var pr = port.getBoundingClientRect();
76      var partial = r.right > pr.right + 2 || r.left < pr.left - 2;
77      stop.classList.toggle('season-ep--scroll-dim', partial && !stop.classList.contains('active') && stop.getAttribute('aria-pressed') !== 'true');
78    });
79  }
80
81  function bindLineLayout(track) {
82    if (track.__uxmLineLayoutBound) return;
83    track.__uxmLineLayoutBound = true;
84    scheduleLineLayout(track);
85    if (typeof ResizeObserver !== 'undefined') {
86      var ro = new ResizeObserver(function () {
87        layoutTimelineLine(track);
88      });
89      ro.observe(track);
90      track.__uxmLineRo = ro;
91    }
92    window.addEventListener('resize', function () {
93      layoutTimelineLine(track);
94    }, { passive: true });
95  }
96
97  function initArc(arc, behavior, preferActive) {
98    var track = arc.querySelector('.season-track');
99    if (!track) return;
100    bindLineLayout(track);
101    centerStop(track, scrollTarget(track, preferActive), behavior);
102    updateScrollDims(track);
103    var port = scrollportEl(track);
104    if (port) {
105      port.addEventListener('scroll', function () {
106        updateScrollDims(track);
107      }, { passive: true });
108    }
109  }
110
111  function initAll(behavior, preferActive) {
112    document.querySelectorAll('.uxm-season-timeline').forEach(function (arc) {
113      var useActive = preferActive != null ? preferActive : arc.classList.contains('season-arc--ideation');
114      initArc(arc, behavior, useActive);
115    });
116  }
117
118  window.UXM_scrollSeasonTimeline = function (root, behavior, preferActive) {
119    var arc = root && root.closest ? root.closest('.uxm-season-timeline') : null;
120    if (arc) initArc(arc, behavior || 'smooth', !!preferActive);
121    else initAll(behavior || 'smooth', !!preferActive);
122  };
123
124  window.UXM_layoutSeasonTimelineLine = function (root) {
125    var track = root && root.querySelector ? root.querySelector('.season-track') : null;
126    if (!track && root && root.classList && root.classList.contains('season-track')) track = root;
127    if (track) layoutTimelineLine(track);
128    else {
129      document.querySelectorAll('.uxm-season-timeline .season-track').forEach(layoutTimelineLine);
130    }
131  };
132
133  if (document.readyState === 'loading') {
134    document.addEventListener('DOMContentLoaded', function () {
135      initAll('auto', false);
136    });
137  } else {
138    initAll('auto', false);
139  }
140
141  if (document.fonts && document.fonts.ready) {
142    document.fonts.ready.then(function () {
143      document.querySelectorAll('.uxm-season-timeline .season-track').forEach(layoutTimelineLine);
144    });
145  }
146})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.