PageSourceSearch

https://www.fuji-den.co.jp/staff-blog/wp-content/themes/glue_free002/js/header-slider.js?ver=1.4.2

js fuji-den.co.jp collected 2026-10-08 10:20:48 UTC 12,038 bytes, 377 lines download raw bytes

1// Youtube variable
2const tcdYoutubeVars = {
3	headerYoutubes: document.querySelectorAll('.swiper-slide .bg_youtube[data-video-id]'),
4	youTubeIframeAPIReady: false,
5	players: {},
6};
7
8if (tcdYoutubeVars.headerYoutubes.length) {
9	// Load Youtube IFrame Player API
10	if (!document.querySelector('script[src*="//www.youtube.com/iframe_api"]')) {
11		tcdYoutubeVars.ApiTag = document.createElement('script');
12		tcdYoutubeVars.ApiTag.src = 'https://www.youtube.com/iframe_api';
13
14		tcdYoutubeVars.firstScriptTag =document.getElementsByTagName('script')[0];
15		tcdYoutubeVars.firstScriptTag.parentNode.insertBefore(tcdYoutubeVars.ApiTag, tcdYoutubeVars.firstScriptTag);
16	}
17
18	window.onYouTubeIframeAPIReady = () => {
19		tcdYoutubeVars.youTubeIframeAPIReady = true;
20		window.dispatchEvent(new Event('tcdYouTubeIframeAPIReady'));
21	};
22}
23
24window.addEventListener('initHeaderSlider', () => {
25	const headerSlider = document.getElementById('header_slider');
26	const headerSlides = headerSlider.querySelectorAll('.swiper-slide');
27	let headerSwiper, firstItem, headerYoutubes;
28
29	if (!headerSlider || !window.Swiper) {
30		return;
31	}
32
33	// Video・Youtube再生監視間隔
34	const observeInterval = 200;
35
36	// Videoの再生コントロール
37	const videoControll = (slide, action) => {
38		const video = slide.querySelector('video');
39		if (!video) {
40			if (!headerSwiper.autoplay.running) {
41				headerSwiper.autoplay.start();
42			}
43			return;
44		}
45
46		// Video再生監視
47		const observeVideo = () => {
48			if (video.paused) {
49				clearInterval(video.tcdTimer);
50				if (!headerSwiper.autoplay.running) {
51					headerSwiper.autoplay.start();
52				}
53				if (slide.classList.contains('swiper-slide-active')) {
54					headerSwiper.slideNext(headerSwiper.params.speed, true);
55				}
56			} else if (
57				slide.classList.contains('swiper-slide-active') &&
58				video.duration - video.currentTime < (headerSwiper.params.speed + observeInterval) / 1000
59			) {
60				clearInterval(video.tcdTimer);
61				headerSwiper.autoplay.start();
62				headerSwiper.slideNext(headerSwiper.params.speed, true);
63			}
64		};
65
66		if (action === 'play') {
67			headerSwiper.autoplay.stop();
68			video.currentTime = 0;
69			video.muted = true;
70			if (headerSwiper.slides.length === 1) {
71				video.loop = true;
72			}
73			video.play();
74			video.tcdTimer = setInterval(observeVideo, observeInterval);
75		} else if (action === 'pause') {
76			clearInterval(video.tcdTimer);
77			video.pause();
78		}
79	};
80
81	// Youtubeの再生コントロール
82	const youtubeControll = (slide, action) => {
83		const ytelem = slide.querySelector('.bg_youtube');
84		if (!ytelem) {
85			return;
86		}
87		if (!ytelem.id) {
88			ytelem.id = 'youtube-' + (Math.floor(Math.random() * (99999 - 10000)) + 10000);
89		}
90
91		// Youtube再生監視
92		const observeYoutube = () => {
93			if (!ytelem.id || !tcdYoutubeVars.players[ytelem.id]) {
94				return;
95			}
96
97			const player = tcdYoutubeVars.players[ytelem.id];
98
99			switch (player.getPlayerState()) {
100				case 3: // YT.PlayerState.BUFFERING
101					break;
102
103				case 1: // YT.PlayerState.PLAYING
104					if (
105						slide.classList.contains('swiper-slide-active') &&
106						player.getDuration() - player.getCurrentTime() < (headerSwiper.params.speed + observeInterval) / 1000
107					) {
108						clearInterval(player.tcdTimer);
109						headerSwiper.autoplay.start();
110						headerSwiper.slideNext(headerSwiper.params.speed, true);
111					}
112					break;
113
114				case 0: // YT.PlayerState.ENDED
115				case 2: // YT.PlayerState.PAUSED
116					clearInterval(player.tcdTimer);
117					if (!headerSwiper.autoplay.running) {
118						headerSwiper.autoplay.start();
119					}
120					if (slide.classList.contains('swiper-slide-active')) {
121						headerSwiper.slideNext(headerSwiper.params.speed, true);
122					}
123					break;
124
125				case 5: // YT.PlayerState.CUED
126					if (slide.classList.contains('swiper-slide-active')) {
127						player.playVideo();
128					}
129					break;
130
131				case -1: // YT.PlayerState.UNSTARTED
132				default:
133					clearInterval(player.tcdTimer);
134			}
135		};
136
137		if (action === 'play') {
138			headerSwiper.autoplay.stop();
139		}
140
141		if (tcdYoutubeVars.players[ytelem.id]) {
142			if (action === 'play') {
143				tcdYoutubeVars.players[ytelem.id].seekTo(0, true);
144				tcdYoutubeVars.players[ytelem.id].playVideo();
145				clearInterval(tcdYoutubeVars.players[ytelem.id].tcdTimer);
146				setTimeout(() => {
147					tcdYoutubeVars.players[ytelem.id].tcdTimer = setInterval(observeYoutube, observeInterval);
148				}, 500);
149			} else if (action === 'pause') {
150				clearInterval(tcdYoutubeVars.players[ytelem.id].tcdTimer);
151				tcdYoutubeVars.players[ytelem.id].pauseVideo();
152			}
153
154			return;
155		}
156
157		const initSlideYoutube = () => {
158			const player = new YT.Player(ytelem.id, {
159				videoId: ytelem.dataset.videoId,
160				playerVars: {
161					controls: 0,
162					fs: 0,
163					iv_load_policy: 3,
164					loop: headerSlides.length === 1 ? 1 : 0,
165					mute: 1,
166					playlist: headerSlides.length === 1 ? ytelem.dataset.videoId : null,
167					playsinline: 1,
168					rel: 0,
169					showinfo: 0,
170				},
171				events: {
172					onReady: (e) => {
173						if (!tcdYoutubeVars.players[ytelem.id]) {
174							tcdYoutubeVars.players[ytelem.id] = player;
175							fitYoutube();
176
177							if (action === 'play' && slide.classList.contains('swiper-slide-active')
178							) {
179								player.playVideo();
180								setTimeout(() => {
181									player.tcdTimer = setInterval(observeYoutube, observeInterval);
182								}, 500);
183							}
184						}
185					},
186					// Swiperでloop: trueだとDOM操作でスライド順を操作する関係でonStateChangeは1週目しか動作しない
187					//onStateChange: (e) => {},
188				},
189			});
190		};
191
192		if (tcdYoutubeVars.youTubeIframeAPIReady) {
193			initSlideYoutube();
194		} else {
195			window.addEventListener('tcdYouTubeIframeAPIReady', initSlideYoutube, { once: true });
196		}
197	};
198
199	// Youtube fit to slider
200	const fitYoutube = () => {
201		const styles = {};
202
203		if (Math.floor((headerSwiper.height / headerSwiper.width) * 100) > 56) {
204			// Slider size is horizontally longer than 16:9
205			const ytw = Math.ceil((headerSwiper.height / 9) * 16);
206			const ytl = (ytw - headerSwiper.width) / -2;
207			styles.width = ytw + 'px';
208			styles.left = ytl + 'px';
209			styles.height = headerSwiper.height + 'px';
210			styles.top = '0px';
211		} else {
212			// Slider size is vertically longer than 16: 9
213			const yth = Math.ceil((headerSwiper.width / 16) * 9);
214			const ytt = (yth - headerSwiper.height) / -2;
215			styles.height = yth + 'px';
216			styles.top = ytt + 'px';
217			styles.width = headerSwiper.width + 'px';
218			styles.left = '0px';
219		}
220
221		// iframe化でDOM変わるので再取得してスタイルセット
222		headerYoutubes = headerSlider.querySelectorAll('.swiper-slide .bg_youtube');
223		headerYoutubes.forEach((el) => {
224			el.style.height = styles.height;
225			el.style.left = styles.left;
226			el.style.top = styles.top;
227			el.style.width = styles.width;
228		});
229	};
230
231	// 1枚目スライド
232	firstItem = headerSlider.querySelector('.swiper-slide.first_item');
233
234	// Youtubeスライドs
235	headerYoutubes = headerSlider.querySelectorAll('.swiper-slide .bg_youtube');
236
237	// Swiper
238	headerSwiper = new Swiper(headerSlider, {
239		effect: 'fade',
240    direction: headerSlider.dataset.slide_direction,
241		loop: true,
242		slidesPerView: 1,
243		speed: headerSlider.dataset.fade_speed,
244		autoplay: {
245			delay: headerSlider.dataset.interval - 0 || 5000,
246			disableOnInteraction: false,
247		},
248    pagination: {
249      el: '#header_slider_pagination',
250      clickable: true,
251    },
252    allowTouchMove: false,
253    threshold:999999,
254    breakpoints: {
255      1200: {
256        allowTouchMove: true,
257        threshold:100,
258      }
259    },
260		on: {
261			resize: (swiper) => {
262				if (headerYoutubes.length) {
263					fitYoutube();
264				}
265			},
266			slideChangeTransitionStart: (swiper) => {
267
268        // スライドアニメーション中はスワイプを受け付け停止
269        if (!document.body.classList.contains('mobile')) {
270          headerSwiper.allowTouchMove = false;
271        }
272
273        // スライドインしてくるアイテムのみにanimation_startクラスを付ける
274//        swiper.slides[swiper.activeIndex].classList.add('animation_start');
275        var newSlideStart = swiper.slides[swiper.activeIndex];
276        newSlideStart.classList.add('animation_start');
277        // will-changeをtransformに設定
278        newSlideStart.style.willChange = 'transform';
279        newSlideStart.querySelector('.item_inner').style.willChange = 'transform';
280        //newSlideStart.querySelector('.bg_image').style.willChange = 'transform';
281
282        // スライドアニメーション開始時にpaginationを無効化
283        var pagination = document.querySelector('.swiper-pagination');
284        pagination.style.pointerEvents = 'none';
285
286				// 1枚目スライド first_itemクラス削除
287				if (firstItem) {
288					firstItem.classList.remove('disable-inner-transition', 'first_item');
289					firstItem = null;
290				}
291
292				const newSlide = swiper.slides[swiper.activeIndex];
293				const prevSlide = swiper.previousIndex !== undefined ? swiper.slides[swiper.previousIndex] : null;
294
295				if (newSlide.dataset.itemType === 'type2') {
296					videoControll(newSlide, 'play');
297				} else if (newSlide.dataset.itemType === 'type3') {
298					youtubeControll(newSlide, 'play');
299				} else if (!swiper.autoplay.running) {
300					swiper.autoplay.start();
301				}
302
303				newSlide.classList.remove('p-effect-reverse', 'p-effect-slidein', 'p-effect-slideout');
304
305				prevSlide && prevSlide.classList.remove('p-effect-reverse', 'p-effect-slideout');
306
307				// クラスのslidePrevTransitionStartを待つためsetTimeout
308				setTimeout(() => {
309					newSlide.classList.add('p-effect-slidein');
310					prevSlide && prevSlide.classList.remove('p-effect-slidein');
311					prevSlide && prevSlide.classList.add('p-effect-slideout');
312				}, 1);
313			},
314			slideChangeTransitionEnd: (swiper) => {
315
316        // スワイプの受け付けを再開
317        if (!document.body.classList.contains('mobile')) {
318          setTimeout(() => {
319            headerSwiper.allowTouchMove = true;
320          }, 1000);
321        }
322
323        // 全てのアイテムからanimation_startクラスを外す
324        for (var i = 0; i < swiper.slides.length; i++) {
325//          swiper.slides[i].classList.remove('animation_start');
326          var slide = swiper.slides[i];
327          slide.classList.remove('animation_start');
328          // will-changeをリセット
329          slide.style.willChange = 'auto';
330          var itemInner = slide.querySelector('.item_inner');
331          var bgImage = slide.querySelector('.bg_image');
332          if (itemInner) itemInner.style.willChange = 'auto';
333          if (bgImage) bgImage.style.willChange = 'auto';
334        }
335
336        // スライドアニメーション終了時にpaginationを再度有効化
337        var pagination = document.querySelector('.swiper-pagination');
338        setTimeout(function() {
339          pagination.style.pointerEvents = 'all';
340        }, 500);
341
342				const newSlide = swiper.slides[swiper.activeIndex];
343				const prevSlide = swiper.previousIndex !== undefined ? swiper.slides[swiper.previousIndex] : null;
344
345				newSlide.classList.remove('p-effect-reverse');
346
347				if (prevSlide) {
348					if (prevSlide.dataset.itemType === 'type2') {
349						videoControll(prevSlide, 'pause');
350					} else if (prevSlide.dataset.itemType === 'type3') {
351						youtubeControll(prevSlide, 'pause');
352					}
353
354					prevSlide.classList.remove('p-effect-reverse', 'p-effect-slidein', 'p-effect-slideout');
355				}
356			},
357			slidePrevTransitionStart: (swiper) => {
358				const newSlide = swiper.slides[swiper.activeIndex];
359				const prevSlide = swiper.previousIndex !== undefined ? swiper.slides[swiper.previousIndex] : null;
360
361				// 戻るエフェクト
362				newSlide.classList.add('p-effect-reverse');
363				prevSlide && prevSlide.classList.add('p-effect-reverse');
364			},
365		},
366	});
367
368	// 1枚目スライドエフェクト
369	firstItem.classList.add('p-effect-slidein');
370
371	// 1枚目スライドが動画・Youtubeの対策
372	if (firstItem.dataset.itemType === 'type2') {
373		videoControll(firstItem, 'play');
374	} else if (firstItem.dataset.itemType === 'type3') {
375		youtubeControll(firstItem, 'play');
376	}
377});

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.