1document.addEventListener('DOMContentLoaded', function () { 2 if(jQuery('.client-testimonials-slider').length) { 3 new Swiper('.client-testimonials-slider', { 4 loop: false, 5 slidesPerView: 1, 6 spaceBetween: 0, 7 autoHeight: true, 8 direction: "vertical", 9 10 navigation: { 11 nextEl: '.testimonial-next', 12 prevEl: '.testimonial-prev', 13 }, 14 pagination: { 15 el: ".testimonial-pagination", 16 clickable: true, 17 }, 18 }); 19 20 function countIncrement() { 21 const observerOptions = { 22 threshold: 0.5, 23 }; 24 25 const observer = new IntersectionObserver((entries, observer) => { 26 entries.forEach((entry) => { 27 if (entry.isIntersecting) { 28 const $el = jQuery(entry.target); 29 const targetValue = parseInt($el.data("target")); 30 31 jQuery({ countNum: 0 }).animate( 32 { 33 countNum: targetValue, 34 }, 35 { 36 duration: 2000, 37 easing: "swing", 38 step: function () { 39 $el.text(Math.floor(this.countNum)); 40 }, 41 complete: function () { 42 $el.text(this.countNum); 43 }, 44 }, 45 ); 46 47 observer.unobserve(entry.target); 48 } 49 }); 50 }, observerOptions); 51 52 jQuery(".count-increment").each(function () { 53 observer.observe(this); 54 }); 55 } 56 countIncrement(); 57} 58 59}); 60 61document.addEventListener('DOMContentLoaded', function () { 62 if (jQuery('.demad-solution-stats-slider').length) { 63 64 new Swiper('.demad-solution-stats-slider', { 65 66 loop: true, 67 68 slidesPerView: 1, 69 70 spaceBetween: 10, 71 72 autoplay: { 73 delay: 3000, 74 disableOnInteraction: false, 75 pauseOnMouseEnter: false 76 }, 77 78 pagination: { 79 el: '.swiper-pagination', 80 clickable: true, 81 }, 82 83 }); 84 85 } 86 87 /* 88 * News Slider 89 */ 90 if (document.querySelector('.newsSwiper')) { 91 92 new Swiper('.newsSwiper', { 93 94 loop: true, 95 96 slidesPerView: 1, 97 98 spaceBetween: 20, 99 100 autoplay: { 101 delay: 3000, 102 disableOnInteraction: false, 103 pauseOnMouseEnter: false 104 }, 105 106 pagination: { 107 el: '.swiper-pagination', 108 clickable: true, 109 }, 110 111 navigation: { 112 nextEl: '.swiper-button-next', 113 prevEl: '.swiper-button-prev', 114 }, 115 116 breakpoints: { 117 768: { 118 slidesPerView: 1, 119 }, 120 121 1024: { 122 slidesPerView: 1, 123 } 124 } 125 126 }); 127 128 } 129 130}); 131 132/* Menu Animation */ 133// document.addEventListener("DOMContentLoaded", function () { 134// if (typeof gsap === "undefined") { 135// console.warn("GSAP is not available."); 136// return; 137// } 138// const ACTIVE_COLOR = "#00bfcc"; 139// const MENU_SELECTOR = 140// "#primary-menu a, " + 141// "#menu-secondary_menu a, " + 142// ".thinking-item > .title, .revenue-agency-sec .service-tags p "; 143// const CTA_TEXT_SELECTOR = 144// ".animated-buttons-wrapper .btn-text"; 145// function setupMenuLink(link) { 146// if (!link) { 147// return; 148// } 149// if (link.dataset.gsapReady === "true") { 150// return; 151// } 152// if (link.closest(".cta-btn, .animated-buttons-wrapper")) { 153// return; 154// } 155// if (link.querySelector(":scope > .gsap-menu-text")) { 156// link.dataset.gsapReady = "true"; 157// return; 158// } 159// const originalText = link.textContent 160// .replace(/\s+/g, " ") 161// .trim(); 162// if (!originalText) { 163// return; 164// } 165// link.dataset.gsapReady = "true"; 166// const walker = document.createTreeWalker( 167// link, 168// NodeFilter.SHOW_TEXT 169// ); 170// const textNodes = []; 171// while (walker.nextNode()) { 172// textNodes.push(walker.currentNode); 173// }
174// textNodes.forEach(function (node) { 175// node.remove(); 176// }); 177// const wrapper = document.createElement("span"); 178// wrapper.className = "gsap-menu-text"; 179// const normal = document.createElement("span"); 180// normal.className = "gsap-menu-text-normal"; 181// normal.textContent = originalText; 182// const hover = document.createElement("span"); 183// hover.className = "gsap-menu-text-hover"; 184// hover.textContent = originalText; 185// wrapper.appendChild(normal); 186// wrapper.appendChild(hover); 187// link.insertBefore(wrapper, link.firstChild); 188 189// gsap.set(wrapper, { 190// position: "relative", 191// display: "inline-block", 192// overflow: "hidden", 193// verticalAlign: "top" 194// }); 195// gsap.set(normal, { 196// display: "block", 197// yPercent: 0 198// }); 199// gsap.set(hover, { 200// position: "absolute", 201// left: 0, 202// top: "100%", 203// display: "block", 204// color: ACTIVE_COLOR, 205// whiteSpace: "nowrap", 206// yPercent: 0 207// }); 208 209// /* == HOVER IN == */ 210 211// link.addEventListener("mouseenter", function () { 212// gsap.killTweensOf([normal, hover]); 213// gsap.to(normal, { 214// yPercent: -100,
215// duration: 0.45, 216// ease: "power3.out", 217// overwrite: true 218// }); 219// gsap.to(hover, { 220// yPercent: -100, 221// duration: 0.45, 222// ease: "power3.out", 223// overwrite: true 224// }); 225// }); 226// /* == HOVER OUT === */ 227// link.addEventListener("mouseleave", function () { 228// gsap.killTweensOf([normal, hover]); 229// gsap.to(normal, { 230// yPercent: 0, 231// duration: 0.4, 232// ease: "power3.inOut", 233// overwrite: true 234// }); 235// gsap.to(hover, { 236// yPercent: 0, 237// duration: 0.4, 238// ease: "power3.inOut", 239// overwrite: true 240// }); 241// }); 242// } 243// /* === CTA TEXT ANIMATION === */ 244// function setupCTA(buttonText) { 245// if (!buttonText) { 246// return; 247// } 248// if (buttonText.dataset.gsapCTAReady === "true") { 249// return; 250// } 251// const originalText = buttonText.textContent 252// .replace(/\s+/g, " ") 253// .trim(); 254// if (!originalText) { 255// return; 256// } 257// buttonText.dataset.gsapCTAReady = "true"; 258// const wrapper = document.createElement("span"); 259// wrapper.className = "gsap-btn-text"; 260// const normal = document.createElement("span"); 261// normal.className = "gsap-btn-text-normal"; 262// normal.textContent = originalText; 263// const hover = document.createElement("span"); 264// hover.className = "gsap-btn-text-hover"; 265// hover.textContent = originalText; 266// wrapper.appendChild(normal); 267// wrapper.appendChild(hover); 268// buttonText.innerHTML = ""; 269// buttonText.appendChild(wrapper); 270// /* == GSAP INITIAL STATE == */ 271// gsap.set(wrapper, { 272// position: "relative", 273// display: "inline-block", 274// overflow: "hidden", 275// verticalAlign: "top" 276// }); 277// gsap.set(normal, { 278// display: "block", 279// yPercent: 0 280// }); 281// gsap.set(hover, { 282// position: "absolute", 283// left: 0, 284// top: "100%", 285// display: "block", 286// color: ACTIVE_COLOR, 287// whiteSpace: "nowrap", 288// yPercent: 0 289// }); 290// /* === HOVER IN === */ 291 292// buttonText.addEventListener("mouseenter", function () { 293// gsap.killTweensOf([normal, hover]); 294// gsap.to(normal, { 295// yPercent: -100,
296// duration: 0.45, 297// ease: "power3.out", 298// overwrite: true 299// }); 300// gsap.to(hover, { 301// yPercent: -100, 302// duration: 0.45, 303// ease: "power3.out", 304// overwrite: true 305// }); 306// }); 307// /* === HOVER OUT === */ 308// buttonText.addEventListener("mouseleave", function () { 309// gsap.killTweensOf([normal, hover]); 310// gsap.to(normal, { 311// yPercent: 0, 312// duration: 0.4, 313// ease: "power3.inOut", 314// overwrite: true 315// }); 316// gsap.to(hover, { 317// yPercent: 0, 318// duration: 0.4, 319// ease: "power3.inOut", 320// overwrite: true 321// }); 322// }); 323// } 324// /* == THINKING TITLE â CTA ARROW / BUTTON SYNC == */ 325// function setupThinkingArrowSync() { 326// document.querySelectorAll(".thinking-item").forEach(function (article) { 327 328// const title = article.querySelector(".title"); 329 330// if (!title || title.dataset.arrowSyncReady === "true") { 331// return; 332// } 333 334// // Target ONLY the icon inside this thinking-item 335// const arrow = article.querySelector( 336// ".right .ub-demo-swatch .ub-icon-btn" 337// ); 338 339// const button = article.querySelector( 340// ".animated-buttons-wrapper .cta-btn" 341// ); 342 343// if (!arrow && !button) { 344// return; 345// } 346 347// title.dataset.arrowSyncReady = "true"; 348 349// /* 350// * ========================================== 351// * TITLE â ARROW / BUTTON 352// * ========================================== 353// */ 354 355// title.addEventListener("mouseenter", function () { 356 357// if (button) { 358// button.dispatchEvent( 359// new MouseEvent("mouseenter", { 360// bubbles: false, 361// cancelable: true, 362// view: window 363// }) 364// ); 365// } 366 367// if (arrow) { 368// arrow.dispatchEvent( 369// new MouseEvent("mouseenter", { 370// bubbles: false, 371// cancelable: true, 372// view: window 373// }) 374// ); 375// } 376 377// }); 378 379// title.addEventListener("mouseleave", function () { 380 381// if (button) { 382// button.dispatchEvent( 383// new MouseEvent("mouseleave", { 384// bubbles: false, 385// cancelable: true, 386// view: window 387// }) 388// ); 389// } 390 391// if (arrow) { 392// arrow.dispatchEvent( 393// new MouseEvent("mouseleave", { 394// bubbles: false, 395// cancelable: true, 396// view: window 397// }) 398// ); 399// } 400 401// }); 402 403// /* 404// * ========================================== 405// * ARROW â TITLE 406// * ========================================== 407// */ 408 409// if (arrow) { 410// arrow.addEventListener("mouseenter", function (e) { 411// if (!e.isTrusted) return; 412// title.dispatchEvent(new MouseEvent("mouseenter", { bubbles: false, cancelable: true, view: window })); 413// }); 414 415// arrow.addEventListener("mouseleave", function (e) { 416// if (!e.isTrusted) return; 417// title.dispatchEvent(new MouseEvent("mouseleave", { bubbles: false, cancelable: true, view: window })); 418// }); 419// } 420 421// }); 422// } 423// function initializeAll() { 424// document.querySelectorAll(MENU_SELECTOR) 425// .forEach(function (link) { 426// setupMenuLink(link); 427// }); 428// document.querySelectorAll(CTA_TEXT_SELECTOR) 429// .forEach(function (buttonText) { 430// setupCTA(buttonText); 431// }); 432// setupThinkingArrowSync(); 433// } 434// initializeAll(); 435// const observer = new MutationObserver(function (mutations) { 436// let newContent = false;
437// mutations.forEach(function (mutation) { 438// if ( 439// mutation.addedNodes && 440// mutation.addedNodes.length 441// ) { 442// newContent = true; 443// } 444// }); 445// if (newContent) { 446// requestAnimationFrame(function () { 447// initializeAll(); 448// }); 449// } 450// }); 451// observer.observe(document.body, { 452// childList: true, 453// subtree: true 454// }); 455// }); 456/* Menu Animation */ 457document.addEventListener("DOMContentLoaded", function () { 458 if (typeof gsap === "undefined") { 459 console.warn("GSAP is not available."); 460 return; 461 } 462 const ACTIVE_COLOR = "#00bfcc"; 463 const MENU_SELECTOR = 464 "#primary-menu a, " + 465 "#menu-secondary_menu a, " + 466 ".thinking-item > .title, .revenue-agency-sec .service-tags p "; 467 const CTA_TEXT_SELECTOR = 468 ".animated-buttons-wrapper .btn-text"; 469 470 // [perf] Everything this script cares about, used to filter DOM mutations 471 const WATCH_SELECTOR = 472 MENU_SELECTOR + ", " + CTA_TEXT_SELECTOR + ", .thinking-item"; 473 474 // [perf] Initial styles written directly as inline styles. 475 // Same result as the previous gsap.set() calls (inline styles, same 476 // specificity), but plain style writes never force the browser to 477 // recalculate styles. gsap.set() reads computed styles for every 478 // property, which forced a style recalculation for every single link. 479 const WRAPPER_CSS = 480 "position:relative;display:inline-block;overflow:hidden;vertical-align:top;"; 481 const NORMAL_CSS = 482 "display:block;"; 483 const HOVER_CSS = 484 "position:absolute;left:0;top:100%;display:block;color:" + ACTIVE_COLOR + 485 ";white-space:nowrap;"; 486 487 function setupMenuLink(link) { 488 if (!link) { 489 return; 490 } 491 if (link.dataset.gsapReady === "true") { 492 return; 493 } 494 if (link.closest(".cta-btn, .animated-buttons-wrapper")) { 495 return; 496 } 497 if (link.querySelector(":scope > .gsap-menu-text")) { 498 link.dataset.gsapReady = "true"; 499 return; 500 } 501 const originalText = link.textContent 502 .replace(/\s+/g, " ") 503 .trim(); 504 if (!originalText) { 505 return; 506 } 507 link.dataset.gsapReady = "true"; 508 const walker = document.createTreeWalker( 509 link, 510 NodeFilter.SHOW_TEXT 511 ); 512 const textNodes = []; 513 while (walker.nextNode()) { 514 textNodes.push(walker.currentNode); 515 } 516 textNodes.forEach(function (node) { 517 node.remove(); 518 }); 519 const wrapper = document.createElement("span"); 520 wrapper.className = "gsap-menu-text"; 521 wrapper.style.cssText = WRAPPER_CSS; // [perf] was gsap.set 522 const normal = document.createElement("span"); 523 normal.className = "gsap-menu-text-normal"; 524 normal.style.cssText = NORMAL_CSS; // [perf] was gsap.set 525 normal.textContent = originalText; 526 const hover = document.createElement("span"); 527 hover.className = "gsap-menu-text-hover"; 528 hover.style.cssText = HOVER_CSS; // [perf] was gsap.set 529 hover.textContent = originalText; 530 wrapper.appendChild(normal); 531 wrapper.appendChild(hover); 532 link.insertBefore(wrapper, link.firstChild); 533 534 /* == HOVER IN == */ 535 link.addEventListener("mouseenter", function () { 536 gsap.killTweensOf([normal, hover]); 537 gsap.to(normal, { 538 yPercent: -100, 539 duration: 0.45, 540 ease: "power3.out", 541 overwrite: true 542 }); 543 gsap.to(hover, { 544 yPercent: -100, 545 duration: 0.45, 546 ease: "power3.out", 547 overwrite: true 548 }); 549 }); 550 /* == HOVER OUT === */ 551 link.addEventListener("mouseleave", function () { 552 gsap.killTweensOf([normal, hover]); 553 gsap.to(normal, { 554 yPercent: 0, 555 duration: 0.4, 556 ease: "power3.inOut", 557 overwrite: true 558 }); 559 gsap.to(hover, { 560 yPercent: 0, 561 duration: 0.4, 562 ease: "power3.inOut", 563 overwrite: true 564 }); 565 }); 566 } 567 568 /* === CTA TEXT ANIMATION === */ 569 function setupCTA(buttonText) { 570 if (!buttonText) { 571 return; 572 } 573 if (buttonText.dataset.gsapCTAReady === "true") { 574 return; 575 } 576 const originalText = buttonText.textContent 577 .replace(/\s+/g, " ") 578 .trim(); 579 if (!originalText) { 580 return; 581 } 582 buttonText.dataset.gsapCTAReady = "true"; 583 const wrapper = document.createElement("span"); 584 wrapper.className = "gsap-btn-text"; 585 wrapper.style.cssText = WRAPPER_CSS; // [perf] was gsap.set 586 const normal = document.createElement("span"); 587 normal.className = "gsap-btn-text-normal"; 588 normal.style.cssText = NORMAL_CSS; // [perf] was gsap.set 589 normal.textContent = originalText; 590 const hover = document.createElement("span"); 591 hover.className = "gsap-btn-text-hover"; 592 hover.style.cssText = HOVER_CSS; // [perf] was gsap.set 593 hover.textContent = originalText; 594 wrapper.appendChild(normal); 595 wrapper.appendChild(hover); 596 buttonText.innerHTML = ""; 597 buttonText.appendChild(wrapper); 598 599 /* === HOVER IN === */ 600 buttonText.addEventListener("mouseenter", function () { 601 gsap.killTweensOf([normal, hover]); 602 gsap.to(normal, { 603 yPercent: -100, 604 duration: 0.45, 605 ease: "power3.out", 606 overwrite: true 607 }); 608 gsap.to(hover, { 609 yPercent: -100, 610 duration: 0.45, 611 ease: "power3.out", 612 overwrite: true 613 }); 614 }); 615 /* === HOVER OUT === */ 616 buttonText.addEventListener("mouseleave", function () { 617 gsap.killTweensOf([normal, hover]); 618 gsap.to(normal, { 619 yPercent: 0, 620 duration: 0.4, 621 ease: "power3.inOut", 622 overwrite: true 623 }); 624 gsap.to(hover, { 625 yPercent: 0, 626 duration: 0.4, 627 ease: "power3.inOut", 628 overwrite: true 629 }); 630 }); 631 } 632 633 /* == THINKING TITLE â CTA ARROW / BUTTON SYNC == (unchanged) */ 634 function setupThinkingArrowSync() { 635 document.querySelectorAll(".thinking-item").forEach(function (article) { 636 637 const title = article.querySelector(".title"); 638 639 if (!title || title.dataset.arrowSyncReady === "true") { 640 return; 641 } 642 643 const arrow = article.querySelector( 644 ".right .ub-demo-swatch .ub-icon-btn" 645 ); 646 647 const button = article.querySelector( 648 ".animated-buttons-wrapper .cta-btn" 649 ); 650 651 if (!arrow && !button) { 652 return; 653 } 654 655 title.dataset.arrowSyncReady = "true"; 656
657 /* TITLE â ARROW / BUTTON */ 658 title.addEventListener("mouseenter", function () { 659 if (button) { 660 button.dispatchEvent( 661 new MouseEvent("mouseenter", { bubbles: false, cancelable: true, view: window }) 662 ); 663 } 664 if (arrow) { 665 arrow.dispatchEvent( 666 new MouseEvent("mouseenter", { bubbles: false, cancelable: true, view: window }) 667 ); 668 } 669 }); 670 671 title.addEventListener("mouseleave", function () { 672 if (button) { 673 button.dispatchEvent( 674 new MouseEvent("mouseleave", { bubbles: false, cancelable: true, view: window }) 675 ); 676 } 677 if (arrow) { 678 arrow.dispatchEvent( 679 new MouseEvent("mouseleave", { bubbles: false, cancelable: true, view: window }) 680 ); 681 } 682 }); 683 684 /* ARROW â TITLE */ 685 if (arrow) { 686 arrow.addEventListener("mouseenter", function (e) { 687 if (!e.isTrusted) return; 688 title.dispatchEvent(new MouseEvent("mouseenter", { bubbles: false, cancelable: true, view: window })); 689 }); 690 691 arrow.addEventListener("mouseleave", function (e) { 692 if (!e.isTrusted) return; 693 title.dispatchEvent(new MouseEvent("mouseleave", { bubbles: false, cancelable: true, view: window })); 694 }); 695 } 696 }); 697 } 698 699 function initializeAll() { 700 document.querySelectorAll(MENU_SELECTOR) 701 .forEach(function (link) { 702 setupMenuLink(link); 703 }); 704 document.querySelectorAll(CTA_TEXT_SELECTOR) 705 .forEach(function (buttonText) { 706 setupCTA(buttonText); 707 }); 708 setupThinkingArrowSync(); 709 } 710 711 /* ========================================================== 712 [perf] MutationObserver: only react to RELEVANT changes 713 Before: ANY element added ANYWHERE on the page (sliders, 714 GSAP pin-spacers, GTM / Facebook / reCAPTCHA iframes, and 715 this script's own wrappers) re-scanned the whole document, 716 sometimes several times per frame. 717 Now: re-scan only when added content contains menu links, 718 CTA text or thinking items, and at most once per frame. 719 ========================================================== */ 720 function isOwnWrapper(node) { 721 return node.nodeType === 1 && 722 (node.classList.contains("gsap-menu-text") || 723 node.classList.contains("gsap-btn-text")); 724 } 725 726 function isRelevant(mutation) { 727 const added = mutation.addedNodes; 728 if (!added || !added.length) return false; 729 730 let hasForeignNode = false; 731 732 for (let i = 0; i < added.length; i++) { 733 const node = added[i]; 734 if (isOwnWrapper(node)) continue; // ignore our own inserts 735 hasForeignNode = true; 736 if (node.nodeType === 1 && 737 (node.matches(WATCH_SELECTOR) || node.querySelector(WATCH_SELECTOR))) { 738 return true; // new link / CTA / thinking item 739 } 740 } 741 742 // Something (e.g. text) was added INSIDE an element we care about 743 const parent = mutation.target; 744 return hasForeignNode && 745 parent.nodeType === 1 && 746 !!parent.closest(WATCH_SELECTOR); 747 } 748 749 let scanScheduled = false; 750 751 const observer = new MutationObserver(function (mutations) { 752 if (scanScheduled) return; // a scan is already queued 753 if (!mutations.some(isRelevant)) return; // nothing relevant changed 754 scanScheduled = true; 755 requestAnimationFrame(function () { 756 scanScheduled = false; 757 initializeAll(); 758 }); 759 }); 760 761 /* [perf] Run setup when the browser is idle instead of inside the 762 DOMContentLoaded task, so it doesn't join other startup scripts 763 in one long blocking task. Hover effects are ready within 764 ~1â2 seconds at most, before anyone can realistically hover. */ 765 function whenIdle(fn) { 766 if ("requestIdleCallback" in window) { 767 window.requestIdleCallback(fn, { timeout: 2000 }); 768 } else { 769 setTimeout(fn, 200); 770 } 771 } 772 773 whenIdle(function () { 774 initializeAll(); 775 observer.observe(document.body, { 776 childList: true, 777 subtree: true 778 }); 779 }); 780}); 781/* Menu Animation */
782/* Menu Animation */ 783 784// contact form 785document.addEventListener("DOMContentLoaded", function () { 786 const fields = document.querySelectorAll( 787 ".contact-form-wrap input, .contact-form-wrap textarea" 788 ); 789 fields.forEach(function (field) { 790 const fieldSection = field.closest(".floating-relative"); 791 const label = fieldSection 792 ? fieldSection.querySelector(".floating-placeholder") 793 : null; 794 function checkField() { 795 const isActive = 796 document.activeElement === field || 797 field.value.trim() !== ""; 798 if (label) { 799 label.classList.toggle("is-floating", isActive); 800 } 801 if (fieldSection) { 802 fieldSection.classList.toggle("field-active", isActive); 803 } 804 } 805 field.addEventListener("focus", checkField); 806 field.addEventListener("blur", checkField); 807 field.addEventListener("input", checkField); 808 checkField(); 809 }); 810}); 811// Home page horizontal scroll image courousal 812document.addEventListener('DOMContentLoaded', function () { 813 new Swiper('.my-gallery-swiper', { 814 slidesPerView: 1, 815 spaceBetween: 0, 816 loop: true, 817 818 autoplay: { 819 delay: 3000, 820 disableOnInteraction: false 821 }, 822 823 pagination: { 824 el: '.gallery-pagination .swiper-pagination', 825 clickable: true 826 } 827 828 }); 829}); 830 831// Home page bottom sec anime 832document.addEventListener("DOMContentLoaded", () => { 833 hasElement = document.querySelector('.brand-text'); 834 if(!hasElement) return; 835 gsap.registerPlugin(TextPlugin); 836 gsap.to(".brand-text", { 837 text: "Brand", 838 duration: 2, ease: "none" 839 }); 840 841 gsap.from(".demand-text", { 842 clipPath: "inset(0 100% 0 0)", 843 duration: 1.2, ease: "power3.inOut" 844 }); 845 846}) 847// Home page bottom sec anime
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.