1"use strict"; 2 3(function ($, win, doc) { 4 if (!$ || typeof $.fn.slick !== "function") return; 5 const reduceMotion = 6 typeof win.matchMedia === "function" && 7 win.matchMedia("(prefers-reduced-motion: reduce)").matches; 8 const TAB_SYNC_BP = 1199; 9 10 /** @param {number} width */ 11 function isDesktopTabs(width) { 12 return width > TAB_SYNC_BP; 13 } 14 15 /** @param {Element | null | undefined} tabEl */ 16 function scrollTabStripToTabLeft(tabEl) { 17 if (!tabEl || typeof tabEl.closest !== "function") return; 18 var strip = tabEl.closest(".js-pol-tabs-nav"); 19 if (!strip || strip.scrollWidth <= strip.clientWidth + 1) return; 20 21 var tabRect = tabEl.getBoundingClientRect(); 22 var stripRect = strip.getBoundingClientRect(); 23 var padLeft = 24 parseFloat(win.getComputedStyle(strip).paddingLeft || "0") || 0; 25 26 var delta = tabRect.left - stripRect.left - padLeft; 27 var target = strip.scrollLeft + delta; 28 var maxScroll = Math.max(0, strip.scrollWidth - strip.clientWidth); 29 target = Math.max(0, Math.min(target, maxScroll)); 30 31 strip.scrollTo({ 32 left: target, 33 behavior: reduceMotion ? "auto" : "smooth", 34 }); 35 } 36 37 /** @param {JQuery<Element>} $slider */ 38 function initNestedTabSlider($slider) { 39 if (!$slider.length || $slider.attr("data-nested") !== "1") return; 40 41 var $wrap = $slider.closest(".tab-sliders--nested"); 42 var $prev = $wrap.find(".js-pol-tab-slider-prev"); 43 var $next = $wrap.find(".js-pol-tab-slider-next"); 44 45 if ($slider.hasClass("slick-initialized")) { 46 $slider.slick("setPosition"); 47 return; 48 } 49 50 $slider.slick({ 51 slidesToShow: 1, 52 slidesToScroll: 1, 53 infinite: false, 54 speed: reduceMotion ? 0 : 280, 55 arrows: Boolean($prev.length && $next.length), 56 appendArrows: $wrap.find(".tab-sliders__nav--nested").length 57 ? $wrap.find(".tab-sliders__nav--nested") 58 : undefined, 59 prevArrow: $prev.length ? $prev : undefined, 60 nextArrow: $next.length ? $next : undefined, 61 swipe: false, 62 draggable: false, 63 }); 64 } 65 66 /** @param {JQuery<Element>} $root */ 67 function syncNestedTabSliders($root) { 68 var desktop = isDesktopTabs(win.innerWidth); 69 70 $root.find('.js-pol-tab-slider[data-nested="1"]').each(function () { 71 var $slider = $(this); 72 if (!desktop) { 73 if ($slider.hasClass("slick-initialized")) { 74 $slider.slick("unslick"); 75 } 76 return; 77 } 78 initNestedTabSlider($slider); 79 }); 80 } 81 82 /** @param {JQuery<Element>} $root */ 83 function initPolTabs($root) { 84 var $nav = $root.find(".js-pol-tabs-nav"); 85 var $content = $root.find(".js-pol-tabs-for"); 86 var $tabs = $root.find('[role="tab"]'); 87 var $panels = $content.find('[role="tabpanel"]'); 88 var $arrowHost = $content.siblings(".tab-sliders__nav").first(); 89 var $prev = $root.find(".js-pol-tabs-prev"); 90 var $next = $root.find(".js-pol-tabs-next"); 91 var resizeTimer = null; 92 93 if (!$nav.length || !$content.length || !$tabs.length) return; 94 95 /** @param {number} index */ 96 function updateAria(index) { 97 $tabs.each(function (i) { 98 var selected = i === index; 99 $(this) 100 .attr("aria-selected", selected ? "true" : "false") 101 .attr("tabindex", selected ? "0" : "-1"); 102 }); 103 $panels.each(function (i) { 104 $(this).attr("aria-hidden", i === index ? "false" : "true"); 105 }); 106 } 107 108 /** @param {number} index */ 109 /** @param {boolean} [animate] */ 110 function goToSlide(index, animate) { 111 if (!$content.hasClass("slick-initialized")) return; 112 var max = $tabs.length - 1; 113 var next = Math.max(0, Math.min(index, max)); 114 $content.slick("slickGoTo", next, animate === false); 115 updateAria(next); 116 if (isDesktopTabs(win.innerWidth)) { 117 var $panel = $($panels.get(next)); 118 initNestedTabSlider($panel.find('.js-pol-tab-slider[data-nested="1"]')); 119 } 120 } 121 122 function initContentSlider() { 123 if ($content.hasClass("slick-initialized")) return; 124 125 var mobile = !isDesktopTabs(win.innerWidth); 126 127 $content.slick({ 128 slidesToShow: 1, 129 slidesToScroll: 1, 130 infinite: false, 131 speed: reduceMotion ? 0 : 280, 132 arrows: mobile && Boolean($prev.length && $next.length), 133 appendArrows: $arrowHost.length ? $arrowHost : undefined, 134 prevArrow: $prev.length ? $prev : undefined, 135 nextArrow: $next.length ? $next : undefined, 136 swipe: mobile, 137 draggable: mobile, 138 }); 139 140 $content.on("afterChange.polTabs", function (_evt, _slick, currentSlide) { 141 updateAria(currentSlide); 142 var tab = $tabs.get(currentSlide); 143 if (tab) scrollTabStripToTabLeft(tab); 144 if (isDesktopTabs(win.innerWidth)) { 145 var $panel = $($panels.get(currentSlide)); 146 initNestedTabSlider($panel.find('.js-pol-tab-slider[data-nested="1"]')); 147 } 148 }); 149 } 150 151 function syncMode() { 152 initContentSlider(); 153 154 if (!$content.hasClass("slick-initialized")) return; 155 156 var desktop = isDesktopTabs(win.innerWidth); 157 $content.slick( 158 "slickSetOption", 159 "arrows", 160 !desktop && Boolean($prev.length && $next.length), 161 true 162 ); 163 $content.slick("slickSetOption", "swipe", !desktop, false); 164 $content.slick("slickSetOption", "draggable", !desktop, false); 165 $content.slick("setPosition"); 166 syncNestedTabSliders($root); 167 168 if (desktop) { 169 var activeIndex = $tabs.index( 170 $tabs.filter('[aria-selected="true"]').first() 171 ); 172 if (activeIndex < 0) activeIndex = 0; 173 var $panel = $($panels.get(activeIndex)); 174 initNestedTabSlider($panel.find('.js-pol-tab-slider[data-nested="1"]')); 175 } 176 } 177 178 $tabs.on("click.polTabs", function () { 179 var $btn = $(this); 180 var index = $tabs.index(this); 181 if ( 182 $btn.attr("aria-selected") === "true" && 183 isDesktopTabs(win.innerWidth) 184 ) { 185 return; 186 } 187 188 goToSlide(index); 189 win.requestAnimationFrame(function () { 190 scrollTabStripToTabLeft($btn[0]); 191 }); 192 }); 193 194 $tabs.on("keydown.polTabs", function (evt) { 195 var i = $tabs.index(this); 196 var max = $tabs.length - 1; 197 var nextIndex = null; 198 if (evt.key === "ArrowRight" || evt.key === "ArrowDown") 199 nextIndex = Math.min(max, i + 1); 200 else if (evt.key === "ArrowLeft" || evt.key === "ArrowUp") 201 nextIndex = Math.max(0, i - 1); 202 else if (evt.key === "Home") nextIndex = 0; 203 else if (evt.key === "End") nextIndex = max; 204 205 if (nextIndex === null || nextIndex === i) return; 206 evt.preventDefault(); 207 $($tabs[nextIndex]).focus().trigger("click"); 208 }); 209 210 syncMode(); 211 212 $(win).on("resize.polTabs", function () { 213 win.clearTimeout(resizeTimer); 214 resizeTimer = win.setTimeout(syncMode, 150); 215 }); 216 } 217 218 $(function () { 219 $(".js-pol-tabs").each(function () { 220 initPolTabs($(this)); 221 }); 222 }); 223})(typeof jQuery !== "undefined" ? jQuery : null, window, document); 224 225(function ($, win) { 226 if (!$ || typeof $.fn.slick !== "function") return; 227 228 var LOGO_SLIDER_BP_TABLET = 751; 229 var LOGO_SLIDER_BP_DESKTOP = 992; 230 var logoSliderInstanceCount = 0; 231 var reduceMotion = 232 typeof win.matchMedia === "function" && 233 win.matchMedia("(prefers-reduced-motion: reduce)").matches; 234 235 /** @param {number} width */ 236 function getLogoSlidesToShow(width) { 237 if (width < LOGO_SLIDER_BP_TABLET) return 1; 238 if (width < LOGO_SLIDER_BP_DESKTOP) return 3; 239 return 4; 240 } 241 242 /** @param {number} width */ 243 function isDesktopLogoViewport(width) { 244 return width >= LOGO_SLIDER_BP_DESKTOP; 245 } 246 247 /** @param {JQuery<Element>} $root */ 248 function initThreeColDisplayLogo($root) { 249 var $track = $root.find(".js-three-col-logo-grid"); 250 var $prev = $root.find(".js-three-col-logo-prev"); 251 var $next = $root.find(".js-three-col-logo-next");
252 var $nav = $root.find(".three-col-display__logo-nav"); 253 var slideCount = $root.find(".three-col-display__column").length; 254 var autoplay = 255 String($root.data("logo-autoplay")) === "1" || 256 $root.data("logo-autoplay") === 1; 257 var resizeTimer = null; 258 var instanceId = ++logoSliderInstanceCount; 259 var resizeNs = ".threeColLogo-" + instanceId; 260 261 if (!$track.length) return; 262 263 function mountSlider() { 264 if ($track.hasClass("slick-initialized")) return; 265 266 $track.slick({ 267 slidesToShow: 4, 268 slidesToScroll: 1, 269 infinite: false, 270 speed: reduceMotion ? 0 : 280, 271 arrows: Boolean($prev.length && $next.length), 272 appendArrows: $nav.length ? $nav : undefined, 273 prevArrow: $prev.length ? $prev : undefined, 274 nextArrow: $next.length ? $next : undefined, 275 swipe: true, 276 draggable: true, 277 responsive: [ 278 { 279 breakpoint: LOGO_SLIDER_BP_DESKTOP, 280 settings: { 281 slidesToShow: 3, 282 slidesToScroll: 1, 283 }, 284 }, 285 { 286 breakpoint: LOGO_SLIDER_BP_TABLET, 287 settings: { 288 slidesToShow: 1, 289 slidesToScroll: 1, 290 }, 291 }, 292 ], 293 }); 294 } 295 296 function unmountSlider() { 297 if (!$track.hasClass("slick-initialized")) return; 298 $track.slick("unslick"); 299 } 300 301 function syncMode() { 302 mountSlider(); 303 304 if (!$track.hasClass("slick-initialized")) return; 305 306 var slidesToShow = getLogoSlidesToShow(win.innerWidth); 307 var needsInteraction = slideCount > slidesToShow; 308 var hasArrows = slideCount > 1 && Boolean($prev.length && $next.length); 309 var shouldAutoplay = 310 autoplay && 311 !reduceMotion && 312 needsInteraction && 313 isDesktopLogoViewport(win.innerWidth); 314 315 $root.toggleClass("is-logo-nav-needed", needsInteraction && hasArrows); 316 $track.slick("slickSetOption", "arrows", needsInteraction && hasArrows, true); 317 $track.slick("slickSetOption", "swipe", needsInteraction, false); 318 $track.slick("slickSetOption", "draggable", needsInteraction, false); 319 $track.slick("slickSetOption", "infinite", shouldAutoplay, true); 320 $track.slick("slickSetOption", "autoplay", shouldAutoplay, true); 321 $track.slick("slickSetOption", "autoplaySpeed", 5000, false); 322 $track.slick("slickSetOption", "pauseOnHover", true, false); 323 $track.slick("slickSetOption", "pauseOnFocus", true, false); 324 $track.slick("setPosition"); 325 326 if (shouldAutoplay) { 327 $track.slick("slickPlay"); 328 } else { 329 $track.slick("slickPause"); 330 } 331 } 332 333 syncMode(); 334 335 $(win).on("resize" + resizeNs, function () { 336 win.clearTimeout(resizeTimer); 337 resizeTimer = win.setTimeout(syncMode, 150); 338 }); 339 340 $root.data("threeColLogoCleanup", function () { 341 $(win).off(resizeNs); 342 if (resizeTimer) win.clearTimeout(resizeTimer); 343 $root.removeClass("is-logo-nav-needed"); 344 unmountSlider(); 345 }); 346 } 347 348 $(function () { 349 $(".js-three-col-display--logo").each(function () { 350 initThreeColDisplayLogo($(this)); 351 }); 352 }); 353})(typeof jQuery !== "undefined" ? jQuery : null, window); 354 355(function ($, win) { 356 if (!$) return; 357 358 var reduceMotion = 359 typeof win.matchMedia === "function" && 360 win.matchMedia("(prefers-reduced-motion: reduce)").matches; 361 362 $(function () { 363 $(".js-drawers-accordion").each(function () { 364 var $root = $(this); 365 var $items = $root.find(".drawers__item"); 366 var duration = reduceMotion ? 0 : 300; 367 368 $root.find(".drawers__trigger").on("click", function () { 369 var $btn = $(this); 370 var $item = $btn.closest(".drawers__item"); 371 var $panel = $item.find(".drawers__panel"); 372 var isOpen = $btn.attr("aria-expanded") === "true"; 373 374 if (!$panel.length) return; 375 376 if (isOpen) { 377 $btn.attr("aria-expanded", "false"); 378 $item.removeClass("drawers__item--open"); 379 $panel.stop(true, true).slideUp(duration, function () { 380 $panel.attr("hidden", ""); 381 }); 382 return; 383 } 384 385 $items.not($item).each(function () { 386 var $other = $(this); 387 var $otherBtn = $other.find(".drawers__trigger"); 388 var $otherPanel = $other.find(".drawers__panel"); 389 390 if ($otherBtn.attr("aria-expanded") !== "true") { 391 return; 392 } 393 394 $otherBtn.attr("aria-expanded", "false"); 395 $other.removeClass("drawers__item--open");
396 $otherPanel.stop(true, true).slideUp(duration, function () { 397 $otherPanel.attr("hidden", ""); 398 }); 399 }); 400 401 $btn.attr("aria-expanded", "true"); 402 $item.addClass("drawers__item--open"); 403 $panel.removeAttr("hidden"); 404 $panel.stop(true, true).slideDown(duration); 405 }); 406 }); 407 }); 408})(typeof jQuery !== "undefined" ? jQuery : null, window); 409 410(function ($, win, doc) { 411 if (!$) return; 412 413 function polBiosIsEditorContext() { 414 if (doc.body.classList.contains("block-editor-page")) { 415 return true; 416 } 417 if (doc.body.classList.contains("wp-admin")) { 418 return true; 419 } 420 if ($(".bios--editor-preview").length) { 421 return true; 422 } 423 return false; 424 } 425 426 /** @param {JQuery<Element>} $root */ 427 function closeBioDialog($root) { 428 var $dialog = $root.find(".js-bios-dialog"); 429 var $overlay = $root.find(".js-bios-overlay"); 430 431 $root.removeClass("bios--open"); 432 $dialog.attr("hidden", ""); 433 $overlay.attr("hidden", "").attr("aria-hidden", "true"); 434 doc.body.classList.remove("bios-modal-open"); 435 $(doc).off("keydown.bios"); 436 437 var $trigger = $root.data("bios-last-trigger"); 438 if ($trigger && $trigger.length) { 439 $trigger.trigger("focus"); 440 } 441 } 442 443 /** @param {JQuery<Element>} $root @param {JQuery<Element>} $card */ 444 function openBioDialog($root, $card) { 445 var $dialog = $root.find(".js-bios-dialog");
446 var $overlay = $root.find(".js-bios-overlay"); 447 var name = $card.data("bio-name") || ""; 448 var title = $card.data("bio-title") || ""; 449 var organization = $card.data("bio-organization") || ""; 450 var image = $card.data("bio-image") || ""; 451 var alt = $card.data("bio-alt") || ""; 452 var linkedin = $card.data("bio-linkedin") || ""; 453 var email = $card.data("bio-email") || ""; 454 var bioId = $card.data("bio-id"); 455 456 $root.find(".js-bios-dialog-name").text(name); 457 458 var $dialogTitle = $root.find(".js-bios-dialog-title"); 459 if (title) { 460 $dialogTitle.text(title).removeAttr("hidden"); 461 } else { 462 $dialogTitle.text("").attr("hidden", ""); 463 } 464 465 var $dialogOrg = $root.find(".js-bios-dialog-organization"); 466 if (organization) { 467 $dialogOrg.text(organization).removeAttr("hidden"); 468 } else { 469 $dialogOrg.text("").attr("hidden", ""); 470 } 471 472 var $copy = $root.find(".js-bios-dialog-copy"); 473 var $bioSource = bioId ? $root.find("#bios-bio-" + bioId) : $(); 474 if ($bioSource.length) { 475 $copy.html($bioSource.html()); 476 } else { 477 $copy.empty(); 478 } 479 480 var $photo = $root.find(".js-bios-dialog-photo"); 481 var $photoWrap = $photo.closest(".bios__dialog-media"); 482 if ($photo.length && image) { 483 $photo.attr("src", image).attr("alt", alt); 484 $photoWrap.removeAttr("hidden"); 485 } else if ($photoWrap.length) { 486 $photo.attr("src", "").attr("alt", ""); 487 $photoWrap.attr("hidden", ""); 488 } 489 490 var $social = $root.find(".js-bios-dialog-social"); 491 var $socialList = $social.find(".bios__social-list"); 492 var emailIcon = $social.data("email-icon") || ""; 493 var linkedinIcon = $social.data("linkedin-icon") || ""; 494 495 if (email) { 496 var $emailItem = $socialList.find(".js-bios-social-email"); 497 if (!$emailItem.length) { 498 $socialList.append( 499 '<li class="bios__social-item js-bios-social-email">' + 500 '<a class="bios__social-link" href="mailto:' + 501 email + 502 '" title="Email ' + 503 name + 504 '">' + 505 '<figure class="bios__social-icon" aria-hidden="true">' + 506 '<img src="' + 507 emailIcon + 508 '" alt="" width="21" height="17" decoding="async" />' + 509 "</figure></a></li>" 510 ); 511 } else { 512 $emailItem 513 .find("a") 514 .attr("href", "mailto:" + email) 515 .attr("title", "Email " + name); 516 } 517 } else { 518 $socialList.find(".js-bios-social-email").remove(); 519 } 520 521 if (linkedin) { 522 var $linkedinItem = $socialList.find(".js-bios-social-linkedin"); 523 if (!$linkedinItem.length) { 524 $socialList.append( 525 '<li class="bios__social-item js-bios-social-linkedin">' + 526 '<a class="bios__social-link" href="' + 527 linkedin + 528 '" target="_blank" rel="noopener noreferrer" title="View ' + 529 name + 530 ' on LinkedIn">' + 531 '<figure class="bios__social-icon" aria-hidden="true">' + 532 '<img src="' + 533 linkedinIcon + 534 '" alt="" width="18" height="18" decoding="async" />' + 535 "</figure></a></li>" 536 ); 537 } else { 538 $linkedinItem 539 .find("a") 540 .attr("href", linkedin) 541 .attr("title", "View " + name + " on LinkedIn"); 542 } 543 } else { 544 $socialList.find(".js-bios-social-linkedin").remove(); 545 } 546 547 if ($socialList.children().length) { 548 $social.removeAttr("hidden"); 549 } else { 550 $social.attr("hidden", ""); 551 } 552 553 $root.data("bios-last-trigger", $card); 554 $root.addClass("bios--open"); 555 $overlay.removeAttr("hidden").attr("aria-hidden", "false"); 556 $dialog.removeAttr("hidden"); 557 doc.body.classList.add("bios-modal-open"); 558 559 $root.find(".js-bios-close").trigger("focus"); 560 561 $(doc).on("keydown.bios", function (evt) { 562 if (evt.key === "Escape") { 563 closeBioDialog($root); 564 } 565 }); 566 } 567 568 $(function () { 569 if (polBiosIsEditorContext()) { 570 return; 571 } 572 573 $(".js-bios").each(function () { 574 var $root = $(this); 575 576 if ($root.hasClass("bios--editor-preview")) { 577 return; 578 } 579 580 $root.on("click", ".bios__card", function (evt) { 581 evt.preventDefault(); 582 openBioDialog($root, $(this)); 583 }); 584 585 $root.on("click", ".js-bios-close", function () { 586 closeBioDialog($root); 587 }); 588 589 $root.on("click", ".js-bios-overlay", function () { 590 closeBioDialog($root); 591 }); 592 593 $root.on("click", ".js-bios-dialog", function (evt) { 594 evt.stopPropagation(); 595 }); 596 }); 597 }); 598})(typeof jQuery !== "undefined" ? jQuery : null, window, document); 599 600(function ($, win, doc) { 601 if (!$ || typeof $.fn.slick !== "function") return; 602 603 var TIMELINE_DESKTOP_BP = 1200; 604 var timelineInstanceCount = 0; 605 var reduceMotion = 606 typeof win.matchMedia === "function" && 607 win.matchMedia("(prefers-reduced-motion: reduce)").matches; 608 609 /** @param {number} width */ 610 function isDesktopTimeline(width) { 611 return width >= TIMELINE_DESKTOP_BP; 612 } 613 614 /** @param {JQuery<Element>} $root */ 615 function destroyTimeline($root) { 616 var cleanup = $root.data("timeline-cleanup"); 617 if (typeof cleanup === "function") { 618 cleanup(); 619 $root.removeData("timeline-cleanup"); 620 } 621 } 622 623 /** @param {JQuery<Element>} $root */ 624 function initTimeline($root) { 625 destroyTimeline($root); 626 var $years = $root.find(".js-timeline-year"); 627 var $panels = $root 628 .find(".js-timeline-panel") 629 .not('[data-year-index="all"]'); 630 var $filter = $root.find(".js-timeline-filter"); 631 var $filterTrigger = $root.find(".js-timeline-filter-trigger"); 632 var $filterMenu = $root.find(".js-timeline-filter-menu"); 633 var $filterValue = $root.find(".js-timeline-filter-value"); 634 var $filterCloseValue = $root.find(".js-timeline-filter-close-value"); 635 var $filterOptions = $root.find(".js-timeline-filter-option"); 636 var $filterClose = $root.find(".js-timeline-filter-close"); 637 /** @type {"all" | number} */ 638 var filterMode = "all"; 639 var activeIndex = 0; 640 var chainAnimating = false;
641 var resizeTimer = null; 642 var chainFadeMs = reduceMotion ? 0 : 280; 643 var instanceId = ++timelineInstanceCount; 644 var filterNs = ".timelineFilter-" + instanceId; 645 var resizeNs = ".timeline-" + instanceId; 646 var chainNs = ".timelineChain-" + instanceId; 647 var allLabel = 648 ($root.attr("data-timeline-all-label") || "All Years").trim() || 649 "All Years"; 650 651 if (!$panels.length) return; 652 653 function isAllMode() { 654 return filterMode === "all" && !isDesktopTimeline(win.innerWidth); 655 } 656 657 function syncFilterClass() { 658 $root.toggleClass("timeline--filter-all", isAllMode()); 659 } 660 661 /** @param {string} label @param {number} activeYearIndex */ 662 function updateFilterUi(label, activeYearIndex) { 663 if ($filterValue.length) $filterValue.text(label); 664 if ($filterCloseValue.length) $filterCloseValue.text(label); 665 $filterOptions.each(function () { 666 var $opt = $(this); 667 var raw = $opt.attr("data-year-index"); 668 var selected = isAllMode() 669 ? raw === "all" 670 : raw !== "all" && Number(raw) === activeYearIndex; 671 $opt.attr("aria-current", selected ? "true" : "false"); 672 }); 673 } 674 675 /** @param {JQuery<Element>} $panel */ 676 function initPanelSlider($panel) { 677 var $track = $panel.find(".js-timeline-text"); 678 var $prev = $panel.find(".js-timeline-prev"); 679 var $next = $panel.find(".js-timeline-next"); 680 681 if (!$track.length || $track.hasClass("slick-initialized")) return; 682 683 $track.slick({ 684 slidesToShow: 1, 685 slidesToScroll: 1, 686 infinite: false, 687 speed: reduceMotion ? 0 : 280, 688 arrows: Boolean($prev.length && $next.length), 689 appendArrows: $panel.find(".timeline__arrows"), 690 prevArrow: $prev.length ? $prev : undefined, 691 nextArrow: $next.length ? $next : undefined, 692 swipe: !isDesktopTimeline(win.innerWidth), 693 draggable: !isDesktopTimeline(win.innerWidth), 694 }); 695 } 696 697 /** @param {JQuery<Element>} $panel */ 698 function syncPanelSlider($panel) { 699 var $track = $panel.find(".js-timeline-text"); 700 if (!$track.hasClass("slick-initialized")) return; 701 702 var desktop = isDesktopTimeline(win.innerWidth); 703 $track.slick("slickSetOption", "swipe", !desktop, false); 704 $track.slick("slickSetOption", "draggable", !desktop, false); 705 $track.slick("setPosition"); 706 } 707 708 /** @param {JQuery<Element>} $panel */ 709 function activatePanelSlider($panel) { 710 var $track = $panel.find(".js-timeline-text"); 711 712 if (!$track.length) return; 713 714 if (!$track.hasClass("slick-initialized")) { 715 initPanelSlider($panel); 716 return; 717 } 718 719 win.requestAnimationFrame(function () { 720 syncPanelSlider($panel); 721 win.requestAnimationFrame(function () { 722 if ($track.hasClass("slick-initialized")) { 723 $track.slick("setPosition"); 724 } 725 }); 726 }); 727 } 728 729 /** @param {JQuery<Element>} $panel @param {number} panelIndex */ 730 function syncChainArrows($panel, panelIndex) { 731 var $prev = $panel.find(".js-timeline-prev"); 732 var $next = $panel.find(".js-timeline-next"); 733 734 if (!isAllMode()) { 735 $prev.removeClass("is-chain-disabled").attr("aria-disabled", "false"); 736 $next.removeClass("is-chain-disabled").attr("aria-disabled", "false"); 737 return; 738 } 739 740 var $track = $panel.find(".js-timeline-text"); 741 if (!$track.hasClass("slick-initialized")) return; 742 743 var current = $track.slick("slickCurrentSlide"); 744 var count = $track.slick("getSlick").slideCount; 745 var canPrev = panelIndex > 0 || current > 0; 746 var canNext = panelIndex < $panels.length - 1 || current < count - 1; 747 748 $prev.toggleClass("is-chain-disabled", !canPrev); 749 $next.toggleClass("is-chain-disabled", !canNext); 750 $prev.attr("aria-disabled", !canPrev ? "true" : "false"); 751 $next.attr("aria-disabled", !canNext ? "true" : "false"); 752 } 753 754 /** @param {number} index @param {number} [slideIndex] @param {{ animate?: boolean }} [options] */ 755 function setActivePanel(index, slideIndex, options) { 756 options = options || {}; 757 var next = Math.max(0, Math.min(index, $panels.length - 1)); 758 var shouldAnimate = 759 options.animate && 760 isAllMode() && 761 chainFadeMs > 0 && 762 next !== activeIndex && 763 !chainAnimating; 764 765 if (shouldAnimate) { 766 chainAnimating = true; 767 var $from = $panels.eq(activeIndex); 768 $from.addClass("timeline__panel--chain-out"); 769 win.setTimeout(function () { 770 $from.removeClass("timeline__panel--chain-out"); 771 finishSetActivePanel(next, slideIndex, true); 772 chainAnimating = false;
773 }, chainFadeMs); 774 return; 775 } 776 777 finishSetActivePanel(next, slideIndex, false); 778 } 779 780 /** @param {number} next @param {number} [slideIndex] @param {boolean} withFadeIn */ 781 function finishSetActivePanel(next, slideIndex, withFadeIn) { 782 activeIndex = next; 783 784 $years.each(function (i) { 785 $(this).attr("aria-current", i === next ? "true" : "false"); 786 }); 787 788 $panels.each(function (i) { 789 var $panel = $(this); 790 if (i === next) { 791 $panel.removeAttr("hidden"); 792 if (withFadeIn) $panel.addClass("timeline__panel--chain-in"); 793 activatePanelSlider($panel); 794 } else { 795 $panel.removeClass("timeline__panel--chain-in timeline__panel--chain-out"); 796 $panel.attr("hidden", ""); 797 } 798 }); 799 800 if (isAllMode()) { 801 updateFilterUi(allLabel, next); 802 } else if (typeof filterMode === "number") { 803 var yearLabel = $years.eq(next).find(".timeline__year-label").text().trim(); 804 if (yearLabel) updateFilterUi(yearLabel, next); 805 } 806 807 syncFilterClass(); 808 809 if (typeof slideIndex === "number") { 810 var $track = $panels.eq(next).find(".js-timeline-text"); 811 if ($track.hasClass("slick-initialized")) { 812 $track.slick("slickGoTo", slideIndex, withFadeIn ? false : !reduceMotion); 813 } 814 } 815 816 var $activePanel = $panels.eq(next); 817 syncChainArrows($activePanel, next); 818 819 if (withFadeIn) { 820 win.requestAnimationFrame(function () { 821 $activePanel.removeClass("timeline__panel--chain-in"); 822 }); 823 } 824 } 825 826 /** @param {number} index */ 827 function setActiveYear(index) { 828 filterMode = index; 829 setActivePanel(index, 0, { animate: false }); 830 } 831 832 /** @param {number} yearIndex @param {number} slideIndex @param {{ animate?: boolean }} [options] */ 833 function goToPanelSlide(yearIndex, slideIndex, options) { 834 options = options || {}; 835 if (yearIndex < 0 || yearIndex >= $panels.length || chainAnimating) return; 836 837 if (yearIndex === activeIndex) { 838 if (typeof slideIndex === "number") { 839 var $track = $panels.eq(yearIndex).find(".js-timeline-text"); 840 if ($track.hasClass("slick-initialized")) { 841 $track.slick("slickGoTo", slideIndex, !reduceMotion); 842 } 843 } 844 syncChainArrows($panels.eq(yearIndex), yearIndex); 845 return; 846 } 847 848 setActivePanel(yearIndex, slideIndex, { 849 animate: options.animate !== false, 850 }); 851 } 852 853 /** @param {JQuery<Element>} $panel */ 854 function handleChainNext($panel) { 855 if (!isAllMode() || chainAnimating) return; 856 var idx = $panels.index($panel); 857 if (idx < 0) return; 858 var $track = $panel.find(".js-timeline-text"); 859 if (!$track.hasClass("slick-initialized")) return; 860 var current = $track.slick("slickCurrentSlide"); 861 var count = $track.slick("getSlick").slideCount; 862 if (current >= count - 1 && idx < $panels.length - 1) { 863 goToPanelSlide(idx + 1, 0, { animate: true }); 864 } 865 } 866 867 /** @param {JQuery<Element>} $panel */ 868 function handleChainPrev($panel) { 869 if (!isAllMode() || chainAnimating) return; 870 var idx = $panels.index($panel); 871 if (idx < 0) return; 872 var $track = $panel.find(".js-timeline-text"); 873 if (!$track.hasClass("slick-initialized")) return; 874 var current = $track.slick("slickCurrentSlide"); 875 if (current <= 0 && idx > 0) { 876 var $prevTrack = $panels.eq(idx - 1).find(".js-timeline-text"); 877 var prevCount = $prevTrack.hasClass("slick-initialized") 878 ? $prevTrack.slick("getSlick").slideCount 879 : 1; 880 goToPanelSlide(idx - 1, prevCount - 1, { animate: true }); 881 } 882 } 883 884 $panels.each(function (panelIndex) { 885 var $panel = $(this); 886 initPanelSlider($panel); 887 var $track = $panel.find(".js-timeline-text"); 888 $track.on("afterChange" + chainNs, function () { 889 syncChainArrows($panel, panelIndex); 890 }); 891 $track.on("edge" + chainNs, function (_evt, _slick, direction) { 892 if (!isAllMode() || chainAnimating) return; 893 if (direction === "left" && panelIndex < $panels.length - 1) { 894 goToPanelSlide(panelIndex + 1, 0, { animate: true }); 895 } else if (direction === "right" && panelIndex > 0) { 896 var $prevTrack = $panels.eq(panelIndex - 1).find(".js-timeline-text"); 897 if (!$prevTrack.hasClass("slick-initialized")) return; 898 var prevCount = $prevTrack.slick("getSlick").slideCount; 899 goToPanelSlide(panelIndex - 1, prevCount - 1, { animate: true }); 900 } 901 }); 902 }); 903 904 $root.on("click" + chainNs, ".js-timeline-next", function () { 905 if ($(this).attr("aria-disabled") === "true") return;
906 handleChainNext($(this).closest(".js-timeline-panel")); 907 }); 908 909 $root.on("click" + chainNs, ".js-timeline-prev", function () { 910 if ($(this).attr("aria-disabled") === "true") return; 911 handleChainPrev($(this).closest(".js-timeline-panel")); 912 }); 913 914 function closeFilterMenu() { 915 if (!$filter.length) return; 916 $filter.removeClass("timeline__filter--open"); 917 $filterTrigger.attr("aria-expanded", "false"); 918 $filterMenu.attr("hidden", ""); 919 } 920 921 function openFilterMenu() { 922 if (!$filter.length) return; 923 $filter.addClass("timeline__filter--open"); 924 $filterTrigger.attr("aria-expanded", "true"); 925 $filterMenu.removeAttr("hidden"); 926 } 927 928 $years.on("click.timeline", function () { 929 var index = $years.index(this); 930 setActiveYear(index); 931 if (this.blur) this.blur(); 932 }); 933 934 $filterTrigger.on("click.timeline", function () { 935 if ($filterMenu.attr("hidden") !== undefined) { 936 openFilterMenu(); 937 } else { 938 closeFilterMenu(); 939 } 940 }); 941 942 $filterOptions.on("click.timeline", function () { 943 var raw = $(this).attr("data-year-index"); 944 if (raw === "all") { 945 filterMode = "all"; 946 setActivePanel(0, 0, { animate: false }); 947 } else { 948 var index = Number(raw); 949 if (Number.isNaN(index)) return; 950 setActiveYear(index); 951 } 952 closeFilterMenu(); 953 }); 954 955 $filterClose.on("click.timeline", function () { 956 closeFilterMenu(); 957 }); 958 959 $(doc).on("click" + filterNs, function (evt) { 960 if (!$filter.length || $filterMenu.attr("hidden") !== undefined) return; 961 if ($(evt.target).closest(".js-timeline-filter", $root[0]).length) return; 962 closeFilterMenu(); 963 }); 964 965 $(win).on("keydown" + filterNs, function (evt) { 966 if (evt.key === "Escape") closeFilterMenu(); 967 }); 968 969 $(win).on("resize" + resizeNs, function () { 970 win.clearTimeout(resizeTimer); 971 resizeTimer = win.setTimeout(function () { 972 syncFilterClass(); 973 $panels.each(function () { 974 syncPanelSlider($(this)); 975 }); 976 syncChainArrows($panels.eq(activeIndex), activeIndex); 977 }, 150); 978 }); 979 980 $root.data("timeline-cleanup", function () { 981 $years.off(".timeline"); 982 $filterTrigger.off(".timeline"); 983 $filterOptions.off(".timeline"); 984 $filterClose.off(".timeline"); 985 $root.off(chainNs); 986 $(doc).off("click" + filterNs); 987 $(win).off("keydown" + filterNs); 988 $(win).off("resize" + resizeNs); 989 if (resizeTimer) win.clearTimeout(resizeTimer); 990 $panels.each(function () { 991 var $track = $(this).find(".js-timeline-text"); 992 $track.off(chainNs); 993 if ($track.hasClass("slick-initialized")) { 994 $track.slick("unslick"); 995 } 996 }); 997 }); 998 999 filterMode = "all"; 1000 setActivePanel(0, 0, { animate: false }); 1001 } 1002 1003 $(function () { 1004 $(".js-timeline").each(function () { 1005 initTimeline($(this)); 1006 }); 1007 }); 1008})(typeof jQuery !== "undefined" ? jQuery : null, window, document); 1009 1010// âââ CB10 Media carousel + video lightbox ââââââââââââââââââââââââââââââââââââ 1011(function ($, win, doc) { 1012 if (!$ || typeof $.fn.slick !== "function") return; 1013 1014 var reduceMotion = 1015 typeof win.matchMedia === "function" && 1016 win.matchMedia("(prefers-reduced-motion: reduce)").matches; 1017 1018 /** @param {string} url */ 1019 function getVideoEmbedUrl(url) { 1020 if (!url) return ""; 1021 1022 var ytMatch = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&?/]+)/); 1023 if (ytMatch) { 1024 return "https://www.youtube.com/embed/" + ytMatch[1] + "?autoplay=1"; 1025 } 1026 1027 var vimeoMatch = url.match(/vimeo\.com\/(\d+)/); 1028 if (vimeoMatch) { 1029 return "https://player.vimeo.com/video/" + vimeoMatch[1] + "?autoplay=1"; 1030 } 1031 1032 return ""; 1033 } 1034 1035 /** @param {JQuery<Element>} $root */ 1036 function closeMediaLightbox($root) { 1037 var $lightbox = $root.find(".js-media-lightbox"); 1038 var $iframe = $root.find(".js-media-lightbox-iframe"); 1039 1040 $lightbox.attr("hidden", ""); 1041 $iframe.attr("src", ""); 1042 doc.body.classList.remove("media-lightbox-open"); 1043 $(doc).off("keydown.mediaLightbox"); 1044 1045 var $trigger = $root.data("media-last-trigger"); 1046 if ($trigger && $trigger.length) { 1047 $trigger.trigger("focus"); 1048 } 1049 } 1050 1051 /** @param {JQuery<Element>} $root @param {JQuery<Element>} $trigger */ 1052 function openMediaLightbox($root, $trigger) { 1053 var videoUrl = $trigger.attr("data-video-url") || ""; 1054 var embedUrl = getVideoEmbedUrl(videoUrl); 1055 if (!embedUrl) return; 1056 1057 var $lightbox = $root.find(".js-media-lightbox"); 1058 var $iframe = $root.find(".js-media-lightbox-iframe"); 1059 1060 $root.data("media-last-trigger", $trigger); 1061 $iframe.attr("src", embedUrl); 1062 $lightbox.removeAttr("hidden"); 1063 doc.body.classList.add("media-lightbox-open"); 1064 $root.find(".js-media-lightbox-close").first().trigger("focus"); 1065 1066 $(doc).on("keydown.mediaLightbox", function (evt) { 1067 if (evt.key === "Escape") { 1068 closeMediaLightbox($root); 1069 } 1070 }); 1071 } 1072 1073 /** @param {JQuery<Element>} $root */ 1074 function initMedia($root) { 1075 var $track = $root.find(".js-media-track");
1076 var $nav = $root.find(".media__nav"); 1077 var $prev = $root.find(".js-media-prev"); 1078 var $next = $root.find(".js-media-next"); 1079 var resizeTimer = null; 1080 var resizeNs = ".media-" + String(Math.random()).slice(2); 1081 var slideCount = $track.children(".media__slide").length; 1082 var hasCarousel = slideCount >= 2; 1083 1084 if (!$track.length) return; 1085 1086 if (!hasCarousel) { 1087 $nav.attr("hidden", ""); 1088 } 1089 1090 if (hasCarousel && !$track.hasClass("slick-initialized")) { 1091 $track.slick({ 1092 centerMode: true, 1093 slidesToShow: 1, 1094 slidesToScroll: 1, 1095 variableWidth: true, 1096 infinite: true, 1097 speed: reduceMotion ? 0 : 300, 1098 arrows: Boolean($prev.length && $next.length), 1099 appendArrows: $nav.length ? $nav : undefined, 1100 prevArrow: $prev.length ? $prev : undefined, 1101 nextArrow: $next.length ? $next : undefined, 1102 swipe: true, 1103 draggable: true, 1104 }); 1105 1106 $track.on("afterChange.media init.media", function () { 1107 $track.slick("setPosition"); 1108 }); 1109 1110 $track.trigger("init.media"); 1111 } 1112 1113 $(win).on("resize" + resizeNs, function () { 1114 clearTimeout(resizeTimer); 1115 resizeTimer = win.setTimeout(function () { 1116 if ($track.hasClass("slick-initialized")) { 1117 $track.slick("setPosition"); 1118 } 1119 }, 150); 1120 }); 1121 1122 $root.on("click.mediaVideo", ".js-media-video-trigger", function () { 1123 openMediaLightbox($root, $(this)); 1124 }); 1125 1126 $root.on("click.mediaLightboxClose", ".js-media-lightbox-close", function () { 1127 closeMediaLightbox($root); 1128 }); 1129 1130 $root.on("click.mediaLightboxPanel", ".media__lightbox-panel", function (evt) { 1131 evt.stopPropagation(); 1132 }); 1133 1134 $root.data("media-cleanup", function () { 1135 $(win).off(resizeNs); 1136 $track.off(".media"); 1137 $root.off(".mediaVideo .mediaLightboxClose .mediaLightboxPanel"); 1138 closeMediaLightbox($root); 1139 if ($track.hasClass("slick-initialized")) { 1140 $track.slick("unslick"); 1141 } 1142 }); 1143 } 1144 1145 $(function () { 1146 $(".js-media").each(function () { 1147 initMedia($(this)); 1148 }); 1149 }); 1150})(typeof jQuery !== "undefined" ? jQuery : null, window, document); 1151 1152//# sourceMappingURL=script.js.map
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.