PageSourceSearch

https://www.wonsec.com/js/app.js?v=20260923-live-chat-tab-fix-v16

js wonsec.com collected 2026-10-08 05:58:07 UTC 9,848 bytes, 273 lines download raw bytes

1import { detectUserRegion, initCookieConsent, readCachedUserRegion } from "./cookie-consent.js";
2import {
3  bindGlobalNavigation,
4  bindSiteNavScrollHide,
5  ensureSiteFooter,
6  getCurrentPageId,
7  parseQuery,
8  runPageEntrypoint,
9} from "./router.js?v=20260914-nav-compliance-v4";
10import { ensureSiteFloatHotlineBar } from "./site-float-hotline-bar.js";
11import { ensureSitePageHero, applySiteDocumentTitle } from "./site-page-hero.js?v=20260904-form-submit-fix";
12import { ensureSiteBottomCta } from "./site-bottom-cta.js?v=20260904-form-submit-fix";
13import { bindLiveChatTriggers, initLiveChat } from "./live-chat.js?v=20260923-live-chat-tab-fix-v16";
14import { ASSET_VERSION } from "./asset-version.js?v=20260924-cra-tool-static-v32";
15import {
16  mobileLayoutMediaQuery,
17  isTabletViewport,
18} from "./mobile-layout-constants.js?v=20260904-form-submit-fix";
19import { applyCmsPageSeo } from "./site-seo.js";
20
21function pageModule(path, exportName) {
22  return () => import(`${path}?v=${ASSET_VERSION}`).then((m) => m[exportName]);
23}
24
25/** 按 pageId 动态加载,避免每次导航都拉全站页面模块 */
26const PAGE_LOADERS = {
27  home: pageModule("./pages/home.js", "initHomePage"),
28  condox: pageModule("./pages/condox.js", "initCondoxPage"),
29  "product-detail": pageModule("./pages/product-detail.js", "initProductDetailPage"),
30  "compliance-detail": pageModule("./pages/product-detail.js", "initProductDetailPage"),
31  solutions: pageModule("./pages/solutions.js", "initSolutionsPage"),
32  "industry-solution": pageModule("./pages/industry-solution.js", "initIndustrySolutionPage"),
33  news: pageModule("./pages/news.js", "initNewsPage"),
34  "news-detail": pageModule("./pages/news-detail.js", "initNewsDetailPage"),
35  downloads: pageModule("./pages/downloads.js", "initDownloadsPage"),
36  about: pageModule("./pages/about.js", "initAboutPage"),
37  "about-job": pageModule("./pages/about-job.js", "initAboutJobPage"),
38  "cookie-policy": pageModule("./pages/cookie-policy.js", "initCookiePolicyPage"),
39  cases: pageModule("./pages/cases.js", "initCasesPage"),
40};
41
42/** 仅允许 query / 预置全局覆盖;默认解析见 api/cms-client.js getCmsBaseUrl */
43function configureCmsBaseUrl(query) {
44  const queryBase = query.raw.get("cmsBaseUrl");
45  if (queryBase) {
46    try {
47      const url = new URL(queryBase);
48      const host = url.hostname.toLowerCase();
49      const pageHost = window.location.hostname.toLowerCase();
50      const ok =
51        host === "localhost" ||
52        host === "127.0.0.1" ||
53        host === pageHost;
54      if (ok) {
55        window.__CMS_BASE_URL__ = queryBase.replace(/\/+$/, "");
56      }
57    } catch {
58      // ignore invalid cmsBaseUrl
59    }
60  }
61}
62
63function resolveLanguage(region, queryLanguage) {
64  const forced = document.body?.dataset?.forceLanguage;
65  if (forced === "zh" || forced === "en") return forced;
66  if (queryLanguage === "zh" || queryLanguage === "en") {
67    try { sessionStorage.setItem("wonsec_lang", queryLanguage); } catch {}
68    return queryLanguage;
69  }
70  return "zh";
71}
72
73function forceMobileLayoutFromQuery() {
74  try {
75    return new URLSearchParams(window.location.search).get("mobileLayout") === "1";
76  } catch {
77    return false;
78  }
79}
80
81function ensureMobileSiteStyles() {
82  if (!isMobileLayout()) return;
83  if (document.querySelector("link[data-mobile-site-css]")) return;
84  const link = document.createElement("link");
85  link.rel = "stylesheet";
86  link.dataset.mobileSiteCss = "";
87  link.href = new URL(`../styles/mobile-site.css?v=${ASSET_VERSION}`, import.meta.url).href;
88  document.head.appendChild(link);
89}
90
91function initMobileLayout() {
92  const mq = window.matchMedia(mobileLayoutMediaQuery());
93  const sync = () => {
94    const mobile = forceMobileLayoutFromQuery() || mq.matches;
95    const tablet = mobile && isTabletViewport();
96    document.documentElement.classList.toggle("layout-mobile", mobile);
97    document.documentElement.classList.toggle("layout-desktop", !mobile);
98    document.documentElement.classList.toggle("layout-tablet", tablet);
99  };
100  sync();
101  if (typeof mq.addEventListener === "function") {
102    mq.addEventListener("change", sync);
103    window.matchMedia("(min-width: 769px)").addEventListener("change", sync);
104  } else if (typeof mq.addListener === "function") {
105    mq.addListener(sync);
106    window.matchMedia("(min-width: 769px)").addListener(sync);
107  }
108  return mq;
109}
110
111function isMobileLayout() {
112  return forceMobileLayoutFromQuery() || document.documentElement.classList.contains("layout-mobile");
113}
114
115/** 产品汇总页已下线:直链与旧书签统一进首页(保留 query/hash) */
116function redirectIfProductsHubHidden() {
117  const { pathname } = window.location;
118  if (!pathname.endsWith("/pages/products/index.html")) return false;
119  const next = new URL("/pages/index.html", window.location.origin);
120  next.search = window.location.search;
121  next.hash = window.location.hash;
122  window.location.replace(next.href);
123  return true;
124}
125
126function hasExplicitLanguage(query) {
127  const forced = document.body?.dataset?.forceLanguage;
128  if (forced === "zh" || forced === "en") return true;
129  return query.language === "zh" || query.language === "en";
130}
131
132/**
133 * 有语言提示或本地缓存时不阻塞首屏;否则短超时兜底,避免 ipapi 拖慢整站。
134 */
135async function resolveRegionForBootstrap(query) {
136  const cached = readCachedUserRegion();
137  if (cached) return cached;
138  if (hasExplicitLanguage(query)) {
139    return {
140      countryCode: "",
141      isOverseas: query.language === "en" || document.body?.dataset?.forceLanguage === "en",
142    };
143  }
144
145  const fallback = { countryCode: "", isOverseas: false };
146  try {
147    return await Promise.race([
148      detectUserRegion(),
149      new Promise((resolve) => {
150        window.setTimeout(() => resolve(fallback), 450);
151      }),
152    ]);
153  } catch {
154    return fallback;
155  }
156}
157
158async function loadPageEntrypoints() {
159  const pageId = getCurrentPageId();
160  const loader = PAGE_LOADERS[pageId];
161  if (!loader) return {};
162  const init = await loader();
163  return { [pageId]: init };
164}
165
166function softImport(path, thenFn) {
167  return import(`${path}?v=${ASSET_VERSION}`)
168    .then(thenFn)
169    .catch((err) => {
170      console.warn(`[app] failed to load ${path}`, err);
171    });
172}
173
174async function bootstrap() {
175  if (redirectIfProductsHubHidden()) return;
176  initMobileLayout();
177  ensureMobileSiteStyles();
178  const query = parseQuery();
179  configureCmsBaseUrl(query);
180
181  softImport("./cms-designer.js", (m) => m.initCmsDesigner());
182
183  const regionPromise = detectUserRegion();
184  const region = await resolveRegionForBootstrap(query);
185  const language = resolveLanguage(region, query.language);
186
187  document.documentElement.lang = language === "en" ? "en" : "zh-CN";
188  if (document.body) document.body.dataset.uiLanguage = language;
189  bindGlobalNavigation(language);
190  bindLiveChatTriggers(language, region);
191  initLiveChat({ language, region });
192
193  const pageEntrypointsPromise = loadPageEntrypoints();
194  await ensureSitePageHero(language);
195  ensureSiteFooter(language);
196
197  if (document.body?.dataset?.pageId === "compliance-detail") {
198    softImport("./home-cta-banner.js", (m) => {
199      m.mountCraHomeCtaBanner(language === "en" ? "en" : "zh");
200      m.bindComplianceDetailInternalLinks();
201    });
202  } else if (/\/one-stop-compliance\.html$/i.test(window.location.pathname)) {
203    softImport("./home-cta-banner.js", (m) => {
204      const uiLang = language === "en" ? "en" : "zh";
205      m.bindComplianceDetailInternalLinks();
206      m.refreshOneStopDetailLinks(document, uiLang);
207    });
208  }
209  softImport("./home-cta-banner.js", (m) =>
210    m.mountOneStopHomeCtaBanner(language === "en" ? "en" : "zh"),
211  );
212
213  softImport("./meeting-booking-modal.js", (m) =>
214    m.ensureMeetingBookingGlobalBind(language),
215  );
216
217  if (!isMobileLayout()) {
218    softImport("./site-float-actions.js", (m) => m.ensureSiteFloatActions(language));
219  } else {
220    document.querySelectorAll(".site-float, [data-site-float]").forEach((el) => el.remove());
221  }
222  ensureSiteFloatHotlineBar(language);
223  bindSiteNavScrollHide();
224
225  const pageEntrypoints = await pageEntrypointsPromise;
226  await runPageEntrypoint(pageEntrypoints, {
227    queryOverrides: { language },
228  });
229  softImport("./meeting-booking-modal.js", (m) =>
230    m.ensureMeetingBookingGlobalBind(language),
231  );
232  applySiteDocumentTitle(language);
233  // Chinese pages only: CMS SEO overrides hardcoded title + injects description/keywords
234  await applyCmsPageSeo(language);
235  ensureSiteBottomCta(language);
236
237  if (document.body?.dataset?.pageId === "compliance-detail") {
238    softImport("./home-cta-banner.js", (m) => {
239      const uiLang = language === "en" ? "en" : "zh";
240      m.mountCraHomeCtaBanner(uiLang);
241      m.bindComplianceDetailInternalLinks();
242      m.refreshComplianceDetailLinks(document, uiLang);
243    });
244  } else if (/\/one-stop-compliance\.html$/i.test(window.location.pathname)) {
245    softImport("./home-cta-banner.js", (m) => {
246      const uiLang = language === "en" ? "en" : "zh";
247      m.bindComplianceDetailInternalLinks();
248      m.refreshOneStopDetailLinks(document, uiLang);
249    });
250  }
251
252  const freshRegion = await regionPromise.catch(() => region);
253  bindLiveChatTriggers(language, freshRegion);
254  initLiveChat({ language, region: freshRegion });
255  const consentResult = await initCookieConsent(freshRegion);
256  const canTrack =
257    consentResult?.consent?.requiredOnly === true ||
258    consentResult?.consent?.granted === true;
259  if (canTrack) {
260    softImport("./analytics-tracker.js", (m) =>
261      m.initPageAnalyticsTracking({
262        language,
263        sourceRegion: freshRegion?.isOverseas ? "overseas" : "domestic",
264        countryCode: freshRegion?.countryCode || "",
265      }),
266    );
267    softImport("./baidu-analytics.js", (m) => m.initBaiduAnalytics());
268  }
269}
270
271bootstrap().catch((err) => {
272  console.error("[app] bootstrap failed", err);
273});

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.