PageSourceSearch

https://event.cts.com.tw/2026asiangames/js/script.a9b22c1.js

js cts.com.tw collected 2026-09-24 08:40:59 UTC 4,775 bytes, 140 lines download raw bytes

1// Menu
2const hamburger = document.querySelector(".hamburger");
3const nav = document.querySelector(".nav");
4const backdrop = document.querySelector(".backdrop");
5hamburger.addEventListener("click", function () {
6  hamburger.classList.toggle("active");
7  nav.classList.toggle("active");
8  backdrop.classList.toggle("active");
9});
10
11document.querySelectorAll("nav a").forEach((link) => {
12  link.addEventListener("click", function () {
13    hamburger.classList.remove("active");
14    nav.classList.remove("active");
15    backdrop.classList.remove("active");
16  });
17});
18
19// News carousel
20const newsContainer = document.querySelector(".news-container");
21const newsViewport = document.querySelector(".news-viewport");
22const newsPrevious = document.querySelector(".news-prev");
23const newsNext = document.querySelector(".news-next");
24
25function escapeHtml(value) {
26  const element = document.createElement("div");
27  element.textContent = value || "";
28  return element.innerHTML;
29}
30
31function formatDate(value) {
32  const date = new Date(value);
33  if (Number.isNaN(date.getTime())) return "";
34
35  const pad = (num) => String(num).padStart(2, "0");
36
37  return `${date.getFullYear()}.${pad(date.getMonth() + 1)}.${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
38}
39
40function articleMarkup(article, showMoreOverlay = false) {
41  const thumbnailUrl = article.thumbnailUrl;
42
43  return `
44      <article class="news-card">
45        <a href="${escapeHtml(article.url)}" target="_blank" rel="noopener noreferrer">
46          <div class="news-card-image">
47            <img src="${escapeHtml(thumbnailUrl)}" alt="${escapeHtml(article.title)}" loading="lazy" />
48          </div>
49          <div class="news-card-content">
50            <time datetime="${escapeHtml(article.datetime)}">${formatDate(article.datetime)}</time>
51            <h3>${escapeHtml(article.title)}</h3>
52            <p>${escapeHtml(article.description)}</p>
53          </div>
54        </a>
55        ${
56          showMoreOverlay
57            ? `<a class="news-more-overlay" href="https://news.cts.com.tw/topic/8567fecd-5090-4054-9e5c-337d709ef9cb" target="_blank" rel="noopener noreferrer"><span>看更多</span><span>名古屋亞運新聞</span></a>`
58            : ""
59        }
60      </article>`;
61}
62
63function adMarkup() {
64  return `
65  <article class="news-card">
66    <div id="div-gpt-ad-news-ad-0" class="news-ad" data-ad data-ad-format="square" aria-label="廣告">
67    <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7608737321945861"
68     crossorigin="anonymous"></script>
69<ins class="adsbygoogle"
70     style="display:block"
71     data-ad-format="fluid"
72     data-ad-layout-key="-79+ez-1k-3m+cp"
73     data-ad-client="ca-pub-7608737321945861"
74     data-ad-slot="9763806309"></ins>
75<script>
76     (adsbygoogle = window.adsbygoogle || []).push({});
77</script>
78    </div>
79    <div class="ad-note">廣告/ADVERTISING</div>
80  </article>`;
81}
82
83async function loadNews() {
84  try {
85    const response = await fetch(
86      `json/news-articles.json?refresh=${Date.now()}`,
87      {
88        cache: "no-store",
89      },
90    );
91    if (!response.ok)
92      throw new Error(`News request failed: ${response.status}`);
93
94    const payload = await response.json();
95    const articles = Array.isArray(payload) ? payload : payload.data;
96    // console.log(articles);
97    if (!Array.isArray(articles)) throw new Error("News data is not an array");
98    const latestArticles = articles
99      .filter((article) => article && article.title && article.url)
100      .sort(
101        (first, second) => new Date(second.datetime) - new Date(first.datetime),
102      )
103      .slice(0, 7);
104
105    newsContainer.innerHTML = latestArticles
106      .slice(0, 6)
107      .map((article) => articleMarkup(article))
108      .join("");
109    newsContainer.insertAdjacentHTML("beforeend", adMarkup());
110    newsContainer.insertAdjacentHTML(
111      "beforeend",
112      latestArticles[6] ? articleMarkup(latestArticles[6], true) : "",
113    );
114
115    // initializeAds(newsContainer);
116
117    const embla = EmblaCarousel(newsViewport, {
118      align: "start",
119      containScroll: "trimSnaps",
120      loop: latestArticles.length > 8,
121    });
122    newsPrevious.addEventListener("click", () => embla.scrollPrev());
123    newsNext.addEventListener("click", () => embla.scrollNext());
124    const updateControls = () => {
125      newsPrevious.disabled = !embla.canScrollPrev();
126      newsNext.disabled = !embla.canScrollNext();
127    };
128    embla.on("select", updateControls);
129    embla.on("reInit", updateControls);
130    updateControls();
131  } catch (error) {
132    newsContainer.innerHTML =
133      '<p class="news-state">新聞暫時無法載入,請稍後再試。</p>';
134    console.error(error);
135  }
136}
137
138loadNews();
139
140// initializeAds();

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.