From: Tom Hughes Date: Sat, 13 Oct 2012 14:55:34 +0000 (+0100) Subject: Merge branch 'master' into notes X-Git-Tag: live~6160^2~95 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/00375024263970a43ea7d39e3c65dfd0f32e8869?hp=4377418d53a668d369b38f298db46cb7ef68b0de Merge branch 'master' into notes Conflicts: Gemfile.lock app/views/browse/_map.html.erb app/views/site/index.html.erb --- diff --git a/Gemfile b/Gemfile index 5193881af..ce13c6532 100644 --- a/Gemfile +++ b/Gemfile @@ -20,7 +20,7 @@ gem 'rinku', '>= 1.2.2', :require => 'rails_rinku' gem 'oauth-plugin', '>= 0.4.1', :require => 'oauth-plugin' gem 'open_id_authentication', '>= 1.1.0' gem 'validates_email_format_of', '>= 1.5.1' -gem 'composite_primary_keys', '>= 5.0.8' +gem 'composite_primary_keys', '>= 5.0.9' gem 'http_accept_language', '>= 1.0.2' gem 'paperclip', '~> 2.0' gem 'deadlock_retry', '>= 1.2.0' @@ -64,4 +64,5 @@ group :assets do gem 'coffee-rails', '~> 3.2.1' gem 'uglifier', '>= 1.0.3' gem 'therubyracer' + gem 'ejs' end diff --git a/Gemfile.lock b/Gemfile.lock index 666b6a094..23eeceb19 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,7 +32,7 @@ GEM arel (3.0.2) bigdecimal (1.1.0) builder (3.0.3) - cocaine (0.3.0) + cocaine (0.4.0) coffee-rails (3.2.2) coffee-script (>= 2.2.0) railties (~> 3.2.0) @@ -40,10 +40,11 @@ GEM coffee-script-source execjs coffee-script-source (1.3.3) - composite_primary_keys (5.0.8) - activerecord (~> 3.2.0) + composite_primary_keys (5.0.9) + activerecord (~> 3.2.0, >= 3.2.8) deadlock_retry (1.2.0) dynamic_form (1.1.4) + ejs (1.1.1) erubis (2.7.0) execjs (1.4.0) multi_json (~> 1.0) @@ -52,14 +53,14 @@ GEM hike (1.2.1) htmlentities (4.3.1) http_accept_language (1.0.2) - httpauth (0.1) - httpclient (2.2.7) + httpauth (0.2.0) + httpclient (2.3.0.1) i18n (0.6.1) i18n-js (3.0.0.rc2) i18n iconv (0.1) journey (1.0.4) - jquery-rails (2.1.2) + jquery-rails (2.1.3) railties (>= 3.1.0, < 5.0) thor (~> 0.14) json (1.7.5) @@ -76,9 +77,9 @@ GEM i18n (>= 0.4.0) mime-types (~> 1.16) treetop (~> 1.4.8) - memcached (1.4.5) + memcached (1.4.6) mime-types (1.19) - minitest (3.4.0) + minitest (4.1.0) multi_json (1.3.6) multipart-post (1.1.5) nokogiri (1.5.5) @@ -96,7 +97,7 @@ GEM rack (~> 1.2) open_id_authentication (1.1.0) rack-openid (~> 1.3) - paperclip (2.7.0) + paperclip (2.8.0) activerecord (>= 2.3.0) activesupport (>= 2.3.2) cocaine (>= 0.0.2) @@ -111,7 +112,7 @@ GEM ruby-openid (>= 2.1.8) rack-ssl (1.3.2) rack - rack-test (0.6.1) + rack-test (0.6.2) rack (>= 1.0) rails (3.2.8) actionmailer (= 3.2.8) @@ -133,9 +134,9 @@ GEM rake (0.9.2.2) rdoc (3.12) json (~> 1.4) - redcarpet (2.1.1) - rinku (1.7.0) - ruby-openid (2.2.0) + redcarpet (2.2.1) + rinku (1.7.2) + ruby-openid (2.2.1) sanitize (2.0.3) nokogiri (>= 1.4.4, < 1.6) sass (3.2.1) @@ -151,8 +152,8 @@ GEM libv8 (~> 3.3.10) thor (0.16.0) tilt (1.3.3) - timecop (0.5.1) - treetop (1.4.10) + timecop (0.5.2) + treetop (1.4.11) polyglot polyglot (>= 0.3.1) tzinfo (0.3.33) @@ -168,9 +169,10 @@ DEPENDENCIES SystemTimer (>= 1.1.3) bigdecimal coffee-rails (~> 3.2.1) - composite_primary_keys (>= 5.0.8) + composite_primary_keys (>= 5.0.9) deadlock_retry (>= 1.2.0) dynamic_form + ejs htmlentities http_accept_language (>= 1.0.2) httpclient diff --git a/app/assets/images/attribution_example.png b/app/assets/images/attribution_example.png new file mode 100644 index 000000000..463c80ed0 Binary files /dev/null and b/app/assets/images/attribution_example.png differ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 71eb71711..6ee15af5b 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -6,13 +6,9 @@ //= require augment //= require openlayers //= require i18n/translations -//= require globals -//= require params +//= require osm //= require piwik -//= require browse -//= require export //= require map -//= require key //= require menu //= require sidebar //= require richtext @@ -30,7 +26,7 @@ function zoomPrecision(zoom) { * Called as the user scrolls/zooms around to aniplate hrefs of the * view tab and various other links */ -function updatelinks(lon,lat,zoom,layers,minlon,minlat,maxlon,maxlat,objtype,objid) { +function updatelinks(lon,lat,zoom,layers,minlon,minlat,maxlon,maxlat,object) { var toPrecision = zoomPrecision(zoom); var node; @@ -59,8 +55,8 @@ function updatelinks(lon,lat,zoom,layers,minlon,minlat,maxlon,maxlat,objtype,obj args.layers = layers; } - if (objtype && $(link).hasClass("object")) { - args[objtype] = objid; + if (object && $(link).hasClass("object")) { + args[object.type] = object.id; } var minzoom = $(link).data("minzoom"); @@ -88,8 +84,8 @@ function updatelinks(lon,lat,zoom,layers,minlon,minlat,maxlon,maxlat,objtype,obj var prefix = shortlinkPrefix(); // Add ?{node,way,relation}=id to the arguments - if (objtype && objid) { - args[objtype] = objid; + if (object) { + args[object.type] = object.id; } // This is a hack to omit the default mapnik layer from the shortlink. @@ -104,7 +100,7 @@ function updatelinks(lon,lat,zoom,layers,minlon,minlat,maxlon,maxlat,objtype,obj // ?{node,way,relation}= can be safely omitted from the shortlink // which encodes lat/lon/zoom. If new URL parameters are added to // the main slippy map this needs to be changed. - if (args.layers || args[objtype]) { + if (args.layers || object) { this.href = setArgs(prefix + "/go/" + code, args); } else { this.href = prefix + "/go/" + code; diff --git a/app/assets/javascripts/browse.js b/app/assets/javascripts/browse.js index 769cc112e..08b355991 100644 --- a/app/assets/javascripts/browse.js +++ b/app/assets/javascripts/browse.js @@ -1,549 +1,99 @@ -function startBrowse(sidebarHtml) { - var browseBoxControl; - var browseMode = "auto"; - var browseBounds; - var browseFeatureList; - var browseActiveFeature; - var browseDataLayer; - var browseSelectControl; - var browseObjectList; - var areasHidden = false; - - OpenLayers.Feature.Vector.style['default'].strokeWidth = 3; - OpenLayers.Feature.Vector.style['default'].cursor = "pointer"; - - map.dataLayer.active = true; - - $("#sidebar_title").html(I18n.t('browse.start_rjs.data_frame_title')); - $("#sidebar_content").html(sidebarHtml); - - openSidebar(); - - var vectors = new OpenLayers.Layer.Vector(); - - browseBoxControl = new OpenLayers.Control.DrawFeature(vectors, OpenLayers.Handler.RegularPolygon, { - handlerOptions: { - sides: 4, - snapAngle: 90, - irregular: true, - persist: true - } - }); - browseBoxControl.handler.callbacks.done = endDrag; - map.addControl(browseBoxControl); - - map.events.register("moveend", map, updateData); - map.events.triggerEvent("moveend"); - - $("#browse_select_view").click(useMap); - - $("#browse_select_box").click(startDrag); - - $("#browse_hide_areas_box").html(I18n.t('browse.start_rjs.hide_areas')); - $("#browse_hide_areas_box").show(); - $("#browse_hide_areas_box").click(hideAreas); - - function updateData() { - if (browseMode == "auto") { - if (map.getZoom() >= 15) { - useMap(false); - } else { - setStatus(I18n.t('browse.start_rjs.zoom_or_select')); - } - } - } - - $("#sidebar").one("closed", function () { - if (map.dataLayer.active) { - map.dataLayer.active = false; - - if (browseSelectControl) { - browseSelectControl.destroy(); - browseSelectControl = null; - } - - if (browseBoxControl) { - browseBoxControl.destroy(); - browseBoxControl = null; - } - - if (browseActiveFeature) { - browseActiveFeature.destroy(); - browseActiveFeature = null; - } - - if (browseDataLayer) { - browseDataLayer.destroy(); - browseDataLayer = null; - } - - map.dataLayer.setVisibility(false); - map.events.unregister("moveend", map, updateData); - } - }); - - function startDrag() { - $("#browse_select_box").html(I18n.t('browse.start_rjs.drag_a_box')); - - browseBoxControl.activate(); - - return false; - } - - function useMap(reload) { - var bounds = map.getExtent(); - var projected = bounds.clone().transform(map.getProjectionObject(), epsg4326); - - if (!browseBounds || !browseBounds.containsBounds(projected)) { - var center = bounds.getCenterLonLat(); - var tileWidth = bounds.getWidth() * 1.2; - var tileHeight = bounds.getHeight() * 1.2; - var tileBounds = new OpenLayers.Bounds(center.lon - (tileWidth / 2), - center.lat - (tileHeight / 2), - center.lon + (tileWidth / 2), - center.lat + (tileHeight / 2)); - - browseBounds = tileBounds; - getData(tileBounds, reload); - - browseMode = "auto"; - - $("#browse_select_view").hide(); - } - - return false; - } - - function hideAreas() { - $("#browse_hide_areas_box").html(I18n.t('browse.start_rjs.show_areas')); - $("#browse_hide_areas_box").show(); - $("#browse_hide_areas_box").click(showAreas); - - areasHidden = true; - - useMap(true); - } - - function showAreas() { - $("#browse_hide_areas_box").html(I18n.t('browse.start_rjs.hide_areas')); - $("#browse_hide_areas_box").show(); - $("#browse_hide_areas_box").click(hideAreas); - - areasHidden = false; - - useMap(true); - } - - function endDrag(bbox) { - var bounds = bbox.getBounds(); - var projected = bounds.clone().transform(map.getProjectionObject(), epsg4326); - - browseBoxControl.deactivate(); - browseBounds = projected; - getData(bounds); - - browseMode = "manual"; - - $("#browse_select_box").html(I18n.t('browse.start_rjs.manually_select')); - $("#browse_select_view").show(); - } - - function displayFeatureWarning(count, limit, callback) { - clearStatus(); - - var div = document.createElement("div"); - - var p = document.createElement("p"); - p.appendChild(document.createTextNode(I18n.t("browse.start_rjs.loaded_an_area_with_num_features", { num_features: count, max_features: limit }))); - div.appendChild(p); - - var input = document.createElement("input"); - input.type = "submit"; - input.value = I18n.t('browse.start_rjs.load_data'); - input.onclick = callback; - div.appendChild(input); - - $("#browse_content").html(""); - $("#browse_content").append(div); - } - - function customDataLoader(resp, options) { - if (map.dataLayer.active) { - var request = resp.priv; - var doc = request.responseXML; - - if (!doc || !doc.documentElement) { - doc = request.responseText; - } - - resp.features = this.format.read(doc); - - if (!this.maxFeatures || resp.features.length <= this.maxFeatures) { - options.callback.call(options.scope, resp); - } else { - displayFeatureWarning(resp.features.length, this.maxFeatures, function () { - options.callback.call(options.scope, resp); - }); - } - } - } - - function getData(bounds, reload) { - var projected = bounds.clone().transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326")); - var size = projected.getWidth() * projected.getHeight(); - - if (size > OSM.MAX_REQUEST_AREA) { - setStatus(I18n.t("browse.start_rjs.unable_to_load_size", { max_bbox_size: OSM.MAX_REQUEST_AREA, bbox_size: size })); - } else { - loadData("/api/" + OSM.API_VERSION + "/map?bbox=" + projected.toBBOX(), reload); - } - } - - function loadData(url, reload) { - setStatus(I18n.t('browse.start_rjs.loading')); - - $("#browse_content").empty(); - - var formatOptions = { - checkTags: true, - interestingTagsExclude: ['source','source_ref','source:ref','history','attribution','created_by','tiger:county','tiger:tlid','tiger:upload_uuid'] - }; - - if (areasHidden) formatOptions.areaTags = []; - - if (!browseDataLayer || reload) { - var style = new OpenLayers.Style(); - - style.addRules([new OpenLayers.Rule({ - symbolizer: { - Polygon: { fillColor: '#ff0000', strokeColor: '#ff0000' }, - Line: { fillColor: '#ffff00', strokeColor: '#000000', strokeOpacity: '0.4' }, - Point: { fillColor: '#00ff00', strokeColor: '#00ff00' } - } - })]); - - if (browseDataLayer) browseDataLayer.destroyFeatures(); - - /* - * Modern browsers are quite happy showing far more than 100 features in - * the data browser, so increase the limit to 2000 by default, but keep - * it restricted to 500 for IE8 and 100 for older IEs. - */ - var maxFeatures = 2000; - - /*@cc_on - if (navigator.appVersion < 8) { - maxFeatures = 100; - } else if (navigator.appVersion < 9) { - maxFeatures = 500; - } - @*/ - - browseDataLayer = new OpenLayers.Layer.Vector("Data", { - strategies: [ - new OpenLayers.Strategy.Fixed() - ], - protocol: new OpenLayers.Protocol.HTTP({ - url: url, - format: new OpenLayers.Format.OSM(formatOptions), - maxFeatures: maxFeatures, - handleRead: customDataLoader - }), - projection: new OpenLayers.Projection("EPSG:4326"), - displayInLayerSwitcher: false, - styleMap: new OpenLayers.StyleMap({ - 'default': style, - 'select': { strokeColor: '#0000ff', strokeWidth: 8 } - }) - }); - browseDataLayer.events.register("loadend", browseDataLayer, dataLoaded ); - map.addLayer(browseDataLayer); - - browseSelectControl = new OpenLayers.Control.SelectFeature(browseDataLayer, { onSelect: onFeatureSelect }); - browseSelectControl.handlers.feature.stopDown = false; - browseSelectControl.handlers.feature.stopUp = false; - map.addControl(browseSelectControl); - browseSelectControl.activate(); +$(document).ready(function () { + function remoteEditHandler(bbox, select) { + var left = bbox.left - 0.0001; + var top = bbox.top + 0.0001; + var right = bbox.right + 0.0001; + var bottom = bbox.bottom - 0.0001; + var loaded = false; + + $("#linkloader").load(function () { loaded = true; }); + + if (select) { + $("#linkloader").attr("src", "http://127.0.0.1:8111/load_and_zoom?left=" + left + "&top=" + top + "&right=" + right + "&bottom=" + bottom + "&select=" + select); } else { - browseDataLayer.destroyFeatures(); - browseDataLayer.refresh({ url: url }); - } - - browseActiveFeature = null; - } - - function dataLoaded() { - if (this.map.dataLayer.active) { - clearStatus(); - - browseObjectList = document.createElement("div"); - - var heading = document.createElement("p"); - heading.className = "browse_heading"; - heading.appendChild(document.createTextNode(I18n.t('browse.start_rjs.object_list.heading'))); - browseObjectList.appendChild(heading); - - var list = document.createElement("ul"); - - for (var i = 0; i < this.features.length; i++) { - var feature = this.features[i]; - - // Type, for linking - var type = featureType(feature); - var typeName = featureTypeName(feature); - var li = document.createElement("li"); - li.appendChild(document.createTextNode(typeName + " ")); - - // Link, for viewing in the tab - var link = document.createElement("a"); - link.href = "/browse/" + type + "/" + feature.osm_id; - var name = featureName(feature); - link.appendChild(document.createTextNode(name)); - link.feature = feature; - link.onclick = OpenLayers.Function.bind(viewFeatureLink, link); - li.appendChild(link); - - list.appendChild(li); - } - - browseObjectList.appendChild(list); - - var link = document.createElement("a"); - link.href = this.protocol.url; - link.appendChild(document.createTextNode(I18n.t('browse.start_rjs.object_list.api'))); - browseObjectList.appendChild(link); - - $("#browse_content").html(browseObjectList); - } - } - - function viewFeatureLink() { - var layer = this.feature.layer; - - for (var i = 0; i < layer.selectedFeatures.length; i++) { - var f = layer.selectedFeatures[i]; - layer.drawFeature(f, layer.styleMap.createSymbolizer(f, "default")); - } - - onFeatureSelect(this.feature); - - if (browseMode != "auto") { - map.setCenter(this.feature.geometry.getBounds().getCenterLonLat()); + $("#linkloader").attr("src", "http://127.0.0.1:8111/load_and_zoom?left=" + left + "&top=" + top + "&right=" + right + "&bottom=" + bottom); } - return false; - } - - function loadObjectList() { - $("#browse_content").empty(); - $("#browse_content").append(browseObjectList); + setTimeout(function () { + if (!loaded) alert(I18n.t('site.index.remote_failed')); + }, 1000); return false; } - function onFeatureSelect(feature) { - // Unselect previously selected feature - if (browseActiveFeature) { - browseActiveFeature.layer.drawFeature( - browseActiveFeature, - browseActiveFeature.layer.styleMap.createSymbolizer(browseActiveFeature, "default") - ); - } - - // Redraw in selected style - feature.layer.drawFeature( - feature, feature.layer.styleMap.createSymbolizer(feature, "select") - ); - - // If the current object is the list, don't innerHTML="", since that could clear it. - if ($("#browse_content").firstChild == browseObjectList) { - $("#browse_content").removeChild(browseObjectList); - } else { - $("#browse_content").empty(); - } - - // Create a link back to the object list - var div = document.createElement("div"); - div.style.textAlign = "center"; - div.style.marginBottom = "20px"; - $("#browse_content").append(div); - var link = document.createElement("a"); - link.href = "#"; - link.onclick = loadObjectList; - link.appendChild(document.createTextNode(I18n.t('browse.start_rjs.object_list.back'))); - div.appendChild(link); - - var table = document.createElement("table"); - table.width = "100%"; - table.className = "browse_heading"; - $("#browse_content").append(table); + var map = createMap("small_map", { + controls: [ new OpenLayers.Control.Navigation() ] + }); - var tr = document.createElement("tr"); - table.appendChild(tr); + var params = $("#small_map").data(); + if (params.type == "changeset") { + var bbox = new OpenLayers.Bounds(params.minlon, params.minlat, params.maxlon, params.maxlat); + var centre = bbox.getCenterLonLat(); - var heading = document.createElement("td"); - heading.appendChild(document.createTextNode(featureNameSelect(feature))); - tr.appendChild(heading); + map.zoomToExtent(proj(bbox)); + addBoxToMap(bbox); - var td = document.createElement("td"); - td.align = "right"; - tr.appendChild(td); + $("#loading").hide(); + $("#browse_map .geolink").show(); - var type = featureType(feature); - var link = document.createElement("a"); - link.href = "/browse/" + type + "/" + feature.osm_id; - link.appendChild(document.createTextNode(I18n.t('browse.start_rjs.object_list.details'))); - td.appendChild(link); + $("a[data-editor=remote]").click(function () { + return remoteEditHandler(bbox); + }); - var div = document.createElement("div"); - div.className = "browse_details"; + updatelinks(centre.lon, centre.lat, 16, null, params.minlon, params.minlat, params.maxlon, params.maxlat); + } else if (params.type == "note") { + var centre = new OpenLayers.LonLat(params.lon, params.lat); - $("#browse_content").append(div); + setMapCenter(centre, 16); + addMarkerToMap(centre); - // Now the list of attributes - var ul = document.createElement("ul"); - for (var key in feature.attributes) { - var li = document.createElement("li"); - var b = document.createElement("b"); - b.appendChild(document.createTextNode(key)); - li.appendChild(b); - li.appendChild(document.createTextNode(": " + feature.attributes[key])); - ul.appendChild(li); - } + var bbox = getMapExtent(); - div.appendChild(ul); + $("#loading").hide(); + $("#browse_map .geolink").show(); - var link = document.createElement("a"); - link.href = "/browse/" + type + "/" + feature.osm_id + "/history"; - link.appendChild(document.createTextNode(I18n.t('browse.start_rjs.show_history'))); - link.onclick = OpenLayers.Function.bind(loadHistory, { - type: type, feature: feature, link: link + $("a[data-editor=remote]").click(function () { + return remoteEditHandler(bbox); }); - div.appendChild(link); - - // Stash the currently drawn feature - browseActiveFeature = feature; - } - - function loadHistory() { - this.link.href = ""; - this.link.innerHTML = I18n.t('browse.start_rjs.wait'); - - $.ajax("/api/" + OSM.API_VERSION + "/" + this.type + "/" + this.feature.osm_id + "/history", { - complete: OpenLayers.Function.bind(displayHistory, this) - }); + updatelinks(centre.lon, centre.lat, 16, null, bbox.left, bbox.bottom, bbox.right, bbox.top) + } else { + $("#object_larger_map").hide(); + $("#object_edit").hide(); - return false; - } + var object = {type: params.type, id: params.id}; - function displayHistory(request) { - if (browseActiveFeature.osm_id != this.feature.osm_id || $("#browse_content").firstChild == browseObjectList) { - return false; + if (!params.visible) { + object.version = params.version - 1; } - this.link.parentNode.removeChild(this.link); + addObjectToMap(object, true, function(extent) { + $("#loading").hide(); + $("#browse_map .geolink").show(); - var doc = request.responseXML; + if (extent) { + extent = unproj(extent); - var table = document.createElement("table"); - table.width = "100%"; - table.className = "browse_heading"; - $("#browse_content").append(table); + var centre = extent.getCenterLonLat(); - var tr = document.createElement("tr"); - table.appendChild(tr); - - var heading = document.createElement("td"); - heading.appendChild(document.createTextNode(I18n.t("browse.start_rjs.history_for_feature", { feature: featureNameHistory(this.feature) }))); - tr.appendChild(heading); - - var td = document.createElement("td"); - td.align = "right"; - tr.appendChild(td); - - var link = document.createElement("a"); - link.href = "/browse/" + this.type + "/" + this.feature.osm_id + "/history"; - link.appendChild(document.createTextNode(I18n.t('browse.start_rjs.details'))); - td.appendChild(link); - - var div = document.createElement("div"); - div.className = "browse_details"; - - var nodes = doc.getElementsByTagName(this.type); - var history = document.createElement("ul"); - for (var i = nodes.length - 1; i >= 0; i--) { - var user = nodes[i].getAttribute("user") || I18n.t('browse.start_rjs.private_user'); - var timestamp = nodes[i].getAttribute("timestamp"); - var item = document.createElement("li"); - item.appendChild(document.createTextNode(I18n.t("browse.start_rjs.edited_by_user_at_timestamp", { user: user, timestamp: timestamp }))); - history.appendChild(item); - } - div.appendChild(history); - - $("#browse_content").append(div); - } - - function featureType(feature) { - if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { - return "node"; - } else { - return "way"; - } - } - - function featureTypeName(feature) { - if (featureType(feature) == "node") { - return I18n.t('browse.start_rjs.object_list.type.node'); - } else if (featureType(feature) == "way") { - return I18n.t('browse.start_rjs.object_list.type.way'); - } - } - - function featureName(feature) { - var lang = $('html').attr('lang'); - if (feature.attributes['name:' + lang]) { - return feature.attributes['name:' + lang]; - } else if (feature.attributes.name) { - return feature.attributes.name; - } else { - return feature.osm_id; - } - } + $("a.bbox[data-editor=remote]").click(function () { + return remoteEditHandler(extent); + }); - function featureNameSelect(feature) { - var lang = $('html').attr('lang'); - if (feature.attributes['name:' + lang]) { - return feature.attributes['name:' + lang]; - } else if (feature.attributes.name) { - return feature.attributes.name; - } else if (featureType(feature) == "node") { - return I18n.t("browse.start_rjs.object_list.selected.type.node", { id: feature.osm_id }); - } else if (featureType(feature) == "way") { - return I18n.t("browse.start_rjs.object_list.selected.type.way", { id: feature.osm_id }); - } - } + $("a.object[data-editor=remote]").click(function () { + return remoteEditHandler(extent, params.type + params.id); + }); - function featureNameHistory(feature) { - var lang = $('html').attr('lang'); - if (feature.attributes['name:' + lang]) { - return feature.attributes['name:' + lang]; - } else if (feature.attributes.name) { - return feature.attributes.name; - } else if (featureType(feature) == "node") { - return I18n.t("browse.start_rjs.object_list.history.type.node", { id: feature.osm_id }); - } else if (featureType(feature) == "way") { - return I18n.t("browse.start_rjs.object_list.history.type.way", { id: feature.osm_id }); - } - } + $("#object_larger_map").show(); + $("#object_edit").show(); - function setStatus(status) { - $("#browse_status").html(status); - $("#browse_status").show(); + updatelinks(centre.lon, centre.lat, 16, null, extent.left, extent.bottom, extent.right, extent.top, object); + } else { + $("#small_map").hide(); + } + }); } - function clearStatus() { - $("#browse_status").html(""); - $("#browse_status").hide(); - } -} + createMenu("area_edit", "area_edit_menu", "right"); + createMenu("object_edit", "object_edit_menu", "right"); +}); diff --git a/app/assets/javascripts/changeset.js b/app/assets/javascripts/changeset.js new file mode 100644 index 000000000..ba6e541b6 --- /dev/null +++ b/app/assets/javascripts/changeset.js @@ -0,0 +1,83 @@ +$(document).ready(function () { + var highlight; + + function highlightChangeset(id) { + var feature = vectors.getFeatureByFid(id); + var bounds = feature.geometry.getBounds(); + + if (bounds.containsBounds(map.getExtent())) { + bounds = map.getExtent().scale(1.1); + } + + if (highlight) vectors.removeFeatures(highlight); + + highlight = new OpenLayers.Feature.Vector(bounds.toGeometry(), {}, { + strokeWidth: 2, + strokeColor: "#ee9900", + fillColor: "#ffff55", + fillOpacity: 0.5 + }); + + vectors.addFeatures(highlight); + + $("#tr-changeset-" + id).addClass("selected"); + } + + function unHighlightChangeset(id) { + vectors.removeFeatures(highlight); + + $("#tr-changeset-" + id).removeClass("selected"); + } + + var map = createMap("changeset_list_map", { + controls: [ + new OpenLayers.Control.Navigation(), + new OpenLayers.Control.Zoom(), + new OpenLayers.Control.SimplePanZoom() + ] + }); + + var bounds = new OpenLayers.Bounds(); + + $("[data-changeset]").each(function () { + var changeset = $(this).data('changeset'); + if (changeset.bbox) { + var bbox = new OpenLayers.Bounds(changeset.bbox.minlon, changeset.bbox.minlat, changeset.bbox.maxlon, changeset.bbox.maxlat); + + bounds.extend(bbox); + + addBoxToMap(bbox, changeset.id, true); + } + }); + + vectors.events.on({ + "featureselected": function(feature) { + highlightChangeset(feature.feature.fid); + }, + "featureunselected": function(feature) { + unHighlightChangeset(feature.feature.fid); + } + }); + + var selectControl = new OpenLayers.Control.SelectFeature(vectors, { + multiple: false, + hover: true + }); + map.addControl(selectControl); + selectControl.activate(); + + var params = OSM.mapParams(); + if (params.bbox) { + map.zoomToExtent(proj(new OpenLayers.Bounds(params.minlon, params.minlat, params.maxlon, params.maxlat))); + } else { + map.zoomToExtent(proj(bounds)); + } + + $("[data-changeset]").mouseover(function() { + highlightChangeset($(this).data("changeset").id); + }); + + $("[data-changeset]").mouseout(function() { + unHighlightChangeset($(this).data("changeset").id); + }); +}); diff --git a/app/assets/javascripts/diary_entry.js b/app/assets/javascripts/diary_entry.js new file mode 100644 index 000000000..c16930480 --- /dev/null +++ b/app/assets/javascripts/diary_entry.js @@ -0,0 +1,37 @@ +$(document).ready(function () { + var marker; + + function setLocation(e) { + closeMapPopup(); + + var lonlat = getEventPosition(e); + + $("#latitude").val(lonlat.lat); + $("#longitude").val(lonlat.lon); + + if (marker) { + removeMarkerFromMap(marker); + } + + marker = addMarkerToMap(lonlat, null, I18n.t('diary_entry.edit.marker_text')); + } + + $("#usemap").click(function (e) { + e.preventDefault(); + + $("#map").show(); + $("#usemap").hide(); + + var params = $("#map").data(); + var centre = new OpenLayers.LonLat(params.lon, params.lat); + var map = createMap("map"); + + setMapCenter(centre, params.zoom); + + if ($("#latitude").val() && $("#longitude").val()) { + marker = addMarkerToMap(centre, null, I18n.t('diary_entry.edit.marker_text')); + } + + map.events.register("click", map, setLocation); + }); +}); diff --git a/app/assets/javascripts/edit.js b/app/assets/javascripts/edit.js new file mode 100644 index 000000000..0b2b329b5 --- /dev/null +++ b/app/assets/javascripts/edit.js @@ -0,0 +1,43 @@ +function maximiseMap() { + $("#left").hide(); + $("#greeting").hide(); + $("#tabnav").hide(); + + $("#content").css("top", "0px"); + if ($("html").attr("dir") == "ltr") { + $("#content").css("left", "0px"); + } else { + $("#content").css("right", "0px"); + } + + handleResize(); +} + +function minimiseMap() { + $("#left").show(); + $("#greeting").show(); + $("#tabnav").show(); + + $("#content").css("top", "30px"); + if ($("html").attr("dir") == "ltr") { + $("#content").css("left", "185px"); + } else { + $("#content").css("right", "185px"); + } + + handleResize(); +} + +$(document).ready(function () { + $(window).resize(handleResize); + handleResize(); + + $("#search_form").submit(function () { + $("#sidebar_title").html(I18n.t('site.sidebar.search_results')); + $("#sidebar_content").load($(this).attr("action"), { + query: $("#query").val() + }, openSidebar); + + return false; + }); +}); diff --git a/app/assets/javascripts/export.js b/app/assets/javascripts/export.js deleted file mode 100644 index ae1871b50..000000000 --- a/app/assets/javascripts/export.js +++ /dev/null @@ -1,318 +0,0 @@ -function startExport(sidebarHtml) { - var vectors, - box, - transform, - markerLayer, - markerControl, - epsg4326 = new OpenLayers.Projection("EPSG:4326"), - epsg900913 = new OpenLayers.Projection("EPSG:900913"); - - vectors = new OpenLayers.Layer.Vector("Vector Layer", { - displayInLayerSwitcher: false - }); - map.addLayer(vectors); - - box = new OpenLayers.Control.DrawFeature(vectors, OpenLayers.Handler.RegularPolygon, { - handlerOptions: { - sides: 4, - snapAngle: 90, - irregular: true, - persist: true - } - }); - box.handler.callbacks.done = endDrag; - map.addControl(box); - - transform = new OpenLayers.Control.TransformFeature(vectors, { - rotate: false, - irregular: true - }); - transform.events.register("transformcomplete", transform, transformComplete); - map.addControl(transform); - - map.events.register("moveend", map, mapMoved); - map.events.register("changebaselayer", map, htmlUrlChanged); - - $("#sidebar_title").html(I18n.t('export.start_rjs.export')); - $("#sidebar_content").html(sidebarHtml); - - $("#maxlat,#minlon,#maxlon,#minlat").change(boundsChanged); - - $("#drag_box").click(startDrag); - - $("#add_marker").click(startMarker); - - $("#format_osm,#format_mapnik,#format_html").click(formatChanged); - - $("#mapnik_scale").change(mapnikSizeChanged); - - openSidebar(); - - if (map.baseLayer.name == "Mapnik") { - $("#format_mapnik").prop("checked", true); - } - - formatChanged(); - setBounds(map.getExtent()); - - $("body").removeClass("site-index").addClass("site-export"); - - $("#sidebar").one("closed", function () { - $("body").removeClass("site-export").addClass("site-index"); - - clearBox(); - clearMarker(); - map.events.unregister("moveend", map, mapMoved); - map.events.unregister("changebaselayer", map, htmlUrlChanged); - map.removeLayer(vectors); - }); - - function getMercatorBounds() { - var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), - $("#maxlon").val(), $("#maxlat").val()); - - return bounds.transform(epsg4326, epsg900913); - } - - function boundsChanged() { - var bounds = getMercatorBounds(); - - map.events.unregister("moveend", map, mapMoved); - map.zoomToExtent(bounds); - - clearBox(); - drawBox(bounds); - - validateControls(); - mapnikSizeChanged(); - } - - function startDrag() { - $("#drag_box").html(I18n.t('export.start_rjs.drag_a_box')); - - clearBox(); - box.activate(); - }; - - function endDrag(bbox) { - var bounds = bbox.getBounds(); - - map.events.unregister("moveend", map, mapMoved); - setBounds(bounds); - drawBox(bounds); - box.deactivate(); - validateControls(); - - $("#drag_box").html(I18n.t('export.start_rjs.manually_select')); - } - - function transformComplete(event) { - setBounds(event.feature.geometry.bounds); - validateControls(); - } - - function startMarker() { - $("#add_marker").html(I18n.t('export.start_rjs.click_add_marker')); - - if (!markerLayer) { - markerLayer = new OpenLayers.Layer.Vector("",{ - displayInLayerSwitcher: false, - style: { - externalGraphic: OpenLayers.Util.getImageLocation("marker.png"), - graphicXOffset: -10.5, - graphicYOffset: -25, - graphicWidth: 21, - graphicHeight: 25 - } - }); - map.addLayer(markerLayer); - - markerControl = new OpenLayers.Control.DrawFeature(markerLayer, OpenLayers.Handler.Point); - map.addControl(markerControl); - - markerLayer.events.on({ "featureadded": endMarker }); - } - - markerLayer.destroyFeatures(); - markerControl.activate(); - - return false; - } - - function endMarker(event) { - markerControl.deactivate(); - - $("#add_marker").html(I18n.t('export.start_rjs.change_marker')); - $("#marker_inputs").show(); - - var geom = event.feature.geometry.clone().transform(epsg900913, epsg4326); - - $("#marker_lon").val(geom.x.toFixed(5)); - $("#marker_lat").val(geom.y.toFixed(5)); - - htmlUrlChanged(); - } - - function clearMarker() { - $("#marker_lon,#marker_lat").val(""); - $("#marker_inputs").hide(); - $("#add_marker").html(I18n.t('export.start_rjs.add_marker')); - - if (markerLayer) { - markerControl.destroy(); - markerLayer.destroy(); - markerLayer = null; - markerControl = null; - } - } - - function mapMoved() { - setBounds(map.getExtent()); - validateControls(); - } - - function setBounds(bounds) { - var toPrecision = zoomPrecision(map.getZoom()); - - bounds = bounds.clone().transform(map.getProjectionObject(), epsg4326); - - $("#minlon").val(toPrecision(bounds.left)); - $("#minlat").val(toPrecision(bounds.bottom)); - $("#maxlon").val(toPrecision(bounds.right)); - $("#maxlat").val(toPrecision(bounds.top)); - - mapnikSizeChanged(); - htmlUrlChanged(); - } - - function clearBox() { - transform.deactivate(); - vectors.destroyFeatures(); - } - - function drawBox(bounds) { - var feature = new OpenLayers.Feature.Vector(bounds.toGeometry()); - - vectors.addFeatures(feature); - transform.setFeature(feature); - } - - function validateControls() { - var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val()); - - if (bounds.getWidth() * bounds.getHeight() > OSM.MAX_REQUEST_AREA) { - $("#export_osm_too_large").show(); - } else { - $("#export_osm_too_large").hide(); - } - - var max_scale = maxMapnikScale(); - var disabled = true; - - if ($("#format_osm").prop("checked")) { - disabled = bounds.getWidth() * bounds.getHeight() > OSM.MAX_REQUEST_AREA; - } else if ($("#format_mapnik").prop("checked")) { - disabled = $("#mapnik_scale").val() < max_scale; - } - - $("#export_commit").prop("disabled", disabled); - $("#mapnik_max_scale").html(roundScale(max_scale)); - } - - function htmlUrlChanged() { - var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val()); - var layerName = map.baseLayer.keyid; - var url = "http://" + OSM.SERVER_URL + "/export/embed.html?bbox=" + bounds.toBBOX() + "&layer=" + layerName; - var markerUrl = ""; - - if ($("#marker_lat").val() && $("#marker_lon").val()) { - markerUrl = "&mlat=" + $("#marker_lat").val() + "&mlon=" + $("#marker_lon").val(); - url += "&marker=" + $("#marker_lat").val() + "," + $("#marker_lon").val(); - } - - var html = ''; - - // Create "larger map" link - var center = bounds.getCenterLonLat(); - - bounds.transform(epsg4326, epsg900913); - var zoom = map.getZoomForExtent(bounds); - - var layers = getMapLayers(); - - var text = I18n.t('export.start_rjs.view_larger_map'); - var escaped = []; - - for (var i = 0; i < text.length; ++i) { - var c = text.charCodeAt(i); - escaped.push(c < 127 ? text.charAt(i) : "&#" + c + ";"); - } - - html += '
'+escaped.join("")+''; - - $("#export_html_text").val(html); - - if ($("#format_html").prop("checked")) { - $("#export_html_text").prop("selected", true); - } - } - - function formatChanged() { - $("#export_commit").show(); - - if ($("#format_osm").prop("checked")) { - $("#export_osm").show(); - } else { - $("#export_osm").hide(); - } - - if ($("#format_mapnik").prop("checked")) { - $("#mapnik_scale").val(roundScale(map.getScale())); - $("#export_mapnik").show(); - - mapnikSizeChanged(); - } else { - $("#export_mapnik").hide(); - } - - if ($("#format_html").prop("checked")) { - $("#export_html").show(); - $("#export_commit").hide(); - $("#export_html_text").prop("selected", true); - } else { - $("#export_html").hide(); - - clearMarker(); - } - - validateControls(); - } - - function maxMapnikScale() { - var bounds = getMercatorBounds(); - - return Math.floor(Math.sqrt(bounds.getWidth() * bounds.getHeight() / 0.3136)); - } - - function mapnikImageSize(scale) { - var bounds = getMercatorBounds(); - - return new OpenLayers.Size(Math.round(bounds.getWidth() / scale / 0.00028), - Math.round(bounds.getHeight() / scale / 0.00028)); - } - - function roundScale(scale) { - var precision = 5 * Math.pow(10, Math.floor(Math.LOG10E * Math.log(scale)) - 2); - - return precision * Math.ceil(scale / precision); - } - - function mapnikSizeChanged() { - var size = mapnikImageSize($("#mapnik_scale").val()); - - $("#mapnik_image_width").html(size.w); - $("#mapnik_image_height").html(size.h); - - validateControls(); - } -} diff --git a/app/assets/javascripts/globals.js.erb b/app/assets/javascripts/globals.js.erb deleted file mode 100644 index 3c3bd92a7..000000000 --- a/app/assets/javascripts/globals.js.erb +++ /dev/null @@ -1,9 +0,0 @@ -OSM = { -<% if defined?(PIWIK_LOCATION) and defined?(PIWIK_SITE) %> - PIWIK_LOCATION: <%= PIWIK_LOCATION.to_json %>, - PIWIK_SITE: <%= PIWIK_SITE.to_json %>, -<% end %> - MAX_REQUEST_AREA: <%= MAX_REQUEST_AREA.to_json %>, - SERVER_URL: <%= SERVER_URL.to_json %>, - API_VERSION: <%= API_VERSION.to_json %> -}; diff --git a/app/assets/javascripts/index.js b/app/assets/javascripts/index.js new file mode 100644 index 000000000..85f5dab0d --- /dev/null +++ b/app/assets/javascripts/index.js @@ -0,0 +1,122 @@ +//= require index/browse +//= require index/export +//= require index/key + +$(document).ready(function () { + var marker; + var params = OSM.mapParams(); + var map = createMap("map"); + + map.events.register("moveend", map, updateLocation); + map.events.register("changelayer", map, updateLocation); + + if (!params.object_zoom) { + if (params.bbox) { + var bbox = new OpenLayers.Bounds(params.minlon, params.minlat, params.maxlon, params.maxlat); + + map.zoomToExtent(proj(bbox)); + + if (params.box) { + addBoxToMap(bbox); + } + } else { + setMapCenter(new OpenLayers.LonLat(params.lon, params.lat), params.zoom); + } + } + + if (params.layers) { + setMapLayers(params.layers); + } + + if (params.marker) { + marker = addMarkerToMap(new OpenLayers.LonLat(params.mlon, params.mlat)); + } + + if (params.object) { + addObjectToMap(params.object, params.object_zoom); + } + + handleResize(); + + $("body").on("click", "a.set_position", function () { + var data = $(this).data(); + var centre = new OpenLayers.LonLat(data.lon, data.lat); + + if (data.minLon && data.minLat && data.maxLon && data.maxLat) { + var bbox = new OpenLayers.Bounds(data.minLon, data.minLat, data.maxLon, data.maxLat); + + map.zoomToExtent(proj(bbox)); + } else { + setMapCenter(centre, data.zoom); + } + + if (marker) { + removeMarkerFromMap(marker); + } + + marker = addMarkerToMap(centre, getArrowIcon()); + + return false; + }); + + function updateLocation() { + var lonlat = unproj(map.getCenter()); + var zoom = map.getZoom(); + var layers = getMapLayers(); + var extents = unproj(map.getExtent()); + var expiry = new Date(); + + updatelinks(lonlat.lon, lonlat.lat, zoom, layers, extents.left, extents.bottom, extents.right, extents.top, params.object); + + expiry.setYear(expiry.getFullYear() + 10); + $.cookie("_osm_location", [lonlat.lon, lonlat.lat, zoom, layers].join("|"), {expires: expiry}); + } + + function remoteEditHandler(event) { + var extent = unproj(map.getExtent()); + var loaded = false; + + $("#linkloader").load(function () { loaded = true; }); + $("#linkloader").attr("src", "http://127.0.0.1:8111/load_and_zoom?left=" + extent.left + "&top=" + extent.top + "&right=" + extent.right + "&bottom=" + extent.bottom); + + setTimeout(function () { + if (!loaded) alert(I18n.t('site.index.remote_failed')); + }, 1000); + + return false; + } + + $("a[data-editor=remote]").click(remoteEditHandler); + + if (OSM.preferred_editor == "remote" && $('body').hasClass("site-edit")) { + remoteEditHandler(); + } + + $(window).resize(function() { + var centre = map.getCenter(); + var zoom = map.getZoom(); + + handleResize(); + + map.setCenter(centre, zoom); + }); + + $("#search_form").submit(function () { + var extent = unproj(map.getExtent()); + + $("#sidebar_title").html(I18n.t('site.sidebar.search_results')); + $("#sidebar_content").load($(this).attr("action"), { + query: $("#query").val(), + minlon: extent.left, + minlat: extent.bottom, + maxlon: extent.right, + maxlat: extent.top + }, openSidebar); + + return false; + }); + + if ($("#query").val()) { + $("#search_form").submit(); + } +}); diff --git a/app/assets/javascripts/index/browse.js b/app/assets/javascripts/index/browse.js new file mode 100644 index 000000000..1792c8577 --- /dev/null +++ b/app/assets/javascripts/index/browse.js @@ -0,0 +1,467 @@ +//= require templates/browse/feature +//= require templates/browse/feature_list +//= require templates/browse/feature_history + +$(document).ready(function () { + $("#show_data").click(function (e) { + $.ajax({ url: $(this).attr('href'), success: function (sidebarHtml) { + startBrowse(sidebarHtml); + }}); + e.preventDefault(); + }); + + function startBrowse(sidebarHtml) { + var browseBoxControl; + var browseMode = "auto"; + var browseBounds; + var browseFeatureList; + var browseActiveFeature; + var browseDataLayer; + var browseSelectControl; + var browseObjectList; + var areasHidden = false; + + OpenLayers.Feature.Vector.style['default'].strokeWidth = 3; + OpenLayers.Feature.Vector.style['default'].cursor = "pointer"; + + map.dataLayer.active = true; + + $("#sidebar_title").html(I18n.t('browse.start_rjs.data_frame_title')); + $("#sidebar_content").html(sidebarHtml); + + openSidebar(); + + var vectors = new OpenLayers.Layer.Vector(); + + browseBoxControl = new OpenLayers.Control.DrawFeature(vectors, OpenLayers.Handler.RegularPolygon, { + handlerOptions: { + sides: 4, + snapAngle: 90, + irregular: true, + persist: true + } + }); + browseBoxControl.handler.callbacks.done = endDrag; + map.addControl(browseBoxControl); + + map.events.register("moveend", map, updateData); + map.events.triggerEvent("moveend"); + + $("#browse_select_view").click(useMap); + + $("#browse_select_box").click(startDrag); + + $("#browse_hide_areas_box").html(I18n.t('browse.start_rjs.hide_areas')); + $("#browse_hide_areas_box").show(); + $("#browse_hide_areas_box").click(hideAreas); + + function updateData() { + if (browseMode == "auto") { + if (map.getZoom() >= 15) { + useMap(false); + } else { + setStatus(I18n.t('browse.start_rjs.zoom_or_select')); + } + } + } + + $("#sidebar").one("closed", function () { + if (map.dataLayer.active) { + map.dataLayer.active = false; + + if (browseSelectControl) { + browseSelectControl.destroy(); + browseSelectControl = null; + } + + if (browseBoxControl) { + browseBoxControl.destroy(); + browseBoxControl = null; + } + + if (browseActiveFeature) { + browseActiveFeature.destroy(); + browseActiveFeature = null; + } + + if (browseDataLayer) { + browseDataLayer.destroy(); + browseDataLayer = null; + } + + map.dataLayer.setVisibility(false); + map.events.unregister("moveend", map, updateData); + } + }); + + function startDrag() { + $("#browse_select_box").html(I18n.t('browse.start_rjs.drag_a_box')); + + browseBoxControl.activate(); + + return false; + } + + function useMap(reload) { + var bounds = map.getExtent(); + var projected = unproj(bounds); + + if (!browseBounds || !browseBounds.containsBounds(projected)) { + var center = bounds.getCenterLonLat(); + var tileWidth = bounds.getWidth() * 1.2; + var tileHeight = bounds.getHeight() * 1.2; + var tileBounds = new OpenLayers.Bounds(center.lon - (tileWidth / 2), + center.lat - (tileHeight / 2), + center.lon + (tileWidth / 2), + center.lat + (tileHeight / 2)); + + browseBounds = tileBounds; + getData(tileBounds, reload); + + browseMode = "auto"; + + $("#browse_select_view").hide(); + } + + return false; + } + + function hideAreas() { + $("#browse_hide_areas_box").html(I18n.t('browse.start_rjs.show_areas')); + $("#browse_hide_areas_box").show(); + $("#browse_hide_areas_box").click(showAreas); + + areasHidden = true; + + useMap(true); + } + + function showAreas() { + $("#browse_hide_areas_box").html(I18n.t('browse.start_rjs.hide_areas')); + $("#browse_hide_areas_box").show(); + $("#browse_hide_areas_box").click(hideAreas); + + areasHidden = false; + + useMap(true); + } + + function endDrag(bbox) { + var bounds = bbox.getBounds(); + var projected = unproj(bounds); + + browseBoxControl.deactivate(); + browseBounds = projected; + getData(bounds); + + browseMode = "manual"; + + $("#browse_select_box").html(I18n.t('browse.start_rjs.manually_select')); + $("#browse_select_view").show(); + } + + function displayFeatureWarning(count, limit, callback) { + clearStatus(); + + var div = document.createElement("div"); + + var p = document.createElement("p"); + p.appendChild(document.createTextNode(I18n.t("browse.start_rjs.loaded_an_area_with_num_features", { num_features: count, max_features: limit }))); + div.appendChild(p); + + var input = document.createElement("input"); + input.type = "submit"; + input.value = I18n.t('browse.start_rjs.load_data'); + input.onclick = callback; + div.appendChild(input); + + $("#browse_content").html(""); + $("#browse_content").append(div); + } + + function customDataLoader(resp, options) { + if (map.dataLayer.active) { + var request = resp.priv; + var doc = request.responseXML; + + if (!doc || !doc.documentElement) { + doc = request.responseText; + } + + resp.features = this.format.read(doc); + + if (!this.maxFeatures || resp.features.length <= this.maxFeatures) { + options.callback.call(options.scope, resp); + } else { + displayFeatureWarning(resp.features.length, this.maxFeatures, function () { + options.callback.call(options.scope, resp); + }); + } + } + } + + function getData(bounds, reload) { + var projected = unproj(bounds); + var size = projected.getWidth() * projected.getHeight(); + + if (size > OSM.MAX_REQUEST_AREA) { + setStatus(I18n.t("browse.start_rjs.unable_to_load_size", { max_bbox_size: OSM.MAX_REQUEST_AREA, bbox_size: size })); + } else { + loadData("/api/" + OSM.API_VERSION + "/map?bbox=" + projected.toBBOX(), reload); + } + } + + function loadData(url, reload) { + setStatus(I18n.t('browse.start_rjs.loading')); + + $("#browse_content").empty(); + + var formatOptions = { + checkTags: true, + interestingTagsExclude: ['source','source_ref','source:ref','history','attribution','created_by','tiger:county','tiger:tlid','tiger:upload_uuid'] + }; + + if (areasHidden) formatOptions.areaTags = []; + + if (!browseDataLayer || reload) { + var style = new OpenLayers.Style(); + + style.addRules([new OpenLayers.Rule({ + symbolizer: { + Polygon: { fillColor: '#ff0000', strokeColor: '#ff0000' }, + Line: { fillColor: '#ffff00', strokeColor: '#000000', strokeOpacity: '0.4' }, + Point: { fillColor: '#00ff00', strokeColor: '#00ff00' } + } + })]); + + if (browseDataLayer) browseDataLayer.destroyFeatures(); + + /* + * Modern browsers are quite happy showing far more than 100 features in + * the data browser, so increase the limit to 2000 by default, but keep + * it restricted to 500 for IE8 and 100 for older IEs. + */ + var maxFeatures = 2000; + + /*@cc_on + if (navigator.appVersion < 8) { + maxFeatures = 100; + } else if (navigator.appVersion < 9) { + maxFeatures = 500; + } + @*/ + + browseDataLayer = new OpenLayers.Layer.Vector("Data", { + strategies: [ + new OpenLayers.Strategy.Fixed() + ], + protocol: new OpenLayers.Protocol.HTTP({ + url: url, + format: new OpenLayers.Format.OSM(formatOptions), + maxFeatures: maxFeatures, + handleRead: customDataLoader + }), + projection: new OpenLayers.Projection("EPSG:4326"), + displayInLayerSwitcher: false, + styleMap: new OpenLayers.StyleMap({ + 'default': style, + 'select': { strokeColor: '#0000ff', strokeWidth: 8 } + }) + }); + browseDataLayer.events.register("loadend", browseDataLayer, dataLoaded ); + map.addLayer(browseDataLayer); + + browseSelectControl = new OpenLayers.Control.SelectFeature(browseDataLayer, { onSelect: onFeatureSelect }); + browseSelectControl.handlers.feature.stopDown = false; + browseSelectControl.handlers.feature.stopUp = false; + map.addControl(browseSelectControl); + browseSelectControl.activate(); + } else { + browseDataLayer.destroyFeatures(); + browseDataLayer.refresh({ url: url }); + } + + browseActiveFeature = null; + } + + function dataLoaded() { + if (this.map.dataLayer.active) { + clearStatus(); + + var features = []; + for (var i = 0; i < this.features.length; i++) { + var feature = this.features[i]; + features.push({ + typeName: featureTypeName(feature), + url: "/browse/" + featureType(feature) + "/" + feature.osm_id, + name: featureName(feature), + id: feature.id + }); + } + + browseObjectList = $(JST["templates/browse/feature_list"]({ + features: features, + url: this.protocol.url + }))[0]; + + loadObjectList(); + } + } + + function viewFeatureLink() { + var feature = browseDataLayer.getFeatureById($(this).data("feature-id")); + var layer = feature.layer; + + for (var i = 0; i < layer.selectedFeatures.length; i++) { + var f = layer.selectedFeatures[i]; + layer.drawFeature(f, layer.styleMap.createSymbolizer(f, "default")); + } + + onFeatureSelect(feature); + + if (browseMode != "auto") { + map.setCenter(feature.geometry.getBounds().getCenterLonLat()); + } + + return false; + } + + function loadObjectList() { + $("#browse_content").html(browseObjectList); + $("#browse_content").find("a[data-feature-id]").click(viewFeatureLink); + + return false; + } + + function onFeatureSelect(feature) { + // Unselect previously selected feature + if (browseActiveFeature) { + browseActiveFeature.layer.drawFeature( + browseActiveFeature, + browseActiveFeature.layer.styleMap.createSymbolizer(browseActiveFeature, "default") + ); + } + + // Redraw in selected style + feature.layer.drawFeature( + feature, feature.layer.styleMap.createSymbolizer(feature, "select") + ); + + // If the current object is the list, don't innerHTML="", since that could clear it. + if ($("#browse_content").firstChild == browseObjectList) { + $("#browse_content").removeChild(browseObjectList); + } else { + $("#browse_content").empty(); + } + + $("#browse_content").html(JST["templates/browse/feature"]({ + name: featureNameSelect(feature), + url: "/browse/" + featureType(feature) + "/" + feature.osm_id, + attributes: feature.attributes + })); + + $("#browse_content").find("a.browse_show_list").click(loadObjectList); + $("#browse_content").find("a.browse_show_history").click(loadHistory); + + // Stash the currently drawn feature + browseActiveFeature = feature; + } + + function loadHistory() { + $(this).attr("href", "").text(I18n.t('browse.start_rjs.wait')); + + var feature = browseActiveFeature; + + $.ajax({ + url: "/api/" + OSM.API_VERSION + "/" + featureType(feature) + "/" + feature.osm_id + "/history", + success: function (xml) { + if (browseActiveFeature != feature || $("#browse_content").firstChild == browseObjectList) { + return; + } + + $(this).remove(); + + var history = []; + var nodes = xml.getElementsByTagName(featureType(feature)); + for (var i = nodes.length - 1; i >= 0; i--) { + history.push({ + user: nodes[i].getAttribute("user") || I18n.t('browse.start_rjs.private_user'), + timestamp: nodes[i].getAttribute("timestamp") + }); + } + + $("#browse_content").append(JST["templates/browse/feature_history"]({ + name: featureNameHistory(feature), + url: "/browse/" + featureType(feature) + "/" + feature.osm_id, + history: history + })); + }.bind(this) + }); + + return false; + } + + function featureType(feature) { + if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { + return "node"; + } else { + return "way"; + } + } + + function featureTypeName(feature) { + if (featureType(feature) == "node") { + return I18n.t('browse.start_rjs.object_list.type.node'); + } else if (featureType(feature) == "way") { + return I18n.t('browse.start_rjs.object_list.type.way'); + } + } + + function featureName(feature) { + var lang = $('html').attr('lang'); + if (feature.attributes['name:' + lang]) { + return feature.attributes['name:' + lang]; + } else if (feature.attributes.name) { + return feature.attributes.name; + } else { + return feature.osm_id; + } + } + + function featureNameSelect(feature) { + var lang = $('html').attr('lang'); + if (feature.attributes['name:' + lang]) { + return feature.attributes['name:' + lang]; + } else if (feature.attributes.name) { + return feature.attributes.name; + } else if (featureType(feature) == "node") { + return I18n.t("browse.start_rjs.object_list.selected.type.node", { id: feature.osm_id }); + } else if (featureType(feature) == "way") { + return I18n.t("browse.start_rjs.object_list.selected.type.way", { id: feature.osm_id }); + } + } + + function featureNameHistory(feature) { + var lang = $('html').attr('lang'); + if (feature.attributes['name:' + lang]) { + return feature.attributes['name:' + lang]; + } else if (feature.attributes.name) { + return feature.attributes.name; + } else if (featureType(feature) == "node") { + return I18n.t("browse.start_rjs.object_list.history.type.node", { id: feature.osm_id }); + } else if (featureType(feature) == "way") { + return I18n.t("browse.start_rjs.object_list.history.type.way", { id: feature.osm_id }); + } + } + + function setStatus(status) { + $("#browse_status").html(status); + $("#browse_status").show(); + } + + function clearStatus() { + $("#browse_status").html(""); + $("#browse_status").hide(); + } + } +}); \ No newline at end of file diff --git a/app/assets/javascripts/index/export.js b/app/assets/javascripts/index/export.js new file mode 100644 index 000000000..8696338ab --- /dev/null +++ b/app/assets/javascripts/index/export.js @@ -0,0 +1,328 @@ +$(document).ready(function () { + $("#exportanchor").click(function (e) { + $.ajax({ url: $(this).data('url'), success: function (sidebarHtml) { + startExport(sidebarHtml); + }}); + e.preventDefault(); + }); + + if (window.location.pathname == "/export") { + $("#exportanchor").click(); + } + + function startExport(sidebarHtml) { + var vectors, + box, + transform, + markerLayer, + markerControl; + + vectors = new OpenLayers.Layer.Vector("Vector Layer", { + displayInLayerSwitcher: false + }); + map.addLayer(vectors); + + box = new OpenLayers.Control.DrawFeature(vectors, OpenLayers.Handler.RegularPolygon, { + handlerOptions: { + sides: 4, + snapAngle: 90, + irregular: true, + persist: true + } + }); + box.handler.callbacks.done = endDrag; + map.addControl(box); + + transform = new OpenLayers.Control.TransformFeature(vectors, { + rotate: false, + irregular: true + }); + transform.events.register("transformcomplete", transform, transformComplete); + map.addControl(transform); + + map.events.register("moveend", map, mapMoved); + map.events.register("changebaselayer", map, htmlUrlChanged); + + $("#sidebar_title").html(I18n.t('export.start_rjs.export')); + $("#sidebar_content").html(sidebarHtml); + + $("#maxlat,#minlon,#maxlon,#minlat").change(boundsChanged); + + $("#drag_box").click(startDrag); + + $("#add_marker").click(startMarker); + + $("#format_osm,#format_mapnik,#format_html").click(formatChanged); + + $("#mapnik_scale").change(mapnikSizeChanged); + + openSidebar(); + + if (map.baseLayer.name == "Mapnik") { + $("#format_mapnik").prop("checked", true); + } + + formatChanged(); + setBounds(map.getExtent()); + + $("body").removeClass("site-index").addClass("site-export"); + + $("#sidebar").one("closed", function () { + $("body").removeClass("site-export").addClass("site-index"); + + clearBox(); + clearMarker(); + map.events.unregister("moveend", map, mapMoved); + map.events.unregister("changebaselayer", map, htmlUrlChanged); + map.removeLayer(vectors); + }); + + function getMercatorBounds() { + var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), + $("#maxlon").val(), $("#maxlat").val()); + + return proj(bounds); + } + + function boundsChanged() { + var bounds = getMercatorBounds(); + + map.events.unregister("moveend", map, mapMoved); + map.zoomToExtent(bounds); + + clearBox(); + drawBox(bounds); + + validateControls(); + mapnikSizeChanged(); + } + + function startDrag() { + $("#drag_box").html(I18n.t('export.start_rjs.drag_a_box')); + + clearBox(); + box.activate(); + }; + + function endDrag(bbox) { + var bounds = bbox.getBounds(); + + map.events.unregister("moveend", map, mapMoved); + setBounds(bounds); + drawBox(bounds); + box.deactivate(); + validateControls(); + + $("#drag_box").html(I18n.t('export.start_rjs.manually_select')); + } + + function transformComplete(event) { + setBounds(event.feature.geometry.bounds); + validateControls(); + } + + function startMarker() { + $("#add_marker").html(I18n.t('export.start_rjs.click_add_marker')); + + if (!markerLayer) { + markerLayer = new OpenLayers.Layer.Vector("",{ + displayInLayerSwitcher: false, + style: { + externalGraphic: OpenLayers.Util.getImageLocation("marker.png"), + graphicXOffset: -10.5, + graphicYOffset: -25, + graphicWidth: 21, + graphicHeight: 25 + } + }); + map.addLayer(markerLayer); + + markerControl = new OpenLayers.Control.DrawFeature(markerLayer, OpenLayers.Handler.Point); + map.addControl(markerControl); + + markerLayer.events.on({ "featureadded": endMarker }); + } + + markerLayer.destroyFeatures(); + markerControl.activate(); + + return false; + } + + function endMarker(event) { + markerControl.deactivate(); + + $("#add_marker").html(I18n.t('export.start_rjs.change_marker')); + $("#marker_inputs").show(); + + var geom = unproj(event.feature.geometry); + + $("#marker_lon").val(geom.x.toFixed(5)); + $("#marker_lat").val(geom.y.toFixed(5)); + + htmlUrlChanged(); + } + + function clearMarker() { + $("#marker_lon,#marker_lat").val(""); + $("#marker_inputs").hide(); + $("#add_marker").html(I18n.t('export.start_rjs.add_marker')); + + if (markerLayer) { + markerControl.destroy(); + markerLayer.destroy(); + markerLayer = null; + markerControl = null; + } + } + + function mapMoved() { + setBounds(map.getExtent()); + validateControls(); + } + + function setBounds(bounds) { + var toPrecision = zoomPrecision(map.getZoom()); + + bounds = unproj(bounds); + + $("#minlon").val(toPrecision(bounds.left)); + $("#minlat").val(toPrecision(bounds.bottom)); + $("#maxlon").val(toPrecision(bounds.right)); + $("#maxlat").val(toPrecision(bounds.top)); + + mapnikSizeChanged(); + htmlUrlChanged(); + } + + function clearBox() { + transform.deactivate(); + vectors.destroyFeatures(); + } + + function drawBox(bounds) { + var feature = new OpenLayers.Feature.Vector(bounds.toGeometry()); + + vectors.addFeatures(feature); + transform.setFeature(feature); + } + + function validateControls() { + var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val()); + + if (bounds.getWidth() * bounds.getHeight() > OSM.MAX_REQUEST_AREA) { + $("#export_osm_too_large").show(); + } else { + $("#export_osm_too_large").hide(); + } + + var max_scale = maxMapnikScale(); + var disabled = true; + + if ($("#format_osm").prop("checked")) { + disabled = bounds.getWidth() * bounds.getHeight() > OSM.MAX_REQUEST_AREA; + } else if ($("#format_mapnik").prop("checked")) { + disabled = $("#mapnik_scale").val() < max_scale; + } + + $("#export_commit").prop("disabled", disabled); + $("#mapnik_max_scale").html(roundScale(max_scale)); + } + + function htmlUrlChanged() { + var bounds = new OpenLayers.Bounds($("#minlon").val(), $("#minlat").val(), $("#maxlon").val(), $("#maxlat").val()); + var layerName = map.baseLayer.keyid; + var url = "http://" + OSM.SERVER_URL + "/export/embed.html?bbox=" + bounds.toBBOX() + "&layer=" + layerName; + var markerUrl = ""; + + if ($("#marker_lat").val() && $("#marker_lon").val()) { + markerUrl = "&mlat=" + $("#marker_lat").val() + "&mlon=" + $("#marker_lon").val(); + url += "&marker=" + $("#marker_lat").val() + "," + $("#marker_lon").val(); + } + + var html = ''; + + // Create "larger map" link + var center = bounds.getCenterLonLat(); + + var zoom = map.getZoomForExtent(proj(bounds)); + + var layers = getMapLayers(); + + var text = I18n.t('export.start_rjs.view_larger_map'); + var escaped = []; + + for (var i = 0; i < text.length; ++i) { + var c = text.charCodeAt(i); + escaped.push(c < 127 ? text.charAt(i) : "&#" + c + ";"); + } + + html += '
'+escaped.join("")+''; + + $("#export_html_text").val(html); + + if ($("#format_html").prop("checked")) { + $("#export_html_text").prop("selected", true); + } + } + + function formatChanged() { + $("#export_commit").show(); + + if ($("#format_osm").prop("checked")) { + $("#export_osm").show(); + } else { + $("#export_osm").hide(); + } + + if ($("#format_mapnik").prop("checked")) { + $("#mapnik_scale").val(roundScale(map.getScale())); + $("#export_mapnik").show(); + + mapnikSizeChanged(); + } else { + $("#export_mapnik").hide(); + } + + if ($("#format_html").prop("checked")) { + $("#export_html").show(); + $("#export_commit").hide(); + $("#export_html_text").prop("selected", true); + } else { + $("#export_html").hide(); + + clearMarker(); + } + + validateControls(); + } + + function maxMapnikScale() { + var bounds = getMercatorBounds(); + + return Math.floor(Math.sqrt(bounds.getWidth() * bounds.getHeight() / 0.3136)); + } + + function mapnikImageSize(scale) { + var bounds = getMercatorBounds(); + + return new OpenLayers.Size(Math.round(bounds.getWidth() / scale / 0.00028), + Math.round(bounds.getHeight() / scale / 0.00028)); + } + + function roundScale(scale) { + var precision = 5 * Math.pow(10, Math.floor(Math.LOG10E * Math.log(scale)) - 2); + + return precision * Math.ceil(scale / precision); + } + + function mapnikSizeChanged() { + var size = mapnikImageSize($("#mapnik_scale").val()); + + $("#mapnik_image_width").html(size.w); + $("#mapnik_image_height").html(size.h); + + validateControls(); + } + } +}); diff --git a/app/assets/javascripts/key.js b/app/assets/javascripts/index/key.js similarity index 100% rename from app/assets/javascripts/key.js rename to app/assets/javascripts/index/key.js diff --git a/app/assets/javascripts/map.js.erb b/app/assets/javascripts/map.js.erb index 8aa9868b3..c06c9c8ea 100644 --- a/app/assets/javascripts/map.js.erb +++ b/app/assets/javascripts/map.js.erb @@ -106,13 +106,13 @@ function addMarkerToMap(position, icon, description) { return marker; } -function addObjectToMap(url, zoom, callback) { +function addObjectToMap(object, zoom, callback) { var layer = new OpenLayers.Layer.Vector("Objects", { strategies: [ new OpenLayers.Strategy.Fixed() ], protocol: new OpenLayers.Protocol.HTTP({ - url: url, + url: OSM.apiUrl(object), format: new OpenLayers.Format.OSM() }), style: { @@ -196,7 +196,6 @@ function openMapPopup(marker, description) { function closeMapPopup() { if (popup) { map.removePopup(popup); - delete popup; } } @@ -204,10 +203,6 @@ function removeMarkerFromMap(marker){ markers.removeMarker(marker); } -function removeBoxFromMap(box){ - vectors.removeFeature(box); -} - function proj(x) { return x.clone().transform(epsg4326, map.getProjectionObject()); } @@ -224,7 +219,7 @@ function setMapCenter(center, zoom) { } function getEventPosition(event) { - return map.getLonLatFromViewPortPx(event.xy).clone().transform(map.getProjectionObject(), epsg4326); + return unproj(map.getLonLatFromViewPortPx(event.xy)); } function getMapLayers() { diff --git a/app/assets/javascripts/notes.js.erb b/app/assets/javascripts/notes.js.erb index c55c11ec9..63047b3c9 100644 --- a/app/assets/javascripts/notes.js.erb +++ b/app/assets/javascripts/notes.js.erb @@ -1,213 +1,227 @@ -function addNoteLayer(map, notesUrl, newNoteControls, newNoteForm, minZoom) { - var newNotes; - - var saveNewNotes = function (o) { - var layer = o.object; - newNotes = layer.getFeaturesByAttribute("status", "new") - layer.removeFeatures(newNotes, { silent: true }); - }; - - var restoreNewNotes = function (o) { - var layer = o.object; - layer.addFeatures(newNotes); - newNotes = undefined; - }; - - var describeNote = function (n) { - var description = "

