PageSourceSearch

https://gpph-group.com/wp-content/themes/gpph/assets/cart-gpph-native/cart-loader.js

js gpph-group.com collected 2026-10-07 02:35:11 UTC 13,833 bytes, 423 lines download raw bytes

1(function ($) {
2    'use strict';
3
4    var autoUpdateTimer = null;
5    var cartLightboxInitialized = false;
6
7    function isMobileCartViewport() {
8        return window.matchMedia('(max-width: 767px)').matches;
9    }
10
11    function getBestImageSource(img) {
12        if (!img) {
13            return '';
14        }
15
16        if (img.currentSrc) {
17            return img.currentSrc;
18        }
19
20        var srcset = img.getAttribute('srcset') || '';
21        if (srcset) {
22            var candidates = srcset.split(',').map(function (entry) {
23                var parts = entry.trim().split(/\s+/);
24                return parts[0] || '';
25            }).filter(Boolean);
26
27            if (candidates.length) {
28                return candidates[candidates.length - 1];
29            }
30        }
31
32        return img.getAttribute('src') || '';
33    }
34
35    function ensureCartLightbox() {
36        if (!document.body || document.querySelector('.gpph-cart-lightbox')) {
37            return;
38        }
39
40        document.body.insertAdjacentHTML(
41            'beforeend',
42            '' +
43                '<div class="gpph-cart-lightbox" aria-hidden="true">' +
44                    '<div class="gpph-cart-lightbox__dialog" role="dialog" aria-modal="true" aria-label="Podglad produktu">' +
45                        '<button type="button" class="gpph-cart-lightbox__close" aria-label="Zamknij podglad">&times;</button>' +
46                        '<div class="gpph-cart-lightbox__media">' +
47                            '<img class="gpph-cart-lightbox__image" alt="">' +
48                        '</div>' +
49                    '</div>' +
50                '</div>'
51        );
52    }
53
54    function setCartLightboxState(isOpen, imageSrc, imageAlt) {
55        var lightbox = document.querySelector('.gpph-cart-lightbox');
56        if (!lightbox) {
57            return;
58        }
59
60        var image = lightbox.querySelector('.gpph-cart-lightbox__image');
61        if (!image) {
62            return;
63        }
64
65        if (isOpen) {
66            image.src = imageSrc || '';
67            image.alt = imageAlt || '';
68            lightbox.classList.add('is-open');
69            lightbox.setAttribute('aria-hidden', 'false');
70            document.body.classList.add('gpph-cart-lightbox-open');
71            return;
72        }
73
74        lightbox.classList.remove('is-open');
75        lightbox.setAttribute('aria-hidden', 'true');
76        document.body.classList.remove('gpph-cart-lightbox-open');
77        image.removeAttribute('src');
78        image.alt = '';
79    }
80
81    function bindCartLightboxEvents() {
82        if (cartLightboxInitialized) {
83            return;
84        }
85
86        ensureCartLightbox();
87        cartLightboxInitialized = true;
88
89        $(document).on('click.gpphCartLightbox', '.woocommerce-cart-form table.cart td.product-thumbnail a', function (event) {
90            if (!isMobileCartViewport()) {
91                return;
92            }
93
94            var img = this.querySelector('img');
95            var imageSrc = getBestImageSource(img);
96            if (!imageSrc) {
97                return;
98            }
99
100            event.preventDefault();
101            setCartLightboxState(true, imageSrc, (img && img.getAttribute('alt')) || '');
102        });
103
104        $(document).on('click.gpphCartLightbox', '.gpph-cart-lightbox, .gpph-cart-lightbox__close', function (event) {
105            if (
106                event.target.classList.contains('gpph-cart-lightbox') ||
107                event.target.classList.contains('gpph-cart-lightbox__close')
108            ) {
109                setCartLightboxState(false);
110            }
111        });
112
113        $(document).on('keydown.gpphCartLightbox', function (event) {
114            if (event.key === 'Escape') {
115                setCartLightboxState(false);
116            }
117        });
118    }
119
120    function parseNumber(value, fallbackValue) {
121        var parsed = parseFloat(value);
122        return Number.isFinite(parsed) ? parsed : fallbackValue;
123    }
124
125    function getQuantityMeta($input) {
126        var stepRaw = String($input.attr('step') || '1');
127        var step = parseNumber(stepRaw, 1);
128        var min = parseNumber($input.attr('min'), 0);
129        var max = parseNumber($input.attr('max'), Number.POSITIVE_INFINITY);
130
131        if (!Number.isFinite(step) || step <= 0) {
132            step = 1;
133            stepRaw = '1';
134        }
135
136        if (!Number.isFinite(min)) {
137            min = 0;
138        }
139
140        if (!Number.isFinite(max) || max <= 0) {
141            max = Number.POSITIVE_INFINITY;
142        }
143
144        var precision = 0;
145        if (stepRaw.indexOf('.') !== -1) {
146            precision = stepRaw.split('.')[1].length;
147        }
148
149        return {
150            min: min,
151            max: max,
152            step: step,
153            precision: precision
154        };
155    }
156
157    function normalizeValue(value, precision) {
158        var factor = Math.pow(10, precision);
159        return Math.round(value * factor) / factor;
160    }
161
162    function formatValue(value, precision) {
163        if (precision > 0) {
164            return normalizeValue(value, precision).toFixed(precision).replace(/\.?0+$/, '');
165        }
166
167        return String(Math.round(value));
168    }
169
170    function refreshStepperState($quantity) {
171        var $input = $quantity.find('input.qty').first();
172        if (!$input.length) {
173            return;
174        }
175
176        var meta = getQuantityMeta($input);
177        var current = parseNumber($input.val(), meta.min);
178        var epsilon = Math.pow(10, -(meta.precision + 2));
179        var $minus = $quantity.find('.gpph-cart-qty-btn--minus');
180        var $plus = $quantity.find('.gpph-cart-qty-btn--plus');
181
182        if ($minus.length) {
183            $minus.prop('disabled', current <= (meta.min + epsilon));
184        }
185
186        if ($plus.length) {
187            if (meta.max === Number.POSITIVE_INFINITY) {
188                $plus.prop('disabled', false);
189            } else {
190                $plus.prop('disabled', current >= (meta.max - epsilon));
191            }
192        }
193    }
194
195    function syncQuantitySteppers() {
196        if (!$('body').hasClass('woocommerce-cart')) {
197            return;
198        }
199
200        $('.woocommerce-cart-form .quantity').each(function () {
201            var $quantity = $(this);
202            var $input = $quantity.find('input.qty').first();
203
204            if (!$input.length) {
205                return;
206            }
207
208            if (!$quantity.find('.gpph-cart-qty-stepper').length) {
209                var $stepper = $('<div class="gpph-cart-qty-stepper" data-gpph-qty-stepper="1"></div>');
210                var $minus = $('<button type="button" class="gpph-cart-qty-btn gpph-cart-qty-btn--minus" aria-label="Zmniejsz ilosc">-</button>');
211                var $plus = $('<button type="button" class="gpph-cart-qty-btn gpph-cart-qty-btn--plus" aria-label="Zwieksz ilosc">+</button>');
212
213                $input.attr('inputmode', 'numeric');
214
215                $input.after($stepper);
216                $stepper.append($minus);
217                $stepper.append($input);
218                $stepper.append($plus);
219            }
220
221            refreshStepperState($quantity);
222        });
223    }
224
225    function bindQuantityStepperEvents() {
226        $(document).off('click.gpphCartQty', '.gpph-cart-qty-btn');
227        $(document).off('input.gpphCartQty change.gpphCartQty', '.woocommerce-cart-form .quantity input.qty');
228
229        function queueCartUpdate() {
230            clearTimeout(autoUpdateTimer);
231
232            autoUpdateTimer = setTimeout(function () {
233                var form = document.querySelector('form.woocommerce-cart-form');
234                var updateButton = form ? form.querySelector('[name="update_cart"]') : null;
235
236                if (!form || !updateButton) {
237                    return;
238                }
239
240                if (updateButton.classList.contains('loading')) {
241                    return;
242                }
243
244                updateButton.disabled = false;
245                updateButton.removeAttribute('disabled');
246
247                if (typeof form.requestSubmit === 'function') {
248                    form.requestSubmit(updateButton);
249                    return;
250                }
251
252                if (typeof updateButton.click === 'function') {
253                    updateButton.click();
254                    return;
255                }
256
257                form.submit();
258            }, 420);
259        }
260
261        $(document).on('click.gpphCartQty', '.gpph-cart-qty-btn', function (event) {
262            event.preventDefault();
263
264            var $button = $(this);
265            if ($button.prop('disabled')) {
266                return;
267            }
268
269            var $quantity = $button.closest('.quantity');
270            var $input = $quantity.find('input.qty').first();
271            if (!$input.length) {
272                return;
273            }
274
275            var meta = getQuantityMeta($input);
276            var current = parseNumber($input.val(), meta.min);
277            var direction = $button.hasClass('gpph-cart-qty-btn--plus') ? 1 : -1;
278            var next = current + (direction * meta.step);
279
280            if (next < meta.min) {
281                next = meta.min;
282            }
283            if (next > meta.max) {
284                next = meta.max;
285            }
286
287            next = normalizeValue(next, meta.precision);
288            if (next === current) {
289                refreshStepperState($quantity);
290                return;
291            }
292
293            $input.val(formatValue(next, meta.precision)).trigger('input').trigger('change');
294            $('button[name="update_cart"], input[name="update_cart"]').prop('disabled', false).removeAttr('disabled');
295
296            refreshStepperState($quantity);
297        });
298
299        $(document).on('input.gpphCartQty change.gpphCartQty', '.woocommerce-cart-form .quantity input.qty', function () {
300            refreshStepperState($(this).closest('.quantity'));
301            queueCartUpdate();
302        });
303    }
304
305    function initCartLoader() {
306        if (!$('body').hasClass('woocommerce-cart')) {
307            return;
308        }
309
310        var $root = $('.gpph-cart-native').first();
311        if (!$root.length || $root.data('gpphCartLoaderReady')) {
312            return;
313        }
314
315        $root.data('gpphCartLoaderReady', true);
316
317        if (!$root.find('.gpph-cart-native__loader').length) {
318            $root.append(
319                '<div class="gpph-cart-native__loader" aria-hidden="true">' +
320                    '<div class="gpph-cart-native__loader-card" role="status" aria-l
320ive="polite">' +
321                        '<span class="gpph-cart-native__loader-spinner" aria-hidden="true"></span>' +
322                        '<span class="gpph-cart-native__loader-text">Aktualizacja koszyka...</span>' +
323                    '</div>' +
324                '</div>'
325            );
326        }
327
328        var minVisibleMs = 320;
329        var safetyMs = 15000;
330        var startedAt = 0;
331        var safetyTimer = null;
332        var hideTimer = null;
333
334        function forceOff() {
335            clearTimeout(autoUpdateTimer);
336            clearTimeout(safetyTimer);
337            clearTimeout(hideTimer);
338            $root.removeClass('gpph-cart-native--is-loading').removeAttr('aria-busy');
339        }
340
341        function setOn() {
342            clearTimeout(hideTimer);
343
344            if ($root.hasClass('gpph-cart-native--is-loading')) {
345                return;
346            }
347
348            startedAt = Date.now();
349            $root.addClass('gpph-cart-native--is-loading').attr('aria-busy', 'true');
350
351            clearTimeout(safetyTimer);
352            safetyTimer = setTimeout(forceOff, safetyMs);
353        }
354
355        function setOff() {
356            if (!$root.hasClass('gpph-cart-native--is-loading')) {
357                return;
358            }
359
360            var elapsed = Date.now() - startedAt;
361            var delay = Math.max(0, minVisibleMs - elapsed);
362
363            clearTimeout(safetyTimer);
364            clearTimeout(hideTimer);
365
366            hideTimer = setTimeout(function () {
367                $root.removeClass('gpph-cart-native--is-loading').removeAttr('aria-busy');
368            }, delay);
369        }
370
371        function isCartAjax(url) {
372            if (!url) {
373                return false;
374            }
375
376            return (
377                url.indexOf('wc-ajax=update_shipping_method') !== -1 ||
378                url.indexOf('wc-ajax=update_cart') !== -1 ||
379                url.indexOf('wc-ajax=apply_coupon') !== -1 ||
380                url.indexOf('wc-ajax=remove_coupon') !== -1 ||
381                url.indexOf('wc-ajax=get_refreshed_fragments') !== -1
382            );
383        }
384
385        $(document).on('change', 'input[name^="shipping_method"]', setOn);
386        $(document).on('click', 'button[name="update_cart"], button[name="apply_coupon"], a.remove', setOn);
387        $(document).on('submit', 'form.woocommerce-cart-form', setOn);
388        $(document).ajaxSend(function (_event, _jqXHR, settings) {
389            if (isCartAjax(settings && settings.url)) {
390                setOn();
391            }
392        });
393
394        $(document).ajaxComplete(function (_event, _jqXHR, settings) {
395            if (isCartAjax(settings && settings.url)) {
396                setOff();
397            }
398        });
399
400        $(document.body).on(
401            'updated_wc_div updated_cart_totals applied_coupon removed_coupon wc_fragments_refreshed wc_fragment_refresh',
402            function () {
403                clearTimeout(autoUpdateTimer);
404                setOff();
405            }
406        );
407
408        $(window).on('pageshow', forceOff);
409    }
410
411    function initCartInteractions() {
412        initCartLoader();
413        bindQuantityStepperEvents();
414        syncQuantitySteppers();
415        bindCartLightboxEvents();
416    }
417
418    $(initCartInteractions);
419    $(document.body).on(
420        'updated_wc_div updated_cart_totals applied_coupon removed_coupon wc_fragments_refreshed wc_fragment_refresh',
421        initCartInteractions
422    );
423})(jQuery);

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.