1/******/ (function() { // webpackBootstrap 2/******/ var __webpack_modules__ = ({ 3
vendor: 10,814 bytes, lines 4-449
4/***/ "./node_modules/headroom.js/dist/headroom.js": 5/*!***************************************************!*\ 6 !*** ./node_modules/headroom.js/dist/headroom.js ***! 7 \***************************************************/ 8/***/ (function(module) { 9 10/*! 11 * headroom.js v0.12.0 - Give your page some headroom. Hide your header until you need it 12 * Copyright (c) 2020 Nick Williams - http://wicky.nillia.ms/headroom.js 13 * License: MIT 14 */ 15 16(function (global, factory) { 17 true ? module.exports = factory() : 18 0; 19}(this, function () { 'use strict'; 20 21 function isBrowser() { 22 return typeof window !== "undefined"; 23 } 24 25 /** 26 * Used to detect browser support for adding an event listener with options 27 * Credit: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener 28 */ 29 function passiveEventsSupported() { 30 var supported = false; 31 32 try { 33 var options = { 34 // eslint-disable-next-line getter-return 35 get passive() { 36 supported = true; 37 } 38 }; 39 window.addEventListener("test", options, options); 40 window.removeEventListener("test", options, options); 41 } catch (err) { 42 supported = false; 43 } 44 45 return supported; 46 } 47 48 function isSupported() { 49 return !!( 50 isBrowser() && 51 function() {}.bind && 52 "classList" in document.documentElement && 53 Object.assign && 54 Object.keys && 55 requestAnimationFrame 56 ); 57 } 58 59 function isDocument(obj) { 60 return obj.nodeType === 9; // Node.DOCUMENT_NODE === 9 61 } 62 63 function isWindow(obj) { 64 // `obj === window` or `obj instanceof Window` is not sufficient, 65 // as the obj may be the window of an iframe. 66 return obj && obj.document && isDocument(obj.document); 67 } 68 69 function windowScroller(win) { 70 var doc = win.document; 71 var body = doc.body; 72 var html = doc.documentElement; 73 74 return { 75 /** 76 * @see http://james.padolsey.com/javascript/get-document-height-cross-browser/ 77 * @return {Number} the scroll height of the document in pixels 78 */ 79 scrollHeight: function() { 80 return Math.max( 81 body.scrollHeight, 82 html.scrollHeight, 83 body.offsetHeight, 84 html.offsetHeight, 85 body.clientHeight, 86 html.clientHeight 87 ); 88 }, 89 90 /** 91 * @see http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript 92 * @return {Number} the height of the viewport in pixels 93 */ 94 height: function() { 95 return win.innerHeight || html.clientHeight || body.clientHeight; 96 }, 97 98 /** 99 * Gets the Y scroll position 100 * @return {Number} pixels the page has scrolled along the Y-axis 101 */ 102 scrollY: function() { 103 if (win.pageYOffset !== undefined) { 104 return win.pageYOffset; 105 } 106 107 return (html || body.parentNode || body).scrollTop; 108 } 109 }; 110 } 111 112 function elementScroller(element) { 113 return { 114 /** 115 * @return {Number} the scroll height of the element in pixels 116 */ 117 scrollHeight: function() { 118 return Math.max( 119 element.scrollHeight, 120 element.offsetHeight, 121 element.clientHeight 122 ); 123 }, 124 125 /** 126 * @return {Number} the height of the element in pixels 127 */ 128 height: function() { 129 return Math.max(element.offsetHeight, element.clientHeight); 130 }, 131 132 /** 133 * Gets the Y scroll position 134 * @return {Number} pixels the element has scrolled along the Y-axis 135 */ 136 scrollY: function() { 137 return element.scrollTop; 138 } 139 }; 140 } 141 142 function createScroller(element) { 143 return isWindow(element) ? windowScroller(element) : elementScroller(element); 144 } 145 146 /** 147 * @param element EventTarget 148 */ 149 function trackScroll(element, options, callback) { 150 var isPassiveSupported = passiveEventsSupported(); 151 var rafId; 152 var scrolled = false; 153 var scroller = createScroller(element); 154 var lastScrollY = scroller.scrollY(); 155 var details = {}; 156 157 function update() { 158 var scrollY = Math.round(scroller.scrollY()); 159 var height = scroller.height(); 160 var scrollHeight = scroller.scrollHeight(); 161 162 // reuse object for less memory churn 163 details.scrollY = scrollY; 164 details.lastScrollY = lastScrollY; 165 details.direction = scrollY > lastScrollY ? "down" : "up"; 166 details.distance = Math.abs(scrollY - lastScrollY); 167 details.isOutOfBounds = scrollY < 0 || scrollY + height > scrollHeight; 168 details.top = scrollY <= options.offset[details.direction]; 169 details.bottom = scrollY + height >= scrollHeight; 170 details.toleranceExceeded = 171 details.distance > options.tolerance[details.direction]; 172 173 callback(details); 174 175 lastScrollY = scrollY; 176 scrolled = false; 177 } 178 179 function handleScroll() { 180 if (!scrolled) { 181 scrolled = true; 182 rafId = requestAnimationFrame(update); 183 } 184 } 185 186 var eventOptions = isPassiveSupported 187 ? { passive: true, capture: false } 188 : false; 189 190 element.addEventListener("scroll", handleScroll, eventOptions); 191 update(); 192 193 return { 194 destroy: function() { 195 cancelAnimationFrame(rafId); 196 element.removeEventListener("scroll", handleScroll, eventOptions); 197 } 198 }; 199 } 200 201 function normalizeUpDown(t) { 202 return t === Object(t) ? t : { down: t, up: t }; 203 } 204 205 /** 206 * UI enhancement for fixed headers. 207 * Hides header when scrolling down 208 * Shows header when scrolling up 209 * @constructor 210 * @param {DOMElement} elem the header element 211 * @param {Object} options options for the widget 212 */ 213 function Headroom(elem, options) { 214 options = options || {}; 215 Object.assign(this, Headroom.options, options); 216 this.classes = Object.assign({}, Headroom.options.classes, options.classes); 217 218 this.elem = elem; 219 this.tolerance = normalizeUpDown(this.tolerance); 220 this.offset = normalizeUpDown(this.offset); 221 this.initialised = false; 222 this.frozen = false; 223 } 224 Headroom.prototype = { 225 constructor: Headroom, 226 227 /** 228 * Start listening to scrolling 229 * @public 230 */ 231 init: function() { 232 if (Headroom.cutsTheMustard && !this.initialised) { 233 this.addClass("initial"); 234 this.initialised = true; 235 236 // defer event registration to handle browser 237 // potentially restoring previous scroll position 238 setTimeout( 239 function(self) { 240 self.scrollTracker = trackScroll( 241 self.scroller, 242 { offset: self.offset, tolerance: self.tolerance }, 243 self.update.bind(self) 244 ); 245 }, 246 100, 247 this 248 ); 249 } 250 251 return this; 252 }, 253 254 /** 255 * Destroy the widget, clearing up after itself 256 * @public 257 */ 258 destroy: function() { 259 this.initialised = false; 260 Object.keys(this.classes).forEach(this.removeClass, this); 261 this.scrollTracker.destroy(); 262 }, 263 264 /** 265 * Unpin the element 266 * @public 267 */ 268 unpin: function() { 269 if (this.hasClass("pinned") || !this.hasClass("unpinned")) { 270 this.addClass("unpinned"); 271 this.removeClass("pinned"); 272 273 if (this.onUnpin) { 274 this.onUnpin.call(this); 275 } 276 } 277 }, 278 279 /** 280 * Pin the element 281 * @public 282 */ 283 pin: function() { 284 if (this.hasClass("unpinned")) { 285 this.addClass("pinned"); 286 this.removeClass("unpinned"); 287 288 if (this.onPin) { 289 this.onPin.call(this); 290 } 291 } 292 }, 293 294 /** 295 * Freezes the current state of the widget 296 * @public 297 */ 298 freeze: function() { 299 this.frozen = true; 300 this.addClass("frozen"); 301 }, 302 303 /** 304 * Re-enables the default behaviour of the widget 305 * @public 306 */ 307 unfreeze: function() { 308 this.frozen = false; 309 this.removeClass("frozen"); 310 }, 311 312 top: function() { 313 if (!this.hasClass("top")) { 314 this.addClass("top"); 315 this.removeClass("notTop"); 316 317 if (this.onTop) { 318 this.onTop.call(this); 319 } 320 } 321 }, 322 323 notTop: function() { 324 if (!this.hasClass("notTop")) { 325 this.addClass("notTop"); 326 this.removeClass("top"); 327 328 if (this.onNotTop) { 329 this.onNotTop.call(this); 330 } 331 } 332 }, 333 334 bottom: function() { 335 if (!this.hasClass("bottom")) { 336 this.addClass("bottom"); 337 this.removeClass("notBottom"); 338 339 if (this.onBottom) { 340 this.onBottom.call(this); 341 } 342 } 343 }, 344 345 notBottom: function() { 346 if (!this.hasClass("notBottom")) { 347 this.addClass("notBottom"); 348 this.removeClass("bottom"); 349 350 if (this.onNotBottom) { 351 this.onNotBottom.call(this); 352 } 353 } 354 }, 355 356 shouldUnpin: function(details) { 357 var scrollingDown = details.direction === "down"; 358 359 return scrollingDown && !details.top && details.toleranceExceeded; 360 }, 361 362 shouldPin: function(details) { 363 var scrollingUp = details.direction === "up"; 364 365 return (scrollingUp && details.toleranceExceeded) || details.top; 366 }, 367 368 addClass: function(className) { 369 this.elem.classList.add.apply( 370 this.elem.classList, 371 this.classes[className].split(" ") 372 ); 373 }, 374 375 removeClass: function(className) { 376 this.elem.classList.remove.apply( 377 this.elem.classList, 378 this.classes[className].split(" ") 379 ); 380 }, 381 382 hasClass: function(className) { 383 return this.classes[className].split(" ").every(function(cls) { 384 return this.classList.contains(cls); 385 }, this.elem); 386 }, 387 388 update: function(details) { 389 if (details.isOutOfBounds) { 390 // Ignore bouncy scrolling in OSX 391 return; 392 } 393 394 if (this.frozen === true) { 395 return; 396 } 397 398 if (details.top) { 399 this.top(); 400 } else { 401 this.notTop(); 402 } 403 404 if (details.bottom) { 405 this.bottom(); 406 } else { 407 this.notBottom(); 408 } 409 410 if (this.shouldUnpin(details)) { 411 this.unpin(); 412 } else if (this.shouldPin(details)) { 413 this.pin(); 414 } 415 } 416 }; 417 418 /** 419 * Default options 420 * @type {Object} 421 */ 422 Headroom.options = { 423 tolerance: { 424 up: 0, 425 down: 0 426 }, 427 offset: 0, 428 scroller: isBrowser() ? window : null, 429 classes: { 430 frozen: "headroom--frozen", 431 pinned: "headroom--pinned", 432 unpinned: "headroom--unpinned", 433 top: "headroom--top", 434 notTop: "headroom--not-top", 435 bottom: "headroom--bottom", 436 notBottom: "headroom--not-bottom", 437 initial: "headroom" 438 } 439 }; 440 441 Headroom.cutsTheMustard = isSupported(); 442 443 return Headroom; 444 445})); 446 447 448/***/ }), 449
450/***/ "./assets/js/base/_focus-within.js": 451/*!*****************************************!*\ 452 !*** ./assets/js/base/_focus-within.js ***! 453 \*****************************************/ 454/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 455 456"use strict"; 457__webpack_require__.r(__webpack_exports__); 458/* harmony export */ __webpack_require__.d(__webpack_exports__, { 459/* harmony export */ "default": function() { return /* export default binding */ __WEBPACK_DEFAULT_EXPORT__; } 460/* harmony export */ }); 461class FocusWithin { 462 constructor(node, className) { 463 this.node = node; 464 this.className = className; 465 this.focused = false; 466 467 // add events with capturing cause focus/blur don't bubble 468 this.node.addEventListener('focus', this.focus.bind(this), true); 469 this.node.addEventListener('blur', this.blur.bind(this), true); 470 } 471 toggle() { 472 return this.focused ? this.blur() : this.focus(); 473 } 474 focus() { 475 this.focused = true; 476 this.node.classList.add(this.className); 477 this.node.dispatchEvent(new CustomEvent('site:focus-within:focus')); 478 } 479 blur() { 480 this.focused = false; 481 this.node.classList.remove(this.className); 482 this.node.dispatchEvent(new CustomEvent('site:focus-within:blur')); 483 } 484} 485/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(node, className = 'focus-within') { 486 // pass dom element directly 487 if (node instanceof HTMLElement) { 488 return new FocusWithin(node, className); 489 } 490 491 // pass selector 492 if (typeof node === 'string') { 493 node = document.querySelectorAll(node); 494 } 495 496 // convert to Array if not an array 497 if (!Array.isArray(node)) { 498 node = Array.from(node); 499 } 500 501 // convert to FocusWithin objects 502 return node.map(n => new FocusWithin(n, className)); 503} 504 505/***/ }), 506
507/***/ "./assets/js/base/_object-fit-cover.js": 508/*!*********************************************!*\ 509 !*** ./assets/js/base/_object-fit-cover.js ***! 510 \*********************************************/ 511/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 512 513"use strict"; 514__webpack_require__.r(__webpack_exports__); 515/* harmony export */ __webpack_require__.d(__webpack_exports__, { 516/* harmony export */ "default": function() { return /* binding */ objectFitCover; } 517/* harmony export */ }); 518/** 519 * IE11 Fix to convert object-fit: cover to background-size: cover 520 * 521 * @param {string|NodeList|Array} nodes 522 * @param {string} img the img selector 523 * @param {string} position the background position to use 524 */ 525function objectFitCover(nodes = '.object-fit-cover', img = 'img', position = 'center') { 526 if (typeof nodes === 'string') { 527 nodes = Array.from(document.querySelectorAll(nodes)); 528 } 529 if (!nodes.length) { 530 return; 531 } 532 for (let i = 0, nodesLength = nodes.length; i < nodesLength; i++) { 533 let imgNode = nodes[i].querySelector(img); 534 if (!imgNode) { 535 continue; 536 } 537 nodes[i].style.backgroundPosition = position; 538 nodes[i].style.backgroundSize = 'cover'; 539 nodes[i].style.backgroundImage = `url(${imgNode.currentSrc || imgNode.src})`; 540 imgNode.style.display = 'none'; 541 } 542} 543if (document.readyState.match(/complete|loaded/)) { 544 objectFitCover(); 545} else { 546 document.addEventListener('DOMContentLoaded', objectFitCover); 547} 548 549/***/ }), 550
551/***/ "./assets/js/base/_tabIndex.js": 552/*!*************************************!*\ 553 !*** ./assets/js/base/_tabIndex.js ***! 554 \*************************************/ 555/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 556 557"use strict"; 558__webpack_require__.r(__webpack_exports__); 559/* harmony export */ __webpack_require__.d(__webpack_exports__, { 560/* harmony export */ disable: function() { return /* binding */ disable; }, 561/* harmony export */ enable: function() { return /* binding */ enable; }, 562/* harmony export */ tabCapable: function() { return /* binding */ tabCapable; } 563/* harmony export */ }); 564/** 565 * Array of selectors that are tab index capable 566 */ 567const tabCapable = ['select', 'input', 'textarea', 'button', 'a', 'iframe', 'object', 'embed', '*[contenteditable]', '*[tabindex]']; 568 569/** 570 * Disable nodes tabIndex while saving the previous tabIndex value in node.dataset 571 * 572 * @param {string} exclude query selector to filter disabling items 573 * @param {HTMLElement} scope Defaults to document 574 * @returns {array} 575 */ 576function disable(exclude = null, scope = document) { 577 scope = scope || document; 578 let nodes = Array.from(scope.querySelectorAll(tabCapable.join(', '))); 579 if (exclude) { 580 nodes = nodes.filter(node => !node.matches(exclude) && !node.closest(exclude)); 581 } 582 nodes.forEach(node => { 583 if (node.tabIndex && node.tabIndex !== '-1') { 584 node.dataset.tabIndex = node.tabIndex; 585 } 586 node.tabIndex = '-1'; 587 }); 588 return nodes; 589} 590 591/** 592 * Enable nodes tabIndex by restoring a previously saved tabIndex or removing it entirely 593 * 594 * @param {string} exclude query selector to filter disabling items 595 * @param {HTMLElement} scope Defaults to document 596 * @returns {array} 597 */ 598function enable(exclude = null, scope = document) { 599 let nodes = Array.from(scope.querySelectorAll(tabCapable.join(', '))); 600 if (exclude) { 601 nodes = nodes.filter(node => !node.matches(exclude) && !node.closest(exclude)); 602 } 603 nodes.forEach(node => { 604 if (node.dataset.tabIndex) { 605 node.tabIndex = node.dataset.tabIndex; 606 } else { 607 node.removeAttribute('tabIndex'); 608 } 609 }); 610 return nodes; 611} 612/* harmony default export */ __webpack_exports__["default"] = ({ 613 tabCapable, 614 enable, 615 disable 616}); 617 618/***/ }), 619
620/***/ "./assets/js/base/_throttle.js": 621/*!*************************************!*\ 622 !*** ./assets/js/base/_throttle.js ***! 623 \*************************************/ 624/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 625 626"use strict"; 627__webpack_require__.r(__webpack_exports__); 628/* harmony export */ __webpack_require__.d(__webpack_exports__, { 629/* harmony export */ "default": function() { return /* export default binding */ __WEBPACK_DEFAULT_EXPORT__; } 630/* harmony export */ }); 631/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(fn, time = 50) { 632 let timer = null; 633 function throttledFn(...args) { 634 if (!timer) { 635 timer = setTimeout(() => { 636 fn(...args); 637 timer = null; 638 }, time); 639 } 640 } 641 throttledFn.cancel = () => { 642 clearTimeout(timer); 643 timer = null; 644 }; 645 return throttledFn; 646} 647 648/***/ }), 649
650/***/ "./assets/js/modules/_masthead.js": 651/*!****************************************!*\ 652 !*** ./assets/js/modules/_masthead.js ***! 653 \****************************************/ 654/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 655 656"use strict"; 657__webpack_require__.r(__webpack_exports__); 658/* harmony import */ var headroom_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! headroom.js */ "./node_modules/headroom.js/dist/headroom.js"); 659/* harmony import */ var _base_tabIndex_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../base/_tabIndex.js */ "./assets/js/base/_tabIndex.js"); 660 661 662class MastheadParent { 663 constructor(node, controller) { 664 this.node = node; 665 this.controller = controller; 666 if (!this.node) { 667 return; 668 } 669 670 // stores the timeout id of the enter hover intent 671 this.enterTimeout = null; 672 673 // stores the timeout of the leave hover intent 674 this.leaveTimeout = null; 675 676 // is the current item active 677 this.active = false; 678 679 // reference the direct child link in case we need to preventDefault on click 680 this.link = this.node.querySelector(':scope > .masthead__link'); 681 682 // does this item have a back button on the mobile menu 683 this.back = this.node.querySelector('.masthead__back'); 684 685 // what types of pointer events are 'hoverable' 686 this.hoverTypes = ['mouse', 'pen']; 687 688 // trigger the enter hover intent depending on the pointer type 689 const onPointerEnter = e => { 690 if (this.hoverTypes.includes(e.pointerType) && 'hover' === this.controller.getPointerMode()) { 691 if (typeof this.leaveTimeout === 'number') { 692 window.clearTimeout(this.leaveTimeout); 693 this.leaveTimeout = null; 694 } 695 this.enterTimeout = setTimeout(() => this.activate(), this.controller.hoverDelay); 696 } 697 }; 698 699 // trigger the leave hover intent depending on the pointer type 700 const onPointerLeave = e => { 701 if (this.hoverTypes.includes(e.pointerType) && 'hover' === this.controller.getPointerMode()) { 702 if (typeof this.enterTimeout === 'number') { 703 window.clearTimeout(this.enterTimeout); 704 this.enterTimeout = null; 705 } 706 this.leaveTimeout = window.setTimeout(() => this.deactivate(), this.controller.hoverDelay); 707 } 708 }; 709 710 // store the last pointer type on pointerup so we can potentially preventDefault onClick 711 const onPointerUp = e => { 712 this.pointerType = e.pointerType ?? null; 713 }; 714 715 // if not in hover mode, or we're not a hoverable type, simply toggle instead of following the link 716 const onClick = e => { 717 if ('hover' !== this.controller.getPointerMode() || !this.hoverTypes.includes(this.pointerType)) { 718 e.preventDefault(); 719 this.toggle(); 720 } 721 if (this.pointerType) { 722 delete this.pointerType; 723 } 724 }; 725 726 // when a element outside of this node is focused, close this menu 727 const onFocus = () => { 728 let target = document.activeElement; 729 while (target && target.parentNode) { 730 if (target === this.node) { 731 return; 732 } 733 target = target.parentNode; 734 } 735 this.deactivate(); 736 }; 737 this.node.addEventListener('pointerenter', onPointerEnter); 738 this.node.addEventListener('pointerleave', onPointerLeave); 739 this.node.addEventListener('pointerup', onPointerUp); 740 document.body.addEventListener('focus', onFocus, true); 741 if (this.back) { 742 this.back.addEventListener('click', this.deactivate.bind(this)); 743 } 744 if (this.link) { 745 this.link.addEventListener('click', onClick); 746 } 747 } 748 749 /** 750 * Toggle this dropdown menu state 751 */ 752 toggle() { 753 this.active ? this.deactivate() : this.activate(); 754 } 755 756 /** 757 * Activate this dropdown menu state 758 */ 759 activate() { 760 if (!this.active) { 761 this.active = true; 762 this.controller.deactivate(this); 763 this.node.classList.add(this.controller.parentActiveClass); 764 this.node.dispatchEvent(new Event('masthead:activate', { 765 bubbles: true 766 })); 767 } 768 } 769 770 /** 771 * Deactivate this dropdown menu state 772 */ 773 deactivate() { 774 if (this.active) { 775 this.active = false;
776 this.node.classList.remove(this.controller.parentActiveClass); 777 this.node.dispatchEvent(new Event('masthead:deactivate', { 778 bubbles: true 779 })); 780 } 781 } 782} 783class Masthead { 784 constructor() { 785 this.node = document.querySelector('.masthead'); 786 if (!this.node) { 787 return; 788 } 789 790 // no mode by default (can be search|menu) 791 this.mode = null; 792 793 // what mouse/pen mode do we want to operate under - hover or click 794 this.pointerMode = this.node.dataset.pointerMode || 'hover'; 795 796 // the delay used for hover-intent 797 this.hoverDelay = 200; 798 799 // the item active class 800 this.parentActiveClass = 'masthead__item--active'; 801 802 // node references for interaction 803 this.nav = this.node.querySelector('.masthead__nav'); 804 this.menuIcon = this.node.querySelector('.masthead__menu-icon'); 805 this.search = this.node.querySelector('.masthead__search'); 806 this.searchIcon = this.node.querySelector('.masthead__search-icon'); 807 this.closeIcon = this.node.querySelector('.masthead__close-icon'); 808 this.language = this.node.querySelector('.masthead__language'); 809 810 // at what media query is the mobile menu triggered - update this value to match whatever is used in _masthead.scss 811 this.mobileMediaQuery = `(max-width: ${this.node.dataset.mobileBreakpoint || '62em'})`; 812 813 // initialize menu items that are parents 814 this.parents = Array.from(this.node.querySelectorAll('.masthead__item--depth-0.masthead__item--has-children')).map(node => { 815 return new MastheadParent(node, this); 816 }); 817 818 // initialize the language parent class 819 if (this.language) { 820 this.languageParent = new MastheadParent(this.language, this); 821 this.languageParent.node.addEventListener('masthead:activate', () => this.node.classList.add('masthead--mode-language')); 822 this.languageParent.node.addEventListener('masthead:deactivate', () => this.node.classList.remove('masthead--mode-language')); 823 } 824 825 // headroom sticky hide configuration - @see https://www.npmjs.com/package/headroom.js 826 this.headroom = new headroom_js__WEBPACK_IMPORTED_MODULE_0__(this.node, { 827 tolerance: { 828 up: 7, 829 down: 5 830 }, 831 classes: { 832 initial: 'masthead', 833 pinned: 'masthead--pinned', 834 unpinned: 'masthead--unpinned', 835 top: 'masthead--top', 836 notTop: 'masthead--not-top', 837 bottom: 'masthead--bottom', 838 notBottom: 'masthead--not-bottom', 839 frozen: 'masthead--frozen' 840 } 841 }); 842 this.headroom.init(); 843 this.headroom.update(this.headroom); 844 845 // deactivate the mode of the menu on escape key 846 const onKeyUp = e => { 847 switch (e.key) { 848 case 'Escape': 849 if (this.mode) { 850 this.setMode(''); 851 } 852 break; 853 } 854 }; 855 856 // deactivate mode when clicking outside of the masthead 857 const onClick = e => { 858 let target = e.target; 859 while (target.parentNode) { 860 if (target === this.nav) { 861 return; 862 } 863 target = target.parentNode; 864 } 865 this.deactivate(); 866 }; 867 (0,_base_tabIndex_js__WEBPACK_IMPORTED_MODULE_1__.disable)(null, this.search); 868 this.node.addEventListener('keyup', onKeyUp); 869 if (this.searchIcon) { 870 this.searchIcon.addEventListener('click', e => { 871 e.stopPropagation(); 872 this.toggleMode('search'); 873 }); 874 } 875 if (this.menuIcon) { 876 this.menuIcon.addEventListener('click', e => { 877 e.stopPropagation(); 878 this.toggleMode('menu'); 879 }); 880 } 881 if (this.closeIcon) { 882 this.closeIcon.addEventListener('click', e => { 883 e.stopPropagation(); 884 this.setMode(); 885 }); 886 } 887 document.body.addEventListener('click', onClick); 888 } 889 890 /** 891 * Deactivate all dropdown menus (optionally exclude one menu) 892 * 893 * @param {MastheadParent} exclude 894 */ 895 deactivate(exclude) { 896 this.parents.forEach(parent => { 897 if (!exclude || parent !== exclude) { 898 parent.deactivate(); 899 } 900 }); 901 if (!window.matchMedia(this.mobileMediaQuery).matches) { 902 this.setMode(''); 903 } 904 } 905 906 /** 907 * Set the interactive mode of the masthead 908 * 909 * @param {string} mode search|menu 910 * @returns void 911 */ 912 setMode(mode = '') { 913 if (this.mode && mode !== this.mode) { 914 const lastMode = this.mode; 915 if ('search' === lastMode) { 916 (0,_base_tabIndex_js__WEBPACK_IMPORTED_MODULE_1__.disable)(null, this.search); 917 const onTransitionEnd = () => { 918 this.search.hidden = true; 919 this.search.removeEventListener('transitionend', onTransitionEnd); 920 if (!this.node.classList.contains('masthead--search-overlay')) { 921 this.nav.classList.remove('masthead__nav--search'); 922 } 923 }; 924 this.search.addEventListener('transitionend', onTransitionEnd); 925 } 926 this.node.classList.remove(`masthead--mode-${lastMode}`); 927 document.documentElement.classList.remove('has-masthead-mode', `has-masthead--mode-${lastMode}`); 928 } 929 this.mode = mode; 930 if (mode) { 931 if ('search' === this.mode) { 932 (0,_base_tabIndex_js__WEBPACK_IMPORTED_MODULE_1__.enable)(null, this.search); 933 this.search.removeAttribute('hidden'); 934 const input = this.search.querySelector('input'); 935 if (input) { 936 input.focus(); 937 } 938 if (!this.node.classList.contains('masthead--search-overlay')) { 939 this.nav.classList.add('masthead__nav--search'); 940 } 941 } 942 setTimeout(() => { 943 this.node.classList.add(`masthead--mode-${this.mode}`); 944 document.documentElement.classList.add('has-masthead-mode', `has-masthead--mode-${mode}`); 945 }, 10); 946 } 947 this.node.dispatchEvent(new Event('masthead:mode', { 948 detail: this 949 })); 950 } 951 952 /** 953 * Toggle the interactive mode of the masthead 954 * 955 * @param {string} mode search|menu 956 * @returns void 957 */ 958 toggleMode(mode) { 959 this.setMode(this.mode === mode ? '' : mode); 960 } 961 962 /** 963 * Gets the mode of the pointerType of how the dropdowns should react to pointer events 964 * 965 * - mobile view should always be click based even with mouse/pen pointer events 966 * - update the breakpoint 967 * 968 * @returns string hover|click 969 */ 970 getPointerMode() { 971 if ('hover' === this.pointerMode && window.matchMedia(this.mobileMediaQuery).matches) { 972 return 'click'; 973 } 974 return this.pointerMode; 975 } 976} 977/* harmony default export */ __webpack_exports__["default"] = (new Masthead()); 978 979/***/ }), 980
981/***/ "./assets/js/modules/_video.js": 982/*!*************************************!*\ 983 !*** ./assets/js/modules/_video.js ***! 984 \*************************************/ 985/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 986 987"use strict"; 988__webpack_require__.r(__webpack_exports__); 989/* harmony export */ __webpack_require__.d(__webpack_exports__, { 990/* harmony export */ initVideoControls: function() { return /* binding */ initVideoControls; } 991/* harmony export */ }); 992function initVideoControls() { 993 const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; 994 document.querySelectorAll('.video-custom-controls__control').forEach(function (btn) { 995 const video = btn.closest('.wp-block-cover').querySelector('video'); 996 // Pause video by default if reduced motion is preferred 997 if (video && prefersReducedMotion) { 998 video.pause(); 999 btn.classList.add('is-play'); 1000 btn.querySelector('.a11y').textContent = 'Play video'; 1001 } 1002 btn.addEventListener('click', function () { 1003 if (video) { 1004 if (video.paused) { 1005 video.play(); 1006 this.classList.remove('is-play'); 1007 btn.querySelector('.a11y').textContent = 'Pause video'; 1008 } else { 1009 video.pause(); 1010 this.classList.add('is-play'); 1011 btn.querySelector('.a11y').textContent = 'Play video'; 1012 } 1013 } 1014 }); 1015 }); 1016} 1017 1018/***/ })
1018 1019 1020/******/ }); 1021/************************************************************************/ 1022/******/ // The module cache 1023/******/ var __webpack_module_cache__ = {}; 1024/******/ 1025/******/ // The require function 1026/******/ function __webpack_require__(moduleId) { 1027/******/ // Check if module is in cache 1028/******/ var cachedModule = __webpack_module_cache__[moduleId]; 1029/******/ if (cachedModule !== undefined) { 1030/******/ return cachedModule.exports; 1031/******/ } 1032/******/ // Create a new module (and put it into the cache) 1033/******/ var module = __webpack_module_cache__[moduleId] = { 1034/******/ // no module.id needed 1035/******/ // no module.loaded needed 1036/******/ exports: {} 1037/******/ }; 1038/******/ 1039/******/ // Execute the module function 1040/******/ if (!(moduleId in __webpack_modules__)) { 1041/******/ delete __webpack_module_cache__[moduleId]; 1042/******/ var e = new Error("Cannot find module '" + moduleId + "'"); 1043/******/ e.code = 'MODULE_NOT_FOUND'; 1044/******/ throw e; 1045/******/ } 1046/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__); 1047/******/ 1048/******/ // Return the exports of the module 1049/******/ return module.exports; 1050/******/ } 1051/******/ 1052/************************************************************************/ 1053/******/ /* webpack/runtime/define property getters */ 1054/******/ !function() { 1055/******/ // define getter functions for harmony exports 1056/******/ __webpack_require__.d = function(exports, definition) { 1057/******/ for(var key in definition) { 1058/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 1059/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 1060/******/ } 1061/******/ } 1062/******/ }; 1063/******/ }(); 1064/******/ 1065/******/ /* webpack/runtime/hasOwnProperty shorthand */ 1066/******/ !function() { 1067/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } 1068/******/ }(); 1069/******/ 1070/******/ /* webpack/runtime/make namespace object */ 1071/******/ !function() { 1072/******/ // define __esModule on exports 1073/******/ __webpack_require__.r = function(exports) { 1074/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 1075/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 1076/******/ } 1077/******/ Object.defineProperty(exports, '__esModule', { value: true }); 1078/******/ }; 1079/******/ }(); 1080/******/ 1081/************************************************************************/ 1082var __webpack_exports__ = {}; 1083// This entry needs to be wrapped in an IIFE because it needs to be in strict mode. 1084!function() { 1085"use strict"; 1086/*!******************************!*\ 1087 !*** ./assets/js/scripts.js ***! 1088 \******************************/ 1089__webpack_require__.r(__webpack_exports__); 1090/* harmony import */ var _base_throttle_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base/_throttle.js */ "./assets/js/base/_throttle.js"); 1091/* harmony import */ var _base_focus_within_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./base/_focus-within.js */ "./assets/js/base/_focus-within.js"); 1092/* harmony import */ var _base_object_fit_cover_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./base/_object-fit-cover.js */ "./assets/js/base/_object-fit-cover.js"); 1093/* harmony import */ var _modules_masthead_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./modules/_masthead.js */ "./assets/js/modules/_masthead.js"); 1094/* harmony import */ var _modules_video_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./modules/_video.js */ "./assets/js/modules/_video.js"); 1095 1096 1097 1098 1099 1100class Scripts { 1101 constructor() { 1102 document.addEventListener('DOMContentLoaded', this.ready.bind(this)); 1103 window.addEventListener('resize', (0,_base_throttle_js__WEBPACK_IMPORTED_MODULE_0__["default"])(this.resize.bind(this), 25)); 1104 this.resize(); 1105 } 1106 ready() { 1107 (0,_base_focus_within_js__WEBPACK_IMPORTED_MODULE_1__["default"])('label, form, fieldset'); 1108 this.fetchSvgs(); 1109 (0,_modules_video_js__WEBPACK_IMPORTED_MODULE_4__.initVideoControls)(); 1110 } 1111 resize() { 1112 if (!document.body) { 1113 return; 1114 } 1115 1116 // using this to allow css to know if it should exclude the scroll bar in calc's 1117 if (window.innerWidth === document.body.clientWidth) { 1118 document.documentElement.classList.remove('has-scrollbar'); 1119 } else { 1120 document.documentElement.classList.add('has-scrollbar'); 1121 } 1122 } 1123 fetchSvgs(selector = '.image-svg-replace', scope = document) { 1124 scope.querySelectorAll(selector).forEach(img => this.fetchSvg(img)); 1125 } 1126 async fetchSvg(img) { 1127 try { 1128 if (!img || !img.src) { 1129 throw new Error('Invalid svg image tag'); 1130 } 1131 const response = await window.fetch(img.src); 1132 if ('image/svg+xml' !== response.headers.get('content-type')) { 1133 throw new Error('Response is not svg'); 1134 } 1135 const text = await response.text(); 1136 if (!text) { 1137 throw new Error('Empty svg - not replacing'); 1138 } 1139 const parser = new DOMParser(); 1140 const doc = parser.parseFromString(text, 'image/svg+xml'); 1141 const scripts = Array.from(doc.querySelectorAll('script')).map(script => script.parentNode.removeChild(script)); 1142 const svg = doc.querySelector('svg'); 1143 ['height', 'width', 'class', 'style', 'className'].forEach(attribute => { 1144 if (img.getAttribute(attribute)) { 1145 switch (attribute) { 1146 case 'className': 1147 // merge class names 1148 svg.classList.add(img.classList); 1149 break; 1150 case 'style': 1151 // merge and overwrite inline styles 1152 img.getAttribute('style').split(';').forEach(stmt => { 1153 const [prop, value] = stmt.split(':'); 1154 if (prop && value) { 1155 svg.style[prop] = value; 1156 } 1157 }); 1158 break; 1159 default: 1160 // overwrite attributes 1161 svg.setAttribute(attribute, img.getAttribute(attribute)); 1162 break; 1163 } 1164 } 1165 }); 1166 img.parentNode.insertBefore(svg, img);
1167 scripts.forEach(script => { 1168 const svgScript = document.createElement('script'); 1169 svgScript.innerHTML = script.innerHTML.replace(/^<!\[CDATA\[/, '').replace(/\]\]>$/, ''); 1170 img.parentNode.appendChild(svgScript); 1171 }); 1172 img.parentNode.removeChild(img); 1173 } catch (error) { 1174 console.error(error); 1175 } 1176 } 1177} 1178/* harmony default export */ __webpack_exports__["default"] = (new Scripts()); 1179}(); 1180var __webpack_export_target__ = (wdg = typeof wdg === "undefined" ? {} : wdg); 1181for(var __webpack_i__ in __webpack_exports__) __webpack_export_target__[__webpack_i__] = __webpack_exports__[__webpack_i__]; 1182if(__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, "__esModule", { value: true }); 1183/******/ })() 1184; 1185//# sourceMappingURL=scripts.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.