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.