PageSourceSearch

https://bishofit.com.ua/js/addons/bishofit_category/hero.js?ver=1791400217

js bishofit.com.ua collected 2026-10-07 22:55:21 UTC 14,365 bytes, 260 lines download raw bytes

1(function (w, d) {
2    'use strict';
3    function init(root) {
4        if (root.dataset.ready) { return; }
5        var viewport = root.querySelector('.bshhero__viewport');
6        var slides = Array.prototype.slice.call(viewport.children);
7        var dots = Array.prototype.slice.call(root.querySelectorAll('[data-slide]'));
8        var desktop = w.matchMedia('(min-width: 1024px)');
9        var phone = w.matchMedia('(max-width: 743px)');
10        var slideWidth = 0, alignAfterLayout = false, sizeObserver = null, layoutNeedsMeasure = false;
11        var reduced = w.matchMedia('(prefers-reduced-motion: reduce)');
12        var current = 0, copies = 0, step = 0, loop = false;
13        var frame = 0, settle = 0, timer = 0, hover = false, focused = false, touching = false, visible = true;
14        var scrollFrame = 0, scrolling = false, wanted = null, marked = -1, alignedTo = null;
15        var observedScrollLeft = 0;
16        var delay = Math.max(0, Number(root.dataset.delay) || 0);
17        var media = null;
18        root.dataset.ready = '1';
19        function originalOnError(img) {
20            if (!img || img.tagName !== 'IMG' || img.hasAttribute('data-bshhero-fallback')) { return; }
21            var picture = img.parentNode;
22            var source = picture && picture.querySelector('source[data-bshhero-original]');
23            if (!img.hasAttribute('srcset') && !source) { return; }
24            img.setAttribute('data-bshhero-fallback', '1');
25            if (source) {
26                source.setAttribute('srcset', source.getAttribute('data-bshhero-original'));
27                source.removeAttribute('sizes');
28            }
29            img.removeAttribute('srcset');
30            img.removeAttribute('sizes');
31        }
32        // Capture also covers loop clones. The original URL is already in src;
33        // if a native thumbnail is unavailable, retry the original once.
34        root.addEventListener('error', function (event) { originalOnError(event.target); }, true);
35        Array.prototype.forEach.call(root.querySelectorAll('img'), function (img) {
36            if (img.complete && !img.naturalWidth) { originalOnError(img); }
37        });
38        function mark(commit) {
39            if (marked !== current) {
40                if (dots[marked]) { dots[marked].removeAttribute('aria-current'); }
41                if (dots[current]) { dots[current].setAttribute('aria-current', 'true'); }
42                root.dataset.active = String(current);
43                marked = current;
44            }
45            // Moving dots must not start every video crossed during a swipe.
46            if (commit && media) { media.setCurrent(current); }
47        }
48        function stop() { w.clearTimeout(timer); timer = 0; }
49        function canAdvance() { return slides.length > 1 && (!desktop.matches || loop); }
50        function arm() {
51            stop();
52            if (!canAdvance() || !delay || scrolling || reduced.matches || (desktop.matches && hover) || focused || touching || !visible || d.hidden || !root.isConnected) { return; }
53            timer = w.setTimeout(function () {
54                if (!loop && current === slides.length - 1) { navigate(0, true); }
55                else { move(1); }
56            }, delay);
57        }
58        function jump(index, smooth) {
59            viewport.scrollTo({left: index * step, behavior: smooth && !reduced.matches ? 'smooth' : 'instant'});
60        }
61        function logical(physical) {
62            var index = physical - copies;
63            return loop ? ((index % slides.length) + slides.length) % slides.length
64                : Math.max(0, Math.min(slides.length - 1, index));
65        }
66        function beginScroll() {
67            stop();
68            if (!scrolling) {
69                scrolling = true;
70                if (media && media.setMoving) { media.setMoving(true); }
71            }
72        }
73        function settleSoon() {
74            w.clearTimeout(settle);
75            settle = w.setTimeout(finishScroll, 150);
76        }
77        function navigate(physical, smooth) {
78            if (!step) { return; }
79            wanted = logical(physical);
80            if (!canAdvance() || Math.abs(viewport.scrollLeft - physical * step) < 1) {
81                // A new click can cancel an animation before its first frame.
82                if (scrolling && canAdvance()) { jump(physical, false); }
83                w.clearTimeout(settle); settle = 0;
84                if (scrollFrame) { w.cancelAnimationFrame(scrollFrame); scrollFrame = 0; }
85                current = wanted;
86                scrolling = false; wanted = null;
87                mark(true);
88                if (media && media.setMoving) { media.setMoving(false); }
89                arm(); return;
90            }
91            alignedTo = null;
92            beginScroll(); jump(physical, smooth); settleSoon();
93        }
94        function move(delta) {
95            if (!step) { return; }
96            var target = (wanted === null ? current : wanted) + delta;
97            if (loop) { navigate(copies + target, true); }
98            else { navigate(Math.max(0, Math.min(slides.length - 1, target)), true); }
99        }
100        function clone(slide) {
101            var copy = slide.cloneNode(true);
102            copy.dataset.heroClone = '1';
103            copy.setAttribute('aria-hidden', 'true');
104            Array.prototype.forEach.call(copy.querySelectorAll('[id]'), function (el) { el.removeAttribute('id'); });
105            Array.prototype.forEach.call(copy.querySelectorAll('a,button,[tabindex]'), function (el) { el.setAttribute('tabindex', '-1'); });
106            Array.prototype.forEach.call(copy.querySelectorAll('img'), function (img) { img.removeAttribute('fetchpriority'); img.loading = 'lazy'; });
107            copy.removeAttribute('data-video-state');
108            Array.prototype.forEach.call(copy.querySelectorAll('video'), function (video) { video.removeAttribute('src'); video.preload = 'none'; });
109            return copy;
110        }
111        function measure() {
112            frame = 0;
113            if (!root.isConnected) { stop(); return; }
114            // ResizeObserver delivers the already-computed slide width. Reading
115            // offsetLeft here forced a document-wide layout during startup.
116            if (w.ResizeObserver) {
117                if (!slideWidth) { return; }
118                step = slideWidth + (desktop.matches ? 24 : (phone.matches ? 10 : 22));
119            } else {
120                var children = viewport.children;
121                step = children.length > 1 ? children[1].offsetLeft - children[0].offsetLeft : 0;
122            }
123            // Initial mobile position is already zero. Even scrollTo(0)
124            // can force layout, so only align after a real position change.
125            if (alignAfterLayout || current !== 0 || loop) {
126                alignedTo = (current + copies) * step;
127                jump(current + copies, false);
128                alignAfterLayout = false;
129            }
130            scrolling = false; wanted = null;
131            mark(true);
132            if (media && media.setMoving) { media.setMoving(false); }
133            arm();
134        }
135        function layout() {
136            stop();
137            w.clearTimeout(settle);
138            if (scrollFrame) { w.cancelAnimationFrame(scrollFrame); scrollFrame = 0; }
139            var nextLoop = desktop.matches && slides.length > 3;
140            if (nextLoop !== loop) {
141                alignAfterLayout = true;
142                Array.prototype.forEach.call(viewport.querySelectorAll('[data-hero-clone]'), function (el) { el.remove(); });
143                loop = nextLoop;
144                copies = loop ? 3 : 0;
145                if (loop) {
146                    var before = d.createDocumentFragment(), after = d.createDocumentFragment();
147                    slides.slice(-copies).forEach(function (slide) { before.appendChild(clone(slide)); });
148                    slides.slice(0, copies).forEach(function (slide) { after.appendChild(clone(slide)); });
149                    viewport.insertBefore(before, viewport.firstChild); viewport.appendChild(after);
150                }
151            }
152            root.dataset.loop = String(loop);
153            root.dataset.autoplay = String(canAdvance() && delay > 0 && !reduced.matches);
154            if (frame) { w.cancelAnimationFrame(frame); frame = 0; }
155            if (sizeObserver) {
156                // Clones and breakpoint styles must be laid out before scrollTo.
157                // A fresh observation also delivers when the slide width stayed
158                // the same, so reduced-motion and loop changes still settle.
159                layoutNeedsMeasure = true;
160                sizeObserver.unobserve(slides[0]);
161                sizeObserver.observe(slides[0]);
162            } else {
163                frame = w.requestAnimationFrame(measure);
164            }
165        }
166        function syncScroll() {
167            scrollFrame = 0;
168            if (!step || !root.isConnected) { return; }
169            // Native scroll events arrive before rAF. Reuse their position;
170            // reading it here after another addon's writes forced layout again.
171            current = logical(Math.round(Math.max(0, observedScrollLeft) / step));
172            mark(false);
173        }
174        function finishScroll() {
175            w.clearTimeout(settle); settle = 0;
176            if (!step || !scrolling || touching) { return; }
177            if (scrollFrame) { w.cancelAnimationFrame(scrollFrame); scrollFrame = 0; }
178            var physical = Math.round(Math.max(0, viewport.scrollLeft) / step);
179            current = logical(physical);
180            if (loop && (physical < copies || physical >= copies + slides.length)) {
181                alignedTo = (copies + current) * step;
182                jump(copies + current, false);
183            }
184            wanted = null; scrolling = false;
185            mark(true);
186            if (media && media.setMoving) { media.setMoving(false); }
187            arm();
188        }
189        viewport.addEventListener('scroll', function () {
190            // Read once before beginScroll/media/dot updates can change styles.
191            observedScrollLeft = viewport.scrollLeft;
192            if (alignedTo !== null && Math.abs(observedScrollLeft - alignedTo) < 1) {
193                alignedTo = null; return;
194            }
195            alignedTo = null;
196            beginScroll();
197            if (!scrollFrame) { scrollFrame = w.requestAnimationFrame(syncScroll); }
198            settleSoon();
199        }, {passive: true});
200        // Native scrollend includes momentum and snap completion. The timer
201        // remains a fallback for older browsers and never delays the paginator.
202        viewport.addEventListener('scrollend', finishScroll, {passive: true});
203        viewport.addEventListener('keydown', function (event) {
204            if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
205                event.preventDefault(); move(event.key === 'ArrowRight' ? 1 : -1);
206            } else if (event.key === 'Home' || event.key === 'End') {
207                event.preventDefault(); navigate(copies + (event.key === 'Home' ? 0 : slides.length - 1), true);
208            }
209        });
210        root.querySelector('.bshhero__prev').addEventListener('click', function () { move(-1); });
211        root.querySelector('.bshhero__next').addEventListener('click', function () { move(1); });
212        dots.forEach(function (dot, i) { dot.addEventListener('click', function () { navigate(copies + i, true); }); });
213        root.addEventListener('mouseenter', function () { if (desktop.matches) { hover = true; stop(); } });
214        root.addEventListener('mouseleave', function () { hover = false; arm(); });
215        root.addEventListener('focusin', function (event) { focused = desktop.matches || event.target.matches(':focus-visible'); if (focused) { stop(); } });
216        root.addEventListener('focusout', function (event) { focused = root.contains(event.relatedTarget); arm(); });
217        // Do not move the banner under a finger held on the carousel.
218        function hold(event) {
219            touching = true;
220            if (viewport.contains(event.target) && !event.target.closest('button')) { wanted = null; }
221            stop();
222        }
223        function release() { if (!touching) { return; } touching = false; if (scrolling) { settleSoon(); } else { arm(); } }
224        root.addEventListener(w.PointerEvent ? 'pointerdown' : 'touchstart', hold, {passive: true});
225        w.addEventListener(w.PointerEvent ? 'pointerup' : 'touchend', release, {passive: true});
226        w.addEventListener(w.PointerEvent ? 'pointercancel' : 'touchcancel', release, {passive: true});
227        viewport.addEventListener('wheel', function () { wanted = null; }, {passive: true});
228        d.addEventListener('visibilitychange', arm);
229        if (w.IntersectionObserver) {
230            new w.IntersectionObserver(function (entries) { visible = entries[0].isIntersecting; arm(); }).observe(root);
231        }
232        if (w.ResizeObserver) {
233            sizeObserver = new w.ResizeObserver(function (entries) {
234                var width = entries[0].contentRect.width;
235                if (!(width > 0) || (width === slideWidth && !layoutNeedsMeasure)) { return; }
236                slideWidth = width;
237                layoutNeedsMeasure = false;
238                if (frame) { w.cancelAnimationFrame(frame); }
239                // ResizeObserver supplies a completed layout. Align before this
240                // callback writes state, rather than defer to a dirty next rAF.
241                measure();
242            });
243        }
244        else { w.addEventListener('resize', layout, {passive: true}); }
245        [desktop, phone, reduced].forEach(function (query) {
246            if (query.addEventListener) { query.addEventListener('change', layout); }
247            else if (query.addListener) { query.addListener(layout); }
248        });
249        if (w.BishofitHeroMedia) {
250            media = w.BishofitHeroMedia(root, function (index) {
251                navigate(copies + index, false);
252            });
253        }
254        layout();
255    }
256    function scan() { Array.prototype.forEach.call(d.querySelectorAll('[data-bshhero]'), init); }
257    if (d.readyState === 'loading') { d.addEventListener('DOMContentLoaded', scan, {once: true}); }
258    else { scan(); }
259    if (w.Tygh && w.Tygh.$ && w.Tygh.$.ceEvent) { w.Tygh.$.ceEvent('on', 'ce.commoninit', scan); }
260}(window, document));

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.