1let homeHero = document.querySelector('.homeHero'); 2if (homeHero) { 3 let $hero = $('.homeHero .swiper-container.slick'); 4 5 // Users who have asked their OS to reduce motion should not get an 6 // auto-advancing hero or a looping background video (WCAG 2.3.3). 7 let prefersReducedMotion = window.matchMedia 8 && window.matchMedia('(prefers-reduced-motion: reduce)').matches; 9 10 $hero.slick({ 11 dots: true, 12 arrows: false, 13 infinite: true, 14 speed: 800, 15 autoplay: !prefersReducedMotion, 16 slidesToShow: 1, 17 slidesToScroll: 1, 18 responsive: [ 19 { 20 breakpoint: 1024, 21 settings: { 22 adaptiveHeight: true 23 } 24 } 25 ] 26 }); 27 28 // ----------------------------------------------------------------------- 29 // Pause / play control â WCAG 2.2.2 Pause, Stop, Hide (A) 30 // 31 // Motion that starts on its own and runs for more than five seconds needs 32 // a mechanism to pause it. The hero does this two ways: an auto-advancing 33 // slick carousel, and looping <video> slides that autoplay. One control 34 // handles both, so it is injected whenever either is present. 35 // ----------------------------------------------------------------------- 36 let sliderRunning = $hero.length && $hero.hasClass('slick-initialized'); 37 let heroVideos = homeHero.querySelectorAll('video'); 38 39 if (sliderRunning || heroVideos.length) { 40 41 // Honour reduced-motion for the videos too: the markup has autoplay on 42 // the element itself, so it has to be stopped here. 43 if (prefersReducedMotion) { 44 for (let i = 0; i < heroVideos.length; i++) { 45 heroVideos[i].autoplay = false; 46 heroVideos[i].pause(); 47 } 48 } 49 50 let playing = !prefersReducedMotion; 51 52 let setHeroMotion = function (run) { 53 if (sliderRunning) { 54 $hero.slick(run ? 'slickPlay' : 'slickPause'); 55 } 56 for (let i = 0; i < heroVideos.length; i++) { 57 if (run) { 58 let p = heroVideos[i].play(); 59 // Browsers reject play() if the element is off-screen or 60 // blocked by policy; that is not an error worth surfacing. 61 if (p && typeof p.catch === 'function') { p.catch(function () {}); } 62 } else { 63 heroVideos[i].pause(); 64 } 65 } 66 }; 67 68 let pauseBtn = document.createElement('button'); 69 pauseBtn.type = 'button'; 70 pauseBtn.className = 'heroPause'; 71 pauseBtn.setAttribute('data-state', playing ? 'playing' : 'paused'); 72 pauseBtn.setAttribute('aria-label', playing ? 'Pause slideshow' : 'Play slideshow'); 73 pauseBtn.innerHTML = '<span class="heroPause__glyph" aria-hidden="true"></span>'; 74 75 pauseBtn.addEventListener('click', function () { 76 playing = !playing; 77 setHeroMotion(playing); 78 pauseBtn.setAttribute('data-state', playing ? 'playing' : 'paused'); 79 pauseBtn.setAttribute('aria-label', playing ? 'Pause slideshow' : 'Play slideshow'); 80 }); 81 82 homeHero.appendChild(pauseBtn); 83 84 if (sliderRunning) { 85 // Slick pauses on hover by default but not on keyboard focus. Hold 86 // the carousel still while a keyboard user is reading a slide or 87 // tabbing through its links, then resume if they left it playing. 88 homeHero.addEventListener('focusin', function () { 89 if (playing) $hero.slick('slickPause'); 90 }); 91 92 homeHero.addEventListener('focusout', function (event) { 93 if (!playing) return; 94 if (!homeHero.contains(event.relatedTarget)) { 95 $hero.slick('slickPlay'); 96 } 97 }); 98 99 // Slides cloned for the infinite loop duplicate their contents for 100 // screen readers and put duplicate links in the tab order. Hide the 101 // clones from assistive tech and take them out of tab order. 102 let hideClones = function () { 103 let clones = homeHero.querySelectorAll('.slick-slide.slick-cloned'); 104 for (let i = 0; i < clones.length; i++) { 105 clones[i].setAttribute('aria-hidden', 'true'); 106 let focusables = clones[i].querySelectorAll('a[href], button, input, select, textarea, [tabindex]'); 107 for (let j = 0; j < focusables.length; j++) { 108 focusables[j].setAttribute('tabindex', '-1'); 109 } 110 } 111 }; 112 hideClones(); 113 $hero.on('afterChange', hideClones); 114 } 115 } 116}
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.