PageSourceSearch

https://www.der-roemer-shop.de/templates/NOVA/js/global.js?v=5.3.0

js der-roemer-shop.de collected 2026-09-24 23:57:50 UTC 22,086 bytes, 625 lines download raw bytes

1'use strict';
2
3$('body').on('click', '.option li', function (e) {
4    var i = $(this).parents('.select').attr('id'),
5        v = $(this).children().text(),
6        o = $(this).attr('id');
7    $('#' + i + ' .selected').attr('id', o).text(v);
8});
9
10// prevent multiple form submit on client side
11$('.submit_once').closest('form').on('submit', function() {
12    $(this).find('.submit_once').prop('disabled', 'true');
13    return true;
14});
15
16/**
17 *  Format file size
18 */
19function formatSize(size) {
20    var fileSize = Math.round(size / 1024),
21        suffix = 'KB',
22        fileSizeParts;
23
24    if (fileSize > 1000) {
25        fileSize = Math.round(fileSize / 1000);
26        suffix = 'MB';
27    }
28
29    fileSizeParts = fileSize.toString().split('.');
30    fileSize = fileSizeParts[0];
31
32    if (fileSizeParts.length > 1) {
33        fileSize += '.' + fileSizeParts[1].substr(0, 2);
34    }
35    fileSize += suffix;
36
37    return fileSize;
38}
39
40function getCategoryMenu(categoryId, success) {
41    var xx = {};
42    var io = $.evo.io();
43
44    io.call('getCategoryMenu', [categoryId], xx, function (error, data) {
45        if (error) {
46            console.error(data);
47        } else if (typeof success === 'function') {
48            success(xx.response);
49        }
50    });
51
52    return true;
53}
54
55function categoryMenu(rootcategory) {
56    if (typeof rootcategory === 'undefined') {
57        rootcategory = $('.sidebar-offcanvas .navbar-categories').html();
58    }
59
60    $('.sidebar-offcanvas li a.nav-sub').on('click', function(e) {
61        var navbar = $('.sidebar-offcanvas .navbar-categories'),
62            ref = $(this).data('ref');
63
64        if (ref === 0) {
65            $(navbar).html(rootcategory);
66            categoryMenu(rootcategory);
67        }
68        else {
69            getCategoryMenu(ref, function(data) {
70                $(navbar).html(data);
71                categoryMenu(rootcategory);
72            });
73        }
74
75        return false;
76    });
77}
78
79function compatibility() {
80    var __enforceFocus = $.fn.modal.Constructor.prototype.enforceFocus;
81    $.fn.modal.Constructor.prototype.enforceFocus = function () {
82        if ($('.modal-body .g-recaptcha').length === 0) {
83            __enforceFocus.apply(this, arguments);
84        }
85    };
86}
87function regionsToState(){
88    $('.js-country-select').on('change', function() {
89
90        var result = {};
91        var io = $.evo.io();
92        var country = $(this).find(':selected').val();
93        country = (country !== null && country !== undefined) ? country : '';
94        var connection_id = $(this).attr('id').toString().replace("-country","");
95
96        io.call('getRegionsByCountry', [country], result, function (error, data) {
97            if (error) {
98                console.error(data);
99            } else {
100                var state_id = connection_id+'-state';
101                var state = $('#'+state_id);
102                var state_data = state.data();
103
104                if (typeof(result.response) === 'undefined' || state.length === 0) {
105                    return;
106                }
107                var title = state_data.defaultoption;
108                var stateIsRequired = result.response.required;
109                var data = result.response.states;
110                var def = $('#'+state_id).val();
111                if(typeof(data)!=='undefined'){
112                    if (data !== null && data.length > 0) {
113                        if (stateIsRequired){
114                            var state = $('<select />').attr({ id: state_id, name: state.attr('name'), class: 'custom-select required form-control js-state-select', required: 'required'});
115                        } else {
116                            var state = $('<select />').attr({ id: state_id, name: state.attr('name'), class: 'custom-select form-control js-state-select'});
117                        }
118
119                        Object.keys(state_data).forEach(function(key,index) {
120                            state.data(key,state_data[key]);
121                        });
122
123                        state.append('<option value="">' + title + '</option>');
124                        $(data).each(function(idx, item) {
125                            state.append(
126                                $('<option></option>').val(item.iso).html(item.name)
127                                    .attr('selected', item.iso == def || item.name == def ? 'selected' : false)
128                            );
129                        });
130                        $('#'+state_id).replaceWith(state);
131                    } else {
132                        if (stateIsRequired) {
133                            var state = $('<input />').attr({ type: 'text', id: state_id, name: state.attr('name'),  class: 'required form-control js-state-select', placeholder: title, required: 'required' });
134                        } else {
135                            var state = $('<input />').attr({ type: 'text', id: state_id, name: state.attr('name'),  class: 'form-control js-state-select', placeholder: title });
136                        }
137                        Object.keys(state_data).forEach(function(key,index) {
138                            state.data(key,state_data[key]);
139                        });
140                        $('#'+state_id).replaceWith(state);
141                    }
142                    if (stateIsRequired){
143                        state.parent().find('.state-optional').addClass('d-none');
144                    } else {
145                        state.parent().find('.state-optional').removeClass('d-none');
146                    }
147                }
148            }
149        });
150        return false;
151    }).trigger('change');
152}
153
154function loadContent(url)
155{
156    $.evo.extended().loadContent(url, function() {
157        $.evo.extended().register();
158
159        if (typeof $.evo.article === 'function') {
160            $.evo.article().onLoad();
161            $.evo.article().register();
162            addValidationListener();
163        }
164
165        let topbarHeight      = $('#header-top-bar').outerHeight() || 0,
166            wrapperHeight     = $('#jtl-nav-wrapper').outerHeight() || 0,
167            productListHeight = $('#product-list').offset().top || 0,
168            pageNavHeight     = $('.productlist-page-nav').outerHeight() || 0;
169        $('html,body').animate({
170            scrollTop: productListHeight - wrapperHeight - topbarHeight - pageNavHeight - 20
171        }, 100);
172    });
173}
174
175function sanitizeOutput(val) {
176    return val.replace(/\&/g, '&amp;')
177        .replace(/\</g, '&lt;')
178        .replace(/\>/g, '&gt;')
179        .replace(/\"/g, '&quot;')
180        .replace(/\'/g, '&#x27;')
181        .replace(/\//g, '&#x2F;');
182}
183
184function addValidationListener() {
185    var forms      = $('form.jtl-validate'),
186        inputs     = $('form.jtl-validate input, form.jtl-validate textarea').not('[type="radio"],[type="checkbox"]'),
187        selects    = $('form.jtl-validate select'),
188        checkables = $('form.jtl-validate input[type="radio"], form.jtl-validate input[type="checkbox"]'),
189        $body      = $('body');
190
191    for (var i = 0; i < forms.length; i++) {
192        forms[i].addEventListener('invalid', function (event) {
193            event.preventDefault();
194            $(event.target).closest('.form-group').find('div.form-error-msg').remove();
195            $(event.target).closest('.form-group')
196                .addClass('has-error')
197                .append('<div class="form-error-msg w-100">' + sanitizeOutput(event.target.validationMessage) + '</div>');
198
199            if (!$body.data('doScrolling')) {
200                var $firstError = $(event.target).closest('.form-group.has-error');
201                if ($firstError.length > 0) {
202                    $body.data('doScrolling', true);
203                    var $nav        = $('#jtl-nav-wrapper.sticky-top'),
204                        fixedOffset = $nav.length > 0 ? $nav.outerHeight() : 0,
205                        vpHeight    = $(window).height(),
206                        scrollTop   = $(window).scrollTop();
207                    if ($firstError.offset().top > (scrollTop + vpHeight) || $firstError.offset().top < scrollTop) {
208                        $('html, body').animate(
209                            {
210                                scrollTop: $firstError.offset().top - fixedOffset - parseInt($firstError.css('margin-top'))
211                            },
212                            {
213                                done: function () {
214                                    $body.data('doScrolling', false);
215                                }
216                            }, 300
217                        );
218                    }
219                }
220            }
221        }, true);
222    }
223
224    for (var i = 0; i < inputs.length; i++) {
225        inputs[i].addEventListener('blur', function (event) {
226            checkInputError(event);
227        }, true);
228    }
229    for (var i = 0; i < checkables.length; i++) {
230        checkables[i].addEventListener('click', function (event) {
231            checkInputError(event);
232        }, true);
233    }
234    for (var i = 0; i < selects.length; i++) {
235        selects[i].addEventListener('change', function (event) {
236            checkInputError(event);
237        }, true);
238    }
239}
240
241function checkInputError(event)
242{
243    var $target = $(event.target);
244    if ($target.parents('.cfg-group') != undefined) {
245        $target.parents('.cfg-group').find('div.form-error-msg').remove();
246    }
247    $target.parents('.form-group').find('div.form-error-msg').remove();
248
249    if ($target.data('must-equal-to') !== undefined) {
250        var $equalsTo = $($target.data('must-equal-to'));
251        if ($equalsTo.length === 1) {
252            var theOther = $equalsTo[0];
253            if (theOther.value !== '' && theOther.value !== event.target.value && event.target.value !== '') {
254                event.target.setCustomValidity($target.data('custom-message') !== undefined ? $target.data('custom-message') : sanitizeOutput(event.target.validationMessage));
255            } else {
256                event.target.setCustomValidity('');
257            }
258        }
259    }
260
261    if (event.target.validity.valid) {
262        $target.closest('.form-group').removeClass('has-error');
263    } else {
264        $target.closest('.form-group').addClass('has-error').append('<div class="form-error-msg">' + sanitizeOutput(event.target.validationMessage) + '</div>');
265    }
266}
267
268function captcha_filled() {
269    $('.g-recaptcha').closest('.form-group').find('div.form-error-msg').remove();
270}
271
272function isTouchCapable() {
273    return 'ontouchstart' in window || (window.DocumentTouch && document instanceof window.DocumentTouch);
274}
275
276function initWow()
277{
278    new WOW().init();
279}
280/*
281$(window).load(function(){
282    navigation();
283});*/
284
285$(document).ready(function () {
286    $('.collapse-non-validate')
287        .on('hidden.bs.collapse', function(e) {
288            $(e.target)
289                .addClass('hidden')
290                .find('fieldset, .form-control')
291                .attr('disabled', true);
292            e.stopPropagation();
293        })
294        .on('show.bs.collapse', function(e) {
295            $(e.target)
296                .removeClass('hidden')
297                .attr('disabled', false);
298            e.stopPropagation();
299        }).on('shown.bs.collapse', function(e) {
300            $(e.target)
301                .find('fieldset, .form-control')
302                .filter(function (i, e) {
303                    return $(e).closest('.collapse-non-validate.collapse').hasClass('show');
304                })
305                .attr('disabled', false);
306            e.stopPropagation();
307        });
308    $('.collapse-non-validate.collapse.show')
309        .removeClass('hidden')
310        .find('fieldset, .form-control')
311        .attr('disabled', false);
312    $('.collapse-non-validate.collapse:not(.show)')
313        .addClass('hidden')
314        .find('fieldset, .form-control')
315        .attr('disabled', true);
316
317    $('.collapse.collapse-with-button')
318        .on('show.bs.collapse', function (e) {
319            let btn = $('a[data-toggle="collapse"][href="#' + $(e.target).attr("id") + '"][data-label-show][data-label-hide]');
320            btn.html(btn.data('labelHide'));
321        })
322        .on('hidden.bs.collapse', function (e) {
323            let btn = $('a[data-toggle="collapse"][href="#' + $(e.target).attr("id") + '"][data-label-show][data-label-hide]');
324            btn.html(btn.data('labelShow'));
325        });
326    $('.collapse.collapse-with-clip')
327        .on('shown.bs.collapse', function (e) {
328            $('#clip-text-' + $(e.target).attr("id")).hide();
329        })
330        .on('hide.bs.collapse', function (e) {
331            $('#clip-text-' + $(e.target).attr("id")).show();
332        });
333
334    $('#complete-order-button').on('click', function () {
335        var commentField = $('#comment'),
336            commentFieldHidden = $('#comment-hidden');
337        if (commentField && commentFieldHidden) {
338            commentFieldHidden.val(commentField.val());
339        }
340    });
341
342    $(document).on('click', '.footnote-vat a, .versand, .popup', function(e) {
343        let url     = e.currentTarget.href,
344            classes = $(this).data('modal-classes') || '';
345        url += (url.indexOf('?') === -1) ? '?isAjax=true' : '&isAjax=true';
346        eModal.ajax({
347            size: 'xl ' + classes,
348            url: url,
349            title: typeof e.currentTarget.title !== 'undefined' ? e.currentTarget.title : '',
350            keyboard: true,
351            tabindex: -1,
352            buttons: false
353        });
354        e.stopPropagation();
355        return false;
356    });
357
358    $(document).on('click', '.pagination-ajax a:not(.active), .js-pagination-ajax:not(.active)', function(e) {
359        var url = $(this).attr('href');
360        history.pushState(null, null, url);
361        loadContent(url);
362        return e.preventDefault();
363    });
364
365    if ($('.js-pagination-ajax').length > 0) {
366        window.addEventListener('popstate', function(e) {
367            loadContent(document.location.href);
368        }, false);
369    }
370
371    $('.dropdown .dropdown-menu.keepopen').on('click touchstart', function(e) {
372        e.stopPropagation();
373    },{passive: true});
374
375    if (typeof $.fn.jtl_search === 'undefined') {
376        var productSearch = new Bloodhound({
377            datumTokenizer: Bloodhound.tokenizers.obj.whitespace('keyword'),
378            queryTokenizer: Bloodhound.tokenizers.whitespace,
379            remote:         {
380                url:      $.evo.io().options.ioUrl + '?io={"name":"suggestions", "params":["%QUERY"]}',
381                wildcard: '%QUERY'
382            }
383        });
384
385        let $searchInput = $('input[name="qs"]');
386        $searchInput.typeahead(
387            {
388                highlight: true
389            },
390            {
391                name:      'product-search',
392                display:   'keyword',
393                source:    productSearch,
394                templates: {
395                    suggestion: function (e) {
396                        return e.suggestion;
397                    }
398                }
399            }
400        );
401        $searchInput.on('keydown keyup blur', function () {
402            if ($(this).val().length === 0) {
403                $(this).closest('form').find('.form-clear').addClass('d-none');
404            } else {
405                $(this).closest('form').find('.form-clear').removeClass('d-none');
406            }
407        });
408        $('.search-wrapper .form-clear').on('click', function() {
409            $searchInput.typeahead('val', '');
410            $(this).addClass('d-none');
411        });
412    }
413
414    var citySuggestion = new Bloodhound({
415        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('keyword'),
416        queryTokenizer: Bloodhound.tokenizers.whitespace,
417        remote:         {
418            url:      $.evo.io().options.ioUrl + '?io={"name":"getCitiesByZip", "params":["%QUERY", "' + $(this).closest('fieldset').find('.country-input').val() + '", "' + $(this).closest('fieldset').find('.postcode_input').val() + '"]}',
419            wildcard: '%QUERY'
420        },
421        dataType: "json"
422    });
423    $('.city_input').on('focusin', function () {
424        citySuggestion.remote.url = $.evo.io().options.ioUrl + '?io={"name":"getCitiesByZip", "params":["%QUERY", "' + $(this).closest('fieldset').find('.country-input').val() + '", "' + $(this).closest('fieldset').find('.postcode_input').val() + '"]}';
425    });
426    $('.postcode_input').on('change', function () {
427        citySuggestion.remote.url = $.evo.io().options.ioUrl + '?io={"name":"getCitiesByZip", "params":["%QUERY", "' + $(this).closest('fieldset').find('.country-input').val() + '", "' + $(this).val() + '"]}';
428    });
429    $('.country_input').on('change', function () {
430        citySuggestion.remote.url = $.evo.io().options.ioUrl + '?io={"name":"getCitiesByZip", "params":["%QUERY", "' + $(this).val() + '", "' + $(this).closest('fieldset').find('.postcode_input').val() + '"]}';
431    });
432
433    $('.city_input').typeahead(
434        {
435            hint: true,
436            minLength: 0
437        },
438        {
439            limit:  50,
440            name:   'cities',
441            source: citySuggestion
442        }
443    );
444
445    $('.btn-offcanvas').on('click', function() {
446        $('body').trigger('click');
447    });
448
449    if ("ontouchstart" in document.documentElement) {
450        $('.variations .swatches .variation').on('mouseover', function() {
451            $(this).trigger('click');
452        });
453    }
454
455    /*
456     * show subcategory on caret click
457     */
458    $('section.box-categories .nav-panel li a').on('click', function(e) {
459        if ($(e.target).hasClass("nav-toggle")) {
460            $(e.delegateTarget)
461                .parent('li')
462                .find('> ul.nav').toggle();
463            return false;
464        }
465    });
466
467    /*
468     * show linkgroup on caret click
469     */
470    $('section.box-linkgroup .nav-panel li a').on('click', function(e) {
471        if ($(e.target).hasClass("nav-toggle")) {
472            $(e.delegateTarget)
473                .parent('li')
474                .find('> ul.nav').toggle();
475            return false;
476        }
477    });
478
479    /*
480     * Banner
481     */
482    var bannerLink = $('.banner > a:not(.empty-popover)');
483    bannerLink.popover({
484        html:      true,
485        placement: 'bottom',
486        trigger:   'hover',
487        container: 'body',
488        sanitize: false,
489        template:  	'<div class="popover popover-min-width" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>',
490        content:   function () {
491            return $(this).children('.area-desc').html()
492        }
493    });
494
495    bannerLink.on('mouseenter', function () {
496        $(this).animate({
497            borderWidth: 2,
498            opacity:     0.5
499        }, 300);
500    });
501
502    bannerLink.on('mouseleave', function () {
503        $(this).animate({
504            borderWidth: 0,
505            opacity:     1
506        }, 300);
507    });
508
509    $('.banner').on('mouseenter', function () {
510        $(this).children('a').animate({
511            borderWidth: 8,
512            opacity:     0
513        }, 900, function () {
514            $(this).css({opacity: 1, borderWidth: 0});
515        });
516    });
517
518    $('.banner > a[href=""]').on('click', function () {
519        return false;
520    });
521
522    /*
523     * alert actions
524     */
525    $('.alert .close').on('click', function (){
526        $(this).parent().fadeOut(1000);
527    });
528
529    $('.alert').each(function(){
530        if ($(this).data('fade-out') > 0) {
531            $(this).fadeOut($(this).data('fade-out'));
532        }
533    });
534
535    /*
536     * margin to last filter-box
537     */
538    $('aside .box[class*=box-filter-]').last().addClass('mb-5');
539
540    /*
541     * set bootstrap viewport
542     */
543    (function($, document, window, viewport){
544        var $body = $('body');
545
546        $(window).on('resize',
547            viewport.changed(function() {
548                $body.attr('data-viewport', viewport.current());
549            })
550        );
551        $body.attr('data-viewport', viewport.current());
552        $body.attr('data-touchcapable', isTouchCapable() ? 'true' : 'false');
553    })(jQuery, document, window, ResponsiveBootstrapToolkit);
554
555
556    $('.onchangeSubmit').on('change', function(){
557        this.form.submit();
558    });
559
560    $('#mobile-search-dropdown').on('click', function() {
561        setTimeout(function(){
562            $('#search-header-desktop').focus();
563        },100);
564    });
565
566    categoryMenu();
567    regionsToState();
568    compatibility();
569    addValidationListener();
570    initWow();
571    setClickableRow();
572
573    document.addEventListener('lazybeforesizes', function(e){
574        //use width of parent node instead of the image width itself
575        var parent = e.target.parentNode;
576
577        if(parent.nodeName == 'PICTURE'){
578            parent = parent.parentNode;
579        }
580        e.detail.width = parent.offsetWidth || e.detail.width;
581    });
582
583    // init auto expand for textareas
584    $('textarea.auto-expand').on('input click', function (event) {
585        autoExpand(event.target);
586    });
587
588    $('input[maxlength][data-chars-left-msg]').on('input', function (event) {
589        let maxLength = $(this).attr('maxlength'),
590            limit     = .1 * maxLength,
591            remaining  = maxLength - $(this).val().length;
592
593        $(this).closest('.form-group').find('.char-left').remove();
594
595        if (remaining <= limit) {
596            $(this).closest('.form-group').append(
597                '<div class="text-warning char-left"><b>' + remaining + '</b> ' + $(this).data('chars-left-msg') + '</div>'
598            );
599        }
600    });
601});
602
603function setClickableRow()
604{
605    $('.clickable-row').off().on('click', function() {
606        window.location = $(this).data('href');
607    });
608}
609
610function isMobileByBodyClass() {
611    return $('body').hasClass('is-mobile');
612}
613
614function autoExpand(field) {
615    field.style.height = 'inherit';
616
617    let computed = window.getComputedStyle(field),
618        height = parseInt(computed.getPropertyValue('border-top-width'), 10)
619            + parseInt(computed.getPropertyValue('padding-top'), 10)
620            + field.scrollHeight
621            + parseInt(computed.getPropertyValue('padding-bottom'), 10)
622            + parseInt(computed.getPropertyValue('border-bottom-width'), 10);
623
624    field.style.height = height + 'px';
625}

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.