--- /dev/null
+OSM.DirectionsRouteOutput = function (map) {
+ const popup = L.popup({ autoPanPadding: [100, 100] });
+
+ const polyline = L.polyline([], {
+ color: "#03f",
+ opacity: 0.3,
+ weight: 10
+ });
+
+ const highlight = L.polyline([], {
+ color: "#ff0",
+ opacity: 0.5,
+ weight: 12
+ });
+
+ let downloadURL = null;
+
+ function formatTotalDistance(m) {
+ if (m < 1000) {
+ return OSM.i18n.t("javascripts.directions.distance_m", { distance: Math.round(m) });
+ } else if (m < 10000) {
+ return OSM.i18n.t("javascripts.directions.distance_km", { distance: (m / 1000.0).toFixed(1) });
+ } else {
+ return OSM.i18n.t("javascripts.directions.distance_km", { distance: Math.round(m / 1000) });
+ }
+ }
+
+ function formatStepDistance(m) {
+ if (m < 5) {
+ return "";
+ } else if (m < 200) {
+ return OSM.i18n.t("javascripts.directions.distance_m", { distance: String(Math.round(m / 10) * 10) });
+ } else if (m < 1500) {
+ return OSM.i18n.t("javascripts.directions.distance_m", { distance: String(Math.round(m / 100) * 100) });
+ } else if (m < 5000) {
+ return OSM.i18n.t("javascripts.directions.distance_km", { distance: String(Math.round(m / 100) / 10) });
+ } else {
+ return OSM.i18n.t("javascripts.directions.distance_km", { distance: String(Math.round(m / 1000)) });
+ }
+ }
+
+ function formatHeight(m) {
+ return OSM.i18n.t("javascripts.directions.distance_m", { distance: Math.round(m) });
+ }
+
+ function formatTime(s) {
+ let m = Math.round(s / 60);
+ const h = Math.floor(m / 60);
+ m -= h * 60;
+ return h + ":" + (m < 10 ? "0" : "") + m;
+ }
+
+ const routeOutput = {};
+
+ routeOutput.write = function (content, engine, route) {
+ polyline
+ .setLatLngs(route.line)
+ .addTo(map);
+
+ const distanceText = $("<p>").append(
+ OSM.i18n.t("javascripts.directions.distance") + ": " + formatTotalDistance(route.distance) + ". " +
+ OSM.i18n.t("javascripts.directions.time") + ": " + formatTime(route.time) + ".");
+ if (typeof route.ascend !== "undefined" && typeof route.descend !== "undefined") {
+ distanceText.append(
+ $("<br>"),
+ OSM.i18n.t("javascripts.directions.ascend") + ": " + formatHeight(route.ascend) + ". " +
+ OSM.i18n.t("javascripts.directions.descend") + ": " + formatHeight(route.descend) + ".");
+ }
+
+ const turnByTurnTable = $("<table class='table table-hover table-sm mb-3'>")
+ .append($("<tbody>"));
+
+ content
+ .empty()
+ .append(
+ distanceText,
+ turnByTurnTable
+ );
+
+ for (const [i, [direction, instruction, dist, lineseg]] of route.steps.entries()) {
+ const row = $("<tr class='turn'/>").appendTo(turnByTurnTable);
+
+ if (direction) {
+ row.append("<td class='border-0'><svg width='20' height='20' class='d-block'><use href='#routing-sprite-" + direction + "' /></svg></td>");
+ } else {
+ row.append("<td class='border-0'>");
+ }
+ row.append(`<td><b>${i + 1}.</b> ${instruction}`);
+ row.append("<td class='distance text-body-secondary text-end'>" + formatStepDistance(dist));
+
+ row.on("click", function () {
+ popup
+ .setLatLng(lineseg[0])
+ .setContent(`<p><b>${i + 1}.</b> ${instruction}</p>`)
+ .openOn(map);
+ });
+
+ row.hover(function () {
+ highlight
+ .setLatLngs(lineseg)
+ .addTo(map);
+ }, function () {
+ map.removeLayer(highlight);
+ });
+ }
+
+ const blob = new Blob([JSON.stringify(polyline.toGeoJSON())], { type: "application/json" });
+ URL.revokeObjectURL(downloadURL);
+ downloadURL = URL.createObjectURL(blob);
+
+ content.append(`<p class="text-center"><a href="${downloadURL}" download="${
+ OSM.i18n.t("javascripts.directions.filename")
+ }">${
+ OSM.i18n.t("javascripts.directions.download")
+ }</a></p>`);
+
+ content.append("<p class=\"text-center\">" +
+ OSM.i18n.t("javascripts.directions.instructions.courtesy", { link: engine.creditline }) +
+ "</p>");
+ };
+
+ routeOutput.fit = function () {
+ map.fitBounds(polyline.getBounds().pad(0.05));
+ };
+
+ routeOutput.isVisible = function () {
+ return map.hasLayer(polyline);
+ };
+
+ routeOutput.remove = function (content) {
+ content.empty();
+ map
+ .removeLayer(popup)
+ .removeLayer(polyline);
+ };
+
+ return routeOutput;
+};
//= require ./directions-endpoint
+//= require ./directions-route-output
//= require_self
//= require_tree ./directions
let lastLocation = [];
let chosenEngine;
- const popup = L.popup({ autoPanPadding: [100, 100] });
-
- const polyline = L.polyline([], {
- color: "#03f",
- opacity: 0.3,
- weight: 10
- });
-
- const highlight = L.polyline([], {
- color: "#ff0",
- opacity: 0.5,
- weight: 12
- });
+ const routeOutput = OSM.DirectionsRouteOutput(map);
const endpointDragCallback = function (dragging) {
- if (!map.hasLayer(polyline)) return;
+ if (!routeOutput.isVisible()) return;
if (dragging && !chosenEngine.draggable) return;
if (dragging && controller) return;
OSM.DirectionsEndpoint(map, $("input[name='route_to']"), { icon: "MARKER_RED" }, endpointDragCallback, endpointChangeCallback)
];
- let downloadURL = null;
-
const expiry = new Date();
expiry.setYear(expiry.getFullYear() + 10);
OSM.router.route("/" + OSM.formatHash(map));
});
- function formatTotalDistance(m) {
- if (m < 1000) {
- return OSM.i18n.t("javascripts.directions.distance_m", { distance: Math.round(m) });
- } else if (m < 10000) {
- return OSM.i18n.t("javascripts.directions.distance_km", { distance: (m / 1000.0).toFixed(1) });
- } else {
- return OSM.i18n.t("javascripts.directions.distance_km", { distance: Math.round(m / 1000) });
- }
- }
-
- function formatStepDistance(m) {
- if (m < 5) {
- return "";
- } else if (m < 200) {
- return OSM.i18n.t("javascripts.directions.distance_m", { distance: String(Math.round(m / 10) * 10) });
- } else if (m < 1500) {
- return OSM.i18n.t("javascripts.directions.distance_m", { distance: String(Math.round(m / 100) * 100) });
- } else if (m < 5000) {
- return OSM.i18n.t("javascripts.directions.distance_km", { distance: String(Math.round(m / 100) / 10) });
- } else {
- return OSM.i18n.t("javascripts.directions.distance_km", { distance: String(Math.round(m / 1000)) });
- }
- }
-
- function formatHeight(m) {
- return OSM.i18n.t("javascripts.directions.distance_m", { distance: Math.round(m) });
- }
-
- function formatTime(s) {
- let m = Math.round(s / 60);
- const h = Math.floor(m / 60);
- m -= h * 60;
- return h + ":" + (m < 10 ? "0" : "") + m;
- }
-
function setEngine(id) {
const engines = OSM.Directions.engines;
const desired = engines.find(engine => engine.id === id);
map.setSidebarOverlaid(false);
controller = new AbortController();
chosenEngine.getRoute(points, controller.signal).then(function (route) {
- polyline
- .setLatLngs(route.line)
- .addTo(map);
-
+ routeOutput.write($("#directions_content"), chosenEngine, route);
if (fitRoute) {
- map.fitBounds(polyline.getBounds().pad(0.05));
- }
-
- const distanceText = $("<p>").append(
- OSM.i18n.t("javascripts.directions.distance") + ": " + formatTotalDistance(route.distance) + ". " +
- OSM.i18n.t("javascripts.directions.time") + ": " + formatTime(route.time) + ".");
- if (typeof route.ascend !== "undefined" && typeof route.descend !== "undefined") {
- distanceText.append(
- $("<br>"),
- OSM.i18n.t("javascripts.directions.ascend") + ": " + formatHeight(route.ascend) + ". " +
- OSM.i18n.t("javascripts.directions.descend") + ": " + formatHeight(route.descend) + ".");
- }
-
- const turnByTurnTable = $("<table class='table table-hover table-sm mb-3'>")
- .append($("<tbody>"));
-
- $("#directions_content")
- .empty()
- .append(
- distanceText,
- turnByTurnTable
- );
-
- // Add each row
- for (const [i, [direction, instruction, dist, lineseg]] of route.steps.entries()) {
- const row = $("<tr class='turn'/>").appendTo(turnByTurnTable);
-
- if (direction) {
- row.append("<td class='border-0'><svg width='20' height='20' class='d-block'><use href='#routing-sprite-" + direction + "' /></svg></td>");
- } else {
- row.append("<td class='border-0'>");
- }
- row.append(`<td><b>${i + 1}.</b> ${instruction}`);
- row.append("<td class='distance text-body-secondary text-end'>" + formatStepDistance(dist));
-
- row.on("click", function () {
- popup
- .setLatLng(lineseg[0])
- .setContent(`<p><b>${i + 1}.</b> ${instruction}</p>`)
- .openOn(map);
- });
-
- row.hover(function () {
- highlight
- .setLatLngs(lineseg)
- .addTo(map);
- }, function () {
- map.removeLayer(highlight);
- });
+ routeOutput.fit();
}
-
- const blob = new Blob([JSON.stringify(polyline.toGeoJSON())], { type: "application/json" });
- URL.revokeObjectURL(downloadURL);
- downloadURL = URL.createObjectURL(blob);
-
- $("#directions_content").append(`<p class="text-center"><a href="${downloadURL}" download="${
- OSM.i18n.t("javascripts.directions.filename")
- }">${
- OSM.i18n.t("javascripts.directions.download")
- }</a></p>`);
-
- $("#directions_content").append("<p class=\"text-center\">" +
- OSM.i18n.t("javascripts.directions.instructions.courtesy", { link: chosenEngine.creditline }) +
- "</p>");
}).catch(function () {
- map.removeLayer(polyline);
+ routeOutput.remove($("#directions_content"));
if (reportErrors) {
$("#directions_content").html("<div class=\"alert alert-danger\">" + OSM.i18n.t("javascripts.directions.errors.no_route") + "</div>");
}
function hideRoute(e) {
e.stopPropagation();
- map.removeLayer(polyline);
- $("#directions_content").html("");
- popup.close();
+ routeOutput.remove($("#directions_content"));
map.setSidebarOverlaid(true);
// TODO: collapse width of sidebar back to previous
}
endpoints[0].clearValue();
endpoints[1].clearValue();
- map
- .removeLayer(popup)
- .removeLayer(polyline);
+ routeOutput.remove($("#directions_content"));
};
return page;