diff --git a/app.js b/app.js index 55221f0..0f1bede 100644 --- a/app.js +++ b/app.js @@ -36,6 +36,31 @@ const symbols = { regional: 'πŸš†', express: 'πŸš„', longDistance: 'πŸš…', ferry: 'πŸ›₯️' }; +// ============================= +// Aktive Filter +// ============================= +let activeProducts = Array.from(document.querySelectorAll('#controls input[type="checkbox"]')) + .filter(c => c.checked) + .map(c => c.value); + +// Checkbox Event +document.querySelectorAll('#controls input[type="checkbox"]').forEach(cb => { + cb.addEventListener('change', () => { + activeProducts = Array.from(document.querySelectorAll('#controls input[type="checkbox"]')) + .filter(c => c.checked) + .map(c => c.value); + + Object.values(vehicleMarkers).forEach(marker => { + const prod = marker.options.vehicleProduct || ''; + if (activeProducts.includes(prod)) { + if (!map.hasLayer(marker)) map.addLayer(marker); + } else { + if (map.hasLayer(marker)) map.removeLayer(marker); + } + }); + }); +}); + // ============================= // Hilfsfunktionen // ============================= @@ -53,7 +78,7 @@ function getLineColor(lineName, product) { } function createDivIcon(vehicle) { - const product = vehicle.line?.product; + const product = vehicle.line?.product || ''; const lineName = vehicle.line?.name || '?'; const symbol = symbols[product] || '❓'; @@ -79,7 +104,9 @@ function createDivIcon(vehicle) { `; - return L.divIcon({ html: iconHtml, className: '', iconSize: [30, 40], iconAnchor: [15, 20] }); + const icon = L.divIcon({ html: iconHtml, className: '', iconSize: [30, 40], iconAnchor: [15, 20] }); + icon.product = product; + return icon; } const lineColor = getLineColor(lineName, product); @@ -92,7 +119,9 @@ function createDivIcon(vehicle) { `; - return L.divIcon({ html: iconHtml, className: '', iconSize: [30, 40], iconAnchor: [15, 20] }); + const icon = L.divIcon({ html: iconHtml, className: '', iconSize: [30, 40], iconAnchor: [15, 20] }); + icon.product = product; + return icon; } // ============================= @@ -120,16 +149,18 @@ async function loadVehicles() { if (vehicleMarkers[id]) { vehicleMarkers[id].setLatLng([loc.latitude, loc.longitude]); } else { - const marker = L.marker([loc.latitude, loc.longitude], { icon }) - .bindPopup(`Linie: ${vehicle.line?.name || 'unbekannt'}
Typ: ${vehicle.line?.product || 'unbekannt'}
Richtung: ${vehicle.direction || 'unbekannt'}`) - .addTo(vehiclesLayer); + const marker = L.marker([loc.latitude, loc.longitude], { icon }); + marker.options.vehicleProduct = vehicle.line?.product || ''; + if (activeProducts.includes(marker.options.vehicleProduct)) { + marker.addTo(map); + } vehicleMarkers[id] = marker; } }); Object.keys(vehicleMarkers).forEach(id => { if (!newIds.has(id)) { - vehiclesLayer.removeLayer(vehicleMarkers[id]); + if (map.hasLayer(vehicleMarkers[id])) map.removeLayer(vehicleMarkers[id]); delete vehicleMarkers[id]; } }); @@ -157,69 +188,3 @@ function locateAndLoad() { locateAndLoad(); setInterval(loadVehicles, 30000); map.on('moveend', loadVehicles); - -// ============================= -// BahnhΓΆfe mit Live-Abfahrten -// ============================= -const stations = [ - { name: "Berlin Zoologischer Garten", id: "900023201", coords: [52.5069, 13.3326] }, - { name: "Berlin Alexanderplatz", id: "900100003", coords: [52.5215, 13.4115] }, - { name: "Berlin Gesundbrunnen", id: "900007102", coords: [52.5483, 13.3889] }, - { name: "Berlin Spandau", id: "900029101", coords: [52.5341, 13.1977] }, - { name: "Berlin SΓΌdkreuz", id: "900058101", coords: [52.4752, 13.3653] }, - { name: "Berlin Ostbahnhof", id: "900100004", coords: [52.5100, 13.4340] } -]; - -async function loadStationDepartures(stationId, marker, stationName) { - const symbols = { - bus: '🚌', tram: '🚎', subway: 'πŸš‰', suburban: 'πŸš‹', - regional: 'πŸš†', express: 'πŸš„', longDistance: 'πŸš…', ferry: 'πŸ›₯️' - }; - - try { - const res = await fetch(`https://v6.vbb.transport.rest/stops/${stationId}/departures?duration=30&results=10`); - if (!res.ok) throw new Error(`HTTP ${res.status}`); - const data = await res.json(); - const departures = data.departures || []; - - let html = `${stationName}
`; - html += ``; - html += ``; - - departures.forEach((dep, index) => { - const line = dep.line?.name || "?"; - const product = dep.line?.product; - const icon = symbols[product] || '❓'; - const direction = dep.direction || "?"; - const when = dep.when ? new Date(dep.when) : null; - const planned = dep.plannedWhen ? new Date(dep.plannedWhen) : null; - const delay = when && planned ? Math.round((when - planned) / 60000) : 0; - const timeStr = when ? when.toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit" }) : "n/a"; - const delayStr = delay > 0 ? `+${delay} min` : ""; - - const color = getLineColor(line, product); - const bg = index % 2 === 0 ? '#f9f9f9' : '#fff'; - - html += ` - - - - `; - }); - - html += `
LinieRichtungZeit
${icon} ${line}${direction}${timeStr} ${delayStr}
`; - marker.setPopupContent(html).openPopup(); - } catch (err) { - marker.setPopupContent(`${stationName}
Fehler beim Laden`); - console.error(err); - } -} - - -stations.forEach(station => { - const marker = L.marker(station.coords) - .addTo(map) - .bindPopup(`${station.name}
Lade Abfahrten...`); - - marker.on('click', () => loadStationDepartures(station.id, marker, station.name)); -});