X-Git-Url: https://git.openstreetmap.org/rails.git/blobdiff_plain/336a80530cb38c4b138493ef547961ea36b82ee3..8a9261ea0749ce9bf714073542a017133de01378:/app/views/browse/start.rjs diff --git a/app/views/browse/start.rjs b/app/views/browse/start.rjs index 5ea29921e..11f9edfd4 100644 --- a/app/views/browse/start.rjs +++ b/app/views/browse/start.rjs @@ -1,181 +1,337 @@ -page.replace_html :sidebar_title, 'Browse' +page.replace_html :sidebar_title, 'Data' page.replace_html :sidebar_content, :partial => 'start' page << <API)"; - - obj_list = document.createElement("ul"); - for (var i = 0; i < this.features.length; i++) { - var feature = this.features[i]; - var type ="way"; - if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { - type = "node"; - } - var nice_name = type.substr(0,1).toUpperCase() + type.substr(1,type.length); - var li = document.createElement("li"); - li.appendChild(document.createTextNode(nice_name + " ")); - var link = document.createElement("a"); - link.href = "/browse/"+type+"/"+feature.osm_id; - var name = feature.attributes.name || feature.osm_id; - link.appendChild(document.createTextNode(name)); - li.appendChild(link); - li.appendChild(document.createTextNode(" ")); - var link = document.createElement("a"); - link.href = "#"; - link.appendChild(document.createTextNode("+")); - link.feature = feature; - link.onclick = OpenLayers.Function.bind(function() { - 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")); - } - on_feature_hover(this.feature); - map.setCenter(this.feature.geometry.getBounds().getCenterLonLat()); - }, link); - li.appendChild(link); - obj_list.appendChild(li); - } - $("object").innerHTML = ""; - $("object").appendChild(obj_list); - } - function getData(bounds) { - $("status").innerHTML = "Loading..."; - bounds.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326")); - var url = "/api/0.5/map?bbox="+bounds.toBBOX(); - if (!gml) { - var def = OpenLayers.Feature.Vector.style['default']; - 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'}} + + var gml, sf, objList, currentFeature, featureList, mode = "auto", currentBounds, browsing; + OpenLayers.Feature.Vector.style['default'].strokeWidth = 3; + OpenLayers.Feature.Vector.style['default'].cursor = "pointer"; + + function start() { + openSidebar({ onclose: stopBrowse }); + var vectors = new OpenLayers.Layer.Vector(); + + box = new OpenLayers.Control.DrawFeature(vectors, OpenLayers.Handler.RegularPolygon, { + handlerOptions: { + sides: 4, + snapAngle: 90, + irregular: true, + persist: true, + callbacks: { done: endDrag } } - )]); - gml = new OpenLayers.Layer.GML("Data",url, - {format: OpenLayers.Format.OSM, formatOptions: {checkTags: true}, - styleMap: new OpenLayers.StyleMap({'default': style, 'select': {'strokeColor': '#0000ff'}}) - } - ); - gml.events.register("loadend", gml, dataLoaded ); - map.addLayer(gml); - sf = new OpenLayers.Control.SelectFeature(gml, {'onSelect': on_feature_hover}); - map.addControl(sf); - sf.activate(); + }); + map.addControl(box); + map.events.register("moveend", map, showData); + map.events.triggerEvent("moveend"); + browsing = true; + } - } else { - gml.setUrl(url); + function showData() { + if (mode == "manual") { return; } + if (map.getZoom() >= 15) { + useMap(); + } else { + $("status").innerHTML = "Zoom in or Select an area of the map to view."; + } + } + + function stopBrowse() { + if (gml) { + gml.destroy(); + gml = null; + } + if (sf) { + sf.destroy(); + sf = null; + } + if (currentFeature) { + currentFeature.destroy(); + currentFeature = null; + } + map.events.unregister("moveend", map, showData); + browsing = false; } - } - function endDrag(bbox) { - var bounds = bbox.getBounds(); - setBounds(bounds); - box.deactivate(); - getData(bounds); - $("drag_box").innerHTML = "Select an area to see features"; + + function startDrag() { + $("drag_box").innerHTML='Drag a box on the map to select an area'; + box.activate(); + return false; + }; + $("drag_box").onclick = startDrag; + + function useMap() { + var bounds = map.getExtent(); + var projected = bounds.clone().transform(map.getProjectionObject(), epsg4326); + if (!currentBounds || !currentBounds.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)); - } - function loadObjList() { - $("object").innerHTML=""; - $("object").appendChild(obj_list); - } + currentBounds = tileBounds; + getData(tileBounds); + mode = "auto"; + $("drag_box").style.display="inline"; + $("use_map").style.display="none"; + } + return false; + } + $("use_map").onclick = useMap; - function on_feature_hover(feature) { - if (currentFeature) { - currentFeature.layer.drawFeature( - currentFeature, currentFeature.layer.styleMap.createSymbolizer(currentFeature, "default") - ); - } - feature.layer.drawFeature( - feature, feature.layer.styleMap.createSymbolizer(feature, "select") - ); - if ($("object").firstChild == $("object").obj_list) { - $("object").removeChild(obj_list); - } else { + function endDrag(bbox) { + var bounds = bbox.getBounds(); + box.deactivate(); + getData(bounds); + $("drag_box").innerHTML = "Manually select a different area"; + mode = "manual"; + $("use_map").style.display="inline"; + $("drag_box").style.display="none"; + } + + function displayFeatureWarning() { + $("status").innerHTML = ""; + var div = document.createElement("div"); + var p = document.createElement("p"); + p.appendChild(document.createTextNode("You have loaded an area which contains " + featureList.length + " features. In general, some browsers may not cope well with displaying this quantity of data. Generally, browsers work best at displaying less than 100 features at a time: doing anything else may make your browser slow/unresponsive. If you are sure you want to display this data, you may do so by clicking the button below.")); + div.appendChild(p); + var input = document.createElement("input"); + input.type = "submit"; + input.value = "Load Data"; + input.onclick = loadFeatureList; + div.appendChild(input); + $("object").innerHTML=""; + $("object").appendChild(div); + } + + function loadFeatureList() { + gml.addFeatures(featureList); + gml.events.triggerEvent("loadend"); + return false; + } + + function customDataLoader(request) { + if (!browsing) { return; } + var doc = request.responseXML; + + if (!doc || !doc.documentElement) { + doc = request.responseText; + } + + var options = {}; + + OpenLayers.Util.extend(options, this.formatOptions); + if (this.map && !this.projection.equals(this.map.getProjectionObject())) { + options.externalProjection = this.projection; + options.internalProjection = this.map.getProjectionObject(); + } + + var gml = this.format ? new this.format(options) : new OpenLayers.Format.GML(options); + var features = gml.read(doc); + if (!this.maxFeatures || features.length <= this.maxFeatures) { + this.addFeatures(features); + this.events.triggerEvent("loadend"); + featureList = []; + } else { + featureList = features; + displayFeatureWarning(); + } + } + + function getData(bounds) { + + bounds.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326")); + var size = bounds.getWidth() * bounds.getHeight(); + if (size > 0.25) { + $("status").innerHTML = "Unable to load: Bounding box size of " + size + " is too large. (Must be smaller than 0.25)
"; + return; + } + + var url = "/api/0.5/map?bbox="+bounds.toBBOX(); + + loadGML(url); + } + function loadGML(url) { + $("status").innerHTML = "Loading..."; $("object").innerHTML = ""; - } - var div = document.createElement("div"); - var link = document.createElement("a"); - link.href="#"; - link.onclick = loadObjList; - link.appendChild(document.createTextNode("Back to Object List")); - div.appendChild(link) - $("object").appendChild(div); - var ul = document.createElement("ul"); - var type ="way"; - if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { - type = "node"; - } - var li = document.createElement("li"); - var link = document.createElement("a"); - link.href = "/browse/"+type+"/"+feature.osm_id; - link.appendChild(document.createTextNode(feature.osm_id)); - li.appendChild(link); - ul.appendChild(li); - for (var key in feature.attributes) { - var li = document.createElement("li"); - li.appendChild(document.createTextNode(key + ": " + feature.attributes[key])); - ul.appendChild(li); - } - $("object").appendChild(ul); - currentFeature = feature; - } - function setBounds(bounds) { - var epsg4326 = new OpenLayers.Projection("EPSG:4326"); - var decimals = Math.pow(10, Math.floor(map.getZoom() / 3)); + if (!gml) { + 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'}} + } + )]); + gml = new OpenLayers.Layer.GML("Data",url, + {format: OpenLayers.Format.OSM, formatOptions: {checkTags: true}, + maxFeatures: 100, requestSuccess: customDataLoader, + styleMap: new OpenLayers.StyleMap({'default': style, 'select': {'strokeColor': '#0000ff', strokeWidth: 8}}) + } + ); + gml.events.register("loadend", gml, dataLoaded ); + map.addLayer(gml); + + sf = new OpenLayers.Control.SelectFeature(gml, {'onSelect': onFeatureSelect}); + sf.handler.stopDown = false; + sf.handler.stopUp = false; + map.addControl(sf); + sf.activate(); + + } else { + gml.setUrl(url); + } - bounds = bounds.clone().transform(map.getProjectionObject(), epsg4326); + currentFeature = null; + } + function dataLoaded() { + if (!browsing) { return; } + $("status").innerHTML = "Loaded " + this.features.length + " features. (API)"; + + objList = document.createElement("ul"); + for (var i = 0; i < this.features.length; i++) { + var feature = this.features[i]; + + // Type, for linking + var type ="way"; + if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { + type = "node"; + } + var nice_name = type.substr(0,1).toUpperCase() + type.substr(1,type.length); + var li = document.createElement("li"); + li.appendChild(document.createTextNode(nice_name + " ")); + + // Link, for viewing in the tab + var link = document.createElement("a"); + link.href = "/browse/" + type + "/" + feature.osm_id; + var name = feature.attributes.name || feature.osm_id; + link.appendChild(document.createTextNode(name)); + link.feature = feature; + link.onclick = OpenLayers.Function.bind(viewFeatureLink, link); + li.appendChild(link); - $("minlon").innerHTML = Math.round(bounds.left * decimals) / decimals; - $("minlat").innerHTML = Math.round(bounds.bottom * decimals) / decimals; - $("maxlon").innerHTML = Math.round(bounds.right * decimals) / decimals; - $("maxlat").innerHTML = Math.round(bounds.top * decimals) / decimals; - } + objList.appendChild(li); + } + $("object").innerHTML = ""; + $("object").appendChild(objList); + } + + 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 (mode != "auto") { + map.setCenter(this.feature.geometry.getBounds().getCenterLonLat()); + } + return false; + } + + function loadObjList() { + $("object").innerHTML=""; + $("object").appendChild(objList); + return false; + } + + function onFeatureSelect(feature) { + // Unselect previously selected feature + if (currentFeature) { + currentFeature.layer.drawFeature( + currentFeature, currentFeature.layer.styleMap.createSymbolizer(currentFeature, "default") + ); + } + + // Redraw in selected style + feature.layer.drawFeature( + feature, feature.layer.styleMap.createSymbolizer(feature, "select") + ); -start(); + // If the current object is the list, don't innerHTML="", since that could clar it. + if ($("object").firstChild == objList) { + $("object").removeChild(objList); + } else { + $("object").innerHTML = ""; + } + + // Create a link back to the object list + var div = document.createElement("div"); + var link = document.createElement("a"); + link.href="#"; + link.onclick = loadObjList; + link.appendChild(document.createTextNode("Back to Object List")); + div.appendChild(link) + $("object").appendChild(div); + + // Now the list of attributes + var ul = document.createElement("ul"); + var type = "way"; + if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { + type = "node"; + } + var li = document.createElement("li"); + var link = document.createElement("a"); + link.href = "/browse/"+type+"/"+feature.osm_id; + link.appendChild(document.createTextNode(feature.osm_id)); + li.appendChild(link); + ul.appendChild(li); + 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 li = document.createElement("li"); + var link = document.createElement("a"); + link.href = "/browse/"+type+"/"+feature.osm_id+"/history"; + link.appendChild(document.createTextNode("History")); + li.appendChild(link); + ul.appendChild(li); + link.onclick = OpenLayers.Function.bind(loadHistory, {type: type, feature: feature, link: link}); + $("object").appendChild(ul); + + + // Stash the currently drawn feature + currentFeature = feature; + } + function loadHistory() { + this.link.href = ""; + this.link.innerHTML = "Wait..."; + new Ajax.Request("/api/0.5/"+this.type+"/"+this.feature.osm_id+"/history", {onComplete: OpenLayers.Function.bind(displayHistory, this)}); + return false; + } + function displayHistory(request) { + if (currentFeature.osm_id != this.feature.osm_id || $("object").firstChild == objList) { + return false; + } + this.link.parentNode.parentNode.removeChild(this.link.parentNode); + var doc = request.responseXML; + var div = document.createElement("div"); + var h3 = document.createElement("h3"); + h3.appendChild(document.createTextNode("History")); + div.appendChild(h3); + 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") || "private user"; + var timestamp = nodes[i].getAttribute("timestamp"); + var item = document.createElement("li"); + item.appendChild(document.createTextNode("Edited by " + user + " at " + timestamp)); + history.appendChild(item); + } + div.appendChild(history); + var link = document.createElement("a"); + link.appendChild(document.createTextNode("History")); + link.href = "/browse/"+this.type+"/"+this.feature.osm_id+"/history"; + div.appendChild(link); + $("object").appendChild(div); + } + + start(); EOJ