1document.addEventListener('DOMContentLoaded', function () { 2 var activeTrigger = null; 3 var modal = document.createElement('div'); 4 var playerContainer = document.createElement('div'); 5 var closeButton = document.createElement('button'); 6 7 modal.className = 'bblf-video-modal'; 8 modal.hidden = true; 9 modal.setAttribute('aria-hidden', 'true'); 10 modal.setAttribute('role', 'dialog'); 11 modal.setAttribute('aria-modal', 'true'); 12 modal.setAttribute('aria-label', 'Video player'); 13 14 playerContainer.className = 'bblf-video-modal__player'; 15 closeButton.className = 'bblf-video-modal__close'; 16 closeButton.type = 'button'; 17 closeButton.setAttribute('aria-label', 'Close video'); 18 closeButton.innerHTML = '×'; 19 20 modal.appendChild(closeButton); 21 modal.appendChild(playerContainer); 22 document.body.appendChild(modal); 23 24 function closeVideoModal() { 25 if (modal.hidden) { 26 return; 27 } 28 29 playerContainer.replaceChildren(); 30 modal.hidden = true; 31 modal.setAttribute('aria-hidden', 'true'); 32 document.body.classList.remove('bblf-video-modal-open'); 33 window.dispatchEvent(new CustomEvent('bblf:video-modal-close')); 34 35 if (activeTrigger) { 36 activeTrigger.focus(); 37 } 38 activeTrigger = null; 39 } 40 41 function openVideoModal(trigger) { 42 var videoId = trigger.getAttribute('data-bblf-video-id'); 43 if (!videoId) { 44 return; 45 } 46 47 activeTrigger = trigger; 48 playerContainer.replaceChildren(); 49 50 var iframe = document.createElement('iframe'); 51 iframe.src = 'https://www.youtube-nocookie.com/embed/' + encodeURIComponent(videoId) + '?autoplay=1&rel=0'; 52 iframe.title = trigger.textContent.trim() || 'BBLF 2026 video'; 53 iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'; 54 iframe.allowFullscreen = true; 55 playerContainer.appendChild(iframe); 56 57 modal.hidden = false; 58 modal.setAttribute('aria-hidden', 'false'); 59 document.body.classList.add('bblf-video-modal-open'); 60 window.dispatchEvent(new CustomEvent('bblf:video-modal-open')); 61 closeButton.focus(); 62 } 63 64 document.addEventListener('click', function (event) { 65 var trigger = event.target.closest('[data-bblf-video-id]'); 66 if (!trigger) { 67 return; 68 } 69 70 event.preventDefault(); 71 openVideoModal(trigger); 72 }); 73 74 closeButton.addEventListener('click', closeVideoModal); 75 modal.addEventListener('click', function (event) { 76 if (event.target === modal) { 77 closeVideoModal(); 78 } 79 }); 80 document.addEventListener('keydown', function (event) { 81 if (event.key === 'Escape') { 82 closeVideoModal(); 83 } 84 }); 85 86 var homepageCarouselElement = document.querySelector('[data-bblf-home-video-carousel]'); 87 if (homepageCarouselElement && typeof Swiper !== 'undefined') { 88 var slideCount = homepageCarouselElement.querySelectorAll('.swiper-slide').length; 89 var shouldLoop = slideCount > 4; 90 var reducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; 91 var shouldAutoplay = shouldLoop && !reducedMotion; 92 var homepageCarousel = new Swiper(homepageCarouselElement, { 93 slidesPerView: 1, 94 spaceBetween: 16, 95 speed: 600, 96 watchOverflow: true, 97 loop: shouldLoop, 98 navigation: { 99 nextEl: '.bblf-home-video-carousel__arrow--next', 100 prevEl: '.bblf-home-video-carousel__arrow--previous' 101 }, 102 autoplay: shouldAutoplay ? { 103 delay: 4500, 104 disableOnInteraction: false, 105 pauseOnMouseEnter: true 106 } : false, 107 breakpoints: { 108 480: { 109 slidesPerView: 2, 110 spaceBetween: 16 111 }, 112 768: { 113 slidesPerView: 3, 114 spaceBetween: 20 115 }, 116 1024: { 117 slidesPerView: 4, 118 spaceBetween: 22 119 } 120 } 121 }); 122 123 homepageCarousel.on('touchStart', function () {
124 if (homepageCarousel.autoplay) { 125 homepageCarousel.autoplay.pause(); 126 } 127 }); 128 homepageCarousel.on('touchEnd', function () { 129 if (homepageCarousel.autoplay) { 130 homepageCarousel.autoplay.start(); 131 } 132 }); 133 window.addEventListener('bblf:video-modal-open', function () { 134 if (homepageCarousel.autoplay) { 135 homepageCarousel.autoplay.stop(); 136 } 137 }); 138 window.addEventListener('bblf:video-modal-close', function () { 139 if (shouldAutoplay && homepageCarousel.autoplay) { 140 homepageCarousel.autoplay.start(); 141 } 142 }); 143 } 144 145 document.querySelectorAll('.bblf-video-card__media img').forEach(function (image) { 146 image.dataset.thumbnailStep = '0'; 147 image.addEventListener('error', function () { 148 var fallback = image.dataset.fallbackSrc; 149 var videoMatch = image.src.match(/\/vi\/([^/]+)\//); 150 var videoId = videoMatch ? videoMatch[1] : ''; 151 var nextThumbnails = ['hqdefault.jpg', 'mqdefault.jpg']; 152 var step = parseInt(image.dataset.thumbnailStep || '0', 10); 153 154 if (videoId && step < nextThumbnails.length) { 155 image.dataset.thumbnailStep = String(step + 1); 156 image.src = 'https://i.ytimg.com/vi/' + videoId + '/' + nextThumbnails[step]; 157 return; 158 } 159 160 image.onerror = null; 161 image.src = fallback; 162 }); 163 }); 164});
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.