]> git.openstreetmap.org Git - rails.git/blobdiff - app/views/browse/start.rjs
change layout: now a link, no longer a tab
[rails.git] / app / views / browse / start.rjs
index e8bbb17205e36c853357a11c796c936ad40ec876..2c48c70ff9f1df7bafd0472fb7303b9825348bd6 100644 (file)
 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;
-     } 
-     if (currentFeature) {
-         currentFeature.destroy(); 
-         currentFeature = 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'}}
+    
+    var gml, sf, objList, currentFeature, featureList;
+    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, validateLinks);
+        map.events.triggerEvent("moveend");
+        if (map.getZoom() >= 16) {
+            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, validateLinks);
+    }
+    
+    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();
+        getData(bounds);
+        return false;
+    }
+    $("use_map").onclick = useMap;
+    
+    function endDrag(bbox) {
+        var bounds = bbox.getBounds();
+        box.deactivate();
+        getData(bounds);
+        $("drag_box").innerHTML = "Manually select a different area";
+    }
+    
+    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;
+    }    
 
-    } else {
-        gml.setUrl(url);
+    function customDataLoader(request) { 
+        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 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 { 
+    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)<br />"; 
+            return;
+        }
+
+        var url = "/api/0.5/map?bbox="+bounds.toBBOX();
+        
+        loadGML(url);
+    }
+    function loadGML(url) {
+        $("status").innerHTML = "Loading...";
+        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);
+        }
+
+        currentFeature = null;
+    }
+    function dataLoaded() { 
+        $("status").innerHTML = "Loaded " + this.features.length + " features. (<a href='"+ this.url+"'>API</a>)";
+        
+        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);
+
+            objList.appendChild(li);
+        }
         $("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));
+        $("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);
+        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")
+          );
+        }
 
-    bounds = bounds.clone().transform(map.getProjectionObject(), epsg4326);
+        // Redraw in selected style
+        feature.layer.drawFeature(
+          feature, feature.layer.styleMap.createSymbolizer(feature, "select")
+        );
 
-    $("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;
-  }
+        // 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);
+        }
+        $("object").appendChild(ul);
+        
+        // Stash the currently drawn feature
+        currentFeature = feature; 
+    }   
+    
+    function validateLinks() {
+        var bounds = this.getExtent();
+        bounds = bounds.clone().transform(map.getProjectionObject(), epsg4326);
 
-start();
+        if (bounds.getWidth() * bounds.getHeight() > 0.25) {
+          $("use_map").style.display = "none";
+        } else {
+          $("use_map").style.display = "inline";
+        }  
+    }
+    start();
 EOJ