PageSourceSearch

https://www.technolyt.com/mix/js/shoppingcart.js?id=741269f2130257ec9d5b1685908d1009

js technolyt.com collected 2026-10-10 00:17:44 UTC 61,361 bytes, 1,474 lines download raw bytes

1$(document).ready(function () {
2    UpdateDiscountRuleToggleBtn();
3
4    if (!$('#checkout-form').length && authType !== 'salesagent') {
5        if (!/^\/(?:[a-z]{2}\/)?shoppingcart$/.test(window.location.pathname) && ((!/^\/(?:[a-z]{2}\/)?catalog\/item/.test(window.location.pathname)) || $('.ordermatrix-skeleton').length == 0)) {
6            update_shoppingcart();
7        }
8    }
9
10    $('#matrix-form').on('submit', function (e) {
11        e.preventDefault();
12    });
13
14    // [BBFW-3102] Update discount rules when amount changes
15    $(".input_variant_qty").on("blur", function () {
16        var $this = $(this);
17        var model = $this.data("model");
18        var color = $this.data("color");
19
20        $("#" + model + color).load(" #" + model + color + " > *");
21    });
22
23    $('#set_all_discounts_value').change(function () {
24        val = $(this).val();
25        val = val.trim().replace(',', '.').replace(/[^0-9]\.]/gi, '');
26        if (val == '') {
27            val = 0;
28        }
29        $(this).val(parseFloat(val).toFixed(2));
30    });
31
32    $(document).on('change', 'select[name="discount_type"]', function (e) {
33        window.location = $(this).val();
34    });
35
36    $(document).on('click', '#set_all_discounts_button', function (e) {
37        let discountProductGroup = parseInt($("select[name='set_all_discounts_product_group']").val()),
38            discountInputs = discountProductGroup !== 0  ? $('.input_discount[data-product-group-id="' + discountProductGroup + '"]') : $('.input_discount'),
39            discountAmount = $('#set_all_discounts_value').val();
40
41        discountAmount = discountAmount.trim().replace(',', '.').replace(/[^0-9]\.]/gi, '');
42        if (discountAmount === '') {
43            discountAmount = 0;
44        }
45
46        discountInputs.each(function (index) {
47            $('#set_all_discounts_value').val(parseFloat(discountAmount).toFixed(2));
48            $(this).val(discountAmount);
49            $(this).trigger('change');
50        });
51    });
52
53    $('#shoppingcart_checkout #order_comments_1').change(function () {
54        saveCheckoutVars('order_comments_1', $(this).val());
55    });
56
57    $('#shoppingcart_checkout #order_comments_2').change(function () {
58        saveCheckoutVars('order_comments_2', $(this).val());
59    });
60
61    $('#shoppingcart_checkout #your_reference').change(function () {
62        saveCheckoutVars('your_reference', $(this).val());
63    });
64
65    $('#shoppingcart_checkout #deliverywindows').change(function () {
66        saveCheckoutVars('delivery_window_code', $(this).val());
67    });
68
69    $('#shoppingcart_checkout .delivery_window_code_style').change(function () {
70        saveCheckoutVars($(this).attr('data-id'), $(this).val());
71    });
72
73    $('#shoppingcart_checkout #preferred_delivery_date').change(function () {
74        saveCheckoutVars('preferred_delivery_date', $(this).val());
75    });
76
77    $('#shoppingcart_checkout #shippingmethod').change(function () {
78        $('.checkout_submit').attr('disabled', 'disabled');
79
80        $.post('/ajax/shoppingcart/save_checkout_vars', {key: 'shippingmethod_id', value: $(this).val()}, function () {
81            document.location.reload();
82        });
83    });
84
85    $('#shoppingcart_checkout #preferred_delivery_week').change(function () {
86        saveCheckoutVars('preferred_delivery_week', $(this).val());
87    });
88
89    $('#shoppingcart_checkout #partial_delivery_allowed').change(function () {
90        saveCheckoutVars('partial_delivery_allowed', $(this).val());
91    });
92
93    $('#shoppingcart_checkout #add_discount_code').click(function () {
94        var discountcode = $('#discount_code').val();
95
96        $.post('/ajax/shoppingcart/set_discount_code', {discount_code: discountcode}, function () {
97            document.location.reload();
98        });
99    });
100
101    $('#shoppingcart_checkout #remove_discount_code').click(function () {
102
103        $.post('/ajax/shoppingcart/remove_discount_code', function () {
104            document.location.reload();
105        });
106    });
107
108    $('#shoppingcart_checkout #print_options').click(function () {
109        document.location.href = '/shoppingcart/prints';
110    });
111
112    var signature = $('input[name="output"]');
113
114    $("#checkout-form").submit(function () {
115
116        if ($('#deliverywindows').length > 0) {
117            if ($('#deliverywindows').val() == 0) {
118                alert(lang['SELECT_SHIPPING_WINDOW_ERROR']);
119                return false;
120            }
121        }
122
123        delivery_window_error = false;
124        $('.delivery_window_code_style').each(function () {
125            if ($(this).val() == 0) {
126                delivery_window_error = true;
127            }
128        });
129        if (delivery_window_error) {
130            alert(lang['SELECT_SHIPPING_WINDOW_ERROR']);
131            return false;
132        }
133
134        if ($('#preferred_delivery_week').val() === 0 || $('#preferred_delivery_week').val() === '') {
135            alert(lang['PREFERED_DELIVERYWEEK_ERROR']);
136            return false;
137        }
138
139        if ($('#shippingmethod').val() == 0) {
140            alert(lang['SHIPPINGMETHOD_ERROR']);
141            return false;
142        }
143
144        if ($('#terms_agree').length > 0) {
145            if (!$('#terms_agree').is(':checked')) {
146                alert(lang['TERMS_AGREEMENT_ERROR']);
147                return false;
148            }
149        }
150
151        if (signature.prop('required') && signature.length && !signature.val()) {
152            alert(lang['SIGNATURE_ERROR']);
153            return false;
154        }
155
156        // make sure we cannot post again
157        $('.checkout_submit').attr('disabled', 'disabled');
158
159        return true;
160    });
161
162    $('#shoppingcart_checkout .delivery_window_set_all').click(function () {
163        if (confirm(lang['DELIVERY_WINDOW_SET_ALL'])) {
164            var new_value = $(this).siblings('label').children('select').val(); // works for new template
165            if (new_value === undefined) {
166                new_value = $(this).siblings('select').val(); // works for old template
167            }
168
169            // post all
170            var updated = {};
171            $('.delivery_window_code_style').each(function () {
172                var current_value = $(this).val();
173                if (current_value != new_value) {
174                    $(this).val(new_value);
175                    if ($(this).val() == new_value) {
176                        updated[$(this).attr('data-id')] = $(this).val();
177                    } else {
178                        // option not available so set old value
179                        $(this).val(current_value);
180                    }
181                }
182            });
183
184            $.post('/ajax/shoppingcart/save_checkout_vars', {key: 'multiple', value: JSON.stringify(updated)});
185        }
186    });
187
188    $(document).on('click', '.info-button', function (e) {
189        e.preventDefault();
190        var $button = $(this);
191        var $infoModal = $button.next();
192        var variantModalUrl = $button.data('variant-url');
193        var loadingText = $button.data('loading-text') || lang['LOADING'];
194        var errorText = $button.data('error-text') || lang['SOMETHING_WENT_WRONG'];
195
196        if (variantModalUrl && !$infoModal.data('variantLoaded') && !$infoModal.data('variantLoading')) {
197            var $modalBody = $infoModal.find('.modal-body').first();
198            $infoModal.data('variantLoading', true);
199            $modalBody.empty().append(
200                $('<p/>', {
201                    class: 'p-2'
202                }).text(loadingText + '...')
203            );
204
205            $.get(variantModalUrl)
206                .done(function (responseHtml) {
207                    var $response = $('<div/>').html(responseHtml);
208                    var $variantBody = $response.find('.modal-body').first();
209
210                    if ($variantBody.length) {
211                        $modalBody.html($variantBody.html());
212                        $infoModal.data('variantLoaded', true);
213                    } else {
214                        $modalBody.empty().append(
215                            $('<p/>', {
216                                class: 'p-2'
217                            }).text(errorText)
218                        );
219                    }
220                })
221                .fail(function () {
222                    $modalBody.empty().append(
223                        $('<p/>', {
224                            class: 'p-2'
225                        }).text(errorText)
226                    );
227                })
228                .always(function () {
229                    $infoModal.data('variantLoading', false);
230                });
231        }
232
233        if ($infoModal.hasClass('show')) {
234            $infoModal.modal('hide');
235        } else {
236            $infoModal.modal('show');
237        }
238    });
239
240    $(document).on('hide.bs.modal', '.size-modal', function (event) {
241        if (event.target !== this) {
242            return;
243        }
244
245        $(this).find('.variant-modal.show').modal('hide');
246    });
247
248    $(document).on('hide.bs.modal', '.size-modal .variant-modal', function (event) {
249        if (event.target !== this) {
250            return;
251        }
252
253        var activeElement = document.activeElement;
254        if (activeElement && this.contains(activeElement) && typeof activeElement.blur === 'function') {
255            activeElement.blur();
256        }
257    });
258
259    $(document).on('hidden.bs.modal', '.size-modal, .size-modal .variant-modal', function () {
260        normalizeModalBackdropState();
261    });
262
263    var $mobileMenuButton = $('.mobile-menu-button');
264    var $navModal = $('.nav-modal');
265    $mobileMenuButton.on('click', function (e) {
266        e.preventDefault();
267        if ($navModal.hasClass('show')) {
268            $navModal.modal('hide');
269            $mobileMenuButton.html('<i class="fas fa-bars"></i>')
270        } else {
271            $navModal.modal('show');
272            $mobileMenuButton.html('<i class="fas fa-times"></i>')
273            $('.modal-backdrop').css("top", "51px");
274        }
275    });
276
277    var $window = $(window)
278    bindStyleRowMobileEvent($window);
279
280    document.addEventListener('order-matrix-loaded', function () {
281        bindStyleRowMobileEvent($window);
282        hideEmptyDiscountBoxes();
283    });
284
285    $(document).on('click', '.btn.trigger-collapsible', function () {
286        saveCollapsibleState();
287    });
288
289    handleCollapsibleStates();
290
291    var $priceBlockInput = $('.price-block input[type=number]');
292    $priceBlockInput.on('focusin', function () {
293        $(this).on('wheel', function (e) {
294            e.preventDefault();
295        });
296    });
297    $priceBlockInput.on('focusout', function () {
298        $(this).unbind('wheel');
299    });
300
301    var recommendation = $('.carousel-container.recommendation')
302    recommendation.find('.carousel').sly({
303        itemNav: 'basic',
304        horizontal: true,
305        activateOn: 'mouseenter',
306        mouseDragging: 1,
307        touchDragging: 1,
308        releaseSwing: 1,
309        startAt: 0,
310        speed: 300,
311        elasticBounds: 1,
312        easing: 'easeOutExpo',
313        prevPage: recommendation.find('.prev'),
314        nextPage: recommendation.find('.next')
315    });
316
317    hideEmptyDiscountBoxes();
318});
319
320function saveCheckoutVars(key, value) {
321    $.post('/ajax/shoppingcart/save_checkout_vars', {key: key, value: value});
322}
323
324function normalizeModalBackdropState()
325{
326    var visibleModalsCount = $('.modal.show').length;
327    var $backdrops = $('.modal-backdrop');
328
329    if (visibleModalsCount === 0) {
330        $backdrops.remove();
331        $('body').removeClass('modal-open');
332        return;
333    }
334
335    $('body').addClass('modal-open');
336
337    if ($backdrops.length > 1) {
338        $backdrops.slice(0, -1).remove();
339    }
340}
341
342/**
343 * @param $window
344 */
345function bindStyleRowMobileEvent($window)
346{
347    $('.style_row').each(function () {
348        var $this = $(this);
349        $this.on('click', '.item-colors', function () {
350            if ($window.width() <= 1024) {
351                $('#size-modal-' + $this.data('model') + '-' + $this.data('color')).modal('show');
352            }
353        })
354    });
355}
356
357/**
358 * Save collapsible states
359 */
360function saveCollapsibleState()
361{
362    setTimeout(function () {
363        var order_matrix = $('.ordermatrix'),
364            collapsible_states = {};
365
366        order_matrix.each(function () {
367            var element = $(this);
368
369            collapsible_states[element.attr('id')] = (element.hasClass('show') ? true : false);
370        });
371
372        $.cookie('collapsible_states', JSON.stringify(collapsible_states));
373    }, 500);
374}
375
376/**
377 * Handle collapsible states, show elements if they are stored with "true" in the cookie
378 */
379function handleCollapsibleStates()
380{
381    var collapsible_states_cookie = $.cookie('collapsible_states');
382    if (collapsible_states_cookie) {
383        var collapsible_states = JSON.parse(collapsible_states_cookie);
384        $.each(collapsible_states, function (key, value) {
385            if (value === true) {
386                $('#' + key).addClass('show');
387            }
388        });
389    }
390}
391
392if (!/^\/(?:[a-z]{2}\/)?shoppingcart$/.test(window.location.pathname)) {
393    function update_shoppingcart(inputobject)
394    {
395        var update = {};
396        var ordermatrix = null;
397        var qty_changed_by_order_steps = false;
398
399        // Get all data
400        if (inputobject) {
401            let value = parseInt($(inputobject).val());
402            let maxOrderQty = parseInt($(inputobject).attr('data-max-order-qty'));
403
404            // Check for max order qty
405            if (value > maxOrderQty) {
406                value = $(inputobject).attr('data-max-order-qty');
407                $(inputobject).val(value);
408                alert(lang['MAXIMUM_ORDER_QUANTITY_REACHED_MESSAGE']);
409            }
410
411            // Get updates
412            update['model'] = $(inputobject).attr('data-model'); // !! Don't use .data() to retrieve this info because it wil convert '01' into '1' !!
413            update['color'] = $(inputobject).attr('data-color'); // !! Don't use .data() to retrieve this info because it wil convert '01' into '1' !!
414            update['size'] = $(inputobject).attr('data-size'); // !! Don't use .data() to retrieve this info because it wil convert '01' into '1' !!
415            update['order_steps'] = $(inputobject).attr('data-order-steps');
416            update['value'] = $(inputobject).val();
417
418            if (update['value'] != 0 && update['order_steps'] != 0 && (update['order_steps'] !== update['value'])) {
419                if ((update['value'] % update['order_steps']) / 100 != 0) {
420                    qty_changed_by_order_steps = true;
421                }
422                update['value'] = Math.ceil(update['value'] / update['order_steps']) * update['order_steps'];
423            }
424
425            update['value'] = update['value'] * $(inputobject).attr('data-multiple_qty');
426
427            if ($(inputobject).attr('data-discounttype')) {
428                update['discounttype'] = $(inputobject).attr('data-discounttype');
429                update['unitprice'] = $(inputobject).attr('data-unitprice');
430                update['unitlistprice'] = $(inputobject).attr('data-unitlistprice');
431                update['quantity'] = $(inputobject).attr('data-quantity');
432                update['hasbeenrounded'] = $(inputobject).attr('data-hasbeenrounded');
433                update['given_discount'] = $(inputobject).val();
434            }
435        }
436
437        let parent_path = window.location.pathname;
438        parent_path = parent_path.substring(parent_path.lastIndexOf('/') +1);
439
440        // Do ajax call
441        $.ajax({
442            headers: {
443                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
444            },
445            url: '/ajax/shoppingcart/update',
446            type: 'post',
447            cache: false,
448            data: {
449                'update': update,
450                'use_live_prices': (parent_path === 'shoppingcart'),
451            },
452            dataType: 'json',
453            //async: false, @ToDo: find a way to disable async calls. This one is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
454            success: function (data) {
455                if (data.models) {
456                    if ( inputobject ) {
457                        var f = $('input[data-model="' + update['model']  + '"][data-color="' + update['color'] + '"][data-size="' + update['size'] + '"]');
458                        var model_exists = ( typeof(data.models[update['model']]) === 'object' );
459                        var style_exists = ( model_exists && typeof(data.models[update['model']].colors[update['color']]) === 'object' );
460                        var variant_exists = ( style_exists && typeof(data.models[update['model']].colors[update['color']].sizes[update['size']]) === 'object' );
461                        var qty = 0;
462                        var model_no_hash = inputobject.data('model');
463                        var cartAddedNotificationElement = $(document).find('#ordermatrix-' + model_no_hash + '-notification');
464
465                        $('.cart-added-notification').addClass('hidden');
466
467                        if ( variant_exists ) {
468                            var backorder_quantity = data.models[update['model']].backorder_quantity;
469                            var quantity_in_update = data.models[update['model']].colors[update['color']].sizes[update['size']].quantity;
470                            var multiple_qty = data.models[update['model']].colors[update['color']].sizes[update['size']].multiple_qty;
471
472                            if (multiple_qty === null) {
473                                multiple_qty = data.models[update['model']].multiple_qty;
474                            }
475
476                            if (multiple_qty > 0) {
477                                qty = Math.round(quantity_in_update / multiple_qty);
478                            } else {
479                                qty = Math.round(quantity_in_update);
480                            }
481                        }
482                        f.val((qty == 0) ? '' : qty);
483
484                        if ( style_exists ) {
485                            $('.style-total-quantity[data-model="' + update['model'] + '"][data-color="' + update['color'] + '"]').html(data.models[update['model']].colors[update['color']].quantity / multiple_qty);
486                            $('.style-total-qty-times-multiple[data-model="' + update['model'] + '"][data-color="' + update['color'] + '"]').html(data.models[update['model']].colors[update['color']].quantity);
487                            $('.style-total-unit-price[data-model="' + update['model'] + '"][data-color="' + update['color'] + '"]').html(data.models[update['model']].colors[update['color']].formatted_total_unit_price);
488
489                            if (data.models[update['model']].colors[update['color']].open_orderlines_info) {
490                                $('.open-orderlines-message[data-model="' + update['model'] + '"][data-color="' + update['color'] + '"] span').text(data.models[update['model']].colors[update['color']].open_orderlines_info);
491                                $('.open-orderlines-message[data-model="' + update['model'] + '"][data-color="' + update['color'] + '"]').show();
492                            }
493
494                            if (qty > 0) {
495                                cartAddedNotificationElement.removeClass('hidden');
496                            }
497
498                            var update_amount = 0;
499                            if (data.models[update['model']].colors[update['color']].given_discount_amount != 0) {
500                                update_amount = (data.models[update['model']].colors[update['color']].formatted_given_discount_amount).replace(' ', ' -');
501                            } else {
502                                update_amount = data.formatted_zero_price;
503                            }
504                            $('.style_given_discount[data-model="' + update['model'] + '"][data-color="' + update['color'] + '"]').html(update_amount);
505                        } else {
506                            $('.style-total-quantity[data-model="' + update['model'] + '"][data-color="' + update['color'] + '"]').html(0);
507                            $('.style-total-qty-times-multiple[data-model="' + update['model'] + '"][data-color="' + update['color'] + '"]').html(0);
508                            $('.style-total-unit-price[data-model="' + update['model'] + '"][data-color="' + update['color'] + '"]').html(data.formatted_zero_price);
509                        }
510
511                        if (model_exists) {
512                            qty = data.models[update['model']].quantity;
513                            qty_incl_prepack_items = data.models[update['model']].quantity_incl_prepack_items;
514                            if (qty != qty_incl_prepack_items) {
515                                qty += ' ('+qty_incl_prepack_items+')';
516                            }
517
518                            $('.shoppingcart-quantity-' + update['model']).html(qty / multiple_qty);
519                            $('.shoppingcart-quantity-units-' + update['model']).html(qty);
520
521                            var $shoppingCartQuantityBackorders = $('#shoppingcart-quantity-backorders-' + update['model']);
522                            var $shoppingCartQuantityBackordersUnit = $('#shoppingcart-quantity-backorders-units-' + update['model']);
523
524                            $shoppingCartQuantityBackorders.html(backorder_quantity / multiple_qty);
525                            if (backorder_quantity / multiple_qty) {
526                                $shoppingCartQuantityBackorders.parent().show();
527                            } else {
528                                $shoppingCartQuantityBackorders.parent().hide();
529                            }
530
531                            // show backorder units only if it differs from quantity; if there is a multiple_qty
532                            $shoppingCartQuantityBackordersUnit.html(backorder_quantity);
533                            if (backorder_quantity && multiple_qty > 1) {
534                                $shoppingCartQuantityBackordersUnit.parent().show();
535                            } else {
536                                $shoppingCartQuantityBackordersUnit.parent().hide();
537                            }
538
539                            $('.shoppingcart-totalprice-' + update['model']).html(data.models[update['model']].formatted_total_unit_price_minus_given_discount_amount);
540                            $('.shoppingcart-strikethrough-totalprice-' + update['model']).html(data.models[update['model']].formatted_total_not_live_unit_price);
541
542                            if ($('.info-block.simple-product #ordermatrix-' + update['model'] + ' div strong').length && data.models[update['model']].formatted_min_unit_price) {
543                                $('.info-block.simple-product #ordermatrix-' + update['model'] + ' div strong').html(data.models[update['model']].formatted_min_unit_price);
544                            }
545
546                            if ($('#ordermatrix-' + update['model'] + ' div span.price span').length && data.models[update['model']].formatted_min_unit_price) {
547                                $('#ordermatrix-' + update['model'] + ' div span.price span').html(data.models[update['model']].formatted_min_unit_price);
548                            }
549                        } else {
550                            $('#ordermatrix-' + update['model']).find('.tier-price-block').html('').hide();
551                            $('.shoppingcart-quantity-' + update['model']).html(0);
552                            $('.shoppingcart-totalprice-' + update['model']).html(data.formatted_zero_price);
553                        }
554
555                        var discount_field = $('.input_discount[data-model="' + update['model']  + '"][data-color="' + update['color'] + '"]');
556                        if (!update['discounttype']) {
557                            // quantity update, reset discount
558                            discount_field.val(discount_field.attr('data-mindiscount'));
559                        }
560
561                        if (data.models[update['model']]) {
562                            tiers = data.models[update['model']].tiers;
563
564                            // must loop, because one variantquantity change can affect all others
565                            model = update['model'];
566                            model_data = data.models[model];
567
568                            $.each(model_data.colors, function (color, color_data) {
569                                if (!$.isEmptyObject(tiers)) {
570                                    displayActiveModelColorTiers(update['model'], color, tiers);
571                                }
572
573                                $.each(color_data.sizes, function (size, size_data) {
574                                    var size_quantity = Math.round(size_data.quantity / model_data.multiple_qty),
575                                        inputElement = $('input[data-model="' + model + '"][data-color="' + color + '"][data-size="' + size + '"]');
576
577                                    if (!$.isEmptyObject(tiers)) {
578                                        if (size_quantity == 0) {
579                                            inputElement.empty();
580                                        } else {
581                                            inputElement.val(size_quantity);
582                                        }
583
584                                        updateVariantPriceInfo(model, color, size, size_data);
585                                    }
586
587                                    displayPriceTierInfo(model, color, size, size_quantity, size_data);
588                                    updateVariantPrice(model, color, size, size_data.formatted_unit_price);
589                                });
590                            });
591                        }
592
593                        displayBackorderInfo(f);
594
595                        // Trigger qty changed by order steps popup
596                        if (qty_changed_by_order_steps && !$.cookie('dont_show_qty_changed_by_order_steps_again')) {
597                            showQtyChangedByOrderStepsModal();
598                        }
599
600                        if (dynamicPricesInCatalog == 1 && $('.price-block#ordermatrix-' +update['model'] + ' .price.current span').length && data.models[update['model']].formatted_min_unit_price) {
601                            $('.price-block#ordermatrix-' +update['model'] + ' .price.current span').html(data.models[update['model']].formatted_min_unit_price);
602                        }
603
604                        document.dispatchEvent(new CustomEvent('GTMAmountChanged', {
605                            detail: {
606                                inputObject: document.getElementById(inputobject.attr('id')) // inputobject is a jQuery object, we need a DOM element
607                            }
608                        }));
609
610                        UpdateDiscountRuleToggleBtn();
611                    } else {
612                        $.each(data.models, function (model, model_data) {
613                            var tiers = data.models[model].tiers;
614
615                            $.each(model_data.colors, function (color, color_data) {
616                                $.each(color_data.sizes, function (size, size_data) {
617                                    var size_quantity = Math.round(size_data.quantity / model_data.multiple_qty),
618                                        inputElement = $('input[data-model="' + model + '"][data-color="' + color + '"][data-size="' + size + '"]');
619
620                                    if (size_quantity == 0) {
621                                        inputElement.empty();
622                                    } else {
623                                        inputElement.val(size_quantity);
624                                    }
625
626                                    inputElement.attr('data-current-qty', size_quantity);
627
628                                    $('.style-total-quantity[data-model="' + model + '"][data-color="' + color + '"]').html(data.models[model].colors[color].quantity / model_data.multiple_qty);
629                                    $('.style-total-qty-times-multiple[data-model="' + model + '"][data-color="' + color + '"]').html(data.models[model].colors[color].quantity);
630                                    $('.style-total-unit-price[data-model="' + model + '"][data-color="' + color + '"]').html(data.models[model].colors[color].formatted_total_unit_price);
631
632                                    displayActiveModelColorTiers(model, color, tiers);
633                                    displayPriceTierInfo(model, color, size, size_quantity, size_data);
634                                    updateVariantPrice(model, color, size, size_data.formatted_unit_price);
635                                });
636                            });
637
638                            qty = model_data.quantity;
639                            multiple_qty = model_data.multiple_qty;
640                            qty_incl_prepack_items = model_data.quantity_incl_prepack_items;
641                            backorder_quantity = model_data.backorder_quantity;
642
643                            if (qty != qty_incl_prepack_items) {
644                                qty += ' (' + qty_incl_prepack_items + ')';
645                            }
646                            $('.shoppingcart-quantity-' + model).html(qty / multiple_qty);
647                            $('.shoppingcart-quantity-units-' + model).html(qty);
648
649                            var $shoppingCartQuantityBackorders = $('#shoppingcart-quantity-backorders-' + model);
650                            var $shoppingCartQuantityBackordersUnit = $('#shoppingcart-quantity-backorders-units-' + model);
651
652                            $shoppingCartQuantityBackorders.html(backorder_quantity / multiple_qty);
653                            if (backorder_quantity / multiple_qty) {
654                                $shoppingCartQuantityBackorders.parent().show();
655                            } else {
656                                $shoppingCartQuantityBackorders.parent().hide();
657                            }
658
659                            // show backorder units only if it differs from quantity; if there is a multiple_qty
660                            $shoppingCartQuantityBackordersUnit.html(backorder_quantity);
661                            if (backorder_quantity && multiple_qty > 1) {
662                                $shoppingCartQuantityBackordersUnit.parent().show();
663                            } else {
664                                $shoppingCartQuantityBackordersUnit.parent().hide();
665                            }
666                            $('.shoppingcart-totalprice-' + model).html(model_data.formatted_total_unit_price_minus_given_discount_amount);
667                            $('.shoppingcart-strikethrough-totalprice-' + model).html(model_data.formatted_total_not_live_unit_price);
668
669                            if ($('.info-block.simple-product #ordermatrix-' +model + ' div strong').length && model_data.formatted_min_unit_price) {
670                                $('.info-block.simple-product #ordermatrix-' + model + ' div strong').html(model_data.formatted_min_unit_price);
671                            }
672
673                            if (dynamicPricesInCatalog == 1 && $('.price-block#ordermatrix-' +model + ' .price.current span').length && model_data.formatted_min_unit_price) {
674                                $('.price-block#ordermatrix-' +model + ' .price.current span').html(model_data.formatted_min_unit_price);
675                            }
676                        });
677                    }
678                } else {
679                    $('.input_variant_qty').val('0');
680                    $('.input_variant_qty').next('.tier-price-block').html('').hide();
681
682                    $('.style-total-quantity').html('0');
683                    $('.style-total-unit-price').html(data.formatted_total_unit_price);
684
685                    $('.model-total-quantity').html('0');
686                    $('.model-total-unit-price').html(data.formatted_total_unit_price);
687
688                    document.querySelectorAll('*[data-role=AddedToCartNotification]').forEach(el => {
689                        el.classList.add('hidden');
690                    });
691
692                    if (update['model'] !== undefined) {
693                        $('.shoppingcart-quantity-units-' + update['model']).html(0);
694                        $('.shoppingcart-quantity-backorders-' + update['model']).html(0);
695                        $('.shoppingcart-totalprice-' + update['model']).html(data.formatted_total_unit_price);
696                    }
697
698                    var f = $('input[data-model="' + update['model'] + '"][data-color="' + update['color'] + '"][data-size="' + update['size'] + '"]');
699                    displayBackorderInfo(f);
700                    updateVariantPrice(update['model'], update['color'], update['size'], 'originalFormattedUnitPrice');
701
702                    if (f.length) {
703                        let id = f.length > 1 ? f[1].id : f.id;
704
705                        document.dispatchEvent(new CustomEvent('GTMAmountChanged', {
706                            detail: {
707                                inputObject: document.getElementById(id) // inputobject is a jQuery object, we need a DOM element
708                            }
709                        }));
710                    }
711                }
712
713                if (data.quantity) {
714                    $('.shoppingcart-stats-button').show();
715                } else {
716                    $('.shoppingcart-stats-button').hide();
717                }
718
719                var $bagDropdown = $('#bag-dropdown');
720                $('#global-shoppingcart .cart-total-qty').html(data.quantity);
721                if (data.quantity) {
722                    $bagDropdown.addClass('filled');
723                    $bagDropdown.find('.num-in-bag').html('(' + parseInt(data.quantity) + ')');
724                } else {
725                    $bagDropdown.find('.num-in-bag').html('(0)');
726                    $bagDropdown.removeClass('filled');
727                }
728                $('#global-shoppingcart .cart-total-price').html(data.formatted_total_unit_price_minus_given_discount_amount);
729
730                qty = data.quantity;
731                qty_incl_prepack_items = data.quantity_incl_prepack_items;
732                if (qty != qty_incl_prepack_items) {
733                    qty += ' (' + qty_incl_prepack_items + ')';
734                }
735                $('#shoppingcart-overview-quantity').html(qty);
736                $('#shoppingcart-overview-total-unit-price').html(data.formatted_total_unit_price_minus_discounts);
737                if (data.given_discount_amount > 0) {
738                    $('.given_discounts_container').show();
739                } else {
740                    $('.given_discounts_container').hide();
741                }
742                if (data.shoppingcart_tier_amount > 0) {
743                    $('.shoppingcart_tier_discount_container').show();
744                } else {
745                    $('.shoppingcart_tier_discount_container').hide();
746                }
747                $('#shoppingcart-overview-subtotal-unit-price').html(data.formatted_total_unit_price);
748                $('#shoppingcart-overview-total_unit_price_minus_given_discount_amount').html(data.formatted_total_unit_price_minus_given_discount_amount);
749                $('#shoppingcart-overview-discount').html(data.formatted_given_discount_amount);
750                $('#shoppingcart-tier-overview-discount').html(data.formatted_shoppingcart_tier_amount);
751
752                $('#global-shoppingcart-tier').html(data.shoppingcart_tier_line);
753
754                // if the price has changed compared to the initial price on load, we need a reload of the live prices to continue
755                let onloadQuantity  = $('.shop-overview--basket').attr('data-initial-quantity-on-load');
756                let currentQuantity = data.quantity;
757                if (onloadQuantity && onloadQuantity != currentQuantity) {
758                    $('#submit-shoppingcart span').html(lang['REFRESH_LIVE_PRICES']);
759                    $('#submit-shoppingcart').attr('href', window.location.href);
760                    $('#submit-shoppingcart').attr('data-url', window.location.href);
761                }
762
763                if (data.credit_is_reached) {
764                    $('.credit-is-not-reached').hide();
765                    $('#submit-shoppingcart').removeAttr('disabled');
766                } else {
767                    $('.credit-is-not-reached').show();
768                    $('#submit-shoppingcart').attr('disabled', 'disabled');
769                }
770
771                // update backorder info
772                if (typeof inputobject === 'undefined' ) {
773                    displayBackorderInfo();
774                } else {
775                    show_stock_message();
776                }
777
778                handleMinimalOrderAmountMessage(data);
779            },
780        });
781    }
782}
783
784/**
785 * Determines when to add backorder-class for showing stock-message and backorder-button
786 * @param f
787 */
788function displayBackorderInfo(f)
789{
790    if ($('.input_variant_qty').length > 0) {
791        show_stock_message();
792        add_backorder_class(f);
793        show_backorder_button();
794    }
795}
796
797/**
798 * Determines if truck elements need to have a backorder class
799 */
800function add_backorder_class(f)
801{
802    if (typeof f !== 'undefined') {
803        updateMatrixInputClass(f);
804    } else {
805        $('.input_variant_qty').each(function () {
806            updateMatrixInputClass($(this));
807        });
808    }
809}
810
811function updateMatrixInputClass(element)
812{
813    var $this = element;
814    var order_amount = get_order_amount($this); // Get the amount that's filled in by user or 0
815    var in_stock = parseInt($this.attr('data-stock') / $this.attr('data-multiple_qty'));
816
817    if (isNaN(in_stock)) {
818        in_stock = 0;
819    }
820
821    var matrix_product = $this.hasClass('matrix_product');
822
823    let truck;
824    if (matrix_product) {
825        if ((order_amount > 0 && order_amount > in_stock) || in_stock <= 0) {
826            $this.removeClass('ordered');
827            $this.addClass('backordered');
828            $this.parent().addClass('backordered');
829
830            if (truck !== undefined) {
831                if (truck.length > 0) {
832                    truck.parent('.stock-block').removeClass('green');
833                    truck.parent('.stock-block').addClass('red');
834                }
835            }
836        } else {
837            $this.removeClass('backordered');
838            $this.parent().removeClass('backordered');
839
840            if (order_amount > 0) {
841                $this.addClass('ordered');
842                $this.parent().addClass('ordered');
843            } else {
844                $this.removeClass('ordered');
845                $this.parent().removeClass('ordered');
846            }
847
848            if (truck !== undefined) {
849                truck.parent('.stock-block').removeClass('red');
850                truck.parent('.stock-block').addClass('green');
851            }
852        }
853    }
854}
855
856
857/**
858 * Get the amount that's filled in by user or 0
859 * @param element
860 * @returns {number}
861 */
862function get_order_amount(element)
863{
864    let order_amount = parseInt($(element).val());
865    if (isNaN(order_amount)) {
866        order_amount = 0;
867    }
868    return order_amount;
869}
870
871/**
872 * Determines when to show backorder stock message, must be shown when any fa-truck has class backorder
873 */
874function show_stock_message()
875{
876    // Loop through all backorder messages to determine if they should be shown or hidden
877    $('.backorder_message').each(function () {
878        let $message = $(this);
879        let show_backorder_message = false;
880        let model = $message.data('model');
881        let color = $message.data('color');
882        let $variantInputs = $('.input_variant_qty[data-model="' + model + '"][data-color="' + color + '"]:visible');
883
884        // Loop through all inputs belonging to the message to determine if there are backorder items in the shoppingcart
885        $variantInputs.each(function () {
886            let order_amount = get_order_amount($(this)); // Get the amount that's filled in by user or 0
887            let in_stock = parseInt($(this).attr('data-stock'), 10);
888            let noos = String($(this).attr('data-noos'));
889
890            if (order_amount > 0 && order_amount > in_stock) {
891                if ((noos === '1' && showBackorderStock !== '0') || (noos === '2' && showBackorderStockNoos !== '0')) {
892                    show_backorder_message = true;
893                }
894            }
895        });
896
897        // We now know if the message should be shown
898        $message.toggle(show_backorder_message);
899    });
900}
901
902/**
903 * Determine if backorder_overview button must be visible or not
904 */
905function show_backorder_button()
906{
907    if ($('.backorder_overview').length > 0) {
908        if ($('.fa-truck').length > 0) {
909            $('.backorder_overview').show();
910        } else {
911            $('.backorder_overview').hide();
912        }
913    }
914}
915
916/**
917 * Show next price tier
918 *
919 * @param model
920 * @param color
921 * @param size
922 * @param size_quantity
923 * @param size_data
924 */
925function displayPriceTierInfo(model, color, size, size_quantity, size_data)
926{
927    let hasPriceTiers = size_data.hasOwnProperty('price_tiers') && !$.isEmptyObject(size_data.price_tiers),
928        isSimpleProduct = $('.info-block.simple-product').length > 0,
929        price_tiers = hasPriceTiers ? size_data.price_tiers : [],
930        inputElement = isSimpleProduct
931            ? $('input[data-model="' + model + '"][data-color="' + color + '"][data-size="' + size + '"]')
932            : $('.cell-bottom input[data-model="' + model + '"][data-color="' + color + '"][data-size="' + size + '"]'),
933        tierPriceBlock = isSimpleProduct
934            ? inputElement.closest('.price-block').find('.tier-price-block')
935            : inputElement.parent().find('.tier-price-block'),
936        inputsGrid = $(inputElement.closest('.inputs-grid'));
937
938    if (hasPriceTiers && size_data.current_price_tier && price_tiers[size_data.current_price_tier]) {
939        let nextTier = price_tiers[size_data.current_price_tier];
940        let nextTierMinQuantity = nextTier.minimum_quantity;
941        tierPriceBlock.html('+ ' + (nextTierMinQuantity - size_quantity) + ' ' + nextTier.formatted_unit_price).show();
942    } else {
943        tierPriceBlock.html('').hide();
944    }
945
946    if (!isSimpleProduct) {
947        let height = $(inputElement.closest('.cell-bottom').last()).height(),
948            cellBottom = inputsGrid.find('.item_row .cell-bottom'),
949            tierPriceBlockVisible = inputsGrid.find('.tier-price-block:visible').length > 0,
950            currenPriceTierElement = inputElement.last().closest('.sizes-el').find('.current-price-tier');
951
952        // Show current price tier
953        if (size_data.current_price_tier !== undefined) {
954            currenPriceTierElement.html('T' + size_data.current_price_tier).show();
955        } else {
956            currenPriceTierElement.html('').hide();
957        }
958
959        // Adjust height of cell-bottom
960        cellBottom.each(function () {
961            $(this).height(tierPriceBlockVisible ? height - ($(this).hasClass('sold-out') ? 2 : 0) + 'px' : 'auto');
962        });
963    }
964}
965
966/**
967 * Update variant price (in order matrix)
968 *
969 * @param model
970 * @param color
971 * @param size
972 * @param formatted_unit_price
973 */
974function updateVariantPrice(model, color, size, formatted_unit_price)
975{
976    let variantPriceElement = $('.variant-price[data-model="' + model + '"][data-color="' + color + '"][data-size="' + size + '"]');
977
978    if (variantPriceElement.length) {
979        // Check if we need to show the original formatted unit price (if cart qty for this variant is 0
980        if (formatted_unit_price === 'originalFormattedUnitPrice') {
981            formatted_unit_price = variantPriceElement.attr('data-original-formatted-unit-price');
982        }
983
984        variantPriceElement.html(formatted_unit_price);
985    }
986}
987
988function displayActiveModelColorTiers(model, color, tiers)
989{
990    // first reset all variant-price-hover tier-lines
991    $('.variant_price_' + model + ' .tier_info').hide();
992    // is something active
993    var some_active_total = false;
994    // show inactive ?
995    show_inactive_discountrules = $('.discount_rule_toggle_btn i').hasClass('fa-chevron-down');
996    // then loop trough tiers
997    $.each(tiers, function (tier_id, tier_data) {
998        page_identifier = model + '_' + color + '_' + tier_id;
999        var rule_elements = $(".rule_" + page_identifier);
1000        is_active = false;
1001        if (tier_data.active_tier_sizes && tier_data.active_tier_sizes.length > 0) {
1002            rule_elements.each(function () {
1003                var $this = $(this);
1004
1005                // Remove possible old active rule
1006                $(this).removeClass('active');
1007
1008                // exists in page
1009                // must remove colourgroup_code, we dont have this in cartlines
1010                matching_sizes = [];
1011                $.each(tier_data.active_tier_sizes, function (counter, ident) {
1012                    if (ident.indexOf(color + '*') !== -1) {
1013                        matching_sizes.push(ident.replace(color + '*', ''));
1014                    }
1015                });
1016
1017                $.each(matching_sizes, function (counter, size) {
1018                    // show a line in variant-price hover
1019                    size = base64(size);
1020                    $('#variant_price_' + model + '_' + color + '_' + size + ' .variant_price_tier_line').html(tier_data.name + ' (' + tier_data.percentage + '%)');
1021                    $('#variant_price_' + model + '_' + color + '_' + size + ' .tier_info').show();
1022                })
1023
1024                default_all_sizes = $this.attr('data-default_all');
1025
1026                html = '';
1027                if (default_all_sizes === '1') {
1028                    // show all sizes
1029                    if (matching_sizes.length > 0) {
1030                        html = '<span class="discountrule_table_active">' + $this.attr('data-default_fill') + ' (' + matching_sizes.join(', ') + ')</span>';
1031                        is_active = true;
1032                    } else {
1033                        html = $this.attr('data-default_fill');
1034                    }
1035                } else {
1036                    // show individual sizes
1037                    html = $this.attr('data-default_fill');
1038                    if (matching_sizes.length > 0) {
1039                        html = ', ' + html + ', ';
1040                        $.each(matching_sizes, function (index, size) {
1041                            search = ', ' + size + ',';
1042                            replace = ', <span class="discountrule_table_active">' + size + '</span>,';
1043                            html = html.replace(search, replace);
1044                        });
1045                        html = html.substring(1, html.length - 2);
1046                        is_active = true;
1047                    }
1048                }
1049
1050                if (is_active) {
1051                    $this.addClass('active');
1052                }
1053            })
1054        } else {
1055            // page_element.find('.tier_note').html(page_element.attr('data-default_fill'));
1056            rule_elements.each(function () {
1057                $(this).removeClass('active');
1058            });
1059        }
1060
1061        if (is_active) {
1062            some_active_total = true;
1063        }
1064    });
1065
1066    UpdateDiscountRuleToggleBtn();
1067}
1068
1069function UpdateDiscountRuleToggleBtn()
1070{
1071    $('.discount_rule_toggle_btn').each(function () {
1072        var $this = $(this);
1073        var $text = $this.find('span');
1074        var hash = this.dataset.modelHash;
1075        var colorHash = this.dataset.colorHash;
1076        var len = $(this).prev('.discountrule_table[data-model-hash="' + hash + '"][data-color-hash="' + colorHash + '"]').children('.active').length;
1077        if (len) {
1078            $this.addClass('active');
1079            $text.text(len + ' ' + lang['DISCOUNTS_ACTIVE']);
1080        } else {
1081            $this.removeClass('active');
1082            $text.text(lang['ZERO_DISCOUNTS']);
1083        }
1084    });
1085}
1086
1087function updateVariantPriceInfo(model, color, size, size_data)
1088{
1089    variant_price_table_identifier = 'variant_price_' + model + '_' + color + '_' + size;
1090    $('#' + variant_price_table_identifier + ' .total_discount').html(size_data.formatted_total_discount);
1091    if (size_data.total_discount > 0) {
1092        $('#' + variant_price_table_identifier + ' .total_discount_block').show();
1093    } else {
1094        $('#' + variant_price_table_identifier + ' .total_discount_block').hide();
1095    }
1096    $('#' + variant_price_table_identifier + ' .your_unit_price').html(size_data.formatted_unit_price);
1097}
1098
1099function base64(input)
1100{
1101    var Base64 = {
1102        _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
1102+/=", encode: function (e) {
1103            var t = "";
1104            var n, r, i, s, o, u, a;
1105            var f = 0;
1106            e = Base64._utf8_encode(e);
1107            while (f < e.length) {
1108                n = e.charCodeAt(f++);
1109                r = e.charCodeAt(f++);
1110                i = e.charCodeAt(f++);
1111                s = n >> 2;
1112                o = (n & 3) << 4 | r >> 4;
1113                u = (r & 15) << 2 | i >> 6;
1114                a = i & 63;
1115                if (isNaN(r)) {
1116                    u = a = 64
1117                } else if (isNaN(i)) {
1118                    a = 64
1119                }
1120                t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a)
1121            }
1122            return t
1123        }, decode: function (e) {
1124            var t = "";
1125            var n, r, i;
1126            var s, o, u, a;
1127            var f = 0;
1128            e = e.replace(/[++^A-Za-z0-9+/=]/g, "");
1129            while (f < e.length) {
1130                s = this._keyStr.indexOf(e.charAt(f++));
1131                o = this._keyStr.indexOf(e.charAt(f++));
1132                u = this._keyStr.indexOf(e.charAt(f++));
1133                a = this._keyStr.indexOf(e.charAt(f++));
1134                n = s << 2 | o >> 4;
1135                r = (o & 15) << 4 | u >> 2;
1136                i = (u & 3) << 6 | a;
1137                t = t + String.fromCharCode(n);
1138                if (u != 64) {
1139                    t = t + String.fromCharCode(r)
1140                }
1141                if (a != 64) {
1142                    t = t + String.fromCharCode(i)
1143                }
1144            }
1145            t = Base64._utf8_decode(t);
1146            return t
1147        }, _utf8_encode: function (e) {
1148            e = e.replace(/\r\n/g, "n");
1149            var t = "";
1150            for (var n = 0; n < e.length; n++) {
1151                var r = e.charCodeAt(n);
1152                if (r < 128) {
1153                    t += String.fromCharCode(r)
1154                } else if (r > 127 && r < 2048) {
1155                    t += String.fromCharCode(r >> 6 | 192);
1156                    t += String.fromCharCode(r & 63 | 128)
1157                } else {
1158                    t += String.fromCharCode(r >> 12 | 224);
1159                    t += String.fromCharCode(r >> 6 & 63 | 128);
1160                    t += String.fromCharCode(r & 63 | 128)
1161                }
1162            }
1163            return t
1164        }, _utf8_decode: function (e) {
1165            var t = "";
1166            var n = 0;
1167            var r = c1 = c2 = 0;
1168            while (n < e.length) {
1169                r = e.charCodeAt(n);
1170                if (r < 128) {
1171                    t += String.fromCharCode(r);
1172                    n++
1173                } else if (r > 191 && r < 224) {
1174                    c2 = e.charCodeAt(n + 1);
1175                    t += String.fromCharCode((r & 31) << 6 | c2 & 63);
1176                    n += 2
1177                } else {
1178                    c2 = e.charCodeAt(n + 1);
1179                    c3 = e.charCodeAt(n + 2);
1180                    t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
1181                    n += 3
1182                }
1183            }
1184            return t
1185        }
1186    }
1187    var encodedString = Base64.encode(input);
1188    encodedString = encodedString.replace(/=/g, '');
1189    return encodedString;
1190}
1191
1192if (!/^\/(?:[a-z]{2}\/)?shoppingcart$/.test(window.location.pathname)) {
1193    function bindInputField()
1194    {
1195        $(document).on('change', '.input_variant_qty', function () {
1196            // only allow 0-9 in input
1197            var $this = $(this);
1198            var v = $this.val().trim().replace(/[^0-9]/gi, '');
1199
1200            // only update input when the value is different, an update causes the cursor to move
1201            if (v != $this.val()) {
1202                $this.val(v);
1203            }
1204
1205            // New value is more than current quantity
1206            if (v > $this.data('current-qty') && useTweakwiseEventTag) {
1207                const price = v * $(this).data('tweakwise-variant-price');
1208
1209                document.dispatchEvent(new CustomEvent('TweakwiseAddToCart',  {
1210                    detail: {
1211                        productKey: $(this).data('tweakwise-item-id'),
1212                        quantity: v,
1213                        price: price.toFixed(2)
1214                    }
1215                }));
1216            }
1217
1218            // If more characters then 4, make font smaller to fit in simple product field
1219            if ($(this).val().length > 4) {
1220                $(this).css('font-size', 'x-small');
1221            } else {
1222                $(this).css('font-size', 'inherit');
1223            }
1224
1225            update_shoppingcart($this);
1226        });
1227    }
1228
1229    $(document).on('change', '.input_variant_qty', function () {
1230        // only allow 0-9 in input
1231        var $this = $(this);
1232        var v = $this.val().trim().replace(/[^0-9]/gi, '');
1233
1234        // only update input when the value is different, an update causes the cursor to move
1235        if (v != $this.val()) {
1236            $this.val(v);
1237        }
1238
1239        // New value is more than current quantity
1240        if (v > $this.data('current-qty') && useTweakwiseEventTag) {
1241            const price = v * $(this).data('tweakwise-variant-price');
1242
1243            document.dispatchEvent(new CustomEvent('TweakwiseAddToCart',  {
1244                detail: {
1245                    productKey: $(this).data('tweakwise-item-id'),
1246                    quantity: v,
1247                    price: price.toFixed(2)
1248                }
1249            }));
1250        }
1251
1252        // If more characters then 4, make font smaller to fit in simple product field
1253        if ($(this).val().length > 4) {
1254            $(this).css('font-size', 'x-small');
1255        } else {
1256            $(this).css('font-size', 'inherit');
1257        }
1258
1259        update_shoppingcart($this);
1260    });
1261}
1262
1263function saveMatrixSetting(value)
1264{
1265    $.cookie('collapsible_states', null);
1266
1267    $.ajax({
1268        headers: {
1269            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
1270        },
1271        url: '/ajax/shoppingcart/save_matrix_toggle',
1272        type: 'post',
1273        data: {
1274            'toggle': value
1275        }
1276    });
1277}
1278
1279$('.discount-box').on('hidden.bs.dropdown', function () {
1280    var $icon = $('button > i', this);
1281    $icon.removeClass("fas fa-caret-up").addClass("fas fa-caret-down");
1282})
1283
1284$('.discount_rule_toggle_btn').click(function () {
1285    toggleDiscountRuleDisplay(this);
1286});
1287
1288function toggleDiscountRuleDisplay(elem)
1289{
1290    var $elem = $(elem);
1291    var $icon = $('i', $elem);
1292    var show_inactive_discountrules = $icon.hasClass('fas fa-caret-up');
1293    // var hash = elem.dataset.modelHash;
1294    // var table = $elem.next('.discountrule_table');
1295
1296    if (show_inactive_discountrules) {
1297        // toggle, so we must hide them now
1298        // $('.inactive_discount_rule').hide();
1299        // table.hide();
1300        $icon.removeClass("fas fa-caret-up").addClass("fas fa-caret-down");
1301    } else {
1302        // toggle, so we must show them now
1303        // $('.inactive_discount_rule').show();
1304        // table.show();
1305        $icon.removeClass("fas fa-caret-down").addClass("fas fa-caret-up");
1306    }
1307    // save cookie
1308    $.ajax({
1309        headers: {
1310            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
1311        },
1312        url: '/ajax/shoppingcart/save_discountline_toggle',
1313        type: 'post',
1314        data: {
1315            'show_inactive_discountrules': (show_inactive_discountrules == false)
1316        }
1317    });
1318
1319    update_shoppingcart();
1320}
1321
1322/**
1323 * Show qty changed by order steps modal
1324 */
1325function showQtyChangedByOrderStepsModal()
1326{
1327    $('.page-modal .modal-title').html(lang['QTY_CHANGED_BY_ORDER_STEPS']);
1328    $('.page-modal .modal-body.replacable-content').html(
1329        '<p>' + lang['QTY_CHANGED_BY_ORDER_STEPS'] + '</p>'
1330        + '<div class="niceCheckbox">'
1331        + '<input type="checkbox" name="dont_show_qty_changed_by_order_steps_again" id="dont_show_qty_changed_by_order_steps_again" />'
1332        + '<label for="dont_show_qty_changed_by_order_steps_again" class="custom-checkbox" onclick="hideQtyChangedByOrderStepsModal()"></label>'
1333        + '<label for="dont_show_qty_changed_by_order_steps_again" class="checkbox-text-label" onclick="hideQtyChangedByOrderStepsModal()">' + lang['DONT_SHOW_AGAIN'] + '</label>'
1334        + '</div>'
1335    );
1336
1337    $('.stock-modal').modal('show');
1338}
1339
1340/**
1341 * Hide qty changed by order steps modal
1342 */
1343function hideQtyChangedByOrderStepsModal()
1344{
1345    $.cookie('dont_show_qty_changed_by_order_steps_again', 1, {path: '/'});
1346}
1347
1348if (!/^\/(?:[a-z]{2}\/)?shoppingcart$/.test(window.location.pathname)) {
1349    $(document).on('click', '.price-block .btn-number, .pv-product .btn-number', function (e) {
1350        e.preventDefault();
1351
1352        var fieldName = $(this).attr('data-field'),
1353            type = $(this).attr('data-type'),
1354            matrixId = $(this).closest('.price-block').attr('id'),
1355            input = $("#" + matrixId + " input[name='" + fieldName + "']"),
1356            currentVal = parseInt(input.val()),
1357            hasOrderSteps = (typeof input.data('order-steps') !== 'undefined'),
1358            orderSteps = input.data('order-steps'),
1359            newVal = (hasOrderSteps ? Math.max(1, orderSteps) : 1);
1360
1361        // Check if currentVal is NaN
1362        if (currentVal !== currentVal) {
1363            currentVal = 0;
1364        }
1365
1366        if (type == 'minus') {
1367            if (currentVal > 0) {
1368                input.val(currentVal - newVal).trigger('change');
1369            }
1370        } else if (type == 'plus') {
1371            input.val(currentVal + newVal).trigger('change');
1372        }
1373    });
1374}
1375
1376$(document).on('click', '.ordermatrix .btn-plusminus', function (e) {
1377    e.preventDefault();
1378
1379    var fieldName = $(this).attr('data-field'),
1380        type = $(this).attr('data-type'),
1381        input = $("#" + fieldName),
1382        currentVal = parseInt(input.val()),
1383        hasOrderSteps = (typeof input.data('order-steps') !== 'undefined'),
1384        orderSteps = input.data('order-steps'),
1385        newVal = (hasOrderSteps ? Math.max(1, orderSteps) : 1);
1386
1387    // Check if currentVal is NaN
1388    if (currentVal != currentVal) {
1389        currentVal = 0;
1390    }
1391
1392    if (type == 'minus') {
1393        if (currentVal > 0) {
1394            input.val(currentVal - newVal)
1395                .trigger('change');
1396        }
1397    } else if (type == 'plus') {
1398        input.val(currentVal + newVal)
1399            .trigger('change');
1400    }
1401});
1402
1403function openModal()
1404{
1405    $('.page-modal').modal('show');
1406}
1407
1408function change_image_in_container(imageNode, imageSrc)
1409{
1410    var img = new Image();
1411    img.onload = function () {
1412        imageNode.attr('src', imageSrc);
1413    };
1414    img.src = imageSrc;
1415}
1416
1417function hideEmptyDiscountBoxes()
1418{
1419    $('.discount-area .discount-box').each(function () {
1420        if ($(this).find('.show-discount-box').data('active-discount') === 0) {
1421            $(this).hide();
1422        }
1423    });
1424}
1425
1426/**
1427 * Handle minimal order amount message
1428 *
1429 * @param data
1430 */
1431function handleMinimalOrderAmountMessage(data)
1432{
1433    let minimalOrderAmountMessages = document.querySelectorAll('.alert.alert-info.minimal_order_amount_message');
1434
1435    if (data.minimal_order_amount_message) {
1436        if (minimalOrderAmountMessages.length) {
1437            minimalOrderAmountMessages.forEach(element => {
1438                element.querySelector('span').innerHTML = data.minimal_order_amount_message;
1439                element.style.display = 'block';
1440            });
1441        } else {
1442            let messageWrapper = document.createElement('div'),
1443                closeButton = document.createElement('a'),
1444                message = document.createElement('span');
1445
1446            messageWrapper.classList.add('alert', 'alert-info', 'minimal_order_amount_message');
1447
1448            closeButton.classList.add('close');
1449            closeButton.setAttribute('data-dismiss', 'alert');
1450            closeButton.setAttribute('href', '#');
1451            closeButton.innerHTML = '×';
1452
1453            message.innerHTML = data.minimal_order_amount_message;
1454
1455            messageWrapper.append(closeButton);
1456            messageWrapper.append(message);
1457
1458            // Check if top-icon-bag-dropdown element exists in page
1459            if (document.getElementById('top-icon-bag-dropdown')) {
1460                document.getElementById('top-icon-bag-dropdown').append(messageWrapper);
1461            }
1462
1463            if (/^\/(?:[a-z]{2}\/)?shoppingcart$/.test(window.location.pathname)) {
1464                document.querySelector('.main-content').prepend(messageWrapper.cloneNode(true));
1465            }
1466        }
1467    } else {
1468        if (minimalOrderAmountMessages.length) {
1469            minimalOrderAmountMessages.forEach(element => {
1470                element.style.display = 'none';
1471            });
1472        }
1473    }
1474}

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.