PageSourceSearch

https://www.cnplayguide.com/resources/js/page-top.js

js cnplayguide.com collected 2026-09-24 17:47:56 UTC 11,413 bytes, 400 lines download raw bytes

1
2
3// ========================================
4// = = TOPページ初期化
5// ========================================
6document.addEventListener("DOMContentLoaded", async () => {
7  try {
8    // -------------------------
9    // データ取得
10    // -------------------------
11    const [
12      featuredBanners,
13      featuredTickets,
14      presaleTickets,
15      weeklyTickets,
16      news,
17      banner,
18      featuredEvents,
19    ] = (await Promise.all([
20      fetchData(API_ENDPOINTS.featuredBanners, "xml"),
21      fetchData(API_ENDPOINTS.featuredTickets),
22      fetchData(API_ENDPOINTS.presaleTickets),
23      fetchData(API_ENDPOINTS.weeklyTickets),
24      fetchData(API_ENDPOINTS.news),
25      fetchData(API_ENDPOINTS.banner),
26      fetchData(API_ENDPOINTS.featuredEvents),
27    ])).map(normalizeLineBreaks);
28
29    // -------------------------
30    // 描画
31    // -------------------------
32    renderFeaturedBanners(featuredBanners);
33    renderFeaturedTickets(featuredTickets);
34    renderPresaleTickets(presaleTickets);
35    renderWeeklyTickets(weeklyTickets);
36    renderBanner(banner);
37    renderLatestNews(news);
38    renderNewsList(news);
39    renderFeaturedEvents(featuredEvents);
40
41    // -------------------------
42    // UI初期化
43    // -------------------------
44    initializeSearch();
45    initHamburgerMenu();
46    initNewsToggle();
47    initFooterAccordion();
48    initSlider();
49    initBannerClose();
50  } catch (error) {
51    console.error(error); // ← 追加
52  }
53});
54
55// * TOP専用 ****************************************
56// ========================================
57// = = レンダリング関連
58// ========================================
59function createSlideElement(template, item, config) {
60  const clone = template.content.cloneNode(true);
61
62  if (config.setLink) {
63    const linkElement = clone.querySelector(config.linkSelector || ".slide");
64    if (linkElement) linkElement.href = item.url;
65  }
66
67  const image = clone.querySelector(".slide__image img");
68  if (image) {
69    setImage(image, item.image, stripBr(item.title), config.fallbackImage);
70  }
71
72  const genre = clone.querySelector(".slide__genre");
73  if (genre) {
74    setGenre(genre, item.category);
75  }
76
77  const title = clone.querySelector(".slide__title");
78  if (title) title.innerHTML = item.title;
79
80  const date = clone.querySelector(".slide__date");
81  if (date) {
82    setDateText(date, item.date);
83  }
84
85  const description = clone.querySelector(".slide__description");
86  if (description) {
87    const span = description.querySelector("span");
88    if (span) {
89      span.innerHTML = item.detail;
90    } else {
91      description.innerHTML = item.detail;
92    }
93  }
94
95  const location = clone.querySelector(".slide__location");
96  if (location) {
97    if (item.location) {
98      const span = location.querySelector("span");
99      if (span) {
100        span.innerHTML = item.location;
101      } else {
102        location.innerHTML = item.location;
103      }
104    } else {
105      location.remove();
106    }
107  }
108
109  if (config.customSetup) {
110    config.customSetup(clone, item);
111  }
112
113  return clone;
114}
115
116function renderFeaturedBanners(items) {
117  const container = document.querySelector("#featuredBanners");
118  const template = document.querySelector("#featuredBannerTemplate");
119
120  if (!container || !template || !Array.isArray(items) || items.length === 0) {
121    if (container) container.style.display = "none";
122    return;
123  }
124
125  const fragment = document.createDocumentFragment();
126
127  items.forEach((item) => {
128    const config = {
129      setLink: false,
130      fallbackImage: IMAGE_CONFIG.NO_IMAGE_BLACK,
131      customSetup: (clone) => {
132        const buttons = clone.querySelectorAll(".slide");
133        buttons.forEach((button) => {
134          button.href = item.url;
135        });
136      },
137    };
138
139    const clone = createSlideElement(template, item, config);
140    fragment.appendChild(clone);
141  });
142
143  container.appendChild(fragment);
144}
145
146function renderFeaturedTickets(items) {
147  const section = document.querySelector("section:has(#featuredTickets)");
148  const container = document.querySelector("#featuredTickets");
149  const template = document.querySelector("#featuredTicketsTemplate");
150
151  if (!container || !template || !Array.isArray(items) || items.length === 0) {
152    section.style.display = "none";
153    return;
154  }
155
156  const fragment = document.createDocumentFragment();
157
158  items.forEach((item) => {
159    const config = {
160      setLink: true,
161      fallbackImage: IMAGE_CONFIG.NO_IMAGE_BLACK,
162      customSetup: (clone) => {
163        const buttons = clone.querySelectorAll(".slide__button");
164        buttons.forEach((button) => {
165          button.innerHTML = item.status;
166        });
167      },
168    };
169
170    const clone = createSlideElement(template, item, config);
171    fragment.appendChild(clone);
172  });
173
174  container.appendChild(fragment);
175}
176
177function renderPresaleTickets(items) {
178  renderTicketSlides(
179    items,
180    "#presaleTickets",
181    "#presaleTicketsTemplate",
182    IMAGE_CONFIG.NO_IMAGE_WHITE,
183  );
184}
185
186function renderWeeklyTickets(items) {
187  renderTicketSlides(
188    items,
189    "#weeklyTickets",
190    "#weeklyTicketsTemplate",
191    IMAGE_CONFIG.NO_IMAGE_WHITE,
192  );
193}
194
195function renderTicketSlides(
196  items,
197  containerSelector,
198  templateSelector,
199  fallbackImage,
200) {
201  const section = document.querySelector(
202    "section:has(" + containerSelector + ")",
203  );
204  const container = document.querySelector(containerSelector);
205  const template = document.querySelector(templateSelector);
206
207  if (!container || !template || !Array.isArray(items) || items.length === 0) {
208    section.style.display = "none";
209    return;
210  }
211
212  const fragment = document.createDocumentFragment();
213
214  items.forEach((item) => {
215    const config = {
216      setLink: true,
217      fallbackImage,
218    };
219
220    const clone = createSlideElement(template, item, config);
221    fragment.appendChild(clone);
222  });
223
224  container.appendChild(fragment);
225}
226
227function renderLatestNews(data) {
228  const section = document.querySelector("section.news--ratest");
229  const container = document.querySelector(".news--ratest .news__date span");
230
231  if (!section || !container || !Array.isArray(data) || data.length === 0) {
232    section.style.display = "none";
233    return;
234  }
235
236  container.textContent = data[0].date;
237}
238
239function renderNewsList(data) {
240  const section = document.querySelector("#jump-news");
241  const container = document.querySelector("#newsList");
242  const template = document.querySelector("#newsTemplate");
243  const toggleButton = document.querySelector(".news__toggle-button");
244  const newsContents = document.querySelector(".news__contents");
245
246  if (
247    !section ||
248    !container ||
249    !template ||
250    !Array.isArray(data) ||
251    data.length === 0
252  ) {
253    if (section) section.style.display = "none";
254    return;
255  }
256
257  const existingItems = container.querySelectorAll(".news__item");
258  existingItems.forEach((item) => item.remove());
259
260  const fragment = document.createDocumentFragment();
261
262  data.forEach((datum) => {
263    const clone = template.content.cloneNode(true);
264    const newsItem = clone.querySelector(".news__item");
265    const labelElement = clone.querySelector(".news__label");
266    const titleElement = clone.querySelector(".news__title");
267    const dateElement = clone.querySelector(".news__date");
268
269    if (newsItem) newsItem.href = datum.url || "";
270    if (labelElement) labelElement.textContent = datum.label || "";
271    if (titleElement) titleElement.textContent = datum.title || "";
272    if (dateElement) dateElement.textContent = datum.date || "";
273
274    fragment.appendChild(clone);
275  });
276
277  container.appendChild(fragment);
278
279  // 初期の高さを設定
280  function setInitialHeight() {
281    if (!newsContents) return;
282    const isWide = window.innerWidth >= 768;
283    const visibleCount = isWide ? 3 : 2;
284    const items = container.querySelectorAll(".news__item");
285    let totalHeight = 0;
286
287    items.forEach((item, index) => {
288      if (index < visibleCount) {
289        totalHeight += item.getBoundingClientRect().height;
290      }
291    });
292
293    newsContents.style.height = `${totalHeight + 1}px`;
294  }
295
296  setInitialHeight();
297
298  // ボタン表示判定
299  function updateToggleButtonVisibility() {
300    if (!toggleButton) return;
301    const isWide = window.innerWidth >= 768;
302    const threshold = isWide ? 4 : 3;
303    toggleButton.style.display = data.length >= threshold ? "" : "none";
304  }
305
306  updateToggleButtonVisibility();
307
308  // リサイズ時に再判定(重複登録を防ぐ)
309  if (!renderNewsList._resizeListenerAdded) {
310    window.addEventListener("resize", () => {
311      setInitialHeight();
312      updateToggleButtonVisibility();
313    });
314    renderNewsList._resizeListenerAdded = true;
315  }
316}
317
318function toggleNews() {
319  const container = document.querySelector("#newsList");
320  const button = document.querySelector(".news__toggle-button");
321  const buttonText = button.querySelector(".news__button-text");
322
323  const isOpen = container.classList.toggle("is-open");
324  buttonText.textContent = isOpen
325    ? button.dataset.textClose
326    : button.dataset.textOpen;
327}
328
329function renderBanner(bannerData) {
330  const container = document.querySelector("#floatingBanner");
331
332  if (!container) {
333    console.warn("バナーコンテナが見つかりません");
334    return;
335  }
336  if (!bannerData || !bannerData.image || !bannerData.url) {
337    return;
338  }
339  // バナーコンテナを表示
340  container.style.display = "block";
341
342  // リンクを設定
343  const link = container.querySelector("a");
344  if (link && bannerData.url) {
345    link.href = bannerData.url;
346  }
347
348  // 画像を設定
349  const image = container.querySelector("img");
350  if (image && bannerData.image) {
351    setImage(image, bannerData.image, bannerData.title || "");
352  }
353}
354
355function renderFeaturedEvents(items) {
356  const section = document.querySelector("section:has(#featuredEvents)");
357  const container = document.querySelector("#featuredEvents");
358  const template = document.querySelector("#featuredEventsTemplate");
359
360  if (!container || !template || !Array.isArray(items) || items.length === 0) {
361    if (section) section.style.display = "none";
362    return;
363  }
364
365  const fragment = document.createDocumentFragment();
366
367  items.forEach((item) => {
368    const clone = template.content.cloneNode(true);
369
370    const link = clone.querySelector(".banner");
371    if (link) link.href = item.url || ""; // ✅
372
373    const image = clone.querySelector(".banner__img");
374    if (image) {
375      image.src = item.img || ""; // ✅
376      image.alt = item.alt || "";
377    }
378
379    fragment.appendChild(clone);
380  });
381
382  container.appendChild(fragment);
383}
384
385function initBannerClose() {
386  const bannerContainer = document.querySelector("#floatingBanner");
387  const closeButton = bannerContainer?.querySelector(".banner__close");
388
389  // クローズボタンのクリックイベント
390  if (closeButton) {
391    closeButton.addEventListener("click", closeBanner);
392  }
393}
394
395function closeBanner() {
396  const bannerContainer = document.querySelector("#floatingBanner");
397  if (bannerContainer) {
398    bannerContainer.style.display = "none";
399  }
400}

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.