From 57f253c10b6c25e34797a1c0d1909e0063f80435 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominik=20Weckm=C3=BCller?=
<47481567+do-me@users.noreply.github.com>
Date: Fri, 27 Dec 2024 17:34:18 +0100
Subject: [PATCH] Add files via upload
---
index.html | 22 ++++++++
main.js | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++
styles.css | 98 ++++++++++++++++++++++++++++++++++
3 files changed, 273 insertions(+)
create mode 100644 index.html
create mode 100644 main.js
create mode 100644 styles.css
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..962d73c
--- /dev/null
+++ b/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+ MapLibre GL JS with Geocoder
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..7abe1d4
--- /dev/null
+++ b/main.js
@@ -0,0 +1,153 @@
+var map = new maplibregl.Map({
+ container: 'map',
+ style: 'https://sgx.geodatenzentrum.de/gdz_basemapworld_vektor/styles/bm_web_wld_col.json',
+ center: [10, 51],
+ zoom: 6,
+});
+
+const addressInput = document.getElementById('addressInput');
+const searchResults = document.getElementById('searchResults');
+let marker = null;
+let resultsVisible = false;
+
+
+async function geocodeAddress(address) {
+const photonUrl = `https://photon.komoot.io/api/?q=${encodeURIComponent(address)}`;
+ try {
+ const response = await fetch(photonUrl);
+ const data = await response.json();
+
+ if (data && data.features && data.features.length > 0) {
+ const result = data.features[0];
+ const coords = result.geometry.coordinates;
+ updateMapAndMarker(coords);
+ clearSearchResults();
+
+ } else {
+ alert('No results found for this address.');
+ }
+ } catch (error) {
+ console.error('Error during geocoding', error);
+ alert('Error during geocoding.');
+ }
+}
+
+function updateMapAndMarker(coords) {
+map.flyTo({
+ center: coords,
+ zoom: 15,
+});
+
+if (marker) {
+ marker.remove();
+}
+
+marker = new maplibregl.Marker()
+ .setLngLat(coords)
+ .addTo(map);
+}
+
+async function fetchSuggestions(address) {
+if (!address) {
+ clearSearchResults();
+ return;
+}
+
+const photonUrl = `https://photon.komoot.io/api/?q=${encodeURIComponent(address)}&limit=5`;
+ try {
+ const response = await fetch(photonUrl);
+ const data = await response.json();
+ displaySuggestions(data.features);
+ } catch (error) {
+ console.error('Error fetching suggestions', error);
+ }
+}
+
+function displaySuggestions(results) {
+clearSearchResults();
+
+if (!results || results.length === 0) {
+ resultsVisible = false;
+ searchResults.style.display = 'none';
+ return;
+}
+
+results.forEach(result => {
+ const props = result.properties;
+ let addressParts = [];
+
+ if (props.name) {
+ addressParts.push(props.name);
+ }
+ if (props.street) {
+ addressParts.push(props.street);
+ }
+ if (props.housenumber) {
+ addressParts.push(props.housenumber)
+ }
+
+ if(props.postcode && props.city) {
+ addressParts.push(props.postcode + ' ' + props.city )
+ }
+
+ const addressString = addressParts.join(', ');
+
+ const listItem = document.createElement('li');
+ listItem.textContent = addressString;
+
+ listItem.addEventListener('click', () => {
+ const coords = result.geometry.coordinates;
+ addressInput.value = listItem.textContent;
+ updateMapAndMarker(coords);
+ clearSearchResults();
+ });
+
+ searchResults.appendChild(listItem);
+});
+ resultsVisible = true;
+ searchResults.style.display = 'block';
+}
+
+function clearSearchResults() {
+searchResults.innerHTML = '';
+searchResults.style.display = 'none';
+resultsVisible = false;
+}
+
+
+addressInput.addEventListener('keydown', (event) => {
+ if (event.key === 'Enter') {
+ event.preventDefault(); // Prevent form submission
+ if (searchResults.children.length > 0 ) {
+ const firstResult = searchResults.children[0];
+ firstResult.click();
+ } else {
+ const address = addressInput.value;
+ if (address) {
+ geocodeAddress(address);
+ } else {
+ alert('Please enter an address.');
+ }
+ }
+ }
+});
+
+addressInput.addEventListener('input', () => {
+ const address = addressInput.value;
+ fetchSuggestions(address);
+});
+
+
+addressInput.addEventListener('focus', () => {
+if (resultsVisible === false && addressInput.value) {
+ fetchSuggestions(addressInput.value)
+} else if (resultsVisible === false) {
+ clearSearchResults()
+}
+});
+
+
+// Event listener to close search results on map click
+map.on('click', () => {
+ clearSearchResults();
+});
\ No newline at end of file
diff --git a/styles.css b/styles.css
new file mode 100644
index 0000000..74377f5
--- /dev/null
+++ b/styles.css
@@ -0,0 +1,98 @@
+body {
+ margin: 0;
+ padding: 0;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+ -webkit-font-smoothing: antialiased; /* Improve text rendering on webkit browsers */
+ -moz-osx-font-smoothing: grayscale; /* Improve text rendering on firefox */
+ background-color: #f8f8f8; /* Light background color */
+}
+
+#map {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ width: 100%;
+ transition: filter 0.3s ease; /*Smooth transition for map interactions*/
+}
+
+#geocoder {
+ position: absolute;
+ top: 20px; /* Increased top padding to avoid clutter*/
+ left: 50%; /* Center on page*/
+ transform: translateX(-50%); /* Center on page*/
+ z-index: 1;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */
+}
+
+
+#geocoder input {
+ padding: 10px 14px; /* Padding for comfortable spacing*/
+ border: 1px solid #ddd; /* Lighter border for subtle look */
+ border-radius: 8px;
+ width: 450px; /* Reduced width (75% of 600px) */
+ box-sizing: border-box;
+ font-size: 1rem;
+ color: #333; /* Darker text for better readability */
+ transition: border-color 0.3s ease, box-shadow 0.3s ease; /* Smooth transition for input focus */
+ outline: none; /* Removing the default outline*/
+}
+
+#geocoder input:focus {
+ border-color: #aaa; /* Darker border on focus */
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); /* More noticeable shadow */
+}
+
+#searchResults {
+ position: absolute;
+ top: calc(100% + 5px);
+ left: 0; /* Align with the left edge of the input field */
+ background-color: white;
+ border: 1px solid #ddd; /* Lighter border */
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ max-height: 250px; /* Slightly more space for results */
+ overflow-y: auto;
+ z-index: 2;
+ width: 450px; /* Reduced width (75% of 600px) */
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+ border-radius: 8px;
+ display: none;
+ box-sizing: border-box; /* Include padding/border in width calculation */
+}
+
+#searchResults li {
+ padding: 10px 14px; /* Padding for list items*/
+ border-bottom: 1px solid #eee;
+ cursor: pointer;
+ color: #333;
+ transition: background-color 0.2s ease;
+}
+
+
+#searchResults li:last-child {
+ border-bottom: none;
+}
+
+#searchResults li:hover {
+ background-color: #f0f0f0; /* Light grey on hover */
+}
+
+/* Custom Scrollbar Styling */
+#searchResults::-webkit-scrollbar {
+ width: 8px; /* Width of the scrollbar */
+}
+
+#searchResults::-webkit-scrollbar-track {
+ background: #f1f1f1; /* Color of the track */
+ border-radius: 4px; /* Rounded track */
+}
+
+#searchResults::-webkit-scrollbar-thumb {
+ background: #c1c1c1; /* Color of the thumb */
+ border-radius: 4px; /* Rounded thumb */
+}
+
+#searchResults::-webkit-scrollbar-thumb:hover {
+ background: #a8a8a8; /* Darker color on hover */
+}
\ No newline at end of file