PageSourceSearch

https://www.gsscloud.com/templates/vital2022/js/global.js?b63ae3952263319d4e7755155824cb94

js gsscloud.com collected 2026-09-30 22:00:11 UTC 11,320 bytes, 305 lines download raw bytes

1document.addEventListener('DOMContentLoaded', () => {
2  // Nav burger active function
3  const targetBurger = document.querySelector('.burger');
4  const targetRwdNavList = document.querySelector('.nav');
5  const targetNavListPanel = document.querySelector('.nav__list');
6
7  // 讀 _rwd.scss 輸出的 --bp-laptop-m,跟 nav-product-dropdown.js 共用同一個斷點來源
8  const bpLaptopM =
9    getComputedStyle(document.documentElement).getPropertyValue('--bp-laptop-m').trim() || '1024px';
10  const mqMobile = window.matchMedia(`(max-width: ${bpLaptopM})`);
11
12  // inert 跟「mobile 斷點內 + 目前是否 panel-open」同步,不只在 click 那一刻切換——
13  // 否則頁面剛載入時 .nav__list 視覺上已收合但 inert 從沒被設過,Tab 還是能走進去
14  // (拿掉 CSS visibility 後不會再自動排除在 tab order 外,見 _nav.scss 的說明)。
15  const syncNavListInert = () => {
16    targetNavListPanel?.toggleAttribute(
17      'inert',
18      mqMobile.matches && !targetRwdNavList.classList.contains('panel-open'),
19    );
20  };
21  syncNavListInert();
22  mqMobile.addEventListener('change', (e) => {
23    // Resize 回 desktop 時一併清掉 panel-open:inert 是真的 DOM 屬性,不會被
24    // media query 排除,留著 class 沒意義但順手清掉
25    if (!e.matches) targetRwdNavList.classList.remove('panel-open');
26    syncNavListInert();
27  });
28
29  // 統一關閉所有 push-view host(含 .nav__login),順手清掉 drawer 的 inert,
30  // 不然中途被 burger 關掉時會漏清
31  const closeOtherPushViewPanels = () => {
32    document.querySelectorAll('.push-view-host.panel-open').forEach((el) => {
33      el.classList.remove('panel-open');
34      el.querySelector(':scope > .nav__login__drawer')?.setAttribute('inert', '');
35    });
36  };
37  targetBurger.addEventListener('click', () => {
38    const isOpening = !targetRwdNavList.classList.contains('panel-open');
39    if (isOpening) {
40      // 跟 .nav__login(立即登入/會員選單)手機版互斥:開 burger drawer 前先關掉它
41      closeOtherPushViewPanels();
42    }
43    targetRwdNavList.classList.toggle('panel-open');
44    syncNavListInert();
45    // body scroll lock 由 CSS :has() 處理(見 _nav.scss),這裡不用手動加減 class
46    if (!isOpening) {
47      // 關閉漢堡選單時一併清掉 push-view panel 狀態,避免下次打開時停在上次的 L2 panel
48      closeOtherPushViewPanels();
49    }
50  });
51
52  // Footer respond web design function
53  const targetFooterMenuDeeper = document.getElementsByClassName('menuitem_footer-dropdown');
54  const targetFooterHeader = document.getElementsByClassName('footer-dropdown');
55  const targetFooterChild = document.querySelectorAll('.footer__list .nav-child');
56  function addFooterDropdownCollapseListener() {
57    Object.keys(targetFooterMenuDeeper).forEach((key) => {
58      const header = targetFooterHeader[key];
59      const child = targetFooterChild[key];
60
61      header.addEventListener('click', () => {
62        if (document.body.clientWidth > 551) return;
63
64        const isActive = header.classList.contains('footer-dropdown_active');
65        if (isActive) {
66          header.classList.remove('footer-dropdown_active', 'rotate-anchor');
67          child.removeAttribute('style');
68        } else {
69          header.classList.add('footer-dropdown_active', 'rotate-anchor');
70          const paddingTop = 26;
71          const paddingBottom = 20;
72          child.style.padding = `${paddingTop}px 0 ${paddingBottom}px`;
73          child.style.opacity = '1';
74          const totalPadding = paddingTop + paddingBottom;
75          child.style.maxHeight = `${child.scrollHeight + totalPadding}px`;
76        }
77      });
78    });
79  }
80  addFooterDropdownCollapseListener();
81  function unsetFooterChildMaxHeight() {
82    Object.keys(targetFooterMenuDeeper).forEach((key) => {
83      targetFooterChild[key].removeAttribute('style');
84    });
85  }
86  function defaultFooterHeaderStatus() {
87    if (window.innerWidth > 551) {
88      unsetFooterChildMaxHeight();
89      return;
90    }
91    // setFooterHeaderMaxHeight();
92  }
93  defaultFooterHeaderStatus();
94
95  function resetFooterHeaderActive() {
96    Object.keys(targetFooterHeader).forEach((key) => {
97      targetFooterHeader[key].classList.remove('footer-dropdown_active', 'rotate-anchor');
98    });
99  }
100
101  window.addEventListener('resize', () => {
102    if (window.innerWidth > 551) {
103      resetFooterHeaderActive();
104      unsetFooterChildMaxHeight();
105    }
106  });
107
108  // Toggle Grid or List
109  // jQuery('.showcase__content__masonary__check').on('click', function () {
110  //   const showcaseIsGrid = jQuery('.showcase__content__masonary__check').is(':checked');
111  //   const showcaseCategory = jQuery('.showcase__content__category');
112  //   if (showcaseIsGrid) showcaseCategory.addClass('isGrid');
113  //   if (!showcaseIsGrid) showcaseCategory.removeClass('isGrid');
114  // });
115  // Showcase dropdown
116  // jQuery('.showcase__nav.mobile').on('click', function (e) {
117  //   e.stopPropagation();
118  //   const showcaseDropdown = jQuery('.showcase__nav .dropdown');
119  //   const isHide = showcaseDropdown.hasClass('hide');
120  //   if (isHide) showcaseDropdown.removeClass('hide');
121  //   if (!isHide) showcaseDropdown.addClass('hide');
122  // });
123  // jQuery(document).on('click', function () {
124  //   const showcaseDropdown = jQuery('.showcase__nav .dropdown');
125  //   const isHide = showcaseDropdown.hasClass('hide');
126  //   if (!isHide) showcaseDropdown.addClass('hide');
127  // });
128
129  // 成功案例 storiesItem - One Minute Quick Look Icon
130  const quicklookIcons = {
131    zh: ['fa-light fa-clock', 'fa-light fa-chart-mixed'],
132    en: ['fa-regular fa-book', 'fa-regular fa-burst', 'fa-regular fa-face-smile'],
133    // ja: ['fa-regular fa-star', ...],
134  };
135
136  const htmlLang = document.documentElement.lang || 'zh';
137  const langKey = htmlLang.split('-')[0];
138  const icons = quicklookIcons[langKey] || quicklookIcons['zh'];
139
140  document.querySelectorAll('#js_oneminIcon > .quicklook-section')?.forEach((section, index) => {
141    section
142      .querySelector('.quicklook-title')
143      ?.insertAdjacentHTML('afterbegin', `<i class="${icons[index] || icons[0]}"></i>`);
144  });
145
146  // Dialog 開啟與關閉
147  const dialogWrap = document.querySelector('.dialog__wrap');
148  const dialogContainer = document.querySelectorAll('.dialog__container');
149  const dialogOpenBtn = document.querySelectorAll('.dialog__btn--open');
150  const dialogCloseBtn = document.querySelector('.dialog__btn--close');
151  if (dialogWrap) {
152    dialogOpenBtn.forEach((btn) => {
153      btn.addEventListener('click', ({ target }) => {
154        const {
155          dataset: { dialog = '' },
156        } = target;
157        dialogWrap.style.cssText = 'opacity: 1; pointer-events: auto';
158        document.querySelector(`#${dialog}`).classList.add('active');
159      });
160    });
161  }
162
163  if (dialogCloseBtn) {
164    dialogCloseBtn.addEventListener('click', () => {
165      dialogWrap.style.cssText = 'opacity: 0; pointer-events: none';
166      dialogContainer.forEach((t) => t.classList.remove('active'));
167    });
168  }
169
170  // Dialog 點擊內容以外自動關閉
171  if (dialogWrap) {
172    dialogWrap.addEventListener('click', (event) => {
173      const dialogActive = document.querySelector('.dialog__container.active');
174      const rect = dialogActive.getBoundingClientRect();
175      const isInDialog =
176        rect.top <= event.clientY &&
177        event.clientY <= rect.top + rect.height &&
178        rect.left <= event.clientX &&
179        event.clientX <= rect.left + rect.width;
180      if (!isInDialog) {
181        dialogWrap.style.cssText = 'opacity: 0; pointer-events: none';
182        dialogContainer.forEach((t) => t.classList.remove('active'));
183      }
184    });
185  }
186  // Select2 Text Search
187  const searchWrap = document.querySelector('.fc_filter_text_search');
188  const searchInput = document.querySelector('input.select2-input');
189  if (searchInput) {
190    let inputW = searchWrap.offsetWidth;
191    document.documentElement.style.setProperty('--select2-drop-width', `${inputW}px`);
192  }
193
194  // Dialog 開啟與關閉
195  const modalWrap = document.querySelectorAll('.modal__wrap');
196  const modalOpenBtn = document.querySelectorAll('.modal__btn--open');
197  const modalCloseBtn = document.querySelectorAll('.modal__btn--close');
198  modalOpenBtn.forEach((btn) => {
199    btn.addEventListener('click', ({ target }) => {
200      const {
201        dataset: { modal = '' },
202      } = target;
203      document.querySelector(`#${modal}`).showModal();
204      document.body.style.cssText = 'overflow:hidden';
205    });
206  });
207
208  const modalClose = (el) => {
209    el.setAttribute('closing', '');
210    el.addEventListener(
211      'animationend',
212      () => {
213        el.removeAttribute('closing');
214        el.close();
215      },
216      { once: true },
217    );
218    document.body.style.cssText = '';
219  };
220
221  if (modalCloseBtn) {
222    modalCloseBtn.forEach((btns) => {
223      btns.addEventListener('click', (btn, index) => {
224        // console.log(btn);
225        const modal = btn.target.closest('dialog');
226        modalClose(modal);
227      });
228    });
229  }
230
231  // Dialog 點擊內容以外自動關閉
232  if (modalWrap) {
233    modalWrap.forEach((modals) => {
234      modals.addEventListener('click', (modal, index) => {
235        const el = modal.target;
236        const modalOpen = el.hasAttribute('open');
237        const rect = el.getBoundingClientRect();
238        const isInDialog =
239          rect.top <= modal.clientY &&
240          modal.clientY <= rect.top + rect.height &&
241          rect.left <= modal.clientX &&
242          modal.clientX <= rect.left + rect.width;
243        if (!isInDialog && modalOpen) {
244          modalClose(el);
245        }
246      });
247    });
248  }
249
250  // privacy 點擊開啟
251  const dropBox = document.querySelectorAll('.dropdown__box');
252  const dropOpenBtn = document.querySelectorAll("[data-toggle='dropdown']");
253  if (dropOpenBtn) {
254    dropOpenBtn.forEach((btns) => {
255      btns.addEventListener('click', (btn) => {
256        btn.stopPropagation();
257        const dropParent = btn.target.closest('.dropdown__wrap');
258        dropParent.classList.add('open');
259      });
260    });
261  }
262  // privacy 點擊關閉
263  if (dropBox) {
264    window.addEventListener('click', (e) => {
265      dropBox.forEach((drop) => {
266        const dropParent = drop.closest('.dropdown__wrap');
267        const dropOpen = dropParent.classList.contains('open');
268        const mouseIn = drop.contains(e.target);
269        if (!mouseIn && dropOpen) {
270          dropParent.classList.remove('open');
271        }
272      });
273    });
274  }
275
276  // ad track
277  /*
278  // 範例 adtrack 結構
279  const adtrack = {
280    'btn-1': "cyntellianalytics.track('CloudBizContact');",
281    'btn-2': "cyntellianalytics.track('CloudBizDemo');"
282  };
283  */
284  const btns = document.querySelectorAll(
285    '.btn:not(nav .btn):not(footer .btn), .button:not(nav .button):not(footer .button)',
286  );
287  btns.forEach((btn, idx) => {
288    btn.setAttribute('data-track', `btn-${idx + 1}`);
289  });
290
291  if (typeof adtrack !== 'undefined' && adtrack) {
292    // 取得所有 .btn 和 .button
293    btns.forEach((btn) => {
294      const trackKey = btn.getAttribute('data-track');
295      const script = adtrack[trackKey];
296      if (script) {
297        btn.setAttribute('onclick', script);
298      }
299    });
300    // 綁定完後清除所有 data-track
301    // btns.forEach((btn) => {
302    //   btn.removeAttribute('data-track');
303    // });
304  }
305});

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.