Private/Get-DhJsBoot.ps1
|
function Get-DhJsBoot { # Auto-split fragment of the dashboard runtime JS (see Get-DhJsContent). return @' /* ========================================================================= BOOT ========================================================================= */ document.addEventListener('DOMContentLoaded', function () { renderSummary(); renderBlocks(); TABLES_CONFIG.forEach(function (cfg) { engines[cfg.id] = new TableEngine(cfg); }); /* Bar charts and Mode-A pie charts need engines ready */ BLOCKS_CONFIG.forEach(function (block) { if (block.blockType === 'barchart') { var container = document.getElementById('block-'+block.id); if (container) renderBarChart(container, block); } else if (block.blockType === 'piechart' && block.mode === 'fromtable') { var container = document.getElementById('block-'+block.id); if (container) renderPieChart(container, block); } }); /* Alert banners — render AFTER engines exist so action filters work, and AFTER initNav() exposes window._showPanel. Moved below. */ /* Global filter bar (v1.9.0) — restore any saved selection, render the controls, then subscribe every table (and its derived charts) so a change re-filters the whole page at once. */ var _gfSaved = URLState.load().gf; if (_gfSaved) { if (_gfSaved.facets) Object.keys(_gfSaved.facets).forEach(function (f) { GlobalFilter.facets[f] = _gfSaved.facets[f]; }); if (_gfSaved.ranges) Object.keys(_gfSaved.ranges).forEach(function (f) { GlobalFilter.ranges[f] = _gfSaved.ranges[f]; }); } renderGlobalFilters(); GlobalFilter.subscribe(function () { Object.keys(engines).forEach(function (id) { var e = engines[id]; e.currentPage = 1; e.render(); e._refreshLinkedBarCharts(); e._renderCharts(); }); updateNavBadges(); }); /* Tables already rendered above without the restored filter — apply it now. */ if (GlobalFilter.active()) { Object.keys(engines).forEach(function (id) { var e = engines[id]; e.currentPage = 1; e.render(); e._refreshLinkedBarCharts(); e._renderCharts(); }); } initNav(); syncNavTop(); window.addEventListener('resize', syncNavTop); initThemeToggle(); initDensityToggle(); initTableCollapsibles(); /* Alert banners — initNav() has now exposed window._showPanel, and engines[] exists, so action buttons can navigate + filter. */ renderAlerts(); /* ── Restore URL state: density + card filters ── */ var _saved = URLState.load(); if (_saved.density) { /* Apply saved density class */ var _densityStates = ['normal','compact','comfortable']; var _densityLabels = { normal:'⊞ Normal', compact:'⊟ Compact', comfortable:'⊚ Spacious' }; if (_densityStates.indexOf(_saved.density) !== -1) { tableDensity = _saved.density; document.body.classList.add('density-' + tableDensity); var _db = document.getElementById('btn-density-toggle'); if (_db) _db.textContent = _densityLabels[tableDensity]; } } if (_saved.cardFilters) { /* Re-apply saved card filters — mark active cards and update engines */ Object.keys(_saved.cardFilters).forEach(function (filterId) { var cf = _saved.cardFilters[filterId]; cardFilters[filterId] = cf; /* Mark active cards visually */ var grid = document.getElementById('fcgrid-' + filterId); if (grid) { grid.querySelectorAll('.filter-card').forEach(function (card) { var cardVal = card.querySelector('.filter-card-name'); if (cardVal && cf.values && cf.values.indexOf(cardVal.textContent) !== -1) { card.classList.add('active'); } }); } /* Update engine */ if (cf.tableId && engines[cf.tableId]) { engines[cf.tableId]._applyCardFilters(); } }); } updateNavBadges(); }); })(); '@ } |