PageSourceSearch

https://nichebrains.ai/wp-content/themes/hello-elementor-child-master/script.js?ver=1.0.1

js nichebrains.ai collected 2026-10-05 12:19:42 UTC 5,883 bytes, 189 lines download raw bytes

1(function ($) {
2  "use strict";
3
4  /* ----------------------------------------
5     GLOBAL HELPERS
6  ---------------------------------------- */
7  const hasEl = (selector) => document.querySelector(selector);
8
9  const initGSAP = () => {
10    if (typeof gsap !== "undefined" && typeof ScrollTrigger !== "undefined") {
11      gsap.registerPlugin(ScrollTrigger);
12      return true;
13    }
14    return false;
15  };
16
17  /* ----------------------------------------
18     ELEMENTOR INIT
19  ---------------------------------------- */
20  $(window).on("elementor/frontend/init", function () {
21    elementorFrontend.hooks.addAction(
22      "frontend/element_ready/global",
23      function () {
24
25        /* 1. HOME – Timeline scroll + click */
26        const section = document.querySelector(".timeline-container");
27        if (section) {
28          const items = section.querySelectorAll(".timeline-item");
29          if (!items.length) return;
30
31          let maxProgress = 0;
32          const activate = (i) => {
33            items.forEach((el, index) =>
34              el.classList.toggle("active", index === i)
35            );
36          };
37          activate(0);
38
39          const onScroll = () => {
40            const rect = section.getBoundingClientRect();
41            const winH = window.innerHeight;
42            const startPoint = winH * 0.4;
43
44            if (rect.top > startPoint || rect.bottom < 200) return;
45
46            let progress = Math.max(0, startPoint - rect.top);
47
48            const lastItem = items[items.length - 1];
49            maxProgress = lastItem.offsetTop + 40;
50            progress = Math.min(progress, maxProgress);
51
52            const segment = maxProgress / (items.length - 1);
53            const index = Math.min(
54              Math.floor(progress / segment),
55              items.length - 1
56            );
57
58            activate(index);
59            section.style.setProperty("--after-height", `${progress}px`);
60          };
61
62          window.addEventListener("scroll", onScroll, { passive: true });
63
64          items.forEach((item, index) => {
65            item.addEventListener("click", () => {
66              const segment = maxProgress / (items.length - 1);
67              section.style.setProperty(
68                "--after-height",
69                `${segment * index}px`
70              );
71              activate(index);
72            });
73          });
74        }
75
76        /* 2. HOME – Text color scroll animation */
77        if (hasEl(".about-cont p") && initGSAP()) {
78          const paragraph = document.querySelector(".about-cont p");
79          if (!paragraph.classList.contains("gsap-processed")) {
80            paragraph.classList.add("gsap-processed");
81
82            const words = paragraph.innerText.split(" ");
83            paragraph.innerHTML = words
84              .map((w) => `<span class="word">${w}</span>`)
85              .join(" ");
86
87            gsap.fromTo(
88              ".about-cont p .word",
89              { color: "#B6B6B6" },
90              {
91                color: "#030467",
92                stagger: 0.1,
93                ease: "none",
94                scrollTrigger: {
95                  trigger: ".about-cont",
96                  start: "top 90%",
97                  end: "bottom 50%",
98                  scrub: true,
99                },
100              }
101            );
102          }
103        }
104
105        /* 3. ABOUT – Tabs progress indicator */
106        if (hasEl(".story-tab")) {
107          const updateProgress = () => {
108            const tabs = $(".story-tab .e-n-tab-title");
109            const active = tabs.filter("[aria-selected='true']").index();
110            if (active < 0) return;
111
112            const step = 100 / tabs.length;
113            $(".story-tab .e-n-tabs-heading")
114              .css("--progress", `${(active + 1) * step}%`);
115          };
116
117          updateProgress();
118          $(".story-tab .e-n-tab-title").on("click", () =>
119            setTimeout(updateProgress, 50)
120          );
121        }
122
123        /* 4. LOGO SLIDER – Middle active slide */
124        const initLogoSlider = () => {
125          const swiperEl = document.querySelector(".slider-logo .swiper");
126          const swiper = swiperEl?.swiper;
127          if (!swiper) return setTimeout(initLogoSlider, 200);
128
129          const setMiddle = () => {
130            const slides = swiper.slides;
131            if (!slides?.length) return;
132
133            const perView =
134              Number(swiper.params.slidesPerView) ||
135              Math.round(swiper.el.clientWidth / slides[0].clientWidth) ||
136              1;
137
138            let idx =
139              (swiper.activeIndex + Math.floor(perView / 2)) %
140              slides.length;
141
142            $(slides).removeClass("middle-active");
143            $(slides[idx]).addClass("middle-active");
144          };
145
146          swiper.on("init slideChange transitionEnd resize", setMiddle);
147          setTimeout(() => {
148            try { swiper.update(); } catch (e) {}
149            setMiddle();
150          }, 250);
151        };
152
153        if (hasEl(".slider-logo .swiper")) {
154          initLogoSlider();
155        }
156
157      }
158    );
159  });
160
161  /* ----------------------------------------
162     5. ENGAGE EXPERTS – Custom arrows
163  ---------------------------------------- */
164  $(".success-stories-prev a, .success-stories-next a")
165    .attr("href", "javascript:void(0)");
166
167  $(".success-stories-prev").on("click", () =>
168    $(".elementor-swiper-button-prev").trigger("click")
169  );
170
171  $(".success-stories-next").on("click", () =>
172    $(".elementor-swiper-button-next").trigger("click")
173  );
174
175  /* ----------------------------------------
176     6. ELEMENTOR POPUP – Gravity Forms Phone Number Field Validation
177  ---------------------------------------- */
178  jQuery(document).on('elementor/popup/show', function () {
179
180    jQuery(document).off('input.gfphone').on('input.gfphone', '#input_3_4', function () {
181        this.value = this.value.replace(/[^0-9]/g, '');
182    });
183
184});
185
186
187
188
189})(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.