diff --git a/proxy/css/ui.css b/proxy/css/ui.css
index 6726793f..ab21ca76 100644
--- a/proxy/css/ui.css
+++ b/proxy/css/ui.css
@@ -27,9 +27,6 @@ body {
#search-results, #search-milestones-form {
display: none;
}
-#search-results .no-results {
- text-align: center;
-}
#legend {
position: absolute;
diff --git a/proxy/index.html b/proxy/index.html
index c9e7c958..177dcb2e 100644
--- a/proxy/index.html
+++ b/proxy/index.html
@@ -92,7 +92,7 @@
Search
-
+
diff --git a/proxy/js/styles.mjs b/proxy/js/styles.mjs
index bdb3be99..46c49663 100644
--- a/proxy/js/styles.mjs
+++ b/proxy/js/styles.mjs
@@ -889,6 +889,13 @@ const sources = {
tileSize: 256,
attribution: '© OpenStreetMap contributors'
},
+ search: {
+ type: 'geojson',
+ data: {
+ type: 'FeatureCollection',
+ features: [],
+ },
+ },
openrailwaymap_low: {
type: 'vector',
url: `${origin}/railway_line_low`,
@@ -954,6 +961,18 @@ const backgroundMap = {
}
};
+const searchResults = {
+ id: 'search',
+ type: 'circle',
+ source: 'search',
+ paint: {
+ 'circle-radius': 8,
+ 'circle-color': 'rgba(183, 255, 0, 0.7)',
+ 'circle-stroke-width': 2,
+ 'circle-stroke-color': 'black',
+ }
+};
+
// TODO remove all [switch, [zoom]] to ensure legend displays only visible features
const layers = {
standard: [
@@ -1838,6 +1857,7 @@ const layers = {
'text-padding': 10,
},
},
+ searchResults,
],
speed: [
@@ -2011,6 +2031,7 @@ const layers = {
'symbol-spacing': 100,
},
},
+ searchResults,
],
signals: [
@@ -2303,6 +2324,7 @@ const layers = {
],
}
},
+ searchResults,
],
electrification: [
@@ -2562,6 +2584,7 @@ const layers = {
'symbol-spacing': 100,
},
},
+ searchResults,
],
gauge: [
@@ -2839,6 +2862,7 @@ const layers = {
'symbol-spacing': 100,
},
},
+ searchResults,
],
};
diff --git a/proxy/js/ui.js b/proxy/js/ui.js
index 15b945cd..0ddb074e 100644
--- a/proxy/js/ui.js
+++ b/proxy/js/ui.js
@@ -13,6 +13,20 @@ const backgroundRasterUrlControl = document.getElementById('backgroundRasterUrl'
const legend = document.getElementById('legend')
const legendMapContainer = document.getElementById('legend-map')
+function registerLastSearchResults(results) {
+ const data = {
+ type: 'FeatureCollection',
+ features: results.map(result => ({
+ type: 'Feature',
+ geometry: {
+ type: 'Point',
+ coordinates: [result.latitude, result.longitude],
+ },
+ })),
+ };
+ map.getSource('search').setData(data);
+}
+
function facilitySearchQuery(type, term) {
const encoded = encodeURIComponent(term)
@@ -67,20 +81,48 @@ function searchForMilestones(ref, position) {
}
function showSearchResults(results, renderItem) {
- let content = '';
- if (results.length === 0) {
- content += `No results
`
- } else {
- results.forEach(result => {
- content += `${renderItem(result)}`
- })
- }
- searchResults.innerHTML = content;
+ registerLastSearchResults(results);
+
+ const bounds = results.length > 0
+ ? JSON.stringify(results.reduce(
+ (bounds, result) =>
+ bounds.extend({lat: result.longitude, lon: result.latitude}),
+ new maplibregl.LngLatBounds({lat: results[0].longitude, lon: results[0].latitude})
+ ).toArray())
+ : null;
+
+ searchResults.innerHTML = results.length === 0
+ ? `
+
+
+ 0 results
+
+
+ `
+ : `
+
+
+ ${results.length} results
+
+
+
+
+ `;
searchResults.style.display = 'block';
}
function hideSearchResults() {
searchResults.style.display = 'none';
+ registerLastSearchResults([]);
}
function showSearch() {
@@ -118,6 +160,13 @@ function searchMilestones() {
hideSearchResults();
}
+function viewSearchResultsOnMap(bounds) {
+ hideSearch();
+ map.fitBounds(bounds, {
+ padding: 40,
+ });
+}
+
function showConfiguration() {
backgroundSaturationControl.value = configuration.backgroundSaturation ?? defaultConfiguration.backgroundSaturation;
backgroundOpacityControl.value = configuration.backgroundOpacity ?? defaultConfiguration.backgroundOpacity;