PageSourceSearch

https://absolute-teamsport-soc.de/templates/NOVA/js/jtl.evo.js?v=5.3.1

js absolute-teamsport-soc.de collected 2026-09-24 13:17:01 UTC 48,789 bytes, 1,250 lines download raw bytes

1(function () {
2    'use strict';
3
4    if (!$.evo) {
5        $.evo = {};
6    }
7
8    var EvoClass = function() {};
9
10    EvoClass.prototype = {
11        options: {
12            captcha: {},
13            scrollSearch: '.smoothscroll-top-search'
14        },
15
16        constructor: EvoClass,
17
18        generateSlickSlider: function() {
19            let self = this;
20
21            const observer = new window.IntersectionObserver(entries => {
22                for (const entry of entries) {
23                    if (entry.isIntersecting) {
24                        let mainNode = $(entry.target);
25                        mainNode.removeClass('slick-lazy');
26                        if (!mainNode.hasClass('slick-initialized')) {
27                            mainNode.find('.product-wrapper').removeClass('mx-auto ml-auto-util mr-auto');
28                            self.initSlick(mainNode, mainNode.data('slick-type'), mainNode.data('display-counts'));
29                            mainNode.find('.slick-active a:first-child').attr({
30                                'tabindex': '-1'
31                            });
32
33                        }
34                    }
35                }
36            }, {
37                root: null,
38                threshold: 0.1, // set offset 0.1 means trigger if atleast 10% of element in viewport
39            })
40
41            document.querySelectorAll('.slick-lazy').forEach(function(slickItem) {
42                observer.observe(slickItem)
43            });
44
45            document.querySelectorAll('.slick-lazy').forEach(function(slickItem) {
46                let startX;
47                let supportsPassive = false;
48                try {
49                    let opts = Object.defineProperty({}, 'passive', {
50                        get: function() {
51                            supportsPassive = true;
52                        }
53                    });
54                    window.addEventListener("testPassive", null, opts);
55                    window.removeEventListener("testPassive", null, opts);
56                } catch (e) {}
57
58                slickItem.addEventListener('touchstart', function (e) {
59                    startX = e.changedTouches[0].pageX;
60
61                },supportsPassive ? { passive: true } : false);
62                slickItem.addEventListener('touchmove', function (e) {
63                    let mainNode = $(this);
64                    if (!mainNode.hasClass('slick-initialized')
65                        && Math.abs(startX - e.changedTouches[0].pageX) > 80
66                    ) {
67                        mainNode.removeClass('slick-lazy');
68                        mainNode.find('.product-wrapper').removeClass('mx-auto ml-auto-util mr-auto');
69                        self.initSlick(mainNode, mainNode.data('slick-type'), mainNode.data('display-counts'));
70                        let slickOptions = mainNode.slick('getSlick');
71                        if(slickOptions.slideCount > mainNode.slick('slickGetOption', 'slidesToShow')) {
72                            let goTo;
73                            $.each(slickOptions.originalSettings.responsive, function (key, value) {
74                                if (value.breakpoint === slickOptions.activeBreakpoint
75                                    && value.settings.slidesToShow !== undefined
76                                ) {
77                                    goTo = value.settings.slidesToShow;
78                                }
79                            });
80                            if (goTo === undefined) {
81                                goTo = slickOptions.originalSettings.slidesToScroll
82                            }
83                            mainNode.slick('slickGoTo', goTo || 2);
84                        }
85                    }
86                }, supportsPassive ? { passive: true } : false);
87            });
88        },
89
90        initSlick: function (node, sliderType, displayCounts = '') {
91            displayCounts = displayCounts.split(',');
92            displayCounts = [
93                parseInt(displayCounts[0]) || 2,
94                parseInt(displayCounts[1]) || 3,
95                parseInt(displayCounts[2]) || 5,
96                parseInt(displayCounts[3]) || 7,
97            ];
98            let sliderOptions = {
99                'box-slider' : {
100                    arrows:         false,
101                    lazyLoad:       'ondemand',
102                    slidesToShow:   1,
103                    slidesToScroll: 1,
104                    mobileFirst:    true,
105                    responsive: [
106                        {
107                            breakpoint: 992,
108                            settings: {
109                                arrows: true,
110                            }
111                        }
112                    ]
113                },
114                'slider-half' : {
115                    arrows:       false,
116                    lazyLoad:     'ondemand',
117                    mobileFirst:    true,
118                    slidesToShow: 2,
119                    slidesToScroll: 2,
120                    responsive:   [
121                        {
122                            breakpoint: 992,
123                            settings: {
124                                arrows: true,
125                            }
126                        },
127                        {
128                            breakpoint: 1300,
129                            settings: {
130                                slidesToShow: 3,
131                                slidesToScroll: 3,
132                                arrows: true,
133                            }
134                        }
135                    ]
136                },
137                'slider-three' : {
138                    arrows:       false,
139                    lazyLoad:     'ondemand',
140                    mobileFirst:    true,
141                    slidesToShow: 1,
142                    slidesToScroll: 1,
143                    responsive:   [
144                        {
145                            breakpoint: 768,
146                            settings: {
147                                slidesToShow: 2,
148                                slidesToScroll: 2,
149                            }
150                        },
151                        {
152                            breakpoint: 992,
153                            settings: {
154                                arrows: true,
155                            }
156                        },
157                        {
158                            breakpoint: 1300,
159                            settings: {
160                                arrows: true,
161                                slidesToShow: 3,
162                                slidesToScroll: 3,
163                            }
164                        }
165                    ]
166                },
167                'product-slider' : {
168                    rows:           0,
169                    arrows:         false,
170                    lazyLoad:       'ondemand',
171                    slidesToShow:   displayCounts[0] || 2,
172                    slidesToScroll: displayCounts[0] || 2,
173                    mobileFirst:    true,
174                    responsive:     [
175                        {
176                            breakpoint: 768,
177                            settings: {
178                                slidesToShow: displayCounts[1] || 3,
179                                slidesToScroll: displayCounts[1] || 3,
180                            }
181                        },
182                        {
183                            breakpoint: 992,
184                            settings: {
185                                slidesToShow: displayCounts[2] || 5,
186                                slidesToScroll: displayCounts[2] || 5,
187                                arrows: true,
188                            }
189                        },
190                        {
191                            breakpoint: 1300,
192                            settings: {
193                                slidesToShow: displayCounts[3] || 7,
194                                slidesToScroll: displayCounts[3] || 7,
195                                arrows: true,
196                            }
197                        }
198                    ]
199                },
200                'news-slider' : {
201                    rows:           0,
202                    slidesToShow:   1,
203                    slidesToScroll: 1,
204                    arrows:         false,
205                    infinite:       false,
206                    lazyLoad:       'ondemand',
207                    mobileFirst:    true,
208                    responsive:     [
209                        {
210                            breakpoint: 768,
211                            settings: {
212                                slidesToShow: 2,
213                                slidesToScroll: 2,
214                            }
215                        },
216                        {
217                            breakpoint: 992,
218                            settings: {
219                                slidesToShow:3,
220                                slidesToScroll: 3,
221                                arrows: true
222                            }
223                        },
224                        {
225                            breakpoint: 1300,
226                            settings: {
227                                slidesToShow:5,
228                                slidesToScroll: 5,
229                                arrows: true
230                            }
231                        }
232                    ]
233                },
234                'freegift' : {
235                    slidesToShow:   3,
236                    slidesToScroll: 3,
237                    arrows:   false,
238                    infinite: false,
239                    responsive: [
240                        {
241                            breakpoint: 768,
242                            settings: {
243                                slidesToShow: 2,
244                                slidesToScroll: 2,
245                            }
246                        },
247                        {
248                            breakpoint: 992,
249                            settings: {
250                                arrows: true
251                            }
252                        }
253                    ]
254                },
255                'gallery' : {
256                    lazyLoad: 'ondemand',
257                    infinite: true,
258                    dots:     false,
259                    arrows:   true,
260                    speed: 500,
261                    fade: true,
262                    cssEase: 'linear',
263                    asNavFor: '#gallery_preview',
264                    responsive:     [
265                        {
266                            breakpoint: 992,
267                            settings: {
268                                dots: true
269                            }
270                        }
271                    ]
272                },
273                'gallery_preview' : {
274                    lazyLoad:       'ondemand',
275                    slidesToShow:   5,
276                    slidesToScroll: 1,
277                    asNavFor:       '#gallery',
278                    dots:           false,
279                    arrows:         true,
280                    focusOnSelect:  true,
281                    responsive:     [
282                        {
283                            breakpoint: 768,
284                            settings:   {
285                                slidesToShow: 4,
286                                slidesToScroll: 1,
287                            }
288                        },
289                        {
290                            breakpoint: 576,
291                            settings: {
292                                slidesToShow: 3,
293                                slidesToScroll: 1,
294                            }
295                        }
296                    ]
297                }
298            };
299            if ($('#content').hasClass('col-lg-9')) {
300                sliderOptions['news-slider']['slidesToShow'] = 2;
301            }
302            if (sliderType === 'gallery_preview') {
303                sliderType = 'gallery';
304                node = $('#gallery');
305            }
306            if (sliderType === 'gallery') {
307                $('.js-gallery-images').removeClass('d-none');
308                $('.slick-inital-arrow').remove();
309                $('.initial-slick-dots').remove();
310                $('#gallery_preview').slick(sliderOptions['gallery_preview']);
311            }
312
313            return node.slick(sliderOptions[sliderType]);
314        },
315
316        scrollStuff: function() {
317            var breakpoint = 0,
318                pos,
319                sidePanel = $('#sidepanel_left');
320
321            if(sidePanel.length) {
322                breakpoint = sidePanel.position().top + sidePanel.hiddenDimension('height');
323            }
324
325            pos = breakpoint - $(this).scrollTop();
326
327            if ($(this).scrollTop() > 200 && !$('#to-top').hasClass('active')) {
328                $('#to-top').addClass('active');
329            } else if($(this).scrollTop() < 200 && $('#to-top').hasClass('active')) {
330                $('#to-top').removeClass('active');
331            }
332
333            if ($(window).width() > 768) {
334                var $document = $(document),
335                    $element = $('.navbar-fixed-top'),
336                    className = 'nav-closed';
337
338                $document.scroll(function() {
339                    $element.toggleClass(className, $document.scrollTop() >= 150);
340                });
341
342            }
343        },
344
345        productTabsPriceFlow: function() {
346            var dateFormat = 'DD.MM.YYYY';
347            if ($('html').attr('lang') !== 'de') {
348                dateFormat = 'MM/DD/YYYY';
349            }
350            var chartOptions = {
351                responsive:       true,
352                scaleBeginAtZero: false,
353                aspectRatio:3,
354                tooltips: {
355                    callbacks: {
356                        label: function (tooltipItem, data) {
357                            var label = window.chartDataTooltip;
358                            label += Math.round(tooltipItem.yLabel * 100) / 100;
359                            label += ' '+window.chartDataCurrency;
360                            return label;
361                        }
362                    }
363                },
364                scales: {
365                    xAxes: [{
366                        type: 'time',
367                        time: {
368                            parser: 'DD.MM.YYYY',
369                            // round: 'day'
370                            tooltipFormat: dateFormat
371                        },
372                        display: false
373                    }],
374                }
375            };
376            if (typeof window.priceHistoryChart !== 'undefined' && window.priceHistoryChart === null) {
377                window.priceHistoryChart = new Chart(window.ctx, {
378                    type: 'line',
379                    data: window.chartData,
380                    options: chartOptions
381                });
382            }
383        },
384
385        tooltips: function() {
386            $('[data-toggle="tooltip"]').tooltip();
387        },
388
389        bootlint: function() {
390            (function(){
391                var p = window.alert;
392                var s = document.createElement("script");
393                window.alert = function() {
394                    console.info(arguments);
395                };
396                s.onload = function() {
397                    bootlint.showLintReportForCurrentDocument([]);
398                    window.alert = p;
399                };
400                s.src = "https://maxcdn.bootstrapcdn.com/bootlint/latest/bootlint.min.js";
401                document.body.appendChild(s);
402            })();
403        },
404
405        showNotify: function(options) {
406            eModal.alert({
407                size: 'xl',
408                buttons: false,
409                title: options.title,
410                message: options.text,
411                keyboard: true,
412                tabindex: -1})
413                .then(
414                 function() {
415                    $.evo.generateSlickSlider();
416                }
417            );
418        },
419
420        popupDep: function() {
421            $('#main-wrapper').on('click', '.popup-dep', function(e) {
422                var id    = '#popup' + $(this).attr('id'),
423                    title = $(this).attr('title'),
424                    html  = $(id).html();
425                eModal.alert({
426                    message: html,
427                    title: title,
428                    keyboard: true,
429                    buttons: false,
430                    tabindex: -1})
431                    .then(
432                        function () {
433                            //the modal just copies all the html.. so we got duplicate IDs which confuses recaptcha
434                            var recaptcha = $('.tmp-modal-content .g-recaptcha');
435                            if (recaptcha.length === 1) {
436                                var siteKey = recaptcha.data('sitekey'),
437                                    newRecaptcha = $('<div />');
438                                if (typeof  siteKey !== 'undefined') {
439                                    //create empty recapcha div, give it a unique id and delete the old one
440                                    newRecaptcha.attr('id', 'popup-recaptcha').addClass('g-recaptcha form-group');
441                                    recaptcha.replaceWith(newRecaptcha);
442                                    grecaptcha.render('popup-recaptcha', {
443                                        'sitekey' : siteKey,
444                                        'callback' : 'captcha_filled'
445
446                                    });
447                                }
448                            }
449                            addValidationListener();
450                            $('.g-recaptcha-response').attr('required', true);
451                        }
452                    );
453                return false;
454            });
455        },
456
457        popover: function() {
458            /*
459             * <a data-toggle="popover" data-ref="#popover-content123">Click me</a>
460             * <div id="popover-content123" class="popover">content here</div>
461             */
462            $('[data-toggle="popover"]').popover({
463                html: true,
464                sanitize: false,
465                content: function() {
466                    var ref = $(this).attr('data-ref');
467                    return $(ref).html();
468                }
469            });
470        },
471
472        smoothScrollToAnchor: function(href, pushToHistory) {
473            var anchorRegex = /^#[\w\-]+$/;
474            if (!anchorRegex.test(href)) {
475                return false;
476            }
477
478            var target, targetOffset;
479            target = $('#' + href.slice(1));
480
481            if (target.length > 0) {
482                // scroll below the static megamenu
483                var nav         = $('#jtl-nav-wrapper.sticky-top');
484                var fixedOffset = nav.length > 0 ? nav.outerHeight() : 0;
485
486                targetOffset = target.offset().top - fixedOffset - parseInt(target.css('margin-top'));
487                $('html, body').animate({scrollTop: targetOffset});
488
489                if (pushToHistory) {
490                    history.pushState({}, document.title, location.pathname + href);
491                }
492
493                return true;
494            }
495
496            return false;
497        },
498
499        smoothScroll: function() {
500            var supportHistory = (history && history.pushState) ? true : false;
501            var that = this;
502
503            this.smoothScrollToAnchor(location.hash, false);
504            $(document).delegate('a[href^="#"]', 'click', function(e) {
505                var elem = e.target;
506                if (!e.isDefaultPrevented()) {
507                    // only runs if no other click event is fired
508                    if (that.smoothScrollToAnchor(elem.getAttribute('href'), supportHistory)) {
509                        e.preventDefault();
510                    }
511                }
512            });
513        },
514
515        initSkipToScroll: function() {
516            // set focus on skip-to links
517            let links = $('.btn-skip-to');
518            var that = this;
519
520            links.on('click', function(e) {
521                let url    = new URL(e.target.href);
522                let target = url.hash;
523
524                that.smoothScrollToAnchor(target, false);
525                $(target).focus();
526            });
527        },
528
529        initScrollSearchEvent: function() {
530            this.destroyScrollSearchEvent();
531            let lastScroll       = 0,
532                $scrollTopSearch = $(this.options.scrollSearch);
533            if ($scrollTopSearch.length) {
534                $(document).on('scroll.search', function () {
535                    let newScroll = $(this).scrollTop();
536                    if (newScroll < lastScroll) {
537                        if ($(window).scrollTop() > 100) {
538                            $scrollTopSearch.removeClass('d-none');
539                        } else {
540                            $scrollTopSearch.addClass('d-none');
541                        }
542                    } else {
543                        $scrollTopSearch.addClass('d-none');
544                    }
545                    lastScroll = newScroll;
546                });
547            }
548        },
549
550        destroyScrollSearchEvent: function() {
551            $(this.options.scrollSearch).addClass('d-none');
552            $(document).off('scroll.search');
553        },
554
555        initScrollEvents: function() {
556            this.initScrollSearchEvent();
557
558            //scroll top button
559            let toTopbuttonVisible     = false,
560                $toTopbutton           = $('.smoothscroll-top'),
561                toTopbuttonActiveClass = 'show';
562
563            function scrolltoTop() {
564                $(window).scrollTop(0);
565            }
566
567            function handleVisibilityTopButton() {
568                let currentPosition = $(window).scrollTop();
569                if (currentPosition > 800) {
570                    if (!toTopbuttonVisible) {
571                        $toTopbutton.addClass(toTopbuttonActiveClass);
572                        toTopbuttonVisible = true;
573                    }
574                } else if (toTopbuttonVisible) {
575                    toTopbuttonVisible = false;
576                    $toTopbutton.removeClass(toTopbuttonActiveClass)
577                }
578            }
579
580            if ($toTopbutton.length) {
581                $(window).on('scroll', handleVisibilityTopButton);
582                $toTopbutton.on('click', scrolltoTop);
583                handleVisibilityTopButton();
584            }
585        },
586
587        resetForParallax: function() {
588            $(window).trigger('resize').trigger('scroll');
589        },
590
591        addCartBtnAnimation: function() {
592            var animating = false;
593
594            initCustomization();
595
596            function initCustomization() {
597                var addToCartBtn = $('#add-to-cart button[type="submit"]'),
598                    form         = $('#buy_form');
599                //detect click on the add-to-cart button
600                form.on('submit', function(e) {
601                    if(!animating ) {
602                        //animate if not already animating
603                        animating =  true;
604
605                        addToCartBtn.addClass('is-added').find('path').eq(0).animate({
606                            //draw the check icon
607                            'stroke-dashoffset':0
608                        }, 300, function(){
609                            setTimeout(function(){
610                                addToCartBtn.removeClass('is-added').find('span.btn-basket-check').on('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
611                                    //wait for the end of the transition to reset the check icon
612                                    addToCartBtn.find('path').eq(0).css('stroke-dashoffset', '19.79');
613                                    animating =  false;
614                                });
615
616                                if( $('.no-csstransitions').length > 0 ) {
617                                    // check if browser doesn't support css transitions
618                                    addToCartBtn.find('path').eq(0).css('stroke-dashoffset', '19.79');
619                                    animating =  false;
620                                }
621                            }, 600);
622                        });
623                    }
624                });
625            }
626
627        },
628
629        checkout: function() {
630            // show only the first submit button (i.g. the button from payment plugin)
631            var $submits = $('#checkout-shipping-payment')
632                .closest('form')
633                .find('button[type="submit"]');
634            $submits.addClass('d-none');
635            $submits.first().removeClass('d-none');
636
637            $('input[name="Versandart"]', '#checkout-shipping-payment').on('change', function() {
638                var id    = parseInt($(this).val());
639                var $form = $(this).closest('form');
640                if (isNaN(id)) {
641                    return;
642                }
643
644                $form.find('fieldset, button[type="submit"]')
645                    .attr('disabled', true);
646
647                var urlInstance = null;
648                if ($form.length === 1 && $form.attr('action') !== undefined) {
649                    urlInstance = new URL($form.attr('action'));
650                    urlInstance.searchParams.append('kVersandart', '' + id);
651                }
652                var url = urlInstance === null
653                    ? $('#jtl-io-path').data('path') + '/bestellvorgang.php?kVersandart=' + id
654                    : urlInstance.href;
655                $.evo.loadContent(url, function() {
656                    $.evo.checkout();
657                }, null, true);
658            });
659
660            $('#country').on('change', function (e) {
661                var val = $(this).find(':selected').val();
662
663                $.evo.io().call('checkDeliveryCountry', [val], {}, function (error, data) {
664                    var $shippingSwitch = $('#checkout_register_shipping_address');
665
666                    if (data.response) {
667                        $shippingSwitch.removeAttr('disabled');
668                        $shippingSwitch.parent().removeClass('d-none');
669                    } else {
670                        $shippingSwitch.attr('disabled', true);
671                        $shippingSwitch.parent().addClass('d-none');
672                        if ($shippingSwitch.prop('checked')) {
673                            $shippingSwitch.prop('checked', false);
674                            $('#select-shipping-address').collapse('show');
675                        }
676                    }
677                });
678            });
679        },
680
681        loadContent: function(url, callback, error, animation, wrapper) {
682            var that        = this;
683            var $wrapper    = (typeof wrapper === 'undefined' || wrapper.length === 0) ? $('#result-wrapper') : $(wrapper);
684            var ajaxOptions = {data: 'isAjax'};
685            if (animation) {
686                $wrapper.addClass('loading');
687            }
688
689            that.trigger('load.evo.content', { url: url });
690
691            $.ajax(url, ajaxOptions).done(function(html) {
692                var $data = $(html);
693                if (animation) {
694                    $data.addClass('loading');
695                }
696                $wrapper.replaceWith($data);
697                $wrapper = $data;
698                if (typeof callback === 'function') {
699                    callback();
700                }
701            })
702            .fail(function() {
703                if (typeof error === 'function') {
704                    error();
705                }
706            })
707            .always(function() {
708                $wrapper.removeClass('loading');
709                that.trigger('contentLoaded'); // compatibility
710                that.trigger('loaded.evo.content', { url: url });
711            });
712        },
713
714        startSpinner: function (target) {
715            target = target || $('body');
716            if ($('.jtl-spinner').length === 0) {
717                target.append('<div class="jtl-spinner"><i class="fa fa-spinner fa-pulse"></i></div>');
718            }
719        },
720
721        stopSpinner: function () {
722            $('.jtl-spinner').remove();
723        },
724
725        trigger: function(event, args) {
726            $(document).trigger('evo:' + event, args);
727            return this;
728        },
729
730        error: function() {
731            if (console && console.error) {
732                if (1 in arguments && arguments[1] === 'abort') {
733                    console.info(arguments);
734                } else {
735                    console.error(arguments);
736                }
737            }
738        },
739
740        addInactivityCheck: function(wrapper, timeoutMS = 500, stopEnter = false) {
741            var timeoutID,
742                that = this,
743                currentBox;
744
745            setup();
746
747            function setup() {
748                $(wrapper + ' .form-counter input, ' + wrapper + ' .choose_quantity input').on('change',resetTimer);
749                $(wrapper + ' .form-counter .btn-decrement, ' + wrapper + ' .form-counter .btn-increment')
750                    .on('click keydown',resetTimer)
751                    .on('touchstart',resetTimer,{passive: true});
752                if (stopEnter) {
753                    $(wrapper + ' input.quantity').on('keypress', function (e) {
754                        if (e.key === 'Enter') {
755                            return false;
756                        } else {
757                            resetTimer(e);
758                        }
759                    });
760                }
761            }
762
763            function startTimer() {
764                timeoutID = window.setTimeout(goInactive, timeoutMS);
765            }
766
767            function resetTimer(e) {
768                // prevents form submit on navigating via tab-key
769                if (e.keyCode !== 9) {
770                    if (wrapper === '#wl-items-form') {
771                        currentBox = $(e.target).closest('.productbox-inner');
772                    }
773                    if (timeoutID == undefined) {
774                        startTimer();
775                    }
776                    window.clearTimeout(timeoutID);
777
778                    startTimer();
779                }
780            }
781
782            function goInactive() {
783                if (wrapper === '#cart-form') {
784                    $(wrapper).submit();
785                } else if (wrapper === '#wl-items-form') {
786                    that.updateWishlistItem(currentBox);
787                }
788            }
789        },
790
791        updateWishlistItem: function($wrapper) {
792            let formID   = 'wl-items-form';
793            $.evo.extended().startSpinner($wrapper);
794            $.evo.io().call(
795                'updateWishlistItem',
796                [
797                    parseInt($('#' + formID + ' input[name="kWunschliste"]').val()),
798                    $.evo.io().getFormValues(formID)
799                ],
800                $(this) , function(error, data) {
801                    $.evo.extended().stopSpinner();
802                    $wrapper.removeClass('loading');
803                });
804        },
805
806        fixStickyElements: function() {
807            var sticky    = '.cart-summary';
808            var navHeight = $('#jtl-nav-wrapper').outerHeight(true);
809            navHeight = navHeight === undefined ? 0 : parseInt(navHeight + 40);
810            $(sticky).css('top', navHeight);
811        },
812
813        setWishlistVisibilitySwitches: function() {
814            $('.wl-visibility-switch').on('change', function () {
815                $.evo.io().call(
816                    'setWishlistVisibility',
817                    [$(this).data('wl-id'), $(this).is(":checked"), $('.
817jtl_token').val()],
818                    $(this),
819                    function(error, data) {
820                    if (error) {
821                        return;
822                    }
823                    var $wlPrivate    = $('span[data-switch-label-state="private-' + data.response.wlID + '"]'),
824                        $wlPublic     = $('span[data-switch-label-state="public-' + data.response.wlID + '"]'),
825                        $wlURLWrapper = $('#wishlist-url-wrapper'),
826                        $wlURL        = $('#wishlist-url');
827                    if (data.response.state) {
828                        $wlPrivate.addClass('d-none');
829                        $wlPublic.removeClass('d-none');
830                        $wlURLWrapper.removeClass('d-none');
831                        $wlURL.val($wlURL.data('static-route') + data.response.url)
832                    } else {
833                        $wlPrivate.removeClass('d-none');
834                        $wlPublic.addClass('d-none');
835                        $wlURLWrapper.addClass('d-none');
836                    }
837                });
838            });
839        },
840
841        setDeliveryAdressDefaultSwitches: function() {
842            $('.la-default-switch').on('change', function () {
843                let input = $(this);
844                $('.la-default-switch').each(function() {
845                    if (input.attr('id') !== $(this).attr('id')) {
846                        $(this).prop('checked', false);
847                    } else {
848                        $(this).prop('checked', true);
849                    }
850                });
851                $.evo.io().call(
852                    'setDeliveryaddressDefault',
853                    [$(this).data('la-id'), $('.jtl_token').val()],
854                    $(this), function(error, data) {
855                        if (error) {
856                            return;
857                        }
858                        if (!data.response.result) {
859                            input.prop('checked', false);
860                        }
861                    }
862                );
863            });
864        },
865
866        initEModals: function () {
867            $('.author-modal').on('click', function (e) {
868                e.preventDefault();
869                let modalID = $(this).data('target');
870                eModal.alert({
871                    title: $(modalID).attr('title'),
872                    message: $(modalID).html(),
873                    buttons: false
874                });
875            });
876        },
877
878        initPriceSlider: function ($wrapper, redirect) {
879            let priceRange      = $wrapper.find('[data-id="js-price-range"]').val(),
880                priceRangeID    = $wrapper.find('[data-id="js-price-range-id"]').val(),
881                priceRangeMin   = 0,
882                priceRangeMax   = $wrapper.find('[data-id="js-price-range-max"]').val(),
883                currentPriceMin = priceRangeMin,
884                currentPriceMax = priceRangeMax,
885                $priceRangeFrom = $("#" + priceRangeID + "-from"),
886                $priceRangeTo = $("#" + priceRangeID + "-to"),
887                $priceSlider = document.getElementById(priceRangeID);
888
889            if($priceSlider === null) {
890                return;
891            }
892
893            if (priceRange) {
894                let priceRangeMinMax = priceRange.split('_');
895                currentPriceMin = priceRangeMinMax[0];
896                currentPriceMax = priceRangeMinMax[1];
897                $priceRangeFrom.val(currentPriceMin);
898                $priceRangeTo.val(currentPriceMax);
899            }
900            noUiSlider.create($priceSlider, {
901                start: [parseInt(currentPriceMin), parseInt(currentPriceMax)],
902                connect: true,
903                range: {
904                    'min': parseInt(priceRangeMin),
905                    'max': parseInt(priceRangeMax)
906                },
907                step: 1,
908                format: {
909                    to: function (value) {
910                        return parseInt(value);
911                    },
912                    from: function (value) {
913                        return parseInt(value);
914                    }
915                },
916                handleAttributes: [
917                    { 'aria-label': 'lower' },
918                    { 'aria-label': 'upper' },
919                ],
920            });
921            $priceSlider.noUiSlider.on('change', function (values, handle) {
922                setTimeout(function(){
923                    $.evo.redirectToNewPriceRange(values[0] + '_' + values[1], redirect, $wrapper);
924                },0);
925            });
926            $priceSlider.noUiSlider.on('update', function (values, handle) {
927                $priceRangeFrom.val(values[0]);
928                $priceRangeTo.val(values[1]);
929            });
930            $('.price-range-input').on('change', function () {
931                let prFrom = parseInt($priceRangeFrom.val()),
932                    prTo = parseInt($priceRangeTo.val());
933                $.evo.redirectToNewPriceRange(
934                    (prFrom > 0 ? prFrom : priceRangeMin) + '_' + (prTo > 0 ? prTo : priceRangeMax),
935                    redirect,
936                    $wrapper
937                );
938            });
939        },
940
941        initFilters: function (href) {
942            let $wrapper = $('.js-collapse-filter');
943            $('#submitMobileFilters').addClass('disabled');
944            $.evo.extended().startSpinner($wrapper);
945
946            $.ajax(href, {data: {'useMobileFilters':1}})
947                .done(function(data) {
948                    $wrapper.html(data);
949                    $.evo.initPriceSlider($wrapper, false);
950                    $.evo.initItemSearch('filter');
951                })
952                .always(function() {
953                    $('#submitMobileFilters').removeClass('disabled');
954                    $.evo.extended().stopSpinner();
955                });
956        },
957
958        initFilterEvents: function() {
959            let initiallized = false;
960            $('#js-filters').on('click', function() {
961                if (!initiallized) {
962                    $.evo.initFilters(window.location.href);
963                    initiallized = true;
964                }
965            });
966        },
967
968        redirectToNewPriceRange: function (priceRange, redirect, $wrapper) {
969            let currentURL  = window.location.href;
970            if (!redirect) {
971                currentURL  = $wrapper.find('[data-id="js-price-range-url"]').val();
972            }
973            let redirectURL = $.evo.updateURLParameter(
974                currentURL,
975                'pf',
976                priceRange
977            );
978            if (redirect) {
979                window.location.href = redirectURL;
980            } else {
981                $.evo.initFilters(redirectURL);
982            }
983        },
984
985        updateURLParameter: function (url, param, paramVal) {
986            let newAdditionalURL = '',
987                tempArray        = url.split('?'),
988                baseURL          = tempArray[0],
989                additionalURL    = tempArray[1],
990                temp             = '';
991            if (additionalURL) {
992                tempArray = additionalURL.split('&');
993                for (let i=0; i<tempArray.length; i++){
994                    if(tempArray[i].split('=')[0] != param){
995                        newAdditionalURL += temp + tempArray[i];
996                        temp = '&';
997                    }
998                }
999            }
1000
1001            return baseURL + '?' + newAdditionalURL + temp + param + '=' + paramVal;
1002        },
1003
1004        updateReviewHelpful: function(item) {
1005            let formData = $.evo.io().getFormValues('reviews-list');
1006            formData[item.prop('name')] = '';
1007            formData['reviewID'] = item.data('review-id');
1008
1009            $.evo.io().call(
1010                'updateReviewHelpful',
1011                [formData],
1012                $(this) , function(error, data) {
1013                    if (error) {
1014                        return;
1015                    }
1016                    let review = data.response.review;
1017
1018                    $('[data-review-id="' + review.kBewertung + '"]').removeClass('on-list');
1019                    item.addClass('on-list');
1020                    $('[data-review-count-id="hilfreich_' + review.kBewertung + '"]').html(review.nHilfreich);
1021                    $('[data-review-count-id="nichthilfreich_' + review.kBewertung + '"]').html(review.nNichtHilfreich);
1022                });
1023        },
1024
1025        initReviewHelpful: function() {
1026            $('.js-helpful').on('click', function (e) {
1027                e.preventDefault();
1028                $.evo.extended().updateReviewHelpful($(this));
1029            });
1030        },
1031
1032        initWishlist: function() {
1033            let wlFormID = '#wl-items-form';
1034            if ($(wlFormID).length) {
1035                $.evo.extended().addInactivityCheck(wlFormID, 300, true);
1036                $('.js-update-wl').on('change', function () {
1037                    $.evo.extended().updateWishlistItem($(this).closest('.productbox-inner'));
1038                });
1039                $(window).on('resize', function () {
1040                    setWishlistItemheights();
1041                });
1042                setWishlistItemheights();
1043            }
1044            function setWishlistItemheights() {
1045                $('.product-list').children().each(function() {
1046                    $(this).css('height', window.innerWidth > globals.breakpoints.xl ? $(this).height() : 'unset');
1047                });
1048            }
1049        },
1050
1051        initPaginationEvents: function() {
1052            $('.pagination-wrapper select').on('change', function () {
1053                this.form.submit();
1054            });
1055        },
1056
1057        initItemSearch: function(context) {
1058            let searchWrapper  = '.' + context + '-search-wrapper',
1059                searchInput    = '.' + context + '-search',
1060                itemValue      = '.' + context + '-item-value',
1061                item           = '.' + context + '-item',
1062                clear          = '.form-clear',
1063                inputSelected  = 'input-group-selected',
1064                $searchWrapper = $(searchWrapper);
1065
1066            if ($searchWrapper.length === 0) {
1067                return;
1068            }
1069            $searchWrapper.each((i, itemWrapper) => {
1070                $(itemWrapper).find(searchInput).on('input', function () {
1071                    filterSearch($(itemWrapper));
1072                    $(itemWrapper).find('.collapse').collapse('show');
1073                }).on('keydown', e => {
1074                    if (e.key === 'Escape') {
1075                        e.stopPropagation();
1076                    }
1077                });
1078            });
1079            $(searchWrapper + ' ' + clear).on('click', function() {
1080                $(this).prev().val('');
1081                $(this).addClass('d-none');
1082                filterSearch($(this).closest(searchWrapper));
1083            });
1084            $(searchInput).on('focusin', function() {
1085                $(this).closest(searchWrapper).addClass(inputSelected);
1086            }).on('focusout', function() {
1087                $(this).closest(searchWrapper).removeClass(inputSelected);
1088            });
1089
1090            function filterSearch (itemWrapper) {
1091                let searchTerm = itemWrapper.find(searchInput).val().toLowerCase();
1092                itemWrapper.find(itemValue).each((i, itemTMP) => {
1093                    itemTMP = $(itemTMP);
1094                    let text = itemTMP.text().toLowerCase();
1095                    if (text.indexOf(searchTerm) === -1) {
1096                        itemTMP.closest(item).hide();
1097                    } else {
1098                        itemTMP.closest(item).show();
1099                    }
1100                    if (searchTerm.length === 0) {
1101                        itemWrapper.find(clear).addClass('d-none');
1102                    } else {
1103                        itemWrapper.find(clear).removeClass('d-none');
1104                    }
1105                });
1106            }
1107        },
1108
1109        initSliders: function() {
1110            let wrapper  = '.js-slider-wrapper',
1111                buttonF  = '.js-btn-slider-sf',
1112                buttonB  = '.js-btn-slider-sb',
1113                items    = '.js-slider-items';
1114
1115            $(wrapper).each(function (e) {
1116                let $buttonF   = $(this).find(buttonF),
1117                    $buttonB   = $(this).find(buttonB),
1118                    $items     = $(this).find(items);
1119
1120                $buttonF.on('click', function () {
1121                    $items.animate(
1122                        { scrollLeft: $items.scrollLeft() + $items.width() },
1123                        300,
1124                        'swing',
1125                        function () {
1126                            checkButtonDisable($buttonB, $buttonF, $items);
1127                        });
1128                });
1129                $buttonB.on('click', function () {
1130                    $items.animate(
1131                        { scrollLeft: $items.scrollLeft() - $items.width() },
1132                        300,
1133                        'swing',
1134                        function () {
1135                            checkButtonDisable($buttonB, $buttonF, $items);
1136                        });
1137                });
1138                $items.on('touchend', function (e) {
1139                    checkButtonDisable($buttonB, $buttonF, $items);
1140                });
1141            });
1142
1143            function checkButtonDisable($buttonB, $buttonF, $items) {
1144                let currentScroll = $items.scrollLeft();
1145                if (currentScroll <= 1) {
1146                    $buttonB.prop('disabled', true);
1147                } else {
1148                    $buttonB.prop('disabled', false);
1149                }
1150                if (currentScroll >= $items[0].scrollWidth - $items.width()) {
1151                    $buttonF.prop('disabled', true);
1152                } else {
1153                    $buttonF.prop('disabled', false);
1154                }
1155            }
1156        },
1157
1158        initSwatchFocus: function($wrapper) {
1159            $('.swatches-image>input, .swatches-text>input', $wrapper).on('focusin', function () {
1160                $(this).parent('label').addClass('focus');
1161            }).on('focusout', function () {
1162                $(this).parent('label').removeClass('focus');
1163            });
1164        },
1165
1166        registerImageHover: function($wrapper) {
1167            $(window).on("load resize", function() {
1168                let productWrapper = $('.product-wrapper');
1169                $.each(productWrapper, function() {
1170                    // Skip if element is inside a closed collapse.
1171                    let collapse = $(this).closest('.collapse');
1172                    if (collapse.length === 0 || collapse.hasClass('show')) {
1173                        let boxHeight = $(this).height()
1174                        $(this).height(boxHeight);
1175                    }
1176                })
1177            })
1178        },
1179
1180        /**
1181         * $.evo.extended() is deprecated, please use $.evo instead
1182         */
1183        extended: function() {
1184            return $.evo;
1185        },
1186
1187        register: function() {
1188            this.productTabsPriceFlow();
1189            this.generateSlickSlider();
1190            setTimeout(() => {
1191                $('.nav-tabs').tabdrop();
1192            }, 200);
1193            this.tooltips();
1194            this.popupDep();
1195            this.popover();
1196            this.addCartBtnAnimation();
1197            this.checkout();
1198            if ($('body').data('page') == 3) {
1199                this.addInactivityCheck('#cart-form',500,true);
1200            }
1201            this.fixStickyElements();
1202            this.setWishlistVisibilitySwitches();
1203            this.setDeliveryAdressDefaultSwitches();
1204            this.initEModals();
1205            $.evo.article().initConfigListeners();
1206            this.initScrollEvents();
1207            this.initSkipToScroll();
1208            this.initReviewHelpful();
1209            this.initWishlist();
1210            this.initPaginationEvents();
1211            this.initFilterEvents();
1212            this.initItemSearch('filter');
1213            this.initSliders();
1214            this.initSwatchFocus();
1215            this.registerImageHover();
1216            this.wireUpPRGLinks();
1217        },
1218
1219        wireUpPRGLinks()
1220        {
1221            for (const prgLink of document.querySelectorAll('[data-prg-href]')) {
1222                prgLink.addEventListener('click', e => {
1223                    e.preventDefault();
1224                    let targetUrl = atob(prgLink.dataset.prgHref);
1225                    let urlInput = document.createElement('input');
1226                    let virtualForm = document.createElement('form');
1227                    document.body.append(virtualForm);
1228                    urlInput.name = 'prgTargetUrl';
1229                    urlInput.value = targetUrl;
1230                    virtualForm.action = window.jtlShopBaseUrl + '/prg';
1231                    virtualForm.method = 'post';
1232                    virtualForm.append(urlInput);
1233                    virtualForm.submit();
1234                });
1235            }
1236        },
1237    };
1238
1239    $(document).ready(function () {
1240        $.evo.register();
1241    });
1242
1243    // PLUGIN DEFINITION
1244    // =================
1245    $.evo = new EvoClass();
1246})(jQuery);
1247
1248function g_recaptcha_callback() {
1249    $.evo.renderCaptcha();
1250}

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.