add in-map node/way browser
authorChristopher Schmidt <crschmidt@crschmidt.net>
Mon, 21 Apr 2008 23:18:08 +0000 (23:18 +0000)
committerChristopher Schmidt <crschmidt@crschmidt.net>
Mon, 21 Apr 2008 23:18:08 +0000 (23:18 +0000)
app/controllers/browse_controller.rb
app/views/browse/_start.rhtml [new file with mode: 0644]
app/views/browse/start.rjs [new file with mode: 0644]
app/views/layouts/site.rhtml
config/database.yml
config/routes.rb

index 3ecec6348a35363ea9ba58a9ea2749f48bed0420..b56e4f17e7214437be98d431399fac0b4be30a72 100644 (file)
@@ -2,6 +2,8 @@ class BrowseController < ApplicationController
   before_filter :authorize_web  
   layout 'site'
 
+  def start
+  end
   def index
     @nodes = Node.find(:all, :order => "timestamp DESC", :limit=> 20)  
   end
diff --git a/app/views/browse/_start.rhtml b/app/views/browse/_start.rhtml
new file mode 100644 (file)
index 0000000..616cd7d
--- /dev/null
@@ -0,0 +1,18 @@
+<div style="padding:10px;">
+  <div class="export_bounds">
+    <span class="bounds_span" id="maxlat"></span> 
+    <br/>
+    <span class="bounds_span" style="padding:10px" id="minlon"></span> 
+    <span class="bounds_span" style="padding:10px" id="maxlon"></span> 
+    <br/>
+    <span class="bounds_span" id="minlat"></span> 
+    <p class="export_hint">
+      <a id="use_map" href="#">View Data For Current Map View</a>
+      <br />
+      <a id='drag_box' href="#">Manually select a different area</a>  
+    </p>
+  </div>
+
+<div id="status"></div>
+<div id="object"></div>
+</div>
diff --git a/app/views/browse/start.rjs b/app/views/browse/start.rjs
new file mode 100644 (file)
index 0000000..5ea2992
--- /dev/null
@@ -0,0 +1,181 @@
+page.replace_html :sidebar_title, 'Browse'
+page.replace_html :sidebar_content, :partial => 'start'
+page << <<EOJ
+ var gml, sf, obj_list, currentFeature;
+ OpenLayers.Feature.Vector.style['default'].strokeWidth = 3;
+ OpenLayers.Feature.Vector.style['default'].cursor = "pointer";
+ function start() {
+   openSidebar({ onclose: stopBrowse });
+   vectors = new OpenLayers.Layer.Vector("Vector Layer", {
+     displayInLayerSwitcher: false
+   });
+   box = new OpenLayers.Control.DrawFeature(vectors, OpenLayers.Handler.RegularPolygon, { 
+     handlerOptions: {
+       sides: 4,
+       snapAngle: 90,
+       irregular: true,
+       persist: true,
+       callbacks: { done: endDrag }
+     }
+   });
+   map.addControl(box);
+ }
+ function stopBrowse() {
+     if (gml) {
+       gml.destroy();
+       gml = null; 
+     } 
+     if (sf) {   
+         sf.destroy();  
+         sf = null;
+     }  
+ }
+ 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();
+      setBounds(bounds);
+      getData(bounds); 
+  }
+  $("use_map").onclick = useMap;
+  function dataLoaded() { 
+      $("status").innerHTML = "Loaded " + this.features.length + " features. (<a href='"+ this.url+"'>API</a>)";
+      
+      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'}}
+          }
+        )]);
+        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();
+
+    } else {
+        gml.setUrl(url);
+    }
+  }
+  function endDrag(bbox) {
+    var bounds = bbox.getBounds();
+    setBounds(bounds);
+    box.deactivate();
+    getData(bounds);
+    $("drag_box").innerHTML = "Select an area to see features";
+
+  }
+  function loadObjList() {
+      $("object").innerHTML="";
+      $("object").appendChild(obj_list);
+  }
+    
+  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 { 
+        $("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));
+
+    bounds = bounds.clone().transform(map.getProjectionObject(), epsg4326);
+
+    $("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;
+  }
+
+start();
+EOJ
index dd43e8b4df640d641e9927d5aa029e575de2a638..d9641891ca75f5e69714fbc8f4616d546fd65364 100644 (file)
@@ -54,7 +54,7 @@
         <% end %>
         <li><%= link_to 'GPS Traces', {:controller => 'trace', :action => 'list'}, {:id => 'traceanchor', :title => 'manage traces', :class => traceclass} %></li>
         <li><%= link_to 'User Diaries', {:controller => 'diary_entry', :action => 'list'}, {:id => 'diaryanchor', :title => 'view user diaries', :class => diaryclass} %></li>
-        <li><%= link_to 'Browse', {:controller => 'browse', :action => 'index'}, {:id => 'browseanchor', :title => 'browse data', :class => browseclass} %></li>
+        <li><%= link_to_remote 'Browse', {:url => {:controller => 'browse', :action => 'start'}}, {:href => url_for( {:controller => 'browse', :action => 'index'}), :id => 'browseanchor', :title => 'browse data', :class => browseclass} %></li>
       </ul>
     </div>
 
index b884f3b938fea8c5ea541e0d4af5fbbc16529dd7..19b5dd8d5227ae5c04720b61afd9a101661c9cbe 100644 (file)
@@ -12,9 +12,8 @@
 #   http://dev.mysql.com/doc/refman/5.0/en/old-client.html
 development:
   adapter: mysql
-  database: openstreetmap
-  username: openstreetmap
-  password: openstreetmap
+  database: osm
+  user: root  
   host: localhost
 
 # Warning: The database defined as 'test' will be erased and
index a93946c527bcb2d06189789ed983b6f8e155b3e9..b6ab25c13a0d3ca660b28d80df26e4fa3e64dec6 100644 (file)
@@ -55,6 +55,7 @@ ActionController::Routing::Routes.draw do |map|
   map.connect "api/#{API_VERSION}/swf/trackpoints", :controller =>'swf', :action =>'trackpoints'
   
   # Data browsing
+  map.connect '/browse/start', :controller => 'browse', :action => 'start'
   map.connect '/browse', :controller => 'browse', :action => 'index'
   map.connect '/browse/way/:id', :controller => 'browse', :action => 'way', :id => /\d+/
   map.connect '/browse/way/:id/history', :controller => 'browse', :action => 'way_history', :id => /\d+/