PageSourceSearch

https://www.frenzygo.com/js/fg-page-loader.js?v=703a3f3e01d8f72a69579e35f12f740511d24a05

js frenzygo.com collected 2026-10-02 00:49:31 UTC 9,324 bytes, 353 lines download raw bytes

1/**
2 * FrenzyGo — page navigation loader (progress bar + branded ring overlay).
3 * Uses sessionStorage so the loader survives full page navigations (mobile + desktop).
4 */
5(function (global) {
6  'use strict';
7
8  var NAV_KEY = 'fg-page-nav';
9  var NAV_MAX_AGE_MS = 45000;
10  var OVERLAY_DELAY_MS = 120;
11  var MOBILE_OVERLAY_DELAY_MS = 0;
12  var MIN_VISIBLE_MS = 220;
13
14  var state = {
15    active: false,
16    overlayTimer: null,
17    startedAt: 0,
18    root: null,
19    bound: false,
20    lastNavAt: 0,
21  };
22
23  function storageGet(key) {
24    try {
25      return global.sessionStorage.getItem(key);
26    } catch (e) {
27      return null;
28    }
29  }
30
31  function storageSet(key, value) {
32    try {
33      global.sessionStorage.setItem(key, value);
34    } catch (e) {}
35  }
36
37  function storageRemove(key) {
38    try {
39      global.sessionStorage.removeItem(key);
40    } catch (e) {}
41  }
42
43  function prefersReducedMotion() {
44    return global.matchMedia && global.matchMedia('(prefers-reduced-motion: reduce)').matches;
45  }
46
47  function isMobileViewport() {
48    return global.matchMedia && global.matchMedia('(max-width: 767px)').matches;
49  }
50
51  function isLoaderPage() {
52    var body = global.document && global.document.body;
53    if (!body) return false;
54    return body.classList.contains('fg-app') || body.classList.contains('fg-auth');
55  }
56
57  function readPendingNavigation() {
58    var raw = storageGet(NAV_KEY);
59    if (!raw) return false;
60    var ts = Number(raw);
61    if (!ts || Number.isNaN(ts)) {
62      storageRemove(NAV_KEY);
63      return false;
64    }
65    if (Date.now() - ts > NAV_MAX_AGE_MS) {
66      storageRemove(NAV_KEY);
67      return false;
68    }
69    return true;
70  }
71
72  function buildRoot() {
73    var doc = global.document;
74    var root = doc.createElement('div');
75    root.id = 'fg-page-loader-root';
76    root.className = 'fg-page-loader';
77    root.setAttribute('aria-hidden', 'true');
78    root.setAttribute('aria-live', 'polite');
79    root.setAttribute('role', 'status');
80
81    var bar = doc.createElement('div');
82    bar.className = 'fg-page-loader__bar';
83    bar.setAttribute('aria-hidden', 'true');
84
85    var overlay = doc.createElement('div');
86    overlay.className = 'fg-page-loader__overlay';
87    overlay.setAttribute('aria-hidden', 'true');
88
89    var brand = doc.createElement('div');
90    brand.className = 'fg-page-loader__brand';
91
92    var spinner = doc.createElement('div');
93    spinner.className = 'fg-page-loader__spinner';
94    spinner.setAttribute('aria-hidden', 'true');
95
96    var ring = doc.createElement('div');
97    ring.className = 'fg-page-loader__ring';
98    spinner.appendChild(ring);
99
100    var label = doc.createElement('p');
101    label.className = 'fg-page-loader__label';
102    label.textContent = 'Loading…';
103
104    brand.appendChild(spinner);
105    brand.appendChild(label);
106    overlay.appendChild(brand);
107    root.appendChild(bar);
108    root.appendChild(overlay);
109    return root;
110  }
111
112  function ensureRoot() {
113    if (state.root) return state.root;
114    var doc = global.document;
115    if (!doc || !doc.body) return null;
116
117    var existing = doc.getElementById('fg-page-loader-root');
118    if (existing) {
119      state.root = existing;
120      return existing;
121    }
122
123    var root = buildRoot();
124    doc.body.appendChild(root);
125    state.root = root;
126    return root;
127  }
128
129  function clearOverlayTimer() {
130    if (state.overlayTimer) {
131      global.clearTimeout(state.overlayTimer);
132      state.overlayTimer = null;
133    }
134  }
135
136  function markNavigationPending() {
137    storageSet(NAV_KEY, String(Date.now()));
138  }
139
140  function clearNavigationPending() {
141    storageRemove(NAV_KEY);
142  }
143
144  function scheduleOverlay(immediate) {
145    clearOverlayTimer();
146    if (prefersReducedMotion()) return;
147
148    var delay = immediate
149      ? 0
150      : isMobileViewport()
151        ? MOBILE_OVERLAY_DELAY_MS
152        : OVERLAY_DELAY_MS;
153
154    state.overlayTimer = global.setTimeout(function () {
155      if (state.active && state.root) {
156        state.root.classList.add('is-overlay');
157      }
158    }, delay);
159  }
160
161  function start(opts) {
162    opts = opts || {};
163    if (!isLoaderPage()) return;
164
165    var root = ensureRoot();
166    if (!root) return;
167
168    if (!state.active) {
169      state.active = true;
170      state.startedAt = Date.now();
171    }
172
173    root.classList.remove('is-done', 'is-finishing');
174    root.classList.add('is-active');
175    scheduleOverlay(!!opts.immediateOverlay);
176  }
177
178  function finish() {
179    clearNavigationPending();
180
181    if (!state.root || !state.active) {
182      if (state.root) {
183        state.root.classList.remove('is-active', 'is-overlay', 'is-finishing');
184        state.root.classList.add('is-done');
185      }
186      state.active = false;
187      clearOverlayTimer();
188      return;
189    }
190
191    clearOverlayTimer();
192    var elapsed = Date.now() - state.startedAt;
193    var wait = Math.max(0, MIN_VISIBLE_MS - elapsed);
194
195    global.setTimeout(function () {
196      if (!state.root) return;
197      state.root.classList.remove('is-active', 'is-overlay');
198      state.root.classList.add('is-finishing');
199      global.setTimeout(function () {
200        if (!state.root) return;
201        state.root.classList.remove('is-finishing');
202        state.root.classList.add('is-done');
203        state.active = false;
204      }, 280);
205    }, wait);
206  }
207
208  function sameOriginHref(href) {
209    try {
210      var url = new URL(href, global.location.href);
211      return url.origin === global.location.origin;
212    } catch (e) {
213      return false;
214    }
215  }
216
217  function shouldNavigate(el, href, ev) {
218    if (!href || href.indexOf('#') === 0) return false;
219    if (ev && (ev.defaultPrevented || ev.button !== 0 || ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey)) {
220      return false;
221    }
222    if (el.getAttribute('target') === '_blank') return false;
223    if (el.hasAttribute('download')) return false;
224    if (el.getAttribute('rel') === 'external') return false;
225    if (el.dataset && el.dataset.fgNoLoader === 'true') return false;
226    if (/^(mailto:|tel:|javascript:)/i.test(href)) return false;
227    if (!sameOriginHref(href)) return false;
228
229    try {
230      var next = new URL(href, global.location.href);
231      if (next.pathname === global.location.pathname && next.search === global.location.search) {
232        return false;
233      }
234    } catch (e2) {
235      return false;
236    }
237    return true;
238  }
239
240  function findLink(el) {
241    while (el && el !== global.document.body) {
242      if (el.tagName === 'A' && el.href) return el;
243      el = el.parentElement;
244    }
245    return null;
246  }
247
248  function highlightNavItem(link) {
249    if (!link || !link.closest) return;
250    var item = link.closest('.fixed-footer.fg-bottom-nav .item');
251    if (!item) return;
252    item.classList.add('fg-nav-tap-active');
253    global.setTimeout(function () {
254      item.classList.remove('fg-nav-tap-active');
255    }, 200);
256  }
257
258  function beginNavigation() {
259    var now = Date.now();
260    if (now - state.lastNavAt < 450) return;
261    state.lastNavAt = now;
262    markNavigationPending();
263    start({ immediateOverlay: true });
264  }
265
266  function onPointerUp(ev) {
267    var link = findLink(ev.target);
268    if (!link) return;
269    if (!shouldNavigate(link, link.getAttribute('href') || link.href, ev)) return;
270    highlightNavItem(link);
271    beginNavigation();
272  }
273
274  function onSubmit(ev) {
275    var form = ev.target;
276    if (!form || form.tagName !== 'FORM') return;
277    if (form.dataset && form.dataset.fgNoLoader === 'true') return;
278    if (form.getAttribute('target') === '_blank') return;
279    var method = (form.getAttribute('method') || 'get').toLowerCase();
280    if (method === 'dialog') return;
281    if (form.dataset && (form.dataset.fgAjax === 'true' || form.classList.contains('fg-ajax-form'))) {
282      return;
283    }
284    beginNavigation();
285  }
286
287  function isReloadNavigation() {
288    try {
289      var nav = performance.getEntriesByType && performance.getEntriesByType('navigation')[0];
290      return !!(nav && nav.type === 'reload');
291    } catch (e) {
292      return false;
293    }
294  }
295
296  function clearPendingNavigation() {
297    storageRemove(NAV_KEY);
298  }
299
300  function onPageReady() {
301    if (isReloadNavigation()) {
302      clearPendingNavigation();
303    }
304    finish();
305  }
306
307  function resumePendingNavigation() {
308    if (isReloadNavigation()) {
309      clearPendingNavigation();
310      return;
311    }
312    if (!readPendingNavigation()) return;
313    start({ immediateOverlay: true });
314  }
315
316  function bindEvents() {
317    if (state.bound) return;
318    state.bound = true;
319    global.document.addEventListener('click', onPointerUp, true);
320    global.addEventListener('pageshow', onPageReady);
321    global.addEventListener('load', onPageReady);
322  }
323
324  function init() {
325    if (!global.document || !global.document.body) return;
326    if (!isLoaderPage()) return;
327
328    ensureRoot();
329    resumePendingNavigation();
330    bindEvents();
331
332    global.FGPageLoader = {
333      start: start,
334      finish: finish,
335      beginNavigation: beginNavigation,
336    };
337  }
338
339  function boot() {
340    if (!global.document) return;
341    if (global.document.body && isLoaderPage() && readPendingNavigation() && !isReloadNavigation()) {
342      ensureRoot();
343      start({ immediateOverlay: true });
344    }
345    if (global.document.readyState === 'loading') {
346      global.document.addEventListener('DOMContentLoaded', init);
347    } else {
348      init();
349    }
350  }
351
352  boot();
353})(typeof window !== 'undefined' ? window : this);

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.