2 import { onDestroy } from 'svelte';
3 import UrlSubmitForm from '../components/UrlSubmitForm.svelte';
4 import { SvelteURLSearchParams } from 'svelte/reactivity';
6 import { zoomLevels } from '../lib/helpers.js';
7 import { map_store, refresh_page } from '../lib/stores.js';
9 let { lat = '', lon = '', zoom = '', api_request_params = {} } = $props();
11 function gotoCoordinates(newlat, newlon, newzoom) {
12 if (newlat === null || newlon === null) return;
14 let params = new SvelteURLSearchParams();
15 params.set('lat', newlat);
16 params.set('lon', newlon);
17 params.set('zoom', newzoom || zoom);
18 refresh_page('reverse', params);
21 const unsubscribe = map_store.subscribe(map => {
23 map.on('click', (e) => {
24 let coords = e.latlng.wrap();
25 gotoCoordinates(coords.lat.toFixed(5), coords.lng.toFixed(5));
30 // common mistake is to copy&paste latitude and longitude into the 'lat' search box
31 function maybeSplitLatitude(e) {
32 var coords_split = e.target.value.split(/,|%2C/);
33 if (coords_split.length === 2) {
34 document.querySelector('input[name=lat]').value = L.Util.trim(coords_split[0]);
35 document.querySelector('input[name=lon]').value = L.Util.trim(coords_split[1]);
39 function set_api_param(e) {
40 document.querySelector('input[name=' + e.target.dataset.apiParam + ']').value = e.target.value;
43 function onSwitchCoords(e) {
46 gotoCoordinates(lon, lat);
49 onDestroy(unsubscribe);
53 <div class="col-auto">
54 <label for="reverse-lat">lat</label>
56 <div class="col-auto">
57 <input id="reverse-lat"
60 class="form-control form-control-sm d-inline"
61 placeholder="latitude"
62 pattern="^-?\d+(\.\d+)?$"
64 onchange={maybeSplitLatitude} />
66 <div class="col-auto">
67 <button id="switch-coords"
68 onclick={onSwitchCoords}
69 class="btn btn-outline-secondary btn-sm"
70 title="switch lat and lon"><></button>
72 <div class="col-auto">
73 <label for="reverse-lon">lon</label>
75 <div class="col-auto">
76 <input id="reverse-lon"
79 class="form-control form-control-sm"
80 placeholder="longitude"
81 pattern="^-?\d+(\.\d+)?$"
84 <div class="col-auto">
85 <label for="reverse-zoom">max zoom</label>
87 <div class="col-auto">
88 <select id="reverse-zoom" name="zoom" class="form-select form-select-sm" bind:value={zoom}>
89 <option value="">---</option>
90 {#each zoomLevels() as zoomTitle, i}
91 <option value="{i}">{i} - {zoomTitle}</option>
96 name="layer" value="{api_request_params.layer || ''}" />
97 <div class="col-auto">
98 <button type="submit" class="btn btn-primary btn-sm mx-1">Search</button>
101 <UrlSubmitForm page="reverse" {content} />
103 <!-- Additional options -->
104 <details id="searchAdvancedOptions" class="mt-2">
105 <summary><small>Advanced options</small></summary>
108 <label for="option_layer">Layer</label>
109 <input id="option_layer" name="layer" placeholder="e.g. address,poi,railway,natural,manmade"
110 value="{api_request_params.layer || ''}"
111 data-api-param="layer" onchange={set_api_param}
112 class="form-control form-control-sm d-inline w-auto api-param-setting">
131 #searchAdvancedOptions ul {
132 list-style-type: none;
137 #searchAdvancedOptions li {
138 display: inline-block;
141 border: 1px dotted #ccc;
145 #searchAdvancedOptions label {
149 @media (max-width: 850px) {
150 #reverse-lon, #reverse-lat, #reverse-zoom {