PageSourceSearch

https://lojahusqvarna.pt/src/themes/picostrap5-child-base/js/functions.js?ver=1785163648

js lojahusqvarna.pt collected 2026-10-04 13:27:52 UTC 44,657 bytes, 1,305 lines download raw bytes

1//Ajax
2var urlAjax = js_params.ajaxurl;
3
4//Scroll
5var scroll_inicial = 0;
6var scroll_contador = 0;
7var scroll_ga = 1;
8var scroll_pos_init = 0;
9
10//Arranque
11
12jQuery(document).ready(function () {
13  jQuery(".choice input").change(function () {
14    if (jQuery(".choice input.kitepos[type=radio]").is(":checked")) {
15      jQuery(".add-cart-product-qty").removeClass("d-flex").addClass("d-none");
16      jQuery(".btn-cart").removeClass("d-flex").addClass("d-none");
17      jQuery("#btn-kit").show();
18    } else {
19      jQuery(".add-cart-product-qty").removeClass("d-none").addClass("d-flex");
20      jQuery(".btn-cart").removeClass("d-none").addClass("d-flex");
21      jQuery("#btn-kit").hide();
22      jQuery("#form-kit").hide();
23    }
24  });
25
26  //Añadimos los enlaces legales a los formularios
27  if (jQuery(".gf-legal a").length) {
28    jQuery(".gf-legal a").each(function (index) {
29      var link = "";
30      if (jQuery(".link-politica-privacidad").attr("href")) {
31        //Si el botón está en un menú
32        link = jQuery(this).attr("href");
33      } else {
34        link = jQuery(this).find("a").attr("href");
35      }
36
37      jQuery(this).attr("href", link);
38      jQuery(this).attr("target", "_blank");
39    });
40  }
41  //Añadimos La página a los envíos de formulario
42  if (jQuery(".gf-page").length) {
43    jQuery(".gf-page").each(function (index) {
44      var $input = jQuery(this).find("input");
45      $input.val(document.title);
46    });
47  }
48
49  //Cookies
50  if (!localStorage.getItem("cookies")) {
51    jQuery(".cookies").css("display", "block");
52    jQuery(".cookies-boton").click(function (e) {
53      localStorage.setItem("cookies", "activa");
54      jQuery(".cookies").slideUp("fast");
55      return false;
56    });
57  }
58  //GTM envío confirmación
59  jQuery(document).bind("gform_confirmation_loaded", function (event, formId) {
60    gtm_tipo = "gtm-pageview";
61    gtm_pag_pag = "/gracias-page" + window.location.pathname;
62    gtm_pag_tit = "Gracias - " + document.title;
63    gtm_pasar();
64  });
65
66  //Añadimos los cierres a los desplegables
67  if (jQuery(".desplegable-lat").length) {
68    jQuery(".desplegable-lat").each(function (index) {
69      var id = jQuery(this).attr("id");
70      jQuery(this).append(
71        '<a href="javascript:void(0)" class="desplegable-fondo desplegable-plegar" data-obj="#' +
72          id +
73          '"></a>',
74      );
75      jQuery(this)
76        .find(".desplegable-lat-bloque-contain")
77        .append(
78          '<a href="javascript:void(0)" class="desplegable-plegar btn-cerrar" data-obj="#' +
79            id +
80            '"><span class="fa fa-times" aria-hidden="true"></span></a>',
81        );
82    });
83  }
84
85  if (jQuery(".popup").length) {
86    jQuery(".popup").each(function (index) {
87      var id = jQuery(this).attr("id");
88      if (!jQuery(this).find("desplegable-fondo").length) {
89        jQuery(this)
90          .find(".popup-bloque")
91          .append(
92            '<a href="javascript:void(0)" class="desplegable-fondo desplegable-plegar" data-obj="#' +
93              id +
94              '"></a>',
95          );
96      }
97      if (!jQuery(this).find(".btn-cerrar").length) {
98        jQuery(this)
99          .find(".popup-bloque-contain")
100          .append(
101            '<a href="javascript:void(0)" class="desplegable-plegar btn-cerrar" data-obj="#' +
102              id +
103              '"><span class="fa fa-times" aria-hidden="true"></span></a>',
104          );
105      }
106    });
107  }
108
109  //Añadimos el botón para desplegar los submenús verticales
110  if (jQuery(".menu-ver .menu-item-has-children").length) {
111    jQuery(".menu-ver .menu-item-has-children").each(function (index) {
112      var btn = '<div class="menu-ver-btn"></div>';
113      jQuery(this).append(btn);
114    });
115  }
116
117  //Animaciones Scroll
118  scroll_pos_init = jQuery(window).scrollTop() + jQuery(window).height();
119  posScroll();
120  let posScrollTicking = false;
121  jQuery(window).scroll(function () {
122    if (!posScrollTicking) {
123      window.requestAnimationFrame(function () {
124        posScroll();
125        posScrollTicking = false;
126      });
127      posScrollTicking = true;
128    }
129  });
130
131  //Resize
132  maquetacion();
133  jQuery(window).resize(maquetacion);
134
135  // Cerrar menú on click fuera
136  jQuery(document).click(function (event) {
137    var click = jQuery(event.target);
138    var _open = jQuery(".navbar-collapse").hasClass("show");
139    if (_open === true && !click.hasClass("navbar-toggler")) {
140      jQuery(".navbar-toggler").click();
141    }
142  });
143
144  let closedCats = true;
145  jQuery(".colapsar-categorias-blog").click(function () {
146    if (closedCats) {
147      jQuery(this)
148        .find("i")
149        .removeClass("fa-chevron-down")
150        .addClass("fa-chevron-up");
151      jQuery(this).find(".colapse-vermas").addClass("d-none");
152      jQuery(this).find(".colapse-vermenos").removeClass("d-none");
153      closedCats = false;
154    } else {
155      jQuery(this)
156        .find("i")
157        .removeClass("fa-chevron-up")
158        .addClass("fa-chevron-down");
159      jQuery(this).find(".colapse-vermenos").addClass("d-none");
160      jQuery(this).find(".colapse-vermas").removeClass("d-none");
161      closedCats = true;
162    }
163  });
164});
165
166jQuery(document).on("updated_checkout", function () {
167  //Inicializamos popover
168  jQuery('[data-toggle="popover"]').popover({ html: true });
169  jQuery(document).on("show.bs.popover", function () {
170    jQuery(".popover").not(this).popover("hide");
171  });
172});
173
174jQuery(document).on("gform_post_render", function (e, f, p) {
175  let placeholder = "¿En qué estás interesado?";
176  if (window.location.href.indexOf("lojahusqvarna") > -1) {
177    placeholder = "Que temas lhe interessam?";
178  }
179  jQuery(".jquery-multiselect select").multiSelect({
180    // Custom templates
181    containerHTML: '<div class="multi-select-container">',
182    menuHTML: '<div class="multi-select-menu">',
183    buttonHTML: '<span class="multi-select-button">',
184    menuItemsHTML: '<div class="multi-select-menuitems">',
185    menuItemHTML: '<label class="multi-select-menuitem">',
186    presetsHTML: '<div class="multi-select-presets">',
187
188    // sets some HTML (eg: <div class="multi-select-modal">) to enable the modal overlay.
189    modalHTML: undefined,
190
191    // Active CSS class
192    activeClass: "multi-select-container--open",
193
194    // Text to show when no option is selected
195    noneText: placeholder,
196
197    // Text to show when all options are selected
198    allText: undefined,
199
200    // an array of preset option groups
201    // presets: [{
202    //   name: 'All categories',
203    //   all: true // select all
204    // },{
205    //   name: 'My categories',
206    //   options: ['a', 'c']
207    // }]
208    presets: undefined,
209
210    // CSS class added to the container, when the menu is about to extend beyond the right edge of the position<a href="https://www.jqueryscript.net/menu/">Menu</a>Within element
211    positionedMenuClass: "multi-select-container--positioned",
212
213    // If you provide a jQuery object here, the plugin will add a class (see positionedMenuClass option) to the container when the right edge of the dropdown menu is about to extend outside the specified element, giving you the opportunity to use CSS to prevent the menu extending, for example, by allowing the option labels to wrap onto multiple lines.
214    positionMenuWithin: undefined,
215
216    // The plugin will attempt to keep this distance, in pixels, clear between the bottom of the menu and the bottom of the viewport, by setting a fixed height style if the menu would otherwise approach this distance from the bottom edge of the viewport.
217    viewportBottomGutter: 20,
218
219    // minimal height
220    menuMinHeight: 200,
221  });
222});
223
224//------------------------------------------------------------------------- Scroll
225function posScroll() {
226  var nav_ancho = jQuery(window).width();
227  var nav_alto = jQuery(window).height();
228  var scroll_pos = jQuery(window).scrollTop();
229
230  var $header = jQuery(".header");
231  if (scroll_pos > 30) {
232    $header.addClass("header-scroll");
233
234    if (scroll_pos > 200) {
235      jQuery(".comprar-flotante").addClass("add-cart-product-float");
236      if (scroll_pos <= scroll_inicial) {
237        $header.removeClass("header-scroll-hide");
238      } else {
239        $header.addClass("header-scroll-hide");
240        scroll_contador = 0;
241      }
242    }
243    //Desplazador
244    jQuery(".desplazador-top").addClass("desplazador-top-show");
245  } else {
246    $header.removeClass("header-scroll header-scroll-hide");
247    jQuery(".desplazador-top").removeClass("desplazador-top-show");
248    jQuery(".comprar-flotante").removeClass("add-cart-product-float");
249    scroll_inicial = 0;
250  }
251
252  //Animaciones Scroll
253  jQuery(".anim-scroll").each(function (index) {
254    var pos = jQuery(this).offset().top;
255    var pos_anim = scroll_pos + nav_alto;
256    if (scroll_pos_init > pos) {
257      jQuery(this).addClass("anim-start");
258    } else if (pos <= pos_anim) {
259      jQuery(this).addClass("anim-start");
260    }
261  });
262
263  //Delimitador
264  scroll_inicial = scroll_pos;
265}
266
267//---------------------------------------------------------------------------------------------------------- Maquetación
268function maquetacion() {}
269
270//----------------------------------------------------------------------------------------------------------- Formulario
271
272jQuery(document).on("gform_post_render", function (e, f, p) {
273  jQuery("#gform_ajax_frame_" + f).attr("src", "about:blank"); //Prevenimos que se envién duplicados en el formulario
274});
275//------------------------------------------------------------------------------------------------------------ MENÚS
276
277//--------- Mostrar submenus horizontales
278jQuery(document).on(
279  "mouseenter",
280  ".menu-hor.menu-pc .menu-item-has-children",
281  function (e) {
282    if (jQuery("body").css("overflow") != "hidden") {
283      var $obj = jQuery(this).find("> .sub-menu");
284      $obj.slideDown("fast", function () {
285        jQuery($obj).css("overflow", "visible");
286      });
287    }
288  },
289);
290
291jQuery(document).on(
292  "mouseleave",
293  ".menu-hor.menu-pc .menu-item-has-children",
294  function (e) {
295    if (jQuery("body").css("overflow") != "hidden") {
296      var $obj = jQuery(this).find("> .sub-menu");
297      $obj.slideUp(0);
298    }
299  },
300);
301
302//--------- Mostrar submenus Verticales
303jQuery(document).on(
304  "click",
305  ".menu-ver .menu-item-has-children .menu-ver-btn",
306  function (e) {
307    var $obj = jQuery(this).siblings(".sub-menu");
308    if (jQuery(this).parent().attr("data-estado")) {
309      $obj.slideUp("fast");
310      jQuery(this).parent().removeAttr("data-estado");
311    } else {
312      $obj.slideDown("fast", function () {
313        jQuery($obj).css("overflow", "visible");
314      });
315      jQuery(this).parent().attr("data-estado", "on");
316    }
317  },
318);
319
320//------------------------------------------------------------------------------------------------------------ DESPLEGABLES LATERALES
321
322jQuery(document).on("click", ".desplegable-desplegar", function (e) {
323  var obj = jQuery(this).attr("data-obj");
324  obj;
325  var $obj = jQuery(obj);
326
327  //Si hay que cambiar el texto
328  if (jQuery(this).data("txt-off")) {
329    jQuery(this).html(jQuery(this).data("txt-off"));
330  }
331
332  //Si hay que cambiar iconos
333  if (jQuery(this).data("ico-on") && jQuery(this).data("ico-off")) {
334    jQuery(this).find(".fa").removeClass(jQuery(this).data("ico-off"));
335    jQuery(this).find(".fa").addClass(jQuery(this).data("ico-on"));
336  }
337
338  //Cambio de elemento si tiene cierre
339  if (
340    jQuery(this).data("txt-on") ||
341    jQuery(this).data("ico-on") ||
342    jQuery(this).data("off")
343  ) {
344    jQuery(this).removeClass("desplegable-desplegar");
345    jQuery(this).addClass("desplegable-plegar");
346  }
347
348  //Función de despliege
349  desplegar_desplegable($obj);
350
351  event.preventDefault();
352});
353
354function desplegar_desplegable($obj) {
355  if ($obj.hasClass("desplegable-lat")) {
356    //Si es botón lateral
357    $obj.addClass("desplegable-lat-visible");
358  } else if ($obj.hasClass("popup")) {
359    //Si es botón lateral
360    $obj.fadeIn("fast");
361  } else {
362    //Si es desplegable simple
363    $obj.slideDown("fast", function () {
364      jQuery($obj).css("overflow", "visible");
365    });
366    jQuery(this).removeClass("desplegable-desplegar");
367    jQuery(this).addClass("desplegable-plegar");
368  }
369
370  //Si hay fondo oscuro
371  if ($obj.find(".desplegable-fondo").length) {
372    $obj.find(".desplegable-fondo").fadeIn("800");
373    jQuery("body").css({
374      height: "100%",
375      overflow: "hidden",
376    });
377  }
378}
379
380//--------- Desplegable Plegar
381jQuery(document).on("click", ".desplegable-plegar", function (e) {
382  e.preventDefault();
383  // Buscamos el popup padre más cercano
384  var $popup = jQuery(this).closest(".popup");
385  if ($popup.length) {
386    $popup.fadeOut("fast");
387    // Si hay fondo, lo cerramos también
388    $popup.find(".desplegable-fondo").fadeOut("800");
389    jQuery("body").css({ height: "auto", overflow: "visible" });
390  }
391});
392jQuery(document).on("click", ".desplegable-plegar", function (e) {
393  var obj = jQuery(this).attr("data-obj");
394  var $obj = jQuery(obj);
395
396  if ($obj.hasClass("desplegable-lat")) {
397    //Si es botón lateral
398    $obj.removeClass("desplegable-lat-visible");
399  } else if ($obj.hasClass("popup")) {
400    //Si es botón lateral
401    $obj.fadeOut("fast");
402  } else {
403    //Si es desplegable simple
404    $obj.slideUp("fast");
405    if (jQuery(this).data("txt-on") || jQuery(this).data("ico-on")) {
406      jQuery(this).removeClass("desplegable-plegar");
407      jQuery(this).addClass("desplegable-desplegar");
408    }
409  }
410
411  //Si hay fondo oscuro
412  if ($obj.find(".desplegable-fondo").length) {
413    $obj.find(".desplegable-fondo").fadeOut("800");
414    jQuery("body").css({
415      height: "auto",
416      overflow: "visible",
417    });
418  }
419
420  //Si hay que cambiar el texto
421  if (jQuery(this).data("txt-on")) {
422    jQuery(this).html(jQuery(this).data("txt-on"));
423  }
424
425  //Si hay que cambiar iconos
426  if (jQuery(this).data("ico-on") && jQuery(this).data("ico-off")) {
427    jQuery(this).find(".fa").removeClass(jQuery(this).data("ico-on"));
428    jQuery(this).find(".fa").addClass(jQuery(this).data("ico-off"));
429  }
430
431  event.preventDefault();
432});
433
434//----------------------------------------------------------------------------------------------------------- Ocultar menú
435jQuery(document).on("click", ".menu-item > a", function (e) {
436  //Revisamos si el menú lateral esta desplegado
437  if (jQuery("body").css("overflow") == "hidden" && jQuery(this).attr("href")) {
438    jQuery("#header-contenedor-movil").css("right", "-100%");
439    jQuery(".desplegable-fondo").fadeOut("800");
440    jQuery(".desplegable-fondo").removeClass("desplegable-lat-plegar");
441    jQuery("body").css({
442      height: "auto",
443      overflow: "visible",
444    });
445  }
446});
447
448//----------------------------------------------------------------------------------------------------------- Desplazar
449jQuery(document).on("click", ".desplazar", function (e) {
450  var destino = "";
451
452  if (jQuery(this).attr("href")) {
453    //Si el botón está en un menú
454    destino = jQuery(this).attr("href");
455  } else {
456    destino = jQuery(this).find("a").attr("href");
457  }
458
459  //Revisamos si tiene una url completa
460  if (destino.indexOf("http") == -1) {
461    //Eliminamos la URL
462    destino = destino.split("#");
463    destino = "#" + destino[1];
464  }
465
466  //Revisamos si el menú lateral esta desplegado
467  if (jQuery("body").css("overflow") == "hidden") {
468    jQuery("#header-contenedor-movil").css("right", "-100%");
469    jQuery(".desplegable-fondo").fadeOut("800");
470    jQuery(".desplegable-fondo").removeClass("desplegable-lat-plegar");
471    jQuery("body").css({
472      height: "auto",
473      overflow: "visible",
474    });
475  }
476
477  //REvisamos si existe el elemento en página para efectuar la animación
478  if (destino == "#") {
479    jQuery("body,html").animate({ scrollTop: 0 }, 500);
480    return false;
481  } else if (jQuery(destino).length) {
482    var distancia = jQuery(destino).offset().top - 20;
483    jQuery("body,html").animate({ scrollTop: distancia - 50 }, 500);
484    return false;
485  }
486});
487
488//***************************************************************************************************************Recuperar parámetros
489
490function getParameterByName(name) {
491  //Recuperar el modo de llegada
492  name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
493  var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
494    results = regex.exec(location.search);
495  return results === null
496    ? ""
497    : decodeURIComponent(results[1].replace(/\+/g, " "));
498}
499
500//***************************************************************************************************************limpiar Cadenas()*/
501function limpiar_cadena(cadena) {
502  // Definimos los caracteres que queremos eliminar
503  var specialChars = "¡!@#$^&%*()+[]{}|:<>¿.";
504  // Los eliminamos todos
505  for (var i = 0; i < specialChars.length; i++) {
506    cadena = cadena.replace(new RegExp("\\" + specialChars[i], "gi"), "");
507  }
508  // Lo queremos devolver limpio en minusculas
509  cadena = cadena.toLowerCase();
510  // Quitamos espacios y los sustituimos por _ porque nos gusta mas asi
511  cadena = cadena.replace(/ /g, "_");
512  // Quitamos acentos y "ñ". Fijate en que va sin comillas el primer parametro
513  cadena = cadena.replace(/-/gi, "_");
514  cadena = cadena.replace(/,/gi, "|");
515  cadena = cadena.replace(/á/gi, "a");
516  cadena = cadena.replace(/é/gi, "e");
517  cadena = cadena.replace(/í/gi, "i");
518  cadena = cadena.replace(/ó/gi, "o");
519  cadena = cadena.replace(/ú/gi, "u");
520  cadena = cadena.replace(/ñ/gi, "n");
521  cadena = cadena.replace(/ň/gi, "n");
522
523  return cadena;
524}
525
526function solo_numeros(cadena) {
527  // Definimos los caracteres que queremos eliminar
528  cadena = cadena.replace(/[^\d]/, "");
529  cadena = cadena.replace(/ /g, "");
530  cadena = cadena.replace(/ /g, "");
531  cadena = cadena.substr(5, cadena.length);
532  return cadena;
533}
534
535//***************************************************************************************************************Fechas()*/
536function conseguir_fecha() {
537  var f = new Date();
538  var f_ano = f.getFullYear();
539  var f_mes = f.getMonth() + 1;
540  var f_dia = f.getDate();
541  var f_hora = f.getHours();
542  var f_min = f.getMinutes();
543  var f_seg = f.getSeconds();
544  var fecha_final = "" + f_ano + f_mes + f_dia + f_hora + f_min + f_seg;
545  return fecha_final;
546}
547
548//***************************************************************************************************************Analítica*/
549var gtm_tipo = undefined;
550var gtm_ev_cat = undefined;
551var gtm_ev_act = undefined;
552var gtm_ev_lab = undefined;
553var gtm_pag_pag = undefined;
554var gtm_pag_tit = undefined;
555
556function gtm_limpiar() {
557  gtm_tipo = undefined;
558  gtm_ev_cat = undefined;
559  gtm_ev_act = undefined;
560  gtm_ev_lab = undefined;
561  gtm_pag_pag = undefined;
562  gtm_pag_tit = undefined;
563}
564
565function gtm_pasar() {
566  dataLayer.push({
567    event: gtm_tipo,
568    event_data: {
569      category: gtm_ev_cat,
570      action: gtm_ev_act,
571      label: gtm_ev_lab,
572    },
573    pageview_data: {
574      page: gtm_pag_pag,
575      title: gtm_pag_tit,
576    },
577  });
578
579  gtm_limpiar();
580}
581
582//----------------------------------------------------------------------------------------------------------- Seguimiento de contactos
583jQuery(document).on("click", ".link-contacto a", function (e) {
584  gtm_tipo = "gtm-event";
585  gtm_ev_cat = "contacto";
586  gtm_ev_act = "clic";
587  gtm_ev_lab = "link";
588  gtm_pasar();
589});
590
591jQuery(document).on("click", ".link-contacto-a", function (e) {
592  gtm_tipo = "gtm-event";
593  gtm_ev_cat = "contacto";
594  gtm_ev_act = "clic";
595  gtm_ev_lab = "link";
596  gtm_pasar();
597});
598
599//----------------------------------------------------------------------------------------------------------- Btn ver mais categorías
600document.addEventListener("DOMContentLoaded", function () {
601  var categoryList = document.querySelector(".category-list");
602  var btnVerMasCategorias = document.querySelector(".btn-ver-mas-categorias");
603
604  if (btnVerMasCategorias) {
605    // Solo si el botón existe
606    btnVerMasCategorias.addEventListener("click", function () {
607      var hiddenItems = categoryList.querySelectorAll("li");
608
609      // Mostrar/ocultar categorías según el estado del botón
610      if (btnVerMasCategorias.textContent === "ver mais categorías") {
611        hiddenItems.forEach(function (item, index) {
612          if (index >= 3) {
613            item.classList.remove("toggler"); // Mostrar los items
614          }
615        });
616        btnVerMasCategorias.textContent = "Ver menos categorías";
617      } else {
618        hiddenItems.forEach(function (item, index) {
619          if (index >= 3) {
620            item.classList.add("toggler"); // Ocultar los items
621          }
622        });
623        btnVerMasCategorias.textContent = "ver mais categorías";
624      }
625
626      // // Hacer scroll a la lista si se colapsa
627      // if (btnVerMasCategorias.textContent === "ver mais categorías") {
628      //   categoryList.scrollIntoView({ behavior: "smooth" });
629      // }
630    });
631  }
632});
633jQuery(document).ready(function ($) {
634  // Seleccionamos el checkbox y el campo de la empresa
635  var $checkbox = $("#billing_eres_empresa");
636  var $companyField = $("#billing_company_field");
637
638  // Comprobamos el estado inicial (si está marcado al cargar la página)
639  if ($checkbox.is(":checked")) {
640    $companyField.removeClass("d-none");
641  } else {
642    $companyField.addClass("d-none");
643  }
644
645  // Al cambiar el estado del checkbox
646  $checkbox.on("change", function () {
647    if ($(this).is(":checked")) {
648      $companyField.removeClass("d-none");
649    } else {
650      $companyField.addClass("d-none");
651    }
652  });
653
654  $(document).on("click", ".boton-add-cart-ficha", function (e) {
655    // e.preventDefault();
656    // console.log("click");
657
658    const button = this;
659    if (!$(button).hasClass("loading")) {
660      $(button).addClass("loading");
661      setTimeout(() => $(button).removeClass("loading"), 3700);
662    }
663  });
664  $(document).on("click", ".single_add_to_cart_button", function (e) {
665    const button = this;
666    if (!$(button).hasClass("loading")) {
667      $(button).addClass("loading");
668      setTimeout(() => $(button).removeClass("loading"), 3700);
669    }
670  });
671  jQuery(document.body).on(
672    "added_to_cart",
673    function (e, fragments, cart_hash, $button) {
674      cambio_boton_minicart();
675
676      jQuery.ajax({
677        type: "POST",
678        url: urlAjax,
679        data: { action: "cambio_minicart" },
680        success: function (response) {
681          jQuery("#mini-cart-content").html(response);
682          var $miniCart = jQuery("#mini-cart");
683          desplegar_desplegable($miniCart);
684        },
685      });
686    },
687  );
688});
689document.addEventListener("DOMContentLoaded", function () {
690  document.body.addEventListener("click", function (e) {
691    const trigger = e.target.closest('[data-bs-toggle="popover"]');
692    if (!trigger) return;
693
694    e.preventDefault();
695
696    let pop = bootstrap.Popover.getInstance(trigger);
697    if (!pop) {
698      pop = new bootstrap.Popover(trigger, {
699        container: "body",
700        html: true,
701        trigger: "manual",
702      });
703      pop.show();
704    } else {
705      pop.toggle();
706    }
707  });
708});
709document.addEventListener("DOMContentLoaded", function () {
710  // Backdrop propio para offcanvasCondiciones (z-index distinto al resto)
711  const offcanvasCondiciones = document.getElementById("offcanvasCondiciones");
712  if (offcanvasCondiciones) {
713    offcanvasCondiciones.addEventListener("show.bs.offcanvas", function () {
714      requestAnimationFrame(function () {
715        const backdrops = document.querySelectorAll(
716          ".offcanvas-backdrop:not(.offcanvas-backdrop-condiciones)",
717        );
718        const backdrop = backdrops[backdrops.length - 1];
719        if (backdrop) backdrop.classList.add("offcanvas-backdrop-condiciones");
720      });
721    });
722  }
723});
724
725document.addEventListener("DOMContentLoaded", function () {
726  document.querySelectorAll(".item-conditions").forEach(function (btn) {
727    btn.addEventListener("click", function () {
728      var condition = this.dataset.condition;
729
730      // Primero ocultar todos
731      document
732        .querySelectorAll("#offcanvasCondiciones [data-condition]")
733        .forEach(function (el) {
734          el.classList.add("d-none");
735        });
736
737      // Luego mostrar solo los del condition pulsado
738      document
739        .querySelectorAll(
740          '#offcanvasCondiciones [data-condition="' + condition + '"]',
741        )
742        .forEach(function (el) {
743          el.classList.remove("d-none");
744        });
745    });
746  });
747});
748
749document.addEventListener("DOMContentLoaded", function () {
750  // Navbar sticky al hacer scroll
751  (function () {
752    const navbar = document.querySelector(".navbar");
753    const topbar = document.querySelector(".w-top-header");
754    const promoBar = document.querySelector(".promo-bar");
755    if (!navbar || !topbar) return;
756
757    let topbarHeight = topbar.offsetHeight;
758    let navbarHeight = navbar.offsetHeight;
759    let isSticky = false;
760
761    window.addEventListener("resize", function () {
762      topbarHeight = topbar.offsetHeight;
763      navbarHeight = navbar.offsetHeight;
764    });
765
766    let ticking = false;
767    window.addEventListener("scroll", function () {
768      if (!ticking) {
769        window.requestAnimationFrame(function () {
770          const scrollY = window.scrollY;
771          if (scrollY > topbarHeight && !isSticky) {
772            navbar.classList.add("navbar-sticky");
773            if (promoBar) {
774              promoBar.classList.add("promo-bar-sticky");
775              promoBar.style.top = navbarHeight + "px";
776            }
777            isSticky = true;
778          } else if (scrollY <= topbarHeight && isSticky) {
779            navbar.classList.remove("navbar-sticky");
780            if (promoBar) {
781              promoBar.classList.remove("promo-bar-sticky");
782              promoBar.style.top = "";
783            }
784            isSticky = false;
785          }
786          ticking = false;
787        });
788        ticking = true;
789      }
790    });
791  })();
792});
793
794// Eventos del menú
795document.addEventListener("DOMContentLoaded", function () {
796  const megamenu = document.getElementById("offcanvasMegaMenu");
797  const buscador = document.getElementById("offcanvasBuscador");
798  const miniCart = document.getElementById("mini-cart");
799  if (!megamenu) return;
800
801  // Helpers para cerrar cada elemento
802  function closeMegamenu() {
803    if (megamenu.classList.contains("show")) {
804      const inst = bootstrap.Offcanvas.getInstance(megamenu);
805      if (inst) inst.hide();
806    }
807  }
808  function closeBuscador() {
809    if (buscador && buscador.classList.contains("show")) {
810      buscador.classList.remove("show");
811      const overlay = document.querySelector(".algolia-overlay.show");
812      if (overlay) overlay.classList.remove("show");
813    }
814  }
815  function closeDropdowns() {
816    document.querySelectorAll(".dropdown-menu.show").forEach(function (menu) {
817      const toggle = menu.previousElementSibling;
818      if (toggle) {
819        const dropdown = bootstrap.Dropdown.getInstance(toggle);
820        if (dropdown) dropdown.hide();
821      }
822    });
823  }
824  function closeMiniCart() {
825    if (miniCart && miniCart.classList.contains("desplegable-lat-visible")) {
826      miniCart.classList.remove("desplegable-lat-visible");
827      const fondo = miniCart.querySelector(".desplegable-fondo");
828      if (fondo) jQuery(fondo).fadeOut("800");
829      jQuery("body").css({ height: "auto", overflow: "visible" });
830    }
831  }
832
833  // Al abrir megamenú → cerrar buscador, dropdowns y mini-cart
834  megamenu.addEventListener("show.bs.offcanvas", function () {
835    closeBuscador();
836    closeDropdowns();
837    closeMiniCart();
838  });
839
840  // Al abrir buscador → cerrar megamenú, dropdowns y mini-cart
841  if (buscador) {
842    const buscadorObserver = new MutationObserver(function () {
843      if (buscador.classList.contains("show")) {
844        closeMegamenu();
845        closeDropdowns();
846        closeMiniCart();
847        addBlur();
848      } else {
849        removeBlur();
850      }
851    });
852    buscadorObserver.observe(buscador, {
853      attributes: true,
854      attributeFilter: ["class"],
855    });
856  }
857
858  // Al hacer click en dropdown → cerrar megamenú, buscador y mini-cart
859  document
860    .querySelectorAll(".navbar-static-links .dropdown-toggle")
861    .forEach(function (toggle) {
862      toggle.addEventListener("click", function () {
863        closeMegamenu();
864        closeBuscador();
865        closeMiniCart();
866      });
867    });
868
869  // Al abrir mini-cart → cerrar megamenú, buscador y dropdowns
870  if (miniCart) {
871    const miniCartObserver = new MutationObserver(function () {
872      if (miniCart.classList.contains("desplegable-lat-visible")) {
873        closeMegamenu();
874        closeBuscador();
875        closeDropdowns();
876      }
877    });
878    miniCartObserver.observe(miniCart, {
879      attributes: true,
880      attributeFilter: ["class"],
881    });
882  }
883
884  // Toggle columnas megamenú
885  megamenu.addEventListener("click", function (e) {
886    const item = e.target.closest(".megamenu-parent-item");
887    if (!item) return;
888
889    if (item.dataset.hasChildren === "0") {
890      window.location.href = item.dataset.url;
891      return;
892    }
893
894    const catId = item.dataset.catId;
895
896    megamenu
897      .querySelectorAll(".megamenu-parent-item")
898      .forEach((el) => el.classList.remove("is-active"));
899    item.classList.add("is-active");
900
901    megamenu
902      .querySelectorAll(".megamenu-child-list")
903      .forEach((el) => el.classList.remove("is-active"));
904    const targetSubcats = megamenu.querySelector(
905      `.megamenu-child-list[data-cat-id="${catId}"]`,
906    );
907    if (targetSubcats) targetSubcats.classList.add("is-active");
908
909    megamenu
910      .querySelectorAll(".megamenu-popular-block")
911      .forEach((el) => el.classList.remove("is-active"));
912    const targetPopular = megamenu.querySelector(
913      `.megamenu-popular-block[data-cat-id="${catId}"]`,
914    );
915    if (targetPopular) targetPopular.classList.add("is-active");
916
917    megamenu
918      .querySelectorAll(".megamenu-promo-block")
919      .forEach((el) => el.classList.remove("is-active"));
920    const targetBanner = megamenu.querySelector(
921      `.megamenu-promo-block[data-cat-id="${catId}"]`,
922    );
923    if (targetBanner) targetBanner.classList.add("is-active");
924  });
925
926  // Activo en trigger del megamenú
927  const megaMenuTrigger = document.querySelector('[href="#offcanvasMegaMenu"]');
928  if (megaMenuTrigger) {
929    megamenu.addEventListener("show.bs.offcanvas", function () {
930      megaMenuTrigger.classList.add("active");
931    });
932    megamenu.addEventListener("hide.bs.offcanvas", function () {
933      megaMenuTrigger.classList.remove("active");
934    });
935  }
936
937  // Activo en dropdowns del walker
938  document
939    .querySelectorAll(".navbar-static-links .dropdown")
940    .forEach(function (li) {
941      li.addEventListener("show.bs.dropdown", function () {
942        li.querySelector(":scope > .dropdown-toggle")?.classList.add("active");
943      });
944      li.addEventListener("hide.bs.dropdown", function () {
945        li.querySelector(":scope > .dropdown-toggle")?.classList.remove(
946          "active",
947        );
948      });
949    });
950
951  // Blur de fondo al abrir menús
952  function addBlur() {
953    document.body.classList.add("menu-blur");
954  }
955  function removeBlur() {
956    const dropdownOpen = document.querySelector(
957      ".navbar-static-links .dropdown-menu.show",
958    );
959    const megamenuOpen = megamenu.classList.contains("show");
960    const buscadorOpen = buscador && buscador.classList.contains("show");
961    if (!dropdownOpen && !megamenuOpen && !buscadorOpen) {
962      document.body.classList.remove("menu-blur");
963    }
964  }
965
966  megamenu.addEventListener("show.bs.offcanvas", addBlur);
967  megamenu.addEventListener("hidden.bs.offcanvas", removeBlur);
968
969  if (buscador) {
970    buscador.addEventListener("show.bs.offcanvas", addBlur);
971    buscador.addEventListener("hidden.bs.offcanvas", removeBlur);
972  }
973
974  document
975    .querySelectorAll(".navbar-static-links .dropdown")
976    .forEach(function (li) {
977      li.addEventListener("show.bs.dropdown", addBlur);
978      li.addEventListener("hidden.bs.dropdown", removeBlur);
979    });
980});
981
982document.addEventListener("DOMContentLoaded", function () {
983  const mobileMenu = document.getElementById("offcanvasMobileMenu");
984  if (!mobileMenu) return;
985
986  const slider = mobileMenu.querySelector(".mobile-menu-slider");
987
988  function slideToScreen(screen) {
989    if (screen === "subcats") {
990      slider.classList.add("subcats-open");
991    } else {
992      slider.classList.remove("subcats-open");
993    }
994  }
995
996  function syncTabs(panelId) {
997    mobileMenu.querySelectorAll(".mobile-menu-tab").forEach((t) => {
998      t.classList.toggle("is-active", t.dataset.panel === panelId);
999    });
1000  }
1001
1002  function activatePanel(panelId) {
1003    mobileMenu.querySelectorAll(".mobile-panel").forEach((p) => {
1004      p.classList.remove("is-active");
1005      p.style.cssText = "";
1006    });
1007    const target = mobileMenu.querySelector(
1008      `.mobile-panel[data-panel="${panelId}"]`,
1009    );
1010    if (target) target.classList.add("is-active");
1011  }
1012
1013  // Cambio de tab
1014  mobileMenu.addEventListener("click", function (e) {
1015    const tab = e.target.closest(".mobile-menu-tab");
1016    if (!tab) return;
1017
1018    if (tab.dataset.hasChildren === "0") {
1019      window.location.href = tab.dataset.url;
1020      return;
1021    }
1022
1023    const panelId = tab.dataset.panel;
1024    slideToScreen("main");
1025    syncTabs(panelId);
1026    activatePanel(panelId);
1027  });
1028
1029  // Click en categoría padre → pantalla 2
1030  mobileMenu.addEventListener("click", function (e) {
1031    const catItem = e.target.closest(".mobile-panel-item--cat");
1032    if (!catItem) return;
1033
1034    if (catItem.dataset.hasChildren === "0") {
1035      window.location.href = catItem.dataset.url;
1036      return;
1037    }
1038
1039    const catId = catItem.dataset.catId;
1040    const catName = catItem.querySelector("span").textContent;
1041
1042    const backLabel = mobileMenu.querySelector("#mobileBackLabel");
1043    if (backLabel) backLabel.textContent = catName;
1044
1045    mobileMenu
1046      .querySelectorAll(".mobile-subcats-list")
1047      .forEach((l) => l.classList.add("d-none"));
1048    const targetList = mobileMenu.querySelector(
1049      `.mobile-subcats-list[data-cat-id="${catId}"]`,
1050    );
1051    if (targetList) targetList.classList.remove("d-none");
1052
1053    mobileMenu
1054      .querySelectorAll(".mobile-popular-block")
1055      .forEach((b) => b.classList.add("d-none"));
1056    const targetPopular = mobileMenu.querySelector(
1057      `.mobile-popular-block[data-cat-id="${catId}"]`,
1058    );
1059    if (targetPopular) targetPopular.classList.remove("d-none");
1060
1061    mobileMenu
1062      .querySelectorAll(".mobile-banner-block")
1063      .forEach((b) => b.classList.add("d-none"));
1064    const targetBanner = mobileMenu.querySelector(
1065      `.mobile-banner-block[data-cat-id="${catId}"]`,
1066    );
1067    if (targetBanner) targetBanner.classList.remove("d-none");
1068
1069    slideToScreen("subcats");
1070  });
1071
1072  // Botón volver
1073  mobileMenu.addEventListener("click", function (e) {
1074    if (!e.target.closest(".mobile-panel-back")) return;
1075    slideToScreen("main");
1076  });
1077
1078  // Reset al cerrar
1079  mobileMenu.addEventListener("hidden.bs.offcanvas", function () {
1080    slideToScreen("main");
1081    slider.style.transition = "none";
1082    setTimeout(() => {
1083      slider.style.transition = "";
1084    }, 50);
1085    syncTabs("productos");
1086    activatePanel("productos");
1087    mobileMenu
1088      .querySelectorAll(".mobile-subcats-list")
1089      .forEach((l) => l.classList.add("d-none"));
1090    mobileMenu
1091      .querySelectorAll(".mobile-popular-block")
1092      .forEach((b) => b.classList.add("d-none"));
1093    mobileMenu
1094      .querySelectorAll(".mobile-banner-block")
1095      .forEach((b) => b.classList.add("d-none"));
1096    mobileMenu.querySelector("#mobileBackLabel").textContent = "";
1097  });
1098});
1099document.addEventListener("DOMContentLoaded", function () {
1100  // Solo ejecutar si el banner existe (solo en portada)
1101  var bannerSenior = document.getElementById("banner-senior");
1102  if (!bannerSenior) return;
1103
1104  setTimeout(function () {
1105    bannerSenior.classList.add("activo");
1106  }, 25000);
1107
1108  document.addEventListener("click", function (e) {
1109    if (!e.target.closest("#banner-senior .close")) return;
1110    bannerSenior.classList.remove("activo");
1111  });
1112});
1113
1114// fav-heart: marca los botones cuyo producto ya está en la wishlist y actualiza icono del header
1115function husqvarnaUpdateWishlistButtons() {
1116  if (typeof husqvarna_wishlist === "undefined" || !Array.isArray(husqvarna_wishlist.ids)) return;
1117  document.querySelectorAll(".fav-heart[data-product-id]").forEach(function(btn) {
1118    var id = parseInt(btn.dataset.productId, 10);
1119    var isAdded = husqvarna_wishlist.ids.indexOf(id) !== -1;
1120    btn.classList.toggle("added", isAdded);
1121    btn.title = isAdded ? "Eliminar dos favoritos" : "Adicionar aos favoritos";
1122  });
1123  var favIcon = document.getElementById("header-fav-icon");
1124  if (favIcon) {
1125    favIcon.src = husqvarna_wishlist.ids.length > 0 ? favIcon.dataset.srcFilled : favIcon.dataset.srcEmpty;
1126  }
1127}
1128
1129// MutationObserver en #hits para re-marcar cuando Algolia re-renderiza (filtros, paginación)
1130document.addEventListener("DOMContentLoaded", function() {
1131  husqvarnaUpdateWishlistButtons();
1132  var hits = document.getElementById("hits");
1133  if (hits) {
1134    new MutationObserver(husqvarnaUpdateWishlistButtons).observe(hits, { childList: true, subtree: true });
1135  }
1136});
1137
1138// fav-heart: muestra el banner de confirmación con el texto indicado y lo oculta a los 6s
1139// opts.mode: "add" (por defecto, enlace "Ir a favoritos") o "remove" (enlace "Cancelar" para deshacer)
1140function husqvarnaShowFavoritosBanner(text, opts) {
1141  opts = opts || {};
1142  var bannerFavoritos = document.getElementById("banner-favoritos");
1143  if (!bannerFavoritos) return;
1144  var bannerFavoritosText = document.getElementById("banner-favoritos-text");
1145  if (bannerFavoritosText) bannerFavoritosText.textContent = text;
1146
1147  var favLink = bannerFavoritos.querySelector(".fav-link");
1148  if (favLink) {
1149    if (opts.mode === "remove") {
1150      favLink.textContent = "Cancelar";
1151      favLink.setAttribute("href", "javascript:void(0)");
1152      favLink.dataset.action = "cancel-remove";
1153      favLink.dataset.productId = opts.productId;
1154    } else {
1155      favLink.textContent = "Ir para favoritos";
1156      favLink.setAttribute("href", "/favoritos/");
1157      delete favLink.dataset.action;
1158      delete favLink.dataset.productId;
1159    }
1160  }
1161
1162  bannerFavoritos.classList.add("activo");
1163  clearTimeout(bannerFavoritos._husqvarnaTimeout);
1164  bannerFavoritos._husqvarnaTimeout = setTimeout(function() {
1165    bannerFavoritos.classList.remove("activo");
1166  }, 6000);
1167}
1168
1169// fav-heart: botón de cierre manual del banner
1170document.addEventListener("click", function(e) {
1171  if (!e.target.closest(".close-fav")) return;
1172  var bannerFavoritos = document.getElementById("banner-favoritos");
1173  if (!bannerFavoritos) return;
1174  clearTimeout(bannerFavoritos._husqvarnaTimeout);
1175  bannerFavoritos.classList.remove("activo");
1176});
1177
1178// fav-heart: añade un producto a la wishlist vía AJAX (usado tanto al pulsar el corazón como al cancelar una retirada)
1179function husqvarnaAddToWishlist(id, btn) {
1180  jQuery.ajax({
1181    type: "POST",
1182    url: husqvarna_wishlist.ajax_url,
1183    data: { action: "husqvarna_add_to_wishlist", product_id: id, nonce: husqvarna_wishlist.nonce },
1184    success: function(response) {
1185      if (!response.success) return;
1186      if (husqvarna_wishlist.ids.indexOf(id) === -1) husqvarna_wishlist.ids.push(id);
1187      husqvarnaUpdateWishlistButtons();
1188      if (typeof window.dataLayer !== "undefined" && btn) {
1189        var favPrice = parseFloat(btn.dataset.price) || 0;
1190        window.dataLayer.push({ ecommerce: null });
1191        window.dataLayer.push({
1192          event: "add_to_wishlist",
1193          ecommerce: {
1194            currency: "EUR",
1195            value: favPrice,
1196            items: [{
1197              item_id: btn.dataset.sku || String(id),
1198              item_name: btn.dataset.name || "",
1199              item_brand: "Husqvarna",
1200              item_category: btn.dataset.category || "",
1201              price: favPrice,
1202              quantity: 1
1203            }]
1204          }
1205        });
1206      }
1207    }
1208  });
1209}
1210
1211// fav-heart: enlace "Cancelar" del banner — deshace una retirada de favoritos reciente
1212document.addEventListener("click", function(e) {
1213  var cancelLink = e.target.closest('.fav-link[data-action="cancel-remove"]');
1214  if (!cancelLink) return;
1215  e.preventDefault();
1216
1217  var id = parseInt(cancelLink.dataset.productId, 10);
1218  if (!id) return;
1219
1220  var btn = document.querySelector('.fav-heart[data-product-id="' + id + '"]');
1221  husqvarnaAddToWishlist(id, btn);
1222
1223  // Si la fila de favoritos aún no se ha eliminado del DOM, se restaura su visibilidad
1224  var row = document.getElementById("yith-wcwl-row-" + id);
1225  if (row) row.style.opacity = "1";
1226
1227  var bannerFavoritos = document.getElementById("banner-favoritos");
1228  if (bannerFavoritos) {
1229    clearTimeout(bannerFavoritos._husqvarnaTimeout);
1230    bannerFavoritos.classList.remove("activo");
1231  }
1232});
1233
1234// fav-heart: delegated handler — añade o elimina según estado del botón
1235document.addEventListener("click", function(e) {
1236  var btn = e.target.closest(".fav-heart");
1237  if (!btn) return;
1238  e.preventDefault();
1239  e.stopPropagation();
1240
1241  if (typeof husqvarna_wishlist === "undefined") return;
1242
1243  var productId = btn.dataset.productId || btn.dataset.rowId;
1244  if (!productId) return;
1245  var id = parseInt(productId, 10);
1246
1247  if (!btn.classList.contains("added")) btn.classList.toggle("is-animating");
1248
1249  if (btn.classList.contains("added")) {
1250    // Eliminar de la wishlist
1251    jQuery.ajax({
1252      type: "POST",
1253      url: husqvarna_wishlist.ajax_url,
1254      data: { action: "husqvarna_remove_from_wishlist", product_id: id, nonce: husqvarna_wishlist.nonce },
1255      success: function(response) {
1256        if (response.success) {
1257          var idx = husqvarna_wishlist.ids.indexOf(id);
1258          if (idx !== -1) husqvarna_wishlist.ids.splice(idx, 1);
1259          btn.classList.remove("added");
1260          husqvarnaUpdateWishlistButtons();
1261          husqvarnaShowFavoritosBanner("Eliminado dos favoritos.", { mode: "remove", productId: id });
1262          if (typeof window.dataLayer !== "undefined") {
1263            var favPrice = parseFloat(btn.dataset.price) || 0;
1264            window.dataLayer.push({ ecommerce: null });
1265            window.dataLayer.push({
1266              event: "remove_from_wishlist",
1267              ecommerce: {
1268                currency: "EUR",
1269                value: favPrice,
1270                items: [{
1271                  item_id: btn.dataset.sku || String(id),
1272                  item_name: btn.dataset.name || "",
1273                  item_brand: "Husqvarna",
1274                  item_category: btn.dataset.category || "",
1275                  price: favPrice,
1276                  quantity: 1
1277                }]
1278              }
1279            });
1280          }
1281          // En la página de favoritos: ocultar y eliminar la card del DOM
1282          var row = document.getElementById("yith-wcwl-row-" + id);
1283          if (row) {
1284            row.style.transition = "opacity 0.3s";
1285            row.style.opacity = "0";
1286            setTimeout(function() { row.remove(); }, 300);
1287          }
1288        }
1289      }
1290    });
1291  } else {
1292    // Añadir a la wishlist
1293    husqvarnaAddToWishlist(id, btn);
1294    husqvarnaShowFavoritosBanner("Adicionado aos favoritos!", { mode: "add" });
1295  }
1296}, true); // capture phase: interceptamos antes de que el <a> padre procese el click
1297
1298document.addEventListener("touchstart", function(e) {
1299  var btn = e.target.closest(".fav-heart");
1300  if (btn && !btn.classList.contains("added")) btn.classList.toggle("is-animating");
1301}, { passive: true });
1302
1303document.addEventListener("animationend", function(e) {
1304  if (e.target.classList.contains("fav-heart")) e.target.classList.toggle("is-animating");
1305});

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.