]> git.openstreetmap.org Git - nominatim-ui.git/blob - src/components/ResultsList.svelte
Rebundle latest version
[nominatim-ui.git] / src / components / ResultsList.svelte
1 <script>
2   import { results_store } from '../lib/stores.js';
3   import { formatLabel } from '../lib/helpers.js';
4
5   import DetailsLink from './DetailsLink.svelte';
6   import Welcome from './Welcome.svelte';
7   import MapIcon from './MapIcon.svelte';
8
9   export let reverse_search = false;
10   export let current_result = null;
11
12   let aSearchResults;
13   let iHighlightNum;
14   let sMoreURL;
15
16   results_store.subscribe(data => {
17     if (!data) { return; }
18     aSearchResults = data;
19     iHighlightNum = 0;
20     current_result = aSearchResults[0];
21
22
23     let search_params = new URLSearchParams(window.location.search);
24
25     let aResults = data;
26     // lonvia wrote: https://github.com/osm-search/nominatim-ui/issues/24
27     // I would suggest to remove the guessing and always show the link. Nominatim only returns
28     // one or two results when it believes the result to be a good enough match.
29     // if (aResults.length >= 10) {
30     var aExcludePlaceIds = [];
31     if (search_params.has('exclude_place_ids')) {
32       aExcludePlaceIds = search_params.get('exclude_place_ids').split(',');
33     }
34     for (var i = 0; i < aResults.length; i += 1) {
35       aExcludePlaceIds.push(aResults[i].place_id);
36     }
37     var parsed_url = new URLSearchParams(window.location.search);
38     parsed_url.set('exclude_place_ids', aExcludePlaceIds.join(','));
39     sMoreURL = '?' + parsed_url.toString();
40   });
41
42   function handleClick(e) {
43     let result_el = e.target;
44     if (!result_el.className.match('result')) {
45       result_el = result_el.parentElement;
46     }
47     let pos = Number(result_el.dataset.position);
48
49     current_result = aSearchResults[pos];
50     iHighlightNum = pos;
51   }
52
53 </script>
54
55 {#if aSearchResults && aSearchResults.length > 0}
56   <div id="searchresults" role="list">
57
58     {#each aSearchResults as aResult, iResNum}
59       <!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
60       <div class="result"
61            class:highlight={iResNum === iHighlightNum}
62            role="listitem"
63            data-position="{iResNum}"
64            on:click|stopPropagation={handleClick}
65            on:keypress|stopPropagation={handleClick}>
66         <div style="float:right">
67           <MapIcon aPlace={aResult} />
68         </div>
69         <span class="name">{aResult.display_name}</span>
70         <span class="type">{formatLabel(aResult)}</span>
71         <p class="coords">{aResult.lat},{aResult.lon}</p>
72
73         <DetailsLink extra_classes="btn btn-outline-secondary btn-sm" feature={aResult}>
74           details
75         </DetailsLink>
76       </div>
77     {/each}
78
79     {#if sMoreURL && !reverse_search}
80       <div class="more">
81         <a class="btn btn-primary" href="{sMoreURL}">
82           Search for more results
83         </a>
84       </div>
85     {/if}
86   </div>
87 {:else if aSearchResults}
88   {#if reverse_search}
89     <div id="intro" class="sidebar">Search for coordinates or click anywhere on the map.</div>
90   {:else}
91     <div class="noresults">No search results found</div>
92   {/if}
93 {:else}
94   <Welcome/>
95 {/if}
96
97 <style>
98   .result {
99     font-size: 0.8em;
100     margin: 5px;
101     margin-top: 0;
102     padding: 4px 8px;
103     border-radius: 2px;
104     background: var(--bs-secondary-bg);
105     border: 1px solid var(--bs-secondary-color);
106     cursor: pointer;
107     min-height: 5em;
108   }
109
110   .result.highlight {
111     background-color: var(--bs-primary-bg-subtle);
112     border-color: var(--bs-primary-color-subtle);
113   }
114   .result.highlight :global(a) {
115     margin: 10px auto;
116     display: block;
117     max-width: 10em;
118     padding: 1px;
119     color: var(--bs-secondary-color);
120     background-color: var(--bs-secondary-bg);
121   }
122   .result .type {
123     color: var(--bs-secondary-color);
124     font-size: 0.8em;
125   }
126   .result :global(a) {
127     display: none;
128   }
129
130   .result .coords {
131     display: none;
132   }
133
134   .noresults{
135     text-align: center;
136     padding: 1em;
137   }
138
139   .more{
140     text-align:center;
141     margin-top: 1em;
142   }
143
144   .result.highlight :global(a):hover {
145     background-color: var(--bs-primary-bg-subtle);
146   }
147 </style>