diff --git a/templates/index.html b/templates/index.html
index fe7fb8b..47c64d2 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -672,7 +672,7 @@
font-weight: 500;
padding: 2px 7px;
white-space: nowrap;
- pointer-events: none;
+ cursor: pointer;
}
/* Custom circular pin that reflects the POI type */
@@ -1064,14 +1064,12 @@
// Build a viewbox from the currently visible map area so
// results are restricted to what the user can see.
- const mb = map.getBounds();
-
- const viewbox = [
- mb.west,
- mb.north,
- mb.east,
- mb.south
- ].join(",");
+ //
+ // Only send a viewbox once the map has loaded AND the
+ // bounds are geometrically valid. Otherwise we fall back
+ // straight to a global search (see below).
+ const viewbox =
+ getValidViewbox();
let data =
@@ -1293,6 +1291,133 @@
}
+ /* =========================================================
+ VIEWBOX HELPER
+ ========================================================= */
+
+ /*
+ * How far beyond the visible map area we extend the
+ * search box, in kilometres. This keeps results from
+ * being cut off at the screen edges.
+ */
+ const VIEWBOX_PADDING_KM = 5;
+
+
+ /*
+ * Convert a distance in metres to degrees of longitude
+ * at a given latitude.
+ */
+ function metersToLonDegrees(meters, lat) {
+
+ const rad =
+ lat * Math.PI / 180;
+
+ return meters /
+ (111320 * Math.cos(rad));
+ }
+
+
+ /*
+ * Convert a distance in metres to degrees of latitude.
+ */
+ function metersToLatDegrees(meters) {
+
+ return meters / 110574;
+ }
+
+
+ /*
+ * Return a "west,north,east,south" string for the
+ * currently visible map area, expanded by
+ * VIEWBOX_PADDING_KM on every side, or null if the map
+ * isn't ready yet or the bounds aren't usable. A null
+ * value makes the caller perform an unrestricted
+ * (global) search instead.
+ */
+ function getValidViewbox() {
+
+ if (!map.loaded())
+ return null;
+
+
+ const mb = map.getBounds();
+
+ let west =
+ mb.getWest();
+
+ let north =
+ mb.getNorth();
+
+ let east =
+ mb.getEast();
+
+ let south =
+ mb.getSouth();
+
+
+ /*
+ * Reject NaN / infinite values and inverted boxes.
+ */
+ if (
+ !isFinite(west) ||
+ !isFinite(north) ||
+ !isFinite(east) ||
+ !isFinite(south)
+ )
+ return null;
+
+
+ if (
+ east <= west ||
+ north <= south
+ )
+ return null;
+
+
+ /*
+ * Expand the box by the padding distance so that
+ * places just outside the viewport are still found.
+ */
+ const padMeters =
+ VIEWBOX_PADDING_KM * 1000;
+
+ const midLat =
+ (north + south) / 2;
+
+ const dLat =
+ metersToLatDegrees(padMeters);
+
+ const dLon =
+ metersToLonDegrees(
+ padMeters,
+ midLat
+ );
+
+
+ west -= dLon;
+ east += dLon;
+ north += dLat;
+ south -= dLat;
+
+
+ /*
+ * Clamp to valid geographic ranges after expansion.
+ */
+ north = Math.min(north, 90);
+ south = Math.max(south, -90);
+ west = Math.max(west, -180);
+ east = Math.min(east, 180);
+
+
+ return [
+ west,
+ north,
+ east,
+ south
+ ].join(",");
+ }
+
+
/* =========================================================
PERFORM SEARCH
========================================================= */