X-Git-Url: https://git.openstreetmap.org./rails.git/blobdiff_plain/c3d1123965b2d9bc34299c3a6c64d186c62c0ed2..e6b0e1ae7ef45b87a61f18bb50296273d6dd1bfb:/app/assets/javascripts/osm.js.erb diff --git a/app/assets/javascripts/osm.js.erb b/app/assets/javascripts/osm.js.erb index 3c3378f98..25d6596c2 100644 --- a/app/assets/javascripts/osm.js.erb +++ b/app/assets/javascripts/osm.js.erb @@ -1,111 +1,214 @@ +//= depend_on settings.yml +//= depend_on settings.local.yml +//= depend_on layers.yml +//= depend_on key.yml + OSM = { -<% if defined?(PIWIK_LOCATION) and defined?(PIWIK_SITE) %> - PIWIK_LOCATION: <%= PIWIK_LOCATION.to_json %>, - PIWIK_SITE: <%= PIWIK_SITE.to_json %>, -<% end %> + ...<%= + %i[ + matomo + max_request_area + server_protocol + server_url + api_version + status + max_note_request_area + overpass_url + overpass_credentials + nominatim_url + graphhopper_url + fossgis_osrm_url + fossgis_valhalla_url + thunderforest_key + tracestrack_key + ] + .each_with_object({}) do |key, hash| + hash[key.to_s.upcase] = Settings.send(key) if Settings.respond_to?(key) + end.to_json + %>, - MAX_REQUEST_AREA: <%= MAX_REQUEST_AREA.to_json %>, - SERVER_URL: <%= SERVER_URL.to_json %>, - API_VERSION: <%= API_VERSION.to_json %>, + DEFAULT_LOCALE: <%= I18n.default_locale.to_json %>, - mapParams: function (search) { - var params = {}, mapParams = {}, loc; + LAYER_DEFINITIONS: <%= YAML.load_file(Rails.root.join("config/layers.yml")).to_json %>, + LAYERS_WITH_MAP_KEY: <%= YAML.load_file(Rails.root.join("config/key.yml")).keys.to_json %>, + + MARKER_GREEN: <%= image_path("marker-green.png").to_json %>, + MARKER_RED: <%= image_path("marker-red.png").to_json %>, + + MARKER_ICON: <%= image_path("leaflet/dist/images/marker-icon.png").to_json %>, + MARKER_ICON_2X: <%= image_path("leaflet/dist/images/marker-icon-2x.png").to_json %>, + MARKER_SHADOW: <%= image_path("leaflet/dist/images/marker-shadow.png").to_json %>, + + NEW_NOTE_MARKER: <%= image_path("new_note_marker.svg").to_json %>, + OPEN_NOTE_MARKER: <%= image_path("open_note_marker.svg").to_json %>, + CLOSED_NOTE_MARKER: <%= image_path("closed_note_marker.svg").to_json %>, - search = (search || window.location.search).replace('?', '').split('&'); + apiUrl: function (object) { + const apiType = object.type === "note" ? "notes" : object.type; + let url = "/api/" + OSM.API_VERSION + "/" + apiType + "/" + object.id; - for (var i = 0; i < search.length; ++i) { - var pair = search[i], - j = pair.indexOf('='), - key = pair.slice(0, j), - val = pair.slice(++j); - params[key] = decodeURIComponent(val); + if (object.type === "way" || object.type === "relation") { + url += "/full"; + } else if (object.version) { + url += "/" + object.version; } + return url; + }, + + params: function (search) { + const query = search || window.location.search; + return Object.fromEntries(new URLSearchParams(query)); + }, + + mapParams: function (search) { + const params = OSM.params(search), + mapParams = {}; + if (params.mlon && params.mlat) { mapParams.marker = true; mapParams.mlon = parseFloat(params.mlon); mapParams.mlat = parseFloat(params.mlat); } - if (params.layers) { - mapParams.layers = params.layers; + // Old-style object parameters; still in use for edit links e.g. /edit?way=1234 + for (const type of ["node", "way", "relation", "note"]) { + if (params[type]) { + mapParams.object = { type, id: parseInt(params[type], 10) }; + } } - if (params.node || params.way || params.relation) { - mapParams.object = true; - mapParams.object_zoom = true; - - if (params.node) { - mapParams.object_type = 'node'; - mapParams.object_id = parseInt(params.node); - } else if (params.way) { - mapParams.object_type = 'way'; - mapParams.object_id = parseInt(params.way); - } else if (params.relation) { - mapParams.object_type = 'relation'; - mapParams.object_id = parseInt(params.relation); - } + const hash = OSM.parseHash(location.hash); + + const loc = Cookies.get("_osm_location")?.split("|"); + + function bboxToLatLngBounds({ minlon, minlat, maxlon, maxlat }) { + return L.latLngBounds([minlat, minlon], [maxlat, maxlon]); } - // Decide on a lat lon to initialise the map with. Various ways of doing this - if (params.bbox) { - var bbox = params.bbox.split(","); - mapParams.bbox = true; - mapParams.minlon = parseFloat(bbox[0]); - mapParams.minlat = parseFloat(bbox[1]); - mapParams.maxlon = parseFloat(bbox[2]); - mapParams.maxlat = parseFloat(bbox[3]); - mapParams.object_zoom = false; + // Decide on a map starting position. Various ways of doing this. + if (hash.center) { + mapParams.lon = hash.center.lng; + mapParams.lat = hash.center.lat; + mapParams.zoom = hash.zoom; + } else if (params.bbox) { + const [minlon, minlat, maxlon, maxlat] = params.bbox.split(","); + mapParams.bounds = bboxToLatLngBounds({ minlon, minlat, maxlon, maxlat }); } else if (params.minlon && params.minlat && params.maxlon && params.maxlat) { - mapParams.bbox = true; - mapParams.minlon = parseFloat(params.minlon); - mapParams.minlat = parseFloat(params.minlat); - mapParams.maxlon = parseFloat(params.maxlon); - mapParams.maxlat = parseFloat(params.maxlat); - mapParams.object_zoom = false; - } else if (params.lon && params.lat) { - mapParams.lon = parseFloat(params.lon); - mapParams.lat = parseFloat(params.lat); - mapParams.zoom = parseInt(params.zoom || 5); - mapParams.object_zoom = false; + mapParams.bounds = bboxToLatLngBounds(params); } else if (params.mlon && params.mlat) { - mapParams.lon = parseFloat(params.mlon); - mapParams.lat = parseFloat(params.mlat); - mapParams.zoom = parseInt(params.zoom || 12); - mapParams.object_zoom = false; - } else if (loc = $.cookie('_osm_location')) { - loc = loc.split("|"); - mapParams.lon = parseFloat(loc[0]); - mapParams.lat = parseFloat(loc[1]); - mapParams.zoom = parseInt(loc[2]); - mapParams.layers = loc[3]; + mapParams.lon = params.mlon; + mapParams.lat = params.mlat; + mapParams.zoom = params.zoom || 12; + } else if (loc) { + [mapParams.lon, mapParams.lat, mapParams.zoom] = loc; } else if (OSM.home) { mapParams.lon = OSM.home.lon; mapParams.lat = OSM.home.lat; mapParams.zoom = 10; } else if (OSM.location) { - mapParams.bbox = true; - mapParams.minlon = OSM.location.minlon; - mapParams.minlat = OSM.location.minlat; - mapParams.maxlon = OSM.location.maxlon; - mapParams.maxlat = OSM.location.maxlat; + mapParams.bounds = bboxToLatLngBounds(OSM.location); } else { mapParams.lon = -0.1; mapParams.lat = 51.5; - mapParams.zoom = parseInt(params.zoom || 5); + mapParams.zoom = params.zoom || 5; } - if (mapParams.bbox) { - mapParams.box = params.box == "yes"; - mapParams.lon = (mapParams.minlon + mapParams.maxlon) / 2; - mapParams.lat = (mapParams.minlat + mapParams.maxlat) / 2; - } + if (typeof mapParams.lat === "string") mapParams.lat = parseFloat(mapParams.lat); + if (typeof mapParams.lon === "string") mapParams.lon = parseFloat(mapParams.lon); + if (typeof mapParams.zoom === "string") mapParams.zoom = parseInt(mapParams.zoom, 10); + + 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); } return mapParams; + }, + + parseHash: function (hash) { + const args = {}; + + const i = hash.indexOf("#"); + if (i < 0) { + return args; + } + + const hashParams = new URLSearchParams(hash.slice(i + 1)); + + 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); + args.zoom = zoom; + } + + if (hashParams.has("layers")) { + args.layers = hashParams.get("layers"); + } + + return args; + }, + + formatHash: function (args) { + let center, zoom, layers; + + if (args instanceof L.Map) { + center = args.getCenter(); + zoom = args.getZoom(); + layers = args.getLayersCode(); + } else { + center = args.center || L.latLng(args.lat, args.lon); + zoom = args.zoom; + layers = args.layers || ""; + } + + layers = layers.replace("M", ""); + + let hash = "#map=" + [zoom, ...OSM.cropLocation(center, zoom)].join("/"); + + if (layers) { + hash += "&layers=" + layers; + } + + return hash; + }, + + zoomPrecision: function (zoom) { + const pixels = Math.pow(2, 8 + zoom); + const degrees = 180; + return Math.ceil(Math.log10(pixels / degrees)); + }, + + cropLocation: function (latLng, zoom) { + const precision = OSM.zoomPrecision(zoom), + wrapped = latLng.wrap(); + return [wrapped.lat, wrapped.lng].map(c => c.toFixed(precision)); + }, + + locationCookie: function (map) { + const zoom = map.getZoom(), + center = OSM.cropLocation(map.getCenter(), zoom).reverse(); + return [...center, zoom, map.getLayersCode()].join("|"); + }, + + distance: function (latlng1, latlng2) { + 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( + Math.pow(Math.sin(latdiff / 2), 2) + + (Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(lngdiff / 2), 2)) + )); } };