1/** 2 * Global variable to hold all YouTube player instances. 3 * @type {Object<string, YT.Player>} 4 */ 5var players = {}; 6var youtubeApiRequested = false; 7 8function loadYouTubeApi() { 9 if (youtubeApiRequested || window.YT && window.YT.Player) { 10 return; 11 } 12 13 youtubeApiRequested = true; 14 var tag = document.createElement('script'); 15 tag.src = 'https://www.youtube.com/iframe_api'; 16 tag.async = true; 17 document.head.appendChild(tag); 18} 19 20/** 21 * This function is called by the YouTube API when it's ready. 22 * We use this to initialize all players in our slider. 23 */ 24function onYouTubeIframeAPIReady() { 25 const mainSlider = document.querySelector('.main-slider'); 26 const mainSwiper = mainSlider && mainSlider.swiper; 27 if (mainSwiper) { 28 initializeYouTubePlayers(mainSwiper); 29 } 30} 31 32/** 33 * Finds all YouTube player placeholders and creates YT.Player objects for them. 34 * @param {Swiper} swiperInstance - The mainSwiper instance. 35 */ 36function initializeYouTubePlayers(swiperInstance) { 37 const playerDivs = swiperInstance.el.querySelectorAll('.swiper-youtube-player'); 38 39 playerDivs.forEach(playerDiv => { 40 const videoId = playerDiv.dataset.videoId; 41 const playerId = playerDiv.id; 42 43 const player = new YT.Player(playerId, { 44 height: '100%', 45 width: '100%', 46 videoId: videoId, 47 // Parameters for background-style video 48 playerVars: { 49 'autoplay': 0, // We control autoplay 50 'controls': 1, // 0 No controls 1 with controls 51 'rel': 0, // No related videos 52 'modestbranding': 1, // Minimal YouTube logo 53 'mute': 1, // MUST be muted for autoplay 54 'loop': 1, // We'll loop it 55 'playlist': videoId, // 'loop' requires 'playlist' to be set 56 'playsinline': 1 // Essential for mobile 57 }, 58 events: { 59 'onReady': (event) => onPlayerReady(event, swiperInstance), 60 'onStateChange': (event) => onPlayerStateChange(event, swiperInstance) 61 } 62 }); 63 64 // Store the player object 65 players[playerId] = player; 66 }); 67} 68 69/** 70 * Fired when a player is ready. 71 * If it's the first slide, we play it. 72 * @param {object} event - The YouTube API event. 73 * @param {Swiper} swiperInstance - The mainSwiper instance. 74 */ 75function onPlayerReady(event, swiperInstance) { 76 // Mute it again (fallback) 77 event.target.mute(); 78 79 // Check if this player is in the ACTIVE slide 80 const activeSlide = swiperInstance.slides[swiperInstance.activeIndex]; 81 if (event.target.getIframe().id === activeSlide.querySelector('.swiper-youtube-player')?.id) { 82 handleSlideVideo(activeSlide, swiperInstance); 83 } 84} 85 86/** 87 * Fired when a video's state changes (playing, paused, ended, etc.) 88 * @param {object} event - The YouTube API event. 89 * @param {Swiper} swiperInstance - The mainSwiper instance. 90 */ 91function onPlayerStateChange(event, swiperInstance) { 92 // Check if the video has ENDED 93 if (event.data === YT.PlayerState.ENDED) { 94 // Manually advance to the next slide 95 swiperInstance.slideNext(); 96 } 97} 98 99/** 100 * Main function to handle slide video logic. 101 * @param {HTMLElement} activeSlide - The current active swiper-slide element. 102 * @param {Swiper} swiperInstance - The mainSwiper instance. 103 */ 104function handleSlideVideo(activeSlide, swiperInstance) { 105 const playerDiv = activeSlide.querySelector('.swiper-youtube-player'); 106 107 if (playerDiv && players[playerDiv.id]) { 108 // --- This is a VIDEO slide --- 109 const player = players[playerDiv.id]; 110 111 // 1. Stop Swiper's default autoplay 112 swiperInstance.autoplay.stop(); 113 114 // 2. Play the video 115 player.playVideo(); 116 117 } else { 118 // --- This is an IMAGE slide --- 119 120 // 1. Restart Swiper's 8-second autoplay 121 swiperInstance.autoplay.start(); 122 } 123} 124 125/** 126 * Main DOMContentLoaded event 127 */ 128document.addEventListener('DOMContentLoaded', function () { 129 if (window.matchMedia('(max-width: 767px)').matches) { 130 return; 131 } 132 133 if (document.querySelector('.main-slider') && document.querySelector('.thumbs-slider')) { 134 135 const thumbsSwiper = new Swiper('.thumbs-slider', { 136 spaceBetween: 10, 137 slidesPerView: 5, // Show 5 thumbnails 138 freeMode: true, 139 watchSlidesProgress: true, 140 breakpoints: { 141 320: { slidesPerView: 2, spaceBetween: 10 }, 142 768: { slidesPerView: 4, spaceBetween: 10 }, 143 1024: { slidesPerView: 5, spaceBetween: 15 }, 144 }, 145 }); 146 147 const mainSwiper = new Swiper('.main-slider', { 148 spaceBetween: 10, 149 effect: 'fade', 150 fadeEffect: { 151 crossFade: true 152 }, 153 thumbs: { 154 swiper: thumbsSwiper, // Link to the thumbnail slider 155 }, 156 autoplay: { 157 delay: 8000, // This will be the default for IMAGE slides 158 disableOnInteraction: true, 159 }, 160 161 on: { 162 /** 163 * On init, wait for the YouTube API to initialize players. 164 * The 'onYouTubeIframeAPIReady' function will handle the rest. 165 */ 166 init: function () { 167 // Check if the API is *already* ready (can happen on fast reloads) 168 if (window.YT && window.YT.Player) { 169 initializeYouTubePlayers(this); 170 } 171 // The 'onPlayerReady' function will handle playing the first slide. 172 }, 173 /** 174 * Before slide change, pause all players. 175 */ 176 transitionStart: function () {
177 Object.values(players).forEach(player => { 178 if (player && typeof player.pauseVideo === 'function') { 179 player.pauseVideo(); 180 } 181 }); 182 }, 183 /** 184 * After slide change, run the handler for the NEW active slide. 185 */ 186 transitionEnd: function () { 187 handleSlideVideo(this.slides[this.activeIndex], this); 188 } 189 } 190 }); 191 192 if (document.querySelector('.swiper-youtube-player')) { 193 loadYouTubeApi(); 194 } 195 } 196});
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.