PageSourceSearch

https://votertools.voteidaho.gov/TEDElectionLink/_content/TEDxData…/RegistryGridFooter.amb2htf5bs.razor.js

js voteidaho.gov collected 2026-10-02 07:51:09 UTC 4,627 bytes, 79 lines download raw bytes

1// Colocated driver for RegistryGridFooter — the circuit-free grid footer. The footer renders as
2// plain HTML (buttons/select carrying data-action attributes) and the delegated listeners here
3// route its events host-shaped, mirroring RegistryCompactSearch.razor.js:
4// - Interactive host (a live circuit): the host registered a .NET bridge under the footer's
5//   rendered id — ONE interop call per click hands the action to the grid/adapter.
6// - Static grid tile: the footer sits INSIDE the html-tile poll island, so paging rides the poll
7//   URL (&page= 1-based, &pagesize=) and a poke re-renders the tile server-side with the requested
8//   page. The URL is the state store — every swap paints the server's answer for it. Batch-load
9//   and scroll-top have no static path (the server already caps rows; there's no circuit scroll
10//   state) — without a bridge those actions are no-ops, and hosts don't render them statically.
11//
12// Loaded two ways, both converging on one install: the app hosts include it as a plain
13// <script type="module"> tag beside Header.razor.js (so static tiles behave with no circuit),
14// and interactive hosts' interop imports it to register their bridge. The window flag makes
15// whichever load runs second a no-op.
16
17// Bridge registry: footer element id → DotNetObjectReference. Window-scoped so the listeners and
18// later register calls can never see different maps. Entries leave on component dispose; a missed
19// dispose (hard circuit drop) just leaves a dead ref whose invoke rejects — dispatch swallows that.
20export function registerFooterHandler(id, dotNetRef) {
21    if (id) (window.__tedGridFooterHandlers ??= new Map()).set(id, dotNetRef);
22}
23
24export function unregisterFooterHandler(id) {
25    if (id && window.__tedGridFooterHandlers) window.__tedGridFooterHandlers.delete(id);
26}
27
28export function init() {
29    if (window.__tedGridFooterInit) return;
30    window.__tedGridFooterInit = true;
31
32    function dispatch(footer, action, value) {
33        const bridge = window.__tedGridFooterHandlers && window.__tedGridFooterHandlers.get(footer.id);
34        if (bridge) {
35            bridge.invokeMethodAsync('HandleFooterAction', action, value).catch(() => { /* circuit gone */ });
36            return;
37        }
38
39        // Static tile: paging rides the poll URL. The footer lives inside the swap target, so the
40        // enclosing island is simply the closest one (never another tile's).
41        const island = footer.closest('.ted-html-tile[data-html-poll]');
42        if (!island) return;
43        try {
44            const url = new URL(island.getAttribute('data-html-poll'), location.href);
45            if (action === 'page-change' && value != null) {
46                if (value <= 1) url.searchParams.delete('page');
47                else url.searchParams.set('page', String(value));
48            } else if (action === 'page-size-change' && value != null) {
49                // Always explicit, including 0 ("All") — an absent pagesize means the tile's
50                // CONFIGURED page size, so deleting the param couldn't express show-all.
51                url.searchParams.set('pagesize', String(value));
52                url.searchParams.delete('page');
53            } else {
54                return; // load-next / load-all / scroll-top: bridge-only actions
55            }
56            island.setAttribute('data-html-poll', url.pathname + url.search);
57        } catch { return; /* malformed URL — leave the poll as-is */ }
58        if (island.tedStop && typeof island.tedStop.poke === 'function') island.tedStop.poke();
59    }
60
61    document.addEventListener('click', (e) => {
62        const btn = e.target.closest('[data-grid-footer] button[data-action]');
63        if (!btn || btn.disabled) return;
64        const footer = btn.closest('[data-grid-footer]');
65        const page = btn.hasAttribute('data-page') ? parseInt(btn.getAttribute('data-page'), 10) : null;
66        dispatch(footer, btn.getAttribute('data-action'), Number.isNaN(page) ? null : page);
67    });
68
69    document.addEventListener('change', (e) => {
70        const sel = e.target.closest && e.target.closest('[data-grid-footer] select[data-action="page-size-change"]');
71        if (!sel) return;
72        const size = parseInt(sel.value, 10);
73        if (!Number.isNaN(size)) dispatch(sel.closest('[data-grid-footer]'), 'page-size-change', size);
74    });
75}
76
77// Self-install on load — mirrors RegistryCompactSearch.razor.js, so either load path (the app's
78// script tag or an interactive host's interop import) behaves the same.
79init();

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.