Zum Inhalt

Autocomplete mit Filter

Dieses Beispiel zeigt, wie Sie Autocomplete-Ergebnisse mithilfe des Parameters filterOptions.includedGeoEntities auf bestimmte Geo-Entitätstypen beschränken können. Hier werden die Ergebnisse auf Städte beschränkt (CITY und CITY_WITH_ZIP).

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Autocomplete API – City Filter</title>
</head>
<body>
    <label>Search for cities only (filtered by <code>CITY</code> and <code>CITY_WITH_ZIP</code>)</label>
    <div class="search-wrapper">
        <input id="query" type="search" placeholder="Enter a city name..." autocomplete="off">
        <ul id="results"></ul>
    </div>
    <div id="selected" style="display:none">
        <strong>Selected city</strong>
        <div id="selected-content"></div>
    </div>

    <script>
        const apiKey = "[INSERT API-KEY]";

        const TOKEN_URL = `https://www.yellowmap.de/api_rst/api/autocompleteToken?apiKey=${(apiKey === decodeURIComponent(apiKey) ? encodeURIComponent(apiKey) : apiKey)}`;
        const AUTOCOMPLETE_URL = "https://autocomplete.smartmaps.cloud/api/v5/Autocomplete";

        let token = null;
        let tokenExpiry = 0;

        async function getToken() {
            if (token && Date.now() < tokenExpiry) return token;
            const response = await fetch(TOKEN_URL);
            token = await response.json();
            tokenExpiry = Date.now() + 9 * 60 * 1000;
            return token;
        }

        async function searchCities(query) {
            const authToken = await getToken();
            const response = await fetch(AUTOCOMPLETE_URL, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": `Bearer ${authToken}`
                },
                body: JSON.stringify({
                    query,
                    geoJson: true,
                    top: 7,
                    filterOptions: {
                        includedGeoEntities: ["CITY", "CITY_WITH_ZIP"]
                    }
                })
            });
            return response.json();
        }

        const input = document.getElementById("query");
        const resultsList = document.getElementById("results");
        const selectedDiv = document.getElementById("selected");
        const selectedContent = document.getElementById("selected-content");

        let debounceTimer;

        input.addEventListener("input", () => {
            clearTimeout(debounceTimer);
            const value = input.value.trim();
            if (value.length < 2) {
                resultsList.innerHTML = "";
                return;
            }
            debounceTimer = setTimeout(async () => {
                const data = await searchCities(value);
                const features = data.features || [];
                resultsList.innerHTML = features.map((f, i) =>
                    `<li data-index="${i}">${f.properties.displayValue} (${f.properties.country || ""})</li>`
                ).join("");

                resultsList.querySelectorAll("li").forEach(li => {
                    li.addEventListener("click", () => {
                        const feature = features[li.dataset.index];
                        const props = feature.properties;
                        input.value = props.displayValue;
                        resultsList.innerHTML = "";
                        selectedContent.innerHTML = `
                            <div><b>City:</b> ${props.city || "—"}</div>
                            <div><b>State:</b> ${props.state || "—"}</div>
                            <div><b>Country:</b> ${props.countryLongName || "—"} (${props.country || "—"})</div>
                            <div><b>Coordinates:</b> ${feature.geometry.coordinates[1].toFixed(5)}, ${feature.geometry.coordinates[0].toFixed(5)}</div>
                        `;
                        selectedDiv.style.display = "block";
                    });
                });
            }, 300);
        });
    </script>
</body>
</html>