[fix](trx-frontend-http): make map links work before the map has loaded
The AIS and APRS mini views link each position to the map, and neither did anything: the map module installs itself lazily, and it was the one defining window.navigateToAprsMap, so until something had opened the Map tab the global did not exist. AIS calls it inline from onclick and threw "not a function"; APRS guards the call and so failed silently. The grid links on FT8, FT4, FT2 and WSPR rows went the same way through navigateToMapLocator. The app owns both globals now, installed at startup. They record the target, switch tabs through navigateToTab — the only path that materialises the panel from its template, loads the module and updates the history entry, none of which the module's own hand-rolled tab switch did — and the target is applied once the module reports ready. The module keeps the focusing, which is its job, and exposes it as focusMapPosition and focusMapLocator. The smoke test now calls the link from a cold page, asserting the map module is not loaded first so the check cannot pass by accident. Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -5601,6 +5601,39 @@ var _activeTab = "main";
|
||||
function tabFromPath2(pathname = window.location.pathname) {
|
||||
return tabFromPath(pathname);
|
||||
}
|
||||
var pendingMapTarget = null;
|
||||
function applyMapTarget(target) {
|
||||
const map = window.trx.modules.map;
|
||||
if (!map) return false;
|
||||
if (target.kind === "position") {
|
||||
map.focusMapPosition?.(target.lat, target.lon);
|
||||
} else {
|
||||
map.focusMapLocator?.(target.grid, target.preferredType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function requestMapTarget(target) {
|
||||
pendingMapTarget = target;
|
||||
navigateToTab("map");
|
||||
if (window.trx.modules.map) {
|
||||
requestAnimationFrame(() => {
|
||||
drainPendingMapTarget();
|
||||
});
|
||||
}
|
||||
}
|
||||
function drainPendingMapTarget() {
|
||||
const target = pendingMapTarget;
|
||||
if (!target) return;
|
||||
if (applyMapTarget(target)) pendingMapTarget = null;
|
||||
}
|
||||
window.navigateToAprsMap = (lat, lon) => {
|
||||
if (!isFiniteNumber(lat) || !isFiniteNumber(lon)) return;
|
||||
requestMapTarget({ kind: "position", lat, lon });
|
||||
};
|
||||
window.navigateToMapLocator = (grid, preferredType = null) => {
|
||||
if (!grid) return;
|
||||
requestMapTarget({ kind: "locator", grid, preferredType });
|
||||
};
|
||||
var _mapInitTimer = null;
|
||||
function _initMapWhenReady() {
|
||||
const loadingEl2 = document.getElementById("map-loading");
|
||||
@@ -5617,6 +5650,7 @@ function _initMapWhenReady() {
|
||||
requestAnimationFrame(() => {
|
||||
map.sizeAprsMapToViewport();
|
||||
map.aprsMap?.invalidateSize();
|
||||
drainPendingMapTarget();
|
||||
});
|
||||
});
|
||||
return;
|
||||
|
||||
@@ -1669,16 +1669,7 @@ var mapWindow = window;
|
||||
popupAnchor: [0, -12]
|
||||
});
|
||||
}
|
||||
mapWindow.navigateToAprsMap = function(lat, lon) {
|
||||
T._activeTab = "map";
|
||||
document.querySelectorAll(".tab-bar .tab").forEach((t) => {
|
||||
t.classList.remove("active");
|
||||
});
|
||||
const mapTabBtn = document.querySelector(".tab-bar .tab[data-tab='map']");
|
||||
if (mapTabBtn) mapTabBtn.classList.add("active");
|
||||
document.querySelectorAll(".tab-panel").forEach((p) => p.style.display = "none");
|
||||
const mapPanel = mapEl("tab-map");
|
||||
if (mapPanel) mapPanel.style.display = "";
|
||||
function focusMapPosition(lat, lon) {
|
||||
initAprsMap();
|
||||
sizeAprsMapToViewport();
|
||||
if (aprsMap) {
|
||||
@@ -1690,19 +1681,10 @@ var mapWindow = window;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
mapWindow.navigateToMapLocator = function(grid, preferredType = null) {
|
||||
}
|
||||
function focusMapLocator(grid, preferredType = null) {
|
||||
const normalizedGrid = String(grid || "").trim().toUpperCase();
|
||||
if (!/^[A-R]{2}\d{2}(?:[A-X]{2})?$/.test(normalizedGrid)) return false;
|
||||
T._activeTab = "map";
|
||||
document.querySelectorAll(".tab-bar .tab").forEach((t) => {
|
||||
t.classList.remove("active");
|
||||
});
|
||||
const mapTabBtn = document.querySelector(".tab-bar .tab[data-tab='map']");
|
||||
if (mapTabBtn) mapTabBtn.classList.add("active");
|
||||
document.querySelectorAll(".tab-panel").forEach((p) => p.style.display = "none");
|
||||
const mapPanel = mapEl("tab-map");
|
||||
if (mapPanel) mapPanel.style.display = "";
|
||||
initAprsMap();
|
||||
sizeAprsMapToViewport();
|
||||
if (!aprsMap) return false;
|
||||
@@ -1747,7 +1729,7 @@ var mapWindow = window;
|
||||
requestAnimationFrame(focusMarker);
|
||||
});
|
||||
return true;
|
||||
};
|
||||
}
|
||||
function buildReceiverPopupHtml(rigIds) {
|
||||
const call = T.serverCallsign || T.ownerCallsign || "Receiver";
|
||||
let meta = "";
|
||||
@@ -2332,7 +2314,7 @@ var mapWindow = window;
|
||||
selectedMapQsoKey = selectedMapQsoKey === entry.pathKey ? null : entry.pathKey ?? null;
|
||||
syncDecodeContactPathVisibility();
|
||||
if (selectedMapQsoKey && entry.sourceGrid) {
|
||||
mapWindow.navigateToMapLocator?.(entry.sourceGrid, entry.sourceType);
|
||||
focusMapLocator(entry.sourceGrid, entry.sourceType);
|
||||
}
|
||||
});
|
||||
const head = document.createElement("div");
|
||||
@@ -2438,7 +2420,7 @@ var mapWindow = window;
|
||||
card.className = "map-qso-card";
|
||||
if (entry.grid) {
|
||||
card.addEventListener("click", () => {
|
||||
mapWindow.navigateToMapLocator?.(entry.grid ?? "", entry.sourceType);
|
||||
focusMapLocator(entry.grid ?? "", entry.sourceType);
|
||||
});
|
||||
}
|
||||
const head = document.createElement("div");
|
||||
@@ -2544,7 +2526,7 @@ var mapWindow = window;
|
||||
card.className = "map-qso-card";
|
||||
if (entry.grid) {
|
||||
card.addEventListener("click", () => {
|
||||
mapWindow.navigateToMapLocator?.(entry.grid ?? "", entry.sourceType);
|
||||
focusMapLocator(entry.grid ?? "", entry.sourceType);
|
||||
});
|
||||
}
|
||||
const head = document.createElement("div");
|
||||
@@ -3049,6 +3031,8 @@ var mapWindow = window;
|
||||
}
|
||||
modules.map = {
|
||||
initAprsMap,
|
||||
focusMapPosition,
|
||||
focusMapLocator,
|
||||
sizeAprsMapToViewport,
|
||||
syncAprsReceiverMarker,
|
||||
updateMapRigFilter,
|
||||
|
||||
Reference in New Issue
Block a user