]> git.openstreetmap.org Git - rails.git/commitdiff
Merge remote-tracking branch 'upstream/pull/5685'
authorTom Hughes <tom@compton.nu>
Sun, 16 Feb 2025 13:18:14 +0000 (13:18 +0000)
committerTom Hughes <tom@compton.nu>
Sun, 16 Feb 2025 13:18:14 +0000 (13:18 +0000)
56 files changed:
app/abilities/api_ability.rb
app/assets/javascripts/application.js
app/assets/javascripts/diary_entry.js
app/assets/javascripts/embed.js.erb
app/assets/javascripts/fixthemap.js
app/assets/javascripts/id.js
app/assets/javascripts/index.js
app/assets/javascripts/index/changeset.js
app/assets/javascripts/index/contextmenu.js
app/assets/javascripts/index/directions-endpoint.js
app/assets/javascripts/index/directions.js
app/assets/javascripts/index/export.js
app/assets/javascripts/index/history.js
app/assets/javascripts/index/layers/data.js
app/assets/javascripts/index/layers/notes.js
app/assets/javascripts/index/new_note.js
app/assets/javascripts/index/note.js
app/assets/javascripts/index/query.js
app/assets/javascripts/index/search.js
app/assets/javascripts/leaflet.key.js
app/assets/javascripts/leaflet.layers.js
app/assets/javascripts/leaflet.locate.js
app/assets/javascripts/leaflet.map.js
app/assets/javascripts/leaflet.note.js
app/assets/javascripts/leaflet.query.js
app/assets/javascripts/leaflet.share.js
app/assets/javascripts/leaflet.sidebar-pane.js
app/assets/javascripts/leaflet.sidebar.js
app/assets/javascripts/leaflet.zoom.js
app/assets/javascripts/matomo.js
app/assets/javascripts/osm.js.erb
app/assets/javascripts/richtext.js
app/assets/javascripts/router.js
app/assets/javascripts/user.js
app/assets/javascripts/welcome.js
app/controllers/api/changeset_comments_controller.rb
app/controllers/api/changesets_controller.rb
app/controllers/api/notes_controller.rb
app/controllers/changeset_comments/feeds_controller.rb
app/controllers/concerns/query_methods.rb [new file with mode: 0644]
app/models/user.rb
app/views/api/changeset_comments/_changeset_comment.json.jbuilder [new file with mode: 0644]
app/views/api/changeset_comments/_changeset_comment.xml.builder [new file with mode: 0644]
app/views/api/changeset_comments/index.json.jbuilder [new file with mode: 0644]
app/views/api/changeset_comments/index.xml.builder [new file with mode: 0644]
app/views/api/changesets/_changeset.json.jbuilder
app/views/api/changesets/_changeset.xml.builder
config/eslint.js
config/routes.rb
config/settings.yml
config/settings/test.yml
test/application_system_test_case.rb
test/controllers/api/changeset_comments_controller_test.rb
test/controllers/api/notes_controller_test.rb
test/javascripts/osm_test.js
test/teaspoon_env.rb

index ec4de8f8e03b99dc795f88cecf6421aefb11c00e..acacec049af1f20f6372c3a008945961fdda6c29 100644 (file)
@@ -11,6 +11,7 @@ class ApiAbility
       can :create, Note unless user
 
       can [:read, :download], Changeset
+      can :read, ChangesetComment
       can :read, Tracepoint
       can :read, User
       can :read, [Node, Way, Relation, OldNode, OldWay, OldRelation]
