1document.addEventListener("DOMContentLoaded", function (event) { 2 // Stuff goes here 3 4 //*** HAMBURGER MENU *** 5 6 document.querySelector("#js-nav-menu").addEventListener("click", function (event) { 7 8 const navBody = document.querySelector(".js-nav-body"); 9 navBody.classList.toggle("open"); 10 11 let hamburgerButton = document.querySelector("#js-nav-menu"); 12 // toggle aria-expanded attribute value for accessibility 13 hamburgerButton.setAttribute("aria-expanded", hamburgerButton.getAttribute('aria-expanded') === 'true' ? 'false' : 'true'); 14 15 // for when their is a banner above the nav bar: add class so that mobile nav close button can be correctly positioned 16 let hamburgerButtonWrapper = document.querySelector(".hamburger-button-wrapper"); 17 hamburgerButtonWrapper.classList.toggle("nav-open"); 18 19 20 event.preventDefault(); 21 }); 22 23 // Open collapsed submenu 24 const navButtons = document.querySelectorAll(".nav-button"); 25 const navButtonsArray = [...navButtons]; 26 27 navButtonsArray.forEach(button => button.addEventListener("click", mobileNavigate)); 28 29 function mobileNavigate(e) { 30 // for pages that have submenu 31 if (e.target?.nextElementSibling?.classList.contains("submenu--with-expand") && window.innerWidth < 768) { 32 const openSubMenu = document.querySelector(".submenu--expanded"); 33 // Autocollapse submenus 34 if (openSubMenu) { 35 openSubMenu.classList.remove("submenu--expanded"); 36 openSubMenu.previousElementSibling.firstChild.classList.remove("nav-product-button--tangerine", "nav-company-button--pear", "nav-newsroom-button--capri"); 37 openSubMenu.previousElementSibling.classList.remove("button-submenu--expanded"); 38 } 39 40 const target = e.target.firstChild; 41 if (openSubMenu == e.target.nextElementSibling) return; 42 43 e.target.nextElementSibling.classList.add("submenu--expanded"); 44 e.target.classList.add("button-submenu--expanded"); 45 46 if (target == document.querySelector("#nav-product-button")) { 47 target.classList.add("nav-product-button--tangerine"); 48 } else if (target == document.querySelector("#nav-company-button")) { 49 target.classList.add("nav-company-button--pear"); 50 } else if (target == document.querySelector("#nav-newsroom-button")) { 51 target.classList.add("nav-newsroom-button--capri"); 52 } 53 } 54 } 55 56 // remove link from mobile nav buttons that have submenu 57 function removeLinkOnMobile() { 58 if (window.innerWidth < 768) { 59 document.querySelector("#nav-product-button").style.pointerEvents = "none"; 60 document.querySelector("#nav-company-button").style.pointerEvents = "none"; 61 document.querySelector("#nav-newsroom-button").style.pointerEvents = "none"; 62 63 document.querySelector("#nav-mission-button").parentElement.addEventListener('click', function (e) { 64 window.open(e.currentTarget.querySelector("A").href, "_self") 65 }); 66 67 document.querySelector("#nav-product-button").addEventListener('click', function (e) { 68 e.preventDefault(); 69 }); 70 document.querySelector("#nav-company-button").addEventListener('click', function (e) { 71 e.preventDefault(); 72 73 }); 74 document.querySelector("#nav-newsroom-button").addEventListener('click', function (e) { 75 e.preventDefault(); 76 }); 77 } 78 } 79 80 // check for window being resized 81 window.addEventListener("resize", function () { 82 removeLinkOnMobile(); 83 }); 84 85 // call function 86 removeLinkOnMobile(); 87 88 89 //*** MOUSE HOVERING LINKS *** 90 var items = document.querySelectorAll(".js-nav-body > div > a"); 91 92 for (var i = 0; i < items.length; i++) { 93 94 items[i].addEventListener("mouseover", function (event) { 95 96 //Hides previously open submenus 97 98 var otherSubMenus = document.querySelectorAll(".submenu"); 99 for (var i = 0; i < otherSubMenus.length; i++) { 100 101 if (otherSubMenus != nextSibling) { 102 otherSubMenus[i].classList.remove("submenu--shown") 103 otherSubMenus[i].classList.remove("submenu--visible"); 104 } 105 } 106 107 //Adds .submenu--shown to next sibling with class .submenu., then adds .submenu--visible for animation purposes, then triggers submenu
107container 108 109 var nextSibling = event.target.closest("div").nextElementSibling; 110 var subMenuContainer = document.querySelector('#submenu-container'); 111 112 if (nextSibling != null && nextSibling.classList.contains("submenu")) { 113 nextSibling.classList.add("submenu--shown"); 114 115 // This used to be wrapped in setTimeout, but it triggered some kind of rendering problem in Safari. https://github.com/DATAMlNER/www/issues/38 116 nextSibling.classList.add("submenu--visible"); 117 118 subMenuContainer.classList.remove("submenu-container-closed"); 119 subMenuContainer.classList.add("submenu-container-open"); 120 } else { 121 subMenuContainer.classList.add("submenu-container-closed"); 122 subMenuContainer.classList.remove("submenu-container-open"); 123 } 124 125 //Changing line color of buttons 126 127 // const integrationButton = document.querySelector("#nav-integrations-button"); 128 const missionButton = document.querySelector("#nav-mission-button"); 129 const productButton = document.querySelector("#nav-product-button"); 130 const companyButton = document.querySelector("#nav-company-button"); 131 const contactButton = document.querySelector("#nav-contact-button"); 132 const newsroomButton = document.querySelector("#nav-newsroom-button"); 133 134 if (event.target == missionButton) { 135 document.querySelector("#submenu-container").style.borderBottom = "solid 3px var(--brand-rose-plus-color)"; 136 } 137 138 // if (event.target == integrationButton) { 139 // document.querySelector("#submenu-container").style.borderBottom ="solid 3px var(--brand-rose-plus-color)"; 140 // } 141 142 else if (event.target == productButton) { 143 if (location.pathname == "/product/" || location.pathname == "/product/screening-auto-resolver/") { 144 document.querySelector("#submenu-container").style.borderBottom = "solid 3px var(--brand-tangerine-plus-color)"; 145 146 } else if (location.pathname == "/product/screening/") { 147 document.querySelector("#submenu-container").style.borderBottom = "solid 3px var(--brand-tangerine-plus-color)"; 148 149 } else if (location.pathname == "/product/transaction-monitoring/") { 150 document.querySelector("#submenu-container").style.borderBottom = "solid 3px var(--brand-pear-plus-color)"; 151 152 } else if (location.pathname == "/product/kyc-risk-scoring/") { 153 document.querySelector("#submenu-container").style.borderBottom = "solid 3px var(--brand-capri-plus-color)"; 154 155 } else if (location.pathname == "/product/salv-bridge/" || location.pathname == "/salv-bridge-estonia/") { 156 document.querySelector("#submenu-container").style.borderBottom = "solid 3px var(--brand-rose-plus-color)"; 157 158 } else { 159 document.querySelector("#submenu-container").style.borderBottom = "solid 3px var(--brand-tangerine-plus-color)"; 160 } 161 } else if (event.target == companyButton) { 162 document.querySelector("#submenu-container").style.borderBottom = "solid 3px var(--brand-pear-plus-color)"; 163 } else if (event.target == newsroomButton) { 164 document.querySelector("#submenu-container").style.borderBottom = "solid 3px var(--brand-capri-plus-color)"; 165 } else if (event.target == contactButton) { 166 167 document.querySelector("#submenu-container").style.borderBottom = "solid 3px var(--brand-slate-color)"; 168 } else { 169 document.querySelector("#submenu-container").style.borderBottom = ""; 170 } 171 172 }); 173 } 174 175 //*** PRODUCT SUBNAV HOVER COLOURS *** 176 177 const productSubnav = document.querySelector("#product-subnav"); 178 const productPageLink = document.querySelector(".nav-button--active"); 179 180 if (location.pathname == "/product/" || location.pathname == "/product/screening-auto-resolver/") { 181 productSubnav.classList.add("platform-active"); 182 productPageLink.classList.add("platform-active"); 183 184 } else if (location.pathname == "/product/screening/") { 185 productSubnav.classList.add("screening-active"); 186 productPageLink.classList.add("screening-active"); 187 188 } else if (location.pathname == "/product/transaction-monitoring/") { 189 productSubnav.classList.add("monitoring-active"); 190 productPageLink.classList.add("monitoring-active"); 191 192 } else if (location.pathname == "/product/kyc-risk-scoring/") { 193 productSubnav.classList.add("kyc-active"); 194 productPageLink.classList.add("kyc-active"); 195 196 } else if (location.pathname.includes("/product/salv-bridge/")) { 197 productSubnav.classList.add("bridge-active"); 198 productPageLink.classList.add("bridge-active"); 199 } else if (location.pathname == "/salv-bridge-estonia/") { 200 productSubnav.classList.add("bridge-active"); 201 productPageLink.firstChild.style.color = "var(--brand-rose-color)"; 202 } else { 203 productSubnav.classList.add("tangerine-active"); 204 } 205 206 //*** MOUSE LEAVING NAVBAR *** 207 208 document.querySelector('.nav-wrapper').addEventListener("mouseleave", function (event) { 209
210 // Closes submenu container 211 var subMenuContainer = document.querySelector('#submenu-container'); 212 213 subMenuContainer.classList.add("submenu-container-closed"); 214 subMenuContainer.classList.remove("submenu-container-open"); 215 216 // Checks if any of the submenus should be left open and visible and implements 217 var otherSubMenus = document.querySelectorAll(".submenu"); 218 219 function submenuVisible(i) { 220 221 i.classList.add("submenu--shown"); 222 223 setTimeout(function () { 224 i.classList.add("submenu--visible"); 225 }, 110); 226 } 227 228 for (var i = 0; i < otherSubMenus.length; i++) { 229 230 if (otherSubMenus[i].classList.contains("submenu--active--page")) { 231 232 submenuVisible(otherSubMenus[i]); 233 234 subMenuContainer.classList.remove("submenu-container-closed"); 235 subMenuContainer.classList.add("submenu-container-open"); 236 } else { 237 otherSubMenus[i].classList.remove("submenu--shown"); 238 otherSubMenus[i].classList.remove("submenu--visible"); 239 240 } 241 } 242 // Changes line color back to default 243 document.querySelector("#submenu-container").style.borderBottom = ""; 244 }); 245 246 //*** BOOK A DEMO MODAL *** 247 248 var modal = document.getElementById("demoModal"); 249 250 var btn = document.querySelectorAll(".contactbutton"); 251 252 var closeBtns = document.getElementsByClassName("close") 253 254 // When the user clicks on the button, open the modal 255 for (i = 0; i < btn.length; i++) { 256 btn[i].onclick = function () { 257 modal.style.display = "block"; 258 } 259 } 260 261 // When the user clicks on <span> (x), close the modal 262 Array.from(closeBtns).forEach( 263 closeBtn => { 264 closeBtn.onclick = function () { 265 modal.style.display = "none"; 266 } 267 } 268 ) 269 270 // When the user clicks anywhere outside of the modal, close it 271 window.onclick = function (event) { 272 if (event.target == modal) { 273 modal.style.display = "none"; 274 } 275 } 276 277 278 //*** TOGGLE Q&A ACCORDION *** 279 280 // select all questions 281 const questionContainers = document.querySelectorAll(".js-toggle"); 282 283 // loop throught questions and add event listeners for clicking event 284 // to execute opening and closing individual questions 285 for (let i = 0; i < questionContainers.length; i++) { 286 questionContainers[i].addEventListener("click", openCurrentAccordion); 287 } 288 289 // open clicked question and auto collapse the previous open question 290 function openCurrentAccordion() { 291 for (let i = 0; i < questionContainers.length; i++) { 292 // get qa-box and answer elements 293 const qaBox = questionContainers[i].parentElement.parentElement; 294 const answer = questionContainers[i].parentElement.nextElementSibling; 295 296 // auto collapse previous question, set hight style of open question 297 if (this === questionContainers[i] && !qaBox.classList.contains('open')) { 298 qaBox.classList.add('open'); 299 answer.style.height = 'auto'; 300 301 // set aria-expanded true on opened question 302 questionContainers[i].setAttribute("aria-expanded", "true"); 303 304 const newHeight = answer.clientHeight + 'px'; 305 306 answer.style.height = '0px'; 307 308 setTimeout(function () { 309 answer.style.height = newHeight; 310 }, 0); 311 312 } else { 313 // remove styling from closed question 314 qaBox.classList.remove('open'); 315 answer.style.height = '0px'; 316 // set aria-expanded false on closed questions 317 questionContainers[i].setAttribute("aria-expanded", "false"); 318 } 319 } 320 } 321 322 323 //*** HOME AND PRODUCT PAGE TABS *** 324 325 326 var tabToggle = document.querySelectorAll('.tab-toggle'); 327 328 for (i = 0; i < tabToggle.length; i++) { 329 330 331 tabToggle[i].addEventListener('click', function (event) { 332 333 event.preventDefault(); 334 335 //change button appearance 336 337 for (i = 0; i < tabToggle.length; i++) { 338 tabToggle[i].classList.remove("active"); 339 } 340 this.classList.add("active"); 341 342 //swap content 343 344 var fintechContent = document.querySelectorAll('.fintech'); 345 var enterpriseContent = document.querySelectorAll('.enterprise'); 346 347 for (i = 0; i < fintechContent.length; i++) { 348 349 if (document.getElementById('fintech-tab').classList.contains('active')) { 350 fintechContent[i].style.display = "inherit"; 351 } else { 352 fintechContent[i].style.display = "none"; 353 } 354 355 if (document.getElementById('enterprise-tab').classList.contains('active')) { 356 enterpriseContent[i].style.display = "inherit"; 357 } else { 358 enterpriseContent[i].style.display = "none"; 359 } 360 } 361 }); 362 363 } 364 365 //*** MAILCHIMP FORM - REMOVE INPUT WHEN SUBMITTED *** 366 // const inputWrapper = document.querySelector(".input-wrapper"); 367 // const successMessage = document.querySelector("#mce-success-response"); 368 // const errorMessages = document.querySelectorAll(".response-error"); 369 // const errorIcon = document.querySelector(".input__error-icon"); 370 // const successIcon = document.querySelector(".input__success-icon"); 371 // const signUpForm = document.querySelector("#mc-embedded-subscribe-form"); 372 // const footerSubtitle = document.querySelector(".nav-footer--subtitle"); 373 // const formConsentText = document.querySelector(".nav-footer--newsletter-consent"); 374 375 // // hide all error messages on form submission - so that only one error message is shown at a time (error messages are made visible by mailchimp) 376 // signUpForm.addEventListener("submit", () => { 377 // [...errorMessages].filter(error =>
377 !error.classList.contains('mce_inline_error')).forEach(error => error.style.display = "none"); 378 // }); 379 380 // // Options for the observer (which mutations to observe) 381 // const config = { attributes: true }; 382 383 // // Callback function to execute when mutations are observed 384 // const successCallback = (mutationList, observer) => { 385 // for (const mutation of mutationList) { 386 // // when thereä's an attribute change on the success message 387 // if (mutation.type === "attributes" && mutation.target.style.display !== "none") { 388 // inputWrapper.classList.add("submitted"); 389 // footerSubtitle.classList.add("submitted"); 390 // formConsentText.classList.add("submitted"); 391 // successIcon.classList.add("show"); 392 // errorIcon.classList.remove("show"); 393 // } 394 // observer.disconnect(); 395 // } 396 // }; 397 398 // const errorCallback = (mutationList, observer) => { 399 // for (const mutation of mutationList) { 400 // if (mutation.type === "attributes" && mutation.target.style.display !== "none") { 401 // errorIcon.classList.add("show"); 402 // } 403 // // if all the error messages are not shown, remove the error icon 404 // // only remove the error icon when non of the error messages are shown 405 // else if (mutation.type === "attributes" && [...errorMessages].filter(error => error.style.display === "none").length == errorMessages.length ) { 406 // errorIcon.classList.remove("show"); 407 // } 408 // } 409 // } 410 411 // // Create an observer instance linked to the callback function 412 // const successObserver = new MutationObserver(successCallback); 413 // const errorObserver = new MutationObserver(errorCallback); 414 415 // // Start observing the target node for configured mutations 416 // successObserver.observe(successMessage, config); 417 // errorObserver.observe(errorMessages[0], config); 418 // errorObserver.observe(errorMessages[1], config); 419 420 421 //*** TESTIMONIALS CAROUSEL *** 422 423 let carouselPosition = 0; 424 const testimonials = document.querySelectorAll(".testimonial-item"); 425 const testimonialsContainer = document.querySelector(".testimonials-carousel"); 426 const totalTestimonials = testimonials.length; 427 const previousButton = document.getElementById("testimonials-carousel__button--previous"); 428 const nextButton = document.getElementById("testimonials-carousel__button--next"); 429 const dots = document.querySelectorAll(".testimonials-carousel__dots-wrapper__dot"); 430 const dotsArray = [...dots]; 431 432 // add event listeners to nav buttons 433 previousButton?.addEventListener("click", function () { 434 moveToPreviousTestimonial(); 435 }); 436 437 nextButton?.addEventListener("click", function () { 438 moveToNextTestimonial(); 439 }); 440 441 442 // style line color 443 const testimonialDecorationLine = document.querySelector(".home__testimonials"); 444 445 function setLineColor() { 446 if (carouselPosition == 0) { 447 testimonialDecorationLine.classList.remove("line--rose", "line--tangerine", "line--pear", "line--capri"); 448 testimonialDecorationLine.classList.add("line--rose"); 449 } else if (carouselPosition == 1) { 450 testimonialDecorationLine.classList.remove("line--rose", "line--tangerine", "line--pear", "line--capri"); 451 testimonialDecorationLine.classList.add("line--tangerine"); 452 } else if (carouselPosition == 2) { 453 testimonialDecorationLine.classList.remove("line--rose", "line--tangerine", "line--pear", "line--capri"); 454 testimonialDecorationLine.classList.add("line--pear"); 455 } else if (carouselPosition == 3) { 456 testimonialDecorationLine.classList.remove("line--rose", "line--tangerine", "line--pear", "line--capri"); 457 testimonialDecorationLine.classList.add("line--capri"); 458 } 459 } 460 461 if (testimonialDecorationLine) setLineColor(); 462 463 // update carousel position 464 function updateCarouselPosition() { 465 for (let testimonial of testimonials) { 466 testimonial.classList.remove("testimonial--visible"); 467 testimonial.setAttribute('style', 'transform:translateX(-' + 150 * carouselPosition + '%)'); 468 }
469 testimonials[carouselPosition].classList.add("testimonial--visible"); 470 // indicate visible testimonial on dots 471 dotsArray.forEach(dot => dot.classList.remove("testimonials-carousel__dots-wrapper__dot--active")); 472 dotsArray[carouselPosition].classList.add("testimonials-carousel__dots-wrapper__dot--active"); 473 } 474 475 // move carousel 476 function moveToPreviousTestimonial() { 477 if (carouselPosition == 0) { 478 carouselPosition = totalTestimonials - 1; 479 } else { 480 carouselPosition--; 481 } 482 483 updateCarouselPosition(); 484 setLineColor(); 485 } 486 487 function moveToNextTestimonial() { 488 if (carouselPosition == totalTestimonials - 1) { 489 carouselPosition = 0; 490 } else { 491 carouselPosition++; 492 } 493 494 updateCarouselPosition(); 495 setLineColor(); 496 } 497 498 // automatically move carousel 499 let autoscroll; 500 501 502 function autoPlayOnDesktop() { 503 if (location.pathname == "/") { 504 if (window.innerWidth > 768) { 505 autoscroll = setInterval(function () { 506 moveToNextTestimonial() 507 }, 9000); 508 509 // stop autoplay on hover 510 testimonialsContainer.onmouseover = function () { 511 autoscroll = clearInterval(autoscroll); 512 }; 513 514 testimonialsContainer.onmouseout = function () { 515 clearInterval(autoscroll); 516 autoscroll = setInterval(function () { 517 moveToNextTestimonial() 518 }, 9000); 519 }; 520 } 521 } 522 523 } 524 525 // call function 526 // autoPlayOnDesktop(); 527 528 529 // hide dots on product pages 530 if (location.pathname != "/") { 531 document.querySelector(".testimonials-carousel__dots-wrapper")?.classList.add("hide"); 532 } 533 534 // set which testimonial to show on each product page 535 function displayFixedCarousel() { 536 if (location.pathname == "/product/screening/") { 537 carouselPosition = 1; 538 testimonialDecorationLine.classList.remove("line--rose", "line--tangerine", "line--pear", "line--capri"); 539 testimonialDecorationLine.classList.add("line--tangerine"); 540 for (let testimonial of testimonials) { 541 testimonial.classList.remove("testimonial--visible"); 542 testimonial.setAttribute('style', 'transform:translateX(-' + 150 * carouselPosition + '%)'); 543 } 544 testimonials[carouselPosition].classList.add("testimonial--visible"); 545 document.querySelector(".testimonials-carousel__dots-wrapper").style.display == "none"; 546 } else if (location.pathname == "/product/transaction-monitoring/") { 547 carouselPosition = 2; 548 testimonialDecorationLine.classList.remove("line--rose", "line--tangerine", "line--pear", "line--capri"); 549 testimonialDecorationLine.classList.add("line--pear"); 550 for (let testimonial of testimonials) { 551 testimonial.classList.remove("testimonial--visible"); 552 testimonial.setAttribute('style', 'transform:translateX(-' + 150 * carouselPosition + '%)'); 553 } 554 testimonials[carouselPosition].classList.add("testimonial--visible"); 555 } else if (location.pathname == "/product/kyc-risk-scoring/") { 556 carouselPosition = 3; 557 testimonialDecorationLine.classList.remove("line--rose", "line--tangerine", "line--pear", "line--capri"); 558 testimonialDecorationLine.classList.add("line--capri"); 559 for (let testimonial of testimonials) { 560 testimonial.classList.remove("testimonial--visible"); 561 testimonial.setAttribute('style', 'transform:translateX(-' + 150 * carouselPosition + '%)'); 562 } 563 testimonials[carouselPosition].classList.add("testimonial--visible"); 564 } else if (location.pathname == "/product/salv-bridge/") { 565 carouselPosition = 0; 566 testimonialDecorationLine.classList.remove("line--rose", "line--tangerine", "line--pear", "line--capri"); 567 testimonialDecorationLine.classList.add("line--rose"); 568 for (let testimonial of testimonials) { 569 testimonial.classList.remove("testimonial--visible"); 570 testimonial.setAttribute('style', 'transform:translateX(-' + 150 * carouselPosition + '%)'); 571 }
572 testimonials[carouselPosition].classList.add("testimonial--visible"); 573 } 574 } 575 576 //run function to display carousel as static on product pages 577 if (testimonials && testimonialDecorationLine) displayFixedCarousel(); 578 579 // make carousel draggable on mobile 580 let touchPosition; 581 582 function handleTouchStart(e) { 583 const touchDown = e.touches[0].clientX; 584 touchPosition = touchDown; 585 } 586 587 const handleTouchMove = (e) => { 588 const touchDown = touchPosition; 589 590 if (touchDown === null) { 591 return; 592 } 593 ; 594 595 const currentTouch = e.touches[0].clientX; 596 const diff = touchDown - currentTouch; 597 598 if (diff > 10) { 599 moveToNextTestimonial(); 600 } 601 ; 602 603 if (diff < -10) { 604 moveToPreviousTestimonial(); 605 } 606 ; 607 608 touchPosition = null; 609 } 610 611 // only allow swiping on landing page 612 // if (location.pathname == "/") { 613 // testimonialsContainer.addEventListener('touchstart', handleTouchStart); 614 // testimonialsContainer.addEventListener('touchmove', handleTouchMove); 615 // } 616 617 // //*** BLOG - TABLE OF CONTENTS *** 618 const sidePanel = document.querySelector(".post__side-panel"); 619 const tocWrapper = document.querySelector(".toc-wrapper"); 620 const firstParagraph = document.querySelector("#post__wrapper > div > p"); 621 const postShareContainer = document.querySelector(".post__share-container"); 622 const postShareContainerInnerWrapper = document.querySelector(".post__share-container__inner-wrapper"); 623 624 // if the blog post starts with an image, add margin-top ot the toc wrapper to keep alignment 625 if (firstParagraph?.getElementsByTagName('img').length > 0) { 626 sidePanel.style.setProperty("margin-top", `32px`); 627 } 628 629 // if there's table of contents, (there were h2s to generate from), add Contents title 630 const tocTitleWrapper = document.querySelector(".toc-title-wrapper"); 631 const tableOfContents = document.querySelector("#table-of-contents"); 632 633 if (tableOfContents) { 634 const tocTitle = document.createElement("p"); 635 var tocTitleText = document.createTextNode("Table of Contents"); 636 tocTitle.appendChild(tocTitleText); 637 tocTitle.classList.add("toc-title"); 638 tocTitleWrapper.appendChild(tocTitle).focus(); 639 tocTitleWrapper.classList.add("in"); 640 641 } else { 642 // remove table of contents if it's empty 643 tocWrapper?.remove(); 644 sidePanel?.style.setProperty("margin-top", `0px`); 645 postShareContainer?.classList.add("no-border"); 646 if (firstParagraph?.getElementsByTagName('img').length <= 0) { 647 postShareContainerInnerWrapper?.classList.add("no-margin"); 648 } 649 } 650 651 // Get poosition of last line 652 function getHeightOfContent(containerElement) { 653 const linesInBlogs = [...document.querySelectorAll(".blog #postContent hr")]; 654 if (linesInBlogs.length > 0) { 655 return linesInBlogs[linesInBlogs.length - 1].offsetTop - containerElement.offsetTop; 656 } 657 658 // Handle case where no lines are found 659 return null; 660 } 661 662 // Highlight active section 663 const tocHeaders = document.querySelector("#post__wrapper > div")?.querySelectorAll("h2, .h3-in-toc"); 664 665 // Add H3 elements with class "h3-in-toc" to toc 666 if (window.location.pathname.toString().includes("/blog")) { 667 const h3sInBlogPost = [...document.querySelectorAll(".h3-in-toc")].reverse(); 668 669 h3sInBlogPost.forEach((h3) => { 670 const li = document.createElement("li"); 671 li.classList.add("toc-h3"); 672 const linkInLi = document.createElement("a"); 673 let linkText = document.createTextNode(h3.textContent); 674 linkInLi.appendChild(linkText); 675 linkInLi.href = "#" + h3.id; 676 li.appendChild(linkInLi); 677 678 // Calculate the closest preceding H2 for each H3 679 const closestH2ID = findClosestH2ID(h3); 680 const H2inToc = document.querySelector(`#table-of-contents a[href='#${closestH2ID}']`).parentElement; 681 682 // Insert the li element after the appropriate H2 element 683 H2inToc.after(li); 684 }); 685 686 // Find the closest H2 ID 687 function findClosestH2ID(h3) { 688 let previous = h3.previousElementSibling; 689 while (previous) { 690 if (previous.tagName === "H2") { 691 return previous.id; 692 } 693 previous = previous.previousElementSibling; 694 } 695 return null; // If no preceding H2 is found 696 } 697 } 698 699 // When all elements are added to the blog post 700 const postSideBar = document.querySelector(".blog #postSideBar"); 701 const postContent = document.querySelector(".blog #postContent"); 702 let postContentHeight = 0; 703 704 if (postContent) { 705 const postContentObserverCallback = () => {
706 const newPostContentHeight = postContent.getBoundingClientRect().height; 707 708 let postSideBarStyle = sidePanel.currentStyle || window.getComputedStyle(sidePanel); 709 let postSideBarMarginBottom = +postSideBarStyle.marginBottom.slice(0, -2) 710 711 if (newPostContentHeight !== postContentHeight) { 712 const heightOfContent = getHeightOfContent(postContent); 713 if (!heightOfContent) return; 714 715 postSideBar.style.height = heightOfContent + postShareContainer.getBoundingClientRect().height + postSideBarMarginBottom; 716 postContentHeight = newPostContentHeight; 717 } 718 }; 719 720 const postContentObserver = new MutationObserver(postContentObserverCallback); 721 postContentObserver.observe(postContent, {attributes: false, childList: true, subtree: true}); 722 postContentObserverCallback() 723 } 724 725 726 window.onscroll = () => { 727 if (!tocHeaders) return; 728 729 const scrollPos = document.body.scrollTop; 730 const navWrapperBounding = document.querySelector(".nav-wrapper").getBoundingClientRect(); 731 const scrollOffset = navWrapperBounding.bottom - navWrapperBounding.top + 150; 732 733 // highlight currently visible header in table of contents 734 // remove highlight from all elements 735 document.querySelector('.highlighted')?.classList.remove('highlighted'); 736 737 const headerInView = [...tocHeaders].reverse().find((header) => header.offsetTop <= (scrollPos + scrollOffset)); 738 if (!headerInView) return; 739 740 const highlightedTocLink = document.querySelector(`.toc a[href="#${headerInView.id}"]`); 741 highlightedTocLink.classList.add('highlighted'); 742 } 743 744 745 //*** HOME PRODUCT CARDS - make whole div clickable *** 746 const screeningCard = document.querySelector("#screening-solutions-card"); 747 const monitoringCard = document.querySelector("#monitoring-solutions-card"); 748 const kycCard = document.querySelector("#kyc-solutions-card"); 749 const intelligenceSharingCard = document.querySelector("#intelligence-sharing-solutions-card"); 750 751 const solutionsCards = document.querySelectorAll(".solutions-card"); 752 const solutionsCardsArray = [...solutionsCards]; 753 754 // On wide screen: make whole card clickable 755 if ((window.location.pathname == "/" || window.location.pathname == "/product/")) { //Make whole divs clickable 756 screeningCard.addEventListener("click", openProductPage); 757 monitoringCard.addEventListener("click", openProductPage); 758 kycCard.addEventListener("click", openProductPage); 759 intelligenceSharingCard.addEventListener("click", openProductPage); 760 } 761 762 // expand card on click and collapse previously open card 763 // function openCard(event) { 764 // for (let i = 0; i < solutionsCardsArray.length; i++) { 765 // if (this === solutionsCardsArray[i]) { 766 // solutionsCardsArray[i].classList.toggle("solutions-card--collapsed"); 767 // solutionsCardsArray[i].classList.toggle("solutions-card--expanded"); 768 // } else if (this === solutionsCardsArray[i].querySelector("A")) { 769 // event.stopPropagation(); 770 // } else { 771 // solutionsCardsArray[i].classList.add("solutions-card--collapsed"); 772 // solutionsCardsArray[i].classList.remove("solutions-card--expanded"); 773 // } 774 // } 775 // } 776 777 // redirect to target page 778 function openProductPage(e) { 779 window.open(e.currentTarget.querySelector("A").href, "_self") 780 } 781 782 783 //*** PRODUCT CARDS on product pages *** 784 const smallSolutionsCards = [...document.querySelectorAll(".solutions-card--small")]; 785 smallSolutionsCards.forEach(card => card.addEventListener("click", openProductPage)); 786 787 788 //*** PRODUCT BENEFITS AND FEATURES READ MORE BUTTON TOGGLE *** 789 //*** Bridge page: INDICATE EXPANDED USE CASE CARD *** 790 791 const readMoreButtons = document.querySelectorAll(".product__benefits-and-features__read-more-button"); 792 const readMoreButtonsArray = [...readMoreButtons]; 793
794 function openReadMoreButtonAccordion(button) { 795 if (button) { 796 button.parentElement.parentElement.previousElementSibling.classList.toggle("read-more--visible"); // hidden text in accordion 797 button.parentElement.parentElement.parentElement.classList.toggle("open"); // use case card 798 button.parentElement.parentElement.parentElement.parentElement.parentElement.classList.toggle(`open-${button.parentElement.parentElement.parentElement.dataset.order}`); // use case wrapper to indicate which one is open 799 button.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.classList.toggle(`open-${button.parentElement.parentElement.parentElement.dataset.order}`); // whole use case section to indicate which one is open 800 button.setAttribute("aria-expanded", button.getAttribute('aria-expanded') === 'true' ? 'false' : 'true'); // read more button 801 if (button.parentElement.parentElement.previousElementSibling.classList.contains("read-more--visible")) { 802 button.innerHTML = "Show less" + '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M360.5 217.5l-152 143.1C203.9 365.8 197.9 368 192 368s-11.88-2.188-16.5-6.562L23.5 217.5C13.87 208.3 13.47 193.1 22.56 183.5C31.69 173.8 46.94 173.5 56.5 182.6L192 310.9l135.5-128.4c9.562-9.094 24.75-8.75 33.94 .9375C370.5 193.1 370.1 208.3 360.5 217.5z"/></svg>'; 803 } else { 804 button.innerHTML = "Read more" + '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M360.5 217.5l-152 143.1C203.9 365.8 197.9 368 192 368s-11.88-2.188-16.5-6.562L23.5 217.5C13.87 208.3 13.47 193.1 22.56 183.5C31.69 173.8 46.94 173.5 56.5 182.6L192 310.9l135.5-128.4c9.562-9.094 24.75-8.75 33.94 .9375C370.5 193.1 370.1 208.3 360.5 217.5z"/></svg>'; 805 } 806 ; 807 808 } 809 } 810 811 readMoreButtonsArray.forEach(button => button?.addEventListener("click", () => openReadMoreButtonAccordion(button))); 812 813 814 //*** ABOVE NAVIAGTION BAR BANNER - CLOSE *** 815 const bannerCloseButton = document.querySelector("#top-banner__close-button"); 816 const topBanner = document.querySelector(".top-banner-wrapper"); 817 const hamburgerButtonWrapper = document.querySelector(".hamburger-button-wrapper"); 818 const homeHeroLarger = document.querySelector("#home-hero"); 819 820 // Get session storage (it's null at this point) 821 let topBannerStatus = sessionStorage.getItem("top-banner"); 822 823 // If there's no saves session storage or the the abnner ahsn't been dismissed -> show the banner 824 if (sessionStorage.getItem("top-banner") === null || topBannerStatus !== "dismissed") { 825 topBanner?.classList.remove("hide"); 826 // for hero layout adjustments 827 hamburgerButtonWrapper?.classList.add("with-top-banner"); 828 homeHeroLarger?.classList.add("with-top-banner"); 829 830 // for animation 831 setTimeout(() => { 832 topBanner?.classList.add("opaque"); 833 }, 0) 834 } 835 836 // dismiss banner 837 bannerCloseButton?.addEventListener("click", () => { 838 topBanner.classList.add("hide"); 839 hamburgerButtonWrapper.classList.remove("with-top-banner"); 840 homeHeroLarger?.classList.remove("with-top-banner"); 841 sessionStorage.setItem("top-banner", "dismissed"); 842 }) 843 844 845 //*** LOGOS CAROUSEL: dynamically set variable through javascript for the carousel width, set aniamtion though JS so that it works on Safari as well *** 846 const slider = document.querySelector(".logos-carousel"); 847 const sliderTrack = document.querySelector(".logos-carousel__slider-track"); 848 slider?.style.setProperty("--slidesWidthSum", `${slider.scrollWidth / -2}px`); 849 if (sliderTrack) { 850 sliderTrack.style.animation = "scrollLogos var(--scrollSpeed) linear infinite"; 851 } 852 853 //*** IMAGES CAROUSEL: dynamically set variable through javascript for the carousel width, set animation though JS so that it works on Safari as well *** 854 const imagesSlider = document.querySelector(".home__key-benefits__carousel"); 855 const imagesSliderTrack = document.querySelector(".home__key-benefits__carousel__slider-track"); 856 857 if (window.innerWidth < 768) { 858 imagesSlider?.style.setProperty("--imagesWidthSum", `${imagesSlider.scrollWidth / -2}px`); 859 if (imagesSliderTrack) { 860 imagesSliderTrack.style.animation = "scrollImages var(--scrollSpeed) linear infinite"; 861 } 862 } 863 864
865 //*** CLIENTS TESTIMONIALS HORIZONTAL ACCORDION *** 866 const testimonalCardsContainer = document.querySelector(".clients-testimonials--horizontal__inner"); 867 const testimonialCards = [...document.querySelectorAll(".clients-testimonials--horizontal__container")]; 868 let testimonialPosition = 0; // 0-3 869 const testimonialCardDots = [...document.querySelectorAll(".clients-testimonials--horizontal__dot")]; 870 871 // mobile - add expanded styling 872 if (window.innerWidth < 768) { 873 testimonialCards.forEach(card => card.classList.add("expanded")); 874 } 875 876 // desktop - remove shaded styling 877 if (window.innerWidth > 768) { 878 testimonialCards.forEach(card => card.classList.remove("shaded")); 879 } 880 881 testimonialCards?.forEach((testimonialCard) => { 882 testimonialCard.addEventListener('click', (e) => { 883 if (window.innerWidth > 768) { 884 testimonialCards.find((card) => card.classList.contains("expanded"))?.classList.remove("expanded"); 885 } 886 887 testimonialCards?.filter(card =>
887 card.classList.contains("current")).forEach(testimonial => testimonial.classList.remove("current")); 888 889 e.currentTarget.classList.add("expanded"); 890 891 // add a class that indicates which card is expanded (used to style arrow direction) 892 testimonalCardsContainer.classList.replace( 893 testimonalCardsContainer.className.match(/expanded-.*?-testimonial/)[0], 894 `expanded-${[...e.currentTarget.className.matchAll(/\w*-testimonial/g)][1]}` 895 ); 896 897 // mobile - when clicked on an adjacent card - move to that card, and add shaded styling 898 if (window.innerWidth < 768) { 899 testimonalCardsContainer.style.transform = `translateX(-${[...testimonalCardsContainer.children].indexOf(e.currentTarget) * 25}%)`; 900 901 testimonialCards?.filter(card => card.classList.contains("shaded")).forEach(testimonial => testimonial.classList.remove("shaded")); 902 e.currentTarget.nextElementSibling?.classList.add("shaded"); 903 e.currentTarget.previousElementSibling?.classList.add("shaded"); 904 905 testimonialPosition = [...testimonalCardsContainer.children].indexOf(testimonialCards.find((card) => card === e.currentTarget)); 906 907 updateTestimonialDots(); 908 } 909 }); 910 }); 911 912 // MOBILE DRAGGABILITY 913 const totalTestimonialCards = testimonialCards.length; 914 915 // swipe testimonial cards to next one 916 function swipeToNextTestimonialCard() { 917 if (testimonialPosition == totalTestimonialCards - 1) { 918 return; 919 } else { 920 testimonalCardsContainer.style.transform = `translateX(-${(testimonialPosition + 1) * 25}%)`; 921 922 testimonialCards?.filter(card => card.classList.contains("shaded")).forEach(testimonial => testimonial.classList.remove("shaded")); 923 testimonialCards[testimonialPosition + 1]?.previousElementSibling?.classList.add("shaded"); 924 testimonialCards[testimonialPosition + 1]?.nextElementSibling?.classList.add("shaded"); 925 926 testimonialPosition++; 927 } 928 } 929 930 // swipe testimonial cards to previous one 931 function swipeToPreviousTestimonialCard() { 932 if (testimonialPosition == 0) { 933 return; 934 } else { 935 testimonalCardsContainer.style.transform = `translateX(-${(testimonialPosition - 1) * 25}%)`; 936 937 testimonialCards?.filter(card => card.classList.contains("shaded")).forEach(testimonial => testimonial.classList.remove("shaded")); 938 testimonialCards[testimonialPosition - 1]?.previousElementSibling?.classList.add("shaded"); 939 testimonialCards[testimonialPosition - 1]?.nextElementSibling?.classList.add("shaded"); 940 941 testimonialPosition--; 942 } 943 } 944 945 // make carousel draggable on mobile 946 let touchTestimonialPosition; 947 948 function handleTestimonialTouchStart(e) { 949 const touchDownOnTestimonialsContainer = e.touches[0].clientX; 950 touchTestimonialPosition = touchDownOnTestimonialsContainer; 951 } 952 953 const handleTestimonialTouchMove = (e) => { 954 const touchDownOnTestimonialsContainer = touchTestimonialPosition; 955 956 if (touchDownOnTestimonialsContainer === null) { 957 return; 958 } 959 ; 960 961 const currentTestimonialTouch = e.touches[0].clientX; 962 const difference = touchDownOnTestimonialsContainer - currentTestimonialTouch; 963 964 if (difference > 10) { 965 swipeToNextTestimonialCard(); 966 } 967 ; 968 969 if (difference < -10) { 970 swipeToPreviousTestimonialCard(); 971 } 972 ; 973 974 updateTestimonialDots(); 975 976 touchTestimonialPosition = null; 977 } 978 979 function updateTestimonialDots() { 980 testimonialCardDots.forEach(dot => dot.classList.remove("clients-testimonials--horizontal__active-dot")); 981 testimonialCardDots[testimonialPosition].classList.add("clients-testimonials--horizontal__active-dot"); 982 } 983 984 testimonalCardsContainer?.addEventListener('touchstart', handleTestimonialTouchStart); 985 testimonalCardsContainer?.addEventListener('touchmove', handleTestimonialTouchMove); 986 987 988 //*** Landing page: COLOUR KEY MESSAGE TITLES ON HOVER *** 989 const colouredSpans = document.querySelectorAll('[data-coloured-text]'); 990 991 colouredSpans?.forEach(span => { 992 span.addEventListener("mouseover", () => { 993 span.parentElement.classList.add(span.dataset.colouredText); 994 }); 995 }) 996 997 colouredSpans?.forEach(span => { 998 span.addEventListener("mouseleave", () => { 999 span.parentElement.classList.remove(span.dataset.colouredText); 1000 }); 1001 }) 1002 1003
1004 //*** VIEW IMAGE IN LARGE IN BLOG POST MODAL *** 1005 1006 const imageModal = document.getElementById("imageModal"); 1007 1008 const imagesToEnlarge = [...document.querySelectorAll(".image-to-enlarge img")]; 1009 1010 const imageInModal = document.querySelector(".image-in-modal"); 1011 1012 const imageModalCloseButton = document.querySelector(".image-modal-close-button"); 1013 1014 // When the user clicks on an image that has "image-to-enlarge" class, open the modal and in it the image 1015 if (window.innerWidth > 768) { 1016 imagesToEnlarge.forEach(image => image.addEventListener("click", () => { 1017 imageModal.classList.add("open"); 1018 imageInModal.src = image.getAttribute("src"); 1019 })); 1020 } 1021 1022 // When the user clicks on <span> (x), close the modal 1023 imageModalCloseButton?.addEventListener("click", () => imageModal.classList.remove("open")); 1024 1025 // When the user clicks anywhere outside of the modal, close it 1026 imageModal?.addEventListener("click", () => imageModal.classList.remove("open")) 1027 1028 1029 //*** BLOG - ADD GRADIENT ON BOTH SIDES OF THE FILER CONTAINER *** 1030 const filtersContainer = document.querySelector(".blog__tags-filter-container"); 1031 const firstFilter = document.querySelector("#first-tag"); 1032 1033 // Add gradietn to beginning of tag filters container when scrolled away - intersection observer 1034 const filtersCallback = (entries, observer) => { 1035 entries.forEach((entry) => { 1036 if (entry.isIntersecting) { 1037 filtersContainer.classList.remove("scrolled"); 1038 } else { 1039 filtersContainer.classList.add("scrolled"); 1040 } 1041 }); 1042 }; 1043 1044 const filtersOptions = { 1045 root: null, 1046 rootMargin: '0px', 1047 threshold: 0.5 1048 }; 1049 1050 const scrollObserver = new IntersectionObserver(filtersCallback, filtersOptions); 1051 if (firstFilter) { 1052 scrollObserver.observe(firstFilter); 1053 } 1054 1055 // Scroll active tag into view after page load 1056 const activeTag = document.querySelector(".tag-filter.active"); 1057 1058 if (window.innerWidth < 768 && activeTag) { 1059 activeTag.scrollIntoView({behavior: 'smooth', block: 'nearest', inline: 'center'}); 1060 } 1061 1062 1063 //*** OPEN BRIDGE USE CASE ACCORDION WHEN LINKED TO IT FROM EXTERNAL SOURCE *** 1064 if (window.location.hash != '') { 1065 const hash = window.location.hash; 1066 1067 // Q&A accordions on product pages 1068 if (hash.includes("aml-bridge-question") || hash.includes("screening-question") || hash.includes("monitoring-question") || hash.includes("kyc-question")) { 1069 const questionToOpen = document.querySelector(`.qa-box ${hash}`); 1070 questionToOpen.parentElement.parentElement.classList.toggle("open"); 1071 questionToOpen.parentElement.nextElementSibling.style.height = "auto"; 1072 questionToOpen.setAttribute("aria-expanded", "true"); 1073 1074 const newerHeight = questionToOpen.parentElement.nextElementSibling.clientHeight + 'px'; 1075 1076 questionToOpen.parentElement.nextElementSibling.style.height = '0px'; 1077 1078 setTimeout(function () { 1079 questionToOpen.parentElement.nextElementSibling.style.height = newerHeight; 1080 }, 0); 1081 1082 } else { // Bridge page use case cards 1083 const bridgeUseCaseToOpenButton = document.querySelector(`${hash} .product__benefits-and-features__read-more-button`); 1084 openReadMoreButtonAccordion(bridgeUseCaseToOpenButton); 1085 // add outline aniamtion 1086 bridgeUseCaseToOpenButton?.parentElement.parentElement.parentElement.classList.add("animate-border"); 1087 } 1088 } 1089 1090 1091 //*** BRIDGE UI CAROUSEL *** 1092 const swipeCarousel = document.querySelector(".swipe-carousel"); 1093 const swipeCarouselContainers = [...document.querySelectorAll(".swipe--content")]; 1094 const swipeCarouselColumns = document.querySelector(".swipe-carousel__columns"); 1095 const swipeCarouselDots = [...document.querySelectorAll(".swipe-carousel__navigation__dot")]; 1096 1097 let swipeCarouselPosition = 0; //0-1, two options 1098 const totalSwipeCarouselContainers = swipeCarouselContainers.length; 1099 1100 // swipe Bridge UI container to next one 1101 function swipeToNextSwipeCarousel() { 1102 if (swipeCarouselPosition == totalSwipeCarouselContainers - 1) { 1103 return; 1104 } else { 1105 swipeCarouselColumns.style.transform = `translateX(-${(swi
1105peCarouselPosition + 1) * (100 / totalSwipeCarouselContainers)}%)`; 1106 swipeCarouselPosition++; 1107 } 1108 1109 } 1110 1111 // swipe Bridge UI container to previous one 1112 function swipeToPreviousSwipeCarousel() { 1113 if (swipeCarouselPosition == 0) { 1114 return; 1115 } else { 1116 swipeCarouselColumns.style.transform = `translateX(-${(swipeCarouselPosition - 1) * (100 / totalSwipeCarouselContainers)}%)`; 1117 swipeCarouselPosition--; 1118 } 1119 } 1120 1121 // update dots indicating which Bridge UI column is active/visible 1122 function updateSwipeCarouselDots() { 1123 swipeCarouselDots.forEach(dot => dot.classList.remove("active")); 1124 swipeCarouselDots[swipeCarouselPosition].classList.add("active"); 1125 } 1126 1127 // make Bridge UI carousel draggable on mobile 1128 let touchSwipeCarouselPosition; 1129 1130 function handleSwipeCarouselTouchStart(e) { 1131 const touchDownOnSwipeCarouselContainer = e.touches[0].clientX; 1132 touchSwipeCarouselPosition = touchDownOnSwipeCarouselContainer; 1133 } 1134 1135 const handleSwipeCarouselTouchMove = (e) => { 1136 const touchDownOnSwipeCarouselContainer = touchSwipeCarouselPosition; 1137 1138 if (touchDownOnSwipeCarouselContainer === null) { 1139 return; 1140 } 1141 ; 1142 1143 const currentSwipeCarouselTouch = e.touches[0].clientX; 1144 const differences = touchDownOnSwipeCarouselContainer - currentSwipeCarouselTouch; 1145 1146 if (differences > 10) { 1147 swipeToNextSwipeCarousel(); 1148 } 1149 ; 1150 1151 if (differences < -10) { 1152 swipeToPreviousSwipeCarousel(); 1153 } 1154 ; 1155 1156 updateSwipeCarouselDots(); 1157 1158 touchSwipeCarouselPosition = null; 1159 1160 swipeCarouselColumns.classList.replace( 1161 swipeCarouselColumns.className.match(/active-swipe-.*/)[0], 1162 `active-swipe-${swipeCarouselPosition}` 1163 ); 1164 } 1165 1166 if (window.innerWidth < 768) { 1167 swipeCarousel?.addEventListener('touchstart', handleSwipeCarouselTouchStart); 1168 swipeCarousel?.addEventListener('touchmove', handleSwipeCarouselTouchMove); 1169 } 1170 1171 1172 // Redirect to link in clicked element 1173 1174 function navigateTolink(e) { 1175 window.open(e.currentTarget.querySelector("A").href, "_self"); 1176 } 1177 1178 // Careers page job cards are rendered from the Personio feed after this handler 1179 // runs, so their whole-card click is bound by delegation in 1180 // _includes/personio-jobs.html instead. 1181 1182 // Blog page - Make full blog card clickable 1183 1184 const blogPostCard = [...document.querySelectorAll(".post-list")]; 1185 1186 blogPostCard?.forEach(post => post.addEventListener("click", navigateTolink)); 1187 1188});
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.