PageSourceSearch

https://trisula.co.id/wp-content/plugins/tj-solvior-core/assets/js/tj-core.js?ver=1.1.3

js trisula.co.id collected 2026-10-03 22:36:43 UTC 50,605 bytes, 1,713 lines download raw bytes

1(function ($) {
2  "use strict";
3  /**
4   * @param $scope The Widget wrapper element as a jQuery element
5   * @param $ The jQuery alias
6   */
7  // Make sure you run this code under Elementor.
8  $(window).on("elementor/frontend/init", function () {
9    // global widget
10    elementorFrontend.hooks.addAction("frontend/element_ready/widget", function ($scope, $) {
11      // background image
12      let bgImage = $scope.find("[data-bg-image]");
13      if (bgImage.length > 0) {
14        bgImage.each(function () {
15          $(this).css("background-image", "url(" + $(this).attr("data-bg-image") + ")");
16        });
17      }
18
19      let maskImage = $scope.find("[data-mask]");
20      if (maskImage.length > 0) {
21        maskImage.each(function () {
22          $(this).css("mask-image", "url(" + $(this).attr("data-mask") + ")");
23        });
24      }
25
26      // PureCounter initialization
27      let pureCounter = $scope.find(".purecounter");
28      if (pureCounter.length > 0 && typeof PureCounter !== "undefined") {
29        // Clear previous counter instance if necessary
30        if (window.pureCounter) {
31          window.pureCounter.destroy && window.pureCounter.destroy(); // optional cleanup if needed
32        }
33        // Create new counter instance
34        window.pureCounter = new PureCounter();
35      }
36
37      // right swipe
38      document.querySelectorAll(".rightSwipeWrap").forEach((wrap, i) => {
39        gsap.set(wrap.querySelectorAll(".right-swipe"), {
40          transformPerspective: 1200,
41          x: "10rem",
42          rotateY: -20,
43          opacity: 0,
44          transformOrigin: "right center",
45        });
46        gsap.to(wrap.querySelectorAll(".right-swipe"), {
47          transformPerspective: 1200,
48          x: 0,
49          rotateY: 0,
50          opacity: 1,
51          delay: 0.3,
52          ease: "power3.out",
53          scrollTrigger: {
54            trigger: wrap,
55            start: "top 80%",
56            id: "rightSwipeWrap-" + i,
57            toggleActions: "play none none none",
58            // markers: true,
59          },
60        });
61      });
62
63      // left swipe
64      document.querySelectorAll(".leftSwipeWrap").forEach((wrap, i) => {
65        gsap.set(wrap.querySelectorAll(".left-swipe"), {
66          transformPerspective: 1200,
67          x: "-10rem",
68          rotateY: 20,
69          opacity: 0,
70          transformOrigin: "left center",
71        });
72        gsap.to(wrap.querySelectorAll(".left-swipe"), {
73          transformPerspective: 1200,
74          x: 0,
75          rotateY: 0,
76          opacity: 1,
77          delay: 0.3,
78          ease: "power3.out",
79          scrollTrigger: {
80            trigger: wrap,
81            start: "top 80%",
82            id: "leftSwipeWrap-" + i,
83            toggleActions: "play none none none",
84            // markers: true,
85          },
86        });
87      });
88    });
89
90    // tj-hero-slider
91    elementorFrontend.hooks.addAction(
92      "frontend/element_ready/tj-hero-banner-slider.default",
93
94      function ($scope, $) {
95        let heroSlider = $scope.find(".full-slider-active");
96
97        let bannerWrap = $scope.find(".bannerWrap");
98
99        let loop = bannerWrap.attr("data-loop") == "yes" ? true : false;
100        let nav = bannerWrap.attr("data-nav") == "yes" ? true : false;
101        let autoplay = bannerWrap.attr("data-autoplay") == "yes" ? true : false;
102        let delay = bannerWrap.attr("data-delay") ? bannerWrap.attr("data-delay") : "5000";
103
104        if (heroSlider.length > 0) {
105          const sliderId = heroSlider.attr("id");
106
107          var heroSlide = new Swiper(`#${sliderId}`, {
108            slidesPerView: 1,
109            spaceBetween: 0,
110            effect: "fade",
111            loop: loop,
112            speed: 2000,
113            ...(autoplay
114              ? {
115                  autoplay: {
116                    delay: delay,
117                  },
118                }
119              : {}),
120            ...(nav
121              ? {
122                  navigation: {
123                    prevEl: ".tj-btn-prev",
124                    nextEl: ".tj-btn-next",
125                  },
126                }
127              : {}),
128            pagination: {
129              el: ".tj-sw-pagination",
130              type: "fraction",
131              clickable: true,
132              renderFraction: function (currentClass, totalClass) {
133                return '<span class="' + currentClass + '"></span>' + ' <span class="dash"><span class="dash-inner"></span></span> ' + '<span class="' + totalClass + '"></span>';
134              },
135            },
136            on: {
137              init: function () {
138                updateDashWidth(this);
139              },
140              slideChange: function () {
141                updateDashWidth(this);
142              },
143            },
144          });
145          function updateDashWidth(swiper) {
146            const dashInner = swiper.el.querySelector(".dash-inner");
147            if (dashInner) {
148              const realIndex = swiper.realIndex;
149              const totalSlides = swiper.slides.length - swiper.loopedSlides * 2;
150              const progressPercent = ((realIndex + 1) / totalSlides) * 100;
151              dashInner.style.width = progressPercent + "%";
152            }
153          }
154        }
155      }
156    );
157
158    // tj-counter-two
159    elementorFrontend.hooks.addAction(
160      "frontend/element_ready/tj-counter-two.default",
161
162      function ($scope, $) {
163        var $counterItem = $scope.find(".funfact-item-two");
164
165        if ($counterItem.length > 0) {
166          var $counter = $counterItem.find(".odometer");
167
168          if (!$counter.length) {
169            return;
170          }
171
172          $counter.appear(
173            function () {
174              var odo = $counter;
175              odo.each(function () {
176                var countNumber = $(this).attr("data-count");
177                $(this).html(countNumber);
178              });
179            },
180            {
181              offset: "80%",
182            }
183          );
184        }
185      }
186    );
187
188    // tj-counter
189    elementorFrontend.hooks.addAction(
190      "frontend/element_ready/tj-counter.default",
191
192      function ($scope, $) {
193        var $counterItem = $scope.find(".counter-item");
194        if ($counterItem.length > 0) {
195          var $counter = $counterItem.find(".odometer");
196          if (!$counter.length) {
197            return;
198          }
199
200          $counter.appear(
201            function () {
202              var odo = $counter;
203              odo.each(function () {
204                var countNumber = $(this).attr("data-count");
205                $(this).html(countNumber);
206              });
207            },
208            {
209              offset: "80%",
210            }
211          );
212        }
213      }
214    );
215
216    // tj-about
217    elementorFrontend.hooks.addAction(
218      "frontend/element_ready/tj-about.default",
219
220      function ($scope, $) {
221        var $counterItem = $scope.find(".funfact-item-one");
222        if ($counterItem.length > 0) {
223          var $counter = $counterItem.find(".odometer");
224          if (!$counter.length) {
225            return;
226          }
227          $counter.appear(
228            function () {
229              var odo = $counter;
230              odo.each(function () {
231                var countNumber = $(this).attr("data-count");
232                $(this).html(countNumber);
233              });
234            },
235            {
236              offset: "80%",
237            }
238          );
239        }
240      }
241    );
242
243    // tj-about-two
244    elementorFrontend.hooks.addAction(
245      "frontend/element_ready/tj-about-two.default",
246
247      function ($scope, $) {
248        var $counterItem = $scope.find(".counter-item");
249        if ($counterItem.length > 0) {
250          var $counter = $counterItem.find(".odometer");
251          if (!$counter.length) {
252            return;
253          }
254          $counter.appear(
255            function () {
256              var odo = $counter;
257              odo.each(function () {
258                var countNumber = $(this).attr("data-count");
259                $(this).html(countNumber);
260              });
261            },
262            {
263              offset: "80%",
264            }
265          );
266        }
267      }
268    );
269
270    // tj-about-image
271    elementorFrontend.hooks.addAction(
272      "frontend/element_ready/tj-about-image.default",
273
274      function ($scope, $) {
275        var $counterItem = $scope.find(".testimonial-funfact");
276        if ($counterItem.length > 0) {
277          var $counter = $counterItem.find(".odometer");
278          if (!$counter.length) {
279            return;
280          }
281          $counter.appear(
282            function () {
283              var odo = $counter;
284              odo.each(function () {
285                var countNumber = $(this).attr("data-count");
286                $(this).html(countNumber);
287              });
288            },
289            {
290              offset: "80%",
291            }
292          );
293        }
294      }
295    );
296
297    // tj-banner-four
298    elementorFrontend.hooks.addAction(
299      "frontend/element_ready/tj-banner-four.default",
300
301      function ($scope, $) {
302        var $counterItem = $scope.find(".counter-item");
303        if ($counterItem.length > 0) {
304          var $counter = $counterItem.find(".odometer");
305          if (!$counter.length) {
306            return;
307          }
308          $counter.appear(
309            function () {
310              var odo = $counter;
311              odo.each(function () {
312                var countNumber = $(this).attr("data-count");
313                $(this).html(countNumber);
314              });
315            },
316            {
317              offset: "80%",
318            }
319          );
320        }
321      }
322    );
323
324    // image slider
325    elementorFrontend.hooks.addAction(
326      "frontend/element_ready/tj-image-slider.default",
327
328      function ($scope, $) {
329        let wrap = $scope.find(".carouselWrap");
330
331        var loop = wrap.attr("data-loop") == "yes" ? true : false;
332        var autoplay = wrap.attr("data-autoplay") == "yes" ? true : false;
333        var delay = wrap.attr("data-delay") ? wrap.attr("data-delay") : "1";
334
335        // Image Slider 1
336        let imageSlider = $scope.find(".h6-hero-slider");
337        if (imageSlider.length > 0) {
338          let sliderId = imageSlider.attr("id");
339
340          var imageSlide = new Swiper(`#${sliderId}`, {
341            slidesPerView: "auto",
342            spaceBetween: 30,
343            freemode: true,
344            centeredSlides: true,
345            loop: loop,
346            speed: 8000,
347            allowTouchMove: false,
348
349            ...(autoplay
350              ? {
351                  autoplay: {
352                    delay: delay,
353                  },
354                }
355              : {}),
356
357            breakpoints: {
358              0: {
359                spaceBetween: 20,
360              },
361              1400: {
362                spaceBetween: 30,
363              },
364            },
365          });
366        }
367      }
368    );
369
370    // tj-services
371    elementorFrontend.hooks.addAction(
372      "frontend/element_ready/tj-services.default",
373
374      function ($scope, $) {
375        let wrap = $scope.find(".carouselWrap");
376
377        var loop = wrap.attr("data-loop") == "yes" ? true : false;
378        var dot = wrap.attr("data-dot") == "yes" ? true : false;
379        var autoplay = wrap.attr("data-autoplay") == "yes" ? true : false;
380        var delay = wrap.attr("data-delay") ? wrap.attr("data-delay") : "5000";
381
382        // Service Slider 1
383        let serviceSlider = $scope.find(".tj-service-slider");
384        if (serviceSlider.length > 0) {
385          let sliderId = serviceSlider.attr("id");
386
387          var serviceSlide = new Swiper(`#${sliderId}`, {
388            slidesPerView: 3,
389            spaceBetween: 24,
390            loop: loop,
391            speed: 1500,
392
393            ...(autoplay
394              ? {
395                  autoplay: {
396                    delay: delay,
397                  },
398                }
399              : {}),
400
401            ...(dot
402              ? {
403                  pagination: {
404                    el: ".service-pagination",
405                    clickable: true,
406                  },
407                }
408              : {}),
409            navigation: {
410              nextEl: ".slider-next",
411              prevEl: ".slider-prev",
412            },
413
414            breakpoints: {
415              0: {
416                slidesPerView: 1,
417              },
418              768: {
419                slidesPerView: 2,
420              },
421              992: {
422                slidesPerView: 3,
423              },
424              1024: {
425                slidesPerView: 3,
426              },
427            },
428          });
429        }
430
431        let serviceSlider6 = $scope.find(".h6-services-slider");
432        if (serviceSlider6.length > 0) {
433          let sliderId6 = serviceSlider6.attr("id");
434
435          var serviceSlide6 = new Swiper(`#${sliderId6}`, {
436            slidesPerView: 1,
437            spaceBetween: 30,
438            loop: loop,
439            speed: 1500,
440
441            ...(autoplay
442              ? {
443                  autoplay: {
444                    delay: delay,
445                  },
446                }
447              : {}),
448
449            ...(dot
450              ? {
451                  pagination: {
452                    el: ".swiper_pagination",
453                    clickable: true,
454                  },
455                }
456              : {}),
457            breakpoints: {
458              0: {
459                slidesPerView: 1,
460              },
461              768: {
462                slidesPerView: 2,
463              },
464              992: {
465                slidesPerView: 3,
466              },
467            },
468          });
469        }
470
471        // GSAP ScrollTrigger Animation
472        if (typeof gsap !== "undefined" && typeof ScrollTrigger !== "undefined") {
473          gsap.registerPlugin(ScrollTrigger);
474
475          const serviceStack = $scope.find(".service-stack");
476
477          if (serviceStack.length > 0 && window.innerWidth > 991) {
478            serviceStack.each(function () {
479              gsap.to(this, {
480                opacity: 0,
481                scale: 0.9,
482                y: 50,
483                scrollTrigger: {
484                  trigger: this,
485                  scrub: true,
486                  start: "top top",
487                  pin: true,
488                  pinSpacing: false,
489                  markers: false,
490                },
491              });
492            });
493          }
494        }
495      }
496    );
497
498    // service list
499    elementorFrontend.hooks.addAction("frontend/element_ready/tj-service-list.default", function ($scope, $) {
500      const wrap = $scope.find(".carouselWrap");
501
502      const loop = wrap.attr("data-loop") === "yes";
503      const dot = wrap.attr("data-dot") == "yes" ? true : false;
504      const autoplay = wrap.attr("data-autoplay") === "yes";
505      const delay = parseInt(wrap.attr("data-delay") || "5000");
506
507      let serviceContent = $scope.find(".h5-service-content");
508      let serviceItem = $scope.find(".service-style-5");
509      $(serviceContent).on("mouseover", function () {
510        $(this).parent(serviceItem).addClass("active").siblings().removeClass("active");
511      });
512
513      // home 9 service slider
514      const serviceSlider9 = $scope.find(".h9-services-slider");
515      if (serviceSlider9.length > 0) {
516        const sliderId = serviceSlider9.attr("id");
517
518        new Swiper(`#${sliderId}`, {
519          slidesPerView: 1,
520          spaceBetween: 30,
521          loop: loop,
522          speed: 1500,
523          ...(autoplay && {
524            autoplay: {
525              delay: delay,
526            },
527          }),
528          ...(dot
529            ? {
530                pagination: {
531                  el: ".swiper_pagination",
532                  clickable: true,
533                },
534              }
535            : {}),
536          breakpoints: {
537            0: {
538              slidesPerView: 1,
539            },
540            768: {
541              slidesPerView: 2,
542            },
543            992: {
544              slidesPerView: 3,
545            },
546          },
547        });
548      }
549    });
550
551    // tj-project
552    elementorFrontend.hooks.addAction("frontend/element_ready/tj-project-carousel.default", function ($scope, $) {
553      const wrap = $scope.find(".carouselWrap");
554
555      const loop = wrap.attr("data-loop") === "yes";
556      const dot = wrap.attr("data-dot") == "yes" ? true : false;
557      const nav = wrap.attr("data-nav") == "yes" ? true : false;
558      const autoplay = wrap.attr("data-autoplay") === "yes";
559      const delay = parseInt(wrap.attr("data-delay") || "5000");
560
561      // Find Swiper inside this widget
562      const projectSlider = $scope.find(".project-slider");
563      if (projectSlider.length > 0) {
564        const sliderId = projectSlider.attr("id");
565
566        new Swiper(`#${sliderId}`, {
567          slidesPerView: 4,
568          spaceBetween: 24,
569          loop: loop,
570          speed: 2000,
571          ...(autoplay && {
572            autoplay: {
573              delay: delay,
574            },
575          }),
576          ...(nav && {
577            navigation: {
578              nextEl: ".project-next",
579              prevEl: ".project-prev",
580            },
581          }),
582          breakpoints: {
583            375: {
584              slidesPerView: 1,
585            },
586            576: {
587              slidesPerView: 2,
588            },
589            768: {
590              slidesPerView: 2,
591            },
592            992: {
593              slidesPerView: 3,
594            },
595            1200: {
596              slidesPerView: 3,
597            },
598            1400: {
599              slidesPerView: 4,
600            },
601          },
602        });
603      }
604      // Custom Cursor Logic
605      const cursor = document.querySelector(".tj-cursor"); // global
606      const container = $scope[0].querySelector(".project-slider-one"); // scoped swiper container
607
608      if (cursor && container) {
609        // Initial GSAP setup
610        gsap.set(cursor, { xPercent: -50, yPercent: -50 });
611
612        // Move cursor on pointer
613        document.addEventListener("pointermove", (e) => {
614          gsap.to(cursor, {
615            duration: 0,
616            x: e.clientX,
617            y: e.clientY,
618          });
619        });
620
621        // Show/hide on hover within this widget's container
622        container.addEventListener("mouseenter", () => {
623          cursor.style.opacity = "1";
624          cursor.style.visibility = "visible";
625        });
626
627        container.addEventListener("mouseleave", () => {
628          cursor.style.opacity = "0";
629          cursor.style.visibility = "hidden";
630        });
631
632        // Wrap `cursor` with jQuery
633        const $cursor = $(cursor);
634
635        $("a, .sub-menu").on("mouseenter", function () {
636          $cursor.addClass("d-none");
637        });
638        $("a, .sub-menu").on("mouseleave", function () {
639          $cursor.removeClass("d-none");
640        });
641      }
642
643      // home 5 projects
644      const projectSlider5 = $scope.find(".h5-case-study-slider");
645      if (projectSlider5.length > 0) {
646        const sliderId = projectSlider5.attr("id");
647
648        new Swiper(`#${sliderId}`, {
649          slidesPerView: 1,
650          spaceBetween: 20,
651          loop: loop,
652          speed: 2000,
653          arrow: false,
654          ...(autoplay && {
655            autoplay: {
656              delay: delay,
657            },
658          }),
659          ...(dot
660            ? {
661                pagination: {
662                  el: ".swiper_pagination",
663                  clickable: true,
664                },
665              }
666            : {}),
667          breakpoints: {
668            992: {
669              slidesPerView: 2,
670              spaceBetween: 30,
671            },
672          },
673        });
674      }
675
676      // home 7 projects
677      const project7Slider = $scope.find(".h7-case-study-slider");
678      if (project7Slider.length > 0) {
679        const sliderId = project7Slider.attr("id");
680
681        var project7 = new Swiper(`#${sliderId}`, {
682          slidesPerView: 1,
683          loop: loop,
684          speed: 1800,
685          effect: "coverflow",
686          grabCursor: true,
687          centeredSlides: true,
688          spaceBetween: -100,
689          coverflowEffect: {
690            rotate: 0,
691            stretch: 0,
692            depth: 800,
693            modifier: 1,
694            slideShadows: false,
695          },
696          ...(autoplay && {
697            autoplay: {
698              delay: delay,
699            },
700          }),
701          ...(dot
702            ? {
703                pagination: {
704                  el: ".swiper_pagination",
705                  clickable: true,
706                },
707              }
708            : {}),
709          ...(nav
710            ? {
711                navigation: {
712                  nextEl: ".tj-project-nav-next",
713                  prevEl: ".tj-project-nav-prev",
714                },
715              }
716            : {}),
717        });
718      }
719
720      // home 8 projects
721      const projectSlider8 = $scope.find(".h8-case-study-slider");
722      if (projectSlider8.length > 0) {
723        const sliderId = projectSlider8.attr("id");
724
725        new Swiper(`#${sliderId}`, {
726          slidesPerView: 1,
727          spaceBetween: 20,
728          loop: loop,
729          speed: 2000,
730          arrow: false,
731          ...(autoplay && {
732            autoplay: {
733              delay: delay,
734            },
735          }),
736          ...(dot
737            ? {
738                pagination: {
739                  el: ".swiper_pagination",
740                  clickable: true,
741                },
742              }
743            : {}),
744          breakpoints: {
745            992: {
746              slidesPerView: 2,
747              spaceBetween: 30,
748            },
749          },
750        });
751      }
752
753      // home 9 projects
754      let h8BlogWrap = $scope.find(".h9-case-study-wrapper");
755      if (h8BlogWrap.length > 0) {
756        $(".h9-case-study-item").on("mouseover", function () {
757          $(this).addClass("active").siblings().removeClass("active");
758        });
759      }
760    });
761
762    // tj project stack
763    elementorFrontend.hooks.addAction(
764      "frontend/element_ready/tj-project-list-2.default",
765
766      function ($scope, $) {
767        // GSAP ScrollTrigger Animation
768        if (typeof gsap !== "undefined" && typeof ScrollTrigger !== "undefined") {
769          gsap.registerPlugin(ScrollTrigger);
770
771          const h6ProjectStack = $scope.find(".project-stack");
772
773          if (h6ProjectStack.length > 0 && window.innerWidth > 991) {
774            h6ProjectStack.each(function () {
775              gsap.to(this, {
776                scrollTrigger: {
777                  trigger: this,
778                  scrub: true,
779                  start: "top top",
780                  pin: true,
781                  pinSpacing: false,
782                  markers: false,
783                },
784              });
785            });
786          }
787
788          const h10ProjectStack = $scope.find(".service-stack");
789          if (h10ProjectStack.length > 0 && window.innerWidth > 991) {
790            h10ProjectStack.each(function () {
791              gsap.to(this, {
792                opacity: 0,
793                scale: 0.9,
794                y: 50,
795                scrollTrigger: {
796                  trigger: this,
797                  scrub: true,
798                  start: "top top",
799                  pin: true,
800                  pinSpacing: false,
801                  markers: false,
802                },
803              });
804            });
805          }
806        }
807      }
808    );
809
810    // tj-brand-carousel
811    elementorFrontend.hooks.addAction(
812      "frontend/element_ready/tj-brand-carousel.default",
813
814      function ($scope, $) {
815        let wrap = $scope.find(".carouselWrap");
816
817        var loop = wrap.attr("data-loop") == "yes" ? true : false;
818        var autoplay = wrap.attr("data-autoplay") == "yes" ? true : false;
819        var delay = wrap.attr("data-delay") ? wrap.attr("data-delay") : "1";
820
821        // brand 1
822        let brandCarouselWrap1 = $scope.find(".brand-slider-1");
823        if (brandCarouselWrap1.length > 0) {
824          let carouselId = brandCarouselWrap1.attr("id");
825          var brandCarousel = new Swiper(`#${carouselId}`, {
826            slidesPerView: "auto",
827            spaceBetween: 30,
828            freemode: true,
829            centeredSlides: true,
830            allowTouchMove: false,
831            loop: loop,
832            speed: 3000,
833            ...(autoplay
834              ? {
835                  autoplay: {
836                    delay: delay,
837                    disableOnInteraction: false,
838                  },
839                }
840              : {}),
841            breakpoints: {
842              0: {
843                slidesPerView: 2,
844              },
845              576: {
846                slidesPerView: 2.5,
847              },
848              768: {
849                slidesPerView: 3.3,
850              },
851              992: {
852                slidesPerView: 4.5,
853              },
854              1200: {
855                slidesPerView: 5.2,
856              },
857              1400: {
858                slidesPerView: 6,
859              },
860            },
861          });
862        }
863
864        // brand 2
865        let brandCarouselWrap2 = $scope.find(".brand-slider-2");
866        if (brandCarouselWrap2.length > 0) {
867          let carouselId = brandCarouselWrap2.attr("id");
868          var brandCarousel2 = new Swiper(`#${carouselId}`, {
869            slidesPerView: "auto",
870            spaceBetween: 30,
871            freemode: true,
872            centeredSlides: true,
873            allowTouchMove: false,
874            loop: loop,
875            speed: 3000,
876            ...(autoplay
877              ? {
878                  autoplay: {
879                    delay: delay,
880                    disableOnInteraction: false,
881                  },
882                }
883              : {}),
884            breakpoints: {
885              0: {
886                slidesPerView: 2,
887              },
888              576: {
889                slidesPerView: 2.5,
890              },
891              768: {
892                slidesPerView: 3.3,
893              },
894              992: {
895                slidesPerView: 4.5,
896              },
897              1200: {
898                slidesPerView: 5.2,
899              },
900              1400: {
901                slidesPerView: 6,
902              },
903            },
904          });
905        }
906      }
907    );
908
909    // tj-marquee
910    elementorFrontend.hooks.addAction(
911      "frontend/element_ready/tj-marquee.default",
912
913      function ($scope, $) {
914        let marquee = $scope.find(".marquee-slider");
915
916        if (marquee.length > 0) {
917          const marqueeId = marquee.attr("id");
918
919          var marqueeSlider = new Swiper(`#${marqueeId}`, {
920            slidesPerView: "auto",
921            spaceBetween: 0,
922            freemode: true,
923            centeredSlides: true,
924            loop: true,
925            speed: 4000,
926            allowTouchMove: false,
927            autoplay: {
928              delay: 1,
929              disableOnInteraction: true,
930            },
931          });
932        }
933
934        // home 6
935        let h6Marquee = $scope.find(".h6-marquee-slider");
936        if (h6Marquee.length > 0) {
937          const marqueeId = h6Marquee.attr("id");
938
939          let marqueeSlider = new Swiper(`#${marqueeId}`, {
940            slidesPerView: "auto",
941            spaceBetween: 20,
942            freemode: true,
943            centeredSlides: true,
944            loop: true,
945            speed: 4000,
946            allowTouchMove: false,
947            autoplay: {
948              delay: 1,
949            },
950          });
951        }
952      }
953    );
954
955    // tj-project-list
956    elementorFrontend.hooks.addAction(
957      "frontend/element_ready/tj-project-list.default",
958
959      function ($scope, $) {
960        let scrollContent = $scope.find(".marquee-slider-wrapper-two");
961
962        if (scrollContent.length > 0) {
963          gsap.to(".marquee-slider-wrapper-two", {
964            scrollTrigger: {
965              trigger: ".tj-project-section-two",
966              start: "top center-=200",
967              pin: ".marquee-slider-wrapper-two",
968              end: "bottom bottom-=200",
969              markers: false,
970              pinSpacing: false,
971              scrub: 1,
972            },
973          });
974        }
975      }
976    );
977
978    // tj-team
979    elementorFrontend.hooks.addAction(
980      "frontend/element_ready/tj-team.default",
981
982      function ($scope, $) {
983        let wrap = $scope.find(".carouselWrap");
984
985        let loop = wrap.attr("data-loop") == "yes" ? true : false;
986        let dot = wrap.attr("data-dot") == "yes" ? true : false;
987        let autoplay = wrap.attr("data-autoplay") == "yes" ? true : false;
988        let delay = wrap.attr("data-delay") ? wrap.attr("data-delay") : "5000";
989
990        let teamSlider = $scope.find(".tj-team-slider");
991        if (teamSlider.length > 0) {
992          const sliderId = teamSlider.attr("id");
993
994          var teamslide = new Swiper(`#${sliderId}`, {
995            slidesPerView: 4,
996            spaceBetween: 24,
997            loop: loop,
998            speed: 1500,
999            ...(autoplay
1000              ? {
1001                  autoplay: {
1002                    delay: delay,
1003                  },
1004                }
1005              : {}),
1006            ...(dot
1007              ? {
1008                  pagination: {
1009                    el: ".service-pagination",
1010                    clickable: true,
1011                  },
1012                }
1013              : {}),
1014            breakpoints: {
1015              0: {
1016                slidesPerView: 1,
1017              },
1018              460: {
1019                slidesPerView: 2,
1020              },
1021              768: {
1022                slidesPerView: 2,
1023              },
1024              992: {
1025                slidesPerView: 3,
1026              },
1027              1024: {
1028                slidesPerView: 4,
1029              },
1030            },
1031          });
1032        }
1033
1034        // home 10 team
1035        let teamWrapper = $scope.find(".h10-team-wrapper");
1036        if (teamWrapper.length > 0) {
1037          $(".h10-team-item").on("mouseover", function () {
1038            $(this).addClass("active").siblings().removeClass("active");
1039          });
1040        }
1041      }
1042    );
1043
1044    // tj-testimonial
1045    elementorFrontend.hooks.addAction(
1046      "frontend/element_ready/tj-testimonial.default",
1047
1048      function ($scope, $) {
1049        let wrap = $scope.find(".carouselWrap");
1050
1051        let loop = wrap.attr("data-loop") == "yes" ? true : false;
1052        let nav = wrap.attr("data-nav") == "yes" ? true : false;
1053        let dot = wrap.attr("data-dot") == "yes" ? true : false;
1054        let autoplay = wrap.attr("data-autoplay") == "yes" ? true : false;
1055        let delay = wrap.attr("data-delay") ? wrap.attr("data-delay") : "5000";
1056
1057        let testimonialSlider = $scope.find(".tj-testimonial-slider");
1058        if (testimonialSlider.length > 0) {
1059          const sliderId = testimonialSlider.attr("id");
1060
1061          var testimonial = new Swiper(`#${sliderId}`, {
1062            slidesPerView: 3,
1063            spaceBetween: 24,
1064            loop: loop,
1065            speed: 1500,
1066            ...(autoplay
1067              ? {
1068                  autoplay: {
1069                    delay: delay,
1070                  },
1071                }
1072              : {}),
1073            ...(nav
1074              ? {
1075                  navigation: {
1076                    nextEl: ".slider-next",
1077                    prevEl: ".slider-prev",
1078                  },
1079                }
1080              : {}),
1081            ...(dot
1082              ? {
1083                  pagination: {
1084                    el: ".testimonial-pagination",
1085                    clickable: true,
1086                  },
1087                }
1088              : {}),
1089            breakpoints: {
1090              0: {
1091                slidesPerView: 1,
1092              },
1093              768: {
1094                slidesPerView: 1,
1095              },
1096              992: {
1097                slidesPerView: 2,
1098              },
1099              1024: {
1100                slidesPerView: 2,
1101              },
1102            },
1103          });
1104          var star_rating_width = $(".fill-ratings span").width();
1105          $(".star-ratings").width(star_rating_width);
1106        }
1107
1108        // testimonial slider 2
1109        let testimonialSlider2 = $scope.find(".tj-testimonial-slider-two");
1110        if (testimonialSlider2.length > 0) {
1111          const sliderId = testimonialSlider2.attr("id");
1112          var testimonial = new Swiper(`#${sliderId}`, {
1113            slidesPerView: 1,
1114            spaceBetween: 0,
1115            loop: loop,
1116            speed: 1500,
1117            ...(autoplay
1118              ? {
1119                  autoplay: {
1120                    delay: delay,
1121                  },
1122                }
1123              : {}),
1124            ...(nav
1125              ? {
1126                  navigation: {
1127                    nextEl: ".slider-next",
1128                    prevEl: ".slider-prev",
1129                  },
1130                }
1131              : {}),
1132          });
1133          var star_rating_width = $(".fill-ratings span").width();
1134          $(".star-ratings").width(star_rating_width);
1135        }
1136
1137        // testimonial slider 3
1138        let testimonialSlider3 = $scope.find(".testimonial-slider-two");
1139        if (testimonialSlider3.length > 0) {
1140          const sliderId = testimonialSlider3.attr("id");
1141
1142          var testimonial = new Swiper(`#${sliderId}`, {
1143            slidesPerView: 3,
1144            spaceBetween: 65,
1145            centeredSlides: true,
1146            loop: loop,
1147            speed: 2000,
1148            ...(autoplay
1149              ? {
1150                  autoplay: {
1151                    delay: delay,
1152                  },
1153                }
1154              : {}),
1155            ...(dot
1156              ? {
1157                  pagination: {
1158                    el: ".testimonial-pagination",
1159                    clickable: true,
1160                  },
1161                }
1162              : {}),
1163            breakpoints: {
1164              320: {
1165                slidesPerView: 1,
1166              },
1167              576: {
1168                slidesPerView: 1.5,
1169              },
1170              768: {
1171                slidesPerView: 1.5,
1172              },
1173              992: {
1174                slidesPerView: 1.5,
1175              },
1176              1200: {
1177                slidesPerView: 1.9,
1178              },
1179              1440: {
1180                slidesPerView: 2.9,
1181              },
1182            },
1183          });
1184          var star_rating_width = $(".fill-ratings span").width();
1185          $(".star-ratings").width(star_rating_width);
1186        }
1187
1188        // testimonial slider 4
1189        let testimonialSlider4 = $scope.find(".h6-testimonial-slider");
1190        if (testimonialSlider4.length > 0) {
1191          let slider4Id = testimonialSlider4.attr("id");
1192
1193          let testimonial = new Swiper(`#${slider4Id}`, {
1194            slidesPerView: 1,
1195            spaceBetween: 30,
1196            loop: loop,
1197            speed: 1500,
1198            ...(autoplay
1199              ? {
1200                  autoplay: {
1201                    delay: delay,
1202                  },
1203                }
1204              : {}),
1205            ...(nav
1206              ? {
1207                  navigation: {
1208                    nextEl: ".slider-next",
1209                    prevEl: ".slider-prev",
1210                  },
1211                }
1212              : {}),
1213            ...(dot
1214              ? {
1215                  pagination: {
1216                    el: ".testimonial-pagination",
1217                    clickable: true,
1218                  },
1219                }
1220              : {}),
1221            breakpoints: {
1222              450: {
1223                slidesPerView: 1.5,
1224              },
1225              576: {
1226                slidesPerView: 1.5,
1227              },
1228              768: {
1229                slidesPerView: 1.5,
1230              },
1231              992: {
1232                slidesPerView: 2.5,
1233              },
1234              1200: {
1235                slidesPerView: 2.5,
1236              },
1237              1400: {
1238                slidesPerView: 3,
1239              },
1240            },
1241          });
1242          var star_rating_width = $(".fill-ratings span").width();
1243          $(".star-ratings").width(star_rating_width);
1244        }
1245
1246        // testimonial tab
1247        let h7TestimonialWrap = $scope.find(".h7-testimonial-wrap");
1248        if (h7TestimonialWrap.length > 0) {
1249          $(".h7-testimonial-single .testimonial-content").on("click", function () {
1250            $(this).parent(".h7-testimonial-single").addClass("active").siblings().removeClass("active");
1251          });
1252          var star_rating_width = $(".fill-ratings span").width();
1253          $(".star-ratings").width(star_rating_width);
1254        }
1255
1256        // testimonial slider 8
1257
1258        const testimonialsMarqueeSliders = {};
1259
1260        function testimonialsMarquee(selector, isReverse = false, speed = 8000) {
1261          const screenWidth = window.innerWidth;
1262          const direction = screenWidth >= 768 ? "vertical" : "horizontal";
1263
1264          // Destroy previous instance if exists
1265          if (testimonialsMarqueeSliders[selector]) {
1266            testimonialsMarqueeSliders[selector].destroy(true, true);
1267          }
1268
1269          // Init if element exists
1270          if ($(selector).length > 0) {
1271            testimonialsMarqueeSliders[selector] = new Swiper(selector, {
1272              slidesPerView: "auto",
1273              spaceBetween: screenWidth >= 768 ? 30 : 24,
1274              centeredSlides: true,
1275              loop: true,
1276              allowTouchMove: false,
1277              speed: speed,
1278              direction: direction,
1279              autoplay: {
1280                delay: 0,
1281                disableOnInteraction: false,
1282                reverseDirection: isReverse,
1283              },
1284            });
1285          }
1286        }
1287
1288        // Use scoped selectors within widget
1289        const upSelector = $scope.find(".tj-slider-up");
1290        const downSelector = $scope.find(".tj-slider-down");
1291
1292        if (upSelector.length) {
1293          testimonialsMarquee(`.${upSelector.attr("class").split(" ").join(".")}`, false, 8000);
1294        }
1295        if (downSelector.length) {
1296          testimonialsMarquee(`.${downSelector.attr("class").split(" ").join(".")}`, true, 8000);
1297        }
1298
1299        // home 9 testimonial
1300        let clientThumb = $scope.find(".client-thumb");
1301        if (clientThumb.length > 0) {
1302          let clientId = clientThumb.attr("id");
1303          var thumbs = new Swiper(`#${clientId}`, {
1304            slidesPerView: 3,
1305            spaceBetween: 20,
1306            loop: true,
1307            speed: 1500,
1308            freeMode: true,
1309            watchSlidesProgress: true,
1310            slideToClickedSlide: true,
1311            breakpoints: {
1312              0: {
1313                slidesPerView: 1.4,
1314                spaceBetween: 10,
1315              },
1316              430: {
1317                slidesPerView: 1.6,
1318              },
1319              530: {
1320                slidesPerView: 2,
1321                spaceBetween: 10,
1322              },
1323              768: {
1324                slidesPerView: 2.4,
1325              },
1326              992: {
1327                slidesPerView: 3,
1328                centeredSlides: true,
1329              },
1330            },
1331          });
1332        }
1333
1334        let testimonialSlider9 = $scope.find(".h9-testimonial-slider");
1335        if (testimonialSlider9.length > 0) {
1336          let slider9Id = testimonialSlider9.attr("id");
1337
1338          let testimonial = new Swiper(`#${slider9Id}`, {
1339            slidesPerView: 1,
1340            spaceBetween: 28,
1341            loopedSlides: 3,
1342            loop: loop,
1343            speed: 1500,
1344            ...(autoplay
1345              ? {
1346                  autoplay: {
1347                    delay: delay,
1348                  },
1349                }
1350              : {}),
1351            ...(nav
1352              ? {
1353                  navigation: {
1354                    nextEl: ".slider-next",
1355                    prevEl: ".slider-prev",
1356                  },
1357                }
1358              : {}),
1359            ...(dot
1360              ? {
1361                  pagination: {
1362                    el: ".swiper_pagination",
1363                    clickable: true,
1364                  },
1365                }
1366              : {}),
1367          });
1368          testimonial.controller.control = thumbs;
1369          thumbs.controller.control = testimonial;
1370        }
1371
1372        // home 10 testimonial
1373        let testimonialSlider10 = $scope.find(".h10-testimonial-slider");
1374        if (testimonialSlider10.length > 0) {
1375          let slider10Id = testimonialSlider10.attr("id");
1376
1377          let testimonial10 = new Swiper(`#${slider10Id}`, {
1378            slidesPerView: 1,
1379            spaceBetween: 30,
1380            loop: loop,
1381            speed: 1500,
1382            navigation: {
1383              nextEl: ".slider-next",
1384              prevEl: ".slider-prev",
1385            },
1386            ...(autoplay
1387              ? {
1388                  autoplay: {
1389                    delay: delay,
1390                  },
1391                }
1392              : {}),
1393            ...(dot
1394              ? {
1395                  pagination: {
1396                    el: ".testimonial-pagination",
1397                    clickable: true,
1398                  },
1399                }
1400              : {}),
1401            breakpoints: {
1402              768: {
1403                slidesPerView: 2,
1404              },
1405              1200: {
1406                slidesPerView: 3,
1407              },
1408            },
1409          });
1410        }
1411      }
1412    );
1413
1414    // tj-progress-bar
1415    elementorFrontend.hooks.addAction(
1416      "frontend/element_ready/tj-progress-bar.default",
1417
1418      function ($scope, $) {
1419        // circle progress bar
1420        let progressItem = $scope.find(".knob");
1421        if (typeof $.fn.knob != "undefined") {
1422          $(progressItem).each(function () {
1423            var $this = $(this),
1424              knobVal = $this.attr("data-rel");
1425
1426            $this.knob({
1427              draw: function () {
1428                $(this.i).val(this.cv + "%");
1429              },
1430            });
1431
1432            $this.appear(
1433              function () {
1434                $({
1435                  value: 0,
1436                }).animate(
1437                  {
1438                    value: knobVal,
1439                  },
1440                  {
1441                    duration: 2000,
1442                    easing: "swing",
1443                    step: function () {
1444                      $this.val(Math.ceil(this.value)).trigger("change");
1445                    },
1446                  }
1447                );
1448              },
1449              {
1450                accX: 0,
1451                accY: -150,
1452              }
1453            );
1454          });
1455        }
1456        // horizontal progress bar
1457        const progressContainers = document.querySelectorAll(".tj-progress");
1458
1459        if (progressContainers?.length) {
1460          progressContainers.forEach((progressContainer) => {
1461            const targetedProgressBar = progressContainer.querySelector(".tj-progress__bar");
1462            const completedPercent = parseInt(targetedProgressBar.getAttribute("data-perchant"), 10) || 0;
1463
1464            gsap.to(targetedProgressBar, {
1465              width: `${completedPercent}%`, // Correct width
1466              ease: "power2.out",
1467              duration: 1,
1468              scrollTrigger: {
1469                trigger: progressContainer, // Use container for better scroll handling
1470                start: "top 90%",
1471                end: "top 30%",
1472              },
1473              onUpdate: function () {
1474                let progressValue = Math.round(this.progress() * 100); // Corrected scaling
1475                let displayPercent = Math.round((completedPercent * progressValue) / 100); // Fixes low % issue
1476
1477                const percentageText = progressContainer.querySelector(".tj-progress__perchant");
1478                if (percentageText) {
1479                  percentageText.textContent = displayPercent + "%";
1480                }
1481              },
1482            });
1483          });
1484        }
1485      }
1486    );
1487
1488    // tj-process
1489    elementorFrontend.hooks.addAction("frontend/element_ready/tj-process.default", function ($scope, $) {
1490      let processItem = $scope.find(".h5-process_item");
1491
1492      if (processItem.length > 0) {
1493        // Add active class to the first item by default
1494        processItem.first().addClass("active");
1495
1496        // On hover, activate the hovered item and deactivate siblings
1497        processItem.on("mouseenter", function () {
1498          $(this).addClass("active").siblings().removeClass("active");
1499        });
1500      }
1501
1502      // process style 2
1503      let processWrapper = $scope.find(".h7-process-inner");
1504      if (processWrapper.length > 0) {
1505        // process hover effect
1506        const $processContainer = $(".h7-process-inner");
1507        if ($processContainer.length) {
1508          const $processItems = $processContainer.find(".h7-process-item");
1509          const $processLineActive = $processContainer.find(".process-line-active");
1510          // add active class to item
1511          if ($processItems.length) {
1512            const totalPortion = 100 / $processItems.length;
1513
1514            $processLineActive.css({
1515              left: "0",
1516              top: "0",
1517            });
1518
1519            // Activate the first item by default
1520            $processItems.removeClass("active");
1521            $processItems.eq(0).addClass("active");
1522            $processLineActive.css("top", `0%`);
1523
1524            $processItems.each(function (idx) {
1525              $(this).on("mouseenter", function () {
1526                $processItems.removeClass("active");
1527                $processLineActive.css("top", `${totalPortion * idx}%`);
1528                $(this).addClass("active");
1529              });
1530            });
1531          }
1532        }
1533      }
1534
1535      // process style 3
1536      let processWrapper8 = $scope.find(".h8-process-inner");
1537      if (processWrapper8.length > 0) {
1538        // process hover effect
1539        const $processContainer8 = $(".h8-process-inner");
1540        if ($processContainer8.length) {
1541          const $processItems8 = $processContainer8.find(".process-item");
1542          const $processLineActive8 = $processContainer8.find(".process-line-active");
1543          // add active class to item
1544          if ($processItems8.length) {
1545            const totalPortion = 100 / $processItems8.length;
1546
1547            $processLineActive8.css({
1548              left: "0",
1549              top: "0",
1550            });
1551
1552            // Activate the first item by default
1553            $processItems8.removeClass("active");
1554            $processItems8.eq(0).addClass("active");
1555            $processLineActive8.css("left", `0%`);
1556
1557            $processItems8.each(function (idx) {
1558              $(this).on("mouseenter", function () {
1559                $processItems8.removeClass("active");
1560                $processLineActive8.css("left", `${totalPortion * idx}%`);
1561                $(this).addClass("active");
1562              });
1563            });
1564          }
1565        }
1566      }
1567    });
1568
1569    // tj-advanced-tab
1570    elementorFrontend.hooks.addAction("frontend/element_ready/tj-advanced-tab.default", function ($scope, $) {
1571      let wrapper = $scope.find(".h6-team-wrapper");
1572      let teamSlider = $scope.find(".team-tab-slider");
1573
1574      let tabs = $scope.find(".h6-tab");
1575      let tabsContent = $scope.find(".h6-tab-content");
1576
1577      if (wrapper.length > 0) {
1578        let sliderID = teamSlider.attr("id");
1579
1580        let team = new Swiper(`#${sliderID}`, {
1581          slidesPerView: 1,
1582          spaceBetween: 24,
1583          loop: false,
1584          speed: 1500,
1585          breakpoints: {
1586            320: {
1587              spaceBetween: 15,
1588              slidesPerView: 2.5,
1589            },
1590            576: {
1591              slidesPerView: 3.5,
1592            },
1593            768: {
1594              slidesPerView: 4.2,
1595            },
1596            1024: {
1597              slidesPerView: 5.5,
1598            },
1599            1200: {
1600              slidesPerView: 6,
1601            },
1602          },
1603        });
1604
1605        [...tabs].forEach((tab) => {
1606          tab.addEventListener("click", () => {
1607            [...tabs].forEach((t) => t.classList.remove("active"));
1608            [...tabsContent].forEach((c) => c.classList.remove("active"));
1609
1610            tab.classList.add("active");
1611            const index = tab.getAttribute("data-index");
1612            document.getElementById("tab-" + index).classList.add("active");
1613          });
1614        });
1615      }
1616    });
1617
1618    // tj-video-info
1619    elementorFrontend.hooks.addAction("frontend/element_ready/tj-video-info.default", function ($scope, $) {
1620      let videoPopup = $scope.find(".video-popup");
1621
1622      if (videoPopup.length > 0) {
1623        new VenoBox({
1624          selector: ".video-popup",
1625          numeration: true,
1626          spinner: "pulse",
1627        });
1628      }
1629    });
1630
1631    // home 8 latest post
1632    elementorFrontend.hooks.addAction("frontend/element_ready/tj-latest-posts.default", function ($scope, $) {
1633      let h8BlogWrap = $scope.find(".h8-blog-wrapper");
1634      if (h8BlogWrap.length > 0) {
1635        $(".h8-blog-item .blog-images").on("mouseover", function () {
1636          $(this).parent(".h8-blog-item").addClass("active").siblings().removeClass("active");
1637        });
1638      }
1639    });
1640
1641    // home 9 hero banner
1642    elementorFrontend.hooks.addAction("frontend/element_ready/tj-hero-banner.default", function ($scope, $) {
1643      let marquee9 = $scope.find(".h9-hero-marquee-slider");
1644      if (marquee9.length > 0) {
1645        const marqueeId = marquee9.attr("id");
1646        var marqueeSlider = new Swiper(`#${marqueeId}`, {
1647          slidesPerView: "auto",
1648          spaceBetween: 0,
1649          freemode: true,
1650          centeredSlides: true,
1651          loop: true,
1652          speed: 8000,
1653          allowTouchMove: false,
1654          autoplay: {
1655            delay: 1,
1656            disableOnInteraction: true,
1657          },
1658        });
1659      }
1660
1661      // Initialize Chart.js pie chart
1662      const ctx = $scope.find(".tj-pie-chart");
1663      if (ctx.length > 0 && typeof Chart !== "undefined") {
1664        ctx.each(function () {
1665          const ctxSingle = this;
1666
1667          // Get data-color and sanitize
1668          let bgColorsAttr = ctxSingle.getAttribute("data-color");
1669
1670          // Fix: support comma-separated or JSON-like string
1671          let backgroundColors = ["#f7f7f7", "#f7f7f7", "#0075ff"];
1672          if (bgColorsAttr) {
1673            try {
1674              // Try to parse as JSON first (if it's like '["#fff","#000"]')
1675              if (bgColorsAttr.trim().startsWith("[")) {
1676                backgroundColors = JSON.parse(bgColorsAttr);
1677              } else {
1678                // Fallback to comma-separated string
1679                backgroundColors = bgColorsAttr.split(",").map((c) => c.trim().replace(/^['"]|['"]$/g, ""));
1680              }
1681            } catch (e) {
1682              console.warn("Invalid data-color format", e);
1683            }
1684          }
1685
1686          const data = {
1687            datasets: [
1688              {
1689                label: "47",
1690                data: [20, 12, 15],
1691                backgroundColor: backgroundColors,
1692                borderWidth: 0,
1693                spacing: 4,
1694                hoverOffset: 0,
1695              },
1696            ],
1697          };
1698
1699          const options = {
1700            cutout: "60%",
1701          };
1702
1703          new Chart(ctxSingle, {
1704            type: "doughnut",
1705            data,
1706            options,
1707          });
1708        });
1709      }
1710      // end
1711    });
1712  });
1713})(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.