Note " + n.id + "

"; - - n.comments.forEach(function (c) { - description += "

" + c.action + " by "; - description += c.user + " at " + c.date + "
" + c.text + "

"; - }); +$(document).ready(function () { + var params = OSM.mapParams(); - return description; - } +// map.noteLayer = addNoteLayer(map, $("#show_notes").attr("href"), $("#createnoteanchor"), $("#new-note"), 11); - var noteSelected = function (o) { - var feature = o.feature; - var location = feature.geometry.getBounds().getCenterLonLat(); - var content; - var close; - - if (feature.attributes.status === "new") { - var form = newNoteForm.clone(); - form.removeClass("hidden"); - content = form.html(); - close = false; - } else { - content = describeNote(feature.attributes); - close = true; - }; + $("#show_notes").click(function () { + map.noteLayer.setVisibility(true); + }); - feature.popup = new OpenLayers.Popup.FramedCloud( - feature.attributes.id, location, null, content, null, close, - function (e) { map.noteSelector.unselect(feature) } - ); + if (params.notes) { + map.noteLayer.setVisibility(true); + } - map.addPopup(feature.popup); - // feature.popup.show(); + function addNoteLayer(map, notesUrl, newNoteControls, newNoteForm, minZoom) { + var newNotes; - $(feature.popup.contentDiv).find("textarea").autoGrow(); + var saveNewNotes = function (o) { + var layer = o.object; + newNotes = layer.getFeaturesByAttribute("status", "new") + layer.removeFeatures(newNotes, { silent: true }); + }; + + var restoreNewNotes = function (o) { + var layer = o.object; + layer.addFeatures(newNotes); + newNotes = undefined; + }; - $(feature.popup.contentDiv).find("input#note-submit").click(function (e) { - var location = unproj(feature.geometry.getBounds().getCenterLonLat()); - var form = $(e.target).parents("form").first(); + var describeNote = function (n) { + var description = "

