PageSourceSearch

https://www.techmarcos.com/wp-content/themes/techmarcos/assets/js/modules/ui/events.js

js techmarcos.com collected 2026-10-06 14:17:54 UTC 2,309 bytes, 89 lines download raw bytes

1/**
2 * Window event bus.
3 *
4 * One throttled `scroll` listener and one debounced `resize`/`orientationchange`
5 * listener for the whole page; features register callbacks instead of each
6 * binding their own window listener. This is a shared singleton (ES module), so
7 * the core entry and any conditional entry register into the same queues.
8 *
9 * Why: scroll/resize fire dozens of times a second — coalescing to one
10 * rAF-throttled scroll pass and one debounced resize pass avoids layout
11 * thrashing and redundant work.
12 *
13 * @module ui/events
14 */
15import { debounce, rafThrottle } from "../core/raf.js";
16
17const $ = window.jQuery;
18const $window = $(window);
19const NS = ".tmEvents";
20
21/** @type {Array<() => void>} */
22const scrollHandlers = [];
23/** @type {Array<() => void>} */
24const resizeHandlers = [];
25
26let bound = false;
27let firedInitial = false;
28
29/**
30 * Register a scroll callback (deduplicated).
31 * @param {() => void} handler
32 */
33export function onScroll(handler) {
34  if (typeof handler === "function" && !scrollHandlers.includes(handler)) {
35    scrollHandlers.push(handler);
36  }
37}
38
39/**
40 * Register a resize/orientationchange callback (deduplicated).
41 * @param {() => void} handler
42 */
43export function onResize(handler) {
44  if (typeof handler === "function" && !resizeHandlers.includes(handler)) {
45    resizeHandlers.push(handler);
46  }
47}
48
49function runScroll() {
50  scrollHandlers.forEach((handler) => handler());
51}
52
53function runResize() {
54  resizeHandlers.forEach((handler) => handler());
55}
56
57/** Run every registered handler once (used after registration and on load). */
58export function runAll() {
59  runResize();
60  runScroll();
61}
62
63const throttledScroll = rafThrottle(runScroll);
64const debouncedResize = debounce(runResize, 150);
65
66/**
67 * Bind the window listeners exactly once and do an initial pass on load. Safe to
68 * call from multiple entries — only the first call binds.
69 */
70export function ensureWindowEvents() {
71  if (bound) return;
72  bound = true;
73
74  $window
75    .on(`scroll${NS}`, throttledScroll)
76    .on(`resize${NS} orientationchange${NS}`, debouncedResize);
77
78  const fireInitial = () => {
79    if (firedInitial) return;
80    firedInitial = true;
81    runAll();
82  };
83
84  if (document.readyState === "complete") {
85    fireInitial();
86  } else {
87    $window.on(`load${NS}`, fireInitial);
88  }
89}

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.