diff --git a/assets/geo_osm.css b/assets/geo_osm.css index e69de29..9bb020d 100755 --- a/assets/geo_osm.css +++ b/assets/geo_osm.css @@ -0,0 +1,151 @@ +:root { + --rex-geo-background: #fff; + --rex-geo-background-hover: #f8f9fa; + --rex-geo-text: #212529; + --rex-geo-border: #dee2e6; + --rex-geo-input-bg: #fff; + --rex-geo-input-text: #212529; + --rex-geo-input-border: #dee2e6; + --rex-geo-shadow: rgba(0,0,0,0.1); + --rex-geo-primary: #2196F3; + --rex-geo-primary-hover: #1e87db; + --rex-geo-success: #4CAF50; + --rex-geo-success-hover: #45a049; +} + +/* Dark theme colors */ +:root[data-theme="dark"], +.rex-has-theme.rex-theme-dark { + --rex-geo-background: #32373c; + --rex-geo-background-hover: #3c4146; + --rex-geo-text: #fff; + --rex-geo-border: #404448; + --rex-geo-input-bg: #282c30; + --rex-geo-input-text: #fff; + --rex-geo-input-border: #404448; + --rex-geo-shadow: rgba(0,0,0,0.3); +} + +@media (prefers-color-scheme: dark) { + :root { + --rex-geo-background: #32373c; + --rex-geo-background-hover: #3c4146; + --rex-geo-text: #fff; + --rex-geo-border: #404448; + --rex-geo-input-bg: #282c30; + --rex-geo-input-text: #fff; + --rex-geo-input-border: #404448; + --rex-geo-shadow: rgba(0,0,0,0.3); + } +} +.rex-geo-search-modal { + display: none; + position: fixed; + z-index: 1000; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.5); +} + +.rex-geo-search-content { + background-color: var(--rex-geo-background); + color: var(--rex-geo-text); + margin: 10% auto; + padding: 30px; + border-radius: 8px; + width: 90%; + max-width: 800px; + position: relative; + box-shadow: 0 4px 6px var(--rex-geo-shadow); + border: 1px solid var(--rex-geo-border); +} + +.rex-geo-search-close { + position: absolute; + right: 15px; + top: 10px; + font-size: 28px; + cursor: pointer; + opacity: 0.7; + color: var(--rex-geo-text); +} + +.rex-geo-search-close:hover { + opacity: 1; +} + +.rex-geo-search-wrapper { + margin: 20px auto; + width: 90%; +} + +.rex-geo-search-input { + width: 100%; + font-size: 24px !important; + padding: 15px !important; + border: 2px solid var(--rex-geo-input-border) !important; + border-radius: 8px !important; + height: auto !important; + background-color: var(--rex-geo-input-bg) !important; + color: var(--rex-geo-input-text) !important; +} + +.rex-geo-search-input:focus { + border-color: var(--rex-geo-primary) !important; + outline: none; + box-shadow: 0 0 0 3px rgba(33,150,243,0.2) !important; +} + +.search-results { + max-height: 400px; + overflow-y: auto; + margin: 15px auto; + width: 90%; +} + +.search-result { + padding: 12px 15px; + cursor: pointer; + border-bottom: 1px solid var(--rex-geo-border); + transition: background-color 0.2s ease; + font-size: 16px; + color: var(--rex-geo-text); +} + +.search-result:hover { + background-color: var(--rex-geo-background-hover); +} + +.btn-group { + margin-bottom: 10px; +} + +.btn-group .btn { + margin-right: 5px; +} + +.btn.browser-location { + background-color: var(--rex-geo-success); + border-color: var(--rex-geo-success); + color: #fff; +} + +.btn.browser-location:hover { + background-color: var(--rex-geo-success-hover); + border-color: var(--rex-geo-success-hover); +} + +.btn.search, +.btn.set { + background-color: var(--rex-geo-primary); + border-color: var(--rex-geo-primary); + color: #fff; +} + +.btn.search:hover, +.btn.set:hover { + background-color: var(--rex-geo-primary-hover); + border-color: var(--rex-geo-primary-hover); +} diff --git a/assets/geo_osm.js b/assets/geo_osm.js index a4c115a..0e274ba 100755 --- a/assets/geo_osm.js +++ b/assets/geo_osm.js @@ -1,6 +1,6 @@ function rex_geo_osm_get_address(addressfields) { var out = []; - for(var i=0;iOpenStreetMap contributors' }).addTo(map); - } - else { - + } else { var mapboxAttribution = 'Map data © OpenStreetMap contributors, ' + 'CC-BY-SA, ' + 'Imagery © Mapbox'; - var streets = L.tileLayer('//api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token='+mapbox_token, {id: 'mapbox.streets', attribution: mapboxAttribution}), - streets_sattelite = L.tileLayer('//api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token='+mapbox_token, {id: 'mapbox.streets-satellite', attribution: mapboxAttribution}); + var streets = L.tileLayer('//api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token='+mapbox_token, + {id: 'mapbox.streets', attribution: mapboxAttribution}), + streets_sattelite = L.tileLayer('//api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token='+mapbox_token, + {id: 'mapbox.streets-satellite', attribution: mapboxAttribution}); - var map = L.map('map-'+id, { + map = L.map('map-'+id, { center: [current_lat, current_lng], zoom: 16, layers: [streets, streets_sattelite] }); var baseMaps = { - "Karte": streets, - "Satellit": streets_sattelite + "Map": streets, + "Satellite": streets_sattelite }; L.control.layers(baseMaps).addTo(map); } - var marker = L.marker([current_lat, current_lng], { draggable: true }).on('dragend', function(ev) { @@ -69,10 +57,96 @@ var rex_geo_osm = function(addressfields, geofields, id, mapbox_token) { $(geofields.lat+','+geofields.lng).on('keyup', function() { var lat = $(geofields.lat).val(); var lng = $(geofields.lng).val(); - map.setView([lat, lng, 16]); + map.setView([lat, lng], 16); marker.setLatLng([lat, lng]); }); + // Show/hide search modal + $('#search-geo-'+id).on('click', function() { + $('#rex-geo-search-modal-'+id).show(); + $('#rex-geo-search-input-'+id).focus(); + }); + + $('.rex-geo-search-close').on('click', function() { + $(this).closest('.rex-geo-search-modal').hide(); + }); + + // Live search + $('#rex-geo-search-input-'+id).on('input', function(e) { + e.preventDefault(); + performSearch($(this).val()); + }); + + let searchTimeout; + + function performSearch(searchText) { + if(searchText.trim() === '') { + $('#rex-geo-search-results-'+id).empty(); + return; + } + + clearTimeout(searchTimeout); + searchTimeout = setTimeout(() => { + var xhr = new XMLHttpRequest(); + xhr.onload = function () { + if (xhr.status >= 200 && xhr.status < 300) { + var json = JSON.parse(xhr.response); + displaySearchResults(json); + } else { + console.log('An error occurred.'); + } + }; + xhr.open('GET', 'https://nominatim.openstreetmap.org/search?q='+encodeURIComponent(searchText)+'&format=json&polygon=0&addressdetails=1&limit=5'); + xhr.send(); + }, 300); + } + + function displaySearchResults(results) { + const resultsContainer = $('#rex-geo-search-results-'+id); + resultsContainer.empty(); + + if(results.length === 0) { + resultsContainer.append('
No results found
'); + return; + } + + results.forEach(result => { + const resultDiv = $('
'); + resultDiv.text(result.display_name); + resultDiv.on('click', () => selectLocation(result)); + resultsContainer.append(resultDiv); + }); + } + + function selectLocation(location) { + $(geofields.lat).val(location.lat); + $(geofields.lng).val(location.lon); + map.setView([location.lat, location.lon], 16); + marker.setLatLng([location.lat, location.lon]); + $('#rex-geo-search-modal-'+id).hide(); + $('#rex-geo-search-input-'+id).val(''); + $('#rex-geo-search-results-'+id).empty(); + } + + // Browser geolocation + $('#browser-geo-'+id).on('click', function() { + if ("geolocation" in navigator) { + navigator.geolocation.getCurrentPosition(function(position) { + var lat = position.coords.latitude; + var lng = position.coords.longitude; + $(geofields.lat).val(lat); + $(geofields.lng).val(lng); + map.setView([lat, lng], 16); + marker.setLatLng([lat, lng]); + }, function(error) { + alert("Geolocation failed: " + error.message); + }); + } else { + alert("Your browser doesn't support geolocation."); + } + }); + + // Original address geocoding $('#set-geo-'+id).on('click', function(e) { e.preventDefault(); @@ -81,30 +155,27 @@ var rex_geo_osm = function(addressfields, geofields, id, mapbox_token) { var postalcode = $(addressfields[1]).val(); if(street=='' || city=='' || postalcode == '') { - alert('Bitte vorerst die Adresse vollständig ausfüllen.'); + alert('Please fill in the complete address first.'); return true; } - var xhr = new XMLHttpRequest(); xhr.onload = function () { if (xhr.status >= 200 && xhr.status < 300) { var json = JSON.parse(xhr.response); if(json.length==0) { - alert('Adresse nicht gefunden.') + alert('Address not found') return false; } $(geofields.lat).val(json[0].lat); $(geofields.lng).val(json[0].lon); - setTimeout(function(){ - $(geofields.lat).keyup(); - }, 200); + map.setView([json[0].lat, json[0].lon], 16); + marker.setLatLng([json[0].lat, json[0].lon]); } else { - console.log('Es trat ein Fehler auf.'); + console.log('An error occurred.'); } }; - xhr.open('GET', 'https://nominatim.openstreetmap.org/search?street='+street+'&city='+city+'&postalcode='+postalcode+'&format=json&polygon=0&addressdetails=0&limit=1'); + xhr.open('GET', 'https://nominatim.openstreetmap.org/search?q='+encodeURIComponent(street+' '+city+' '+postalcode)+'&format=json&polygon=0&addressdetails=0&limit=1'); xhr.send(); - - }) + }); } diff --git a/lang/de_de.lang b/lang/de_de.lang index 5157d9f..74e11f2 100755 --- a/lang/de_de.lang +++ b/lang/de_de.lang @@ -1,3 +1,7 @@ yform_geo_osm = Geo (OSM) yform_geo_osm_overview = Geo (OSM) Übersicht -yform_geo_osm_set_data = Geo-Koordinaten anhand von Adressdaten ermitteln \ No newline at end of file +yform_geo_osm_get_coords = Koordinaten von Adresse ermitteln +yform_geo_osm_search_address = Adresse suchen +yform_geo_osm_get_location = Meinen Standort übernehmen +yform_geo_osm_search = Suchen +yform_geo_osm_search_placeholder = Adresse eingeben... diff --git a/lang/en_gb.lang b/lang/en_gb.lang index b368f22..e109313 100755 --- a/lang/en_gb.lang +++ b/lang/en_gb.lang @@ -1,3 +1,7 @@ yform_geo_osm = Geo (OSM) yform_geo_osm_overview = Geo (OSM) Overview -yform_geo_osm_set_data = Get location based on address data \ No newline at end of file +yform_geo_osm_get_coords = Get coordinates from address +yform_geo_osm_search_address = Search address +yform_geo_osm_get_location = Get current location +yform_geo_osm_search = Search +yform_geo_osm_search_placeholder = Enter address... diff --git a/package.yml b/package.yml index 49f2383..57241ea 100755 --- a/package.yml +++ b/package.yml @@ -1,5 +1,5 @@ package: yform_geo_osm -version: '1.2.10' +version: '1.3.0' author: 'Friends Of REDAXO' supportpage: https://github.com/FriendsOfREDAXO/yform_geo_osm diff --git a/ytemplates/bootstrap/value.osm_geocode.tpl.php b/ytemplates/bootstrap/value.osm_geocode.tpl.php index 8195215..b4c73c9 100755 --- a/ytemplates/bootstrap/value.osm_geocode.tpl.php +++ b/ytemplates/bootstrap/value.osm_geocode.tpl.php @@ -1,27 +1,26 @@ getWarningClass()); +$class_group = trim('form-group yform-element ' . $this->getWarningClass()); $class_label = 'control-label'; $address_selectors = []; - -foreach($addressfields as $afield) - foreach($this->params["values"] as $val) - if ($val->getName() == $afield) +foreach($addressfields as $afield) { + foreach($this->params["values"] as $val) { + if ($val->getName() == $afield) { $address_selectors[] = "#".$val->getFieldId(); + } + } +} $geo_selectors = []; - foreach($this->params["values"] as $val) { - if ($val->getName() == $geofields[0]) + if ($val->getName() == $geofields[0]) { $geo_selectors['lat'] = "#".$val->getFieldId(); - - if ($val->getName() == $geofields[1]) + } + if ($val->getName() == $geofields[1]) { $geo_selectors['lng'] = "#".$val->getFieldId(); - + } } - $js = ''; rex_extension::register('OUTPUT_FILTER', 'yform_geo_osm::addDynJs', rex_extension::LATE, ['js' => $js]); +?> +
+ -?> -
- +
+
+ + + +
+ +
-
-
+ +
+
+ × +
+ +
+
+
+