Note " + n.id + "

"; - $.ajax(form.prop("action"), { - type: form.prop("method"), - data: { - lon: location.lon, - lat: location.lat, - text: form.find("textarea#comment").val() - }, - success: function (data) { - map.noteSelector.unselect(feature); + n.comments.forEach(function (c) { + description += "

" + c.action + " by "; + description += c.user + " at " + c.date + "
" + c.text + "

"; + }); - feature.attributes.status = "open"; - feature.attributes.id = data; + return description; + } - map.noteLayer.drawFeature(feature); + var noteSelected = function (o) { + var feature = o.feature; + var location = feature.geometry.getBounds().getCenterLonLat(); + var content; + var close; + + if (feature.attributes.status === "new") { + var form = newNoteForm.clone(); + form.removeClass("hidden"); + content = form.html(); + close = false; + } else { + content = describeNote(feature.attributes); + close = true; + }; + + feature.popup = new OpenLayers.Popup.FramedCloud( + feature.attributes.id, location, null, content, null, close, + function (e) { map.noteSelector.unselect(feature) } + ); + + map.addPopup(feature.popup); + // feature.popup.show(); + + $(feature.popup.contentDiv).find("textarea").autoGrow(); + + $(feature.popup.contentDiv).find("input#note-submit").click(function (e) { + var location = unproj(feature.geometry.getBounds().getCenterLonLat()); + var form = $(e.target).parents("form").first(); + + $.ajax(form.prop("action"), { + type: form.prop("method"), + data: { + lon: location.lon, + lat: location.lat, + text: form.find("textarea#comment").val() + }, + success: function (data) { + map.noteSelector.unselect(feature); + + feature.attributes.status = "open"; + feature.attributes.id = data; + + map.noteLayer.drawFeature(feature); + + map.noteMover.deactivate(); + } + }); - map.noteMover.deactivate(); - } + e.preventDefault(); }); - e.preventDefault(); - }); + $(feature.popup.contentDiv).find("input#note-cancel").click(function (e) { + feature.attributes.status = "cancelled"; - $(feature.popup.contentDiv).find("input#note-cancel").click(function (e) { - feature.attributes.status = "cancelled"; + map.noteSelector.unselect(feature); + map.noteLayer.removeFeatures(feature); - map.noteSelector.unselect(feature); - map.noteLayer.removeFeatures(feature); + feature.destroy(); - feature.destroy(); + map.noteMover.deactivate(); - map.noteMover.deactivate(); + e.preventDefault(); + }); - e.preventDefault(); - }); + feature.popup.updateSize(); + }; - feature.popup.updateSize(); - }; + var noteUnselected = function (o) { + var feature = o.feature; - var noteUnselected = function (o) { - var feature = o.feature; + map.removePopup(feature.popup); + + delete feature.popup; + }; - map.removePopup(feature.popup); + var allowNoteReports = function () { + if (map.getZoom() > minZoom) { + newNoteControls.show(); + } else { + newNoteControls.hide(); + } + }; - delete feature.popup; - }; + var addNote = function () { + var lonlat = map.getCenter(); + var layer = map.noteLayer; + var geometry = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat); + var feature = new OpenLayers.Feature.Vector(geometry, { + status: "new" + }); - var allowNoteReports = function () { - if (map.getZoom() > minZoom) { - newNoteControls.show(); - } else { - newNoteControls.hide(); - } - }; - - var addNote = function () { - var lonlat = map.getCenter(); - var layer = map.noteLayer; - var geometry = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat); - var feature = new OpenLayers.Feature.Vector(geometry, { - status: "new" - }); + layer.addFeatures(feature); + map.noteSelector.unselectAll(); + map.noteSelector.select(feature); + map.noteMover.activate(); + map.noteLayer.setVisibility(true); + }; - layer.addFeatures(feature); - map.noteSelector.unselectAll(); - map.noteSelector.select(feature); - map.noteMover.activate(); - map.noteLayer.setVisibility(true); - }; - - map.noteLayer = new OpenLayers.Layer.Vector("Notes", { - visibility: false, - displayInLayerSwitcher: false, - projection: new OpenLayers.Projection("EPSG:4326"), - styleMap: new OpenLayers.StyleMap(new OpenLayers.Style({ - graphicWidth: 22, - graphicHeight: 22, - graphicOpacity: 0.7, - graphicXOffset: -11, - graphicYOffset: -11 - }, { - rules: [ - new OpenLayers.Rule({ - filter: new OpenLayers.Filter.Comparison({ - type: OpenLayers.Filter.Comparison.EQUAL_TO, - property: "status", - value: "new" + map.noteLayer = new OpenLayers.Layer.Vector("Notes", { + visibility: false, + displayInLayerSwitcher: false, + projection: new OpenLayers.Projection("EPSG:4326"), + styleMap: new OpenLayers.StyleMap(new OpenLayers.Style({ + graphicWidth: 22, + graphicHeight: 22, + graphicOpacity: 0.7, + graphicXOffset: -11, + graphicYOffset: -11 + }, { + rules: [ + new OpenLayers.Rule({ + filter: new OpenLayers.Filter.Comparison({ + type: OpenLayers.Filter.Comparison.EQUAL_TO, + property: "status", + value: "new" + }), + symbolizer: { + externalGraphic: "<%= image_path 'new_note_marker.png' %>" + } }), - symbolizer: { - externalGraphic: "<%= image_path 'new_note_marker.png' %>" - } - }), - new OpenLayers.Rule({ - filter: new OpenLayers.Filter.Comparison({ - type: OpenLayers.Filter.Comparison.EQUAL_TO, - property: "status", - value: "open" - }), - symbolizer: { - externalGraphic: "<%= image_path 'open_note_marker.png' %>" - } - }), - new OpenLayers.Rule({ - filter: new OpenLayers.Filter.Comparison({ - type: OpenLayers.Filter.Comparison.EQUAL_TO, - property: "status", - value: "closed" + new OpenLayers.Rule({ + filter: new OpenLayers.Filter.Comparison({ + type: OpenLayers.Filter.Comparison.EQUAL_TO, + property: "status", + value: "open" + }), + symbolizer: { + externalGraphic: "<%= image_path 'open_note_marker.png' %>" + } }), - symbolizer: { - externalGraphic: "<%= image_path 'closed_note_marker.png' %>" - } - }) - ] - })), - strategies: [ - new OpenLayers.Strategy.BBOX() - ], - protocol: new OpenLayers.Protocol.HTTP({ - url: notesUrl, - format: new OpenLayers.Format.GeoJSON() - }) - }); + new OpenLayers.Rule({ + filter: new OpenLayers.Filter.Comparison({ + type: OpenLayers.Filter.Comparison.EQUAL_TO, + property: "status", + value: "closed" + }), + symbolizer: { + externalGraphic: "<%= image_path 'closed_note_marker.png' %>" + } + }) + ] + })), + strategies: [ + new OpenLayers.Strategy.BBOX() + ], + protocol: new OpenLayers.Protocol.HTTP({ + url: notesUrl, + format: new OpenLayers.Format.GeoJSON() + }) + }); - map.noteLayer.events.register("beforefeaturesremoved", map, saveNewNotes); - map.noteLayer.events.register("featuresremoved", map, restoreNewNotes); - map.noteLayer.events.register("featureselected", map, noteSelected); - map.noteLayer.events.register("featureunselected", map, noteUnselected); + map.noteLayer.events.register("beforefeaturesremoved", map, saveNewNotes); + map.noteLayer.events.register("featuresremoved", map, restoreNewNotes); + map.noteLayer.events.register("featureselected", map, noteSelected); + map.noteLayer.events.register("featureunselected", map, noteUnselected); - map.addLayer(map.noteLayer); + map.addLayer(map.noteLayer); - map.noteSelector = new OpenLayers.Control.SelectFeature(map.noteLayer, { - autoActivate: true - }); + map.noteSelector = new OpenLayers.Control.SelectFeature(map.noteLayer, { + autoActivate: true + }); - map.addControl(map.noteSelector); - - map.noteMover = new OpenLayers.Control.DragFeature(map.noteLayer, { - onDrag: function (feature, pixel) { - feature.popup.lonlat = feature.geometry.getBounds().getCenterLonLat(); - feature.popup.updatePosition(); - }, - featureCallbacks: { - over: function (feature) { - if (feature.attributes.status === "new") { - map.noteMover.overFeature.apply(map.noteMover, [feature]); + map.addControl(map.noteSelector); + + map.noteMover = new OpenLayers.Control.DragFeature(map.noteLayer, { + onDrag: function (feature, pixel) { + feature.popup.lonlat = feature.geometry.getBounds().getCenterLonLat(); + feature.popup.updatePosition(); + }, + featureCallbacks: { + over: function (feature) { + if (feature.attributes.status === "new") { + map.noteMover.overFeature.apply(map.noteMover, [feature]); + } } } - } - }); + }); - map.addControl(map.noteMover); + map.addControl(map.noteMover); - newNoteControls.click(addNote); + newNoteControls.click(addNote); - map.events.register("zoomend", map, allowNoteReports); + map.events.register("zoomend", map, allowNoteReports); - return map.noteLayer; -} + return map.noteLayer; + } +}); diff --git a/app/assets/javascripts/osm.js.erb b/app/assets/javascripts/osm.js.erb new file mode 100644 index 000000000..33f190412 --- /dev/null +++ b/app/assets/javascripts/osm.js.erb @@ -0,0 +1,121 @@ +OSM = { +<% if defined?(PIWIK_LOCATION) and defined?(PIWIK_SITE) %> + PIWIK_LOCATION: <%= PIWIK_LOCATION.to_json %>, + PIWIK_SITE: <%= PIWIK_SITE.to_json %>, +<% end %> + + MAX_REQUEST_AREA: <%= MAX_REQUEST_AREA.to_json %>, + SERVER_URL: <%= SERVER_URL.to_json %>, + API_VERSION: <%= API_VERSION.to_json %>, + + apiUrl: function (object) { + var url = "/api/" + OSM.API_VERSION + "/" + object.type + "/" + object.id; + + if (object.type != "node") { + url += "/full"; + } else if (object.version) { + url += "/" + object.version; + } + + return url; + }, + + mapParams: function (search) { + var params = {}, mapParams = {}, loc; + + search = (search || window.location.search).replace('?', '').split('&'); + + 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 (params.mlon && params.mlat) { + mapParams.marker = true; + mapParams.mlon = parseFloat(params.mlon); + mapParams.mlat = parseFloat(params.mlat); + } + + if (params.layers) { + mapParams.layers = params.layers; + } + + if (params.node || params.way || params.relation) { + mapParams.object_zoom = true; + + if (params.node) { + mapParams.object = {type: 'node', id: parseInt(params.node)}; + } else if (params.way) { + mapParams.object = {type: 'way', id: parseInt(params.way)}; + } else if (params.relation) { + mapParams.object = {type: 'relation', id: parseInt(params.relation)}; + } + } + + // 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; + } 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; + } 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]; + } 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; + } else { + mapParams.lon = -0.1; + mapParams.lat = 51.5; + mapParams.zoom = parseInt(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; + } + + mapParams.notes = params.notes == "yes"; + + var scale = parseFloat(params.scale); + if (scale > 0) { + mapParams.zoom = Math.log(360.0 / (scale * 512.0)) / Math.log(2.0); + } + + return mapParams; + } +}; diff --git a/app/assets/javascripts/params.js b/app/assets/javascripts/params.js deleted file mode 100644 index 5373625dc..000000000 --- a/app/assets/javascripts/params.js +++ /dev/null @@ -1,100 +0,0 @@ -OSM.mapParams = function (search) { - var params = {}, mapParams = {}, loc; - - search = (search || window.location.search).replace('?', '').split('&'); - - 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 (params.mlon && params.mlat) { - mapParams.marker = true; - mapParams.mlon = parseFloat(params.mlon); - mapParams.mlat = parseFloat(params.mlat); - } - - if (params.layers) { - mapParams.layers = params.layers; - } - - 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); - } - } - - // 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; - } 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; - } 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]; - } 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; - } else { - mapParams.lon = -0.1; - mapParams.lat = 51.5; - mapParams.zoom = parseInt(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; - } - - var scale = parseFloat(params.scale); - if (scale > 0) { - mapParams.zoom = Math.log(360.0 / (scale * 512.0)) / Math.log(2.0); - } - - return mapParams; -}; diff --git a/app/assets/javascripts/templates/browse/feature.jst.ejs b/app/assets/javascripts/templates/browse/feature.jst.ejs new file mode 100644 index 000000000..5a3fe3644 --- /dev/null +++ b/app/assets/javascripts/templates/browse/feature.jst.ejs @@ -0,0 +1,19 @@ +
+ <%- I18n.t('browse.start_rjs.object_list.back') %> +
+ + + + + +
<%- name %> + <%- I18n.t('browse.start_rjs.object_list.details') %> +
+
+ + <%- I18n.t('browse.start_rjs.show_history') %> +
diff --git a/app/assets/javascripts/templates/browse/feature_history.jst.ejs b/app/assets/javascripts/templates/browse/feature_history.jst.ejs new file mode 100644 index 000000000..6f870ac5b --- /dev/null +++ b/app/assets/javascripts/templates/browse/feature_history.jst.ejs @@ -0,0 +1,15 @@ + + + + + +
<%- I18n.t("browse.start_rjs.history_for_feature", {feature: name}) %> + <%- I18n.t('browse.start_rjs.details') %> +
+
+ +
diff --git a/app/assets/javascripts/templates/browse/feature_list.jst.ejs b/app/assets/javascripts/templates/browse/feature_list.jst.ejs new file mode 100644 index 000000000..ada7d0874 --- /dev/null +++ b/app/assets/javascripts/templates/browse/feature_list.jst.ejs @@ -0,0 +1,9 @@ +
+

