1jQuery(document).ready(function ($) { 2 jQuery(".ot-sdk-show-settings a").click(function () { 3 jQuery(".moove_gdpr_icon").trigger("click"); 4 }); 5 if ( 6 $("body").hasClass("single-post") || 7 $("body").hasClass("single-event") || 8 $("body").hasClass("page-id-521") 9 ) { 10 $(".news-ancestor").addClass("current-ancestor"); 11 } 12 if ( 13 $("body").hasClass("single-job") || 14 $("body").hasClass("single-people") || 15 $("body").hasClass("single-impact-story") || 16 $("body").hasClass("single-tender") 17 ) { 18 $(".about-ancestor").addClass("current-ancestor"); 19 } 20 if ( 21 $("body").hasClass("single-training") || 22 $("body").hasClass("single-resource") 23 ) { 24 $(".training-ancestor").addClass("current-ancestor"); 25 } 26 if ( 27 $("body").hasClass("page-id-1549") || 28 $("body").hasClass("parent-pageid-1549") || 29 $("body").hasClass("page-id-1407") || 30 $("body").hasClass("parent-pageid-3100") 31 ) { 32 $(".services-ancestor").addClass("current-ancestor"); 33 } 34 if ($("body").hasClass("single-initiative")) { 35 $(".work-ancestor").addClass("current-ancestor"); 36 } 37 38 // menu scroll 39 var lastScrollTop = 0; 40 var mastheadHeight = $("#masthead").outerHeight(); 41 var anchorScrolling = false; // Flag to track anchor link scrolling 42 43 // Detect anchor link clicks 44 $('a[href^="#"]').on("click", function (e) { 45 anchorScrolling = true; 46 setTimeout(function () { 47 anchorScrolling = false; 48 }, 1000); // Reset the flag after 1 second 49 }); 50 51 $(window).scroll(function () { 52 if (anchorScrolling) return; // Skip if scrolling is from an anchor link 53 54 if ($(window).width() >= 1080) { 55 var st = $(this).scrollTop(); 56 if (st > mastheadHeight) { 57 if (st > lastScrollTop) { 58 // Scroll down 59 $("#masthead").css("transform", "translateY(-100%)"); 60 } else { 61 // Scroll up 62 $("#masthead").css("transform", "translateY(0)"); 63 } 64 } 65 lastScrollTop = st; 66 } 67 }); 68 69 // carousels 70 var $awards_slider = $(".awards-carousel"); 71 var $progressBar = $(".awards-carousel-wrap .progress"); 72 var $progressBarLabel = $(".awards-carousel-wrap .slider__label"); 73 74 $awards_slider.on( 75 "beforeChange", 76 function (event, slick, currentSlide, nextSlide) { 77 var calc = (nextSlide / (slick.slideCount - 1)) * 100; 78 $progressBar 79 .css("background-size", calc + "% 100%") 80 .attr("aria-valuenow", calc); 81 $progressBarLabel.text(calc + "% completed"); 82 } 83 ); 84 85 $awards_slider.on("init", function (event, slick) { 86 if (slick.slideCount <= slick.options.slidesToShow) { 87 $progressBar.hide(); 88 } 89 }); 90 91 $awards_slider.slick({ 92 slidesToShow: 5, 93 slidesToScroll: 1, 94 infinite: true, 95 dots: false, 96 arrows: true, 97 autoplay: false, 98 swipeToSlide: true, 99 touchThreshold: 100, 100 autoplaySpeed: 3000, 101 pauseOnHover: false, 102 prevArrow: 103 '<button class="slick-prev" aria-label="Previous" type="button"><img src="/wp-content/uploads/2024/07/uil-angle-right.svg" alt=""></button>', 104 nextArrow: 105 '<button class="slick-next" aria-label="Next" type="button"><img src="/wp-content/uploads/2024/07/uil-angle-right.svg" alt=""></button>', 106 responsive: [ 107 { 108 breakpoint: 1471, 109 settings: { 110 slidesToShow: 4, 111 }, 112 }, 113 { 114 breakpoint: 1081, 115 settings: { 116 slidesToShow: 3, 117 }, 118 }, 119 { 120 breakpoint: 782, 121 settings: { 122 slidesToShow: 2, 123 }, 124 }, 125 { 126 breakpoint: 640, 127 settings: { 128 slidesToShow: 1, 129 }, 130 }, 131 ], 132 }); 133 134 var $partners_slider = $(".partners-carousel"); 135 var $partnersprogressBar = $(".partners-carousel-wrap .progress"); 136 var $partnersprogressBarLabel = $(".partners-carousel-wrap .slider__label"); 137 138 $partners_slider.on( 139 "beforeChange", 140 function (event, slick, currentSlide, nextSlide) { 141 var calc = (nextSlide / (slick.slideCount - 1)) * 100; 142 $partnersprogressBar 143 .css("background-size", calc + "% 100%") 144 .attr("aria-valuenow", calc); 145 $partnersprogressBarLabel.text(calc + "% completed"); 146 } 147 ); 148 149 $partners_slider.on("init", function (event, slick) { 150 if (slick.slideCount <= slick.options.slidesToShow) { 151 $partnersprogressBar.hide(); 152 } 153 }); 154 155 $partners_slider.slick({ 156 slidesToShow: 5, 157 slidesToScroll: 1, 158 infinite: true, 159 dots: false, 160 arrows: true, 161 autoplay: false, 162 autoplaySpeed: 3000, 163 pauseOnHover: false, 164 prevArrow: 165 '<button class="slick-prev" aria-label="Previous" type="button"><img src="/wp-content/uploads/2024/07/uil-angle-right.svg" alt=""></button>', 166 nextArrow: 167 '<button class="slick-next" aria-label="Next" type="button"><img src="/wp-content/uploads/2024/07/uil-angle-right.svg" alt=""></button>', 168 responsive: [ 169 { 170 breakpoint: 1471, 171 settings: { 172 slidesToShow: 4, 173 }, 174 }, 175 { 176 breakpoint: 1081, 177 settings: { 178 slidesToShow: 3, 179 }, 180 }, 181 { 182 breakpoint: 782, 183 settings: { 184 slidesToShow: 2, 185 }, 186 }, 187 { 188 breakpoint: 640, 189 settings: { 190 slidesToShow: 1, 191 }, 192 }, 193 ], 194 }); 195 196 var $people_slider = $(".posts-carousel-wrap.people .posts-carousel"); 197 var $people_progressBar = $(".posts-carousel-wrap.people .progress"); 198 var $people_progressBarLabel = $( 199 ".posts-carousel-wrap.people .slider__label" 200 ); 201 202 $people_slider.on( 203 "beforeChange", 204 function (event, slick, currentSlide, nextSlide) { 205 var calc = (nextSlide / (slick.slideCount - 1)) * 100; 206 $people_progressBar 207 .css("background-size", calc + "% 100%") 208 .attr("aria-valuenow", calc); 209 $people_progressBarLabel.text(calc + "% completed"); 210 } 211 ); 212 213 $people_slider.on("init", function (event, slick) { 214 if (slick.slideCount <= slick.options.slidesToShow) { 215 $people_progressBar.hide(); 216 } 217 }); 218 219 $people_slider.slick({ 220 slidesToShow: 4, 221 slidesToScroll: 1, 222 infinite: true, 223 dots: false, 224 arrows: true, 225 autoplay: false, 226 autoplaySpeed: 5000, 227 pauseOnHover: false, 228 prevArrow: 229 '<button class="slick-prev" aria-label="Previous" type="button"><img src="/wp-content/uploads/2024/07/uil-angle-right.svg" alt=""></button>', 230 nextArrow: 231 '<button class="slick-next" aria-label="Next" type="button"><img src="/wp-content/uploads/2024/07/uil-angle-right.svg" alt=""></button>', 232 responsive: [ 233 { 234 breakpoint: 1471, 235 settings: { 236 slidesToShow: 3, 237 }, 238 }, 239 { 240 breakpoint: 782, 241 settings: { 242 slidesToShow: 2, 243 }, 244 }, 245 { 246 breakpoint: 640, 247 settings: { 248 slidesToShow: 1, 249 }, 250 }, 251 ], 252 }); 253 254 // RSS Feed 255 var $rss_slider = $(".rss-carousel"); 256 var $rssprogressBar = $(".rss-carousel-wrap .progress"); 257 var $rssprogressBarLabel = $(".rss-carousel-wrap .slider__label"); 258 259 $rss_slider.on( 260 "beforeChange", 261 function (event, slick, currentSlide, nextSlide) { 262 var calc = (nextSlide / (slick.slideCount - 1)) * 100; 263 $rssprogressBar 264 .css("background-size", calc + "% 100%") 265 .attr("aria-valuenow", calc); 266 $rssprogressBarLabel.text(calc + "% completed"); 267 } 268 ); 269 270 $rss_slider.on("init", function (event, slick) { 271 if (slick.slideCount <= slick.options.slidesToShow) { 272 $rssprogressBar.hide(); 273 } 274 }); 275 276 $rss_slider.slick({ 277 slidesToShow: 4, 278 slidesToScroll: 1, 279 infinite: true, 280 dots: false, 281 arrows: true, 282 autoplay: false, 283 autoplaySpeed: 3000, 284 pauseOnHover: true, 285 prevArrow: 286 '<button class="slick-prev" aria-label="Previous" type="button"><img src="/wp-content/uploads/2024/07/uil-angle-right.svg" alt=""></button>', 287 nextArrow: 288 '<button class="slick-next" aria-label="Next" type="button"><img src="/wp-content/uploads/2024/07/uil-angle-right.svg" alt=""></button>', 289 responsive: [ 290 { 291 breakpoint: 1471, 292 settings: { 293 slidesToShow: 3, 294 }, 295 }, 296 { 297 breakpoint: 782, 298 settings: { 299 slidesToShow: 2, 300 }, 301 }, 302 { 303 breakpoint: 640, 304 settings: { 305 slidesToShow: 1, 306 }, 307 }, 308 ], 309 }); 310 311 // click events 312 $(".static-banner img.close").click(function () { 313 $(this).parent().parent().addClass("clicked"); 314 $(this).parent().parent().slideUp(); 315 }); 316 $("a.copy-link").click(function (event) { 317 $(this).addClass("clicked"); 318 event.preventDefault(); 319 navigator.clipboard.writeText($(this).attr("href")); 320 var self = $(this); 321 setTimeout(function () { 322 self.removeClass("clicked"); 323 }, 2000); 324 }); 325 $(".accordion-item:not(.faq)") 326 .attr("tabindex", "0") 327 .on("click keydown", function (event) { 328 // Check if the event is a click or if it's a keydown for Enter (13) or Space (32) 329 if ( 330 event.type === "click" || 331 (event.type === "keydown" && 332 (event.key === "Enter" || event.key === " ")) 333 ) { 334 var content = $(this).find(".accordion-content"); 335 $(".accordion-content") 336 .not(content) 337 .slideUp() 338 .parent() 339 .removeClass("active"); 340 content.slideToggle().parent().toggleClass("active"); 341 342 // Prevent default action for the Enter and Space keys 343 if (event.type === "keydown") { 344 event.preventDefault(); 345 } 346 } 347 }); 348 $(".image-container").each(function () { 349 var $container = $(this);
350 var imageCount = $container.find(".image-block").length; 351 $container.addClass("image-count-" + imageCount); 352 353 if (imageCount === 1) { 354 $container.find(".caption").show(); 355 } else { 356 $container.find(".caption").hide(); 357 } 358 }); 359 360 const $tabs = $(".awards-tabs .tabs-list a"); 361 const $tabs_mob = $( 362 ".awards-tabs .tabs-list-mobile #trustlaw-awards-tabs-mobile" 363 ); 364 const $contents = $(".awards-block .awards-content .tab-content"); 365 $tabs.first().addClass("active"); 366 $contents.hide().first().addClass("active").show(); 367 $tabs.on("click", function (e) { 368 e.preventDefault(); 369 $tabs.removeClass("active"); 370 $(this).addClass("active"); 371 $contents.removeClass("active").hide(); 372 const tabId = $(this).attr("href"); 373 $(tabId).addClass("active").fadeIn(); 374 }); 375 $tabs_mob.on("change", function () { 376 $contents.removeClass("active").hide(); 377 const tabId = $(this).find(":selected").val(); 378 $(tabId).addClass("active").fadeIn(); 379 }); 380 381 $(".tab-item").on("click", function (e) { 382 e.preventDefault(); 383 var target = $(this).attr("data-tab"); 384 385 $(".tab-item").removeClass("active"); 386 $(this).addClass("active"); 387 388 $(".tab-content").removeClass("active"); 389 $("#" + target).addClass("active"); 390 }); 391 392 $(".people-grid:not(.repeater-grid) .filter-buttons button").on( 393 "click", 394 function () { 395 var $this = $(this); 396 var category = $this.data("category"); 397 if ($this.hasClass("active")) { 398 $this.removeClass("active"); 399 category = "all"; 400 } else { 401 $(".filter-buttons button").removeClass("active"); 402 $this.addClass("active"); 403 } 404 $.ajax({ 405 url: ajaxurl, 406 type: "post", 407 data: { 408 action: "load_people_posts", 409 category: category, 410 }, 411 success: function (response) { 412 $("#people-posts").html(response); 413 }, 414 }); 415 } 416 ); 417 418 $(".people-grid.repeater-grid .filter-buttons button").on( 419 "click", 420 function () { 421 var $this = $(this); 422 var category = $this.data("category"); 423 if ($this.hasClass("active")) { 424 $this.removeClass("active"); 425 category = "all"; 426 } else { 427 $(".filter-buttons button").removeClass("active"); 428 $this.addClass("active"); 429 } 430 $(".people-grid.repeater-grid .post-carousel-item").each(function () { 431 var cat = $(this).attr("data-cat"); 432 433 if (!$(this).hasClass(category)) { 434 $(this).fadeOut(); 435 } else { 436 $(this).fadeIn(); 437 } 438 }); 439 } 440 ); 441 442 $(".news-grid .filter-buttons button").on("click", function () { 443 var $this = $(this); 444 var category = $this.data("category"); 445 if ($this.hasClass("active")) { 446 $this.removeClass("active"); 447 category = "all"; 448 } else { 449 $(".filter-buttons button").removeClass("active"); 450 $this.addClass("active"); 451 } 452 $.ajax({ 453 url: ajaxurl, 454 type: "post", 455 data: { 456 action: "load_latest_news", 457 category: category, 458 }, 459 success: function (response) { 460 $("#latest-news").html(response); 461 }, 462 }); 463 }); 464 465 $(".rss-grid .filter-buttons button").on("click", function () { 466 var category = $(this).data("category"); 467 $(".filter-buttons button").removeClass("active"); 468 $(this).addClass("active"); 469 $.ajax({ 470 url: ajaxurl, 471 type: "post", 472 data: { 473 action: "load_rss_feed", 474 category: category, 475 }, 476 success: function (response) { 477 $("#rss-feed").html(response); 478 }, 479 }); 480 }); 481 482 if ($(".reports-grid").length) { 483 update_pagination(); 484 } 485 486 function load_reports() { 487 $.ajax({ 488 url: ajaxurl, 489 type: "post", 490 data: { 491 action: "load_reports", 492 page: page, 493 }, 494 success: function (response) { 495 $("#reports-container").html(response); 496 update_pagination(); 497 }, 498 }); 499 } 500 501 function update_pagination() { 502 $(".pagination a").on("click", function (e) { 503 e.preventDefault(); 504 page = $(this).data("page"); 505 load_reports(); 506 $("html, body").animate( 507 { 508 scrollTop: $("#reports-container").offset().top - 165, 509 }, 510 500 511 ); 512 }); 513 } 514 515 $("div:not(#reports-container) > .pagination a.page-num").each(function () { 516 if ($(this).data("page") == page) { 517 $(this).addClass("active"); 518 } else { 519 $(this).removeClass("active"); 520 } 521 }); 522 523 // if ($(".partners-grid").length) { 524 // load_partners() 525 // } 526 527 // function load_partners() { 528 // $.ajax({ 529 // url: ajaxurl, 530 // type: "post", 531 // data: { 532 // action: "load_partners_posts" 533 // }, 534 // success: function (response) { 535 // $("#partners-posts").html(response) 536 // } 537 // }) 538 // } 539 540 lightbox(); 541 function lightbox() { 542 $(".open-lightbox").click(function () { 543 close_all_lightboxes(); 544 var target = $(this).attr("data-lb"); 545 $('.trf-lightbox[data-lb="' + target + '"]').fadeIn(); 546 }); 547 $(".close-lightbox, .lightbox-overlay").click(function () { 548 close_all_lightboxes(); 549 }); 550 function close_all_lightboxes() { 551 $(".trf-lightbox").fadeOut(); 552 } 553 $(document).keyup(function (e) { 554 if (e.key === "Escape") { 555 close_all_lightboxes(); 556 } 557 }); 558 } 559 560 $(document).on("algolia_rendered", function () { 561 $("select.ais-MenuSelect-select").each(function () { 562 var element = $(this); 563 element.selectmenu({ 564 change: function (event, ui) { 565 // Trigger change on the original select element 566 element.val(ui.item.value); 567 568 // Create and dispatch an 'input' event 569 var inputEvent = new Event("input", { 570 bubbles: true, 571 cancelable: true, 572 }); 573 var changeEvent = new Event("change", { 574 bubbles: true, 575 cancelable: true, 576 }); 577 element[0].dispatchEvent(inputEvent); 578 element[0].dispatchEvent(changeEvent); 579 }, 580 }); 581 }); 582 583 $("select.ais-SortBy-select").each(function () { 584 var element = $(this); 585 586 element.selectmenu({ 587 change: function (event, ui) { 588 element.val(ui.item.value).trigger("change"); 589 searchHelper.setIndex(element.val()).search(); 590 }, 591 create: function (event, ui) { 592 // Get the button after creation 593 var button = $(this).selectmenu("widget"); 594 595 // Remove the competing aria attributes 596 button.removeAttr("aria-labelledby"); 597 598 // Optional: if you want to keep the aria-label on the button 599 button.attr("aria-label", "Sort By"); 600 601 // Force an observer to maintain these attributes 602 var observer = new MutationObserver(function (mutations) { 603 button.removeAttr("aria-labelledby"); 604 }); 605 606 observer.observe(button[0], { 607 attributes: true, 608 attributeFilter: ["aria-labelledby"], 609 }); 610 }, 611 }); 612 }); 613 614 $("li.ais-Hits-item, li.ais-InfiniteHits-item").each(function () { 615 var link = $(this).find("a").attr("href"); 616 if (link) { 617 $(this).css("cursor", "pointer"); 618 $(this).on("click", function () { 619 window.location.href = link; 620 }); 621 } 622 }); 623 }); 624 625 $( 626 "#jumplinks-dropdown, #trustlaw-awards-tabs-mobile, #download-selector, #awards-dropdown" 627 ).each(function () { 628 var element = $(this); 629 element.selectmenu({ 630 change: function (event, ui) { 631 element.val(ui.item.value); 632 var inputEvent = new Event("input", { 633 bubbles: true, 634 cancelable: true, 635 }); 636 var changeEvent = new Event("change", { 637 bubbles: true, 638 cancelable: true, 639 }); 640 element[0].dispatchEvent(inputEvent); 641 element[0].dispatchEvent(changeEvent); 642 }, 643 }); 644 }); 645 646 $(".wp-block-columns.link-parent, .wp-block-column.link-parent").each( 647 function () { 648 var link = $(this).find("a").not(".button, .custom-btn").attr("href"); 649 if (link) { 650 $(this).css("cursor", "pointer"); 651 $(this).on("click", function () { 652 window.location.href = link; 653 }); 654 } 655 } 656 ); 657 658 var a = 0; 659 $(window).scroll(function () { 660 if ($(".statistic").length) { 661 var oTop = $(".statistic").offset().top - window.innerHeight; 662 if (a == 0 && $(window).scrollTop() > oTop) { 663 $(".statistic").each(function () { 664 var $this = $(this).find(".count"); 665 var countTo = $this.attr("data-count"); 666 667 // Check if reduced motion is enabled 668 if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) { 669 // Directly set the final count value 670 $this.text(countTo); 671 } else { 672 // Proceed with the animation 673 $({ 674 countNum: $this.text(), 675 }).animate( 676 { 677 countNum: countTo, 678 }, 679 { 680 duration: 2000,
681 easing: "swing", 682 step: function () { 683 $this.text(addCommas(Math.floor(this.countNum))); 684 }, 685 complete: function () { 686 $this.text(addCommas(this.countNum)); // Ensure final value is set 687 }, 688 } 689 ); 690 } 691 }); 692 a = 1; 693 } 694 } 695 }); 696 function addCommas(n) { 697 return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 698 } 699 700 if (document.querySelector(".underline-hover")) { 701 document.querySelectorAll(".underline-hover a").forEach((link) => { 702 let content = link.innerHTML; 703 704 // Extract the icon 705 let icon = content.match(/^[^a-zA-Z]*[^a-zA-Z]+/); 706 707 // Extract the text 708 let text = content.replace(icon, "").trim(); 709 710 // Rebuild the content with the icon and a span wrapping the text 711 link.innerHTML = `${icon ? icon[0] : ""}<span>${text}</span>`; 712 }); 713 } 714 715 if (window.matchMedia("(max-width: 500px)").matches) { 716 if (document.querySelector(".algolia-inner-search span.button")) { 717 document 718 .querySelector(".algolia-inner-search span.button") 719 .addEventListener("click", function () { 720 document 721 .querySelector("#ais-main") 722 .scrollIntoView({ behavior: "smooth" }); 723 }); 724 } 725 } 726 727 // fake linking 728 $( 729 ".rss-Hit-item, .highlight-hit-box, .manual-card-hit, .post-carousel-item-hit" 730 ).each(function () { 731 var link = $(this).find("a").attr("href"); 732 // console.log(link) 733 if (link) { 734 $(this).css("cursor", "pointer"); 735 $(this).on("click", function () { 736 window.location.href = link; 737 }); 738 } 739 }); 740}); 741 742jQuery(document).ready(function ($) { 743 // Create an observer instance linked to a callback function 744 var observer = new MutationObserver(function (mutationsList, observer) { 745 mutationsList.forEach(function (mutation) { 746 if (mutation.type === "childList") { 747 // Check if the dynamically added element exists 748 var $select = $("#sgE-7952946-1-7-element"); 749 if ($select.length && !$select.data("selectmenu-applied")) { 750 // Initialize the selectmenu 751 $select.selectmenu(); 752 // Mark the select element to avoid re-initialization 753 $select.data("selectmenu-applied", true); 754 } 755 } 756 }); 757 }); 758 759 // Specify which element you want to observe (the parent container) 760 var targetNode = document.body; // Can be more specific if you know the parent container 761 var config = { childList: true, subtree: true }; // Observe direct children and subtree 762 763 // Start observing the target node for configured mutations 764 observer.observe(targetNode, config); 765 766 /*------ 767 In impact story removes em tag for 1st paragraph 768 ------*/ 769 if (document.querySelector(".single-impact-story .wp-block-column")) { 770 function removeEmFromFirstP(parentSelector) { 771 const $firstP = $(parentSelector).find("p:first"); 772 773 if ($firstP.children(":first").is("em")) { 774 const emContent = $firstP.children("em").html(); 775 $firstP.html(emContent); 776 } 777 } 778 removeEmFromFirstP(".single-impact-story .wp-block-column"); 779 } 780}); 781 782// Accessible awards tabs 783jQuery(document).ready(function ($) { 784 const $tabs = $(".awards-tabs .tabs-list a"); 785 const $tabPanels = $(".awards-tabs .tab-content"); 786 787 function handleTabClick(event) { 788 event.preventDefault(); 789 const $selectedTab = $(this); 790 const selectedPanelId = $selectedTab.attr("aria-controls"); 791 792 // Update all tabs 793 $tabs.attr("aria-selected", "false").attr("tabindex", "-1"); 794 795 // Set the selected tab 796 $selectedTab.attr("aria-selected", "true").attr("tabindex", "0").focus(); 797 798 // Hide all tab panels 799 $tabPanels.attr("aria-hidden", "true"); 800 801 // Show the selected panel 802 $("#" + selectedPanelId).attr("aria-hidden", "false"); 803 } 804 805 function activateTab(index) { 806 $tabs.eq(index).trigger("click"); 807 } 808 809 function focusNextTab(currentIndex) { 810 const newIndex = (currentIndex + 1) % $tabs.length; 811 activateTab(newIndex); 812 } 813 814 function focusPreviousTab(currentIndex) { 815 const newIndex = (currentIndex - 1 + $tabs.length) % $tabs.length; 816 activateTab(newIndex); 817 } 818 819 $tabs.on("click", handleTabClick); 820 821 $tabs.on("keydown", function (e) { 822 const currentIndex = $tabs.index(this); 823 switch (e.key) { 824 case "ArrowRight": 825 focusNextTab(currentIndex); 826 break; 827 case "ArrowLeft": 828 focusPreviousTab(currentIndex); 829 break; 830 case "Tab": 831 if (!e.shiftKey && isLastFocusableElementInPanel($(this))) { 832 e.preventDefault(); 833 focusNextTab(currentIndex); 834 } 835 break; 836 } 837 }); 838 839 $tabPanels.on("keydown", "a, button, input, textarea, select", function (e) { 840 const $panel = $(this).closest(".tab-content"); 841 const $lastFocusable = $panel 842 .find("a, button, input, textarea, select") 843 .last(); 844 845 if (e.key === "Tab" && !e.shiftKey && $(this).is($lastFocusable)) { 846 e.preventDefault(); 847 const currentIndex = $tabs.index($tabs.filter('[aria-selected="true"]')); 848 focusNextTab(currentIndex); 849 } 850 }); 851 852 function isLastFocusableElementInPanel($element) { 853 const $panel = $element.closest(".tab-content"); 854 const $lastFocusable = $panel 855 .find("a, button, input, textarea, select") 856 .last(); 857 return $element.is($lastFocusable); 858 } 859}); 860 861// Accessible nav 862jQuery(document).ready(function ($) { 863 const menuItemsWithDropdowns = $(".menu-item.has-child"); 864 865 // Function to add show-dropdown class and expand dropdown 866 function showDropdown(menuItem) { 867 menuItem.addClass("show-dropdown"); 868 menuItem.find("> a").attr("aria-expanded", "true"); 869 } 870 871 // Function to remove show-dropdown class and collapse dropdown 872 function hideDropdown(menuItem) { 873 menuItem.removeClass("show-dropdown"); 874 menuItem.find("> a").attr("aria-expanded", "false"); 875 } 876 877 menuItemsWithDropdowns.each(function () { 878 const menuItem = $(this); 879 const parentLink = menuItem.find("> a"); 880 const dropdownLinks = menuItem.find(".trf-dropdown a"); 881 882 // Focus first submenu link when tabbing from the parent link 883 parentLink.on("keydown", function (e) { 884 if (e.key === "Tab" && !e.shiftKey) { 885 e.preventDefault(); 886 showDropdown(menuItem); 887 dropdownLinks.first().focus(); 888 } 889 }); 890
891 // Keep dropdown open when focusing within the submenu 892 dropdownLinks.on("focusin", function () { 893 showDropdown(menuItem); 894 }); 895 896 // Handle shift+Tab on first submenu link to return focus to parent link 897 dropdownLinks.first().on("keydown", function (e) { 898 if (e.key === "Tab" && e.shiftKey) { 899 e.preventDefault(); 900 hideDropdown(menuItem); 901 parentLink.focus(); 902 } 903 }); 904 905 // Hide dropdown when focus leaves all elements inside .trf-dropdown 906 menuItem.find(".trf-dropdown").on("focusout", function () { 907 setTimeout(function () { 908 if (!menuItem.find(":focus").length) { 909 hideDropdown(menuItem); 910 } 911 }, 0); 912 }); 913 }); 914 915 // Close all dropdowns when clicking outside 916 $(document).on("click", function (e) { 917 if (!$(e.target).closest(".menu-item").length) { 918 menuItemsWithDropdowns.each(function () { 919 hideDropdown($(this)); 920 }); 921 } 922 }); 923}); 924 925jQuery(document).ready(function ($) { 926 var copyLinkButton = $(".social-sharing button.copy-link"); 927 var copyLinkMessage = $("#copy-link-message"); 928 var linkToCopy = window.location.href; // Use current page URL 929 930 copyLinkButton.on("click", function (event) { 931 event.preventDefault(); 932 if (navigator.clipboard && navigator.clipboard.writeText) { 933 navigator.clipboard 934 .writeText(linkToCopy) 935 .then(function () { 936 // Copy successful 937 copyLinkButton.addClass("clicked"); 938 copyLinkMessage.text("Copied link to Clipboard"); 939 setTimeout(function () { 940 copyLinkButton.removeClass("clicked"); 941 copyLinkMessage.text(""); 942 }, 2000); 943 }) 944 .catch(function (err) { 945 console.error("Could not copy text: ", err); 946 }); 947 } else { 948 // Fallback for unsupported browsers 949 var tempInput = $("<input>"); 950 $("body").append(tempInput); 951 tempInput.val(linkToCopy).select(); 952 document.execCommand("copy"); 953 tempInput.remove(); 954 955 copyLinkButton.addClass("clicked"); 956 copyLinkMessage.text("Copied link to Clipboard"); 957 setTimeout(function () { 958 copyLinkButton.removeClass("clicked"); 959 copyLinkMessage.text(""); 960 }, 2000); 961 } 962 }); 963}); 964 965// Accessible tabs 966jQuery(document).ready(function ($) { 967 const $tabs = $( 968 "div:not(.awards-tabs) .tabs-list .tab-link, .flourish-tabs .tab-link" 969 ); 970 const $tabPanels = $( 971 "div:not(.awards-tabs) .tabs-content .tab-content, .flourish-tabs .tab-content" 972 ); 973 974 // Initialize tabs 975 $tabs.each(function (index) { 976 const $tab = $(this); 977 $tab.on("click", handleTabClick); 978 $tab.on("keydown", handleTabKeyDown); 979 }); 980 981 $tabPanels.each(function () { 982 const $panel = $(this); 983 $panel.on( 984 "keydown", 985 "a, button, input, textarea, select", 986 handlePanelKeyDown 987 ); 988 }); 989 990 function handleTabClick(event) { 991 event.preventDefault(); 992 const $selectedTab = $(this); 993 const selectedPanelId = $selectedTab.attr("aria-controls"); 994 995 // Update all tabs 996 $tabs 997 .attr("aria-selected", "false") 998 .attr("tabindex", "-1") 999 .parent() 1000 .removeClass("active"); 1001 1002 // Set the selected tab 1003 $selectedTab 1004 .attr("aria-selected", "true") 1005 .attr("tabindex", "0") 1006 .parent() 1007 .addClass("active") 1008 .focus(); 1009 1010 // Hide all tab panels 1011 $tabPanels.attr("hidden", "hidden").attr("aria-hidden", "true"); 1012 1013 // Show the selected panel 1014 $("#" + selectedPanelId) 1015 .removeAttr("hidden") 1016 .attr("aria-hidden", "false"); 1017 } 1018 1019 function handleTabKeyDown(event) { 1020 const key = event.key; 1021 const $currentTab = $(this); 1022 const currentIndex = $tabs.index($currentTab); 1023 1024 switch (key) { 1025 case "ArrowRight": 1026 case "ArrowDown": 1027 if (currentIndex < $tabs.length - 1) { 1028 focusNextTab(currentIndex); 1029 } 1030 break; 1031 1032 case "ArrowLeft": 1033 case "ArrowUp": 1034 if (currentIndex > 0) { 1035 focusPreviousTab(currentIndex); 1036 } 1037 break; 1038 1039 case "Home": 1040 focusTab(0); 1041 break; 1042 1043 case "End": 1044 focusTab($tabs.length - 1); 1045 break; 1046 1047 case "Enter": 1048 case " ": 1049 handleTabClick.call(this, event); 1050 break; 1051 1052 case "Tab": 1053 if (!event.shiftKey) { 1054 const $selectedPanel = $("#" + $currentTab.attr("aria-controls")); 1055 const $firstFocusable = getFirstFocusableElement($selectedPanel); 1056 1057 if ($firstFocusable.length) { 1058 event.preventDefault(); 1059 $firstFocusable.focus(); 1060 } 1061 } 1062 break; 1063 1064 default: 1065 break; 1066 } 1067 } 1068 1069 function handlePanelKeyDown(event) {
1070 const key = event.key; 1071 const $currentElement = $(this); 1072 const $panel = $currentElement.closest(".tab-content"); 1073 const $focusableElements = getFocusableElements($panel); 1074 const currentIndex = $focusableElements.index($currentElement); 1075 1076 if ( 1077 key === "Tab" && 1078 !event.shiftKey && 1079 currentIndex === $focusableElements.length - 1 1080 ) { 1081 // If it's the last focusable element in the panel 1082 const $currentTab = $tabs.filter('[aria-selected="true"]'); 1083 const currentTabIndex = $tabs.index($currentTab); 1084 1085 if (currentTabIndex < $tabs.length - 1) { 1086 // Not the last tab, move to the next tab 1087 event.preventDefault(); 1088 focusNextTab(currentTabIndex); 1089 } else { 1090 } 1091 } else if (key === "Tab" && event.shiftKey && currentIndex === 0) { 1092 // If it's the first focusable element and Shift+Tab is pressed 1093 event.preventDefault(); 1094 const $currentTab = $tabs.filter('[aria-selected="true"]'); 1095 $currentTab.focus(); 1096 } 1097 } 1098 1099 function focusNextTab(currentIndex) { 1100 if (currentIndex < $tabs.length - 1) { 1101 $tabs.eq(currentIndex + 1).focus(); 1102 } else { 1103 } 1104 } 1105 1106 function focusPreviousTab(currentIndex) { 1107 if (currentIndex > 0) { 1108 $tabs.eq(currentIndex - 1).focus(); 1109 } else { 1110 } 1111 } 1112 1113 function focusTab(index) { 1114 $tabs.eq(index).focus(); 1115 } 1116 1117 function getFocusableElements($container) { 1118 return $container 1119 .find( 1120 'a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])' 1121 ) 1122 .filter(":visible"); 1123 } 1124 1125 function getFirstFocusableElement($container) { 1126 return getFocusableElements($container).first(); 1127 } 1128 1129 // Initialize the first tab and panel 1130 $tabs 1131 .first() 1132 .attr("aria-selected", "true") 1133 .attr("tabindex", "0") 1134 .parent() 1135 .addClass("active"); 1136 $tabPanels.first().removeAttr("hidden").attr("aria-hidden", "false"); 1137});
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.