PageSourceSearch

https://www.luxnetcorp.com.tw/assets/frontend/javascript/plugins/gtut_youtube_player_text07.js

js luxnetcorp.com.tw collected 2026-10-04 13:25:48 UTC 7,484 bytes, 213 lines download raw bytes

1class GtutYoutubeText07Player {
2    constructor(selector, videoIframe, config) {
3
4        this.videoIframe = videoIframe
5        this.videoId = document.querySelector(`${selector}`).getAttribute('data-video-id');
6        this.overlay = document.querySelector(`${selector} .version_text_yt_overlay`);
7        this.player = null; // 在類別中定義播放器成員變量
8        this.youtubeSettings = {
9            videoId: this.transformVideoId(this.videoId),
10            height: '1440',
11            width: '2560',
12            useCoverImg: true,
13            autoPlay: true,
14            loop: true,
15            bleed: false,
16            playerVars: {
17                controls: 0,
18                fs: 0,
19                iv_load_policy: 3,
20                rel: 0,
21                modestbranding: 1,
22                playsinline: 1,
23            },
24            events: {
25                onReady: this.onPlayerReady,
26                onStateChange: this.onPlayerStateChange,
27            },
28        };
29        this.firstRePlayVideo = true;
30        this.firstInThisSite = sessionStorage.getItem("inThisSite_text07");
31        if (this.firstInThisSite) {
32            this.firstRePlayVideo = false;
33        } else {
34            sessionStorage.setItem("inThisSite_text07", true);
35        }
36        this.extendConfig = this.extendConfig.bind(this);
37        this.addCoverImg = this.addCoverImg.bind(this);
38        this.removerCoverImg = this.removerCoverImg.bind(this);
39        this.checkLoopShowControls = this.checkLoopShowControls.bind(this);
40        // Call initialization function
41        this.playerInitialized = false;
42        this.apiLoaded = false;
43        this.init(config);
44    }
45    init(config) {
46        this.youtubeSettings = this.extendConfig(this.youtubeSettings, config);
47        if (!this.youtubeSettings.loop) {
48            this.youtubeSettings.playerVars.controls = 1;
49        }
50        if (!this.apiLoaded) {
51            // 加載 YT API
52            let existingScript = document.querySelector('script[src="' + 'https://www.youtube.com/iframe_api' + '"]');
53            if (!existingScript) {
54                const tag = document.createElement('script');
55                tag.src = 'https://www.youtube.com/iframe_api';
56                const firstScriptTag = document.getElementsByTagName('script')[0];
57                firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
58            }
59
60            // 标记 API 已加载
61            this.apiLoaded = true;
62        }
63
64        // console.log('等待');
65                // 等待 YT API 加載完成
66        if (window.onYouTubeIframeAPIReady) {
67            const oldCallback = window.onYouTubeIframeAPIReady;
68            window.onYouTubeIframeAPIReady = () => {
69                oldCallback();
70                this.initPlayer();
71            }
72            this.initPlayer();
73            // console.log('07yt api ready');
74        } else {
75
76            window.onYouTubeIframeAPIReady = () => {
77                this.initPlayer();
78            }
79
80                // console.log('07 else');
81        }
82        // console.log('init07');
83
84    }
85
86    initPlayer() {
87        // console.log('initPlayer07');
88            if (!this.playerInitialized) {
89                const hiddenProperty = 'hidden' in document
90                ? 'hidden'
91                : 'webkitHidden' in document
92                    ? 'webkitHidden'
93                    : 'mozHidden' in document
94                        ? 'mozHidden'
95                        : null;
96            const visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange');
97            let leaveTime;
98            let backTime;
99            const onVisibilityChange = () => {
100                if (!document[hiddenProperty]) {
101                    backTime = Date.now();
102                    if (leaveTime == undefined || backTime > leaveTime + 600000) {
103                        location.reload();
104                    }
105                } else {
106                    leaveTime = Date.now();
107                }
108            };
109                document.addEventListener(visibilityChangeEvent, onVisibilityChange);
110                const that = this
111            function checkYTPlayer() {
112                if (typeof YT !== 'undefined') {
113                    // YT exists, create the player
114                    that.player = new YT.Player(`${that.videoIframe}`, that.youtubeSettings);
115                } else {
116                    // YT does not exist yet, check again after 200 milliseconds
117                    setTimeout(checkYTPlayer, 300);
118                }
119            }
120
121            // 開始檢查 YT Player
122            checkYTPlayer();
123            if (this.youtubeSettings.useCoverImg) {
124                this.addCoverImg(this.youtubeSettings.useCoverImg);
125            }
126                this.playerInitialized = true;
127                // console.log('playerInitialized07');
128        }
129    }
130
131    transformVideoId(id) {
132        const youtubeVideoIdLength = 11;
133        let newId = '';
134        if (id.length <= youtubeVideoIdLength) {
135            return id;
136        }
137        if (id.indexOf('watch?v=') > 0) {
138            newId = id.substr(id.indexOf('watch?v=') + 8, youtubeVideoIdLength);
139        } else if (id.indexOf('youtu.be/') > 0) {
140            newId = id.substr(id.indexOf('youtu.be/') + 9, youtubeVideoIdLength);
141        } else if (id.indexOf('/embed/') > 0) {
142            newId = id.substr(id.indexOf('/embed/') + 7, youtubeVideoIdLength);
143        } else {
144            newId = id.substr(id.lastIndexOf('/') + 1, id.length);
145            if (newId.length > youtubeVideoIdLength) {
146                newId = newId.substr(0, youtubeVideoIdLength);
147            }
148        }
149        return newId;
150    }
151
152    addCoverImg(src) {
153        let imgUrl;
154        if (src === true) {
155            imgUrl = `https://img.youtube.com/vi/${this.youtubeSettings.videoId}/maxresdefault.jpg`;
156            const customCoverImg = this.overlay.getAttribute('data-coverimg');
157            if (customCoverImg) {
158                imgUrl = customCoverImg;
159            }
160        } else {
161            imgUrl = src;
162        }
163
164        this.overlay.style.backgroundImage = `url(${imgUrl})`;
165    }
166
167    removerCoverImg() {
168        this.overlay.style.opacity = 0;
169    }
170
171    extendConfig(a, b) {
172        for (const key in b) if (b.hasOwnProperty(key)) a[key] = b[key];
173        return a;
174    }
175
176    checkLoopShowControls= () => {
177        if (!this.youtubeSettings.loop) {
178            this.overlay.style.pointerEvents = 'none';
179        }
180    }
181
182
183    onPlayerReady = (e) => {
184        // console.log('onPlayerReady07');
185        if (this.youtubeSettings.useCoverImg) {
186            this.removerCoverImg();
187        }
188        if (this.youtubeSettings.autoPlay) {
189            e.target.mute().playVideo();
190        } else {
191            this.overlay.style.cursor = 'pointer';
192            this.overlay.addEventListener('click', () => {
193                e.target.playVideo();
194                this.checkLoopShowControls();
195            });
196        }
197    }
198
199    onPlayerStateChange = (event) => {
200        if (event.data === 0 && this.youtubeSettings.loop) {
201            if (this.firstRePlayVideo) {
202                this.player.loadVideoById(this.transformVideoId(this.videoId));
203                this.firstRePlayVideo = false;
204            } else {
205                event.target.playVideo();
206            }
207        }
208        if (event.data === 0 && !this.youtubeSettings.loop) {
209            this.checkLoopShowControls();
210        }
211    }
212}
213

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.