PageSourceSearch

https://shop.nait.ca/eSolution_config/themes/Arrow/js/carousel-catalogue.js

js nait.ca collected 2026-09-24 18:25:57 UTC 3,439 bytes, 113 lines download raw bytes

1(function () {
2    const debounce = (fn, ms) => {
3        let t;
4        return (...args) => {
5            clearTimeout(t);
6            t = setTimeout(() => fn.apply(this, args), ms);
7        };
8    };
9
10    function perPage(root) {
11        const m = parseInt(root.dataset.perpageMobile || '2', 10);
12        const t = parseInt(root.dataset.perpageTablet || '2', 10);
13        const d = parseInt(root.dataset.perpageDesktop || '4', 10);
14
15        if (window.innerWidth <= 768) return m; // mobile
16        return d; // desktop
17    }
18
19    function initCatalogueCarousel(root) {
20        const wrapper  = root.querySelector('.carousel-track-wrapper');
21        const track    = root.querySelector('.carousel-track');
22        const cards    = Array.from(root.querySelectorAll('.carousel-card'));
23        const prev     = root.querySelector('.carousel-btn.prev');
24        const next     = root.querySelector('.carousel-btn.next');
25        const dotsWrap = root.querySelector('.carousel-indicators');
26
27        let currentIndex = 0;
28        let pages = 1;
29
30
31// carousel indicators
32        function buildDots() {
33            dotsWrap.innerHTML = '';
34
35            for (let i = 0; i < pages; i++) {
36                const dot = document.createElement('span');
37                dot.className = 'carousel-dot';
38
39                dot.addEventListener('click', () => {
40                    currentIndex = i * perPage(root);
41                    update();
42                });
43
44                dotsWrap.appendChild(dot);
45            }
46        }
47
48        function measure() {
49            const visibleCount = perPage(root);
50            pages = Math.max(1, Math.ceil(cards.length / visibleCount));
51
52            currentIndex = Math.min(
53                currentIndex,
54                Math.max(0, cards.length - visibleCount)
55            );
56
57            buildDots();
58            update();
59        }
60
61
62        function update() {
63            const card = cards[0];
64            if (!card) return;
65
66            const cardWidth = Math.round(card.getBoundingClientRect().width);
67            const visibleCount = perPage(root);
68
69            const maxIndex = Math.max(0, cards.length - visibleCount);
70            currentIndex = Math.min(currentIndex, maxIndex);
71
72            const translate = Math.round(currentIndex * cardWidth);
73            track.style.transform = `translate3d(-${translate}px, 0, 0)`;
74
75            // arrows
76            prev.classList.toggle('is-hidden', currentIndex === 0);
77            next.classList.toggle('is-hidden', currentIndex === maxIndex);
78
79            // dots (FIXED)
80            const activeDot = (currentIndex >= maxIndex)
81                ? pages - 1
82                : Math.floor(currentIndex / visibleCount);
83
84            dotsWrap.querySelectorAll('.carousel-dot')
85                .forEach((dot, i) =>
86                    dot.classList.toggle('active', i === activeDot)
87                );
88        }
89
90
91        /* ---------- carousel control buttons---------- */
92
93        prev.addEventListener('click', () => {
94            if (currentIndex > 0) {
95                currentIndex--;
96                update();
97            }
98        });
99
100        next.addEventListener('click', () => {
101            currentIndex++;
102            update();
103        });
104
105        window.addEventListener('resize', debounce(measure, 150));
106
107        measure();
108    }
109
110    document
111        .querySelectorAll('.catalogue-carousel')
112        .forEach(initCatalogueCarousel);
113})();

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.