PageSourceSearch

https://www.scampparnashop.hu/wa_script/js/app.js?_=2026-09-11-00-00

js scampparnashop.hu collected 2026-10-03 21:37:54 UTC 61,980 bytes, 2,201 lines download raw bytes

1/**
2 * @copyright (c) 2018, Bohemiasoft s.r.o. 25.04.2018
3 */
4;var BS = BS || {};
5(function(exports, global, settings) {
6  'use strict';
7
8  var obj = {
9
10    /**
11     * Vrací true pokud je zadaný parametr číslo a zároveň není NaN
12     * @param num
13     * @returns {boolean}
14     */
15    isNumber: function(num) {
16      return typeof num === "number" && !isNaN(num);
17    },
18
19    /**
20     * Vrací true pokud je předaná hodnota celé číslo
21     * @param val
22     */
23    isInteger: function(val) {
24      //pokud můžeme, použijeme objekt Number
25      if(global.Number && global.Number.isInteger) {
26        return global.Number.isInteger(val);
27      } else {
28        return this.isNumber(val)
29          && global.isFinite(val)
30          && val % 1 === 0;
31      }
32    },
33
34    /**
35     * Vrací true pokud má číslo nějaký exponent (desetinná místa)
36     * @param val
37     * @returns {*|boolean}
38     */
39    isFloat: function(val) {
40      return this.isNumber(val)
41        && global.isFinite(val)
42        && val % 1 !== 0;
43    },
44
45    /**
46     * Vrací přesnost (počet desetinných míst).
47     * Vrací 0 pokud se jedná o celé číslo nebo předaný argument není číslo
48     * @param num
49     * @returns {number}
50     */
51    precision: function(num) {
52      var p = 0, e = 1;
53      if(this.isNumber(num)
54        && global.isFinite(num)) {
55        while(this.round(num * e) / e !== num) {
56          p++;
57          e = Math.pow(10, p);
58        }
59      }
60      return p;
61    },
62
63    /**
64     * Zaokrouhlení čísla
65     * @param num
66     * @param p
67     * @returns (number)
68     */
69    round: function(num, p) {
70      var v;
71      p = p || 0;
72      if(!this.isNumber(num) || !this.isInteger(p)) {
73        v = 0;
74      } else {
75        var f = Math.pow(10, p);
76        v = Math.round(num * f) / f;
77      }
78      return v;
79    },
80
81    /**
82     * Parsování stringu na číslo
83     * @param string
84     * @returns (number)
85     */
86    parse: function(string) {
87      var v = string;
88      if(settings.decPoint !== ".") {
89        //poslední výskyt - např. 12(,)(54)
90        var patt = "(%s%)([^%s%]+)$";
91        patt = patt.replace(new RegExp("%s%", "g"), settings.decPoint);
92        v = v.replace(new RegExp(patt), function() {
93          return "." + arguments[2];
94        });
95      }
96      return parseFloat(v);
97    },
98
99    /**
100     * Jednoduché formátování čísla na výstup (string)
101     * @param num
102     * @param p
103     * @returns {string}
104     */
105    format: function(num, p) {
106      var f;
107      p = p || 0;
108      num = this.round(num, p);
109      f = num.toFixed(p);
110      if(p > 0) {
111        f = f.replace(".", settings.decPoint);
112      }
113      return f;
114    },
115
116    /**
117     * Vrátí nastavení objektu
118     * Pokud je param prop zadán, vrátí konkrétní nastavení, jinak celý objekt
119     * @param prop
120     * @returns {*}
121     */
122    getSettings: function(prop) {
123      if(prop) {
124        return settings[prop];
125      } else {
126        return Object.assign({}, settings);
127      }
128    }
129  };
130
131  if(!exports.Number) {
132    exports.Number = obj;
133  }
134})(BS, window, BS.env);
135
136(function(BS, $, undefined) {
137  'use strict';
138
139  function init_tooltips() {
140    $("[data-tip]").each(function() {
141      var options = {};
142      if(this.dataset.tipOptions) {
143        try {
144          options = JSON.parse(this.dataset.tipOptions);
145        } catch(err) {
146          console.error("Tip options wrong format!");
147        }
148      }
149      var tipSettings = {
150        classes: ["app-tooltip"],
151        showArrow: true,
152        offsetY: 0,
153        offsetX: 0
154      };
155      if(options.class) {
156        var c = options.class.split(/\s+/);
157        tipSettings.classes = tipSettings.classes.concat(c);
158      }
159      if(options.showArrow !== undefined) {
160        tipSettings.showArrow = !!options.showArrow;
161        //TODO přečist z nastavení
162        tipSettings.offsetY = tipSettings.showArrow ? 0 : -10;
163      }
164      $(this).qtip({
165        content: {
166          text: $("#" + this.dataset.tipContent)
167        },
168        position: {
169          at: "top center",
170          my: "bottom center",
171          viewport: ($(window)),
172          adjust: {
173            y: tipSettings.offsetY,
174            x: tipSettings.offsetX
175          }
176        },
177        show: {
178          event: "mouseenter",
179          solo: false
180        },
181        hide: {
182          event: "mouseleave",
183          delay: 100
184        },
185        style: {
186          classes: tipSettings.classes.join(" "),
187          tip: tipSettings.showArrow
188        }
189      });
190    });
191  }
192
193  if(!BS.ui) BS.ui = {};
194  BS.ui.tooltip = {
195    init: function() {
196      init_tooltips();
197    }
198  }
199})(BS, jQuery);
200
201(function(BS, closeBtn, notification) {
202
203  function removeNotification(btn) {
204    var parent = btn.parentElement,
205        found = false;
206    while(!found && parent) {
207      if(parent.classList.contains(notification)) {
208        found = true;
209      }
210    }
211    parent.parentNode.removeChild(parent);
212  }
213
214  if(!BS.ui) BS.ui = {};
215  BS.ui.notifications = {
216    init: function() {
217      document.body.addEventListener("click", function(e) {
218        var el = e.target;
219        if(el.classList.contains(closeBtn)) {
220          removeNotification(el);
221        }
222      });
223    }
224  }
225})(BS, "notification-close", "notification");
226
227(function(BS, WA, $) {
228  'use strict';
229
230  function init(form) {
231    form.validate({
232      rules: {
233        subscribe_name: {
234          required: true
235        },
236        subscribe_email: {
237          required: true,
238          email: true
239        },
240        subscribe_accept: {
241          required: true
242        }
243      },
244      messages: {
245        subscribe_name: {
246          required: WA.Translation._error_empty_field
247        },
248        subscribe_email: {
249          required: WA.Translation._error_empty_field,
250          email: WA.Translation._error_invalid_mail
251        }
252      },
253      highlight: function(el) {
254        $(el).closest(".form-group").addClass("has-error");
255      },
256      unhighlight: function(el) {
257        $(el).closest(".form-group").removeClass("has-error");
258      },
259      errorPlacement: function(error, el) {
260        if (el.attr("name") !== "subscribe_accept") {
261          error.insertAfter(el);
262        }
263      }
264    });
265  }
266
267  if(!BS.GDPR) BS.GDPR = {};
268  BS.GDPR.subscribeForm = {
269    init: function(form) {
270      var actualForm = $(form).find("form");
271      init(actualForm);
272    }
273  };
274
275})(BS, WA, jQuery);
276
277(function(BS, WA, $) {
278  'use strict';
279
280  function initForm(form) {
281    form.find("input[name='newsletter_mail']").on("focus", function() {
282      //načteme a zobrazíme captchu
283      var cField = form.find(".captcha-input").children("input").get(0);
284      //v případě reCaptcha volby políčko neexistuje...
285      if(cField) {
286        if(BS.captcha
287          && $.isFunction(BS.captcha[cField.name])) {
288          //reload obrázku
289          BS.captcha[cField.name]();
290        }
291      }
292      form.find(".captcha-box").removeClass("hidden");
293    });
294    form.validate({
295      rules: {
296       newsletter_mail: {
297         required: true,
298         email: true
299       },
300       gdpr_accept: {
301         required: true
302       }
303      },
304      messages: {
305       newsletter_mail: {
306         required: WA.Translation._error_empty_field,
307         email: WA.Translation._error_invalid_mail
308       }
309      },
310      highlight: function(el) {
311       if(el.name === "newsletter_mail") {
312         $(el).parent().addClass("has-error");
313       }
314      },
315      unhighlight: function(el) {
316       if(el.name === "newsletter_mail") {
317         $(el).parent().removeClass("has-error");
318       }
319      },
320      errorPlacement: function(error, el) {
321       if (el.attr("name") !== "gdpr_accept") {
322         error.insertAfter(el);
323       }
324      }
325    });
326  }
327
328  if(!BS.GDPR) BS.GDPR = {};
329  BS.GDPR.newsletterForm = {
330    init: function(selector) {
331      $(selector).each(function() {
332        initForm($(this).closest("form"));
333      });
334    }
335  }
336
337})(BS, WA, jQuery);
338
339(function(window, document, exports, undefined) {
340  'use strict';
341
342  var PopMessage = function(options) {
343    options = options || {};
344    var self = this,
345        timer = parseInt(options.timer);
346    this._options = options;
347    this.create(options);
348    if(!isNaN(timer)
349      && timer > 0) {
350      self.timeout = setTimeout(function() {
351        self.hide();
352      }, timer);
353    }
354  };
355
356  PopMessage.prototype = {
357
358    create: function(options) {
359      var self = this;
360      var wrapper = this.createElement(PopMessage.template.el);
361
362      //interaktivita
363      var controls = wrapper.querySelector(".pop-controls");
364      if(controls) {
365        if(options.interactive === true) {
366          var closeBtn = wrapper.querySelector(".pop-close");
367          if(closeBtn) {
368            closeBtn.addEventListener("click", function(e) {
369              self.hide();
370            });
371          }
372        } else {
373          controls.remove();
374        }
375      }
376
377      //ikona
378      var icon = wrapper.querySelector(".pop-icon");
379      if(icon) {
380        if(this.isStringSet(options.icon)) {
381          this.addClass(icon.children[0], options.icon);
382          this.addClass(wrapper, "w-icon");
383        } else {
384          icon.remove();
385        }
386      }
387
388      //typ
389      if(this.isStringSet(options.type)) {
390        this.addClass(wrapper, options.type);
391      }
392
393      //titulek
394      var title = wrapper.querySelector(".pop-title");
395      if(title) {
396        if(this.isStringSet(options.title)) {
397          this.setText(title, options.title);
398        } else {
399          title.remove();
400        }
401      }
402
403      //zprava
404      var content = wrapper.querySelector(".pop-content");
405      if(content) {
406        if(this.isStringSet(options.message))
407        {
408          this.setText(content, options.message);
409        }
410      }
411
412      this.el = wrapper;
413    },
414
415    hide: function() {
416      //odstranění z domu
417      if(this.timeout) {
418        clearTimeout(this.timeout);
419        this.timeout = null;
420      }
421      this.el.remove();
422      this.callFunc("onHide", this.el);
423    },
424
425    show: function() {
426      document.body.append(this.el);
427      this.callFunc("onShow", this.el);
428    },
429
430    createElement: function(elHtml) {
431      var t = document.createElement("div");
432      t.innerHTML = elHtml.trim();
433
434      return t.firstChild;
435    },
436
437    addClass: function(el, classList) {
438      var classes = classList.split(/\s+/),
439          i = 0;
440      //IE má pouze základní podporu pro classList.add()
441      //třídy musíme vložit postupně
442      for(; i < classes.length; i++) {
443        el.classList.add(classes[i]);
444      }
445    },
446
447    isString: function(v) {
448      return typeof v === "string";
449    },
450
451    isStringSet: function(v) {
452      return this.isString(v) && v !== "";
453    },
454
455    callFunc: function(c) {
456      if(this.isCallbackSet(c)) {
457        this._options.callbacks[c].apply(this, Array.prototype.slice.call(arguments, 1));
458      }
459    },
460
461    isCallbackSet: function(c) {
462      if(typeof this._options.callbacks === "object" && this._options.callbacks !== null) {
463        return typeof this._options.callbacks[c] === "function";
464      } else {
465        return false;
466      }
467    },
468
469    setText: function(el, text) {
470      el.innerText = text.trim();
471    }
472  };
473
474  PopMessage.template = {
475    el: '<div class="pop-message"><div class="pop-container"><div class="pop-controls"><span class="pop-close"><i>&#215;</i></span></div><div class="pop-icon"><i></i></div><h5 class="pop-title"></h5><p class="pop-content"></p></div></div>'
476  };
477
478  exports.PopMessage = PopMessage;
479
480})(window, document, BS.ui);
481
482(function(ui, texts, design) {
483  'use strict';
484
485  //pouze jedna instance
486  var pop = null;
487
488  ui.popMessage = {
489    show: function(options) {
490      console.log(options);
491      this.hide();
492      pop = new ui.PopMessage(options);
493      pop.show();
494    },
495
496    hide: function() {
497      if(pop) {
498        pop.hide();
499        pop = null;
500      }
501    },
502
503    alert: function(message, showIcon, options = {}) {
504      showIcon = typeof showIcon !== "undefined" ? !!showIcon : true;
505      //šablony mohou používat různé sady ikon
506      var iconClass = design.isLayout3 ? "fa fa-exclamation" : "icon-exclamation-sign";
507      options = Object.assign({
508        type: "alert",
509        title: texts._error,
510        message: message,
511        timer: 5000, //5s
512        icon: showIcon ? iconClass : "",
513        interactive: true,
514        callbacks: {
515          onHide: function() {
516            pop = null;
517          }
518        }
519      }, options);
520      this.show(options);
521    },
522      success: function(message, showIcon, options = {}) {
523          showIcon = typeof showIcon !== "undefined" ? !!showIcon : true;
524          //šablony mohou používat různé sady ikon
525          var iconClass = design.isLayout3 ? "fa fa-check" : "icon-check";
526          options = Object.assign({
527              type: "success",
528              title: texts._success,
529              message: message,
530              timer: 5000, //5s
531              icon: showIcon ? iconClass : "",
532              interactive: true,
533              callbacks: {
534                  onHide: function() {
535                      pop = null;
536                  }
537              }
538          }, options);
539          this.show(options);
540      },
541    warning: function(message, showIcon, options = {}) {
542      showIcon = typeof showIcon !== "undefined" ? !!showIcon : true;
543      //šablony mohou používat různé sady ikon
544      var iconClass = design.isLayout3 ? "fa fa-question" : "icon-exclamation-sign";
545      options = Object.assign({
546        type: "warning",
547        title: texts._warning,
548        message: message,
549        timer: 5000, //5s
550        icon: showIcon ? iconClass : "",
551        interactive: true,
552        callbacks: {
553          onHide: function() {
554            pop = null;
555          }
556        }
557      }, options);
558      this.show(options);
559    }
560
561  };
562})(BS.ui, WA.Translation, BS.Design);
563
564(function (document, BS, exports, undefined) {
565  'use strict';
566
567  var spinActions = {
568    INC: 1,
569    DEC: 2
570  };
571  var evPluginName = "InputSpinner";
572
573  function InputSpinner(el, options) {
574    this.wrapper = el;
575    this.input = el.querySelector(".spin-input");
576    this.product_info = {};
577    if(this.input.dataset.productInfo) {
578      this.product_info = JSON.parse(this.input.dataset.productInfo);
579    }
580    this.widgets = {
581      inc: el.querySelector(".spin-inc"),
582      dec: el.querySelector(".spin-dec")
583    };
584    this.state = "";
585    this.vars = {
586      spins: 1,
587      timeout: null
588    };
589    this.settings = this.extendSettings(InputSpinner.defaults, options);
590    //inicializace
591    this.registerEvents();
592  }
593
594  InputSpinner.prototype = {
595    extendSettings: function(obj1, obj2) {
596      var obj = {},
597          key;
598      for(key in obj1) {
599        if(obj1.hasOwnProperty(key)) {
600          if(!obj2.hasOwnProperty(key)) {
601            obj[key] = obj1[key];
602          } else {
603            obj[key] = obj2[key];
604          }
605        }
606      }
607      return obj;
608    },
609    /**
610     * Registarce událostí
611     */
612    registerEvents: function() {
613      var self = this;
614      if(this.widgets.inc) {
615        this.widgets.inc.addEventListener("mousedown", function(e) {
616          self.startSpin(spinActions.INC);
617        });
618      }
619      if(this.widgets.dec) {
620        this.widgets.dec.addEventListener("mousedown", function(e) {
621          self.startSpin(spinActions.DEC);
622        });
623      }
624      if(this.widgets.inc
625        || this.widgets.dec) {
626        //mouseup na document, jelikož po stisknutí myšítka a posunutí kurzoru je event vyvolán pro jiný element!
627        document.addEventListener("mouseup", function(e) {
628          if(self.isSpinning()) {
629            self.stopSpin();
630          }
631        });
632      }
633      if(this.input) {
634        this.input.addEventListener("change", function(e) {
635          if((e instanceof CustomEvent || e.detail !== undefined) && e.detail.plugin === evPluginName) return;
636          var v = self.getValue(),
637              newV;
638          if(v < self.settings.min) {
639            newV = self.settings.min;
640          } else if(v > self.settings.max) {
641            newV = self.settings.max;
642          } else {
643            newV = v;
644          }
645          if(newV !== undefined) {
646            self.setValue(newV);
647          }
648        });
649      }
650    },
651    /**
652     * Přičtení hodnoty, další volání funkcí setTimeout
653     * @param dir int
654     */
655    startSpin: function(dir) {
656      var d;
657      if(this.vars.spins === 1) {
658        //první kolo
659        if(dir === spinActions.INC) {
660          this.increment();
661        } else if(dir === spinActions.DEC) {
662          this.decrement();
663        }
664        d = 1;
665      } else if(this.vars.spins < 3) {
666        d = 1.5;
667      } else if(this.vars.spins < 8) {
668        d = 2.5;
669      } else {
670        d = 4;
671      }
672
673      var self = this;
674      this.vars.timeout = setTimeout(function() {
675        self.timeoutFn(dir);
676      }, Math.ceil(this.settings.speed / d));
677      this.vars.spins++;
678    },
679    /**
680     * Zastavení přičítání
681     */
682    stopSpin: function() {
683      window.clearTimeout(this.vars.timeout);
684      this.vars.spins = 1;
685      this.vars.timeout = null;
686      this.triggerEvent(this.input, "change", this.getEventData());
687    },
688    /**
689     * Funkce pro přičtení/odečtení hodnoty.
690     * Zároveň volá další kolo
691     * @param dir int
692     */
693    timeoutFn: function(dir) {
694      if(dir === spinActions.INC) {
695        this.increment();
696      } else if(dir === spinActions.DEC) {
697        this.decrement();
698      }
699      this.startSpin(dir);
700    },
701    /**
702     * Zvýšení hodnoty o nastavený krok
703     */
704    increment: function() {
705      var val = this.getValue(),
706          p = BS.Number.precision(val);
707      if(val !== false) {
708        if(val < this.settings.maxSpin) {
709          var pw = Math.pow(10, p);
710          val = Math.round(val * pw + this.settings.step * pw) / pw;
711          if(val > this.settings.maxSpin) {
712            val = this.settings.maxSpin;
713          }
714          this.state = "+";
715          this.setValue(val);
716        }
717      }
718    },
719    /**
720     * Snížení hodnoty o nastavený krok
721     */
722    decrement: function() {
723      var val = this.getValue(),
724          p = BS.Number.precision(val);
725      if(val !== false) {
726        if(val > this.settings.minSpin) {
727          var pw = Math.pow(10, p);
728          val = Math.round(val * pw - this.settings.step * pw) / pw;
729          if(val < this.settings.minSpin) {
730            val = this.settings.minSpin;
731          }
732          this.state = "-";
733          this.setValue(val);
734        }
735      }
736    },
737    isSpinning: function() {
738      return this.vars.timeout !== null;
739    },
740    /**
741     * Nastavení hodnoty v políčku
742     * @param val
743     * @param triggerEv
744     */
745    setValue: function(val, triggerEv) {
746      var p = 0,
747          valP = BS.Number.precision(val);
748      if(this.settings.floatEnabled
749        && this.settings.precision > 0) {
750        p = valP > this.settings.precision ? this.settings.precision : valP;
751      }
752      if(this.input) {
753        this.input.value = BS.multiples.checkIncDec(BS.Number.format(val, p), this.product_info || null, this.state);
754        if(!!triggerEv) {
755          this.triggerEvent(this.input, "change", {});
756        }
757      }
758    },
759    /**
760     * Vyvolání eventu
761     * @param el
762     * @param event
763     * @param params
764     */
765    triggerEvent: function(el, event, params) {
766      var ev;
767      if(typeof window.CustomEvent === "function") {
768        //normální prohlížeče
769        ev = new CustomEvent(event, {bubbles: true, detail: params});
770      } else {
771        //IE
772        ev = document.createEvent("CustomEvent");
773        ev.initCustomEvent(event, true, false, params);
774      }
775      el.dispatchEvent(ev);
776    },
777
778    /**
779     * Vrácení hodnoty z políčka
780     * @returns {number|boolean}
781     */
782    getValue: function() {
783      var value;
784      if(this.input) {
785        value = BS.Number.parse(this.input.value) || this.settings.defaultValue;
786      } else {
787        value = false;
788      }
789
790      return value;
791    },
792
793    /**
794     * Vrátí object s custom event daty rozšířený o předané parametry
795     * @param params
796     * @returns object
797     */
798    getEventData: function(params) {
799      params = params || {};
800      var p = {plugin: evPluginName};
801      var keys = Object.keys(params);
802      for(var i = 0; i < keys.length; i++) {
803        if(keys[i] !== "plugin") {
804          p[keys[i]] = params[keys[i]];
805        }
806      }
807
808      return p;
809    }
810  };
811
812  InputSpinner.defaults = {
813    //krok
814    step: 1,
815    //minimální hodnota, která může být do políčka vložena
816    min: 1,
817    //minimální hodnota, na kterou je možné se proklikat
818    minSpin: 1,
819    //maximální hodnota, na kterou je možné se proklikat
820    maxSpin: 9999,
821    //výchozí hodnota (např. pokud není vloženo číslo)
822    defaultValue: 1,
823    //počet povolených deset. míst (pokud floatEnabled == true)
824    precision: 2,
825    //maximální hodnota, která může být do políčka vložena
826    max: 9999,
827    //rychlost
828    speed: 500,
829    //povolení deset. čísel
830    floatEnabled: false
831  };
832  exports.InputSpinner = InputSpinner;
833})(document, BS, BS.ui);
834
835(function(plugin, env, ui) {
836  var pluginName = "__pluginInputSpinner";
837  var options = {
838    floatEnabled: env.basketFloatEnabled,
839    min: env.basketFloatEnabled ? 0.01 : 1
840  };
841  var initInputSpinners = function() {
842    $(plugin).each(function() {
843      if(!$.data(this, pluginName)) {
844        $.data(this, pluginName, new ui.InputSpinner(this, options));
845      }
846    });
847  };
848
849  ui.inputSpinner = {
850    init: initInputSpinners
851  };
852})("[data-input-spinner]", BS.env, BS.ui);
853
854(function(exports, document, undefined) {
855  "use strict";
856
857  var _initialized = false;
858  var _map = {};
859  var _selShipping = null;
860  var _form;
861
862  var _getServices = function(method) {
863    return _map[method] !== undefined ? _map[method] : null;
864  };
865
866  var _runEvents = function(els, selected) {
867    if(!els) return;
868
869    for(var i = 0, node; i < els.length; i++) {
870      node = els[i];
871      //vynutime odskrtnuti
872      if(node.check || !selected) {
873        node.el.checked = selected;
874      }
875    }
876  };
877
878  var _mapServices = function() {
879    var svcs = document.querySelectorAll(".delivery-additional-svcs"),
880        inputs;
881    for(var i = 0, method; i < svcs.length; i++) {
882      method = svcs[i].dataset.deliveryMethod;
883      if(method !== undefined) {
884        inputs = svcs[i].querySelectorAll("input[data-additional-service]");
885        if(inputs.length) {
886          _map[method] = {
887            els: []
888          };
889          for(var j = 0; j < inputs.length; j++) {
890            _map[method].els.push({
891              el: inputs[j],
892              check: parseInt(inputs[j].dataset.additionalServiceCheck) === 1
893            });
894          }
895        }
896      }
897    }
898  };
899
900  var _registerFormEvents = function() {
901    _form.addEventListener("change", function(e) {
902      if(e.target.nodeName === "INPUT"
903        && e.target.name === "postovne_form") {
904        var svc;
905        //zruseni predchozich
906        if(_selShipping) {
907          svc = _getServices(_selShipping);
908          if(svc) {
909            _runEvents(svc.els, false);
910          }
911        }
912
913        svc = _getServices(e.target.value);
914        if(svc) {
915          _runEvents(svc.els, true);
916        }
917
918        _selShipping = e.target.value;
919      }
920    });
921  };
922
923
924  if(!exports.delivery) exports.delivery = {};
925  exports.delivery.additionalServices = {
926    init: function(selector) {
927      _form = document.getElementById(selector);
928      if(!_initialized && _form !== null) {
929        _mapServices();
930        _registerFormEvents();
931        _initialized = true;
932      } else {
933        console.error("Already initialized");
934      }
935    }
936  };
937}).apply(this, [BS, document]);
938
939(function(exports, document) {
940  "use strict";
941
942  class Tab {
943    constructor(container) {
944      this.container = container;
945      this.nav = container.querySelector(".nav-tabs");
946      this.registerEvents();
947    }
948
949    registerEvents() {
950      this.nav.addEventListener('click', e => {
951        var navLink = e.target.closest('.nav-link');
952        if(navLink) {
953          e.preventDefault();
954          this.show(navLink);
955        }
956      });
957    }
958
959    show(navLink) {
960      var activePane = document.getElementById(navLink.getAttribute('href').substring(1));
961      if(!activePane) {
962        throw new Error("Tab pane not found for " + navLink.getAttribute('href'));
963      }
964
965      this.updatePanes(activePane);
966      this.updateNav(navLink);
967    }
968
969    updatePanes(activePane) {
970      var tabs = this.container.querySelectorAll('.tab-pane');
971      for(var i = 0; i < tabs.length; i++) {
972        var pane = tabs[i];
973        if(pane === activePane) {
974           pane.classList.add('active'); 
975        } else {
976          pane.classList.remove('active');
977        }
978      }
979    }
980
981    updateNav(activeLink) {
982      var links = this.nav.querySelectorAll('.nav-link');
983      for(var i = 0; i < links.length; i++) {
984        var link = links[i];
985        if(link === activeLink) {
986          link.classList.add('active');
987        } else {
988          link.classList.remove('active');
989        }
990      }
991    }
992  }
993
994  exports.Tab = Tab;
995}).apply(this, [BS, document]);
996
997$(function() {
998  BS.ui.tooltip.init();
999  BS.ui.notifications.init();
1000  (function(form) {
1001    if(form) {
1002      BS.GDPR.subscribeForm.init(form);
1003    }
1004  })(document.getElementById("subscribeForm"));
1005  BS.GDPR.newsletterForm.init(".wrapper_newsletter");
1006
1007  (function(carousel) {
1008    'use strict';
1009    var wrapper = $(carousel);
1010    if(wrapper.length) {
1011      wrapper.find(".owl-carousel").owlCarousel({
1012        autoplay: true,
1013        autoplayTimeout: 5000,
1014        items: 3,
1015        loop: false,
1016        nav: true,
1017        dots: false,
1018        lazyLoad: true,
1019        autoWidth: false,
1020        autoplayHoverPause: true,
1021        rewind: true,
1022        margin: 10,
1023        navText: ["<i class='nav-icon'></i>","<i class='nav-icon'></i>"],
1024        navContainerClass: "nav-container",
1025        navClass: ["nav-prev", "nav-next"]
1026      });
1027    }
1028  })("#categoriesCarousel");
1029
1030  (function(productGallery) {
1031    'use strict';
1032    var gallery = $(productGallery), carousel, settings;
1033    var defaults = {
1034      autoplay: false,
1035      autoplayTimeout: 5000,
1036      items: 1,
1037      loop: true,
1038      nav: true,
1039      rewind: false,
1040      dots: true,
1041      navText: ["<i class='nav-icon'></i>","<i class='nav-icon'></i>"],
1042      navContainerClass: "nav-container",
1043      navClass: ["nav-prev", "nav-next"]
1044    };
1045    var fixed = {
1046      lazyLoad: true
1047    };
1048    if(gallery.length) {
1049      carousel = gallery.find(".owl-carousel");
1050      if(carousel.length) {
1051        settings = carousel.data("carousel") || {};
1052        carousel
1053          .owlCarousel($.extend(true, {}, defaults, settings, fixed));
1054      }
1055    }
1056  })("#productGallery");
1057
1058  BS.ui.inputSpinner.init();
1059
1060  (function(BS, formSelector) {
1061    'use strict';
1062
1063    var reloadPage = function(page, delay) {
1064      setTimeout(function() {
1065        if(page
1066          && page !== "")
1067        {
1068          window.location.href = page;
1069        }
1070        else
1071        {
1072          window.location.reload();
1073        }
1074      }, ( (Number.isInteger(delay)) ? delay : 0 ));
1075    };
1076
1077    var form = $(formSelector).eq(0);
1078    var requestSend = false;
1079    if(form.length) {
1080      form.on("submit", function(e) {
1081        e.preventDefault();
1082        if(!requestSend) {
1083          var request = BS.extend(BS.Request.$default, {
1084            data: {
1085              action: "Eshop_login",
1086              request: {
1087                action: "login",
1088                data: {
1089                  login_data: {
1090                    username: form.get(0).login.value,
1091                    password: form.get(0).heslo.value
1092                  },
1093                  info: {
1094                    page: window.location.pathname,
1095                    url: window.location.href
1096                  }
1097                }
1098              },
1099              id_zakaznik: BS.User.id
1100            },
1101            success: function(data) {
1102              if(data.success) {
1103                form.find(".login-error").removeClass("show-msg");
1104                form.find(".login-success").addClass("show-msg");
1105                reloadPage(data.redirect ? data.redirect_to : null, 1000);
1106              } else {
1107                form.find(".login-error").addClass("show-msg");
1108                requestSend = false;
1109              }
1110            }
1111          });
1112          $.ajax(request);
1113          requestSend = true;
1114        }
1115      });
1116    }
1117  })(BS, "form[data-form-login]");
1118
1119  if(document.body.classList.contains("page-e-basket")) {
1120    BS.delivery.additionalServices.init("basket_form");
1121  }
1122
1123  // select2 , pro krypton a kryptonit jiná šířka, pro staré šablony nezobrazovat
1124  if(BS.Design.template.name !== undefined && BS.Design.isLayout3 && !BS.Design.template.name.match(/krypton/) ) {
1125    $('.public-select2-styled').select2({
1126          width:"95%"
1127        }).maximizeSelect2Height();
1128  }
1129  else if (BS.Design.template.name !== undefined && BS.Design.template.name.match(/krypton/))
1130  {
1131    $('.public-select2-styled').select2().maximizeSelect2Height();
1132  }
1133
1134  $('body').on('click', '.hc-gdpr-min' ,function () {
1135    $('.hc-gdpr-long').toggle();
1136  });
1137
1138  // zobrazí loadítko při kliku na objednat v košíku pokud zákazník nahrál nějaký obrázek
1139  $('body.page-e-basket').on('submit', function(){
1140
1141    if($('.leave-note .product-upload-img').length > 0 ) {
1142      var files = $('input[type="file"]');
1143      $.each(files, function (key, item) {
1144        if (item.files[0] !== undefined) {
1145          BS.Fce.showLoadingOverlay(WA.Translation._uploading , WA.Translation._take_time);
1146          return false;
1147        }
1148      });
1149    }
1150  });
1151
1152  (function() {
1153    "use strict";
1154
1155    const map = new WeakMap();
1156
1157    class PricePreview {
1158      constructor(element) {
1159       this.element = element;
1160       this.clone = element.cloneNode(true);
1161      }
1162
1163      update(html) {
1164        this.element.innerHTML = html;
1165      }
1166
1167      default() {
1168        var clone = this.clone.cloneNode(true);
1169        this.element.replaceWith(clone);
1170        this.element = clone;
1171      }
1172    };
1173    
1174    class QuantityDiscount {
1175      constructor(container, options) {
1176        this.container = container;
1177        this.options = options;
1178        this.level = null;
1179        this.init();
1180      }
1181
1182      init() {
1183        var container = this.container,
1184          input = container.querySelector('.quantity-input'),
1185          priceSelector,
1186          priceVatSelector,
1187          that = this,
1188          priceEl,
1189          priceElVat;
1190          
1191        if(!input) {
1192          return;
1193        }
1194
1195        if(container.classList.contains('detail-info')) {
1196          priceVatSelector = '.price-vat > .price-value';
1197          priceSelector = '.price-novat';
1198        } else if(container.classList.contains('product3')) {
1199          priceVatSelector = '.product3Price';
1200        } else if(container.classList.contains('product')) {
1201          priceVatSelector = '.productPrice';
1202        } else {
1203          throw new Error("Unknown container type");
1204        }
1205
1206        priceElVat = container.querySelector(priceVatSelector);
1207        if(!priceElVat) {
1208          console.log("No price element found");
1209          return;
1210        }
1211
1212        this.priceVatPreview = new PricePreview(priceElVat);
1213        priceEl = container.querySelector(priceSelector);
1214        this.pricePreview = priceEl ? new PricePreview(priceEl) : null;
1215
1216        $(input).on("change", function() {
1217          that.update();
1218        });
1219        this.input = input;
1220      }
1221
1222      getLevel(value) {
1223        var val = parseFloat(value);
1224        var level;
1225
1226        level = this.options.levels.findIndex(function(level) {
1227          return val >= level.quantity;
1228        });
1229
1230        return level !== -1 ? this.options.levels[level] : null;
1231      }
1232
1233      update() {
1234        var level = this.getLevel(this.input.value);
1235        if(level) {
1236            if(level !== this.level) {
1237              this.priceVatPreview.update(level.price_vat_html);
1238              if(this.pricePreview && level.price_html) {
1239                this.pricePreview.update(level.price_html);
1240              }
1241            }
1242        } else if(this.level) {
1243          this.priceVatPreview.default();
1244          if(this.pricePreview) {
1245            this.pricePreview.default();
1246          }
1247        }
1248
1249        BS.event.trigger('quantity-discount:update', { level });
1250      
1251        this.level = level;
1252      }
1253    }
1254
1255    var initWidgets = function() {
1256      var containers = document.querySelectorAll('[data-quantity-discount]');
1257      for(var i = 0; i < containers.length; i++) {
1258        var instance,
1259          container = containers[i];
1260        if(!map.has(container)) {
1261          try {
1262            instance = new QuantityDiscount(container, {
1263              levels: JSON.parse(container.dataset.quantityDiscount),
1264            });
1265            map.set(container, instance);
1266          } catch(err) {
1267            console.error(err);
1268          }
1269        }
1270      }
1271    };
1272
1273    initWidgets();
1274    $(document).on('page:productsLoaded', function() {
1275      initWidgets();
1276    });
1277  })();
1278
1279  (function() {
1280    "use strict";
1281
1282    var container = document.querySelector('[data-unit-prices]');
1283    if(!container) return;
1284    var priceLabels = container.querySelectorAll('[data-unit-price-label]');
1285    try {
1286      var levels = JSON.parse(container.dataset.unitPrices);
1287    } catch(err) {
1288      console.error("Error initializing unit prices:", err);
1289      return;
1290    }
1291
1292    var findPricelevel = function(level) {
1293      var quantity = level ? level.quantity : null;
1294
1295      return levels.find(function(l) {
1296        return l.quantity === quantity;
1297      });
1298    }
1299
1300    var replacePrices = function(level) {
1301      var priceLevel = findPricelevel(level);
1302      for(var i = 0; i < priceLabels.length; i++) {
1303        var index = priceLabels[i].dataset.unitPriceLabel;
1304        var key = 'label' + index;
1305        if(priceLevel.hasOwnProperty(key)) {
1306          priceLabels[i].innerHTML = priceLevel[key];
1307        }
1308      }
1309    };
1310
1311    BS.event.on('quantity-discount:update', function(e) {
1312      replacePrices(e.level);
1313    });
1314  })();
1315
1316});
1317
1318$(window).click(function() {
1319  let large_selector = $(".energy-tag-large-container");
1320  if(large_selector.is(':visible'))
1321  {
1322    large_selector.addClass('hidden');
1323  }
1324});
1325
1326$(document).on('click', '.energy-tag-container', function(){
1327  event.stopPropagation();
1328  let large_selector = $(".energy-tag-large-container");
1329  if(large_selector.is(':visible'))
1330  {
1331    large_selector.addClass('hidden');
1332  }
1333  else
1334  {
1335    large_selector.removeClass('hidden');
1336  }
1337});
1338
1339$(document).on('click', '.cookies-notify__detail_button', function(){
1340  var detail_box_selector = $('.cookies-notify__detail_box');
1341  var arrow_selector = $('#cookies-notify__detail_button_arrow');
1342  if(detail_box_selector.is(':visible'))
1343  {
1344    detail_box_selector.addClass('hidden');
1345    arrow_selector.html('<i class="fa fa-chevron-down"></i>');
1346  }
1347  else
1348  {
1349    detail_box_selector.removeClass('hidden');
1350    arrow_selector.html('<i class="fa fa-chevron-up"></i>');
1351  }
1352});
1353
1354$(document).on('click', '.cookies-notify__cookie_type', function(){
1355  var type = $(this).data('type');
1356  var table_selector = $("#cookies-notify__cookie_detail_table tbody");
1357  $(".cookie-active").removeClass('cookie-active');
1358  $(this).addClass('cookie-active');
1359  $.ajax( $.extend(true, {}, BS.Request.$default, {
1360      data: {
1361          action: "Cookies_notify",
1362          params: {
1363              request_type: 'cookie_list',
1364              type: type,
1365          },
1366      },
1367      success: function(response) {
1368          table_selector.empty();
1369          $(".cookie_description_active").removeClass('cookie_description_active').addClass('hidden');
1370          $("#cookie-notify__description_" + type).addClass('cookie_description_active').removeClass('hidden');
1371          $(".cookie-notify__cookie_description").html(response.data.description);
1372          delete response.data.description;
1373          $.each(response.data, function(i, item){
1374            table_selector.append("<tr>" +
1375                "<td>" + item.name + "</td>" +
1376                "<td>" + item.description + "</td>" +
1377                "<td>" + item.expires + "</td>");
1378          });
1379
1380      }
1381  }));
1382});
1383$(document).on('click', '#cookies-nofify__close_detail, #cookies-notify__detail-close', function(){
1384  $('.cookies-notify__detail_box').addClass('hidden');
1385});
1386
1387document.addEventListener("DOMContentLoaded", function(){
1388  BS.multiples.ifNotISpinner();
1389
1390  (function() {
1391    "use strict";
1392
1393    var picker = document.getElementById('gift_picker'),
1394        form = document.getElementById('gift_picker_form'), 
1395        gift_lists,
1396        selected_gift;
1397    if(!picker) return;
1398    gift_lists = picker.querySelectorAll('.gift-picker__list');
1399
1400    // Palladium ponechava uz vybrane darky v nabidce, opakovany klik by skoncil chybou
1401    var keep_selected = !!(window.BS && BS.Design && BS.Design.template
1402      && BS.Design.template.is_selected('palladium'));
1403
1404    var selectGift = function(item, gift) {
1405      var id_input = form.querySelector('input[name="gift[id]"]');
1406      var type_input = form.querySelector('input[name="gift[type]"]');
1407      item.classList.add('gift-picker__item--selected');
1408      if(id_input && type_input) {
1409        id_input.value = gift.id;
1410        type_input.value = gift.type;
1411        selected_gift = gift;
1412
1413        var radio = item.querySelector('.gift-picker__check');
1414        if(radio) {
1415          radio.checked = true;
1416        }
1417        form.requestSubmit();
1418      }
1419    };
1420
1421    var selectHandler = function(e) {
1422      var gift,
1423          item = e.target.closest('.gift-picker__item');
1424      if(!item) return;
1425      if(keep_selected && item.classList.contains('gift-picker__item--selected')) return;
1426
1427      try {
1428        gift = item && JSON.parse(item.dataset.gift);
1429      } catch(err) {
1430        console.error(err);
1431        gift = null;
1432      }
1433
1434      if(gift) {
1435        selectGift(item, gift);
1436      }
1437    }
1438
1439    $(gift_lists).on('click', ':not(.gift-picker__link)', selectHandler);
1440    form.addEventListener('submit', function(e) {
1441      if(!selected_gift) {
1442        e.preventDefault();
1443        return;
1444      }
1445    });
1446
1447    if($.fn.owlCarousel) {
1448      var items_xs = gift_lists.length
1449        ? parseInt(window.getComputedStyle(gift_lists[0]).getPropertyValue('--gift-items-xs'), 10) || 1
1450        : 1;
1451      var syncWidth = function() {
1452        var $list = $(this), width = $list.width(), owl = $list.data('owl.carousel');
1453        if(owl && $list.data('measured-width') !== width) {
1454          $list.data('measured-width', width);
1455          owl.invalidate('width');
1456          owl.refresh();
1457        }
1458      };
1459      $(gift_lists).on('refreshed.owl.carousel', syncWidth);
1460      $(gift_lists).owlCarousel({
1461        loop:false,
1462        lazyLoad: false,
1463        margin:16,
1464        nav:true,
1465        onLoadLazy: true,
1466        responsive:{
1467            0:{
1468                items: 1
1469            },
1470            300:{
1471                items: items_xs
1472            },
1473            480:{
1474                items: 2
1475            },
1476            960:{
1477                items: 3
1478            },
1479            1230:{
1480                items: 6
1481            }
1482        }
1483      });
1484      $(gift_lists).each(syncWidth);
1485    }
1486  })();
1487
1488  (function() {
1489    "use strict";
1490
1491    const widgets = new WeakMap();
1492    const popupEl = document.getElementById('wishlist_popup');
1493    let api, popup;
1494
1495    class WishlistApi {
1496      addProduct(data) {
1497        return new Promise(function(resolve, reject) {
1498          const request = BS.extend(BS.Request.$default, {
1499            data: {
1500              action: "Wishlist\\Controller",
1501              id_zakaznik: BS.User.id,
1502              params: {
1503                action: 'add_product',
1504                data: data
1505              },
1506            },
1507            success: function(response) {
1508              if(response.success) {
1509                resolve({
1510                  response: response.data,
1511                  data,
1512                });
1513              } else {
1514                reject(new Error(response.error || WA.Translation._wishlist_save_error));
1515              }
1516            },
1517            error: function(xhr, status, error) {
1518              reject(new Error(error || WA.Translation._wishlist_save_error));
1519            }
1520          });
1521          $.ajax(request);
1522        });
1523      }
1524
1525      removeProduct(data) {
1526        return new Promise(function(resolve, reject) {
1527          const request = BS.extend(BS.Request.$default, {
1528            data: {
1529              action: "Wishlist\\Controller",
1530              id_zakaznik: BS.User.id,
1531              params: {
1532                action: 'remove_product',
1533                data: data
1534              },
1535            },
1536            success: function(response) {
1537              if(response.success) {
1538                resolve({
1539                  response: response.data,
1540                  data,
1541                });
1542              } else {
1543                reject(new Error(response.error || WA.Translation._wishlist_save_error));
1544              }
1545            },
1546            error: function(xhr, status, error) {
1547              reject(new Error(error || WA.Translation._wishlist_save_error));
1548            }
1549          });
1550          $.ajax(request);
1551        });
1552      }
1553
1554      getProductWishlists(product) {
1555        return new Promise((resolve, reject) => {
1556          const request = BS.extend(BS.Request.$default, {
1557            data: {
1558              action: "Wishlist\\Controller",
1559              id_zakaznik: BS.User.id,
1560              params: {
1561                action: 'get_product_wishlists',
1562                data: product
1563              },
1564            },
1565            success: function(response) {
1566              if(response.success) {
1567                resolve({
1568                  response: response.data,
1569                  product,
1570                });
1571              } else {
1572                reject(new Error(response.error || WA.Translation._wishlist_save_error));
1573              }
1574            },
1575            error: function(xhr, status, error) {
1576              reject(new Error(error || WA.Translation._wishlist_save_error));
1577            },
1578          });
1579          $.ajax(request);
1580        });
1581      }
1582    }
1583
1584    class WishlistPopup {
1585      messageTimer = null;
1586      enabled = false;
1587
1588      constructor(popup, api) {
1589        this.popup = popup;
1590        this.widget = null;
1591        this.api = api;
1592        this.init();
1593      }
1594
1595      init() {
1596        this.enabled = !this.popup.dataset.hasOwnProperty('wishlistDisabled');
1597        if(this.enabled) {
1598          const form = this.popup.querySelector('form');
1599          form.addEventListener('submit', this.onSubmitHandler.bind(this));
1600          const list = this.popup.querySelector('.wishlists');
1601          list.addEventListener('change', this.onWishlistChange.bind(this));
1602          this.list = list;
1603          this.popup.querySelector('.wishlist-popup__new').addEventListener('click', this.showNameInput.bind(this));
1604        }
1605        //outside click
1606        document.addEventListener('click', this.onDocumentClick.bind(this));
1607      }
1608
1609      onDocumentClick(e) {
1610        if(!this.popup || !this.popup.classList.contains('wishlist-popup--show')) {
1611          return;
1612        }
1613
1614        const target = e.target;
1615        if(!this.popup.contains(target) && !this.widget.button.contains(target)) {
1616          this.popup.classList.remove('wishlist-popup--show');
1617          if(this.enabled) {
1618            this.resetControls();
1619          }
1620          this.widget = null;
1621        }
1622      }
1623
1624      onWishlistChange(e) {
1625        const checkbox = e.target;
1626        const wishlist = checkbox.closest('[data-wishlist]');
1627        const idWishlist = parseInt(wishlist.dataset.wishlist);
1628        if(checkbox.checked) {
1629          this.api.addProduct(this.mergeSaveData({ id_wishlist: idWishlist }))
1630          .then(this.onAddSuccess.bind(this, null))
1631          .catch(this.onSaveError.bind(this))
1632          ;
1633        } else {
1634          this.api.removeProduct(this.mergeSaveData({ id_wishlist: idWishlist }))
1635          .then(this.onRemoveSuccess.bind(this))
1636          .catch(this.onSaveError.bind(this))
1637          ;
1638        }
1639      }
1640
1641      onSubmitHandler(e) {
1642        e.preventDefault();
1643        const name = this.getNameInput().value.trim();
1644        if(name === '') {
1645          return;
1646        }
1647
1648        this.api.addProduct(this.mergeSaveData({ name }))
1649        .then(this.onAddSuccess.bind(this, name))
1650        .catch(this.onSaveError.bind(this))
1651        ;
1652      }
1653
1654      showNameInput() {
1655        this.resetNameInput();
1656        this.toggleNameControls(false);
1657      }
1658
1659      getNameInput() {
1660        return this.popup.querySelector('input[name="wishlist_name"]');
1661      }
1662
1663      resetNameInput() {
1664        const nameInput = this.getNameInput();
1665        if(nameInput) {
1666          nameInput.value = '';
1667        }
1668      }
1669
1670      toggleNameControls(btnVisible = true) {
1671        const newBtn = this.popup.querySelector('.wishlist-popup__new');
1672        const nameInput = this.popup.querySelector('.wishlist-popup__name');
1673        if(btnVisible) {
1674          newBtn.style.display = '';
1675          nameInput.style.display = 'none';
1676        } else {
1677          newBtn.style.display = 'none';
1678          nameInput.style.display = '';
1679        }
1680      }
1681
1682      resetControls() {
1683        this.toggleNameControls(true);
1684        this.resetNameInput();
1685      }
1686
1687      mergeSaveData(data) {
1688        const wishlistData = this.widget.data;
1689
1690        return Object.assign({}, data, {
1691          id_product: wishlistData.id_product,
1692          id_variant: wishlistData.id_variant,
1693        });
1694      }
1695
1696      onAddSuccess(name, { response }) {
1697        if(response.created) {
1698          BS.Fce.call_conversion_request('add_to_wishlist', {
1699            product_id: this.widget.data.id_product,
1700            variant_id: this.widget.data.id_variant,
1701            count: 1
1702          });
1703        }
1704        const wishlists = this.widget.data.wishlists;
1705        const index = wishlists.indexOf(response.id_wishlist);
1706        if(index === -1) {
1707          wishlists.push(response.id_wishlist)
1708          if(name) {
1709            const wishlistRow = this.getWishlistRow(response.id_wishlist);
1710            if(wishlistRow) {
1711              const checkbox = wishlistRow.querySelector('input[type="checkbox"]');
1712              if(checkbox) {
1713                checkbox.checked = true;
1714              }
1715            } else {
1716              this.addItemToList(name, response.id_wishlist);
1717            }
1718          }
1719        }
1720        this.resetControls();
1721        this.widget.onChange();
1722      }
1723      
1724      getWishlistRow(id) {
1725        return this.popup.querySelector(`[data-wishlist="${id}"]`);
1726      }
1727
1728      addItemToList(name, id) {
1729        const template = this.list.dataset.wishlistTemplate;
1730        this.list.insertAdjacentHTML('beforeend', template.replace('__name__', name).replace('__id__', id));
1731      }
1732
1733      onRemoveSuccess({ data }) {
1734        const wishlists = this.widget.data.wishlists;
1735        const index = wishlists.indexOf(data.id_wishlist);
1736        if(index !== -1) {
1737          wishlists.splice(index, 1);
1738        }
1739        this.widget.onChange();
1740      }
1741
1742      onSaveError(error) {
1743        console.error(error);
1744      }
1745
1746      show(widget) {
1747        if(this.widget === widget) {
1748          return;
1749        }
1750
1751        this.widget = widget;
1752        if(this.enabled) {
1753          this.resetControls();
1754          this.updateList(widget);
1755        }
1756
1757        const arrowEl = this.popup.querySelector('.wishlist-popup__arrow');
1758        this.popup.classList.add('wishlist-popup--show');
1759        window.FloatingUIDOM.computePosition(widget.button, this.popup, {
1760          placement: 'bottom-center',
1761          middleware: [
1762            window.FloatingUIDOM.offset({
1763              mainAxis: 10, // 10px offset from the button
1764              crossAxis: 0, // no offset on the cross axis
1765            }),
1766            window.FloatingUIDOM.autoPlacement(),
1767            window.FloatingUIDOM.arrow({ element: arrowEl, padding: 10 }),
1768          ],
1769        }).then(({ x, y, middlewareData, placement }) => {
1770          Object.assign(this.popup.style, {
1771              left: `${x}px`,
1772              top: `${y}px`,
1773          });
1774
1775          const arrowPlacementClass = `wishlist-popup__arrow--${placement.split('-')[0]}`;
1776          arrowEl.className = `wishlist-popup__arrow ${arrowPlacementClass}`;
1777
1778          if (middlewareData.arrow) {
1779            const {x : arrowX, y : arrowY} = middlewareData.arrow;
1780            Object.assign(arrowEl.style, {
1781              left: arrowX != null ? `${arrowX}px` : '',
1782              top: arrowY != null ? `${arrowY}px` : '',
1783            });
1784          }
1785        });
1786      }
1787
1788      updateList(widget) {
1789        this.list.innerHTML = '';
1790        this.popup.classList.add('wishlist-popup--loading');
1791        this.api.getProductWishlists(widget.data)
1792        .then(({ response }) => {
1793          this.widget.data.wishlists = response.wishlists.filter(w =>
1793 w.active).map(w => w.id);
1794          this.list.insertAdjacentHTML('afterbegin', response.html);
1795        })
1796        .catch(err => {
1797          console.error(err);
1798          this.showErrorMessage();
1799        })
1800        .finally(() => {
1801          this.popup.classList.remove('wishlist-popup--loading');
1802        })
1803        ;
1804      }
1805    }
1806
1807    class WishlistWidget {
1808      constructor(button, popup, api) {
1809        this.button = button;
1810        this.popup = popup;
1811        this.init();
1812      }
1813
1814      init() {
1815        const button = this.button;
1816        button.addEventListener('click', this.showPopup.bind(this));
1817        this.data = JSON.parse(button.dataset.wishlist || '{}');
1818      }
1819
1820      showPopup(event) {
1821        event.preventDefault();
1822        event.stopPropagation();
1823        this.popup.show(this);
1824      }
1825
1826      onChange() {
1827        const isEmpty = this.data.wishlists.length === 0;
1828        if(isEmpty) {
1829          this.button.classList.remove('wishlist-button--fill');
1830        } else {
1831          this.button.classList.add('wishlist-button--fill');
1832        }
1833        this.updateIcon(!isEmpty);
1834      }
1835
1836      updateIcon(fill) {
1837        const property = `icon${fill ? 'Solid' : 'Empty'}`;
1838        this.button.querySelector('.wishlist-button__icon').innerHTML = this.button.dataset[property];
1839      }
1840    }
1841
1842    var initWishlistButtons = function(popup) {
1843      const buttons = document.querySelectorAll('.wishlist-button');
1844      for(const button of buttons) {
1845        if(!button || widgets.has(button)) continue;
1846        widgets.set(button, new WishlistWidget(button, popup));
1847      }
1848    };
1849
1850    if(popupEl) {
1851      api = new WishlistApi();
1852      popup = new WishlistPopup(popupEl, api);
1853      initWishlistButtons(popup);
1854    }
1855
1856    BS.Wishlist = {
1857      initButtons: function() {
1858        if(popup) {
1859          initWishlistButtons(popup);
1860        }
1861      }
1862    };
1863  })();
1864
1865  // Watchdog button in productList (product variants table on detail page) — Palladium only
1866  document.addEventListener('click', function(e) {
1867    var btn = e.target.closest('.watchdog-productlist-btn[data-watchdog-product-id]');
1868    if (!btn) return;
1869    e.preventDefault();
1870    var form = document.getElementById('watch_dog_form');
1871    if (form) {
1872      var idProductInput = form.querySelector('input[name="id_product"]');
1873      var isVariantInput = form.querySelector('input[name="is_variant"]');
1874      var productUrlInput = form.querySelector('input[name="product_url"]');
1875      var priceInput = form.querySelector('input[name="price_value"]');
1876      if (idProductInput) idProductInput.value = btn.dataset.watchdogProductId;
1877      if (isVariantInput) isVariantInput.value = btn.dataset.watchdogIsVariant;
1878      if (productUrlInput) productUrlInput.value = btn.dataset.watchdogProductUrl;
1879      if (priceInput && btn.dataset.watchdogPrice) priceInput.value = btn.dataset.watchdogPrice;
1880    }
1881    var trigger = document.getElementById('open_watch_dog');
1882    if (trigger) trigger.click();
1883  });
1884
1885  (function(BS, document) {
1886    "use strict";
1887
1888    const wishlistPageApp = document.getElementById('wishlist-page');
1889    if(!wishlistPageApp) return;
1890
1891    const addListModal = document.getElementById('wishlist_create_modal');
1892    const confirmModal = document.getElementById('wishlist_confirm_modal');
1893    let confirmAction = null;
1894    const tabs = wishlistPageApp.querySelector('.tabs');
1895    let tabInstance = null;
1896    if(tabs) {
1897      tabInstance = new BS.Tab(wishlistPageApp.querySelector('.tabs'));
1898    }
1899
1900    const addToBasket = event => {
1901      const form = event.target;
1902      const basketVersion = BS.Basket.variant();
1903      switch(basketVersion) {
1904        case 2:
1905        case 3:
1906          event.preventDefault();
1907          buy_event($(form), 1);
1908          break;
1909        case 4:
1910          event.preventDefault();
1911          run_basket_fuctionality(form);
1912          break;
1913        case 6:
1914          event.preventDefault();
1915          break;
1916      }
1917    };
1918
1919    const confirmHandler = e => {
1920      if(confirmAction) {
1921        confirmAction(e);
1922      }
1923    };
1924
1925    const cancelHanlder = e => {
1926      $.magnificPopup.close();
1927    };
1928
1929    const confirm = (message, onConfirm) => {
1930      confirmModal.querySelector('[data-wishlist-confirm-message]').innerHTML = message;
1931      confirmAction = onConfirm;
1932      $.magnificPopup.open({
1933        items: {
1934          src: $(confirmModal)
1935        },
1936        modal: true,
1937        closeOnBgClick: true,
1938        showCloseBtn: true,
1939        callbacks: {
1940          close: () => {
1941            confirmAction = null;
1942          },
1943        }
1944      });
1945    };
1946
1947    const showNoListMessage = () => {
1948      wishlistPageApp.insertAdjacentHTML('beforeend', wishlistPageApp.dataset.wishlistTemplateNoList);
1949    };
1950
1951    const hideDialog = () => {
1952      $.magnificPopup.close();
1953    };
1954
1955    const removeList = btn => {
1956      const listId = btn.dataset.wishlistRemove;
1957      const request = BS.extend(BS.Request.$default, {
1958        data: {
1959          action: "Wishlist\\Controller",
1960          id_zakaznik: BS.User.id,
1961          params: {
1962            action: 'remove_list',
1963            data: {
1964              id: listId,
1965            }
1966          },
1967        },
1968        success: function(response) {
1969          if(response.success) {
1970            const navItem = btn.closest('.nav-item');
1971            if(navItem) {
1972              navItem.remove();
1973            }
1974
1975            const tabPane = wishlistPageApp.querySelector(`[data-wishlist-id="${listId}"]`);
1976            if(tabPane) {
1977              tabPane.remove();
1978            }
1979
1980            if(wishlistPageApp.querySelectorAll('[data-wishlist-id]').length > 0) {
1981              //pokud neni zadna zalozka aktivni, zvolime prvni
1982              if(!tabs.querySelector('.nav-item.active')) {
1983                const firstTab = wishlistPageApp.querySelector('.nav-item');
1984                if(firstTab) {
1985                  tabInstance.show(firstTab.querySelector('.nav-link'));
1986                }
1987              }
1988            } else {
1989              showNoListMessage();
1990            }
1991            hideDialog();
1992          }
1993        },
1994        error: function(xhr, status, error) {
1995          console.error("Error removing wishlist:", error);
1996          hideDialog();
1997        }
1998      });
1999      $.ajax(request);
2000    };
2001
2002    const removeItem = btn => {
2003      const itemId = btn.dataset.wishlistRemoveItem;
2004      const request = BS.extend(BS.Request.$default, {
2005        data: {
2006          action: "Wishlist\\Controller",
2007          id_zakaznik: BS.User.id,
2008          params: {
2009            action: 'remove_product',
2010            data: {
2011              id: itemId,
2012              return_html: true,
2013            }
2014          },
2015        },
2016        success: function(response) {
2017          if(response.success) {
2018            const row = btn.closest('.wishlist-product');
2019            const tabPane = btn.closest('.tab-pane'); 
2020            if(row) {
2021              row.remove();
2022            }
2023
2024            if(tabPane.querySelectorAll('.wishlist-product').length > 0) {
2025              const totalPriceEl = tabPane.querySelector('.wishlist-total-price');
2026              totalPriceEl.innerHTML = response.data.total_price_formatted;
2027            } else {
2028              tabPane.innerHTML = wishlistPageApp.dataset.wishlistTemplateNoItem;
2029            }
2030          }
2031        },
2032        error: function(xhr, status, error) {
2033          console.error("Error removing wishlist item:", error);
2034        }
2035      });
2036      $.ajax(request);
2037    };
2038
2039    const showAddListModal = () => {
2040      $.magnificPopup.open({
2041        items: {
2042          src: $(addListModal)
2043        },
2044        modal: false,
2045        closeOnContentClick: false,
2046        closeOnBgClick: true,
2047        closeBtnInside: false,
2048        showCloseBtn: false,
2049      });
2050    };
2051
2052    const validateAddListForm = e => {
2053      const form = e.target;
2054      const nameField = form.querySelector('input[name="wishlist[name]"]');
2055      if(!nameField) {
2056        e.preventDefault();
2057        return;
2058      }
2059
2060      const name = nameField.value.trim();
2061      if(name === '') {
2062        e.preventDefault();
2063        return;
2064      }
2065    };
2066
2067    const addAllItemsToBasket = async (e, btn) => {
2068      const list = btn.closest('[data-wishlist-id]');
2069      if(!list) return;
2070      const rows = list.querySelectorAll('[data-wishlist-row]');
2071      var requestData = new FormData();
2072      for(const [index, row] of rows.entries()) {
2073        const rowForm = new FormData(row);
2074        const buyBtn = row.querySelector('[data-wishlist-buy-item]');
2075        const variantId = rowForm.get('variant_selected');
2076        requestData.append(`items[${index}][item]`, buyBtn.dataset.id);
2077        requestData.append(`items[${index}][item_variant]`, variantId);
2078        requestData.append(`items[${index}][variant_selected]`, variantId);
2079        requestData.append(`items[${index}][kusy]`, rowForm.get('kusy'));
2080      }
2081
2082      try {
2083        const response = await fetch(`/wa_script/basket_ajax.php?method=add&bulk=1&from_wishlist=1&id=${BS.User.id}`, {
2084          method: 'POST',
2085          body: requestData,
2086        });
2087        if(!response.ok) {
2088          throw new Error(`HTTP error! status: ${response.status}`);
2089        }
2090
2091        const responseData = await response.json();
2092        if(responseData.basket_url) {
2093          window.location.href = responseData.basket_url;
2094        }
2095      } catch(err) {
2096        console.error("Error preparing request data:", err);
2097      }
2098    };
2099
2100    const nav = wishlistPageApp.querySelector('.nav-tabs');
2101    if(nav) {
2102      nav.addEventListener('click', e => {
2103        const removeBtn = e.target.closest('[data-wishlist-remove]');
2104        if(!removeBtn) return;
2105
2106        confirm(WA.Translation._wishlist_remove_confirm, () => {
2107          removeList(e.target);
2108        });
2109      });
2110    }
2111
2112    if(tabs) {
2113      tabs.addEventListener('click', e => {
2114        const removeBtn = e.target.closest('[data-wishlist-remove-item]');
2115        if(removeBtn) {
2116          removeItem(removeBtn);
2117        }
2118      });
2119    }
2120    wishlistPageApp.querySelector('[data-wishlist-add]').addEventListener('click', showAddListModal);
2121    addListModal.querySelector('[data-wishlist-add-form]').addEventListener('submit', validateAddListForm);
2122    confirmModal.querySelector('[data-wishlist-confirm]').addEventListener('click', confirmHandler);
2123    confirmModal.querySelector('[data-wishlist-cancel]').addEventListener('click', cancelHanlder);
2124    wishlistPageApp.addEventListener('submit', addToBasket);
2125    wishlistPageApp.addEventListener('click', e => {
2126      const btn = e.target.closest('[data-wishlist-buy-all]');
2127      if(btn) {
2128        addAllItemsToBasket(e, btn);
2129      }
2130    });
2131    wishlistPageApp.addEventListener('click', e => {
2132      const btn = e.target.closest('[data-watchdog-product-id]');
2133      if(!btn) return;
2134      e.preventDefault();
2135      const form = document.getElementById('watch_dog_form');
2136      if(form) {
2137        const idProductInput = form.querySelector('input[name="id_product"]');
2138        const isVariantInput = form.querySelector('input[name="is_variant"]');
2139        const productUrlInput = form.querySelector('input[name="product_url"]');
2140        if(idProductInput) idProductInput.value = btn.dataset.watchdogProductId;
2141        if(isVariantInput) isVariantInput.value = btn.dataset.watchdogIsVariant;
2142        if(productUrlInput) productUrlInput.value = btn.dataset.watchdogProductUrl;
2143      }
2144      const trigger = document.getElementById('open_watch_dog');
2145      if(trigger) trigger.click();
2146    });
2147  }).apply(this, [BS, document]);
2148});
2149
2150document.addEventListener('DOMContentLoaded', () => {
2151  const input = document.querySelector('#search input#q');
2152  if (!input) return;
2153
2154  const words = (typeof WA_SEARCH_PLACEHOLDERS !== 'undefined' && Array.isArray(WA_SEARCH_PLACEHOLDERS) && WA_SEARCH_PLACEHOLDERS.length > 0)
2155    ? WA_SEARCH_PLACEHOLDERS
2156    : null;
2157
2158  if (!words) return;
2159
2160  const typingSpeed = 80;
2161  const deletingSpeed = 50;
2162  const pauseAfterType = 1200;
2163
2164  let wordIndex = 0;
2165  let charIndex = 0;
2166  let isDeleting = false;
2167
2168  function animatePlaceholder() {
2169    // pokud je input aktivní nebo obsahuje text, animaci stopni
2170    if (document.activeElement === input || input.value.length) {
2171      setTimeout(animatePlaceholder, 300);
2172      return;
2173    }
2174
2175    const word = words[wordIndex];
2176
2177    if (!isDeleting) {
2178      charIndex++;
2179      input.placeholder = word.slice(0, charIndex);
2180
2181      if (charIndex === word.length) {
2182        setTimeout(() => isDeleting = true, pauseAfterType);
2183      }
2184    } else {
2185      charIndex--;
2186      input.placeholder = word.slice(0, charIndex);
2187
2188      if (charIndex === 0) {
2189        isDeleting = false;
2190        wordIndex = (wordIndex + 1) % words.length;
2191      }
2192    }
2193
2194    setTimeout(
2195        animatePlaceholder,
2196        isDeleting ? deletingSpeed : typingSpeed
2197    );
2198  }
2199
2200  animatePlaceholder();
2201});

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.