PageSourceSearch

https://godrejhf.com/scripts/scripts.js

js godrejhf.com collected 2026-10-03 21:13:32 UTC 53,462 bytes, 1,646 lines download raw bytes

1import {
2  sampleRUM,
3  buildBlock,
4  loadHeader,
5  loadFooter,
6  decorateButtons,
7  decorateIcons,
8  decorateSections,
9  decorateBlocks,
10  decorateTemplateAndTheme,
11  waitForLCP,
12  loadBlocks,
13  loadCSS,
14  loadSubHeader,
15  loadSecFooter,
16  loadnewDesktopFooter,
17  loadnewMobileFooter,
18  loadnewTabletFooter,
19  loadnewDesktopHeader,
20  loadnewMobileHeader,
21  loadnewTabletHeader,
22  loadnewDesktopSubFooter,
23  loadnewMobileSubFooter,
24  loadnewTabletSubFooter,
25  loadnewDesktopSubHeader,
26  loadnewMobileSubHeader,
27  loadnewTabletSubHeader,
28  getMetadata,
29} from "./aem.js";
30import ffetch from "./ffetch.js";
31import { createExpression, renderExpressions } from "./expressions.js";
32import { loadFragment } from "../blocks/fragment/fragment.js";
33const LCP_BLOCKS = ['main-teaser']; // add your LCP blocks to the list
34
35/**
36 * Builds hero block and prepends to main in a new section.
37 * @param {Element} main The container element
38 */
39
40function buildHeroBlock(main) {
41  const firstSection = main.querySelector("div");
42  if (!firstSection) return;
43  const firstElement = firstSection.firstElementChild;
44  if (
45    firstElement.tagName === "DIV" &&
46    firstElement.classList.length &&
47    !firstElement.classList.contains("hero")
48  )
49    return;
50}
51
52async function fetchInterestRates() {
53  const interestRates = await ffetch("/interest-rates-sheet.json").all();
54  return interestRates;
55}
56
57async function fetchCustomerSupportExcludedPaths() {
58  try {
59    const rows = await ffetch("/testing/urls-without-customer-support.json").all();
60    return rows
61      .map((row) => row.URL?.trim().replace(/\/$/, ""))
62      .filter(Boolean);
63  } catch (e) {
64    console.error("fetchCustomerSupportExcludedPaths failed:", e);
65    return [];
66  }
67}
68
69function renderInterestExpressions(main) {
70  const render = async () => {
71    try {
72      const interestRate = await fetchInterestRates();
73      renderExpressions(main, interestRate);
74    } catch (error) {
75      console.error("Interest expression render failed:", error);
76    }
77  };
78
79  if ("requestIdleCallback" in window) {
80    window.requestIdleCallback(render, { timeout: 2000 });
81  } else {
82    window.setTimeout(render, 0);
83  }
84}
85
86createExpression("interest", ({ context, args }) => {
87  const subcategory = args;
88  const interestRateData = context.find((item) => item.key == subcategory);
89  const interest = interestRateData ? interestRateData.interest_rate : "N/A";
90  return `${interest}%`;
91});
92
93/**
94 * load fonts.css and set a session storage flag
95 */
96let fontsLoading = false;
97async function loadFonts() {
98  if (fontsLoading) return; // prevent duplicate calls
99  fontsLoading = true;
100  await loadCSS(`${window.hlx.codeBasePath}/styles/fonts.css`);
101  try {
102    if (!window.location.hostname.includes("localhost"))
103      sessionStorage.setItem("fonts-loaded", "true");
104  } catch (e) {
105    // do nothing
106  }
107}
108
109/**
110 * Builds a singular, Title Case name from the last hyphenated segment of the
111 * current URL, e.g. "/our-products/home-loans" -> "Home Loan".
112 */
113function getNameFromUrlSlug() {
114  const segments = window.location.pathname.replace(/\/$/, "").split("/");
115  const lastSegment = segments[segments.length - 1] || "";
116  const words = lastSegment.split("-").filter(Boolean);
117  const lastIndex = words.length - 1;
118  return words
119    .map((word, index) => {
120      const singular = index === lastIndex && word.length > 1 && word.toLowerCase().endsWith("s")
121        ? word.slice(0, -1)
122        : word;
123      return singular.charAt(0).toUpperCase() + singular.slice(1).toLowerCase();
124    })
125    .join(" ");
126}
127
128// Max loan amount (in INR) per product name, used as the offer price on
129// /our-products pages. Pages not listed here fall back to the default price.
130const PRODUCT_PRICE_MAP = {
131  "Home Loan": "100000000", // ₹10 crore
132  "Business Loan": "7500000", // ₹75 lakhs
133  "Personal Loan": "3000000", // ₹30 lakhs
134  "Affordable Home Loan": "10000000", // ₹1 crore
135};
136
137/**
138 * Checks the authored /product-schema-url.json sheet for a row whose URL
139 * matches the current page path.
140 */
141async function isListedInProductSchemaSheet() {
142  try {
143    const response = await fetch("/product-schema-url.json");
144    if (!response.ok) return false;
145    const { data } = await response.json();
146    const currentPath = window.location.pathname.replace(/\/$/, "") || "/";
147    return (data || []).some((row) => {
148      const rowUrl = row.URLs || row.url || "";
149      try {
150        const rowPath = new URL(rowUrl, window.location.origin).pathname.replace(/\/$/, "") || "/";
151        return rowPath === currentPath;
152      } catch (e) {
153        return false;
154      }
155    });
156  } catch (e) {
157    return false;
158  }
159}
160
161/**
162 * Injects Product JSON-LD schema for /our-products pages and for any page
163 * listed in the authored /product-schema-url.json sheet.
164 * Name, description, price, etc. are read from page metadata so each
165 * product page can override them without a code change.
166 */
167async function injectProductSchema() {
168  if (document.querySelector('script[data-schema="product"]')) return;
169  const isProductPage = window.location.pathname.startsWith("/our-products")
170    || await isListedInProductSchemaSheet();
171  if (!isProductPage) return;
172
173  const pageUrl = window.location.href;
174  const name = getNameFromUrlSlug() || getMetadata("og:title") || document.title;
175  const description = getMetadata("description") || "";
176  const price = getMetadata("schemaprice") || PRODUCT_PRICE_MAP[name] || "500000";
177  const priceCurrency = getMetadata("schemacurrency") || "INR";
178  const offerDescription = getMetadata("offerdescription") || description;
179
180  const schemaData = {
181    "@context": "https://schema.org",
182    "@type": "Product",
183    name,
184    description,
185    url: pageUrl,
186    brand: {
187      "@type": "Brand",
188      name: "Godrej Capital",
189    },
190    offers: {
191      "@type": "Offer",
192      priceCurrency,
193      price,
194      description: offerDescription,
195      url: pageUrl,
196      seller: {
197        "@type": "Organization",
198        name: "Godrej Capital",
199      },
200    },
201  };
202
203  const script = document.createElement("script");
204  script.type = "application/ld+json";
205  script.dataset.schema = "product";
206  script.textContent = JSON.stringify(schemaData);
207  document.head.appendChild(script);
208}
209
210/**
211 * Injects Article JSON-LD schema for /media-blog/knowledge-centre pages.
212 * Headline, description, image, and publish date are read from page
213 * metadata so each article can override them without a code change.
214 */
215function getAuthoredPublishedDate() {
216  const descriptionEl = document.querySelector(".published-date-content .description p");
217  if (!descriptionEl) return "";
218  const match = descriptionEl.textContent.match(/Published on\s+(.+)/i);
219  if (!match) return "";
220  const parsedDate = new Date(match[1].trim());
221  if (Number.isNaN(parsedDate.getTime())) return "";
222  // Build the ISO date from local date parts rather than toISOString(), which
223  // converts to UTC and can shift the date back a day in timezones ahead of UTC.
224  const year = parsedDate.getFullYear();
225  const month = String(parsedDate.getMonth() + 1).padStart(2, "0");
226  const day = String(parsedDate.getDate()).padStart(2, "0");
227  return `${year}-${month}-${day}`;
228}
229
230function injectArticleSchema() {
231  if (!window.location.pathname.startsWith("/media-blog/knowledge-centre")) return;
232  if (document.querySelector('script[data-schema="article"]')) return;
233
234  const pageUrl = window.location.href;
235  const headline = getMetadata("og:title") || document.title;
236  const description = getMetadata("description") || "";
237  const image = `${window.location.origin}/media-blog/knowledge-centre/media_1f204d42bd6dee128df0bfb93f564ae8d6ed50edd.png?width=1200&format=pjpg&optimize=medium`;
238  const isProdHost = window.location.hostname === "www.godrejcapital.com";
239  const defaultLogo = isProdHost
240    ? `${window.location.origin}/media_1cc56a3925a23333a077a2e3cd585d00469995b9f.jpg?width=750&format=jpg&optimize=medium`
241    : `${window.location.origin}/media_131a71264056e38eb6704956773f890efe585f108.png?width=750&format=png&optimize=medium`;
242  const logo = getMetadata("logo") || defaultLogo;
243  const datePublished = getAuthoredPublishedDate();
244  const schemaData = {
245    "@context": "https://schema.org",
246    "@type": "Article",
247    headline,
248    description,
249    url: pageUrl,
250    datePublished,
251    image: {
252      "@type": "ImageObject",
253      url: image,
254    },
255    author: {
256      "@type": "Organization",
257      name: "Godrej Capital",
258      url: window.location.origin,
259    },
260    publisher: {
261      "@type": "Organization",
262      name: "Godrej Capital",
263      logo: {
264        "@type": "ImageObject",
265        url: logo,
266      },
267    },
268    mainEntityOfPage: {
269      "@type": "WebPage",
270      "@id": pageUrl,
271    },
272  };
273
274  const script = document.createElement("script");
275  script.type = "application/ld+json";
276  script.dataset.schema = "article";
277  script.textContent = JSON.stringify(schemaData);
278  document.head.appendChild(script);
279}
280
281/**
282 * Injects HowTo JSON-LD schema for the /apply-now landing page.
283 * The guide content is fixed (not authored per-page); only the URL
284 * is resolved dynamically so it matches the current environment.
285 */
286function injectHowToSchema() {
287  const path = window.location.pathname.replace(/\/$/, "");
288  if (path !== "/apply-now") return;
289  if (document.querySelector('script[data-schema="howto"]')) return;
290
291  const pageUrl = window.location.href;
292
293  const schemaData = {
294    "@context": "https://schema.org",
295    "@type": "HowTo",
296    name: "How to Apply for a Loan on Godrej Capital",
297    description: "A step-by-step guide to applying for a Home Loan, Business Loan, or Loan Against Property on Godrej Capital's website.",
298    url: pageUrl,
299    image: "https://www.godrejcapital.com/media_1474825b7b1b4458819317c02c017617aa1318b00.png",
300    totalTime: "PT10M",
301    tool: [
302      { "@type": "HowToTool", name: "Mobile Phone / Desktop" },
303      { "@type": "HowToTool", name: "Valid Mobile Number for OTP" },
304      { "@type": "HowToTool", name: "KYC & Income Documents" },
305    ],
306    step: [
307      {
308        "@type": "HowToStep",
309        position: "1",
310        name: "Visit the Godrej Capital Website",
311        text: "Go to www.godrejcapital.com and click on the 'Apply Now' button for your desired loan product — Home Loan, Business Loan, or Loan Against Property.",
312        url: pageUrl,
313      },
314      {
315        "@type": "HowToStep",
316        position: "2",
317        name: "Enter Your Mobile Number",
318        text: "Fill in your registered mobile number on the loan application form to begin the process.",
319        url: pageUrl,
320      },
321      {
322        "@type": "HowToStep",
323        position: "3",
324        name: "OTP Verification",
325        text: "Verify your identity by entering the One-Time Password (OTP) sent to your registered mobile number.",
326        url: pageUrl,
327      },
328      {
329        "@type": "HowToStep",
330        position: "4",
331        name: "Enter Loan Requirements",
332        text: "Provide details related to your loan amount, preferred tenure, and the purpose of the loan.",
333        url: pageUrl,
334      },
335      {
336        "@type": "HowToStep",
337        position: "5",
338        name: "Submit Personal & Employment Details",
339        text: "Enter your personal information along with your employment or business details for eligibility assessment.",
340        url: pageUrl,
341      },
342      {
343        "@type": "HowToStep",
344        position: "6",
345        name: "Compare & Apply for Best Offer",
346        text: "Review the available loan offers tailored to your profile and apply for the one that best suits your financial needs.",
347        url: pageUrl,
348      },
349      {
350        "@type": "HowToStep",
351        position: "7",
352        name: "Submit Required Documents",
353        text: "Upload the necessary KYC documents, income proof, and employment details for verification and loan processing.",
354        url: pageUrl,
355      },
356      {
357        "@type": "HowToStep",
358        position: "8",
359        name: "Loan Approval & Disbursement",
360        text: "Upon successful verification of your documents and eligibility, receive your loan approval and disbursement directly to your account.",
361        url: pageUrl,
362      },
363    ],
364  };
365
366  const script = document.createElement("script");
367  script.type = "application/ld+json";
368  script.dataset.schema = "howto";
369  script.textContent = JSON.stringify(schemaData);
370  document.head.appendChild(script);
371}
372
373/**
374 * Builds all synthetic blocks in a container element.
375 * @param {Element} main The container element
376 */
377function buildAutoBlocks(main) {
378  try {
379    buildHeroBlock(main);
380  } catch (error) {
381    // eslint-disable-next-line no-console
382    console.error("Auto Blocking failed", error);
383  }
384}
385
386function updateLinks() {
387  // Get all anchor tags in the document
388  const links = document.querySelectorAll("a");
389  links.forEach((link) => {
390    
391    // Check if the link has an href attribute
392    if (!link.href) {
393      return; // Skip this link if no href
394    }
395
396    // Some authored placeholder links (e.g. href="https://#") aren't a valid
397    // URL — new URL() throws for those, which would otherwise abort this
398    // forEach and skip every link that comes after it in the document.
399    let url;
400    try {
401      url = new URL(link.href);
402    } catch (e) {
403      return;
404    }
405
406    if (url.searchParams.has("gtm")) {
407      // Get the gtm value
408      const gtmValue = url.searchParams.get("gtm");
409      // Add data attribute with the gtm value
410      link.setAttribute("data-gtm", gtmValue);
411      // Remove the gtm query parameter from the URL
412      url.searchParams.delete("gtm");
413      link.href = url.toString();
414    }
415    if (url.searchParams.has("open_in_new_tab")) {
416      const newTab = url.searchParams.get("open_in_new_tab");
417      if (newTab == "true") {
418        link.setAttribute("target", "_blank");
419        link.addEventListener("click", () => {
420          url.searchParams.delete("open_in_new_tab");
421          link.href = url.toString();
422        });
423      }
424    }
425  });
426  // Process all 'div' elements with data-url attribute
427  const divs = document.querySelectorAll("div[data-link]");
428  divs.forEach((div) => {
429    let url;
430    try {
431      url = new URL(div.getAttribute("data-link"));
432    } catch (e) {
433      return;
434    }
435    if (url.searchParams.has("open_in_new_tab")) {
436      const newUrl = new URL(url.href);
437      newUrl.searchParams.delete("open_in_new_tab");
438      newUrl.searchParams.delete("gtm");
439      div.addEventListener("click", (e) => {
440        e.preventDefault();
441        window.open(newUrl.href, "_blank");
442      });
443    } else {
444      const newUrl = new URL(url.href);
445      newUrl.searchParams.delete("gtm");
446      div.addEventListener("click", () => {
447        window.location.href = newUrl.href;
448      });
449    }
450  });
451}
452
453function updateButtonWithGtm() {
454  const buttons = document.querySelectorAll("button");
455  buttons.forEach((button) => {
456    if (button.hasAttribute("data-path")) {
457      let redirectionUrl = new URL(
458        button.getAttribute("data-path"),
459        window.location.origin
460      );
461      if (redirectionUrl) {
462        // Get the gtm value
463        const gtmValue = redirectionUrl.searchParams.get("gtm");
464        if (gtmValue !== null && gtmValue !== undefined && gtmValue !== "") {
465          // Add data attribute with the gtm value
466          button.setAttribute("data-gtm", gtmValue);
467          // Remove the gtm query parameter from the URL
468          redirectionUrl.searchParams.delete("gtm");
469          button.href = redirectionUrl.toString();
470        }
471      } else {
472        return;
473      }
474    } else {
475      return;
476    }
477  });
478}
479
480function getAnchorButtonTag() {
481  const buttonEle = document.querySelectorAll("button");
482  const anchorEle = document.querySelectorAll("a");
483
484  buttonEle.forEach((button) => {
485    button.addEventListener("click", function () {
486      if (this.hasAttribute("data-gtm")) {
487        const gtmValue = this.getAttribute("data-gtm");
488        if (gtmValue !== null && gtmValue !== undefined && gtmValue !== "") {
489          dataStoreInDataLayer(gtmValue);
490        }
491      }
492    });
493  });
494
495  anchorEle.forEach((anchor) => {
496    anchor.addEventListener("click", function () {
497      if (this.hasAttribute("data-gtm")) {
498        const gtmValue = this.getAttribute("data-gtm");
499        if (gtmValue !== null && gtmValue !== undefined && gtmValue !== "") {
500          dataStoreInDataLayer(gtmValue);
501        }
502      }
503    });
504  });
505}
506
507function dataStoreInDataLayer(gtmValue) {
508  window.dataLayer = window.dataLayer || [];
509  window.dataLayer.push({
510    gtmEvent: gtmValue ? gtmValue : "NA",
511  });
512}
513
514/**
515 * Decorates the main element.
516 * @param {Element} main The main element
517 */
518// eslint-disable-next-line import/prefer-default-export
519export function decorateMain(main) {
520  // hopefully forward compatible button decoration
521  decorateButtons(main);
522  decorateIcons(main);
523  buildAutoBlocks(main);
524  decorateSections(main);
525  decorateBlocks(main);
526  //  addingDomainToLink('/domain-sheet.json');
527}
528
529/**
530 * Loads everything needed to get to LCP.
531 * @param {Element} doc The container element
532 */
533async function loadEager(doc) {
534  document.documentElement.lang = "en";
535  decorateTemplateAndTheme();
536  const main = doc.querySelector("main");
537  if (main) {
538    decorateMain(main);
539    document.body.classList.add("appear");
540    const currentPath = window.location.pathname;
541    if (
542      currentPath == "/become-our-partner" ||
543      currentPath.includes("campaign")
544    ) {
545      document.body.classList.add("appear-become");
546    } else if (currentPath.includes("clubone")) {
547      document.body.classList.add("club-one-margin");
548      document.body.classList.add("club-oneBody");
549    } else if (currentPath.includes("testclub")) {
550      document.body.classList.add("club-one-margin");
551      document.body.classList.add("club-oneBody");
552    }
553    await waitForLCP(LCP_BLOCKS);
554  }
555
556  try {
557    /* if desktop (proxy for fast connection) or fonts already loaded, load fonts.css */
558    if (window.innerWidth >= 900 || sessionStorage.getItem("fonts-loaded")) {
559      loadFonts();
560    }
561  } catch (e) {
562    // do nothing
563  }
564}
565
566/**
567 * Loads everything that doesn't need to be delayed.
568 * @param {Element} doc The container element
569 */
570async function loadLazy(doc) {
571  const main = doc.querySelector("main");
572  await loadBlocks(main);
573
574  // Moved from loadEager — interest rates are non-critical, don't block LCP
575  renderInterestExpressions(main);
576
577  const [npsFrag, applyNowFrag, customerSupportFrag, customerSupportExcludedPaths] = await Promise.all([
578    loadFragment("/nps/feedbackform"),
579    loadFragment("/applynowformnew/applynowformnew"),
580    loadFragment("/testing/customer-support"),
581    fetchCustomerSupportExcludedPaths(),
582  ]);
583
584  if (npsFrag) {
585    const npsfragSection = npsFrag.querySelector(
586      ".section.feedbackform-container"
587    );
588    if (npsfragSection) {
589      if (!window.location.href.includes("clubone")) {
590        main.append(npsfragSection);
591      }
592    }
593  }
594
595  // const applyBottomFrag = await loadFragment('/applynowformbottom/applynowbottom');
596  // if(applyBottomFrag){
597  //   const applyBottomSection = applyBottomFrag.querySelector('.section.applynowbottom-container');
598  //   if(applyBottomSection){
599  //     main.append(applyBottomSection);
600  //   }
601  // }
602
603  if (applyNowFrag) {
604    const applyNowFragSection = applyNowFrag.querySelector(
605      ".section.applynowformnew-container"
606    );
607    if (applyNowFragSection) {
608      main.append(applyNowFragSection);
609      applyNowFragSection.style.display = "none";
610    }
611  }
612
613  // customer-support-v1 is no longer authored per page — it's rendered on every
614  // page, sourced from the single /testing/customer-support doc. Skip it on the
615  // 404/error page (main.error, same marker 404.html itself checks for) and on
616  // any page listed in /testing/urls-without-customer-support.json.
617  const currentPagePath = window.location.pathname.replace(/\/$/, "");
618  const isCustomerSupportExcludedPage = customerSupportExcludedPaths.includes(currentPagePath);
619  const customerSupportBlock = customerSupportFrag?.querySelector(".customer-support-v1");
620  const shouldRenderCentralizedCustomerSupport = Boolean(customerSupportBlock)
621    && !main.classList.contains("error")
622    && !isCustomerSupportExcludedPage;
623
624  // Tells customer-support-v1.css whether the centralized instance is on this
625  // page, so it only hides a page-authored (legacy) block once the centralized
626  // one is there to replace it — on an excluded/404 page, or when the doc
627  // failed to load, the authored block falls back to its default display
628  // instead of being hidden with nothing to replace it.
629  document.body.classList.toggle("customer-support-centralized", shouldRenderCentralizedCustomerSupport);
630
631  if (shouldRenderCentralizedCustomerSupport) {
632    const customerSupportSection = customerSupportBlock.closest(".section");
633    if (customerSupportSection) {
634      main.append(customerSupportSection);
635    }
636  }
637
638  const { hash } = window.location;
639  const element = hash ? doc.getElementById(hash.substring(1)) : false;
640  if (hash && element) element.scrollIntoView();
641
642  const hideDefaultDesktopHeader = doc.querySelector(
643    'meta[name="hidedefaultdesktopheader"]'
644  );
645  const hideDefaultDesktopHeaderContent = hideDefaultDesktopHeader
646    ? hideDefaultDesktopHeader.getAttribute("content")
647    : "false";
648
649  const hideDefaultMobileHeader = doc.querySelector(
650    'meta[name="hidedefaultmobileheader"]'
651  );
652  const hideDefaultMobileHeaderContent = hideDefaultMobileHeader
653    ? hideDefaultMobileHeader.getAttribute("content")
654    : "false";
655
656  const hideDefaultTabletHeader = doc.querySelector(
657    'meta[name="hidedefaultmobileheader"]'
658  );
659  const hideDefaultTabletHeaderContent = hideDefaultTabletHeader
660    ? hideDefaultTabletHeader.getAttribute("content")
661    : "false";
662
663  const hideDefaultDesktopSubHeader = doc.querySelector(
664    'meta[name="hidedefaultdesktopsubheader"]'
665  );
666  const hideDefaultDesktopSubHeaderContent = hideDefaultDesktopSubHeader
667    ? hideDefaultDesktopSubHeader.getAttribute("content")
668    : "false";
669
670  const hideDefaultMobileSubHeader = doc.querySelector(
671    'meta[name="hidedefaultmobilesubheader"]'
672  );
673  const hideDefaultMobileSubHeaderContent = hideDefaultMobileSubHeader
674    ? hideDefaultMobileSubHeader.getAttribute("content")
675    : "false";
676
677  const hideDefaultTabletSubHeader = doc.querySelector(
678    'meta[name="hidedefaulttabletsubheader"]'
679  );
680  const hideDefaultTabletSubHeaderContent = hideDefaultTabletSubHeader
681    ? hideDefaultTabletSubHeader.getAttribute("content")
682    : "false";
683
684  const newDesktopHeader = doc.querySelector('meta[name="newdesktopheader"]');
685  const newDesktopHeaderContent = newDesktopHeader
686    ? newDesktopHeader.getAttribute("content")
687    : "false";
688  const newMobileHeader = doc.querySelector('meta[name="newmobileheader"]');
689  const newMobileHeaderContent = newMobileHeader
690    ? newMobileHeader.getAttribute("content")
691    : "false";
692
693  const newTabletHeader = doc.querySelector('meta[name="newtabletheader"]');
694  const newTabletHeaderContent = newTabletHeader
695    ? newTabletHeader.getAttribute("content")
696    : "false";
697
698  const newDesktopSubHeader = doc.querySelector(
699    'meta[name="newdesktopsubheader"]'
700  );
701  const newDesktopSubHeaderContent = newDesktopSubHeader
702    ? newDesktopSubHeader.getAttribute("content")
703    : "false";
704
705  const newMobileSubHeader = doc.querySelector(
706    'meta[name="newmobilesubheader"]'
707  );
708  const newMobileSubHeaderContent = newMobileSubHeader
709    ? newMobileSubHeader.getAttribute("content")
710    : "false";
711
712  const newTabletSubHeader = doc.querySelector(
713    'meta[name="newtabletsubheader"]'
714  );
715  const newTabletSubHeaderContent = newTabletSubHeader
716    ? newTabletSubHeader.getAttribute("content")
717    : "false";
718
719  const hideDefaultDesktopFooter = doc.querySelector(
720    'meta[name="hidedefaultdesktopfooter"]'
721  );
722  const hideDefaultDesktopFooterContent = hideDefaultDesktopFooter
723    ? hideDefaultDesktopFooter.getAttribute("content")
724    : "false";
725
726  const hideDefaultMobileFooter = doc.querySelector(
727    'meta[name="hidedefaultmobilefooter"]'
728  );
729  const hideDefaultMobileFooterContent = hideDefaultMobileFooter
730    ? hideDefaultMobileFooter.getAttribute("content")
731    : "false";
732
733  const hideDefaultTabletFooter = doc.querySelector(
734    'meta[name="hidedefaulttabletfooter"]'
735  );
736  const hideDefaultTabletFooterContent = hideDefaultTabletFooter
737    ? hideDefaultTabletFooter.getAttribute("content")
738    : "false";
739
740  const hideDefaultDesktopSubFooter = doc.querySelector(
741    'meta[name="hidedefaultdesktopsubfooter"]'
742  );
743  const hideDefaultDesktopSubFooterContent = hideDefaultDesktopSubFooter
744    ? hideDefaultDesktopSubFooter.getAttribute("content")
745    : "false";
746
747  const hideDefaultMobileSubFooter = doc.querySelector(
748    'meta[name="hidedefaultmobilesubfooter"]'
749  );
750  const hideDefaultMobileSubFooterContent = hideDefaultMobileSubFooter
751    ? hideDefaultMobileSubFooter.getAttribute("content")
752    : "false";
753
754  const hideDefaultTabletSubFooter = doc.querySelector(
755    'meta[name="hidedefaulttabletsubfooter"]'
756  );
757  const hideDefaultTabletSubFooterContent = hideDefaultTabletSubFooter
758    ? hideDefaultTabletSubFooter.getAttribute("content")
759    : "false";
760
761  const newDesktopFooter = doc.querySelector('meta[name="newdesktopfooter"]');
762  const newDesktopFooterContent = newDesktopFooter
763    ? newDesktopFooter.getAttribute("content")
764    : "false";
765
766  const newMobileFooter = doc.querySelector('meta[name="newmobilefooter"]');
767  const newMobileFooterContent = newMobileFooter
768    ? newMobileFooter.getAttribute("content")
769    : "false";
770
771  const newTabletFooter = doc.querySelector('meta[name="newtabletfooter"]');
772  const newTabletFooterContent = newTabletFooter
773    ? newTabletFooter.getAttribute("content")
774    : "false";
775
776  const newDesktopSubFooter = doc.querySelector(
777    'meta[name="newdesktopsubfooter"]'
778  );
779  const newDesktopSubFooterContent = newDesktopSubFooter
780    ? newDesktopSubFooter.getAttribute("content")
781    : "false";
782
783  const newMobileSubFooter = doc.querySelector(
784    'meta[name="newmobilesubfooter"]'
785  );
786  const newMobileSubFooterContent = newMobileSubFooter
787    ? newMobileSubFooter.getAttribute("content")
788    : "false";
789
790  const newTabletSubFooter = doc.querySelector(
791    'meta[name="newtabletsubfooter"]'
792  );
793  const newTabletSubFooterContent = newTabletSubFooter
794    ? newTabletSubFooter.getAttribute("content")
795    : "false";
796
797  const desktopHeaderBlockName = doc.querySelector(
798    'meta[name="desktopheaderblockname"]'
799  );
800  const desktopHeaderBlockNameContent = desktopHeaderBlockName
801    ? desktopHeaderBlockName.getAttribute("content")
802    : "";
803
804  const mobileHeaderBlockName = doc.querySelector(
805    'meta[name="mobileheaderblockname"]'
806  );
807  const mobileHeaderBlockNameContent = mobileHeaderBlockName
808    ? mobileHeaderBlockName.getAttribute("content")
809    : "";
810
811  const tabletHeaderBlockName = doc.querySelector(
812    'meta[name="tabletheaderblockname"]'
813  );
814  const tabletHeaderBlockNameContent = tabletHeaderBlockName
815    ? tabletHeaderBlockName.getAttribute("content")
816    : "";
817
818  const desktopFooterBlockName = doc.querySelector(
819    'meta[name="desktopfooterblockname"]'
820  );
821  const desktopFooterBlockNameContent = desktopFooterBlockName
822    ? desktopFooterBlockName.getAttribute("content")
823    : "";
824
825  const mobileFooterBlockName = doc.querySelector(
826    'meta[name="mobilefooterblockname"]'
827  );
828  const mobileFooterBlockNameContent = mobileFooterBlockName
829    ? mobileFooterBlockName.getAttribute("content")
830    : "";
831
832  const tabletFooterBlockName = doc.querySelector(
833    'meta[name="tabletfooterblockname"]'
834  );
835  const tabletFooterBlockNameContent = tabletFooterBlockName
836    ? tabletFooterBlockName.getAttribute("content")
837    : "";
838
839  const desktopSubHeaderBlockName = doc.querySelector(
840    'meta[name="desktopsubheaderblockname"]'
841  );
842  const desktopSubHeaderBlockNameContent = desktopSubHeaderBlockName
843    ? desktopSubHeaderBlockName.getAttribute("content")
844    : "";
845
846  const mobileSubHeaderBlockName = doc.querySelector(
847    'meta[name="mobilesubheaderblockname"]'
848  );
849  const mobileSubHeaderBlockNameContent = mobileSubHeaderBlockName
850    ? mobileSubHeaderBlockName.getAttribute("content")
851    : "";
852
853  const tabletSubHeaderBlockName = doc.querySelector(
854    'meta[name="tabletsubheaderblockname"]'
855  );
856  const tabletSubHeaderBlockNameContent = tabletSubHeaderBlockName
857    ? tabletSubHeaderBlockName.getAttribute("content")
858    : "";
859
860  const desktopSubFooterBlockName = doc.querySelector(
861    'meta[name="desktopsubfooterblockname"]'
862  );
863  const desktopSubFooterBlockNameContent = desktopSubFooterBlockName
864    ? desktopSubFooterBlockName.getAttribute("content")
865    : "";
866
867  const mobileSubFooterBlockName = doc.querySelector(
868    'meta[name="mobilesubfooterblockname"]'
869  );
870  const mobileSubFooterBlockNameContent = mobileSubFooterBlockName
871    ? mobileSubFooterBlockName.getAttribute("content")
872    : "";
873
874  const tabletSubFooterBlockName = doc.querySelector(
875    'meta[name="tabletsubfooterblockname"]'
876  );
877  const tabletSubFooterBlockNameContent = tabletSubFooterBlockName
878    ? tabletSubFooterBlockName.getAttribute("content")
879    : "";
880
881  if (newDesktopHeaderContent === "false" && isDesktop()) {
882    loadHeader(doc.querySelector("header"));
883  }
884
885  if (newDesktopHeaderContent === "true" && isDesktop()) {
886    loadnewDesktopHeader(
887      doc.querySelector("header"),
888      desktopHeaderBlockNameContent
889    );
890  }
891
892  if (newMobileHeaderContent === "false" && isMobile()) {
893    loadHeader(doc.querySelector("header"));
894  }
895
896  if (newMobileHeaderContent === "true" && isMobile()) {
897    loadnewMobileHeader(
898      doc.querySelector("header"),
899      mobileHeaderBlockNameContent
900    );
901  }
902
903  if (newTabletHeaderContent === "false" && isTablet()) {
904    loadHeader(doc.querySelector("header"));
905  }
906
907  if (newTabletHeaderContent === "true" && isTablet()) {
908    loadnewTabletHeader(
909      doc.querySelector("header"),
910      tabletHeaderBlockNameContent
911    );
912  }
913
914  if (newDesktopSubHeaderContent === "false" && isDesktop()) {
915    loadSubHeader(doc.querySelector("header"));
916  }
917
918  if (newDesktopSubHeaderContent === "true" && isDesktop()) {
919    loadnewDesktopSubHeader(
920      doc.querySelector("header"),
921      desktopSubHeaderBlockNameContent
922    );
923  }
924
925  if (newMobileSubHeaderContent === "false" && isMobile()) {
926    loadSubHeader(doc.querySelector("header"));
927  }
928
929  if (newMobileSubHeaderContent === "true" && isMobile()) {
930    loadnewMobileSubHeader(
931      doc.querySelector("header"),
932      mobileSubHeaderBlockNameContent
933    );
934  }
935
936  if (newTabletSubHeaderContent === "false" && isTablet()) {
937    loadSubHeader(doc.querySelector("header"));
938  }
939
940  if (newTabletSubHeaderContent === "true" && isTablet()) {
941    loadnewTabletSubHeader(
942      doc.querySelector("header"),
943      tabletSubHeaderBlockNameContent
944    );
945  }
946
947  if (newDesktopFooterContent === "false" && isDesktop()) {
948    loadFooter(doc.querySelector("footer"));
949  }
950
951  if (newDesktopFooterContent === "true" && isDesktop()) {
952    loadnewDesktopFooter(
953      doc.querySelector("footer"),
954      desktopFooterBlockNameContent
955    );
956  }
957
958  if (newMobileFooterContent === "false" && isMobile()) {
959    loadFooter(doc.querySelector("footer"));
960  }
961
962  if (newMobileFooterContent === "true" && isMobile()) {
963    loadnewMobileFooter(
964      doc.querySelector("footer"),
965      mobileFooterBlockNameContent
966    );
967  }
968
969  if (newTabletFooterContent === "false" && isTablet()) {
970    loadFooter(doc.querySelector("footer"));
971  }
972
973  if (newTabletFooterContent === "true" && isTablet()) {
974    loadnewTabletFooter(
975      doc.querySelector("footer"),
976      tabletFooterBlockNameContent
977    );
978  }
979
980  // if (newSubFooterContent === 'false' && isDesktop()) {
981  //   loadSecFooter(doc.querySelector('footer'));
982  // }
983  if (newDesktopSubFooterContent === "false" && isDesktop()) {
984    loadSecFooter(doc.querySelector("footer"));
985  }
986
987  if (newDesktopSubFooterContent === "true" && isDesktop()) {
988    loadnewDesktopSubFooter(
989      doc.querySelector("footer"),
990      desktopSubFooterBlockNameContent
991    );
992  }
993
994  if (newMobileSubFooterContent === "false" && isMobile()) {
995    loadSecFooter(doc.querySelector("footer"));
996  }
997
998  if (newMobileSubFooterContent === "true" && isMobile()) {
999    loadnewMobileSubFooter(
1000      doc.querySelector("footer"),
1001      mobileSubFooterBlockNameContent
1002    );
1003  }
1004
1005  if (newTabletSubFooterContent === "false" && isTablet()) {
1006    loadSecFooter(doc.querySelector("footer"));
1007  }
1008
1009  if (newTabletSubFooterContent === "true" && isTablet()) {
1010    loadnewTabletSubFooter(
1011      doc.querySelector("footer"),
1012      tabletSubFooterBlockNameContent
1013    );
1014  }
1015
1016  if (hideDefaultDesktopHeaderContent === "true" && isDesktop()) {
1017    if (doc.querySelector(".header")) {
1018      doc.querySelector(".header").style.display = "none";
1019      main.classList.add("remove-header");
1020    }
1021  }
1022
1023  if (hideDefaultTabletHeaderContent === "true" && isTablet()) {
1024    if (doc.querySelector(".header")) {
1025      doc.querySelector(".header").style.display = "none";
1026      main.classList.add("remove-header");
1027    }
1028  }
1029
1030  if (hideDefaultMobileHeaderContent === "true" && isMobile()) {
1031    if (doc.querySelector(".header")) {
1032      doc.querySelector(".header").style.display = "none";
1033      main.classList.add("remove-header");
1034    }
1035  }
1036
1037  if (hideDefaultDesktopSubHeaderContent === "true" && isDesktop()) {
1038    if (doc.querySelector(".subheader")) {
1039      doc.querySelector(".subheader").style.display = "none";
1040      main.classList.add("remove-subheader");
1041    }
1042  }
1043
1044  if (hideDefaultMobileSubHeaderContent === "true" && isMobile()) {
1045    if (doc.querySelector(".subheader")) {
1046      doc.querySelector(".subheader").style.display = "none";
1047      main.classList.add("remove-subheader");
1048    }
1049  }
1050
1051  if (hideDefaultTabletSubHeaderContent === "true" && isTablet()) {
1052    if (doc.querySelector(".subheader")) {
1053      doc.querySelector(".subheader").style.display = "none";
1054      main.classList.add("remove-subheader");
1055    }
1056  }
1057
1058  if (hideDefaultDesktopFooterContent === "true" && isDesktop()) {
1059    if (doc.querySelector(".footer")) {
1060      doc.querySelector(".footer").style.display = "none";
1061      main.classList.add("remove-footer");
1062    }
1063  }
1064
1065  if (hideDefaultMobileFooterContent === "true" && isMobile()) {
1066    if (doc.querySelector(".footer")) {
1067      doc.querySelector(".footer").style.display = "none";
1068      main.classList.add("remove-footer");
1069    }
1070  }
1071
1072  if (hideDefaultTabletFooterContent === "true" && isTablet()) {
1073    if (doc.querySelector(".footer")) {
1074      doc.querySelector(".footer").style.display = "none";
1075      main.classList.add("remove-footer");
1076    }
1077  }
1078
1079  if (hideDefaultDesktopSubFooterContent === "true" && isDesktop()) {
1080    if (doc.querySelector(".secfooter")) {
1081      doc.querySelector(".secfooter").style.display = "none";
1082      main.classList.add("remove-subfooter");
1083    }
1084  }
1085
1086  if (hideDefaultMobileSubFooterContent === "true" && isMobile()) {
1087    if (doc.querySelector(".secfooter")) {
1088      doc.querySelector(".secfooter").style.display = "none";
1089      main.classList.add("remove-subfooter");
1090    }
1091  }
1092
1093  if (hideDefaultTabletSubFooterContent === "true" && isTablet()) {
1094    if (doc.querySelector(".secfooter")) {
1095      doc.querySelector(".secfooter").style.display = "none";
1096      main.classList.add("remove-subfooter");
1097    }
1098  }
1099
1100  loadCSS(`${window.hlx.codeBasePath}/styles/lazy-styles.css`);
1101  loadFonts();
1102
1103  sampleRUM("lazy");
1104  sampleRUM.observe(main.querySelectorAll("div[data-block-name]"));
1105  sampleRUM.observe(main.querySelectorAll("picture > img"));
1106}
1107
1108/**
1109 * Loads everything that happens a lot later,
1110 * without impacting the user experience.
1111 */
1112let gtmLoadScheduled = false;
1113
1114function loadGTMContainer() {
1115  if (gtmLoadScheduled) {
1116    return;
1117  }
1118  gtmLoadScheduled = true;
1119  import("./gtmScript-prod.js").then((module) => module.addGTMContainer());
1120}
1121
1122function scheduleGTMContainerLoad() {
1123  window.dataLayer = window.dataLayer || [];
1124  const events = ["pointerdown", "keydown", "touchstart", "scroll"];
1125  const loadOnInteraction = () => {
1126    events.forEach((eventName) => {
1127      window.removeEventListener(eventName, loadOnInteraction);
1128    });
1129    loadGTMContainer();
1130  };
1131
1132  events.forEach((eventName) => {
1133    window.addEventListener(eventName, loadOnInteraction, { once: true, passive: true });
1134  });
1135}
1136
1137function loadDelayed() {
1138  // eslint-disable-next-line import/no-cycle
1139  window.setTimeout(() => {
1140    import("./delayed.js");
1141    const isProductionHost = [
1142      "godrejcapital.com",
1143      "www.godrejcapital.com",
1144      "godrejhf.com",
1145      "www.godrejhf.com",
1146      "godrejfinance.com",
1147      "www.godrejfinance.com",
1148    ].includes(window.location.hostname);
1149    if (!isProductionHost) {
1150      import("./gtmScript-uat.js").then(module => module.addGTMContainer());
1151    }
1152  }, 6000);
1153  scheduleGTMContainerLoad();
1154  // load anything that can be postponed to the latest here
1155}
1156
1157function isMobile() {
1158  return window.matchMedia("(max-width: 743px)").matches;
1159}
1160
1161function isTablet() {
1162  return window.matchMedia("(min-width: 744px) and (max-width: 1199px)")
1163    .matches;
1164}
1165
1166function isDesktop() {
1167  return window.matchMedia("(min-width: 1200px)").matches;
1168}
1169
1170async function fetchAndReplaceUrl(apiUrl) {
1171  // Prevent reload loop: if this page load was already triggered by a redirect, skip
1172  if (sessionStorage.getItem("redirected")) {
1173    sessionStorage.removeItem("redirected");
1174    return window.location.href;
1175  }
1176
1177  try {
1178    const response = await fetch(apiUrl);
1179
1180    if (!response.ok) {
1181      throw new Error("Failed to fetch data from API");
1182    }
1183    const data = await response.json();
1184    let currentUrl = window.location.href;
1185    const originalUrl = currentUrl; // Save the original URL
1186
1187    // Replace URL parts with the values from the API data
1188    data.data.forEach((item) => {
1189      const regex = new RegExp(item.key, "g");
1190      currentUrl = currentUrl.replace(regex, item.value);
1191    });
1192
1193    // Only update the URL and reload if it has actually changed
1194    if (currentUrl !== originalUrl) {
1195      sessionStorage.setItem("redirected", "true"); // Guard against reload loop
1196      window.history.pushState({}, "", currentUrl); // Update the browser URL
1197      window.location.reload(); // Reload the page once
1198    }
1199
1200    return currentUrl;
1201  } catch (error) {
1202    console.error("Error:", error);
1203    return window.location.href;
1204  }
1205}
1206
1207function hideParticularText() {
1208  const elements = document.querySelectorAll("p, span, div, li, td, h1, h2, h3, h4, h5, h6");
1209  elements.forEach((element) => {
1210    if (element.childElementCount === 0 && element.textContent.trim() === "#blank#") {
1211      element.style.display = "none";
1212    }
1213  });
1214}
1215
1216function debounce(fn, delay = 150) {
1217  let timer;
1218  return (...args) => {
1219    clearTimeout(timer);
1220    timer = setTimeout(() => fn(...args), delay);
1221  };
1222}
1223
1224function getResponsiveValue(values) {
1225  const w = window.innerWidth;
1226  if (w >= 1440) return values.dxl;
1227  if (w >= 1200) return values.dx;
1228  if (w >= 768) return values.t;
1229  return values.m;
1230}
1231
1232function applyLineHeightByClassPattern() {
1233  const blocks = document.querySelectorAll('[class*="lh-"]');
1234  const handlers = [];
1235
1236  blocks.forEach((block) => {
1237    Array.from(block.classList).filter((cls) => cls.startsWith("lh-")).forEach((targetClass) => {
1238      const match = targetClass.match(/lh-dxl(\d+)px-dx(\d+)px-t(\d+)px-m(\d+)px-(\w+)/);
1239      if (!match) return;
1240      const [, dxl, dx, t, m, tagName] = match;
1241      const values = { dxl: parseFloat(dxl), dx: parseFloat(dx), t: parseFloat(t), m: parseFloat(m) };
1242      const apply = () => {
1243        block.querySelectorAll(tagName).forEach((el) => { el.style.lineHeight = `${getResponsiveValue(values)}px`; });
1244      };
1245      apply();
1246      handlers.push(apply);
1247    });
1248  });
1249
1250  if (handlers.length) {
1251    window.addEventListener("resize", debounce(() =>
1251 handlers.forEach((h) => h())));
1252  }
1253}
1254
1255function applyWordSpacingByClassPattern() {
1256  const blocks = document.querySelectorAll('[class*="ws-"]');
1257  const handlers = [];
1258
1259  blocks.forEach((block) => {
1260    const targetClass = Array.from(block.classList).find((cls) => cls.startsWith("ws-"));
1261    if (!targetClass) return;
1262    const match = targetClass.match(/ws-dxl(\d+)px-dx(\d+)px-t(\d+)px-m(\d+)px-(\w+)/);
1263    if (!match) return;
1264    const [, dxl, dx, t, m, tagName] = match;
1265    const values = { dxl: parseFloat(dxl), dx: parseFloat(dx), t: parseFloat(t), m: parseFloat(m) };
1266    const apply = () => {
1267      block.querySelectorAll(tagName).forEach((el) => { el.style.wordSpacing = `${getResponsiveValue(values)}px`; });
1268    };
1269    apply();
1270    handlers.push(apply);
1271  });
1272
1273  if (handlers.length) {
1274    window.addEventListener("resize", debounce(() => handlers.forEach((h) => h())));
1275  }
1276}
1277
1278function applyFontWeightByClassPattern() {
1279  const blocks = document.querySelectorAll('[class*="fw-"]');
1280  const handlers = [];
1281
1282  blocks.forEach((block) => {
1283    Array.from(block.classList).filter((cls) => cls.startsWith("fw-")).forEach((targetClass) => {
1284      const match = targetClass.match(/fw-dxl(\d+)-dx(\d+)-t(\d+)-m(\d+)-(\w+)/);
1285      if (!match) return;
1286      const [, dxl, dx, t, m, tagName] = match;
1287      const values = { dxl: parseFloat(dxl), dx: parseFloat(dx), t: parseFloat(t), m: parseFloat(m) };
1288      const apply = () => {
1289        block.querySelectorAll(tagName).forEach((el) => { el.style.fontWeight = `${getResponsiveValue(values)}`; });
1290      };
1291      apply();
1292      handlers.push(apply);
1293    });
1294  });
1295
1296  if (handlers.length) {
1297    window.addEventListener("resize", debounce(() => handlers.forEach((h) => h())));
1298  }
1299}
1300
1301function applyFontSizeByClassPattern() {
1302  const blocks = document.querySelectorAll('[class*="fs-"]');
1303  const handlers = [];
1304
1305  blocks.forEach((block) => {
1306    Array.from(block.classList).filter((cls) => cls.startsWith("fs-")).forEach((targetClass) => {
1307      const match = targetClass.match(/fs-dxl(\d+)px-dx(\d+)px-t(\d+)px-m(\d+)px-(\w+)/);
1308      if (!match) return;
1309      const [, dxl, dx, t, m, tagName] = match;
1310      const values = { dxl: parseFloat(dxl), dx: parseFloat(dx), t: parseFloat(t), m: parseFloat(m) };
1311      const apply = () => {
1312        block.querySelectorAll(tagName).forEach((el) => { el.style.fontSize = `${getResponsiveValue(values)}px`; });
1313      };
1314      apply();
1315      handlers.push(apply);
1316    });
1317  });
1318
1319  if (handlers.length) {
1320    window.addEventListener("resize", debounce(() => handlers.forEach((h) => h())));
1321  }
1322}
1323
1324function redirectAnchorLinksHomePage() {
1325  const anchors = document.querySelectorAll('a[href="/"]');
1326  anchors.forEach((anchor) => {
1327    anchor.addEventListener("click", function (event) {
1328      event.preventDefault();
1329      window.location.href = "/";
1330    });
1331  });
1332}
1333
1334function checkUserVisited() {
1335  const key = "userVisited";
1336  const storedData = localStorage.getItem(key);
1337
1338  const currentDate = new Date();
1339  const feedbackButton = document.querySelector(".feedback-title-btn");
1340
1341  if (!feedbackButton) return;
1342
1343  if (storedData) {
1344    const { value, timestamp } = JSON.parse(storedData);
1345    const storedDate = timestamp ? new Date(timestamp) : null;
1346
1347    // Check if timestamp exists and is older than 60 days
1348    if (
1349      !storedDate ||
1350      (currentDate - storedDate) / (1000 * 60 * 60 * 24) > 60
1351    ) {
1352      localStorage.removeItem(key);
1353      feedbackButton.classList.remove("disabled-feedback");
1354      return false;
1355    }
1356
1357    // ✅ Only disable the button if value === true
1358    if (value) {
1359      feedbackButton.classList.add("disabled-feedback");
1360    } else {
1361      feedbackButton.classList.remove("disabled-feedback");
1362    }
1363    return value;
1364  }
1365
1366  // First-time visit: Store data with a timestamp
1367  const newValue = false;
1368  const data = {
1369    value: newValue,
1370    timestamp: currentDate.toISOString(), // Add timestamp
1371  };
1372
1373  localStorage.setItem(key, JSON.stringify(data));
1374
1375  if (newValue) {
1376    feedbackButton.classList.add("disabled-feedback");
1377  } else {
1378    feedbackButton.classList.remove("disabled-feedback");
1379  }
1380
1381  return newValue;
1382}
1383
1384function getVisitedUrls() {
1385  let urls = sessionStorage.getItem("visitedUrls");
1386  if (urls) {
1387    return JSON.parse(urls);
1388  } else {
1389    return [];
1390  }
1391}
1392
1393function addVisitedUrl(url) {
1394  let visitedUrls = getVisitedUrls();
1395  if (!visitedUrls.includes(url)) {
1396    visitedUrls.push(url);
1397    sessionStorage.setItem("visitedUrls", JSON.stringify(visitedUrls));
1398  }
1399}
1400
1401async function loadPage() {
1402  await loadEager(document);
1403  await loadLazy(document);
1404  await injectProductSchema();
1405  injectArticleSchema();
1406  injectHowToSchema();
1407  loadDelayed();
1408  updateButtonWithGtm();
1409  scrollToAnchor("target");
1410  getAnchorButtonTag();
1411  scrollToButton("target");
1412  ScrollLoanBtn();
1413  const idleCallback = window.requestIdleCallback || ((fn) => setTimeout(fn, 200));
1414  // Runs only now, once loadLazy has fully decorated every block (including
1415  // fragment-injected ones like customer-support-v1 and applynowformnew, and
1416  // blocks like marque-tab-gc that rebuild their DOM from authored content) —
1417  // running it earlier from decorateMain() raced those blocks and missed any
1418  // open_in_new_tab=true link they hadn't rendered yet.
1419  idleCallback(() => updateLinks());
1420  idleCallback(() => fetchAndReplaceUrl("/old-redirection.json"));
1421  idleCallback(() => hideParticularText());
1422  applyLineHeightByClassPattern();
1423  applyWordSpacingByClassPattern();
1424  applyFontWeightByClassPattern();
1425  applyFontSizeByClassPattern();
1426  redirectAnchorLinksHomePage();
1427  checkUserVisited();
1428  addVisitedUrl(window.location.href);
1429}
1430
1431loadPage();
1432function scrollToAnchor(keyword) {
1433  const anchors = document.querySelectorAll("a");
1434  const currentUrl = new URL(window.location.href);
1435  const urlParams = new URLSearchParams(currentUrl.search);
1436  const targetId = urlParams.get(keyword);
1437  let timer = null;
1438
1439  // Helper to find element by ID, class, or data-id attribute
1440  const findElement = (id) => {
1441    return document.querySelector(`#${id}`)
1442      || document.querySelector(`.${id}`)
1443      || document.querySelector(`[data-id="${id}"]`);
1444  };
1445
1446  // Scroll if the element is already on this page
1447  if (targetId) {
1448    const targetElement = findElement(targetId);
1449    if (targetElement) {
1450      // Scroll after short delay to ensure element is in DOM
1451      timer = setTimeout(() => {
1452        const header = document.querySelector("header");
1453        const headerHeight = header ? header.offsetHeight : 0;
1454        const targetPosition =
1455          targetElement.getBoundingClientRect().top +
1456          window.scrollY -
1457          3 * headerHeight;
1458
1459        window.scrollTo({
1460          top: targetPosition,
1461          behavior: "smooth",
1462        });
1463
1464        targetElement.classList.add("highlight");
1465        setTimeout(() => targetElement.classList.remove("highlight"), 2000);
1466
1467        // Clean the URL
1468        urlParams.delete(keyword);
1469        const newUrl = urlParams.toString()
1470          ? `${currentUrl.pathname}?${urlParams.toString()}`
1471          : currentUrl.pathname;
1472        history.replaceState(null, "", newUrl);
1473      }, 100);
1474    }
1475  }
1476
1477  // Handle anchor clicks
1478  anchors.forEach((anchor) => {
1479    const href = anchor.getAttribute("href");
1480    if (!href || !href.includes(`${keyword}=`)) return;
1481
1482    const anchorUrl = new URL(href, window.location.origin);
1483    const anchorTargetId = anchorUrl.searchParams.get(keyword);
1484
1485    anchor.addEventListener("click", function (event) {
1486      const samePage = anchorUrl.pathname === currentUrl.pathname;
1487      if (samePage) {
1488        const targetElement = findElement(anchorTargetId);
1489        if (targetElement) {
1490          event.preventDefault(); // Prevent default only for same-page anchor
1491
1492          const header = document.querySelector("header");
1493          const headerHeight = header ? header.offsetHeight : 0;
1494          const targetPosition =
1495            targetElement.getBoundingClientRect().top +
1496            window.scrollY -
1497            3 * headerHeight;
1498
1499          window.scrollTo({
1500            top: targetPosition,
1501            behavior: "smooth",
1502          });
1503
1504          targetElement.classList.add("highlight");
1505          setTimeout(() => targetElement.classList.remove("highlight"), 2000);
1506          // Clean the URL
1507          urlParams.delete(keyword);
1508          const newUrl = urlParams.toString()
1509            ? `${currentUrl.pathname}?${urlParams.toString()}`
1510            : currentUrl.pathname;
1511          history.replaceState(null, "", newUrl);
1512        }
1513      } // Else let it navigate normally (other page)
1514    });
1515  });
1516}
1517
1518function ScrollLoanBtn() {
1519  const applybtn = document.querySelector(".applynowform-container");
1520  if (applybtn) {
1521    const fieldsetdiv = applybtn.querySelector("#loanTypeFieldset");
1522    if (!fieldsetdiv) return;
1523    const checkDiv = fieldsetdiv.querySelector(".checked");
1524    const currentPath = new URL(window.location.href);
1525    if (checkDiv) {
1526      window.scrollTo({
1527        top: 300, // Scroll to the element's position
1528        behavior: "smooth", // Smooth scrolling effect
1529      });
1530      currentPath.searchParams.delete("gtm");
1531      window.history.replaceState(null, "", currentPath);
1532    }
1533  }
1534}
1535function clearCustomDropdowns() {
1536  // Remove all existing custom dropdown parts
1537  const selects = document.querySelectorAll(
1538    ".select-selected-becomepartner, .select-items-becomepartner"
1539  );
1540  selects.forEach((el) => el.remove());
1541}
1542
1543function checkCheckboxByLabelText(labelText) {
1544  const blockBecome = document.querySelector(".becomepartnerform");
1545  const fields = document.querySelectorAll(
1546    ".form1 .field-wrapper.checkbox-wrapper.selection-wrapper"
1547  );
1548
1549  // Loop through each field
1550  for (let field of fields) {
1551    const label = field.querySelector("label");
1552    const input = field.querySelector('input[type="checkbox"]');
1553    if (label && input && label.textContent.trim() === labelText) {
1554      input.checked = true;
1555      field.classList.add("checked");
1556    }
1557  }
1558  const isHousingFinanceHost = ["godrejhf.com", "www.godrejhf.com"]
1559    .includes(window.location.hostname);
1560  if (blockBecome && !isHousingFinanceHost) {
1561    Promise.all([
1562      import("../blocks/becomepartnerform/becomepartnerform.js"),
1563      import("../blocks/form/inputFieldsValidation.js"),
1564    ]).then(([{ getCustomDrop, showHideDropdown }, { initFormValidation }]) => {
1565      clearCustomDropdowns();
1566      getCustomDrop();
1567      initFormValidation(blockBecome, ".form1", ".form1 #submit-btn");
1568      showHideDropdown();
1569    }).catch((error) => console.error("Partner form initialization failed:", error));
1570  }
1571}
1572
1573function scrollToButton(keyword) {
1574  const allButtons = document.querySelectorAll("button");
1575  allButtons.forEach((button) => {
1576    const dataLink = button.getAttribute("data-link");
1577    if (dataLink) {
1578      const urlParams = new URLSearchParams(dataLink.split("?")[1]);
1579      const gtmValue = urlParams.get("gtm");
1580      if (gtmValue) {
1581        button.setAttribute("data-gtm", gtmValue);
1582      }
1583      const targetId = urlParams.get(keyword);
1584      if (targetId) {
1585        const targetElement = document.querySelector(`.${targetId}`);
1586
1587        if (targetElement) {
1588          button.addEventListener("click", (e) => {
1589            e.preventDefault();
1590            const selectiveDiv = button.parentNode.parentNode.parentNode;
1591            if (selectiveDiv) {
1592              const associatedParagraph = document.querySelector(
1593                `#form-loancategoryplaceholder`
1594              );
1595              const selectiveTextDiv = selectiveDiv.firstChild;
1596              const selectiveText = selectiveTextDiv.textContent.trim();
1597              checkCheckboxByLabelText(selectiveText);
1598              if (associatedParagraph && !associatedParagraph.classList.contains("active-dropdown")) {
1599                associatedParagraph.click();
1600              }
1601            }
1602
1603            // Defer layout reads to the next frame so they happen after the
1604            // dropdown layout settles, avoiding a forced reflow.
1605            requestAnimationFrame(() => {
1606              const header = document.querySelector("header");
1607              const headerHeight = header ? header.offsetHeight : 0;
1608              const targetPosition =
1609                targetElement.getBoundingClientRect().top +
1610                window.scrollY -
1611                3 * headerHeight;
1612
1613              window.scrollTo({
1614                top: targetPosition,
1615                behavior: "smooth",
1616              });
1617
1618              // Update the URL with the target ID
1619              const newUrl = new URL(window.location.href);
1620              window.history.pushState(null, "", newUrl);
1621
1622              // Remove the `gtm` parameter from the current URL
1623              newUrl.searchParams.delete("gtm");
1624              window.history.replaceState(null, "", newUrl);
1625            });
1626          });
1627        } else {
1628          button.addEventListener("click", (e) => {
1629            e.preventDefault();
1630
1631            const targetUrl = new URL(dataLink, window.location.origin);
1632            targetUrl.searchParams.delete("gtm"); // Remove 'gtm' from query params
1633            window.location.href = targetUrl.toString();
1634          });
1635        }
1636      } else {
1637        button.addEventListener("click", (e) => {
1638          e.preventDefault();
1639          const targetUrl = new URL(dataLink, window.location.origin);
1640          targetUrl.searchParams.delete("gtm");
1641          window.location.href = targetUrl.toString();
1642        });
1643      }
1644    }
1645  });
1646}

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.