1// for Assoc Link Swiper 2function assocLinkSwiper() { 3 const swiper = new Swiper(".swiper", { 4 slidesPerView: 1, 5 direction: "horizontal", 6 spaceBetween: 40, 7 pagination: { 8 el: ".swiper-pagination", 9 clickable: true, 10 }, 11 enabled: true, 12 breakpoints: { 13 768: { 14 enabled: false, 15 }, 16 }, 17 }); 18 19 function resetSwiperOnResize() { 20 swiper.update(); 21 const activeIndex = swiper.activeIndex; 22 if (activeIndex !== 0) { 23 swiper.slideTo(0); 24 } 25 } 26 27 window.addEventListener("resize", resetSwiperOnResize); 28} 29document.addEventListener("DOMContentLoaded", function () { 30 if (typeof Swiper !== "undefined") { 31 assocLinkSwiper(); 32 } else { 33 console.error("Swiper library is not loaded."); 34 } 35}); 36 37function checkUserAgent() { 38 // if($('.app-store-link').length > 0) { 39 if (/Android/i.test(navigator.userAgent)) { 40 $("body").attr("userAgent", "android"); 41 } else { 42 if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) { 43 $("body").attr("userAgent", "ios"); 44 } else { 45 $("body").attr("userAgent", "desktop"); 46 } 47 } 48 // } 49} 50function openChatBot() { 51 $(".chatbot").on("click", function (e) { 52 e.preventDefault(); 53 $keyreply.dispatch("OPEN_CHAT_WINDOW"); 54 $keyreply.dispatch("START"); 55 }); 56} 57function inpageNav() { 58 var navBar = $("#myNavbar"); 59 if (navBar.length > 0) { 60 $(window).on("orientationchange", function () { 61 window.location.reload(); 62 }); 63 } 64 if (navBar.find(".nav-item").length < 5) { 65 navBar.addClass("centered"); 66 } 67 var megaMenu = $(".navbar.navbar-expand-lg"); 68 navBar.find(".nav.nav-pills .nav-item .nav-link").each(function () { 69 var itemId = $(this).attr("href"); 70 if ($(itemId).length < 1) { 71 $(this).closest(".nav-item").remove(); 72 } 73 }); 74 if (megaMenu.length > 0) { 75 var lastScrollTop = 0; 76 $(window).on("scroll", function () { 77 var st = $(this).scrollTop(); 78 if (st < 20) { 79 megaMenu.removeAttr("data-scrolling"); 80 megaMenu.removeClass("otw-scrolling"); 81 } else { 82 if (st > lastScrollTop) { 83 // downscroll code 84 megaMenu.addClass("otw-scrolling"); 85 megaMenu.attr("data-scrolling", false); 86 // $('.navbar-toggler[aria-expanded="true"]').trigger('click'); 87 } else { 88 // upscroll code 89 megaMenu.addClass("otw-scrolling"); 90 megaMenu.attr("data-scrolling", true); 91 } 92 } 93 lastScrollTop = st; 94 }); 95 } 96 let flowing = false; 97 if (navBar.length > 0) { 98 navBar.find(".nav-link").on("click", function (e) { 99 e.preventDefault(); 100 if (flowing) return; 101 flowing = true; 102 navBar.find(".nav.nav-pills .nav-link.active").removeClass("active"); 103 $(this).addClass("active"); 104 var activeItemLeft = $(this).position().left; 105 var activeItemWidth = $(this).innerWidth(); 106 $(".tab-bar-anim").css({ 107 width: activeItemWidth, 108 left: activeItemLeft, 109 }); 110 111 const section = $(this)[0].getAttribute("href"); 112 document.querySelector(section).scrollIntoView({ behavior: "instant" }); 113 114 setTimeout(() => { 115 flowing = false; 116 }, 500); 117 }); 118 var hash = window.location.hash; 119 if (hash && window.performance.navigation.type == 1) { 120 var activePageSection = navBar.find( 121 '.nav-link[href="' + window.location.hash + '"]' 122 ); 123 124 if (activePageSection.length > 0) { 125 var activeItemLeft = activePageSection.position().left; 126 var activeItemWidth = activePageSection.innerWidth(); 127 128 $(".tab-bar-anim").css({ 129 width: activeItemWidth, 130 left: activeItemLeft, 131 }); 132 } 133 } 134 var firstSectionPos = $(".page-section:first-child")?.offset()?.top - 64; 135 136 $(window).on("scroll", function (e) { 137 e.preventDefault(); 138 if ( 139 $(window).scrollTop() > firstSectionPos && 140 $(window).scrollTop() < $(".footer").offset().top - 150 141 ) { 142 megaMenu.slideUp("fast"); 143 navBar.attr("sticky", true); 144 navBar.slideDown("fast"); 145 if ($(".nav li:not(:last-child)").css("display") !== "none") { 146 if (!flowing) { 147 requestAnimationFrame(() => { 148 var activeItemLeft = navBar 149 .find(".nav-link.active") 150 .position().left; 151 152 console.log("active", activeItemLeft); 153 var activeItemWidth = navBar 154 .find(".nav-link.active") 155 .innerWidth(); 156 $(".tab-bar-anim").css({ 157 width: activeItemWidth, 158 left: activeItemLeft, 159 }); 160 }); 161 } 162 } 163 } else { 164 navBar.attr("sticky", false); 165 navBar.slideUp("fast"); 166 megaMenu.slideDown("fast"); 167 } 168 169 var scrollTop = $(window).scrollTop(), 170 divOffset = navBar.offset().top, 171 dist = divOffset - scrollTop; 172 if (dist > 16) { 173 $("#myNavbar ul li:first-child a").addClass("active"); 174 } 175 }); 176 177 var activeTextFirstTime = navBar 178 .find(".nav.nav-pills .nav-item:first-child span") 179 .text(); 180 navBar.find(".nav.nav-pills").each(function () { 181 $(this).append( 182 $(document.createElement("li")) 183 .addClass("nav-item dropdown nav-list") 184 .attr("id", "myNavbarMob") 185 .html( 186 '<a href="#" class="dropdown-toggle" data-bs-toggle="dropdown">' + 187 activeTextFirstTime + 188 '</a><div class="dropdown-menu"></div>' 189 ) 190 ); 191 $(this) 192 .find(".nav-link") 193 .each(function () { 194 var href = $(this).attr("href"); 195 $(this) 196 .clone() 197 .contents() 198 .wrap('<a href="' + href + "-mob" + '" class="dropdown-item" />') 199 .parent() 200 .appendTo($("#myNavbarMob .dropdown-menu")); 201 202 const navBarMob = $("#myNavbarMob"); 203 if (navBarMob.length > 0) { 204 navBarMob.find("a.dropdown-item").on("click", function () { 205 const newText = $(this).find("span").text(); 206 navBarMob.find(".dropdown-toggle.active").text(newText); 207 }); 208 $(window).on("scroll", function () { 209 const linkitems = navBarMob.find("a.dropdown-item.active"); 210 const newText = $(linkitems).find("span").text(); 211 navBarMob.find(".dropdown-toggle.active").text(newText); 212 }); 213 } 214 }); 215 }); 216 217 if ($(window).width() < 992) { 218 $(".page-section").each(function () { 219 var that = $(this); 220 var sectionId = $(this).attr("id"); 221 $(this).attr("id", sectionId + "-mob"); 222 }); 223 } 224 225 window.addEventListener( 226 "resize", 227 function () { 228 if ($(window).width() < 992) { 229 $(".page-section").each(function () { 230 var sectionId = $(this).attr("id"); 231 var arr = sectionId.split("-"); 232 var myNewArray = arr.filter(function (elem, index, self) { 233 return index === self.indexOf(elem); 234 }); 235 if (myNewArray.indexOf("mob") != -1) { 236 sectionId = myNewArray.join("-"); 237 $(this).attr("id", sectionId); 238 } else { 239 $(this).attr("id", sectionId + "-mob"); 240 } 241 }); 242 } else { 243 $(".page-section").each(function () { 244 var sectionId = $(this).attr("id"); 245 var str = sectionId.split("-mob"); 246 $(this).attr("id", str[0]); 247 }); 248 } 249 }, 250 true 251 ); 252 } 253} 254function highlightText(element, regex) { 255 let text = element.html(); 256 text = text.replace(/(<span class="highlight">|<\/span>)/gim, ""); 257 258 const newText = text 259 .replace("&", "&") 260 .replace(regex, '<span class="highlight">$&</span>'); 261 element.html(newText); 262} 263function alphabetFilter() { 264 if ($("[data-search-unions]").length > 0) { 265 var resultSection = $("[data-search-unions-result]"); 266 var groupLength = resultSection.find(".alphabet-group").length; 267 $("[data-search-unions]").on("keyup search", function () { 268 var value = $(this).val().toLowerCase(); 269 270 resultSection.find(".icon-text").filter(function () { 271 $(this) 272 .closest(".col-lg-4") 273 .toggle($(this).text().toLowerCase().indexOf(value) > -1); 274 275 // highlight text if match 276 if ($(this).text().toLowerCase().indexOf(value) > -1) { 277 const regex = new RegExp(value, "gi"); 278 highlightText($(this).find(".title"), regex); 279 highlightText($(this).find(".editor"), regex); 280 } 281 }); 282 resultSection.find(".alphabet-group").filter(function () { 283 $(this).toggle( 284 $(this).find(".icon-text").text().toLowerCase().indexOf(value) > -1 285 ); 286 }); 287 if (resultSection.find(".alphabet-group:hidden").length === groupLength) { 288 $("[data-no-result]").removeClass("d-none"); 289 } else { 290 $("[data-no-result]").addClass("d-none"); 291 } 292 }); 293 } 294} 295function glossaryFilter() { 296 if ($("[data-search-glossaries]").length > 0) { 297 var resultSection = $("[data-search-glossaries-result]"); 298 var groupLength = resultSection.find(".alphabet-group").length; 299 $("[data-search-glossaries]").on("keyup search", function () { 300 var value = $(this).val().toLowerCase(); 301 resultSection.find("[data-glossary-term]").filter(function () { 302 $(this) 303 .closest(".glossary-term") 304 .toggle($(this).text().toLowerCase().indexOf(value) > -1); 305 306 // highlight text if match 307 if ($(this).text().toLowerCase().indexOf(value) > -1) { 308 const regex = new RegExp(value, "gi"); 309 highlightText($(this), regex); 310 } 311 }); 312 resultSection 313 .find(".alphabet-group, .result-section") 314 .filter(function () { 315 $(this).toggle( 316 $(this) 317 .find("[data-glossary-term]") 318 .text() 319 .toLowerCase() 320 .indexOf(value) > -1 321 ); 322 }); 323 324 if (resultSection.find(".alphabet-group:hidden").length === groupLength) { 325 $("[data-no-result]").removeClass("d-none"); 326 } else { 327 $("[data-no-result]").addClass("d-none"); 328 } 329 }); 330 } 331} 332function videoCarousel() {
333 var videoCarousel = $("[data-video-carousel]"); 334 if (videoCarousel.length > 0) { 335 videoCarousel 336 .find(".slider-for") 337 .slick({ 338 slidesToShow: 1, 339 slidesToScroll: 1, 340 pauseOnHover: false, 341 infinite: true, 342 arrows: false, 343 fade: true, 344 asNavFor: ".slider-nav", 345 }) 346 .on("beforeChange", function (event, slick, currentSlide, nextSlide) { 347 var current = $(slick.$slides[currentSlide]); 348 current.html(current.html()); 349 }); 350 351 videoCarousel.find(".slider-nav").slick({ 352 slidesToShow: 3, 353 slidesToScroll: 1, 354 asNavFor: ".slider-for", 355 dots: false, 356 arrows: false, 357 infinite: true, 358 focusOnSelect: true, 359 mobileFirst: true, 360 centerMode: false, 361 initialSlide: 1, 362 variableWidth: true, 363 responsive: [ 364 { 365 breakpoint: 992, 366 settings: { 367 slidesToShow: 4, 368 slidesToScroll: 1, 369 vertical: true, 370 verticalSwiping: true, 371 variableWidth: false, 372 }, 373 }, 374 ], 375 }); 376 } 377} 378function searchAutoComplete(input) { 379 var options = { 380 url: function (phrase) { 381 let url = input.data("url"); 382 if (input.data("url").indexOf("http") < 0) { 383 url = window.location.origin + url; 384 } 385 url = new URL(url); 386 let params = new URLSearchParams(url.search); 387 params.set("t", input.val()); 388 url.search = params.toString(); 389 return url; 390 }, 391 392 getValue: function (element) { 393 return element.value; 394 }, 395 minCharNumber: 0, 396 ajaxSettings: { 397 dataType: "json", 398 method: "POST", 399 data: { 400 dataType: "json", 401 }, 402 success: function (response) { 403 if ( 404 response.length == 0 && 405 input.val().length > 1 && 406 $("#autocomplete-no-result").length < 1 407 ) { 408 let notFoundDiv = '<p id="autocomplete-no-result"> Not found</p>'; 409 $(".easy-autocomplete-container").append(notFoundDiv); 410 } 411 if (input.val().length == 0 || response.length > 0) { 412 $("#autocomplete-no-result").remove(); 413 } 414 }, 415 }, 416 417 preparePostData: function (data) { 418 data.phrase = input.val(); 419 return data; 420 }, 421 requestDelay: 200, 422 template: { 423 type: "links", 424 fields: { 425 link: "url", 426 }, 427 }, 428 list: { 429 match: { 430 enabled: false, 431 }, 432 }, 433 }; 434 input.easyAutocomplete(options); 435} 436 437function formValidation() { 438 var forms = $(".needs-validation"); 439 440 // Loop over them and prevent submission 441 Array.prototype.slice.call(forms).forEach(function (form) { 442 form.addEventListener( 443 "submit", 444 function (event) { 445 if (!form.checkValidity()) { 446 event.preventDefault(); 447 event.stopPropagation(); 448 } 449 450 form.classList.add("was-validated"); 451 }, 452 false 453 ); 454 }); 455 $(".form-select").selectmenu(); 456 $(".datepicker").datepicker({ 457 dateFormat: "dd/mm/yy", 458 }); 459} 460 461function coveoRendering() { 462 let coveoFlagDesktop = false;
463 let coveoFlagMobile = false; 464 var accessToken = $("body").attr("data-accessToken"); 465 var organizationId = $("body").attr("data-organizationId"); 466 var searchHub = $("body").attr("data-searchHub"); 467 468 if (accessToken && organizationId && searchHub) { 469 // initialize for Search Result page 470 (async () => { 471 await customElements.whenDefined("atomic-search-interface"); 472 let searchInterface = $(".coveo-search-results atomic-search-interface"); 473 if (searchInterface.length > 0) { 474 searchInterface = searchInterface[0]; 475 await searchInterface.initialize({ 476 platformUrl: "https://platform-au.cloud.coveo.com", 477 accessToken: accessToken, 478 organizationId: organizationId, 479 searchHub: searchHub, 480 }); 481 searchInterface.executeFirstSearch(); 482 searchInterface.i18n.addResourceBundle("en", "caption-filetype", { 483 ".html": "html", 484 }); 485 } 486 })(); 487 // initialize for Search Dropdown once click on Search Icon at the first time 488 $(".search-group.dropdown-toggle").on("show.bs.dropdown", function () { 489 if ( 490 (!coveoFlagDesktop && $(window).width() > 991) || 491 (!coveoFlagMobile && $(window).width() <= 991) 492 ) { 493 (async () => { 494 await customElements.whenDefined("atomic-search-interface"); 495 let searchInterface = $(this)
496 .closest(".nav-item") 497 .find("atomic-search-interface"); 498 if (searchInterface.length > 0) { 499 searchInterface = searchInterface[0]; 500 await searchInterface.initialize({ 501 platformUrl: "https://platform-au.cloud.coveo.com", 502 accessToken: accessToken, 503 organizationId: organizationId, 504 searchHub: searchHub, 505 }); 506 searchInterface.executeFirstSearch(); 507 searchInterface.i18n.addResourceBundle("en", "caption-filetype", { 508 ".html": "html", 509 }); 510 } 511 })(); 512 if ($(window).width() > 991) { 513 coveoFlagDesktop = true; 514 } else { 515 coveoFlagMobile = true; 516 } 517 } 518 }); 519 } 520} 521 522function fancyBoxRendering() { 523 if ($(".fancybox").length > 0) { 524 $(".fancybox").fancybox({ 525 beforeShow: function () { 526 this.inner.append( 527 '<span class="image-count">' + 528 (this.index + 1) + 529 " / " + 530 this.group.length 531 ) + "</span>"; 532 }, 533 }); 534 } 535 if ($(".fancybox-media").length > 0) { 536 $(".fancybox-media").fancybox({ 537 openEffect: "none", 538 closeEffect: "none", 539 prevEffect: "none", 540 nextEffect: "none", 541 arrows: false, 542 helpers: { 543 media: {}, 544 buttons: {}, 545 }, 546 beforeClose: function () { 547 var video = this.inner.find("video")[0]; 548 video.pause(); 549 video.currentTime = 0; 550 }, 551 }); 552 } 553} 554 555function closeAnnouncement() { 556 const closeButton = document.getElementById("close-button"); 557 const tab = document.getElementById("announcement-tab"); 558 559 closeButton?.addEventListener("click", () => { 560 tab?.classList?.add("close-announcement"); 561 }); 562} 563 564function compassAnimation() { 565 const contentContainer = document.getElementById("contentContainer"); 566 const blockContainer = document.getElementById("blockContainer"); 567 568 document 569 ?.getElementById("coloured-block-1") 570 ?.querySelector("#top") 571 ?.classList.add(`colour-1`); 572 document 573 ?.getElementById("coloured-block-1") 574 ?.querySelector("#side") 575 ?.setAttribute("fill", `url(#color1`); 576 577 let selectedBlock; 578 let totalBlock = blockContainer?.childElementCount; 579 580 if (blockContainer?.children !== undefined) { 581 Array?.from(blockContainer?.children)?.forEach(function (childDiv, index) { 582 childDiv?.addEventListener("click", function () { 583 selectedBlock = index + 1; 584 585 Array?.from(blockContainer?.children).forEach(function ( 586 otherChildDiv, 587 otherIndex 588 ) { 589 if (otherIndex !== index) { 590 var otherTopElement = otherChildDiv.querySelector("#top"); 591 var sideElement = otherChildDiv.querySelector("#side"); 592 otherTopElement.classList.add("colour-0"); 593 sideElement.setAttribute("fill", `url(#grey)`); 594 } 595 }); 596 597 var topElement = childDiv.querySelector("#top"); 598 var sideElement = childDiv.querySelector("#side"); 599 600 topElement.classList.remove(`colour-0`); 601 topElement.classList.add(`colour-${index + 1}`); 602 sideElement.setAttribute("fill", `url(#color${index + 1})`); 603 604 Array.from(contentContainer?.children).forEach(function ( 605 textDiv, 606 index 607 ) { 608 if (selectedBlock === index + 1) { 609 textDiv.classList.remove("hide-block"); 610 } else { 611 textDiv.classList.add("hide-block"); 612 } 613 }); 614 }); 615 }); 616 } 617 618 window.addEventListener("scroll", () => { 619 const scrollPosition = window.scrollY + 500; 620 621 // Calculate the index based on the scroll position 622 const index = Math.floor(scrollPosition / (window.innerHeight * 2)); 623 // Make sure the index is within the bounds of the texts array 624 if (index >= 0 && index < totalBlock) { 625 // Update the selected block based on the scroll 626 selectedBlock = index + 1; 627
628 Array.from(blockContainer.children).forEach(function (childDiv, index) { 629 var topElement = childDiv.querySelector("#top"); 630 var sideElement = childDiv.querySelector("#side"); 631 632 if (selectedBlock === index + 1) { 633 topElement.classList.remove(`colour-0`); 634 topElement.classList.add(`colour-${selectedBlock}`); 635 sideElement.setAttribute("fill", `url(#color${selectedBlock})`); 636 } else { 637 topElement.classList.add(`colour-0`); 638 sideElement.setAttribute("fill", `url(#grey)`); 639 } 640 }); 641 642 // Handle showing/hiding text content here based on the selected block 643 Array.from(contentContainer.children).forEach(function ( 644 textDiv, 645 textIndex 646 ) { 647 if (selectedBlock === textIndex + 1) { 648 textDiv.classList.remove("hide-block"); 649 } else { 650 textDiv.classList.add("hide-block"); 651 } 652 }); 653 } 654 }); 655} 656 657function tpeQuizLogic() { 658 const question1Input = document.querySelector('[data-sc-field-name="Q1"]'); 659 const question2Input = document.querySelector('[data-sc-field-name="Q2"]'); 660 const question3Input = document.querySelector('[data-sc-field-name="Q3"]'); 661 const question4Input = document.querySelector('[data-sc-field-name="Q4"]'); 662 const question5Input = document.querySelector('[data-sc-field-name="Q5"]'); 663 const question6Input = document.querySelector('[data-sc-field-name="Q6"]'); 664 const question7Input = document.querySelector('[data-sc-field-name="Q7"]'); 665 666 const response = { 667 question1: "", 668 question2: "", 669 question3: "", 670 question4: "", 671 question5: "", 672 question6: "", 673 question7: "", 674 question8: "", 675 questionqna: { name: "", company: "", email: "", contact: "", note: "" }, 676 }; 677 678 const answers = { 679 Items: [], 680 }; 681 682 for (let i = 1; i <= 8; i++) { 683 const questionObj = { 684 Question: `Question ${i}`, 685 Answers: [], 686 }; 687 688 answers.Items.push(questionObj); 689 } 690 691 // CONTROLS FOR QUESTION 1 692 const question1 = document.querySelectorAll(".question-1-option"); 693 let selectedOption = null; 694 question1.forEach((ques) => { 695 ques.addEventListener("click", () => { 696 // Check if there is a previously selected option 697 if (selectedOption) { 698 selectedOption.classList.remove("selected"); 699 } 700 701 ques.classList.add("selected"); 702 selectedOption = ques; 703 704 const optionText = ques.querySelector(".text").textContent.trim(); 705 answers.Items[0].Answers = []; 706 answers.Items[0].Answers.push(optionText); 707 question1Input.nodeValue = optionText; 708 question1Input.value = optionText; 709 710 if (answers.Items[0].Answers.length > 0) { 711 nextButton1.classList.add("activate-button"); 712 nextButton1.disabled = false; 713 } 714 }); 715 }); 716 717 // CONTROLS FOR QUESTION 2 718 const dropdownButton = document.getElementById("dropdown-button"); 719 const dropdownMenu = document.getElementById("dropdown-menu"); 720 const dropdownIcon = document.getElementById("dropdown-icon"); 721 const dropdownOptions = dropdownMenu?.querySelectorAll("li"); 722 723 dropdownButton?.addEventListener("click", () => { 724 if (answers.Items[1].Answers.length > 0) { 725 nextButton2.classList.add("activate-button"); 726 nextButton2.disabled = false; 727 } 728 729 dropdownIcon.classList.toggle("selected-icon"); 730 dropdownMenu.classList.toggle("expanded"); 731 dropdownMenu.classList.toggle("show"); 732 }); 733 734 dropdownOptions?.forEach((option) => { 735 option.addEventListener("click", () => { 736 const iconHTML = dropdownButton.querySelector("i").outerHTML; 737 const anchorElement = option.querySelector("li a"); 738 739 dropdownButton.innerHTML = `${anchorElement.textContent} ${iconHTML}`; 740 741 // const anchorElement = option.querySelector("li a"); 742 // dropdownButton.innerText = anchorElement.textContent; 743 744 dropdownButton.classList.add("selected-option"); 745 dropdownMenu.classList.remove("expanded"); 746 }); 747 });
748 749 // Close the menu when clicking outside 750 document.addEventListener("click", (event) => { 751 if ( 752 !dropdownButton?.contains(event?.target) && 753 !dropdownMenu?.contains(event?.target) 754 ) { 755 if (answers.Items[1].Answers.length > 0) { 756 nextButton2.classList.add("activate-button"); 757 nextButton2.disabled = false; 758 } 759 dropdownMenu?.classList?.remove("show"); 760 } 761 }); 762 763 // Add click event listeners to the menu items 764 const menuItems = dropdownMenu?.querySelectorAll("li"); 765 766 menuItems?.forEach((menuItem) => { 767 menuItem.addEventListener("click", (event) => { 768 // Log the selected option 769 answers.Items[1].Answers = []; 770 answers.Items[1].Answers.push(menuItem.textContent.trim()); 771 question2Input.nodeValue = answers.Items[1].Answers.join("|"); 772 question2Input.value = answers.Items[1].Answers.join("|"); 773 774 nextButton2.classList.add("activate-button"); 775 nextButton2.disabled = false; 776 777 event.stopPropagation(); 778 779 // Close the menu 780 dropdownMenu.classList.remove("show"); 781 // Prevent the click event from propagating further 782 }); 783 }); 784 785 // CONTROLS FOR QUESTION 3 786 const question3 = document.querySelectorAll(".question-3-option"); 787 const greyCircles = document.querySelectorAll(".grey-circle-prio"); 788 const redText = document.querySelectorAll(".red-text"); 789 let selectedCount = 0; 790 let textPriority = ["Highest priority", "Medium priority", "Lowest priority"]; 791 let answer3 = []; 792 793 question3.forEach((ques, index) => { 794 ques.addEventListener("click", () => { 795 console.log(answers?.Items[2]?.Answers); 796 console.log(answers?.Items[2]?.Answers[0]?.length); 797 798 if (answers?.Items[2]?.Answers[0]?.length === 2) { 799 nextButton3.classList.add("activate-button"); 800 nextButton3.disabled = false; 801 } else { 802 nextButton3.classList.remove("activate-button"); 803 nextButton3.disabled = true; 804 } 805 806 ques.classList.toggle("selected"); 807 808 // Toggle the class 'selected-priority' on the corresponding grey-circle element 809 greyCircles[index].classList.toggle("selected-priority"); 810 redText[index].textContent = textPriority[selectedCount]; 811 const isSelected = ques.classList.contains("selected"); 812 813 // If it's selected, add the answer to the array 814 if (isSelected && answers.Items[2].Answers.length !== 3) { 815 answer3.push(ques.querySelector(".text").textContent.trim()); 816 } else { 817 // If it's deselected, remove the answer from the array 818 819 const answerIndex = answer3.indexOf( 820 ques.querySelector(".text").textContent 821 ); 822 823 if (answerIndex !== -1) { 824 answer3.splice(answerIndex, 1); 825 } 826 827 if (answers.Items[2].Answers.length >= 1) { 828 question3.forEach((item, itemIndex) => { 829 if (itemIndex !== index) { 830 item.classList.toggle("selected", false); 831 } 832 }); 833 834 greyCircles.forEach((item, index) => { 835 item.classList.toggle("selected-priority", false); 836 item.textContent = null; 837 }); 838 839 redText.forEach((item, index) => { 840 item.textContent = null; 841 }); 842 843 answer3.length = 0; 844 selectedCount = 1; 845 } 846 } 847 answers.Items[2].Answers = []; 848 answers.Items[2].Answers.push(answer3); 849 const pipeSeparatedString = answer3.join("|"); 850 question3Input.nodeValue = pipeSeparatedString; 851 question3Input.value = pipeSeparatedString; 852 853 // Update the text content of the grey-circle to the order of selection 854 if (ques.classList.contains("selected")) { 855 selectedCount++; 856 greyCircles[index].textContent = selectedCount; 857 } else { 858 selectedCount--; 859 greyCircles[index].textContent = ""; 860 redText[index].textContent = ""; 861 } 862 }); 863 });
864 865 // CONTROLS FOR QUESTION 4 866 const question4 = document.querySelectorAll(".question-4-option"); 867 let answer4 = []; 868 869 question4.forEach((ques, index) => { 870 ques.addEventListener("click", () => { 871 const greyCircle2 = ques.querySelector(".grey-circle"); 872 console.log(ques); 873 const tick = ques.querySelector("#tick"); 874 875 // console.log(tick) 876 877 ques.classList.toggle("selected"); 878 greyCircle2.classList.toggle("selected-red-circle"); 879 tick?.classList.toggle("show-icon"); 880 881 // console.log(tick); 882 883 // Check if the card is selected or not 884 const isSelected = ques.classList.contains("selected"); 885 886 // If it's selected, add the answer to the array 887 if (isSelected) { 888 answer4.push(ques.querySelector(".text").textContent.trim()); 889 } else { 890 // If it's deselected, remove the answer from the array 891 const answerIndex = answer4.indexOf( 892 ques.querySelector(".text").textContent 893 ); 894 if (answerIndex !== -1) { 895 answer4.splice(answerIndex, 1); 896 } 897 } 898 899 answers.Items[3].Answers = []; 900 answers.Items[3].Answers.push(answer4); 901 question4Input.nodeValue = answers.Items[3].Answers.join("|"); 902 question4Input.value = answers.Items[3].Answers.join("|"); 903 console.log(answers); 904 905 if (answers?.Items[3]?.Answers[0]?.length > 0) { 906 nextButton4.classList.add("activate-button"); 907 nextButton4.disabled = false; 908 } else { 909 nextButton4.classList.remove("activate-button"); 910 nextButton4.disabled = true; 911 } 912 }); 913 }); 914 915 // CONTROLS FOR QUESTION 5 916 const question5 = document.querySelectorAll(".question-5-option"); 917 question5.forEach((ques) => { 918 ques.addEventListener("click", () => { 919 // Check if there is a previously selected option 920 if (selectedOption) { 921 selectedOption.classList.remove("selected"); 922 } 923 924 ques.classList.add("selected"); 925 selectedOption = ques; 926 927 const optionText = ques.querySelector(".text").textContent.trim(); 928 answers.Items[4].Answers = []; 929 answers.Items[4].Answers.push(optionText); 930 question5Input.nodeValue = optionText; 931 question5Input.value = optionText; 932 console.log(answers); 933 934 if (answers.Items[4].Answers.length > 0) { 935 nextButton5.classList.add("activate-button"); 936 nextButton5.disabled = false; 937 } 938 }); 939 }); 940 941 // CONTROLS FOR QUESTION 6 942 const question6 = document.querySelectorAll(".question-6-option"); 943 question6.forEach((ques) => { 944 ques.addEventListener("click", () => { 945 // Check if there is a previously selected option 946 if (selectedOption) { 947 selectedOption.classList.remove("selected"); 948 } 949 950 ques.classList.add("selected"); 951 selectedOption = ques; 952 953 const optionText = ques.querySelector(".text").textContent.trim(); 954 answers.Items[5].Answers = []; 955 answers.Items[5].Answers.push(optionText); 956 question6Input.nodeValue = optionText; 957 question6Input.value = optionText; 958 console.log(answers); 959 960 if (answers.Items[5].Answers.length > 0) { 961 nextButton6.classList.add("activate-button"); 962 nextButton6.disabled = false; 963 } 964 }); 965 }); 966 967 // CONTROLS FOR QUESTION 7 968 const question7 = document.querySelectorAll(".question-7-option"); 969 question7.forEach((ques) => { 970 ques.addEventListener("click", () => { 971 // Check if there is a previously selected option 972 if (selectedOption) { 973 selectedOption.classList.remove("selected"); 974 } 975 976 ques.classList.add("selected"); 977 selectedOption = ques;
978 979 const optionText = ques.querySelector(".text").textContent.trim(); 980 answers.Items[6].Answers = []; 981 answers.Items[6].Answers.push(optionText); 982 question7Input.nodeValue = answers.Items[6].Answers.join("|"); 983 question7Input.value = answers.Items[6].Answers.join("|"); 984 console.log(answers); 985 986 if (answers.Items[6].Answers.length > 0) { 987 nextButton7.classList.add("activate-button"); 988 nextButton7.disabled = false; 989 } 990 }); 991 }); 992 993 const questionContainers = [ 994 document.getElementById("question-1"), 995 document.getElementById("question-2"), 996 document.getElementById("question-3"), 997 document.getElementById("question-4"), 998 document.getElementById("question-5"), 999 document.getElementById("question-6"), 1000 document.getElementById("question-7"), 1001 document.getElementById("question-8"), 1002 document.getElementById("progress-bar"), 1003 // Add more question containers here as needed 1004 ]; 1005 1006 // Initialize the current question index 1007 let currentQuestionIndex = 0; 1008 1009 // Function to show the current question and hide the others 1010 function showCurrentQuestion() { 1011 questionContainers.map((container, index) => { 1012 if (index === currentQuestionIndex) { 1013 if (container?.style) { 1014 container.style.display = "flex"; 1015 } 1016 } else { 1017 if (container?.style) { 1018 container.style.display = "none"; 1019 } 1020 } 1021 }); 1022 } 1023 1024 // Overlay 1025 const darkOverlay = document.querySelector(".dark-overlay"); 1026 const whiteOverlay = document.getElementById("white-overlay"); 1027 1028 // Background Images 1029 const firstImage = document.getElementById("first-image"); 1030 const secondImage = document.getElementById("second-image"); 1031 1032 // Quiz 1033 const quizContainer = document.getElementById("all-question"); 1034 1035 // Moving Assets 1036 const plane = document.getElementById("plane"); 1037 const cloudBed = document.getElementById("cloud-bed"); 1038 1039 const cloudOne = document.getElementById("cloud-one"); 1040 const cloudTwo = document.getElementById("cloud-two"); 1041 const cloudThree = document.getElementById("cloud-three"); 1042 1043 const bikerImage = document.getElementById("biker-image"); 1044 const boatImage = document.getElementById("boat-image"); 1045 1046 // Loading bar 1047 const loadingBar = document.getElementById("loading-white-bar"); 1048 const resultLoadingBar = document.getElementById("results-loading"); 1049 1050 if (loadingBar && loadingBar.style) { 1051 loadingBar.style.width = "0%"; 1052 } 1053 1054 // Animate in 1055 setTimeout(() => { 1056 firstImage?.classList.remove("pre-load"); 1057 }, 200); 1058 1059 setTimeout(() => { 1060 secondImage?.classList.remove("pre-load"); 1061 firstImage?.classList.add("move-up-delay"); 1062 }, 1800); 1063 1064 // Start the quiz after 2 seconds 1065 1066 setTimeout(() => { 1067 if (loadingBar && loadingBar.style) { 1068 loadingBar.style.width = "12.5%"; 1069 } 1070 quizContainer?.classList?.replace("hide", "show"); 1071 bikerImage?.classList.replace("hide", "show"); 1072 firstImage?.classList.add("blurred"); 1073 secondImage?.classList.add("blurred"); 1074 bikerImage?.classList.add("blurred"); 1075 }, 4000); 1076 1077 // Initially, show the first question 1078 showCurrentQuestion(); 1079 1080 // Get references to the "Next" and "Back" buttons by their IDs 1081 const nextButton1 = document.getElementById("next-button-1"); 1082 const backButton1 = document.getElementById("back-button-1"); 1083 1084 const nextButton2 = document.getElementById("next-button-2"); 1085 const backButton2 = document.getElementById("back-button-2"); 1086 1087 const nextButton3 = document.getElementById("next-button-3"); 1088 const backButton3 = document.getElementById("back-button-3"); 1089 1090 const nextButton4 = document.getElementById("next-button-4"); 1091 const backButton4 = document.getElementById("back-button-4"); 1092 1093 const nextButton5 = document.getElementById("next-button-5"); 1094 const backButton5 = document.getElementById("back-button-5"); 1095 1096 const nextButton6 = document.getElementById("next-button-6"); 1097 const backButton6 = document.getElementById("back-button-6"); 1098 1099 const nextButton7 = document.getElementById("next-button-7"); 1100 const backButton7 = document.getElementById("back-button-7"); 1101 1102 const nextButton8 = document.querySelector(".TPE-QuizSubmissionButton"); 1103 const skipButton8 = document.querySelector(".TPE-Quiz-Skip-Btn"); 1104 1105 nextButton1?.addEventListener("click", () => { 1106 if (currentQuestionIndex < questionContainers.length - 1) { 1107 currentQuestionIndex++; 1108 showCurrentQuestion(); 1109 loadingBar.style.width = "25%"; 1110 } 1111 });
1112 1113 backButton1?.addEventListener("click", () => { 1114 if (currentQuestionIndex > 0) { 1115 currentQuestionIndex--; 1116 showCurrentQuestion(); 1117 } 1118 }); 1119 1120 nextButton2?.addEventListener("click", () => { 1121 firstImage.classList.remove("move-slow"); 1122 secondImage.classList.remove("move-fast"); 1123 1124 if (currentQuestionIndex < questionContainers.length - 1) { 1125 currentQuestionIndex++; 1126 1127 quizContainer.classList.replace("show", "hide"); 1128 firstImage.classList.remove("blurred"); 1129 secondImage.classList.remove("blurred"); 1130 bikerImage.classList.remove("blurred"); 1131 bikerImage.classList.add("move-down"); 1132 loadingBar.style.width = "25%"; 1133 1134 setTimeout(() => { 1135 firstImage.classList.replace("initial", "move-down"); 1136 secondImage.classList.replace("initial", "move-down"); 1137 1138 showCurrentQuestion(); 1139 setTimeout(() => { 1140 quizContainer.classList.replace("hide", "show"); 1141 boatImage.classList.replace("disappears", "appears"); 1142 firstImage.classList.add("blurred"); 1143 secondImage.classList.add("blurred"); 1144 boatImage.classList.add("blurred"); 1145 1146 loadingBar.style.width = "37.5%"; 1147 }, 2000); 1148 }, 1300); 1149 } 1150 }); 1151 1152 backButton2?.addEventListener("click", () => { 1153 if (currentQuestionIndex > 0) { 1154 currentQuestionIndex--; 1155 showCurrentQuestion(); 1156 loadingBar.style.width = "12.5%"; 1157 } 1158 }); 1159 1160 nextButton3?.addEventListener("click", () => { 1161 loadingBar.style.width = "50%"; 1162 if (currentQuestionIndex < questionContainers.length - 1) { 1163 currentQuestionIndex++; 1164 showCurrentQuestion(); 1165 } 1166 }); 1167 1168 backButton3?.addEventListener("click", () => { 1169 if (currentQuestionIndex > 0) { 1170 currentQuestionIndex--; 1171 } 1172 1173 firstImage.classList.add("move-slow"); 1174 secondImage.classList.add("move-fast"); 1175 quizContainer.classList.replace("show", "hide"); 1176 firstImage.classList.remove("blurred"); 1177 secondImage.classList.remove("blurred"); 1178 boatImage.classList.remove("blurred"); 1179 1180 setTimeout(() => { 1181 firstImage.classList.replace("move-down", "initial"); 1182 secondImage.classList.replace("move-down", "initial"); 1183 boatImage.classList.replace("appears", "disappears"); 1184 1185 showCurrentQuestion(); 1186 setTimeout(() => { 1187 quizContainer.classList.replace("hide", "show"); 1188 firstImage.classList.add("blurred"); 1189 secondImage.classList.add("blurred"); 1190 bikerImage.classList.add("blurred"); 1191 bikerImage.classList.remove("move-down"); 1192 loadingBar.style.width = "25%"; 1193 }, 2000); 1194 }, 1000); 1195 }); 1196 1197 nextButton4?.addEventListener("click", () => { 1198 if (currentQuestionIndex < questionContainers.length - 1) { 1199 currentQuestionIndex++; 1200 } 1201 1202 quizContainer.classList.replace("show", "hide"); 1203 firstImage.classList.remove("blurred"); 1204 1205 cloudOne.classList.remove("disappears"); 1206 cloudOne.classList.remove("disappears-up"); 1207 cloudTwo.classList.remove("disappears"); 1208 cloudTwo.classList.remove("disappears-up"); 1209 cloudThree.classList.remove("disappears"); 1210 cloudThree.classList.remove("disappears-up"); 1211 cloudOne.classList.add("blurred-xl"); 1212 cloudTwo.classList.add("blurred-xs"); 1213 cloudThree.classList.add("blurred"); 1214 1215 boatImage.classList.remove("blurred"); 1216 boatImage.classList.replace("appears", "disappears"); 1217 1218 setTimeout(() => { 1219 firstImage.classList.replace("move-down", "move-down-sky"); 1220 setTimeout(() => { 1221 cloudOne.classList.add("appears"); 1222 }, 100); 1223 1224 setTimeout(() => { 1225 cloudTwo.classList.add("appears"); 1226 }, 300); 1227 1228 setTimeout(() => { 1229 cloudThree.classList.add("appears"); 1230 }, 500); 1231 showCurrentQuestion(); 1232 setTimeout(() => { 1233 quizContainer.classList.replace("hide", "show"); 1234 firstImage.classList.add("blurred"); 1235 loadingBar.style.width = "62.5%"; 1236 }, 2000); 1237 }, 1000); 1238 });
1239 1240 backButton4?.addEventListener("click", () => { 1241 if (currentQuestionIndex > 0) { 1242 currentQuestionIndex--; 1243 showCurrentQuestion(); 1244 loadingBar.style.width = "37.5%"; 1245 } 1246 }); 1247 1248 nextButton5?.addEventListener("click", () => { 1249 if (currentQuestionIndex < questionContainers.length - 1) { 1250 currentQuestionIndex++; 1251 showCurrentQuestion(); 1252 loadingBar.style.width = "75%"; 1253 } 1254 }); 1255 1256 backButton5?.addEventListener("click", () => { 1257 if (currentQuestionIndex > 0) { 1258 currentQuestionIndex--; 1259 } 1260 1261 quizContainer.classList.replace("show", "hide"); 1262 firstImage.classList.remove("blurred"); 1263 1264 setTimeout(() => { 1265 firstImage.classList.replace("move-down-sky", "move-down"); 1266 cloudOne.classList.replace("appears", "disappears-up"); 1267 cloudTwo.classList.replace("appears", "disappears-up"); 1268 cloudThree.classList.replace("appears", "disappears-up"); 1269 1270 showCurrentQuestion(); 1271 setTimeout(() => { 1272 boatImage.classList.replace("disappears", "appears"); 1273 quizContainer.classList.replace("hide", "show"); 1274 firstImage.classList.add("blurred"); 1275 boatImage.classList.add("blurred"); 1276 loadingBar.style.width = "50%"; 1277 }, 2000); 1278 }, 1000); 1279 }); 1280 1281 nextButton6?.addEventListener("click", () => { 1282 if (currentQuestionIndex < questionContainers.length - 1) { 1283 currentQuestionIndex++; 1284 } 1285 1286 quizContainer.classList.replace("show", "hide"); 1287 firstImage.classList.remove("blurred"); 1288 secondImage.classList.remove("blurred"); 1289 cloudBed.classList.remove("disappears"); 1290 plane.classList.remove("disappears"); 1291 1292 plane.classList.add("appears"); 1293 cloudOne.classList.replace("appears", "disappears"); 1294 cloudTwo.classList.replace("appears", "disappears"); 1295 cloudThree.classList.replace("appears", "disappears"); 1296 1297 setTimeout(() => { 1298 firstImage.classList.replace("move-down-sky", "move-down-plane"); 1299 cloudBed.classList.add("appears"); 1300 1301 showCurrentQuestion(); 1302 setTimeout(() => { 1303 quizContainer.classList.replace("hide", "show"); 1304 firstImage.classList.add("blurred"); 1305 secondImage.classList.add("blurred"); 1306 cloudBed.classList.add("blurred"); 1307 plane.classList.add("blurred"); 1308 loadingBar.style.width = "87.5%"; 1309 }, 3000); 1310 }, 1000); 1311 }); 1312 1313 backButton6?.addEventListener("click", () => { 1314 if (currentQuestionIndex > 0) { 1315 currentQuestionIndex--; 1316 showCurrentQuestion(); 1317 loadingBar.style.width = "62.5%"; 1318 } 1319 }); 1320 1321 backButton7?.addEventListener("click", () => { 1322 if (currentQuestionIndex > 0) { 1323 currentQuestionIndex--; 1324 } 1325 1326 quizContainer.classList.replace("show", "hide"); 1327 firstImage.classList.remove("blurred"); 1328 1329 cloudBed.classList.remove("blurred"); 1330 plane.classList.remove("blurred"); 1331 1332 setTimeout(() => { 1333 firstImage.classList.replace("move-down-plane", "move-down-sky"); 1334 1335 setTimeout(() => { 1336 cloudOne.classList.replace("disappears", "appears"); 1337 cloudTwo.classList.replace("disappears", "appears"); 1338 cloudThree.classList.replace("disappears", "appears"); 1339 }, 1000); 1340 1341 cloudBed.classList.replace("appears", "disappears"); 1342 plane.classList.replace("appears", "disappears"); 1343 1344 showCurrentQuestion(); 1345 setTimeout(() => { 1346 quizContainer.classList.replace("hide", "show"); 1347 firstImage.classList.add("blurred"); 1348 1349 cloudOne.classList.add("blurred-xl"); 1350 cloudTwo.classList.add("blurred-xs"); 1351 cloudThree.classList.add("blurred"); 1352 loadingBar.style.width = "75%"; 1353 }, 2000); 1354 }, 1000); 1355 });
1356 1357 nextButton7?.addEventListener("click", () => { 1358 if (currentQuestionIndex < questionContainers.length - 1) { 1359 currentQuestionIndex++; 1360 showCurrentQuestion(); 1361 } 1362 loadingBar.style.width = "100%"; 1363 }); 1364 1365 nextButton8?.addEventListener("click", () => { 1366 let flag = validateForm(); 1367 1368 if (flag) { 1369 if (currentQuestionIndex < questionContainers.length - 1) { 1370 currentQuestionIndex++; 1371 showCurrentQuestion(); 1372 } 1373 1374 setTimeout(() => { 1375 resultLoadingBar.classList.replace( 1376 "loading-bar-white", 1377 "loading-bar-white-3" 1378 ); 1379 }, 0); 1380 } 1381 }); 1382 1383 skipButton8?.addEventListener("click", () => { 1384 if (currentQuestionIndex < questionContainers.length - 1) { 1385 currentQuestionIndex++; 1386 showCurrentQuestion(); 1387 } 1388 1389 setTimeout(() => { 1390 resultLoadingBar.classList.replace( 1391 "loading-bar-white", 1392 "loading-bar-white-3" 1393 ); 1394 }, 0); 1395 }); 1396 1397 function validateForm() { 1398 var name = document?.querySelectorAll('input[data-sc-field-name="name"]')[0] 1399 ?.value; 1400 var company = document?.querySelectorAll( 1401 'input[data-sc-field-name="company"]' 1402 )[0]?.value; 1403 var designation = document?.querySelectorAll( 1404 'input[data-sc-field-name="designation"]' 1405 )[0]?.value; 1406 var email = document?.querySelectorAll( 1407 'input[data-sc-field-name="email"]' 1408 )[0]?.value; 1409 var Checkbox = document 1410 ?.querySelectorAll('input[data-sc-field-name="Checkbox"]')[0] 1411 ?.getAttribute("isCheck"); 1412 var EmailValidationClass = document 1413 ?.querySelectorAll('input[data-sc-field-name="email"]')[0] 1414 ?.getAttribute("class"); 1415 var FocusSelectElement = document?.querySelector( 1416 'select[data-sc-field-name="Focus"]' 1417 )?.value; 1418 1419 if ( 1420 name !== "" && 1421 company !== "" && 1422 designation !== "" && 1423 FocusSelectElement != "default" && 1424 email !== "" && 1425 EmailValidationClass === "qna-input valid" && 1426 Checkbox === "true" 1427 ) { 1428 return true; 1429 } else { 1430 return false; 1431 } 1432 } 1433 const checkElement = document.querySelectorAll( 1434 'input[data-sc-field-name="Checkbox"]' 1435 )[0]; 1436 checkElement?.addEventListener("click", function (event) { 1437 // alert("hi"); 1438 if (checkElement.hasAttribute("isCheck")) { 1439 if (checkElement.getAttribute("isCheck") === "false") { 1440 checkElement.setAttribute("isCheck", "true"); 1441 } else { 1442 checkElement.setAttribute("isCheck", "false"); 1443 } 1444 } else { 1445 checkElement.setAttribute("isCheck", "true"); 1446 } 1447 }); 1448 1449 document.addEventListener("click", function (event) { 1450 let flag = validateForm(); 1451 if (flag) { 1452 nextButton8?.classList.add("activate-button"); 1453 } else { 1454 nextButton8?.classList?.remove("activate-button"); 1455 } 1456 }); 1457 1458 document.addEventListener("keydown", function (event) { 1459 let flag = validateForm(); 1460 if (flag) { 1461 nextButton8?.classList.add("activate-button"); 1462 } else { 1463 nextButton8?.classList.remove("activate-button"); 1464 } 1465 }); 1466 1467 document 1468 ?.getElementsByTagName("form")[0] 1469 ?.addEventListener("keydown", function (event) { 1470 if (event.key === "Enter") { 1471 if (!nextButton8?.classList?.contains("activate-button")) { 1472 event.preventDefault(); // Prevent the Enter key press from submitting the form 1473 } else { 1474 nextButton8.click(); 1475 } 1476 } 1477 }); 1478 1479 const tpeLogo = document.getElementById("tpe-logo"); 1480 1481 // redirect to homepage on logo click 1482 if (tpeLogo) { 1483 tpeLogo?.addEventListener("click", function () { 1484 console.log("testing"); 1485 }); 1486 } 1487} 1488 1489function blockRedirection() { 1490 const elements = document.querySelectorAll(".block-href"); 1491
1492 elements.forEach(function (element) { 1493 element.addEventListener("click", function (event) { 1494 event.preventDefault(); 1495 }); 1496 }); 1497} 1498 1499// For UFSE double filters + query strings 1500// This is specifically for showing the red tick when checking the checkboxes 1501function nestedFilterAction() { 1502 // This is for expanding the filter 1503 const toggleIcons = document.querySelectorAll(".toggle-icon"); 1504 toggleIcons.forEach(function (toggleIcon) { 1505 toggleIcon.addEventListener("click", function () { 1506 const nestedFilters = toggleIcon 1507 .closest(".nested-filter-li") 1508 .querySelector(".nested-filters"); 1509 if (nestedFilters?.style?.maxHeight) { 1510 nestedFilters.style.paddingTop = "0px"; 1511 nestedFilters.style.maxHeight = null; 1512 toggleIcon.classList.remove("ri-subtract-line"); 1513 toggleIcon.classList.add("ri-add-line"); 1514 } else { 1515 nestedFilters.style.paddingTop = "20px"; 1516 nestedFilters.style.maxHeight = "1000px"; 1517 toggleIcon.classList.remove("ri-add-line"); 1518 toggleIcon.classList.add("ri-subtract-line"); 1519 } 1520 }); 1521 }); 1522} 1523 1524// For UFSE file uploads in build your profile form 1525function fileUpload() { 1526 document.addEventListener("DOMContentLoaded", function () { 1527 var fileUploadGroups = document.querySelectorAll(".file-upload-group"); 1528 fileUploadGroups.forEach(function (group) { 1529 var fileInput = group.querySelector(".file-input"); 1530 var uploadFileContainer = group.querySelector(".upload-file-container"); 1531 var allFiles = []; 1532 1533 fileInput.addEventListener("change", function () { 1534 var maxFileCount = parseInt( 1535 this.getAttribute("data-val-filecount-max"), 1536 10 1537 ); 1538 var newFiles = Array.from(this.files); 1539 1540 if (maxFileCount === 1) { 1541 // If max file count is 1, replace the existing file 1542 allFiles = newFiles; 1543 } else { 1544 // Append new files to the existing ones 1545 newFiles.forEach((file) => { 1546 if (!allFiles.some((f) => f.name === file.name)) { 1547 allFiles.push(file); 1548 } 1549 }); 1550 } 1551 1552 resetAndRepopulateInput(fileInput, allFiles); 1553 updateUploadedFilesDisplay(uploadFileContainer, allFiles, fileInput); 1554 }); 1555 }); 1556 1557 // This is to show the uploaded file at the bottom of the file input 1558 function updateUploadedFilesDisplay(container, files, input) { 1559 container.innerHTML = ""; 1560 files.forEach(function (file, index) { 1561 var uploadedFileDiv = document.createElement("div"); 1562 uploadedFileDiv.className = "uploaded-file"; 1563 1564 var textContainerDiv = document.createElement("div"); 1565 textContainerDiv.className = "text-container"; 1566 1567 var icon = document.createElement("i"); 1568 icon.className = "ri-file-text-line icon"; 1569 textContainerDiv.appendChild(icon); 1570 1571 var fileNameParagraph = document.createElement("p"); 1572 fileNameParagraph.textContent = file.name; 1573 textContainerDiv.appendChild(fileNameParagraph); 1574 1575 uploadedFileDiv.appendChild(textContainerDiv); 1576 1577 var removeText = document.createElement("p"); 1578 removeText.className = "remove-text"; 1579 removeText.textContent = "Remove"; 1580 removeText.style.cursor = "pointer"; 1581 if (input.id == 'fxb_6a5405b7-344f-4cca-9aa6-4f6e1b171067_Fields_d0ffac70-d85e-469f-867d-20c899265b87__Files') { 1582 removeText.setAttribute("type", "profile-picture"); 1583 } 1584 removeText.onclick = function () { 1585 files.splice(index, 1); 1586 resetAndRepopulateInput(input, files); 1587 updateUploadedFilesDisplay(container, files, input); 1588 }; 1589 uploadedFileDiv.appendChild(removeText); 1590 1591 container.appendChild(uploadedFileDiv); 1592 }); 1593 1594 // Update the margin based on the number of files 1595 if (files.length > 0) { 1596 container.style.marginBottom = "24px"; 1597 } else { 1598 container.style.marginBottom = "0"; 1599 } 1600 } 1601 1602 // When user click cancel without uploading any files, the exsiting file wont be deleted 1603 function resetAndRepopulateInput(input, files) { 1604 var dataTransfer = new DataTransfer();
1605 files.forEach((file) => dataTransfer.items.add(file)); 1606 input.files = dataTransfer.files; 1607 } 1608 }); 1609} 1610 1611(function ($, window, undefined) { 1612 "use strict"; 1613 1614 $(".slider-button .item").on("click", function (e) { 1615 $(this).siblings().removeClass("active"); 1616 $(this).addClass("active"); 1617 }); 1618 1619 inpageNav(); 1620 checkUserAgent(); 1621 alphabetFilter(); 1622 glossaryFilter(); 1623 videoCarousel(); 1624 openChatBot(); 1625 formValidation(); 1626 fancyBoxRendering(); 1627 coveoRendering(); 1628 closeAnnouncement(); 1629 compassAnimation(); 1630 tpeQuizLogic(); 1631 blockRedirection(); 1632 nestedFilterAction(); 1633 fileUpload(); 1634 1635 if ($("[data-autocomplete]").length > 0) { 1636 searchAutoComplete($("[data-autocomplete]")); 1637 } 1638 1639 if ($(window).width() > 991) { 1640 $(window).on("scroll", function () { 1641 if ( 1642 $(".navbar.navbar-expand-lg .nav-item .dropdown-toggle").hasClass( 1643 "show" 1644 ) 1645 ) { 1646 $( 1647 ".navbar.navbar-expand-lg .nav-item .dropdown-toggle.show" 1648 )[0].click(); 1649 } 1650 }); 1651 } 1652 if ($(window).width() <= 576) { 1653 $(".nav-link.dropdown-toggle").on("click", function () { 1654 var spaceToScroll = 1655 $(this).closest("li").index() * $(this).innerHeight() + 2; 1656 if ($(this).position().top > 16) { 1657 $(".navbar-collapse").animate({ scrollTop: spaceToScroll }, 300); 1658 } 1659 }); 1660 } 1661 if ($(window).width() < 992) { 1662 $(".nav-item > .navbar-toggler").on("click", function () { 1663 if ($(".nav-item > .navbar-toggler").attr("aria-expanded") == "false") { 1664 $(".navbar-expand-lg").attr("showing", false); 1665 $("body").removeClass("nav-opening"); 1666 } else { 1667 $(".navbar-expand-lg").attr("showing", true); 1668 $("body").addClass("nav-opening"); 1669 } 1670 }); 1671 $("#dropdownUserMb").on("click", function () { 1672 $(".navbar-expand-lg").attr("showing", true); 1673 if ( 1674 $(".nav-item > .navbar-toggler[data-bs-toggle]").attr( 1675 "aria-expanded" 1676 ) == "true" 1677 ) { 1678 $("#navbar-content").removeClass("show"); 1679 $(".nav-item > .navbar-toggler[data-bs-toggle]") 1680 .attr("aria-expanded", false) 1681 .addClass("collapsed"); 1682 } 1683 }); 1684 } 1685 // resize screen and change position of hero carousel banner 1686 const carouselIndicatorPos = function (heroBannerCarousel) { 1687 var imageHeight = heroBannerCarousel.find(".image").height() + 24; 1688 var carouselIndicator = heroBannerCarousel.find(".slider-control-bar"); 1689 carouselIndicator.css({ top: imageHeight }); 1690 if ($(window).width() < 992) { 1691 imageHeight = heroBannerCarousel.find(".image").height() + 24; 1692 if ($(window).width() < 577) { 1693 imageHeight = imageHeight - 8; 1694 } 1695 carouselIndicator.css({ top: imageHeight }); 1696 } else { 1697 carouselIndicator.css({ top: "" }); 1698 } 1699 }; 1700 var heroBannerCarousel = $(".hero-banner-carousel"); 1701 if (heroBannerCarousel.length > 0) { 1702 heroBannerCarousel 1703 .find(".carousel-indicators .item:first-child") 1704 .addClass("active"); 1705 } 1706 1707 var newsCarousel = $(".singleCarousel"); 1708 if (newsCarousel.length > 0) { 1709 var totalSlide = newsCarousel.find(".carousel-item").length; 1710 newsCarousel.find(".slider-total").text(totalSlide); 1711 newsCarousel.on("slid.bs.carousel", function () { 1712 var carouselData = $(this).find(".carousel-item.active"); 1713 var currentIndex = carouselData.index(); 1714 console.log(currentIndex); 1715 newsCarousel.find(".slider-index").text(currentIndex + 1); 1716 }); 1717 }
1718 var autoScrollCarousel = $(".auto-scroll-carousel .slider"); 1719 if (autoScrollCarousel.length > 0) { 1720 autoScrollCarousel.slick({ 1721 slidesToShow: 5, 1722 slidesToScroll: 5, 1723 autoplay: true, 1724 autoplaySpeed: 2000, 1725 arrows: true, 1726 infinite: true, 1727 dots: true, 1728 responsive: [ 1729 { 1730 breakpoint: 576, 1731 settings: { 1732 slidesToShow: 3, 1733 slidesToScroll: 3, 1734 }, 1735 }, 1736 ], 1737 }); 1738 } 1739 1740 var enterpriseCarousel = $(".enterprise-carousel .slider"); 1741 if (enterpriseCarousel.length > 0 && $(window).width() > 1141) { 1742 enterpriseCarousel.slick({ 1743 slidesToShow: 3.5, 1744 slidesToScroll: 1, 1745 arrows: true, 1746 variableWidth: true, 1747 dots: false, 1748 infinite: false, 1749 }); 1750 } 1751 1752 var exclusiveDealsCarousel = $(".exclusive-deals-carousel .slider"); 1753 if (exclusiveDealsCarousel.length > 0) { 1754 exclusiveDealsCarousel.slick({ 1755 slidesToShow: 1, 1756 slidesToScroll: 1, 1757 variableWidth: true, 1758 infinite: false, 1759 dots: true, 1760 appendDots: $(".deals-carousel-navigation-container"), 1761 useTransform: false, 1762 responsive: [ 1763 { 1764 breakpoint: 1025, 1765 settings: { 1766 infinite: false, 1767 arrows: false, 1768 dots: true, 1769 autoplay: true, 1770 autoplaySpeed: 3000, 1771 touchThreshold: 1000, 1772 swipeToSlide: false, 1773 cssEase: "linear", 1774 }, 1775 }, 1776 ], 1777 }); 1778 } 1779 1780 var $copyUrl = $(".share-icon.copy-url"); 1781 if ($copyUrl.length > 0) { 1782 var $url = $(location).attr("href"); 1783 var dummy = document.createElement("input"); 1784 $copyUrl.on("click", function () { 1785 document.body.appendChild(dummy); 1786 dummy.value = $url; 1787 dummy.select(); 1788 document.execCommand("copy"); 1789 document.body.removeChild(dummy); 1790 $copyUrl.find(".confirmed-copied").addClass("copied"); 1791 setTimeout(() => { 1792 $copyUrl.find(".confirmed-copied").removeClass("copied"); 1793 }, 1000); 1794 }); 1795 } 1796 1797 $(".invite-link-wrapper .copy-url").on("click", function () { 1798 var $url = $(this).siblings(".invite-link").text(); 1799 var dummy = document.createElement("input"); 1800 document.body.appendChild(dummy); 1801 dummy.value = $url; 1802 dummy.select(); 1803 document.execCommand("copy"); 1804 document.body.removeChild(dummy); 1805 $(this).find(".confirmed-copied").addClass("copied"); 1806 setTimeout(() => { 1807 $(this).find(".confirmed-copied").removeClass("copied"); 1808 }, 1000); 1809 }); 1810 1811 $(".referral-code-wrapper .copy-url").on("click", function () { 1812 var $url = $(this).siblings(".referral-code").text(); 1813 var dummy = document.createElement("input"); 1814 document.body.appendChild(dummy); 1815 dummy.value = $url; 1816 dummy.select(); 1817 document.execCommand("copy"); 1818 document.body.removeChild(dummy); 1819 $(this).find(".confirmed-copied").addClass("copied"); 1820 setTimeout(() => { 1821 $(this).find(".confirmed-copied").removeClass("copied"); 1822 }, 1000); 1823 }); 1824 1825 if ($(".vertical-tabs").length > 0) { 1826 var hash = location.hash.replace(/^#/, ""); 1827 if (hash) { 1828 var triggerEl = document.querySelector("#" + hash + "-tab"); 1829 triggerEl.click(); 1830 } 1831 } 1832 1833 $(function () { 1834 const sharingSection = $("#sharing-section"); 1835 const socialSharing = $("#social-sharing"); 1836 if (socialSharing.length > 0 && sharingSection.length > 0) { 1837 var top = sharingSection.offset().top; 1838 var bottom = sharingSection.innerHeight() + top - 200; 1839 $(window).on("scroll", function () { 1840 if ($(window).scrollTop() > top && $(window).scrollTop() < bottom) { 1841 socialSharing.attr("sticky", true); 1842 } else { 1843 socialSharing.attr("sticky", false); 1844 } 1845 }); 1846 } 1847 });
1848 $(function () { 1849 const eventRegister = $(".event-register"); 1850 if (eventRegister.length > 0) { 1851 var top = eventRegister.offset().top; 1852 var bottom = 1853 eventRegister.closest(".editor-wrapper").next().offset().top + 200; 1854 $(window).on("scroll", function () { 1855 if ($(window).scrollTop() > top && $(window).scrollTop() < bottom) { 1856 eventRegister.attr("sticky", true); 1857 } else { 1858 eventRegister.attr("sticky", false); 1859 } 1860 }); 1861 } 1862 }); 1863 $(function () { 1864 const $carousel = $("#newsCarousel"); 1865 if (!$carousel.length) return; 1866 $carousel.find(".active").attr("data-processing", ""); 1867 $carousel[0].addEventListener("slid.bs.carousel", function () { 1868 $carousel.find("[data-processing]").removeAttr("data-processing"); 1869 $carousel.find(".active").attr("data-processing", ""); 1870 }); 1871 }); 1872 1873 /* ------------------------ Media Carousel Component ------------------------ */ 1874 var mediaCarousel = $(".media-carousel"); 1875 if (mediaCarousel.length > 0) { 1876 var nextContent = mediaCarousel.find(".next-title"); 1877 mediaCarousel.find(".slider-for").slick({ 1878 slidesToShow: 1, 1879 slidesToScroll: 1, 1880 pauseOnHover: false, 1881 autoplay: true, 1882 autoplaySpeed: 10000, 1883 infinite: true, 1884 arrows: true, 1885 fade: true, 1886 asNavFor: ".slider-nav", 1887 mobileFirst: true, 1888 adaptiveHeight: true, 1889 responsive: [ 1890 { 1891 breakpoint: 1024, 1892 settings: { 1893 adaptiveHeight: false, 1894 }, 1895 }, 1896 ], 1897 }); 1898 mediaCarousel.find(".slider-nav").slick({ 1899 slidesToShow: 3, 1900 slidesToScroll: 3, 1901 asNavFor: ".slider-for",
1902 dots: false, 1903 arrows: false, 1904 infinite: true, 1905 focusOnSelect: true, 1906 variableWidth: true, 1907 }); 1908 1909 if (mediaCarousel.find(".slick-initialized").length > 0) { 1910 mediaCarousel 1911 .find(".slider-for .slick-current .progress-bar") 1912 .attr("data-loaded", true); 1913 mediaCarousel 1914 .find(".slider-nav .slick-current") 1915 .attr("data-loaded", true); 1916 $(".slick-current").attr("data-current", true); 1917 } 1918 1919 mediaCarousel.on("afterChange", function (event, slick, currentSlide) { 1920 $(".slick-slide").attr("data-current", false); 1921 $(".slick-current").attr("data-current", true); 1922 mediaCarousel 1923 .find('.slick-current[data-loaded= "true"]') 1924 .attr("data-loaded", false); 1925 const nextSlide = 1926 $(".slick-current").next().length > 0 1927 ? $(".slick-current").next() 1928 : $(".slick-current").siblings().filter("[data-slick-index=0]"); 1929 nextContent.text(nextSlide.find(".card-title").text()); 1930 }); 1931 } 1932 /* ------------------------ Start Top Stories Component ------------------------ */ 1933 var topStories = $(".top-stories-carousel"); 1934 if (topStories.length > 0) { 1935 topStories.find(".slider-for").slick({ 1936 slidesToShow: 1, 1937 slidesToScroll: 1, 1938 pauseOnHover: false, 1939 autoplay: true, 1940 autoplaySpeed: 10000, 1941 infinite: true, 1942 arrows: true, 1943 fade: true, 1944 asNavFor: ".slider-nav", 1945 mobileFirst: true, 1946 adaptiveHeight: true, 1947 focusOnSelect: false, 1948 responsive: [ 1949 { 1950 breakpoint: 1024, 1951 settings: { 1952 adaptiveHeight: false, 1953 }, 1954 }, 1955 ], 1956 }); 1957 1958 topStories.find(".slider-nav").slick({ 1959 slidesToShow: 4, 1960 slidesToScroll: 1, 1961 asNavFor: ".slider-for",
1962 dots: false, 1963 arrows: false, 1964 infinite: true, 1965 focusOnSelect: true, 1966 vertical: true, 1967 verticalSwiping: true, 1968 draggable: false, 1969 responsive: [ 1970 { 1971 breakpoint: 991, 1972 settings: { 1973 vertical: false, 1974 verticalSwiping: false, 1975 slidesToShow: 4, 1976 slidesToScroll: 1, 1977 }, 1978 }, 1979 { 1980 breakpoint: 768, 1981 settings: { 1982 vertical: false, 1983 verticalSwiping: false, 1984 slidesToShow: 2, 1985 slidesToScroll: 1, 1986 }, 1987 }, 1988 ], 1989 }); 1990 1991 // Init 1992 if (topStories.find(".slick-initialized").length > 0) { 1993 topStories 1994 .find(".slider-for .slick-current .progress-bar") 1995 .attr("data-loaded", true); 1996 topStories.find(".slider-nav .slick-current").attr("data-loaded", true); 1997 $(".slick-current").attr("data-current", true); 1998 updateNavSlides(0); 1999 $(".slider-for").slick("slickPause"); 2000 $(".slider-for").slick("slickSetOption", "autoplaySpeed", 10000); 2001 $(".slider-for").slick("slickPlay"); 2002 // Reset progress bar transition duration to default before setting to 10s 2003 $(".progress-bar").css("transition-duration", ""); 2004 $(".progress-bar").css("transition-duration", "10s"); 2005 } 2006 2007 topStories.on("afterChange", function (event, slick, currentSlide) { 2008 $(".slick-slide").attr("data-current", false); 2009 $(".slick-current").attr("data-current", true); 2010 topStories 2011 .find('.slick-current[data-loaded= "true"]') 2012 .attr("data-loaded", false); 2013 }); 2014 2015 function updateNavSlides(currentSlide) { 2016 const navSlider = topStories.find(".slider-nav"); 2017 const allSlides = navSlider.find(".slick-slide:not(.slick-cloned)"); 2018 const totalSlides = allSlides.length; 2019 2020 // Hide all slides first 2021 allSlides.hide(); 2022 2023 // Show current slide 2024 allSlides.filter(`[data-slick-index="${currentSlide + 1}"]`).show(); 2025 2026 // Show previous 3 slides 2027 for (let i = 1; i <= 3; i++) { 2028 const prevIndex = (currentSlide - i + totalSlides) % totalSlides; 2029 allSlides.filter(`[data-slick-index="${prevIndex + 1}"]`).show(); 2030 } 2031 2032 // Show next 3 slides 2033 for (let i = 1; i <= 3; i++) { 2034 const nextIndex = (currentSlide + i) % totalSlides; 2035 allSlides.filter(`[data-slick-index="${nextIndex + 1}"]`).show(); 2036 } 2037 2038 // Refresh slick to recalculate 2039 navSlider.slick("setPosition"); 2040 } 2041 2042 // Update on slide change 2043 topStories 2044 .find(".slider-for") 2045 .on("afterChange", function (event, slick, currentSlide) { 2046 updateNavSlides(currentSlide); 2047 // Reset autoplay speed and progress bar duration 2048 $(".slider-for").slick("slickPause"); 2049 $(".slider-for").slick("slickSetOption", "autoplaySpeed", 10000); 2050 $(".slider-for").slick("slickPlay"); 2051 // Reset progress bar transition duration to default before setting to 10s 2052 $(".progress-bar").css("transition-duration", ""); 2053 $(".progress-bar").css("transition-duration", "10s"); 2054 }); 2055 } 2056 2057 /* ------------------------ End Top Stories Component ------------------------ */ 2058 2059 var helpCenterTopic = $(".faq-cmp"); 2060 if (helpCenterTopic.length > 0) { 2061 var hash = window.location.hash; 2062 if (hash) { 2063 // $('html, body').animate({ 2064 // scrollTop: $($('[data-bs-target="'+hash+'"]')).offset().top - 64 2065 // }, 300, function(){ 2066 // $('[data-bs-target="'+hash+'"]').click(); 2067 // }); 2068 $('[data-bs-target="' + hash + '"]').click(); 2069 } 2070 } 2071 2072 if ($(".event-form-cancel-button").length > 0) { 2073 $(".event-form-cancel-button").on("click", function (e) { 2074 var flag = false; 2075 var eventForm = $(this).closest("form"); 2076 eventForm.find("input:not([type=hidden])").each(function () { 2077 if ($(this).val().length > 0) { 2078 flag = true; 2079 } 2080 }); 2081 eventForm.find("select").each(function () { 2082 if ($(this).val()) { 2083 flag = true; 2084 } 2085 }); 2086 if (flag) { 2087 e.preventDefault(); 2088 $("#confirmationModal").modal("show"); 2089 $(".discard-btn").on("click", function (e) { 2090 if (history.length > 1) { 2091 e.preventDefault(); 2092 history.back(1); 2093 } 2094 }); 2095 } else { 2096 // performance.navigation.type = 1 : refresh page 2097 // performance.navigation.type = 0 : from any page 2098 if (history.length > 1 && performance.navigation.type !== 1) { 2099 e.preventDefault(); 2100 history.back(1); 2101 } 2102 } 2103 }); 2104 } 2105 $("#send-sms").on("click", function (e) { 2106 e.preventDefault(); 2107 2108 var phoneNumbers = []; 2109 var modal = $("#referFriendModal"); 2110 $("#referFriendModal .phone-number input").each(function (e) { 2111 if ($(this).val()) { 2112 phoneNumbers.push($(this).val()); 2113 } 2114 }); 2115 if (phoneNumbers.length === 0) {
2116 modal.find(".invalid-feedback").show(); 2117 } else { 2118 modal.find(".invalid-feedback").hide(); 2119 var payloadData = { 2120 smsId: $("#send-sms").data("sms-id"), 2121 phoneNumbers: phoneNumbers, 2122 }; 2123 $.ajax({ 2124 url: "/api/notify/getphonenumbers", 2125 dataType: "json", 2126 type: "post", 2127 contentType: "application/json", 2128 data: JSON.stringify(payloadData), 2129 beforeSend: function () { 2130 modal.find("input").val(""); 2131 modal.modal("hide"); 2132 // show loading status 2133 $("#statusModal").modal("show"); 2134 }, 2135 success: function (data, textStatus, jQxhr) { 2136 var res = data; 2137 if (res) { 2138 modal = $("#statusModal"); 2139 modal.removeClass("loading-modal").addClass("statusModal"); 2140 var modalContent = modal.find(".modal-content"); 2141 modalContent.html(""); 2142 var count = res.Total; 2143 if (res.Status == "200") { 2144 modalContent.append( 2145 '<div class="modal-header"><span type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">Close</span></div><div class="modal-body"><i class="ri-checkbox-circle-fill"></i><h3 class="card-title">Success!</h3><div class="desc">Your referral code has been sent successfully.</div></div>' 2146 ); 2147 } else { 2148 if (res.FailedNumbers.length == count) { 2149 // all sms are failed sending 2150 modalContent.append( 2151 '<div class="modal-header"><span type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">Close</span></div><div class="modal-body"><i class="ri-close-circle-fill"></i><h3 class="card-title">Messages failed to sent!</h3><div class="desc">Sorry, your messages have not been sent. Please refresh your page and try again.</div></div>' 2152 ); 2153 } else { 2154 // some sms failed sending , the other is sent successfully 2155 var failedCount = res.FailedNumbers.length; 2156 var failedNumbers = "+65 " + res.FailedNumbers[0]; 2157 if (res.FailedNumbers.length == 2) { 2158 failedNumbers = 2159 failedNumbers + " and +65 " + res.FailedNumbers[1]; 2160 } 2161 var textFailed = 2162 res.FailedNumbers.length == 1 ? " has " : " have "; 2163 modalContent.append( 2164 '<div class="modal-header"><span type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">Close</span></div><div class="modal-body"><i class="ri-close-circle-fill"></i><h3 class="card-title">' + 2165 failedCount + 2166 " out of " + 2167 count + 2168 ' message failed to sent!</h3><div class="desc">Sorry, your message to ' + 2169 failedNumbers + 2170 textFailed + 2171 "not been sent. Please refresh your page and try again.</div></div>" 2172 ); 2173 } 2174 } 2175 } 2176 }, 2177 error: function (jqXhr, textStatus, errorThrown) { 2178 console.log(errorThrown); 2179 }, 2180 }); 2181 } 2182 }); 2183})(jQuery, window); 2184 2185// All Programme page and Pagination JS END 2186 2187function CopyToClipboard(id) { 2188 var r = document.createRange(); 2189 r.selectNode(document.getElementById(id)); 2190 window.getSelection().removeAllRanges(); 2191 window.getSelection().addRange(r); 2192 document.execCommand("copy"); 2193 window.getSelection().removeAllRanges(); 2194} 2195 2196// Singal News page carousel 2197$(function () { 2198 var $slider = $("#singleNewsCarousel"); 2199 if (!$slider) return; 2200 $slider.carousel(); 2201}); 2202 2203// For UFSE build your profile 2204// Change all to uppercase 2205$(document).ready(function () { 2206 $(".NRIC-Field").on("input", function () { 2207 $(this).val($(this).val().toUpperCase()); 2208 });
2209}); 2210 2211// For UFSE build your profile submit button 2212// Show loading gif and text if there's no error 2213// Hide the sign up rounded tag at the top of the page as well 2214$(".frmbtn").click(function () { 2215 setTimeout(function () { 2216 if ($(".input-validation-error").length === 0) { 2217 $(".txtLoader").removeClass("d-none"); 2218 $(".txtLoadertxt").removeClass("d-none"); 2219 $(".sign-up-tag").addClass("d-none"); 2220 } 2221 }, 1); 2222}); 2223 2224// Function to toggle visibility based on the selected category value 2225function toggleCategoryVisibility(categoryValue, selectElement) { 2226 2227 var selectedOption= selectElement.find('option[selected="selected"]'); 2228 selectElement.find("option").each(function (index, element) { 2229 2230 if (!selectedOption && !element.hasAttribute("data-custom-attribute")) { 2231 selectElement.val(element); 2232 } 2233 2234 var isVisible = 2235 element.getAttribute("data-custom-attribute") === categoryValue; 2236 $(element).toggleClass("d-none", !isVisible); 2237 if (isVisible) { 2238 $(element).attr("hidden"); 2239 } else { 2240 $(element).removeAttr("hidden"); 2241 } 2242 }); 2243} 2244 2245// Function to handle radio button change and toggle visibility 2246function handleRadioButtonChange(radioGroupName, selectElementId) { 2247 $("input[type=radio][data-sc-field-name=" + radioGroupName + "]").change( 2248 function () { 2249 var selectedValue = this.value; 2250 var selectElement = $( 2251 "select[data-sc-field-name=" + selectElementId + "]" 2252 ); 2253 toggleCategoryVisibility(selectedValue, selectElement); 2254 } 2255 ); 2256} 2257 2258// Function to initialize visibility based on default values 2259function initializeVisibility(radioGroupName, selectElementId) { 2260 var selectedValue = $( 2261 "input[type=radio][data-sc-field-name=" + radioGroupName + "]:checked" 2262 ).val(); 2263 var selectElement = $("select[data-sc-field-name=" + selectElementId + "]"); 2264 toggleCategoryVisibility(selectedValue, selectElement); 2265} 2266 2267// Coveo autofocus function 2268function handleAutoFocus() { 2269 const dropdownToggle1 = document.getElementById("search-group-mobile"); // mobile 2270 const dropdownToggle2 = document.getElementById("search-group-desktop"); // desktop 2271 2272 dropdownToggle1?.addEventListener("click", function () { 2273 setTimeout(() => { 2274 const shadowRoot = 2275 document.querySelector("#nav-search-mobile").shadowRoot; 2276 let inputElem = shadowRoot.querySelector("input"); // Access the input element within the shadow DOM 2277 inputElem.focus(); 2278 }, 0); 2279 }); 2280 2281 dropdownToggle2?.addEventListener("click", function () { 2282 setTimeout(() => { 2283 const shadowRoot = document.querySelector( 2284 "#nav-search-desktop" 2285 ).shadowRoot; 2286 let inputElem = shadowRoot.querySelector("input"); // Access the input element within the shadow DOM 2287 inputElem.focus(); 2288 }, 0); 2289 }); 2290} 2291 2292// Handle radio button changes and initialize visibility on document ready 2293$(document).ready(function () { 2294 handleRadioButtonChange("ExpertiseCategory", "Expertise"); 2295 handleRadioButtonChange("CategoryBelong", "AddtionalExpertise"); 2296 initializeVisibility("ExpertiseCategory", "Expertise"); 2297 initializeVisibility("CategoryBelong", "AddtionalExpertise"); 2298 handleAutoFocus(); 2299}); 2300 2301//Career Page 2302 2303(function () { 2304 // Scroll Reveal â auto-runs 2305 document.addEventListener("DOMContentLoaded", function () { 2306 try { 2307 const revealElements = document.querySelectorAll(".reveal-on-scroll"); 2308 2309 const observer = new IntersectionObserver( 2310 (entries) => { 2311 entries.forEach((entry) => { 2312 if (entry.isIntersecting) { 2313 entry.target.classList.add("is-visible"); 2314 observer.unobserve(entry.target); // â Stop observing after reveal 2315 } 2316 }); 2317 }, 2318 { threshold: 0.1 } 2319 ); 2320
2321 revealElements.forEach((el) => observer.observe(el)); 2322 } catch (error) { 2323 console.error("Scroll reveal failed:", error); 2324 } 2325 }); 2326 2327 // Career Swiper â only runs when explicitly called 2328 function initCareerSwiper() { 2329 try { 2330 const swiper = new Swiper(".carousel-swiper", { 2331 loop: true, 2332 autoHeight: true, 2333 slidesPerView: 1, 2334 spaceBetween: 30, 2335 navigation: { 2336 nextEl: ".swiper-button-next", 2337 prevEl: ".swiper-button-prev", 2338 }, 2339 }); 2340 return swiper; 2341 } catch (error) { 2342 console.error("Failed to initialize Career Swiper:", error); 2343 return null; 2344 } 2345 } 2346 2347 // Expose only this function to HTML 2348 window.initCareerSwiper = initCareerSwiper; 2349})(); 2350 2351document.addEventListener("DOMContentLoaded", function () { 2352 const container = document.getElementById("form-main"); 2353 const url = container?.getAttribute("profile-pic"); 2354 2355 if (!url) return; 2356 2357 fetch(url) 2358 .then(r => r.blob()) 2359 .then(b => { 2360 // Extract filename from URL 2361 let filename = url.split('/').pop().split('?')[0]; // handles query params too 2362 if (!filename.includes('.')) { 2363 // fallback to blob type if no extension 2364 const ext = b.type.split('/')[1]; 2365 filename = `profile-picture.${ext}`; 2366 } 2367 2368 const f = new File([b], filename, { type: b.type }); 2369 const dt = new DataTransfer(); 2370 dt.items.add(f); 2371 2372 const input = document.getElementById("fxb_6a5405b7-344f-4cca-9aa6-4f6e1b171067_Fields_d0ffac70-d85e-469f-867d-20c899265b87__Files"); 2373 if (!input) return; 2374 2375 input.files = dt.files; 2376 input.dispatchEvent(new Event('change', { bubbles: true })); 2377 2378 console.log('Done:', f.name, f.type, f.size); 2379 }) 2380 .catch(err => console.error("Image fetch failed:", err)); 2381}); 2382 2383document.addEventListener("DOMContentLoaded", function () { 2384 const input = document.getElementById("fxb_6a5405b7-344f-4cca-9aa6-4f6e1b171067_Fields_d0ffac70-d85e-469f-867d-20c899265b87__Files"); 2385 const container = document.querySelector(".upload-file-container"); 2386 2387 // Handle file selection 2388 input.addEventListener("change", function () { 2389 const file = this.files[0]; 2390 if (!file) return; 2391 2392 if (!file.type.startsWith("image/")) { 2393 alert("Please select an image"); 2394 return; 2395 } 2396 2397 const reader = new FileReader(); 2398 2399 reader.onload = function (e) { 2400 // Remove any previous preview image 2401 const existingPreview = container.nextElementSibling; 2402 if (existingPreview && existingPreview.classList.contains("dynamic-preview")) { 2403 existingPreview.remove(); 2404 } 2405 2406 // Create new image dynamically 2407 const img = document.createElement("img"); 2408 img.src = e.target.result; 2409 img.className = "dynamic-preview"; 2410 img.style.display = "block"; 2411 img.style.width = "100px"; 2412 img.style.marginTop = "10px"; 2413 img.style.paddingBottom = "10px"; 2414 2415 // Insert image right after container 2416 //container.insertAdjacentElement("afterend", img); 2417 }; 2418 2419 reader.readAsDataURL(file); 2420 }); 2421 2422 // Event delegation for Remove button 2423 document.addEventListener("click", function (e) { 2424 if (e.target && e.target.classList.contains("remove-text")) { 2425 const existingPreview = container.nextElementSibling; 2426 if (existingPreview && existingPreview.classList.contains("dynamic-preview") && e.target.hasAttribute("type")) { 2427 //existingPreview.remove(); 2428 input.value = ""; // reset file input 2429 } 2430 } 2431 }); 2432}); 2433 2434document.addEventListener("DOMContentLoaded", function () { 2435 const container = document.getElementById("form-main"); 2436 if (!container) return; 2437 2438 // --- GLOBAL FETCH CACHE (avoid duplicate downloads) --- 2439 const fetchCache = {}; 2440 2441 // --- 1. CONFIGURE ATTRIBUTE TO INPUT MAPPING --- 2442 const fileMappings = [ 2443 { 2444 attribute: "portfoliofiles", 2445 inputId: "fxb_6a5405b7-344f-4cca-9aa6-4f6e1b171067_Fields_a0745062-ad4b-44a3-b066-d80a81b89a94__Files", 2446 isConditional: true 2447 }, 2448 { 2449 attribute: "awardsfiles", 2450 inputId: "fxb_6a5405b7-344f-4cca-9aa6-4f6e1b171067_Fields_690c8ef5-fa7a-4ba3-b50d-ea812697b3a0__Files" 2451 }, 2452 { 2453 attribute: "relevantmediafiles", 2454 inputId: "fxb_6a5405b7-344f-4cca-9aa6-4f6e1b171067_Fields_xxx-relevantmedia" // replace with correct ID 2455 }, 2456 { 2457 attribute: "accreditationsfiles", 2458 inputId: "fxb_6a5405b7-344f-4cca-9aa6-4f6e1b171067_Fields_15055262-cb27-4515-9422-602786e22d38__Files" 2459 } 2460 ]; 2461 2462 // --- SINGLE OBSERVER (performance optimized) --- 2463 const globalFileUrlMap = {}; 2464 const observer = new MutationObserver(() => { 2465 applyLinksToPreview(globalFileUrlMap); 2466 });
2467 observer.observe(container, { childList: true, subtree: true }); 2468 2469 // --- 2. CONDITIONAL LOGIC FOR PORTFOLIOFILES --- 2470 const portfolioMapping = fileMappings.find(f => f.isConditional); 2471 if (portfolioMapping) { 2472 const portfolioInput = document.getElementById(portfolioMapping.inputId); 2473 2474 const accreditations = container.getAttribute("accreditationsfiles"); 2475 const relevantMedia = container.getAttribute("relevantmediafiles"); 2476 const awards = container.getAttribute("awardsfiles"); 2477 2478 let mainFiles = ""; 2479 2480 if ((!accreditations || accreditations.trim() === "") && 2481 (!relevantMedia || relevantMedia.trim() === "") && 2482 (!awards || awards.trim() === "")) { 2483 mainFiles = container.getAttribute("portfoliofiles") || ""; 2484 } else { 2485 mainFiles = relevantMedia || ""; 2486 } 2487 2488 if (portfolioInput && mainFiles) { 2489 processFiles(mainFiles, portfolioInput, globalFileUrlMap, fetchCache); 2490 } 2491 } 2492 2493 // --- 3. PROCESS OTHER ATTRIBUTES ---
2494 fileMappings.forEach(mapping => { 2495 if (mapping.isConditional) return; 2496 2497 const filesString = container.getAttribute(mapping.attribute); 2498 const input = document.getElementById(mapping.inputId); 2499 2500 if (!filesString || !input) return; 2501 2502 processFiles(filesString, input, globalFileUrlMap, fetchCache); 2503 }); 2504}); 2505 2506function processFiles(filesString, input, globalFileUrlMap, fetchCache) { 2507 2508 const files = filesString 2509 .split('|') 2510 .map(item => { 2511 const index = item.indexOf('~'); 2512 if (index === -1) { 2513 console.warn("Invalid file entry:", item); 2514 return null; 2515 } 2516 2517 return [ 2518 item.substring(0, index), 2519 item.substring(index + 1) 2520 ]; 2521 }) 2522 .filter(x => x && x[0] && x[1]); 2523 2524 const dt = new DataTransfer(); 2525 2526 // --- FETCH FILES --- 2527 const fetchPromises = files.map(([url, filename]) => { 2528 2529 // --- FETCH CACHE --- 2530 if (!fetchCache[url]) { 2531 fetchCache[url] = fetch(url) 2532 .then(r => r.blob()) 2533 .catch(err => { 2534 console.warn("Failed to fetch:", url, err); 2535 return null; 2536 }); 2537 } 2538 2539 return fetchCache[url].then(blob => { 2540 if (!blob) return; 2541 2542 // --- fallback filename --- 2543 if (!filename || !filename.includes('.')) { 2544 filename = url.split('/').pop().split('?')[0]; 2545 } 2546 2547 // --- PREVENT DUPLICATE FILENAMES --- 2548 let uniqueName = filename; 2549 let counter = 1; 2550 2551 while (globalFileUrlMap[uniqueName]) { 2552 uniqueName = `${filename} (${counter++})`; 2553 } 2554 2555 globalFileUrlMap[uniqueName] = url; 2556 2557 dt.items.add(new File([blob], uniqueName, { type: blob.type })); 2558 }); 2559 }); 2560 2561 Promise.all(fetchPromises).then(() => { 2562 if (dt.items.length > 0) { 2563 input.files = dt.files; 2564 input.dispatchEvent(new Event('change', { bubbles: true })); 2565 2566 setTimeout(() => applyLinksToPreview(globalFileUrlMap), 300); 2567 } 2568 }); 2569 2570 // --- MANUAL FILE UPLOADS --- 2571 input.addEventListener('change', function () { 2572 Array.from(input.files).forEach(file => { 2573 if (!globalFileUrlMap[file.name]) { 2574 globalFileUrlMap[file.name] = URL.createObjectURL(file); 2575 } 2576 }); 2577 applyLinksToPreview(globalFileUrlMap); 2578 }); 2579} 2580// --- APPLY CLICKABLE LINKS --- 2581function applyLinksToPreview(mapping) { 2582 const fileTexts = document.querySelectorAll(".uploaded-file p"); 2583
2584 fileTexts.forEach(p => { 2585 const fileName = p.textContent.trim(); 2586 const url = mapping[fileName]; 2587 2588 if (url && !p.getAttribute('data-linked')) { 2589 p.style.cursor = "pointer"; 2590 p.style.textDecoration = "underline"; 2591 p.style.color = "#007bff"; 2592 p.setAttribute('data-linked', 'true'); 2593 2594 p.onclick = function (e) { 2595 e.preventDefault(); 2596 e.stopPropagation(); 2597 window.open(url, '_blank'); 2598 }; 2599 } 2600 }); 2601} 2602/* ========================================== 2603 PDF Annotation Link Layer (shared helper) 2604 ========================================== */ 2605function buildAnnotationLayer(page, viewport, slot, insertBefore) { 2606 page.getAnnotations({ intent: 'display' }).then(function (annotations) { 2607 // Remove any previous annotation layer in this slot (re-render on zoom) 2608 var prev = slot.querySelector('.pb-annotation-layer'); 2609 if (prev) prev.remove(); 2610 2611 var linkAnnotations = []; 2612 for (var i = 0; i < annotations.length; i++) { 2613 if (annotations[i].subtype === 'Link' && annotations[i].url) { 2614 linkAnnotations.push(annotations[i]); 2615 } 2616 } 2617 if (linkAnnotations.length === 0) return; 2618 2619 var layer = document.createElement('div'); 2620 layer.className = 'pb-annotation-layer'; 2621 layer.style.width = Math.floor(viewport.width) + 'px'; 2622 layer.style.height = Math.floor(viewport.height) + 'px'; 2623 2624 for (var j = 0; j < linkAnnotations.length; j++) { 2625 var annot = linkAnnotations[j]; 2626 var rect = annot.rect; // [x1, y1, x2, y2] in PDF coordinate space 2627 2628 // Transform PDF rect to viewport coordinates 2629 var topLeft = viewport.convertToViewportPoint(rect[0], rect[3]); 2630 var bottomRight = viewport.convertToViewportPoint(rect[2], rect[1]); 2631 2632 var left = Math.min(topLeft[0], bottomRight[0]); 2633 var top = Math.min(topLeft[1], bottomRight[1]); 2634 var width = Math.abs(bottomRight[0] - topLeft[0]); 2635 var height = Math.abs(bottomRight[1] - topLeft[1]); 2636 2637 var link = document.createElement('a'); 2638 link.href = annot.url; 2639 link.target = '_blank'; 2640 link.rel = 'noopener noreferrer'; 2641 link.className = 'pb-annotation-link'; 2642 link.style.left = left + 'px'; 2643 link.style.top = top + 'px'; 2644 link.style.width = width + 'px'; 2645 link.style.height = height + 'px'; 2646 link.title = annot.url; 2647 2648 layer.appendChild(link); 2649 } 2650 2651 if (insertBefore) { 2652 slot.insertBefore(layer, insertBefore); 2653 } else { 2654 slot.appendChild(layer); 2655 } 2656 }); 2657} 2658 2659/* ========================================== 2660 AI Playbook PDF Viewer 2661 ========================================== */ 2662(function pbInit() { 2663 if (typeof jQuery === 'undefined' || typeof pdfjsLib === 'undefined') { setTimeout(pbInit, 100); return; } 2664 var jQ = jQuery; 2665 var API_BASE = '/api/sitecore/PdfViewer'; 2666 var currentPlaybookId = null; 2667 var currentPlaybookTitle = ''; 2668 2669 // PDF.js setup 2670 pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js'; 2671 var DPR = Math.min(window.devicePixelRatio || 1, 2); 2672 var ZOOM_STEPS = [0.5, 0.67, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2, 2.5, 3]; 2673 var pdfState = { doc: null, scale: 1, currentPage: 1, rendering: false, renderQueued: false, observer: null, rawBuffer: null }; 2674 var formObserver = null; 2675 var formSubmitted = false; 2676 2677 // Reference to the hidden Sitecore form source container 2678 var formSource = document.getElementById('pb-sitecore-form-source'); 2679 2680 // Auto-open form if returning from a reload (form was in success state) 2681 var pendingPlaybook = sessionStorage.getItem('pb-pending-playbook'); 2682 if (pendingPlaybook) { 2683 sessionStorage.removeItem('pb-pending-playbook'); 2684 try { 2685 var pending = JSON.parse(pendingPlaybook);
2686 currentPlaybookId = pending.id; 2687 currentPlaybookTitle = pending.title; 2688 setTimeout(function () { showForm(); }, 500); 2689 } catch (e) { } 2690 } 2691 2692 // --- Card click --- 2693 jQ(document).on('click', '.ai-playbook-card', function (e) { 2694 e.preventDefault(); 2695 var card = jQ(this); 2696 currentPlaybookId = card.data('playbook-id'); 2697 currentPlaybookTitle = card.data('playbook-title') || card.find('.title').text().trim(); 2698 if (!currentPlaybookId) return; 2699 jQ.ajax({ 2700 url: API_BASE + '/CheckSession', 2701 method: 'GET', 2702 data: { playbookId: currentPlaybookId }, 2703 dataType: 'json', 2704 success: function (resp) { 2705 if (resp.alreadySubmitted) { showPdf(currentPlaybookId, currentPlaybookTitle); } 2706 else { showForm(); } 2707 }, 2708 error: function () { showForm(); } 2709 }); 2710 }); 2711 2712 // --- Close overlay --- 2713 jQ(document).on('click', '.playbook-modal__close, .playbook-overlay__backdrop', function () { 2714 jQ('#playbook-overlay').fadeOut(200, function () { 2715 resetViewer(); 2716 returnFormToSource(); 2717 jQ('.playbook-modal').removeClass('playbook-modal--viewer'); 2718 jQ('#playbook-form-panel').show(); 2719 jQ('#playbook-viewer-panel').hide(); 2720 }); 2721 jQ('body').css('overflow', ''); 2722 }); 2723 jQ(document).on('keydown', function (e) { if (e.which === 27 && jQ('#playbook-overlay').is(':visible')) { jQ('.playbook-modal__close').trigger('click'); } }); 2724 2725 // --- Toolbar controls --- 2726 jQ(document).on('click', '#pb-prev', function () { goToPage(pdfState.currentPage - 1); }); 2727 jQ(document).on('click', '#pb-next', function () { goToPage(pdfState.currentPage + 1); }); 2728 jQ(document).on('change', '#pb-page-input', function () { 2729 var n = parseInt(jQ(this).val(), 10); 2730 if (n && n >= 1 && pdfState.doc && n <= pdfState.doc.numPages) { goToPage(n); } 2731 else { jQ(this).val(pdfState.currentPage); } 2732 }); 2733 jQ(document).on('click', '#pb-zoom-out', function () { stepZoom(-1); }); 2734 jQ(document).on('click', '#pb-zoom-in', function () { stepZoom(1); }); 2735 jQ(document).on('click', '#pb-fit', function () { fitToWidth(); }); 2736 2737 // Download â uses in-memory buffer so PDF URL is never exposed 2738 jQ(document).on('click', '#pb-download', function () { 2739 if (!pdfState.rawBuffer) return; 2740 var blob = new Blob([pdfState.rawBuffer], { type: 'application/pdf' }); 2741 var url = URL.createObjectURL(blob); 2742 var a = document.createElement('a'); 2743 a.href = url; 2744 a.download = (currentPlaybookTitle || 'playbook').replace(/[^a-zA-Z0-9 _-]/g, '') + '.pdf'; 2745 document.body.appendChild(a); 2746 a.click(); 2747 document.body.removeChild(a); 2748 setTimeout(function () { URL.revokeObjectURL(url); }, 1000); 2749 }); 2750 2751 // ========================================== 2752 // Sitecore Form â move, observe, reset 2753 // ========================================== 2754 2755 function showForm() { 2756 if (formSubmitted) { 2757 sessionStorage.setItem('pb-pending-playbook', JSON.stringify({ id: currentPlaybookId, title: currentPlaybookTitle })); 2758 window.location.reload(); 2759 return; 2760 } 2761 2762 jQ('.playbook-modal').removeClass('playbook-modal--viewer'); 2763 jQ('#playbook-form-panel').show(); 2764 jQ('#playbook-viewer-panel').hide(); 2765 2766 var formSlot = document.getElementById('pb-form-slot'); 2767 if (formSource) { 2768 var formInner = formSource.querySelector('.pb-sitecore-form-inner'); 2769 if (formInner) { 2770 formSlot.appendChild(formInner); 2771 } 2772 } 2773 2774 // Populate the hidden "ResourceName" field with the block name 2775 var resourceField = formSlot.querySelector('[data-sc-field-name="ResourceName"]'); 2776 if (resourceField) { 2777 resourceField.value = currentPlaybookTitle; 2778 } 2779 2780 jQ('#playbook-overlay').fadeIn(200); 2781 jQ('body').css('overflow', 'hidden'); 2782 2783 startFormObserver(); 2784 } 2785 2786 function returnFormToSource() { 2787 if (formObserver) { formObserver.disconnect(); formObserver = null; } 2788 var formInner = document.querySelector('#pb-form-slot .pb-sitecore-form-inner'); 2789 if (formInner && formSource) { 2790 formSource.appendChild(formInner); 2791 } 2792 } 2793 2794 function startFormObserver() { 2795 if (formObserver) formObserver.disconnect(); 2796 var formSlot = document.getElementById('pb-form-slot'); 2797 if (!formSlot) return; 2798 2799 // Track whether the user has clicked Submit so the observer 2800 // doesn't fire during initial load or unrelated DOM changes. 2801 var submitClicked = false; 2802 2803 var form = formSlot.querySelector('form[data-sc-fxb]'); 2804 if (form) { 2805 jQ(form).on('click', 'input[type="submit"], button[type="submit"]', function () { 2806 submitClicked = true; 2807 }); 2808 } 2809 2810 formObserver = new MutationObserver(function () { 2811 if (!submitClicked) return; 2812 var formSlotEl = document.getElementById('pb-form-slot'); 2813 if (!formSlotEl) return; 2814 2815 // Case 1: Sitecore replaced the form entirely with a success message 2816 // (form element is gone, success h1 or text is present) 2817 var formEl = formSlotEl.querySelector('form[data-sc-fxb]'); 2818 if (!formEl) { 2819 onFormSuccess(); 2820 return; 2821 } 2822 2823 // Case 2: Form re-rendered after successful Submit (no validation errors) 2824 // Sitecore re-renders the form with empty validation spans on success. 2825 var errorSpans = formSlotEl.querySelectorAll('.field-validation-error'); 2826 var hasErrors = false; 2827 for (var i = 0; i < errorSpans.length; i++) { 2828 if (errorSpans[i].textContent.trim()) { 2829 hasErrors = true; 2830 break; 2831 } 2832 } 2833 if (!hasErrors) { 2834 onFormSuccess(); 2835 } else { 2836 // Validation failed â allow re-submission 2837 submitClicked = false; 2838 } 2839 }); 2840 2841 formObserver.observe(formSlot, { childList: true, subtree: true });
2842 } 2843 2844 function onFormSuccess() { 2845 if (formSubmitted) return; 2846 if (formObserver) { formObserver.disconnect(); formObserver = null; } 2847 formSubmitted = true; 2848 2849 jQ.ajax({ 2850 url: API_BASE + '/MarkSession', 2851 method: 'POST', 2852 data: { playbookId: currentPlaybookId }, 2853 dataType: 'json' 2854 }); 2855 2856 showPdf(currentPlaybookId, currentPlaybookTitle); 2857 } 2858 2859 // ========================================== 2860 // PDF Viewer 2861 // ========================================== 2862 2863 function showPdf(playbookId, title) { 2864 jQ('.playbook-modal').addClass('playbook-modal--viewer'); 2865 jQ('#playbook-form-panel').hide(); 2866 jQ('#playbook-viewer-panel').show(); 2867 jQ('#playbook-viewer-title').text(title || 'AI Playbook'); 2868 jQ('#pb-loading').show(); 2869 jQ('#pb-viewer-scroll').hide(); 2870 jQ('#pb-pages').empty(); 2871 jQ('body').css('overflow', 'hidden'); 2872 2873 jQ('#playbook-overlay').fadeIn(200, function () { 2874 var pdfUrl = API_BASE + '/GetPdf?playbookId=' + encodeURIComponent(playbookId); 2875 var xhr = new XMLHttpRequest(); 2876 xhr.open('GET', pdfUrl, true); 2877 xhr.responseType = 'arraybuffer'; 2878 xhr.onload = function () { 2879 if (xhr.status === 200) { 2880 pdfState.rawBuffer = xhr.response.slice(0); 2881 loadPdf(xhr.response); 2882 } else { 2883 jQ('#pb-loading').hide(); 2884 jQ('#pb-viewer-scroll').show(); 2885 jQ('#pb-pages').html('<p style="text-align:center;color:#999;padding:40px;">Failed to load PDF. Please try again.</p>'); 2886 } 2887 }; 2888 xhr.onerror = function () { 2889 jQ('#pb-loading').hide(); 2890 jQ('#pb-viewer-scroll').show(); 2891 jQ('#pb-pages').html('<p style="text-align:center;color:#999;padding:40px;">Failed to load PDF. Please try again.</p>'); 2892 }; 2893 xhr.send(); 2894 }); 2895 } 2896 2897 function loadPdf(arrayBuffer) { 2898 pdfjsLib.getDocument({ data: arrayBuffer }).promise.then(function (doc) { 2899 pdfState.doc = doc; 2900 pdfState.currentPage = 1; 2901 jQ('#pb-page-count').text(doc.numPages); 2902 jQ('#pb-page-input').val(1); 2903 jQ('#pb-loading').hide(); 2904 jQ('#pb-viewer-scroll').show(); 2905 // Desktop: start at 125%; mobile: fit to width 2906 if (window.innerWidth > 640) { setScale(1.25); } else { fitToWidth(); } 2907 }).catch(function (err) { 2908 console.error('[PdfViewer] PDF.js error:', err); 2909 jQ('#pb-loading').hide(); 2910 jQ('#pb-viewer-scroll').show(); 2911 jQ('#pb-pages').html('<p style="text-align:center;color:#999;padding:40px;">Unable to render this PDF.</p>'); 2912 }); 2913 } 2914 2915 function renderAllPages() { 2916 if (!pdfState.doc) return; 2917 if (pdfState.rendering) { pdfState.renderQueued = true; return; } 2918 pdfState.rendering = true; 2919 2920 if (pdfState.observer) pdfState.observer.disconnect(); 2921 if (pdfState.lazyObserver) pdfState.lazyObserver.disconnect(); 2922 var pagesEl = document.getElementById('pb-pages'); 2923 pagesEl.innerHTML = ''; 2924 2925 var totalPages = pdfState.doc.numPages; 2926 pdfState.renderedPages = {}; 2927 2928 var setupDone = 0; 2929 for (var i = 1; i <= totalPages; i++) { 2930 (function (pageNum) { 2931 pdfState.doc.getPage(pageNum).then(function (page) { 2932 var viewport = page.getViewport({ scale: pdfState.scale }); 2933 var slot = document.createElement('div'); 2934 slot.className = 'pb-page-slot'; 2935 slot.setAttribute('data-page', pageNum); 2936 slot.style.width = Math.floor(viewport.width) + 'px'; 2937 slot.style.height = Math.floor(viewport.height) + 'px'; 2938 slot.style.background = '#f5f5f5'; 2939 2940 var tag = document.createElement('span'); 2941 tag.className = 'pb-page-tag'; 2942 tag.textContent = pageNum; 2943 slot.appendChild(tag); 2944 2945 var existing = pagesEl.querySelectorAll('.pb-page-slot'); 2946 var inserted = false; 2947 for (var k = 0; k < existing.length; k++) { 2948 if (parseInt(existing[k].getAttribute('data-page'), 10) > pageNum) { 2949 pagesEl.insertBefore(slot, existing[k]); 2950 inserted = true; 2951 break; 2952 } 2953 } 2954 if (!inserted) pagesEl.appendChild(slot); 2955 2956 setupDone++; 2957 if (setupDone === totalPages) { 2958 startLazyObserver(); 2959 observeCurrentPage(); 2960 pdfState.rendering = false; 2961 if (pdfState.renderQueued) { 2962 pdfState.renderQueued = false; 2963 renderAllPages(); 2964 } 2965 updateNavButtons(); 2966 } 2967 }); 2968 })(i); 2969 } 2970 } 2971 2972 function startLazyObserver() { 2973 var scrollEl = document.getElementById('pb-viewer-scroll'); 2974 pdfState.lazyObserver = new IntersectionObserver(function (entries) { 2975 for (var j = 0; j < entries.length; j++) { 2976 if (entries[j].isIntersecting) { 2977 var slot = entries[j].target; 2978 var pageNum = parseInt(slot.getAttribute('data-page'), 10); 2979 if (!pdfState.renderedPages[pageNum]) { 2980 pdfState.renderedPages[pageNum] = true; 2981 renderPageInSlot(pageNum, slot); 2982 } 2983 } 2984 } 2985 }, { root: scrollEl, rootMargin: '200px 0px' }); 2986 2987 var slots = document.querySelectorAll('#pb-pages .pb-page-slot'); 2988 for (var k = 0; k < slots.length; k++) { 2989 pdfState.lazyObserver.observe(slots[k]); 2990 } 2991 } 2992 2993 function renderPageInSlot(pageNum, slot) { 2994 pdfState.doc.getPage(pageNum).then(function (page) { 2995 var viewport = page.getViewport({ scale: pdfState.scale }); 2996 var canvas = document.createElement('canvas'); 2997 canvas.width = Math.floor(viewport.width * DPR); 2998 canvas.height = Math.floor(viewport.height * DPR); 2999 canvas.style.width = Math.floor(viewport.width) + 'px'; 3000 canvas.style.height = Math.floor(viewport.height) + 'px'; 3001 3002 var tag = slot.querySelector('.pb-page-tag'); 3003 slot.insertBefore(canvas, tag); 3004 slot.style.background = ''; 3005 slot.style.height = ''; 3006 3007 var ctx = canvas.getContext('2d', { willReadFrequently: true });
3008 page.render({ 3009 canvasContext: ctx, 3010 viewport: viewport, 3011 transform: DPR !== 1 ? [DPR, 0, 0, DPR, 0, 0] : null 3012 }); 3013 3014 // Overlay clickable links from PDF annotations 3015 buildAnnotationLayer(page, viewport, slot, tag); 3016 }); 3017 } 3018 3019 function observeCurrentPage() { 3020 var scrollEl = document.getElementById('pb-viewer-scroll'); 3021 pdfState.observer = new IntersectionObserver(function (entries) { 3022 var best = null; 3023 for (var j = 0; j < entries.length; j++) { 3024 if (entries[j].isIntersecting && (!best || entries[j].intersectionRatio > best.intersectionRatio)) { 3025 best = entries[j]; 3026 } 3027 } 3028 if (best) { 3029 var pageNum = parseInt(best.target.getAttribute('data-page'), 10); 3030 pdfState.currentPage = pageNum; 3031 jQ('#pb-page-input').val(pageNum); 3032 updateNavButtons(); 3033 } 3034 }, { root: scrollEl, threshold: [0.25, 0.5, 0.75] }); 3035 3036 var slots = document.querySelectorAll('#pb-pages .pb-page-slot'); 3037 for (var k = 0; k < slots.length; k++) { 3038 pdfState.observer.observe(slots[k]); 3039 } 3040 } 3041 3042 function goToPage(n) { 3043 if (!pdfState.doc) return; 3044 n = Math.max(1, Math.min(pdfState.doc.numPages, n)); 3045 pdfState.currentPage = n; 3046 jQ('#pb-page-input').val(n); 3047 updateNavButtons(); 3048 var slot = document.querySelector('#pb-pages .pb-page-slot[data-page="' + n + '"]'); 3049 if (slot) slot.scrollIntoView({ behavior: 'smooth', block: 'start' }); 3050 } 3051 3052 function updateNavButtons() { 3053 if (!pdfState.doc) return; 3054 jQ('#pb-prev').prop('disabled', pdfState.currentPage <= 1); 3055 jQ('#pb-next').prop('disabled', pdfState.currentPage >= pdfState.doc.numPages); 3056 } 3057 3058 function setScale(s) { 3059 pdfState.scale = Math.max(0.25, Math.min(4, s)); 3060 jQ('#pb-zoom-label').text(Math.round(pdfState.scale * 100) + '%'); 3061 renderAllPages(); 3062 } 3063 3064 function stepZoom(dir) { 3065 var cur = pdfState.scale; 3066 var next; 3067 if (dir > 0) { 3068 next = null; 3069 for (var i = 0; i < ZOOM_STEPS.length; i++) { if (ZOOM_STEPS[i] > cur + 0.001) { next = ZOOM_STEPS[i]; break; } } 3070 if (!next) next = cur * 1.25; 3071 } else { 3072 next = null; 3073 for (var i = ZOOM_STEPS.length - 1; i >= 0; i--) { if (ZOOM_STEPS[i] < cur - 0.001) { next = ZOOM_STEPS[i]; break; } } 3074 if (!next) next = cur / 1.25; 3075 } 3076 setScale(next); 3077 } 3078 3079 function fitToWidth() { 3080 if (!pdfState.doc) return; 3081 pdfState.doc.getPage(pdfState.currentPage || 1).then(function (page) { 3082 var viewport = page.getViewport({ scale: 1 }); 3083 var scrollEl = document.getElementById('pb-viewer-scroll'); 3084 var available = scrollEl.clientWidth - 64; 3085 var newScale = Math.max(0.25, Math.min(4, available / viewport.width)); 3086 pdfState.scale = newScale; 3087 jQ('#pb-zoom-label').text(Math.round(newScale * 100) + '%'); 3088 renderAllPages(); 3089 }); 3090 } 3091 3092 function resetViewer() { 3093 if (pdfState.observer) pdfState.observer.disconnect(); 3094 if (pdfState.lazyObserver) pdfState.lazyObserver.disconnect(); 3095 pdfState.doc = null; 3096 pdfState.rawBuffer = null; 3097 pdfState.scale = 1; 3098 pdfState.currentPage = 1; 3099 pdfState.rendering = false; 3100 pdfState.renderQueued = false; 3101 pdfState.renderedPages = {}; 3102 jQ('#pb-pages').empty(); 3103 jQ('#pb-page-input').val(1); 3104 jQ('#pb-page-count').text('0'); 3105 jQ('#pb-zoom-label').text('100%'); 3106 } 3107})(); 3108 3109/* ========================================== 3110 Teaser PDF Viewer â Membership-Gated 3111 ========================================== */ 3112(function tpInit() { 3113 if (typeof jQuery === 'undefined' || typeof pdfjsLib === 'undefined') { setTimeout(tpInit, 100); return; } 3114 var jQ = jQuery; 3115 var API_BASE = '/api/sitecore/PdfViewer'; 3116 var FREE_PAGES = 2; 3117 3118 pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js'; 3119 var DPR = Math.min(window.devicePixelRatio || 1, 2); 3120 var ZOOM_STEPS = [0.5, 0.67, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2, 2.5, 3]; 3121 var tpState = { doc: null, scale: 1, currentPage: 1, rendering: false, renderQueued: false, observer: null, lazyObserver: null, renderedPages: {}, accessLevel: 'anonymous', loginUrl: '' }; 3122 3123 jQ(document).on('click', '.teaser-pdf-card', function (e) { 3124 e.preventDefault(); 3125 var card = jQ(this); 3126 var pdfId = card.data('pdf-id'); 3127 var pdfTitle = card.data('pdf-title') || card.find('.title').text().trim(); 3128 tpState.accessLevel = card.data('access-level') || 'anonymous'; 3129 tpState.loginUrl = card.data('login-url') || '/api/sitecore/LinkPassAPI/Login'; 3130 if (!pdfId) return; 3131 showTeaserPdf(pdfId, pdfTitle); 3132 });
3133 3134 jQ(document).on('click', '#teaser-pdf-overlay .playbook-modal__close, #teaser-pdf-overlay .playbook-overlay__backdrop', function () { 3135 jQ('#teaser-pdf-overlay').fadeOut(200, function () { resetTeaserViewer(); }); 3136 jQ('body').css('overflow', ''); 3137 }); 3138 jQ(document).on('keydown', function (e) { if (e.which === 27 && jQ('#teaser-pdf-overlay').is(':visible')) { jQ('#teaser-pdf-overlay .playbook-modal__close').first().trigger('click'); } }); 3139 3140 jQ(document).on('click', '#tp-prev', function () { tpGoToPage(tpState.currentPage - 1); }); 3141 jQ(document).on('click', '#tp-next', function () { tpGoToPage(tpState.currentPage + 1); }); 3142 jQ(document).on('change', '#tp-page-input', function () { 3143 var n = parseInt(jQ(this).val(), 10); 3144 var maxPage = getMaxVisiblePage(); 3145 if (n && n >= 1 && n <= maxPage) { tpGoToPage(n); } 3146 else { jQ(this).val(tpState.currentPage); } 3147 }); 3148 jQ(document).on('click', '#tp-zoom-out', function () { tpStepZoom(-1); }); 3149 jQ(document).on('click', '#tp-zoom-in', function () { tpStepZoom(1); }); 3150 jQ(document).on('click', '#tp-fit', function () { tpFitToWidth(); }); 3151 3152 function showTeaserPdf(pdfId, title) { 3153 resetTeaserViewer(); 3154 jQ('#teaser-viewer-title').text(title || 'Document'); 3155 jQ('#tp-loading').show(); 3156 jQ('#tp-viewer-scroll').hide(); 3157 jQ('body').css('overflow', 'hidden'); 3158 3159 // Start XHR only after modal is fully visible â ensures clientWidth is accurate for fitToWidth 3160 jQ('#teaser-pdf-overlay').fadeIn(200, function () { 3161 var pdfUrl = API_BASE + '/GetPdf?playbookId=' + encodeURIComponent(pdfId); 3162 var xhr = new XMLHttpRequest(); 3163 xhr.open('GET', pdfUrl, true); 3164 xhr.responseType = 'arraybuffer'; 3165 xhr.onload = function () { 3166 if (xhr.status === 200) { loadTeaserPdf(xhr.response); } 3167 else { 3168 jQ('#tp-loading').hide(); 3169 jQ('#tp-viewer-scroll').show(); 3170 jQ('#tp-pages').html('<p style="text-align:center;color:#999;padding:40px;">Failed to load PDF.</p>'); 3171 } 3172 }; 3173 xhr.onerror = function () { 3174 jQ('#tp-loading').hide(); 3175 jQ('#tp-viewer-scroll').show(); 3176 jQ('#tp-pages').html('<p style="text-align:center;color:#999;padding:40px;">Failed to load PDF.</p>'); 3177 }; 3178 xhr.send(); 3179 }); 3180 } 3181 3182 function loadTeaserPdf(arrayBuffer) { 3183 pdfjsLib.getDocument({ data: arrayBuffer }).promise.then(function (doc) { 3184 tpState.doc = doc; 3185 tpState.currentPage = 1; 3186 var displayCount = tpState.accessLevel === 'member' ? doc.numPages : Math.min(doc.numPages, FREE_PAGES + 1); 3187 jQ('#tp-page-count').text(displayCount); 3188 jQ('#tp-page-input').val(1); 3189 jQ('#tp-loading').hide(); 3190 jQ('#tp-viewer-scroll').show(); 3191 // Desktop: start at 125%; mobile: fit to width 3192 if (window.innerWidth > 640) { tpSetScale(1.25); } else { tpFitToWidth(); } 3193 }).catch(function (err) { 3194 console.error('[TeaserPdf] PDF.js error:', err); 3195 jQ('#tp-loading').hide(); 3196 jQ('#tp-viewer-scroll').show(); 3197 jQ('#tp-pages').html('<p style="text-align:center;color:#999;padding:40px;">Unable to render this PDF.</p>'); 3198 }); 3199 } 3200 3201 function tpRenderAllPages() { 3202 if (!tpState.doc) return; 3203 if (tpState.rendering) { tpState.renderQueued = true; return; } 3204 tpState.rendering = true; 3205 3206 if (tpState.observer) tpState.observer.disconnect(); 3207 if (tpState.lazyObserver) tpState.lazyObserver.disconnect(); 3208 var pagesEl = document.getElementById('tp-pages'); 3209 pagesEl.innerHTML = ''; 3210 tpState.renderedPages = {}; 3211 3212 var totalPages = tpState.doc.numPages; 3213 var isMember = tpState.accessLevel === 'member'; 3214 var pagesToCreate = isMember ? totalPages : Math.min(totalPages, FREE_PAGES + 1); 3215 var setupDone = 0; 3216 3217 for (var i = 1; i <= pagesToCreate; i++) { 3218 (function (pageNum) { 3219 tpState.doc.getPage(pageNum).then(function (page) { 3220 var viewport = page.getViewport({ scale: tpState.scale }); 3221 var slot = document.createElement('div'); 3222 slot.className = 'pb-page-slot'; 3223 slot.setAttribute('data-page', pageNum); 3224 slot.style.width = Math.floor(viewport.width) + 'px'; 3225 slot.style.height = Math.floor(viewport.height) + 'px'; 3226 slot.style.background = '#f5f5f5'; 3227 3228 if (!isMember && pageNum > FREE_PAGES) { 3229 slot.classList.add('tp-blurred'); 3230 var blurOverlay = document.createElement('div'); 3231 blurOverlay.className = 'tp-blur-overlay'; 3232 slot.appendChild(blurOverlay); 3233 } 3234 3235 var tag = document.createElement('span'); 3236 tag.className = 'pb-page-tag'; 3237 tag.textContent = pageNum; 3238 slot.appendChild(tag); 3239 3240 var existing = pagesEl.querySelectorAll('.pb-page-slot'); 3241 var inserted = false; 3242 for (var k = 0; k < existing.length; k++) { 3243 if (parseInt(existing[k].getAttribute('data-page'), 10) > pageNum) { 3244 pagesEl.insertBefore(slot, existing[k]); 3245 inserted = true; 3246 break; 3247 } 3248 } 3249 if (!inserted) pagesEl.appendChild(slot); 3250 3251 setupDone++; 3252 if (setupDone === pagesToCreate) { 3253 // Inject gate card after page 3 slot for non-members 3254 if (!isMember) { 3255 var gateSlot = pagesEl.querySelector('.pb-page-slot[data-page="' + (FREE_PAGES + 1) + '"]'); 3256 if (gateSlot) { 3257 var gateCard = document.createElement('div'); 3258 gateCard.id = 'tp-gate-card'; 3259 gateCard.className = 'tp-gate-card'; 3260 gateCard.innerHTML = 3261 '<div class="tp-gate-icon">🔒</div>' + 3262 '<h3 class="tp-gate-title">Available to NTUC members only</h3>' + 3263 '<p class="tp-gate-desc">If you are a registered member, log in to continue.</p>' + 3264 '<a id="tp-login-btn" href="' + tpState.loginUrl + '" class="tp-gate-btn">Log in or join as a member</a>'; 3265 gateSlot.parentNode.insertBefore(gateCard, gateSlot); 3266 } 3267 } 3268 tpStartLazyObserver(); 3269 tpObserveCurrentPage(); 3270 tpState.rendering = false; 3271 if (tpState.renderQueued) { 3272 tpState.renderQueued = false; 3273 tpRenderAllPages(); 3274 } 3275 tpUpdateNavButtons(); 3276 } 3277 }); 3278 })(i); 3279 } 3280 } 3281 3282 function tpStartLazyObserver() { 3283 var scrollEl = document.getElementById('tp-viewer-scroll'); 3284 tpState.lazyObserver = new IntersectionObserver(function (entries) { 3285 for (var j = 0; j < entries.length; j++) { 3286 if (entries[j].isIntersecting) { 3287 var slot = entries[j].target; 3288 var pageNum = parseInt(slot.getAttribute('data-page'), 10); 3289 if (!tpState.renderedPages[pageNum]) { 3290 tpState.renderedPages[pageNum] = true; 3291 tpRenderPageInSlot(pageNum, slot); 3292 } 3293 } 3294 } 3295 }, { root: scrollEl, rootMargin: '200px 0px' }); 3296 3297 var slots = document.querySelectorAll('#tp-pages .pb-page-slot'); 3298 for (var k = 0; k < slots.length; k++) { 3299 tpState.lazyObserver.observe(slots[k]); 3300 } 3301 } 3302 3303 function tpRenderPageInSlot(pageNum, slot) { 3304 tpState.doc.getPage(pageNum).then(function (page) { 3305 var viewport = page.getViewport({ scale: tpState.scale }); 3306 var canvas = document.createElement('canvas'); 3307 canvas.width = Math.floor(viewport.width * DPR); 3308 canvas.height = Math.floor(viewport.height * DPR); 3309 canvas.style.width = Math.floor(viewport.width) + 'px'; 3310 canvas.style.height = Math.floor(viewport.height) + 'px'; 3311 3312 var blurOverlay = slot.querySelector('.tp-blur-overlay'); 3313 if (blurOverlay) { 3314 slot.insertBefore(canvas, blurOverlay); 3315 } else { 3316 var tag = slot.querySelector('.pb-page-tag'); 3317 slot.insertBefore(canvas, tag); 3318 } 3319 slot.style.background = ''; 3320 slot.style.height = ''; 3321 3322 var ctx = canvas.getContext('2d', { willReadFrequently: true });
3323 page.render({ 3324 canvasContext: ctx, 3325 viewport: viewport, 3326 transform: DPR !== 1 ? [DPR, 0, 0, DPR, 0, 0] : null 3327 }); 3328 3329 // Overlay clickable links from PDF annotations 3330 var insertBefore = blurOverlay || slot.querySelector('.pb-page-tag'); 3331 buildAnnotationLayer(page, viewport, slot, insertBefore); 3332 }); 3333 } 3334 3335 function tpObserveCurrentPage() { 3336 var scrollEl = document.getElementById('tp-viewer-scroll'); 3337 tpState.observer = new IntersectionObserver(function (entries) { 3338 var best = null; 3339 for (var j = 0; j < entries.length; j++) { 3340 if (entries[j].isIntersecting && (!best || entries[j].intersectionRatio > best.intersectionRatio)) { 3341 best = entries[j]; 3342 } 3343 } 3344 if (best) { 3345 var pageNum = parseInt(best.target.getAttribute('data-page'), 10); 3346 tpState.currentPage = pageNum; 3347 jQ('#tp-page-input').val(pageNum); 3348 tpUpdateNavButtons(); 3349 } 3350 }, { root: scrollEl, threshold: [0.25, 0.5, 0.75] }); 3351 3352 var slots = document.querySelectorAll('#tp-pages .pb-page-slot'); 3353 for (var k = 0; k < slots.length; k++) { 3354 tpState.observer.observe(slots[k]); 3355 } 3356 } 3357 3358 function getMaxVisiblePage() { 3359 if (!tpState.doc) return 1; 3360 if (tpState.accessLevel === 'member') return tpState.doc.numPages; 3361 return Math.min(tpState.doc.numPages, FREE_PAGES + 1); 3362 } 3363 3364 function tpGoToPage(n) { 3365 if (!tpState.doc) return; 3366 var max = getMaxVisiblePage(); 3367 n = Math.max(1, Math.min(max, n)); 3368 tpState.currentPage = n; 3369 jQ('#tp-page-input').val(n); 3370 tpUpdateNavButtons(); 3371 var slot = document.querySelector('#tp-pages .pb-page-slot[data-page="' + n + '"]'); 3372 if (slot) slot.scrollIntoView({ behavior: 'smooth', block: 'start' }); 3373 } 3374 3375 function tpUpdateNavButtons() { 3376 if (!tpState.doc) return; 3377 var max = getMaxVisiblePage(); 3378 jQ('#tp-prev').prop('disabled', tpState.currentPage <= 1); 3379 jQ('#tp-next').prop('disabled', tpState.currentPage >= max); 3380 } 3381 3382 function tpSetScale(s) { 3383 tpState.scale = Math.max(0.25, Math.min(4, s)); 3384 jQ('#tp-zoom-label').text(Math.round(tpState.scale * 100) + '%'); 3385 tpRenderAllPages(); 3386 } 3387 3388 function tpStepZoom(dir) { 3389 var cur = tpState.scale; 3390 var next; 3391 if (dir > 0) { 3392 next = null; 3393 for (var i = 0; i < ZOOM_STEPS.length; i++) { if (ZOOM_STEPS[i] > cur + 0.001) { next = ZOOM_STEPS[i]; break; } } 3394 if (!next) next = cur * 1.25; 3395 } else { 3396 next = null; 3397 for (var i = ZOOM_STEPS.length - 1; i >= 0; i--) { if (ZOOM_STEPS[i] < cur - 0.001) { next = ZOOM_STEPS[i]; break; } } 3398 if (!next) next = cur / 1.25; 3399 } 3400 tpSetScale(next); 3401 } 3402 3403 function tpFitToWidth() { 3404 if (!tpState.doc) return; 3405 tpState.doc.getPage(tpState.currentPage || 1).then(function (page) { 3406 var viewport = page.getViewport({ scale: 1 }); 3407 var scrollEl = document.getElementById('tp-viewer-scroll'); 3408 var available = scrollEl.clientWidth - 48; 3409 var newScale = Math.max(0.25, Math.min(4, available / viewport.width)); 3410 tpState.scale = newScale; 3411 jQ('#tp-zoom-label').text(Math.round(newScale * 100) + '%'); 3412 tpRenderAllPages(); 3413 }); 3414 } 3415 3416 function resetTeaserViewer() { 3417 if (tpState.observer) tpState.observer.disconnect(); 3418 if (tpState.lazyObserver) tpState.lazyObserver.disconnect(); 3419 tpState.doc = null; 3420 tpState.scale = 1; 3421 tpState.currentPage = 1; 3422 tpState.rendering = false; 3423 tpState.renderQueued = false; 3424 tpState.renderedPages = {}; 3425 jQ('#tp-pages').empty(); // also removes the injected gate card 3426 jQ('#tp-page-input').val(1); 3427 jQ('#tp-page-count').text('0'); 3428 jQ('#tp-zoom-label').text('100%'); 3429 } 3430})();
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.