]> git.openstreetmap.org Git - nominatim-ui.git/blob - src/components/SearchSectionReverse.svelte
svelte 4.x => 5.0
[nominatim-ui.git] / src / components / SearchSectionReverse.svelte
1 <script>
2   import { onDestroy } from 'svelte';
3   import UrlSubmitForm from '../components/UrlSubmitForm.svelte';
4
5   import { zoomLevels } from '../lib/helpers.js';
6   import { map_store, refresh_page } from '../lib/stores.js';
7
8   export let lat = '';
9   export let lon = '';
10   export let zoom = '';
11   export let api_request_params = {};
12
13   function gotoCoordinates(newlat, newlon, newzoom) {
14     if (newlat === null || newlon === null) return;
15
16     let params = new URLSearchParams();
17     params.set('lat', newlat);
18     params.set('lon', newlon);
19     params.set('zoom', newzoom || zoom);
20     refresh_page('reverse', params);
21   }
22
23   const unsubscribe = map_store.subscribe(map => {
24     if (map) {
25       map.on('click', (e) => {
26         let coords = e.latlng.wrap();
27         gotoCoordinates(coords.lat.toFixed(5), coords.lng.toFixed(5));
28       });
29     }
30   });
31
32   // common mistake is to copy&paste latitude and longitude into the 'lat' search box
33   function maybeSplitLatitude(e) {
34     var coords_split = e.target.value.split(/,|%2C/);
35     if (coords_split.length === 2) {
36       document.querySelector('input[name=lat]').value = L.Util.trim(coords_split[0]);
37       document.querySelector('input[name=lon]').value = L.Util.trim(coords_split[1]);
38     }
39   }
40
41   function set_api_param(e) {
42     document.querySelector('input[name=' + e.target.dataset.apiParam + ']').value = e.target.value;
43   }
44
45   onDestroy(unsubscribe);
46 </script>
47
48 <UrlSubmitForm page="reverse">
49   <div class="col-auto">
50     <label for="reverse-lat">lat</label>
51   </div>
52   <div class="col-auto">
53     <input id="reverse-lat"
54            name="lat"
55            type="text"
56            class="form-control form-control-sm d-inline"
57            placeholder="latitude"
58            pattern="^-?\d+(\.\d+)?$"
59            bind:value={lat}
60            on:change={maybeSplitLatitude} />
61   </div>
62   <div class="col-auto">
63     <button id="switch-coords"
64        on:click|preventDefault|stopPropagation={() => gotoCoordinates(lon, lat)}
65        class="btn btn-outline-secondary btn-sm"
66        title="switch lat and lon">&lt;&gt;</button>
67   </div>
68   <div class="col-auto">
69     <label for="reverse-lon">lon</label>
70   </div>
71   <div class="col-auto">
72     <input id="reverse-lon"
73            name="lon"
74            type="text"
75            class="form-control form-control-sm"
76            placeholder="longitude"
77            pattern="^-?\d+(\.\d+)?$"
78            bind:value={lon} />
79   </div>
80   <div class="col-auto">
81     <label for="reverse-zoom">max zoom</label>
82   </div>
83   <div class="col-auto">
84     <select id="reverse-zoom" name="zoom" class="form-select form-select-sm" bind:value={zoom}>
85       <option value="">---</option>
86       {#each zoomLevels() as zoomTitle, i}
87         <option value="{i}">{i} - {zoomTitle}</option>
88       {/each}
89     </select>
90   </div>
91   <input type="hidden"
92          name="layer" value="{api_request_params.layer || ''}" />
93   <div class="col-auto">
94     <button type="submit" class="btn btn-primary btn-sm mx-1">Search</button>
95   </div>
96 </UrlSubmitForm>
97
98 <!-- Additional options -->
99 <details id="searchAdvancedOptions" class="mt-2">
100   <summary><small>Advanced options</small></summary>
101   <ul>
102     <li>
103       <label for="option_layer">Layer</label>
104       <input id="option_layer" name="layer" placeholder="e.g. address,poi,railway,natural,manmade"
105         value="{api_request_params.layer || ''}"
106         data-api-param="layer" on:change={set_api_param}
107         class="form-control form-control-sm d-inline w-auto api-param-setting">
108     </li>
109   </ul>
110 </details>
111
112 <style>
113   label {
114     font-size: 0.9rem;
115     margin-top: 0.3rem;
116   }
117
118   #switch-coords {
119     font-size: 0.6rem;
120     font-weight: bold;
121     cursor: pointer;
122     padding: 2px;
123     margin: 5px;
124   }
125
126   #searchAdvancedOptions ul {
127     list-style-type: none;
128     padding: 0;
129     font-size: 0.85rem;
130   }
131
132   #searchAdvancedOptions li {
133     display: inline-block;
134     padding: 4px 10px;
135     border-radius: 5px;
136     border: 1px dotted #ccc;
137     margin-right: 1em;
138   }
139
140   #searchAdvancedOptions label {
141     margin-right: 0.5em;
142   }
143
144   @media (max-width: 850px) {
145     #reverse-lon, #reverse-lat, #reverse-zoom {
146       width: 8em;
147     }
148   }
149 </style>