Merge data browser branch to trunk.
This commit is contained in:
commit
97aefa23d0
31 changed files with 1022 additions and 9 deletions
|
@ -43,8 +43,8 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
def check_database_availability
|
||||
if OSM_STATUS == :database_offline
|
||||
def check_database_availability(need_api = false)
|
||||
if OSM_STATUS == :database_offline or (need_api and OSM_STATUS == :api_offline)
|
||||
redirect_to :controller => 'site', :action => 'offline'
|
||||
end
|
||||
end
|
||||
|
|
109
app/controllers/browse_controller.rb
Normal file
109
app/controllers/browse_controller.rb
Normal file
|
@ -0,0 +1,109 @@
|
|||
class BrowseController < ApplicationController
|
||||
layout 'site'
|
||||
|
||||
before_filter :authorize_web
|
||||
before_filter { |c| c.check_database_availability(true) }
|
||||
|
||||
def start
|
||||
end
|
||||
|
||||
def index
|
||||
@nodes = Node.find(:all, :order => "timestamp DESC", :limit=> 20)
|
||||
end
|
||||
|
||||
def relation
|
||||
begin
|
||||
@relation = Relation.find(params[:id])
|
||||
|
||||
@name = @relation.tags['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @relation.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Relation | ' + (@name)
|
||||
@next = Relation.find(:first, :order => "id ASC", :conditions => [ "visible = true AND id > :id", { :id => @relation.id }] )
|
||||
@prev = Relation.find(:first, :order => "id DESC", :conditions => [ "visible = true AND id < :id", { :id => @relation.id }] )
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
end
|
||||
|
||||
def relation_history
|
||||
begin
|
||||
@relation = Relation.find(params[:id])
|
||||
|
||||
@name = @relation.tags['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @relation.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Relation History | ' + (@name)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
end
|
||||
|
||||
def way
|
||||
begin
|
||||
@way = Way.find(params[:id])
|
||||
|
||||
@name = @way.tags['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @way.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Way | ' + (@name)
|
||||
@next = Way.find(:first, :order => "id ASC", :conditions => [ "visible = true AND id > :id", { :id => @way.id }] )
|
||||
@prev = Way.find(:first, :order => "id DESC", :conditions => [ "visible = true AND id < :id", { :id => @way.id }] )
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
end
|
||||
|
||||
def way_history
|
||||
begin
|
||||
@way = Way.find(params[:id])
|
||||
|
||||
@name = @way.tags['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @way.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Way History | ' + (@name)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
end
|
||||
|
||||
def node
|
||||
begin
|
||||
@node = Node.find(params[:id])
|
||||
|
||||
@name = @node.tags_as_hash['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @node.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Node | ' + (@name)
|
||||
@next = Node.find(:first, :order => "id ASC", :conditions => [ "visible = true AND id > :id", { :id => @node.id }] )
|
||||
@prev = Node.find(:first, :order => "id DESC", :conditions => [ "visible = true AND id < :id", { :id => @node.id }] )
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
end
|
||||
|
||||
def node_history
|
||||
begin
|
||||
@node = Node.find(params[:id])
|
||||
|
||||
@name = @node.tags_as_hash['name'].to_s
|
||||
if @name.length == 0:
|
||||
@name = "#" + @node.id.to_s
|
||||
end
|
||||
|
||||
@title = 'Node History | ' + (@name)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render :nothing => true, :status => :not_found
|
||||
end
|
||||
end
|
||||
end
|
2
app/helpers/browse_helper.rb
Normal file
2
app/helpers/browse_helper.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
module BrowseHelper
|
||||
end
|
|
@ -50,4 +50,22 @@ class OldNode < ActiveRecord::Base
|
|||
el1['timestamp'] = self.timestamp.xmlschema
|
||||
return el1
|
||||
end
|
||||
|
||||
def tags_as_hash
|
||||
hash = {}
|
||||
Tags.split(self.tags) do |k,v|
|
||||
hash[k] = v
|
||||
end
|
||||
hash
|
||||
end
|
||||
|
||||
# Pretend we're not in any ways
|
||||
def ways
|
||||
return []
|
||||
end
|
||||
|
||||
# Pretend we're not in any relations
|
||||
def containing_relation_members
|
||||
return []
|
||||
end
|
||||
end
|
||||
|
|
|
@ -108,4 +108,19 @@ class OldRelation < ActiveRecord::Base
|
|||
end
|
||||
return el1
|
||||
end
|
||||
|
||||
# Temporary method to match interface to nodes
|
||||
def tags_as_hash
|
||||
return self.tags
|
||||
end
|
||||
|
||||
# Temporary method to match interface to relations
|
||||
def relation_members
|
||||
return self.old_members
|
||||
end
|
||||
|
||||
# Pretend we're not in any relations
|
||||
def containing_relation_members
|
||||
return []
|
||||
end
|
||||
end
|
||||
|
|
|
@ -109,4 +109,19 @@ class OldWay < ActiveRecord::Base
|
|||
end
|
||||
return el1
|
||||
end
|
||||
|
||||
# Temporary method to match interface to nodes
|
||||
def tags_as_hash
|
||||
return self.tags
|
||||
end
|
||||
|
||||
# Temporary method to match interface to ways
|
||||
def way_nodes
|
||||
return self.old_nodes
|
||||
end
|
||||
|
||||
# Pretend we're not in any relations
|
||||
def containing_relation_members
|
||||
return []
|
||||
end
|
||||
end
|
||||
|
|
|
@ -234,4 +234,8 @@ class Relation < ActiveRecord::Base
|
|||
return false
|
||||
end
|
||||
|
||||
# Temporary method to match interface to nodes
|
||||
def tags_as_hash
|
||||
return self.tags
|
||||
end
|
||||
end
|
||||
|
|
|
@ -257,4 +257,9 @@ class Way < ActiveRecord::Base
|
|||
self.delete_with_relations_and_history(user)
|
||||
|
||||
end
|
||||
|
||||
# Temporary method to match interface to nodes
|
||||
def tags_as_hash
|
||||
return self.tags
|
||||
end
|
||||
end
|
||||
|
|
22
app/views/browse/_common_details.rhtml
Normal file
22
app/views/browse/_common_details.rhtml
Normal file
|
@ -0,0 +1,22 @@
|
|||
<tr>
|
||||
<th>Edited at:</th>
|
||||
<td><%= h(common_details.timestamp) %></td>
|
||||
</tr>
|
||||
|
||||
<% if common_details.user.data_public %>
|
||||
<tr>
|
||||
<th>Edited by:</th>
|
||||
<td><%= link_to h(common_details.user.display_name), :controller => "user", :action => "view", :display_name => common_details.user.display_name %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
<% unless common_details.tags_as_hash.empty? %>
|
||||
<tr valign="top">
|
||||
<th>Tags:</th>
|
||||
<td>
|
||||
<table padding="0">
|
||||
<%= render :partial => "tag", :collection => common_details.tags_as_hash %>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
8
app/views/browse/_containing_relation.rhtml
Normal file
8
app/views/browse/_containing_relation.rhtml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<tr>
|
||||
<td>
|
||||
<%= link_to "Relation " + containing_relation.id.to_s, :action => "relation", :id => containing_relation.id.to_s %>
|
||||
<% unless containing_relation.member_role.blank? %>
|
||||
(as <%= h(containing_relation.member_role) %>)
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
64
app/views/browse/_map.rhtml
Normal file
64
app/views/browse/_map.rhtml
Normal file
|
@ -0,0 +1,64 @@
|
|||
<%= javascript_include_tag '/openlayers/OpenLayers.js' %>
|
||||
<%= javascript_include_tag '/openlayers/OpenStreetMap.js' %>
|
||||
<%= javascript_include_tag 'map.js' %>
|
||||
<td align="right">
|
||||
<% if map.visible %>
|
||||
<div id="small_map" style="width:250px; height: 300px; border: solid 1px black">
|
||||
</div>
|
||||
<span id="loading">Loading...</span>
|
||||
<a id="larger_map" href=""></a>
|
||||
<% else %>
|
||||
Deleted
|
||||
<% end %>
|
||||
</td>
|
||||
<script type="text/javascript">
|
||||
function init() {
|
||||
var obj_type = "<%= map.class.name.downcase %>";
|
||||
var obj_id = <%= map.id %>;
|
||||
var url = "/api/<%= "#{API_VERSION}" %>/<%= map.class.name.downcase %>/<%= map.id %>";
|
||||
|
||||
if (obj_type != "node") {
|
||||
url += "/full";
|
||||
}
|
||||
|
||||
var map = createMap("small_map", {
|
||||
controls: [ new OpenLayers.Control.Navigation() ]
|
||||
});
|
||||
|
||||
var osm_layer = new OpenLayers.Layer.GML("OSM", url, {
|
||||
format: OpenLayers.Format.OSM,
|
||||
projection: new OpenLayers.Projection("EPSG:4326")
|
||||
});
|
||||
|
||||
osm_layer.events.register("loadend", osm_layer, function() {
|
||||
$("loading").innerHTML = "";
|
||||
|
||||
if (this.features.length) {
|
||||
var extent = this.features[0].geometry.getBounds();
|
||||
|
||||
for (var i = 1; i < this.features.length; i++) {
|
||||
extent.extend(this.features[i].geometry.getBounds());
|
||||
}
|
||||
|
||||
if (extent) {
|
||||
this.map.zoomToExtent(extent);
|
||||
} else {
|
||||
this.map.zoomToMaxExtent();
|
||||
}
|
||||
|
||||
var center = getMapCenter();
|
||||
$("larger_map").href = '/?lat='+center.lat+'&lon='+center.lon+'&zoom='+this.map.getZoom();
|
||||
$("larger_map").innerHTML = "View Larger Map";
|
||||
} else {
|
||||
$("small_map").style.display = "none";
|
||||
}
|
||||
});
|
||||
|
||||
map.addLayer(osm_layer);
|
||||
|
||||
osm_layer.loadGML();
|
||||
osm_layer.loaded = true;
|
||||
}
|
||||
|
||||
window.onload = init;
|
||||
</script>
|
13
app/views/browse/_navigation.rhtml
Normal file
13
app/views/browse/_navigation.rhtml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<div style="float:right; text-align:center; width: 250px;">
|
||||
<% if @prev %>
|
||||
<
|
||||
<%= link_to @prev.id.to_s, :id => @prev.id %>
|
||||
<% end %>
|
||||
<% if @prev and @next %>
|
||||
|
|
||||
<% end %>
|
||||
<% if @next %>
|
||||
<%= link_to @next.id.to_s, :id => @next.id %>
|
||||
>
|
||||
<% end %>
|
||||
</div>
|
19
app/views/browse/_node_details.rhtml
Normal file
19
app/views/browse/_node_details.rhtml
Normal file
|
@ -0,0 +1,19 @@
|
|||
<table>
|
||||
|
||||
<%= render :partial => "common_details", :object => node_details %>
|
||||
|
||||
<% unless node_details.ways.empty? and node_details.containing_relation_members.empty? %>
|
||||
<tr valign="top">
|
||||
<th>Part of:</th>
|
||||
<td>
|
||||
<table padding="0">
|
||||
<% node_details.ways.each do |way| %>
|
||||
<tr><td><%= link_to "Way " + way.id.to_s, :action => "way", :id => way.id.to_s %></td></tr>
|
||||
<% end %>
|
||||
<%= render :partial => "containing_relation", :collection => node_details.containing_relation_members %>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
</table>
|
27
app/views/browse/_relation_details.rhtml
Normal file
27
app/views/browse/_relation_details.rhtml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<table>
|
||||
|
||||
<%= render :partial => "common_details", :object => relation_details %>
|
||||
|
||||
<% unless relation_details.relation_members.empty? %>
|
||||
<tr valign="top">
|
||||
<th>Members:</th>
|
||||
<td>
|
||||
<table padding="0">
|
||||
<%= render :partial => "relation_member", :collection => relation_details.relation_members %>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
<% unless relation_details.containing_relation_members.empty? %>
|
||||
<tr>
|
||||
<th>Part of:</th>
|
||||
<td>
|
||||
<table padding="0">
|
||||
<%= render :partial => "containing_relation", :collection => relation_details.containing_relation_members %>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
</table>
|
10
app/views/browse/_relation_member.rhtml
Normal file
10
app/views/browse/_relation_member.rhtml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<tr>
|
||||
<td>
|
||||
<%= h(relation_member.member_type.capitalize) %>
|
||||
<%= link_to relation_member.member_id.to_s, :action => relation_member.member_type, :id => relation_member.member_id %>
|
||||
<% unless relation_member.member_role.blank? %>
|
||||
as
|
||||
<%= h(relation_member.member_role) %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
13
app/views/browse/_start.rhtml
Normal file
13
app/views/browse/_start.rhtml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<div>
|
||||
<div style="text-align: center">
|
||||
<p style="margin-top: 10px; margin-bottom: 20px">
|
||||
<a id="browse_select_view" href="#">View data for current map view</a>
|
||||
<br />
|
||||
<a id="browse_select_box" href="#">Manually select a different area</a>
|
||||
</p>
|
||||
</div>
|
||||
<div id="browse_status" style="text-align: center; display: none">
|
||||
</div>
|
||||
<div id="browse_content">
|
||||
</div>
|
||||
</div>
|
3
app/views/browse/_tag.rhtml
Normal file
3
app/views/browse/_tag.rhtml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<tr>
|
||||
<td><%= h(tag[0]) %> = <%= h(tag[1]) %></td>
|
||||
</tr>
|
27
app/views/browse/_way_details.rhtml
Normal file
27
app/views/browse/_way_details.rhtml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<table>
|
||||
|
||||
<%= render :partial => "common_details", :object => way_details %>
|
||||
|
||||
<tr valign="top">
|
||||
<th>Nodes:</th>
|
||||
<td>
|
||||
<table padding="0">
|
||||
<% way_details.way_nodes.each do |wn| %>
|
||||
<tr><td><%= link_to "Node " + wn.node_id.to_s, :action => "node", :id => wn.node_id.to_s %></td></tr>
|
||||
<% end %>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<% unless way_details.containing_relation_members.empty? %>
|
||||
<tr>
|
||||
<th>Part of:</th>
|
||||
<td>
|
||||
<table padding="0">
|
||||
<%= render :partial => "containing_relation", :collection => way_details.containing_relation_members %>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
</table>
|
12
app/views/browse/index.rhtml
Normal file
12
app/views/browse/index.rhtml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<h2><%= @nodes.length %> Recently Changed Nodes</h2>
|
||||
<ul>
|
||||
<% @nodes.each do |node|
|
||||
name = node.tags_as_hash['name'].to_s
|
||||
if name.length == 0:
|
||||
name = "(No name)"
|
||||
end
|
||||
name = name + " - " + node.id.to_s
|
||||
%>
|
||||
<li><%= link_to h(name), :action => "node", :id => node.id %></li>
|
||||
<% end %>
|
||||
</ul>
|
20
app/views/browse/node.rhtml
Normal file
20
app/views/browse/node.rhtml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<table width="100%">
|
||||
<tr>
|
||||
<td>
|
||||
<h2>Node: <%= h(@name) %></h2>
|
||||
</td>
|
||||
<td>
|
||||
<%= render :partial => "navigation" %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<%= render :partial => "node_details", :object => @node %>
|
||||
<hr />
|
||||
<%= link_to "Download XML", :controller => "node", :action => "read" %>
|
||||
or
|
||||
<%= link_to "view history", :action => "node_history" %>
|
||||
</td>
|
||||
<%= render :partial => "map", :object => @node %>
|
||||
</tr>
|
||||
</table>
|
16
app/views/browse/node_history.rhtml
Normal file
16
app/views/browse/node_history.rhtml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<h2>Node History: <%= h(@name) %></h2>
|
||||
|
||||
<table width="100%">
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<% @node.old_nodes.reverse.each do |node| %>
|
||||
<%= render :partial => "node_details", :object => node %>
|
||||
<hr />
|
||||
<% end %>
|
||||
<%= link_to "Download XML", :controller => "old_node", :action => "history" %>
|
||||
or
|
||||
<%= link_to "view details", :action => "node" %>
|
||||
</td>
|
||||
<%= render :partial => "map", :object => @node %>
|
||||
</tr>
|
||||
</table>
|
20
app/views/browse/relation.rhtml
Normal file
20
app/views/browse/relation.rhtml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<table width="100%">
|
||||
<tr>
|
||||
<td>
|
||||
<h2>Relation: <%= h(@name) %></h2>
|
||||
</td>
|
||||
<td>
|
||||
<%= render :partial => "navigation" %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<%= render :partial => "relation_details", :object => @relation %>
|
||||
<hr />
|
||||
<%= link_to "Download XML", :controller => "relation", :action => "read" %>
|
||||
or
|
||||
<%= link_to "view history", :action => "relation_history" %>
|
||||
</td>
|
||||
<%= render :partial => "map", :object => @relation %>
|
||||
</tr>
|
||||
</table>
|
16
app/views/browse/relation_history.rhtml
Normal file
16
app/views/browse/relation_history.rhtml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<h2>Relation History: <%= h(@name) %></h2>
|
||||
|
||||
<table width="100%">
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<% @relation.old_relations.reverse.each do |relation| %>
|
||||
<%= render :partial => "relation_details", :object => relation %>
|
||||
<hr />
|
||||
<% end %>
|
||||
<%= link_to "Download XML", :controller => "old_relation", :action => "history" %>
|
||||
or
|
||||
<%= link_to "view details", :action => "relation" %>
|
||||
</td>
|
||||
<%= render :partial => "map", :object => @relation %>
|
||||
</tr>
|
||||
</table>
|
481
app/views/browse/start.rjs
Normal file
481
app/views/browse/start.rjs
Normal file
|
@ -0,0 +1,481 @@
|
|||
page.replace_html :sidebar_title, 'Data'
|
||||
page.replace_html :sidebar_content, :partial => 'start'
|
||||
page << <<EOJ
|
||||
var browseBoxControl;
|
||||
var browseActive;
|
||||
var browseMode = "auto";
|
||||
var browseBounds;
|
||||
var browseFeatureList;
|
||||
var browseActiveFeature;
|
||||
var browseDataLayer;
|
||||
var browseSelectControl;
|
||||
var browseObjectList;
|
||||
|
||||
OpenLayers.Feature.Vector.style['default'].strokeWidth = 3;
|
||||
OpenLayers.Feature.Vector.style['default'].cursor = "pointer";
|
||||
|
||||
function startBrowse() {
|
||||
openSidebar({ onclose: stopBrowse });
|
||||
|
||||
var vectors = new OpenLayers.Layer.Vector();
|
||||
|
||||
browseBoxControl = new OpenLayers.Control.DrawFeature(vectors, OpenLayers.Handler.RegularPolygon, {
|
||||
handlerOptions: {
|
||||
sides: 4,
|
||||
snapAngle: 90,
|
||||
irregular: true,
|
||||
persist: true,
|
||||
callbacks: { done: endDrag }
|
||||
}
|
||||
});
|
||||
map.addControl(browseBoxControl);
|
||||
|
||||
map.events.register("moveend", map, showData);
|
||||
map.events.triggerEvent("moveend");
|
||||
|
||||
browseActive = true;
|
||||
}
|
||||
|
||||
function showData() {
|
||||
if (browseMode == "auto") {
|
||||
if (map.getZoom() >= 15) {
|
||||
useMap();
|
||||
} else {
|
||||
setStatus("Zoom in or select an area of the map to view");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function stopBrowse() {
|
||||
if (browseActive) {
|
||||
browseActive = false;
|
||||
|
||||
if (browseDataLayer) {
|
||||
browseDataLayer.destroy();
|
||||
browseDataLayer = null;
|
||||
}
|
||||
|
||||
if (browseSelectControl) {
|
||||
browseSelectControl.destroy();
|
||||
browseSelectControl = null;
|
||||
}
|
||||
|
||||
if (browseBoxControl) {
|
||||
browseBoxControl.destroy();
|
||||
browseBoxControl = null;
|
||||
}
|
||||
|
||||
if (browseActiveFeature) {
|
||||
browseActiveFeature.destroy();
|
||||
browseActiveFeature = null;
|
||||
}
|
||||
|
||||
map.dataLayer.setVisibility(false);
|
||||
map.events.unregister("moveend", map, showData);
|
||||
}
|
||||
}
|
||||
|
||||
function startDrag() {
|
||||
$("browse_select_box").innerHTML='Drag a box on the map to select an area';
|
||||
|
||||
browseBoxControl.activate();
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
$("browse_select_box").onclick = startDrag;
|
||||
|
||||
function useMap() {
|
||||
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);
|
||||
|
||||
browseMode = "auto";
|
||||
|
||||
$("browse_select_view").style.display = "none";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$("browse_select_view").onclick = useMap;
|
||||
|
||||
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").innerHTML = "Manually select a different area";
|
||||
$("browse_select_view").style.display = "inline";
|
||||
}
|
||||
|
||||
function displayFeatureWarning() {
|
||||
clearStatus();
|
||||
|
||||
var div = document.createElement("div");
|
||||
|
||||
var p = document.createElement("p");
|
||||
p.appendChild(document.createTextNode("You have loaded an area which contains " + browseFeatureList.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);
|
||||
|
||||
$("browse_content").innerHTML = "";
|
||||
$("browse_content").appendChild(div);
|
||||
}
|
||||
|
||||
function loadFeatureList() {
|
||||
browseDataLayer.addFeatures(browseFeatureList);
|
||||
browseDataLayer.events.triggerEvent("loadend");
|
||||
|
||||
browseFeatureList = [];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function customDataLoader(request) {
|
||||
if (browseActive) {
|
||||
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);
|
||||
|
||||
browseFeatureList = gml.read(doc);
|
||||
|
||||
if (!this.maxFeatures || browseFeatureList.length <= this.maxFeatures) {
|
||||
loadFeatureList();
|
||||
} else {
|
||||
displayFeatureWarning();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getData(bounds) {
|
||||
var projected = bounds.clone().transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
|
||||
var size = projected.getWidth() * projected.getHeight();
|
||||
|
||||
if (size > 0.25) {
|
||||
setStatus("Unable to load: Bounding box size of " + size + " is too large (must be smaller than 0.25)");
|
||||
} else {
|
||||
loadGML("/api/0.5/map?bbox=" + projected.toBBOX());
|
||||
}
|
||||
}
|
||||
|
||||
function loadGML(url) {
|
||||
setStatus("Loading...");
|
||||
$("browse_content").innerHTML = "";
|
||||
|
||||
if (!browseDataLayer) {
|
||||
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' }
|
||||
}
|
||||
})]);
|
||||
|
||||
browseDataLayer = new OpenLayers.Layer.GML("Data", url, {
|
||||
format: OpenLayers.Format.OSM,
|
||||
formatOptions: { checkTags: true },
|
||||
maxFeatures: 100,
|
||||
requestSuccess: customDataLoader,
|
||||
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.handler.stopDown = false;
|
||||
browseSelectControl.handler.stopUp = false;
|
||||
map.addControl(browseSelectControl);
|
||||
browseSelectControl.activate();
|
||||
} else {
|
||||
browseDataLayer.setUrl(url);
|
||||
}
|
||||
|
||||
browseActiveFeature = null;
|
||||
}
|
||||
|
||||
function dataLoaded() {
|
||||
if (browseActive) {
|
||||
clearStatus();
|
||||
|
||||
browseObjectList = document.createElement("div")
|
||||
|
||||
var heading = document.createElement("p");
|
||||
heading.className = "browse_heading";
|
||||
heading.appendChild(document.createTextNode("Object list"));
|
||||
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 = ucFirst(type);
|
||||
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 = feature.attributes.name || feature.osm_id;
|
||||
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.url;
|
||||
link.appendChild(document.createTextNode("API"));
|
||||
browseObjectList.appendChild(link);
|
||||
|
||||
$("browse_content").innerHTML = "";
|
||||
$("browse_content").appendChild(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());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function loadObjectList() {
|
||||
$("browse_content").innerHTML="";
|
||||
$("browse_content").appendChild(browseObjectList);
|
||||
|
||||
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").innerHTML = "";
|
||||
}
|
||||
|
||||
// Create a link back to the object list
|
||||
var div = document.createElement("div");
|
||||
div.style.textAlign = "center";
|
||||
div.style.marginBottom = "20px";
|
||||
$("browse_content").appendChild(div);
|
||||
var link = document.createElement("a");
|
||||
link.href = "#";
|
||||
link.onclick = loadObjectList;
|
||||
link.appendChild(document.createTextNode("Display object list"));
|
||||
div.appendChild(link);
|
||||
|
||||
var table = document.createElement("table");
|
||||
table.width = "100%";
|
||||
table.className = "browse_heading";
|
||||
$("browse_content").appendChild(table);
|
||||
|
||||
var tr = document.createElement("tr");
|
||||
table.appendChild(tr);
|
||||
|
||||
var heading = document.createElement("td");
|
||||
heading.appendChild(document.createTextNode(featureName(feature)));
|
||||
tr.appendChild(heading);
|
||||
|
||||
var td = document.createElement("td");
|
||||
td.align = "right";
|
||||
tr.appendChild(td);
|
||||
|
||||
var type = featureType(feature);
|
||||
var link = document.createElement("a");
|
||||
link.href = "/browse/" + type + "/" + feature.osm_id;
|
||||
link.appendChild(document.createTextNode("Details"));
|
||||
td.appendChild(link);
|
||||
|
||||
var div = document.createElement("div");
|
||||
div.className = "browse_details";
|
||||
|
||||
$("browse_content").appendChild(div);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
div.appendChild(ul);
|
||||
|
||||
var link = document.createElement("a");
|
||||
link.href = "/browse/" + type + "/" + feature.osm_id + "/history";
|
||||
link.appendChild(document.createTextNode("Show history"));
|
||||
link.onclick = OpenLayers.Function.bind(loadHistory, {
|
||||
type: type, feature: feature, link: link
|
||||
});
|
||||
|
||||
div.appendChild(link);
|
||||
|
||||
// Stash the currently drawn feature
|
||||
browseActiveFeature = 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 (browseActiveFeature.osm_id != this.feature.osm_id || $("browse_content").firstChild == browseObjectList) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.link.parentNode.removeChild(this.link);
|
||||
|
||||
var doc = request.responseXML;
|
||||
|
||||
var table = document.createElement("table");
|
||||
table.width = "100%";
|
||||
table.className = "browse_heading";
|
||||
$("browse_content").appendChild(table);
|
||||
|
||||
var tr = document.createElement("tr");
|
||||
table.appendChild(tr);
|
||||
|
||||
var heading = document.createElement("td");
|
||||
heading.appendChild(document.createTextNode("History for " + featureName(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("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") || "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);
|
||||
|
||||
$("browse_content").appendChild(div);
|
||||
}
|
||||
|
||||
function featureType(feature) {
|
||||
if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
|
||||
return "node";
|
||||
} else {
|
||||
return "way";
|
||||
}
|
||||
}
|
||||
|
||||
function featureName(feature) {
|
||||
if (feature.attributes.name) {
|
||||
return feature.attributes.name;
|
||||
} else {
|
||||
return ucFirst(featureType(feature)) + " " + feature.osm_id;
|
||||
}
|
||||
}
|
||||
|
||||
function setStatus(status) {
|
||||
$("browse_status").innerHTML = status;
|
||||
$("browse_status").style.display = "block";
|
||||
}
|
||||
|
||||
function clearStatus() {
|
||||
$("browse_status").innerHTML = "";
|
||||
$("browse_status").style.display = "none";
|
||||
}
|
||||
|
||||
function ucFirst(str) {
|
||||
return str.substr(0,1).toUpperCase() + str.substr(1,str.length);
|
||||
}
|
||||
|
||||
startBrowse();
|
||||
EOJ
|
20
app/views/browse/way.rhtml
Normal file
20
app/views/browse/way.rhtml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<table width="100%">
|
||||
<tr>
|
||||
<td>
|
||||
<h2>Way: <%= h(@name) %></h2>
|
||||
</td>
|
||||
<td>
|
||||
<%= render :partial => "navigation" %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<%= render :partial => "way_details", :object => @way %>
|
||||
<hr />
|
||||
<%= link_to "Download XML", :controller => "way", :action => "read" %>
|
||||
or
|
||||
<%= link_to "view history", :action => "way_history" %>
|
||||
</td>
|
||||
<%= render :partial => "map", :object => @way %>
|
||||
</tr>
|
||||
</table>
|
16
app/views/browse/way_history.rhtml
Normal file
16
app/views/browse/way_history.rhtml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<h2>Way History: <%= h(@name) %></h2>
|
||||
|
||||
<table width="100%">
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<% @way.old_ways.reverse.each do |way| %>
|
||||
<%= render :partial => "way_details", :object => way %>
|
||||
<hr />
|
||||
<% end %>
|
||||
<%= link_to "Download XML", :controller => "old_way", :action => "history" %>
|
||||
or
|
||||
<%= link_to "view details", :action => "way" %>
|
||||
</td>
|
||||
<%= render :partial => "map", :object => @way %>
|
||||
</tr>
|
||||
</table>
|
|
@ -94,6 +94,12 @@ by the OpenStreetMap project and its contributors.
|
|||
function mapInit(){
|
||||
map = createMap("map");
|
||||
|
||||
<% unless OSM_STATUS == :api_offline or OSM_STATUS == :database_offline %>
|
||||
map.dataLayer = new OpenLayers.Layer("Data", { "visibility": false });
|
||||
map.dataLayer.events.register("visibilitychanged", map.dataLayer, toggleData);
|
||||
map.addLayer(map.dataLayer);
|
||||
<% end %>
|
||||
|
||||
<% if bbox %>
|
||||
var bbox = new OpenLayers.Bounds(<%= minlon %>, <%= minlat %>, <%= maxlon %>, <%= maxlat %>);
|
||||
|
||||
|
@ -126,6 +132,14 @@ by the OpenStreetMap project and its contributors.
|
|||
handleResize();
|
||||
}
|
||||
|
||||
function toggleData() {
|
||||
if (map.dataLayer.visibility) {
|
||||
<%= remote_function :url => { :controller => 'browse', :action => 'start' } %>
|
||||
} else {
|
||||
closeSidebar();
|
||||
}
|
||||
}
|
||||
|
||||
function getPosition() {
|
||||
return getMapCenter();
|
||||
}
|
||||
|
|
|
@ -57,6 +57,16 @@ ActionController::Routing::Routes.draw do |map|
|
|||
map.connect "api/#{API_VERSION}/amf", :controller =>'amf', :action =>'talk'
|
||||
map.connect "api/#{API_VERSION}/swf/trackpoints", :controller =>'swf', :action =>'trackpoints'
|
||||
|
||||
# Data browsing
|
||||
map.connect '/browse', :controller => 'browse', :action => 'index'
|
||||
map.connect '/browse/start', :controller => 'browse', :action => 'start'
|
||||
map.connect '/browse/way/:id', :controller => 'browse', :action => 'way', :id => /\d+/
|
||||
map.connect '/browse/way/:id/history', :controller => 'browse', :action => 'way_history', :id => /\d+/
|
||||
map.connect '/browse/node/:id', :controller => 'browse', :action => 'node', :id => /\d+/
|
||||
map.connect '/browse/node/:id/history', :controller => 'browse', :action => 'node_history', :id => /\d+/
|
||||
map.connect '/browse/relation/:id', :controller => 'browse', :action => 'relation', :id => /\d+/
|
||||
map.connect '/browse/relation/:id/history', :controller => 'browse', :action => 'relation_history', :id => /\d+/
|
||||
|
||||
# web site
|
||||
|
||||
map.connect '/', :controller => 'site', :action => 'index'
|
||||
|
|
|
@ -7,9 +7,11 @@ OpenLayers._getScriptLocation = function () {
|
|||
return "/openlayers/";
|
||||
}
|
||||
|
||||
function createMap(divName) {
|
||||
function createMap(divName, options) {
|
||||
options = options || {};
|
||||
|
||||
map = new OpenLayers.Map(divName, {
|
||||
controls: [
|
||||
controls: options.controls || [
|
||||
new OpenLayers.Control.ArgParser(),
|
||||
new OpenLayers.Control.Attribution(),
|
||||
new OpenLayers.Control.LayerSwitcher(),
|
||||
|
@ -18,7 +20,7 @@ function createMap(divName) {
|
|||
new OpenLayers.Control.ScaleLine()
|
||||
],
|
||||
units: "m",
|
||||
maxResolution: 156543,
|
||||
maxResolution: 156543.0339,
|
||||
numZoomLevels: 20
|
||||
});
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ OpenLayers.Layer.OSM = OpenLayers.Class(OpenLayers.Layer.TMS, {
|
|||
initialize: function(name, url, options) {
|
||||
options = OpenLayers.Util.extend({
|
||||
attribution: "Data by <a href='http://openstreetmap.org/'>OpenStreetMap</a>",
|
||||
maxExtent: new OpenLayers.Bounds(-20037508,-20037508,20037508,20037508),
|
||||
maxResolution: 156543,
|
||||
maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
|
||||
maxResolution: 156543.0339,
|
||||
units: "m",
|
||||
projection: "EPSG:900913",
|
||||
transitionEffect: "resize"
|
||||
|
|
|
@ -454,6 +454,18 @@ hides rule from IE5-Mac \*/
|
|||
background: #bbb;
|
||||
}
|
||||
|
||||
.browse_heading {
|
||||
margin: 0px;
|
||||
padding: 3px 6px 3px 6px;
|
||||
border: 1px solid #ccc;
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
.browse_details {
|
||||
margin: 0px;
|
||||
padding: 0px 6px 0px 6px;
|
||||
}
|
||||
|
||||
.search_results_heading {
|
||||
margin: 0px;
|
||||
padding: 3px 6px 3px 6px;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue