mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-11-15 07:07:07 +00:00
fix a latitude typed past ±90 in the waypoint tool (#398)
The pin followed the latitude and longitude fields on every keystroke, and min/max on a number field don't stop typing, so a value on the way to a coordinate (389) reached Marker.setLngLat and MapLibre threw "Invalid LngLat latitude value". An empty field moved the pin to the equator, saving with one threw on null.toFixed, and an out-of-range value saved as typed. The pin now stays where it was and Save is disabled until both fields hold a coordinate in range, and the field that doesn't is marked invalid. Co-authored-by: vcoppe <vianney.coppe@gmail.com>
This commit is contained in:
1 parent
9e289c33be
commit
2608870505
1 file changed
+21
-2
@@ -45,6 +45,19 @@
|
|||||||
|
|
||||||
let marker: Marker | null = null;
|
let marker: Marker | null = null;
|
||||||
|
|
||||||
|
// A number field holds what is typed, out of range or empty (null) on the way to a
|
||||||
|
// coordinate, and a map click sets strings. MapLibre throws on a latitude past ±90.
|
||||||
|
function inRange(value: number | string | null, limit: number) {
|
||||||
|
if (value === null || value === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const n = Number(value);
|
||||||
|
return Number.isFinite(n) && Math.abs(n) <= limit;
|
||||||
|
}
|
||||||
|
let latitudeValid = $derived(inRange(latitude, 90));
|
||||||
|
let longitudeValid = $derived(inRange(longitude, 180));
|
||||||
|
let coordinatesValid = $derived(latitudeValid && longitudeValid);
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
if ($selectedWaypoint) {
|
if ($selectedWaypoint) {
|
||||||
selectedWaypoint.reset();
|
selectedWaypoint.reset();
|
||||||
@@ -78,6 +91,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function createOrUpdateWaypoint() {
|
async function createOrUpdateWaypoint() {
|
||||||
|
if (!coordinatesValid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (typeof latitude === 'string') {
|
if (typeof latitude === 'string') {
|
||||||
latitude = parseFloat(latitude);
|
latitude = parseFloat(latitude);
|
||||||
}
|
}
|
||||||
@@ -128,7 +144,8 @@
|
|||||||
marker = null;
|
marker = null;
|
||||||
}
|
}
|
||||||
} else if (latitude != 0 || longitude != 0) {
|
} else if (latitude != 0 || longitude != 0) {
|
||||||
if ($map) {
|
// while a coordinate is being typed the pin stays where it last was
|
||||||
|
if ($map && coordinatesValid) {
|
||||||
if (marker) {
|
if (marker) {
|
||||||
marker.setLngLat([longitude, latitude]).getElement().innerHTML =
|
marker.setLngLat([longitude, latitude]).getElement().innerHTML =
|
||||||
getSvgForSymbol(symbolKey);
|
getSvgForSymbol(symbolKey);
|
||||||
@@ -248,6 +265,7 @@
|
|||||||
min={-90}
|
min={-90}
|
||||||
max={90}
|
max={90}
|
||||||
class="text-xs h-8"
|
class="text-xs h-8"
|
||||||
|
aria-invalid={!latitudeValid}
|
||||||
disabled={!canCreate && !$selectedWaypoint}
|
disabled={!canCreate && !$selectedWaypoint}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -261,6 +279,7 @@
|
|||||||
min={-180}
|
min={-180}
|
||||||
max={180}
|
max={180}
|
||||||
class="text-xs h-8"
|
class="text-xs h-8"
|
||||||
|
aria-invalid={!longitudeValid}
|
||||||
disabled={!canCreate && !$selectedWaypoint}
|
disabled={!canCreate && !$selectedWaypoint}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -269,7 +288,7 @@
|
|||||||
<div class="flex flex-row gap-1.5 items-center">
|
<div class="flex flex-row gap-1.5 items-center">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
disabled={!canCreate && !$selectedWaypoint}
|
disabled={(!canCreate && !$selectedWaypoint) || !coordinatesValid}
|
||||||
class="grow shrink h-fit min-h-8 whitespace-normal py-1"
|
class="grow shrink h-fit min-h-8 whitespace-normal py-1"
|
||||||
onclick={createOrUpdateWaypoint}
|
onclick={createOrUpdateWaypoint}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in new issue
Block a user