PageSourceSearch

https://bikesandhikesla.com/wp-content/themes/bikesandhikes/assets/js/home.js?ver=1.0

js bikesandhikesla.com collected 2026-09-26 03:10:44 UTC 7,550 bytes, 200 lines download raw bytes

1// Logos slider - infinite seamless loop
2document.addEventListener("DOMContentLoaded", () => {
3    const prefersReducedMotion =
4        window.matchMedia &&
5        window.matchMedia("(prefers-reduced-motion: reduce)").matches;
6    const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
7    const saveData = !!(connection && connection.saveData);
8    const slowConnection =
9        !!(connection && typeof connection.effectiveType === "string" && /(^|-)2g$|3g/.test(connection.effectiveType));
10    const shouldAutoplayHeroVideo =
11        window.innerWidth >= 1024 && !prefersReducedMotion && !saveData && !slowConnection;
12
13    const logosContainer = document.querySelector(".logos");
14    const logosSlide = document.querySelector(".logos-slide");
15
16    if (logosContainer && logosSlide) {
17        const wrapper = document.createElement("div");
18        wrapper.className = "logos-track";
19
20        const clone = logosSlide.cloneNode(true);
21        clone.setAttribute("aria-hidden", "true");
22
23        wrapper.appendChild(logosSlide);
24        wrapper.appendChild(clone);
25        logosContainer.appendChild(wrapper);
26    }
27
28    // Hero slider video: start video for a label (load from data-src only when needed, show video, hide poster, play from start)
29    function startVideoForLabel(label) {
30        const video = label.querySelector("video");
31        if (!video || !video.dataset.src) return;
32        if (!video.src || video.src === window.location.href) {
33            video.src = video.dataset.src;
34            video.load();
35        }
36        const poster = label.querySelector(".video-poster");
37        if (poster) poster.style.display = "none";
38        video.style.display = "block";
39        video.currentTime = 0; // always start from beginning when switching to this slide
40        video.play().catch(() => {});
41        const btn = label.querySelector(".start-video");
42        if (btn) btn.classList.add("playing");
43    }
44
45    function pauseVideoForLabel(label) {
46        const video = label.querySelector("video");
47        if (video) video.pause();
48        const btn = label.querySelector(".start-video");
49        if (btn) btn.classList.remove("playing");
50    }
51
52    // On initial load: play video only for the checked hero slide (good for performance)
53    const checkedInput = document.querySelector(
54        'input[name="hero-slider"]:checked'
55    );
56    if (checkedInput && shouldAutoplayHeroVideo) {
57        const label = document.querySelector(`label[for="${checkedInput.id}"]`);
58        if (label) startVideoForLabel(label);
59    }
60
61    // Hero indicators + swipe (mobile): same behaviour as generic slider-nav
62    const heroSlidesWrap = document.querySelector(".hero-slider-slides");
63    const heroIndicators = document.querySelector("[data-hero-indicators]");
64    const heroPrevButton = document.querySelector("[data-hero-prev]");
65    const heroNextButton = document.querySelector("[data-hero-next]");
66    const heroInputs = document.querySelectorAll('input[name="hero-slider"]');
67    const totalHeroSlides = heroInputs.length;
68
69    function syncHeroIndicators() {
70        if (!heroIndicators) return;
71        const checked = document.querySelector(
72            'input[name="hero-slider"]:checked'
73        );
74        const idx = checked ? Array.from(heroInputs).indexOf(checked) : 0;
75        heroIndicators.querySelectorAll("li").forEach((li, i) => {
76            li.classList.toggle("is-active", i === idx);
77        });
78    }
79
80    function goToHeroSlide(index) {
81        const i = Math.max(0, Math.min(index, totalHeroSlides - 1));
82        const input = heroInputs[i];
83        if (input) {
84            input.checked = true;
85            input.dispatchEvent(new Event("change", { bubbles: true }));
86        }
87    }
88
89    function stepHeroSlide(direction) {
90        if (!totalHeroSlides) return;
91        const checked = document.querySelector('input[name="hero-slider"]:checked');
92        const currentIndex = checked ? Array.from(heroInputs).indexOf(checked) : 0;
93        const nextIndex = (currentIndex + direction + totalHeroSlides) % totalHeroSlides;
94        goToHeroSlide(nextIndex);
95    }
96
97    const heroForm = document.querySelector(".hero-slider-section form");
98    if (heroForm) {
99        heroForm.addEventListener("change", (e) => {
100            if (e.target.name !== "hero-slider" || e.target.type !== "radio")
101                return;
102            syncHeroIndicators();
103            const newLabel = document.querySelector(
104                `label[for="${e.target.id}"]`
105            );
106            if (newLabel && shouldAutoplayHeroVideo) startVideoForLabel(newLabel);
107            document
108                .querySelectorAll(".hero-slider-section label")
109                .forEach((l) => {
110                    if (l !== newLabel) pauseVideoForLabel(l);
111                });
112        });
113    }
114
115    if (heroIndicators) {
116        syncHeroIndicators();
117        heroIndicators.addEventListener("click", (e) => {
118            const btn = e.target.closest("button[data-page]");
119            if (btn) {
120                const page = parseInt(btn.dataset.page, 10);
121                goToHeroSlide(page);
122            }
123        });
124    }
125
126    if (heroPrevButton) {
127        heroPrevButton.addEventListener("click", () => stepHeroSlide(-1));
128    }
129
130    if (heroNextButton) {
131        heroNextButton.addEventListener("click", () => stepHeroSlide(1));
132    }
133
134    // Touch swipe on hero (mobile): swipe left = next, swipe right = prev
135    if (heroSlidesWrap && totalHeroSlides > 1) {
136        let touchStartX = 0;
137        heroSlidesWrap.addEventListener(
138            "touchstart",
139            (e) => {
140                touchStartX = e.changedTouches[0].clientX;
141            },
142            { passive: true }
143        );
144        heroSlidesWrap.addEventListener(
145            "touchend",
146            (e) => {
147                const touchEndX = e.changedTouches[0].clientX;
148                const diff = touchStartX - touchEndX;
149                const threshold = 50;
150                if (diff > threshold) stepHeroSlide(1);
151                else if (diff < -threshold) stepHeroSlide(-1);
152            },
153            { passive: true }
154        );
155    }
156
157    const videoButtons = document.querySelectorAll(".start-video");
158    videoButtons.forEach((button) => {
159        button.addEventListener("click", (event) => {
160            event.preventDefault();
161            event.stopPropagation();
162
163            const label = button.closest("label");
164            if (!label) return;
165
166            const video = label.querySelector("video");
167            if (!video) return;
168
169            if (!video.src && video.dataset.src) {
170                video.src = video.dataset.src;
171                video.load();
172            }
173
174            if (video.style.display === "none") {
175                video.style.display = "block";
176            }
177            const poster = label.querySelector(".video-poster");
178            if (poster) poster.style.display = "none";
179
180            if (video.paused) {
181                video.play();
182            } else {
183                video.pause();
184            }
185        });
186
187        const label = button.closest("label");
188        if (!label) return;
189        const video = label.querySelector("video");
190        if (!video) return;
191
192        video.addEventListener("play", () => button.classList.add("playing"));
193        video.addEventListener("pause", () =>
194            button.classList.remove("playing")
195        );
196        video.addEventListener("ended", () =>
197            button.classList.remove("playing")
198        );
199    });
200});

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.