index 212474a89fb01ef3d4dc792824deef3286a5e57f..a3fd93e27c1daaa3cd08a5881f6d266cf6e16e1b 100644 (file)
@@ -75,7 +75,7 @@ window.updateLinks = function (loc, zoom, layers, object) {
 
   // Disable the button group and also the buttons to avoid
   // inconsistent behaviour when zooming
-  var editDisabled = zoom < 13;
+  const editDisabled = zoom < 13;
   $("#edit_tab")
     .tooltip({ placement: "bottom" })
     .tooltip(editDisabled ? "enable" : "disable")
@@ -96,7 +96,7 @@ $(document).ready(function () {
   let moreItemWidth = 0;
 
   function updateHeader() {
-    var windowWidth = $(window).width();
+    const windowWidth = $(window).width();
 
     if (windowWidth < breakpointWidth) {
       $("body").addClass("small-nav");
index bd5fd4dd62f359ecd0b163e555c87bd6420bd0f3..e55d0900d0b13a9e7d6081a6998043fa74784aeb 100644 (file)
@@ -1,5 +1,5 @@
 $(document).ready(function () {
-  var marker, map;
+  let marker, map;
 
   function setLocation(e) {
     const latlng = e.latlng.wrap();
@@ -21,9 +21,9 @@ $(document).ready(function () {
     $("#map").show();
     $("#usemap").hide();
 
-    var params = $("#map").data();
-    var centre = [params.lat, params.lon];
-    var position = $("html").attr("dir") === "rtl" ? "topleft" : "topright";
+    const params = $("#map").data();
+    const centre = [params.lat, params.lon];
+    const position = $("html").attr("dir") === "rtl" ? "topleft" : "topright";
 
     map = L.map("map", {
       attributionControl: false,
index 34a8b68bcf8740e880fcb6e7574ce8adc169e75b..aff13add80debee64834bcf9b8852a0c4201840e 100644 (file)
@@ -32,7 +32,7 @@ window.onload = function () {
 <% end %>
   };
 
-  var map = L.map("map");
+  const map = L.map("map");
   map.attributionControl.setPrefix("");
   map.removeControl(map.attributionControl);
 
@@ -80,7 +80,7 @@ L.Control.OSMReportAProblem = L.Control.Attribution.extend({
   },
 
   onAdd: function (map) {
-    var container = L.Control.Attribution.prototype.onAdd.call(this, map);
+    const container = L.Control.Attribution.prototype.onAdd.call(this, map);
 
     map.on("moveend", this._update, this);
 
index 221b5355fe30283b1a960932365f43e06dfba994..2b3101db4bdab0fc90f587735b288a0d53c1539c 100644 (file)
@@ -1,7 +1,7 @@
 $(document).ready(function () {
-  var params = OSM.params();
+  const params = OSM.params();
 
-  var url = "/note/new";
+  let url = "/note/new";
   if (!params.zoom) params.zoom = 17;
   if (params.lat && params.lon) url += OSM.formatHash(params);
   $(".icon.note").attr("href", url);
index 15f77b1c14dda0d3542b40979d1987cdd8e13e98..f2063ff0ef17c50347d97a7c4d44674f5e0b471a 100644 (file)
@@ -3,7 +3,7 @@
 /* globals iD */
 
 document.addEventListener("DOMContentLoaded", function () {
-  var container = document.getElementById("id-container");
+  const container = document.getElementById("id-container");
 
   if (typeof iD === "undefined" || !iD.utilDetect().support) {
     container.innerHTML = "This editor is supported " +
@@ -11,16 +11,16 @@ document.addEventListener("DOMContentLoaded", function () {
       "Please upgrade your browser or use JOSM to edit the map.";
     container.className = "unsupported";
   } else {
-    var idContext = iD.coreContext();
+    const idContext = iD.coreContext();
     idContext.connection().apiConnections([]);
-    var url = location.protocol + "//" + location.host;
+    const url = location.protocol + "//" + location.host;
     idContext.preauth({
       url: url,
       apiUrl: url === "https://www.openstreetmap.org" ? "https://api.openstreetmap.org" : url,
       access_token: container.dataset.token
     });
 
-    var id = idContext
+    const id = idContext
       .embed(true)
       .assetPath("iD/")
       .assetMap(JSON.parse(container.dataset.assetMap))
@@ -33,18 +33,18 @@ document.addEventListener("DOMContentLoaded", function () {
       return;
     }
 
-    var hashChangedAutomatically = false;
+    let hashChangedAutomatically = false;
     id.map().on("move.embed", parent.$.throttle(250, function () {
       if (id.inIntro()) return;
-      var zoom = ~~id.map().zoom(),
-          center = id.map().center(),
-          llz = { lon: center[0], lat: center[1], zoom: zoom };
+      const zoom = ~~id.map().zoom(),
+            center = id.map().center(),
+            llz = { lon: center[0], lat: center[1], zoom: zoom };
 
       parent.updateLinks(llz, zoom);
 
       // Manually resolve URL to avoid iframe JS context weirdness.
       // https://gist.github.com/jfirebaugh/5439412
-      var hash = parent.OSM.formatHash(llz);
+      const hash = parent.OSM.formatHash(llz);
       if (hash !== parent.location.hash) {
         hashChangedAutomatically = true;
         parent.location.replace(parent.location.href.replace(/(#.*|$)/, hash));
@@ -63,7 +63,7 @@ document.addEventListener("DOMContentLoaded", function () {
 
     parent.$("body").on("click", "a.set_position", function (e) {
       e.preventDefault();
-      var data = parent.$(this).data();
+      const data = parent.$(this).data();
       goToLocation(data);
     });
 
@@ -73,7 +73,7 @@ document.addEventListener("DOMContentLoaded", function () {
         return;
       }
       e.preventDefault();
-      var data = parent.OSM.mapParams();
+      const data = parent.OSM.mapParams();
       goToLocation(data);
     });
   }
index 0d235834d2ce97ab150ba18ad26261a96aa24260..0fa85a0cc09295177fa1a7d3b8c9a62e742c61b4 100644 (file)
@@ -25,7 +25,7 @@
 //= require router
 
 $(document).ready(function () {
-  var map = new L.OSM.Map("map", {
+  const map = new L.OSM.Map("map", {
     zoomControl: false,
     layerControl: false,
     contextmenu: true,
@@ -33,7 +33,7 @@ $(document).ready(function () {
   });
 
   OSM.loadSidebarContent = function (path, callback) {
-    var content_path = path;
+    let content_path = path;
 
     map.setSidebarOverlaid(false);
 
@@ -81,7 +81,7 @@ $(document).ready(function () {
   const token = $("head").data("oauthToken");
   if (token) OSM.oauth = { authorization: "Bearer " + token };
 
-  var params = OSM.mapParams();
+  const params = OSM.mapParams();
 
   map.attributionControl.setPrefix("");
 
@@ -93,19 +93,19 @@ $(document).ready(function () {
     }
   });
 
-  var sidebar = L.OSM.sidebar("#map-ui")
+  const sidebar = L.OSM.sidebar("#map-ui")
     .addTo(map);
 
-  var position = $("html").attr("dir") === "rtl" ? "topleft" : "topright";
+  const position = $("html").attr("dir") === "rtl" ? "topleft" : "topright";
 
   function addControlGroup(controls) {
     for (const control of controls) control.addTo(map);
 
-    var firstContainer = controls[0].getContainer();
+    const firstContainer = controls[0].getContainer();
     $(firstContainer).find(".control-button").first()
       .addClass("control-button-first");
 
-    var lastContainer = controls[controls.length - 1].getContainer();
+    const lastContainer = controls[controls.length - 1].getContainer();
     $(lastContainer).find(".control-button").last()
       .addClass("control-button-last");
   }
@@ -169,7 +169,7 @@ $(document).ready(function () {
 
   $(".leaflet-control .control-button").tooltip({ placement: "left", container: "body" });
 
-  var expiry = new Date();
+  const expiry = new Date();
   expiry.setYear(expiry.getFullYear() + 10);
 
   map.on("moveend baselayerchange overlayadd overlayremove", function () {
@@ -191,11 +191,11 @@ $(document).ready(function () {
     Cookies.set("_osm_welcome", "hide", { secure: true, expires: expiry, path: "/", samesite: "lax" });
   });
 
-  var bannerExpiry = new Date();
+  const bannerExpiry = new Date();
   bannerExpiry.setYear(bannerExpiry.getFullYear() + 1);
 
   $("#banner .btn-close").on("click", function (e) {
-    var cookieId = e.target.id;
+    const cookieId = e.target.id;
     $("#banner").hide();
     e.preventDefault();
     if (cookieId) {
@@ -206,7 +206,7 @@ $(document).ready(function () {
   if (OSM.MATOMO) {
     map.on("baselayerchange overlayadd", function (e) {
       if (e.layer.options) {
-        var goal = OSM.MATOMO.goals[e.layer.options.layerId];
+        const goal = OSM.MATOMO.goals[e.layer.options.layerId];
 
         if (goal) {
           $("body").trigger("matomogoal", goal);
@@ -226,14 +226,14 @@ $(document).ready(function () {
   }
 
   function remoteEditHandler(bbox, object) {
-    var remoteEditHost = "http://127.0.0.1:8111",
-        osmHost = location.protocol + "//" + location.host,
-        query = new URLSearchParams({
-          left: bbox.getWest() - 0.0001,
-          top: bbox.getNorth() + 0.0001,
-          right: bbox.getEast() + 0.0001,
-          bottom: bbox.getSouth() - 0.0001
-        });
+    const remoteEditHost = "http://127.0.0.1:8111",
+          osmHost = location.protocol + "//" + location.host,
+          query = new URLSearchParams({
+            left: bbox.getWest() - 0.0001,
+            top: bbox.getNorth() + 0.0001,
+            right: bbox.getEast() + 0.0001,
+            bottom: bbox.getSouth() - 0.0001
+          });
 
     if (object && object.type !== "note") query.set("select", object.type + object.id); // can't select notes
     sendRemoteEditCommand(remoteEditHost + "/load_and_zoom?" + query, function () {
@@ -256,7 +256,7 @@ $(document).ready(function () {
   }
 
   $("a[data-editor=remote]").click(function (e) {
-    var params = OSM.mapParams(this.search);
+    const params = OSM.mapParams(this.search);
     remoteEditHandler(map.getBounds(), params.object);
     e.preventDefault();
   });
@@ -276,7 +276,7 @@ $(document).ready(function () {
   }
 
   OSM.Index = function (map) {
-    var page = {};
+    const page = {};
 
     page.pushstate = page.popstate = function () {
       map.setSidebarOverlaid(true);
@@ -298,21 +298,21 @@ $(document).ready(function () {
   };
 
   OSM.Browse = function (map, type) {
-    var page = {};
+    const page = {};
 
-    page.pushstate = page.popstate = function (path, id) {
+    page.pushstate = page.popstate = function (path, id, version) {
       OSM.loadSidebarContent(path, function () {
-        addObject(type, id);
+        addObject(type, id, version);
       });
     };
 
-    page.load = function (path, id) {
-      addObject(type, id, true);
+    page.load = function (path, id, version) {
+      addObject(type, id, version, true);
     };
 
-    function addObject(type, id, center) {
-      var hashParams = OSM.parseHash(window.location.hash);
-      map.addObject({ type: type, id: parseInt(id, 10) }, function (bounds) {
+    function addObject(type, id, version, center) {
+      const hashParams = OSM.parseHash(window.location.hash);
+      map.addObject({ type: type, id: parseInt(id, 10), version: version && parseInt(version, 10) }, function (bounds) {
         if (!hashParams.center && bounds.isValid() &&
             (center || !map.getBounds().contains(bounds))) {
           OSM.router.withoutMoveListener(function () {
@@ -330,7 +330,7 @@ $(document).ready(function () {
   };
 
   OSM.OldBrowse = function () {
-    var page = {};
+    const page = {};
 
     page.pushstate = page.popstate = function (path) {
       OSM.loadSidebarContent(path);
@@ -339,7 +339,7 @@ $(document).ready(function () {
     return page;
   };
 
-  var history = OSM.History(map);
+  const history = OSM.History(map);
 
   OSM.router = OSM.Router(map, {
     "/": OSM.Index(map),
@@ -353,7 +353,7 @@ $(document).ready(function () {
     "/user/:display_name/history": history,
     "/note/:id": OSM.Note(map),
     "/node/:id(/history)": OSM.Browse(map, "node"),
-    "/node/:id/history/:version": OSM.OldBrowse(),
+    "/node/:id/history/:version": OSM.Browse(map, "node"),
     "/way/:id(/history)": OSM.Browse(map, "way"),
     "/way/:id/history/:version": OSM.OldBrowse(),
     "/relation/:id(/history)": OSM.Browse(map, "relation"),
index 772b33f6651b3238540087404db224cbeaa1c4b1..6c1c6a2df7a2df382120f7c23da38b2cf4be859f 100644 (file)
@@ -1,6 +1,6 @@
 OSM.Changeset = function (map) {
-  var page = {},
-      content = $("#sidebar_content");
+  const page = {},
+        content = $("#sidebar_content");
 
   page.pushstate = page.popstate = function (path) {
     OSM.loadSidebarContent(path, function () {
@@ -12,7 +12,7 @@ OSM.Changeset = function (map) {
     const changesetData = content.find("[data-changeset]").data("changeset");
     changesetData.type = "changeset";
 
-    var hashParams = OSM.parseHash(window.location.hash);
+    const hashParams = OSM.parseHash(window.location.hash);
     initialize();
     map.addObject(changesetData, function (bounds) {
       if (!hashParams.center && bounds.isValid()) {
@@ -59,8 +59,8 @@ OSM.Changeset = function (map) {
   function initialize() {
     content.find("button[data-method][data-url]").on("click", function (e) {
       e.preventDefault();
-      var data = $(e.target).data();
-      var include_data = e.target.name === "comment";
+      const data = $(e.target).data();
+      const include_data = e.target.name === "comment";
       updateChangeset(data.method, data.url, include_data);
     });
 
index d7e6b427da6ce585a03b8e0581ddfd793e9d9a24..6f85a5252e15a02a42de1b9a8b26f59cb6e3486f 100644 (file)
@@ -69,7 +69,7 @@ OSM.initializeContextMenu = function (map) {
     return $(input).val();
   }
 
-  var updateMenu = function updateMenu() {
+  const updateMenu = function updateMenu() {
     map.contextmenu.setDisabled(2, map.getZoom() < 12);
     map.contextmenu.setDisabled(4, map.getZoom() < 14);
   };
index 11a70c62f051448f7b43e6d2a4b56c22902ccec9..90e95857ff9dcd5c50a21df6c4999e80ecf83605 100644 (file)
@@ -1,5 +1,5 @@
 OSM.DirectionsEndpoint = function Endpoint(map, input, iconUrl, dragCallback, changeCallback) {
-  var endpoint = {};
+  const endpoint = {};
 
   endpoint.marker = L.marker([0, 0], {
     icon: L.icon({
@@ -52,7 +52,7 @@ OSM.DirectionsEndpoint = function Endpoint(map, input, iconUrl, dragCallback, ch
 
   function inputChangeListener(e) {
     // make text the same in both text boxes
-    var value = e.target.value;
+    const value = e.target.value;
     endpoint.setValue(value);
   }
 
@@ -61,8 +61,8 @@ OSM.DirectionsEndpoint = function Endpoint(map, input, iconUrl, dragCallback, ch
     delete endpoint.geocodeRequest;
     input.removeClass("is-invalid");
 
-    var coordinatesMatch = value.match(/^\s*([+-]?\d+(?:\.\d*)?)(?:\s+|\s*[/,]\s*)([+-]?\d+(?:\.\d*)?)\s*$/);
-    var latlng = coordinatesMatch && L.latLng(coordinatesMatch[1], coordinatesMatch[2]);
+    const coordinatesMatch = value.match(/^\s*([+-]?\d+(?:\.\d*)?)(?:\s+|\s*[/,]\s*)([+-]?\d+(?:\.\d*)?)\s*$/);
+    const latlng = coordinatesMatch && L.latLng(coordinatesMatch[1], coordinatesMatch[2]);
 
     if (latlng && endpoint.cachedReverseGeocode && endpoint.cachedReverseGeocode.latlng.equals(latlng)) {
       setLatLng(latlng);
@@ -92,8 +92,8 @@ OSM.DirectionsEndpoint = function Endpoint(map, input, iconUrl, dragCallback, ch
   };
 
   endpoint.swapCachedReverseGeocodes = function (otherEndpoint) {
-    var g0 = endpoint.cachedReverseGeocode;
-    var g1 = otherEndpoint.cachedReverseGeocode;
+    const g0 = endpoint.cachedReverseGeocode;
+    const g1 = otherEndpoint.cachedReverseGeocode;
     delete endpoint.cachedReverseGeocode;
     delete otherEndpoint.cachedReverseGeocode;
     if (g0) otherEndpoint.cachedReverseGeocode = g0;
index 0ac66d9d640f3d970f2a867757e0d6ae59ffb3a6..2338f537f581224b3e141636e83b662857de8236 100644 (file)
@@ -4,59 +4,59 @@
 
 OSM.Directions = function (map) {
   let controller = null; // the AbortController for the current route request if a route request is in progress
-  var chosenEngine;
+  let chosenEngine;
 
-  var popup = L.popup({ autoPanPadding: [100, 100] });
+  const popup = L.popup({ autoPanPadding: [100, 100] });
 
-  var polyline = L.polyline([], {
+  const polyline = L.polyline([], {
     color: "#03f",
     opacity: 0.3,
     weight: 10
   });
 
-  var highlight = L.polyline([], {
+  const highlight = L.polyline([], {
     color: "#ff0",
     opacity: 0.5,
     weight: 12
   });
 
-  var endpointDragCallback = function (dragging) {
+  const endpointDragCallback = function (dragging) {
     if (!map.hasLayer(polyline)) return;
     if (dragging && !chosenEngine.draggable) return;
     if (dragging && controller) return;
 
     getRoute(false, !dragging);
   };
-  var endpointChangeCallback = function () {
+  const endpointChangeCallback = function () {
     getRoute(true, true);
   };
 
-  var endpoints = [
+  const endpoints = [
     OSM.DirectionsEndpoint(map, $("input[name='route_from']"), OSM.MARKER_GREEN, endpointDragCallback, endpointChangeCallback),
     OSM.DirectionsEndpoint(map, $("input[name='route_to']"), OSM.MARKER_RED, endpointDragCallback, endpointChangeCallback)
   ];
 
-  var expiry = new Date();
+  const expiry = new Date();
   expiry.setYear(expiry.getFullYear() + 10);
 
-  var engines = OSM.Directions.engines;
+  const engines = OSM.Directions.engines;
 
   engines.sort(function (a, b) {
-    var localised_a = I18n.t("javascripts.directions.engines." + a.id),
-        localised_b = I18n.t("javascripts.directions.engines." + b.id);
+    const localised_a = I18n.t("javascripts.directions.engines." + a.id),
+          localised_b = I18n.t("javascripts.directions.engines." + b.id);
     return localised_a.localeCompare(localised_b);
   });
 
-  var select = $("select.routing_engines");
+  const select = $("select.routing_engines");
 
   engines.forEach(function (engine, i) {
     select.append("<option value='" + i + "'>" + I18n.t("javascripts.directions.engines." + engine.id) + "</option>");
   });
 
   $(".directions_form .reverse_directions").on("click", function () {
-    var coordFrom = endpoints[0].latlng,
-        coordTo = endpoints[1].latlng,
-        routeFrom = "",
+    const coordFrom = endpoints[0].latlng,
+          coordTo = endpoints[1].latlng;
+    let routeFrom = "",
         routeTo = "";
     if (coordFrom) {
       routeFrom = coordFrom.lat + "," + coordFrom.lng;
@@ -90,8 +90,8 @@ OSM.Directions = function (map) {
   }
 
   function formatTime(s) {
-    var m = Math.round(s / 60);
-    var h = Math.floor(m / 60);
+    let m = Math.round(s / 60);
+    const h = Math.floor(m / 60);
     m -= h * 60;
     return h + ":" + (m < 10 ? "0" : "") + m;
   }
@@ -136,7 +136,7 @@ OSM.Directions = function (map) {
         map.fitBounds(polyline.getBounds().pad(0.05));
       }
 
-      var distanceText = $("<p>").append(
+      const distanceText = $("<p>").append(
         I18n.t("javascripts.directions.distance") + ": " + formatDistance(route.distance) + ". " +
         I18n.t("javascripts.directions.time") + ": " + formatTime(route.time) + ".");
       if (typeof route.ascend !== "undefined" && typeof route.descend !== "undefined") {
@@ -146,9 +146,9 @@ OSM.Directions = function (map) {
           I18n.t("javascripts.directions.descend") + ": " + formatHeight(route.descend) + ".");
       }
 
-      var turnByTurnTable = $("<table class='table table-hover table-sm mb-3'>")
+      const turnByTurnTable = $("<table class='table table-hover table-sm mb-3'>")
         .append($("<tbody>"));
-      var directionsCloseButton = $("<button type='button' class='btn-close'>")
+      const directionsCloseButton = $("<button type='button' class='btn-close'>")
         .attr("aria-label", I18n.t("javascripts.close"));
 
       $("#sidebar_content")
@@ -166,7 +166,7 @@ OSM.Directions = function (map) {
       route.steps.forEach(function (step) {
         const [ll, direction, instruction, dist, lineseg] = step;
 
-        var row = $("<tr class='turn'/>");
+        const row = $("<tr class='turn'/>");
         row.append("<td class='border-0'><div class='direction i" + direction + "'/></td> ");
         row.append("<td>" + instruction);
         row.append("<td class='distance text-body-secondary text-end'>" + getDistText(dist));
@@ -218,7 +218,7 @@ OSM.Directions = function (map) {
     }
   }
 
-  var chosenEngineIndex = findEngine("fossgis_osrm_car");
+  let chosenEngineIndex = findEngine("fossgis_osrm_car");
   if (Cookies.get("_osm_directions_engine")) {
     chosenEngineIndex = findEngine(Cookies.get("_osm_directions_engine"));
   }
@@ -236,17 +236,17 @@ OSM.Directions = function (map) {
   });
 
   $(".routing_marker_column img").on("dragstart", function (e) {
-    var dt = e.originalEvent.dataTransfer;
+    const dt = e.originalEvent.dataTransfer;
     dt.effectAllowed = "move";
-    var dragData = { type: $(this).data("type") };
+    const dragData = { type: $(this).data("type") };
     dt.setData("text", JSON.stringify(dragData));
     if (dt.setDragImage) {
-      var img = $("<img>").attr("src", $(e.originalEvent.target).attr("src"));
+      const img = $("<img>").attr("src", $(e.originalEvent.target).attr("src"));
       dt.setDragImage(img.get(0), 12, 21);
     }
   });
 
-  var page = {};
+  const page = {};
 
   page.pushstate = page.popstate = function () {
     $(".search_form").hide();
@@ -258,12 +258,12 @@ OSM.Directions = function (map) {
 
     $("#map").on("drop", function (e) {
       e.preventDefault();
-      var oe = e.originalEvent;
-      var dragData = JSON.parse(oe.dataTransfer.getData("text"));
-      var type = dragData.type;
-      var pt = L.DomEvent.getMousePosition(oe, map.getContainer()); // co-ordinates of the mouse pointer at present
+      const oe = e.originalEvent;
+      const dragData = JSON.parse(oe.dataTransfer.getData("text"));
+      const type = dragData.type;
+      const pt = L.DomEvent.getMousePosition(oe, map.getContainer()); // co-ordinates of the mouse pointer at present
       pt.y += 20;
-      var ll = map.containerPointToLatLng(pt);
+      const ll = map.containerPointToLatLng(pt);
       const llWithPrecision = OSM.cropLocation(ll, map.getZoom());
       endpoints[type === "from" ? 0 : 1].setValue(llWithPrecision.join(", "));
     });
@@ -275,7 +275,7 @@ OSM.Directions = function (map) {
           route = (params.get("route") || "").split(";");
 
     if (params.has("engine")) {
-      var engineIndex = findEngine(params.get("engine"));
+      const engineIndex = findEngine(params.get("engine"));
 
       if (engineIndex >= 0) {
         setEngine(engineIndex);
index 3b23b9cbf3abba23e53375f89cabf95eeea2d9b3..05d90381bb9d9b586c9bcd28cc92738be86dd8a6 100644 (file)
@@ -1,7 +1,7 @@
 OSM.Export = function (map) {
-  var page = {};
+  const page = {};
 
-  var locationFilter = new L.LocationFilter({
+  const locationFilter = new L.LocationFilter({
     enableButton: false,
     adjustButton: false
   }).on("change", update);
@@ -13,7 +13,7 @@ OSM.Export = function (map) {
   }
 
   function boundsChanged() {
-    var bounds = getBounds();
+    const bounds = getBounds();
     map.fitBounds(bounds);
     locationFilter.setBounds(bounds);
     locationFilter.enable();
index 52929018bbd60886c3e3528f4ccb4be0d04ed5c2..c36ae5f185683d58eddf99946e90bab7bd1bcc3c 100644 (file)
@@ -1,7 +1,7 @@
 //= require jquery-simulate/jquery.simulate
 
 OSM.History = function (map) {
-  var page = {};
+  const page = {};
 
   $("#sidebar_content")
     .on("click", ".changeset_more a", loadMore)
@@ -12,7 +12,7 @@ OSM.History = function (map) {
       unHighlightChangeset($(this).data("changeset").id);
     });
 
-  var group = L.featureGroup()
+  const group = L.featureGroup()
     .on("mouseover", function (e) {
       highlightChangeset(e.layer.id);
     })
@@ -28,13 +28,13 @@ OSM.History = function (map) {
   };
 
   function highlightChangeset(id) {
-    var layer = group.getLayer(id);
+    const layer = group.getLayer(id);
     if (layer) layer.setStyle({ fillOpacity: 0.3, color: "#FF6600", weight: 3 });
     $("#changeset_" + id).addClass("selected");
   }
 
   function unHighlightChangeset(id) {
-    var layer = group.getLayer(id);
+    const layer = group.getLayer(id);
     if (layer) layer.setStyle({ fillOpacity: 0, color: "#FF9500", weight: 2 });
     $("#changeset_" + id).removeClass("selected");
   }
@@ -49,8 +49,8 @@ OSM.History = function (map) {
 
   function displayMoreChangesets(html) {
     $("#sidebar_content .changeset_more").replaceWith(html);
-    var oldList = $("#sidebar_content .changesets ol").first();
-    var newList = oldList.next("ol");
+    const oldList = $("#sidebar_content .changesets ol").first();
+    const newList = oldList.next("ol");
     newList.children().appendTo(oldList);
     newList.remove();
   }
@@ -60,8 +60,8 @@ OSM.History = function (map) {
 
     if (window.location.pathname === "/history") {
       data.set("bbox", map.getBounds().wrap().toBBoxString());
-      var feedLink = $("link[type=\"application/atom+xml\"]"),
-          feedHref = feedLink.attr("href").split("?")[0];
+      const feedLink = $("link[type=\"application/atom+xml\"]"),
+            feedHref = feedLink.attr("href").split("?")[0];
       feedLink.attr("href", feedHref + "?" + data);
     }
 
@@ -79,7 +79,7 @@ OSM.History = function (map) {
     e.preventDefault();
     e.stopPropagation();
 
-    var div = $(this).parents(".changeset_more");
+    const div = $(this).parents(".changeset_more");
 
     $(this).hide();
     div.find(".loader").show();
@@ -90,17 +90,17 @@ OSM.History = function (map) {
     });
   }
 
-  var changesets = [];
+  let changesets = [];
 
   function updateBounds() {
     group.clearLayers();
 
     for (const changeset of changesets) {
-      var bottomLeft = map.project(L.latLng(changeset.bbox.minlat, changeset.bbox.minlon)),
-          topRight = map.project(L.latLng(changeset.bbox.maxlat, changeset.bbox.maxlon)),
-          width = topRight.x - bottomLeft.x,
-          height = bottomLeft.y - topRight.y,
-          minSize = 20; // Min width/height of changeset in pixels
+      const bottomLeft = map.project(L.latLng(changeset.bbox.minlat, changeset.bbox.minlon)),
+            topRight = map.project(L.latLng(changeset.bbox.maxlat, changeset.bbox.maxlon)),
+            width = topRight.x - bottomLeft.x,
+            height = bottomLeft.y - topRight.y,
+            minSize = 20; // Min width/height of changeset in pixels
 
       if (width < minSize) {
         bottomLeft.x -= ((minSize - width) / 2);
@@ -138,7 +138,7 @@ OSM.History = function (map) {
     updateBounds();
 
     if (window.location.pathname !== "/history") {
-      var bounds = group.getBounds();
+      const bounds = group.getBounds();
       if (bounds.isValid()) map.fitBounds(bounds);
     }
   }
index 25dc66a28ffee9e0061856257f509224989bb523..8925cc48001341a2bfd44adf2dc248d513f11010 100644 (file)
@@ -40,7 +40,7 @@ OSM.initializeDataLayer = function (map) {
   });
 
   function updateData() {
-    var bounds = map.getBounds();
+    const bounds = map.getBounds();
     if (!loadedBounds || !loadedBounds.contains(bounds)) {
       getData();
     }
@@ -78,8 +78,8 @@ OSM.initializeDataLayer = function (map) {
   }
 
   function getData() {
-    var bounds = map.getBounds();
-    var url = "/api/" + OSM.API_VERSION + "/map.json?bbox=" + bounds.toBBoxString();
+    const bounds = map.getBounds();
+    const url = "/api/" + OSM.API_VERSION + "/map.json?bbox=" + bounds.toBBoxString();
 
     /*
      * Modern browsers are quite happy showing far more than 100 features in
@@ -102,7 +102,7 @@ OSM.initializeDataLayer = function (map) {
       .then(function (data) {
         dataLayer.clearLayers();
 
-        var features = dataLayer.buildFeatures(data);
+        const features = dataLayer.buildFeatures(data);
 
         function addFeatures() {
           $("#browse_status").empty();
index 9aa1f203f5546a82a7e7788ee3c2ff9e3a54f01f..104f6f2f22cbf40d226bdfe1c411cb108c6a354f 100644 (file)
@@ -3,7 +3,7 @@ OSM.initializeNotesLayer = function (map) {
   const noteLayer = map.noteLayer;
   let notes = {};
 
-  var noteIcons = {
+  const noteIcons = {
     "new": L.icon({
       iconUrl: OSM.NEW_NOTE_MARKER,
       iconSize: [25, 40],
@@ -39,7 +39,7 @@ OSM.initializeNotesLayer = function (map) {
   });
 
   function updateMarker(old_marker, feature) {
-    var marker = old_marker;
+    let marker = old_marker;
     if (marker) {
       marker.setIcon(noteIcons[feature.properties.status]);
     } else {
@@ -67,11 +67,11 @@ OSM.initializeNotesLayer = function (map) {
   };
 
   function loadNotes() {
-    var bounds = map.getBounds();
-    var size = bounds.getSize();
+    const bounds = map.getBounds();
+    const size = bounds.getSize();
 
     if (size <= OSM.MAX_NOTE_REQUEST_AREA) {
-      var url = "/api/" + OSM.API_VERSION + "/notes.json?bbox=" + bounds.toBBoxString();
+      const url = "/api/" + OSM.API_VERSION + "/notes.json?bbox=" + bounds.toBBoxString();
 
       if (noteLoader) noteLoader.abort();
 
@@ -84,15 +84,15 @@ OSM.initializeNotesLayer = function (map) {
     }
 
     function success(json) {
-      var oldNotes = notes;
+      const oldNotes = notes;
       notes = {};
       for (const feature of json.features) {
-        var marker = oldNotes[feature.properties.id];
+        const marker = oldNotes[feature.properties.id];
         delete oldNotes[feature.properties.id];
         notes[feature.properties.id] = updateMarker(marker, feature);
       }
 
-      for (var id in oldNotes) {
+      for (const id in oldNotes) {
         noteLayer.removeLayer(oldNotes[id]);
       }
     }
index 6b24be07d28a20e6eebd37ed960d85667af7cd93..b1457d10b0233a745b5e9c4a2736637bcfe63834 100644 (file)
@@ -1,12 +1,12 @@
 OSM.NewNote = function (map) {
-  var noteLayer = map.noteLayer,
-      content = $("#sidebar_content"),
-      page = {},
-      addNoteButton = $(".control-note .control-button"),
-      newNoteMarker,
+  const noteLayer = map.noteLayer,
+        content = $("#sidebar_content"),
+        page = {},
+        addNoteButton = $(".control-note .control-button");
+  let newNoteMarker,
       halo;
 
-  var noteIcons = {
+  const noteIcons = {
     "new": L.icon({
       iconUrl: OSM.NEW_NOTE_MARKER,
       iconSize: [25, 40],
@@ -34,7 +34,7 @@ OSM.NewNote = function (map) {
   });
 
   function createNote(location, text, callback) {
-    fetch("/api/0.6/notes.json?", {
+    fetch("/api/0.6/notes.json", {
       method: "POST",
       headers: { ...OSM.oauth },
       body: new URLSearchParams({
@@ -48,7 +48,7 @@ OSM.NewNote = function (map) {
   }
 
   function addCreatedNoteMarker(feature) {
-    var marker = L.marker(feature.geometry.coordinates.reverse(), {
+    const marker = L.marker(feature.geometry.coordinates.reverse(), {
       icon: noteIcons[feature.properties.status],
       opacity: 0.9,
       interactive: true
@@ -132,7 +132,7 @@ OSM.NewNote = function (map) {
     map.addLayer(noteLayer);
 
     const params = new URLSearchParams(path.substring(path.indexOf("?")));
-    var markerLatlng;
+    let markerLatlng;
 
     if (params.has("lat") && params.has("lon")) {
       markerLatlng = L.latLng(params.get("lat"), params.get("lon"));
@@ -161,7 +161,7 @@ OSM.NewNote = function (map) {
 
       createNote(location, text, (feature) => {
         if (typeof OSM.user === "undefined") {
-          var anonymousNotesCount = Number(Cookies.get("_osm_anonymous_notes_count")) || 0;
+          const anonymousNotesCount = Number(Cookies.get("_osm_anonymous_notes_count")) || 0;
           Cookies.set("_osm_anonymous_notes_count", anonymousNotesCount + 1, { secure: true, expires: 30, path: "/", samesite: "lax" });
         }
         content.find("textarea").val("");
index db5a62456b5a636c59f2c47944c3f1616827fb06..b9310a1af9e159d159dcef7254988d8623dc3983 100644 (file)
@@ -1,8 +1,8 @@
 OSM.Note = function (map) {
-  var content = $("#sidebar_content"),
-      page = {};
+  const content = $("#sidebar_content"),
+        page = {};
 
-  var noteIcons = {
+  const noteIcons = {
     "new": L.icon({
       iconUrl: OSM.NEW_NOTE_MARKER,
       iconSize: [25, 40],
@@ -22,16 +22,10 @@ OSM.Note = function (map) {
 
   page.pushstate = page.popstate = function (path, id) {
     OSM.loadSidebarContent(path, function () {
-      initialize(path, id);
-
-      var data = $(".details").data();
+      const data = $(".details").data();
       if (!data) return;
-      var latLng = L.latLng(data.coordinates.split(","));
-      if (!map.getBounds().contains(latLng)) {
-        OSM.router.withoutMoveListener(function () {
-          map.setView(latLng, 15, { reset: true });
-        });
-      }
+      const latLng = L.latLng(data.coordinates.split(","));
+      initialize(path, id, map.getBounds().contains(latLng));
     });
   };
 
@@ -39,7 +33,7 @@ OSM.Note = function (map) {
     initialize(path, id);
   };
 
-  function initialize(path, id) {
+  function initialize(path, id, skipMoveToNote) {
     content.find("button[name]").on("click", function (e) {
       e.preventDefault();
       const { url, method } = $(e.target).data(),
@@ -64,7 +58,7 @@ OSM.Note = function (map) {
         })
         .then(() => {
           OSM.loadSidebarContent(path, () => {
-            initialize(path, id);
+            initialize(path, id, false);
           });
         })
         .catch(error => {
@@ -82,18 +76,18 @@ OSM.Note = function (map) {
 
     content.find("textarea").val("").trigger("input");
 
-    var data = $(".details").data();
+    const data = $(".details").data();
 
     if (data) {
-      var hashParams = OSM.parseHash(window.location.hash);
+      const hashParams = OSM.parseHash(window.location.hash);
       map.addObject({
         type: "note",
         id: parseInt(id, 10),
         latLng: L.latLng(data.coordinates.split(",")),
         icon: noteIcons[data.status]
       }, function () {
-        if (!hashParams.center) {
-          var latLng = L.latLng(data.coordinates.split(","));
+        if (!hashParams.center && !skipMoveToNote) {
+          const latLng = L.latLng(data.coordinates.split(","));
           OSM.router.withoutMoveListener(function () {
             map.setView(latLng, 15, { reset: true });
           });
@@ -103,8 +97,8 @@ OSM.Note = function (map) {
   }
 
   function updateButtons() {
-    var resolveButton = content.find("button[name='close']");
-    var commentButton = content.find("button[name='comment']");
+    const resolveButton = content.find("button[name='close']");
+    const commentButton = content.find("button[name='comment']");
 
     content.find("button[name]").prop("disabled", false);
     if (content.find("textarea").val() === "") {
index 3673da5db85838b2b72b6bf6667e9196a6124562..ee9d3f41560c9a6ef9441b9fcac2d36dc1c13154 100644 (file)
@@ -1,11 +1,11 @@
 OSM.Query = function (map) {
-  var url = OSM.OVERPASS_URL,
-      credentials = OSM.OVERPASS_CREDENTIALS,
-      queryButton = $(".control-query .control-button"),
-      uninterestingTags = ["source", "source_ref", "source:ref", "history", "attribution", "created_by", "tiger:county", "tiger:tlid", "tiger:upload_uuid", "KSJ2:curve_id", "KSJ2:lat", "KSJ2:lon", "KSJ2:coordinate", "KSJ2:filename", "note:ja"],
-      marker;
+  const url = OSM.OVERPASS_URL,
+        credentials = OSM.OVERPASS_CREDENTIALS,
+        queryButton = $(".control-query .control-button"),
+        uninterestingTags = ["source", "source_ref", "source:ref", "history", "attribution", "created_by", "tiger:county", "tiger:tlid", "tiger:upload_uuid", "KSJ2:curve_id", "KSJ2:lat", "KSJ2:lon", "KSJ2:coordinate", "KSJ2:filename", "note:ja"];
+  let marker;
 
-  var featureStyle = {
+  const featureStyle = {
     color: "#FF6200",
     weight: 4,
     opacity: 1,
@@ -37,13 +37,13 @@ OSM.Query = function (map) {
   });
 
   function showResultGeometry() {
-    var geometry = $(this).data("geometry");
+    const geometry = $(this).data("geometry");
     if (geometry) map.addLayer(geometry);
     $(this).addClass("selected");
   }
 
   function hideResultGeometry() {
-    var geometry = $(this).data("geometry");
+    const geometry = $(this).data("geometry");
     if (geometry) map.removeLayer(geometry);
     $(this).removeClass("selected");
   }
@@ -54,7 +54,7 @@ OSM.Query = function (map) {
 
   function interestingFeature(feature) {
     if (feature.tags) {
-      for (var key in feature.tags) {
+      for (const key in feature.tags) {
         if (uninterestingTags.indexOf(key) < 0) {
           return true;
         }
@@ -65,19 +65,18 @@ OSM.Query = function (map) {
   }
 
   function featurePrefix(feature) {
-    var tags = feature.tags;
-    var prefix = "";
+    const tags = feature.tags;
+    let prefix = "";
 
     if (tags.boundary === "administrative" && tags.admin_level) {
       prefix = I18n.t("geocoder.search_osm_nominatim.admin_levels.level" + tags.admin_level, {
         defaultValue: I18n.t("geocoder.search_osm_nominatim.prefix.boundary.administrative")
       });
     } else {
-      var prefixes = I18n.t("geocoder.search_osm_nominatim.prefix");
-      var key, value;
+      const prefixes = I18n.t("geocoder.search_osm_nominatim.prefix");
 
-      for (key in tags) {
-        value = tags[key];
+      for (const key in tags) {
+        const value = tags[key];
 
         if (prefixes[key]) {
           if (prefixes[key][value]) {
@@ -86,12 +85,12 @@ OSM.Query = function (map) {
         }
       }
 
-      for (key in tags) {
-        value = tags[key];
+      for (const key in tags) {
+        const value = tags[key];
 
         if (prefixes[key]) {
-          var first = value.slice(0, 1).toUpperCase(),
-              rest = value.slice(1).replace(/_/g, " ");
+          const first = value.slice(0, 1).toUpperCase(),
+                rest = value.slice(1).replace(/_/g, " ");
 
           return first + rest;
         }
@@ -106,8 +105,8 @@ OSM.Query = function (map) {
   }
 
   function featureName(feature) {
-    var tags = feature.tags,
-        locales = OSM.preferred_languages;
+    const tags = feature.tags,
+          locales = OSM.preferred_languages;
 
     for (const locale of locales) {
       if (tags["name:" + locale]) {
@@ -128,7 +127,7 @@ OSM.Query = function (map) {
   }
 
   function featureGeometry(feature) {
-    var geometry;
+    let geometry;
 
     if (feature.type === "node" && feature.lat && feature.lon) {
       geometry = L.circleMarker([feature.lat, feature.lon], featureStyle);
@@ -148,7 +147,7 @@ OSM.Query = function (map) {
   }
 
   function runQuery(latlng, radius, query, $section, merge, compare) {
-    var $ul = $section.find("ul");
+    const $ul = $section.find("ul");
 
     $ul.empty();
     $section.show();
@@ -168,13 +167,13 @@ OSM.Query = function (map) {
     })
       .then(response => response.json())
       .then(function (results) {
-        var elements;
+        let elements;
 
         $section.find(".loader").hide();
 
         if (merge) {
           elements = results.elements.reduce(function (hash, element) {
-            var key = element.type + element.id;
+            const key = element.type + element.id;
             if ("geometry" in element) {
               delete element.bounds;
             }
@@ -196,7 +195,7 @@ OSM.Query = function (map) {
         for (const element of elements) {
           if (!interestingFeature(element)) continue;
 
-          var $li = $("<li>")
+          const $li = $("<li>")
             .addClass("list-group-item list-group-item-action")
             .text(featurePrefix(element) + " ")
             .appendTo($ul);
@@ -236,12 +235,12 @@ OSM.Query = function (map) {
   }
 
   function compareSize(feature1, feature2) {
-    var width1 = feature1.bounds.maxlon - feature1.bounds.minlon,
-        height1 = feature1.bounds.maxlat - feature1.bounds.minlat,
-        area1 = width1 * height1,
-        width2 = feature2.bounds.maxlat - feature2.bounds.minlat,
-        height2 = feature2.bounds.maxlat - feature2.bounds.minlat,
-        area2 = width2 * height2;
+    const width1 = feature1.bounds.maxlon - feature1.bounds.minlon,
+          height1 = feature1.bounds.maxlat - feature1.bounds.minlat,
+          area1 = width1 * height1,
+          width2 = feature2.bounds.maxlat - feature2.bounds.minlat,
+          height2 = feature2.bounds.maxlat - feature2.bounds.minlat,
+          area2 = width2 * height2;
 
     return area1 - area2;
   }
@@ -267,20 +266,20 @@ OSM.Query = function (map) {
    * for each object.
    */
   function queryOverpass(lat, lng) {
-    var latlng = L.latLng(lat, lng).wrap(),
-        bounds = map.getBounds().wrap(),
-        zoom = map.getZoom(),
-        bbox = [bounds.getSouthWest(), bounds.getNorthEast()]
-          .map(c => OSM.cropLocation(c, zoom))
-          .join(),
-        geombbox = "geom(" + bbox + ");",
-        radius = 10 * Math.pow(1.5, 19 - zoom),
-        around = "(around:" + radius + "," + lat + "," + lng + ")",
-        nodes = "node" + around,
-        ways = "way" + around,
-        relations = "relation" + around,
-        nearby = "(" + nodes + ";" + ways + ";);out tags " + geombbox + relations + ";out " + geombbox,
-        isin = "is_in(" + lat + "," + lng + ")->.a;way(pivot.a);out tags bb;out ids " + geombbox + "relation(pivot.a);out tags bb;";
+    const latlng = L.latLng(lat, lng).wrap(),
+          bounds = map.getBounds().wrap(),
+          zoom = map.getZoom(),
+          bbox = [bounds.getSouthWest(), bounds.getNorthEast()]
+            .map(c => OSM.cropLocation(c, zoom))
+            .join(),
+          geombbox = "geom(" + bbox + ");",
+          radius = 10 * Math.pow(1.5, 19 - zoom),
+          around = "(around:" + radius + "," + lat + "," + lng + ")",
+          nodes = "node" + around,
+          ways = "way" + around,
+          relations = "relation" + around,
+          nearby = "(" + nodes + ";" + ways + ";);out tags " + geombbox + relations + ";out " + geombbox,
+          isin = "is_in(" + lat + "," + lng + ")->.a;way(pivot.a);out tags bb;out ids " + geombbox + "relation(pivot.a);out tags bb;";
 
     $("#sidebar_content .query-intro")
       .hide();
@@ -315,7 +314,7 @@ OSM.Query = function (map) {
     queryButton.removeClass("active");
   }
 
-  var page = {};
+  const page = {};
 
   page.pushstate = page.popstate = function (path) {
     OSM.loadSidebarContent(path, function () {
index 3c1af5056ad57b06b4d615c5788000ca9262d861..42294576b7bb0fba584a1c181107b9c66f06db7a 100644 (file)
@@ -9,7 +9,7 @@ OSM.Search = function (map) {
 
   $(".search_form a.btn.switch_link").on("click", function (e) {
     e.preventDefault();
-    var query = $(this).closest("form").find("input[name=query]").val();
+    const query = $(this).closest("form").find("input[name=query]").val();
     let search = "";
     if (query) search = "?" + new URLSearchParams({ from: query });
     OSM.router.route("/directions" + search + OSM.formatHash(map));
@@ -18,7 +18,7 @@ OSM.Search = function (map) {
   $(".search_form").on("submit", function (e) {
     e.preventDefault();
     $("header").addClass("closed");
-    var query = $(this).find("input[name=query]").val();
+    const query = $(this).find("input[name=query]").val();
     let search = "/";
     if (query) search = "/search?" + new URLSearchParams({ query });
     OSM.router.route(search + OSM.formatHash(map));
@@ -38,16 +38,16 @@ OSM.Search = function (map) {
     .on("mouseover", "li.search_results_entry:has(a.set_position)", showSearchResult)
     .on("mouseout", "li.search_results_entry:has(a.set_position)", hideSearchResult);
 
-  var markers = L.layerGroup().addTo(map);
+  const markers = L.layerGroup().addTo(map);
 
   function clickSearchMore(e) {
     e.preventDefault();
     e.stopPropagation();
 
-    var div = $(this).parents(".search_more"),
-        csrf_param = $("meta[name=csrf-param]").attr("content"),
-        csrf_token = $("meta[name=csrf-token]").attr("content"),
-        params = new URLSearchParams();
+    const div = $(this).parents(".search_more"),
+          csrf_param = $("meta[name=csrf-param]").attr("content"),
+          csrf_token = $("meta[name=csrf-token]").attr("content"),
+          params = new URLSearchParams();
 
     $(this).hide();
     div.find(".loader").show();
@@ -63,10 +63,10 @@ OSM.Search = function (map) {
   }
 
   function showSearchResult() {
-    var marker = $(this).data("marker");
+    let marker = $(this).data("marker");
 
     if (!marker) {
-      var data = $(this).find("a.set_position").data();
+      const data = $(this).find("a.set_position").data();
 
       marker = L.marker([data.lat, data.lon], { icon: OSM.getUserIcon() });
 
@@ -77,7 +77,7 @@ OSM.Search = function (map) {
   }
 
   function hideSearchResult() {
-    var marker = $(this).data("marker");
+    const marker = $(this).data("marker");
 
     if (marker) {
       markers.removeLayer(marker);
@@ -93,7 +93,7 @@ OSM.Search = function (map) {
   }
 
   function clickSearchResult(e) {
-    var data = $(this).data();
+    const data = $(this).data();
 
     panToSearchResult(data);
 
@@ -104,7 +104,7 @@ OSM.Search = function (map) {
     e.stopPropagation();
   }
 
-  var page = {};
+  const page = {};
 
   page.pushstate = page.popstate = function (path) {
     const params = new URLSearchParams(path.substring(path.indexOf("?")));
@@ -120,16 +120,16 @@ OSM.Search = function (map) {
 
   page.load = function () {
     $(".search_results_entry").each(function (index) {
-      var entry = $(this),
-          csrf_param = $("meta[name=csrf-param]").attr("content"),
-          csrf_token = $("meta[name=csrf-token]").attr("content"),
-          params = new URLSearchParams({
-            zoom: map.getZoom(),
-            minlon: map.getBounds().getWest(),
-            minlat: map.getBounds().getSouth(),
-            maxlon: map.getBounds().getEast(),
-            maxlat: map.getBounds().getNorth()
-          });
+      const entry = $(this),
+            csrf_param = $("meta[name=csrf-param]").attr("content"),
+            csrf_token = $("meta[name=csrf-token]").attr("content"),
+            params = new URLSearchParams({
+              zoom: map.getZoom(),
+              minlon: map.getBounds().getWest(),
+              minlat: map.getBounds().getSouth(),
+              maxlon: map.getBounds().getEast(),
+              maxlat: map.getBounds().getNorth()
+            });
       params.set(csrf_param, csrf_token);
       fetch(entry.data("href"), {
         method: "POST",
@@ -140,7 +140,7 @@ OSM.Search = function (map) {
           entry.html(html);
           // go to first result of first geocoder
           if (index === 0) {
-            var firstResult = entry.find("*[data-lat][data-lon]:first").first();
+            const firstResult = entry.find("*[data-lat][data-lon]:first").first();
             if (firstResult.length) {
               panToSearchResult(firstResult.data());
             }
index 090583ced1ed65923900643c9c95016e71581b95..937d9b0528127754462ac1b71874446507f4712d 100644 (file)
@@ -1,8 +1,8 @@
 L.OSM.key = function (options) {
-  var control = L.OSM.sidebarPane(options, "key", null, "javascripts.key.title");
+  const control = L.OSM.sidebarPane(options, "key", null, "javascripts.key.title");
 
   control.onAddPane = function (map, button, $ui) {
-    var $section = $("<div>")
+    const $section = $("<div>")
       .attr("class", "p-3")
       .appendTo($ui);
 
@@ -24,7 +24,7 @@ L.OSM.key = function (options) {
     }
 
     function updateButton() {
-      var disabled = OSM.LAYERS_WITH_MAP_KEY.indexOf(map.getMapBaseLayerId()) === -1;
+      const disabled = OSM.LAYERS_WITH_MAP_KEY.indexOf(map.getMapBaseLayerId()) === -1;
       button
         .toggleClass("disabled", disabled)
         .attr("data-bs-original-title",
@@ -34,11 +34,11 @@ L.OSM.key = function (options) {
     }
 
     function update() {
-      var layerId = map.getMapBaseLayerId(),
-          zoom = map.getZoom();
+      const layerId = map.getMapBaseLayerId(),
+            zoom = map.getZoom();
 
       $(".mapkey-table-entry").each(function () {
-        var data = $(this).data();
+        const data = $(this).data();
         $(this).toggle(
           layerId === data.layer &&
           (!data.zoomMin || zoom >= data.zoomMin) &&
index a7a2335f3d843fedff03c1816aea7cc00184dd23..f7142ead157b0ba64b8cc19583531ada1f39520e 100644 (file)
@@ -1,34 +1,34 @@
 L.OSM.layers = function (options) {
-  var control = L.OSM.sidebarPane(options, "layers", "javascripts.map.layers.title", "javascripts.map.layers.header");
+  const control = L.OSM.sidebarPane(options, "layers", "javascripts.map.layers.title", "javascripts.map.layers.header");
 
   control.onAddPane = function (map, button, $ui, toggle) {
-    var layers = options.layers;
+    const layers = options.layers;
 
-    var baseSection = $("<div>")
+    const baseSection = $("<div>")
       .attr("class", "base-layers d-grid gap-3 p-3 border-bottom border-secondary-subtle")
       .appendTo($ui);
 
     layers.forEach(function (layer, i) {
-      var id = "map-ui-layer-" + i;
+      const id = "map-ui-layer-" + i;
 
-      var buttonContainer = $("<div class='position-relative'>")
+      const buttonContainer = $("<div class='position-relative'>")
         .appendTo(baseSection);
 
-      var mapContainer = $("<div class='position-absolute top-0 start-0 bottom-0 end-0 z-0 bg-body-secondary'>")
+      const mapContainer = $("<div class='position-absolute top-0 start-0 bottom-0 end-0 z-0 bg-body-secondary'>")
         .appendTo(buttonContainer);
 
-      var input = $("<input type='radio' class='btn-check' name='layer'>")
+      const input = $("<input type='radio' class='btn-check' name='layer'>")
         .prop("id", id)
         .prop("checked", map.hasLayer(layer))
         .appendTo(buttonContainer);
 
-      var item = $("<label class='btn btn-outline-primary border-4 rounded-3 bg-transparent position-absolute p-0 h-100 w-100 overflow-hidden'>")
+      const item = $("<label class='btn btn-outline-primary border-4 rounded-3 bg-transparent position-absolute p-0 h-100 w-100 overflow-hidden'>")
         .prop("for", id)
         .append($("<span class='badge position-absolute top-0 start-0 rounded-top-0 rounded-start-0 py-1 px-2 bg-body bg-opacity-75 text-body text-wrap text-start fs-6 lh-base'>").append(layer.options.name))
         .appendTo(buttonContainer);
 
       map.whenReady(function () {
-        var miniMap = L.map(mapContainer[0], { attributionControl: false, zoomControl: false, keyboard: false })
+        const miniMap = L.map(mapContainer[0], { attributionControl: false, zoomControl: false, keyboard: false })
           .addLayer(new layer.constructor(layer.options));
 
         miniMap.dragging.disable();
@@ -76,7 +76,7 @@ L.OSM.layers = function (options) {
     });
 
     if (OSM.STATUS !== "api_offline" && OSM.STATUS !== "database_offline") {
-      var overlaySection = $("<div>")
+      const overlaySection = $("<div>")
         .attr("class", "overlay-layers p-3")
         .appendTo($ui);
 
@@ -85,11 +85,11 @@ L.OSM.layers = function (options) {
         .attr("class", "text-body-secondary small mb-2")
         .appendTo(overlaySection);
 
-      var overlays = $("<ul class='list-unstyled form-check'>")
+      const overlays = $("<ul class='list-unstyled form-check'>")
         .appendTo(overlaySection);
 
-      var addOverlay = function (layer, name, maxArea) {
-        var item = $("<li>")
+      const addOverlay = function (layer, name, maxArea) {
+        const item = $("<li>")
           .appendTo(overlays);
 
         if (name === "notes" || name === "data") {
@@ -98,13 +98,13 @@ L.OSM.layers = function (options) {
             .tooltip("disable");
         }
 
-        var label = $("<label>")
+        const label = $("<label>")
           .attr("class", "form-check-label")
           .appendTo(item);
 
-        var checked = map.hasLayer(layer);
+        let checked = map.hasLayer(layer);
 
-        var input = $("<input>")
+        const input = $("<input>")
           .attr("type", "checkbox")
           .attr("class", "form-check-input")
           .prop("checked", checked)
@@ -126,7 +126,7 @@ L.OSM.layers = function (options) {
         });
 
         map.on("zoomend", function () {
-          var disabled = map.getBounds().getSize() >= maxArea;
+          const disabled = map.getBounds().getSize() >= maxArea;
           $(input).prop("disabled", disabled);
 
           if (disabled && $(input).is(":checked")) {
index d199292083d93bbbded0586326f6f5e09a0056dc..81b4f1a4eef496fd1691c54e61c9cac43d00e960 100644 (file)
@@ -1,5 +1,5 @@
 L.OSM.locate = function (options) {
-  var control = L.control.locate({
+  const control = L.control.locate({
     icon: "icon geolocate",
     iconLoading: "icon geolocate",
     strings: {
@@ -12,7 +12,7 @@ L.OSM.locate = function (options) {
   });
 
   control.onAdd = function (map) {
-    var container = Object.getPrototypeOf(this).onAdd.apply(this, [map]);
+    const container = Object.getPrototypeOf(this).onAdd.apply(this, [map]);
     $(container)
       .removeClass("leaflet-control-locate leaflet-bar")
       .addClass("control-locate")
index 1b92edf9945ae7f7b996f9cff7a454b1254979d7..34c0bd449174a962e61124d3bd14f575999112ce 100644 (file)
@@ -128,7 +128,7 @@ L.OSM.Map = L.Map.extend({
   },
 
   getLayersCode: function () {
-    var layerConfig = "";
+    let layerConfig = "";
     this.eachLayer(function (layer) {
       if (layer.options && layer.options.code) {
         layerConfig += layer.options.code;
@@ -155,9 +155,9 @@ L.OSM.Map = L.Map.extend({
       [params.mlat, params.mlon] = OSM.cropLocation(marker.getLatLng(), this.getZoom());
     }
 
-    var url = window.location.protocol + "//" + OSM.SERVER_URL + "/",
-        query = new URLSearchParams(params),
-        hash = OSM.formatHash(this);
+    let url = window.location.protocol + "//" + OSM.SERVER_URL + "/";
+    const query = new URLSearchParams(params),
+          hash = OSM.formatHash(this);
 
     if (query) url += "?" + query;
     if (hash) url += hash;
@@ -166,33 +166,31 @@ L.OSM.Map = L.Map.extend({
   },
 
   getShortUrl: function (marker) {
-    var zoom = this.getZoom(),
-        latLng = marker && this.hasLayer(marker) ? marker.getLatLng().wrap() : this.getCenter().wrap(),
-        str = window.location.protocol + "//" + window.location.hostname.replace(/^www\.openstreetmap\.org/i, "osm.org") + "/go/",
-        char_array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_~",
-        x = Math.round((latLng.lng + 180.0) * ((1 << 30) / 90.0)),
-        y = Math.round((latLng.lat + 90.0) * ((1 << 30) / 45.0)),
-        // JavaScript only has to keep 32 bits of bitwise operators, so this has to be
-        // done in two parts. each of the parts c1/c2 has 30 bits of the total in it
-        // and drops the last 4 bits of the full 64 bit Morton code.
-        c1 = interlace(x >>> 17, y >>> 17),
-        c2 = interlace((x >>> 2) & 0x7fff, (y >>> 2) & 0x7fff),
-        digit,
-        i;
-
-    for (i = 0; i < Math.ceil((zoom + 8) / 3.0) && i < 5; ++i) {
-      digit = (c1 >> (24 - (6 * i))) & 0x3f;
+    const zoom = this.getZoom(),
+          latLng = marker && this.hasLayer(marker) ? marker.getLatLng().wrap() : this.getCenter().wrap(),
+          char_array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_~",
+          x = Math.round((latLng.lng + 180.0) * ((1 << 30) / 90.0)),
+          y = Math.round((latLng.lat + 90.0) * ((1 << 30) / 45.0)),
+          // JavaScript only has to keep 32 bits of bitwise operators, so this has to be
+          // done in two parts. each of the parts c1/c2 has 30 bits of the total in it
+          // and drops the last 4 bits of the full 64 bit Morton code.
+          c1 = interlace(x >>> 17, y >>> 17),
+          c2 = interlace((x >>> 2) & 0x7fff, (y >>> 2) & 0x7fff);
+    let str = window.location.protocol + "//" + window.location.hostname.replace(/^www\.openstreetmap\.org/i, "osm.org") + "/go/";
+
+    for (let i = 0; i < Math.ceil((zoom + 8) / 3.0) && i < 5; ++i) {
+      const digit = (c1 >> (24 - (6 * i))) & 0x3f;
       str += char_array.charAt(digit);
     }
-    for (i = 5; i < Math.ceil((zoom + 8) / 3.0); ++i) {
-      digit = (c2 >> (24 - (6 * (i - 5)))) & 0x3f;
+    for (let i = 5; i < Math.ceil((zoom + 8) / 3.0); ++i) {
+      const digit = (c2 >> (24 - (6 * (i - 5)))) & 0x3f;
       str += char_array.charAt(digit);
     }
-    for (i = 0; i < ((zoom + 8) % 3); ++i) str += "-";
+    for (let i = 0; i < ((zoom + 8) % 3); ++i) str += "-";
 
     // Called to interlace the bits in x and y, making a Morton code.
     function interlace(x, y) {
-      var interlaced_x = x,
+      let interlaced_x = x,
           interlaced_y = y;
       interlaced_x = (interlaced_x | (interlaced_x << 8)) & 0x00ff00ff;
       interlaced_x = (interlaced_x | (interlaced_x << 4)) & 0x0f0f0f0f;
@@ -206,7 +204,7 @@ L.OSM.Map = L.Map.extend({
     }
 
     const params = new URLSearchParams();
-    var layers = this.getLayersCode().replace("M", "");
+    const layers = this.getLayersCode().replace("M", "");
 
     if (layers) {
       params.set("layers", layers);
@@ -240,14 +238,14 @@ L.OSM.Map = L.Map.extend({
   },
 
   addObject: function (object, callback) {
-    var objectStyle = {
+    const objectStyle = {
       color: "#FF6200",
       weight: 4,
       opacity: 1,
       fillOpacity: 0.5
     };
 
-    var changesetStyle = {
+    const changesetStyle = {
       weight: 4,
       color: "#FF9500",
       opacity: 1,
@@ -255,7 +253,7 @@ L.OSM.Map = L.Map.extend({
       interactive: false
     };
 
-    var haloStyle = {
+    const haloStyle = {
       weight: 2.5,
       radius: 20,
       fillOpacity: 0.5,
@@ -292,7 +290,7 @@ L.OSM.Map = L.Map.extend({
       if (callback) callback(this._objectLayer.getBounds());
       this.fire("overlayadd", { layer: this._objectLayer });
     } else { // element handled by L.OSM.DataLayer
-      var map = this;
+      const map = this;
       this._objectLoader = new AbortController();
       fetch(OSM.apiUrl(object), {
         headers: { accept: "application/json" },
@@ -347,10 +345,10 @@ L.OSM.Map = L.Map.extend({
   },
 
   setSidebarOverlaid: function (overlaid) {
-    var mediumDeviceWidth = window.getComputedStyle(document.documentElement).getPropertyValue("--bs-breakpoint-md");
-    var isMediumDevice = window.matchMedia(`(max-width: ${mediumDeviceWidth})`).matches;
-    var sidebarWidth = $("#sidebar").width();
-    var sidebarHeight = $("#sidebar").height();
+    const mediumDeviceWidth = window.getComputedStyle(document.documentElement).getPropertyValue("--bs-breakpoint-md");
+    const isMediumDevice = window.matchMedia(`(max-width: ${mediumDeviceWidth})`).matches;
+    const sidebarWidth = $("#sidebar").width();
+    const sidebarHeight = $("#sidebar").height();
     if (overlaid && !$("#content").hasClass("overlay-sidebar")) {
       $("#content").addClass("overlay-sidebar");
       this.invalidateSize({ pan: false });
@@ -384,15 +382,15 @@ L.extend(L.Icon.Default.prototype, {
   _oldGetIconUrl: L.Icon.Default.prototype._getIconUrl,
 
   _getIconUrl: function (name) {
-    var url = this._oldGetIconUrl(name);
+    const url = this._oldGetIconUrl(name);
     return L.Icon.Default.imageUrls[url];
   }
 });
 
 OSM.isDarkMap = function () {
-  var mapTheme = $("body").attr("data-map-theme");
+  const mapTheme = $("body").attr("data-map-theme");
   if (mapTheme) return mapTheme === "dark";
-  var siteTheme = $("html").attr("data-bs-theme");
+  const siteTheme = $("html").attr("data-bs-theme");
   if (siteTheme) return siteTheme === "dark";
   return window.matchMedia("(prefers-color-scheme: dark)").matches;
 };
index 801c6e6dbb0e721d66ad67d19770be32dd5c6c06..e2ca4ffdfda3409580525a33df000b08d1e66c6f 100644 (file)
@@ -1,11 +1,11 @@
 L.OSM.note = function (options) {
-  var control = L.control(options);
+  const control = L.control(options);
 
   control.onAdd = function (map) {
-    var $container = $("<div>")
+    const $container = $("<div>")
       .attr("class", "control-note");
 
-    var link = $("<a>")
+    const link = $("<a>")
       .attr("class", "control-button")
       .attr("href", "#")
       .html("<span class=\"icon note\"></span>")
@@ -14,8 +14,8 @@ L.OSM.note = function (options) {
     map.on("zoomend", update);
 
     function update() {
-      var wasDisabled = link.hasClass("disabled"),
-          isDisabled = OSM.STATUS === "database_offline" || map.getZoom() < 12;
+      const wasDisabled = link.hasClass("disabled"),
+            isDisabled = OSM.STATUS === "database_offline" || map.getZoom() < 12;
       link
         .toggleClass("disabled", isDisabled)
         .attr("data-bs-original-title", I18n.t(isDisabled ?
index 87f45ce9970aa2a0250038836b1d023f6afae4a5..04176487757aac1b95c2d440e2115ecbfaa2c19f 100644 (file)
@@ -1,11 +1,11 @@
 L.OSM.query = function (options) {
-  var control = L.control(options);
+  const control = L.control(options);
 
   control.onAdd = function (map) {
-    var $container = $("<div>")
+    const $container = $("<div>")
       .attr("class", "control-query");
 
-    var link = $("<a>")
+    const link = $("<a>")
       .attr("class", "control-button")
       .attr("href", "#")
       .html("<span class=\"icon query\"></span>")
@@ -14,8 +14,8 @@ L.OSM.query = function (options) {
     map.on("zoomend", update);
 
     function update() {
-      var wasDisabled = link.hasClass("disabled"),
-          isDisabled = map.getZoom() < 14;
+      const wasDisabled = link.hasClass("disabled"),
+            isDisabled = map.getZoom() < 14;
       link
         .toggleClass("disabled", isDisabled)
         .attr("data-bs-original-title", I18n.t(isDisabled ?
index e89608afda7dce94c127d208942be2ee9083c91e..325b168b2637aaf973da902cab3a5fe69f8b1b85 100644 (file)
@@ -1,16 +1,16 @@
 L.OSM.share = function (options) {
-  var control = L.OSM.sidebarPane(options, "share", "javascripts.share.title", "javascripts.share.title"),
-      marker = L.marker([0, 0], { draggable: true }),
-      locationFilter = new L.LocationFilter({
-        enableButton: false,
-        adjustButton: false
-      });
+  const control = L.OSM.sidebarPane(options, "share", "javascripts.share.title", "javascripts.share.title"),
+        marker = L.marker([0, 0], { draggable: true }),
+        locationFilter = new L.LocationFilter({
+          enableButton: false,
+          adjustButton: false
+        });
 
   control.onAddPane = function (map, button, $ui) {
     // Link / Embed
     $("#content").addClass("overlay-right-sidebar");
 
-    var $linkSection = $("<div>")
+    const $linkSection = $("<div>")
       .attr("class", "share-link p-3 border-bottom border-secondary-subtle")
       .appendTo($ui);
 
@@ -18,7 +18,7 @@ L.OSM.share = function (options) {
       .text(I18n.t("javascripts.share.link"))
       .appendTo($linkSection);
 
-    var $form = $("<form>")
+    let $form = $("<form>")
       .appendTo($linkSection);
 
     $("<div>")
@@ -54,7 +54,7 @@ L.OSM.share = function (options) {
       .on("click", "a", function (e) {
         e.preventDefault();
         if (!$(this).hasClass("btn-primary")) return;
-        var id = "#" + $(this).attr("for");
+        const id = "#" + $(this).attr("for");
         $(this).siblings("a")
           .removeClass("active");
         $(this).addClass("active");
@@ -104,7 +104,7 @@ L.OSM.share = function (options) {
 
     // Geo URI
 
-    var $geoUriSection = $("<div>")
+    const $geoUriSection = $("<div>")
       .attr("class", "share-geo-uri p-3 border-bottom border-secondary-subtle")
       .appendTo($ui);
 
@@ -119,7 +119,7 @@ L.OSM.share = function (options) {
 
     // Image
 
-    var $imageSection = $("<div>")
+    const $imageSection = $("<div>")
       .attr("class", "share-image p-3")
       .appendTo($ui);
 
@@ -227,8 +227,8 @@ L.OSM.share = function (options) {
         .appendTo($form);
     }
 
-    var csrf_param = $("meta[name=csrf-param]").attr("content"),
-        csrf_token = $("meta[name=csrf-token]").attr("content");
+    const csrf_param = $("meta[name=csrf-param]").attr("content"),
+          csrf_token = $("meta[name=csrf-token]").attr("content");
 
     $("<input>")
       .attr("name", csrf_param)
@@ -236,7 +236,7 @@ L.OSM.share = function (options) {
       .attr("type", "hidden")
       .appendTo($form);
 
-    var args = {
+    const args = {
       layer: "<span id=\"mapnik_image_layer\"></span>",
       width: "<span id=\"mapnik_image_width\"></span>",
       height: "<span id=\"mapnik_image_height\"></span>"
@@ -319,7 +319,7 @@ L.OSM.share = function (options) {
     }
 
     function escapeHTML(string) {
-      var htmlEscapes = {
+      const htmlEscapes = {
         "&": "&amp;",
         "<": "&lt;",
         ">": "&gt;",
@@ -333,8 +333,8 @@ L.OSM.share = function (options) {
 
     function update() {
       const layer = map.getMapBaseLayer();
-      var canEmbed = Boolean(layer && layer.options.canEmbed);
-      var bounds = map.getBounds();
+      const canEmbed = Boolean(layer && layer.options.canEmbed);
+      let bounds = map.getBounds();
 
       $("#link_marker")
         .prop("checked", map.hasLayer(marker));
@@ -355,7 +355,7 @@ L.OSM.share = function (options) {
       });
 
       if (map.hasLayer(marker)) {
-        var latLng = marker.getLatLng().wrap();
+        const latLng = marker.getLatLng().wrap();
         params.set("marker", latLng.lat + "," + latLng.lng);
       }
 
@@ -386,10 +386,10 @@ L.OSM.share = function (options) {
         bounds = locationFilter.getBounds();
       }
 
-      var scale = $("#mapnik_scale").val(),
-          size = L.bounds(L.CRS.EPSG3857.project(bounds.getSouthWest()),
-                          L.CRS.EPSG3857.project(bounds.getNorthEast())).getSize(),
-          maxScale = Math.floor(Math.sqrt(size.x * size.y / 0.3136));
+      let scale = $("#mapnik_scale").val();
+      const size = L.bounds(L.CRS.EPSG3857.project(bounds.getSouthWest()),
+                            L.CRS.EPSG3857.project(bounds.getNorthEast())).getSize(),
+            maxScale = Math.floor(Math.sqrt(size.x * size.y / 0.3136));
 
       $("#mapnik_minlon").val(bounds.getWest());
       $("#mapnik_minlat").val(bounds.getSouth());
@@ -427,17 +427,17 @@ L.OSM.share = function (options) {
     }
 
     function getScale() {
-      var bounds = map.getBounds(),
-          centerLat = bounds.getCenter().lat,
-          halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180),
-          meters = halfWorldMeters * (bounds.getEast() - bounds.getWest()) / 180,
-          pixelsPerMeter = map.getSize().x / meters,
-          metersPerPixel = 1 / (92 * 39.3701);
+      const bounds = map.getBounds(),
+            centerLat = bounds.getCenter().lat,
+            halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180),
+            meters = halfWorldMeters * (bounds.getEast() - bounds.getWest()) / 180,
+            pixelsPerMeter = map.getSize().x / meters,
+            metersPerPixel = 1 / (92 * 39.3701);
       return Math.round(1 / (pixelsPerMeter * metersPerPixel));
     }
 
     function roundScale(scale) {
-      var precision = 5 * Math.pow(10, Math.floor(Math.LOG10E * Math.log(scale)) - 2);
+      const precision = 5 * Math.pow(10, Math.floor(Math.LOG10E * Math.log(scale)) - 2);
       return precision * Math.ceil(scale / precision);
     }
   };
index 516a446c38811994cf4343b8b507340f3b709efa..06fad7b66dfd4f44bc0c63fe6ae3fdf3ff304f29 100644 (file)
@@ -1,11 +1,11 @@
 L.OSM.sidebarPane = function (options, uiClass, buttonTitle, paneTitle) {
-  var control = L.control(options);
+  const control = L.control(options);
 
   control.onAdd = function (map) {
-    var $container = $("<div>")
+    const $container = $("<div>")
       .attr("class", "control-" + uiClass);
 
-    var button = $("<a>")
+    const button = $("<a>")
       .attr("class", "control-button")
       .attr("href", "#")
       .html("<span class=\"icon " + uiClass + "\"></span>")
@@ -17,7 +17,7 @@ L.OSM.sidebarPane = function (options, uiClass, buttonTitle, paneTitle) {
 
     button.appendTo($container);
 
-    var $ui = $("<div>")
+    const $ui = $("<div>")
       .attr("class", uiClass + "-ui");
 
     $("<div class='d-flex p-3 pb-0'>")
index 1c911a961856e4cfae4cf63816c196ef31bf877e..910da53f20ca17d4ee685ca4fd9acaca74c7fb0c 100644 (file)
@@ -1,7 +1,7 @@
 L.OSM.sidebar = function (selector) {
-  var control = {},
-      sidebar = $(selector),
-      current = $(),
+  const control = {},
+        sidebar = $(selector);
+  let current = $(),
       currentButton = $(),
       map;
 
@@ -17,9 +17,9 @@ L.OSM.sidebar = function (selector) {
   };
 
   control.togglePane = function (pane, button) {
-    var mediumDeviceWidth = window.getComputedStyle(document.documentElement).getPropertyValue("--bs-breakpoint-md");
-    var isMediumDevice = window.matchMedia(`(max-width: ${mediumDeviceWidth})`).matches;
-    var paneWidth = 250;
+    const mediumDeviceWidth = window.getComputedStyle(document.documentElement).getPropertyValue("--bs-breakpoint-md");
+    const isMediumDevice = window.matchMedia(`(max-width: ${mediumDeviceWidth})`).matches;
+    const paneWidth = 250;
 
     current
       .hide()
index 20a02befaf6365d11182b599d6911dc96f00e7a9..71662608c5febec3873145bfda8e8e63bacc734e 100644 (file)
@@ -4,8 +4,8 @@ L.OSM.Zoom = L.Control.extend({
   },
 
   onAdd: function (map) {
-    var zoomName = "zoom",
-        container = L.DomUtil.create("div", zoomName);
+    const zoomName = "zoom",
+          container = L.DomUtil.create("div", zoomName);
 
     this._map = map;
 
@@ -32,14 +32,14 @@ L.OSM.Zoom = L.Control.extend({
   },
 
   _createButton: function (html, title, className, container, fn, context) {
-    var link = L.DomUtil.create("a", "control-button " + className, container);
+    const link = L.DomUtil.create("a", "control-button " + className, container);
     link.innerHTML = html;
     link.href = "#";
     link.title = title;
 
     L.DomUtil.create("span", "icon " + className, link);
 
-    var stop = L.DomEvent.stopPropagation;
+    const stop = L.DomEvent.stopPropagation;
 
     L.DomEvent
       .on(link, "click", stop)
@@ -52,8 +52,8 @@ L.OSM.Zoom = L.Control.extend({
   },
 
   _updateDisabled: function () {
-    var map = this._map,
-        className = "disabled";
+    const map = this._map,
+          className = "disabled";
 
     L.DomUtil.removeClass(this._zoomInButton, className);
     L.DomUtil.removeClass(this._zoomOutButton, className);
index 7d147a55cfb3b36dc21ccd8929526d8ff5d2967e..4ed3de941bfc05255f5bc33f228a00fb2c822c76 100644 (file)
@@ -1,9 +1,9 @@
 if (OSM.MATOMO) {
   $(document).ready(function () {
-    var base = document.location.protocol + "//" + OSM.MATOMO.location + "/";
-    var matomoTracker;
+    const base = document.location.protocol + "//" + OSM.MATOMO.location + "/";
+    let matomoTracker;
 
-    var matomoLoader = $.ajax({
+    const matomoLoader = $.ajax({
       url: base + "matomo.js",
       dataType: "script",
       cache: true,
index 062d537ffe8347195e8a70d588400ae725674a5a..25d6596c2cd6fb160ef54bdba6641ee79e6c8a76 100644 (file)
@@ -44,8 +44,8 @@ OSM = {
   CLOSED_NOTE_MARKER: <%= image_path("closed_note_marker.svg").to_json %>,
 
   apiUrl: function (object) {
-    var apiType = object.type === "note" ? "notes" : object.type;
-    var url = "/api/" + OSM.API_VERSION + "/" + apiType + "/" + object.id;
+    const apiType = object.type === "note" ? "notes" : object.type;
+    let url = "/api/" + OSM.API_VERSION + "/" + apiType + "/" + object.id;
 
     if (object.type === "way" || object.type === "relation") {
       url += "/full";
@@ -57,13 +57,13 @@ OSM = {
   },
 
   params: function (search) {
-    var query = search || window.location.search;
+    const query = search || window.location.search;
     return Object.fromEntries(new URLSearchParams(query));
   },
 
   mapParams: function (search) {
-    var params = OSM.params(search),
-        mapParams = {};
+    const params = OSM.params(search),
+          mapParams = {};
 
     if (params.mlon && params.mlat) {
       mapParams.marker = true;
@@ -78,7 +78,7 @@ OSM = {
       }
     }
 
-    var hash = OSM.parseHash(location.hash);
+    const hash = OSM.parseHash(location.hash);
 
     const loc = Cookies.get("_osm_location")?.split("|");
 
@@ -120,7 +120,7 @@ OSM = {
 
     mapParams.layers = hash.layers || (loc && loc[3]) || "";
 
-    var scale = parseFloat(params.scale);
+    const scale = parseFloat(params.scale);
     if (scale > 0) {
       mapParams.zoom = Math.log(360.0 / (scale * 512.0)) / Math.log(2.0);
     }
@@ -129,19 +129,19 @@ OSM = {
   },
 
   parseHash: function (hash) {
-    var args = {};
+    const args = {};
 
-    var i = hash.indexOf("#");
+    const i = hash.indexOf("#");
     if (i < 0) {
       return args;
     }
 
     const hashParams = new URLSearchParams(hash.slice(i + 1));
 
-    var map = (hashParams.get("map") || "").split("/"),
-        zoom = parseInt(map[0], 10),
-        lat = parseFloat(map[1]),
-        lon = parseFloat(map[2]);
+    const map = (hashParams.get("map") || "").split("/"),
+          zoom = parseInt(map[0], 10),
+          lat = parseFloat(map[1]),
+          lon = parseFloat(map[2]);
 
     if (!isNaN(zoom) && !isNaN(lat) && !isNaN(lon)) {
       args.center = new L.LatLng(lat, lon);
@@ -156,7 +156,7 @@ OSM = {
   },
 
   formatHash: function (args) {
-    var center, zoom, layers;
+    let center, zoom, layers;
 
     if (args instanceof L.Map) {
       center = args.getCenter();
@@ -180,8 +180,8 @@ OSM = {
   },
 
   zoomPrecision: function (zoom) {
-    var pixels = Math.pow(2, 8 + zoom);
-    var degrees = 180;
+    const pixels = Math.pow(2, 8 + zoom);
+    const degrees = 180;
     return Math.ceil(Math.log10(pixels / degrees));
   },
 
@@ -198,12 +198,12 @@ OSM = {
   },
 
   distance: function (latlng1, latlng2) {
-    var lat1 = latlng1.lat * Math.PI / 180,
-        lng1 = latlng1.lng * Math.PI / 180,
-        lat2 = latlng2.lat * Math.PI / 180,
-        lng2 = latlng2.lng * Math.PI / 180,
-        latdiff = lat2 - lat1,
-        lngdiff = lng2 - lng1;
+    const lat1 = latlng1.lat * Math.PI / 180,
+          lng1 = latlng1.lng * Math.PI / 180,
+          lat2 = latlng2.lat * Math.PI / 180,
+          lng2 = latlng2.lng * Math.PI / 180,
+          latdiff = lat2 - lat1,
+          lngdiff = lng2 - lng1;
 
     return 6372795 * 2 * Math.asin(
       Math.sqrt(
index bd00d937e2313068b310681a2be733f04dff0201..eb13392eb5039c22b9694d10810748d199cb715f 100644 (file)
@@ -5,8 +5,8 @@
    * the user next switches to it.
    */
   $(document).on("change", ".richtext_container textarea", function () {
-    var container = $(this).closest(".richtext_container");
-    var preview = container.find(".tab-pane[id$='_preview']");
+    const container = $(this).closest(".richtext_container");
+    const preview = container.find(".tab-pane[id$='_preview']");
 
     preview.children(".richtext_placeholder").attr("hidden", true).removeClass("delayed-fade-in");
     preview.children(".richtext").empty();
    * when switching away from an edit pane
    */
   $(document).on("hide.bs.tab", ".richtext_container button[data-bs-target$='_edit']", function () {
-    var container = $(this).closest(".richtext_container");
-    var editor = container.find("textarea");
-    var preview = container.find(".tab-pane[id$='_preview']");
-    var minHeight = editor.outerHeight() - preview.outerHeight() + preview.height();
+    const container = $(this).closest(".richtext_container");
+    const editor = container.find("textarea");
+    const preview = container.find(".tab-pane[id$='_preview']");
+    const minHeight = editor.outerHeight() - preview.outerHeight() + preview.height();
 
     preview.css("min-height", minHeight + "px");
   });
@@ -29,9 +29,9 @@
    * Install a handler to switch to preview mode
    */
   $(document).on("show.bs.tab", ".richtext_container button[data-bs-target$='_preview']", function () {
-    var container = $(this).closest(".richtext_container");
-    var editor = container.find("textarea");
-    var preview = container.find(".tab-pane[id$='_preview']");
+    const container = $(this).closest(".richtext_container");
+    const editor = container.find("textarea");
+    const preview = container.find(".tab-pane[id$='_preview']");
 
     if (preview.children(".richtext").contents().length === 0) {
       preview.children(".richtext_placeholder").removeAttr("hidden").addClass("delayed-fade-in");
   });
 
   function invalidTextareaListener() {
-    var container = $(this).closest(".richtext_container");
+    const container = $(this).closest(".richtext_container");
 
     container.find("button[data-bs-target$='_edit']").tab("show");
   }
 
   function updateHelp() {
     $(".richtext_container .richtext_help_sidebar:not(:visible):not(:empty)").each(function () {
-      var container = $(this).closest(".richtext_container");
+      const container = $(this).closest(".richtext_container");
       $(this).children().appendTo(container.find(".tab-pane[id$='_help']"));
     });
     $(".richtext_container .richtext_help_sidebar:visible:empty").each(function () {
-      var container = $(this).closest(".richtext_container");
+      const container = $(this).closest(".richtext_container");
       container.find(".tab-pane[id$='_help']").children().appendTo($(this));
       if (container.find("button[data-bs-target$='_help'].active").length) {
         container.find("button[data-bs-target$='_edit']").tab("show");
index 63a320c6a9d76e6a2810289d4f105e448d788a72..2e4b375d79691b0bd7253fce4bcf8671530465b9 100644 (file)
    move the map without the hash changing.
  */
 OSM.Router = function (map, rts) {
-  var escapeRegExp = /[-{}[\]+?.,\\^$|#\s]/g;
-  var optionalParam = /\((.*?)\)/g;
-  var namedParam = /(\(\?)?:\w+/g;
-  var splatParam = /\*\w+/g;
+  const escapeRegExp = /[-{}[\]+?.,\\^$|#\s]/g;
+  const optionalParam = /\((.*?)\)/g;
+  const namedParam = /(\(\?)?:\w+/g;
+  const splatParam = /\*\w+/g;
 
   function Route(path, controller) {
-    var regexp = new RegExp("^" +
+    const regexp = new RegExp("^" +
       path.replace(escapeRegExp, "\\$&")
         .replace(optionalParam, "(?:$1)?")
         .replace(namedParam, function (match, optional) {
@@ -61,14 +61,14 @@ OSM.Router = function (map, rts) {
         })
         .replace(splatParam, "(.*?)") + "(?:\\?.*)?$");
 
-    var route = {};
+    const route = {};
 
     route.match = function (path) {
       return regexp.test(path);
     };
 
     route.run = function (action, path) {
-      var params = [];
+      let params = [];
 
       if (path) {
         params = regexp.exec(path).map(function (param, i) {
@@ -93,15 +93,15 @@ OSM.Router = function (map, rts) {
     }
   };
 
-  var currentPath = window.location.pathname.replace(/(.)\/$/, "$1") + window.location.search,
+  let currentPath = window.location.pathname.replace(/(.)\/$/, "$1") + window.location.search,
       currentRoute = routes.recognize(currentPath),
       currentHash = location.hash || OSM.formatHash(map);
 
-  var router = {};
+  const router = {};
 
   function updateSecondaryNav() {
     $("header nav.secondary > ul > li > a").each(function () {
-      var active = $(this).attr("href") === window.location.pathname;
+      const active = $(this).attr("href") === window.location.pathname;
 
       $(this)
         .toggleClass("text-secondary", !active)
@@ -111,8 +111,8 @@ OSM.Router = function (map, rts) {
 
   $(window).on("popstate", function (e) {
     if (!e.originalEvent.state) return; // Is it a real popstate event or just a hash change?
-    var path = window.location.pathname + window.location.search,
-        route = routes.recognize(path);
+    const path = window.location.pathname + window.location.search,
+          route = routes.recognize(path);
     if (path === currentPath) return;
     currentRoute.run("unload", null, route === currentRoute);
     currentPath = path;
@@ -123,11 +123,11 @@ OSM.Router = function (map, rts) {
   });
 
   router.route = function (url) {
-    var path = url.replace(/#.*/, ""),
-        route = routes.recognize(path);
+    const path = url.replace(/#.*/, ""),
+          route = routes.recognize(path);
     if (!route) return false;
     currentRoute.run("unload", null, route === currentRoute);
-    var state = OSM.parseHash(url);
+    const state = OSM.parseHash(url);
     map.setState(state);
     window.history.pushState(state, document.title, url);
     currentPath = path;
@@ -147,17 +147,17 @@ OSM.Router = function (map, rts) {
   };
 
   router.updateHash = function () {
-    var hash = OSM.formatHash(map);
+    const hash = OSM.formatHash(map);
     if (hash === currentHash) return;
     currentHash = hash;
     router.stateChange(OSM.parseHash(hash));
   };
 
   router.hashUpdated = function () {
-    var hash = location.hash;
+    const hash = location.hash;
     if (hash === currentHash) return;
     currentHash = hash;
-    var state = OSM.parseHash(hash);
+    const state = OSM.parseHash(hash);
     map.setState(state);
     router.stateChange(state, hash);
   };
@@ -176,7 +176,7 @@ OSM.Router = function (map, rts) {
   };
 
   router.load = function () {
-    var loadState = currentRoute.run("load", currentPath);
+    const loadState = currentRoute.run("load", currentPath);
     router.stateChange(loadState || {});
   };
 
index 9366115cecb730d4465711bca85d71f7f2ccf45c..2af9e18cbd06b37b2e9f8165bc2aad7baae08ce4 100644 (file)
@@ -7,8 +7,8 @@
 }());
 
 $(document).ready(function () {
-  var defaultHomeZoom = 12;
-  var map, marker, deleted_lat, deleted_lon;
+  const defaultHomeZoom = 12;
+  let map, marker, deleted_lat, deleted_lon;
 
   if ($("#map").length) {
     map = L.map("map", {
@@ -16,12 +16,12 @@ $(document).ready(function () {
       zoomControl: false
     }).addLayer(new L.OSM.Mapnik());
 
-    var position = $("html").attr("dir") === "rtl" ? "topleft" : "topright";
+    const position = $("html").attr("dir") === "rtl" ? "topleft" : "topright";
 
     L.OSM.zoom({ position: position })
       .addTo(map);
 
-    var locate = L.control.locate({
+    const locate = L.control.locate({
       position: position,
       icon: "icon geolocate",
       iconLoading: "icon geolocate",
@@ -33,7 +33,7 @@ $(document).ready(function () {
       }
     }).addTo(map);
 
-    var locateContainer = locate.getContainer();
+    const locateContainer = locate.getContainer();
 
     $(locateContainer)
       .removeClass("leaflet-control-locate leaflet-bar")
@@ -73,9 +73,9 @@ $(document).ready(function () {
         deleted_lon = null;
         respondToHomeUpdate();
       }).on("moveend", function () {
-        var lat = $("#home_lat").val().trim(),
-            lon = $("#home_lon").val().trim(),
-            location;
+        const lat = $("#home_lat").val().trim(),
+              lon = $("#home_lon").val().trim();
+        let location;
 
         try {
           if (lat && lon) {
@@ -95,15 +95,15 @@ $(document).ready(function () {
       });
 
       $("#home_show").click(function () {
-        var lat = $("#home_lat").val(),
-            lon = $("#home_lon").val();
+        const lat = $("#home_lat").val(),
+              lon = $("#home_lon").val();
 
         map.setView([lat, lon], defaultHomeZoom);
       });
 
       $("#home_delete").click(function () {
-        var lat = $("#home_lat").val(),
-            lon = $("#home_lon").val();
+        const lat = $("#home_lat").val(),
+              lon = $("#home_lon").val();
 
         $("#home_lat, #home_lon").val("");
         deleted_lat = lat;
@@ -122,7 +122,7 @@ $(document).ready(function () {
       });
     } else {
       $("[data-user]").each(function () {
-        var user = $(this).data("user");
+        const user = $(this).data("user");
         if (user.lon && user.lat) {
           L.marker([user.lat, user.lon], { icon: OSM.getUserIcon(user.icon) }).addTo(map)
             .bindPopup(user.description, { minWidth: 200 });
@@ -132,9 +132,9 @@ $(document).ready(function () {
   }
 
   function respondToHomeUpdate() {
-    var lat = $("#home_lat").val().trim(),
-        lon = $("#home_lon").val().trim(),
-        location;
+    const lat = $("#home_lat").val().trim(),
+          lon = $("#home_lon").val().trim();
+    let location;
 
     try {
       if (lat && lon) {
@@ -160,14 +160,14 @@ $(document).ready(function () {
   }
 
   function isCloseEnoughToMapCenter(location) {
-    var inputPt = map.latLngToContainerPoint(location),
-        centerPt = map.latLngToContainerPoint(map.getCenter());
+    const inputPt = map.latLngToContainerPoint(location),
+          centerPt = map.latLngToContainerPoint(map.getCenter());
 
     return centerPt.distanceTo(inputPt) < 10;
   }
 
   function updateAuthUID() {
-    var provider = $("select#user_auth_provider").val();
+    const provider = $("select#user_auth_provider").val();
 
     if (provider === "openid") {
       $("input#user_auth_uid").show().prop("disabled", false);
@@ -210,7 +210,7 @@ $(document).ready(function () {
   });
 
   $("input[name=legale]").change(function () {
-    var url = $(this).data("url");
+    const url = $(this).data("url");
 
     $("#contributorTerms").html("<div class='spinner-border' role='status'><span class='visually-hidden'>" + I18n.t("browse.start_rjs.loading") + "</span></div>");
     $("#contributorTerms").load(url);
index 77d1d513c3e5ba6f64b8fc24c5429cfdd70be335..3e2845bb3bda0e8a0404a30661cd1e07f27f377c 100644 (file)
@@ -1,8 +1,8 @@
 $(document).ready(function () {
-  var params = OSM.params();
+  const params = OSM.params();
 
   if (params.lat && params.lon) {
-    var url = "/edit";
+    let url = "/edit";
 
     if (params.editor) url += "?editor=" + params.editor;
     if (!params.zoom) params.zoom = 17;
index c180571c58b10b0184e1f3dd98ab86f4fb5d8d27..808ac97ea3418257445177caeb8615cc2574ff78 100644 (file)
@@ -1,7 +1,9 @@
 module Api
   class ChangesetCommentsController < ApiController
-    before_action :check_api_writable
-    before_action :authorize
+    include QueryMethods
+
+    before_action :check_api_writable, :except => [:index]
+    before_action :authorize, :except => [:index]
 
     authorize_resource
 
@@ -9,6 +11,15 @@ module Api
 
     before_action :set_request_formats
 
+    ##
+    # show all comments or search for a subset
+    def index
+      @comments = ChangesetComment.includes(:author).where(:visible => true).order("created_at DESC")
+      @comments = query_conditions_time(@comments)
+      @comments = query_conditions_user(@comments, :author)
+      @comments = query_limit(@comments)
+    end
+
     ##
     # Add a comment to a changeset
     def create
index 9111bb609d27d91753d3b6b46a6ee7ae59954eae..3df7b75cea752aeb11a0681b728377d6f6a0d0e0 100644 (file)
@@ -2,6 +2,8 @@
 
 module Api
   class ChangesetsController < ApiController
+    include QueryMethods
+
     before_action :check_api_writable, :only => [:create, :update, :upload, :subscribe, :unsubscribe]
     before_action :setup_user_auth, :only => [:show]
     before_action :authorize, :only => [:create, :update, :upload, :close, :subscribe, :unsubscribe]
@@ -30,7 +32,7 @@ module Api
       changesets = conditions_bbox(changesets, bbox)
       changesets = conditions_user(changesets, params["user"], params["display_name"])
       changesets = conditions_time(changesets, params["time"])
-      changesets = conditions_from_to(changesets, params["from"], params["to"])
+      changesets = query_conditions_time(changesets)
       changesets = conditions_open(changesets, params["open"])
       changesets = conditions_closed(changesets, params["closed"])
       changesets = conditions_ids(changesets, params["changesets"])
@@ -43,7 +45,7 @@ module Api
                    end
 
       # limit the result
-      changesets = changesets.limit(result_limit)
+      changesets = query_limit(changesets)
 
       # preload users, tags and comments, and render result
       @changesets = changesets.preload(:user, :changeset_tags, :comments)
@@ -337,33 +339,6 @@ module Api
       raise OSM::APIBadUserInput, e.message.to_s
     end
 
-    ##
-    # restrict changesets to those opened during a particular time period
-    # works similar to from..to of notes controller, including the requirement of 'from' when specifying 'to'
-    def conditions_from_to(changesets, from, to)
-      if from
-        begin
-          from = Time.parse(from).utc
-        rescue ArgumentError
-          raise OSM::APIBadUserInput, "Date #{from} is in a wrong format"
-        end
-
-        begin
-          to = if to
-                 Time.parse(to).utc
-               else
-                 Time.now.utc
-               end
-        rescue ArgumentError
-          raise OSM::APIBadUserInput, "Date #{to} is in a wrong format"
-        end
-
-        changesets.where(:created_at => from..to)
-      else
-        changesets
-      end
-    end
-
     ##
     # return changesets which are open (haven't been closed yet)
     # we do this by seeing if the 'closed at' time is in the future. Also if we've
@@ -403,19 +378,5 @@ module Api
         changesets.where(:id => ids)
       end
     end
-
-    ##
-    # Get the maximum number of results to return
-    def result_limit
-      if params[:limit]
-        if params[:limit].to_i.positive? && params[:limit].to_i <= Settings.max_changeset_query_limit
-          params[:limit].to_i
-        else
-          raise OSM::APIBadUserInput, "Changeset limit must be between 1 and #{Settings.max_changeset_query_limit}"
-        end
-      else
-        Settings.default_changeset_query_limit
-      end
-    end
   end
 end
index a0095d954b5d6f48dd891560d11c7f755523c964..af0c5e0398a4265ff6e122f927668e69b6910e9b 100644 (file)
@@ -1,5 +1,7 @@
 module Api
   class NotesController < ApiController
+    include QueryMethods
+
     before_action :check_api_writable, :only => [:create, :comment, :close, :reopen, :destroy]
     before_action :setup_user_auth, :only => [:create, :show]
     before_action :authorize, :only => [:close, :reopen, :destroy, :comment]
@@ -36,7 +38,9 @@ module Api
       @max_lat = bbox.max_lat
 
       # Find the notes we want to return
-      @notes = notes.bbox(bbox).order("updated_at DESC").limit(result_limit).preload(:comments)
+      notes = notes.bbox(bbox).order("updated_at DESC")
+      notes = query_limit(notes)
+      @notes = notes.preload(:comments)
 
       # Render the result
       respond_to do |format|
@@ -234,8 +238,9 @@ module Api
 
       # Find the comments we want to return
       @comments = NoteComment.where(:note => notes)
-                             .order(:created_at => :desc).limit(result_limit)
-                             .preload(:author, :note => { :comments => :author })
+                             .order(:created_at => :desc)
+      @comments = query_limit(@comments)
+      @comments = @comments.preload(:author, :note => { :comments => :author })
 
       # Render the result
       respond_to do |format|
@@ -251,19 +256,8 @@ module Api
       @notes = bbox_condition(@notes)
 
       # Add any user filter
-      if params[:display_name] || params[:user]
-        if params[:display_name]
-          @user = User.find_by(:display_name => params[:display_name])
-
-          raise OSM::APIBadUserInput, "User #{params[:display_name]} not known" unless @user
-        else
-          @user = User.find_by(:id => params[:user])
-
-          raise OSM::APIBadUserInput, "User #{params[:user]} not known" unless @user
-        end
-
-        @notes = @notes.joins(:comments).where(:note_comments => { :author_id => @user })
-      end
+      user = query_conditions_user_value
+      @notes = @notes.joins(:comments).where(:note_comments => { :author_id => user }) if user
 
       # Add any text filter
       if params[:q]
@@ -271,29 +265,12 @@ module Api
       end
 
       # Add any date filter
-      if params[:from]
-        begin
-          from = Time.parse(params[:from]).utc
-        rescue ArgumentError
-          raise OSM::APIBadUserInput, "Date #{params[:from]} is in a wrong format"
-        end
-
-        begin
-          to = if params[:to]
-                 Time.parse(params[:to]).utc
-               else
-                 Time.now.utc
-               end
-        rescue ArgumentError
-          raise OSM::APIBadUserInput, "Date #{params[:to]} is in a wrong format"
-        end
-
-        @notes = if params[:sort] == "updated_at"
-                   @notes.where(:updated_at => from..to)
-                 else
-                   @notes.where(:created_at => from..to)
-                 end
-      end
+      time_filter_property = if params[:sort] == "updated_at"
+                               :updated_at
+                             else
+                               :created_at
+                             end
+      @notes = query_conditions_time(@notes, time_filter_property)
 
       # Choose the sort order
       @notes = if params[:sort] == "created_at"
@@ -311,7 +288,8 @@ module Api
                end
 
       # Find the notes we want to return
-      @notes = @notes.distinct.limit(result_limit).preload(:comments)
+      @notes = query_limit(@notes.distinct)
+      @notes = @notes.preload(:comments)
 
       # Render the result
       respond_to do |format|
@@ -328,20 +306,6 @@ module Api
     # utility functions below.
     #------------------------------------------------------------
 
-    ##
-    # Get the maximum number of results to return
-    def result_limit
-      if params[:limit]
-        if params[:limit].to_i.positive? && params[:limit].to_i <= Settings.max_note_query_limit
-          params[:limit].to_i
-        else
-          raise OSM::APIBadUserInput, "Note limit must be between 1 and #{Settings.max_note_query_limit}"
-        end
-      else
-        Settings.default_note_query_limit
-      end
-    end
-
     ##
     # Generate a condition to choose which notes we want based
     # on their status and the user's request parameters
index fef48bb188f885dbfac1188f0541002f16bba88b..148873eea8321b338d54dfd9a51b37045fd1a97e 100644 (file)
@@ -1,5 +1,7 @@
 module ChangesetComments
   class FeedsController < ApplicationController
+    include QueryMethods
+
     before_action :authorize_web
     before_action :set_locale
 
@@ -19,10 +21,13 @@ module ChangesetComments
         changeset = Changeset.find(changeset_id)
 
         # Return comments for this changeset only
-        @comments = changeset.comments.includes(:author, :changeset).reverse_order.limit(comments_limit)
+        @comments = changeset.comments.includes(:author, :changeset).reverse_order
+        @comments = query_limit(@comments)
       else
         # Return comments
-        @comments = ChangesetComment.includes(:author, :changeset).where(:visible => true).order("created_at DESC").limit(comments_limit).preload(:changeset)
+        @comments = ChangesetComment.includes(:author, :changeset).where(:visible => true).order("created_at DESC")
+        @comments = query_limit(@comments)
+        @comments = @comments.preload(:changeset)
       end
 
       # Render the result
@@ -32,21 +37,5 @@ module ChangesetComments
     rescue OSM::APIBadUserInput
       head :bad_request
     end
-
-    private
-
-    ##
-    # Get the maximum number of comments to return
-    def comments_limit
-      if params[:limit]
-        if params[:limit].to_i.positive? && params[:limit].to_i <= 10000
-          params[:limit].to_i
-        else
-          raise OSM::APIBadUserInput, "Comments limit must be between 1 and 10000"
-        end
-      else
-        100
-      end
-    end
   end
 end
diff --git a/app/controllers/concerns/query_methods.rb b/app/controllers/concerns/query_methods.rb
new file mode 100644 (file)
index 0000000..eb06842
--- /dev/null
@@ -0,0 +1,92 @@
+module QueryMethods
+  extend ActiveSupport::Concern
+
+  private
+
+  ##
+  # Filter the resulting items by user
+  def query_conditions_user(items, filter_property)
+    user = query_conditions_user_value
+    items = items.where(filter_property => user) if user
+    items
+  end
+
+  ##
+  # Get user value for query filtering by user
+  # Raises OSM::APIBadUserInput if user not found like notes api does, changesets api raises OSM::APINotFoundError instead
+  def query_conditions_user_value
+    if params[:display_name] || params[:user]
+      if params[:display_name]
+        user = User.find_by(:display_name => params[:display_name])
+
+        raise OSM::APIBadUserInput, "User #{params[:display_name]} not known" unless user
+      else
+        user = User.find_by(:id => params[:user])
+
+        raise OSM::APIBadUserInput, "User #{params[:user]} not known" unless user
+      end
+
+      user
+    end
+  end
+
+  ##
+  # Restrict the resulting items to those created during a particular time period
+  # Using 'to' requires specifying 'from' as well for historical reasons
+  def query_conditions_time(items, filter_property = :created_at)
+    interval = query_conditions_time_value
+
+    if interval
+      items.where(filter_property => interval)
+    else
+      items
+    end
+  end
+
+  ##
+  # Get query time interval from request parameters or nil
+  def query_conditions_time_value
+    if params[:from]
+      begin
+        from = Time.parse(params[:from]).utc
+      rescue ArgumentError
+        raise OSM::APIBadUserInput, "Date #{params[:from]} is in a wrong format"
+      end
+
+      begin
+        to = if params[:to]
+               Time.parse(params[:to]).utc
+             else
+               Time.now.utc
+             end
+      rescue ArgumentError
+        raise OSM::APIBadUserInput, "Date #{params[:to]} is in a wrong format"
+      end
+
+      from..to
+    end
+  end
+
+  ##
+  # Limit the result according to request parameters and settings
+  def query_limit(items)
+    items.limit(query_limit_value)
+  end
+
+  ##
+  # Get query limit value from request parameters and settings
+  def query_limit_value
+    name = controller_path.sub(%r{^api/}, "").tr("/", "_").singularize
+    max_limit = Settings["max_#{name}_query_limit"]
+    default_limit = Settings["default_#{name}_query_limit"]
+    if params[:limit]
+      if params[:limit].to_i.positive? && params[:limit].to_i <= max_limit
+        params[:limit].to_i
+      else
+        raise OSM::APIBadUserInput, "#{controller_name.classify} limit must be between 1 and #{max_limit}"
+      end
+    else
+      default_limit
+    end
+  end
+end
index 16f733c882d30f002f3e7765c703d9bf7bf5254f..21fe2181b20abe9bfce7b196699d6fc368aca722 100644 (file)
@@ -359,11 +359,13 @@ class User < ApplicationRecord
     trace_score = traces.size * 50
     diary_entry_score = diary_entries.visible.inject(0) { |acc, elem| acc + elem.body.spam_score }
     diary_comment_score = diary_comments.visible.inject(0) { |acc, elem| acc + elem.body.spam_score }
+    report_score = Report.where(:category => "spam", :issue => issues.with_status("open")).count * 20
 
     score = description.spam_score / 4.0
     score += diary_entries.visible.where("created_at > ?", 1.day.ago).count * 10
     score += diary_entry_score / diary_entries.visible.length unless diary_entries.visible.empty?
     score += diary_comment_score / diary_comments.visible.length unless diary_comments.visible.empty?
+    score += report_score
     score -= changeset_score
     score -= trace_score
 
diff --git a/app/views/api/changeset_comments/_changeset_comment.json.jbuilder b/app/views/api/changeset_comments/_changeset_comment.json.jbuilder
new file mode 100644 (file)
index 0000000..73b1ec9
--- /dev/null
@@ -0,0 +1,8 @@
+json.id changeset_comment.id
+json.visible changeset_comment.visible
+json.date changeset_comment.created_at.xmlschema
+if changeset_comment.author.data_public?
+  json.uid changeset_comment.author.id
+  json.user changeset_comment.author.display_name
+end
+json.text changeset_comment.body
diff --git a/app/views/api/changeset_comments/_changeset_comment.xml.builder b/app/views/api/changeset_comments/_changeset_comment.xml.builder
new file mode 100644 (file)
index 0000000..951556f
--- /dev/null
@@ -0,0 +1,12 @@
+cattrs = {
+  "id" => changeset_comment.id,
+  "date" => changeset_comment.created_at.xmlschema,
+  "visible" => changeset_comment.visible
+}
+if changeset_comment.author.data_public?
+  cattrs["uid"] = changeset_comment.author.id
+  cattrs["user"] = changeset_comment.author.display_name
+end
+xml.comment(cattrs) do |comment_xml_node|
+  comment_xml_node.text(changeset_comment.body)
+end
diff --git a/app/views/api/changeset_comments/index.json.jbuilder b/app/views/api/changeset_comments/index.json.jbuilder
new file mode 100644 (file)
index 0000000..0286b1a
--- /dev/null
@@ -0,0 +1,5 @@
+json.partial! "api/root_attributes"
+
+json.comments(@comments) do |comment|
+  json.partial! comment
+end
diff --git a/app/views/api/changeset_comments/index.xml.builder b/app/views/api/changeset_comments/index.xml.builder
new file mode 100644 (file)
index 0000000..cfa59c9
--- /dev/null
@@ -0,0 +1,7 @@
+xml.instruct! :xml, :version => "1.0"
+
+xml.osm(OSM::API.new.xml_root_attributes) do |osm|
+  @comments.includes(:author).each do |comment|
+    osm << render(comment)
+  end
+end
index f0e46132008be266b51408ab0b948b649f8fdfc6..7001a95e854ababb5a4293a4c011b5e8c53f7baa 100644 (file)
@@ -23,13 +23,6 @@ json.tags changeset.tags unless changeset.tags.empty?
 
 if @comments
   json.comments(@comments) do |comment|
-    json.id comment.id
-    json.visible comment.visible
-    json.date comment.created_at.xmlschema
-    if comment.author.data_public?
-      json.uid comment.author.id
-      json.user comment.author.display_name
-    end
-    json.text comment.body
+    json.partial! comment
   end
 end
index 08cfbbc79bc9d66065ef6b6ca3362502fe32ecae..072f8fc5d613fc26b011b4b3b4b17ab9a2598c21 100644 (file)
@@ -27,18 +27,7 @@ xml.changeset(attrs) do |changeset_xml_node|
   if @comments
     changeset_xml_node.discussion do |discussion_xml_node|
       @comments.each do |comment|
-        cattrs = {
-          "id" => comment.id,
-          "date" => comment.created_at.xmlschema,
-          "visible" => comment.visible
-        }
-        if comment.author.data_public?
-          cattrs["uid"] = comment.author.id
-          cattrs["user"] = comment.author.display_name
-        end
-        discussion_xml_node.comment(cattrs) do |comment_xml_node|
-          comment_xml_node.text(comment.body)
-        end
+        discussion_xml_node << render(comment)
       end
     end
   end
index 895ab380c16c275d0ff3c984fc212a728078a9c4..6055634aa5a7ef6afab684f4adbb8d988f2a12a6 100644 (file)
@@ -141,9 +141,11 @@ module.exports = [
       "no-useless-call": "error",
       "no-useless-concat": "error",
       "no-useless-return": "error",
+      "no-var": "error",
       "no-void": "error",
       "no-warning-comments": "warn",
       "operator-assignment": "error",
+      "prefer-const": "error",
       "prefer-object-spread": "error",
       "radix": ["error", "always"],
       "yoda": "error"
index b3fc5af15900002fe06d4fe8e5cef36315528d5e..0ffd0a546c431552257073e2e206759da2901c11 100644 (file)
@@ -38,6 +38,8 @@ OpenStreetMap::Application.routes.draw do
   end
 
   namespace :api, :path => "api/0.6" do
+    resources :changeset_comments, :only => :index
+
     resources :nodes, :only => [:index, :create]
     resources :nodes, :path => "node", :id => /\d+/, :only => [:show, :update, :destroy] do
       scope :module => :nodes do
index 2e0346f0031c891d226deeddaa284adb2801cc31..51f4444c4802edce9b6cc2c5869a8f0c4f8a33ed 100644 (file)
@@ -35,6 +35,14 @@ tracepoints_per_page: 5000
 default_changeset_query_limit: 100
 # Maximum limit on the number of changesets returned by the changeset query api method
 max_changeset_query_limit: 100
+# Default limit on the number of changeset comments returned by the api
+default_changeset_comment_query_limit: 100
+# Maximum limit on the number of changesets comments returned by the api
+max_changeset_comment_query_limit: 10000
+# Default limit on the number of changeset comments in feeds
+default_changeset_comments_feed_query_limit: 100
+# Maximum limit on the number of changesets comments in feeds
+max_changeset_comments_feed_query_limit: 10000
 # Maximum number of nodes that will be returned by the api in a map request
 max_number_of_nodes: 50000
 # Maximum number of nodes that can be in a way (checked on save)
index b7cffcc27b33df6ef361155d832cbc265a1f30a2..3cf8c2836284c5b29fd03251753ea5f25aa3b2aa 100644 (file)
@@ -53,5 +53,7 @@ doorkeeper_signing_key: |
   cK1+/2V+OkM/0nXjxPwPj7LiOediUyZNUn48r29uGOL1S83PSUdyST207CP6mZjc
   K8aJmnGsVEAcWPzbpNh14q/c
   -----END PRIVATE KEY-----
+# Run system tests using headless Firefox
+system_test_headless: true
 # Override Firefox binary used in system tests
 #system_test_firefox_binary:
index 852f270b6ef713571339a1ada651a4c3ed219826..f2fcadfd7c582efedfdcd60df7ee0947b896db4b 100644 (file)
@@ -7,7 +7,7 @@ ActiveSupport.on_load(:action_dispatch_system_test_case) do
 end
 
 class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
-  driven_by :selenium, :using => :headless_firefox do |options|
+  driven_by :selenium, :using => Settings.system_test_headless ? :headless_firefox : :firefox do |options|
     options.add_preference("intl.accept_languages", "en")
     options.binary = Settings.system_test_firefox_binary if Settings.system_test_firefox_binary
   end
index e456a3ca416f4cf25113827d0dd7c6b302c7746b..ba4200d3f8d2cfda3f6979b71a8fb74fb5eba0f8 100644 (file)
@@ -5,6 +5,14 @@ module Api
     ##
     # test all routes which lead to this controller
     def test_routes
+      assert_routing(
+        { :path => "/api/0.6/changeset_comments", :method => :get },
+        { :controller => "api/changeset_comments", :action => "index" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/changeset_comments.json", :method => :get },
+        { :controller => "api/changeset_comments", :action => "index", :format => "json" }
+      )
       assert_routing(
         { :path => "/api/0.6/changeset/1/comment", :method => :post },
         { :controller => "api/changeset_comments", :action => "create", :id => "1" }
@@ -31,6 +39,46 @@ module Api
       )
     end
 
+    def test_index
+      user1 = create(:user)
+      user2 = create(:user)
+      changeset1 = create(:changeset, :closed, :user => user2)
+      comment11 = create(:changeset_comment, :changeset => changeset1, :author => user1, :created_at => "2023-01-01", :body => "changeset 1 question")
+      comment12 = create(:changeset_comment, :changeset => changeset1, :author => user2, :created_at => "2023-02-01", :body => "changeset 1 answer")
+      changeset2 = create(:changeset, :closed, :user => user1)
+      comment21 = create(:changeset_comment, :changeset => changeset2, :author => user1, :created_at => "2023-03-01", :body => "changeset 2 note")
+      comment22 = create(:changeset_comment, :changeset => changeset2, :author => user1, :created_at => "2023-04-01", :body => "changeset 2 extra note")
+      comment23 = create(:changeset_comment, :changeset => changeset2, :author => user2, :created_at => "2023-05-01", :body => "changeset 2 review")
+
+      get api_changeset_comments_path
+      assert_response :success
+      assert_comments_in_order [comment23, comment22, comment21, comment12, comment11]
+
+      get api_changeset_comments_path(:limit => 3)
+      assert_response :success
+      assert_comments_in_order [comment23, comment22, comment21]
+
+      get api_changeset_comments_path(:from => "2023-03-15T00:00:00Z")
+      assert_response :success
+      assert_comments_in_order [comment23, comment22]
+
+      get api_changeset_comments_path(:from => "2023-01-15T00:00:00Z", :to => "2023-04-15T00:00:00Z")
+      assert_response :success
+      assert_comments_in_order [comment22, comment21, comment12]
+
+      get api_changeset_comments_path(:user => user1.id)
+      assert_response :success
+      assert_comments_in_order [comment22, comment21, comment11]
+
+      get api_changeset_comments_path(:from => "2023-03-15T00:00:00Z", :format => "json")
+      assert_response :success
+      js = ActiveSupport::JSON.decode(@response.body)
+      assert_not_nil js
+      assert_equal 2, js["comments"].count
+      assert_equal comment23.id, js["comments"][0]["id"]
+      assert_equal comment22.id, js["comments"][1]["id"]
+    end
+
     def test_create_by_unauthorized
       assert_no_difference "ChangesetComment.count" do
         post changeset_comment_path(create(:changeset, :closed), :text => "This is a comment")
@@ -422,5 +470,20 @@ module Api
       assert_response :success
       assert comment.reload.visible
     end
+
+    private
+
+    ##
+    # check that certain comments exist in the output in the specified order
+    def assert_comments_in_order(comments)
+      assert_dom "osm > comment", comments.size do |dom_comments|
+        comments.zip(dom_comments).each do |comment, dom_comment|
+          assert_dom dom_comment, "> @id", comment.id.to_s
+          assert_dom dom_comment, "> @uid", comment.author.id.to_s
+          assert_dom dom_comment, "> @user", comment.author.display_name
+          assert_dom dom_comment, "> text", comment.body
+        end
+      end
+    end
   end
 end
index 17ceb1b9e5b8b58b96ba2d66d22fe310978716c7..f1a0f766c9b23858c4bf9b8d2e646afeb42bb255 100644 (file)
@@ -1066,6 +1066,37 @@ module Api
       assert_select "gpx", :count => 1 do
         assert_select "wpt", :count => 1
       end
+
+      user2 = create(:user)
+      get search_api_notes_path(:user => user2.id, :format => "xml")
+      assert_response :success
+      assert_equal "application/xml", @response.media_type
+      assert_select "osm", :count => 1 do
+        assert_select "note", :count => 0
+      end
+    end
+
+    def test_search_by_time_success
+      note1 = create(:note, :created_at => "2020-02-01T00:00:00Z", :updated_at => "2020-04-01T00:00:00Z")
+      note2 = create(:note, :created_at => "2020-03-01T00:00:00Z", :updated_at => "2020-05-01T00:00:00Z")
+
+      get search_api_notes_path(:from => "2020-02-15T00:00:00Z", :to => "2020-04-15T00:00:00Z", :format => "xml")
+      assert_response :success
+      assert_equal "application/xml", @response.media_type
+      assert_select "osm", :count => 1 do
+        assert_select "note", :count => 1 do
+          assert_select "id", note2.id.to_s
+        end
+      end
+
+      get search_api_notes_path(:from => "2020-02-15T00:00:00Z", :to => "2020-04-15T00:00:00Z", :sort => "updated_at", :format => "xml")
+      assert_response :success
+      assert_equal "application/xml", @response.media_type
+      assert_select "osm", :count => 1 do
+        assert_select "note", :count => 1 do
+          assert_select "id", note1.id.to_s
+        end
+      end
     end
 
     def test_search_by_bbox_success
index a72ca21107f9be065f48dd6bde0c7ad3779f5de4..877af5ad71adf783aaadc38e54447af99ffd34cd 100644 (file)
@@ -23,7 +23,7 @@ describe("OSM", function () {
 
   describe(".params", function () {
     it("parses params", function () {
-      var params = OSM.params("?foo=a&bar=b");
+      const params = OSM.params("?foo=a&bar=b");
       expect(params).to.have.property("foo", "a");
       expect(params).to.have.property("bar", "b");
     });
@@ -41,14 +41,14 @@ describe("OSM", function () {
     });
 
     it("parses marker params", function () {
-      var params = OSM.mapParams("?mlat=57.6247&mlon=-3.6845");
+      const params = OSM.mapParams("?mlat=57.6247&mlon=-3.6845");
       expect(params).to.have.property("mlat", 57.6247);
       expect(params).to.have.property("mlon", -3.6845);
       expect(params).to.have.property("marker", true);
     });
 
     it("parses object params", function () {
-      var params = OSM.mapParams("?node=1");
+      let params = OSM.mapParams("?node=1");
       expect(params).to.have.property("object");
       expect(params.object).to.eql({ type: "node", id: 1 });
 
@@ -62,8 +62,8 @@ describe("OSM", function () {
     });
 
     it("parses bbox params", function () {
-      var expected = L.latLngBounds([57.6247, -3.6845], [57.7247, -3.7845]);
-      var params = OSM.mapParams("?bbox=-3.6845,57.6247,-3.7845,57.7247");
+      const expected = L.latLngBounds([57.6247, -3.6845], [57.7247, -3.7845]);
+      let params = OSM.mapParams("?bbox=-3.6845,57.6247,-3.7845,57.7247");
       expect(params).to.have.property("bounds").deep.equal(expected);
 
       params = OSM.mapParams("?minlon=-3.6845&minlat=57.6247&maxlon=-3.7845&maxlat=57.7247");
@@ -71,7 +71,7 @@ describe("OSM", function () {
     });
 
     it("parses mlat/mlon/zoom params", function () {
-      var params = OSM.mapParams("?mlat=57.6247&mlon=-3.6845");
+      let params = OSM.mapParams("?mlat=57.6247&mlon=-3.6845");
       expect(params).to.have.property("lat", 57.6247);
       expect(params).to.have.property("lon", -3.6845);
       expect(params).to.have.property("zoom", 12);
@@ -92,21 +92,21 @@ describe("OSM", function () {
 
     it("sets lat/lon from OSM.home", function () {
       OSM.home = { lat: 57.6247, lon: -3.6845 };
-      var params = OSM.mapParams("?");
+      const params = OSM.mapParams("?");
       expect(params).to.have.property("lat", 57.6247);
       expect(params).to.have.property("lon", -3.6845);
     });
 
     it("sets bbox from OSM.location", function () {
       OSM.location = { minlon: -3.6845, minlat: 57.6247, maxlon: -3.7845, maxlat: 57.7247 };
-      var expected = L.latLngBounds([57.6247, -3.6845], [57.7247, -3.7845]);
-      var params = OSM.mapParams("?");
+      const expected = L.latLngBounds([57.6247, -3.6845], [57.7247, -3.7845]);
+      const params = OSM.mapParams("?");
       expect(params).to.have.property("bounds").deep.equal(expected);
     });
 
     it("parses params from the _osm_location cookie", function () {
       document.cookie = "_osm_location=-3.6845|57.6247|5|M";
-      var params = OSM.mapParams("?");
+      const params = OSM.mapParams("?");
       expect(params).to.have.property("lat", 57.6247);
       expect(params).to.have.property("lon", -3.6845);
       expect(params).to.have.property("zoom", 5);
@@ -114,7 +114,7 @@ describe("OSM", function () {
     });
 
     it("defaults lat/lon to London", function () {
-      var params = OSM.mapParams("?");
+      let params = OSM.mapParams("?");
       expect(params).to.have.property("lat", 51.5);
       expect(params).to.have.property("lon", -0.1);
       expect(params).to.have.property("zoom", 5);
@@ -126,7 +126,7 @@ describe("OSM", function () {
     });
 
     it("parses layers param", function () {
-      var params = OSM.mapParams("?");
+      let params = OSM.mapParams("?");
       expect(params).to.have.property("layers", "");
 
       document.cookie = "_osm_location=-3.6845|57.6247|5|C";
@@ -141,25 +141,25 @@ describe("OSM", function () {
 
   describe(".parseHash", function () {
     it("parses lat/lon/zoom params", function () {
-      var args = OSM.parseHash("#map=5/57.6247/-3.6845&layers=M");
+      const args = OSM.parseHash("#map=5/57.6247/-3.6845&layers=M");
       expect(args).to.have.property("center").deep.equal(L.latLng(57.6247, -3.6845));
       expect(args).to.have.property("zoom", 5);
     });
 
     it("parses layers params", function () {
-      var args = OSM.parseHash("#map=5/57.6247/-3.6845&layers=M");
+      const args = OSM.parseHash("#map=5/57.6247/-3.6845&layers=M");
       expect(args).to.have.property("layers", "M");
     });
   });
 
   describe(".formatHash", function () {
     it("formats lat/lon/zoom params", function () {
-      var args = { center: L.latLng(57.6247, -3.6845), zoom: 9 };
+      const args = { center: L.latLng(57.6247, -3.6845), zoom: 9 };
       expect(OSM.formatHash(args)).to.eq("#map=9/57.625/-3.685");
     });
 
     it("respects zoomPrecision", function () {
-      var args = { center: L.latLng(57.6247, -3.6845), zoom: 5 };
+      let args = { center: L.latLng(57.6247, -3.6845), zoom: 5 };
       expect(OSM.formatHash(args)).to.eq("#map=5/57.62/-3.68");
 
 
@@ -172,12 +172,12 @@ describe("OSM", function () {
     });
 
     it("formats layers params", function () {
-      var args = { center: L.latLng(57.6247, -3.6845), zoom: 9, layers: "C" };
+      const args = { center: L.latLng(57.6247, -3.6845), zoom: 9, layers: "C" };
       expect(OSM.formatHash(args)).to.eq("#map=9/57.625/-3.685&layers=C");
     });
 
     it("ignores default layers", function () {
-      var args = { center: L.latLng(57.6247, -3.6845), zoom: 9, layers: "M" };
+      const args = { center: L.latLng(57.6247, -3.6845), zoom: 9, layers: "M" };
       expect(OSM.formatHash(args)).to.eq("#map=9/57.625/-3.685");
     });
   });
@@ -230,14 +230,14 @@ describe("OSM", function () {
   describe(".locationCookie", function () {
     it("creates a location cookie value", function () {
       $("body").html($("<div id='map'>"));
-      var map = new L.OSM.Map("map", { center: [57.6247, -3.6845], zoom: 9 });
+      const map = new L.OSM.Map("map", { center: [57.6247, -3.6845], zoom: 9 });
       map.updateLayers("");
       expect(OSM.locationCookie(map)).to.eq("-3.685|57.625|9|M");
     });
 
     it("respects zoomPrecision", function () {
       $("body").html($("<div id='map'>"));
-      var map = new L.OSM.Map("map", { center: [57.6247, -3.6845], zoom: 9 });
+      const map = new L.OSM.Map("map", { center: [57.6247, -3.6845], zoom: 9 });
       map.updateLayers("");
       expect(OSM.locationCookie(map)).to.eq("-3.685|57.625|9|M");
       // map.setZoom() doesn't update the zoom level for some reason
@@ -249,8 +249,8 @@ describe("OSM", function () {
 
   describe(".distance", function () {
     it("computes distance between points", function () {
-      var latlng1 = L.latLng(51.76712, -0.00484),
-          latlng2 = L.latLng(51.7675159, -0.0078329);
+      const latlng1 = L.latLng(51.76712, -0.00484),
+            latlng2 = L.latLng(51.7675159, -0.0078329);
 
       expect(OSM.distance(latlng1, latlng2)).to.be.closeTo(210.664, 0.005);
       expect(OSM.distance(latlng2, latlng1)).to.be.closeTo(210.664, 0.005);
index c14045b1c0179b929f556c4c87fa615db71e16a8..a64274c0a6fa5a5c79008af8393c187f73cc1397 100644 (file)
@@ -100,7 +100,8 @@ Teaspoon.configure do |config|
   # Capybara Webkit: https://github.com/jejacks0n/teaspoon/wiki/Using-Capybara-Webkit
   require "selenium-webdriver"
   config.driver = :selenium
-  firefox_options = Selenium::WebDriver::Firefox::Options.new(:args => ["-headless"])
+  firefox_options = Selenium::WebDriver::Firefox::Options.new
+  firefox_options.args = ["-headless"] if Settings.system_test_headless
   firefox_options.binary = Settings.system_test_firefox_binary if Settings.system_test_firefox_binary
   config.driver_options = {
     :client_driver => :firefox,