PageSourceSearch

https://radiobomsucessoweb.com.br/assets/js/router.js?v=tkzyn8

js radiobomsucessoweb.com.br collected 2026-10-02 01:18:22 UTC 12,905 bytes, 396 lines download raw bytes

1/*
2 *
3 * Only the target container is ever touched, so anything outside it keeps its
4 * DOM node. That is what stops the audio player from restarting on Safari:
5 * the <audio> element is never re-parented and its script never runs twice.
6 */
7(function (window, document) {
8  "use strict";
9
10  var SKIP_CLASSES = ["ext-link", "no-ajaxy", "no-ajax"];
11  var SKIP_PROTOCOLS = ["mailto:", "tel:", "javascript:", "sms:", "whatsapp:"];
12
13  var SKELETON =
14    '<div class="router-skeleton wrap">' +
15    '<div class="router-skeleton__bar skeleton"></div>' +
16    '<div class="router-skeleton__grid">' +
17    '<div class="router-skeleton__block skeleton"></div>' +
18    '<div class="router-skeleton__block skeleton"></div>' +
19    '<div class="router-skeleton__block skeleton"></div>' +
20    '</div></div>';
21
22  function ReqBras(options) {
23    // Single instance: this file self-starts early, and utils.js constructs it
24    // again later. Two instances would mean two click handlers.
25    if (ReqBras.instance) return ReqBras.instance;
26
27    var settings = options || {};
28
29    this.container = settings.elements || "#pContent";
30    this.scrolltop = settings.scrolltop !== false;
31    this.timeout = settings.timeout || 15000;
32    this.skeletonDelay = settings.skeletonDelay || 180;
33    // A theme opts out with data-skeleton="off" on <html>
34    this.skeleton = document.documentElement.dataset.skeleton !== "off";
35    this.prefetch = settings.prefetchoff !== true;
36
37    this.loadedScripts = new Set();
38    this.prefetched = new Set();
39    this.pageTimers = [];
40    this.cache = new Map();
41    this.scrollPositions = {};
42    this.controller = null;
43    this.skeletonTimer = null;
44    this.booted = false;
45
46    this.boot();
47  }
48
49  // Bootstrap sets scroll-behavior: smooth on the root, which turns a plain
50  // scrollTo into a half second animation. Navigation wants a cut, not a
51  // trip: "instant" wins over the sheet.
52  function jump(y) {
53    try {
54      window.scrollTo({ top: y, left: 0, behavior: "instant" });
55    } catch (error) {
56      window.scrollTo(0, y);
57    }
58  }
59
60  // Events keep the old names so existing listeners keep working
61  ReqBras.prototype.emit = function (name, detail) {
62    [window, document].forEach(function (node) {
63      var event = document.createEvent("HTMLEvents");
64      event.initEvent("pronto." + name, false, false);
65      event.data = detail || {};
66      node.dispatchEvent(event);
67    });
68  };
69
70  ReqBras.prototype.target = function () {
71    return document.querySelector(this.container);
72  };
73
74  ReqBras.prototype.boot = function () {
75    if (this.booted) return;
76    this.booted = true;
77
78    var self = this;
79
80    ReqBras.instance = this;
81
82    // Everything already on the page counts as loaded, so it never runs twice.
83    // Runs again on DOMContentLoaded because this file starts before the rest
84    // of the head has been parsed.
85    this.indexScripts();
86    document.addEventListener("DOMContentLoaded", function () { self.indexScripts(); });
87
88    if ("scrollRestoration" in window.history) {
89      window.history.scrollRestoration = "manual";
90    }
91
92    document.addEventListener("click", function (e) { self.onClick(e); }, false);
93    window.addEventListener("popstate", function (e) { self.onPopState(e); }, false);
94
95    if (this.prefetch) {
96      document.addEventListener("mouseover", function (e) { self.onHover(e); }, { passive: true });
97      document.addEventListener("touchstart", function (e) { self.onHover(e); }, { passive: true });
98    }
99
100    if (window.history.replaceState) {
101      window.history.replaceState({ reqbras: true, key: this.key() }, document.title, window.location.href);
102    }
103
104    this.emit("load");
105  };
106
107  ReqBras.prototype.key = function () {
108    return window.location.pathname + window.location.search;
109  };
110
111  ReqBras.prototype.indexScripts = function () {
112    var self = this;
113    document.querySelectorAll("script[src]").forEach(function (script) {
114      self.loadedScripts.add(script.src);
115    });
116  };
117
118  // Security: only same-origin http(s) URLs are ever fetched or injected
119  ReqBras.prototype.isInternal = function (url) {
120    try {
121      var parsed = new URL(url, window.location.href);
122      if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return false;
123      return parsed.origin === window.location.origin;
124    } catch (err) {
125      return false;
126    }
127  };
128
129  ReqBras.prototype.linkFrom = function (node) {
130    return node && node.closest ? node.closest("a[href]") : null;
131  };
132
133  // Returns the URL this link should navigate to, or null when it must be left alone
134  ReqBras.prototype.routable = function (link) {
135    if (!link) return null;
136
137    var href = link.getAttribute("href");
138    if (!href || href.charAt(0) === "#") return null;
139
140    var lower = href.toLowerCase();
141    if (SKIP_PROTOCOLS.some(function (p) { return lower.indexOf(p) === 0; })) return null;
142    if (link.hasAttribute("download") || link.hasAttribute("data-no-ajax")) return null;
143    if (SKIP_CLASSES.some(function (c) { return link.classList.contains(c); })) return null;
144    if (link.target && link.target !== "_self") return null;
145    if (!this.isInternal(href)) return null;
146
147    return new URL(href, window.location.href).href;
148  };
149
150  ReqBras.prototype.onHover = function (e) {
151    var link = this.linkFrom(e.target);
152    var url = this.routable(link);
153
154    if (!url || url === window.location.href || this.cache.has(url)) return;
155
156    // One try per address: a link that fails must not be fetched on every hover
157    if (this.prefetched.has(url)) return;
158    this.prefetched.add(url);
159
160    var self = this;
161
162    fetch(url, { credentials: "same-origin", headers: { "X-Requested-With": "XMLHttpRequest" } })
163      .then(function (response) {
164        if (!response.ok) return;
165        var type = response.headers.get("content-type") || "";
166        if (type.indexOf("text/html") === -1) return;
167        return response.text();
168      })
169      .then(function (html) {
170        if (!html) return;
171
172        // Small cache: enough to make the click feel instant, not to hold the site
173        if (self.cache.size > 8) self.cache.clear();
174        self.cache.set(url, html);
175      })
176      .catch(function () {});
177  };
178
179  ReqBras.prototype.onClick = function (e) {
180    if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
181
182    var link = this.linkFrom(e.target);
183    if (!link) return;
184
185    var href = link.getAttribute("href");
186    if (!href) return;
187
188    // Opt-out classes and other hosts open in a new tab
189    var flagged = SKIP_CLASSES.some(function (c) { return link.classList.contains(c); });
190    var external = !this.isInternal(href);
191    var special = SKIP_PROTOCOLS.some(function (p) { return href.toLowerCase().indexOf(p) === 0; });
192
193    if ((flagged || external) && !special && href.charAt(0) !== "#") {
194      if (!link.target && (external || link.classList.contains("ext-link"))) {
195        link.target = "_blank";
196        link.rel = "noopener noreferrer";
197      }
198      return;
199    }
200
201    var url = this.routable(link);
202    if (!url || !this.target()) return;
203
204    e.preventDefault();
205
206    if (url === window.location.href) return;
207
208    this.scrollPositions[this.key()] = window.pageYOffset;
209
210    if (this.scrolltop) jump(0);
211
212    this.go(url, true);
213  };
214
215  ReqBras.prototype.onPopState = function (e) {
216    if (!e.state || !e.state.reqbras) return;
217    this.go(window.location.href, false, e.state.key);
218  };
219
220  ReqBras.prototype.go = function (url, push, restoreKey) {
221    var self = this;
222
223    if (this.controller) this.controller.abort();
224
225    this.emit("request", { url: url });
226
227    var cached = this.cache.get(url);
228    if (cached) {
229      this.cache.delete(url);
230      this.render(cached, url, push, restoreKey);
231      return;
232    }
233
234    this.showSkeleton();
235
236    var controller = new AbortController();
237    var timer = window.setTimeout(function () { controller.abort(); }, this.timeout);
238    this.controller = controller;
239
240    fetch(url, {
241      credentials: "same-origin",
242      redirect: "follow",
243      headers: { "X-Requested-With": "XMLHttpRequest" },
244      signal: controller.signal
245    })
246      .then(function (response) {
247        if (!response.ok) throw new Error("HTTP " + response.status);
248
249        var type = response.headers.get("content-type") || "";
250        if (type.indexOf("text/html") === -1) throw new Error("Not HTML");
251
252        // A redirect to another origin must never be injected into the page
253        if (!self.isInternal(response.url)) throw new Error("Cross-origin response");
254
255        return response.text();
256      })
257      .then(function (html) {
258        window.clearTimeout(timer);
259        self.controller = null;
260        self.render(html, url, push, restoreKey);
261      })
262      .catch(function (err) {
263        window.clearTimeout(timer);
264        self.controller = null;
265        self.hideSkeleton();
266
267        if (err && err.name === "AbortError") return;
268
269        self.emit("error", { url: url, error: err });
270        window.location.href = url;
271      });
272  };
273
274  // Only shows up when the response is actually slow, so fast clicks do not flash
275  ReqBras.prototype.showSkeleton = function () {
276    var self = this;
277
278    this.hideSkeleton();
279
280    if (!this.skeleton) return;
281
282    this.skeletonTimer = window.setTimeout(function () {
283      var target = self.target();
284      if (target) target.innerHTML = SKELETON;
285    }, this.skeletonDelay);
286  };
287
288  ReqBras.prototype.hideSkeleton = function () {
289    if (!this.skeletonTimer) return;
290    window.clearTimeout(this.skeletonTimer);
291    this.skeletonTimer = null;
292  };
293
294  ReqBras.prototype.render = function (html, url, push, restoreKey) {
295    var target = this.target();
296    if (!target) { window.location.href = url; return; }
297
298    // DOMParser never executes anything while parsing
299    var doc = new DOMParser().parseFromString(html, "text/html");
300    var fresh = doc.querySelector(this.container);
301
302    if (!fresh) { window.location.href = url; return; }
303
304    this.hideSkeleton();
305    this.clearTimers();
306
307    var title = doc.querySelector("title");
308    if (title) document.title = title.textContent;
309
310    // A page with unbalanced markup makes the parser nest the footer, header or
311    // player inside the container. Dropping them here keeps those shells alive.
312    fresh.querySelectorAll("footer.foot, #pHeader, #pWide, #cookie-banner-lgpd, .bras-player, .bras-player-spacer").forEach(function (stray) {
313      stray.remove();
314    });
315
316    // Page CSS hangs on the class of the container, so it travels with the HTML
317    target.className = fresh.className;
318    target.innerHTML = fresh.innerHTML;
319    this.runScripts(target);
320
321    if (push && window.history.pushState) {
322      window.history.pushState({ reqbras: true, key: this.key() }, document.title, url);
323    }
324
325    var restore = restoreKey ? this.scrollPositions[restoreKey] : null;
326
327    if (restore != null) {
328      jump(restore);
329    } else if (this.scrolltop) {
330      jump(0);
331    }
332
333    this.emit("render", { url: url });
334  };
335
336  // Intervals started by page scripts are dropped on the next navigation
337  ReqBras.prototype.clearTimers = function () {
338    this.pageTimers.forEach(function (id) { window.clearInterval(id); });
339    this.pageTimers = [];
340  };
341
342  ReqBras.prototype.runScripts = function (container) {
343    var self = this;
344    var scripts = Array.prototype.slice.call(container.querySelectorAll("script"));
345
346    var nativeInterval = window.setInterval;
347    var nativeTimeout = window.setTimeout;
348
349    window.setInterval = function () {
350      var id = nativeInterval.apply(window, arguments);
351      self.pageTimers.push(id);
352      return id;
353    };
354
355    window.setTimeout = function () {
356      var id = nativeTimeout.apply(window, arguments);
357      self.pageTimers.push(id);
358      return id;
359    };
360
361    try {
362      scripts.forEach(function (script) { self.runScript(script); });
363    } finally {
364      window.setInterval = nativeInterval;
365      window.setTimeout = nativeTimeout;
366    }
367  };
368
369  ReqBras.prototype.runScript = function (script) {
370    var src = script.getAttribute("src");
371
372    if (src) {
373      var absolute = new URL(src, window.location.href).href;
374
375      // Never load the same file twice: that is what duplicated the player handlers
376      if (this.loadedScripts.has(absolute)) { script.remove(); return; }
377      this.loadedScripts.add(absolute);
378    }
379
380    var fresh = document.createElement("script");
381
382    Array.prototype.forEach.call(script.attributes, function (attr) {
383      fresh.setAttribute(attr.name, attr.value);
384    });
385
386    if (!src) fresh.textContent = script.textContent;
387
388    script.parentNode.replaceChild(fresh, script);
389  };
390
391  window.ReqBras = ReqBras;
392
393  // Starts as soon as this file runs, before the heavy libraries in the head.
394  // A slow page still gets working navigation from the first paint.
395  new ReqBras({ elements: "#pContent", scrolltop: true });
396})(window, document);

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.