PageSourceSearch

https://distribucionmayorista.online/themes/warehousechild/assets/js/custom.js

js distribucionmayorista.online collected 2026-10-04 13:26:52 UTC 86,039 bytes, 2,666 lines download raw bytes

1/*
2 * Custom code goes here.
3 * A template should always ship with an empty custom.js
4 */
5
6// notificación -> función addNotification do módulo mailalerts
7function addNotification() {
8  var ids = $("div.js-mailalert  input[type=hidden]");
9
10  $.ajax({
11    type: "POST",
12    url: $("div.js-mailalert").data("url"),
13    data:
14      "id_product=" +
15      ids[0].value +
16      "&id_product_attribute=" +
17      ids[1].value +
18      "&customer_email=" +
19      $("div.js-mailalert  input[type=email]").val(),
20    success: function (resp) {
21      resp = JSON.parse(resp);
22
23      $("div.js-mailalert  span.js-mailalert-response")
24        .html(resp.message)
25        .show();
26      if (!resp.error) {
27        $("div.js-mailalert  a").hide();
28        $("div.js-mailalert  input[type=email]").hide();
29      }
30    },
31  });
32  return false;
33}
34
35$(function () {
36  // span data location
37  $("span[data-loc]").click(function () {
38    var dataLoc = $(this).attr("data-loc");
39    var dataLoc = atob(dataLoc);
40    window.location = dataLoc;
41  });
42
43  // notificacións
44  let $body = $("body");
45  let $productDiv = $("#product");
46
47  $body.on("click", ".js-availabilitynotification", function (event) {
48    let elm = $(event.target).closest(".js-product-miniature");
49    prestashop.emit("clickAvailabilityNotification", {
50      miniature: elm,
51      dataset: elm.data(),
52    });
53    event.preventDefault();
54  });
55
56  prestashop.on("clickAvailabilityNotification", function (elm) {
57    let data = {
58      action: "availabilitynotification",
59      id_product: elm.dataset.idProduct,
60      id_product_attribute: elm.dataset.idProductAttribute,
61    };
62
63    let prevProductMinature = elm.miniature
64      .parent()
65      .prev()
66      .children(".js-product-miniature")
67      .first();
68    let nextProductMinature = elm.miniature
69      .parent()
70      .next()
71      .children(".js-product-miniature")
72      .first();
73
74    $.post(prestashop.urls.pages.product, data, null, "json")
75      .then(function (resp) {
76        let $notificationModal = $(".modal.availabilitynotification").first();
77        if ($notificationModal.length) {
78          showAvailabilityNotificationModal(
79            $body,
80            resp,
81            prevProductMinature,
82            nextProductMinature,
83            $notificationModal,
84          );
85        } else {
86          showAvailabilityNotificationModal(
87            $body,
88            resp,
89            prevProductMinature,
90            nextProductMinature,
91            false,
92          );
93        }
94      })
95      .fail((resp) => {
96        prestashop.emit("handleError", {
97          eventType: "clickAvailabilityNotification",
98          resp: resp,
99        });
100      });
101  });
102
103  var showAvailabilityNotificationModal = (
104    $body,
105    resp,
106    prevProductMinature,
107    nextProductMinature,
108    $oldModal,
109  ) => {
110    var availabilityNotificationAfterShown = (productModal) => {
111      $productCover = productModal.find("#product-images-large");
112
113      new Swiper($productCover[0], {
114        loop: false,
115        effect: "fade",
116        preloadImages: false,
117        lazy: {
118          loadPrevNext: true,
119        },
120        navigation: {
121          nextEl: ".swiper-button-next",
122          prevEl: ".swiper-button-prev",
123        },
124      });
125
126      if (iqitTheme.pp_zoom == "inner") {
127        let $easyzoom = productModal.find(".easyzoom-product").easyZoom();
128      } else {
129        productModal.find(".js-easyzoom-trigger").on("click", (event) => {
130          event.preventDefault();
131        });
132      }
133
134      $(".modal-backdrop.show").first().addClass("backdrop-second");
135
136      prestashop.emit("availabilityNotificationShown", {
137        modal: productModal,
138      });
139    };
140
141    if (!$oldModal) {
142      $body.append(resp.availabilitynotification_html);
143    } else {
144      $oldModal
145        .find("#availabilitynotification-modal-product-content")
146        .replaceWith(
147          $(resp.availabilitynotification_html).find(
148            "#availabilitynotification-modal-product-content",
149          ),
150        );
151    }
152
153    let productModal = $(`#availabilitynotification-modal`);
154    let $prevAvailabilityNotificationBtn = $(
155      "#js-availabilitynotification-prev-btn",
156    );
157    let $nextAvailabilityNotificationBtn = $(
158      "#js-availabilitynotification-next-btn",
159    );
160
161    if (!prevProductMinature.length) {
162      $prevAvailabilityNotificationBtn.hide();
163    }
164    if (!nextProductMinature.length) {
165      $nextAvailabilityNotificationBtn.hide();
166    }
167
168    $prevAvailabilityNotificationBtn.on("click", function (event) {
169      let elm = prevProductMinature;
170      prestashop.emit("clickAvailabilityNotification", {
171        miniature: elm,
172        dataset: elm.data(),
173      });
174      event.preventDefault();
175    });
176
177    $nextAvailabilityNotificationBtn.on("click", function (event) {
178      let elm = nextProductMinature;
179      prestashop.emit("clickAvailabilityNotification", {
180        miniature: elm,
181        dataset: elm.data(),
182      });
183      event.preventDefault();
184    });
185
186    if (!$oldModal) {
187      productModal.modal("show");
188      productModal.on("shown.bs.modal", function () {
189        availabilityNotificationAfterShown(productModal);
190      });
191      productModal.on("hide.bs.modal", function () {
192        productModal.remove();
193        $("#iqitsizecharts-modal").remove();
194      });
195    } else {
196      availabilityNotificationAfterShown(productModal);
197    }
198
199    let sizeChartModal = $("#iqitsizecharts-modal");
200    let $productCover;
201
202    productModal.find("#quantity_wanted").TouchSpin({
203      verticalbuttons: true,
204      verticalupclass: "fa fa-angle-up touchspin-up",
205      verticaldownclass: "fa fa-angle-down touchspin-down",
206      buttondown_class: "btn btn-touchspin js-touchspin",
207      buttonup_class: "btn btn-touchspin js-touchspin",
208      min: 1,
209      max: 1000000,
210    });
211
212    sizeChartModal.on("show.bs.modal", function () {
213      sizeChartModal.detach();
214      sizeChartModal.appendTo("body");
215      $(this).addClass("fv-modal-stack");
216      productModal.addClass("availabilitynotification-second-modal");
217    });
218  };
219
220  // fin notificacións
221
222  prestashop.on("updatedCart", function (event) {
223    if (event.resp.allRequired != "undefined") {
224      if (event.resp.allRequired == 0) {
225        $(".checkout.cart-detailed-actions.card-body div a").addClass(
226          "disabled",
227        );
228      } else {
229        $(".checkout.cart-detailed-actions.card-body div a").removeClass(
230          "disabled",
231        );
232      }
233    }
234    if (event.resp.productQuantities != "undefined") {
235      var productQuantities = event.resp.productQuantities;
236      var elemento = "";
237      for (indice in event.resp.productQuantities) {
238        elemento = $(
239          '[data-product-id="' +
240            productQuantities[indice].id_product +
241            '"][data-id-product-attribute="' +
242            productQuantities[indice].id_product_attribute +
243            '"]',
244        );
245        if (elemento.val() > productQuantities[indice].max_quantity) {
246          elemento.val(productQuantities[indice].max_quantity);
247
248          var eventData = {
249            eventType: "updateCart",
250            reason: {
251              idProductAttribute:
252                productQuantities[indice].id_product_attribute,
253              productId: productQuantities[indice].id_product,
254              downUrl: elemento.data("down-url"),
255              upUrl: elemento.data("up-url"),
256              updateUrl: elemento.data("update-url"),
257            },
258          };
259          prestashop.emit("updateCart", eventData);
260        }
261      }
262    }
263  });
264
265  // Novo buscador
266  let initAutocompleteDistr = (
267    $searchWidgetDistr,
268    $searchBoxDistr,
269    searchURLDistr,
270  ) => {
271    let xhr;
272    // let resultsPerPage = 100000;
273    let resultsPerPage = 15;
274    let allText = $searchBoxDistr.data("all-text");
275    let productText = $searchBoxDistr.data("product-text");
276
277    let iqitSearchAutocompleteDistr = $searchBoxDistr.autoCompleteDistr({
278      minChars: 2,
279      cache: false,
280      source: function (query, response) {
281        try {
282          xhr.abort();
283        } catch (e) {}
284        xhr = $.post(
285          searchURLDistr,
286          {
287            s: query,
288            resultsPerPage: resultsPerPage,
289            ajax: true,
290          },
291          null,
292          "json",
293        )
294          .then(function (resp) {
295            let renderProducts = [
296              { view: resp.rendered_products_ajax, type: "list" },
297            ];
298
299            let showAll = { type: "all" };
300            if (resp.products.length >= resultsPerPage) {
301              renderProducts.push(showAll);
302            }
303
304            response(renderProducts);
305            // response(resp.rendered_products_ajax);
306          })
307          .fail(response);
308      },
309      renderItem: function (rendered_products_ajax, search) {
310        if (rendered_products_ajax.type == "all") {
311          return (
312            '<div class="row btn-all">' +
313            '<div class="autocomplete-suggestion autocomplete-suggestion-show-all dropdown-item" data-type="all" data-val="' +
314            search +
315            '">' +
316            '<div class="row no-gutters align-items-center">' +
317            '<div class="col"><span class="name">' +
318            allText +
319            ' <i class="fa fa-angle-right" aria-hidden="true"></i></span></div>' +
320            "</div>" +
321            "</div>" +
322            "</div>"
323          );
324        } else {
325          return rendered_products_ajax.view;
326        }
327
328        // return rendered_products_ajax;
329      },
330      onSelect: function (e, term, item) {
331        if (item.data("type") == "all") {
332          $searchWidgetDistr.find("form").first().submit();
333        } else {
334          window.location.href = item.data("url");
335        }
336      },
337    });
338  };
339
340  // antigo buscador
341  let initAutocomplete = ($searchWidget, $searchBox, searchURL) => {
342    let xhr;
343    let resultsPerPage = 10;
344    let allText = $searchBox.data("all-text");
345    let brandsText = $searchBox.data("brands-text");
346    let productText = $searchBox.data("product-text");
347    let blogText = $searchBox.data("blog-text");
348
349    let iqitSearchAutocomplete = $searchBox.autoComplete({
350      minChars: 2,
351      cache: false,
352      source: function (query, response) {
353        try {
354          xhr.abort();
355        } catch (e) {}
356        xhr = $.post(
357          searchURL,
358          {
359            s: query,
360            resultsPerPage: resultsPerPage,
361            ajax: true,
362          },
363          null,
364          "json",
365        )
366          .then(function (resp) {
367            if (Object.keys(resp.brands).length) {
368              let brands = { type: "brands", results: resp.brands };
369              resp.products.push(brands);
370            }
371            if (Object.keys(resp.blogposts).length) {
372              let posts = { type: "posts", results: resp.blogposts };
373              resp.products.push(posts);
374            }
375            let showAll = { type: "all" };
376            if (resp.products.length >= resultsPerPage) {
377              resp.products.push(showAll);
378            }
379            response(resp.products);
380          })
381          .fail(response);
382      },
383      renderItem: function (product, search) {
384        if (product.type == "all") {
385          return (
386            '<div class="autocomplete-suggestion autocomplete-suggestion-show-all dropdown-item" data-type="all" data-val="' +
387            search +
388            '">' +
389            '<div class="row no-gutters align-items-center">' +
390            '<div class="col"><span class="name">' +
391            allText +
392            ' <i class="fa fa-angle-right" aria-hidden="true"></i></span></div>' +
393            "</div>" +
394            "</div>"
395          );
396        } else if (product.type == "brands") {
397          let brandsHtml = "";
398
399          Object.keys(product.results).forEach(function (key) {
400            brandsHtml +=
401              '<div class="autocomplete-suggestion dropdown-item" data-url="' +
402              product.results[key].link +
403              '">' +
404              '<div class="row no-gutters align-items-center">' +
405              '<div class="col col-auto col-img"><img class="img-fluid" src="' +
406              product.results[key].image +
407              '" /></div>' +
408              '<div class="col pt-3 pb-3"><span class="name">' +
409              product.results[key].name +
410              "</span></div>" +
411              '<div class="col col-auto col-shop pt-3 pb-3 ">' +
412              brandsText +
413              "</div>" +
414              "</div></div>";
415          });
416          return brandsHtml;
417        } else if (product.type == "posts") {
418          let postsHtml = "";
419
420          Object.keys(product.results).forEach(function (key) {
421            let imageHtml = "";
422            if (typeof product.results[key].banner_thumb !== "undefined") {
423              imageHtml =
424                '<img class="img-fluid" src="' +
425                product.results[key].banner_thumb +
426                '" />';
427            }
428
429            postsHtml +=
430              '<div class="autocomplete-suggestion dropdown-item" data-url="' +
431              product.results[key].url +
432              '">' +
433              '<div class="row no-gutters align-items-center">' +
434              '<div class="col col-auto col-img"><div class="col col-auto col-img">' +
435              imageHtml +
436              "</div></div>" +
437              '<div class="col pt-3 pb-3"><span class="name">' +
438              product.results[key].title +
439              "</span></div>" +
440              '<div class="col col-auto col-shop pt-3 pb-3 ">' +
441              blogText +
442              "</div>" +
443              "</div></div>";
444          });
445          return postsHtml;
446        } else {
447          let imageHtml = "";
448          let addCart = "";
449
450          if (product.id_manufacturer == 156) {
451            addCart =
452              '<a href="' +
453              product.canonical_url +
454              '" class="btn btn-product-list add-to-cart ' +
455              product.quantity +
456              '">' +
457              '<span class="sin-stock" style="">' +
458              product.add_to_cart_labels.stock +
459              "</span>" +
460              "</a>";
461          } else {
462            if (product.quantity > 0) {
463              addCart =
464                '<a style="z-index:99999;"href="' +
465                product.add_to_cart_url +
466                '" class="btn btn-product-list add-to-cart ' +
467                product.quantity +
468                '">' +
469                '<span class="sin-stock" style="">' +
470                product.add_to_cart_labels.stock +
471                "</span>" +
472                "</a>";
473            } else {
474              addCart =
475                '<a href="' +
476                product.canonical_url +
477                '" class="btn btn-product-list no-stock ' +
478                product.quantity +
479                '">' +
480                '<span class="sin-stock" style="">' +
481                product.add_to_cart_labels.no_stock +
482                "</span>" +
483                "</a>";
484            }
485          }
486
487          try {
488            imageHtml =
489              '<div class="col col-auto col-img"><img class="img-fluid" src="' +
490              product.cover.small.url +
491              '" /></div>';
492          } catch (e) {
493            imageHtml = "";
494          }
495
496          // prezo unitario
497          let product_price = product.price;
498          if (product.unit_price) product_price = product.unit_price;
499
500          // produtos resaltados
501          let product_resaltado = "";
502          if (product.hasOwnProperty("resaltado"))
503            product_resaltado = "product-resaltado";
504
505          return (
506            // '<div class="autocomplete-suggestion dropdown-item" data-url="' +
507            // product.url +
508            // '">' +
509            // '<div class="row no-gutters align-items-center">' +
510            // imageHtml +
511            // '<div class="col pt-3 pb-3"><span class="name">' +
512            // product.name +
513            // '</span><span class="product-price">' +
514            // product.price +
515            // "</span></div>" +
516            // '<div class="col col-auto col-shop pt-3 pb-3 ">' +
517            // addCart +
518            // "</div>" +
519            // "</div>" +
520            // "</div>"
521            '<div class="row dropdown-item ' +
522            product_resaltado +
523            '" style="display: flex;padding: 0;margin: 0;width:100%;">
523' +
524            '<div class="autocomplete-suggestion col col-7 pt-3 pb-3" data-url="' +
525            product.url +
526            '">' +
527            '<div class="row no-gutters align-items-center">' +
528            imageHtml +
529            '<div class="col pt-3 pb-3"><span class="name">' +
530            product.name +
531            '</span><span class="product-price">' +
532            // product.price +
533            product_price +
534            "</span></div>" +
535            "</div>" +
536            "</div>" +
537            '<div class="col col-auto col-shop pt-3 pb-3" style="align-self: center;">' +
538            addCart +
539            "</div>" +
540            "</div>"
541          );
542        }
543      },
544      onSelect: function (e, term, item) {
545        if (item.data("type") == "all") {
546          $searchWidget.find("form").submit();
547        } else {
548          window.location.href = item.data("url");
549        }
550      },
551    });
552  };
553
554  let $searchWidgetDistr = $("#search_widget_distr");
555  let $searchBoxDistr = $searchWidgetDistr.find("input[type=text]");
556  let searchURLDistr = $searchWidgetDistr.attr("data-search-controller-url");
557  let $searchToggleDistr = $("#header-search-btn");
558
559  initAutocompleteDistr($searchWidgetDistr, $searchBoxDistr, searchURLDistr);
560
561  let $searchWidgetMobile = $("#search-widget-mobile");
562  let $searchBoxMobile = $searchWidgetMobile.find("input[type=text]");
563  let $searchToggleMobile = $("#mobile-btn-search");
564
565  initAutocomplete($searchWidgetMobile, $searchBoxMobile, searchURLDistr);
566
567  $searchToggleDistr.on("shown.bs.dropdown", function () {
568    setTimeout(function () {
569      $searchBoxDistr.focus();
570    }, 300);
571  });
572
573  $searchToggleMobile.on("shown.bs.dropdown", function () {
574    setTimeout(function () {
575      $("#mobile-btn-search").find("input[type=text]").focus();
576    }, 300);
577  });
578
579  $("#fullscreen-search-backdrop").on("touchstart", function (e) {
580    e.stopPropagation();
581    $("#header-search-btn-drop").dropdown("toggle");
582  });
583});
584
585(function ($) {
586  $.fn.autoCompleteDistr = function (options) {
587    var o = $.extend({}, $.fn.autoComplete.defaults, options);
588
589    // public methods
590    if (typeof options == "string") {
591      this.each(function () {
592        var that = $(this);
593        if (options == "destroy") {
594          // that.off('blur.autocomplete focus.autocomplete keydown.autocomplete keyup.autocomplete');
595          that.off("blur.autocomplete focus.autocomplete keyup.autocomplete");
596          if (that.data("autocomplete"))
597            that.attr("autocomplete", that.data("autocomplete"));
598          else that.removeAttr("autocomplete");
599          $(that.data("sc")).remove();
600          that.removeData("sc").removeData("autocomplete");
601        }
602      });
603      return this;
604    }
605
606    return this.each(function () {
607      var that = $(this);
608      // sc = 'suggestions container'
609
610      that.sc = $(
611        '<div class="autocomplete-suggestions ' + o.menuClass + '"></div>',
612      );
613      that.data("sc", that.sc).data("autocomplete", that.attr("autocomplete"));
614      that.attr("autocomplete", "off");
615      that.cache = {};
616      that.last_val = "";
617
618      that.updateSC = function (resize, next) {
619        that.sc.show();
620      };
621
622      that.sc.insertAfter(that.parent().parent());
623
624      that.siblings(".clear-btn").on("click", function () {
625        that.val("");
626        that.trigger("keyup.autocomplete");
627        $(this).hide();
628      });
629
630      that.sc.on("mouseleave", ".autocomplete-suggestion", function () {
631        $(".autocomplete-suggestion.selected").removeClass("selected");
632      });
633
634      that.sc.on("mouseenter", ".autocomplete-suggestion", function () {
635        $(".autocomplete-suggestion.selected").removeClass("selected");
636        $(this).addClass("selected");
637      });
638
639      that.sc.on("mousedown click", ".autocomplete-suggestion", function (e) {
640        var item = $(this),
641          v = item.data("val");
642        if (v || item.hasClass("autocomplete-suggestion")) {
643          // else outside click
644          that.val(v);
645          o.onSelect(e, v, item);
646          that.sc.hide();
647        }
648        return false;
649      });
650
651      that.on("blur.autocomplete", function () {
652        var val = that.val();
653        if (val.length < o.minChars) {
654          that.sc.hide();
655        }
656      });
657
658      if (!o.minChars)
659        that.on("focus.autocomplete", function () {
660          that.last_val = "\n";
661          that.trigger("keyup.autocomplete");
662        });
663
664      function suggest(data) {
665        var val = that.val();
666        that.cache[val] = data;
667        if (data.length && val.length >= o.minChars) {
668          var s = "";
669          for (var i = 0; i < data.length; i++) s += o.renderItem(data[i], val);
670          that.sc.html(s);
671          that.updateSC(0);
672        } else {
673          that.sc.hide();
674        }
675      }
676
677      // that.on('keydown.autocomplete', function(e){
678      //     // down (40), up (38)
679      //     if ((e.which == 40 || e.which == 38) && that.sc.html()) {
680      //         var next, sel = $('.autocomplete-suggestion.selected', that.sc);
681      //         if (!sel.length) {
682      //             next = (e.which == 40) ? $('.autocomplete-suggestion', that.sc).first() : $('.autocomplete-suggestion', that.sc).last();
683      //             that.val(next.addClass('selected').data('val'));
684      //         } else {
685      //             next = (e.which == 40) ? sel.next('.autocomplete-suggestion') : sel.prev('.autocomplete-suggestion');
686      //             if (next.length) { sel.removeClass('selected'); that.val(next.addClass('selected').data('val')); }
687      //             else { sel.removeClass('selected'); that.val(that.last_val); next = 0; }
688      //         }
689      //         that.updateSC(0, next);
690      //         return false;
691      //     }
692      //     // esc
693      //     else if (e.which == 27){ that.val(that.last_val).sc.hide();console.log("hide -> keydown.autocomplete 1");}
694      //     // enter or tab
695      //     else if (e.which == 13 || e.which == 9) {
696      //         var sel = $('.autocomplete-suggestion.selected', that.sc);
697      //         if (sel.length && that.sc.is(':visible')) { o.onSelect(e, sel.data('val'), sel); setTimeout(function(){ that.sc.hide();  console.log("hide -> keydown.autocomplete 2");}, 20); }
698      //     }
699      // });
700
701      that.on("keyup.autocomplete", function (e) {
702        if (!~$.inArray(e.which, [13, 27, 35, 36, 37, 38, 39, 40])) {
703          var val = that.val();
704          if (val.length > 0) {
705            that.siblings(".clear-btn").show();
706          }
707          if (val.length >= o.minChars) {
708            if (val != that.last_val) {
709              that.last_val = val;
710              clearTimeout(that.timer);
711              if (o.cache) {
712                if (val in that.cache) {
713                  suggest(that.cache[val]);
714                  return;
715                }
716                // no requests if previous suggestions were empty
717                for (var i = 1; i < val.length - o.minChars; i++) {
718                  var part = val.slice(0, val.length - i);
719                  if (part in that.cache && !that.cache[part].length) {
720                    suggest([]);
721                    return;
722                  }
723                }
724              }
725              that.timer = setTimeout(function () {
726                o.source(val, suggest);
727              }, o.delay);
728            }
729          } else {
730            that.last_val = val;
731            that.sc.hide();
732          }
733        }
734      });
735    });
736  };
737
738  $.fn.autoCompleteDistr.defaults = {
739    source: 0,
740    minChars: 2,
741    delay: 150,
742    cache: 1,
743    menuClass: "",
744    renderItem: function (item, search) {
745      // escape special characters
746      search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
747      var re = new RegExp("(" + search.split(" ").join("|") + ")", "gi");
748      return (
749        '<div class="autocomplete-suggestion" data-val="' +
750        item +
751        '">' +
752        item.replace(re, "<b>$1</b>") +
753        "</div>"
754      );
755    },
756    onSelect: function (e, term, item) {},
757  };
758})(jQuery);
759
760// KZdev: novo proceso de pedido -> resumo
761(function ($) {
762  $(document).ready(() => {
763    updatedCartSpin();
764
765    if (typeof prestashop !== "undefined") {
766      prestashop.cart = prestashop.cart || {};
767      // Refresh cart preview
768      prestashop.on("updateCart", function () {
769        if (prestashop.page.page_name === "checkout") {
770          location.reload();
771        }
772      });
773    }
774  });
775
776  function updatedCartSpin() {
777    $(
778      'body#checkout .cart-item.cart-summary-product input[name="product-quantity-spin"]',
779    ).each(function () {
780      if ($(this).TouchSpin().val() == 1) {
781        var button_icon = document.createElement("i");
782        button_icon.setAttribute("class", "fa fa-trash-o");
783        $(this).parent().children(":first").children("button").empty();
784        $(this)
785          .parent()
786          .children(":first")
787          .children("button")
788          .append(button_icon);
789      }
790    });
791  }
792})(jQuery);
793
794/* ---------------------------OS--------------------------------- */
795
796/* -------------------------------------------------------------- */
797// OS
798
799$(document).ready(function () {
800  /**
801   * Regex prefijo
802   */
803
804  /**
805   * Main Menu Expand
806   */
807  let mainMenuExpand = false;
808
809  $("#header .ce-btn-main-menu-expand").on("click", function () {
810    const icon = $(".ce-btn-main-menu-expand .elementor-icon i.ceicon");
811    const header = $("#header");
812
813    if (!mainMenuExpand) {
814      // Expandir el menú
815      mainMenuExpand = true;
816      icon.removeClass("ceicon-burger").addClass("ceicon-close");
817      header[0].style.setProperty("margin-top", "-90px", "important"); // Ajusta el margin-top
818    } else {
819      // Contraer el menú
820      mainMenuExpand = false;
821      icon.removeClass("ceicon-close").addClass("ceicon-burger");
822      header[0].style.setProperty("margin-top", "-140px", "important"); // Restablece el margin-top
823    }
824  });
825
826  /**
827   * Main Menu Responsive
828   */
829  $("#menu-responsive").on("click", function () {
830    // Alternar la clase 'elementor-active' en el botón de menú
831    $(this).toggleClass("elementor-active");
832
833    // Verificar si el menú está activo
834    if ($(this).hasClass("elementor-active")) {
835      // Añadir el ícono "X" al menú si está activo
836      $(this).find("ul.elementor-nav").find(".menu-close-icon").remove(); // Evitar duplicados
837      $(this)
838        .find("ul.elementor-nav")
839        .prepend('<li class="menu-close-icon">✖</li>');
840
841      // Bloquear el scroll
842      $("body").css("overflow", "hidden");
843    } else {
844      // Quitar el ícono "X" si el menú se cierra
845      $(this).find("ul.elementor-nav").find(".menu-close-icon").remove();
846
847      // Restaurar el scroll
848      $("body").css("overflow", "");
849    }
850  });
851
852  // Funcionalidad para cerrar el menú al hacer clic en la "X"
853  $(document).on("click", ".menu-close-icon", function (event) {
854    // Prevenir que el clic en la "X" también dispare el evento del botón principal
855    event.stopPropagation();
856
857    // Eliminar la clase .elementor-active del contenedor del menú
858    $("#menu-responsive").removeClass("elementor-active");
859
860    // Quitar el ícono "X"
861    $(this).closest("ul.elementor-nav").find(".menu-close-icon").remove();
862
863    // Restaurar el scroll
864    $("body").css("overflow", "");
865  });
866
867  /**
868   * Trigger para detectar cuando el scroll está en el top y cuando se hace scroll hacia abajo.
869   */
870  let hasScrolledDown = false; // Bandera para detectar el primer scroll hacia abajo
871
872  $(window).on("scroll", function () {
873    const header = $("#header");
874    const icon = $(".ce-btn-main-menu-expand .elementor-icon i.ceicon");
875    const body = $("body");
876    const windowWidth = $(window).width(); // Obtener el ancho de la ventana
877
878    // Si el scroll está en el top (scrollTop === 0)
879    if ($(window).scrollTop() === 0) {
880      // Cuando estamos al top, restablecer el margin-top del header a 0px
881      mainMenuExpand = false;
882      icon.removeClass("ceicon-close").addClass("ceicon-burger"); // Resetear el icono
883
884      // Ajustar el margin-top del header
885      header[0].style.setProperty("margin-top", "0px", "important"); // Ajustar margin-top a 0px
886
887      // Si el body tiene la clase 'stick_menu_displayed', la mantenemos
888      if (body.hasClass("stick_menu_displayed")) {
889        // Se mantiene la propiedad de la clase stick_menu_displayed
890        // No cambiamos nada, solo dejamos que la clase siga aplicando esos estilos.
891      }
892
893      // Resetear la bandera de scroll hacia abajo
894      hasScrolledDown = false;
895    } else if (!hasScrolledDown) {
896      // Si el scroll ha bajado por primera vez, aplicar la clase 'stick_menu_displayed'
897      body.addClass("stick_menu_displayed"); // Agregar la clase stick_menu_displayed al body
898
899      // Ajustar el margin-top cuando se desciende, dependiendo del tamaño de la ventana
900      if (windowWidth <= 768) {
901        header[0].style.setProperty("margin-top", "0px", "important"); // Ajustar margin-top a 0px en pantallas pequeñas
902      } else {
903        header[0].style.setProperty("margin-top", "-140px", "important"); // Ajustar margin-top a -140px en pantallas grandes
904      }
905
906      // Marcar que el scroll hacia abajo ya ha sucedido
907      hasScrolledDown = true;
908    }
909  });
910
911  /**
912   * Megamenú
913   */
914  function updateMenuContent(element) {
915    //Pintar el menú en la ventana del mega menú
916    const htmlContent = element.find(".cbp-category-tree").html();
917    const linkText = element.find("a.cbp-column-title").text();
918    // Verificar si htmlContent está vacío
919    if (!htmlContent) {
920      return; // No hacer nada si htmlContent está vacío
921    }
922    const newContent = `<p class="category-name">${linkText}</p>${htmlContent}`;
923    const targetDiv = $(
924      "#iqitmegamenu-horizontal .col-8.cbp-menu-column.cbp-menu-element > .cbp-menu-column-inner > div:nth-child(2) > .cbp-menu-column",
925    );
926    targetDiv.html(newContent);
927  }
928
929  // Función para actualizar el href
930  function actualizarHrefPorHover(elemento) {
931    setTimeout(function () {
932      const titulo = $(".iqitmegamenu .col-8 .category-name:first")
933        .text()
934        .trim();
935      const matchingLink = $(elemento)
936        .find("a.cbp-category-title")
937        .filter(function () {
938          return $(this).text().trim() === titulo;
939        });
940      if (matchingLink.length > 0) {
941        const nuevoHref = matchingLink.attr("href");
942        $(".iqitmegamenu .col-8  .menu_row .cbp-menu-column p a").attr(
943          "href",
944          nuevoHref,
945        );
946      }
947    }, 200);
948  }
949
950  /**
951   * Megamenú actualizar href manuales
952   */
953  function actualizarHrefManuales() {
954    $(".cbp-category-link-w").each(function () {
955      var textoElemento = $(this).text().trim().toLowerCase();
956      var textosHref = {
957        "manuales y despieces":
958          "https://distribucionmayorista.online/es/content/14-manuales",
959        "manuals and exploded views":
960          "https://distribucionmayorista.online/en/content/14-manuales",
961        manuels: "https://distribucionmayorista.online/fr/content/14-manuales",
962        manuais: "https://distribucionmayorista.online/pt/content/14-manuales",
963        "handbücher und teile":
964          "https://distribucionmayorista.online/de/content/14-manuales",
965      };
966
967      if (textosHref[textoElemento]) {
968        $(this).find("a").attr("href", textosHref[textoElemento]);
969        /* console.log($(this)); */
970      }
971    });
972  }
973  actualizarHrefManuales();
974
975  $(
976    ".iqitmegamenu .cbp-hrsub, .iqitmegamenu .iqitmegamenu-submenu-container .cbp-category-link-w",
977  ).hover(function () {
978    actualizarHrefPorHover(this);
979  });
980
981  $("#iqitmegamenu-wrapper .cbp-hrmenu-tab").on("mouseenter", function () {
982    const firstItem = $(this).find(".cbp-category-link-w").first();
983    updateMenuContent(firstItem);
984  });
985
986  $("#iqitmegamenu-wrapper .cbp-category-link-w").on("mouseenter", function () {
987    $("#iqitmegamenu-wrapper .cbp-category-link-w").removeClass(
988      "underline-hover",
989    );
990    $(this).addClass("underline-hover");
991    updateMenuContent($(this));
992  });
993
994  $("#iqitmegamenu-wrapper").on("mouseleave", function () {
995    $("#iqitmegamenu-wrapper .cbp-category-link-w").removeClass(
996      "underline-hover",
997    );
998  });
999
1000  // Ejecutar la función cuando la página cargue
1001  window.onload = actualizarHrefManuales;
1002
1003  // Llamar a la función cuando la página haya cargado
1004  window.onload = actualizarHrefManuales;
1005
1006  /**
1007   * Megamenú Marcas - Ordenar marcas por orden alfabético y añadir enlaces dinámicos con idioma en URL
1008   */
1009  $("#cbp-hrmenu-tab-27 .cbp-menu-column").each(function () {
1010    let currentLetter = "";
1011    let letterCount = 0;
1012
1013    // Obtener el idioma actual desde la URL (por ejemplo, '/es/', '/fr/', etc.)
1014    const currentLanguage = window.location.pathname.split("/")[1];
1015
1016    // Definir la ruta correspondiente a marcas según el idioma
1017    let brandsPath = "marcas";
1018    if (currentLanguage === "fr" || currentLanguage === "pt") {
1019      brandsPath = "brands";
1020    } else if (currentLanguage === "de") {
1021      brandsPath = "verkaufsprodukte-der-besten-marken-grosshandelsvertrieb";
1022    }
1023
1024    $(this)
1025      .find("ul.cbp-links li")
1026      .each(function () {
1027        const brandName = $(this).text().trim();
1028        const brandNameUpper = brandName.toUpperCase();
1029        const firstLetter = brandNameUpper.charAt(0);
1030
1031        const allowedBrands = [
1032          "ALIVE",
1033          "AQUARIUS",
1034          "ARRUABARRENA",
1035          "ARTIACH - CUÉTARA",
1036          "BIMBO-MARTINEZ",
1037          "BRETS",
1038          "CASAMAYOR",
1039          "CHEETOS",
1040          "CHOCOLATES VALOR",
1041          "CHUPA CHUPS",
1042          "CLIPPER",
1043          "COCACOLA",
1044          "CONTROL",
1045          "CUÉTARA",
1046          "CUEVAS",
1047          "DAMEL",
1048          "DON SIMON",
1049          "DULCESOL",
1050          "DUREX",
1051          "ELGORRIAGA",
1052          "ENERYETI",
1053          "FACUNDO",
1054          "FERRERO KINDER",
1055          "FILIPINOS",
1056          "FINI",
1057          "GRANINI",
1058          "GREFUSA",
1059          "GULLON",
1060          "HALLS",
1061          "HARIBO",
1062          "HERO",
1063          "HUESITOS",
1064          "JOFEMAR",
1065          "JUICY JAY'S",
1066          "KAS",
1067          "KELIA",
1068          "KELLOGG´S",
1069          "KIT KAT",
1070          "LA BATURRICA",
1071          "LACASA",
1072          "LAYS",
1073          "LIPTON",
1074          "LU",
1075          "MARS",
1076          "MATUTANO",
1077          "MENTOS",
1078          "MILKA",
1079          "MONDELEZ",
1080          "MONSTER",
1081          "NESCAFE",
1082          "NESTEA",
1083          "NESTLE",
1084          "OCB",
1085          "ORBIT",
1086          "OREO",
1087          "PASCUAL",
1088          "PEPSICO",
1089          "PRESTIGE",
1090          "PRINGLES",
1091          "QÉ",
1092          "RAW",
1093          "REDBULL",
1094          "REESE´S",
1095          "REGILAIT",
1096          "ROCKSTAR",
1097          "RUFFLES",
1098          "SAIMAZA",
1099          "SAN BENEDETTO",
1100          "SANDEN VENDO",
1101          "SATISFYER",
1102          "SIMAT",
1103          "SMOKING",
1104          "TORO LOCO",
1105          "TOSFRIT",
1106          "TOY JOY",
1107          "TRIDENT",
1108          "VELARTE",
1109          "VIDAL GOLOSINAS",
1110          "VIGAREX FORTE",
1111          "VILLA",
1112          "WERTHER'S",
1113        ];
1114
1115        if (!allowedBrands.includes(brandNameUpper)) {
1116          $(this).remove();
1117          return;
1118        }
1119
1120        if (firstLetter !== currentLetter) {
1121          currentLetter = firstLetter;
1122          $(this).before(
1123            `<li><span class="capital-letter" data-letter="${currentLetter}" style="cursor: pointer;">${currentLetter}.</span></li>`,
1124          );
1125        }
1126      });
1127
1128    // Añadir funcionalidad de click en la letra
1129    $(".capital-letter").on("click", function () {
1130      const letter = $(this).data("letter");
1131      const url = `https://distribucionmayorista.online/${currentLanguage}/${brandsPath}#man-letter-${letter.toUpperCase()}`;
1132
1133      /* console.log("Guardando en localStorage la letra:", letter); */
1134      localStorage.setItem("selectedLetter", letter.toUpperCase());
1135
1136      window.location.href = url; // Redirigir a la URL con la ancla
1137    });
1138  });
1139
1140  // Aplicar el efecto de scroll tras la redirección
1141  window.onload = function () {
1142    /* console.log("Se ha iniciado el onload"); */
1143
1144    const letter = localStorage.getItem("selectedLetter");
1145    /* console.log("Letra recuperada de localStorage:", letter); */
1146
1147    if (letter) {
1148      // Construimos el selector con la letra recuperada
1149      const targetAnchor = `#man-letter-${letter}`;
1150      /* console.log("targetAnchor:", targetAnchor); */
1151
1152      // Prevenir el comportamiento de scroll automático al hacer la redirección
1153      if (window.location.hash === targetAnchor) {
1154        // Evitar que el navegador haga el scroll automático
1155        history.replaceState(null, null, window.location.href.split("#")[0]);
1156      }
1157
1158      // Buscar el elemento con el atributo `name` correspondiente
1159      const targetElement = document.querySelector(
1160        `a[name="man-letter-${letter}"]`,
1161      );
1162      /* console.log("Elemento encontrado:", targetElement ? "Sí" : "No"); */
1163
1164      if (targetElement) {
1165        /* console.log("ENTRA POR AQUI??"); */
1166        // Obtener la posición del elemento en la página
1167        const elementPosition =
1168          targetElement.getBoundingClientRect().top + window.scrollY;
1169        const menuHeight = document.querySelector(".menu")?.offsetHeight || 100; // Ajusta la altura del menú fijo
1170
1171        // Realizar el scroll con desplazamiento inmediato
1172        window.scrollTo({
1173          top: elementPosition - menuHeight + 100, // Ajuste para no quedar tapado por el menú fijo
1174          behavior: "smooth", // Desplazamiento suave
1175        });
1176
1177        // Eliminar la letra del localStorage después de realizar la acción
1178        localStorage.removeItem("selectedLetter");
1179      } else {
1180        console.warn("No se encontró el destino del enlace:", targetAnchor);
1181      }
1182    }
1183  };
1184
1185  /**
1186   * Quitar href menu Marcas
1187   */
1188  $("#cbp-hrmenu-tab-27 > a").removeAttr("href");
1189
1190  /**
1191   * Página Marcas - Ordenar marcas por orden alfabético
1192   */
1193  $("#brand-mod").each(function () {
1194    let currentLetter = "";
1195
1196    $(this)
1197      .find("ul .facet-label")
1198      .each(function () {
1199        const brandName = $(this).text().trim();
1200        const firstLetter = brandName.charAt(0).toUpperCase();
1201
1202        // Solo agregar el encabezado de letra si es una letra diferente
1203        if (firstLetter !== currentLetter) {
1204          currentLetter = firstLetter;
1205          $(this).before(
1206            `<li><span class="capital-letter">${currentLetter}.</span></li>`,
1207          );
1208        }
1209      });
1210  });
1211
1212  /**
1213   * Añadir Ofertas Vending al menú lateral de la página de Ofertas
1214   */
1215  function addVendingOffersMenuItem() {
1216    const siteUrl = document.location.origin;
1217    const lang = $("html").attr("lang");
1218    const translations = {
1219      es: { text: "Ofertas Vending", href: "/es/255-ofertas-vending" },
1220      fr: { text: "Offres Vending", href: "/fr/255-offres" },
1221      pt: { text: "Ofertas Vending", href: "/pt/255-ofertas" },
1222      en: { text: "Vending Offers", href: "/en/255-offers" },
1223      de: { text: "Vending-Angebote", href: "/de/255-verkaufsangebote" },
1224    };
1225    const { text, href } = translations[lang] || translations["es"];
1226    const imageUrl =
1227      siteUrl + "/themes/warehousechild/assets/img/icono_flame.png";
1228
1229    $("#menu-lateral-ofertas ul").append(
1230      '<li class="menu-item menu-item-type-custom">' +
1231        '<a class="elementor-item" href=' +
1232        href +
1233        ">" +
1234        '<img class="cat-menu" src=' +
1235        imageUrl +
1236        ' alt="' +
1237        text +
1238        '">' +
1239        text +
1240        "</a>" +
1241        "</li>",
1242    );
1243  }
1244
1245  addVendingOffersMenuItem();
1246
1247  function menuResetInputValue() {
1248    const input = $("div.zomlmm input");
1249    input.val("");
1250  }
1251  menuResetInputValue();
1252
1253  $(function () {
1254    var menu = $("#header"); // Reemplaza con la clase real de tu menú
1255    var menuHeight = menu.length ? menu.outerHeight() : 80; // Detecta la altura del menú, usa 80px por defecto
1256
1257    $(".ms-letter-selector a").on("click", function (event) {
1258      event.preventDefault(); // Evita el salto brusco
1259
1260      var targetId = $(this).attr("href").substring(1); // Obtiene el ID sin #
1261      var targetElement = $(`[name="${targetId}"]`);
1262
1263      if (targetElement.length) {
1264        var elementPosition = targetElement.offset().top;
1265
1266        $("html, body").animate(
1267          {
1268            scrollTop: elementPosition - menuHeight + 100, // Offset para compensar el menú
1269          },
1270          100,
1271        ); // Duración del scroll en milisegundos (ajústalo según necesites)
1272      }
1273    });
1274  });
1275
1276  $(document).ready(function () {
1277    // Función para modificar el contenido de .menu-element-id-19
1278    function actualizarContenido() {
1279      var $ulLink = $(".menu-element-id-22 ul.cbp-links li a").first();
1280      if ($ulLink.length) {
1281        var newUrl = $ulLink.attr("href");
1282        var newText = $ulLink.text();
1283        var $img = $ulLink
1284          .closest("li")
1285          .find("a")
1286          .not($ulLink)
1287          .find("img")
1288          .first();
1289        var newImgUrl = $img.length ? $img.attr("src") : "";
1290        var newImgAlt = $img.length ? $img.attr("alt") : "";
1291        var $icon = $ulLink.closest("li").find("i").first();
1292        var newIcon = $icon.length ? $icon.clone() : null;
1293
1294        var $targetBlock = $(
1295          ".menu-element-id-19 .cbp-categories-row .col-12",
1296        ).eq(1);
1297        if ($targetBlock.length) {
1298          var $titleAnchor = $targetBlock.find("a.cbp-column-title");
1299          $titleAnchor.attr("href", newUrl).text(newText);
1300          if (newIcon && !$titleAnchor.next("i").length) {
1301            $titleAnchor.after(newIcon);
1302          }
1303          var $thumbAnchor = $targetBlock.find("a.cbp-category-thumb");
1304          $thumbAnchor.attr("href", newUrl);
1305          if (newImgUrl) {
1306            $thumbAnchor.find("img").attr("src", newImgUrl);
1307          }
1308          if (newImgAlt) {
1309            $thumbAnchor.find("img").attr("alt", newImgAlt);
1310          }
1311        }
1312        // Eliminar el bloque original
1313        $(".menu-element-id-22").remove();
1314      }
1315
1316      // Ahora que el contenido ha sido actualizado, ejecutar la función para modificar el menú lateral
1317      actualizarMenuLateral();
1318    }
1319
1320    // Función para actualizar el menú lateral
1321    function actualizarMenuLateral() {
1322      if (
1323        $("body").hasClass("page-category") ||
1324        $("body").hasClass("page-search")
1325      ) {
1326        $("#menu-lateral-categorias").empty();
1327        var newContent;
1328        if (
1329          $("body").is(
1330            ".category-id-parent-142, .category-id-parent-164, .category-id-parent-167",
1331          )
1332        ) {
1333          newContent = $(
1334            "#cbp-hrmenu-tab-26 .menu-element-id-1 .menu-element-id-2",
1335          ).html();
1336        } else {
1337          newContent = $(".menu-element-id-1 .menu-element-id-2").html();
1338        }
1339        $("#menu-lateral-categorias").html(newContent);
1340      }
1341
1342      $("#menu-lateral-categorias .cbp-category-link-w").each(function () {
1343        const $menu = $(this);
1344        const $linkTitle = $menu.find(".cbp-category-title");
1345        const $linkThumb = $menu.find(".cbp-category-thumb");
1346        const categoryName = $linkTitle.text().trim();
1347        const categoryHref = $linkTitle.attr("href");
1348        const $submenu = $menu
1349          .find(".cbp-category-tree")
1350          .detach()
1351          .insertAfter($menu)
1352          .hide();
1353        const translations = {
1354          es: "Todo",
1355          fr: "Tout",
1356          pt: "Tudo",
1357          en: "All",
1358          de: "Alle",
1359        };
1360        const lang = document.documentElement.lang || "es";
1361        const translatedTodo = translations[lang] || "Todo";
1362        if ($submenu.length > 0) {
1363          $submenu.prepend(`
1364                    <li>
1365                        <div class="cbp-category-link-w">
1366                            <a href="${categoryHref}">${translatedTodo} ${categoryName}</a>
1367                        </div>
1368                    </li>
1369                `);
1370        }
1371        if ($submenu.length > 0) {
1372          const $arrowButton = $(
1373            '<span class="menu-toggle-arrow fas fa-chevron-right"></span>',
1374          );
1375          $menu.prepend($arrowButton);
1376          const toggleSubmenu = function () {
1377            const isOpen = $submenu.is(":visible");
1378            $("#menu-lateral-categorias .cbp-category-tree").slideUp(200);
1379            $("#menu-lateral-categorias .menu-toggle-arrow")
1380              .removeClass("fas fa-chevron-down")
1381              .addClass("fas fa-chevron-right");
1382            $("#menu-lateral-categorias .cbp-category-link-w").removeClass(
1383              "hide-after",
1384            );
1385            if (isOpen) {
1386              $submenu.stop(true, true).slideUp(300);
1387              $arrowButton
1388                .removeClass("fas fa-chevron-down")
1389                .addClass("fas fa-chevron-right");
1390            } else {
1391              $submenu.stop(true, true).slideDown(300);
1392              $arrowButton
1393                .removeClass("fas fa-chevron-right")
1394                .addClass("fas fa-chevron-down");
1395              $menu.addClass("hide-after");
1396            }
1397          };
1398          $arrowButton.on("click", toggleSubmenu);
1399          $linkTitle.on("click", function (e) {
1400            e.preventDefault();
1401            toggleSubmenu();
1402          });
1403          $linkThumb.on("click", function (e) {
1404            e.preventDefault();
1405            toggleSubmenu();
1406          });
1407        }
1408      });
1409
1410      // Después de actualizar el menú lateral, agregar la islita de "Productos Vending"
1411      agregarIslita();
1412
1413      // Agregar las flechas para el submenú de nivel 2
1414      agregarFlechasSubmenuNivel2();
1415    }
1416
1417    // Función para agregar la islita de "Productos Vending" al final del menú lateral
1418    function agregarIslita() {
1419      const lang = document.documentElement.lang || "es";
1420      let linkText, linkUrl;
1421
1422      // Determinar el texto y la URL según el idioma
1423
1424      switch (lang) {
1425        case "fr-FR":
1426          linkText = "Des Offres";
1427          linkUrl = "http://distribucionmayorista.online/fr/promotions";
1428          break;
1429        case "pt":
1430          linkText = "Ofertas";
1431          linkUrl = "http://distribucionmayorista.online/pt/promocoes";
1432          break;
1433        case "en-US":
1434          linkText = "Offers";
1435          linkUrl = "http://distribucionmayorista.online/en/prices-drop";
1436          break;
1437        case "de-de":
1438          linkText = "Verkaufsangebote";
1439          linkUrl = "http://distribucionmayorista.online/de/angebote";
1440          break;
1441        case "nl-nl":
1442          linkText = "Aanbiedingen";
1443          linkUrl = "http://distribucionmayorista.online/nl/aanbiedingen";
1444          break;
1445        case "nl-be":
1446          linkText = "Aanbiedingen";
1447          linkUrl = "http://distribucionmayorista.online/be/aanbiedingen";
1448          break;
1449        case "it-it":
1450          linkText = "Offerte";
1451          linkUrl = "http://distribucionmayorista.online/it/offerte";
1452          break;
1453        default:
1454          linkText = "Ofertas";
1455          linkUrl = "http://distribucionmayorista.online/es/ofertas";
1456          break;
1457      }
1458
1459      const islitaHTML = `
1460            <div class="row menu_row menu-element menu-element-id-vending">
1461                <div class="col-12 cbp-menu-column cbp-menu-element menu-element-id-19">
1462                    <div class="cbp-menu-column-inner">
1463                        <div class="row cbp-categories-row">
1464                            <div class="col-12">
1465                                <div class="cbp-category-link-w">
1466                                    <a href="${linkUrl}" class="cbp-column-title nav-link cbp-category-title">${linkText}</a>
1467                                    <a href="${linkUrl}" class="cbp-category-thumb" style="margin-bottom: 0px;">
1468                                        <span class="replace-2x img-fluid img-ofert"></span>
1469                                    </a>
1470                                </div>
1471                            </div>
1472                        </div>
1473                    </div>
1474                </div>
1475            </div>
1476        `;
1477      $("#menu-lateral-categorias").append(islitaHTML);
1478    }
1479
1480    // Función para agregar las flechas y controlar el despliegue de los submenús .cbp-hrsub-level2
1481    function agregarFlechasSubmenuNivel2() {
1482      $(
1483        "#menu-lateral-categorias .cbp-hrsub-haslevel2 > .cbp-category-link-w > a",
1484      ).each(function () {
1485        const $link = $(this);
1486        const $submenuLevel2 = $link
1487          .closest(".cbp-hrsub-haslevel2")
1488          .find(".cbp-hrsub-level2")
1489          .hide();
1490        const subCategoryName = $link.text().trim(); // Texto de la categoría
1491        const subCategoryHref = $link.attr("href"); // Enlace de la categoría
1492
1493        const translations = {
1494          es: "Todo",
1495          fr: "Tout",
1496          pt: "Tudo",
1497          en: "All",
1498          de: "Alle",
1499        };
1500
1501        const lang = document.documentElement.lang || "es"; // Por defecto, español
1502        const translatedTodo = translations[lang] || "Todo"; // Traducción
1503
1504        if ($submenuLevel2.length > 0) {
1505          $submenuLevel2.prepend(`
1506                    <li>
1507                        <div class="cbp-category-link-w">
1508                            <a href="${subCategoryHref}">${translatedTodo} ${subCategoryName}</a>
1509                        </div>
1510                    </li>
1511                `);
1512        }
1513
1514        if ($submenuLevel2.length > 0) {
1515          const $arrowButtonLevel2 = $(
1516            '<span class="menu-toggle-arrow fas fa-chevron-right"></span>',
1517          );
1518          $link.prepend($arrowButtonLevel2);
1519
1520          const toggleSubmenuLevel2 = function (e) {
1521            e.preventDefault(); // Prevenir el comportamiento predeterminado
1522            e.stopPropagation(); // Evitar la propagación del evento
1523
1524            const isOpen = $submenuLevel2.is(":visible");
1525
1526            if (isOpen) {
1527              $submenuLevel2.stop(true, true).slideUp(300);
1528              $arrowButtonLevel2
1529                .removeClass("fa-chevron-down")
1530                .addClass("fa-chevron-right");
1531            } else {
1532              $submenuLevel2.stop(true, true).slideDown(300);
1533              $arrowButtonLevel2
1534                .removeClass("fa-chevron-right")
1535                .addClass("fa-chevron-down");
1536            }
1537          };
1538
1539          $arrowButtonLevel2.on("click", toggleSubmenuLevel2);
1540          $link.on("click", toggleSubmenuLevel2);
1541        }
1542      });
1543    }
1544
1545    // Ejecutar la primera función, y cuando termine llamará a la segunda
1546    actualizarContenido();
1547  });
1548
1549  /* $('#iqitmegamenu-wrapper .row.cbp-categories-row .col-12 > .cbp-category-link-w > a.cbp-category-title').removeAttr('href'); */
1550
1551  function redondearPrecioTresCifras() {
1552    $(".product-price .elementor-heading-title").each(function () {
1553      // Encuentra el precio en el texto
1554      let priceText = $(this).text().trim();
1555
1556      // Extraer solo el número del precio (puedes ajustar el selector si es necesario)
1557      let match = priceText.match(/(\d+,\d+)/);
1558
1559      if (match) {
1560        // Extraer el valor del precio
1561        let price = match[1].replace(",", "."); // Reemplaza la coma por punto para manipular el número
1562
1563        // Asegurar que el precio tiene tres cifras decimales
1564        let formattedPrice = parseFloat(price).toFixed(3);
1565
1566        // Volver a colocar el formato y coma original
1567        formattedPrice = formattedPrice.replace(".", ",");
1568
1569        // Reemplazar el texto en el DOM
1570        let updatedText = priceText.replace(match[1], formattedPrice);
1571        $(this).text(updatedText);
1572      }
1573    });
1574  }
1575
1576  redondearPrecioTresCifras();
1577
1578  /**
1579   * Productos sin stock
1580   */
1581  var $info = $("body#product .product-additional-info");
1582  if ($info.length > 0 && $info.html().trim() !== "") {
1583    // Si .product-additional-info existe y no está vacío, eliminamos #purchase-controls
1584    $(".purchase-controls").remove();
1585    /* console.log("PRODUCTO SIN STOCK"); */
1586  }
1587
1588  /**
1589   * Eliminar productos duplicados en la lista de deseos
1590   */
1591  function eliminarProductosDuplicados() {
1592    // Seleccionamos todas las filas de la lista de deseos
1593    var productos = $(".wishlist-products-container .wishlist-products-item");
1594    /* console.log("PRODUCTOS LISTA", productos); */
1595
1596    // Creamos un objeto para hacer un seguimiento de los productos que ya hemos encontrado
1597    var productosVistos = {};
1598
1599    productos.each(function () {
1600      // Seleccionamos el enlace o ID único del producto para identificarlo
1601      var enlaceProducto = $(this).find(".wishlist-product-link").attr("href");
1602
1603      // Comprobamos si ya hemos visto este producto
1604      if (productosVistos[enlaceProducto]) {
1605        // Si el producto ya está en productosVistos, eliminamos este duplicado
1606        $(this).remove();
1607      } else {
1608        // Si es un producto nuevo, lo añadimos a productosVistos
1609        productosVistos[enlaceProducto] = true;
1610      }
1611    });
1612  }
1613  function esperarCargaProductos() {
1614    var interval = setInterval(function () {
1615      // Comprobamos si hay productos en la lista
1616      if ($(".wishlist-products-item").length > 0) {
1617        // Si ya hay productos, ejecutamos la función y dejamos de verificar
1618        eliminarProductosDuplicados();
1619        clearInterval(interval); // Detenemos el intervalo
1620      }
1621    }, 100); // Verificamos cada 100ms
1622  }
1623
1624  esperarCargaProductos(); // Llamamos la función de espera
1625
1626  /**
1627   * Pop-up Condiciones de venta en ficha producto
1628   */
1629  $("#terms-sale-popup-link").click(function (e) {
1630    e.preventDefault();
1631    $("#terms-sale-popup-content").addClass("show");
1632  });
1633
1634  $(document).on(
1635    "click",
1636    "#terms-sale-popup-content .elementor-alert-dismiss",
1637    function () {
1638      $("#terms-sale-popup-content").removeClass("show");
1639    },
1640  );
1641
1642  $("#terms-sale-popup-link").click(function (e) {
1643    e.preventDefault();
1644    $("#terms-sale-popup-content").css("display", "");
1645    $("#terms-sale-popup-content").addClass("show");
1646  });
1647
1648  $(document).on(
1649    "click",
1650    "#terms-sale-popup-content .elementor-alert-dismiss",
1651    function () {
1652      $("#terms-sale-popup-content").removeClass("show").css("display", "none");
1653    },
1654  );
1655
1656  /**
1657   * Borrar etiqueta descuento en caso de estar vacías
1658   */
1659  function removeEmptyDiscountBadges() {
1660    $(".discount-badge .elementor-heading-title").each(function () {
1661      if ($(this).html().trim() === "" || $(this).html().trim() === " ") {
1662        $(this).closest(".discount-badge").remove();
1663      }
1664    });
1665  }
1666  removeEmptyDiscountBadges();
1667
1668  /**
1669   * Limitar los caracteres de los nombres en las minituras y carrito
1670   */
1671  function truncateText(selector, maxLength) {
1672    $(selector).each(function () {
1673      let text = $(this).text();
1674      if (text.length > maxLength) {
1675        $(this).text(text.substring(0, maxLength) + "...");
1676      }
1677    });
1678  }
1679
1680  truncateText("#blockcart-content .pb-1 a", 20);
1681  truncateText("#cart .product-line-info a", 20);
1682
1683  /**
1684   * Calcula el precio unitario sin descuento para un artículo específico.
1685   */
1686  function calcularPrecioUnitarioEnArticulo(articulo) {
1687    let $articulo = $(articulo);
1688
1689    let precioSinDescuento = parseFloat(
1690      $articulo
1691        .find(".product-og-price span")
1692        .text()
1693        .replace(",", ".")
1694        .replace(/[^\d.]/g, ""),
1695    );
1696
1697    let ratioUnitario = parseFloat(
1698      $articulo
1699        .find(".product-ratio .elementor-widget-container")
1700        .text()
1701        .replace(",", "."),
1702    );
1703
1704    if (
1705      !isNaN(precioSinDescuento) &&
1706      !isNaN(ratioUnitario) &&
1707      ratioUnitario > 0
1708    ) {
1709      let resultado = (precioSinDescuento / ratioUnitario).toFixed(3) + "€";
1710
1711      $articulo.find(".product-og-ratio p").text(resultado);
1712    }
1713  }
1714
1715  function ejecutarCalculos() {
1716    $(".ce-product-details").each(function () {
1717      calcularPrecioUnitarioEnArticulo(this);
1718    });
1719  }
1720
1721  function iniciarObserverGlobal() {
1722    const observer = new MutationObserver(function (mutations) {
1723      mutations.forEach(function (mutation) {
1724        mutation.addedNodes.forEach(function (node) {
1725          if (node.nodeType !== 1) return;
1726
1727          if ($(node).hasClass("ce-product-details")) {
1728            calcularPrecioUnitarioEnArticulo(node);
1729          }
1730
1731          $(node)
1732            .find(".ce-product-details")
1733            .each(function () {
1734              calcularPrecioUnitarioEnArticulo(this);
1735            });
1736        });
1737      });
1738    });
1739
1740    observer.observe(document.body, {
1741      childList: true,
1742      subtree: true,
1743    });
1744  }
1745
1746  $(window).on("load", function () {
1747    ejecutarCalculos();
1748    iniciarObserverGlobal();
1749  });
1750
1751  // Eliminar tabla de descuentos vacía
1752  if ($("body#product .product-discounts-table").children().length === 0) {
1753    $("body#product .product-discounts-table").remove();
1754  }
1755
1756  /**
1757   * Aplica el cálculo a todos los artículos visibles.
1758   */
1759  function calcularPrecioUnitarioSinDescuento() {
1760    $(".ce-product-grid article").each(function () {
1761      calcularPrecioUnitarioEnArticulo(this);
1762    });
1763    $("#related-products article").each(function () {
1764      calcularPrecioUnitarioEnArticulo(this);
1765    });
1766    calcularPrecioUnitarioEnArticulo("#product-detail");
1767  }
1768
1769  // Inicializamos la función para los elementos ya cargados
1770  calcularPrecioUnitarioSinDescuento();
1771
1772  /**
1773   * Aplica la función después de hacer clic en el botón `#load-more`.
1774   */
1775  $("#load-more").on("click", function () {
1776    // Agrega un pequeño retardo para asegurar que los nuevos productos estén en el DOM
1777    setTimeout(() => {
1778      calcularPrecioUnitarioSinDescuento();
1779    }, 500); // 500ms de retardo ajustable
1780  });
1781
1782  /**
1783   * Mostrar fecha caducidad producto
1784   */
1785  function handleCaducidadRow() {
1786    var caducidadRow = $(".product-expiration-date .ce-product-features__row");
1787    var allowedLabels = ["Cad.", "Exp.", "Val."];
1788
1789    caducidadRow.each(function () {
1790      var label = $(this).find(".ce-product-features__label").text().trim();
1791
1792      if (allowedLabels.includes(label)) {
1793        // Mostrar filas Cad., Exp. o Val.
1794        $(this).show();
1795        $(this).closest("table").show();
1796      } else {
1797        // Ocultar el resto
1798        $(this).hide();
1799      }
1800    });
1801  }
1802
1803  handleCaducidadRow();
1804
1805  // Configurar el observador principal
1806  const observer = new MutationObserver((mutationsList) => {
1807    observer.disconnect(); // Desactivar temporalmente el observador
1808    try {
1809      mutationsList.forEach((mutation) => {
1810        // Verificar si la mutación tiene nodos añadidos
1811        mutation.addedNodes.forEach((node) => {
1812          if (
1813            (node.nodeType === Node.ELEMENT_NODE && // Asegurarse de que sea un elemento
1814              node.id === "ce-product-quick-view") ||
1815            node.id === "ui-id-1"
1816          ) {
1817            // Ejecutar acciones cuando #ce-product-quick-view es añadido
1818            handleCaducidadRow();
1819            calcularPrecioUnitarioEnArticulo("#ce-product-quick-view");
1820            //calcularPrecioUnitarioEnArticulo("#product");
1821            removeEmptyDiscountBadges();
1822            showUnitsPerBox();
1823            // Eliminar tabla de descuentos vacía
1824            if (
1825              $("#ce-product-quick-view .product-discounts-table").children()
1826                .length === 0
1827            ) {
1828              $("#ce-product-quick-view .product-discounts-table").remove();
1829            }
1830
1831            // Configurar un observador específico para #ce-product-quick-view
1832            /* observeQuickViewContent(node); */
1833            /* console.log("prueba"); */
1834          }
1835        });
1836      });
1837    } finally {
1838      observer.observe(document.body, { childList: true, subtree: true }); // Reactivar el observador
1839    }
1840  });
1841
1842  // Configurar el observador en el body para detectar la adición de nodos
1843  observer.observe(document.body, { childList: true, subtree: true });
1844
1845  // Configurar el observador para detectar cambios en el contenido de #product
1846  const targetProductsNode = document.querySelector("body#product");
1847  if (targetProductsNode) {
1848    const productsObserver = new MutationObserver((mutationsList) => {
1849      mutationsList.forEach((mutation) => {
1850        if (
1851          mutation.type === "childList" ||
1852          mutation.type === "characterData"
1853        ) {
1854          // Ejecutar las acciones necesarias después de la actualización
1855          handleCaducidadRow();
1856          /* calcularPrecioUnitarioEnArticulo("#ce-product-quick-view"); */
1857          removeEmptyDiscountBadges();
1858          showUnitsPerBox();
1859          /* console.log("MutationObserver: #product actualizado"); */
1860        }
1861      });
1862    });
1863
1864    // Configurar el observador para observar el contenido y atributos de #product
1865    productsObserver.observe(targetProductsNode, {
1866      childList: true, // Detectar cambios en los hijos
1867      subtree: true, // Detectar cambios en profundidad
1868      characterData: true, // Detectar cambios en el texto de los nodos
1869      attributes: true, // Detectar cambios de atributos (si es necesario)
1870    });
1871  }
1872
1873  $(".btn-product-quick-preview").on("click", function () {
1874    handleCaducidadRow();
1875  });
1876
1877  /**
1878   * Mostrar la badge de oferta en las miniaturas de los productos
1879   * Ocultar `.top-sale-badge .ce-product-badges` si `.ce-product-badge-new` también existe y tiene contenido.
1880   */
1881  $(".ce-product-grid article").each(function () {
1882    let topSaleBadge = $(this).find(".top-sale-badge .ce-product-badges");
1883    let newBadge = $(this).find(".ce-product-badge-new");
1884
1885    // Verifica si ambos elementos existen y si `.ce-product-badge-new` tiene contenido
1886    if (
1887      topSaleBadge.length > 0 &&
1888      newBadge.length > 0 &&
1889      newBadge.html().trim() !== ""
1890    ) {
1891      topSaleBadge.hide(); // Oculta `.top-sale-badge .ce-product-badges`
1892      $(this).find(".bottom-sale-badge").show(); // Muestra el elemento correspondiente
1893    }
1894  });
1895
1896  /**
1897   * Quitar figcaption galerías (si está en blanco el figcaption deja un hueco en blanco)
1898   */
1899  $("#news-section .ce-image-gallery figcaption").each(function () {
1900    let txt = $(this).html().trim();
1901    if (txt === "") {
1902      $(this).remove();
1903    }
1904  });
1905
1906  /**
1907   * Acordeones cerrados por defecto en la home faq section
1908   */
1909  $("#faq-section .elementor-tab-title").removeClass("elementor-active");
1910  $("#faq-section .elementor-tab-content").css("display", "none");
1911
1912  /**
1913   * Capitalizar las marcas en la home
1914   */
1915  $("#section-featured-brands .facet-label a").each(function () {
1916    let texto = $(this).text().toLowerCase();
1917    let capitalizado = texto.replace(/\b\w/g, function (letra) {
1918      return letra.toUpperCase(); // Capitalizar la primera letra de cada palabra
1919    });
1920    $(this).text(capitalizado); // Asignar el texto transformado
1921  });
1922
1923  /**
1924   * Habilitar Scroll con ratón en #section-featured-products
1925   */
1926  var isMouseDown = false;
1927  var startX, scrollLeft;
1928  // Detectar cuando se presiona el ratón dentro del contenedor
1929  $(".ce-product-grid").mousedown(function (e) {
1930    isMouseDown = true;
1931    startX = e.pageX - $(this).offset().left;
1932    scrollLeft = $(this).scrollLeft();
1933    $(this).addClass("is-dragging"); // Cambiar el cursor a "grabbing"
1934    e.preventDefault(); // Prevenir que se seleccione texto o se haga clic en el enlace
1935  });
1936
1937  // Detectar cuando se suelta el ratón
1938  $(document).mouseup(function () {
1939    isMouseDown = false;
1940    $(".ce-product-grid").removeClass("is-dragging"); // Cambiar el cursor a "grab"
1941  });
1942
1943  // Detectar el movimiento del ratón para desplazar
1944  $(".ce-product-grid").mousemove(function (e) {
1945    if (!isMouseDown) return; // Solo permite el desplazamiento si el ratón está presionado
1946    e.preventDefault(); // Evita la selección de texto mientras se arrastra
1947    var x = e.pageX - $(this).offset().left;
1948    var walk = (x - startX) * 2; // Ajustar la velocidad de desplazamiento
1949    $(this).scrollLeft(scrollLeft - walk);
1950  });
1951
1952  // Prevenir el acceso al enlace mientras se arrastra
1953  $(".ce-product-grid a").click(function (e) {
1954    if ($(".ce-product-grid").hasClass("is-dragging")) {
1955      e.preventDefault(); // Evita que el enlace se ejecute si estamos arrastrando
1956    }
1957  });
1958
1959  // Placeholder en textarea de personalización de productos
1960  function setPlaceholderByLang() {
1961    var placeholders = {
1962      es: "Escriba aquí",
1963      fr: "Écrivez ici",
1964      pt: "Escreva aqui",
1965      en: "Write here",
1966      de: "Hier schreiben",
1967    };
1968
1969    var lang = $("html").attr("lang").substring(0, 2).toLowerCase();
1970    $("#product .elementor-widget-product-customization textarea").attr(
1971      "placeholder",
1972      placeholders[lang] || placeholders["en"],
1973    );
1974  }
1975  setPlaceholderByLang();
1976
1977  $(document).ajaxComplete(function () {
1978    calcularPrecioUnitarioSinDescuento();
1979    calcularPrecioUnitarioEnArticulo("#ce-product-quick-view");
1980    /* calcularPrecioUnitarioEnArticulo("#product"); */
1981    truncateText("#cart .product-line-info a", 20);
1982    removeEmptyDiscountBadges();
1983    showUnitsPerBox();
1984    if ($("body#product .product-discounts-table").children().length === 0) {
1985      $("body#product .product-discounts-table").remove();
1986    }
1987    handleCaducidadRow();
1988    /* console.log("Ajax complete"); */
1989  });
1990
1991  // Botón Scroll top
1992  window.onscroll = function () {
1993    const scrollTopBtn = document.getElementById("btnScrollUp");
1994    if (document.documentElement.scrollTop > 200) {
1995      btnScrollUp.style.display = "block"; // Mostrar el botón
1996    } else {
1997      btnScrollUp.style.display = "none"; // Ocultar el botón
1998    }
1999  };
2000
2001  /*  $.ajax({
2002    url:
2003      prestashop.urls.base_url +
2004      "index.php?fc=module&module=yourcustommodule&controller=yourcontroller",
2005    type: "POST",
2006    data: {
2007      id_category: prestashop.category.id,
2008    },
2009    success: function (response) {
2010      $("#imax-seo-adv-desc").html(response);
2011    },
2012    error: function () {
2013      console.log("Error al cargar el contenido del hook.");
2014    },
2015  }); */
2016
2017  // Función para hacer scroll al inicio
2018  function scrollToTop() {
2019    window.scrollTo({
2020      top: 0,
2021      behavior: "smooth",
2022    });
2023  }
2024});
2025
2026document.addEventListener("DOMContentLoaded", function () {
2027  // console.log("Optimización iniciada");
2028
2029  // 1. Diferir carga de CSS de /assets/cache
2030  /*(function () {
2031        var links = [
2032            '/assets/cache/theme-24e15d5288.css',
2033            '/assets/cache/theme-278cf95288.css',
2034            '/assets/cache/theme-4478335288.css',
2035            '/assets/cache/theme-5fb5db5288.css',
2036            '/assets/cache/theme-adcc325288.css',
2037            '/assets/cache/theme-dfdb675288.css',
2038            '/assets/cache/theme-e702ec5288.css',
2039            '/assets/cache/theme-fb4dc45288.css'
2040        ];
2041        links.forEach(function (href) {
2042            var link = document.createElement('link');
2043            link.rel = 'preload';
2044            link.as = 'style';
2045            link.href = href;
2046            link.onload = function () {
2047                this.rel = 'stylesheet';
2048                console.log('CSS cargado:', href);
2049            };
2050            document.head.appendChild(link);
2051        });
2052    })();*/
2053
2054  // 2. Preconectar y diferir Google Fonts
2055  (function () {
2056    ["https://fonts.googleapis.com", "https://fonts.gstatic.com"].forEach(
2057      function (url) {
2058        var preconnect = document.createElement("link");
2059        preconnect.rel = "preconnect";
2060        preconnect.href = url;
2061        if (url.includes("gstatic")) preconnect.crossOrigin = "";
2062        document.head.appendChild(preconnect);
2063      },
2064    );
2065    var fonts = [
2066      "https://fonts.googleapis.com/css2?family=Roboto&display=swap",
2067      "https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap",
2068    ];
2069    fonts.forEach(function (href) {
2070      var link = document.createElement("link");
2071      link.rel = "stylesheet";
2072      link.href = href;
2073      document.head.appendChild(link);
2074      // console.log('Fuente cargada:', href);
2075    });
2076  })();
2077
2078  // Ejecutar al cargar y cuando cambien nodos (AJAX / infinite scroll)
2079  document.addEventListener("DOMContentLoaded", limitProducts);
2080  window.addEventListener("load", limitProducts);
2081
2082  var observerTarget = document.querySelector("#products") || document.body;
2083  if (observerTarget && window.MutationObserver) {
2084    var observer = new MutationObserver(function () {
2085      limitProducts();
2086    });
2087    observer.observe(observerTarget, { childList: true, subtree: true });
2088  }
2089
2090  // También ejecútalo cada 1s un par de veces por si hay scripts que tardan en pintar
2091  var tries = 0;
2092  var interval = setInterval(function () {
2093    limitProducts();
2094    tries++;
2095    if (tries > 6) clearInterval(interval);
2096  }, 1000);
2097})();
2098
2099function addFetchPriority() {
2100  // Selecciona todas las imágenes del carousel
2101  const carouselImages = document.querySelectorAll(".elementor-carousel-image");
2102
2103  carouselImages.forEach((img) => {
2104    if (!img.hasAttribute("fetchpriority")) {
2105      img.setAttribute("fetchpriority", "high");
2106
2107      // Preload para mejorar LCP
2108      const link = document.createElement("link");
2109      link.rel = "preload";
2110      link.as = "image";
2111      link.href = img.src;
2112      document.head.appendChild(link);
2113    }
2114  });
2115}
2116
2117// Espera a que Elementor inicialice los widgets
2118document.addEventListener("elementor/frontend/init", function () {
2119  elementorFrontend.hooks.addAction(
2120    "frontend/element_ready/global",
2121    function ($scope) {
2122      addFetchPriority();
2123    },
2124  );
2125});
2126
2127// Fallback por si alguna imagen ya está cargada
2128window.addEventListener("load", function () {
2129  setTimeout(addFetchPriority, 1000); // Espera 1s para que Elementor termine de renderizar
2130});
2131
2132document.addEventListener("DOMContentLoaded", function () {
2133  const logo = document.querySelector('img[src*="Logo DMO letras"]');
2134
2135  if (logo) {
2136    // Reemplaza el src por una versión redimensionada ya optimizada
2137    logo.src = "/dev/cms/Logo_DMO_letras_116x35.png";
2138
2139    // Ajusta tamaño mostrado
2140    logo.width = 116;
2141    logo.height = 35;
2142
2143    // Añade fetchpriority
2144    logo.setAttribute("fetchpriority", "high");
2145
2146    // Opcional: agregar srcset para retina
2147    logo.srcset = "/dev/cms/Logo_DMO_letras_232x70.png 2x";
2148  }
2149});
2150//Optimizar grid
2151(function () {
2152  // Función para obtener el valor de un parámetro de la URL
2153  function getUrlParam(name, defaultValue) {
2154    const params = new URLSearchParams(window.location.search);
2155    return params.has(name) ? parseInt(params.get(name), 10) : defaultValue;
2156  }
2157
2158  // Función para guardar una cookie
2159  function setCookie(name, value, days = 30) {
2160    const expires = new Date();
2161    expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000);
2162    document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`;
2163  }
2164
2165  // Valor por defecto de productos por página (ajusta según tu configuración)
2166  const defaultProductsPerPage = 16;
2167
2168  // Obtener el valor 'n' de la URL o usar el valor por defecto
2169  let n = getUrlParam("n", defaultProductsPerPage);
2170
2171  // Ajustar 'n' al múltiplo de 4 más cercano hacia arriba
2172  if (n % 4 !== 0) {
2173    n = Math.ceil(n / 4) * 4;
2174  }
2175
2176  // Guardar en cookie
2177  setCookie("n", n);
2178
2179  // Revisar si la URL ya tiene el parámetro 'n' correcto
2180  const currentUrl = new URL(window.location.href);
2181  if (parseInt(currentUrl.searchParams.get("n")) !== n) {
2182    currentUrl.searchParams.set("n", n);
2183    window.location.href = currentUrl.toString(); // Recargar la página con el valor ajustado
2184  }
2185})();
2186
2187$(document).ready(function () {
2188  // Guardar los valores originales de la tercera celda
2189  $(".table-product-discounts tbody tr").each(function () {
2190    var celda = $(this).find("td").eq(2); // tercera celda
2191    celda.attr("data-original", celda.text()); // guardamos valor original
2192  });
2193
2194  // Escuchar cambios en el selector de cantidad de PrestaShop
2195  $(document).on(
2196    "change",
2197    'input[name="qty"], select.qty-selector',
2198    function () {
2199      // Restaurar el valor original de la tercera celda
2200      $(".table-product-discounts tbody tr").each(function () {
2201        var celda = $(this).find("td").eq(2);
2202        celda.text(celda.attr("data-original"));
2203      });
2204    },
2205  );
2206});
2207
2208/**
2209 * Mostrar únicamente las características de los productos que contienen "por caja"
2210 */
2211function showUnitsPerBox(selector) {
2212  var labels = [
2213    "uds. por caja:",
2214    "pour boite",
2215    "por caixa",
2216    "per box",
2217    "pro box",
2218  ];
2219
2220  $(selector + " .ce-product-features__row").each(function () {
2221    var labelText = $(this)
2222      .find(".ce-product-features__label")
2223      .text()
2224      .toLowerCase();
2225
2226    var found = labels.some(function (label) {
2227      return labelText.includes(label.toLowerCase());
2228    });
2229
2230    if (!found) {
2231      $(this).hide();
2232    }
2233  });
2234}
2235
2236// Llamada inicial para ejecutarla en #units-per-box
2237$(document).ready(function () {
2238  showUnitsPerBox("#units-per-box");
2239});
2240
2241document.addEventListener("DOMContentLoaded", function () {
2242  var pathParts = window.location.pathname.split("/");
2243  var categoryName =
2244    pathParts.length > 2 ? pathParts[2].replace(/-/g, " ") : "";
2245  var categoryId = categoryName.toLowerCase().replace(/\s+/g, "_");
2246
2247  var products = [];
2248  document.querySelectorAll(".ce-product-name a").forEach(function (el, i) {
2249    var url = el.getAttribute("href");
2250    var idProduct = url.match(/\/(\d+)-/) ? url.match(/\/(\d+)-/)[1] : "";
2251    var name = el.innerText.trim();
2252
2253    products.push({
2254      item_id: idProduct,
2255      item_name: name,
2256      item_category: categoryName,
2257      index: i + 1,
2258    });
2259  });
2260
2261  dataLayer.push({
2262    event: "view_item_list",
2263    ecommerce: {
2264      item_list_id: categoryId,
2265      item_list_name: categoryName,
2266      items: products,
2267    },
2268  });
2269});
2270
2271document.addEventListener("DOMContentLoaded", function () {
2272  // ID de producto desde la URL (/3712-...)
2273  var idMatch = window.location.pathname.match(/\/(\d+)-/);
2274  var idProduct = idMatch ? idMatch[1] : "";
2275
2276  // Nombre del producto desde el H1
2277  var productName = document.querySelector("h1.ce-product-name")
2278    ? document.querySelector("h1.ce-product-name").innerText.trim()
2279    : "";
2280
2281  // Categoría desde la URL (/es/chocolates/...)
2282  var pathParts = window.location.pathname.split("/");
2283  var productCategory =
2284    pathParts.length > 2 ? pathParts[2].replace(/-/g, " ") : "";
2285
2286  // Precio unitario mostrado
2287  var priceEl = document.querySelector(
2288    '[itemprop="price"], .current-price [content]',
2289  );
2290  var productPrice = priceEl
2291    ? parseFloat(
2292        priceEl.getAttribute("content") ||
2293          priceEl.innerText.replace(/[^\d.,]/g, "").replace(",", "."),
2294      )
2295    : 0;
2296
2297  // Push al dataLayer
2298  dataLayer.push({
2299    event: "view_item",
2300    ecommerce: {
2301      currency: "EUR",
2302      value: productPrice,
2303      items: [
2304        {
2305          item_id: idProduct,
2306          item_name: productName,
2307          item_category: productCategory,
2308          price: productPrice,
2309          quantity: 1,
2310        },
2311      ],
2312    },
2313  });
2314
2315  console.log("view_item enviado:", {
2316    idProduct,
2317    productName,
2318    productCategory,
2319    productPrice,
2320  });
2321});
2322document.addEventListener("DOMContentLoaded", () => {
2323  const addToCartBtns = document.querySelectorAll(
2324    "a[href*='#ce-action=addToCart']",
2325  );
2326  console.log("🛒 Botones encontrados:", addToCartBtns.length);
2327
2328  addToCartBtns.forEach((btn, index) => {
2329    btn.addEventListener("click", (e) => {
2330      console.log(`\n🟢 Clic en botón add_to_cart #${index + 1}`, btn);
2331
2332      // Miramos el contenedor más cercano (ajústalo según tu HTML real)
2333      const productContainer =
2334        btn.closest(".elementor-widget, .product, .elementor-column, li") ||
2335        document;
2336      console.log("📦 Contenedor detectado:", productContainer);
2337
2338      // Nombre del producto
2339      const nameEl = productContainer.querySelector(
2340        ".product-title, .elementor-heading-title, h2, h3, .label",
2341      );
2342      console.log("🔤 nameEl encontrado:", nameEl);
2343      const name = nameEl ? nameEl.innerText.trim() : "Producto sin nombre";
2344
2345      // Precio del producto
2346      const priceEl = productContainer.querySelector(
2347        ".price, .product-price, .woocommerce-Price-amount, .value",
2348      );
2349      console.log("💶 priceEl encontrado:", priceEl);
2350      const priceText = priceEl ? priceEl.innerText.trim() : "0";
2351      const price =
2352        parseFloat(
2353          priceText
2354            .replace(/\./g, "")
2355            .replace(",", ".")
2356            .replace(/[^\d.]/g, ""),
2357        ) || 0;
2358
2359      // ID del producto
2360      const id =
2361        productContainer.dataset.idProduct ||
2362        name.replace(/\s+/g, "-").toLowerCase();
2363
2364      // URL del producto
2365      const linkEl = productContainer.querySelector("a[href]");
2366      const url = linkEl ? linkEl.href : window.location.href;
2367
2368      // Categoría (sacada de la URL si existe /es/categoria/)
2369      const category = url.includes("/es/")
2370        ? url.split("/es/")[1].split("/")[0]
2371        : "general";
2372
2373      const product = {
2374        item_id: id,
2375        item_name: name,
2376        price: price,
2377        quantity: 1,
2378        item_category: category,
2379        item_url: url,
2380      };
2381
2382      // Enviar al dataLayer
2383      window.dataLayer = window.dataLayer || [];
2384      window.dataLayer.push({
2385        event: "add_to_cart",
2386        ecommerce: {
2387          currency: "EUR",
2388          value: product.price,
2389          items: [product],
2390        },
2391      });
2392
2393      console.log("✅ Evento add_to_cart enviado:", product);
2394    });
2395  });
2396});
2397
2398// Alternativa: disparar automáticamente al cargar la página de checkout
2399document.addEventListener("DOMContentLoaded", triggerBeginCheckout);
2400
2401// Wait for the DOM to load
2402document.addEventListener("DOMContentLoaded", function () {
2403  // Get all shipping radio buttons
2404  const shippingOptions = document.querySelectorAll(
2405    'input[name^="delivery_option"]',
2406  );
2407
2408  shippingOptions.forEach((option) => {
2409    option.addEventListener("change", function () {
2410      const selectedOption = this;
2411      const label = document.querySelector(`label[for="${selectedOption.id}"]`);
2412
2413      if (label) {
2414        const carrierName =
2415          label.querySelector(".carrier-name")?.innerText || "";
2416        const carrierDelay =
2417          label.querySelector(".carrier-delay")?.innerText || "";
2418        const carrierPrice =
2419          label.querySelector(".carrier-price")?.innerText || "";
2420
2421        // Push to dataLayer
2422        window.dataLayer = window.dataLayer || [];
2423        window.dataLayer.push({
2424          event: "add_shipping_info",
2425          shipping_method: carrierName,
2426          shipping_price: carrierPrice,
2427          shipping_delay: carrierDelay,
2428        });
2429
2430        console.log("DataLayer push:", {
2431          shipping_method: carrierName,
2432          shipping_price: carrierPrice,
2433          shipping_delay: carrierDelay,
2434        });
2435      }
2436    });
2437  });
2438});
2439
2440document.addEventListener("DOMContentLoaded", function () {
2441  var form = document.querySelector("#js-delivery");
2442  var continueBtn = form ? form.querySelector('button[type="submit"]') : null;
2443
2444  if (continueBtn && form) {
2445    continueBtn.addEventListener("click", function (e) {
2446      e.preventDefault();
2447
2448      // ---- Subtotal ----
2449      var subtotalEl = document.querySelector("#cart-subtotal-products .value");
2450      var cartSubtotal = 0;
2451      if (subtotalEl) {
2452        var subtotalText = subtotalEl.textContent
2453          .trim()
2454          .replace(/\./g, "")
2455          .replace(",", ".");
2456        cartSubtotal = parseFloat(subtotalText) || 0;
2457      }
2458
2459      // ---- Cupón ----
2460      var couponEl = document.querySelector(
2461        '#promo-code input[name="discount_name"]',
2462      );
2463      var cartCoupon = couponEl ? couponEl.value.trim() : "";
2464
2465      // ---- Productos ----
2466      var cartLines = Array.from(
2467        document.querySelectorAll(".cart-summary-product"),
2468      );
2469      var items = cartLines.map(function (el) {
2470        var nameEl = el.querySelector(".product-line-info .label");
2471        var priceEl = el.querySelector(".unit-price .value");
2472        var qtyEl = el.querySelector(".js-cart-line-product-quantity");
2473        var linkEl = el.querySelector(".product-line-info a");
2474
2475        var price = priceEl
2476          ? parseFloat(
2477              priceEl.textContent.trim().replace(/\./g, "").replace(",", "."),
2478            ) || 0
2479          : 0;
2480        var quantity = qtyEl ? parseInt(qtyEl.value) || 1 : 1;
2481        var url = linkEl ? linkEl.href : "";
2482
2483        return {
2484          item_id: el.dataset.id || "",
2485          item_name: nameEl ? nameEl.textContent.trim() : "",
2486          item_category: el.dataset.category || "",
2487          price: price,
2488          quantity: quantity,
2489          item_url: url,
2490        };
2491      });
2492
2493      // ---- Envío del evento con gtag ----
2494      if (typeof gtag === "function") {
2495        gtag("event", "begin_checkout", {
2496          currency: "EUR",
2497          value: cartSubtotal,
2498          coupon: cartCoupon,
2499          items: items,
2500        });
2501      } else {
2502        console.error("gtag no está definido");
2503      }
2504
2505      console.log("Evento begin_checkout enviado:", {
2506        currency: "EUR",
2507        value: cartSubtotal,
2508        coupon: cartCoupon,
2509        items: items,
2510      });
2511
2512      // ---- Asegurar que se mande antes de redirigir ----
2513      setTimeout(function () {
2514        form.submit();
2515      }, 500);
2516    });
2517  }
2518});
2519
2520(function () {
2521  function getCartItems() {
2522    let items = [];
2523
2524    document
2525      .querySelectorAll("#cart-summary-product-list .cart-summary-product")
2526      .forEach((el) => {
2527        const name =
2528          el.querySelector(".product-line-info .label")?.innerText.trim() || "";
2529        const id =
2530          el.querySelector("input.js-cart-line-product-quantity")?.dataset
2531            .productId || "";
2532        const quantity = parseInt(
2533          el.querySelector("input.js-cart-line-product-quantity")?.value || "0",
2534          10,
2535        );
2536        const priceText = el
2537          .querySelector(".unit-price .value")
2538          ?.innerText.replace("€", "")
2539          .replace(",", ".")
2540          .trim();
2541        const price = parseFloat(priceText) || 0;
2542        const link =
2543          el.querySelector(".product-line-info .label")?.getAttribute("href") ||
2544          "";
2545        const image = el.querySelector(".product-image img")?.src || "";
2546
2547        items.push({
2548          item_id: id,
2549          item_name: name,
2550          quantity: quantity,
2551          price: price,
2552          item_url: link,
2553          item_image: image,
2554        });
2555      });
2556
2557    return items;
2558  }
2559
2560  // Lanzamos el evento begin_checkout con lo que hay en el carrito
2561  const items = getCartItems();
2562
2563  window.dataLayer = window.dataLayer || [];
2564  window.dataLayer.push({
2565    event: "begin_checkout",
2566    ecommerce: {
2567      currency: "EUR",
2568      items: items,
2569    },
2570  });
2571
2572  console.log("begin_checkout event enviado:", items);
2573})();
2574
2575(function () {
2576  // Reutilizamos la función getCartItems() para extraer productos del mini carrito
2577  function getCartItems() {
2578    let items = [];
2579    document
2580      .querySelectorAll("#blockcart-content .cart-products li")
2581      .forEach((el) => {
2582        const inputQty = el.querySelector(
2583          "input.js-cart-line-product-quantity",
2584        );
2585        const linkEl = el.querySelector(".col-info a");
2586        const priceEl = el.querySelector(".col-info .col span:last-child");
2587        const imgEl = el.querySelector(".product-image img");
2588
2589        if (!inputQty || !linkEl || !priceEl) return;
2590
2591        const id = inputQty.dataset.productId;
2592        const name = linkEl.innerText.trim();
2593        const quantity = parseInt(inputQty.value || "0", 10);
2594        const priceText = priceEl.innerText
2595          .replace("€", "")
2596          .replace(/\./g, "")
2597          .replace(",", ".")
2598          .trim();
2599        const price = parseFloat(priceText) || 0;
2600        const link = linkEl.href;
2601        const image = imgEl ? imgEl.src : "";
2602
2603        items.push({
2604          item_id: id,
2605          item_name: name,
2606          quantity: quantity,
2607          price: price,
2608          item_url: link,
2609          item_image: image,
2610        });
2611      });
2612    return items;
2613  }
2614
2615  function getSelectedPaymentMethod() {
2616    const selected = document.querySelector(
2617      'input[name="payment-option"]:checked',
2618    );
2619    return selected ? selected.dataset.moduleName || selected.id : "";
2620  }
2621
2622  function getCartTotal() {
2623    const totalEl = document.querySelector(
2624      "#blockcart-content .cart-totals .flex-cart-totals-total .value",
2625    );
2626    if (!totalEl) return 0;
2627    const totalText = totalEl.innerText
2628      .replace("€", "")
2629      .replace(/\./g, "")
2630      .replace(",", ".")
2631      .trim();
2632    return parseFloat(totalText) || 0;
2633  }
2634
2635  function pushAddPaymentInfo() {
2636    const items = getCartItems();
2637    const paymentMethod = getSelectedPaymentMethod();
2638    const cartTotal = getCartTotal();
2639
2640    if (items.length > 0 && paymentMethod) {
2641      window.dataLayer = window.dataLayer || [];
2642      window.dataLayer.push({
2643        event: "add_payment_info",
2644        ecommerce: {
2645          currency: "EUR",
2646          value: cartTotal,
2647          payment_type: paymentMethod,
2648          items: items,
2649        },
2650      });
2651      console.log("add_payment_info enviado:", {
2652        paymentMethod,
2653        cartTotal,
2654        items,
2655      });
2656    }
2657  }
2658
2659  // Ejecutar cuando se seleccione un método de pago
2660  document.querySelectorAll('input[name="payment-option"]').forEach((input) => {
2661    input.addEventListener("change", pushAddPaymentInfo);
2662  });
2663
2664  // También ejecutar al cargar la página si ya hay un método seleccionado
2665  document.addEventListener("DOMContentLoaded", pushAddPaymentInfo);
2666})();

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.