PageSourceSearch

https://www.biurowi.pl/skins/user/rwd_primary_20/js/gc__user.js

js biurowi.pl collected 2026-09-30 02:27:23 UTC 128,446 bytes, 2,842 lines download raw bytes

1$(function GC__Fix__Header() {
2    if (gc__info_bar_placement == 1 && $('div#gc__info_box').length) {
3        $('body').addClass('gc__header__optimisation__off');
4    }
5    if ($('div#gc__info_box').length == 0) {
6        $('body').addClass('gc__no__infobox');
7    }
8});
9$(function GC__Fix() {
10    if (gc__rounded == 1) {
11        $('body').addClass('gc__rounded');
12    }
13    if (gc__bigger__listing == 1) {
14        $('body').addClass('gc__bigger__listing');
15    }
16});
17
18console.log("%c 🚀🎯 Modern 3.0 - włączam poszczególne moduły", "font-weight: 600; font-size: 12px; background: rgb(105,58,180); background: linear-gradient(117deg, rgba(105,58,180,1) 0%, rgba(253,29,29,1) 50%, rgba(90,69,252,1) 100%); color: #ffffff; padding: 4px 5px; border-radius: 15px");
19
20
21var gc__bestsellers__list = [];
22var gc__stored__bestsellers = JSON.parse(localStorage.getItem("gc__bestsellers__list"));
23var gc__favorites = JSON.parse(localStorage.getItem('gc__favorites')) || [];
24
25function GC__Generate__Mask() {
26    if ($('.gc__custom__mask').length == 0) {
27        $('<div class="mask gc__custom__mask gc__notactive"></div>').appendTo($('body'));
28    }
29}
30
31
32function GC__Turn__Off__Menu() {
33    if ($('.menu .innermenu .menu-list').hasClass('gc__active')) {
34        $('div.submenu > ul').removeClass('gc__active_submenu');
35        $('.menu .innermenu .menu-list').removeClass('gc__active');
36        $('body').removeClass('gc__scroll__block');
37        $('.mask.gc__custom__mask').toggleClass('gc__notactive gc__menu__on');
38    }
39}
40function GC__Turn__Off__Search() {
41    if ($('.gc__search__container').hasClass('gc__active__search') && $('.rwd header .logo-bar .search_open').hasClass('search_open')) {
42        $('.gc__search__container').removeClass('gc__active__search');
43        $('.rwd header .logo-bar .js__search').removeClass('search_open visible_block').addClass('none');
44    } else if ($('.gc__search__container').hasClass('.gc__active__search') && $('.rwd header .logo-bar .search_open:not(.search_open)').length > 0) {
45        $('.gc__search__container').toggleClass('gc__active__search');
46    }
47
48    else if ($('.gc__search__container:not(.gc__active__search)').length > 0 && $('.leftcol.s-grid-3.gc__active').length == 0 || $('.rwd header .logo-bar .search_open').hasClass('none')) {
49
50        if ($('.search_open').length > 0) {
51            $('.rwd header .logo-bar .search_open').addClass('search_open visible_block').removeClass('none');
52            $('.gc__search__container').toggleClass('gc__active__search');
53        } else {
54            $('.rwd header .logo-bar .js__search:not(.search_open)').addClass('search_open visible_block').removeClass('none');
55            $('.gc__search__container').toggleClass('gc__active__search');
56        }
57    }
58    else {
59        if ($('.leftcol.s-grid-3.gc__active').length == 0) {
60            $('.gc__search__container').toggleClass('gc__active__search');
61            $('.rwd header .logo-bar .js__search').toggleClass('search_open visible_block none');
62        }
63    }
64}
65function GC__Turn__Off__Basket() {
66    if ($('.basket-contain').hasClass('gc__active__basket')) {
67        $('.mask.gc__basket__on').toggleClass('gc__notactive gc__basket__on');
68        $('.basket-contain').removeClass('gc__active__basket');
69    }
70}
71
72
73
74
75$(document).ready(function () {
76    $('html .consents__modal .consents__heading').text(gc__cookie__management[Shop.lang.name]);
77    if (!$('body').is('[class^="shop_basket"]')) {
78        // Jeśli nie ma klasy zaczynającej się od "shop_basket", wykonaj ten kod
79        $('.gc__social__container').clone().insertBefore($('div#shoper-foot')).addClass('gc__footer__socials');
80    }
81    $('header .logo-bar .search-form .btn').attr('title', 'Szukaj');
82
83    $('.gc__icon__1 .gc__trustbadges__text').text(function (i, txt) { return txt.replace(/\d+/, gc__free__delivery__amount[Shop.lang.name] || gc__free__delivery__amount.en); });
84    if (gc__4__products__listing == 1) {
85        if ($('body').hasClass('shop_product_list')) {
86            $('body').addClass('gc__4__desktop');
87        } else if ($('body').hasClass('shop_index')) {
88            $('body').addClass('gc__5__desktop');
89        }
90    }
91    if (gc__image__helper == 1) {
92        $('body').addClass('gc__image__helper');
93    }
94    if (gc__image__resizer == 1) {
95        $('body').addClass('gc__image__resizer');
96    }
97    if (gc__sticky__menu__desktop == 1) {
98        $('.menu').addClass('gc__sticky');
99    }
100    if (gc__enable__price__line__through == 1){
101        $('body').addClass('gc__price__line__thru');
102    }
103   // $('#box_description [title~="YouTube"]').addClass('gc__video').parent().addClass('gc__video__holder');
104
105    $('.gc__temp__loupe, .gc__close__search, li#activ-search, .js__search-close-btn').click(function () {
106        GC__Turn__Off__Search();
107        GC__Turn__Off__Basket();
108        GC__Turn__Off__Menu();
109    });
110
111    $('.gc__temp__loupe').click(function () {
112        $('.search__input[type="search"]').focus().click();
113    });
114
115    $('.box#box_filter ul li.priceinput input').on('change focus', function () {
116        $('.box#box_filter ul li.priceinput .bottombuttons').fadeIn();
117    });
118
119    if ($('.gc__shipping .gc__free__delivery').length == 0) {
120        $('<div class="gc__free__delivery">' + gc__free__delivery[Shop.lang.name] + '</div>').appendTo($('.gc__shipping'));
121    }
122
123    $('.rwd .menu .innermenu li a.fa-user').attr('href', function () {
124        return $('.gc__myaccount__holder a.gc__fav__main').attr('href');
125    });
126});
127
128$(document).ready(function () {
129    $.fn.visible = function (partial, hidden) {
130        var $t = $(this).eq(0),
131            t = $t.get(0),
132            $w = $(window),
133            viewTop = $w.scrollTop(),
134            viewBottom = viewTop + $w.height(),
135            _top = $t.offset().top,
136            _bottom = _top + $t.height(),
137            compareTop = partial === true ? _bottom : _top,
138            compareBottom = partial === true ? _top : _bottom,
139            clientSize = hidden === true ? t.offsetWidth * t.offsetHeight : true;
140        return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop));
141    };
142
143    function GC__Check__Products() {
144        $(".product").not('.gc__badges__applied').each(function () {
145            if (!$(this).hasClass("gc__loaded") && $(this).visible(true)) {
146                const gc__current__product = $(this);
147                $(this).addClass('gc__loaded'); // Oznacz produkt jako załadowany
148                
149                
150                const gc__prod__id = gc__current__product.attr('data-product-id');
151                if (gc__prod__id > 1) {
152                    if ($('p.logout').length !== 0) {
153                        $('<div class="gc__list__add"><div class="gc__product__badge"><a href="/pl/fav/add/' + gc__prod__id + '" title="' + gc__text__to__favorites[Shop.lang.name] + '" class="gc__addtofav"><span class="gc__span__holder">' + gc__text__to__favorites[Shop.lang.name] + '</span><img src="/skins/user/' + gc__images__version + '/images/user/gc__heart.svg" alt="' + gc__text__to__favorites[Shop.lang.name] + '"></a></div></div>').insertAfter(gc__current__product.find($('a')))
154                    } else {
155                        $('<div class="gc__list__add"><div class="gc__product__badge"><div value="' + gc__prod__id + '" title="' + gc__text__to__favorites[Shop.lang.name] + '" class="gc__addtofav"><div class="gc__span__holder">' + gc__text__to__favorites[Shop.lang.name] + '</div><svg data-v-7df6b261="" data-v-c36c587c="" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" role="presentation" class="svg" data-v-6eb481ef=""><g data-v-7df6b261="" fill="currentColor" stroke="currentColor"><svg data-v-c36c587c="" data-v-7df6b261="" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="svg-icon"><path data-v-c36c587c="" data-v-7df6b261="" d="M11.9 7.696C11.9 4.67 9.682 3 6.948 3 3.649 3 2.035 5.348 2 8.478 2 12.783 6.949 16.304 11.9 21c4.95-4.696 9.9-8.217 9.9-12.522C21.765 5.348 20.151 3 16.85 3c-2.734 0-4.95 1.67-4.95 4.696z" stroke-width="2" stroke-linecap="round"></path></svg></g></svg></a></div></div>').appendTo(gc__current__product)
156                    }
157                }
158                const gc__product__tags = gc__current__product.find('.tags');
159                let gc__badge__holder = gc__current__product.find('.gc__badge__holder');
160                if (gc__product__tags.length > 0) {
161                    if (gc__badge__holder.length === 0) {
162                        // Tworzenie .gc__badge__holder, jeśli nie istnieje
163                        $('<div class="gc__badge__holder gc__skeleton"></div>').insertBefore(gc__current__product.find('span.productname').parent());
164                        // Ponowne przypisanie zmiennej gc__badge__holder po wstawieniu nowego elementu
165                        gc__badge__holder = gc__current__product.find('.gc__badge__holder');
166                    }
167                    // Przeniesienie tagów produktu do .gc__badge__holder
168                    gc__product__tags.appendTo(gc__badge__holder);
169                    gc__badge__holder.removeClass('gc__skeleton');
170                } else {
171                    if (gc__badge__holder.length === 0) {
172                        // Wstawienie .gc__badge__holder z pustą listą tagów, jeśli nie istnieje i nie ma tagów produktu
173                        $('<div class="gc__badge__holder gc__skeleton"><ul class="tags"></ul></div>').insertBefore(gc__current__product.find('span.productname').parent());
174                        gc__current__product.find('.gc__badge__holder').removeClass('gc__skeleton');
175                    }
176                }
177                
178
179
180                let gc__box__check = gc__current__product.closest($('.box'));
181                if (gc__box__check.attr('id') == 'box_bestsellers' 
182    && !gc__box__check.hasClass('gc__same__product__category__holder') 
183    && !gc__box__check.hasClass('gc__classic__related')) {
184                    if ($.isNumeric(gc__prod__id)) {
185                        // if (gc__current__product.find('.bestseller').length > 0) { // dodatkowy warunek
186                        gc__bestsellers__list.push(gc__prod__id);
187                        //console.log('gc__bestsellers__list.push(gc__prod__id); dodaję nowego bestsellera o id '+gc__prod__id);
188                        localStorage.setItem("gc__bestsellers__list", JSON.stringify(gc__bestsellers__list));
189                        //}
190                       
191                    }
192                } if (gc__box__check.attr('id') == 'box_specialoffer') { 
193                    $('<li class="promo"><span>' + gc__promo__badge[Shop.lang.name] + '</span></li>').appendTo($(gc__current__product).find($('.gc__badge__holder ul.tags')));
194                } 
195                if (gc__box__check.attr('id') == 'box_lastadded') {
196                    $('<li class="new"><span>' + gc__tag__translations[Shop.lang.name] + '</span></li>').appendTo($(gc__current__product).find($('.gc__badge__holder ul.tags')));
197                }
198
199                if (gc__current__product.find('del.price__inactive').length > 0 && gc__current__product.find('.tags .promo').length == 0) {
200                
201                    $('<li class="promo"><span>' + gc__promo__badge[Shop.lang.name] + '</span></li>').appendTo($(gc__current__product).find($('.gc__badge__holder ul.tags')));
202                }
203
204
205                if ($(gc__current__product).find('.tags').length !== 0) {                       
206                    if ($(gc__current__product).find('.tags .promo').length === 1) {
207                        const gc__this = $(gc__current__product);
208                        const gc__promo__priceText = $(gc__this).find("div.price > p > em").text().replace(/[^0-9,]/g, '').replace(',', '.');
209                        const gc__regular__priceText = $(gc__this).find("del.price__inactive").text().replace(/[^0-9,]/g, '').replace(',', '.');
210                        const gc__promo__price = parseFloat(gc__promo__priceText);
211                        const gc__regular__price = parseFloat(gc__regular__priceText);
212                        const gc__promo = Math.round((1 - (gc__promo__price / gc__regular__price)) * 100);
213                    
214                        // Sprawdź, czy obliczony procent rabatu jest liczbą
215                        if (!isNaN(gc__promo) && Math.abs(gc__promo) >= gc__min__discount__threshold) {
216                            // Stwórz nowy element <li> z odpowiednią klasą i tekstem, informującym o procentach rabatu
217                            const newPromoLi = $('<li></li>').addClass('promo gc__promo__percent').text(gc__promo + '%');
218                            // Dodaj nowy element <li> do listy <ul class="tags">
219                            $(gc__this).find('.tags').prepend(newPromoLi); // Używamy prepend(), aby dodać na początku listy
220                        }
221                    }
222                } 
223                if (jQuery.inArray(gc__prod__id, gc__stored__bestsellers) === -1) {
224                } else {
225                    $('<li class="bestseller"><span>' + gc__bestseller__badge[Shop.lang.name] + '</span></li>').appendTo($(gc__current__product).find($('.gc__badge__holder ul.tags')));
226                }
227                if (gc__new__custom__badge == 1) {
228                    Object.keys(gc__new__custom__badge__names).forEac
228h(function (gc__new__badge) {
229                        if (jQuery.inArray(gc__prod__id, gc__new__custom__badge__names[gc__new__badge]) === -1) {
230                        } else {
231                            // Pobranie tłumaczenia dla aktualnego języka
232                            let badgeTranslation = gc__new__badge;
233                            if (Shop.lang.name !== 'pl_PL' && badge_translations[gc__new__badge]) {
234                                badgeTranslation = badge_translations[gc__new__badge][Shop.lang.name];
235                            }
236        
237                            if ($(gc__current__product).find('.tags').length !== 0) {
238                                $('<li class="gc__custom__badge ' + gc__new__badge + '"><span>' + badgeTranslation + '</span></li>').appendTo($(gc__current__product).find($('.tags')));
239                            } 
240                        }
241                    });
242                }
243
244                // ===== ZBIORCZA METKA (Black Friday, Cyber Monday itp.) =====
245                if (typeof gc__bulk__badge__mode !== 'undefined' && gc__bulk__badge__mode != 0) {
246                    let should_add_bulk = false;
247
248                    if (gc__bulk__badge__mode == 2) {
249                        // Tryb 2: dodaj do wszystkich produktów
250                        should_add_bulk = true;
251                    } else if (gc__bulk__badge__mode == 1) {
252                        // Tryb 1: dodaj tylko do produktów z metką promo
253                        should_add_bulk = $(gc__current__product).find('.gc__badge__holder ul.tags .promo').length > 0;
254                    }
255
256                    if (should_add_bulk) {
257                        $('<li class="gc__bulk__badge"><span>' + gc__bulk__badge__text[Shop.lang.name] + '</span></li>')
258                            .appendTo($(gc__current__product).find($('.gc__badge__holder ul.tags')));
259                    }
260                }
261
262                gc__current__product.addClass('gc__badges__applied'); // Dodaj klasę sygnalizującą, że odznaka została dodana
263            }
264        });
265    }
266
267    function gc__init__24h__Badge() {
268 
269        // Pobierz ID produktów, które są widoczne (załadowane) i nie mają jeszcze odznaki
270        var gc__productIds = $('.product.gc__loaded').not('.gc__24h__applied').map(function () {
271            return $(this).data('product-id');
272        }).get();
273    
274        if (gc__productIds.length > 0) {
275            frontAPI.getProducts(function (gc__products) {
276                $.each(gc__products.list, function (index, gc__product) {
277                    var gc__productId = gc__product.id;
278                    var gc__deliveryHours = parseInt(gc__product.delivery.hours, 10);
279    
280                    if (gc__deliveryHours === gc__settings.gc__24h__badge__hours__countdown) {
281                        var gc__productElement = $('.product[data-product-id="' + gc__productId + '"]');
282                        var gc__tagsElement = gc__productElement.find('ul.tags');
283                    
284                        var gc__translation = gc__settings.gc__tag__translations[Shop.lang.name];
285                        var gc__badgeElement = '<li class="gc__24h__badge">' + gc__translation + '</li>';
286                    
287                        if (gc__tagsElement.length) {
288                            gc__tagsElement.append(gc__badgeElement);
289                            gc__productElement.addClass('gc__24h__applied'); // Dodaj klasę sygnalizującą, że odznaka została dodana
290                        } 
291                    }
292                });
293            }, {
294                ids: gc__productIds
295            });
296        }
297    }
298    var gc__scrollTimeout;
299    GC__Check__Products();
300    $(window).scroll(function (event) {
301        clearTimeout(gc__scrollTimeout);
302        gc__scrollTimeout = setTimeout(function() {
303            GC__Check__Products();
304            if (!gc__settings.gc__24h__badge__on__off) return; // Sprawdź, czy odznaka 24h jest włączona
305            gc__init__24h__Badge();
306        }, 100); // Opóźnienie 100ms
307    });
308});
309
310
311$('li.promo:not(.gc__promo__percent), li.promo:not(.gc__promo__percent) > span').text(gc__promo__badge[Shop.lang.name]);
312$('#box_productfull .basket .form-basket .button_wrap .availability-notifier-btn').parent().addClass('gc__resize');
313$(function GC__Mobile__WishList() {
314
315    $('.rwd .menu .innermenu li a.fa-user').attr('disabled', true);
316    $('header .logo-bar .gc__favourite__holder a.gc__fav__main .heartMain, .menu-mobile .small-panel').click(function () {
317        if ($(window).width() < 767) {
318            $('header .logo-bar .gc__favourite__holder .gc__content').toggleClass('gc__heart__active');
319            GC__Generate__Mask();
320            $('.mask.gc__custom__mask').toggleClass('gc__notactive gc__wishlist__on');
321        }
322    });
323    $('li.gc__login__holder, .mask.gc__custom__mask.gc__login__mask').click(function () {
324        if ($(window).width() < 767) {
325            $('.gc__mobile__login__content, .gc__mobile__login__content .gc__choose__login').toggleClass('gc__login__on');
326            GC__Generate__Mask();
327            $('.mask.gc__custom__mask').toggleClass('gc__notactive gc__login__mask');
328        }
329    });
330
331});
332
333//$(function GC__Footer__Fix() {
334    //if ($('footer .userfooter').height() > 10 && $(window).width() > 980) {
335      //  $('footer.footer').addClass('gc__footer__enchanced');
336   // }
337//});
338
339function GrowCommerceNewsletterCheckbox(gc__val, gc__check, gc__newsletter_button, gc__mail__error) {
340    function gc__disable() {
341        gc__newsletter_button.prop("disabled", !gc__check.prop('checked'));
342    }
343
344    gc__disable();
345
346    gc__check.prop('checked', false).on('change', function () {
347        if (/^[a-z0-9][a-z0-9-_\.]+@([a-z]|[a-z0-9]?[a-z0-9-]+[a-z0-9])\.[a-z0-9]{2,10}(?:\.[a-z]{2,10})?$/.test(gc__val.val())) {
348            if (!gc__check.prop('checked')) {
349                gc__disable();
350                gc__mail__error.text(gc__newsletter__checkbox[Shop.lang.name]).addClass('gc__shown').addClass('gc__red');
351            } else {
352                gc__newsletter_button.removeAttr("disabled");
353                gc__mail__error.removeClass('gc__shown').removeClass('gc__red');
354            }
355        } else {
356            gc__mail__error.text(gc__newsletter__error[Shop.lang.name]).addClass('gc__shown').addClass('gc__red');
357        }
358    });
359
360    gc__val.on('change', function () {
361        if (/^[a-z0-9][a-z0-9-_\.]+@([a-z]|[a-z0-9]?[a-z0-9-]+[a-z0-9])\.[a-z0-9]{2,10}(?:\.[a-z]{2,10})?$/.test(gc__val.val())) {
362            if (!gc__check.prop('checked')) {
363                gc__disable();
364                gc__mail__error.text(gc__newsletter__checkbox[Shop.lang.name]).addClass('gc__shown').removeClass('gc__red');
365                $('.gc__hide__info').addClass('gc__shown');
366            } else {
367                gc__newsletter_button.removeAttr("disabled");
368                gc__mail__error.removeClass('gc__shown').removeClass('gc__red');
369            }
370        } else {
371            gc__mail__error.text(gc__newsletter__error[Shop.lang.name]).addClass('gc__shown').addClass('gc__red');
372            $('.gc__hide__info').addClass('gc__shown');
373        }
374    });
375}
376
377$(document).ready(function () {
378    var gc__val, gc__check, gc__newsletter_button, gc__mail__error;
379
380    if ($('#box_newsletter').length) {
381        // Klasyczny newsletter
382        gc__val = $('.box#box_newsletter form.gc__new__input fieldset input.newsletter-input');
383        gc__check = $('#box_newsletter #gc_check');
384        gc__newsletter_button = $('#box_newsletter .innerbox form fieldset button.btn.btn-red');
385        gc__mail__error = $('.gc__errors__spacer');
386    } else if ($('#box__newsletter__growcommerce').length) {
387        // Nowy tryb slidera
388        gc__val = $('.box#box__newsletter__growcommerce form.gc__new__input fieldset input.newsletter-input');
389        gc__check = $('#box__newsletter__growcommerce #gc_check');
390        gc__newsletter_button = $('#box__newsletter__growcommerce .innerbox form fieldset button.btn.btn-red');
391        gc__mail__error = $('.gc__errors__spacer');
392    }
393
394    if (gc__val && gc__check && gc__newsletter_button && gc__mail__error) {
395        GrowCommerceNewsletterCheckbox(gc__val, gc__check, gc__newsletter_button, gc__mail__error);
396    }
397});
398
399$(function GC__Fix__Producer__Desc() {
400    if ($('body').hasClass('shop_product_producer') && $('.categorydesc').length) {
401        let gc__long__desc = $('.categorydesc').html().split('[long_desc]')[1];
402        let gc__short__desc = $('.categorydesc').html().split('[long_desc]')[0];
403        $('.categorydesc').html(gc__short__desc);
404        $("<div>").addClass('categorydesc resetcss row longdesc').html(gc__long__desc).insertAfter($('#box_mainproducts > div.innerbox'));
405    }
406});
407
408
409
410const gc__orginalTitle = document.title;
411let nIntervId = null;
412
413function gc__flashText() {
414    try {
415        const newText = gc__newTitle[Shop.lang.name] || gc__newTitle.pl_PL;
416        document.title = document.title === gc__orginalTitle ? newText : gc__orginalTitle;
417    } catch (e) {
418        console.error('Błąd mrugania tytułem:', e);
419        document.title = gc__orginalTitle;
420    }
421}
422
423$(function gc__changeTitle() {
424    if (gc__newTitle__on__off === '1') {
425        $(window).on({
426            'blur': function() {
427                if (!nIntervId) {
428                    nIntervId = setInterval(gc__flashText, 1100);
429                    gc__flashText(); // Natychmiastowa pierwsza zmiana
430                }
431            },
432            'focus': function() {
433                if (nIntervId) {
434                    clearInterval(nIntervId);
435                    nIntervId = null;
436                    document.title = gc__orginalTitle;
437                }
438            },
439            'beforeunload': function() {
440                if (nIntervId) clearInterval(nIntervId);
441            }
442        });
443    }
444});
445
446
447$(function GC__Mobile__Menu() {
448    const menuSelector = '.rwd .menu .innermenu li.small-menu';
449    const imageSrcBase = `/skins/user/${gc__images__version}/images/user/`;
450
451    const menuHeadHtmlGenerator = (isMain = false) => {
452        const menuBackHolderHtml = isMain ? `<a href="/" rel="nofollow" title="${gc__text__mainpage[Shop.lang.name]}"><img alt="${gc__back[Shop.lang.name]}" src="${imageSrcBase}gc__arrow__down.svg" class="gc__back" title="${gc__back[Shop.lang.name]}"><img src="${imageSrcBase}gc__home.svg" class="gc__home" alt="${gc__text__mainpage[Shop.lang.name]}" title="${gc__text__mainpage[Shop.lang.name]}"></a>` : `<img src="${imageSrcBase}gc__arrow__down.svg" class="gc__back" alt="${gc__text__menu[Shop.lang.name]}">${gc__text__menu[Shop.lang.name]}`;
453        return `<div class="gc__menu__head"><div class="gc__back__holder">${menuBackHolderHtml}</div><div class="gc__close__holder"><img alt="${gc__close[Shop.lang.name]}" src="${imageSrcBase}gc__close.svg" style="height: 16px;" class="gc__close"></div></div>`;
454    }
455
456    const prependMenuHeadHtml = (selector, isMain = false) => {
457        $(selector).prepend(menuHeadHtmlGenerator(isMain));
458    }
459
460    prependMenuHeadHtml('ul.menu-list.large.standard', true);
461    $('ul.menu-list.large.standard .gc__menu__head').after(`<div class="gc__catname__holder"><span class="gc__menu__catname">${gc__text__menu[Shop.lang.name]}</span></div>`);
462    prependMenuHeadHtml('ul[class*="level"]:not(.menu-list.large.standard)');
463
464    function updateMenuHeadLink() {
465        $('.submenu > ul').each(function () {
466            var $this = $(this);
467            var gc__current__li = $this.parent('.submenu').parent('li.parent');
468
469            var gc__menu__cat__name = gc__current__li.find('a').first().text(); // bezpośrednie odwołanie do 'a'
470            var gc__menu__href = gc__current__li.find('a').first().attr('href');
471
472            if ($this.find('.gc__catname__holder').length === 0) {
473                var gcCatnameHolderHtml = `<div class="gc__catname__holder"><span class="gc__menu__catname">${gc__menu__cat__name}</span><a href="${gc__menu__href}" title="${gc__menu__cat__name}" id="headlink" class="spanhover mainlevel gc__menu__headlink">${gc__text__seeall[Shop.lang.name]}</a></div>`;
474                $this.find('.gc__menu__head').after(gcCatnameHolderHtml);
475            } else {
476                // Aktualizuj istniejący element
477                $this.find('.gc__menu__headlink').attr('href', gc__menu__href).attr('title', gc__menu__cat__name).text(`${gc__text__seeall[Shop.lang.name]}`);
478                $this.find('.gc__menu__catname').text(gc__menu__cat__name); // Aktualizuj nazwę kategorii
479            }
480        });
481    }
482
483    // Wywołaj funkcję przy ładowaniu strony
484    updateMenuHeadLink();
485
486    // Wywołaj funkcję za każdym razem, gdy kategoria jest zmieniana
487    $(document).on('click', '.menu .innermenu .menu-list li.parent > a', function (event) {
488        if (window.matchMedia('(max-width: 980px)').matches) {
489            event.preventDefault();
490            var $submenu = $(this).next('.submenu').find('ul:first');
491            $submenu.slideToggle(function () { // Zamiast .toggleClass
492                $('.menu .innermenu .parent div ul[class*="level"]').removeClass('gc__current__ul');
493                $submenu.addClass('gc__active_submenu gc__current__ul').removeClass('gc__scroll__block'); // Dodaj klasę po ukończeniu animacji
494                //  $('.menu .innermenu .parent div ul[class*="level"]:not(.gc__current__ul)').addClass('gc__scroll__block');
495                updateMenuHeadLink(); // Wywołaj funkcję po ukończeniu animacji
496            });
497
498        }
499    });
500
501    $(document).on('click', '.gc__turn__menu, .gc__close__holder, .mask.gc__custom__mask.gc__menu__on', function () {
502        GC__Turn__Off__Basket();
503        $('.menu .innermenu .menu-list').toggleClass('gc__active');
504        $('body').toggleClass('gc__scroll__block');
505        $('.menu .innermenu .parent div ul[class*="level"]').removeClass('gc__current__ul');
506        GC__Generate__Mask();
507        $('.mask.gc__custom__mask').toggleClass('gc__notactive gc__menu__on');
508    });
509
510    $(document).on('click', '.gc__back__holder', function () {
511        $(this).closest('.gc__active_submenu').removeClass('gc__active_submenu');
512        $(this).closest('ul[class*="level"]').removeClass('gc__scroll__block');
513    });
514});
515
516$(document).on("click", ".search .js__search-close-btn", function () {
517    GC__Turn__Off__Search();
518    GC__Turn__Off__Basket();
519    GC__Turn__Off__Menu();
520});
521
522$(document).on("click", ".gc__filters__on", function () {
523    $('.mask.gc__custom__mask').toggleClass('gc__notactive gc__filters__on');
524    GC__Turn__Off__Search();
525    GC__Turn__Off__Basket();
526    GC__Turn__Off__Menu();
527    GC__Close__Filters__Mobile();
528});
529$(document).on("click", ".search_open-empty .search__content, .search_open .search__input-area .js__search-close-btn", function () {
530    GC__Turn__Off__Search();
531    GC__Turn__Off__Basket();
532    GC__Turn__Off__Menu();
533    $('.rwd header .logo-bar .search_open').removeClass('search_open visible_block').addClass('none');
534});
535
536
537
538$(function GC__Basket() {
539    $('header .basket:not(.empty-basket) > a, .rwd li.small-cart a').click(function () {
540        if ($('.basket-contain ul li').length) {
541            event.preventDefault();
542            $('.basket-contain').toggleClass('gc__active__basket');
543            $(this).toggleClass('gc__basket__is__on');
544        }
545        GC__Turn__Off__Menu();
546        GC__Generate__Mask();
547        $('.mask.gc__custom__mask').toggleClass('gc__notactive  gc__basket__on');
548    });
549
550
551});
552$(document).on("click", ".gc__basket__on, gc__basket__is__on, .gc__close__menu__holder, .gc__continue__shopping", function GC__BasketMask() {
553    GC__Turn__Off__Basket()
554});
555
556$(function GC__Local__GC__Favorites() {
557    if ($('p.logout').length == 0) {
558        $('.gc__favourite__holder a.gc__fav__main').attr('disabled', true);
559        gc__favorites.forEach(function (favorite) {
560            $('.gc__addtofav[value="' + favorite + '"]').addClass('gc__fav').find('.gc__span__holder').text(gc__text__in__fav[Shop.lang.name]);
561
562        });
563    }
564});
565function gc__updateFavoriteCount() {
566    let gc__empty__container = $('.gc__myaccount__holder .gc__favourite__holder .gc__content .gc__empty__container');
567    if (gc__favorites.length > 0) {
568        gc__empty__container.hide();
569        $('b.count.gc__count').show().find('span').text(gc__favorites.length);
570    } else {
571        gc__empty__container.show(); 
572        $('b.count.gc__count').hide();
573    }
574}
575function gc__getProductFromAPI(id) {
576    setTimeout(() => {
577    frontAPI.getProduct(function (product) {
578      let gc__fav__image = '/environment/cache/images/150_150_productGfx_' + product.main_image_filename;
579      let gc__fav__name = product.name;
580      let gc__fav__url = product.url;
581  
582      // Construct the HTML for the favored item, including elements from your original code
583      let gc__fav__item_html = `
584        <div class="gc__favored__item">
585          <img src="${gc__fav__image}" title="${gc__fav__name}" alt="${gc__fav__name}">
586          <span class="gc__fav__name">${gc__fav__name}</span>
587          <div class="gc__fav__buttons__holder">
588            <div value="${product.id}" title="${gc__text__to__favorites[Shop.lang.name]}" class="gc__addtofav gc__fav">
589              <div class="gc__span__holder">${gc__text__in__fav[Shop.lang.name]}</div>
590              <svg data-v-7df6b261="" data-v-c36c587c="" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" role="presentation" class="svg" data-v-6eb481ef="">
591                <g data-v-7df6b261="" fill="currentColor" stroke="currentColor">
592                  <svg data-v-c36c587c="" data-v-7df6b261="" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="svg-icon">
593                    <path data-v-c36c587c="" data-v-7df6b261="" d="M11.9 7.696C11.9 4.67 9.682 3 6.948 3 3.649 3 2.035 5.348 2 8.478 2 12.783 6.949 16.304 11.9 21c4.95-4.696 9.9-8.217 9.9-12.522C21.765 5.348 20.151 3 16.85 3c-2.734 0-4.95 1.67-4.95 4.696z" stroke-width="2" stroke-linecap="round"></path>
594                  </svg>
595                </g>
596              </svg>
597            </div>
598            <span class="gc__check__fav">
599              <a href="${gc__fav__url}" title="${gc__fav__name}" class="btn">${gc__check__link[Shop.lang.name]}</a>
600            </span>
601          </div>
602        </div>`;
603  
604      // Append the new element to your favored item list container
605      $(gc__fav__item_html).appendTo($('.gc__favored__item__list'));
606    }, {
607      lang: [Shop.lang.name],
608      id: id
609    });
610    }, "500");
611  }
612
613document.addEventListener('DOMContentLoaded', () => {
614    if (gc__favorites.length > 0) {
615        setTimeout(() => {
616        $('.gc__myaccount__holder .gc__favourite__holder .gc__content .gc__empty__container').hide();
617        $('b.count.gc__count').show().find('span').text(gc__favorites.length);
618        $.getScript("https://dcsaascdn.net/js/front-api-1.5.0.min.js", function () {
619            frontAPI.getProducts(function (gc__favorites) {
620                gc__favorites.list.forEach(e => {
621                    let gc__fav__name = e.name;
622                    let gc__fav__url = e.url;
623                    let gc__fav__image = '/environment/cache/images/150_150_productGfx_' + e.main_image_filename;
624
625                    $('<div class="gc__favored__item"><img src="' + gc__fav__image + '" title="' + gc__fav__name + '" alt="' + gc__fav__name + '"><span class="gc__fav__name">' + gc__fav__name + '</span><div class="gc__fav__buttons__holder"><div value="' + e.id + '" title="' + gc__text__to__favorites[Shop.lang.name] + '" class="gc__addtofav gc__fav"><div class="gc__span__holder">' + gc__text__in__fav[Shop.lang.name] + '</div><svg data-v-7df6b261="" data-v-c36c587c="" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" role="presentation" class="svg" data-v-6eb481ef=""><g data-v-7df6b261="" fill="currentColor" stroke="currentColor"><svg data-v-c36c587c="" data-v-7df6b261="" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="svg-icon"><path data-v-c36c587c="" data-v-7df6b261="" d="M11.9 7.696C11.9 4.67 9.682 3 6.948 3 3.649 3 2.035 5.348 2 8.478 2 12.783 6.949 16.304 11.9 21c4.95-4.696 9.9-8.217 9.9-12.522C21.765 5.348 20.151 3 16.85 3c-2.734 0-4.95 1.67-4.95 4.696z" stroke-width="2" stroke-linecap="round"></path></svg></g></svg></div><span class="gc__check__fav"><a href="' + gc__fav__url + '" title="' + gc__fav__name + '" class="btn">' + gc__check__link[Shop.lang.name] + '</a></span></div></div>').appendTo($('.gc__favored__item__list'));
626                });
627            }, {
628                lang: gc__api__lang,
629                ids: gc__favorites
630            });
631        });
632    }, "500");
633    } else {
634        $('.gc__myaccount__holder .gc__favourite__holder .gc__content .gc__empty__container').show();
635    }
636});
637
638
639
640$(document).on("click", ".gc__wishlist__on", function () {
641    $('header .logo-bar .gc__favourite__holder .gc__content').toggleClass('gc__heart__active');
642    $('.mask.gc__custom__mask').toggleClass('gc__notactive gc__wishlist__on');
643});
644
645
646$(document).on("click", '.gc__list__add', function (e) {
647    if ($('p.logout').length == 0) {
648        var id = $(this).parent().attr('data-product-id');
649        var item = $(this).find('.gc__addtofav');
650        var index = gc__favorites.indexOf(id);
651
652        // return if target doesn't have an id (shouldn't happen)
653        if (!id) return;
654        // item is not favorite
655        if (index === -1) {
656            gc__favorites.push(id);
657            gc__getProductFromAPI(id);
658            item.addClass('gc__fav').find('.gc__span__holder').text(gc__text__in__fav[Shop.lang.name]);
659            
660
661            // item is already favorite
662        } else {
663            gc__favorites.splice(index, 1);
664            item.removeClass('gc__fav').find('.gc__span__holder').text(gc__text__to__favorites[Shop.lang.name]);
665            $('.gc__favored__item__list .gc__favored__item .gc__fav__buttons__holder .gc__addtofav[value="'+id+'"]').parent().parent().remove();
666            //   $favItemToRemove.remove();
667            //   $('b.count.gc__count').show().find('span').text(gc__favorites.length);
668        }
669    }
670    localStorage.setItem('gc__favorites', JSON.stringify(gc__favorites));
671    gc__updateFavoriteCount();
672});
673$(document).on("click", '.gc__favored__item .gc__addtofav, .gc__mailfriend .gc__addtofav', function (e) {
674    if ($('p.logout').length == 0) {
675        var id = $(this).attr('value');
676        var item = $(this);
677        var index = gc__favorites.indexOf(id);
678        if (!id) return;
679        if (index == -1) {
680            gc__favorites.push(id);
681            gc__getProductFromAPI(id);
682            item.addClass('gc__fav').find('.gc__span__holder').text(gc__text__in__fav[Shop.lang.name]);
683            $('.gc__fav[value="'+id+'"]').addClass('gc__fav').find('.gc__span__holder').text(gc__text__in__fav[Shop.lang.name]);
684        } else {
685            gc__favorites.splice(index, 1);
686            item.removeClass('gc__fav').find('.gc__span__holder').text(gc__text__to__favorites[Shop.lang.name]);
687            $('.gc__favored__item__list .gc__favored__item .gc__fav__buttons__holder .gc__addtofav[value="'+id+'"]').parent().parent().remove();
688            $('.gc__fav[value="'+id+'"]').removeClass('gc__fav').find('.gc__span__holder').text(gc__text__to__favorites[Shop.lang.name]);
689        }
690    }
691    localStorage.setItem('gc__favorites', JSON.stringify(gc__favorites));
692    gc__updateFavoriteCount();
693});
694
695
696
697$(function GC__Floating__Inputs() {
698    // $('body.shop_basket_address tr.address_type').insertAfter($('.client-data .separator'));
699
700    // $('tr.address_type td.input > label').each(function () {
701    //     let gc__label__text = $(this).text();
702    //     let gc__translated_label = gc__label__translations[Shop.lang.name] + gc__label__text;
703    //     $(this).text(gc__translated_label);
704    // });
705
706    // $('td.input input[type="text"], td.input input[type="tel"]').each(function () {
707    //     $(this).attr('placeholder', '')
708    //         .parent().parent().parent()
709    //         .addClass('gc__new__input')
710    //         .find('td.label label')
711    //         .wrapInner('<span></span>')
712    //         .find('span')
713    //         .before(this);
714    // });
715
716    $('#box_basketaddress label[for="comment"]').parent().parent().addClass('gc__comments');
717    $('<div class="gc__additional__comments"><td class="input"><span class="checkbox-wrap"><input type="checkbox" id="gc__comments"><label for="gc__comments"></label></span><label for="gc__comments">' + gc__comments__label[Shop.lang.name] + '</label></span></td></div>').insertBefore('#box_basketaddress .basket-step-border>
717.f-row .client-add-info.f-grid-6 table:not(.address-different) > tbody>tr:nth-child(1)');
718    $('#gc__comments').on('change', function () {
719        $('.gc__comments').toggleClass('gc__active__comment');
720    });
721});
722
723
724$(function GC__PlusMinusBasket() {
725    // 1. ITERUJ PO KONTENERACH, a nie po każdym polu input.
726    // To zapobiegnie dodawaniu podwójnych przycisków.
727    $('.quantity, .number-wrap').each(function () {
728        var $container = $(this);
729
730        // Sprawdź, czy przyciski już istnieją w tym kontenerze, aby uniknąć duplikatów.
731        if ($container.find('.grow-more').length > 0) {
732            return; // Przejdź do następnego kontenera, nic tu nie rób.
733        }
734
735        // Znajdź właściwe pole input do modyfikacji wewnątrz kontenera.
736        // Celujemy w inputy tekstowe lub numeryczne, które NIE SĄ wyłączone (disabled).
737        var $input = $container.find('input[type="text"], input[type="number"]').not('[disabled]');
738
739        // Jeśli nie znaleziono odpowiedniego inputa w kontenerze, nie dodawaj przycisków.
740        if ($input.length === 0) {
741            return;
742        }
743
744        let more = '<span class="grow-more">+</span>';
745        let less = '<span class="grow-less">-</span>';
746
747        // Dodaj przyciski ZA polem input, które znaleźliśmy.
748        $input.after(more, less);
749    });
750
751    // 2. UŻYJ DELEGACJI ZDARZEŃ
752    // To bardziej wydajne i działa również dla elementów dodanych do strony w przyszłości.
753    // Zdarzenia są przypisane do 'body', ale nasłuchują kliknięć tylko na '.grow-more' i '.grow-less'.
754    
755    $('body').on('click', '.grow-more', function () {
756        // 3. NIEZAWODNE ZNAJDOWANIE POLA INPUT
757        // Znajdź najbliższy kontener, a w nim odpowiedni input.
758        var $qty = $(this).closest('.quantity, .number-wrap').find('input[type="text"], input[type="number"]').not('[disabled]');
759        var currentVal = parseInt($qty.val(), 10); // Dodano 10 jako drugi argument - dobra praktyka.
760
761        // Aktywuj przycisk minus, jeśli był nieaktywny
762        $(this).siblings('.grow-less').addClass('active');
763
764        if (!isNaN(currentVal)) {
765            // Zaktualizuj wartość i od razu wywołaj zdarzenie .change()
766            $qty.val(currentVal + 1).change();
767        }
768    });
769
770    $('body').on('click', '.grow-less', function () {
771        // Znajdź najbliższy kontener, a w nim odpowiedni input.
772        var $qty = $(this).closest('.quantity, .number-wrap').find('input[type="text"], input[type="number"]').not('[disabled]');
773        var currentVal = parseInt($qty.val(), 10);
774
775        if (!isNaN(currentVal) && currentVal > 1) {
776            // Zaktualizuj wartość i od razu wywołaj zdarzenie .change()
777            $qty.val(currentVal - 1).change();
778
779            // Sprawdź, czy NOWA wartość to 1 (oryginalny kod sprawdzał, czy STARA wartość to 2)
780            if (currentVal - 1 === 1) {
781                $(this).removeClass('active');
782            }
783        }
784    });
785});
786
787
788$(function GC__Auto__Alt() {
789    $("a").each(function () {
790        var gc__title = $(this).attr("title");
791        var gc__new__title = $(this).html().replace(/(<([^>]+)>)/gi, "").replace(/\s+/g, "");
792        gc__title || $(this).attr("title", gc__new__title)
793    }),
794        $("img").each(function () {
795            let gc__title = $(this).attr("title");
796            let gc__alt = $(this).attr("alt");
797            let gc__parent__a = $(this).parent("a");
798
799            gc__title || gc__alt || gc__parent__a ? gc__title || gc__alt || !gc__parent__a ? gc__title && !gc__alt ? $(this).attr("alt", "Alt tytuł") : gc__alt && !gc__title && $(this).attr("title", gc__alt) : ($(this).attr("title", gc__parent__a.attr("title")), $(this).attr("alt", gc__parent__a.attr("title"))) : ($(this).attr("title", 'Tytuł grafiki'), $(this).attr("alt", "Alt tekst"))
800        });
801
802});
803
804$(function GC__Social__check() { 0 != gc__facebook ? $(".gc__social__container a.facebook").attr("href", gc__facebook) : $(".gc__social__container a.facebook").hide(), 0 != gc__instagram ? $(".gc__social__container a.instagram").attr("href", gc__instagram) : $(".gc__social__container a.instagram").hide(), 0 != gc__whatsapp ? $(".gc__social__container a.whatsapp").attr("href", gc__whatsapp) : $(".gc__social__container a.whatsapp").hide(), 0 != gc__tiktok ? $(".gc__social__container a.tiktok").attr("href", gc__tiktok) : $(".gc__social__container a.tiktok").hide(), 0 != gc__youtube ? $(".gc__social__container a.youtube").attr("href", gc__youtube) : $(".gc__social__container a.youtube").hide(), 0 == gc__blog && $(".gc__social__container a.blog").hide() });
805
806$(document).on("click", ".gc__show__pass", function GC__ShowPassword() {
807    let gc__show__or__hide = $(this).parent().find('input');
808    let fieldType = $(gc__show__or__hide).attr('type');
809    $(gc__show__or__hide).attr('type', (fieldType === 'password' ? 'text' : 'password'));
810    $(this).toggleClass('gc__show');
811});
812
813$(document).on("click", "li.gc__mobile__login__holder, .mask.gc__custom__mask.gc__login__mask", function GC__Mobile__Login() {
814    if ($(window).width() < 767) {
815        $('.gc__mobile__login__content, .gc__mobile__login__content .gc__choose__login').toggleClass('gc__login__on');
816        GC__Generate__Mask();
817        $('.mask.gc__custom__mask').toggleClass('gc__notactive gc__login__mask');
818    }
819});
820
821$(function GC__Brand__Logo__Fix() {
822    let gc__brand__title__container = $('.boxhead.gc__2');
823    if (gc__brand__logo == 0) {
824        gc__brand__title__container.hide();
825    }
826    if (gc__brand__logo__name != 0) {
827        gc__brand__title__container.find('span').text(gc__brand__logo__name);
828    }
829});
830
831window.onload = function () {
832    if ($('.gc__brand__info').length > 0) {
833        $('.gc__brand__info').text(gc__brand__info);
834    }
835    let gc__img__source = $('#box_productfull .productimg .mainimg img').attr('src');
836    $('.gc__product__photo').attr('src', gc__img__source);
837    $('.payment .radio-wrap input[type=radio]').change(function () {
838        $('.payment').removeClass('selected');
839        $(this).closest('.payment').toggleClass('selected');
840
841    });
842    if (gc__footer__brand == 1) {
843        $('head').append("<style>footer.footer.row:after{content:'" + gc__brand__info + "'}</style>");
844    }
845}
846
847
848$(document).on('click', '.pytanie', function (e) {
849    var $this = $(this);
850    
851    // Jeśli kliknięty element jest labelem wewnątrz .gc__option
852    if ($this.closest('.gc__option').length) {
853        var $parentOption = $this.closest('.gc__option');
854        var $innerOdpowiedz = $parentOption.find('.odpowiedz');
855        
856        if ($innerOdpowiedz.hasClass('show')) {
857            $innerOdpowiedz.removeClass('show');
858        } else {
859            $parentOption.find('.odpowiedz').removeClass('show');
860            $innerOdpowiedz.addClass('show');
861        }
862        return;
863    }
864
865    // Dla głównego kontenera .pytanie
866    if ($this.next().hasClass('show')) {
867        $this.next().removeClass('show');
868    } else {
869        $('.odpowiedz').removeClass('show');
870        $this.next().toggleClass('show');
871    }
872});
873
874$(document).ready(function () {
875    if ($('body.shop_index').length) {
876        $('.floatcenterwrap .paginator li > a').each(function () {
877            $(this).attr('href', function (i, a) { return a + "#box_mainproducts" });
878        });
879    }
880
881});
882
883if (gc__second__image == 1) {
884    Shop.include({
885        selectorFunctions: {
886            imgReplace: {
887                selector: '.product',
888                domready: function ($img) {
889                    $img.on('mouseenter', function () {
890                        $('.replace-img-list img', this).attr('src', $('.replace-img-list img', this).data('srcAlt'));
891                    }).on('mouseleave', function () {
892                        $('.replace-img-list img', this).attr('src', $('.replace-img-list img', this).data('src'));
893                    });
894                }
895            }
896        }
897    });
898}
899
900$(function GC__Floating__Phone() {
901    if (gc__floating__number == 1) {
902        $('.gc__floating__phone.none').removeClass('none').addClass(gc__floating__number__side);
903    }
904});
905
906$(function GC__Basket__Automove() {
907    if ($('body').hasClass('shop_basket_done')) {
908        var countdown;
909        if (gc__basket__autoclick == 1 && gc__target__button.length) {
910            //Dodawanie nowego diva
911            $('<div class="gc__basket__autoclick"><p class="gc__info">' + gc__basket__autoredirect[Shop.lang.name] + ': </p><span><p class="gc__countdown">' + gc__countdown__time + '</p><p class="gc__sec">sec.</p></span></div>').insertBefore('form#online_payment_form');
912
913            //Dodawanie przycisku stop
914            if (gc__add__stop__button == 1) {
915                $('.gc__basket__autoclick').append('<button class="gc__stop__button">' + gc__stop__button__text[Shop.lang.name] + '</button>');
916            }
917
918            //Odliczanie
919            var counter = gc__countdown__time;
920            countdown = setInterval(function () {
921                $('.gc__countdown').html(counter);
922                counter--;
923                if (counter < 0) {
924                    clearInterval(countdown);
925                    //Klikanie przycisku
926                    $(gc__target__button).click();
927                };
928            }, 1000);
929        }
930
931        //Zatrzymanie odliczania
932        $('.gc__stop__button').click(function (e) {
933            e.preventDefault();
934            clearInterval(countdown);
935        });
936    }
937});
938
939$(function gc__Lang__And__Currency() {
940    var $gc__box_languages = $('#box_languages'),
941        $gc__box_currencies = $('#box_currencies'),
942        $gc__social_container = $('.logo-bar .gc__social__container'),
943        $gc__content = $('<div/>', { class: 'gc__content' }),
944        $gc__language_holder = $('<div/>', { class: 'gc__language__holder' }),
945        $gc__img = $('<img/>', { src: "/skins/user/" + gc__images__version + "/images/user/gc__language.svg", alt: "Change language", title: "Change language" }),
946        $gc__target = $('.logo-bar .gc__favourite__holder'),
947        $gc__menu_target = $('.menu .innermenu > ul.menu-list');
948
949    var gc__has_languages = $gc__box_languages.length > 0,
950        gc__has_currencies = $gc__box_currencies.length > 0,
951        gc__has_socials = $gc__social_container.length > 0;
952
953    function gc__move_elements() {
954        if ($(window).width() < 980) {
955            if (gc__has_languages) {
956                if (!$gc__menu_target.find('#box_languages').length) {
957                    var $gc__box_languages_clone = $gc__box_languages.clone(true).removeClass('none');
958                    $gc__box_languages.addClass('none');
959                    $gc__box_languages_clone.appendTo($gc__menu_target);
960                }
961            }
962            if (gc__has_currencies) {
963                if (!$gc__menu_target.find('#box_currencies').length) {
964                    var $gc__box_currencies_clone = $gc__box_currencies.clone(true).removeClass('none');
965                    $gc__box_currencies.addClass('none');
966                    $gc__box_currencies_clone.appendTo($gc__menu_target);
967                }
968            }
969            if (gc__has_socials) {
970                if (!$gc__menu_target.find('.gc__social__container').length) {
971                    var $gc__social_container_clone = $gc__social_container.clone(true).removeClass('none');
972                    $gc__social_container.addClass('none');
973                    $gc__social_container_clone.appendTo($gc__menu_target);
974                }
975            }
976        } else {
977            if (gc__has_languages || gc__has_currencies) {
978                if ($gc__language_holder.parent().length === 0) {
979                    $gc__language_holder.append($gc__img).append($gc__content).insertBefore($gc__target);
980                }
981                if (gc__has_languages) {
982                    $gc__box_languages.removeClass('none').appendTo($gc__content);
983                }
984                if (gc__has_currencies) {
985                    $gc__box_currencies.removeClass('none').appendTo($gc__content);
986                }
987                if (gc__has_socials) {
988                    $gc__social_container.removeClass('none');
989                }
990                // Remove cloned elements from the mobile view
991                $gc__menu_target.find('#box_languages').remove();
992                $gc__menu_target.find('#box_currencies').remove();
993               // $gc__menu_target.find('.gc__social__container').remove();
994            }
995        }
996    }
997
998    if (gc__has_languages || gc__has_currencies || gc__has_socials) {
999        gc__move_elements();
1000        $(window).on('resize', gc__move_elements);
1001    }
1002});
1003
1004
1005if (gc__new__related__show__netto__price == 1) {
1006    $('span.gc__prod__price__netto').removeClass('gc__netto__hide');
1007}
1008
1009
1010$(function GC__Show__More__Menu() {
1011    if (gc__more_menu_settings.gc__more_menu__on__off !== 1) {
1012        return; // Jeśli menu 'Więcej' jest wyłączone, nie wykonuj funkcji
1013    }
1014    var gc__menu__breakpoint = 980;
1015    var gc__mobile__viewport = window.matchMedia("screen and (max-width: " + gc__menu__breakpoint + "px)");
1016
1017    function gc__collapse__menu() {
1018        if (gc__mobile__viewport.matches) {
1019            return;
1020        }
1021
1022        var gc__menu = $(".innermenu .menu-list");
1023        var gc__current_lang = Shop.lang.name; // Pobranie aktualnego języka sklepu
1024        var gc__more__text = gc__more_menu_settings.gc__more_menu__translations[gc__current_lang] || gc__more_menu_settings.gc__more_menu__translations['pl_PL'];
1025
1026        // Dodaj element 'Więcej', jeśli nie istnieje
1027        if (!gc__menu.find('.gc__show__more').length) {
1028            gc__menu.append(
1029                '<li class="parent gc__show__more">' +
1030                '<a href="#" class="spanhover mainlevel">' + gc__more__text + '</a>' +
1031                '<div class="submenu level1">' +
1032                '<ul class="level1 gc__second__menu"></ul>' +
1033                '</div>' +
1034                '</li>'
1035            );
1036        }
1037
1038        var gc__more__li = gc__menu.find('.gc__show__more');
1039        var gc__second__menu = gc__more__li.find('.gc__second__menu');
1040
1041        gc__menu.children('li:not(.gc__show__more)').show();
1042        gc__second__menu.empty();
1043
1044        var gc__menu__width = gc__menu.outerWidth();
1045        var gc__current__width = 0;
1046        var gc__margin__buffer = 20; // Dodatkowe marginesy dla poprawy wyglądu
1047
1048        gc__menu.children('li:not(.gc__show__more)').each(function () {
1049            gc__current__width += $(this).outerWidth(true) + gc__margin__buffer;
1050            if (gc__current__width > gc__menu__width) {
1051                $(this).hide();
1052                gc__second__menu.append($(this).clone().show());
1053            }
1054        });
1055
1056        if (gc__second__menu.children().length === 0) {
1057            gc__more__li.hide();
1058        } else {
1059            gc__more__li.show();
1060        }
1061    }
1062
1063    // Wywołanie funkcji w celu pierwszego dostosowania menu
1064    gc__collapse__menu();
1065
1066    // Reakcja na zmianę rozmiaru okna
1067    $(window).resize(function () {
1068        gc__collapse__menu();
1069    });
1070
1071    // Obsługa kliknięcia w przycisk 'Więcej'
1072    $(document).on('mouseenter', '.gc__show__more', function () {
1073        $(this).children('.submenu').css('display', 'grid');
1074    }).on('mouseleave', '.gc__show__more', function () {
1075        $(this).children('.submenu').css('display', 'none');
1076    });
1077});
1078
1079$(document).ready(function () {
1080    function activateMegaMenu() {
1081        if ($(window).width() >= 980) {
1082            // Sprawdź status megamenu
1083            switch (gc__megamenu__on__off) {
1084                case 1: // Włącz megamenu dla wszystkich kategorii
1085                    $('li.parent').addClass('gc__megamenu__enabled');
1086                    break;
1087                case 2: // Włącz megamenu tylko dla wybranych kategorii
1088                    gc__megamenu__categories.forEach(function (categoryId) {
1089                        $('li#hcategory_' + categoryId).addClass('gc__megamenu__enabled');
1090                    });
1091                    break;
1092                default: // Megamenu wyłączone
1093                    $('li.parent').removeClass('gc__megamenu__enabled');
1094            }
1095        }
1096    }
1097    var gc__current_lang = Shop.lang.name; // Pobranie aktualnego języka sklepu
1098    var gc__more__text = gc__show__more[gc__current_lang] || gc__show__more['pl_PL'];
1099
1100    function gc__collapse__excess__menu__items() {
1101        if (gc__collapse__enable === 1) {
1102            $('.gc__megamenu__enabled .submenu.level2 > ul').each(function () {
1103                var $ul = $(this);
1104                var $lis = $ul.find('> li');
1105                let gc__parent__li = $ul.parent().parent();
1106                
1107                if (gc__collapse__0 === 1) {
1108                    // Chowanie wszystkich elementów div.submenu i dodanie klas gc__plus/gc__minus
1109                    gc__parent__li.addClass('gc__plus');
1110                    
1111                    // Sprawdzenie, czy kliknięcie jest włączone
1112                    if (gc__collapse__0__click === 1) {
1113                        gc__parent__li.addClass('gc__collapse__0__click');
1114                    
1115                        $(gc__parent__li).on('click', function(e) {                            
1116                            if($(e.target).is('a')) {
1117                                e.stopPropagation();
1118                            } else {
1119                                $(this).toggleClass('active');
1120                            }
1121                        });
1122                    }
1123                } else {
1124                    if ($lis.length > gc__collapse__after) {
1125                        var $excessLis = $lis.slice(gc__collapse__after).wrapAll('<div class="gc__more__container"></div>').parent();
1126                        $ul.append('<li class="gc__more__trigger">' + gc__more__text + '</li>');
1127                        $ul.on('mouseenter', '.gc__more__trigger', function () {
1128                            $excessLis.slideDown();
1129                        }).on('mouseleave', function () {
1130                            $excessLis.slideUp();
1131                        });
1132                    }
1133                }
1134            });
1135        }
1136    }
1137
1138
1139
1140    activateMegaMenu();
1141    gc__collapse__excess__menu__items();
1142});
1143
1144
1145
1146// ======================
1147// GŁÓWNA LOGIKA
1148// ======================
1149function GC__Blog__Sliders() {
1150    if (gc__enable_custom_product_insertion !== 1) {
1151        console.log('[GC] Wstawianie produktów wyłączone');
1152        return;
1153    }
1154
1155    const gc__contentContainers = $('article .article-content');
1156    if (!gc__contentContainers.length) {
1157        console.error('[GC] Nie znaleziono kontenerów treści');
1158        return;
1159    }
1160
1161    if (typeof frontAPI === 'undefined') {
1162        console.error('[GC] Brak biblioteki FrontAPI');
1163        return;
1164    }
1165
1166    console.log('[GC] Rozpoczynam przetwarzanie treści');
1167    gc__processContent(gc__contentContainers);
1168}
1169
1170function gc__processContent(containers) {
1171    containers.each(function() {
1172        const gc__container = $(this);
1173        if (gc__container.data('gc-processed')) return;
1174
1175        const gc__originalHtml = gc__container.html();
1176        const [gc__newHtml, gc__markers] = gc__findAndReplaceMarkers(gc__originalHtml);
1177        
1178        gc__container.html(gc__newHtml).data('gc-processed', true);
1179        gc__handleMarkers(gc__markers, gc__container);
1180    });
1181}
1182
1183function gc__findAndReplaceMarkers(html) {
1184    const markers = [];
1185    const productRegex = /\[product id="([\d,\s]+)"\]/g;
1186    const collectionRegex = /\[collection id="(\d+)"\]/g;
1187
1188    const newHtml = html
1189        .replace(productRegex, (match, ids) => {
1190            const cleanIds = ids.replace(/\s/g, '');
1191            markers.push({ type: 'product', ids: cleanIds.split(',') });
1192            return `<div class="gc__product-marker" data-ids="${cleanIds}"></div>`;
1193        })
1194        .replace(collectionRegex, (match, id) => {
1195            markers.push({ type: 'collection', id: id.trim() });
1196            return `<div class="gc__collection-marker" data-id="${id}"></div>`;
1197        });
1198
1199    return [newHtml, markers];
1200}
1201
1202function gc__handleMarkers(markers, container) {
1203    markers.forEach(marker => {
1204        const selector = marker.type === 'product' 
1205            ? `[data-ids="${marker.ids.join(',')}"]` 
1206            : `[data-id="${marker.id}"]`;
1207        
1208        const gc__target = container.find(selector);
1209        if (!gc__target.length) return;
1210
1211        console.log(`[GC] Znaleziono znacznik: ${marker.type}`, marker);
1212
1213        const gc__sliderHtml = `
1214            <div class="gc__slider-container loading">
1215                <div class="gc__header">
1216                    <h3>${gc__blog__slider__title[Shop.lang.name]}</h3>
1217                </div>
1218                <div class="gc__products-wrapper">
1219                    ${gc__generateSkeletons(5)}
1220                </div>
1221            </div>
1222        `;
1223
1224        gc__target.html(gc__sliderHtml);
1225        gc__fetchProducts(marker, gc__target);
1226    });
1227}
1228
1229// ======================
1230// OPERACJE NA PRODUKTACH
1231// ======================
1232function gc__fetchProducts(marker, container) {
1233    const gc__params = {
1234        lang: gc__api__lang === 'en' ? 'en_US' : gc__api__lang,
1235        currency: Shop.currency.iso_code,
1236        urlParams: '?limit=5'
1237    };
1238
1239    if (marker.type === 'product') {
1240        gc__params.ids = marker.ids;
1241        var gc__apiMethod = 'getProducts';
1242    } else {
1243        gc__params.id = marker.id;
1244        var gc__apiMethod = 'getProductsFromCollection';
1245    }
1246
1247    frontAPI[gc__apiMethod](response => {
1248        if (!response?.list?.length) {
1249            console.warn('[GC] Brak produktów - usuwam kontener');
1250            return container.remove();
1251        }
1252
1253        console.log(`[GC] Otrzymano ${response.list.length} produktów`);
1254        const gc__products = response.list
1255            .filter(p => p.can_buy)
1256            .slice(0, 5)
1257            .map(p => {
1258                try {
1259                    return gc__createProductElement(p);
1260                } catch (error) {
1261                    console.error('[GC] Błąd tworzenia produktu:', error);
1262                    return null;
1263                }
1264            })
1265            .filter(Boolean);
1266
1267        const gc__productsContainer = container.find('.gc__products-wrapper');
1268        gc__productsContainer.empty().append(gc__products);
1269
1270        if (gc__enable_custom_product_carousel === 1 && typeof $.fn.owlCarousel !== 'undefined') {
1271            console.log('[GC] Inicjalizuję karuzelę');
1272            gc__productsContainer.owlCarousel({
1273                lazyLoad: true,
1274                loop: gc__products.length >= 5,
1275                margin: 10,
1276                responsive: {0:{items:1}, 380:{items:2}, 800:{items:4}, 1200:{items:5}},
1277                autoplay: gc__blog_slider_autoplay === 1,
1278                autoplayHoverPause: true
1279            });
1280        }
1281        
1282        container.removeClass('loading');
1283    }, gc__params);
1284}
1285
1286function gc__generateSkeletons(count) {
1287    return Array(count).fill(`
1288        <div class="gc__skeleton-item">
1289            <div class="gc__skeleton-image"></div>
1290            <div class="gc__skeleton-name"></div>
1291            <div class="gc__skeleton-price"></div>
1292        </div>
1293    `).join('');
1294}
1295
1296// ======================
1297// INICJALIZACJA
1298// ======================
1299document.addEventListener('DOMContentLoaded', function() {
1300    if (Shop.pageType === "shop_news") {
1301        console.log('[GC] Strona bloga - uruchamiam skrypt');
1302        GC__Blog__Sliders();
1303    }
1304});
1305
1306
1307function gc__getProductsByIDs(gc__ids, gc__callback) {
1308    frontAPI.getProducts(function(gc__response) {
1309        if (gc__response.list && Array.isArray(gc__response.list)) {
1310            gc__callback(gc__response.list);
1311        } else {
1312            console.error('Nieoczekiwana struktura odpowiedzi z API');
1313        }
1314    }, {
1315        lang: gc__api__lang,
1316        ids: gc__ids
1317    });
1318}
1319
1320
1321function gc__createProductElement(gc__product) {
1322    console.log('Rozpoczynam generowanie produktu o id '+gc__product.toString());
1323    let priceHtml = '<div class="price f-row">';
1324    let nettoHtml = '';
1325
1326    if ($('.price-netto').length) {
1327        nettoHtml = '<p class="price-netto">Netto: <em>' + gc__product.price.net.final + '</em></p>';
1328    }
1329    
1330    // Obliczanie rabatu
1331    let gc__discount = 0;
1332    if (gc__show__regular__discount == 1 && typeof gc__product.price.gross.promo !== "undefined") {
1333        let gc__current__price = parseFloat(gc__product.price.gross.promo.replace(/[^0-9.,]/g, '').replace(',', '.'));
1334        let gc__regular__price = parseFloat(gc__product.price.gross.base.replace(/[^0-9.,]/g, '').replace(',', '.'));
1335        gc__discount = Math.round(((gc__current__price / gc__regular__price) - 1) * 100);
1336    }
1337
1338    if (typeof gc__product.price.gross.promo !== "undefined") {
1339        priceHtml +=
1340            '<p class="gc__product__price">' +
1341            '<em>' + gc__product.price.gross.promo + '</em>' +
1342            '</p>' +
1343            '<p class="price__regular">' +
1344            'Cena regularna: <del class="price__inactive">' + gc__product.price.gross.base + '</del>';
1345        
1346        // Dodawanie etykiety rabatu, jeśli spełnione są warunki
1347        if (gc__show__regular__discount == 1 && Math.abs(gc__discount) >= gc__min__discount__threshold) {
1348            priceHtml += '<span class="gc__promo__percent__30d">' + gc__discount + '%</span>';
1349        }
1350        
1351        priceHtml += '</p>' +
1352            '<div class="f-row clear price__omnibus">' +
1353            'Najniższa cena: <strong class="js__omnibus-price-gross price__inactive">' + gc__product.price.gross.historical_lowest_price + '</strong>' +
1354            '</div>' +
1355            nettoHtml;
1356    } else {
1357        priceHtml +=
1358            '<p class="gc__product__price"><em class="color">' + gc__product.price.gross.final + '</em></p>' +
1359            nettoHtml;
1360    }
1361    priceHtml += '</div>';
1362
1363    let productElement = $(
1364        '<div data-product-id="' + gc__product.id + '" class="product row center">' +
1365        '<a href="' + gc__product.url + '" title="' + gc__product.name + '" class="row">' +
1366        '<span class="boximgsize row">' +
1367        '<img loading="lazy" src="/environment/cache/images/500_500_productGfx_' + gc__product.main_image_filename + '" alt="' + gc__product.name + '" title="' + gc__product.name + '">' +
1368        '</span>' +
1369        '<div class="gc__badge__holder"></div>' +
1370        '<div class="productnamewrap row">' +
1371        '<span class="productname">' + gc__product.name + '</span>' +
1372        '</div>' +
1373        '</a>' +
1374        priceHtml +
1375        // Formularz koszyka
1376        '<form class="basket basket-box " action="/pl/basket/add/post" method="post">' +
1377        '<fieldset>' +
1378        '<div class="shaded_inputwrap">' +
1379        '<input aria-label="Ilość" name="quantity" value="1" type="text" class="short center">' +
1380        '</div>' +
1381        '<input type="hidden" value="' + gc__product.stockId + '" name="stock_id" aria-label="Ilość">' +
1382        '<button class="addtobasket btn btn-red" type="submit"><span class="gc__basket">' + gc__text__to__basket[Shop.lang.name] + '</span></button>' +
1383        '</fieldset>' +
1384        '</form>' +
1385        // Dodawanie do ulubionych
1386        '<div class="gc__list__add">' +
1387        '<div class="gc__product__badge">' +
1388        '<div value="48" title="' + gc__text__to__favorites[Shop.lang.name] + '" class="gc__addtofav">' +
1389        '<div class="gc__span__holder">' + gc__text__to__favorites[Shop.lang.name] + '</div>' +
1390        // Ikona serca
1391        '<svg data-v-7df6b261="" data-v-c36c587c="" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" role="presentation" class="svg" data-v-6eb481ef="">' +
1392        '<g data-v-7df6b261="" fill="currentColor" stroke="currentColor">' +
1393        '<svg data-v-c36c587c="" data-v-7df6b261="" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="svg-icon">' +
1394        '<path data-v-c36c587c="" data-v-7df6b261="" d="M11.9 7.696C11.9 4.67 9.682 3 6.948 3 3.649 3 2.035 5.348 2 8.478 2 12.783 6.949 16.304 11.9 21c4.95-4.696 9.9-8.217 9.9-12.522C21.765 5.348 20.151 3 16.85 3c-2.734 0-4.95 1.67-4.95 4.696z" stroke-width="2" stroke-linecap="round"></path>' +
1395        '</svg>' +
1396        '</g>' +
1397        '</svg>' +
1398        '</div>' +
1399        '</div>' +
1400        '</div>' +
1401        '</div>'
1402    );
1403
1404    let tagsElement = $('<ul class="tags"></ul>');
1405    if (typeof gc__product.price.gross.promo != "undefined") {
1406        tagsElement.append('<li class="promo"><span class="gc__product__tag">'+gc__promo__badge[Shop.lang.name]+'</span></li>');
1407    }
1408    if (gc__product.newProduct) {
1409        tagsElement.append('<li class="new"><span class="gc__product__tag">' + gc__tag__translations[Shop.lang.name] + '</span></li>');
1410    }
1411
1412    if (tagsElement.children().length) {
1413        productElement.find('.gc__badge__holder').append(tagsElement);productElement.find('.gc__badge__holder').removeClass('gc__skeleton');
1414    }
1415
1416    return productElement;
1417}
1418
1419function gc__initializeCarousel(gc__currentInnerBox) {
1420    let gc__productCount = gc__currentInnerBox.children().length;
1421    let gc__loop = gc__productCount >= 5;
1422    
1423    //console.log('ilość produktów niby to ' + gc__productCount + ' dla #' + gc__currentInnerBox.attr('id'));
1424
1425    // Inicjowanie karuzeli tylko jeśli innerbox zawiera produkty
1426    if(gc__productCount > 0) {
1427        gc__currentInnerBox.owlCarousel({
1428            lazyLoad: true,
1429            loop: gc__loop,
1430            margin: 10,
1431            autoHeight: true,
1432            responsiveClass: true,
1433            responsive: {
1434                0: {
1435                    items: 1,
1436                    nav: true
1437                },
1438                380: {
1439                    items: 2,
1440                    nav: true
1441                },
1442                800: {
1443                    items: 3,
1444                    nav: true
1445                },
1446                1200: {
1447                    items: 4,
1448                    nav: true,
1449                }
1450            },
1451            autoplay: true,
1452            autoplayHoverPause: true,
1453        });
1454    }
1455}
1456
1457function GC__MENU__INJECTION() {
1458    if (gc__turn__on__megamenu__banners == 0) {
1459        return;
1460    }
1461    $('.menu-list li.parent.gc__megamenu__enabled').each(function() {
1462        let $megamenuContainer = $(this);
1463        let $submenuUl = $megamenuContainer.find('> .submenu.level1');
1464        let $contentDiv = $submenuUl.children('.gc__megamenu__content');
1465        
1466        // Inicjalizacja domyślnej konfiguracji dla tego megamenu
1467        let defaultConfig = gc__megamenu__config['default'];
1468		$megamenuContainer.addClass('gc__megamenu__with__product');
1469        // Sprawdzamy, czy kontener już istnieje, jeśli nie, dodajemy go
1470        if ($contentDiv.length === 0) {
1471            $contentDiv = $('<div>', {
1472                'class': 'gc__megamenu__content'
1473            });
1474            $submenuUl.append($contentDiv);
1475        }
1476
1477        // Wyświetlenie domyślnej zawartości, jeśli jest aktywna
1478        if (defaultConfig.enabled) {
1479            gc__displayContent(defaultConfig.type, defaultConfig.contentId, $contentDiv, true);
1480        }
1481
1482        // Inicjalizacja ostatnio wyświetlanej treści dla tego konkretnego megamenu
1483        let lastDisplayedContent = {
1484            type: defaultConfig.type,
1485            contentId: defaultConfig.contentId
1486        };
1487
1488        // Przypisanie zdarzeń do każdego elementu li wewnątrz megamenu
1489        $submenuUl.find('> ul.level1 > li').each(function() {
1490            let $categoryLi = $(this);
1491            let categoryId = $categoryLi.attr('id');
1492            let categoryConfig = gc__megamenu__config[categoryId] || defaultConfig;
1493
1494            $categoryLi.mouseenter(function() {
1495                console.log('Najechano na kategorię:', categoryId, 'Konfiguracja:', categoryConfig);
1496                gc__displayContent(categoryConfig.type, categoryConfig.contentId, $contentDiv, false);
1497                lastDisplayedContent = {
1498                    type: categoryConfig.type,
1499                    contentId: categoryConfig.contentId
1500                };
1501            });
1502
1503            $categoryLi.mouseleave(function() {
1504                console.log('Odjechano z kategorii:', categoryId);
1505                gc__displayContent(lastDisplayedContent.type, lastDisplayedContent.contentId, $contentDiv, false);
1506            });
1507        });
1508    });
1509}
1510
1511// Funkcja do wyświetlania produktu/banera
1512function gc__displayContent(type, contentId, $container, isDefault) {
1513    // Odczytanie obecnej wysokości i ustawienie jej jako min-height na czas ładowania treści
1514    var currentHeight = $container.height();
1515    $container.css('min-height', currentHeight + 'px');
1516
1517    // Dodajemy loader, jeśli jeszcze nie istnieje
1518    if (!$container.find('.gc__loader').length) {
1519        $container.prepend('<div class="gc__loader"><div></div><div></div><div></div><div></div></div>');
1520    }
1521
1522    // Ukrywamy wszystkie treści i pokazujemy loader
1523    $container.children('.gc__content').hide();
1524    $container.find('.gc__loader').show();
1525
1526    // Funkcja pomocnicza do ukrywania loadera i pokazywania treści
1527    function showContent($content) {
1528        $container.find('.gc__loader').hide();
1529        $content.show();
1530        // Usunięcie min-height po załadowaniu treści
1531        $container.css('min-height', '');
1532    }
1533
1534    // Sprawdź, czy treść, którą chcemy wyświetlić, już istnieje
1535    let $existingContent = $container.find('#' + contentId);
1536    if ($existingContent.length > 0) {
1537        // Jeśli treść istnieje, po prostu ją pokazujemy
1538        showContent($existingContent);
1539    } else {
1540        // Ukrywamy wszystkie treści i pokazujemy loader
1541        $container.children('.gc__content').hide();
1542        $container.find('.gc__loader').show();
1543
1544        if (type === 'banner') {
1545            let bannerHtml = $('#' + contentId).html();
1546            if (bannerHtml) {
1547                $container.append('<div class="gc__banner-display gc__content" id="' + contentId + '" style="display: block;">
1547' + bannerHtml + '</div>');
1548                showContent($container.find('.gc__content#' + contentId));
1549            } else {
1550                console.log("Banner content with ID " + contentId + " not found.");
1551            }
1552        } else if (type === 'product') {
1553            console.log("Pobieram dane produktu o ID" + contentId);
1554            // Zakładamy, że frontAPI i funkcja getProduct są już dostępne
1555            frontAPI.getProduct(function(product) {
1556                if (product && product.main_image_filename && product.name && product.price) {
1557                    let productHtml = '<div class="gc__product-display gc__content" id="' + contentId + '" style="display: block;">' +
1558                                      '<img src="/environment/cache/images/300_300_productGfx_' + product.main_image_filename + '" alt="' + product.name + '">' +
1559                                      '<h4>' + product.name + '</h4>' +
1560                                      '<div class="gc__price gc__price--extended row">' +
1561                                      '<p><em class="gc__color">' + product.price.gross.final + '</em></p>' +
1562                                      '</div></div>';
1563                    $container.append(productHtml);
1564                    showContent($container.find('#' + contentId));
1565                } else {
1566                    console.log("Product data is incomplete or undefined.");
1567                    // Jeśli nie można pobrać produktu, również ukrywamy loader
1568                    $container.find('.gc__loader').hide();
1569                    $container.css('min-height', ''); // Usuwamy min-height jeśli produktu nie ma
1570                }
1571            }, { lang: gc__api__lang, 
1572                id: contentId });
1573        }
1574    }
1575    // Aktualizacja ostatnio wyświetlanej treści, jeśli nie jest to treść domyślna
1576    if (!isDefault) {
1577        lastDisplayedContent = { type: type, contentId: contentId };
1578    }
1579}
1580
1581
1582$(document).ready(function () {
1583    if (gc__turn__on__megamenu__banners == 1) {
1584        setTimeout(function() {
1585            GC__MENU__INJECTION();
1586        }, 600);
1587    }
1588});
1589$(document).ready(function() {
1590    
1591    function gc__calculate__percent__difference(gc__lower, gc__higher) {
1592        return Math.round(((gc__lower / gc__higher) - 1) * 100);
1593    }
1594
1595    function gc__format__price(gc__price) {
1596        return parseFloat(gc__price.replace(/[^0-9,]/g, '').replace(',', '.'));
1597    }
1598
1599    function gc__create__promo__element(gc__percent) {
1600        return $('<span></span>')
1601            .addClass('gc__promo__percent__30d')
1602            .text(gc__percent + '%');
1603    }
1604
1605    // Funkcja do dodawania promocji obok ceny
1606    function gc__add__promo(gc__element, gc__current__price, gc__regular__price) {
1607        const gc__discount = gc__calculate__percent__difference(gc__current__price, gc__regular__price);
1608        if (gc__discount < 0 && Math.abs(gc__discount) >= gc__min__discount__threshold) {
1609            // Usuń tylko metkę gc__promo__percent__30d, jeśli istnieje
1610            gc__element.find('.gc__promo__percent__30d').remove();
1611            
1612            const gc__promo__element = gc__create__promo__element(gc__discount);
1613            gc__element.append(gc__promo__element);
1614        }
1615    }
1616
1617    // Funkcja do obsługi pojedynczego produktu
1618    function gc__process__product(gc__product__element) {
1619        const gc__price__container = gc__product__element.find('.price');
1620        const gc__current__price = gc__format__price(gc__price__container.find('em.color, .main-price.color, .gc__product__price em').first().text());
1621        const gc__regular__price__element = gc__price__container.find('.price__regular');
1622
1623        if (gc__regular__price__element.length) {
1624            const gc__regular__price = gc__format__price(gc__regular__price__element.find('.price__inactive').text());
1625            gc__add__promo(gc__regular__price__element, gc__current__price, gc__regular__price);
1626        }
1627    }
1628
1629    // Obsługa karty produktu
1630    $('.product-main, #box_productfull').each(function() {
1631        gc__process__product($(this));
1632    });
1633
1634    // Obsługa regularnych produktów na liście
1635    $('.product.row.center, .product-inner').each(function() {
1636        gc__process__product($(this));
1637    });
1638});
1639
1640$(document).ready(function() {
1641    if (gc__enable__promo__message === 1) { // Sprawdź, czy komunikat jest włączony
1642        // Znajdź wszystkie produkty z klasą .product.product_inactive
1643        $('.product.product_inactive').each(function() {
1644            // Dodaj klasę .gc__out__of__stock__info__product do produktu
1645            $(this).addClass('gc__out__of__stock__info__product');
1646            
1647            // Stwórz nowy element span z odpowiednimi klasami i tekstem
1648            var gc__promo__element = $('<span class="gc__promo__percent__30d gc__out__of__stock__info">' + gc__message__waiting__delivery[Shop.lang.name] + '</span>');
1649
1650            // Znajdź odpowiedni span wokół zdjęcia produktu
1651            var gc__img__wrap = $(this).find('span.f-grid-12.img-wrap, span.boximgsize.row');
1652
1653            // Dodaj gc__promo__element do środka gc__img__wrap (na końcu)
1654            if (gc__img__wrap.length) {
1655                gc__img__wrap.append(gc__promo__element);
1656            }
1657        });
1658    }
1659});
1660
1661// Funkcja do ustawiania niestandardowych URLi na podstawie ID
1662function gc__setCustomURL(id, url) {
1663    gc__product__link__settings.gc__custom__urls[id] = url;
1664}
1665
1666// Funkcja dodająca link "Show More" do odpowiednich modułów
1667$(document).ready(function() {
1668    if (gc__product__link__onoff == 1) {
1669    const gc__text__to__favorites = gc__product__link__settings.gc__link__name[Shop.lang.name] || gc__product__link__settings.gc__link__name['en'];
1670
1671    const gc__createShowMoreLink = function(url) {
1672        return `<a href="${url}" class="gc__show__more__link"><span>${gc__text__to__favorites}</span><img src="/skins/user/${gc__images__version}/images/user/link.png" alt="${gc__text__to__favorites}" width="14" height="14"></a>`;
1673    };
1674
1675    // Dodaj link do Bestsellera
1676    $('#box_bestsellers .boxhead').each(function() {
1677        $(this).append(gc__createShowMoreLink(gc__product__link__settings.gc__urls.gc__bestsellers__url));
1678    });
1679
1680    // Dodaj link do Nowości
1681    $('#box_lastadded .boxhead').each(function() {
1682        $(this).append(gc__createShowMoreLink(gc__product__link__settings.gc__urls.gc__new__url));
1683    });
1684
1685    // Dodaj link do Promocji
1686    $('#box_specialoffer .boxhead').each(function() {
1687        $(this).append(gc__createShowMoreLink(gc__product__link__settings.gc__urls.gc__promotions__url));
1688    });
1689
1690    // Dodaj linki do niestandardowych URLi
1691    $.each(gc__product__link__settings.gc__custom__urls, function(id, url) {
1692        $('#' + id + ' .boxhead').each(function() {
1693            $(this).append(gc__createShowMoreLink(url));
1694        });
1695    });
1696}
1697});
1698
1699
1700
1701// Funkcja GC__Animated__Typer
1702!function(u){
1703    var d;
1704    u.fn.GC__Animated__Typer=function(t){
1705        d="Microsoft Internet Explorer"==navigator.appName;
1706        var s=u.extend({speed:100,delay:1e3,keywords:["keywords"]},t||{});
1707        return "string"==typeof s.keywords && (s.keywords=[s.keywords]),
1708        this.each(function(){
1709            var t,e,n,r=u(this),a=r.get(0);
1710            function o(){
1711                t=e=0,n=s.keywords[t],r.show(),i()
1712            }
1713            function i(){
1714                d ? r.val(n.substring(0,e++)+"|") : u(r).attr("placeholder",n.substring(0,e++)+"|"),
1715                e>n.length ? u.data(a,"tw_input",setTimeout(function(){
1716                    ++t>=s.keywords.length && (t=0),n=s.keywords[t],e=0,i()
1717                },s.delay)) : u.data(a,"tw_input",setTimeout(i,s.speed))
1718            }
1719            r.focus(function(){
1720                d ? r.val("") : u(r).attr("placeholder","");
1721                var t=u.data(a,"tw_input");
1722                t ? (clearTimeout(t),u.data(a,"tw_input",!1)) : u(this).select()
1723            }),
1724            r.blur(function(){
1725                ""==r.val()&&o()
1726            }),
1727            r.val()||o()
1728        })
1729    }
1730}(jQuery);
1731
1732// Sprawdzenie czy typer jest włączony
1733if (gc__typer__settings.enabled) {
1734    // Inicjalizacja dla wyszukiwarki
1735    $('header:not(.checkout) .logo-bar .search__input').GC__Animated__Typer({
1736        speed: gc__typer__settings.speed,
1737        delay: gc__typer__settings.delay,
1738        keywords: gc__typer__settings.keywords.search
1739    });
1740
1741    // Inicjalizacja dla newslettera
1742    $('div#box__newsletter__growcommerce .f-row .gc__new__input input.newsletter-input').GC__Animated__Typer({
1743        speed: gc__typer__settings.speed,
1744        delay: gc__typer__settings.delay,
1745        keywords: gc__typer__settings.keywords.newsletter
1746    });
1747}
1748if (gc__small__footer__icons__onoff) {
1749    $.getScript("https://dcsaascdn.net/js/front-api-1.5.0.min.js", function () {
1750        var gc__footer__logo__generator = function() {
1751            frontAPI.getBasketInfo(function(basket) {
1752                console.log("gc__basket_logo: ", gc__basket_logo); // Debugowanie
1753
1754                var $footer = $('footer.footer.row');
1755                var $logoHolder = $('<div class="gc__footer__logos__holder"><div class="gc__footer__logos"></div></div>');
1756                var $logoContainer = $logoHolder.find('.gc__footer__logos');
1757
1758                var uniqueLogos = new Set(); // Set dla unikalnych wartości
1759
1760                // Funkcja pomocnicza do dodawania logo
1761                var addLogo = function(name) {
1762                    if (!uniqueLogos.has(name)) {
1763                        uniqueLogos.add(name);
1764                        var imgSrc = '/skins/user/' + gc__images__version + '/images/user/' + name.toUpperCase() + '.png';
1765                        var $img = $('<picture><img loading="lazy" src="' + imgSrc + '" alt="' + name + '" class="image-loaded"></picture>');
1766                        $logoContainer.append($img);
1767                    }
1768                };
1769
1770                // Przetwarzanie metod dostawy
1771                $.each(basket.shippings, function(index, method) {
1772                    var methodTitleLower = method.title.toLowerCase();
1773                    if (!gc__small__footer__icons__excluded__words.some(keyword => methodTitleLower.includes(keyword))) {
1774                        var checkedLogos = new Set();
1775                        $.each(gc__basket_logo, function(i, logo) {
1776                            var logoLower = logo.toLowerCase();
1777                            if (!checkedLogos.has(logoLower) && methodTitleLower.includes(logoLower)) {
1778                                checkedLogos.add(logoLower);
1779                                addLogo(logo);
1780                            }
1781                        });
1782                    }
1783                });
1784
1785                // Przetwarzanie metod płatności
1786                $.each(basket.payments, function(index, method) {
1787                    var methodTitleLower = method.title.toLowerCase();
1788                    if (method.name === "onlinePayment" || methodTitleLower.includes("autopay")) {
1789                        addLogo('Autopay');
1790                        addLogo('Blik');
1791                        addLogo('Google');
1792                        addLogo('Apple');
1793                    }
1794                    if (!gc__small__footer__icons__excluded__words.some(keyword => methodTitleLower.includes(keyword))) {
1795                        var checkedLogos = new Set();
1796                        $.each(gc__basket_logo, function(i, logo) {
1797                            var logoLower = logo.toLowerCase();
1798                            if (!checkedLogos.has(logoLower) && methodTitleLower.includes(logoLower)) {
1799                                checkedLogos.add(logoLower);
1800                                addLogo(logo);
1801                            }
1802                        });
1803                    }
1804                });
1805
1806                // Dodanie wygenerowanej sekcji na początku stopki tylko jeśli są unikalne logotypy do dodania
1807                if (uniqueLogos.size > 0) {
1808                    $footer.prepend($logoHolder);
1809                }
1810            }, { lang: Shop.lang.name });
1811        };
1812
1813        // Wywołanie funkcji do generowania logotypów w stopce
1814        gc__footer__logo__generator();
1815    });
1816}
1817
1818$(window).scroll(function() {
1819
1820    if($('header.checkout').length == 0){
1821
1822    var gc__scroll__top = $(window).scrollTop();
1823    var gc__header = $('.menu.row');
1824    var gc__basket = $('header:not(.checkout) .logo-bar .basket');
1825    var gc__header__offset = gc__header.offset().top;
1826    var gc__basket_count = parseInt($('header .logo-bar .basket>a .countlabel b .count span').text(), 10);
1827    var gc__header__height = gc__header.outerHeight(true); // Uwzględnia padding i border
1828
1829    
1830    // Floating basket logic
1831    if (gc__settings__floating_basket && gc__basket_count > 0) {
1832        if (gc__scroll__top > gc__header__offset - gc__header__height) {
1833            if (!gc__basket.hasClass('gc__basket')) {
1834                gc__basket.addClass('gc__basket');
1835            }
1836        } else {
1837            if (gc__basket.hasClass('gc__basket')) {
1838                gc__basket.removeClass('gc__basket');
1839            }
1840        }
1841        
1842    }
1843
1844    // Header logo animation logic
1845    if (gc__settings__header_logo_animation) {
1846        if (gc__scroll__top > gc__header__offset - gc__header__height) {
1847            if (!gc__header.hasClass('gc__sticky3')) {
1848                gc__header.addClass('gc__sticky3');
1849            }
1850        } else {
1851            if (gc__header.hasClass('gc__sticky3')) {
1852                gc__header.removeClass('gc__sticky3');
1853            }
1854        }
1855    }
1856    }
1857});
1858
1859// Dodatek - Warianty produktów na liście od GrowCommerce (HYBRYDOWA WERSJA: TPL + JS)
1860$(function GC__Product__Variants__On__List() {
1861    console.log('GC Variants: Moduł załadowany (hybrydowy), gc__variants__on__listing = ', typeof gc__variants__on__listing !== 'undefined' ? gc__variants__on__listing : 'UNDEFINED');
1862
1863    if (typeof gc__variants__on__listing === 'undefined') {
1864        console.error('GC Variants: BŁĄD - zmienna gc__variants__on__listing nie jest zdefiniowana! Sprawdź user.js');
1865        return;
1866    }
1867
1868    if (gc__variants__on__listing != 1) {
1869        console.log('GC Variants: Moduł wyłączony przez konfigurację');
1870        return;
1871    }
1872
1873    // Sprawdź czy pokazywać warianty w ogóle
1874    if (typeof gc__variants__show__all__options !== 'undefined' && gc__variants__show__all__options == 0) {
1875        console.log('GC Variants: Pokazywanie wariantów wyłączone (gc__variants__show__all__options = 0)');
1876        return;
1877    }
1878
1879    // Helper: Viewport detection
1880    $.expr.pseudos['in-viewport'] = function(elem) {
1881        const rect = elem.getBoundingClientRect();
1882        return (
1883            rect.top >= 0 &&
1884            rect.left >= 0 &&
1885            rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
1886            rect.right <= (window.innerWidth || document.documentElement.clientWidth)
1887        );
1888    };
1889
1890    // Funkcja: Filtrowanie poziomów opcji (ile grup pokazać)
1891    function gc__apply__option__level__filter($container) {
1892        // KROK 1: Ukryj wszystkie opcje z "MX" w nazwie (np. "MX progi ilościowe")
1893        $container.find('.gc__variant__group').each(function() {
1894            const $group = $(this);
1895            const labelText = $group.find('.gc__variant__label').text().trim();
1896
1897            // Jeśli label zawiera "MX", ukryj całą grupę
1898            if (labelText.includes('MX')) {
1899                $group.hide().addClass('gc__hidden__mx');
1900                return; // Pomiń dalsze przetwarzanie dla tej grupy
1901            }
1902        });
1903
1904        // KROK 2: Zastosuj filtrowanie poziomów opcji (dla pozostałych grup)
1905        // Sprawdź ustawienie gc__variants__show__all__options
1906        const showLevels = typeof gc__variants__show__all__options !== 'undefined' ? gc__variants__show__all__options : 2;
1907
1908        if (showLevels === 2) {
1909            // Pokaż wszystkie poziomy - nic nie rób
1910            return;
1911        }
1912
1913        if (showLevels === 1) {
1914            // Pokaż tylko pierwszy poziom (wśród grup, które nie mają MX)
1915            let visibleIndex = 0;
1916            $container.find('.gc__variant__group').each(function() {
1917                const $group = $(this);
1918
1919                // Pomiń grupy z MX (już ukryte)
1920                if ($group.hasClass('gc__hidden__mx')) {
1921                    return;
1922                }
1923
1924                if (visibleIndex > 0) {
1925                    // Ukryj wszystkie grupy poza pierwszą (które nie są MX)
1926                    $group.addClass('gc__hidden__level');
1927                }
1928                visibleIndex++;
1929            });
1930        }
1931
1932        // showLevels === 0 jest obsłużony wcześniej (moduł się nie uruchamia)
1933    }
1934
1935    // Funkcja: Inicjalizacja wariantów z TPL
1936    function gc__init__variants__from__tpl() {
1937        $('.product .gc__variants__on__list').each(function() {
1938            if ($(this).data('gc-initialized')) return;
1939
1940            const $container = $(this);
1941            const $product = $container.closest('.product');
1942
1943            // Dodaj link do produktu jako data attribute
1944            // Szukaj pierwszego linka do produktu (różne layouty mają różne klasy)
1945            let productUrl = $product.find('a.prodname, a.name, a.productname, a.productnamewrap').first().attr('href');
1946
1947            // Fallback - jeśli nie ma specyficznych klas, weź pierwszy link (z wyjątkiem kotw #)
1948            if (!productUrl) {
1949                productUrl = $product.find('a[href]:not([href^="#"]):not(.gc__addtofav)').first().attr('href');
1950            }
1951
1952            if (!productUrl) {
1953                console.warn('GC Variants: Nie znaleziono URL produktu dla ID=' + $product.data('product-id'));
1954                return;
1955            }
1956            $container.attr('data-product-url', productUrl);
1957
1958            // Pobierz product ID
1959            const productId = $product.data('product-id');
1960            if (productId) {
1961                $container.attr('data-product-id', productId);
1962            }
1963
1964            // Sprawdź czy gc__variants__expanded ma być włączony
1965            if (typeof gc__variants__expanded !== 'undefined' && gc__variants__expanded == 1) {
1966                $container.find('.gc__variants__options').removeClass('gc__collapsed').addClass('gc__expanded');
1967            }
1968
1969            // Sprawdź czy gc__variants__compact_mode ma być włączony
1970            if (typeof gc__variants__compact_mode !== 'undefined' && gc__variants__compact_mode == 1) {
1971                $container.find('.gc__variant__values').addClass('gc__compact');
1972            }
1973
1974            // Wypełnij toggle text + ikona
1975            gc__populate__toggle__text($container);
1976
1977            // Wypełnij truestock notice text
1978            gc__populate__truestock__text($container);
1979
1980            // Zastosuj filtrowanie poziomów opcji (gc__variants__show__all__options)
1981            gc__apply__option__level__filter($container);
1982
1983            // Usuń klasę .none (pokaż kontener)
1984            $container.removeClass('none').data('gc-initialized', true);
1985            $product.addClass('gc__variants__applied');
1986        });
1987    }
1988
1989    // Funkcja: Wypełnienie toggle text z ikoną SVG
1990    function gc__populate__toggle__text($container) {
1991        const $toggle = $container.find('.gc__variants__toggle');
1992        if ($toggle.length === 0) return;
1993
1994        // Jeśli gc__variants__expanded === 1 (domyślnie rozwinięte), ukryj toggle całkowicie
1995        const variantsExpanded = typeof gc__variants__expanded !== 'undefined' ? gc__variants__expanded : 0;
1996        if (variantsExpanded == 1) {
1997            $toggle.hide();
1998            return;
1999        }
2000
2001        const $options = $container.find('.gc__variants__options');
2002        const isExpanded = $options.hasClass('gc__expanded');
2003        const lang = Shop.lang.name;
2004
2005        const text = isExpanded ?
2006            gc__variants__toggle__text.expanded[lang] :
2007            gc__variants__toggle__text.collapsed[lang];
2008
2009        const iconClass = isExpanded ? 'gc__rotated' : '';
2010        const iconHtml = '<img src="' + gc__variants__toggle__icon + '" class="gc__toggle__icon ' + iconClass + '" alt="">';
2011
2012        // Dodaj/usuń klasę gc__expanded na przycisku dla strzałki w ::after
2013        if (isExpanded) {
2014            $toggle.addClass('gc__expanded');
2015        } else {
2016            $toggle.removeClass('gc__expanded');
2017        }
2018
2019        $toggle.html(text + ' ' + iconHtml);
2020    }
2021
2022    // Funkcja: Wypełnienie truestock notice text
2023    function gc__populate__truestock__text($container) {
2024        const $notice = $container.find('.gc__variants__truestock__notice');
2025        const $noticeText = $container.find('.gc__truestock__text');
2026
2027        if (!$notice.length) return; // Brak notice w HTML (nie ma truestock)
2028
2029        // Logika wyświetlania notice:
2030        // 1. Jeśli gc__variants__show__all__options === 0 -> ukryj notice (moduł wyłączony)
2031        // 2. Jeśli gc__variants__show__all__options === 1 -> ukryj notice (tylko pierwszy poziom, dobrze walidowany)
2032        // 3. Jeśli gc__variants__truestock__skip__filtering === 1 -> pokaż notice (pomijamy filtrowanie)
2033        // 4. Jeśli gc__variants__truestock__skip__filtering === 0 AND gc__variants__show__all__options === 2 -> pokaż notice (filtrujemy ale pokazujemy wszystkie poziomy)
2034
2035        const showAllOptions = typeof gc__variants__show__all__options !== 'undefined' ? gc__variants__show__all__options : 2;
2036        const skipFiltering = typeof gc__variants__truestock__skip__filtering !== 'undefined' ? gc__variants__truestock__skip__filtering : 1;
2037
2038        let shouldShowNotice = false;
2039
2040        if (showAllOptions === 0 || showAllOptions === 1) {
2041            // Moduł wyłączony lub tylko pierwszy poziom -> NIE pokazuj notice
2042            shouldShowNotice = false;
2043        } else if (skipFiltering === 1) {
2044            // Pomijamy filtrowanie -> ZAWSZE pokazuj notice (uczciwe ostrzeżenie)
2045            shouldShowNotice = true;
2046        } else if (skipFiltering === 0 && showAllOptions === 2) {
2047            // Filtrujemy ALE pokazujemy wszystkie poziomy -> pokazuj notice (może kłamać)
2048            shouldShowNotice = true;
2049        }
2050
2051        if (shouldShowNotice) {
2052            // Pokaż notice i wypełnij tekstem
2053            if ($noticeText.length && typeof gc__variants__truestock__notice !== 'undefined') {
2054                $noticeText.text(gc__variants__truestock__notice[Shop.lang.name]);
2055            }
2056            $notice.show();
2057        } else {
2058            // Ukryj notice
2059            $notice.hide();
2060        }
2061    }
2062
2063    // Funkcja: Fetch danych produktu z WebAPI
2064    async function gc__fetch__product__data(productId) {
2065        const url = window.location.protocol + '//' + window.location.host + '/webapi/front/' + Shop.lang.name + '/products/' + Shop.values.currency + '/' + productId;
2066
2067        try {
2068            const response = await fetch(url);
2069            if (!response.ok) throw new Error('HTTP ' + response.status);
2070            return await response.json();
2071        } catch (error) {
2072            console.error('GC Variants: Błąd pobierania danych dla produktu ' + productId, error);
2073            throw error;
2074        }
2075    }
2076
2077    // Funkcja: Zastosowanie filtrowania dostępności
2078    // UWAGA: Ta funkcja może dawać BŁĘDNE wyniki dla produktów truestock!
2079    //
2080    // PROBLEM: API zwraca wszystkie wartości opcji, ale NIE konkretne dostępne KOMBINACJE.
2081    // Przykład: Produkt ma opcje "Rozmiar" [S, M, L] i "Kolor" [Czarny, Biały, Czerwony]
2082    // API zwraca value IDs: [50(S), 51(M), 52(L), 86(Czarny), 87(Biały), 88(Czerwony)]
2083    // ALE nie mówi czy kombinacja "S + Czarny" jest dostępna, czy tylko "S + Biały" + "M + Czarny"!
2084    //
2085    // Rezultat: Pokażemy użytkownikowi wszystkie rozmiary i wszystkie kolory,
2086    // ale niektóre pary mogą być niedostępne (np. nie ma "XL + Czerwony").
2087    //
2088    // DLATEGO ZALECAMY: gc__variants__truestock__skip__filtering = 1 (domyślnie)
2089    // i wyraźny notice informujący użytkownika o sprawdzeniu na karcie produktu.
2090    function gc__apply__availability__filter($container, productData) {
2091        // Pobierz wszystkie dostępne value IDs z API
2092        const availableValueIds = new Set();
2093
2094        if (productData.options_configuration && Array.isArray(productData.options_configuration)) {
2095            productData.options_configuration.forEach(function(opt) {
2096                if (opt.values && Array.isArray(opt.values)) {
2097                    opt.values.forEach(function(v) {
2098                        availableValueIds.add(parseInt(v.id));
2099                    });
2100                }
2101            });
2102        }
2103
2104        console.log('GC Variants: Dostępne value IDs dla produktu ' + productData.id + ':', Array.from(availableValueIds));
2105
2106        // Ukryj przyciski których value-id nie ma w availableValueIds
2107        $container.find('.gc__variant__btn').each(function() {
2108            const valueId = parseInt($(this).data('value-id'));
2109
2110            if (availableValueIds.has(valueId)) {
2111                $(this).removeClass('gc__unavailable');
2112            } else {
2113                $(this).addClass('gc__unavailable');
2114            }
2115        });
2116
2117        // Usuń skeleton loader po załadowaniu + fade-in
2118        $container.find('.gc__variant__values').removeClass('gc__skeleton');
2119    }
2120
2121    // Funkcja: WebAPI filtering dla produktów truestock
2122    async function gc__filter__truestock__variants() {
2123        // Sprawdź czy filtrowanie jest włączone
2124        if (typeof gc__variants__truestock__skip__filtering !== 'undefined' && gc__variants__truestock__skip__filtering == 1) {
2125            console.log('GC Variants: Filtrowanie truestock wyłączone (gc__variants__truestock__skip__filtering = 1) - pokazuję wszystkie wartości');
2126
2127            // Oznacz produkty jako "przefiltrowane" bez faktycznego filtrowania
2128            // Usuń skeleton loader i pokaż wszystkie przyciski
2129            $('.product:in-viewport .gc__variants__on__list').each(function() {
2130                const $container = $(this);
2131                const $product = $container.closest('.product');
2132
2133                // Usuń skeleton loader (pokaż wszystkie przyciski)
2134                $container.find('.gc__variant__values.gc__skeleton').removeClass('gc__skeleton');
2135
2136                // Oznacz jako przefiltrowany
2137                $product.addClass('gc__filtered');
2138            });
2139
2140            return;
2141        }
2142
2143        // === PONIŻEJ: EKSPERYMENTALNA LOGIKA FILTROWANIA (gc__variants__truestock__skip__filtering = 0) ===
2144        console.warn('GC Variants: EKSPERYMENTALNE filtrowanie truestock włączone - może pokazywać nieprawidłowe dane!');
2145
2146        const $products = $('.product:in-viewport').not('.gc__filtered');
2147
2148        if ($products.length === 0) return;
2149
2150        const productsToFilter = [];
2151
2152        $products.each(function() {
2153            const $product = $(this);
2154            const $container = $product.find('.gc__variants__on__list');
2155
2156            if ($container.length === 0) {
2157                $product.addClass('gc__filtered');
2158                return;
2159            }
2160
2161            // Sprawdź czy ma truestock
2162            const hasTruestock = $container.find('[data-option-stock="1"]').length > 0;
2163            if (!hasTruestock) {
2164                $product.addClass('gc__filtered');
2165                return;
2166            }
2167
2168            const productId = $container.attr('data-product-id');
2169            if (productId) {
2170                // Skeleton jest już dodany w TPL dla truestock
2171                productsToFilter.push({
2172                    id: productId,
2173                    $product: $product,
2174                    $container: $container
2175                });
2176            }
2177        });
2178
2179        if (productsToFilter.length === 0) return;
2180
2181        console.log('GC Variants: Filtrowanie truestock dla ' + productsToFilter.length + ' produktów (EKSPERYMENTALNE)');
2182
2183        // Fetch data dla produktów z truestock
2184        const promises = productsToFilter.map(function(item) {
2185            return gc__fetch__product__data(item.id)
2186                .then(function(data) {
2187                    gc__apply__availability__filter(item.$container, data);
2188                })
2189                .catch(function(err) {
2190                    console.error('GC Variants: Błąd filtrowania dla produktu ' + item.id, err);
2191                })
2192                .finally(function() {
2193                    item.$product.addClass('gc__filtered');
2194                });
2195        });
2196
2197        await Promise.all(promises);
2198    }
2199
2200    // Event: Toggle rozwijania/zwijania
2201    $(document).on('click', '.gc__variants__toggle', function(e) {
2202        e.preventDefault();
2203        e.stopPropagation();
2204
2205        const $toggle = $(this);
2206        const $container = $toggle.closest('.gc__variants__on__list');
2207        const $options = $container.find('.gc__variants__options');
2208        const $icon = $toggle.find('.gc__toggle__icon');
2209
2210        // Toggle expanded state
2211        const isExpanded = $options.hasClass('gc__expanded');
2212        $options.toggleClass('gc__expanded');
2213        $icon.toggleClass('gc__rotated');
2214
2215        // Toggle class na samym przycisku dla strzałki w ::after
2216        if (isExpanded) {
2217            $toggle.removeClass('gc__expanded');
2218        } else {
2219            $toggle.addClass('gc__expanded');
2220        }
2221
2222        // Update text
2223        gc__populate__toggle__text($container);
2224    });
2225
2226    // Event: Kliknięcie w wariant - redirect z basket_fill
2227    $(document).on('click', '.gc__variant__btn', function(e) {
2228        e.preventDefault();
2229        e.stopPropagation();
2230
2231        if (gc__variants__click__action !== 'redirect') return;
2232
2233        const $container = $(this).closest('.gc__variants__on__list');
2234        const productUrl = $container.attr('data-product-url');
2235
2236        if (!productUrl) {
2237            console.error('GC Variants: Product URL not found');
2238            return;
2239        }
2240
2241        const optionId = $(this).data('option-id');
2242        const valueId = $(this).data('value-id');
2243
2244        const separator = productUrl.indexOf('?') !== -1 ? '&' : '?';
2245        const newUrl = productUrl + separator + 'option_' + optionId + '=' + valueId + '&msg=f51eb183ce';
2246
2247        window.location.href = newUrl;
2248    });
2249
2250    // Obsługa drag/swipe dla compact mode scrollowania
2251    var isDragging = false;
2252    var startX = 0;
2253    var scrollLeft = 0;
2254    var currentContainer = null;
2255
2256    // Mouse drag dla desktop
2257    $(document).on('mousedown', '.gc__variant__values.gc__compact', function(e) {
2258        isDragging = true;
2259        currentContainer = this;
2260        startX = e.pageX - $(this).offset().left;
2261        scrollLeft = $(this).scrollLeft();
2262        $(this).css('cursor', 'grabbing');
2263        e.preventDefault();
2264    });
2265
2266    $(document).on('mousemove', function(e) {
2267        if (!isDragging || !currentContainer) return;
2268        e.preventDefault();
2269        var x = e.pageX - $(currentContainer).offset().left;
2270        var walk = (x - startX) * 1.5;
2271        $(currentContainer).scrollLeft(scrollLeft - walk);
2272    });
2273
2274    $(document).on('mouseup', function() {
2275        if (isDragging) {
2276            isDragging = false;
2277            if (currentContainer) {
2278                $(currentContainer).css('cursor', 'grab');
2279                currentContainer = null;
2280            }
2281        }
2282    });
2283
2284    $(document).on('mouseleave', '.gc__variant__values.gc__compact', function() {
2285        if (isDragging && currentContainer === this) {
2286            isDragging = false;
2287            $(this).css('cursor', 'grab');
2288            currentContainer = null;
2289        }
2290    });
2291
2292    // Touch swipe dla mobile
2293    $(document).on('touchstart', '.gc__variant__values.gc__compact', function(e) {
2294        currentContainer = this;
2295        startX = e.touches[0].pageX;
2296        scrollLeft = $(this).scrollLeft();
2297    });
2298
2299    $(document).on('touchmove', '.gc__variant__values.gc__compact', function(e) {
2300        if (!currentContainer) return;
2301        var x = e.touches[0].pageX;
2302        var walk = (startX - x) * 1.2;
2303        $(this).scrollLeft(scrollLeft + walk);
2304    });
2305
2306    $(document).on('touchend', '.gc__variant__values.gc__compact', function() {
2307        currentContainer = null;
2308    });
2309
2310    // Ustawienie cursora grab dla compact mode
2311    $(document).on('mouseenter', '.gc__variant__values.gc__compact', function() {
2312        if (!isDragging) {
2313            $(this).css('cursor', 'grab');
2314        }
2315    });
2316
2317    // Inicjalizacja na starcie
2318    setTimeout(function() {
2319        gc__init__variants__from__tpl();
2320        gc__filter__truestock__variants();
2321    }, 300);
2322
2323    // Re-init na scroll (lazy loading)
2324    var scrollTimeout;
2325    $(window).on('scroll', function() {
2326        clearTimeout(scrollTimeout);
2327        scrollTimeout = setTimeout(function() {
2328            gc__init__variants__from__tpl();
2329            gc__filter__truestock__variants();
2330        }, 200);
2331    });
2332
2333    console.log('GC Variants: Hybrydowy moduł gotowy!');
2334});
2335// Koniec dodatku - Warianty produktów na liście od GrowCommerce
2336
2337// Dodatek - Darmowa dostawa - pasek postępu w koszyku
2338$(function GC__Free__Delivery__Progress() {
2339    if (gc__free__delivery__on !== 1) return;
2340
2341    function animateProgressBar(selector, targetPercent, duration = 2000) {
2342        const $progressBar = $(selector);
2343        const startValue = parseFloat($progressBar.attr('value')) || 0;
2344        const startTime = Date.now();
2345
2346        $progressBar.attr('max', 100);
2347
2348        const update = () => {
2349            const elapsed = Date.now() - startTime;
2350            const progress = Math.min(elapsed / duration, 1);
2351
2352            const currentValue = startValue + (targetPercent - startValue) * progress;
2353            $progressBar.attr('value', currentValue);
2354
2355            if (progress < 1) {
2356                requestAnimationFrame(update);
2357            }
2358        };
2359
2360        requestAnimationFrame(update);
2361    }
2362
2363    if ($('body').hasClass('shop_basket')) {
2364        if (gc__discount == 1) {
2365            $('#gc__discount').insertAfter($('.gc__product__holder')).addClass('gc__discount__active');
2366        }
2367        $.getScript("https://dcsaascdn.net/js/front-api-1.5.0.min.js", function() {
2368            frontAPI.getBasketInfo(function(basket) {
2369                // Pobierz kwotę progu dla aktualnego języka
2370                let gc__threshold = parseFloat(gc__free__delivery__amount[Shop.lang.name] || gc__free__delivery__amount.en);
2371
2372                // Pobierz aktualną wartość koszyka i walutę
2373                let gc__raw__current__basket = basket.basket.sum_no_shipping;
2374                let gc__currency = gc__raw__current__basket.replace(/[\d\s\.,]/g, '').trim();
2375                var gc__current__basket = parseFloat(gc__raw__current__basket.replace(/[^\d\.,]/g, '').replace(',', '.'));
2376
2377                if (isNaN(gc__current__basket)) gc__current__basket = 0;
2378                if (isNaN(gc__threshold)) gc__threshold = 100;
2379
2380                let gc__to__free__dev = (gc__threshold - gc__current__basket).toFixed(2);
2381                var gc__percent = Math.round(100 * gc__current__basket / gc__threshold);
2382
2383                console.log('GC Free Delivery Progress: Próg=' + gc__threshold + ', Koszyk=' + gc__current__basket + ', Waluta=' + gc__currency);
2384
2385                animateProgressBar('.gc__delivery__progress', gc__percent);
2386                if (gc__current__basket < gc__threshold) {
2387                    $('#gc__delivery__content').html(
2388                        '<div class="gc__delivery__icon"><img src="/skins/user/' + gc__images__version + '/images/user/gc__delivery.svg" alt="Darmowa dostawa"></div>' +
2389                        '<div class="gc__delivery__text">' + gc__delivery__content[Shop.lang.name][0] +
2390                        '<strong class="gc__delivery__amount">' + gc__to__free__dev + ' ' + gc__currency + '</strong>' +
2391                        '</div>' +
2392                        '<a href="/" class="gc__buy__more">Dobierz produkty<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9 18L15 12L9 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></a>'
2393                    );
2394                } else if (gc__current__basket >= gc__threshold) {
2395                    $('#gc__delivery__content').html(
2396                        '<div class="gc__delivery__icon"><img src="/skins/user/' + gc__images__version + '/images/user/gc__delivery.svg" alt="Darmowa dostawa"></div>' +
2397                        '<div class="gc__delivery__text">' +
2398                        '<strong class="gc__delivery__success">' + gc__delivery__content[Shop.lang.name][2] + '</strong>' +
2399                        '</div>'
2400                    );
2401                }
2402            }, {});
2403
2404            frontAPI.getProduct(function(product) {
2405                frontAPI.getCategory(function(category) {
2406                    $('.gc__buy__more').attr('href', category.url);
2407                }, {
2408                    id: product.category.id
2409                });
2410            }, {
2411                id: $('.gc__basket__product').eq(0).attr('data-product-id')
2412            });
2413        });
2414    }
2415
2416    console.log('GC Free Delivery: Pasek postępu w koszyku gotowy!');
2417});
2418// Koniec dodatku - Darmowa dostawa - pasek postępu
2419
2420// Dodatek - Darmowa dostawa - komunikat w pasku informacyjnym
2421$(function GC__Free__Delivery__Info__Bar() {
2422    if (gc__free__delivery__on !== 1) return;
2423    if (typeof gc__free__delivery__info__bar__on !== 'undefined' && gc__free__delivery__info__bar__on !== 1) return;
2424    if ($('#gc__info_box').length === 0) return;
2425
2426    // Funkcja odświeżająca komunikat o darmowej dostawie
2427    function gc__refresh__delivery__info() {
2428        if (!$('#gc__info_box').data('owl.carousel')) {
2429            console.log('GC Free Delivery Info: Owl Carousel nie jest gotowy');
2430            return;
2431        }
2432
2433        $.getScript("https://dcsaascdn.net/js/front-api-1.5.0.min.js", function() {
2434            frontAPI.getBasketInfo(function(basket) {
2435                // Pobierz próg dla aktualnego języka
2436                let gc__threshold = parseFloat(gc__free__delivery__amount[Shop.lang.name] || gc__free__delivery__amount.en);
2437
2438                // Pobierz wartość koszyka i walutę
2439                let gc__raw__current__basket = basket.basket.sum_no_shipping;
2440                let gc__currency = gc__raw__current__basket.replace(/[\d\s\.,]/g, '').trim();
2441                let gc__current__basket = parseFloat(gc__raw__current__basket.replace(/[^\d\.,]/g, '').replace(',', '.'));
2442
2443                if (isNaN(gc__current__basket)) gc__current__basket = 0;
2444                if (isNaN(gc__threshold)) gc__threshold = 100;
2445
2446                let gc__missing = (gc__threshold - gc__current__basket).toFixed(2);
2447
2448                // Pobierz tekst z tłumaczeń
2449                var gc__delivery__text = gc__free__delivery[Shop.lang.name] || gc__free__delivery.en;
2450
2451                // Sprawdź czy użytkownik osiągnął darmową dostawę
2452                if (gc__current__basket >= gc__threshold) {
2453                    gc__delivery__text = gc__delivery__content[Shop.lang.name][2]; // "Dostajesz darmową dostawę! 🎁"
2454                } else {
2455                    // Podmień tylko kwotę (waluta jest już w szablonie tekstu po </span>)
2456                    gc__delivery__text = gc__delivery__text.replace(/<span class="gc__amount">.*?<\/span>/, '<span class="gc__amount">' + gc__missing + '</span>');
2457                }
2458
2459                // Dodaj ikonkę przed tekstem
2460                let gc__icon = '<svg class="gc__delivery__info__icon" viewB
2460ox="0 0 512 512" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="m508.54 145.856-180.396-104.151c-1.052-.608-2.245-.928-3.459-.928h-102.163c-3.822 0-6.919 3.097-6.919 6.919s3.097 6.919 6.919 6.919h76.341l-156.43 90.313h-135.512c-3.822 0-6.919 3.097-6.919 6.919s3.097 6.919 6.919 6.919h130.446v90.315h-82.619c-3.822 0-6.919 3.097-6.919 6.919s3.097 6.919 6.919 6.919h82.619v90.315h-130.448c-3.822 0-6.919 3.097-6.919 6.919s3.097 6.919 6.919 6.919h135.514l178.793 103.223c1.07.619 2.266.928 3.459.928s2.39-.309 3.459-.928l180.396-104.151c2.14-1.234 3.459-3.518 3.459-5.991v-208.306c.001-2.471-1.319-4.757-3.459-5.991zm-183.857-90.171 166.561 96.164-52.757 30.459-166.559-96.166zm-66.591 38.445 166.557 96.166-33.374 19.269-166.562-96.164zm173.48 108.15v63.93l-33.376 19.27v-63.931zm-113.806 250.041-166.561-96.161v-192.329l166.561 96.163zm6.918-204.31-166.563-96.164 52.756-30.458 166.56 96.165zm173.478 108.147-166.559 96.163v-192.327l52.754-30.458v67.926c0 2.471 1.32 4.757 3.459 5.991 1.07.619 2.266.928 3.459.928s2.39-.309 3.459-.928l47.214-27.257c2.14-1.234 3.459-3.518 3.459-5.991v-75.917l52.752-30.457v192.327zm-450.333-308.462c0-3.822 3.097-6.919 6.919-6.919h107.408c3.822 0 6.919 3.097 6.919 6.919s-3.097 6.919-6.919 6.919h-107.408c-3.823 0-6.919-3.097-6.919-6.919z"/></svg>';
2461                gc__delivery__text = gc__icon + gc__delivery__text;
2462
2463                console.log('GC Free Delivery Info: Próg=' + gc__threshold + ', Koszyk=' + gc__current__basket + ', Brakuje=' + gc__missing + ' ' + gc__currency);
2464
2465                // Znajdź i zaktualizuj istniejący slajd lub dodaj nowy
2466                let $existing = $('#gc__info_box .gc__delivery__info__slide');
2467                if ($existing.length) {
2468                    $existing.html(gc__delivery__text);
2469                    console.log('GC Free Delivery Info: Zaktualizowano istniejący slajd');
2470                } else {
2471                    let gc__owl = $('#gc__info_box').data('owl.carousel');
2472                    gc__owl.add('<p class="p1 gc__delivery__info__slide">' + gc__delivery__text + '</p>');
2473                    gc__owl.refresh();
2474                    console.log('GC Free Delivery Info: Dodano nowy slajd');
2475                }
2476            }, {});
2477        });
2478    }
2479
2480    // Czekaj aż Owl Carousel zostanie zainicjalizowany
2481    var gc__check__owl__interval = setInterval(function() {
2482        if ($('#gc__info_box').hasClass('owl-carousel') && $('#gc__info_box').data('owl.carousel')) {
2483            clearInterval(gc__check__owl__interval);
2484            gc__refresh__delivery__info();
2485        }
2486    }, 100);
2487
2488    // Event listener na dodanie do koszyka - odświeżenie po 300ms
2489    $(document).on('click', '.btn.btn-red.addtobasket', function() {
2490        setTimeout(function() {
2491            gc__refresh__delivery__info();
2492            console.log('GC Free Delivery Info: Odświeżono po dodaniu do koszyka');
2493        }, 300);
2494    });
2495
2496    console.log('GC Free Delivery: Moduł paska informacyjnego zainicjalizowany!');
2497});
2498// Koniec dodatku - Darmowa dostawa - pasek informacyjny
2499
2500// ========================================
2501// TYMCZASOWO WYŁĄCZONE - DODATEK STYCZEŃ 2025
2502// GrowCommerce - Bestsellers Category Tabs
2503// Filtrowanie produktów w boksie Bestsellers wg kategorii
2504// ========================================
2505//
2506// BACKUP ZMIENNYCH Z user.js - PRZYWRÓCIĆ W STYCZNIU 2025:
2507// --------------------------------------------------------
2508// let gc__bestsellers__category__tabs__on = 1; // 1 = włączone, 0 = wyłączone
2509//
2510// // Pokaż licznik produktów przy nazwie kategorii (np. "Łóżka (5)")
2511// let gc__bestsellers__tabs__show__count = 1; // 1 = pokazuj, 0 = ukryj
2512//
2513// // Tłumaczenia - zakładka "Wszystkie"
2514// let gc__bestsellers__tabs__all__text = {
2515//     en: 'All',
2516//     en_US: 'All',
2517//     pl_PL: 'Wszystkie',
2518//     de_DE: 'Alle',
2519//     de_AT: 'Alle',
2520//     cs_CZ: 'Vše',
2521//     fr_FR: 'Tout'
2522// };
2523//
2524// // Tłumaczenia - link "Zobacz wszystkie w kategorii"
2525// let gc__bestsellers__tabs__see__all__text = {
2526//     en: 'See all in category',
2527//     en_US: 'See all in category',
2528//     pl_PL: 'Zobacz wszystkie w kategorii',
2529//     de_DE: 'Alle in Kategorie anzeigen',
2530//     de_AT: 'Alle in Kategorie anzeigen',
2531//     cs_CZ: 'Zobrazit vše v kategorii',
2532//     fr_FR: 'Voir tout dans la catégorie'
2533// };
2534//
2535// // Tłumaczenia - kafelek kategorii w Bestsellerach
2536// let gc__bestsellers__tabs__tile__desc__text = {
2537//     en: 'See all products in category',
2538//     en_US: 'See all products in category',
2539//     pl_PL: 'Zobacz wszystkie produkty w kategorii',
2540//     de_DE: 'Alle Produkte in der Kategorie ansehen',
2541//     de_AT: 'Alle Produkte in der Kategorie ansehen',
2542//     cs_CZ: 'Zobrazit všechny produkty v kategorii',
2543//     fr_FR: 'Voir tous les produits de la catégorie'
2544// };
2545//
2546// let gc__bestsellers__tabs__check__text = {
2547//     en: 'check',
2548//     en_US: 'check',
2549//     pl_PL: 'sprawdź',
2550//     de_DE: 'prüfen',
2551//     de_AT: 'prüfen',
2552//     cs_CZ: 'zkontrolovat',
2553//     fr_FR: 'vérifier'
2554// };
2555// --------------------------------------------------------
2556// KONIEC BACKUPU ZMIENNYCH
2557// ========================================
2558//
2559// $(function GC__Bestsellers__Category__Tabs() {
2560//     // Sprawdź czy feature jest włączony
2561//     if (typeof gc__bestsellers__category__tabs__on === 'undefined' || gc__bestsellers__category__tabs__on !== 1) {
2562//         return;
2563//     }
2564//
2565//     var $box = $('#box_bestsellers');
2566//     if (!$box.length) {
2567//         return;
2568//     }
2569//
2570//     var $tabsContainer = $box.find('.gc__bestsellers__category__tabs');
2571//     if (!$tabsContainer.length || $tabsContainer.attr('data-gc-initialized') === 'true') {
2572//         return;
2573//     }
2574//
2575//     var $wrapper = $tabsContainer.find('.gc__category__tabs__wrapper');
2576//     var $innerbox = $box.find('.innerbox');
2577//     // UWAGA: Nie sprawdzamy isCarousel tutaj - carousel może nie być jeszcze zainicjalizowany
2578//     // Sprawdzenie odbywa się w gc__filter__products() przy kliknięciu w zakładkę
2579//
2580//     // Pobierz tłumaczenia
2581//     var lang = (typeof Shop !== 'undefined' && Shop.lang && Shop.lang.name) ? Shop.lang.name : 'pl_PL';
2582//     var allText = (typeof gc__bestsellers__tabs__all__text !== 'undefined')
2583//         ? (gc__bestsellers__tabs__all__text[lang] || gc__bestsellers__tabs__all__text['en'] || 'All')
2584//         : 'Wszystkie';
2585//     var showCount = (typeof gc__bestsellers__tabs__show__count !== 'undefined') ? gc__bestsellers__tabs__show__count : 1;
2586//
2587//     // Tłumaczenia dla pseudo-kafelka kategorii
2588//     var tileDescText = (typeof gc__bestsellers__tabs__tile__desc__text !== 'undefined')
2589//         ? (gc__bestsellers__tabs__tile__desc__text[lang] || gc__bestsellers__tabs__tile__desc__text['en'] || 'See all products in category')
2590//         : 'Zobacz wszystkie produkty w kategorii';
2591//     var checkText = (typeof gc__bestsellers__tabs__check__text !== 'undefined')
2592//         ? (gc__bestsellers__tabs__check__text[lang] || gc__bestsellers__tabs__check__text['en'] || 'check')
2593//         : 'sprawdź';
2594//
2595//     // Ścieżka do obrazków (używamy gc__images__version jak w innych modułach)
2596//     var imagePath = (typeof gc__images__version !== 'undefined')
2597//         ? '/skins/user/' + gc__images__version + '/images/user/'
2598//         : '/libraries/images/user/';
2599//
2600//     // Funkcja tworząca pseudo-kafelek kategorii
2601//     function gc__create__category__tile(catName, catUrl) {
2602//         return '<div class="gc__category__tile product">' +
2603//             '<a href="' + catUrl + '" class="gc__tile__link">' +
2604//                 '<span class="gc__tile__desc">' + tileDescText + '</span>' +
2605//                 '<strong class="gc__tile__category">' + catName + '</strong>' +
2606//                 '<span class="gc__tile__check">' + checkText +
2607//                     ' <img src="' + imagePath + 'gc__arrow__down.svg" alt="" class="gc__tile__arrow">' +
2608//                 '</span>' +
2609//             '</a>' +
2610//         '</div>';
2611//     }
2612//
2613//     // Zbierz unikalne kategorie z produktów
2614//     var categories = {};
2615//     var $products = $innerbox.find('.product[data-category]');
2616//
2617//     $products.each(function() {
2618//         var $prod = $(this);
2619//         var catName = $prod.attr('data-category');
2620//         var catId = $prod.attr('data-category-id');
2621//         var catUrl = $prod.attr('data-category-url');
2622//
2623//         if (catName && catName.trim() !== '') {
2624//             if (!categories[catName]) {
2625//                 categories[catName] = {
2626//                     name: catName,
2627//                     id: catId,
2628//                     url: catUrl,
2629//                     count: 0
2630//                 };
2631//             }
2632//             categories[catName].count++;
2633//         }
2634//     });
2635//
2636//     var categoryList = Object.values(categories);
2637//
2638//     // Jeśli mniej niż 2 kategorie, nie pokazuj zakładek
2639//     if (categoryList.length < 2) {
2640//         return;
2641//     }
2642//
2643//     // Sortuj kategorie alfabetycznie
2644//     categoryList.sort(function(a, b) {
2645//         return a.name.localeCompare(b.name);
2646//     });
2647//
2648//     // Generuj HTML zakładek
2649//     var tabsHtml = '';
2650//
2651//     // Zakładka "Wszystkie" - button, nie link
2652//     var allCount = $products.length;
2653//     tabsHtml += '<button class="gc__category__tab gc__active" data-category="all">';
2654//     tabsHtml += allText;
2655//     if (showCount) {
2656//         tabsHtml += ' <span class="gc__tab__count">(' + allCount + ')</span>';
2657//     }
2658//     tabsHtml += '</button>';
2659//
2660//     // Zakładki kategorii - linki SEO
2661//     categoryList.forEach(function(cat) {
2662//         tabsHtml += '<a href="' + cat.url + '" class="gc__category__tab" data-category="' + cat.name + '" data-category-url="' + cat.url + '">';
2663//         tabsHtml += cat.name;
2664//         if (showCount) {
2665//             tabsHtml += ' <span class="gc__tab__count">(' + cat.count + ')</span>';
2666//         }
2667//         tabsHtml += '</a>';
2668//     });
2669//
2670//     $wrapper.html(tabsHtml);
2671//
2672//     // Pokaż kontener zakładek
2673//     $tabsContainer.removeClass('none');
2674//     $tabsContainer.attr('data-gc-initialized', 'true');
2675//
2676//     // Zapisz oryginalne produkty przed jakimkolwiek filtrowaniem (dla carousel rebuild)
2677//     var originalProductsData = [];
2678//     $products.each(function() {
2679//         var $prod = $(this);
2680//         originalProductsData.push({
2681//             html: this.outerHTML,
2682//             category: $prod.attr('data-category'),
2683//             categoryUrl: $prod.attr('data-category-url')
2684//         });
2685//     });
2686//
2687//     // Obsługa kliknięć na zakładki
2688//     $wrapper.on('click', '.gc__category__tab', function(e) {
2689//         var $tab = $(this);
2690//         var category = $tab.attr('data-category');
2691//
2692//         // Jeśli Ctrl/Cmd+click na link kategorii - pozwól otworzyć w nowej karcie
2693//         if (category !== 'all' && (e.ctrlKey || e.metaKey)) {
2694//             return true; // Standardowe zachowanie linku
2695//         }
2696//
2697//         e.preventDefault();
2698//
2699//         // Aktualizuj aktywną zakładkę
2700//         $wrapper.find('.gc__category__tab').removeClass('gc__active');
2701//         $tab.addClass('gc__active');
2702//
2703//         // Pobierz URL kategorii (dla kafelka)
2704//         var catUrl = $tab.attr('data-category-url') || '';
2705//
2706//         // Filtruj produkty (kafelek tworzony wewnątrz funkcji filtrującej)
2707//         gc__filter__products(category, catUrl);
2708//     });
2709//
2710//     // Funkcja filtrowania produktów
2711//     function gc__filter__products(category, catUrl) {
2712//         // Sprawdź status karuzeli W MOMENCIE KLIKNIĘCIA (nie przy inicjalizacji!)
2713//         // owl-loaded = w pełni zainicjalizowany carousel
2714//         // owl.carousel data = instancja Owl Carousel
2715//         var isCarouselNow = $innerbox.hasClass('owl-loaded') || $innerbox.data('owl.carousel');
2716//
2717//         if (isCarouselNow) {
2718//             // Dla Owl Carousel - rebuild z przefiltrowanymi produktami
2719//             gc__filter__carousel(category, catUrl);
2720//         } else {
2721//             // Dla zwykłego grida - show/hide
2722//             gc__filter__grid(category, catUrl);
2723//         }
2724//     }
2725//
2726//     // Filtrowanie w gridzie (format != 3)
2727//     function gc__filter__grid(category, catUrl) {
2728//         // Usuń istniejący kafelek
2729//         $innerbox.find('.gc__category__tile').remove();
2730//
2731//         // Dodaj kafelek jeśli wybrano kategorię
2732//         if (category !== null && category !== 'all' && catUrl) {
2733//             var $tile = $(gc__create__category__tile(category, catUrl));
2734//             $innerbox.prepend($tile);
2735//         }
2736//
2737//         // Filtruj produkty
2738//         $products.each(function() {
2739//             var $prod = $(this);
2740//             if (category === null || category === 'all' || $prod.attr('data-category') === category) {
2741//                 $prod.removeClass('gc__hidden__by__filter');
2742//             } else {
2743//                 $prod.addClass('gc__hidden__by__filter');
2744//             }
2745//         });
2746//     }
2747//
2748//     // Filtrowanie w Owl Carousel (format == 3) - REBUILD approach
2749//     function gc__filter__carousel(category, catUrl) {
2750//         var owl = $innerbox.data('owl.carousel');
2751//
2752//         // Całkowicie zniszcz carousel i wyczyść strukturę
2753//         if (owl) {
2754//             owl.destroy();
2755//         }
2756//
2757//         // Usuń wszystkie klasy i struktury owl
2758//         $innerbox.removeClass('owl-loaded owl-hidden owl-grab');
2759//         $innerbox.find('.owl-stage-outer').remove();
2760//         $innerbox.find('.owl-nav').remove();
2761//         $innerbox.find('.owl-dots').remove();
2762//
2763//         // Wyczyść innerbox (usuń produkty które były wrapowane przez owl)
2764//         $innerbox.empty();
2765//
2766//         // Dodaj kafelek kategorii jako pierwszy element (jeśli wybrano kategorię)
2767//         if (category !== null && category !== 'all' && catUrl) {
2768//             var tileHtml = gc__create__category__tile(category, catUrl);
2769//             $innerbox.append(tileHtml);
2770//         }
2771//
2772//         // Dodaj przefiltrowane produkty (z zapisanych danych)
2773//         var filteredCount = 0;
2774//         originalProductsData.forEach(function(item) {
2775//             if (category === null || category === 'all' || item.category === category) {
2776//                 $innerbox.append(item.html);
2777//                 filteredCount++;
2778//             }
2779//         });
2780//
2781//         // Reinicjalizuj carousel z PRAWIDŁOWYMI opcjami (zgodnie z gc__footer__sliders.js)
2782//         var hasTile = (category !== null && category !== 'all' && catUrl);
2783//         var totalItems = hasTile ? filteredCount + 1 : filteredCount;
2784//
2785//         // Oblicz ilość produktów jak w gc__footer__sliders.js (linie 90-91)
2786//         var gc__smaller = $innerbox.closest('.f-grid-9').length ? 4 : 5;
2787//         var gc__smaller2 = $innerbox.closest('.f-grid-9').length ? 3 : 4;
2788//
2789//         $innerbox.owlCarousel({
2790//             lazyLoad: false,
2791//             loop: totalItems > 5,
2792//             margin: 10,
2793//             autoHeight: true,
2794//             responsiveClass: true,
2795//             responsive: {
2796//                 0: { items: 1, nav: true },
2797//                 380: { items: 2, nav: true },
2798//                 800: { items: gc__smaller2, nav: true },
2799//                 1200: { items: gc__smaller, nav: true }
2800//             }
2801//         });
2802//
2803//         // Ręcznie załaduj obrazki lozad (IntersectionObserver nie działa dla elementów już w viewport)
2804//         $innerbox.find('img.lozad[data-src]').each(function() {
2805//             var $img = $(this);
2806//             var dataSrc = $img.attr('data-src');
2807//             if (dataSrc) {
2808//                 $img.attr('src', dataSrc);
2809//                 $img.addClass('gc__lozad__loaded');
2810//             }
2811//         });
2812//
2813//         console.log('GC Bestsellers: Carousel rebuilt with ' + filteredCount + ' products' + (hasTile ? ' + tile' : ''));
2814//     }
2815//
2816//     // Desktop: Gradient scroll indicators
2817//     function updateScrollIndicators() {
2818//         if (window.innerWidth < 980) return;
2819//
2820//         var wrapper = $wrapper[0];
2821//         if (!wrapper) return;
2822//
2823//         var hasOverflow = wrapper.scrollWidth > wrapper.clientWidth;
2824//         if (!hasOverflow) {
2825//             $tabsContainer.removeClass('gc__has__scroll__left gc__has__scroll__right');
2826//             return;
2827//         }
2828//
2829//         var scrollLeft = wrapper.scrollLeft;
2830//         var maxScroll = wrapper.scrollWidth - wrapper.clientWidth;
2831//
2832//         $tabsContainer.toggleClass('gc__has__scroll__left', scrollLeft > 10);
2833//         $tabsContainer.toggleClass('gc__has__scroll__right', scrollLeft < maxScroll - 10);
2834//     }
2835//
2836//     $wrapper.on('scroll', updateScrollIndicators);
2837//     $(window).on('resize', updateScrollIndicators);
2838//     setTimeout(updateScrollIndicators, 100);
2839//
2840//     console.log('GC Bestsellers Category Tabs: Zainicjalizowano z ' + categoryList.length + ' kategoriami');
2841// });
2842// Koniec GrowCommerce - Bestsellers Category Tabs

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.