PageSourceSearch

https://shop.zongoraszalon.hu/!common_packages/jquery/own/shop_com…ction_image_carousel.js?mod_time=1784016517

js zongoraszalon.hu collected 2026-10-08 03:18:55 UTC 10,047 bytes, 266 lines download raw bytes

1(function() {
2    let cardImagesObserverInitialized = false;
3
4    const cardImagesObserver = new IntersectionObserver((entries) => {
5        if (!cardImagesObserverInitialized) {
6            cardImagesObserverInitialized = true;
7            return;
8        }
9
10        entries.forEach(entry => {
11            const slide = entry.target;
12            const viewport = slide.parentElement;
13            const slides = Array.from(viewport.children);
14            const currentIndex = slides.indexOf(slide);
15            const card = viewport.closest('.js-product');
16            if (!card) return;
17
18            if (entry.isIntersecting) {
19                const currentImg = slide.classList.contains('js-alt-img')
20                    ? slide
21                    : slide.querySelector('.js-alt-img');
22
23                if (currentImg && currentImg.dataset.src) {
24                    preloadImage(currentImg);
25                }
26
27                const preloadAheadCount = 1;
28
29                for (let i = 1; i <= preloadAheadCount; i++) {
30                    const nextSlide = slides[currentIndex + i];
31                    if (!nextSlide) break;
32
33                    const nextImg = nextSlide.classList.contains('js-alt-img')
34                        ? nextSlide
35                        : nextSlide.querySelector('.js-alt-img');
36
37                    if (nextImg && nextImg.dataset.src) {
38                        preloadImage(nextImg);
39                    }
40                }
41            }
42
43            if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
44                const counter = card.querySelector('.product__img-count span');
45
46                if (counter) {
47                    counter.innerText = `${currentIndex + 1}/${slides.length}`;
48                }
49                updateButtons(card, currentIndex, slides.length);
50            }
51        });
52    }, {
53        threshold: [0.01, 0.5],
54        rootMargin: "0px 100px"
55    });
56
57    function preloadImage(img) {
58        if (!img || !img.dataset.src) return;
59
60        img.classList.add('placeholder', 'placeholder-wave');
61
62        if (img.dataset.srcset) {
63            img.srcset = img.dataset.srcset;
64            img.removeAttribute('data-srcset');
65        }
66        img.src = img.dataset.src;
67        img.removeAttribute('data-src');
68
69        const handleFinalize = () => {
70            img.classList.remove('placeholder', 'placeholder-wave');
71            img.classList.add('is-loaded');
72        };
73
74        // Megvárjuk, amíg a böngésző valóban ki tudja rajzolni a képet
75        img.decode()
76            .then(() => {
77                handleFinalize();
78            })
79            .catch(() => {
80                if (img.complete) {
81                    handleFinalize();
82                } else {
83                    img.addEventListener('load', handleFinalize, { once: true });
84                    img.addEventListener('error', handleFinalize, { once: true });
85                }
86            });
87    }
88
89    function updateButtons(card, currentIndex, total) {
90        const prevBtn = card.querySelector('.product__img-prev-btn');
91        const nextBtn = card.querySelector('.product__img-next-btn');
92        if (!prevBtn || !nextBtn) return;
93
94        prevBtn.disabled = currentIndex === 0;
95        nextBtn.disabled = currentIndex === total - 1;
96    }
97
98    window.initProductImageCarousels = function(container = document) {
99        if (typeof container === 'string') {
100            const selector = container.startsWith('#') || container.startsWith('.')
101                ? container
102                : `#${container}`;
103
104            container = document.querySelector(selector);
105            if (!container) return;
106        }
107
108        let cursor = document.getElementById('cursor');
109        const newViewports = container.querySelectorAll('.js-scrollable:not(.is-ready)');
110
111        newViewports.forEach(viewport => {
112            const card = viewport.closest('.js-product');
113            const slides = Array.from(viewport.querySelectorAll('img'));
114            let scrollTimeout;
115            let wheelTimeout;
116            let scrollEndTimeout;
117            let isThrottled = false;
118            let startX = 0;
119            let startY = 0;
120            let isHorizontal = null;
121            let firstIsPreloaded = false;
122
123            slides.forEach(slide => cardImagesObserver.observe(slide));
124
125            const preloadNextPending = (count = 1) => {
126                const nextImgs = Array.from(
127                    viewport.querySelectorAll('.js-alt-img[data-src]')
128                ).slice(0, count);
129
130                nextImgs.forEach(img => preloadImage(img));
131            };
132
133            const handleIsPaging = () => {
134                if (card) card.classList.add('is-paging');
135                clearTimeout(scrollTimeout);
136                scrollTimeout = setTimeout(() => {
137                    if (card) card.classList.remove('is-paging');
138                }, 3000);
139            };
140
141            const scrollToSlide = (direction) => {
142                const scrollAmount = viewport.offsetWidth * direction;
143                viewport.scrollTo({
144                    left: viewport.scrollLeft + scrollAmount,
145                    behavior: 'smooth'
146                });
147
148                handleIsPaging();
149
150                clearTimeout(scrollEndTimeout);
151                scrollEndTimeout = setTimeout(() => {
152                    isThrottled = false;
153                }, 300);
154            };
155
156            viewport.addEventListener('scrollend', () => {
157                clearTimeout(scrollEndTimeout);
158                isThrottled = false;
159            }, { passive: true });
160
161            const handleWheelThrottled = (e) => {
162                const isAtStart = viewport.scrollLeft <= 0;
163                const isAtEnd = Math.abs(viewport.scrollLeft + viewport.offsetWidth - viewport.scrollWidth) < 5;
164                const isScrollingRight = e.deltaY > 0;
165                const isScrollingLeft = e.deltaY < 0;
166
167                if ((isScrollingRight && !isAtEnd) || (isScrollingLeft && !isAtStart)) {
168                    if (isThrottled) return;
169                    const delta = e.deltaMode === 1 ? e.deltaY * 40 : e.deltaY;
170                    const direction = delta > 0 ? 1 : -1;
171                    isThrottled = true;
172                    scrollToSlide(direction);
173                }
174            };
175
176            const handleWheelPaging = (e) => {
177                if (viewport.scrollWidth > viewport.offsetWidth) {
178                    e.preventDefault();
179                    if (!localStorage.getItem('hasScrolled')) {
180                        localStorage.setItem('hasScrolled', '1');
181                        if (card) card.classList.remove('is-hovered');
182                        if (cursor) cursor.style.display = "none";
183                        viewport.removeEventListener('pointermove', moveCursorMovement);
184                    }
185                    handleWheelThrottled(e);
186                }
187            };
188
189            const moveCursorMovement = (e) => {
190                if (cursor) cursor.style.transform = `translate(${e.clientX - cursor.offsetWidth / 2}px, ${e.clientY - cursor.offsetHeight / 2}px)`;
191            };
192
193            const initButtons = () => {
194                const prevBtn = card.querySelector('.product__img-prev-btn');
195                const nextBtn = card.querySelector('.product__img-next-btn');
196                if (!prevBtn || !nextBtn) return;
197
198                prevBtn.addEventListener('click', () => scrollToSlide(-1));
199                nextBtn.addEventListener('click', () => scrollToSlide(1));
200
201                updateButtons(card, 0, slides.length);
202            };
203
204            viewport.addEventListener('pointerenter', (e) => {
205                wheelTimeout = setTimeout(() => {
206                    viewport.addEventListener('wheel', handleWheelPaging, { passive: false });
207                    if (!firstIsPreloaded) {
208                        preloadNextPending();
209                        firstIsPreloaded = true;
210                    }
211                }, 300);
212
213                if (e.pointerType !== 'mouse' || localStorage.getItem('hasScrolled')) return;
214                if (card) card.classList.add('is-hovered');
215                if (cursor) cursor.style.display = "block";
216                viewport.addEventListener("pointermove", moveCursorMovement);
217            });
218
219            viewport.addEventListener('pointerleave', (e) => {
220                if (e.pointerType !== 'mouse') return;
221
222                clearTimeout(wheelTimeout);
223                clearTimeout(scrollTimeout);
224                viewport.removeEventListener('wheel', handleWheelPaging);
225                if (card) card.classList.remove('is-paging', 'is-hovered');
226                viewport.removeEventListener('pointermove', moveCursorMovement);
227                if (cursor) cursor.style.display = "none";
228            });
229
230            viewport.addEventListener('touchstart', (e) => {
231                startX = e.touches[0].clientX;
232                startY = e.touches[0].clientY;
233                isHorizontal = null;
234
235                if (!firstIsPreloaded) {
236                    preloadNextPending(2);
237                    firstIsPreloaded = true;
238                }
239            }, { passive: true });
240
241            viewport.addEventListener('touchmove', (e) => {
242                const diffX = e.touches[0].clientX - startX;
243                const diffY = e.touches[0].clientY - startY;
244
245                if (isHorizontal === null) {
246                    isHorizontal = Math.abs(diffX) > Math.abs(diffY);
247                }
248
249                if (!isHorizontal) return;
250
251                handleIsPaging();
252            }, { passive: true });
253
254            viewport.addEventListener('touchend', () => {
255                isHorizontal = null;
256            }, { passive: true });
257
258            if (card) initButtons();
259
260            viewport.classList.add('is-ready');
261        });
262    };
263
264    const eventProductImageCarouselReady = new CustomEvent('productImageCarouselReady');
265    document.dispatchEvent(eventProductImageCarouselReady);
266})();

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.