From 73d3569ddcafcbe76f40c4ae9c6f9bcfaef711d8 Mon Sep 17 00:00:00 2001 From: Marwin Hochfelsner <50826859+hlfan@users.noreply.github.com> Date: Mon, 13 Apr 2026 20:28:38 +0200 Subject: [PATCH] Refactor distance unit handling in directions output --- .../index_modules/directions/route-output.js | 171 ++++++++---------- 1 file changed, 73 insertions(+), 98 deletions(-) diff --git a/app/assets/javascripts/index_modules/directions/route-output.js b/app/assets/javascripts/index_modules/directions/route-output.js index a2f0edfaa..6301644b4 100644 --- a/app/assets/javascripts/index_modules/directions/route-output.js +++ b/app/assets/javascripts/index_modules/directions/route-output.js @@ -14,109 +14,90 @@ function RouteOutput(map) { weight: 12 }); - let distanceUnits = "km_m"; - let downloadURL = null; + class UnitFormatter { + constructor(unitObj) { + const units = Object.entries(unitObj).sort((a, b) => a[1] - b[1]); + [[this.minorName, this.minorScale], [this.majorName, this.majorScale]] = units; + } - function translateDistanceUnits(m) { - if (distanceUnits === "mi_ft") { - return [m / 0.3048, "ft", m / 1609.344, "mi"]; - } else if (distanceUnits === "mi_yd") { - return [m / 0.9144, "yd", m / 1609.344, "mi"]; - } else { - return [m, "m", m / 1000, "km"]; + print(name, distance) { + const scope = "javascripts.directions.distance_in_units"; + return OSM.i18n.t(name, { scope, distance }); } - } - function formatTotalDistance(minorValue, minorName, majorValue, majorName) { - const scope = "javascripts.directions.distance_in_units"; + totalDistance(m) { + const minorValue = m / this.minorScale; + const majorValue = m / this.majorScale; - if (minorValue < 1000 || majorValue < 0.25) { - return OSM.i18n.t(minorName, { scope, distance: Math.round(minorValue) }); - } else if (majorValue < 10) { - return OSM.i18n.t(majorName, { scope, distance: majorValue.toFixed(1) }); - } else { - return OSM.i18n.t(majorName, { scope, distance: Math.round(majorValue) }); + if (minorValue < 1000 || majorValue < 0.25) return this.print(this.minorName, Math.round(minorValue)); + if (majorValue < 10) return this.print(this.majorName, majorValue.toFixed(1)); + return this.print(this.majorName, Math.round(majorValue)); } - } - function formatStepDistance(minorValue, minorName, majorValue, majorName) { - const scope = "javascripts.directions.distance_in_units"; - - if (minorValue < 5) { - return ""; - } else if (minorValue < 200) { - return OSM.i18n.t(minorName, { scope, distance: Math.round(minorValue / 10) * 10 }); - } else if (minorValue < 1500 || majorValue < 0.25) { - return OSM.i18n.t(minorName, { scope, distance: Math.round(minorValue / 100) * 100 }); - } else if (majorValue < 5) { - return OSM.i18n.t(majorName, { scope, distance: majorValue.toFixed(1) }); - } else { - return OSM.i18n.t(majorName, { scope, distance: Math.round(majorValue) }); - } - } + stepDistance(m) { + const minorValue = m / this.minorScale; + const majorValue = m / this.majorScale; - function formatHeight(minorValue, minorName) { - const scope = "javascripts.directions.distance_in_units"; + if (minorValue < 5) return ""; + if (minorValue < 200) return this.print(this.minorName, Math.round(minorValue / 10) * 10); + if (minorValue < 1500 || majorValue < 0.25) return this.print(this.minorName, Math.round(minorValue / 100) * 100); + if (majorValue < 5) return this.print(this.majorName, majorValue.toFixed(1)); + return this.print(this.majorName, Math.round(majorValue)); + } - return OSM.i18n.t(minorName, { scope, distance: Math.round(minorValue) }); - } + height(m) { + if (isNaN(m)) return ""; + const minorValue = m / this.minorScale; - function formatTime(s) { - let m = Math.round(s / 60); - const h = Math.floor(m / 60); + return this.print(this.minorName, Math.round(minorValue)); + } - m -= h * 60; + time(s) { + let m = Math.round(s / 60); + const h = Math.floor(m / 60); - return h + ":" + (m < 10 ? "0" : "") + m; - } + m -= h * 60; - function writeSummary(route) { - $("#directions_route_distance").val(formatTotalDistance(...translateDistanceUnits(route.distance))); - $("#directions_route_time").val(formatTime(route.time)); - - if (typeof route.ascend !== "undefined" && typeof route.descend !== "undefined") { - $("#directions_route_ascend_descend").prop("hidden", false); - $("#directions_route_ascend").val(formatHeight(...translateDistanceUnits(route.ascend))); - $("#directions_route_descend").val(formatHeight(...translateDistanceUnits(route.descend))); - } else { - $("#directions_route_ascend_descend").prop("hidden", true); - $("#directions_route_ascend").val(""); - $("#directions_route_descend").val(""); + return h + ":" + (m < 10 ? "0" : "") + m; } } - function writeSteps(route) { - $("#directions_route_steps").empty(); + const FORMATTERS = { + km_m: new UnitFormatter({ km: 1000, m: 1 }), + mi_ft: new UnitFormatter({ mi: 1609.344, ft: 0.3048 }), + mi_yd: new UnitFormatter({ mi: 1609.344, yd: 0.9144 }) + }; + let formatter = FORMATTERS.km_m; + let downloadURL = null; - for (const [i, [direction, instruction, dist, lineseg]] of route.steps.entries()) { - const row = $("
${i + 1}. ${instruction}
`) - .openOn(map); - }); - - row - .on("mouseenter", function () { - highlight - .setLatLngs(lineseg) - .addTo(map); - }) - .on("mouseleave", function () { - map.removeLayer(highlight); - }); - } + function writeTable({ distance, time, ascend, descend, steps }) { + $("#directions_route_distance").val(formatter.totalDistance(distance)); + $("#directions_route_time").val(formatter.time(time)); + + $("#directions_route_ascend_descend").prop("hidden", isNaN(ascend) || isNaN(descend)); + $("#directions_route_ascend").val(formatter.height(ascend)); + $("#directions_route_descend").val(formatter.height(descend)); + + $("#directions_route_steps").empty().append(...steps.map(stepToRow)); + } + + function stepToRow([direction, instruction, dist, lineseg], i) { + const popupText = `${i + 1}. ${instruction}`; + let icon = ""; + if (direction) icon = ``; + + return $("${popupText}
`) + .openOn(map)) + .on("mouseenter", () => highlight + .setLatLngs(lineseg) + .addTo(map)) + .on("mouseleave", () => map.removeLayer(highlight)); } const routeOutput = {}; @@ -126,13 +107,11 @@ function RouteOutput(map) { .setLatLngs(route.line) .addTo(map); - writeSummary(route); - writeSteps(route); + writeTable(route); $("#directions_distance_units_settings input").off().on("change", function () { - distanceUnits = this.value; - writeSummary(route); - writeSteps(route); + formatter = FORMATTERS[this.value] || FORMATTERS.km_m; + writeTable(route); }); const blob = new Blob([JSON.stringify(polyline.toGeoJSON())], { type: "application/geo+json" }); @@ -149,13 +128,9 @@ function RouteOutput(map) { .prop("href", route.demolink); }; - routeOutput.fit = function () { - map.fitBounds(polyline.getBounds().pad(0.05)); - }; + routeOutput.fit = () => map.fitBounds(polyline.getBounds().pad(0.05)); - routeOutput.isVisible = function () { - return map.hasLayer(polyline); - }; + routeOutput.isVisible = () => map.hasLayer(polyline); routeOutput.remove = function () { map -- 2.47.3