Avoid map zoom-out when navigating between routes
Route links (route_master list, other directions) now intercept clicks and call loadRoute() + history.pushState() instead of doing a full page reload, so the map stays at its current position and zooms smoothly into the new route. Ctrl/cmd/middle-click still opens in a new tab via href. Introduce currentRelationId (mutable) to track the loaded relation so loadSegment() uses the correct ID after in-page navigation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3223d4b063
commit
f6dd68ed75
1 changed files with 20 additions and 1 deletions
|
|
@ -22,6 +22,7 @@ let routeMasterLayers = []; // coloured polylines when viewing a route_master
|
||||||
|
|
||||||
// ── State ─────────────────────────────────────────────────────────────────
|
// ── State ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
let currentRelationId = RELATION_ID; // tracks the currently loaded relation
|
||||||
let routeData = null; // response from /api/route/
|
let routeData = null; // response from /api/route/
|
||||||
let segmentGeoJson = null; // last response from /api/segment/ (always includes stops)
|
let segmentGeoJson = null; // last response from /api/segment/ (always includes stops)
|
||||||
let activeSlot = 'from'; // 'from' | 'to' | null
|
let activeSlot = 'from'; // 'from' | 'to' | null
|
||||||
|
|
@ -301,6 +302,21 @@ document.getElementById('include-stops').addEventListener('change', () => {
|
||||||
document.getElementById('slot-from').addEventListener('click', () => setActiveSlot('from'));
|
document.getElementById('slot-from').addEventListener('click', () => setActiveSlot('from'));
|
||||||
document.getElementById('slot-to').addEventListener('click', () => setActiveSlot('to'));
|
document.getElementById('slot-to').addEventListener('click', () => setActiveSlot('to'));
|
||||||
|
|
||||||
|
// ── Navigation ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a relation without a full page reload, updating the browser URL.
|
||||||
|
* Allows middle-click / ctrl-click to still open in a new tab via the href.
|
||||||
|
* @param {number} id
|
||||||
|
* @param {MouseEvent} e
|
||||||
|
*/
|
||||||
|
function navigateTo(id, e) {
|
||||||
|
if (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0) return;
|
||||||
|
e.preventDefault();
|
||||||
|
history.pushState(null, '', `/${id}`);
|
||||||
|
loadRoute(id);
|
||||||
|
}
|
||||||
|
|
||||||
// ── API calls ──────────────────────────────────────────────────────────────
|
// ── API calls ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -320,6 +336,7 @@ async function loadRoute(relationId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
routeData = data;
|
routeData = data;
|
||||||
|
currentRelationId = relationId;
|
||||||
// Clean up any previous route_master view
|
// Clean up any previous route_master view
|
||||||
for (const l of routeMasterLayers) l.remove();
|
for (const l of routeMasterLayers) l.remove();
|
||||||
routeMasterLayers = [];
|
routeMasterLayers = [];
|
||||||
|
|
@ -358,6 +375,7 @@ async function loadRoute(relationId) {
|
||||||
a.href = `/${dir.id}`;
|
a.href = `/${dir.id}`;
|
||||||
a.className = 'stop-item d-block text-decoration-none';
|
a.className = 'stop-item d-block text-decoration-none';
|
||||||
a.textContent = dir.name;
|
a.textContent = dir.name;
|
||||||
|
a.addEventListener('click', (e) => navigateTo(dir.id, e));
|
||||||
dirList.appendChild(a);
|
dirList.appendChild(a);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -373,7 +391,7 @@ async function loadRoute(relationId) {
|
||||||
*/
|
*/
|
||||||
async function loadSegment() {
|
async function loadSegment() {
|
||||||
if (!selectedFrom || !selectedTo || !routeData) return;
|
if (!selectedFrom || !selectedTo || !routeData) return;
|
||||||
const rid = RELATION_ID;
|
const rid = currentRelationId;
|
||||||
const params = new URLSearchParams({ from: selectedFrom, to: selectedTo, stops: '1' });
|
const params = new URLSearchParams({ from: selectedFrom, to: selectedTo, stops: '1' });
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(`/api/segment/${rid}?${params}`);
|
const resp = await fetch(`/api/segment/${rid}?${params}`);
|
||||||
|
|
@ -444,6 +462,7 @@ async function loadRouteMaster(relationId) {
|
||||||
a.href = `/${route.id}`;
|
a.href = `/${route.id}`;
|
||||||
a.className = 'text-decoration-none text-reset flex-grow-1';
|
a.className = 'text-decoration-none text-reset flex-grow-1';
|
||||||
a.textContent = route.name;
|
a.textContent = route.name;
|
||||||
|
a.addEventListener('click', (e) => navigateTo(route.id, e));
|
||||||
|
|
||||||
div.appendChild(dot);
|
div.appendChild(dot);
|
||||||
div.appendChild(a);
|
div.appendChild(a);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue