PageSourceSearch

https://maimongroup.co.il/wp-content/themes/maimon/assets/front/js/app.min.js?ver=1791598002

js maimongroup.co.il collected 2026-10-10 02:07:35 UTC 112,486 bytes, 3,351 lines download raw bytes

1(function ($) {
2  $(document).ready(function () {
3    const _ajax_url = cjpg_ajax_obj.ajaxurl;
4    const _nonce = cjpg_ajax_obj.nonce;
5    const _is_rtl = cjpg_ajax_obj.is_rtl;
6    const _words = cjpg_ajax_obj.words;
7    let wakeLock = null;
8    let ytPlayer;
9
10    $(document).on(
11      "click",
12      ".search_header_area_desktop_btn .button_search_toggle",
13      function (e) {
14        e.preventDefault();
15        _header.show_search_desktop($(this));
16      },
17    );
18    $(document).on(
19      "click",
20      ".search_header_area_mobile_btn .button_search_toggle",
21      function (e) {
22        e.preventDefault();
23        _header.toggle_search_mobile($(this));
24      },
25    );
26    $(document).on("click", function (e) {
27      _header.hide_search_desktop(e);
28    });
29
30    $(document).on("click", ".header_mobile_icon_btn", function (e) {
31      e.preventDefault();
32      _header.toggle_mobile_menu($(this));
33    });
34    $(document).on(
35      "click",
36      ".mobile_header_inner_block_inner .menu-item-has-children > a",
37      function (e) {
38        _header.toggle_mobile_menu_inside(
39          e,
40          $(this),
41          $(".mobile_header_inner_block_inner .menu-item-has-children"),
42        );
43      },
44    );
45    $(document).on("click", ".mobile_overlay_close", function (e) {
46      e.preventDefault();
47      const $btn = $(".header_mobile_icon_btn.active").first();
48      if ($btn.length) {
49        _header.toggle_mobile_menu($btn, true);
50      }
51    });
52    $(document).on("click", "#mobile_header_inner_block_toggle", function (e) {
53      if ($(e.target).is("#mobile_header_inner_block_toggle")) {
54        const $btn = $(".header_mobile_icon_btn.active").first();
55        if ($btn.length) {
56          _header.toggle_mobile_menu($btn, true);
57        }
58      }
59    });
60    $(window).on("scroll", function () {
61      if ($(this).scrollTop() > 100) {
62        _header.sticky(true);
63      } else {
64        _header.sticky(false);
65      }
66    });
67
68    const _header = {
69      sticky: function (bool) {
70        const _t_header = $(".maimon_header");
71        if (window.innerWidth <= 1024) {
72          _t_header.removeClass("stickyHeader");
73          return;
74        }
75        if (bool) {
76          _t_header.addClass("stickyHeader");
77        } else {
78          _t_header.removeClass("stickyHeader");
79        }
80      },
81      show_search_desktop: function ($this) {
82        const _target = $($this.attr("data-target"));
83        const _parent = $("#" + $this.attr("data-parent"));
84        if (_target && _target.length > 0 && _parent && _parent.length > 0) {
85          _parent.hide();
86          _target.removeClass("invisible");
87        }
88        return true;
89      },
90      hide_search_desktop: function (event) {
91        const $el = $(".search_area_widget");
92        const $btn = $(".button_search_toggle");
93        const $btn_parent = $("#" + $btn.attr("data-parent"));
94        if (
95          !$el.is(event.target) &&
96          !$el.has(event.target).length &&
97          !$btn.is(event.target) &&
98          !$btn.has(event.target).length &&
99          !$el.hasClass("invisible")
100        ) {
101          $el.addClass("invisible"); // Hide the block
102          $btn_parent.show();
103        }
104      },
105      toggle_search_mobile: function ($this, bool = false) {
106        const _target = $("#" + $this.attr("aria-controls"));
107        const _o1 = $(".search_open_svg");
108        const _o2 = $(".search_close_svg");
109        if (_target && _target.length > 0) {
110          if (!$this.hasClass("active") && bool === false) {
111            _target.slideDown(200);
112            _o1.hide();
113            _o2.show();
114            $this.addClass("active");
115          } else {
116            _target.slideUp(200);
117            _o1.show();
118            _o2.hide();
119            $this.removeClass("active");
120          }
121        }
122        const mobile_menu_btn = $(".header_mobile_icon_btn");
123        if (
124          mobile_menu_btn &&
125          mobile_menu_btn.length > 0 &&
126          mobile_menu_btn.hasClass("active") &&
127          $this.hasClass("active")
128        ) {
129          mobile_menu_btn.removeClass("active");
130          this.toggle_mobile_menu(mobile_menu_btn, true);
131        }
132        return true;
133      },
134      toggle_mobile_menu: function ($this, bool = false) {
135        const _target = $("#" + $this.attr("aria-controls"));
136        const _body = $("body");
137        const _html = $("html");
138        if (_target && _target.length > 0) {
139          if (!$this.hasClass("active") && bool === false) {
140            const topBarHeight = Math.round(
141              $(".maimon-top-bar:visible").outerHeight() || 0,
142            );
143            const headerHeight = Math.round(
144              $(".maimon_header").outerHeight() || 0,
145            );
146            const overlayTop = Math.max(topBarHeight + headerHeight - 1, 0);
147            const overlayHeight = Math.max(window.innerHeight - overlayTop, 0);
148            _html.addClass("preventor");
149            _body.addClass("preventor");
150            _target.find(".menu-item-has-children").removeClass("active");
151            _target
152              .css({ top: overlayTop + "px", height: 0, display: "block" })
153              .animate({ height: overlayHeight + "px" }, 200);
154            $this.addClass("active");
155          } else {
156            _html.removeClass("preventor");
157            _body.removeClass("preventor");
158            _target.animate({ height: 0 }, 200, function () {
159              $(this).css("display", "none");
160            });
161            $this.removeClass("active");
162          }
163          const _mobile_search_btn = $(
164            ".search_header_area_mobile_btn .button_search_toggle",
165          );
166          if (
167            _mobile_search_btn &&
168            _mobile_search_btn.length > 0 &&
169            _mobile_search_btn.hasClass("active") &&
170            $this.hasClass("active")
171          ) {
172            _mobile_search_btn.removeClass("active");
173            this.toggle_search_mobile(_mobile_search_btn, true);
174          }
175        }
176        return true;
177      },
178      toggle_mobile_menu_inside: function (e, $this, $all) {
179        const $item = $this.closest(".menu-item-has-children");
180        if (!$item.length || !$item.children(".sub-menu").length) {
181          return true;
182        }
183        e.preventDefault();
184        if ($item.hasClass("active")) {
185          $item.removeClass("active");
186        } else {
187          $all.removeClass("active");
188          $item.addClass("active");
189        }
190        return true;
191      },
192      handle_hover_image: function () {
193        $(".menu-link").each(function () {
194          const $link = $(this);
195          const $defaultImg = $link.find(".menu-icon-default");
196          const $hoverImg = $link.find(".menu-icon-hover");
197          if ($defaultImg.length && $hoverImg.length && $hoverImg.attr("src")) {
198            const defaultSrc = $defaultImg.attr("src");
199            const hoverSrc = $hoverImg.attr("src");
200            $hoverImg.remove();
201            // Keep brand logos in original colors.
202            // Only force hover asset when the known default logo is white-on-transparent.
203            const isWhiteMaimonsSvg = /\/Maimons\.svg(?:\?|$)/i.test(
204              defaultSrc,
205            );
206            if (isWhiteMaimonsSvg) {
207              $defaultImg.attr("src", hoverSrc);
208              return;
209            }
210            $link.on("mouseenter focus", function () {
211              $defaultImg.attr("src", hoverSrc);
212            });
213            $link.on("mouseleave blur", function () {
214              $defaultImg.attr("src", defaultSrc);
215            });
216          } else if ($hoverImg.length) {
217            $hoverImg.remove();
218          }
219        });
220      },
221    };
222    _header.handle_hover_image();
223
224    const FAVORITES_KEY = "mamon_favorites_list";
225    const _favorites = {
226      init: function () {
227        this.markFavoritesOnLoad();
228        this.bindEvents();
229        this.loadFavoritesPageIfExists();
230      },
231      bindEvents: function () {
232        $(document).on("click", ".toggle_favorite", function (e) {
233          e.preventDefault();
234          _favorites.toggle_favorite($(this));
235        });
236      },
237      toggle_favorite: function ($this) {
238        const _post_id = $this.attr("data-id");
239        const _target = $("#favorite_btn_wrapper_inner_toggle_" + _post_id);
240        if (!_post_id) return true;
241        let favorites = this.getFavorites();
242        const index = favorites.indexOf(_post_id);
243        const isNowFavorite = index === -1;
244        if (isNowFavorite) {
245          favorites.push(_post_id);
246          _target.addClass("favorite_item");
247          this.setFilledIcon(_target);
248        } else {
249          favorites.splice(index, 1);
250          _target.removeClass("favorite_item");
251          this.setOutlineIcon(_target);
252        }
253        this.saveFavorites(favorites);
254        return true;
255      },
256      setFilledIcon: function ($el) {
257        $el.html(`
258                    <svg xmlns="http://www.w3.org/2000/svg" width="42" height="36" viewBox="0 0 42 36" fill="none">
259                        <path d="M12 1C5.925 1 1 5.87823 1 11.8955C1 22.7911 14 32.6961 21 35C28 32.6961 41 22.7911 41 11.8955C41 5.87823 36.075 1 3
2590 1C26.28 1 22.99 2.82946 21 5.62961C19.9857 4.19854 18.6382 3.03062 17.0715 2.22475C15.5049 1.41887 13.7653 0.998766 12 1Z" fill="#334783" stroke="#334783" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
260                    </svg>
261                `);
262      },
263      setOutlineIcon: function ($el) {
264        $el.html(`
265                    <svg xmlns="http://www.w3.org/2000/svg" width="42" height="36" viewBox="0 0 42 36" fill="none">
266                        <path d="M12 1C5.925 1 1 5.87823 1 11.8955C1 22.7911 14 32.6961 21 35C28 32.6961 41 22.7911 41 11.8955C41 5.87823 36.075 1 30 1C26.28 1 22.99 2.82946 21 5.62961C19.9857 4.19854 18.6382 3.03062 17.0715 2.22475C15.5049 1.41887 13.7653 0.998766 12 1Z" stroke="#334783" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
267                    </svg>
268                `);
269      },
270      getFavorites: function () {
271        try {
272          return JSON.parse(localStorage.getItem(FAVORITES_KEY)) || [];
273        } catch (e) {
274          return [];
275        }
276      },
277      saveFavorites: function (list) {
278        localStorage.setItem(FAVORITES_KEY, JSON.stringify(list));
279      },
280      markFavoritesOnLoad: function () {
281        const favorites = this.getFavorites();
282        favorites.forEach(function (_post_id) {
283          const $target = $("#favorite_btn_wrapper_inner_toggle_" + _post_id);
284          $target.addClass("favorite_item");
285          _favorites.setFilledIcon($target);
286        });
287      },
288      loadFavoritesPageIfExists: function () {
289        const _fv = this;
290        const $favoritesPage = $("#page_favorite_list_wrapper");
291        if ($favoritesPage && $favoritesPage.length > 0) {
292          const favorites = this.getFavorites();
293          if (favorites.length === 0) {
294            $favoritesPage.html(
295              '<div class="favorite_list_wrapper_empty"><h5>' +
296                cjpg_ajax_obj.words.you_dont_have_favorites_recipes_yet +
297                "</h5></div>",
298            );
299            return;
300          }
301          _fv.favorite_loader(true);
302          $.ajax({
303            url: _ajax_url,
304            type: "POST",
305            dataType: "json",
306            data: {
307              action: "get_favorites_html",
308              ids: favorites,
309              nonce: _nonce,
310            },
311            success: function (response) {
312              _fv.favorite_loader();
313              if (response.success) {
314                $favoritesPage.html(response.data.html);
315              } else {
316                $favoritesPage.html(response.data.html);
317              }
318            },
319            error: function () {
320              _fv.favorite_loader();
321              $favoritesPage.html(
322                '<div class="favorite_list_wrapper_empty"><h5>' +
323                  cjpg_ajax_obj.words.you_dont_have_favorites_recipes_yet +
324                  "</h5></div>",
325              );
326            },
327          });
328        }
329      },
330      favorite_loader: function (bool = false) {
331        const _loader = $("#favorite_loader");
332        if (_loader && _loader.length > 0) {
333          if (bool) {
334            _loader.show();
335          } else {
336            _loader.hide();
337          }
338        }
339      },
340    };
341    _favorites.init();
342
343    const _favorites_old = {
344      init: function () {},
345      toggle_favorite: function ($this) {
346        const _action = "maimon_favorite_toggle";
347        const _post_id = $this.attr("data-id");
348        const _target = $("#favorite_btn_wrapper_inner_toggle_" + _post_id);
349        if (_post_id) {
350          const _d = {
351            action: _action,
352            nonce: _nonce,
353            post_id: _post_id,
354          };
355          this.send_ajax(_d, "POST", "toggle_favorite", { _target: _target });
356        }
357        return true;
358      },
359      send_ajax: function (_d, method, callback = "", $args = {}) {
360        let _s_ajax = $.ajax({
361          url: _ajax_url,
362          data: _d,
363          dataType: "json",
364          type: method,
365          xhrFields: {
366            withCredentials: true, // needed only for cross-site or subdomains
367          },
368        });
369        _s_ajax.done(function (response) {
370          if (callback === "toggle_favorite") {
371            if (response.data === "2") {
372              $args._target.addClass("favorite_item");
373            } else {
374              $args._target.removeClass("favorite_item");
375            }
376          } else {
377            console.log(response);
378          }
379        });
380        _s_ajax.fail(function (jqXHR, textStatus, errorThrown) {
381          console.error("AJAX Error:", textStatus, errorThrown);
382        });
383      },
384    };
385
386    $(document).on(
387      "change",
388      ".maimon_career_form_inner_field #resume_id_file",
389      function (e) {
390        _forms.file_upload($(this));
391      },
392    );
393    const _forms = {
394      init: function () {
395        this.normalize_contact_message_placeholder();
396      },
397      normalize_contact_message_placeholder: function () {
398        const defaultValues = ["אנחנו מקשיבים...", "אנחנו מקשיבים…"];
399        $(
400          '.contact-form textarea, .wpcf7 textarea, textarea#message, textarea[name="message"]',
401        ).each(function () {
402          const $field = $(this);
403          const currentValue = ($field.val() || "").trim();
404          const initialValue = (this.defaultValue || "").trim();
405          const currentPlaceholder = ($field.attr("placeholder") || "").trim();
406          const fallbackText = defaultValues.includes(currentValue)
407            ? currentValue
408            : initialValue;
409
410          if (!currentPlaceholder && fallbackText) {
411            $field.attr("placeholder", fallbackText);
412          }
413
414          if (
415            defaultValues.includes(currentValue) ||
416            defaultValues.includes(initialValue)
417          ) {
418            $field.val("");
419            this.defaultValue = "";
420          }
421        });
422      },
423      file_upload: function ($this) {
424        const _target = $(".career_resume_text_file");
425        const fileName = $this.val().split("\\").pop();
426        if (!$this.hasClass("chk")) {
427          let _txt = $this.text();
428          $this.attr("data-opp", _txt);
429        }
430        _target.html("");
431        if (fileName) {
432          _target.text(fileName);
433        } else {
434          _target.text($this.attr("data-opp"));
435        }
436        $this.addClass("chk");
437        return true;
438      },
439    };
440    _forms.init();
441
442    $(document).on("click", ".btn_action_increase", function (e) {
443      e.preventDefault();
444      _accessibility.increase_font($(this));
445    });
446    $(document).on("click", ".btn_action_decrease", function (e) {
447      e.preventDefault();
448      _accessibility.decrease_font($(this));
449    });
450    $(document).on("click", ".btn_action_print", function (e) {
451      e.preventDefault();
452      _accessibility.print_recipe($(this));
453    });
454    $(document).on("click", ".button_screen_locker", function (e) {
455      e.preventDefault();
456      _accessibility.lock_mobile_screen($(this));
457    });
458    const _accessibility = {
459      increase_font: function ($this) {
460        const _op = $(".btn_action_decrease");
461        const _op_max = _op.attr("data-max");
462        const _max = 6;
463        const _max_data = $this.attr("data-max");
464        let _calc = Number(_max_data) + 1;
465        if (_calc > _max) {
466          return true;
467        }
468        $this.attr("data-max", _calc);
469        _op.attr("data-max", Number(_op_max) + 1);
470        this.change_font_size_screen("2");
471        return true;
472      },
473      decrease_font: function ($this) {
474        const _op = $(".btn_action_increase");
475        const _op_max = _op.attr("data-max");
476        const _max = 1;
477        const _max_data = $this.attr("data-max");
478        let _calc = Number(_max_data) - 1;
479        if (_calc < _max) {
480          return true;
481        }
482        $this.attr("data-max", _calc);
483        _op.attr("data-max", Number(_op_max) - 1);
484        this.change_font_size_screen("1");
485        return true;
486      },
487      change_font_size_screen: function (side) {
488        $("span,h1,h2,h3,h4,h5,h6,p,a,strong,b,li,label,input,button")
489          .not(".line_buttons_recipes_wrapper *")
490          .each(function () {
491            const currentSize = parseInt($(this).css("font-size"));
492            if (side === "1") {
493              // decrease size
494              $(this).css("font-size", currentSize - 5 + "px");
495            } else {
496              $(this).css("font-size", currentSize + 5 + "px");
497            }
498          });
499      },
500      print_recipe: function ($this) {
501        const _p_id = $this.attr("data-id");
502        if (!_p_id) {
503          return false;
504        }
505        const _d = {
506          post_id: _p_id,
507          action: "maimon_print_recipe",
508        };
509        this.send_ajax("POST", _d, "print_recipe");
510        return true;
511      },
512      lock_mobile_screen: function ($this) {
513        if (wakeLock !== null) {
514          this.lock_mobile_screen_disable();
515          $this.removeClass("active");
516        } else {
517          this.lock_mobile_screen_enable();
518          $this.addClass("active");
519        }
520        return true;
521      },
522      lock_mobile_screen_disable: function () {
523        if (_general.isSafari()) {
524          if (document.getElementById("iosWakeLock")) return;
525          let video = document.createElement("video");
526          video.id = "iosWakeLock";
527          video.playsInline = true;
528          video.loop = true;
529          video.muted = true; // Ensure it plays silently
530          video.style.display = "none";
531          video.src = "data:video/mp4;base64,AAAA..."; // Replace with actual Base64 data
532          document.body.appendChild(video);
533          video
534            .play()
535            .catch((error) =>
536              console.error("Wake lock video failed to play:", error),
537            );
538        } else {
539          wakeLock.release().then(() => {
540            wakeLock = null;
541          });
542        }
543      },
544      lock_mobile_screen_enable: async function () {
545        if (_general.isSafari()) {
546          let video = document.getElementById("iosWakeLock");
547          if (video) {
548            video.src = "data:video/mp4;base64,AAAA..."; // Base64 silent video
549            video.play();
550            video.remove(); // Remove from DOM
551          }
552        } else {
553          if ("wakeLock" in navigator) {
554            try {
555              wakeLock = await navigator.wakeLock.request("screen");
556              wakeLock.addEventListener("release", () => {
557                console.log("Screen Wake Lock was released.");
558              });
559            } catch (err) {
560              console.error(`Wake Lock failed: ${err.name}, ${err.message}`);
561            }
562          } else {
563            console.warn("Wake Lock API is not supported in this browser.");
564          }
565        }
566      },
567      send_ajax: function (method, data, callback) {
568        const _fv = this;
569        _general.show_loader(true);
570        let ajax_data, _s_ajax;
571        ajax_data = data;
572        ajax_data["nonce"] = _nonce;
573        _s_ajax = $.ajax({
574          url: _ajax_url,
575          data: ajax_data,
576          headers: { "Content-Type": "application/x-www-form-urlencoded" },
577          contentType: "application/json; charset=utf-8",
578          dataType: "json",
579          type: method,
580        });
581        _s_ajax.done(function (response, msg) {
582          _general.show_loader(false);
583          if (response) {
584            if (callback === "print_recipe") {
585              _fv.handle_response(response.data);
586            }
587            return true;
588          }
589        });
590        _s_ajax.fail(function (error, textStatus) {
591          _general.show_loader(false);
592          console.log(error);
593        });
594      },
595      handle_response: function (response) {
596        const _template = response.data;
597        const tempDiv = $("<div>").html(_template); // Create a temporary div with AJAX content
598        this.printContent(tempDiv);
599      },
600      printContent: function (content) {
601        const printWindow = window.open("", "_blank");
602        let stylesheets = document.querySelectorAll(
603          'link[rel="stylesheet"], style',
604        );
605        printWindow.document.write("<html><head><title>Print</title>");
606        stylesheets.forEach((style) => {
607          let clone = style.cloneNode(true);
608          printWindow.document.head.appendChild(clone);
609        });
610        printWindow.document.write("</head><body>");
611        printWindow.document.write(content.html()); // Insert the dynamic content
612        printWindow.document.write("</body></html>");
613        printWindow.document.close();
614        printWindow.focus();
615        printWindow.print();
616        printWindow.close();
617      },
618    };
619
620    $(document).on("change", ".in_post_maimon_checkbox_line_chk", function (e) {
621      e.preventDefault();
622      _general.toggle_line_label_chk($(this));
623    });
624    $(document).on("click", ".video-link", function (e) {
625      e.preventDefault();
626      _general.video_link($(this));
627    }); //Handle video modal
628    $(document).on("click", "#videoModal, .close", function (e) {
629      _general.video_link_close(e);
630    }); // Close modal on click outside or on close button
631    const _general = {
632      init: function () {
633        this.init_alice();
634      },
635      init_alice: function () {
636        if ($("body").hasClass("rtl")) {
637          $(".alice-carousel").css("direction", "ltr");
638          setTimeout(function () {
639            // assuming the carousel exposes a refresh method
640            $(".alice-carousel").each(function () {
641              $(this).data("aliceCarousel")?.update();
642            });
643          }, 500);
644        }
645      },
646      video_link: function ($this) {
647        let videoId = $this.data("video-url");
648        if (videoId) {
649          let videoUrl =
650            videoId + (videoId.includes("?") ? "&" : "?") + "autoplay=1&mute=1";
651          let iframe = $("<iframe>", {
652            id: "modalVideo",
653            width: "560",
654            height: "315",
655            frameborder: "0",
656            allow: "autoplay",
657            allowfullscreen: true,
658            src: videoUrl,
659          });
660          $("#videoModalFrame").html(iframe);
661          $("#videoModal").fadeIn();
662        }
663      },
664      video_link_close: function (e) {
665        if ($(e.target).is("#videoModal") || $(e.target).is(".close")) {
666          $("#videoModal").fadeOut();
667          $("#videoModalFrame").empty(); // Clear the iframe
668        }
669      },
670      isSafari: function () {
671        return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
672      },
673      toggle_line_label_chk: function ($this) {
674        const _label = $this.parent("label");
675        if (_label) {
676          _label.toggleClass("highlight", this.checked);
677        }
678        return true;
679      },
680      show_loader: function (bool) {
681        let _pre = $(".pre_loader_global");
682        if (bool === true) {
683          _pre.removeClass("cj_hidden").show();
684        } else {
685          setTimeout(function () {
686            _pre.addClass("cj_hidden").hide();
687          }, 1000);
688        }
689        return true;
690      },
691    };
692    _general.init();
693
694    const _cursor_spinner = {
695      activeRequests: 0,
696      init: function () {
697        const _self = this;
698        $(document).ajaxSend(function (_event, jqXHR, settings) {
699          if (!_self.is_add_to_cart_request(settings)) {
700            return;
701          }
702          _self.start();
703          jqXHR.always(function () {
704            _self.stop();
705          });
706        });
707      },
708      supports_pointer_spinner: function () {
709        if (typeof window.matchMedia !== "function") {
710          return true;
711        }
712        return window.matchMedia("(pointer: fine)").matches;
713      },
714      is_add_to_cart_request: function (settings) {
715        if (!settings) {
716          return false;
717        }
718        const data = settings.data;
719        if (typeof data === "string") {
720          return /(?:^|&)action=maimon_ajax_add_to_cart(?:&|$)/.test(data);
721        }
722        if (data instanceof URLSearchParams) {
723          return data.get("action") === "maimon_ajax_add_to_cart";
724        }
725        return !!(data && data.action === "maimon_ajax_add_to_cart");
726      },
727      start: function () {
728        if (!this.supports_pointer_spinner()) {
729          return;
730        }
731        this.activeRequests += 1;
732        $("body").addClass("maimon-cursor-spinner-active");
733      },
734      stop: function () {
735        if (!this.supports_pointer_spinner()) {
736          return;
737        }
738        this.activeRequests = Math.max(0, this.activeRequests - 1);
739        if (this.activeRequests > 0) {
740          return;
741        }
742        $("body").removeClass("maimon-cursor-spinner-active");
743      },
744    };
745    _cursor_spinner.init();
746
747    $(document).on(
748      "click",
749      ".single_recipe_video_toggle,.single_page_guide_video_toggle",
750      function (e) {
751        e.preventDefault();
752        _single.toggle_video($(this));
753      },
754    );
755    $(document).on("click", ".float_ingredients_wrap_btn", function (e) {
756      e.preventDefault();
757      _single.toggle_sidebar_ingredients($(this));
758    });
759    $(document).on("click", ".sidebar_ingredients", function (e) {
760      e.preventDefault();
761      _single.toggle_sidebar_ingredients_block(e, $(this));
762    });
763    $(window).on("scroll resize", function () {
764      if ($(window).width() > 768) {
765        _single.sticky();
766        _single.reset_sticky_btn();
767      } else {
768        _single.reset_sticky();
769        _single.sticky_btn();
770      }
771    });
772    $(document).on("click", ".in_post_maimon_video_line", function (e) {
773      e.preventDefault();
774      _admin_op.selected_poster($(this));
775    });
776
777    const offsetTop = 50; // spacing from top
778    let isFixed = false;
779    let isBottomFixed = false;
780    const $floatBox = $(".float_ingredients_wrap");
781    const $srpwmsi = $(".single_recipe_page_wrap_main_sidebar_inner"); // The div that follows scroll
782    const $srpwms = $(".single_recipe_page_wrap_main_sidebar");
783    const $srpwmb = $(".single_recipe_page_wrap_main_body");
784    let startPositionBtn, stopPositionBtn;
785    const _single = {
786      init: function () {
787        //this.sticky();
788        if (
789          $floatBox &&
790          $floatBox.length > 0 &&
791          $floatBox.parent() &&
792          $floatBox.parent().length > 0
793        ) {
794          startPositionBtn = $floatBox.parent().offset().top; // Get the initial top position
795          stopPositionBtn =
796            $floatBox.parent().offset().top +
797            $floatBox.parent().outerHeight() -
798            $floatBox.outerHeight() -
799            offsetTop;
800        }
801        this.maybeShowYoutubePoster();
802      },
803      maybeShowYoutubePoster: function () {
804        const _class_target = $(".show_youtube_poster");
805        const _vid_target = $("#recipeVideoFrame");
806        if (
807          _vid_target &&
808          _vid_target.length > 0 &&
809          _class_target &&
810          _class_target.length > 0
811        ) {
812          const poster = $(".youtube_original_poster");
813          const videoId = this.extractYouTubeVideoId(
814            _vid_target.attr("data-src"),
815          );
816          const thumbnailUrl = `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`;
817          poster.attr("src", thumbnailUrl);
818        }
819      },
820      selected_poster: function ($this) {
821        let $poster = $this.find(".in_post_maimon_video_poster");
822        let $playIcon = $this.find(".in_post_maimon_video_play_icon");
823        let $video = $this.find(".in_post_maimon_video");
824        if ($video.css("display") === "none") {
825          $video.show().get(0).play();
826          $poster.hide();
827          $playIcon.hide();
828        }
829      },
830      toggle_video: function ($this) {
831        const target = $("#" + $this.attr("aria-controls"));
832        const _placehodler = $(".black_img_placeholder img");
833        if (target && target.length > 0) {
834          if ($this.attr("data-type") === "external") {
835            this.play_iframe($this, target);
836          } else {
837            this.play_video($this, target);
838          }
839        }
840        if (_placehodler && _placehodler.length > 0) {
841          _placehodler.hide();
842        }
843        return true;
844      },
845      play_iframe: function ($this, target) {
846        if (typeof YT === "undefined" || typeof YT.Player === "undefined") {
847          console.warn("YouTube API not loaded yet.");
848          return; // prevent error if API is not ready
849        }
850        const videoId = this.extractYouTubeVideoId(target.attr("data-src"));
851        if (!$this.hasClass("active")) {
852          const _id = target.attr("id");
853          target.html('<div id="' + _id + '_iframe"></div>');
854          $(".black_img_placeholder img").fadeOut(300);
855          target.show();
856          ytPlayer = new YT.Player(_id + "_iframe", {
857            videoId: videoId,
858            width: "100%",
859            height: "100%",
860            playerVars: {
861              autoplay: 1,
862              rel: 0,
863            },
864            events: {
865              onReady: function (event) {
866                event.target.playVideo();
867              },
868            },
869          });
870          $this.hide();
871          $this.addClass("active");
872        }
873      },
874      play_video: function ($this, target) {
875        if (target.length > 0) {
876          target.get(0).play();
877          $this.hide();
878          $this.addClass("active");
879          target.on("play", function () {
880            $this.hide(); // Ensure it stays hidden when playing
881          });
882          target.on("ended pause", function () {
883            if (target.get(0).paused) {
884              $this.show();
885              $this.removeClass("active");
886            }
887          });
888        }
889      },
890      monitorYouTubeStop: function (iframe, $button) {
891        if (typeof YT === "undefined" || typeof YT.Player === "undefined") {
892          var tag = document.createElement("script");
893          tag.src = "https://www.youtube.com/iframe_api";
894          var firstScriptTag = document.getElementsByTagName("script")[0];
895          firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
896        }
897        const videoId = new URL(iframe.attr("src")).searchParams.get("v");
898        const player = new YT.Player(iframe[0], {
899          videoId: videoId,
900          events: {
901            onStateChange: function (event) {
902              if (event.data === YT.PlayerState.PLAYING) {
903                $button.hide();
904              } else if (
905                event.data === YT.PlayerState.ENDED ||
906                event.data === YT.PlayerState.PAUSED
907              ) {
908                $button.show();
909                $button.removeClass("active");
910              }
911            },
912          },
913        });
914      },
915      monitorVimeoStop: function (iframe, $button) {
916        const player = new Vimeo.Player(iframe[0]);
917        player.on("play", function () {
918          $button.hide();
919        });
920        player.on("pause", function () {
921          $button.show();
922          $button.removeClass("active");
923        });
924        player.on("ended", function () {
925          $button.show();
926          $button.removeClass("active");
927        });
928      },
929      extractYouTubeVideoId: function (url) {
930        let videoId = null;
931        const regexList = [
932          /youtube\.com\/watch\?v=([a-zA-Z0-9_-]{11})/,
933          /youtu\.be\/([a-zA-Z0-9_-]{11})/,
934          /youtube\.com\/embed\/([a-zA-Z0-9_-]{11})/,
935          /youtube\.com\/shorts\/([a-zA-Z0-9_-]{11})/,
936        ];
937        regexList.some((regex) => {
938          const match = url.match(regex);
939          if (match && match[1]) {
940            videoId = match[1];
941            return true;
942          }
943          return false;
944        });
945        if (!videoId && /^[a-zA-Z0-9_-]{11}$/.test(url)) {
946          videoId = url;
947        }
948        return videoId;
949      },
950      sticky: function () {
951        let windowScroll = $(window).scrollTop();
952        if ($srpwms && $srpwms.length > 0) {
953          let rightOffsetTop = $srpwms.offset().top; // Sidebar initial position
954          let leftOffsetTop = $srpwmb.offset().top; // Content top position
955          let leftHeight = $srpwmb.outerHeight();
956          let rightHeight = $srpwmsi.outerHeight();
957          let rightWidth = $srpwms.outerWidth();
958          let stopPosition = leftOffsetTop + leftHeight - rightHeight; // Bottom limit
959          if (windowScroll >= stopPosition - offsetTop) {
960            $srpwmsi.css({
961              position: "absolute",
962              top: leftHeight - rightHeight + "px",
963              width: rightWidth + "px",
964            });
965            isFixed = false; // Stop being fixed
966          } else if (windowScroll > rightOffsetTop - offsetTop) {
967            if (!isFixed) {
968              $srpwmsi.css({
969                position: "fixed",
970                top: offsetTop + "px",
971                width: rightWidth + "px",
972              });
973              isFixed = true;
974            }
975          } else {
976            $srpwmsi.css({
977              position: "relative",
978              top: "auto",
979              width: "auto",
980            });
981            isFixed = false;
982          }
983        }
984      },
985      sticky_btn: function () {
986        if ($floatBox && $floatBox.length > 0 && stopPositionBtn) {
987          let scrollY = $(window).scrollTop();
988          if (scrollY >= startPositionBtn && scrollY < stopPositionBtn) {
989            if (_is_rtl) {
990              $floatBox.css({
991                position: "fixed",
992                bottom: offsetTop + "px",
993                left: 0,
994                top: "auto!important",
995              });
996            } else {
997              $floatBox.css({
998                position: "fixed",
999                bottom: offsetTop + "px",
1000                right: 0,
1001                top: "auto!important",
1002              });
1003            }
1004          } else if (scrollY >= stopPositionBtn) {
1005            if (_is_rtl) {
1006              $floatBox.css({
1007                position: "absolute",
1008                bottom:
1009                  $floatBox.parent().outerHeight() -
1010                  $floatBox.parent().outerHeight() +
1011                  offsetTop +
1012                  "px",
1013                left: -20 + "px",
1014                top: "auto!important",
1015              });
1016            } else {
1017              $floatBox.css({
1018                position: "absolute",
1019                bottom:
1020                  $floatBox.parent().outerHeight() -
1021                  $floatBox.parent().outerHeight() +
1022                  offsetTop +
1023                  "px",
1024                right: -20 + "px",
1025                top: "auto!important",
1026              });
1027            }
1028          } else {
1029            if (_is_rtl) {
1030              $floatBox.css({
1031                position: "absolute",
1032                bottom: "20%",
1033                left: -20 + "px",
1034                top: "auto!important",
1035              });
1036            } else {
1037              $floatBox.css({
1038                position: "absolute",
1039                bottom: "20%",
1040                right: -20 + "px",
1041                top: "auto!important",
1042              });
1043            }
1044          }
1045        }
1046      },
1047      reset_sticky: function () {
1048        $srpwmsi.css({
1049          position: "relative",
1050          bottom: "auto",
1051          width: "auto",
1052        });
1053        isFixed = false;
1054      },
1055      reset_sticky_btn: function () {
1056        $floatBox.css({
1057          position: "relative",
1058          top: "auto",
1059          width: "auto",
1060        });
1061        isFixed = false;
1062      },
1063      toggle_sidebar_ingredients_block: function (e, $this) {
1064        if ($(e.target).closest(".sidebar_ingredients_inner").length === 0) {
1065          const _btn = $this.find(".float_ingredients_wrap_btn");
1066          if (_btn && _btn.length > 0) {
1067            this.toggle_sidebar_ingredients(_btn);
1068          }
1069        }
1070      },
1071      toggle_sidebar_ingredients: function ($this) {
1072        const _role = $this.attr("data-role");
1073        const _target = $("#" + $this.attr("aria-controls"));
1074        if (_target && _target.length > 0) {
1075          const _opp = $($this.attr("data-opp"));
1076          if (_is_rtl) {
1077            if (_role === "open") {
1078              _target.animate({ left: "0" }, 500);
1079            } else {
1080              _target.animate({ left: "-100%" }, 500);
1081            }
1082          } else {
1083            if (_role === "open") {
1084              _target.animate({ right: "0" }, 500);
1085            } else {
1086              _target.animate({ right: "-100%" }, 500);
1087            }
1088          }
1089          $this.parent().fadeOut(500);
1090          _opp.parent().fadeIn(500);
1091        }
1092        return true;
1093      },
1094    };
1095    _single.init();
1096
1097    $(document).on("change", ".company_taxonomy_filter", function (e) {
1098      e.preventDefault();
1099      _shop.filter_shop_by_company($(this));
1100    });
1101    const _shop = {
1102      filter_shop_by_company: function ($this) {
1103        let selectedCompanies = [];
1104        $(".company_taxonomy_filter:checked").each(function () {
1105          selectedCompanies.push($(this).val());
1106        });
1107        let queryString = selectedCompanies.length
1108          ? "?custom_category=" + selectedCompanies.join(",")
1109          : "";
1110        let redirectUrl =
1111          window.location.origin + window.location.pathname + queryString;
1112        // Redirect to new URL
1113        window.location.href = redirectUrl;
1114      },
1115    };
1116
1117    $(document).on(
1118      "click",
1119      ".archive_posts_filter .category_filter",
1120      function (e) {
1121        e.preventDefault();
1122        _archive.toggle_filter_category($(this));
1123      },
1124    );
1125    $(document).on(
1126      "click",
1127      ".archive_posts_filter .company_filter",
1128      function (e) {
1129        e.preventDefault();
1130        _archive.toggle_filter_company($(this));
1131      },
1132    );
1133    $(document).on("click", "#customSortDropdown", function (e) {
1134      e.preventDefault();
1135      _archive.toggle_options($(this));
1136    });
1137    $(document).on(
1138      "click",
1139      "#customSortDropdown #optionsList li button",
1140      function (e) {
1141        e.preventDefault();
1142        _archive.select_option($(this));
1143      },
1144    );
1145    $(document).on(
1146      "click",
1147      ".archive_posts_filter .load-more-btn",
1148      function (e) {
1149        e.preventDefault();
1150        _archive.load_more($(this));
1151      },
1152    );
1153
1154    $(document).on("click", function (e) {
1155      if (!$(e.target).closest($("#customSortDropdown")).length) {
1156        $("#optionsList").slideUp();
1157        $("#customSortDropdown").removeClass("active");
1158      }
1159    });
1160
1161    const _archive = {
1162      debounceTimer: null,
1163      init: function () {},
1164      toggle_filter_category: function ($this) {
1165        if ($this.hasClass("active")) {
1166          $this.removeClass("active");
1167        } else {
1168          $this.addClass("active");
1169        }
1170        if (!$this.hasClass("category")) {
1171          $(".archive_posts_filter").removeClass("active");
1172        }
1173        this.archive_posts_filter();
1174      },
1175      toggle_filter_company: function ($this) {
1176        const _parent = $(".lobby_companies");
1177        const active = $this.hasClass("active");
1178        $(".archive_posts_filter .company_filter").removeClass("active");
1179        if (!active) {
1180          $this.addClass("active");
1181        }
1182        // clear al categories
1183        $.each($(".category_filter.active"), function (k, v) {
1184          $(this).removeClass("active");
1185        });
1186        if (!active) {
1187          this.archive_categories_display($this);
1188        } else {
1189          this.archive_categories_display($this, true);
1190        }
1191        this.archive_posts_filter();
1192        if ($(".company_filter.active").length > 0) {
1193          _parent.addClass("active_lobby");
1194        } else {
1195          _parent.removeClass("active_lobby");
1196        }
1197      },
1198      toggle_options: function ($this) {
1199        $("#optionsList").slideToggle();
1200        $this.toggleClass("active");
1201      },
1202      select_option: function ($this) {
1203        if ($this.hasClass("active")) {
1204          return;
1205        }
1206        $("#selectedOption").text($this.text());
1207        $("#customSortDropdown #optionsList li button").removeClass("active");
1208        $this.addClass("active");
1209        //toggle categories display for archive
1210        this.archive_posts_filter();
1211      },
1212      load_more: function ($this) {
1213        const page = $this.data("page") + 1;
1214        $this.data("page", page);
1215        this.archive_posts_filter(true, page);
1216        return true;
1217      },
1218      archive_categories_display: function ($this, clear = false) {
1219        const _company = $this.attr("data-company");
1220        const _post_type = $this.attr("data-post_type");
1221        let _all = "0";
1222        if (clear === true) {
1223          _all = "1";
1224        }
1225        const _d = {
1226          action: "maimon_get_categories_ajax",
1227          post_type: _post_type,
1228          company: _company,
1229          nonce: _nonce,
1230          all: _all,
1231        };
1232        this.ajax(_d, "POST", "display_categories");
1233      },
1234      archive_posts_filter: function (
1235        load_more = false,
1236        page = 1,
1237        clear_terms = false,
1238      ) {
1239        const post_type = $(".archive_posts_filter").data("post-type");
1240        const search = $('.archive_posts_filter input[type="search"]').val();
1241        const company = $(".company_filter.active").data("company");
1242        const orderby = $("#optionsList button.active").data("orderby");
1243        const order = $("#optionsList button.active").data("order");
1244        const is_shop = $(".maimon_products_page").data("shop");
1245        let categories = [];
1246        $.each($(".category_filter.active"), function (k, v) {
1247          categories.push($(v).data("category"));
1248        });
1249        const _d = {
1250          action: "maimon_archive_posts_filter",
1251          post_type: post_type,
1252          search: search,
1253          categories: categories,
1254          company: company,
1255          orderby: orderby,
1256          order: order,
1257          page: page,
1258          is_shop: is_shop,
1259          nonce: _nonce,
1260          shop_page: $(".lobby_posts").attr("data-shop-page"),
1261        };
1262        clearTimeout(this.debounceTimer);
1263        const _fv = this;
1264        this.debounceTimer = setTimeout(() => {
1265          _fv.ajax(_d, "POST", "filter", load_more);
1266        }, 300);
1267        return true;
1268      },
1269      ajax: function (_data, method, callback, load_more) {
1270        $.ajax({
1271          url: _ajax_url,
1272          data: _data,
1273          dataType: "json",
1274          method: method,
1275          success: function (response) {
1276            if (callback === "filter") {
1277              if (load_more) {
1278                $(".lobby_posts").append(response.data.html);
1279              } else {
1280                if (true === response.success) {
1281                  $(".lobby_posts").html(response.data.html);
1282                } else {
1283                  $(".lobby_posts").html(
1284                    "<p>" + response.data.message + "</p>",
1285                  );
1286                }
1287              }
1288              if (response.data.load_more) {
1289                $(".load-more-btn").show();
1290              } else {
1291                $(".load-more-btn").hide();
1292              }
1293            } else if (callback === "display_categories") {
1294              if (response.data.status === "success" && response.data.terms) {
1295                const _terms_ids = [];
1296                $.each(response.data.terms, function (k, v) {
1297                  if (v.has_company_posts === "1") {
1298                    _terms_ids.push(v.term_id);
1299                  }
1300                });
1301                const _target = $(".lobby_categories .lobby_categories__items");
1302                $.each(_target.find("button"), function () {
1303                  let categoryId = $(this).data("category");
1304                  if ($.inArray(parseInt(categoryId), _terms_ids) !== -1) {
1305                    $(this).attr("data-has_posts", "1");
1306                  } else {
1307                    $(this).attr("data-has_posts", "0");
1308                  }
1309                });
1310              }
1311            }
1312          },
1313        });
1314      },
1315    };
1316
1317    const _shortcodes = {
1318      init: function () {
1319        // run carousel
1320        const _g_r = $(".slick-slider");
1321        if (_g_r && _g_r.length > 0) {
1322          _g_r.on(
1323            "init reInit afterChange",
1324            function (event, slick, currentSlide) {
1325              const $slider = $(event.currentTarget);
1326              $slider
1327                .find(".slick-slide")
1328                .attr("aria-hidden", "true")
1329                .attr("inert", "true"); // Hide all slides in this slider
1330              $slider
1331                .find(".slick-active")
1332                .attr("aria-hidden", "false")
1333                .removeAttr("inert"); // Show all visible slides in this slider
1334            },
1335          );
1336        }
1337        this.run_carousel_tips();
1338        this.run_product_samples_tips();
1339        this.run_carousel_chefs();
1340        this.run_carousel_shop_products();
1341        this.rerender_home_page_chef_area();
1342      },
1343      run_carousel_shop_products: function () {
1344        const _tr = $(".maimon_products_cases_inner_carousel_list");
1345        if (_tr && _tr.length > 0) {
1346          const _max = 3;
1347          if (_tr.find("li").length >= _max) {
1348            // Mobile: Enable Slick Carousel
1349            if ($(window).width() < 980) {
1350              if (!_tr.hasClass("slick-initialized")) {
1351                let _args = {
1352                  infinite: true,
1353                  slidesToShow: 3, // Default (for large screens)
1354                  slidesToScroll: 1,
1355                  autoplay: true,
1356                  autoplaySpeed: 2000,
1357                  arrows: false,
1358                  dots: false,
1359                  centerMode: false,
1360                  adaptiveHeight: true,
1361                  responsive: [
1362                    {
1363                      breakpoint: 768, // Below 780px
1364                      settings: {
1365                        slidesToShow: 2,
1366                      },
1367                    },
1368                    {
1369                      breakpoint: 480, // Below 480px
1370                      settings: {
1371                        slidesToShow: 1.5,
1372                      },
1373                    },
1374                    {
1375                      breakpoint: 420, // Below 400px
1376                      settings: {
1377                        slidesToShow: 1,
1378                      },
1379                    },
1380                  ],
1381                };
1382                if (_is_rtl) {
1383                  _args.rtl = true;
1384                }
1385                _tr.slick(_args);
1386              }
1387            }
1388            // Desktop: Destroy Slick Carousel
1389            else {
1390              if (_tr.hasClass("slick-initialized")) {
1391                _tr.slick("unslick");
1392              }
1393            }
1394          }
1395        }
1396      },
1397      run_product_samples_tips: function () {
1398        const _tr = $(".maimon_products_may_like_inner_carousel_list");
1399        if (_tr && _tr.length > 0) {
1400          const _max = 4;
1401          if (_tr.find("li").length >= _max) {
1402            // Mobile: Enable Slick Carousel
1403            if ($(window).width() < 1024) {
1404              if (!_tr.hasClass("slick-initialized")) {
1405                let _args = {
1406                  infinite: true,
1407                  slidesToShow: 4, // Default (for large screens)
1408                  slidesToScroll: 1,
1409                  autoplay: true,
1410                  autoplaySpeed: 2000,
1411                  arrows: false,
1412                  dots: false,
1413                  centerMode: false,
1414                  adaptiveHeight: true,
1415                  responsive: [
1416                    {
1417                      breakpoint: 768, // Below 780px
1418                      settings: {
1419                        slidesToShow: 3,
1420                      },
1421                    },
1422                    {
1423                      breakpoint: 480, // Below 480px
1424                      settings: {
1425                        slidesToShow: 2,
1426                      },
1427                    },
1428                    {
1429                      breakpoint: 400, // Below 400px
1430                      settings: {
1431                        slidesToShow: 1,
1432                      },
1433                    },
1434                  ],
1435                };
1436                if (_is_rtl) {
1437                  _args.rtl = true;
1438                }
1439                _tr.slick(_args);
1440              }
1441            }
1442            // Desktop: Destroy Slick Carousel
1443            else {
1444              if (_tr.hasClass("slick-initialized")) {
1445                _tr.slick("unslick");
1446              }
1447            }
1448          }
1449        }
1450      },
1451      run_carousel_chefs: function () {
1452        const _chefs = $("#maimon_chefs_list_inner_wrap_list");
1453        if (_chefs && _chefs.length > 0) {
1454          const _max = 6;
1455          if (_chefs.find("li").length >= _max) {
1456            // Mobile: Enable Slick Carousel
1457            if ($(window).width() <= 768) {
1458              if (!_chefs.hasClass("slick-initialized")) {
1459                let _args = {
1460                  infinite: true,
1461                  slidesToShow: 6, // Default (for large screens)
1462                  slidesToScroll: 2,
1463                  autoplay: true,
1464                  autoplaySpeed: 2000,
1465                  arrows: false,
1466                  dots: false,
1467                  centerMode: false,
1468                  adaptiveHeight: true,
1469                  responsive: [
1470                    {
1471                      breakpoint: 768, // Below 780px
1472                      settings: {
1473                        slidesToShow: 4,
1474                      },
1475                    },
1476                    {
1477                      breakpoint: 480, // Below 480px
1478                      settings: {
1479                        slidesToShow: 3,
1480                      },
1481                    },
1482                  ],
1483                };
1484                if (_is_rtl) {
1485                  _args.rtl = true;
1486                }
1487                _chefs.slick(_args);
1488              }
1489            }
1490            // Desktop: Destroy Slick Carousel
1491            else {
1492              if (_chefs.hasClass("slick-initialized")) {
1493                _chefs.slick("unslick");
1494              }
1495            }
1496          }
1497        }
1498      },
1499      run_carousel_tips: function () {
1500        const _tr = $(".maimon_shortcode_tips_inner_carousel");
1501        if (_tr && _tr.length > 0) {
1502          const _max = 4;
1503          if (
1504            _tr.find(".maimon_shortcode_tips_inner_carousel_item").length >=
1505            _max
1506          ) {
1507            // Mobile: Enable Slick Carousel
1508            if ($(window).width() < 1024) {
1509              if (!_tr.hasClass("slick-initialized")) {
1510                let _args = {
1511                  infinite: true,
1512                  slidesToShow: 4, // Default (for large screens)
1513                  slidesToScroll: 1,
1514                  autoplay: true,
1515                  autoplaySpeed: 2000,
1516                  arrows: false,
1517                  dots: false,
1518                  centerMode: true,
1519                  adaptiveHeight: true,
1520                  responsive: [
1521                    {
1522                      breakpoint: 768, // Below 780px
1523                      settings: {
1524                        slidesToShow: 2,
1525                      },
1526                    },
1527                    {
1528                      breakpoint: 480, // Below 480px
1529                      settings: {
1530                        slidesToShow: 1,
1531                      },
1532                    },
1533                  ],
1534                };
1535                if (_is_rtl) {
1536                  _args.rtl = true;
1537                }
1538                _tr.slick(_args);
1539              }
1540            }
1541            // Desktop: Destroy Slick Carousel
1542            else {
1543              if (_tr.hasClass("slick-initialized")) {
1544                _tr.slick("unslick");
1545              }
1546            }
1547          }
1548        }
1549      },
1550      rerender_home_page_chef_area: function () {
1551        const $list = $(".maimon_chefs_list_inner_wrap_list");
1552        const $centerItem = $list.find(".center_chef_row");
1553        if ($centerItem.length === 0) {
1554          return;
1555        }
1556        $centerItem.detach();
1557        const $items = $list.children().not(".center_chef_row");
1558        if ($(window).width() <= 768) {
1559          const total = $items.length;
1560          const midIndex = Math.floor(total / 2);
1561          $centerItem.insertBefore($items.eq(midIndex));
1562        } else {
1563          const firstTop = $items.first().position().top;
1564          const $firstRowItems = $items.filter(function () {
1565            return $(this).position().top === firstTop;
1566          });
1567          const count = $firstRowItems.length;
1568          const centerIndex = Math.floor(count / 2) - 1;
1569          $centerItem.insertBefore($firstRowItems.eq(centerIndex));
1570        }
1571      },
1572    };
1573    _shortcodes.init();
1574    // Removed: $(window).resize(function() {_shortcodes.init();}); - causes duplicate slider initialization
1575
1576    $(document).on("submit", ".ajax_add_to_cart", function (e) {
1577      e.preventDefault();
1578      _woocommerce_custom.add_to_cart_submit($(this));
1579    });
1580    $(document).on("click", ".maimon_ajax_add_to_cart", function (e) {
1581      var $btn = $(this);
1582      /* Unified product card: productCardActions handles ALL .maimon-product-card — skip here */
1583      if (
1584        $btn.hasClass("maimon_single_ajax_add_to_cart") ||
1585        $btn.closest(".single_product_add_to_cart, .maimon-product-card").length
1586      ) {
1587        return;
1588      }
1589      e.preventDefault();
1590      _woocommerce_custom.add_to_cart_click($btn);
1591    });
1592
1593    const _woocommerce_custom = {
1594      init: function () {
1595        this.relocate_single_product_media();
1596        this.run_gallery();
1597        this.run_icons_nutritions();
1598        $(window)
1599          .off("resize.singleProductMedia")
1600          .on("resize.singleProductMedia", () => {
1601            this.relocate_single_product_media();
1602          });
1603      },
1604      run_icons_nutritions: function () {
1605        const _tr = $(".maimon_single_product_nutritional_lines_inner");
1606        if (_tr && _tr.length > 0) {
1607          const _max = 3;
1608          _tr.each(function () {
1609            const _slider = $(this);
1610            const _count = _slider.find("li").length;
1611            const _desktopSlides = Math.min(_count, 3);
1612            const _tabletSlides = Math.min(_count, 2.2);
1613            const _mobileSlides = Math.min(_count, 2.2);
1614            if (_count <= 1 || _slider.hasClass("slick-initialized")) {
1615              return;
1616            }
1617            const _wrapper = _slider.closest(
1618              ".maimon_single_product_nutritional_lines_slider_wrap",
1619            );
1620            let _args = {
1621              infinite: true,
1622              slidesToShow: _desktopSlides,
1623              slidesToScroll: 1,
1624              autoplay: true,
1625              autoplaySpeed: 2400,
1626              pauseOnHover: true,
1627              pauseOnFocus: true,
1628              arrows: true,
1629              dots: false,
1630              centerMode: false,
1631              adaptiveHeight: true,
1632              draggable: true,
1633              swipe: true,
1634              touchMove: true,
1635              prevArrow:
1636                '<button type="button" class="maimon_nutritional_arrow maimon_nutritional_arrow_prev" aria-label="Previous nutritional items"><span aria-hidden="true"></span></button>',
1637              nextArrow:
1638                '<button type="button" class="maimon_nutritional_arrow maimon_nutritional_arrow_next" aria-label="Next nutritional items"><span aria-hidden="true"></span></button>',
1639              appendArrows: _wrapper,
1640              responsive: [
1641                {
1642                  breakpoint: 767,
1643                  settings: {
1644                    slidesToShow: _tabletSlides,
1645                    arrows: true,
1646                  },
1647                },
1648                {
1649                  breakpoint: 480,
1650                  settings: {
1651                    slidesToShow: _mobileSlides,
1652                    arrows: true,
1653                  },
1654                },
1655              ],
1656            };
1657            if (_is_rtl) {
1658              _args.rtl = true;
1659            }
1660            _slider.slick(_args);
1661          });
1662        }
1663      },
1664      run_gallery: function () {
1665        const _tr = $(".single_page_product_wrap_main_sidebar_inner_carousel:visible");
1666        if (_tr && _tr.length > 0) {
1667          _tr.each(function () {
1668            const $gallery = $(this);
1669            if ($gallery.hasClass("slick-initialized")) {
1670              return;
1671            }
1672            let _args = {
1673              infinite: true,
1674              slidesToShow: 1,
1675              slidesToScroll: 1,
1676              autoplay: false,
1677              arrows: false,
1678              dots: true,
1679              centerMode: false,
1680              adaptiveHeight: true,
1681            };
1682            if (_is_rtl) {
1683              _args.rtl = true;
1684            }
1685            $gallery.slick(_args);
1686          });
1687        }
1688      },
1689      relocate_single_product_media: function () {
1690        const $sidebar = $(".single_page_product_wrap_main_sidebar").first();
1691        const $mobileTarget = $(".single_product_mobile_gallery_target").first();
1692        const $origin = $(".single_page_product_sidebar_origin").first();
1693        if (!$sidebar.length || !$mobileTarget.length || !$origin.length) {
1694          return;
1695        }
1696        const isMobile = window.matchMedia("(max-width: 900px)").matches;
1697        const previousNode = $sidebar.prev()[0] || null;
1698        if (isMobile && previousNode !== $mobileTarget[0]) {
1699          $mobileTarget.after($sidebar);
1700        } else if (!isMobile && previousNode !== $origin[0]) {
1701          $origin.after($sidebar);
1702        }
1703        const $gallery = $sidebar.find(
1704          ".single_page_product_wrap_main_sidebar_inner_carousel.slick-initialized",
1705        );
1706        if ($gallery.length) {
1707          $gallery.slick("setPosition");
1708        }
1709      },
1710      add_to_cart_click: function ($this) {
1711        if ($this.prop("disabled")) return;
1712        const product_id = $this.attr("data-product_id");
1713        var $qtyInput = $this
1714          .closest(".maimon-product-card__actions")
1715          .find(".qty-input");
1716        const quantity = $qtyInput.length
1717          ? parseInt($qtyInput.val(), 10) || 1
1718          : 1;
1719        const nonce = $this.data("nonce") || _nonce;
1720        $this.prop("disabled", true).text(_words.adding);
1721        const _d = {
1722          product_id: product_id,
1723          quantity: quantity,
1724          nonce: nonce,
1725          action: "maimon_ajax_add_to_cart",
1726        };
1727        this.maybe_add_header_counter();
1728        this.ajax(_d, "POST", "add_to_cart", { button: $this });
1729        return true;
1730      },
1731      add_to_cart_submit: function (form) {
1732        const product_id = form.find('input[name="product_id"]').val();
1733        const quantity = form.find('input[name="quantity"]').val();
1734        const button = form.find(".ajax_add_to_cart_button");
1735        button.prop("disabled", true).text(_words.adding);
1736        const _d = {
1737          product_id: product_id,
1738          quantity: quantity,
1739          nonce: _nonce,
1740          action: "maimon_ajax_add_to_cart",
1741        };
1742        if (!product_id || quantity < 1) {
1743          alert(_words.cannot_add_to_cart);
1744          return false;
1745        }
1746        this.maybe_add_header_counter();
1747        this.ajax(_d, "POST", "add_to_cart", { button: button });
1748        return true;
1749      },
1750      maybe_add_header_counter: function () {
1751        const _number = $(
1752          ".header-cart.elementor-menu-cart__toggle_button .cart-icon.woo_cart_fragments",
1753        );
1754        if (_number && _number.length > 0) {
1755          const _span_target = _number.find(".maimon_cart_count");
1756          if (!_span_target.length) {
1757            _number.prepend(
1758              '<span class="maimon_cart_count elementor-button-icon-qty">' +
1759                0 +
1760                "</span>",
1761            );
1762          }
1763        }
1764      },
1765      ajax: function (ajax_data, method, callback, args = {}) {
1766        const _fv = this;
1767        $.ajax({
1768          url: _ajax_url,
1769          data: ajax_data,
1770          headers: { "Content-Type": "application/x-www-form-urlencoded" },
1771          contentType: "application/json; charset=utf-8",
1772          dataType: "json",
1773          type: method,
1774          beforeSend: function () {
1775            _general.show_loader(true);
1776          },
1777          success: function (response) {
1778            _general.show_loader(false);
1779
1780            if (
1781              response &&
1782              (response.fragments ||
1783                (callback === "add_to_cart" && response.success))
1784            ) {
1785              _fv.handle_response(response, callback, args);
1786            } else if (
1787              !(callback === "add_to_cart" && response && response.success)
1788            ) {
1789              console.error("Unexpected response:", response);
1790            }
1791          },
1792          error: function (error) {
1793            _general.show_loader(false);
1794            console.error("AJAX Error:", error);
1795          },
1796          complete: function () {
1797            if ($.active <= 1) {
1798              $("body").removeClass("maimon-cursor-spinner-active");
1799            }
1800          },
1801        });
1802      },
1803      handle_response: function (response, callback = "", args = {}) {
1804        if (callback === "add_to_cart") {
1805          args.button
1806            .prop("disabled", false)
1807            .removeClass("loading")
1808            .text(cjpg_ajax_obj.words.add_to_cart);
1809          var data = response && response.data ? response.data : response;
1810          var fragments =
1811            data && data.fragments
1812              ? data.fragments
1813              : response && response.fragments
1814                ? response.fragments
1815                : {};
1816          var cartHash =
1817            data && data.cart_hash
1818              ? data.cart_hash
1819              : response && response.cart_hash
1820                ? response.cart_hash
1821                : "";
1822          var isSuccess = !!(
1823            response &&
1824            (response.success || (data && data.count !== undefined))
1825          );
1826          if (isSuccess && data && typeof data.count !== "undefined") {
1827            updateCartBadges(data.count);
1828          }
1829          if (Object.keys(fragments).length) {
1830            console.log("Updating cart fragments...", fragments);
1831            $.each(fragments, function (selector, html) {
1832              var $targets = $(selector);
1833              if (!$targets.length) {
1834                return;
1835              }
1836              $targets.each(function () {
1837                $(this).replaceWith(html);
1838              });
1839            });
1840            $(document.body).trigger("wc_fragments_refreshed");
1841          }
1842          $(document.body).trigger("maimon_cart_updated", [
1843            data && typeof data.count !== "undefined"
1844              ? numericCount
1845              : undefined,
1846          ]);
1847          $(document).trigger("maimon_product_added_to_cart");
1848          $(document.body).trigger("maimon_product_added_to_cart");
1849          $(document.body).trigger("added_to_cart", [
1850            fragments,
1851            cartHash,
1852            args.button,
1853          ]);
1854          const _qnt = $(".ajax_add_to_cart #quantity");
1855          const _add_res = $(".ajax_add_to_cart_response");
1856          if (_qnt && _qnt.length > 0) {
1857            _qnt.val(1);
1858            if (_add_res && _add_res.length > 0) {
1859              _add_res.append(
1860                '<em class="temp_result">' + _words.added + "</em>",
1861              );
1862              setTimeout(function () {
1863                _add_res.html("");
1864              }, 2000);
1865            }
1866          }
1867        }
1868      },
1869    };
1870    _woocommerce_custom.init();
1871
1872    $(document).on(
1873      "input keyup touchstart",
1874      ".maimon_search_autocomplete",
1875      function (e) {
1876        e.preventDefault();
1877        _deep_search.do_search($(this));
1878      },
1879    );
1880    $(document).on(
1881      "input keyup touchstart",
1882      ".maimon_search_autocomplete_page input.e-search-input",
1883      function (e) {
1884        e.preventDefault();
1885        _deep_search.do_search_page($(this));
1886      },
1887    );
1888    $(document).on(
1889      "input keyup touchstart",
1890      ".maimon_search_autocomplete_archive",
1891      function (e) {
1892        e.preventDefault();
1893        _deep_search.do_search_archive($(this));
1894      },
1895    );
1896    $(document).on("click", function (e) {
1897      _deep_search.maybe_remove_the_search_result_box(e);
1898    });
1899    $(document).on(
1900      "submit",
1901      "#search_hero_shortcode,.search_header_area_form_global",
1902      function (e) {
1903        const $input = $(this).find('input[type="search"]');
1904        if ($input && $input.length > 0) {
1905          const value = $input.val().trim();
1906          if (value.length < 2) {
1907            e.preventDefault();
1908          }
1909        }
1910      },
1911    );
1912
1913    const _deep_search = {
1914      debounceTimer: null,
1915      maybe_remove_the_search_result_box: function (event) {
1916        if (
1917          !$(event.target).closest(
1918            ".maimon_search_autocomplete, .maimon_search_autocomplete_page, .maimon_search_autocomplete_archive, .search_results_box, .search_results_box_page, .search_results_box_archive, .maimon-search-dropdown",
1919          ).length
1920        ) {
1921          $(
1922            ".search_results_box, .search_results_box_page, .search_results_box_archive",
1923          ).html("");
1924          $(".search_results_box_archive").removeClass("active");
1925          $(".maimon-search-dropdown").hide().empty();
1926        }
1927      },
1928      do_search: function ($this, is_archive = false) {
1929        let $input = $this;
1930        let query = $input.val();
1931        let $wrapper = $input.closest("form");
1932        let $spinner = $wrapper.find(".input_spinner");
1933        let $resultsContainer = $input.next(".search_results_box");
1934        clearTimeout(this.debounceTimer);
1935        if (query.length <= 2) {
1936          if ($resultsContainer) {
1937            $resultsContainer.html("");
1938            $spinner.hide();
1939          }
1940          return;
1941        }
1942        $spinner.show();
1943        const _fv = this;
1944        this.debounceTimer = setTimeout(() => {
1945          if ($resultsContainer.length === 0) {
1946            $resultsContainer = $('<div class="search_results_box"></div>');
1947            $input.after($resultsContainer);
1948          }
1949          const _d = {
1950            action: "maimon_deepSearch",
1951            search: query,
1952            type: is_archive ? "archive" : "normal",
1953          };
1954          _fv.ajax(_d, "POST", $resultsContainer, $spinner);
1955        }, 500);
1956      },
1957      do_search_page: function ($this) {
1958        let $input = $this;
1959        let query = $input.val();
1960        let $wrapper = $input.closest(".form");
1961        let $spinner = $wrapper.find(".input_spinner");
1962        let $resultsContainer = $input
1963          .parents(".e-search-form")
1964          .next(".search_results_box_page");
1965        if (query.length > 2) {
1966          if ($spinner.length === 0) {
1967            $spinner = $('<div class="input_spinner"></div>');
1968            $input.after($spinner);
1969          }
1970          if ($resultsContainer.length === 0) {
1971            $resultsContainer = $(
1972              '<div class="search_results_box_page"></div>',
1973            );
1974            $input.parents(".e-search-form").after($resultsContainer);
1975          }
1976          const _d = {
1977            action: "maimon_deepSearch",
1978            search: query,
1979            type: "page",
1980          };
1981          this.ajax(_d, "POST", $resultsContainer, $spinner);
1982        } else {
1983          if ($resultsContainer) {
1984            $resultsContainer.html("");
1985            $spinner.hide();
1986          }
1987        }
1988        return true;
1989      },
1990      do_search_archive: function ($this) {
1991        let $input = $this;
1992        let query = $input.val();
1993        let $wrapper = $("#lobby_search_block");
1994        let $spinner = $wrapper.find(".input_spinner");
1995        let $resultsContainer = $(".search_results_box_archive");
1996        if (query.length > 2) {
1997          $resultsContainer.addClass("active");
1998          const _d = {
1999            action: "maimon_deepSearch",
2000            search: query,
2001            type: "archive",
2002          };
2003          this.ajax(_d, "POST", $resultsContainer, $spinner);
2004        } else {
2005          if ($resultsContainer) {
2006            $resultsContainer.removeClass("active");
2007            $resultsContainer.html("");
2008            $spinner.hide();
2009          }
2010        }
2011        return true;
2012      },
2013      ajax: function (data, method, $resultsContainer, $spinner) {
2014        let ajax_data;
2015        ajax_data = data;
2016        ajax_data["nonce"] = _nonce;
2017        $.ajax({
2018          url: _ajax_url,
2019          data: ajax_data,
2020          headers: { "Content-Type": "application/x-www-form-urlencoded" },
2021          contentType: "application/json; charset=utf-8",
2022          dataType: "html",
2023          type: method,
2024          beforeSend: function () {
2025            $spinner.show();
2026          },
2027          success: function (response) {
2028            $resultsContainer.html(response);
2029          },
2030          complete: function () {
2031            $spinner.hide();
2032          },
2033        });
2034      },
2035    };
2036
2037    // Checkout step handling moved to checkout-step-fix.js.
2038    // fix slider height issue //
2039    $(".slick-slider").on("setPosition", function () {
2040      setTimeout(_fix_slick_slider.setEqualHeightPerSlider, 100);
2041    });
2042    $(window).on("resize", function () {
2043      setTimeout(_fix_slick_slider.setEqualHeightPerSlider, 100);
2044      // Re-run carousel functions on resize to toggle grid/slider
2045      _shortcodes.run_carousel_tips();
2046      _shortcodes.run_product_samples_tips();
2047      _shortcodes.run_carousel_chefs();
2048      _shortcodes.run_carousel_shop_products();
2049    });
2050    const _fix_slick_slider = {
2051      setEqualHeightPerSlider: function () {
2052        $(".slick-slider").each(function () {
2053          let maxHeight = 0;
2054          let $slider = $(this);
2055          let $slides = $slider.find(".slick-slide");
2056          $slides.each(function () {
2057            let thisHeight = $(this).outerHeight();
2058            if (thisHeight > maxHeight) {
2059              maxHeight = thisHeight;
2060            }
2061          });
2062          $slider.find(".slick-track").css("height", maxHeight + "px");
2063        });
2064      },
2065    };
2066  });
2067
2068  // redirect to thank you page after cf7 submitted
2069  document.addEventListener("DOMContentLoaded", function () {
2070    document.querySelectorAll('input[name="page_url"]').forEach(function (el) {
2071      if (!el.value) el.value = window.location.href;
2072    });
2073  });
2074  $(document).on("wpcf7mailsent", function (e) {
2075    const $form = $(e.target);
2076    const url = $form.find('input[name="page_url"]').val();
2077    // Priority 3: per-form map fallback
2078    if (url) {
2079      // small delay so analytics events can fire
2080      setTimeout(function () {
2081        window.location.assign(url);
2082      }, 500);
2083    }
2084  });
2085})(jQuery);
2086
2087/* ═══ MAIMON CUSTOM JS v1.0.7 ═══ */
2088/**
2089 * custom.js — Maimon Theme Custom JavaScript
2090 * Appended to the end of app.min.js
2091 *
2092 * Sections:
2093 *   Task 2  — Brands mega menu hover (show/hide)
2094 *   Task 3  — Dropdown with image (maimon-mega-dropdown)
2095 *   Task 4  — Mini cart count badge (AJAX update)
2096 *   Task 5  — Cart drawer (open/close, qty, remove, refresh)
2097 *   Task 6  — Products filter sidebar (AJAX filter)
2098 *   Task 8  — Product card qty buttons + AJAX add-to-cart
2099 *   Task 11 — "You may also like" carousel custom arrows
2100 */
2101(function ($) {
2102  "use strict";
2103
2104  /* ==========================================================
2105	   TASK 2 — Brands Mega Menu Horizontal (hover show/hide)
2106	   ========================================================== */
2107  var brandsMega = (function () {
2108    var $menuItem, $subMenu;
2109    var hideTimer = null;
2110    var DELAY = 150;
2110 // ms grace period before closing
2111
2112    function open() {
2113      clearTimeout(hideTimer);
2114      $menuItem.addClass("mega-hover");
2115      $subMenu.addClass("is-visible");
2116    }
2117
2118    function close() {
2119      hideTimer = setTimeout(function () {
2120        $menuItem.removeClass("mega-hover");
2121        $subMenu.removeClass("is-visible");
2122      }, DELAY);
2123    }
2124
2125    function init() {
2126      $menuItem = $("#menu-item-2142");
2127      if (!$menuItem.length) return;
2128
2129      $subMenu = $menuItem.children(".sub-menu");
2130      if (!$subMenu.length) return;
2131
2132      // Show/hide on hover (desktop only)
2133      $menuItem.on("mouseenter", open).on("mouseleave", close);
2134      $subMenu.on("mouseenter", open).on("mouseleave", close);
2135    }
2136
2137    return { init: init };
2138  })();
2139
2140  /* ==========================================================
2141	   TASK 3 — Dropdown with Image (maimon-mega-dropdown)
2142	   ========================================================== */
2143  var megaDropdown = (function () {
2144    var DELAY = 150;
2145
2146    function init() {
2147      $(".maimon-mega-dropdown").each(function () {
2148        var $item = $(this);
2149        var $sub = $item.children(".sub-menu");
2150        var timer = null;
2151
2152        if (!$sub.length) return;
2153
2154        // Populate image section from data-image attribute or first child image
2155        var imageUrl = $item.data("image") || "";
2156        if (!imageUrl) {
2157          var $firstImg = $sub.find("img").first();
2158          if ($firstImg.length) {
2159            imageUrl = $firstImg.attr("src");
2160          }
2161        }
2162
2163        // If we have an image URL and no image container yet, prepend one
2164        if (imageUrl && !$sub.find(".mega-dropdown-image").length) {
2165          $sub.prepend(
2166            '<div class="mega-dropdown-image">' +
2167              '<img src="' +
2168              imageUrl +
2169              '" alt="" loading="lazy">' +
2170              "</div>",
2171          );
2172        }
2173
2174        function openSub() {
2175          clearTimeout(timer);
2176          $item.addClass("mega-hover");
2177          $sub.addClass("is-visible");
2178        }
2179
2180        function closeSub() {
2181          timer = setTimeout(function () {
2182            $item.removeClass("mega-hover");
2183            $sub.removeClass("is-visible");
2184          }, DELAY);
2185        }
2186
2187        $item.on("mouseenter", openSub).on("mouseleave", closeSub);
2188        $sub.on("mouseenter", openSub).on("mouseleave", closeSub);
2189      });
2190    }
2191
2192    return { init: init };
2193  })();
2194
2195  /* ==========================================================
2196	   TASK 4 — Mini Cart Count Badge (AJAX update)
2197	   ========================================================== */
2198  function updateCartBadges(count) {
2199    var numericCount = Math.max(0, parseInt(count, 10) || 0);
2200    var $allBadges = $(
2201      ".maimon_cart_count, .elementor-button-icon-qty, #header-cart-btn .cart-badge, .maimon-cart-count",
2202    );
2203    var $drawerBadges = $("#header-cart-btn .cart-badge, .maimon-cart-count");
2204
2205    $allBadges.text(numericCount);
2206
2207    if ($drawerBadges.length) {
2208      $drawerBadges.toggleClass("has-items", numericCount > 0);
2209      $drawerBadges.css("display", numericCount > 0 ? "flex" : "none");
2210    }
2211  }
2212
2213  window.maimonUpdateCartBadges = updateCartBadges;
2214
2215  var miniCartBadge = (function () {
2216    /**
2217     * Fetch the current cart count from the server
2218     * and update all `.maimon-cart-count` badges.
2219     */
2220    function refreshCount(event, count) {
2221      if (typeof count !== "undefined" && count !== null) {
2222        updateCartBadges(count);
2223        return;
2224      }
2225
2226      if (typeof cjpg_ajax_obj === "undefined") return;
2227
2228      $.post(
2229        cjpg_ajax_obj.ajaxurl,
2230        {
2231          action: "maimon_get_cart_count",
2232          nonce: cjpg_ajax_obj.nonce,
2233        },
2234        function (res) {
2235          if (res.success) {
2236            updateCartBadges(res.data.count);
2237          }
2238        },
2239      );
2240    }
2241
2242    function init() {
2243      // WooCommerce native events
2244      $(document.body).on("added_to_cart", syncProductCards);
2245      $(document.body).on("removed_from_cart", refreshCount);
2246      $(document.body).on("removed_from_cart", syncProductCards);
2247
2248      // Custom event fired by cart drawer and product card after mutations
2249      $(document.body).on("maimon_cart_updated", refreshCount);
2250      $(document.body).on("maimon_cart_updated", syncProductCards);
2251    }
2252
2253    return { init: init };
2254  })();
2255
2256  /* ── Sync product cards on index/shop with cart quantities ── */
2257  function syncProductCards() {
2258    if (typeof cjpg_ajax_obj === "undefined") return;
2259    $.post(
2260      cjpg_ajax_obj.ajaxurl,
2261      {
2262        action: "maimon_get_cart_items",
2263        nonce: cjpg_ajax_obj.nonce,
2264      },
2265      function (res) {
2266        if (!res || !res.success || !res.data || !res.data.items) return;
2267        var qtyByProduct = {};
2268        $.each(res.data.items, function (i, it) {
2269          var pid = parseInt(it.product_id, 10);
2270          if (pid)
2271            qtyByProduct[pid] =
2272              (qtyByProduct[pid] || 0) + (parseInt(it.qty, 10) || 0);
2273        });
2274        $(".maimon-product-card").each(function () {
2275          var $card = $(this);
2276          var $btn = $card.find(".maimon_ajax_add_to_cart");
2277          var pid = $btn.length ? parseInt($btn.data("product_id"), 10) : 0;
2278          var $input = $card.find(".qty-input");
2279          if (!pid || !$input.length) return;
2280          var qty = qtyByProduct[pid] || 0;
2281          if (qty > 0) {
2282            $card.addClass("maimon-product-card--in-cart");
2283            $input.val(qty);
2284            $btn.attr("data-quantity", qty).data("quantity", qty).text(qty);
2285          } else {
2286            $card.removeClass("maimon-product-card--in-cart");
2287            $input.val(1);
2288            var addLabel =
2289              typeof cjpg_ajax_obj !== "undefined" &&
2290              cjpg_ajax_obj.words &&
2291              cjpg_ajax_obj.words.add_to_cart
2292                ? cjpg_ajax_obj.words.add_to_cart
2293                : "\u05D4\u05D5\u05E1\u05E4\u05D4 \u05DC\u05E1\u05DC";
2294            $btn.attr("data-quantity", 1).data("quantity", 1).text(addLabel);
2295          }
2296        });
2297
2298        // Also sync single product page controls from cart state
2299        $(".single_product_add_to_cart .single-product-cart-row").each(
2300          function () {
2301            var $row = $(this);
2302            var pid = parseInt($row.data("product-id"), 10) || 0;
2303            if (!pid) return;
2304            var qty = qtyByProduct[pid] || 0;
2305            if (qty > 0) {
2306              $row
2307                .addClass("single-product-cart-row--in-cart")
2308                .attr("data-in-cart", "1");
2309              $row.find(".single-product-qty-val").text(qty);
2310            } else {
2311              $row
2312                .removeClass("single-product-cart-row--in-cart")
2313                .attr("data-in-cart", "0");
2314              $row.find(".single-product-qty-val").text(1);
2315            }
2316          },
2317        );
2318      },
2319    );
2320  }
2321
2322  /* ==========================================================
2323	   TASK 5 — Cart Drawer (open/close, qty, remove, refresh)
2324	   ========================================================== */
2325  var cartDrawer = (function () {
2326    var $drawer, $overlay, $body, $footer;
2327    var isOpen = false;
2328
2329    /* ── Open the drawer ── */
2330    function open() {
2331      if (isOpen) return;
2332      isOpen = true;
2333      $drawer.addClass("is-open").attr("aria-hidden", "false");
2334      $overlay.addClass("is-visible");
2335      $("body").addClass("maimon-cart-drawer-open");
2336      // Focus the close button for accessibility
2337      $drawer.find(".maimon-cart-drawer__close").trigger("focus");
2338      // Load / refresh drawer content
2339      refreshDrawer();
2340    }
2341
2342    /* ── Close the drawer ── */
2343    function close() {
2344      if (!isOpen) return;
2345      isOpen = false;
2346      $drawer.removeClass("is-open").attr("aria-hidden", "true");
2347      $overlay.removeClass("is-visible");
2348      $("body").removeClass("maimon-cart-drawer-open");
2349    }
2350
2351    /* ── Refresh drawer body + footer via AJAX ── */
2352    function refreshDrawer() {
2353      if (typeof cjpg_ajax_obj === "undefined") return;
2354
2355      $drawer.addClass("is-loading");
2356
2357      $.post(
2358        cjpg_ajax_obj.ajaxurl,
2359        {
2360          action: "maimon_get_cart_drawer",
2361          nonce: cjpg_ajax_obj.nonce,
2362        },
2363        function (res) {
2364          $drawer.removeClass("is-loading");
2365          if (res.success) {
2366            $drawer
2367              .find(".maimon-cart-drawer__body")
2368              .html(res.data.body_html || "");
2369            $drawer
2370              .find(".maimon-cart-drawer__footer")
2371              .html(res.data.footer_html || "");
2372            var $countVal = $drawer.find(".maimon-cart-drawer__count-value");
2373            if ($countVal.length && res.data.count !== undefined) {
2374              $countVal.text(
2375                res.data.count +
2376                  " " +
2377                  (res.data.count === 1
2378                    ? "\u05E4\u05E8\u05D9\u05D8"
2379                    : "\u05E4\u05E8\u05D9\u05D8\u05D9\u05DD"),
2380              );
2381            }
2382            var $footerInner = $drawer.find(
2383              ".maimon-cart-drawer__footer-inner",
2384            );
2385            if ($footerInner.length) {
2386              $footerInner.toggleClass("is-hidden", !!res.data.is_empty);
2387            }
2388          }
2389        },
2390      ).fail(function () {
2391        $drawer.removeClass("is-loading");
2392      });
2393    }
2394
2395    /* ── Update item quantity ── */
2396    function updateQty(cartItemKey, quantity) {
2397      if (typeof cjpg_ajax_obj === "undefined") return;
2398
2399      $.post(
2400        cjpg_ajax_obj.ajaxurl,
2401        {
2402          action: "maimon_update_cart_item",
2403          cart_item_key: cartItemKey,
2404          quantity: quantity,
2405          nonce: cjpg_ajax_obj.nonce,
2406        },
2407        function (res) {
2408          if (res.success) {
2409            refreshDrawer();
2410            $(document.body).trigger("maimon_cart_updated", [
2411              res && res.data ? res.data.count : undefined,
2412            ]);
2413            return;
2414          }
2415
2416          refreshDrawer();
2417          if (res && res.data && res.data.message) {
2418            window.alert(res.data.message);
2419          }
2420        },
2421      ).fail(function () {
2422        refreshDrawer();
2423      });
2424    }
2425
2426    function clampQtyValue(value, $qtyInput) {
2427      var min = parseInt($qtyInput.attr("min"), 10) || 1;
2428      var max = parseInt($qtyInput.attr("max"), 10) || 99;
2429      var parsed = parseInt(value, 10);
2430
2431      if (isNaN(parsed)) {
2432        parsed = min;
2433      }
2434
2435      return Math.max(min, Math.min(parsed, max));
2436    }
2437
2438    function applyDrawerQty($wrap, nextQty) {
2439      var key = $wrap.data("cart-item-key");
2440      var $qty = $wrap.find(".qty-input").first();
2441
2442      if (!key || !$qty.length) return;
2443
2444      var next = clampQtyValue(nextQty, $qty);
2445      var last = clampQtyValue($qty.attr("data-last-value"), $qty);
2446
2447      $qty.val(next);
2448
2449      if (next === last) return;
2450
2451      $qty.attr("data-last-value", next);
2452      updateQty(key, next);
2453    }
2454
2455    /* ── Remove item ── */
2456    function removeItem(cartItemKey) {
2457      if (typeof cjpg_ajax_obj === "undefined") return;
2458
2459      $.post(
2460        cjpg_ajax_obj.ajaxurl,
2461        {
2462          action: "maimon_remove_cart_item",
2463          cart_item_key: cartItemKey,
2464          nonce: cjpg_ajax_obj.nonce,
2465        },
2466        function (res) {
2467          if (res.success) {
2468            refreshDrawer();
2469            $(document.body).trigger("maimon_cart_updated", [
2470              res && res.data ? res.data.count : undefined,
2471            ]);
2472          }
2473        },
2474      );
2475    }
2476
2477    /* ── Bind all events ── */
2478    function bindEvents() {
2479      // Open: cart icon click
2480      $(document).on("click", ".maimon-header-cart", function (e) {
2481        e.preventDefault();
2482        open();
2483      });
2484
2485      // Open: custom event
2486      $(document.body).on("maimon_open_cart_drawer", function () {
2487        open();
2488      });
2489
2490      // Close: X button
2491      $(document).on("click", ".maimon-cart-drawer__close", function () {
2492        close();
2493      });
2494
2495      // Close: overlay click
2496      $(document).on("click", ".maimon-cart-drawer__overlay", function () {
2497        close();
2498      });
2499
2500      // Close: המשך קנייה button
2501      $(document).on("click", ".maimon-cart-drawer__btn-continue", function () {
2502        close();
2503      });
2504
2505      // Close: ESC key
2506      $(document).on("keydown", function (e) {
2507        if (e.key === "Escape" && isOpen) {
2508          close();
2509        }
2510      });
2511
2512      // Qty plus button (delegated inside drawer)
2513      $(document).on(
2514        "click",
2515        '.maimon-cart-drawer .qty-btn[data-action="plus"]',
2516        function () {
2517          var $btn = $(this);
2518          var $wrap = $btn.closest(".maimon-cart-drawer__item");
2519          var $qty = $wrap.find(".qty-input").first();
2520          var cur = clampQtyValue($qty.val(), $qty);
2521
2522          applyDrawerQty($wrap, cur + 1);
2523        },
2524      );
2525
2526      // Qty minus button (delegated inside drawer)
2527      $(document).on(
2528        "click",
2529        '.maimon-cart-drawer .qty-btn[data-action="minus"]',
2530        function () {
2531          var $btn = $(this);
2532          var $wrap = $btn.closest(".maimon-cart-drawer__item");
2533          var $qty = $wrap.find(".qty-input").first();
2534          var cur = clampQtyValue($qty.val(), $qty);
2535
2536          applyDrawerQty($wrap, cur - 1);
2537        },
2538      );
2539
2540      // Qty direct input
2541      $(document).on("input", ".maimon-cart-drawer .qty-input", function () {
2542        var raw = String($(this).val() || "").replace(/[^\d]/g, "");
2543        $(this).val(raw);
2544      });
2545
2546      $(document).on("change", ".maimon-cart-drawer .qty-input", function () {
2547        applyDrawerQty(
2548          $(this).closest(".maimon-cart-drawer__item"),
2549          $(this).val(),
2550        );
2551      });
2552
2553      $(document).on("keydown", ".maimon-cart-drawer .qty-input", function (e) {
2554        if (e.key === "Enter") {
2555          e.preventDefault();
2556          $(this).trigger("change");
2557          $(this).trigger("blur");
2558        }
2559      });
2560
2561      // Remove item button
2562      $(document).on(
2563        "click",
2564        ".maimon-cart-drawer .maimon-cart-drawer__remove",
2565        function () {
2566          var $wrap = $(this).closest(".maimon-cart-drawer__item");
2567          var key = $wrap.data("cart-item-key");
2568          // Fade out the item optimistically
2569          $wrap.fadeOut(200);
2570          removeItem(key);
2571        },
2572      );
2573    }
2574
2575    function init() {
2576      $drawer = $(".maimon-cart-drawer");
2577      $overlay = $(".maimon-cart-drawer__overlay");
2578      $body = $(".maimon-cart-drawer__body");
2579      $footer = $(".maimon-cart-drawer__footer");
2580
2581      if (!$drawer.length) return;
2582
2583      bindEvents();
2584    }
2585
2586    return { init: init };
2587  })();
2588
2589  /* ==========================================================
2590	   TASK 6 — Products Filter Sidebar (AJAX filter + Load More)
2591	   ========================================================== */
2592  var productsFilter = (function () {
2593    var $panel, $grid, $count, $loadMoreWrap, $loadMoreBtn, $sortSelect;
2594    var currentOrder = "date";
2595    var debounceTimer = null;
2596    var loadedCount = 0;
2597    var totalCount = 0;
2598    var INITIAL_PP = 16;
2599    var LOADMORE_PP = 8;
2600
2601    /* ── Read URL search params ── */
2602    function getUrlParams() {
2603      var params = new URLSearchParams(window.location.search);
2604      var brands = params.getAll("brands[]").length
2605        ? params.getAll("brands[]")
2606        : params.getAll("brands");
2607      var categories = params.getAll("categories[]").length
2608        ? params.getAll("categories[]")
2609        : params.getAll("categories");
2610      var legacyCompanies = params.getAll("company");
2611      var legacyCategories = params.getAll("product_category");
2612
2613      legacyCompanies.forEach(function (company) {
2614        brands.push(company);
2615      });
2616      legacyCategories.forEach(function (category) {
2617        categories.push(category);
2618      });
2619
2620      return {
2621        search: params.get("search") || "",
2622        brands: Array.from(new Set(brands)),
2623        categories: Array.from(new Set(categories)),
2624        orderby: params.get("orderby") || "date",
2625      };
2626    }
2627
2628    /* ── Update URL without reload ── */
2629    function updateUrl() {
2630      var filters = getFilters();
2631      var params = new URLSearchParams();
2632
2633      if (filters.search) {
2634        params.set("search", filters.search);
2635      }
2636      filters.brands.forEach(function (b) {
2637        params.append("brands[]", b);
2638      });
2639      filters.categories.forEach(function (c) {
2640        params.append("categories[]", c);
2641      });
2642      if (currentOrder && currentOrder !== "date") {
2643        params.set("orderby", currentOrder);
2644      }
2645
2646      var qs = params.toString();
2647      var newUrl = window.location.pathname + (qs ? "?" + qs : "");
2648      window.history.replaceState(null, "", newUrl);
2649    }
2650
2651    /* ── Collect checked brands, categories, search value ── */
2652    function getFilters() {
2653      var brands = [];
2654      var categories = [];
2655
2656      $panel.find('input[name="brands[]"]:checked').each(function () {
2657        brands.push($(this).val());
2658      });
2659      $panel.find('input[name="categories[]"]:checked').each(function () {
2660        categories.push($(this).val());
2661      });
2662
2663      return {
2664        search: $panel.find(".maimon-filter-search__input").val() || "",
2665        brands: brands,
2666        categories: categories,
2667      };
2668    }
2669
2670    /* ── Execute AJAX filter request ── */
2671    function doFilter(append) {
2672      var filters = getFilters();
2673      var nonce = $panel.data("nonce") || "";
2674      var ajaxUrl =
2675        typeof cjpg_ajax_obj !== "undefined" ? cjpg_ajax_obj.ajaxurl : "";
2676
2677      if (!ajaxUrl) return;
2678
2679      var perPage = append ? LOADMORE_PP : INITIAL_PP;
2680      var offset = append ? loadedCount : 0;
2681
2682      $grid.addClass("maimon-loading");
2683      if ($loadMoreBtn.length) {
2684        $loadMoreBtn.prop("disabled", true).text("\u05D8\u05D5\u05E2\u05DF..."); // "טוען..."
2685      }
2686
2687      if (!append) {
2688        updateUrl();
2689      }
2690
2691      $.ajax({
2692        url: ajaxUrl,
2693        type: "POST",
2694        data: {
2695          action: "maimon_filter_products",
2696          nonce: nonce,
2697          search: filters.search,
2698          brands: filters.brands,
2699          categories: filters.categories,
2700          orderby: currentOrder,
2701          per_page: perPage,
2702          offset: offset,
2703        },
2704        success: function (res) {
2705          $grid.removeClass("maimon-loading");
2706          if (res && res.success) {
2707            if (append) {
2708              $grid.append(res.data.html);
2709            } else {
2710              $grid.html(res.data.html);
2711            }
2712            totalCount = res.data.count;
2713            loadedCount = res.data.loaded;
2714            updateCount(totalCount);
2715            updateLoadMore(res.data.has_more);
2716          }
2717          if ($loadMoreBtn.length) {
2718            $loadMoreBtn
2719              .prop("disabled", false)
2720              .text(
2721                "\u05D8\u05E2\u05DF \u05E2\u05D5\u05D3 \u05DE\u05D5\u05E6\u05E8\u05D9\u05DD",
2722              ); // "טען עוד מוצרים"
2723          }
2724        },
2725        error: function () {
2726          $grid.removeClass("maimon-loading");
2727          if ($loadMoreBtn.length) {
2728            $loadMoreBtn
2729              .prop("disabled", false)
2730              .text(
2731                "\u05D8\u05E2\u05DF \u05E2\u05D5\u05D3 \u05DE\u05D5\u05E6\u05E8\u05D9\u05DD",
2732              );
2733          }
2734        },
2735      });
2736    }
2737
2738    /* ── Update results count label ── */
2739    function updateCount(total) {
2740      if ($count.length) {
2741        $count.text(
2742          "\u05E0\u05DE\u05E6\u05D0\u05D5 \u05E1\u05D4\u05F4\u05DB \u05DB " +
2743            total +
2744            " \u05DE\u05D5\u05E6\u05E8\u05D9\u05DD",
2745        ); // "נמצאו סה״כ כ {x} מוצרים"
2746      }
2747    }
2748
2749    /* ── Show / hide load-more button ── */
2750    function updateLoadMore(hasMore) {
2751      if ($loadMoreWrap.length) {
2752        if (hasMore) {
2753          $loadMoreWrap.show();
2754        } else {
2755          $loadMoreWrap.hide();
2756        }
2757      }
2758    }
2759
2760    /* ── Toggle accordion groups ── */
2761    function initAccordions() {
2762      $panel.on("click", ".maimon-filter-group__header", function () {
2763        var $header = $(this);
2764        var $body = $header.next(".maimon-filter-group__body");
2765        var isOpen = $header.attr("aria-expanded") === "true";
2766
2767        $header.attr("aria-expanded", isOpen ? "false" : "true");
2768
2769        if (isOpen) {
2770          $body.slideUp(200, function () {
2771            $body.attr("hidden", "");
2772          });
2773        } else {
2774          $body.removeAttr("hidden").hide().slideDown(200);
2775        }
2776      });
2777    }
2778
2779    /* ── Debounced search input (400ms) ── */
2780    function initSearch() {
2781      $panel.on("input", ".maimon-filter-search__input", function () {
2782        clearTimeout(debounceTimer);
2783        debounceTimer = setTimeout(function () {
2784          doFilter(false);
2785        }, 400);
2786      });
2787    }
2788
2789    /* ── Checkbox change triggers filter ── */
2790    function initCheckboxes() {
2791      $panel.on("change", 'input[type="checkbox"]', function () {
2792        doFilter(false);
2793      });
2794    }
2795
2796    /* ── Sort dropdown change triggers filter ── */
2797    function initSort() {
2798      $sortSelect = $("#maimon-sort-select");
2799      if ($sortSelect.length) {
2800        $sortSelect.on("change", function () {
2801          currentOrder = $(this).val();
2802          doFilter(false);
2803        });
2804      }
2805    }
2806
2807    /* ── Load More button click ── */
2808    function initLoadMore() {
2809      $loadMoreBtn.on("click", function () {
2810        doFilter(true);
2811      });
2812    }
2813
2814    /* ── Apply URL params to UI on init ── */
2815    function applyUrlParams() {
2816      var params = getUrlParams();
2817      function checkInputsByParam(name, values) {
2818        values.forEach(function (rawValue) {
2819          var value = String(rawValue);
2820          var $input = $panel.find(
2821            'input[name="' + name + '[]"][value="' + value + '"]',
2822          );
2823          if (!$input.length) {
2824            $input = $panel
2825              .find('input[name="' + name + '[]"]')
2826              .filter(function () {
2827                return String($(this).data("termSlug")) === value;
2828              })
2829              .first();
2830          }
2831          if ($input.length) {
2832            $input.prop("checked", true);
2833          }
2834        });
2835      }
2836
2837      if (params.search) {
2838        $panel.find(".maimon-filter-search__input").val(params.search);
2839      }
2840
2841      checkInputsByParam("brands", params.brands);
2842      checkInputsByParam("categories", params.categories);
2843
2844      if (params.orderby) {
2845        currentOrder = params.orderby;
2846        if ($sortSelect && $sortSelect.length) {
2847          $sortSelect.val(params.orderby);
2848        }
2849      }
2850    }
2851
2852    function init() {
2853      $panel = $(".maimon-filter-panel");
2854      $grid = $(".maimon-products-grid");
2855      $count = $(".maimon-results-count");
2856      $loadMoreWrap = $(".maimon-load-more-wrap");
2857      $loadMoreBtn = $(".maimon-load-more-btn");
2858
2859      if (!$panel.length || !$grid.length) return;
2860
2861      initAccordions();
2862      initSearch();
2863      initCheckboxes();
2864      initSort();
2865      initLoadMore();
2866
2867      applyUrlParams();
2868      doFilter(false);
2869    }
2870
2871    return { init: init };
2872  })();
2873
2874  /* ==========================================================
2875	   TASK 8 — Product Card Qty Buttons + AJAX Add-to-Cart
2876	   ========================================================== */
2877  var productCardActions = (function () {
2878    function init() {
2879      // Qty +/- buttons on product cards in grid
2880      $(document).on(
2881        "click",
2882        '.maimon-product-card .maimon-product-card__qty .qty-btn[data-action="plus"]',
2883        function () {
2884          if (
2885            $(this).closest(
2886              ".single_product_add_to_cart, .maimon-cart-drawer, #side-cart-drawer",
2887            ).length
2888          )
2889            return;
2890          var $input = $(this)
2891            .closest(".maimon-product-card__qty")
2892            .find(".qty-input");
2893          var val = parseInt($input.val(), 10) || 1;
2894          var newVal = Math.min(val + 1, 99);
2895          $input.val(newVal);
2896          syncCartBtnQty($(this));
2897
2898          // If card is in-cart, sync exact qty in cart
2899          var $card = $(this).closest(".maimon-product-card");
2900          if ($card.hasClass("maimon-product-card--in-cart")) {
2901            setProductQtyInCart($card, newVal);
2902          }
2903        },
2904      );
2905
2906      $(document).on(
2907        "click",
2908        '.maimon-product-card .maimon-product-card__qty .qty-btn[data-action="minus"]',
2909        function () {
2910          if (
2911            $(this).closest(
2912              ".single_product_add_to_cart, .maimon-cart-drawer, #side-cart-drawer",
2913            ).length
2914          )
2915            return;
2916          var $input = $(this)
2917            .closest(".maimon-product-card__qty")
2918            .find(".qty-input");
2919          var val = parseInt($input.val(), 10) || 1;
2920          var $card = $(this).closest(".maimon-product-card");
2921
2922          // Before add-to-cart keep minimum 1 in UI.
2923          if (!$card.hasClass("maimon-product-card--in-cart")) {
2924            if (val <= 1) return;
2925            $input.val(val - 1);
2926            syncCartBtnQty($(this));
2927            return;
2928          }
2929
2930          var newVal = Math.max(val - 1, 0);
2931          if (newVal === 0) {
2932            $card.removeClass("maimon-product-card--in-cart");
2933            $input.val(1);
2934            syncCartBtnQty($(this));
2935            setProductQtyInCart($card, 0);
2936            return;
2937          }
2938
2939          $input.val(newVal);
2940          syncCartBtnQty($(this));
2941          setProductQtyInCart($card, newVal);
2942        },
2943      );
2944
2945      // AJAX add-to-cart button — intercept before the original handler
2946      $(document).on(
2947        "click",
2948        ".maimon-product-card .maimon_ajax_add_to_cart",
2949        function (e) {
2950          if (
2951            $(this).closest(
2952              ".single_product_add_to_cart, .maimon-cart-drawer, #side-cart-drawer",
2953            ).length
2954          )
2955            return;
2956          e.preventDefault();
2957          e.stopImmediatePropagation(); // Prevent original theme handler
2958
2959          var $btn = $(this);
2960          var $card = $btn.closest(".maimon-product-card");
2961
2962          if ($btn.prop("disabled") || $btn.hasClass("loading")) return;
2963
2964          var productId = $btn.data("product_id");
2965          var $qtyInput = $btn
2966            .closest(".maimon-product-card__actions")
2967            .find(".qty-input");
2968          var quantity = parseInt($qtyInput.val(), 10) || 1;
2969          var nonce =
2970            $btn.data("nonce") ||
2971            (typeof cjpg_ajax_obj !== "undefined"
2972              ? cjpg_ajax_obj.nonce || ""
2973              : "");
2974          var ajaxUrl =
2975            typeof cjpg_ajax_obj !== "undefined" ? cjpg_ajax_obj.ajaxurl : "";
2976
2977          if (!ajaxUrl || !productId) return;
2978
2979          $btn.addClass("loading").text("\u05DE\u05D5\u05E1\u05D9\u05E3..."); // "מוסיף..."
2980
2981          $.ajax({
2982            url: ajaxUrl,
2983            type: "POST",
2984            data: {
2985              action: "maimon_ajax_add_to_cart",
2986              product_id: productId,
2987              quantity: quantity,
2988              nonce: nonce,
2989            },
2990            success: function (res) {
2991              $btn.removeClass("loading");
2992              var isSuccess = !!(res && (res.success || res.fragments));
2993              var dataObj = res && res.data ? res.data : {};
2994              var fragments =
2995                dataObj.fragments || (res ? res.fragments || {} : {});
2996              var cartHash =
2997                dataObj.cart_hash || (res ? res.cart_hash || "" : "");
2998
2999              if (isSuccess) {
3000                // Toggle ALL cards with this product to "in-cart" (incl. Slick clones)
3001                var pid = String(productId);
3002                var $allCards = $(
3003                  '.maimon_ajax_add_to_cart[data-product_id="' + pid + '"]',
3004                ).closest(".maimon-product-card");
3005                $allCards.addClass("maimon-product-card--in-cart");
3006                $allCards
3007                  .find(".maimon-product-card__actions .qty-input")
3008                  .val(quantity);
3009                $allCards
3010                  .find(".maimon_ajax_add_to_cart")
3011                  .attr("data-quantity", quantity)
3012                  .data("quantity", quantity)
3013                  .removeClass("loading")
3014                  .text(quantity);
3015
3016                if (typeof dataObj.count !== "undefined") {
3017                  updateCartBadges(dataObj.count);
3018                }
3019
3020                // Trigger cart update events
3021                $(document.body).trigger("maimon_cart_updated", [
3022                  typeof dataObj.count !== "undefined"
3023                    ? dataObj.count
3024                    : undefined,
3025                ]);
3026                $(document).trigger("maimon_product_added_to_cart");
3027                $(document.body).trigger("maimon_product_added_to_cart");
3028                $(document).trigger("added_to_cart", [
3029                  fragments,
3030                  cartHash,
3031                  $btn,
3032                ]);
3033                $(document.body).trigger("added_to_cart", [
3034                  fragments,
3035                  cartHash,
3036                  $btn,
3037                ]);
3038              } else {
3039                $btn.text("\u05D4\u05D5\u05E1\u05E4\u05D4 \u05DC\u05E1\u05DC"); // "הוספה לסל"
3040              }
3041            },
3042            error: function () {
3043              $btn
3044                .removeClass("loading")
3045                .text("\u05D4\u05D5\u05E1\u05E4\u05D4 \u05DC\u05E1\u05DC");
3046            },
3047          });
3048        },
3049      );
3050    }
3051
3052    /* ── Sync exact product qty in cart for +/- controls ── */
3053    function setProductQtyInCart($card, qty) {
3054      var $btn = $card.find(".maimon_ajax_add_to_cart");
3055      var ajaxUrl =
3056        typeof cjpg_ajax_obj !== "undefined" && cjpg_ajax_obj.ajaxurl
3057          ? cjpg_ajax_obj.ajaxurl
3058          : document.body.getAttribute("data-ajax-url") || "";
3059      if (!ajaxUrl) return;
3060
3061      $.ajax({
3062        url: ajaxUrl,
3063        type: "POST",
3064        data: {
3065          action: "maimon_set_product_qty_in_cart",
3066          product_id: $btn.data("product_id"),
3067          quantity: Math.max(0, parseInt(qty, 10) || 0),
3068          nonce:
3069            $btn.data("nonce") ||
3070            (typeof cjpg_ajax_obj !== "undefined"
3071              ? cjpg_ajax_obj.nonce || ""
3072              : ""),
3073        },
3074        success: function (res) {
3075          if (res && res.success) {
3076            if (res.data && typeof res.data.count !== "undefined") {
3077              updateCartBadges(res.data.count);
3078            }
3079            $(document.body).trigger("maimon_cart_updated", [
3080              res.data && typeof res.data.count !== "undefined"
3081                ? res.data.count
3082                : undefined,
3083            ]);
3084            return;
3085          }
3086
3087          $(document.body).trigger("maimon_cart_updated");
3088          if (res && res.data && res.data.message) {
3089            window.alert(res.data.message);
3090          }
3091        },
3092        error: function () {
3093          $(document.body).trigger("maimon_cart_updated");
3094        },
3095      });
3096    }
3097
3098    /* ── Sync data-quantity on the add-to-cart button ── */
3099    function syncCartBtnQty($btn) {
3100      var $actions = $btn.closest(".maimon-product-card__actions");
3101      var $cart = $actions.find(".maimon_ajax_add_to_cart");
3102      var $input = $actions.find(".qty-input");
3103      if ($cart.length && $input.length) {
3104        $cart
3105          .data("quantity", $input.val())
3106          .attr("data-quantity", $input.val());
3107      }
3108    }
3109
3110    return { init: init };
3111  })();
3112
3113  /* ==========================================================
3114	   TASK 11 — "You May Also Like" Carousel Custom Arrows
3115	   ========================================================== */
3116  var carouselArrows = (function () {
3117    function init() {
3118      // If custom prev/next buttons exist alongside a Slick carousel,
3119      // wire them up. The inline <script> in the PHP template already
3120      // handles its own arrows (.maimon-yml-prev / .maimon-yml-next).
3121      // This handler covers any additional generic arrow pair.
3122      $(document).on("click", ".maimon-carousel-prev", function () {
3123        var $carousel = $(this)
3124          .closest(".maimon-you-may-like__wrapper")
3125          .find(".slick-initialized");
3126        if ($carousel.length) {
3127          $carousel.slick("slickPrev");
3128        }
3129      });
3130
3131      $(document).on("click", ".maimon-carousel-next", function () {
3132        var $carousel = $(this)
3133          .closest(".maimon-you-may-like__wrapper")
3134          .find(".slick-initialized");
3135        if ($carousel.length) {
3136          $carousel.slick("slickNext");
3137        }
3138      });
3139
3140      // Also handle the case where the carousel sits inside a
3141      // different wrapper (e.g. `.maimon_products_may_like_inner_carousel_list`)
3142      $(document).on(
3143        "click",
3144        ".maimon_products_may_like_inner_carousel_list .maimon-carousel-prev",
3145        function () {
3146          var $slider = $(this).siblings(".slick-initialized");
3147          if (!$slider.length) {
3148            $slider = $(this)
3149              .closest(".maimon_products_may_like_inner_carousel_list")
3150              .find(".slick-initialized");
3151          }
3152          if ($slider.length) {
3153            $slider.slick("slickPrev");
3154          }
3155        },
3156      );
3157
3158      $(document).on(
3159        "click",
3160        ".maimon_products_may_like_inner_carousel_list .maimon-carousel-next",
3161        function () {
3162          var $slider = $(this).siblings(".slick-initialized");
3163          if (!$slider.length) {
3164            $slider = $(this)
3165              .closest(".maimon_products_may_like_inner_carousel_list")
3166              .find(".slick-initialized");
3167          }
3168          if ($slider.length) {
3169            $slider.slick("slickNext");
3170          }
3171        },
3172      );
3173    }
3174
3175    return { init: init };
3176  })();
3177
3178  /* ==========================================================
3179	   DOM READY — Initialize all modules
3180	   ========================================================== */
3181  $(document).ready(function () {
3182    brandsMega.init();
3183    megaDropdown.init();
3184    miniCartBadge.init();
3185    cartDrawer.init();
3186    if (!window.maimonArchiveFilterV2Active) {
3187      productsFilter.init();
3188    }
3189    productCardActions.init();
3190    carouselArrows.init();
3191  });
3192})(jQuery);
3193
3194/* ═══ Single Product Qty Buttons (Task 9) ═══ */
3195(function ($) {
3196  "use strict";
3197  window.maimonSingleProductCartBound = true;
3198  $(document).ready(function () {
3199    $(document).on(
3200      "click",
3201      ".single_product_add_to_cart .single-product-add-btn",
3202      function (e) {
3203        e.preventDefault();
3204        e.stopImmediatePropagation();
3205        var $btn = $(this);
3206        var $row = $btn.closest(".single-product-cart-row");
3207        if ($btn.hasClass("loading")) return;
3208        var productId = $btn.data("product_id");
3209        var nonce =
3210          $row.data("nonce") ||
3211          (typeof cjpg_ajax_obj !== "undefined"
3212            ? cjpg_ajax_obj.nonce || ""
3213            : "") ||
3214          (typeof miniCartData !== "undefined" ? miniCartData.nonce : "");
3215        var ajaxUrl =
3216          typeof cjpg_ajax_obj !== "undefined" && cjpg_ajax_obj.ajaxurl
3217            ? cjpg_ajax_obj.ajaxurl
3218            : "";
3219        if (!ajaxUrl || !productId) return;
3220        $btn.addClass("loading").text("מוסיף...");
3221        $.ajax({
3222          url: ajaxUrl,
3223          type: "POST",
3224          data: {
3225            action: "maimon_ajax_add_to_cart",
3226            product_id: productId,
3227            quantity: 1,
3228            nonce: nonce,
3229          },
3230          success: function (res) {
3231            $btn.removeClass("loading").text("הוספה לסל");
3232            var fragments =
3233              res && res.data && res.data.fragments
3234                ? res.data.fragments
3235                : res && res.fragments
3236                  ? res.fragments
3237                  : {};
3238            var cartHash =
3239              res && res.data && res.data.cart_hash
3240                ? res.data.cart_hash
3241                : res && res.cart_hash
3242                  ? res.cart_hash
3243                  : "";
3244            if (res && (res.success || res.fragments)) {
3245              $row
3246                .addClass("single-product-cart-row--in-cart")
3247                .attr("data-in-cart", "1");
3248              $row.find(".single-product-qty-val").text(1);
3249              if (res.data && typeof res.data.count !== "undefined") {
3250                window.maimonUpdateCartBadges(res.data.count);
3251              }
3252              $(document.body).trigger("maimon_cart_updated", [
3253                res.data && typeof res.data.count !== "undefined"
3254                  ? res.data.count
3255                  : undefined,
3256              ]);
3257              $(document).trigger("maimon_product_added_to_cart");
3258              $(document.body).trigger("maimon_product_added_to_cart");
3259              $(document.body).trigger("added_to_cart", [
3260                fragments,
3261                cartHash,
3262                $btn,
3263              ]);
3264            }
3265          },
3266          error: function () {
3267            $btn.removeClass("loading").text("הוספה לסל");
3268          },
3269          complete: function () {
3270            if ($.active <= 1) {
3271              $("body").removeClass("maimon-cursor-spinner-active");
3272            }
3273          },
3274        });
3275      },
3276    );
3277
3278    $(document).on(
3279      "click",
3280      '.single_product_add_to_cart .single-product-qty-btn[data-action="plus"]',
3281      function (e) {
3282        e.preventDefault();
3283        var $row = $(this).closest(".single-product-cart-row");
3284        var $val = $row.find(".single-product-qty-val");
3285        var max = parseInt($row.data("max"), 10) || 999;
3286        var val = parseInt($val.text(), 10) || 1;
3287        var newVal = Math.min(val + 1, max);
3288        if (newVal === val) return;
3289        $val.text(newVal);
3290        singleProductSetQty($row, newVal);
3291      },
3292    );
3293
3294    $(document).on(
3295      "click",
3296      '.single_product_add_to_cart .single-product-qty-btn[data-action="minus"]',
3297      function (e) {
3298        e.preventDefault();
3299        var $row = $(this).closest(".single-product-cart-row");
3300        var $val = $row.find(".single-product-qty-val");
3301        var val = parseInt($val.text(), 10) || 1;
3302        var newVal = Math.max(0, val - 1);
3303        $val.text(newVal);
3304        if (newVal === 0) {
3305          $row
3306            .removeClass("single-product-cart-row--in-cart")
3307            .attr("data-in-cart", "0");
3308        }
3309        singleProductSetQty($row, newVal);
3310      },
3311    );
3312
3313    function singleProductSetQty($row, qty) {
3314      var productId = parseInt($row.data("product-id"), 10) || 0;
3315      var nonce =
3316        $row.data("nonce") ||
3317        (typeof cjpg_ajax_obj !== "undefined"
3318          ? cjpg_ajax_obj.nonce || ""
3319          : "") ||
3320        (typeof miniCartData !== "undefined" ? miniCartData.nonce : "");
3321      var ajaxUrl =
3322        typeof cjpg_ajax_obj !== "undefined" && cjpg_ajax_obj.ajaxurl
3323          ? cjpg_ajax_obj.ajaxurl
3324          : "";
3325      if (!ajaxUrl || !productId) return;
3326      $.post(ajaxUrl, {
3327        action: "maimon_set_product_qty_in_cart",
3328        product_id: productId,
3329        quantity: Math.max(0, parseInt(qty, 10) || 0),
3330        nonce: nonce,
3331      }).done(function (res) {
3332        if (res && res.success) {
3333          if (res.data && typeof res.data.count !== "undefined") {
3334            window.maimonUpdateCartBadges(res.data.count);
3335          }
3336          if (res.data && res.data.product_qty === 0) {
3337            $row
3338              .removeClass("single-product-cart-row--in-cart")
3339              .attr("data-in-cart", "0");
3340            $row.find(".single-product-qty-val").text(1);
3341          }
3342          $(document.body).trigger("maimon_cart_updated", [
3343            res.data && typeof res.data.count !== "undefined"
3344              ? res.data.count
3345              : undefined,
3346          ]);
3347        }
3348      });
3349    }
3350  });
3351})(jQuery);

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.