PageSourceSearch

https://www.tokyu-snow-resort.com/lp/smartclub/help/assets/js/common.js

js tokyu-snow-resort.com collected 2026-09-26 04:59:48 UTC 9,456 bytes, 255 lines download raw bytes

1// ハンバーガーメニューを開いているときにメインコンテンツのスクロールを無効にする
2/*document.addEventListener('DOMContentLoaded', function () {
3  let scrollpos = 0;
4  document.querySelectorAll('[name="headmenu"]').forEach(function (elem) {
5    elem.addEventListener('change', function () {
6      if (this.checked) {
7        // スクロールを無効にする
8        scrollpos = window.scrollY || document.documentElement.scrollTop;
9        document.documentElement.classList.add('scroll-prevent');
10        document.documentElement.style.top = -scrollpos + 'px';
11      } else {
12        // スクロール無効を解除する
13        document.documentElement.classList.remove('scroll-prevent');
14        document.documentElement.style.top = '0';
15        window.scrollTo(0, scrollpos);
16      }
17    });
18  });
19});*/
20
21function matchHeight() {
22  const windowWidth = window.innerWidth;
23
24  // 一度高さをリセット
25  document.querySelectorAll('[data-mh]').forEach(el => {
26    el.style.height = 'auto';
27  });
28
29  // data-mhの値ごとにグループ分け(かつ有効なものだけ)
30  const groups = {};
31  document.querySelectorAll('[data-mh]').forEach(el => {
32    const group = el.getAttribute('data-mh');
33    const enableMobile = el.getAttribute('enable-mobile') === 'true';
34
35    // 896px以下で、モバイル未対応ならスキップ
36    if (windowWidth <= 896 && !enableMobile) return;
37
38    groups[group] = groups[group] || [];
39    groups[group].push(el);
40  });
41
42  // 各グループで最大の高さを計算して揃える
43  for (const key in groups) {
44    const elements = groups[key];
45    const maxHeight = Math.max(...elements.map(el => el.offsetHeight));
46    elements.forEach(el => {
47      el.style.height = `${maxHeight}px`;
48    });
49  }
50}
51
52window.addEventListener('load', matchHeight);
53window.addEventListener('resize', matchHeight);
54
55
56// animation 発火
57document.addEventListener('DOMContentLoaded', () => {
58  const targets = document.querySelectorAll('[data-animation]');
59  const inView = (el) => {
60    const rect = el.getBoundingClientRect();
61    return (
62      rect.top < window.innerHeight && rect.bottom > 0
63    );
64  };
65  const animate = () => {
66    targets.forEach(el => {
67      if (inView(el)) {
68        el.classList.add('is-visible');
69      } else {
70        el.classList.remove('is-visible'); // 何度も出入りできる
71      }
72    });
73  };
74
75  window.addEventListener('scroll', animate);
76  window.addEventListener('resize', animate);
77  animate(); // 初回実行
78});
79
80// ========================
81// スムーススクロール
82// ========================
83// 画面固定配置のヘッダーが存在する場合、ブロックサイズを取得
84// スクロール時にヘッダー高さを含める場合、headerにdata-fixed-headerを記載
85const getHeaderBlockSize = function() {
86  const header = document.querySelector("[data-fixed-header]");
87  if (!header) return 0;
88
89  const computedStyle = window.getComputedStyle(header);
90  const position = computedStyle.position;
91  const blockSize = parseFloat(computedStyle.height);
92  const isFixed = position === "fixed" || position === "sticky";
93
94  console.log(`Header block size: ${blockSize}px`); // デバッグ用に追加
95  return isFixed ? blockSize : 0;
96};
97
98const scrollToTarget = function(element) {
99  const headerBlockSize = getHeaderBlockSize();
100  // ユーザーが視差効果を減らす設定をしているかどうかを判定
101  const isPrefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
102  // 視差効果を減らす設定がされている場合は 'instant'、そうでない場合は 'smooth' にスクロール動作を設定
103  const scrollBehavior = isPrefersReduced ? "instant" : "smooth";
104
105  const elementTop = element.getBoundingClientRect().top;
106  //const offsetPosition = elementTop + window.scrollY - headerBlockSize - 20; // 20px上にスクロールするようにする
107  const offsetPosition = elementTop + window.scrollY - headerBlockSize + 50;
108
109  window.scrollTo({
110    top: offsetPosition,
111    behavior: scrollBehavior,
112  });
113
114  console.log(`Scrolling to element with offset position: ${offsetPosition}px`); // デバッグ用に追加
115};
116
117const focusTarget = function(element) {
118  // ターゲット要素にフォーカスを設定
119  element.focus({ preventScroll: true });
120  // アクティブな要素がターゲット要素でない場合
121  if (document.activeElement !== element) {
122    // ターゲット要素のtabindexを一時的に-1に設定
123    element.setAttribute("tabindex", "-1");
124    // 再度フォーカスを設定
125    element.focus({ preventScroll: true });
126    // フォーカスが外れた後、tabindexを元に戻す
127    element.removeAttribute("tabindex");
128  }
129};
130
131const handleClick = function(event) {
132  // クリックされたボタンが左ボタンでない場合は処理を中断
133  if (event.button !== 0) return;
134  // クリックされたリンク要素を取得
135  // クリックされた要素がa要素またはa要素の子孫ではない場合は処理を中断
136  const currentLink = event.target.closest('a[href*="#"]');
137  if (!currentLink) return;
138
139  const hash = currentLink.hash;
140  // hash(リンクのハッシュ部分)が存在しない場合は処理を中断
141  // クリックされたa要素のrole属性がtabである場合は処理を中断
142  // クリックされたa要素のrole属性がbuttonである場合は処理を中断
143  // クリックされたa要素にdata-smooth-scroll="disabled"が指定されている場合は処理を中断
144  if (!hash ||
145      currentLink.getAttribute("role") === "tab" ||
146      currentLink.getAttribute("role") === "button" ||
147      currentLink.getAttribute("data-smooth-scroll") === "disabled") {
148    return;
149  }
150
151  // アンカーリンクのハッシュ部分からターゲット要素を取得
152  const target = document.getElementById(decodeURIComponent(hash.slice(1))) || (hash === "#top" && document.body);
153
154  if (target) {
155    // デフォルトのリンク遷移を防止
156    event.preventDefault();
157    // ターゲット要素までスムースにスクロール
158    scrollToTarget(target);
159    // ターゲット要素にフォーカスを設定
160    focusTarget(target);
161    // ブラウザの履歴にアンカーリンクのハッシュを追加
162    if (!(hash === "#top")) {
163      history.pushState({}, "", hash);
164    }
165  }
166};
167
168const handleHashOnLoad = function() {
169  const hash = window.location.hash;
170  if (hash) {
171    const target = document.getElementById(decodeURIComponent(hash.slice(1))) || (hash === "#top" && document.body);
172    if (target) {
173      // ターゲット要素までスムースにスクロール
174      scrollToTarget(target);
175      // ターゲット要素にフォーカスを設定
176      focusTarget(target);
177    }
178  }
179};
180
181const initializeSmoothScroll = function() {
182  document.addEventListener("click", handleClick, { capture: true });
183  document.addEventListener("DOMContentLoaded", handleHashOnLoad);
184  window.addEventListener("load", handleHashOnLoad); // ページロード後にハッシュを処理
185};
186
187initializeSmoothScroll();
188
189// ========================
190// 現在のページのヘッダー内メニューにcurrent付与
191// ========================
192document.addEventListener('DOMContentLoaded', function () {
193  const links = document.querySelectorAll('.header-menu li a');
194  const currentPage = location.pathname;
195
196  links.forEach(link => {
197    const href = link.getAttribute('href');
198
199    // hrefが空の場合はcurrentを消去
200    if (!href) {
201      link.parentNode.classList.remove('current');
202      return;
203    }
204
205    // サイトのTOPページの場合
206    if (currentPage === '/index.html' || currentPage === '/') {
207      if (href === '/') {
208        link.parentNode.classList.add('current');
209      } else {
210        link.parentNode.classList.remove('current');
211      }
212    // その他のページの場合
213    } else {
214      // currentPage と href の完全一致を確認
215      if (currentPage === href || currentPage === href + '/' || currentPage + '/' === href) {
216        link.parentNode.classList.add('current');
217      } else {
218        link.parentNode.classList.remove('current');
219      }
220    }
221  });
222});
223
224// ========================
225// ページトップボタン
226// ========================
227// 上にスクロールしたときだけ表示
228const pageTop = document.querySelector('.pagetop');
229let lastScrollY = window.scrollY;
230window.addEventListener('scroll', () => {
231  const currentScrollY = window.scrollY;
232  const isScrollingUp = currentScrollY < lastScrollY;
233  const isBeyond = currentScrollY > 100;
234  if (isScrollingUp && isBeyond) {
235    pageTop.classList.add('show');
236  } else {
237    pageTop.classList.remove('show');
238  }
239  lastScrollY = currentScrollY;
240});
241pageTop.addEventListener('click', () => {
242  window.scrollTo({ top: 0, behavior: 'smooth' });
243});
244
245
246// クリック時にメニュー非表示
247const links = document.querySelectorAll('.global a');
248links.forEach(link => {
249  link.addEventListener('click', () => {
250    const checkbox = document.getElementById('menu-cb');
251    if (checkbox) {
252      checkbox.checked = false;
253    }
254  });
255});

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.