]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index/directions-route-output.js
Write most of route html using erb template
[rails.git] / app / assets / javascripts / index / directions-route-output.js
1 OSM.DirectionsRouteOutput = function (map) {
2   const popup = L.popup({ autoPanPadding: [100, 100] });
3
4   const polyline = L.polyline([], {
5     color: "#03f",
6     opacity: 0.3,
7     weight: 10
8   });
9
10   const highlight = L.polyline([], {
11     color: "#ff0",
12     opacity: 0.5,
13     weight: 12
14   });
15
16   let downloadURL = null;
17
18   function formatTotalDistance(m) {
19     if (m < 1000) {
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) });
23     } else {
24       return OSM.i18n.t("javascripts.directions.distance_km", { distance: Math.round(m / 1000) });
25     }
26   }
27
28   function formatStepDistance(m) {
29     if (m < 5) {
30       return "";
31     } else if (m < 200) {
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) });
37     } else {
38       return OSM.i18n.t("javascripts.directions.distance_km", { distance: String(Math.round(m / 1000)) });
39     }
40   }
41
42   function formatHeight(m) {
43     return OSM.i18n.t("javascripts.directions.distance_m", { distance: Math.round(m) });
44   }
45
46   function formatTime(s) {
47     let m = Math.round(s / 60);
48     const h = Math.floor(m / 60);
49     m -= h * 60;
50     return h + ":" + (m < 10 ? "0" : "") + m;
51   }
52
53   function writeSummary(route) {
54     $("#directions_route_distance").val(formatTotalDistance(route.distance));
55     $("#directions_route_time").val(formatTime(route.time));
56     if (typeof route.ascend !== "undefined" && typeof route.descend !== "undefined") {
57       $("#directions_route_ascend_descend").prop("hidden", false);
58       $("#directions_route_ascend").val(formatHeight(route.ascend));
59       $("#directions_route_descend").val(formatHeight(route.descend));
60     } else {
61       $("#directions_route_ascend_descend").prop("hidden", true);
62       $("#directions_route_ascend").val("");
63       $("#directions_route_descend").val("");
64     }
65   }
66
67   function writeSteps(route) {
68     $("#directions_route_steps").empty();
69
70     for (const [i, [direction, instruction, dist, lineseg]] of route.steps.entries()) {
71       const row = $("<tr class='turn'/>").appendTo($("#directions_route_steps"));
72
73       if (direction) {
74         row.append("<td class='border-0'><svg width='20' height='20' class='d-block'><use href='#routing-sprite-" + direction + "' /></svg></td>");
75       } else {
76         row.append("<td class='border-0'>");
77       }
78       row.append(`<td><b>${i + 1}.</b> ${instruction}`);
79       row.append("<td class='distance text-body-secondary text-end'>" + formatStepDistance(dist));
80
81       row.on("click", function () {
82         popup
83           .setLatLng(lineseg[0])
84           .setContent(`<p><b>${i + 1}.</b> ${instruction}</p>`)
85           .openOn(map);
86       });
87
88       row
89         .on("mouseenter", function () {
90           highlight
91             .setLatLngs(lineseg)
92             .addTo(map);
93         })
94         .on("mouseleave", function () {
95           map.removeLayer(highlight);
96         });
97     }
98   }
99
100   const routeOutput = {};
101
102   routeOutput.write = function (route) {
103     polyline
104       .setLatLngs(route.line)
105       .addTo(map);
106
107     writeSummary(route);
108     writeSteps(route);
109
110     const blob = new Blob([JSON.stringify(polyline.toGeoJSON())], { type: "application/json" });
111     URL.revokeObjectURL(downloadURL);
112     downloadURL = URL.createObjectURL(blob);
113     $("#directions_route_download").prop("href", downloadURL);
114
115     $("#directions_route_credit")
116       .text(route.credit)
117       .prop("href", route.creditlink);
118   };
119
120   routeOutput.fit = function () {
121     map.fitBounds(polyline.getBounds().pad(0.05));
122   };
123
124   routeOutput.isVisible = function () {
125     return map.hasLayer(polyline);
126   };
127
128   routeOutput.remove = function () {
129     map
130       .removeLayer(popup)
131       .removeLayer(polyline);
132
133     $("#directions_route_steps").empty();
134
135     URL.revokeObjectURL(downloadURL);
136     $("#directions_route_download").prop("href", "");
137   };
138
139   return routeOutput;
140 };