Popup mit Overpass befüllt, wie stelle ich die Inhalte anders dar?

Ich habe eine Map auf einer Webseite erstellt und bis jetzt funktioniert alles tadellos. Ich bin damit Anfänger, habe aber Erfahrung mit HTML, CSS und ein wenig JS.

Ich möchte allerdings die Inhalte in dem Popup, die mit Overpass befüllt werden, ändern und zwar erstmal lediglich die Texte und die Reihenfolge.

Es soll zum Beispiel nicht “addr:city”, sondern “City” angezeigt werden.

Idealerweise wäre es schön, wenn man noch die Reihenfolge dieser Tags ändern könnte.

Viele Grüße
Stefan

PS: So sieht es momentan aus:

Dazu veränderst Du den JavaScript-Code, den Du verwendest, um das Popup zu befüllen, so dass

  • bei den “Schlüsseln” eine entsprechende Ersetzung vorgenommen wird
  • die Reihenfolge der Einträge Deinen Wünschen entspricht

Zu den konkreten Änderungen kann ich Dir mangels Hellseherkugel nichts sagen, aber bei den Ersetzungen könnte in folgende Richtung gehen:

// Annahme: Schlüssel steht in key
var ausgabe;
switch (key) {
    case "addr:city":
        ausgabe="City";
        break;
    case "addr:street":
        ausgabe="Straße";
        break;
    // und die weiteren von Dir gewünschten Ersetzungen
    default:
        ausgabe=key;
}

… und in den Inhalt des Popups statt der Variablen key die Variable ausgabe schreiben. Die Sortierung Deinen Wünschen anzupassen, könnte aufwendiger ausfallen.

Vielen Dank für deine schnelle Antwort.

Ich benutze lediglich folgenden Code um die Daten zu importieren, einen key habe ich nicht gefunden.

