1 OSM.DirectionsRouteOutput = function (map) {
2 const popup = L.popup({ autoPanPadding: [100, 100] });
4 const polyline = L.polyline([], {
10 const highlight = L.polyline([], {
16 let downloadURL = null;
18 function formatTotalDistance(m) {
20 return OSM.i18n.t("javascripts.directions.distance_m", { distance: Math.round(m) });
21 } else if (m < 10000) {
22 return OSM.i18n.t("javascripts.directions.distance_km", { distance: (m / 1000.0).toFixed(1) });
24 return OSM.i18n.t("javascripts.directions.distance_km", { distance: Math.round(m / 1000) });
28 function formatStepDistance(m) {
32 return OSM.i18n.t("javascripts.directions.distance_m", { distance: String(Math.round(m / 10) * 10) });
33 } else if (m < 1500) {
34 return OSM.i18n.t("javascripts.directions.distance_m", { distance: String(Math.round(m / 100) * 100) });
35 } else if (m < 5000) {
36 return OSM.i18n.t("javascripts.directions.distance_km", { distance: String(Math.round(m / 100) / 10) });
38 return OSM.i18n.t("javascripts.directions.distance_km", { distance: String(Math.round(m / 1000)) });
42 function formatHeight(m) {
43 return OSM.i18n.t("javascripts.directions.distance_m", { distance: Math.round(m) });
46 function formatTime(s) {
47 let m = Math.round(s / 60);
48 const h = Math.floor(m / 60);
50 return h + ":" + (m < 10 ? "0" : "") + m;
53 const routeOutput = {};
55 routeOutput.write = function (content, route) {
57 .setLatLngs(route.line)
60 const distanceText = $("<p>").append(
61 OSM.i18n.t("javascripts.directions.distance") + ": " + formatTotalDistance(route.distance) + ". " +
62 OSM.i18n.t("javascripts.directions.time") + ": " + formatTime(route.time) + ".");
63 if (typeof route.ascend !== "undefined" && typeof route.descend !== "undefined") {
66 OSM.i18n.t("javascripts.directions.ascend") + ": " + formatHeight(route.ascend) + ". " +
67 OSM.i18n.t("javascripts.directions.descend") + ": " + formatHeight(route.descend) + ".");
70 const turnByTurnTable = $("<table class='table table-hover table-sm mb-3'>")
71 .append($("<tbody>"));
80 for (const [i, [direction, instruction, dist, lineseg]] of route.steps.entries()) {
81 const row = $("<tr class='turn'/>").appendTo(turnByTurnTable);
84 row.append("<td class='border-0'><svg width='20' height='20' class='d-block'><use href='#routing-sprite-" + direction + "' /></svg></td>");
86 row.append("<td class='border-0'>");
88 row.append(`<td><b>${i + 1}.</b> ${instruction}`);
89 row.append("<td class='distance text-body-secondary text-end'>" + formatStepDistance(dist));
91 row.on("click", function () {
93 .setLatLng(lineseg[0])
94 .setContent(`<p><b>${i + 1}.</b> ${instruction}</p>`)
99 .on("mouseenter", function () {
104 .on("mouseleave", function () {
105 map.removeLayer(highlight);
109 const blob = new Blob([JSON.stringify(polyline.toGeoJSON())], { type: "application/json" });
110 URL.revokeObjectURL(downloadURL);
111 downloadURL = URL.createObjectURL(blob);
113 content.append(`<p class="text-center"><a href="${downloadURL}" download="${
114 OSM.i18n.t("javascripts.directions.filename")
116 OSM.i18n.t("javascripts.directions.download")
119 content.append("<p class=\"text-center\">" +
120 OSM.i18n.t("javascripts.directions.instructions.courtesy", {
121 link: `<a href="${route.creditlink}" target="_blank">${route.credit}</a>`
126 routeOutput.fit = function () {
127 map.fitBounds(polyline.getBounds().pad(0.05));
130 routeOutput.isVisible = function () {
131 return map.hasLayer(polyline);
134 routeOutput.remove = function (content) {
138 .removeLayer(polyline);