1class GtutYoutubeText08Player { 2 constructor(selector, videoIframe, config) { 3 4 this.videoIframe = videoIframe 5 this.sectionEl = selector; // selector è®æå¯¦éç DOM å ç´ 6 this.videoId = this.sectionEl.getAttribute('data-video-id'); 7 this.overlay = this.sectionEl.querySelector('.version_text_yt_overlay'); 8 this.player = null; // å¨é¡å¥ä¸å®ç¾©ææ¾å¨æå¡è®é 9 this.youtubeSettings = { 10 videoId: this.transformVideoId(this.videoId), 11 height: '1440', 12 width: '2560', 13 useCoverImg: true, 14 autoPlay: true, 15 loop: true, 16 bleed: false, 17 playerVars: { 18 controls: 0, 19 fs: 0, 20 iv_load_policy: 3, 21 rel: 0, 22 modestbranding: 1, 23 playsinline: 1, 24 }, 25 events: { 26 onReady: this.onPlayerReady, 27 onStateChange: this.onPlayerStateChange, 28 onError: this.onPlayerError, // æ°å¢é¯èª¤èçäºä»¶ 29 }, 30 }; 31 this.firstRePlayVideo = true; 32 this.firstInThisSite = sessionStorage.getItem("inThisSite_text08"); 33 if (this.firstInThisSite) { 34 this.firstRePlayVideo = false; 35 } else { 36 sessionStorage.setItem("inThisSite_text08", true); 37 } 38 this.extendConfig = this.extendConfig.bind(this); 39 this.addCoverImg = this.addCoverImg.bind(this); 40 this.removerCoverImg = this.removerCoverImg.bind(this); 41 this.checkLoopShowControls = this.checkLoopShowControls.bind(this); 42 // Call initialization function 43 this.playerInitialized = false; 44 this.apiLoaded = false; 45 this.init(config); 46 } 47 init(config) { 48 this.youtubeSettings = this.extendConfig(this.youtubeSettings, config); 49 if (!this.youtubeSettings.loop) { 50 this.youtubeSettings.playerVars.controls = 1; 51 } 52 if (!this.apiLoaded) { 53 // å è¼ YT API 54 let existingScript = document.querySelector('script[src="' + 'https://www.youtube.com/iframe_api' + '"]'); 55 if (!existingScript) { 56 const tag = document.createElement('script'); 57 tag.src = 'https://www.youtube.com/iframe_api'; 58 const firstScriptTag = document.getElementsByTagName('script')[0]; 59 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 60 } 61 62 // æ è®° API å·²å è½½ 63 this.apiLoaded = true; 64 } 65 // çå¾ YT API å è¼å®æ 66 if (window.onYouTubeIframeAPIReady) { 67 const oldCallback = window.onYouTubeIframeAPIReady; 68 window.onYouTubeIframeAPIReady = () => { 69 oldCallback(); 70 this.initPlayer(); 71 // console.log('08yt api ready'); 72 } 73 74 this.initPlayer(); 75 } else { 76 window.onYouTubeIframeAPIReady = () => { 77 this.initPlayer(); 78 } 79 } 80 81 // console.log('init08'); 82 83 84 } 85 86 initPlayer() { 87 88 // console.log('initPlayer8'); 89 if (!this.playerInitialized) { 90 const hiddenProperty = 'hidden' in document 91 ? 'hidden' 92 : 'webkitHidden' in document 93 ? 'webkitHidden' 94 : 'mozHidden' in document 95 ? 'mozHidden' 96 : null; 97 const visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange'); 98 let leaveTime; 99 let backTime; 100 const onVisibilityChange = () => { 101 if (!document[hiddenProperty]) { 102 backTime = Date.now(); 103 if (leaveTime == undefined || backTime > leaveTime + 600000) { 104 location.reload(); 105 } 106 } else { 107 leaveTime = Date.now(); 108 } 109 }; 110 document.addEventListener(visibilityChangeEvent, onVisibilityChange); 111 const that = this 112 function checkYTPlayer() { 113 if (typeof YT !== 'undefined') { 114 // YT exists, create the player 115 that.player = new YT.Player(`${that.videoIframe}`, that.youtubeSettings); 116 } else { 117 // YT does not exist yet, check again after 200 milliseconds 118 setTimeout(checkYTPlayer, 300); 119 } 120 } 121 122 // éå§æª¢æ¥ YT Player 123 checkYTPlayer(); 124 125 if (this.youtubeSettings.useCoverImg) { 126 this.addCoverImg(this.youtubeSettings.useCoverImg); 127 } 128 this.playerInitialized = true; 129 130 // console.log('playerInitialized08'); 131 } 132 } 133 134 transformVideoId(id) { 135 const youtubeVideoIdLength = 11; 136 let newId = ''; 137 if (id.length <= youtubeVideoIdLength) { 138 return id; 139 } 140 if (id.indexOf('watch?v=') > 0) { 141 newId = id.substr(id.indexOf('watch?v=') + 8, youtubeVideoIdLength); 142 } else if (id.indexOf('youtu.be/') > 0) { 143 newId = id.substr(id.indexOf('youtu.be/') + 9, youtubeVideoIdLength); 144 } else if (id.indexOf('/embed/') > 0) { 145 newId = id.substr(id.indexOf('/embed/') + 7, youtubeVideoIdLength); 146 } else { 147 newId = id.substr(id.lastIndexOf('/') + 1, id.length); 148 if (newId.length > youtubeVideoIdLength) { 149 newId = newId.substr(0, youtubeVideoIdLength); 150 } 151 } 152 return newId; 153 } 154 155 addCoverImg(src) { 156 let imgUrl; 157 if (src === true) { 158 imgUrl = `https://img.youtube.com/vi/${this.youtubeSettings.videoId}/maxresdefault.jpg`; 159 const customCoverImg = this.overlay.getAttribute('data-coverimg'); 160 if (customCoverImg) { 161 imgUrl = customCoverImg; 162 } 163 } else { 164 imgUrl = src; 165 } 166 167 this.overlay.style.backgroundImage = `url(${imgUrl})`; 168 } 169 170 removerCoverImg() { 171 this.overlay.style.opacity = 0; 172 } 173 174 extendConfig(a, b) { 175 for (const key in b) if (b.hasOwnProperty(key)) a[key] = b[key]; 176 return a; 177 } 178 179 checkLoopShowControls= () => { 180 if (!this.youtubeSettings.loop) { 181 this.overlay.style.pointerEvents = 'none'; 182 } 183 } 184 185 // 顯示å°é¢åçè¼å©æ¹æ³ 186 showFallbackCover() { 187 // 確ä¿å°é¢å顯示 188 if (this.youtubeSettings.useCoverImg) { 189 this.addCoverImg(this.youtubeSettings.useCoverImg); 190 this.overlay.style.opacity = 1; // 確ä¿å°é¢åå¯è¦ 191 this.overlay.style.pointerEvents = 'auto'; // å è¨±äº¤äº 192 } 193 194 // å¯é¸ï¼é±èæé·æ¯ææ¾å¨ iframe 195 const iframe = document.getElementById(this.videoIframe); 196 if (iframe) { 197 iframe.style.display = 'none'; // é±èææ¾å¨ 198 } 199 } 200 onPlayerReady = (e) => { 201 202 // console.log('onPlayerReady08'); 203 if (this.youtubeSettings.useCoverImg) { 204 this.removerCoverImg(); 205 } 206 if (this.youtubeSettings.autoPlay) { 207 e.target.mute().playVideo(); 208 } else { 209 this.overlay.style.cursor = 'pointer'; 210 this.overlay.addEventListener('click', () => { 211 e.target.playVideo(); 212 this.checkLoopShowControls(); 213 }); 214 } 215 } 216 217 onPlayerStateChange = (event) => { 218 if (event.data === 0 && this.youtubeSettings.loop) { 219 if (this.firstRePlayVideo) { 220 this.player.loadVideoById(this.transformVideoId(this.videoId)); 221 this.firstRePlayVideo = false;
222 } else { 223 event.target.playVideo(); 224 } 225 } 226 if (event.data === 0 && !this.youtubeSettings.loop) { 227 this.checkLoopShowControls(); 228 } 229 } 230 onPlayerError = (event) => { 231 console.log('YouTube Player Error:', event.data); // å¯é¸ï¼ç¨æ¼èª¿è©¦ 232 // é¯èª¤ç¢¼åèï¼https://developers.google.com/youtube/iframe_api_reference#Events 233 // 2: ç¡æåæ¸, 5: HTML5ææ¾å¨é¯èª¤, 100: å½±çä¸åå¨, 101/150: ææ¾åé 234 235 // ç¶ç¼çé¯èª¤æï¼é¡¯ç¤ºå°é¢å 236 this.showFallbackCover(); 237 } 238} 239
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.