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 distanceUnits = "km_m";
17 let downloadURL = null;
19 function translateDistanceUnits(m) {
20 if (distanceUnits === "mi_ft") {
21 return [m / 0.3048, "ft", m / 1609.344, "mi"];
22 } else if (distanceUnits === "mi_yd") {
23 return [m / 0.9144, "yd", m / 1609.344, "mi"];
25 return [m, "m", m / 1000, "km"];
29 function formatTotalDistance(minorValue, minorName, majorValue, majorName) {
30 const scope = "javascripts.directions.distance_in_units";
32 if (minorValue < 1000 || majorValue < 0.25) {
33 return OSM.i18n.t(minorName, { scope, distance: Math.round(minorValue) });
34 } else if (majorValue < 10) {
35 return OSM.i18n.t(majorName, { scope, distance: majorValue.toFixed(1) });
37 return OSM.i18n.t(majorName, { scope, distance: Math.round(majorValue) });
41 function formatStepDistance(minorValue, minorName, majorValue, majorName) {
42 const scope = "javascripts.directions.distance_in_units";
46 } else if (minorValue < 200) {
47 return OSM.i18n.t(minorName, { scope, distance: Math.round(minorValue / 10) * 10 });
48 } else if (minorValue < 1500 || majorValue < 0.25) {
49 return OSM.i18n.t(minorName, { scope, distance: Math.round(minorValue / 100) * 100 });
50 } else if (majorValue < 5) {
51 return OSM.i18n.t(majorName, { scope, distance: majorValue.toFixed(1) });
53 return OSM.i18n.t(majorName, { scope, distance: Math.round(majorValue) });
57 function formatHeight(minorValue, minorName) {
58 const scope = "javascripts.directions.distance_in_units";
60 return OSM.i18n.t(minorName, { scope, distance: Math.round(minorValue) });
63 function formatTime(s) {
64 let m = Math.round(s / 60);
65 const h = Math.floor(m / 60);
67 return h + ":" + (m < 10 ? "0" : "") + m;
70 function writeSummary(route) {
71 $("#directions_route_distance").val(formatTotalDistance(...translateDistanceUnits(route.distance)));
72 $("#directions_route_time").val(formatTime(route.time));
73 if (typeof route.ascend !== "undefined" && typeof route.descend !== "undefined") {
74 $("#directions_route_ascend_descend").prop("hidden", false);
75 $("#directions_route_ascend").val(formatHeight(...translateDistanceUnits(route.ascend)));
76 $("#directions_route_descend").val(formatHeight(...translateDistanceUnits(route.descend)));
78 $("#directions_route_ascend_descend").prop("hidden", true);
79 $("#directions_route_ascend").val("");
80 $("#directions_route_descend").val("");
84 function writeSteps(route) {
85 $("#directions_route_steps").empty();
87 for (const [i, [direction, instruction, dist, lineseg]] of route.steps.entries()) {
88 const row = $("<tr class='turn'/>").appendTo($("#directions_route_steps"));
91 row.append("<td class='ps-3'><svg width='20' height='20' class='d-block'><use href='#routing-sprite-" + direction + "' /></svg></td>");
93 row.append("<td class='ps-3'>");
95 row.append(`<td><b>${i + 1}.</b> ${instruction}`);
96 row.append("<td class='pe-3 distance text-body-secondary text-end'>" + formatStepDistance(...translateDistanceUnits(dist)));
98 row.on("click", function () {
100 .setLatLng(lineseg[0])
101 .setContent(`<p><b>${i + 1}.</b> ${instruction}</p>`)
106 .on("mouseenter", function () {
111 .on("mouseleave", function () {
112 map.removeLayer(highlight);
117 const routeOutput = {};
119 routeOutput.write = function (route) {
121 .setLatLngs(route.line)
127 $("#directions_distance_units_settings input").off().on("change", function () {
128 distanceUnits = this.value;
133 const blob = new Blob([JSON.stringify(polyline.toGeoJSON())], { type: "application/json" });
134 URL.revokeObjectURL(downloadURL);
135 downloadURL = URL.createObjectURL(blob);
136 $("#directions_route_download").prop("href", downloadURL);
138 $("#directions_route_credit")
140 .prop("href", route.creditlink);
143 routeOutput.fit = function () {
144 map.fitBounds(polyline.getBounds().pad(0.05));
147 routeOutput.isVisible = function () {
148 return map.hasLayer(polyline);
151 routeOutput.remove = function () {
154 .removeLayer(polyline);
156 $("#directions_distance_units_settings input").off();
158 $("#directions_route_steps").empty();
160 URL.revokeObjectURL(downloadURL);
161 $("#directions_route_download").prop("href", "");