PageSourceSearch

https://coinlaw.io/wp-content/themes/hodl-this-design/assets/scripts/swiper-init.js?ver=3.168.1

js coinlaw.io collected 2026-10-02 02:18:05 UTC 8,007 bytes, 305 lines download raw bytes

1/**
2 * Swiper Initializations
3 *
4 * Consolidates all inline Swiper inits into one cacheable file.
5 *
6 * @package ChildTheme
7 * @since   1.0.0
8 */
9/* global manageSwiperTabindex */
10(function () {
11
12	const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
13
14	function init() {
15
16		// Guard: skip if Swiper library has not loaded yet.
17		if (typeof Swiper === 'undefined') {
18			return;
19		}
20
21		// Helper to find tabbable elements in document order
22		function getTabbableElements() {
23			return Array.from(document.querySelectorAll(
24				'a[href], button, input:not([type="hidden"]), select, textarea, [tabindex]'
25			)).filter(function(el) {
26				// Exclude elements with tabindex="-1", disabled, or not visible
27				return el.offsetParent !== null &&
28					!el.disabled &&
29					el.getAttribute('tabindex') !== '-1';
30			});
31		}
32
33		// Find element before swiper section (skip any swiper-related elements)
34		function getElementBeforeSwiper(swiperEl) {
35			const section = swiperEl.closest('section.featured-posts-swiper') || swiperEl.closest('section.press-release') || swiperEl.closest('section') || swiperEl;
36			const tabbables = getTabbableElements();
37
38			// Find first tabbable inside swiper section
39			for (let i = 0; i < tabbables.length; i++) {
40				if (section.contains(tabbables[i])) {
41					// Go backwards to find element NOT in any swiper section
42					for (let j = i - 1; j >= 0; j--) {
43						const el = tabbables[j];
44						// Skip if element is inside any swiper/carousel
45						if (!el.closest('.swiper, .swiper-container, .featured-posts-swiper, .trending-posts, .press-release, .pr-swiper')) {
46							return el;
47						}
48					}
49					return null;
50				}
51			}
52			return null;
53		}
54
55		// Find next tabbable element after the swiper container
56		function getElementAfterSwiper(swiperEl) {
57			const tabbables = getTabbableElements();
58			// Find last tabbable inside the swiper container (not the whole section)
59			for (let i = tabbables.length - 1; i >= 0; i--) {
60				if (swiperEl.contains(tabbables[i])) {
61					return i < tabbables.length - 1 ? tabbables[i + 1] : null;
62				}
63			}
64			return null;
65		}
66
67		// Make swiper containers accessible for keyboard navigation
68		document.querySelectorAll('.swiper, .swiper-container, .trending-posts').forEach(function (el) {
69			el.setAttribute('tabindex', '-1');
70			if (!el.hasAttribute('role')) {
71				el.setAttribute('role', 'region');
72			}
73			if (!el.hasAttribute('aria-label')) {
74				el.setAttribute('aria-label', 'Carousel');
75			}
76
77			// Handle Tab/Shift+Tab to exit swiper properly
78			el.addEventListener('keydown', function(e) {
79				if (e.key !== 'Tab') return;
80
81				const visibleLinks = Array.from(el.querySelectorAll(
82					'.swiper-slide-visible:not(.swiper-slide-duplicate) a:not([tabindex="-1"]), ' +
83					'.swiper-slide-active:not(.swiper-slide-duplicate) a:not([tabindex="-1"])'
84				));
85
86				if (!visibleLinks.length) return;
87
88				const firstLink = visibleLinks[0];
89				const lastLink = visibleLinks[visibleLinks.length - 1];
90				const activeEl = document.activeElement;
91
92				if (e.shiftKey && activeEl === firstLink) {
93					e.preventDefault();
94					const prevEl = getElementBeforeSwiper(el);
95					if (prevEl) prevEl.focus();
96				} else if (!e.shiftKey && activeEl === lastLink) {
97					e.preventDefault();
98					const nextEl = getElementAfterSwiper(el);
99					if (nextEl) nextEl.focus();
100				}
101			});
102		});
103
104		// Press Releases carousel (front-page)
105		if (document.querySelector('.pr-swiper')) {
106			new Swiper('.pr-swiper', {
107				slidesPerView: 3,
108				spaceBetween: 30,
109				loop: true,
110				keyboard: { enabled: true },
111				a11y: { enabled: true },
112				watchSlidesProgress: true,
113				autoplay: reducedMotion ? false : {
114					delay: 4000,
115					disableOnInteraction: false,
116					pauseOnMouseEnter: true
117				},
118				navigation: {
119					nextEl: '.press-release .swiper-button-next',
120					prevEl: '.press-release .swiper-button-prev'
121				},
122				pagination: {
123					el: '.press-release .swiper-pagination',
124					clickable: true
125				},
126				breakpoints: {
127					0: {
128						slidesPerView: 1
129					},
130					768: {
131						slidesPerView: 2
132					},
133					1200: {
134						slidesPerView: 3
135					}
136				},
137				on: {
138					init: function (swiper) {
139						manageSwiperTabindex(swiper);
140
141						// Pause autoplay on keyboard focus (WCAG 2.2.2).
142						swiper.el.addEventListener('focusin', function () {
143							if (swiper.autoplay && swiper.autoplay.running) {
144								swiper.autoplay.stop();
145							}
146						});
147					},
148					slideChange: manageSwiperTabindex
149				}
150			});
151		}
152
153		// Trending posts carousel (front-page)
154		if (document.querySelector('.trending-posts')) {
155			new Swiper('.trending-posts', {
156				slidesPerView: 1,
157				spaceBetween: 30,
158				loop: true,
159				speed: 800,
160				keyboard: { enabled: true },
161				a11y: { enabled: true },
162				watchSlidesProgress: true,
163				// autoplay: {
164				// 	delay: 3500,
165				// 	disableOnInteraction: false,
166				// },
167				breakpoints: {
168					980: {
169						slidesPerView: 4,
170					},
171					768: {
172						slidesPerView: 3,
173						spaceBetween: 25,
174					},
175					480: {
176						slidesPerView: 1,
177						spaceBetween: 20,
178					},
179				},
180				navigation: {
181					prevEl: '.trending-navigation .swiper-button-prev',
182					nextEl: '.trending-navigation .swiper-button-next',
183				},
184				on: {
185					init: manageSwiperTabindex,
186					slideChange: manageSwiperTabindex
187				}
188			});
189		}
190
191		// Testimonial carousel (front-page)
192		if (document.querySelector('.testimonial-swiper')) {
193			new Swiper('.testimonial-swiper', {
194				slidesPerView: 1,
195				spaceBetween: 30,
196				loop: true,
197				speed: 700,
198				keyboard: { enabled: true },
199				a11y: { enabled: true },
200				effect: 'fade',
201				fadeEffect: {
202					crossFade: true
203				},
204				navigation: {
205					prevEl: '.testimonial-navigation .swiper-button-prev',
206					nextEl: '.testimonial-navigation .swiper-button-next',
207				},
208				// autoplay: {
209				// 	delay: 5000,
210				// 	disableOnInteraction: false,
211				// },
212				on: {
213					init: manageSwiperTabindex,
214					slideChange: manageSwiperTabindex
215				}
216			});
217		}
218
219		// Featured posts carousel (index, archive, single, about, team, contact, 404)
220		if (document.querySelector('.featured-posts-swiper .swiper-container')) {
221			new Swiper('.featured-posts-swiper .swiper-container', {
222				slidesPerView: 1.5,
223				centeredSlides: true,
224				spaceBetween: 5,
225				loop: true,
226				keyboard: { enabled: true },
227				a11y: { enabled: true },
228				watchSlidesProgress: true,
229				autoplay: reducedMotion ? false : {
230					delay: 3500,
231					disableOnInteraction: false,
232					pauseOnMouseEnter: true,
233				},
234				speed: 800,
235				breakpoints: {
236					1300: {
237						slidesPerView: 3.5
238					},
239					1000: {
240						slidesPerView: 2.5
241					}
242				},
243				on: {
244					init: manageSwiperTabindex,
245					slideChange: manageSwiperTabindex
246				}
247			});
248		}
249
250		// Image gallery with thumbnails (single post)
251		if (document.querySelector('.gallery-thumbs')) {
252			const galleryThumbs = new Swiper('.gallery-thumbs', {
253				spaceBetween: 10,
254				slidesPerView: 6,
255				freeMode: true,
256				keyboard: { enabled: true },
257				a11y: { enabled: true },
258				watchSlidesProgress: true,
259				watchSlidesVisibility: true,
260				slideToClickedSlide: true,
261				breakpoints: {
262					700: {
263						slidesPerView: 6
264					},
265					480: {
266						slidesPerView: 3
267					}
268				},
269				loop: true,
270				on: {
271					init: manageSwiperTabindex,
272					slideChange: manageSwiperTabindex
273				}
274			});
275
276			new Swiper('.gallery-top', {
277				spaceBetween: 10,
278				keyboard: { enabled: true },
279				a11y: { enabled: true },
280				navigation: {
281					nextEl: '.swiper-button-next',
282					prevEl: '.swiper-button-prev'
283				},
284				thumbs: {
285					swiper: galleryThumbs
286				},
287				loop: true,
288				autoHeight: false,
289				on: {
290					init: manageSwiperTabindex,
291					slideChange: manageSwiperTabindex
292				}
293			});
294		}
295	}
296
297	// Use readyState check so swipers initialize even when FlyingPress delays scripts
298	// past DOMContentLoaded.
299	if (document.readyState === 'loading') {
300		document.addEventListener('DOMContentLoaded', init);
301	} else {
302		init();
303	}
304
305})();

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.