mirror of
https://github.com/renorris/openfsd
synced 2026-08-10 11:33:29 +08:00
airport-editor: stop status flash from scrolling the map on vertex grab
Vertex drag auto-selects a surface; the select tip unhid a banner and reflowed the layout under the cursor. Skip the tip while dragging and keep the status strip always one line tall so messages never shove the map.
This commit is contained in:
@@ -179,6 +179,25 @@
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Live editor status strip: always occupies one line of vertical space so
|
||||
* show/hide never reflows the toolbar/map (vertex grab was scrolling the page).
|
||||
* Empty state is invisible but still in normal flow.
|
||||
*/
|
||||
.apted-flash[data-js="status"] {
|
||||
min-height: calc(1.25em + 0.7rem + 2px);
|
||||
box-sizing: border-box;
|
||||
margin: 0.25rem 0 0;
|
||||
/* Avoid browser scrolling the flash into view on updates */
|
||||
overflow-anchor: none;
|
||||
}
|
||||
.apted-flash[data-js="status"].is-empty {
|
||||
visibility: hidden;
|
||||
border-color: transparent;
|
||||
background: transparent;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.apted-flash-ok {
|
||||
background: #d1e7dd;
|
||||
color: var(--apted-ok);
|
||||
|
||||
@@ -111,7 +111,11 @@ function main() {
|
||||
if (doc.mode !== MODE_SELECT) return;
|
||||
doc.selection = normalizeSelection(sel);
|
||||
refresh();
|
||||
syncSurfaceSelectTip();
|
||||
// Vertex grab auto-selects the surface — do not flash a status banner
|
||||
// (unhiding the flash strip reflows the page and scrolls the map).
|
||||
if (!overlays.isVertexDragging()) {
|
||||
syncSurfaceSelectTip();
|
||||
}
|
||||
},
|
||||
onVertexDrag(si, vi, lat, lon) {
|
||||
setVertex(doc, si, vi, { lat, lon });
|
||||
@@ -756,29 +760,31 @@ function main() {
|
||||
function showStatus(msg, isError) {
|
||||
const el = root.querySelector('[data-js="status"]');
|
||||
if (!el) return;
|
||||
el.hidden = !msg;
|
||||
// Keep the strip in layout always (never [hidden]) so messages do not
|
||||
// expand the page and shove the map / scroll the viewport.
|
||||
el.hidden = false;
|
||||
el.textContent = msg || '';
|
||||
el.classList.toggle('apted-flash-err', !!isError);
|
||||
el.classList.toggle('is-empty', !msg);
|
||||
el.classList.toggle('apted-flash-err', !!isError && !!msg);
|
||||
el.classList.toggle('apted-flash-ok', !isError && !!msg);
|
||||
el.setAttribute('role', isError ? 'alert' : 'status');
|
||||
el.setAttribute('role', isError && msg ? 'alert' : 'status');
|
||||
el.setAttribute('aria-hidden', msg ? 'false' : 'true');
|
||||
}
|
||||
|
||||
/** Status banner for surface select in Select mode (not mid-drag). */
|
||||
/**
|
||||
* Select tip lives in a reserved status strip (no layout jump). We no longer
|
||||
* push a banner on every surface select — mode tip covers "drag vertices".
|
||||
* Clear only our old tip text if present so deselect stays quiet.
|
||||
*/
|
||||
const SURFACE_SELECT_TIP =
|
||||
'Drag any white vertex to reshape. Click empty map to deselect.';
|
||||
|
||||
/**
|
||||
* Show tip when selection is a surface; clear it when selection leaves a
|
||||
* surface (empty-map deselect, aircraft select). Only on selection change.
|
||||
*/
|
||||
function syncSurfaceSelectTip() {
|
||||
if (doc.mode === MODE_SELECT && doc.selection?.type === 'surface') {
|
||||
showStatus(SURFACE_SELECT_TIP, false);
|
||||
return;
|
||||
}
|
||||
// Drop only our tip — do not wipe errors or other status flashes.
|
||||
const el = root.querySelector('[data-js="status"]');
|
||||
if (el && el.textContent === SURFACE_SELECT_TIP) {
|
||||
if (!el) return;
|
||||
// Quiet: do not inject tip on select (was causing scroll-on-grab).
|
||||
// Clear stale tip if it is still showing from an older build/session.
|
||||
if (el.textContent === SURFACE_SELECT_TIP) {
|
||||
showStatus('', false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -788,6 +788,15 @@ export class OverlayController {
|
||||
this.vertexEditActive = !!active;
|
||||
}
|
||||
|
||||
/**
|
||||
* True while a vertex pointer-drag is active (including the select that starts it).
|
||||
* Callers use this to avoid layout-shifting status flashes mid-grab.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isVertexDragging() {
|
||||
return !!(this._vertexDrag || this._dragging);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw preview polyline for in-progress draw session.
|
||||
* @param {{ lat: number, lon: number }[]} points
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
<div class="apted-flash apted-flash-err" role="alert">{{ .FlashError }}</div>
|
||||
{{ end }}
|
||||
|
||||
<p class="apted-flash" data-js="status" hidden role="status"></p>
|
||||
{{/* Always in flow (is-empty) so status text never reflows the map. */}}
|
||||
<p class="apted-flash is-empty" data-js="status" role="status" aria-hidden="true"></p>
|
||||
|
||||
<div class="apted-toolbar" role="toolbar" aria-label="Editor tools">
|
||||
<label class="btn btn-sm btn-outline-dark apted-file-btn">
|
||||
@@ -212,7 +213,7 @@
|
||||
Static assets are go:embed into the openfsd binary — restart the process after
|
||||
JS/CSS changes. Query string busts browser cache when the binary is rebuilt.
|
||||
*/}}
|
||||
<script src="/static/js/leaflet.js?v=vertex-edit-5"></script>
|
||||
<script src="/static/js/openfsd/leaflet.rotatedmarker.js?v=vertex-edit-5"></script>
|
||||
<script type="module" src="/static/js/openfsd/airport-editor/main.js?v=vertex-edit-5"></script>
|
||||
<script src="/static/js/leaflet.js?v=vertex-edit-6"></script>
|
||||
<script src="/static/js/openfsd/leaflet.rotatedmarker.js?v=vertex-edit-6"></script>
|
||||
<script type="module" src="/static/js/openfsd/airport-editor/main.js?v=vertex-edit-6"></script>
|
||||
{{ end }}
|
||||
|
||||
Reference in New Issue
Block a user