PageSourceSearch

https://bioliss.jp/assets/js/modal.js

js bioliss.jp collected 2026-10-04 14:20:43 UTC 3,978 bytes, 147 lines download raw bytes

1// モーダル
2const modalOpenButtons = document.querySelectorAll('.open-modal-button');
3const modalCloseBtns = document.querySelectorAll('.close-modal-button')
4
5let previousFocusElement = null
6
7// YouTube動画を再生するモーダルのみ設定を反映 ----------------------------------------
8var player;
9var pendingVideoId = null;
10
11function registerYouTubeReadyHandler(handler) {
12  var previousHandler = window.onYouTubeIframeAPIReady;
13  window.onYouTubeIframeAPIReady = function () {
14    if (typeof previousHandler === 'function') {
15      previousHandler();
16    }
17    handler();
18  };
19}
20
21// YouTube Iframe APIを非同期で読み込む
22(function loadYouTubeAPI(){
23  var tag = document.createElement('script');
24  tag.src = "https://www.youtube.com/iframe_api";
25  var firstScriptTag = document.getElementsByTagName('script')[0];
26  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
27})();
28
29function initModalYouTubePlayer() {
30  player = new YT.Player('movieContainer', {
31    height: '360',
32    width: '640',
33    playerVars: {
34        autoplay: 1,
35        disablekb: 1,
36        enablejsapi: 1,
37        iv_load_policy: 3,
38        playsinline: 1,
39        rel: 0,
40    },
41    events: {
42      'onReady': onPlayerReady,
43      'onStateChange': onPlayerStateChange
44    }
45  });
46
47  if (pendingVideoId) {
48    player.loadVideoById(pendingVideoId);
49    pendingVideoId = null;
50  }
51}
52
53registerYouTubeReadyHandler(initModalYouTubePlayer);
54
55function onPlayerReady(event) {
56  event.target.playVideo();
57}
58
59function onPlayerStateChange(event) {
60  var ytStatus = event.target.getPlayerState();
61  if (ytStatus == YT.PlayerState.ENDED) {
62    if (player.isMuted && player.isMuted()) {
63      player.unMute();
64    }
65    player.stopVideo();
66  }
67}
68
69// ---------------------------------------------------------------------------
70
71function openModal(modalContainer) {
72  previousFocusElement = document.activeElement
73  
74  modalContainer.classList.add('open');
75  const focusableElements = modalContainer.querySelectorAll('a, button, input, textarea, select, [tabindex]:not([tabindex="-1"])');
76  if (focusableElements.length > 0) {
77    focusableElements[0].focus();
78  }
79}
80
81function closeModal(modalContainer) {
82  modalContainer.classList.remove('open');
83  
84  if (previousFocusElement && previousFocusElement.focus) {
85    previousFocusElement.focus()
86  }
87
88  // YT動画が再生されている場合は停止
89  if (player) {
90    player.stopVideo();
91  }
92}
93
94if (modalOpenButtons) {
95  modalOpenButtons.forEach(button => {
96    button.addEventListener('click', e => {
97      e.preventDefault(); 
98      const modalContainer = document.querySelector('.' + button.dataset.modal);
99      openModal(modalContainer);
100
101      // YT動画がある場合は動画IDを取得して再生
102      const videoId = button.dataset.videoId;
103      if (videoId) {
104        if (player) {
105          player.loadVideoById(videoId);
106        } else {
107          pendingVideoId = videoId;
108        }
109      }
110    });
111  });
112}
113
114if (modalCloseBtns) {
115  modalCloseBtns.forEach(btn => {
116    btn.addEventListener('click', e => {
117      e.preventDefault();
118      const modalContainer = btn.closest('.modal-container');
119      closeModal(modalContainer);
120
121    });
122  });
123}
124
125window.addEventListener('click', e => {
126  const openContainer = document.querySelector('.modal-container.open');
127  if (!openContainer) return;
128
129  const modalInner = openContainer.querySelector('.modal-inner');
130  if (
131    modalInner &&
132    (e.target === modalInner || !modalInner.contains(e.target)) &&
133    !e.target.closest('.open-modal-button')) {
134    closeModal(openContainer);
135  }
136})
137
138// Escapeキーでモーダルを閉じる
139window.addEventListener('keydown', e => {
140  if (e.key === 'Escape') {
141    const modal = document.querySelector('.modal-container.open');
142    if (modal) {
143      closeModal(modal)
144    }
145  }
146})
147

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.