|
116 | 116 | </noscript> |
117 | 117 | </head> |
118 | 118 | <body> |
119 | | - |
| 119 | + <!-- this map defines > 1 searchable layer each with different results format, |
| 120 | + so it requires a custom search handler (see below) to render the results --> |
120 | 121 | <mapml-viewer lang="en" projection="CBMTILE" controls controlslist="geolocation search" zoom="16" lat="45.406314" lon="-75.6883335"> |
121 | 122 | <map-layer label="Canada Base Map - Transportation" checked> |
122 | 123 | <map-link rel="suggestions" tref="https://geogratis.gc.ca/services/geoname/en/geonames.json?q={searchTerms}*&num=20"></map-link> |
|
155 | 156 | <map-link rel="search" tref="https://photon.komoot.io/api?q={searchTerms}"></map-link> |
156 | 157 | </map-layer> |
157 | 158 | </mapml-viewer> |
| 159 | + <!-- this map uses the default search handler (supports GeoJSON search results only) --> |
158 | 160 | <map lang="fr" is="web-map" projection="OSMTILE" zoom="14" lat="45.406314" lon="-75.6883335" controls controlslist="geolocation search"> |
159 | 161 | <map-layer data-testid="osm-layer" label="OpenStreetMap" checked > |
160 | 162 |
|
|
195 | 197 | document.addEventListener('DOMContentLoaded', () => { |
196 | 198 | const viewer = document.querySelector('mapml-viewer'); |
197 | 199 |
|
198 | | - function renderResults(container, responses, map) { |
199 | | - container.innerHTML = ''; |
| 200 | + function toItems(responses, includeValue) { |
| 201 | + const items = []; |
200 | 202 | for (const r of responses) { |
201 | 203 | const data = r.data; |
202 | 204 | if (!data) continue; |
203 | 205 | // geogratis format (items array) |
204 | 206 | if (data.items) { |
205 | 207 | for (const item of data.items) { |
206 | | - const btn = document.createElement('button'); |
207 | | - btn.className = 'mapml-search-result'; |
208 | | - btn.setAttribute('type', 'button'); |
209 | | - btn.textContent = item.name |
210 | | - + (item.concise ? ' (' + item.concise.code + ')' : '') |
211 | | - + (item.province ? ', ' + item.province.code : ''); |
212 | | - btn.addEventListener('click', () => { |
213 | | - if (item.bbox && item.bbox.length === 4) { |
214 | | - const [west, south, east, north] = item.bbox; |
215 | | - map.fitBounds([[south, west], [north, east]]); |
216 | | - } else { |
217 | | - map.setView([item.latitude, item.longitude], 10); |
218 | | - } |
219 | | - map._container |
220 | | - .querySelector('.mapml-search-panel') |
221 | | - .classList.remove('mapml-search-panel-open'); |
222 | | - }); |
223 | | - container.appendChild(btn); |
| 208 | + const entry = { |
| 209 | + text: item.name |
| 210 | + + (item.concise ? ' (' + item.concise.code + ')' : '') |
| 211 | + + (item.province ? ', ' + item.province.code : ''), |
| 212 | + lat: item.latitude, |
| 213 | + lng: item.longitude, |
| 214 | + bbox: item.bbox || undefined |
| 215 | + }; |
| 216 | + if (includeValue) entry.value = item.name; |
| 217 | + items.push(entry); |
224 | 218 | } |
225 | 219 | } |
226 | 220 | // GeoJSON format (Photon etc.) |
|
231 | 225 | for (const key of ['city', 'county', 'state', 'country']) { |
232 | 226 | if (props[key] && props[key] !== props.name) parts.push(props[key]); |
233 | 227 | } |
234 | | - const btn = document.createElement('button'); |
235 | | - btn.className = 'mapml-search-result'; |
236 | | - btn.setAttribute('type', 'button'); |
237 | | - btn.textContent = parts.filter(Boolean).join(', ') || 'Unnamed'; |
238 | | - btn.addEventListener('click', () => { |
239 | | - const bbox = feature.bbox |
240 | | - || (props.extent && props.extent.length === 4 ? props.extent : null); |
241 | | - if (bbox && bbox.length === 4) { |
242 | | - const [west, south, east, north] = bbox; |
243 | | - map.fitBounds([[south, west], [north, east]]); |
244 | | - } else if (feature.geometry && feature.geometry.coordinates) { |
245 | | - const [lon, lat] = feature.geometry.coordinates; |
246 | | - map.setView([lat, lon], props.zoom || 14); |
247 | | - } |
248 | | - map._container |
249 | | - .querySelector('.mapml-search-panel') |
250 | | - .classList.remove('mapml-search-panel-open'); |
251 | | - }); |
252 | | - container.appendChild(btn); |
| 228 | + const coords = feature.geometry?.coordinates || []; |
| 229 | + const bbox = feature.bbox |
| 230 | + || (props.extent?.length === 4 ? props.extent : undefined); |
| 231 | + const entry = { |
| 232 | + text: parts.filter(Boolean).join(', ') || 'Unnamed', |
| 233 | + lat: coords[1], |
| 234 | + lng: coords[0], |
| 235 | + bbox: bbox || undefined |
| 236 | + }; |
| 237 | + if (includeValue) entry.value = props.name || entry.text; |
| 238 | + items.push(entry); |
253 | 239 | } |
254 | 240 | } |
255 | 241 | } |
| 242 | + return items; |
256 | 243 | } |
257 | 244 |
|
258 | 245 | viewer.addEventListener('mapsuggestions', (e) => { |
259 | 246 | e.preventDefault(); |
260 | | - const container = viewer._map._container.querySelector('.mapml-search-results'); |
261 | | - renderResults(container, e.detail.responses, viewer._map); |
| 247 | + e.detail.setResults(toItems(e.detail.responses, true)); |
262 | 248 | }); |
263 | 249 |
|
264 | 250 | viewer.addEventListener('mapsearch', (e) => { |
265 | 251 | e.preventDefault(); |
266 | | - const container = viewer._map._container.querySelector('.mapml-search-results'); |
267 | | - renderResults(container, e.detail.responses, viewer._map); |
| 252 | + e.detail.setResults(toItems(e.detail.responses, false)); |
268 | 253 | }); |
269 | 254 |
|
270 | | - // --- geonames.org custom handler for the <map is="web-map"> element --- |
271 | | - // const webMap = document.querySelector('map[is=web-map]'); |
272 | | - |
273 | | - // function renderGeonamesOrgResults(container, geonames, map) { |
274 | | - // container.innerHTML = ''; |
275 | | - // for (const item of geonames) { |
276 | | - // const btn = document.createElement('button'); |
277 | | - // btn.className = 'mapml-search-result'; |
278 | | - // btn.setAttribute('type', 'button'); |
279 | | - // btn.textContent = item.name |
280 | | - // + (item.adminName1 ? ', ' + item.adminName1 : '') |
281 | | - // + (item.countryName ? ', ' + item.countryName : ''); |
282 | | - // btn.addEventListener('click', () => { |
283 | | - // if (item.bbox) { |
284 | | - // map.fitBounds([ |
285 | | - // [item.bbox.south, item.bbox.west], |
286 | | - // [item.bbox.north, item.bbox.east] |
287 | | - // ]); |
288 | | - // } else { |
289 | | - // map.setView([parseFloat(item.lat), parseFloat(item.lng)], 10); |
290 | | - // } |
291 | | - // map._container |
292 | | - // .querySelector('.mapml-search-panel') |
293 | | - // .classList.remove('mapml-search-panel-open'); |
294 | | - // }); |
295 | | - // container.appendChild(btn); |
296 | | - // } |
297 | | - // } |
298 | | - |
299 | | - // webMap.addEventListener('mapsuggestions', (e) => { |
300 | | - // e.preventDefault(); |
301 | | - // const container = webMap._map._container.querySelector('.mapml-search-results'); |
302 | | - // const allGeonames = e.detail.responses.flatMap(r => (r.data && r.data.geonames) || []); |
303 | | - // renderGeonamesOrgResults(container, allGeonames, webMap._map); |
304 | | - // }); |
305 | | - |
306 | | - // webMap.addEventListener('mapsearch', (e) => { |
307 | | - // e.preventDefault(); |
308 | | - // const container = webMap._map._container.querySelector('.mapml-search-results'); |
309 | | - // const allGeonames = e.detail.responses.flatMap(r => (r.data && r.data.geonames) || []); |
310 | | - // renderGeonamesOrgResults(container, allGeonames, webMap._map); |
311 | | - // }); |
312 | 255 | }); |
313 | 256 | </script> |
314 | 257 | </body> |
|
0 commit comments