147 lines
5.5 KiB
JavaScript
147 lines
5.5 KiB
JavaScript
/* Shared Leaflet helper: a small OSM route preview (origin/destination
|
|
markers + a straight line between them - we don't have real route
|
|
geometry, just stop coordinates, so this is a "as the crow flies" hint,
|
|
not a turn-by-turn path).
|
|
|
|
Exposes window.PbtMap.createRouteMap(containerId) and self-wires:
|
|
- the "Von"/"Nach" live preview on the trip form (#route-map)
|
|
- the map-pin buttons + dialog on the "Meine Fahrten" list
|
|
|
|
No-ops safely wherever these elements/Leaflet aren't present. */
|
|
(function () {
|
|
"use strict";
|
|
if (typeof window.L === "undefined") return;
|
|
|
|
var ORIGIN_COLOR = "#3fb950";
|
|
var DEST_COLOR = "#f85149";
|
|
var AUSTRIA_CENTER = [47.6, 14.0];
|
|
|
|
function dot(color) {
|
|
return L.divIcon({
|
|
className: "",
|
|
html: '<span style="display:block;width:14px;height:14px;border-radius:50%;' +
|
|
"background:" + color + ';border:2px solid #fff;box-shadow:0 1px 4px rgba(0,0,0,.5)"></span>',
|
|
iconSize: [14, 14],
|
|
iconAnchor: [7, 7],
|
|
});
|
|
}
|
|
|
|
function createRouteMap(containerId) {
|
|
var map = L.map(containerId).setView(AUSTRIA_CENTER, 7);
|
|
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
|
maxZoom: 19,
|
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>-Mitwirkende',
|
|
}).addTo(map);
|
|
|
|
var layers = [];
|
|
function clear() {
|
|
layers.forEach(function (l) { map.removeLayer(l); });
|
|
layers = [];
|
|
}
|
|
|
|
function render(origin, destination) {
|
|
clear();
|
|
var points = [];
|
|
if (origin) {
|
|
var o = L.marker([origin.lat, origin.lon], { icon: dot(ORIGIN_COLOR) }).addTo(map);
|
|
if (origin.label) o.bindTooltip(origin.label);
|
|
layers.push(o);
|
|
points.push([origin.lat, origin.lon]);
|
|
}
|
|
if (destination) {
|
|
var d = L.marker([destination.lat, destination.lon], { icon: dot(DEST_COLOR) }).addTo(map);
|
|
if (destination.label) d.bindTooltip(destination.label);
|
|
layers.push(d);
|
|
points.push([destination.lat, destination.lon]);
|
|
}
|
|
if (points.length === 2) {
|
|
layers.push(
|
|
L.polyline(points, { color: "#4a9eff", weight: 3, dashArray: "6 8", opacity: 0.85 }).addTo(map)
|
|
);
|
|
map.fitBounds(L.latLngBounds(points), { padding: [28, 28], maxZoom: 15 });
|
|
} else if (points.length === 1) {
|
|
map.setView(points[0], 14);
|
|
} else {
|
|
map.setView(AUSTRIA_CENTER, 7);
|
|
}
|
|
return points.length > 0;
|
|
}
|
|
|
|
return { map: map, render: render };
|
|
}
|
|
|
|
window.PbtMap = { createRouteMap: createRouteMap };
|
|
|
|
// --- live preview on the trip form -------------------------------------
|
|
function setupFormPreview(form) {
|
|
var container = form.querySelector("#route-map");
|
|
var placeholder = form.querySelector("[data-route-map-placeholder]");
|
|
var originText = form.querySelector("#origin");
|
|
var destText = form.querySelector("#destination");
|
|
var originHidden = form.querySelector("#origin_stop_id");
|
|
var destHidden = form.querySelector("#destination_stop_id");
|
|
if (!container || !originText || !destText || !originHidden || !destHidden) return;
|
|
|
|
var routeMap = null;
|
|
|
|
function point(hidden, text) {
|
|
var lat = hidden.dataset.stopLat, lon = hidden.dataset.stopLon;
|
|
if (!lat || !lon) return null;
|
|
return { lat: parseFloat(lat), lon: parseFloat(lon), label: text.value.trim() };
|
|
}
|
|
|
|
function apply() {
|
|
var origin = point(originHidden, originText);
|
|
var destination = point(destHidden, destText);
|
|
if (!origin && !destination) {
|
|
container.hidden = true;
|
|
if (placeholder) placeholder.hidden = false;
|
|
return;
|
|
}
|
|
container.hidden = false;
|
|
if (placeholder) placeholder.hidden = true;
|
|
if (!routeMap) routeMap = createRouteMap("route-map");
|
|
routeMap.render(origin, destination);
|
|
setTimeout(function () { routeMap.map.invalidateSize(); }, 0);
|
|
}
|
|
|
|
form.addEventListener("stopchange", apply);
|
|
originText.addEventListener("input", apply);
|
|
destText.addEventListener("input", apply);
|
|
apply();
|
|
}
|
|
|
|
document.querySelectorAll("form").forEach(setupFormPreview);
|
|
|
|
// --- "Meine Fahrten" map-pin buttons + shared dialog --------------------
|
|
var dialog = document.getElementById("route-map-dialog");
|
|
if (dialog) {
|
|
var dialogTitle = document.getElementById("route-map-dialog-title");
|
|
var closeBtn = dialog.querySelector("[data-close-map-dialog]");
|
|
var dialogMap = null;
|
|
|
|
function coordsOf(btn, prefix) {
|
|
var lat = btn.dataset[prefix + "Lat"], lon = btn.dataset[prefix + "Lon"];
|
|
if (!lat || !lon) return null;
|
|
return { lat: parseFloat(lat), lon: parseFloat(lon), label: btn.dataset[prefix + "Label"] || "" };
|
|
}
|
|
|
|
document.querySelectorAll("[data-show-map]").forEach(function (btn) {
|
|
btn.addEventListener("click", function () {
|
|
var origin = coordsOf(btn, "origin");
|
|
var destination = coordsOf(btn, "destination");
|
|
dialogTitle.textContent = (btn.dataset.originLabel || "?") + " → " + (btn.dataset.destinationLabel || "?");
|
|
dialog.showModal();
|
|
if (!dialogMap) dialogMap = createRouteMap("dialog-route-map");
|
|
dialogMap.render(origin, destination);
|
|
setTimeout(function () { dialogMap.map.invalidateSize(); }, 0);
|
|
});
|
|
});
|
|
|
|
if (closeBtn) closeBtn.addEventListener("click", function () { dialog.close(); });
|
|
dialog.addEventListener("click", function (e) {
|
|
if (e.target === dialog) dialog.close(); // click on the backdrop
|
|
});
|
|
}
|
|
})();
|