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.