1let playersBanner = []; 2const ehMobile = () => window.innerWidth <= 640; 3 4class YouTubeVideoBanner extends HTMLElement { 5 static scriptLoadPromise; 6 scriptPath = "https://www.youtube.com/iframe_api"; 7 videoProportion = ehMobile() ? (785 / 640) : (750 / 1920); 8 ytPlayer; 9 10 playerVars = { 11 autoplay: 1, 12 controls: 0, 13 mute: 1, 14 loop: 1 15 }; 16 17 videoEvents = { 18 onReady: ({ target }) => { 19 if (YT.PlayerState.BUFFERING === target.getPlayerState()) { 20 this.videoContainer.dispatchEvent(new CustomEvent('onBuffering')); 21 } 22 }, 23 onStateChange: ({ data }) => { 24 if (YT.PlayerState.BUFFERING === data) { 25 this.videoContainer.dispatchEvent(new CustomEvent('onBuffering')); 26 } 27 28 if (YT.PlayerState.PLAYING === data) { 29 this.videoContainer.dispatchEvent(new CustomEvent('onPlaying')); 30 } 31 } 32 } 33 34 constructor() { 35 super(); 36 37 this.videoContainer = this.parentNode; 38 39 this.videoId = this.getAttribute('data-id'); 40 this.playerVars.playlist = this.videoId; 41 42 this.height = this.getAttribute('height'); 43 this.width = this.getAttribute('width'); 44 this.youTubeVideoElement = this; 45 46 this.setup(); 47 } 48 49 getVideoDimensions() { 50 return { 51 width: this.videoContainer.clientWidth, 52 height: this.videoContainer.clientWidth * this.videoProportion 53 }; 54 } 55 56 resizeHandler() { 57 const iframe = this.videoContainer.querySelector('iframe'); 58 const { width, height } = this.getVideoDimensions(); 59 60 iframe.style.width = `${width}px`; 61 iframe.style.height = `${height * 3}px`; 62 iframe.style.transform = `translateY(-${height}px)`; 63 this.videoContainer.style.maxHeight = `${height}px`; 64 this.videoContainer.style.overflow = 'hidden'; 65 } 66 67 onResizeListeners() { 68 window.addEventListener('resize', () => this.resizeHandler()); 69 document.addEventListener('DOMContentLoaded', () => this.resizeHandler()); 70 $(document).ready(() => this.resizeHandler()); 71 } 72 73 onVideoHiddenListener() { 74 this.videoContainer.addEventListener('onVideoHidden', () => { 75 playersBanner.forEach((player) => { 76 if (player.element.closest('.splide__slide').classList.contains('is-active')) { 77 return; 78 } 79 80 player.player.seekTo(0); 81 player.player.pauseVideo(); 82 }); 83 }); 84 } 85 86 onVideoVisibleListener() { 87 this.videoContainer.addEventListener('onVideoVisible', () => { 88 const id = this.iframeElementId; 89 90 if (!id || !playersBanner[id].player.seekTo) { 91 return; 92 } 93 94 playersBanner[id].player.seekTo(0); 95 playersBanner[id].player.playVideo(); 96 }); 97 } 98 99 async setup() { 100 await this._loadYouTubeAPI(); 101 102 const player = await this._buildPlayer(); 103 const id = player.g.id.replace(/[^\d]/g, ''); 104 105 this.iframeElementId = id; 106 playersBanner[id] = new CustomYouTubeVideoPlayer(player); 107 108 this.onResizeListeners(); 109 this.onVideoHiddenListener(); 110 this.onVideoVisibleListener(); 111 } 112 113 _loadYouTubeAPI() { 114 if (!YouTubeVideoBanner.scriptLoadPromise) { 115 YouTubeVideoBanner.scriptLoadPromise = new Promise(resolve => { 116 const originalOnYouTubeIframeAPIReady = window.onYouTubeIframeAPIReady; 117 YouTubeVideoBanner.triggerYoutubeIframeAPIReady = resolve; 118 119 window.onYouTubeIframeAPIReady = (...args) => { 120 window.onYouTubeIframeAPIReady = null; 121 YouTubeVideoBanner.triggerYoutubeIframeAPIReady(); 122 123 if (originalOnYouTubeIframeAPIReady) { 124 originalOnYouTubeIframeAPIReady(...args); 125 } 126 127 resolve(); 128 }; 129 130 const script = document.createElement('script'); 131 script.src = this.scriptPath; 132 const firstScriptTag = document.getElementsByTagName('script')[0]; 133 firstScriptTag.parentNode.insertBefore(script, firstScriptTag); 134 }); 135 } 136 137 return YouTubeVideoBanner.scriptLoadPromise; 138 } 139 140 _buildPlayer() { 141 this.ytPlayerPromise = new Promise(resolve => { 142 const playerOptions = { 143 events: this.videoEvents, 144 height: this.height, 145 width: this.width, 146 playerVars: this.playerVars, 147 videoId: this.videoId, 148 }; 149 150 const player = new YT.Player( 151 this.youTubeVideoElement, 152 playerOptions 153 ); 154 155 resolve(player); 156 }); 157 158 return this.ytPlayerPromise; 159 } 160} 161 162customElements.define('youtube-video-banner', YouTubeVideoBanner);
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.