PageSourceSearch

https://www.perodua.com.my/assets/js/landing-page.js

js perodua.com.my collected 2026-10-02 10:40:32 UTC 31,350 bytes, 970 lines download raw bytes

1document.addEventListener("DOMContentLoaded", function () {
2  // $(window).scroll(function () {
3  //   if ($(this).scrollTop() > 195) {
4  //     //use `this`, not `document`
5  //     $(".mouse-gif").css({
6  //       opacity: "0",
7  //     });
8
9  //     $(".black-bg-divider .hero-banner-divider").css({
10  //       opacity: "0",
11  //     });
12  //   }
13  //   if ($(this).scrollTop() < 190) {
14  //     //use `this`, not `document`
15  //     $(".mouse-gif").css({
16  //       opacity: "1",
17  //     });
18  //     $(".black-bg-divider .hero-banner-divider").css({
19  //       opacity: "1",
20  //     });
21  //     $(".black-bg-divider").css({
22  //       border: "none",
23  //     });
24  //   }
25  // });
26
27  // Swipers:
28  const exploreSwiperContainer = document.querySelector("#exploreSwiper");
29  const exploreSwiper = document.querySelector(
30    "swiper-container#exploreSwiper",
31  );
32  if (exploreSwiper) {
33    let currentSize = window.innerWidth;
34    const swiperParams = {
35      loop: true,
36      slidesPerView: 1,
37      centeredSlides: true,
38      navigation: true,
39      spaceBetween: 10,
40      breakpoints: {
41        679: {
42          slidesPerView: 2.9,
43        },
44        700: {
45          slidesPerView: 3.1,
46        },
47        1100: {
48          slidesPerView: 4.5,
49        },
50      },
51      pagination: {
52        el: "#exploreSwiper .swiper-pagination",
53        clickable: true,
54      },
55      on: {
56        // init() {},
57      },
58    };
59
60    // now we need to assign all parameters to Swiper element
61    Object.assign(exploreSwiper, swiperParams);
62    // and now initialize it
63    exploreSwiper.initialize();
64    const swiper = exploreSwiperContainer.swiper;
65    if (currentSize > 679) {
66      swiper.slideTo(3);
67    }
68
69    swiper.update();
70    // console.log(swiperParams);
71  }
72
73  const modelsSwiperContainer = document.querySelector("#modelsSwiper");
74  const modelsSwiper = document.querySelector("swiper-container#modelsSwiper");
75
76  if (modelsSwiper) {
77    const compareCta = document.querySelector(
78      ".compare-car-models-container[data-hide-for]",
79    );
80    const hideForName = compareCta
81      ? (compareCta.getAttribute("data-hide-for") || "").toLowerCase()
82      : null;
83
84    function updateCompareCtaVisibility(sw) {
85      if (!compareCta || !hideForName) return;
86      const activeSlide =
87        (sw && sw.slides && sw.slides[sw.activeIndex]) ||
88        document.querySelector("#modelsSwiper .swiper-slide-active");
89      if (!activeSlide) return;
90      const activeName = (
91        activeSlide.getAttribute("data-car-name") || ""
92      ).toLowerCase();
93      compareCta.style.display = activeName === hideForName ? "none" : "";
94    }
95
96    const swiperParams = {
97      slidesPerView: 2,
98      centeredSlides: true,
99      breakpoints: {
100        679: {
101          slidesPerView: 3,
102        },
103        1100: {
104          slidesPerView: 4,
105        },
106      },
107      on: {
108        init(sw) {
109          updateCompareCtaVisibility(sw);
110        },
111        slideChange(sw) {
112          updateCompareCtaVisibility(sw);
113        },
114      },
115    };
116    // now we need to assign all parameters to Swiper element
117    Object.assign(modelsSwiper, swiperParams);
118    // swiper-container auto-inits before this script runs, so the `on`
119    // callbacks above may register after init has already fired. Bind to the
120    // web-component DOM events too so slide changes always update the CTA.
121    modelsSwiper.addEventListener("swiperinit", (e) => {
122      updateCompareCtaVisibility(e.detail && e.detail[0]);
123    });
124    modelsSwiper.addEventListener("swiperslidechange", (e) => {
125      updateCompareCtaVisibility(e.detail && e.detail[0]);
126    });
127    // and now initialize it
128    setTimeout(() => {
129      modelsSwiper.initialize();
130    }, 1000);
131    const swiper = modelsSwiperContainer.swiper;
132    // Run once now in case init already fired before listeners were attached.
133    updateCompareCtaVisibility(swiper);
134
135    if (window.innerWidth >= 769) {
136      swiper.slideTo(3);
137    } else {
138      swiper.slideTo(2);
139    }
140
141    swiper.update();
142    console.log(swiper);
143  }
144  const articlesSwiperContainer = document.querySelector("#articlesSwiper");
145  const articlesSwiper = document.querySelector(
146    "swiper-container#articlesSwiper",
147  );
148
149  if (articlesSwiper) {
150    const swiperParams = {
151      slidesPerView: 1,
152      spaceBetween: 35,
153      breakpoints: {
154        679: {
155          slidesPerView: 3,
156          spaceBetween: 35,
157        },
158      },
159      navigation: true,
160      pagination: true,
161      on: {
162        init() {},
163      },
164    };
165    // now we need to assign all parameters to Swiper element
166    Object.assign(articlesSwiper, swiperParams);
167
168    // and now initialize it
169    articlesSwiper.initialize();
170    const swiper = articlesSwiperContainer.swiper;
171    swiper.update();
172  }
173
174  const weGoBeyondSwiperContainer = document.querySelector("#weGoBeyondSwiper");
175  const weGoBeyondSwiper = document.querySelector(
176    "swiper-container#weGoBeyondSwiper",
177  );
178
179  if (weGoBeyondSwiper) {
180    const swiperParams = {
181      slidesPerView: 1,
182      spaceBetween: 35,
183      navigation: true,
184      pagination: true,
185      on: {
186        init() {},
187      },
188    };
189    // now we need to assign all parameters to Swiper element
190    Object.assign(weGoBeyondSwiper, swiperParams);
191
192    // and now initialize it
193    weGoBeyondSwiper.initialize();
194    const swiper = weGoBeyondSwiperContainer.swiper;
195    swiper.update();
196  }
197
198  const aboutUsSwiperContainer = document.querySelector("#aboutUsSwiper");
199  const aboutUsSwiper = document.querySelector(
200    "swiper-container#aboutUsSwiper",
201  );
202  if (aboutUsSwiper) {
203    const swiperParams = {
204      slidesPerView: 1,
205      spaceBetween: 35,
206      navigation: true,
207      pagination: true,
208      loop:true,
209      on: {
210        init() {
211          console.log("Swiper initialized");
212        },
213        resize: debounce(function () {
214          if (this && !this.destroyed) {
215            console.log("Debounced resize → updating Swiper");
216            this.update();
217          }
218        }, 150),
219      },
220    };
221    // now we need to assign all parameters to Swiper element
222    Object.assign(aboutUsSwiper, swiperParams);
223
224    // and now initialize it
225    aboutUsSwiper.initialize();
226    const swiper = aboutUsSwiperContainer.swiper;
227    swiper.update();
228
229    window.addEventListener("resize", () => {
230      if (swiper) {
231        swiper.update();
232      }
233    });
234  }
235
236  const subBannerSwiperContainer = document.querySelector("#subBannerSwiper");
237  let subBannerSwiper = document.querySelector(
238    "swiper-container#subBannerSwiper",
239  );
240
241  if (subBannerSwiper) {
242    let swiperInstance = null;
243    let currentSwiperContainer = subBannerSwiperContainer;
244
245    const swiperParams = {
246      loop: true,
247      centeredSlides: false,
248      slidesPerView: 1,
249      spaceBetween: 0,
250      autoplay: {
251        delay: 2500,
252        disableOnInteraction: false,
253      },
254      breakpoints: {
255        768: {
256          slidesPerView: 2,
257          spaceBetween: 8,
258        },
259      },
260      navigation: true,
261      pagination: {
262        el: "#subBannerSwiper .swiper-pagination",
263        clickable: true,
264      },
265      on: {
266        init() {
267          console.log("SubBanner swiper initialized");
268        },
269        breakpoint: (swiper, breakpointParams) => {
270          console.log("Breakpoint event triggered:", breakpointParams);
271          // Force update when Swiper detects breakpoint change
272          setTimeout(() => {
273            swiper.update();
274            swiper.updateSize();
275            swiper.updateSlides();
276            swiper.updateProgress();
277            swiper.updateSlidesClasses();
278          }, 100);
279        },
280      },
281    };
282
283    // Initialize swiper
284    function initializeSwiper() {
285      // Re-query the element to ensure we have the latest reference
286      subBannerSwiper = document.querySelector(
287        "swiper-container#subBannerSwiper",
288      );
289      currentSwiperContainer = document.querySelector("#subBannerSwiper");
290
291      if (subBannerSwiper && currentSwiperContainer) {
292        Object.assign(subBannerSwiper, swiperParams);
293        subBannerSwiper.initialize();
294        swiperInstance = currentSwiperContainer.swiper;
295        if (swiperInstance) {
296          swiperInstance.update();
297        }
298      }
299    }
300
301    // Completely destroy and recreate swiper element
302    function recreateSwiper() {
303      // Destroy existing swiper instance
304      if (swiperInstance && !swiperInstance.destroyed) {
305        swiperInstance.destroy(true, true);
306        swiperInstance = null;
307      }
308
309      // Get the parent container and HTML content
310      const parentContainer = currentSwiperContainer.parentNode;
311      const swiperHTML = currentSwiperContainer.innerHTML;
312
313      // Remove the entire swiper container
314      currentSwiperContainer.remove();
315
316      // Create a new swiper container element
317      const newSwiperContainer = document.createElement("swiper-container");
318      newSwiperContainer.id = "subBannerSwiper";
319      newSwiperContainer.innerHTML = swiperHTML;
320
321      // Insert it back into the DOM
322      parentContainer.appendChild(newSwiperContainer);
323
324      // Update all references
325      currentSwiperContainer = document.querySelector("#subBannerSwiper");
326      subBannerSwiper = document.querySelector(
327        "swiper-container#subBannerSwiper",
328      );
329
330      // Small delay to ensure DOM is ready
331      setTimeout(() => {
332        initializeSwiper();
333      }, 150);
334    }
335
336    // Initial setup
337    initializeSwiper();
338
339    // Enhanced resize handler with complete recreation
340    let resizeTimeout;
341    let lastWidth = window.innerWidth;
342    let lastBreakpointState = lastWidth >= 768; // Track breakpoint state
343
344    window.addEventListener("resize", () => {
345      // Cancel any pending update
346      clearTimeout(resizeTimeout);
347
348      // Debounce to avoid excessive calls
349      resizeTimeout = setTimeout(() => {
350        const currentWidth = window.innerWidth;
351        const currentBreakpointState = currentWidth >= 768;
352        const crossedBreakpoint =
353          lastBreakpointState !== currentBreakpointState;
354        const significantChange = Math.abs(currentWidth - lastWidth) > 100;
355
356        if (crossedBreakpoint) {
357          console.log("Crossed 768px breakpoint, recreating swiper");
358          recreateSwiper();
359        } else if (swiperInstance && !swiperInstance.destroyed) {
360          // console.log("Resized — updating swiper");
361          swiperInstance.update();
362        }
363
364        lastWidth = currentWidth;
365        lastBreakpointState = currentBreakpointState;
366      }, 150); // 150–200ms debounce works well
367    });
368  }
369
370  const elevatSwiperContainer = document.querySelector("#elevateYLife");
371  const elevateSwiper = document.querySelector("swiper-container#elevateYLife");
372  if (elevateSwiper) {
373    const swiperParams = {
374      slidesPerView: 1,
375      spaceBetween: 35,
376      loop: true,
377      navigation: true,
378      pagination: true,
379      on: {
380        init() {},
381        resize() {
382          // Force update on resize
383          this.update();
384        },
385      },
386    };
387    // now we need to assign all parameters to Swiper element
388    Object.assign(elevateSwiper, swiperParams);
389
390    // and now initialize it
391    elevateSwiper.initialize();
392    const swiper = elevatSwiperContainer.swiper;
393    swiper.update();
394
395    window.addEventListener("resize", () => {
396      if (swiper) {
397        swiper.update();
398      }
399    });
400  }
401});
402
403function togglePopup(value) {
404  $("." + value)
405    .get(0)
406    .classList.toggle("active");
407}
408
409function openVideoPopup(videoId) {
410  // Set up iframe source with necessary parameters
411  const embedUrl = `https://www.youtube.com/embed/${videoId}?enablejsapi=1&rel=0&autoplay=1`;
412
413  // Inject iframe with the updated URL
414  $(".video-popup iframe").prop("src", embedUrl);
415
416  // Show the popup
417  togglePopup("video-popup");
418
419  // Initialize YouTube API player
420  if (!player) {
421    player = new YT.Player($(".video-popup iframe")[0], {
422      events: {
423        onReady: function (event) {
424          event.target.playVideo();
425        },
426      },
427    });
428  } else {
429    player.loadVideoById(videoId);
430  }
431  playVideoWithSound();
432}
433
434function openMultiVideoPopup(urlArray) {
435  // Build swiper slides with YouTube iframes
436  if (!Array.isArray(urlArray) || urlArray.length === 0) return;
437
438  const contentEl = document.querySelector(".multi-video-popup .popup-content");
439  if (!contentEl) return;
440
441  // Helper to choose correct separator when video string may already contain query params
442  const sep = (s) => (s.includes("?") ? "&" : "?");
443
444  // Build HTML for swiper container + slides
445  const swiperId = "multiVideoSwiper";
446  let slidesHtml = urlArray
447    .map((videoParam, idx) => {
448      // Only the first iframe includes autoplay=1 so other iframes won't start automatically
449      const autoplayParam = idx === 0 ? "&autoplay=1" : "";
450      const src = `https://www.youtube.com/embed/${videoParam}${sep(videoParam)}enablejsapi=1&rel=0&mute=1${autoplayParam}`;
451      return `<swiper-slide>
451<iframe id="multi-video-${idx}" class="multi-youtube-iframe" src="${src}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; autoplay" allowfullscreen></iframe></swiper-slide>`;
452    })
453    .join("");
454
455  contentEl.innerHTML = `
456    <div class="multi-video-swiper-wrapper" style="width:100%;height:100%;">
457      <swiper-container id="${swiperId}" class="multi-video-swiper" slides-per-view="1" navigation="true" pagination="true" style="width:100%;height:100%;">
458        ${slidesHtml}
459      </swiper-container>
460    </div>
461  `;
462
463  // Show the popup
464  togglePopup("multi-video-popup");
465
466  // small helper to send player commands using postMessage (YouTube iframe API)
467  function sendCommandToIframe(iframe, func, args = []) {
468    try {
469      if (!iframe || !iframe.contentWindow) return;
470      const msg = JSON.stringify({
471        event: "command",
472        func: func,
473        args: args,
474      });
475      iframe.contentWindow.postMessage(msg, "*");
476    } catch (e) {
477      // ignore
478    }
479  }
480
481  console.log("[multiVideo] openMultiVideoPopup called. urlArray:", urlArray);
482
483  const swiperParams = {
484    slidesPerView: 1,
485    centeredSlides: true,
486    navigation: true,
487    pagination: {
488      el: `#${swiperId} .swiper-pagination`,
489      clickable: true,
490    },
491    observer: true,
492    observeParents: true,
493    on: {
494      init() {
495        const swiperInst = this;
496        const allIframes = multiSwiperEl.querySelectorAll(
497          ".multi-youtube-iframe",
498        );
499        console.log(
500          "[multiVideo] init — slides:",
501          swiperInst.slides.length,
502          "activeIndex:",
503          swiperInst.activeIndex,
504          "iframes found:",
505          allIframes.length,
506        );
507
508        // Pause/stop all iframes first (covers clones)
509        allIframes.forEach((iframe) => {
510          console.log(
511            "[multiVideo] init — pausing iframe:",
512            iframe.id,
513            iframe.src,
514          );
515          sendCommandToIframe(iframe, "pauseVideo");
516          sendCommandToIframe(iframe, "stopVideo");
517        });
518
519        // Play the currently active slide's iframe (use activeIndex which maps to DOM slide)
520        const activeSlide = swiperInst.slides[swiperInst.activeIndex];
521        const activeIframe =
522          activeSlide && activeSlide.querySelector(".multi-youtube-iframe");
523        console.log(
524          "[multiVideo] init — activeSlide:",
525          activeSlide,
526          "activeIframe:",
527          activeIframe && activeIframe.id,
528        );
529        if (activeIframe) {
530          console.log(
531            "[multiVideo] init — play active iframe:",
532            activeIframe.id,
533          );
534          sendCommandToIframe(activeIframe, "playVideo");
535          setTimeout(() => {
536            sendCommandToIframe(activeIframe, "unMute");
537            sendCommandToIframe(activeIframe, "playVideo");
538          }, 300);
539        }
540      },
541      slideChange(swiperInst) {
542        console.log(
543          "[multiVideo] slideChange — activeIndex:",
544          swiperInst.activeIndex,
545          "realIndex:",
546          swiperInst.realIndex,
547          "previousIndex:",
548          swiperInst.previousIndex,
549        );
550
551        // Get DOM slide that is currently active (handles loop/cloned slides correctly)
552        const activeSlide = swiperInst.slides[swiperInst.activeIndex];
553        const activeIframe =
554          activeSlide && activeSlide.querySelector(".multi-youtube-iframe");
555        console.log(
556          "[multiVideo] slideChange — activeSlide:",
557          activeSlide,
558          "activeIframe:",
559          activeIframe && activeIframe.id,
560        );
561
562        // Pause/stop all iframes first
563        const allIframes = multiSwiperEl.querySelectorAll(
564          ".multi-youtube-iframe",
565        );
566        allIframes.forEach((iframe) => {
567          if (iframe !== activeIframe) {
568            console.log(
569              "[multiVideo] slideChange — stopping iframe:",
570              iframe.id,
571            );
572            sendCommandToIframe(iframe, "pauseVideo");
573            sendCommandToIframe(iframe, "stopVideo");
574            console.log(
575              "[multiVideo] slideChange — iframe contentWindow:",
576              !!(iframe && iframe.contentWindow),
577            );
578          }
579        });
580
581        // Play/unmute the active iframe
582        if (activeIframe) {
583          console.log(
584            "[multiVideo] slideChange — play active iframe:",
585            activeIframe.id,
586          );
587          setTimeout(() => {
588            sendCommandToIframe(activeIframe, "playVideo");
589            setTimeout(() => {
590              sendCommandToIframe(activeIframe, "unMute");
591            }, 200);
592          }, 150);
593        }
594      },
595      // ensure update on breakpoint/resize
596      resize() {
597        if (this && !this.destroyed) this.update();
598      },
599    },
600  };
601
602  // attach params and initialize with retries so we can see debug logs when elements are missing
603  let initAttempts = 0;
604  function tryInitMultiSwiper() {
605    initAttempts++;
606    const multiSwiperEl = document.querySelector(
607      `swiper-container#${swiperId}`,
608    );
609    const multiSwiperContainer = document.querySelector(`#${swiperId}`);
610    console.log("[multiVideo] tryInitMultiSwiper attempt", initAttempts, {
611      multiSwiperEl,
612      multiSwiperContainer,
613    });
614
615    if (!multiSwiperEl || !multiSwiperContainer) {
616      if (initAttempts < 12) {
617        // retry a few times while DOM / webcomponent may upgrade
618        setTimeout(tryInitMultiSwiper, 100);
619        return;
620      }
621      console.log("[multiVideo] could not find swiper elements after retries");
622      return;
623    }
624
625    try {
626      Object.assign(multiSwiperEl, swiperParams);
627      console.log("[multiVideo] assigned params to multiSwiperEl");
628    } catch (e) {
629      console.log("[multiVideo] Object.assign error", e);
630    }
631
632    try {
633      if (typeof multiSwiperEl.initialize === "function") {
634        multiSwiperEl.initialize();
635        console.log("[multiVideo] multiSwiperEl.initialize() called");
636
637        // wait a little then attach handlers directly to the Swiper instance (guarantees events fire)
638        setTimeout(() => {
639          const sw = multiSwiperContainer && multiSwiperContainer.swiper;
640          console.log(
641            "[multiVideo] swiper instance after init:",
642            !!sw,
643            sw && {
644              activeIndex: sw.activeIndex,
645              slides: sw.slides && sw.slides.length,
646            },
647          );
648
649          if (!sw) {
650            console.log("[multiVideo] no swiper instance available yet");
651            return;
652          }
653
654          // Avoid double-attaching
655          if (sw._multiVideoHandlersAttached) {
656            console.log(
657              "[multiVideo] handlers already attached on swiper instance",
658            );
659            return;
660          }
661          sw._multiVideoHandlersAttached = true;
662
663          // Instance-level init handler
664          sw.on("init", function () {
665            console.log(
666              "[multiVideo][inst] init — activeIndex:",
667              this.activeIndex,
668              "slides:",
669              this.slides.length,
670            );
671            const allIframes = multiSwiperEl.querySelectorAll(
672              ".multi-youtube-iframe",
673            );
674            allIframes.forEach((iframe) => {
675              console.log(
676                "[multiVideo][inst] init — pausing iframe:",
677                iframe.id,
678                iframe.src,
679              );
680              sendCommandToIframe(iframe, "pauseVideo");
681            });
682
683            const activeSlide = this.slides[this.activeIndex];
684            const activeIframe =
685              activeSlide && activeSlide.querySelector(".multi-youtube-iframe");
686            console.log(
687              "[multiVideo][inst] init — activeIframe:",
688              activeIframe && activeIframe.id,
689            );
690            if (activeIframe) {
691              sendCommandToIframe(activeIframe, "playVideo");
692              setTimeout(() => {
693                sendCommandToIframe(activeIframe, "unMute");
694                sendCommandToIframe(activeIframe, "playVideo");
695              }, 300);
696            }
697          });
698
699          // Instance-level slideChange handler
700          sw.on("slideChange", function () {
701            console.log(
702              "[multiVideo][inst] slideChange — activeIndex:",
703              this.activeIndex,
704              "realIndex:",
705              this.realIndex,
706              "previousIndex:",
707              this.previousIndex,
708            );
709
710            const activeSlide = this.slides[this.activeIndex];
711            const activeIframe =
712              activeSlide && activeSlide.querySelector(".multi-youtube-iframe");
713            console.log(
714              "[multiVideo][inst] slideChange — activeIframe:",
715              activeIframe && activeIframe.id,
716            );
717
718            const allIframes = multiSwiperEl.querySelectorAll(
719              ".multi-youtube-iframe",
720            );
721            allIframes.forEach((iframe) => {
722              if (iframe !== activeIframe) {
723                console.log(
724                  "[multiVideo][inst] slideChange — stopping iframe:",
725                  iframe.id,
726                );
727                sendCommandToIframe(iframe, "pauseVideo");
728              }
729            });
730
731            if (activeIframe) {
732              console.log(
733                "[multiVideo][inst] slideChange — play active iframe:",
734                activeIframe.id,
735              );
736              setTimeout(() => {
737                sendCommandToIframe(activeIframe, "playVideo");
738                setTimeout(() => {
739                  sendCommandToIframe(activeIframe, "unMute");
740                }, 200);
741              }, 150);
742            }
743          });
744
745          // If the instance was already initialized before we attached handlers, trigger the init handler manually
746          if (sw.initialized) {
747            console.log(
748              "[multiVideo] swiper already initialized — calling instance init handler manually",
749            );
750            sw.emit && sw.emit("init");
751          }
752        }, 50);
753      } else {
754        console.log(
755          "[multiVideo] initialize() not present on element, will attempt again",
756        );
757        if (initAttempts < 12) setTimeout(tryInitMultiSwiper, 100);
758      }
759    } catch (e) {
760      console.log("[multiVideo] initialize threw", e);
761    }
762  }
763  tryInitMultiSwiper();
764}
765
766function closeVideoPopup() {
767  $(".video-popup .popup-content").html(
768    '<iframe id="youtube-player" src="" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>',
769  );
770  togglePopup("video-popup");
771}
772
773function closeMultiVideoPopup() {
774  $(".multi-video-popup .popup-content").html(
775    '<div class="video-placeholder">Video will be loaded here</div>',
776  );
777  togglePopup("multi-video-popup");
778}
779
780function playVideoWithSound() {
781  const iframe = document.getElementById("youtube-player");
782  // Make sure the iframe has `?enablejsapi=1` in the URL
783  iframe.contentWindow.postMessage(
784    '{"event":"command","func":"playVideo","args":""}',
785    "*",
786  );
787  console.log(iframe.contentWindow);
788}
789
790document.addEventListener("DOMContentLoaded", function () {
791  const businessContainers = document.querySelectorAll(
792    ".cl-business-accordion",
793  );
794  let accordionClickHandlers = [];
795  let activeAccordionIndex = 0; // Track currently active accordion
796
797  function initializeAccordion() {
798    const windowWidth = window.innerWidth;
799
800    // Only apply accordion behavior when window width is between 1024px and 1650px
801    if (windowWidth >= 1024 && windowWidth <= 1600) {
802      // Find currently active accordion or default to first one
803      let foundActive = false;
804      businessContainers.forEach(function (container, index) {
805        if (container.classList.contains("active")) {
806          activeAccordionIndex = index;
807          foundActive = true;
808        }
809      });
810
811      // First reset all accordions
812      businessContainers.forEach(function (container) {
813        container.classList.remove("active");
814        const accordionContainer = container.querySelector(
815          ".accordion-container",
816        );
817        if (accordionContainer) {
818          accordionContainer.classList.remove("active");
819        }
820      });
821
822      // Open the active accordion (or default to first)
823      if (businessContainers.length > 0) {
824        businessContainers[activeAccordionIndex].classList.add("active");
825        const activeAccordionContainer = businessContainers[
826          activeAccordionIndex
827        ].querySelector(".accordion-container");
828        if (activeAccordionContainer) {
829          activeAccordionContainer.classList.add("active");
830        }
831      }
832
833      // Add click handlers for accordion functionality
834      businessContainers.forEach(function (container, index) {
835        const clickHandler = function () {
836          const accordionContainer = container.querySelector(
837            ".accordion-container",
838          );
839          const isCurrentlyActive = container.classList.contains("active");
840
841          // If this accordion is already active, do nothing (prevent closing)
842          if (isCurrentlyActive) {
843            return;
844          }
845
846          // Close all other accordion containers
847          businessContainers.forEach(function (otherContainer) {
848            if (otherContainer !== container) {
849              otherContainer.classList.remove("active");
850              const otherAccordionContainer = otherContainer.querySelector(
851                ".accordion-container",
852              );
853              if (otherAccordionContainer) {
854                otherAccordionContainer.classList.remove("active");
855              }
856            }
857          });
858
859          // Open the clicked accordion and update active index
860          container.classList.add("active");
861          activeAccordionIndex = index;
862
863          if (accordionContainer) {
864            accordionContainer.classList.add("active");
865          }
866        };
867
868        container.addEventListener("mouseenter", clickHandler);
869        accordionClickHandlers.push({ container, handler: clickHandler });
870      });
871    } else {
872      // Show all content for screens smaller than 1024px or larger than 1650px
873      businessContainers.forEach(function (container) {
874        container.classList.add("active");
875        const accordionContainer = container.querySelector(
876          ".accordion-container",
877        );
878        if (accordionContainer) {
879          accordionContainer.classList.add("active");
880        }
881      });
882    }
883  }
884
885  function removeAccordionHandlers() {
886    accordionClickHandlers.forEach(function (item) {
887      item.container.removeEventListener("mouseenter", item.handler);
888    });
889    accordionClickHandlers = [];
890  }
891
892  function handleResize() {
893    removeAccordionHandlers();
894    initializeAccordion();
895  }
896
897  // Initialize accordion on page load
898  initializeAccordion();
899
900  // Handle window resize
901  window.addEventListener("resize", handleResize);
902});
903
904document.addEventListener("DOMContentLoaded", function () {
905  const soundContainer = document.getElementById("sound-container");
906  const video = document.querySelector(".splash-screen-banner video");
907  const soundIcon = soundContainer.querySelector("img");
908  let isMuted = true;
909
910  soundContainer.addEventListener("click", function () {
911    if (isMuted) {
912      video.muted = false;
913      video.volume = 0.7; // Set volume to 70%
914      soundIcon.src = "assets/images/splashscreen/sound-on.webp";
915      isMuted = false;
916    } else {
917      video.muted = true;
918      soundIcon.src = "assets/images/splashscreen/sound-off.webp";
919      isMuted = true;
920    }
921  });
922});
923
924function debounce(func, wait = 150) {
925  let timeout;
926  return (...args) => {
927    clearTimeout(timeout);
928    timeout = setTimeout(() => func.apply(this, args), wait);
929  };
930}
931
932// document.addEventListener("DOMContentLoaded", function () {
933//   const closeSplashscreen = document.getElementById("start-icon");
934//   if (closeSplashscreen) {
935//     closeSplashscreen.addEventListener("click", () => {
936//       const splashscreen = document.getElementById("splashscreen");
937//       if (splashscreen) {
938//         splashscreen.classList.add("removed");
939//         splashscreen.addEventListener("animationend", () => {
940//           splashscreen.remove();
941//         });
942//       }
943
944//       const slider = document.querySelector(".parallax-layer");
945//       slider.classList.add("animate");
946//       setTimeout(() => {
947//         slider.classList.remove("animate");
948//       }, 1000);
949//     });
950//   }
951//   const soundSwitch = document.querySelector("#sound-container > img");
952//   if (soundSwitch) {
953//     soundSwitch.addEventListener("click", () => {
954//       const video = document.querySelector("#splashscreen > video");
955//       if (soundSwitch.src.includes("sound-off.webp")) {
956//         soundSwitch.src = soundSwitch.src.replace(
957//           "sound-off.webp",
958//           "sound-on.webp"
959//         );
960//         video.muted = false;
961//       } else {
962//         soundSwitch.src = soundSwitch.src.replace(
963//           "sound-on.webp",
964//           "sound-off.webp"
965//         );
966//         video.muted = true;
967//       }
968//     });
969//   }
970// });

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.