PageSourceSearch

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

js luxnetcorp.com.tw collected 2026-10-04 13:25:49 UTC 7,462 bytes, 215 lines download raw bytes

1class GtutYoutubeText08Player {
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_text08");
31        if (this.firstInThisSite) {
32            this.firstRePlayVideo = false;
33        } else {
34            sessionStorage.setItem("inThisSite_text08", 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            // 等待 YT API 加載完成
64            if (window.onYouTubeIframeAPIReady) {
65                const oldCallback = window.onYouTubeIframeAPIReady;
66                window.onYouTubeIframeAPIReady = () => {
67                    oldCallback();
68                    this.initPlayer();
69                    // console.log('08yt api ready');
70                }
71
72                this.initPlayer();
73            } else {
74                window.onYouTubeIframeAPIReady = () => {
75                    this.initPlayer();
76                }
77            }
78
79        // console.log('init08');
80
81
82    }
83
84    initPlayer() {
85
86            // console.log('initPlayer8');
87            if (!this.playerInitialized) {
88                const hiddenProperty = 'hidden' in document
89                ? 'hidden'
90                : 'webkitHidden' in document
91                    ? 'webkitHidden'
92                    : 'mozHidden' in document
93                        ? 'mozHidden'
94                        : null;
95            const visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange');
96            let leaveTime;
97            let backTime;
98            const onVisibilityChange = () => {
99                if (!document[hiddenProperty]) {
100                    backTime = Date.now();
101                    if (leaveTime == undefined || backTime > leaveTime + 600000) {
102                        location.reload();
103                    }
104                } else {
105                    leaveTime = Date.now();
106                }
107            };
108                document.addEventListener(visibilityChangeEvent, onVisibilityChange);
109            const that = this
110            function checkYTPlayer() {
111                if (typeof YT !== 'undefined') {
112                    // YT exists, create the player
113                    that.player = new YT.Player(`${that.videoIframe}`, that.youtubeSettings);
114                } else {
115                    // YT does not exist yet, check again after 200 milliseconds
116                    setTimeout(checkYTPlayer, 300);
117                }
118            }
119
120            // 開始檢查 YT Player
121            checkYTPlayer();
122
123            if (this.youtubeSettings.useCoverImg) {
124                this.addCoverImg(this.youtubeSettings.useCoverImg);
125            }
126                this.playerInitialized = true;
127
128                // console.log('playerInitialized08');
129        }
130    }
131
132    transformVideoId(id) {
133        const youtubeVideoIdLength = 11;
134        let newId = '';
135        if (id.length <= youtubeVideoIdLength) {
136            return id;
137        }
138        if (id.indexOf('watch?v=') > 0) {
139            newId = id.substr(id.indexOf('watch?v=') + 8, youtubeVideoIdLength);
140        } else if (id.indexOf('youtu.be/') > 0) {
141            newId = id.substr(id.indexOf('youtu.be/') + 9, youtubeVideoIdLength);
142        } else if (id.indexOf('/embed/') > 0) {
143            newId = id.substr(id.indexOf('/embed/') + 7, youtubeVideoIdLength);
144        } else {
145            newId = id.substr(id.lastIndexOf('/') + 1, id.length);
146            if (newId.length > youtubeVideoIdLength) {
147                newId = newId.substr(0, youtubeVideoIdLength);
148            }
149        }
150        return newId;
151    }
152
153    addCoverImg(src) {
154        let imgUrl;
155        if (src === true) {
156            imgUrl = `https://img.youtube.com/vi/${this.youtubeSettings.videoId}/maxresdefault.jpg`;
157            const customCoverImg = this.overlay.getAttribute('data-coverimg');
158            if (customCoverImg) {
159                imgUrl = customCoverImg;
160            }
161        } else {
162            imgUrl = src;
163        }
164
165        this.overlay.style.backgroundImage = `url(${imgUrl})`;
166    }
167
168    removerCoverImg() {
169        this.overlay.style.opacity = 0;
170    }
171
172    extendConfig(a, b) {
173        for (const key in b) if (b.hasOwnProperty(key)) a[key] = b[key];
174        return a;
175    }
176
177    checkLoopShowControls= () => {
178        if (!this.youtubeSettings.loop) {
179            this.overlay.style.pointerEvents = 'none';
180        }
181    }
182
183
184    onPlayerReady = (e) => {
185
186        // console.log('onPlayerReady08');
187        if (this.youtubeSettings.useCoverImg) {
188            this.removerCoverImg();
189        }
190        if (this.youtubeSettings.autoPlay) {
191            e.target.mute().playVideo();
192        } else {
193            this.overlay.style.cursor = 'pointer';
194            this.overlay.addEventListener('click', () => {
195                e.target.playVideo();
196                this.checkLoopShowControls();
197            });
198        }
199    }
200
201    onPlayerStateChange = (event) => {
202        if (event.data === 0 && this.youtubeSettings.loop) {
203            if (this.firstRePlayVideo) {
204                this.player.loadVideoById(this.transformVideoId(this.videoId));
205                this.firstRePlayVideo = false;
206            } else {
207                event.target.playVideo();
208            }
209        }
210        if (event.data === 0 && !this.youtubeSettings.loop) {
211            this.checkLoopShowControls();
212        }
213    }
214}
215

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.