[fix](trx-frontend-http): fix map and statistics tabs requiring refresh to show data

Move template cloning into navigateToTab() so deferred <template>
content is materialized before any tab-specific initialization runs.
Previously the document-level template cloner fired after navigateToTab
due to event propagation order, causing initAprsMap() and
scheduleStatsRender() to target elements that did not yet exist. Also
defer statistics control wiring until the first render so event
listeners are attached after the template is cloned.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-04-04 13:48:08 +02:00
parent 81427cd87b
commit bed49ce13b
3 changed files with 31 additions and 35 deletions
@@ -4444,7 +4444,14 @@ function navigateToTab(name, options = {}) {
document.querySelectorAll(".tab-bar .tab").forEach((t) => t.classList.remove("active"));
btn.classList.add("active");
document.querySelectorAll(".tab-panel").forEach((p) => p.style.display = "none");
document.getElementById(`tab-${name}`).style.display = "";
const panel = document.getElementById(`tab-${name}`);
panel.style.display = "";
// Clone deferred <template> content into the panel before any tab-specific init.
const tmpl = panel.querySelector("template");
if (tmpl) {
panel.appendChild(tmpl.content.cloneNode(true));
tmpl.remove();
}
if (updateHistory) {
updateTabHistory(name, replaceHistory);
}
@@ -1655,21 +1655,7 @@
window.loadPluginsForTab = loadPlugins;
})();
</script>
<script>
(function() {
document.addEventListener('click', function(e) {
var tab = e.target.closest('[data-tab]');
if (!tab) return;
var panel = document.getElementById('tab-' + tab.dataset.tab);
if (!panel) return;
var tmpl = panel.querySelector('template');
if (tmpl) {
panel.appendChild(tmpl.content.cloneNode(true));
tmpl.remove();
}
});
})();
</script>
<!-- Template cloning is handled by navigateToTab() in app.js -->
<script defer src="/vendor/leaflet.js"></script>
</body>
</html>
@@ -3178,11 +3178,33 @@
}
let _statsRenderPending = false;
let _statsControlsWired = false;
function _wireStatsControls() {
if (_statsControlsWired) return;
const rigEl = document.getElementById("stats-rig-filter");
const histEl = document.getElementById("stats-history-limit");
if (!rigEl && !histEl) return; // template not yet cloned
_statsControlsWired = true;
if (rigEl) {
rigEl.addEventListener("change", () => {
statsRigFilter = rigEl.value;
scheduleStatsRender();
});
}
if (histEl) {
histEl.value = String(statsHistoryLimitMinutes);
histEl.addEventListener("change", () => {
statsHistoryLimitMinutes = Number(histEl.value) || 1440;
scheduleStatsRender();
});
}
}
function scheduleStatsRender() {
if (_statsRenderPending) return;
_statsRenderPending = true;
requestAnimationFrame(() => {
_statsRenderPending = false;
_wireStatsControls();
renderStatsCounters();
renderStatsDecodeTypes();
renderStatsBandActivity();
@@ -3194,25 +3216,6 @@
});
}
// Wire up statistics panel controls
(function() {
const rigEl = document.getElementById("stats-rig-filter");
if (rigEl) {
rigEl.addEventListener("change", () => {
statsRigFilter = rigEl.value;
scheduleStatsRender();
});
}
const histEl = document.getElementById("stats-history-limit");
if (histEl) {
histEl.value = String(statsHistoryLimitMinutes);
histEl.addEventListener("change", () => {
statsHistoryLimitMinutes = Number(histEl.value) || 1440;
scheduleStatsRender();
});
}
})();
function buildBookmarkLocatorPopupHtml(grid, bookmarks) {
const list = Array.isArray(bookmarks) ? bookmarks : [];
const rows = list