Zum Inhalt springen
Search Box mit Vorschlägen

Search Box mit Vorschlägen

Die Search Box arbeitet in zwei Schritten: suggest liefert Vorschläge beim Tippen, retrieve die Position des gewählten. Für beide Aufrufe dasselbe session_token verwenden, für die nächste Suche ein neues. Der Typfilter begrenzt die Vorschläge.

    Code

    // Search Box: suggestions while typing (suggest), position and details after the click (retrieve). One session token per search.
    const TOKEN = 'YOUR_TOKEN'; // your public token (mx_pk_…) from https://account.mapx.at
    // Adds the token to every request MapLibre makes to mapx.at (style, tiles, fonts, sprites), never to other hosts.
    const transformRequest = (url) => ({ url: /^https:\/\/([\w-]+\.)?mapx\.at\//.test(url) ? url + (url.includes('?') ? '&' : '?') + 'access_token=' + TOKEN : url });
    const AUTH = { headers: { Authorization: 'Bearer ' + TOKEN } };
    
    maplibregl.addProtocol('pmtiles', new pmtiles.Protocol().tile);
    
    const map = new maplibregl.Map({ transformRequest, container: 'map', style: 'https://api.mapx.at/v1/styles/streets', center: [14.3, 47.6], zoom: 7 });
    map.addControl(new maplibregl.NavigationControl());
    const input = document.getElementById('q'), types = document.getElementById('types'), list = document.getElementById('treffer');
    let marker, token = crypto.randomUUID();
    
    input.addEventListener('input', async () => {
      list.replaceChildren();
      if (input.value.trim().length < 2) return;
      const c = map.getCenter();
      const url = `https://api.mapx.at/v1/searchbox/suggest?q=${encodeURIComponent(input.value)}&session_token=${token}&proximity=${c.lng},${c.lat}&limit=6` + (types.value ? `&types=${types.value}` : '');
      try {
        const res = await fetch(url, AUTH);
        if (!res.ok) throw new Error('HTTP ' + res.status);
        for (const s of (await res.json()).suggestions) {
          const li = document.createElement('li'), b = document.createElement('button');
          b.type = 'button'; b.textContent = `${s.name} (${s.feature_type}) ${s.place_formatted ?? ''}`;
          b.addEventListener('click', () => pick(s.mapbox_id));
          li.append(b); list.append(li);
        }
      } catch (e) { list.textContent = 'Error: ' + e.message; }
    });
    
    async function pick(id) {
      const res = await fetch(`https://api.mapx.at/v1/searchbox/retrieve/${encodeURIComponent(id)}?session_token=${token}`, AUTH);
      const f = (await res.json()).features[0];
      marker?.remove();
      marker = new maplibregl.Marker().setLngLat(f.geometry.coordinates).addTo(map);
      map.flyTo({ center: f.geometry.coordinates, zoom: f.properties.zoom ?? 15 });
      list.replaceChildren();
      token = crypto.randomUUID(); // the session ends with retrieve
    }

    Vollständige HTML-Datei

    Speichern und im Browser öffnen. Es braucht nur MapLibre GL JS 4.7.1 und pmtiles 3.2.1 per CDN, dazu den öffentlichen Token (YOUR_TOKEN ersetzen), keinen Build.

    <!doctype html>
    <html lang="de">
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>mapx Beispiel</title>
    <link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css">
    <script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
    <script src="https://unpkg.com/pmtiles@3.2.1/dist/pmtiles.js"></script>
    <style>html,body{margin:0;font:14px system-ui,sans-serif}#map{height:70vh}</style>
    </head>
    <body>
    <input id="q" type="search" placeholder="Ort, Adresse, Haltestelle oder Gipfel" autocomplete="off" aria-label="Suche"><select id="types" aria-label="Typ"><option value="">Alle Typen</option><option value="address">Adressen</option><option value="street">Straßen</option><option value="place">Orte</option><option value="poi">Points of Interest</option></select><ul id="treffer"></ul>
    <div id="map"></div>
    <script>
    // Search Box: suggestions while typing (suggest), position and details after the click (retrieve). One session token per search.
    const TOKEN = 'YOUR_TOKEN'; // your public token (mx_pk_…) from https://account.mapx.at
    // Adds the token to every request MapLibre makes to mapx.at (style, tiles, fonts, sprites), never to other hosts.
    const transformRequest = (url) => ({ url: /^https:\/\/([\w-]+\.)?mapx\.at\//.test(url) ? url + (url.includes('?') ? '&' : '?') + 'access_token=' + TOKEN : url });
    const AUTH = { headers: { Authorization: 'Bearer ' + TOKEN } };
    
    maplibregl.addProtocol('pmtiles', new pmtiles.Protocol().tile);
    
    const map = new maplibregl.Map({ transformRequest, container: 'map', style: 'https://api.mapx.at/v1/styles/streets', center: [14.3, 47.6], zoom: 7 });
    map.addControl(new maplibregl.NavigationControl());
    const input = document.getElementById('q'), types = document.getElementById('types'), list = document.getElementById('treffer');
    let marker, token = crypto.randomUUID();
    
    input.addEventListener('input', async () => {
      list.replaceChildren();
      if (input.value.trim().length < 2) return;
      const c = map.getCenter();
      const url = `https://api.mapx.at/v1/searchbox/suggest?q=${encodeURIComponent(input.value)}&session_token=${token}&proximity=${c.lng},${c.lat}&limit=6` + (types.value ? `&types=${types.value}` : '');
      try {
        const res = await fetch(url, AUTH);
        if (!res.ok) throw new Error('HTTP ' + res.status);
        for (const s of (await res.json()).suggestions) {
          const li = document.createElement('li'), b = document.createElement('button');
          b.type = 'button'; b.textContent = `${s.name} (${s.feature_type}) ${s.place_formatted ?? ''}`;
          b.addEventListener('click', () => pick(s.mapbox_id));
          li.append(b); list.append(li);
        }
      } catch (e) { list.textContent = 'Error: ' + e.message; }
    });
    
    async function pick(id) {
      const res = await fetch(`https://api.mapx.at/v1/searchbox/retrieve/${encodeURIComponent(id)}?session_token=${token}`, AUTH);
      const f = (await res.json()).features[0];
      marker?.remove();
      marker = new maplibregl.Marker().setLngLat(f.geometry.coordinates).addTo(map);
      map.flyTo({ center: f.geometry.coordinates, zoom: f.properties.zoom ?? 15 });
      list.replaceChildren();
      token = crypto.randomUUID(); // the session ends with retrieve
    }
    </script>
    </body>
    </html>

    Verwendete APIs

    • Search Box GET api.mapx.at/v1/searchbox/suggest
    • Search Box GET api.mapx.at/v1/searchbox/retrieve/{id}