PageSourceSearch

https://wrc2025tokyo.com/scripts/common.js?v=1

js wrc2025tokyo.com collected 2026-09-25 06:06:35 UTC 13,007 bytes, 427 lines download raw bytes

1$(function () {
2  // 画像の読込みバーとファーストアニメーション
3  setLoadingImageBar();
4
5  // 画面内部に入ったらアニメーションを実行
6  setIntersectionObserver();
7
8  // Luxy.jsの設定
9  // setUpLuxy();
10
11  // メニューボタン
12  setMenuButton();
13
14  // ヘッダーの設定
15  setHeader();
16
17  // コメント全文見るボタン
18  setToggleComment();
19
20  // チャンピオンカード
21  setToggleChampion();
22
23  // スクロールアニメーション
24  setScrollAnimation();
25
26  // モーダルの設定
27  setModal();
28
29  // スクロールバー
30  handleScrollBar();
31  dragScrollbar();
32
33  // ハンバーガーメニュー
34  setHamburger();
35
36  // プレイヤーモーダル タブ切り替え
37  // setPlayersModal();
38});
39
40const setLoadingImageBar = async () => {
41  const preloadImages = (imagePaths, callback) => {
42    const loadingBar = document.querySelector(".js-loading-bar");
43    let loadedImages = 0;
44    const totalImages = imagePaths.length;
45    // スマホのみスクロール固定
46    if (window.innerWidth <= 820) {
47      // スクロールをトップにする
48      window.scrollTo(0, 0);
49      document.body.style.overflow = "hidden";
50    }
51    imagePaths.forEach(src => {
52      const img = new Image();
53      img.src = src;
54      img.onload = img.onerror = () => {
55        loadedImages++;
56        loadingBar.style.width = `${(loadedImages / totalImages) * 100}%`;
57        if (loadedImages === totalImages) {
58          callback();
59        }
60      };
61    });
62  };
63  const hidePreloader = () => {
64    setTimeout(() => {
65      // ローディング画面を非表示
66      const cover = document.querySelector(".js-transition-cover");
67      cover.classList.add("is-active");
68      // ファーストアニメーション
69      setFirstAnimation();
70    }, 500);
71  };
72  const images = Array.from(document.querySelectorAll("img")).map(
73    img => img.src
74  );
75  preloadImages(images, hidePreloader);
76};
77
78const setFirstAnimation = () => {
79  setTimeout(() => {
80    startFirstAnimation();
81  }, 500);
82  const startFirstAnimation = () => {
83    // アイコンを順番に表示
84    const firstIcons = document.querySelectorAll(".js-first-animation");
85    firstIcons.forEach(icon => {
86      let time = Math.floor(Math.random() * 700);
87      setTimeout(() => {
88        icon.classList.add("active");
89      }, time);
90    });
91
92    // ロゴを順番に表示
93    const logos = document.querySelectorAll(".js-first-logo-animation");
94    // スマホじゃない場合のみアニメーションを実行
95    if (window.innerWidth > 820) {
96      setTimeout(() => {
97        // 順番にアニメーションを実行
98        logos.forEach((logo, index) => {
99          let time = index * 150;
100          setTimeout(
101            () => {
102              logo.classList.add("active");
103              if (index === logos.length - 1) {
104                // ロゴが最後まで表示されたら、スクロール固定を解除
105                document.body.style.overflow = "visible";
106              }
107            },
108            time + index * 100
109          );
110        });
111      }, 1000);
112    } else {
113      setTimeout(() => {
114        // コピーを非表示
115        const copy = document.querySelector(".js-first-copy");
116        copy.classList.add("is-hidden");
117        // ロゴを表示
118        setTimeout(() => {
119          // 順番にアニメーションを実行
120          logos.forEach((logo, index) => {
121            let time = index * 150;
122            setTimeout(
123              () => {
124                logo.classList.add("active");
125                if (index === 2) {
126                  // ロゴが最後まで表示されたら、スクロール固定を解除
127                  document.body.style.overflow = "visible";
128                }
129              },
130              time + index * 100
131            );
132          });
133        }, 1000);
134      }, 1000);
135    }
136  };
137};
138
139const setHeader = () => {
140  $(window).on("scroll", function () {
141    if ($(this).scrollTop() > 200) {
142      $(".js-header").addClass("js-header-active");
143    } else {
144      $(".js-header").removeClass("js-header-active");
145      const hamburger = document.querySelector(".hamburger");
146      hamburger.classList.remove("hamburger-open");
147    }
148  });
149};
150
151const setIntersectionObserver = () => {
152  // Intersection Observerの設定
153  let observer = new IntersectionObserver(entries => {
154    entries.forEach(entry => {
155      if (entry.isIntersecting) {
156        // 画面内に入った要素に対して"active"クラスを付与
157        $(entry.target).addClass("js-intersection-active");
158        observer.unobserve(entry.target);
159      }
160    });
161  });
162
163  // 監視対象の要素を指定
164  $(".js-intersection-target-fadein, .js-intersection-target-img-fadein").each(
165    function () {
166      observer.observe(this);
167    }
168  );
169};
170
171const setMenuButton = () => {
172  $(".js-menu-toggle-button").on("click", function () {
173    $(".js-menu").toggleClass("open");
174  });
175};
176
177const setUpLuxy = () => {
178  var Touch = "ontouchstart" in window || navigator.msMaxTouchPoints;
179  if (typeof Touch === "undefined") {
180    // Init Luxy.js
181    luxy.init({
182      wrapper: "#luxy",
183      wrapperSpeed: 0.065,
184    });
185  }
186};
187
188const setToggleComment = () => {
189  document.querySelectorAll(".js-comment-toggle-button").forEach(button => {
190    button.addEventListener("click", function () {
191      // ボタンのデータ属性からIDを取得
192      const id = this.getAttribute("data-id");
193      // 対応するテキスト要素を取得
194      const text = document.querySelector(
195        `.js-comment-toggle-text[data-id="${id}"]`
196      );
197      if (text.classList.contains("js-comment-toggle-expanded")) {
198        text.classList.remove("js-comment-toggle-expanded");
199        this.textContent = this.getAttribute("data-open");
200        // 1秒後にwebkit-boxを追加
201        setTimeout(() => {
202          text.classList.add("webkit-box");
203        }, 500);
204      } else {
205        text.classList.remove("webkit-box");
206        text.classList.add("js-comment-toggle-expanded");
207        this.textContent = this.getAttribute("data-close");
208      }
209    });
210    button.addEventListener("touchstart", function () {
211      this.classList.add("active");
212    });
213    button.addEventListener("touchend", function () {
214      this.classList.remove("active");
215    });
216  });
217};
218
219const setToggleChampion = () => {
220  document.querySelectorAll(".js-champion-card").forEach(card => {
221    card.addEventListener("click", function () {
222      const currentId = this.getAttribute("data-id");
223
224      // すべてのカードとプロフィールを取得
225      const cards = $(".js-champion-card");
226
227      // クリックされたカード以外のカードを閉じる
228      cards.each(function () {
229        const front = $(this).find(".front");
230        const back = $(this).find(".back");
231        if (
232          $(this).data("id") == currentId &&
233          !$(this).hasClass("js-champion-expanded")
234        ) {
235          // クリックされたカードの処理
236          $(this).addClass("js-champion-expanded");
237          front.addClass("fade-out");
238          front.removeClass("fade-in");
239          setTimeout(() => {
240            front.css("display", "none");
241            back.css("display", "block");
242            back.addClass("fade-in");
243            back.removeClass("fade-out");
244          }, 300);
245        } else if ($(this).hasClass("js-champion-expanded")) {
246          // 展開されているカードの処理
247          $(this).removeClass("js-champion-expanded");
248          back.addClass("fade-out");
249          back.removeClass("fade-in");
250          setTimeout(() => {
251            front.css("display", "block");
252            back.css("display", "none");
253            front.addClass("fade-in");
254            front.removeClass("fade-out");
255          }, 300);
256        }
257      });
258    });
259  });
260};
261
262const setScrollAnimation = () => {
263  const elements = document.querySelectorAll(".js-scroll-animation");
264  const checkScroll = () => {
265    elements.forEach(el => {
266      const rect = el.getBoundingClientRect();
267      const isVisible = rect.top < window.innerHeight && rect.bottom > 0;
268      if (isVisible) {
269        let time = Math.floor(Math.random() * 700);
270        setTimeout(() => {
271          el.classList.add("active");
272        }, time);
273      }
274    });
275  };
276
277  checkScroll();
278
279  window.addEventListener("scroll", checkScroll);
280};
281
282// 全体で利用している
283const scrollToSection = sectionId => {
284  const section = document.getElementById(sectionId);
285  const hamburger = document.querySelector(".hamburger");
286  if (section) {
287    const headerHeight = document.getElementById("header").offsetHeight;
288    const sectionPosition =
289      section.getBoundingClientRect().top + window.pageYOffset - headerHeight;
290    window.scrollTo({
291      top: sectionPosition,
292      behavior: "smooth",
293    });
294  }
295  if (hamburger && hamburger.classList.contains("hamburger-open")) {
296    hamburger.classList.toggle("hamburger-open");
297  }
298};
299
300const setModal = () => {
301  const modalButton = $(".js-modal-button");
302  const modalClose = $(".js-modal-close");
303  if (!modalButton || !modalClose) {
304    return;
305  }
306  modalButton.on("click", function () {
307    // get target modal from button
308    const target = $(this).data("target");
309    const targetModal = $(`#${target}`);
310    targetModal.addClass("is-active");
311  });
312  modalClose.on("click", function () {
313    const targetModal = $(this).closest(".js-modal");
314    targetModal.removeClass("is-active");
315  });
316};
317
318const handleScrollBar = () => {
319  const main = document.querySelector("main");
320  const scrollbar = document.querySelector("#custom-scrollbar img");
321  const header = document.getElementById("header");
322
323  const updateScrollbar = () => {
324    const headerHeight = header.offsetHeight;
325    const scrollPercentage =
326      window.scrollY / (main.scrollHeight - window.innerHeight);
327    let scrollbarPosition =
328      scrollPercentage * (window.innerHeight - scrollbar.offsetHeight);
329
330    scrollbarPosition = Math.max(scrollbarPosition, headerHeight);
331    scrollbarPosition = Math.min(
332      scrollbarPosition,
333      window.innerHeight - (scrollbar.offsetHeight + 10)
334    ); // ウィンドウの下端を超えないようにする
335
336    scrollbar.style.top = `${scrollbarPosition}px`;
337  };
338
339  window.addEventListener("scroll", updateScrollbar);
340  window.addEventListener("resize", updateScrollbar);
341
342  updateScrollbar(); // 初期位置の設定
343};
344
345const dragScrollbar = () => {
346  const main = document.querySelector("main");
347  const scrollbar = document.querySelector("#custom-scrollbar img");
348  const header = document.getElementById("header");
349
350  let isDragging = false;
351  let startY;
352  let initialTop;
353
354  const onDragStart = e => {
355    isDragging = true;
356    startY = e.clientY || e.touches[0].clientY;
357    initialTop = parseInt(scrollbar.style.top, 10) || 0;
358
359    e.preventDefault();
360  };
361
362  const onDragMove = e => {
363    if (!isDragging) return;
364    const headerHeight = header.offsetHeight;
365    const currentY = e.clientY || e.touches[0].clientY;
366    const deltaY = currentY - startY;
367
368    let newTop = initialTop + deltaY;
369    newTop = Math.max(newTop, headerHeight);
370    newTop = Math.min(
371      newTop,
372      window.innerHeight - (scrollbar.offsetHeight + 10)
373    );
374    scrollbar.style.top = `${newTop}px`;
375
376    const scrollHeightDiff = main.scrollHeight - window.innerHeight;
377    const scrollPercentage =
378      newTop / (window.innerHeight - scrollbar.offsetHeight);
379    const newScrollPosition = scrollPercentage * scrollHeightDiff;
380
381    window.scrollTo(0, newScrollPosition);
382  };
383  const onDragEnd = () => {
384    isDragging = false;
385  };
386
387  scrollbar.addEventListener("mousedown", onDragStart);
388  scrollbar.addEventListener("touchstart", onDragStart);
389  window.addEventListener("mousemove", onDragMove);
390  window.addEventListener("touchmove", onDragMove);
391  window.addEventListener("mouseup", onDragEnd);
392  window.addEventListener("touchend", onDragEnd);
393};
394
395const setHamburger = () => {
396  const hamburgerButton = document.querySelector(".hamburgerButton");
397  const hamburger = document.querySelector(".hamburger");
398
399  hamburgerButton.addEventListener("click", () => {
400    hamburger.classList.toggle("hamburger-open");
401  });
402};
403
404const setPlayersModal = () => {
405  const tabs = document.querySelectorAll(".js-players-tab");
406  tabs.forEach(tab => {
407    tab.addEventListener("click", () => {
408      // tab activeクラス削除
409      tabs.forEach(tab => {
410        tab.classList.remove("is-active");
411      });
412      // tab activeクラス追加
413      tab.classList.add("is-active");
414
415      // content activeクラス削除
416      const contents = document.querySelectorAll(".js-players-content");
417      contents.forEach(content => {
418        content.classList.remove("is-active");
419      });
420      // content activeクラス追加
421      const targetContent = document.getElementById(
422        tab.getAttribute("data-tab")
423      );
424      targetContent.classList.add("is-active");
425    });
426  });
427};

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.