<%- I18n.t('browse.start_rjs.object_list.heading') %>

+ + <%- I18n.t('browse.start_rjs.object_list.api') %> +
diff --git a/app/assets/javascripts/user.js b/app/assets/javascripts/user.js new file mode 100644 index 000000000..77cb86a8d --- /dev/null +++ b/app/assets/javascripts/user.js @@ -0,0 +1,42 @@ +$(document).ready(function () { + var map = createMap("map"); + + if (OSM.home) { + setMapCenter(new OpenLayers.LonLat(OSM.home.lon, OSM.home.lat), 12); + } else { + setMapCenter(new OpenLayers.LonLat(0, 0), 0); + } + + if ($("#map").hasClass("set_location")) { + var marker; + + if (OSM.home) { + marker = addMarkerToMap(new OpenLayers.LonLat(OSM.home.lon, OSM.home.lat)); + } + + map.events.register("click", map, function (e) { + if ($('#updatehome').is(':checked')) { + var lonlat = getEventPosition(e); + + $('#homerow').removeClass(); + $('#home_lat').val(lonlat.lat); + $('#home_lon').val(lonlat.lon); + + if (marker) { + removeMarkerFromMap(marker); + } + + marker = addMarkerToMap(lonlat); + } + }); + } else { + $("[data-user]").each(function () { + var user = $(this).data('user'); + if (user.lon && user.lat) { + var icon = OpenLayers.Marker.defaultIcon(); + icon.url = OpenLayers.Util.getImageLocation(user.icon); + addMarkerToMap(new OpenLayers.LonLat(user.lon, user.lat), icon, user.description); + } + }); + } +}); diff --git a/app/assets/openlayers/theme/openstreetmap/img/missing-tile.png b/app/assets/openlayers/theme/openstreetmap/img/missing-tile.png index b5ecdf092..e6c54616d 100644 Binary files a/app/assets/openlayers/theme/openstreetmap/img/missing-tile.png and b/app/assets/openlayers/theme/openstreetmap/img/missing-tile.png differ diff --git a/app/assets/stylesheets/common.css.scss b/app/assets/stylesheets/common.css.scss index c897e1184..c2b11162c 100644 --- a/app/assets/stylesheets/common.css.scss +++ b/app/assets/stylesheets/common.css.scss @@ -652,6 +652,12 @@ body.site-export #tabnav a#exportanchor { margin-bottom: 5px; } +/* Rules for text content pages */ + +.wide-table { + width: 100%; +} + /* Rules for the home page */ .site-index #map { @@ -1004,18 +1010,48 @@ p#contributorGuidance { /* Rules for message in/out box page */ -#messages { - border: 1px solid #ccc; +.messages { + width: 100%; + border-collapse: collapse; + border-spacing: 0px; + border-width: 0px; } -.inbox-row-unread .inbox-subject { - font-weight: bold; +.messages tbody tr { + border-top: 1px solid #ccc; +} + +.messages .inbox-row { + background: #eee; +} + +.messages tr td, +.messages tr th { + padding: 0px 5px; } .inbox-row .inbox-mark-read { display: none; } +.info-line { + border-bottom: 1px solid #ccc; + padding: 5px 0px 4px 0px; +} + +.info-line form, +.info-line form div { + display: inline; +} + +.info-line .user_thumbnail_tiny { + vertical-align: middle; +} + +.right { + float: right; +} + .inbox-row-unread .inbox-mark-unread { display: none; } @@ -1113,13 +1149,19 @@ textarea { img.user_image { max-width: 100px; max-height: 100px; - border: 1px solid black; + border: 1px solid #ccc; } img.user_thumbnail { max-width: 50px; max-height: 100px; - border: 1px solid black; + border: 1px solid #ccc; +} + +img.user_thumbnail_tiny { + max-width: 25px; + max-height: 25px; + border: 1px solid #ccc; } /* Rule for "nowrap" class that can be applied to anything to stop wrapping */ diff --git a/app/controllers/browse_controller.rb b/app/controllers/browse_controller.rb index 2c22a9b83..5526aacca 100644 --- a/app/controllers/browse_controller.rb +++ b/app/controllers/browse_controller.rb @@ -30,9 +30,6 @@ class BrowseController < ApplicationController @way = Way.find(params[:id], :include => [:way_tags, {:changeset => :user}, {:nodes => [:node_tags, {:ways => :way_tags}]}, :containing_relation_members]) @next = Way.visible.where("id > ?", @way.id).order("id ASC").first @prev = Way.visible.where("id < ?", @way.id).order("id DESC").first - - # Used for edit link, takes approx middle node of way - @midnode = @way.nodes[@way.nodes.length/2] rescue ActiveRecord::RecordNotFound render :action => "not_found", :status => :not_found end diff --git a/app/controllers/changeset_controller.rb b/app/controllers/changeset_controller.rb index 947732fb1..9a4271621 100644 --- a/app/controllers/changeset_controller.rb +++ b/app/controllers/changeset_controller.rb @@ -328,8 +328,6 @@ class ChangesetController < ApplicationController @page = (params[:page] || 1).to_i @page_size = 20 - @bbox = bbox - @edits = changesets.order("changesets.created_at DESC").offset((@page - 1) * @page_size).limit(@page_size).preload(:user, :changeset_tags) render :action => :list diff --git a/app/controllers/site_controller.rb b/app/controllers/site_controller.rb index 015da9e22..606143f4f 100644 --- a/app/controllers/site_controller.rb +++ b/app/controllers/site_controller.rb @@ -39,6 +39,21 @@ class SiteController < ApplicationController if editor == "remote" render :action => :index + return + end + + if params[:node] + bbox = Node.find(params[:node]).bbox.to_unscaled + @lat = bbox.centre_lat + @lon = bbox.centre_lon + elsif params[:way] + bbox = Way.find(params[:way]).bbox.to_unscaled + @lat = bbox.centre_lat + @lon = bbox.centre_lon + elsif params[:gpx] + trace = Trace.visible_to(@user).find(params[:gpx]) + @lat = trace.latitude + @lon = trace.longitude end end diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index bfb0ef83b..9e1585243 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -1,20 +1,22 @@ class UserController < ApplicationController layout :choose_layout - skip_before_filter :verify_authenticity_token, :only => [:api_details, :api_gpx_files] + skip_before_filter :verify_authenticity_token, :only => [:api_read, :api_details, :api_gpx_files] before_filter :disable_terms_redirect, :only => [:terms, :save, :logout, :api_details] before_filter :authorize, :only => [:api_details, :api_gpx_files] - before_filter :authorize_web, :except => [:api_details, :api_gpx_files] - before_filter :set_locale, :except => [:api_details, :api_gpx_files] + before_filter :authorize_web, :except => [:api_read, :api_details, :api_gpx_files] + before_filter :set_locale, :except => [:api_read, :api_details, :api_gpx_files] before_filter :require_user, :only => [:account, :go_public, :make_friend, :remove_friend] - before_filter :check_database_readable, :except => [:login, :api_details, :api_gpx_files] + before_filter :check_database_readable, :except => [:login, :api_read, :api_details, :api_gpx_files] before_filter :check_database_writable, :only => [:new, :account, :confirm, :confirm_email, :lost_password, :reset_password, :go_public, :make_friend, :remove_friend] - before_filter :check_api_readable, :only => [:api_details, :api_gpx_files] + before_filter :check_api_readable, :only => [:api_read, :api_details, :api_gpx_files] before_filter :require_allow_read_prefs, :only => [:api_details] before_filter :require_allow_read_gpx, :only => [:api_gpx_files] before_filter :require_cookies, :only => [:login, :confirm] before_filter :require_administrator, :only => [:set_status, :delete, :list] - before_filter :lookup_this_user, :only => [:set_status, :delete] + around_filter :api_call_handle_error, :only => [:api_read, :api_details, :api_gpx_files] + before_filter :lookup_user_by_id, :only => [:api_read] + before_filter :lookup_user_by_name, :only => [:set_status, :delete] cache_sweeper :user_sweeper, :only => [:account, :set_status, :delete] @@ -373,6 +375,15 @@ class UserController < ApplicationController end end + def api_read + render :nothing => true, :status => :gone unless @this_user.visible? + end + + def api_details + @this_user = @user + render :action => :api_read + end + def api_gpx_files doc = OSM::API.new.get_xml_doc @user.traces.each do |trace| @@ -714,7 +725,13 @@ private ## # ensure that there is a "this_user" instance variable - def lookup_this_user + def lookup_user_by_id + @this_user = User.find(params[:id]) + end + + ## + # ensure that there is a "this_user" instance variable + def lookup_user_by_name @this_user = User.find_by_display_name(params[:display_name]) rescue ActiveRecord::RecordNotFound redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name] unless @this_user diff --git a/app/helpers/browse_helper.rb b/app/helpers/browse_helper.rb index ffc638cdf..c4e4d425a 100644 --- a/app/helpers/browse_helper.rb +++ b/app/helpers/browse_helper.rb @@ -14,7 +14,7 @@ module BrowseHelper name = t 'printable_name.with_version', :id => name, :version => object.version.to_s end - # don't look at object tags if redacted, so as to avoid giving + # don't look at object tags if redacted, so as to avoid giving # away redacted version tag information. unless object.redacted? if object.tags.include? "name:#{I18n.locale}" @@ -63,7 +63,7 @@ module BrowseHelper private - ICON_TAGS = [ + ICON_TAGS = [ "aeroway", "amenity", "barrier", "building", "highway", "historic", "landuse", "leisure", "man_made", "natural", "railway", "shop", "tourism", "waterway" ] @@ -97,10 +97,10 @@ private if key == "wikipedia" # This regex should match Wikipedia language codes, everything # from de to zh-classical - if value =~ /^([a-z-]{2,12}):(.+)$/ + if value =~ /^([a-z-]{2,12}):(.+)$/i # Value is : so split it up + # Note that value is always left as-is, see: https://trac.openstreetmap.org/ticket/4315 lang = $1 - value = $2 else # Value is <title> so default to English Wikipedia lang = 'en' diff --git a/app/helpers/user_helper.rb b/app/helpers/user_helper.rb index 6a239df5d..70125e804 100644 --- a/app/helpers/user_helper.rb +++ b/app/helpers/user_helper.rb @@ -11,6 +11,12 @@ module UserHelper image_tag user.image.url(:small), options end + def user_thumbnail_tiny(user, options = {}) + options[:class] ||= "user_thumbnail_tiny" + + image_tag user.image.url(:small), options + end + def openid_logo image_tag "openid_small.png", :alt => t('user.login.openid_logo_alt'), :class => "openid_logo" end diff --git a/app/models/diary_entry.rb b/app/models/diary_entry.rb index 64a412d28..99a56b2ce 100644 --- a/app/models/diary_entry.rb +++ b/app/models/diary_entry.rb @@ -1,7 +1,7 @@ class DiaryEntry < ActiveRecord::Base - belongs_to :user + belongs_to :user, :counter_cache => true belongs_to :language, :foreign_key => 'language_code' - + has_many :comments, :class_name => "DiaryComment", :include => :user, :order => "diary_comments.id" diff --git a/app/models/relation.rb b/app/models/relation.rb index e5ea85d6d..ce19f7b98 100644 --- a/app/models/relation.rb +++ b/app/models/relation.rb @@ -77,6 +77,12 @@ class Relation < ActiveRecord::Base relation.add_tag_keyval(tag['k'], tag['v']) end + # need to initialise the relation members array explicitly, as if this + # isn't done for a new relation then @members attribute will be nil, + # and the members will be loaded from the database instead of being + # empty, as intended. + relation.members = Array.new + pt.find('member').each do |member| #member_type = logger.debug "each member" diff --git a/app/views/browse/_map.html.erb b/app/views/browse/_map.html.erb index 44823218b..8c28644b1 100644 --- a/app/views/browse/_map.html.erb +++ b/app/views/browse/_map.html.erb @@ -2,23 +2,73 @@ </iframe> <div id="browse_map"> - <% if map.instance_of? Changeset or (map.instance_of? Node and map.version > 1) or map.visible? %> - <div id="small_map"> - </div> + <% if map.instance_of? Changeset or (map.instance_of? Node and map.version > 1) or map.visible %> + + <% content_for :head do %> + <%= javascript_include_tag "browse" %> + <% end %> + + <% + if map.instance_of? Changeset + bbox = map.bbox.to_unscaled + data = { + :type => "changeset", + :id => map.id, + :minlon => bbox.min_lon, + :minlat => bbox.min_lat, + :maxlon => bbox.max_lon, + :maxlat => bbox.max_lat + } + elsif map.instance_of? Note + data = { + :type => "note", + :lon => map.lon, + :lon => map.lat + } + else + data = { + :type => map.class.name.downcase, + :id => map.id, + :version => map.version, + :visible => map.visible + } + end + %> + <%= content_tag "div", "", :id => "small_map", :data => data %> <span id="loading"><%= t 'browse.map.loading' %></span> + <% if map.instance_of? Note -%> - <%= link_to(t("browse.map.larger.area"), { :controller => :site, :action => :index, :notes => "yes" }, { :id => "area_larger_map", :class => "geolink bbox" }) %> + <%= link_to t("browse.map.larger.area"), + root_path(:note => "yes"), + :id => "area_larger_map", + :class => "geolink bbox" %> <% else -%> - <%= link_to(t("browse.map.larger.area"), { :controller => :site, :action => :index, :box => "yes" }, { :id => "area_larger_map", :class => "geolink bbox" }) %> + <%= link_to t("browse.map.larger.area"), + root_path(:box => "yes"), + :id => "area_larger_map", + :class => "geolink bbox" %> <% end -%> <br /> - <%= link_to(h(t("browse.map.edit.area")) + content_tag(:span, "▾", :class => "menuicon"), { :controller => :site, :action => :edit }, { :id => "area_edit", :class => "geolink bbox" }) %> + <%= link_to h(t("browse.map.edit.area")) + content_tag(:span, "▾", :class => "menuicon"), + edit_path, + :id => "area_edit", + :data => { :editor => preferred_editor }, + :class => "geolink bbox" %> + <% unless map.instance_of? Changeset or map.instance_of? Note %> <br /> - <%= link_to(t("browse.map.larger." + map.class.to_s.downcase), { :controller => :site, :action => :index }, { :id => "object_larger_map", :class => "geolink object" }) %> + <%= link_to t("browse.map.larger." + map.class.to_s.downcase), + root_path, + :id => "object_larger_map", + :class => "geolink object" %> <br /> - <%= link_to(h(t("browse.map.edit." + map.class.to_s.downcase)) + content_tag(:span, "▾", :class => "menuicon"), { :controller => :site, :action => :edit }, { :id => "object_edit", :class => "geolink object" }) %> + <%= link_to h(t("browse.map.edit." + map.class.to_s.downcase)) + content_tag(:span, "▾", :class => "menuicon"), + edit_path, + :id => "object_edit", + :data => { :editor => preferred_editor }, + :class => "geolink object" %> <% end %> + <% else %> <%= t 'browse.map.deleted' %> <% end %> @@ -26,157 +76,22 @@ <div id="area_edit_menu" class="menu"> <ul> - <% Editors::ALL_EDITORS.each do |editor| %> - <li><%= link_to t('layouts.edit_with', :editor => t("editor.#{editor}.description")), { :controller => :site, :action => :edit, :editor => editor }, { :id => "#{editor}_area_edit", :class => "geolink bbox" } %></li> + <% Editors::RECOMMENDED_EDITORS.each do |editor| %> + <li><%= link_to t('layouts.edit_with', :editor => t("editor.#{editor}.description")), + edit_path(:editor => editor), + :data => {:editor => editor}, + :class => "geolink bbox" %></li> <% end %> </ul> </div> <div id="object_edit_menu" class="menu"> <ul> - <% Editors::ALL_EDITORS.each do |editor| %> - <li><%= link_to t('layouts.edit_with', :editor => t("editor.#{editor}.description")), { :controller => :site, :action => :edit, :editor => editor }, { :id => "#{editor}_object_edit", :class => "geolink object" } %></li> + <% Editors::RECOMMENDED_EDITORS.each do |editor| %> + <li><%= link_to t('layouts.edit_with', :editor => t("editor.#{editor}.description")), + edit_path(:editor => editor), + :data => {:editor => editor}, + :class => "geolink object" %></li> <% end %> </ul> </div> - -<% if map.instance_of? Changeset or (map.instance_of? Node and map.version > 1) or map.visible? %> - <script type="text/javascript"> - function remoteEditHandler(event, bbox, select) { - var left = bbox.left - 0.0001; - var top = bbox.top + 0.0001; - var right = bbox.right + 0.0001; - var bottom = bbox.bottom - 0.0001; - var loaded = false; - - $("#linkloader").load(function () { loaded = true; }); - - if (select) { - $("#linkloader").attr("src", "http://127.0.0.1:8111/load_and_zoom?left=" + left + "&top=" + top + "&right=" + right + "&bottom=" + bottom + "&select=" + select); - } else { - $("#linkloader").attr("src", "http://127.0.0.1:8111/load_and_zoom?left=" + left + "&top=" + top + "&right=" + right + "&bottom=" + bottom); - } - - setTimeout(function () { - if (!loaded) alert("<%=j t('site.index.remote_failed') %>"); - }, 1000); - - return false; - } - - function init() { - var map = createMap("small_map", { - controls: [ new OpenLayers.Control.Navigation() ] - }); - - <% if map.instance_of? Changeset -%> - <% bbox = map.bbox.to_unscaled %> - var minlon = <%= bbox.min_lon %>; - var minlat = <%= bbox.min_lat %>; - var maxlon = <%= bbox.max_lon %>; - var maxlat = <%= bbox.max_lat %>; - var bbox = new OpenLayers.Bounds(minlon, minlat, maxlon, maxlat); - var centre = bbox.getCenterLonLat(); - - map.zoomToExtent(proj(bbox)); - addBoxToMap(bbox); - - $("#loading").hide(); - $("#browse_map .geolink").show(); - - $("#remote_area_edit").click(function (event) { - return remoteEditHandler(event, bbox); - }); - - <% if preferred_editor == "remote" -%> - $("#area_edit").click(function (event) { - return remoteEditHandler(event, bbox); - }); - <% end -%> - - updatelinks(centre.lon, centre.lat, 16, null, minlon, minlat, maxlon, maxlat) - <% elsif map.instance_of? Note %> - var centre = new OpenLayers.LonLat(<%= map.lon %>, <%= map.lat %>); - - setMapCenter(centre, 16); - addMarkerToMap(centre); - - var bbox = getMapExtent(); - - $("#loading").hide(); - $("#browse_map .geolink").show(); - - $("#remote_area_edit").click(function (event) { - return remoteEditHandler(event, bbox); - }); - - <% if preferred_editor == "remote" -%> - $("#area_edit").click(function (event) { - return remoteEditHandler(event, bbox); - }); - <% end -%> - - updatelinks(centre.lon, centre.lat, 16, null, bbox.left, bbox.bottom, bbox.right, bbox.top) - <% else %> - var obj_type = "<%= map.class.name.downcase %>"; - var obj_id = <%= map.id %>; - var obj_version = <%= map.version %>; - var obj_visible = <%= map.visible %>; - var url = "/api/<%= API_VERSION %>/<%= map.class.name.downcase %>/<%= map.id %>"; - - if (obj_type != "node") { - url += "/full"; - } else if (!obj_visible) { - var previous_version = obj_version - 1; - url += "/" + previous_version; - } - - $("#object_larger_map").hide(); - $("#object_edit").hide(); - - addObjectToMap(url, true, function(extent) { - $("#loading").hide(); - $("#browse_map .geolink").show(); - - if (extent) { - extent.transform(map.getProjectionObject(), map.displayProjection); - - var centre = extent.getCenterLonLat(); - - $("#remote_area_edit").click(function (event) { - return remoteEditHandler(event, extent); - }); - - <% if preferred_editor == "remote" -%> - $("#area_edit").click(function (event) { - return remoteEditHandler(event, extent); - }); - <% end -%> - - $("#remote_object_edit").click(function (event) { - return remoteEditHandler(event, extent, "<%= map.class.to_s.downcase + map.id.to_s %>"); - }); - - <% if preferred_editor == "remote" -%> - $("#object_edit").click(function (event) { - return remoteEditHandler(event, extent, "<%= map.class.to_s.downcase + map.id.to_s %>"); - }); - <% end -%> - - $("#object_larger_map").show(); - $("#object_edit").show(); - - updatelinks(centre.lon, centre.lat, 16, null, extent.left, extent.bottom, extent.right, extent.top, "<%= map.class.to_s.downcase %>", <%= map.id %>); - } else { - $("#small_map").hide(); - } - }); - <% end -%> - - createMenu("area_edit", "area_edit_menu", "right"); - createMenu("object_edit", "object_edit_menu", "right"); - } - - window.onload = init; - </script> -<% end %> diff --git a/app/views/browse/way.html.erb b/app/views/browse/way.html.erb index 167ac6959..aa7b5d0b7 100644 --- a/app/views/browse/way.html.erb +++ b/app/views/browse/way.html.erb @@ -12,6 +12,4 @@ <hr /> <%= link_to(t('browse.way.download_xml'), :controller => "way", :action => "read") %> | <%= link_to(t('browse.way.view_history'), :action => "way_history") %> -<% unless @midnode.nil? -%> -| <%= link_to(t('browse.way.edit'), :controller => "site", :action => "edit", :way => @way.id, :lat => @midnode.lat, :lon => @midnode.lon, :zoom => 16) %> -<% end -%> +| <%= link_to(t('browse.way.edit'), :controller => "site", :action => "edit", :way => @way.id) %> diff --git a/app/views/changeset/_changeset.html.erb b/app/views/changeset/_changeset.html.erb index 88447dde6..ba963ea8e 100644 --- a/app/views/changeset/_changeset.html.erb +++ b/app/views/changeset/_changeset.html.erb @@ -1,6 +1,18 @@ -<% cl = cycle('table0', 'table1') %> +<% + changeset_data = {:id => changeset.id} -<tr class="<%= cl %>" id="tr-changeset-<%= changeset.id%>"> + if changeset.has_valid_bbox? + bbox = changeset.bbox.to_unscaled + changeset_data[:bbox] = { + :minlon => bbox.min_lon, + :minlat => bbox.min_lat, + :maxlon => bbox.max_lon, + :maxlat => bbox.max_lat + } + end +%> + +<%= content_tag "tr", :class => cycle('table0', 'table1'), :id => "tr-changeset-#{changeset.id}", :data => {:changeset => changeset_data} do %> <td> <%= id_link = link_to(changeset.id, @@ -35,14 +47,4 @@ <%= t'changeset.changeset.no_comment' %> <% end %> </td> -</tr> - -<script type="text/javascript"> -$("#tr-changeset-<%= changeset.id%>").mouseover(function() { - highlightChangeset("<%= changeset.id %>"); -}); - -$("#tr-changeset-<%= changeset.id%>").mouseout(function() { - unHighlightChangeset("<%= changeset.id %>"); -}); -</script> +<% end %> diff --git a/app/views/changeset/_map.html.erb b/app/views/changeset/_map.html.erb index a586811f7..9730059ee 100644 --- a/app/views/changeset/_map.html.erb +++ b/app/views/changeset/_map.html.erb @@ -1,83 +1,2 @@ <div id="changeset_list_map"> </div> - -<script type="text/javascript"> - var highlight; - - function highlightChangeset(id) { - var feature = vectors.getFeatureByFid(id); - var bounds = feature.geometry.getBounds(); - - if (bounds.containsBounds(map.getExtent())) { - bounds = map.getExtent().scale(1.1); - } - - if (highlight) vectors.removeFeatures(highlight); - - highlight = new OpenLayers.Feature.Vector(bounds.toGeometry(), {}, { - strokeWidth: 2, - strokeColor: "#ee9900", - fillColor: "#ffff55", - fillOpacity: 0.5 - }); - - vectors.addFeatures(highlight); - - $("#tr-changeset-" + id).addClass("selected"); - } - - function unHighlightChangeset(id) { - vectors.removeFeatures(highlight); - - $("#tr-changeset-" + id).removeClass("selected"); - } - - $(document).ready(function () { - var map = createMap("changeset_list_map", { - controls: [ - new OpenLayers.Control.Navigation(), - new OpenLayers.Control.Zoom(), - new OpenLayers.Control.SimplePanZoom() - ] - }); - - var bounds = new OpenLayers.Bounds(); - - <% @edits.each do |edit| %> - <% if edit.has_valid_bbox? %> - <% bbox = edit.bbox.to_unscaled %> - var minlon = <%= bbox.min_lon %>; - var minlat = <%= bbox.min_lat %>; - var maxlon = <%= bbox.max_lon %>; - var maxlat = <%= bbox.max_lat %>; - var bbox = new OpenLayers.Bounds(minlon, minlat, maxlon, maxlat); - - bounds.extend(bbox); - - addBoxToMap(bbox, "<%= edit.id %>", true); - <% end %> - <% end %> - - vectors.events.on({ - "featureselected": function(feature) { - highlightChangeset(feature.feature.fid); - }, - "featureunselected": function(feature) { - unHighlightChangeset(feature.feature.fid); - } - }); - - var selectControl = new OpenLayers.Control.SelectFeature(vectors, { - multiple: false, - hover: true - }); - map.addControl(selectControl); - selectControl.activate(); - - <% if ! @bbox.nil? %> - map.zoomToExtent(proj(new OpenLayers.Bounds(<%= @bbox %>))); - <% else %> - map.zoomToExtent(proj(bounds)); - <% end %> - }); -</script> diff --git a/app/views/changeset/list.html.erb b/app/views/changeset/list.html.erb index f715e237b..abeea654a 100644 --- a/app/views/changeset/list.html.erb +++ b/app/views/changeset/list.html.erb @@ -1,3 +1,7 @@ +<% content_for :head do -%> + <%= javascript_include_tag "changeset" %> +<% end -%> + <h1><%= @heading %></h1> <p><%= raw(@description) %></p> diff --git a/app/views/diary_entry/edit.html.erb b/app/views/diary_entry/edit.html.erb index 0952c901b..0cdd3b098 100644 --- a/app/views/diary_entry/edit.html.erb +++ b/app/views/diary_entry/edit.html.erb @@ -1,3 +1,7 @@ +<% content_for :head do %> + <%= javascript_include_tag "diary_entry" %> +<% end %> + <h1><%= @title %></h1> <%= error_messages_for 'diary_entry' %> @@ -19,9 +23,9 @@ <tr valign="top"> <td class="fieldName"><%= t 'diary_entry.edit.location' -%></td> <td> - <div id="map"></div> + <%= content_tag "div", "", :id => "map", :data => {:lat => @lat, :lon => @lon, :zoom => @zoom} %> <span class="location"><%= t 'diary_entry.edit.latitude' -%> <%= f.text_field :latitude, :size => 20, :id => "latitude" %> <%= t 'diary_entry.edit.longitude' -%> <%= f.text_field :longitude, :size => 20, :id => "longitude" %></span> - <a href="javascript:openMap()" id="usemap"><%= t 'diary_entry.edit.use_map_link' -%></a> + <a href="#" id="usemap"><%= t 'diary_entry.edit.use_map_link' -%></a> <br/><br/> </td> </tr> @@ -34,42 +38,3 @@ </tr> </table> <% end %> - -<script type="text/javascript"> - <!-- - var marker; - - function setLocation( e ) { - closeMapPopup(); - - var lonlat = getEventPosition(e); - - $("#latitude").val(lonlat.lat); - $("#longitude").val(lonlat.lon); - - if (marker) { - removeMarkerFromMap(marker); - } - - marker = addMarkerToMap(lonlat, null, "<%= t 'diary_entry.edit.marker_text' -%>"); - } - - function openMap() { - $("#map").show(); - $("#usemap").hide(); - - var centre = new OpenLayers.LonLat(<%= @lon %>, <%= @lat %>); - var zoom = <%= @zoom %>; - - var map = createMap("map"); - - setMapCenter(centre, zoom); - - <% if @diary_entry.latitude and @diary_entry.longitude %> - marker = addMarkerToMap(centre, null, "<%= t 'diary_entry.edit.marker_text' -%>"); - <% end %> - - map.events.register("click", map, setLocation); - } -// --> -</script> diff --git a/app/views/layouts/_head.html.erb b/app/views/layouts/_head.html.erb index 91a862f0a..c85594189 100644 --- a/app/views/layouts/_head.html.erb +++ b/app/views/layouts/_head.html.erb @@ -29,6 +29,8 @@ <% if session[:location] %> OSM.location = <%= session[:location].to_json.html_safe %>; <% end %> + + OSM.preferred_editor = <%= preferred_editor.to_json.html_safe %>; </script> <title><%= t 'layouts.project_name.title' %><%= ' | '+ @title if @title %> diff --git a/app/views/layouts/site.html.erb b/app/views/layouts/site.html.erb index 064fbed0a..a8201b912 100644 --- a/app/views/layouts/site.html.erb +++ b/app/views/layouts/site.html.erb @@ -32,7 +32,7 @@
  • <%= link_to h(t('layouts.edit')) + content_tag(:span, "▾", :class => "menuicon"), edit_path, { :id => 'editanchor', :title => t('javascripts.site.edit_tooltip'), - :data => { :minzoom => 13 }, + :data => { :minzoom => 13, :editor => preferred_editor }, :class => 'geolink llz object disabled' } %>
  • <%= link_to t('layouts.history'), browse_changesets_path, { @@ -44,17 +44,18 @@
  • <%= link_to t('layouts.export'), export_path, { :id => 'exportanchor', :title => t('layouts.export_tooltip'), + :data => { :url => url_for(:controller => :export, :action => :start) }, :class => 'geolink llz layers' } %>