var opl = new L.OverPassLayer({
debug: true,
endPoint: ‘https://lz4.overpass-api.de/api/’,
query: ‘node({{bbox}})[“cuisine”=“italian”];out;’,

Wenn ich annehmen darf, dass Du den leaflet-overpass-layer von GuillaumeAmat nutzt, leaflet-overpass-layer/demo at develop · GuillaumeAmat/leaflet-overpass-layer · GitHub,
dann solltest Du den Code in onSuccess: function (data) nach Deinen Wünschen aufbohren, siehe leaflet-overpass-layer/demo/example-with-leaflet-markercluster.html at develop · GuillaumeAmat/leaflet-overpass-layer · GitHub

            onSuccess: function (data) {
                var markerClusterGroup = L.markerClusterGroup();

                data.elements.forEach(function (overpassResult) {
                    markerClusterGroup.addLayer(L.marker([ overpassResult.lat, overpassResult.lon ]));
                });

                map.addLayer(markerClusterGroup);
            },

Am besten zunächst einfach alle Inhalte von data.elements ausgeben lassen, z.B. in der Entwicklerkonsole, damit Du die von Dir gewünschten Modifikationen vornehmen kannst.

Wenn man’s speziell haben will, dann darf man viel von Hand zu Fuß machen:

onSuccess: function (data) {
	// Debug-Ausgabe um den Inhalt von data zu analysieren
	// Es gibt ein elements-Array, das die interessanten Daten enthält
	console.info(data);
	
	for (i=0; i < data.elements.length; i++) {
		// Debug-Ausgabe für ein Element
		e = data.elements[i];
		// Die gesuchten Informationen stehen in e.tags,
		// die Position und die id des Elements direkt in e.lat, e.lon und e.id
		console.info(e.tags);
		var pos = new L.LatLng(e.lat, e.lon);
		var popupContent = "<p>ID=" + e.id + "</p>";
		popupContent += "<dl>";
		Object.entries(e.tags).forEach(([key, value]) => {
			// Hier gilt es einzugreifen, statt key den gewünschten Wert auszugeben
			// und nach eigenen Vorstellungen zu sortieren.
			var ausgabe = "";
			switch(key) {
				case "addr:city":
					ausgabe = "City";
					break;
				case "addr:street":
					ausgabe = "Straße";
					break;
				default:
					ausgabe = key;
			}
			popupContent += "<dt>" + ausgabe + ":</dt><dd>" + value + "</dd>";
		});
		popupContent += "</dl>";
		var popup = L.popup()
			.setContent(popupContent);
		L.marker(pos).bindPopup(popup).addTo(map);
	}
},

wäre ein Ansatz für die Ersetzungen, siehe meine Demo: Leaflet OverPass Layer demo page

Vielen Dank!
Ja, ich benutze den leaflet-overpass-layer.
Hat auf Anhieb geklappt, prima.
Allerdings verschwindet jetzt der individuelle Marker, den habe ich so eingebunden:

var pizzaIcon = L.icon({
iconUrl: ‘m.svg’,
iconSize: [36, 47],
iconAnchor: [18, 47],
popupAnchor: [0, -48]
});


query: ‘node({{bbox}})[“cuisine”=“italian”];out;’,
markerIcon: pizzaIcon,

Den Marker konnte ich jetzt hinzufügen.

L.marker((pos), {icon: pizzaIcon}).bindPopup(popup).addTo(map);

Ergänze vor der for-Schleife den Code zum Erzeugen des Icons.
Bitte beachte, dass Du dazu “new” hinzufügen musst:


onSuccess: function (data) {

	var pizzaIcon = new L.Icon({
			iconUrl: m.svg',
			iconSize: [36, 47],
			iconAnchor: [18, 47],
			popupAnchor: [0, -48]
	});
	
    for (i=0; i < data.elements.length; i++) {
        // gleicher Code

        // Erzeuge Marker mit Deinem Icon, zweiter Parameter hinter der Position
        L.marker(pos, {icon: pizzaIcon}).bindPopup(popup).addTo(map);
    }

Siehe dazu Documentation - Leaflet - a JavaScript library for interactive maps

PS: Ich habe meine Demo entsprechend aktualisiert.
Edit: Ich war zu langsam.

Klasse!
Jetzt sieht es aus wie ich mir das vorgestellt habe.

Jetzt fehlt nur noch die richtige Reihenfolge und dann wäre es perfekt.

Folgende Idee, die beides kombiniert:

Du führst eine Sortier- und Umbenennungsliste.
Zuerst werden alle Tags dieser Liste ausgegeben (und gegebenenfalls umbenannt).
Alle Tags, die umbenannt werden, sind in dieser Liste enthalten.
Anschließend werden die Tags ausgegeben, die in dieser Liste nicht enthalten sind.

Die for-Schleife, die den Inhalt des Popups erzeugt, wäre wie folgt zu ändern.

	for (i=0; i < data.elements.length; i++) {
		var e = data.elements[i];
		// Sortier- und Ersetzungsliste
        // Wird ein Tag nicht ersetzt, aber sortiert, dann sind beide Einträge gleich :-)
		var myreplacements = {
			"name" : "Name",
			"addr:city" : "City",
			"addr:street" : "Straße"
		};

		var pos = new L.LatLng(e.lat, e.lon);
		
		var popupContent = "<p>ID=" + e.id + "</p>";
		popupContent += "<dl>";

		// Füge die vorhandenen Einträge gemäß definierter Ordnung ein
		Object.entries(myreplacements).forEach(([mykey, replacement]) => {
			// Ausgabe nur, wenn der Tag auch vorhanden ist.
			// Dann mit der Ersetzung
			if (mykey in e.tags) {
				popupContent += "<dt>" + replacement + ":</dt><dd>" + e.tags[mykey] + "</dd>";			
			}
		});

		// Füge die restlichen Schlüssel in der vorhandenen Reihenfolge ein
		// Achte darauf, die Einträge auszulassen, die bereits gemäß
		// Sortierreihenfolge ausgegeben wurden.
		Object.entries(e.tags).forEach(([key, value]) => {
			// Diesmal müssen wir in myreplacements nachschauen
			// Ausgabe nur, wenn dort nicht vorhanden, da bereits oben ausgegeben.
			if (!(key in myreplacements)) {
				popupContent += "<dt>" + key + ":</dt><dd>" + value + "</dd>";
			}
		});
		popupContent += "</dl>";
		var popup = L.popup()
			.setContent(popupContent);
		L.marker(pos, {icon: pizzaIcon}).bindPopup(popup).addTo(map);
	}

Demoseite ist entsprechend aktualisiert.

Hat prima geklappt.

Ich frage mich jetzt allerdings ob ich die keys vollständig angegeben habe…gibt es da woanders eine Übersicht?

Folgende keys habe ich bis jetzt gefunden:

// Name:
“name”: “Name”,
“alt_name”: “Alternative name”,
“brand”: “Brand”,
“brand:wikidata”: “Wikidata”,
“brand:wikipedia”: “Wikipedia”,
“old_name”: “Old Name”,
“name:de”: “German name”,
“name:en”: “English name”,

// Adresse:
“addr:city”: “City”,
“addr:suburb”: “Suburb”,
“addr:postcode”: “Zip code”,
“addr:street”: “Street”,
“addr:housenumber”: “House number”,
“addr:country”: “Country”,

// Öffnungszeiten:
“opening_hours”: “Opening hours”,
“opening_hours:kitchen”: “Kitchen opening hours”,
“check_date:opening_hours”: “Check date opening hours”,
“opening_hours:signed”: “Opening hours signed”,

// Kontaktmöglichkeiten:
“phone”: “Phone”,
“contact:phone”: “Phone”,
“mobile”: “Mobile”,
“fax”: “Fax”,
“contact:email”: “Contact Email”,
“email”: “Email”,
“website”: “Website”,
“contact:website”: “Contact website”,
“contact:facebook”: “Contact Facebook”,

// Menü:
“website:menu”: “Menu website”,
“lunch”: “Lunch menus”,

// Rollstuhlfahrer:
“wheelchair”: “Suitable for wheelchair users”,
“wheelchair:description”: “Note for wheelchair users”,
“toilets:wheelchair”: “Toilets accessible for wheelchair users”,

// Angebot:
“cuisine”: “Type of cuisine”,
“amenity”: “Amenity”,

// Art der Speisen:
“organic”: “Organic dishes”,
“diet”: “Diet”,
“diet:vegetarian”: “Vegetarian”,
“diet:vegan”: “Vegan”,
“diet:diabetes”: “diet:diabetes”,
“diet:halal”: “Halal”,
“diet:kosher”: “Kosher”,
“diet:gluten_free”: “Gluten free”,
"diet:lactose_free ": “Lactose free”,
“diet:sugar_free”: “Sugar free”,
“fair_trade”: “Fair trade”,

// Art der Getränke:
“microbrewery”: “Brewery”,
“brewery”: “Beer types”,
“winery”: “Types of wine”,
“distillery”: “Types of spirits”,
“cocktails”: “Cocktails”,

// Bezahlung:
“currency:EUR”: “Currency in Euro”,
“currency:others”: “Other currencies”,
“payment:Methode”: “Payment options”,
“description:payment”: “Note Payment”,
“payment:cash”: “Cash”,
“payment:cards”: “Card payment”,
“payment:credit_cards”: “Credit cards”,
“payment:debit_cards”: “Debit cards”,
“payment:contactless”: “Contactless payment”,
“payment:american_express”: “American express”,
“payment:girocard”: “Girocard”,
“payment:mastercard”: “Mastercard”,
“payment:visa”: “Visa”,
“payment:diners_club”: “Diners club”,
“payment:visa_debit”: “Visa debit”,
“payment:maestro”: “Maestro”,
“payment:qr_code”: “Payment with QR code”,

// Zusätzlicher Service:
“frontcooking”: “Frontcooking”,
“delivery”: “Delivery service”,
“takeaway”: “Food pickup”,
“drive_through”: “Drive through”,
“changing_table”: “Changing table”,
“kids_area”: “Kids area”,
“Internet_access”: “Internet”,
“internet_access”: “Internet”,
“internet_access:fee”: “Internet fee”,
“service:electricity”: “Sockets available”,
“socket”: “Socket”,

// Räumlichkeiten:
“indoor_seating”: “Indoor seating”,
“outdoor_seating”: “Outdoor dining”,
“capacity”: “Number of seats”,
“air_conditioning”: “Air conditioning”,
“bar”: “Bar”,
“smoking”: “Smoking allowed”,
“dog”: “Dogs allowed”,

// Zusätzliche Informationen:
“reservation”: “Reservation”,
“note”: “Note”,
“description”: “Description”,
“source”: “Source”,
“operator”: “Operator”,
“check_date”: “Check date”

Es gibt eine Übersicht (für amenity=restaurant), ja: amenity=restaurant | Tags | OpenStreetMap Taginfo

Zwei Anmerkungen:
Es gibt die Regel “Any tag you like” :slight_smile:
Und willst Du wirklich alles abdecken, wie die vielen Sprachen …

Am liebsten wäre es mir wenn ich einige wenige wichtige Tags aufführe wie zum Beispiel name oder street.

Theoretisch würde das ja gehen, denn das habe ich schon woanders so gesehen, aber wie kann man das in diesem script so gestalten, dass man nur wenige Tags anzeigen lässt.

Geplant ist erstmal alles auf englisch anzubieten.

Das ist ganz einfach:
Führe diese in der “Sortier- und Ersetzliste auf” und lasse die zweite Schleife einfach weg:

	for (i=0; i < data.elements.length; i++) {
		var e = data.elements[i];
		// Sortier- und Ersetzungsliste
        // Wird ein Tag nicht ersetzt, aber sortiert, dann sind beide Einträge gleich :-)
                // Nur die Tags aufführen, die Du anzeigen willst :-)
		var myreplacements = {
    "name": "Name",
    "alt_name": "Alternative name",
    "brand": "Brand",
    "brand:wikidata": "Wikidata"
    
    // Adresse:
    "addr:city": "City",
    "addr:suburb": "Suburb",
    "addr:postcode": "Zip code",
    "addr:street": "Street",
    "addr:housenumber": "House number",
    "addr:country": "Country"
  };

		var pos = new L.LatLng(e.lat, e.lon);
		
		var popupContent = "<p>ID=" + e.id + "</p>";
		popupContent += "<dl>";

		// Füge die vorhandenen Einträge gemäß definierter Ordnung ein
		Object.entries(myreplacements).forEach(([mykey, replacement]) => {
			// Ausgabe nur, wenn der Tag auch vorhanden ist.
			// Dann mit der Ersetzung
			if (mykey in e.tags) {
				popupContent += "<dt>" + replacement + ":</dt><dd>" + e.tags[mykey] + "</dd>";			
			}
		});

		popupContent += "</dl>";
		var popup = L.popup()
			.setContent(popupContent);
		L.marker(pos, {icon: pizzaIcon}).bindPopup(popup).addTo(map);
	}

Sehr cool.

Jetzt ist es so wie ich es ursprünglich haben wollte, mit den wichtigsten Angaben. (6 Punkte.)

Ich habe jetzt noch mit style=‘display:none’ einiges entfernt, ich denke man muss nicht unbedingt darauf hinweisen, dass eine Telefonnummer eine Telefonnummer ist usw.

Jetzt müsste nur noch die Hausnummer rechts neben die Straße gesetzt werden und die Telefonnummer und URL anklickbar sein.

Kann man die tags einzeln ansprechen?

(Dann hätte man sich das mit den Ersetzungen sparen können???)

Also reicht eine einfache Liste bestimmter Angaben aus, wobei unterschiedliche Tags unterschiedlich dargestellt werden sollen.

Wenn es - wie im Screenshot - nur wenige Angaben sind, würde ich mir keinen Stress machen, und Tag für Tag hinzufügen:

		var popupContent = "<p>ID=" + e.id + "</p>";
		popupContent += "<ul>";

		// Ausgabe nur der Werte in folgender Reihenfolge:
		// name
		if ("name" in e.tags) {
			popupContent += "<li>" + e.tags["name"] + "</li>";			
		}
		// Straße + Hausnummer
		var strasse = "";
		if ("addr:street" in e.tags) {
			strasse = e.tags["addr:street"];			
			// Hausnummer ohne Straßenname ist sinnfrei
			var hausnr = ""
			if ("addr:housenumber" in e.tags) {
				hausnr = e.tags["addr:housenumber"];
				strasse += " " + hausnr
			}
			popupContent += "<li>" + strasse + "</li>";			
		}
		
		// Postleitzahl + Ort wäre analog - wobei eine Postleitzahl ohne Ort nicht sinnvoll wäre ...
		
		// Öffnungszeiten
		if ("opening_hours" in e.tags) {
			popupContent += "<li>" + e.tags["opening_hours"] + "</li>";			
		}

		// Telefonnummer (anklickbar)
		if ("contact:phone" in e.tags) {
			popupContent += "<li><a href='" + e.tags["contact:phone"] + "'>" + e.tags["contact:phone"] + "</a></li>";			
		}

		// Webseite (anklickbar)
		if ("website" in e.tags) {
			popupContent += "<li><a href='" + e.tags["website"] + "'>" + e.tags["website"] + "</a></li>";			
		}

		// Ende der Liste
		popupContent += "</ul>";

		var popup = L.popup()
			.setContent(popupContent);
		L.marker(pos, {icon: pizzaIcon}).bindPopup(popup).addTo(map);
	}

Ich finde nichts mehr was man auszusetzen hätte. Alles perfekt. :slight_smile:

Den href für die Telefonnummer wird meines Wissens so angegeben, dann öffnet sich nach dem Klick direkt die Telefonapplikation.

href='tel: