PageSourceSearch

https://seattlemag.com/wp-content/themes/seattlemag/js/homepage-slider.js?ver=1790166293

js seattlemag.com collected 2026-09-24 08:53:29 UTC 3,405 bytes, 131 lines download raw bytes

1/**
2 * Homepage featured-stories slider — progressive enhancement.
3 *
4 * The markup (CSS scroll-snap carousel with anchor-link dots/arrows) is fully
5 * functional with zero JS; the first slide paints without this file. This only
6 * adds: auto-advance, pause-on-interaction, reduced-motion support, and keeping
7 * the dots' aria-current in sync with manual swiping. No jQuery / framework.
8 */
9(function () {
10	'use strict';
11
12	var AUTO_DELAY = 5000;
13	var reduceMotion = window.matchMedia &&
14		window.matchMedia('(prefers-reduced-motion: reduce)').matches;
15
16	function initSlider(root) {
17		var track = root.querySelector('.hfs-track');
18		if (!track) {
19			return;
20		}
21
22		var slides = Array.prototype.slice.call(track.querySelectorAll('.hfs-slide'));
23		var dots = Array.prototype.slice.call(root.querySelectorAll('.hfs-dot'));
24		if (slides.length < 2) {
25			return;
26		}
27
28		root.classList.add('hfs--js');
29
30		var current = 0;
31		var timer = null;
32		var paused = false;
33
34		function setActive(i) {
35			dots.forEach(function (dot, di) {
36				if (di === i) {
37					dot.setAttribute('aria-current', 'true');
38				} else {
39					dot.removeAttribute('aria-current');
40				}
41			});
42		}
43
44		function goTo(i) {
45			current = (i + slides.length) % slides.length;
46			// Instant snap (no glide) — a story "just changes" to the next.
47			track.scrollTo({ left: current * track.clientWidth, behavior: 'auto' });
48			setActive(current);
49		}
50
51		// Dots + arrows are anchor links; hijack so the URL hash doesn't jump.
52		root.addEventListener('click', function (e) {
53			var link = e.target.closest && e.target.closest('a[href^="#hfs-slide-"]');
54			if (!link) {
55				return;
56			}
57			var target = document.getElementById(link.getAttribute('href').slice(1));
58			var idx = slides.indexOf(target);
59			if (idx === -1) {
60				return;
61			}
62			e.preventDefault();
63			goTo(idx);
64			restart();
65		});
66
67		// Keep aria-current in sync with manual swipe / native scroll.
68		var scrollRaf = null;
69		track.addEventListener('scroll', function () {
70			if (scrollRaf) {
71				return;
72			}
73			scrollRaf = window.requestAnimationFrame(function () {
74				scrollRaf = null;
75				var nearest = Math.round(track.scrollLeft / track.clientWidth);
76				nearest = Math.max(0, Math.min(slides.length - 1, nearest));
77				if (nearest !== current) {
78					current = nearest;
79					setActive(current);
80				}
81			});
82		}, { passive: true });
83
84		function tick() {
85			if (!paused) {
86				goTo(current + 1);
87			}
88		}
89
90		function start() {
91			if (reduceMotion || timer) {
92				return;
93			}
94			timer = window.setInterval(tick, AUTO_DELAY);
95		}
96
97		function stop() {
98			if (timer) {
99				window.clearInterval(timer);
100				timer = null;
101			}
102		}
103
104		function restart() {
105			stop();
106			start();
107		}
108
109		// Pause on hover/focus and when the tab is hidden.
110		root.addEventListener('pointerenter', function () { paused = true; });
111		root.addEventListener('pointerleave', function () { paused = false; });
112		root.addEventListener('focusin', function () { paused = true; });
113		root.addEventListener('focusout', function () { paused = false; });
114		document.addEventListener('visibilitychange', function () {
115			paused = document.hidden;
116		});
117
118		setActive(0);
119		start();
120	}
121
122	function init() {
123		Array.prototype.slice.call(document.querySelectorAll('.hfs')).forEach(initSlider);
124	}
125
126	if (document.readyState === 'loading') {
127		document.addEventListener('DOMContentLoaded', init);
128	} else {
129		init();
130	}
131})();

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.