change layout: now a link, no longer a tab
[rails.git] / app / views / browse / start.rjs
1 page.replace_html :sidebar_title, 'Browse'
2 page.replace_html :sidebar_content, :partial => 'start'
3 page << <<EOJ
4     
5     var gml, sf, objList, currentFeature, featureList;
6     OpenLayers.Feature.Vector.style['default'].strokeWidth = 3;
7     OpenLayers.Feature.Vector.style['default'].cursor = "pointer";
8     
9     function start() {
10         openSidebar({ onclose: stopBrowse });
11         var vectors = new OpenLayers.Layer.Vector();
12     
13         box = new OpenLayers.Control.DrawFeature(vectors, OpenLayers.Handler.RegularPolygon, { 
14           handlerOptions: {
15             sides: 4,
16             snapAngle: 90,
17             irregular: true,
18             persist: true,
19             callbacks: { done: endDrag }
20           }
21         });
22         map.addControl(box);
23         map.events.register("moveend", map, validateLinks);
24         map.events.triggerEvent("moveend");
25         if (map.getZoom() >= 16) {
26             useMap();
27         } else {
28             $("status").innerHTML = "Zoom in or Select an area of the map to view.";
29         }    
30     }
31     
32     function stopBrowse() {
33         if (gml) {
34             gml.destroy();
35             gml = null; 
36         } 
37         if (sf) {   
38             sf.destroy();  
39             sf = null;
40         } 
41         if (currentFeature) {
42             currentFeature.destroy(); 
43             currentFeature = null; 
44         } 
45         map.events.unregister("moveend", map, validateLinks);
46     }
47     
48     function startDrag() {
49       $("drag_box").innerHTML='Drag a box on the map to select an area';
50        box.activate(); 
51        return false;
52     };
53     $("drag_box").onclick = startDrag;
54     
55     function useMap() {
56         var bounds = map.getExtent();
57         getData(bounds);
58         return false;
59     }
60     $("use_map").onclick = useMap;
61     
62     function endDrag(bbox) {
63         var bounds = bbox.getBounds();
64         box.deactivate();
65         getData(bounds);
66         $("drag_box").innerHTML = "Manually select a different area";
67     }
68     
69     function displayFeatureWarning() {
70         $("status").innerHTML = "";
71         var div = document.createElement("div");
72         var p = document.createElement("p");
73         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.")); 
74         div.appendChild(p);
75         var input = document.createElement("input");
76         input.type = "submit";
77         input.value = "Load Data";
78         input.onclick = loadFeatureList;
79         div.appendChild(input); 
80         $("object").innerHTML="";
81         $("object").appendChild(div);
82     }
83     
84     function loadFeatureList() {
85         gml.addFeatures(featureList);
86         gml.events.triggerEvent("loadend");
87         return false;
88     }    
89
90     function customDataLoader(request) { 
91         var doc = request.responseXML;
92         
93         if (!doc || !doc.documentElement) {
94             doc = request.responseText;
95         }
96         
97         var options = {};
98         
99         OpenLayers.Util.extend(options, this.formatOptions);
100         if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
101             options.externalProjection = this.projection;
102             options.internalProjection = this.map.getProjectionObject();
103         }    
104         
105         var gml = this.format ? new this.format(options) : new OpenLayers.Format.GML(options);
106         var features = gml.read(doc);
107         if (!this.maxFeatures || features.length <= this.maxFeatures) {
108             this.addFeatures(features);
109             this.events.triggerEvent("loadend");
110             featureList = []; 
111         } else {
112             featureList = features;
113             displayFeatureWarning();
114         }
115     }
116
117     function getData(bounds) {
118         
119         bounds.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
120         var size = bounds.getWidth() * bounds.getHeight(); 
121         if (size > 0.25) {
122             $("status").innerHTML = "Unable to load: Bounding box size of " + size + " is too large. (Must be smaller than 0.25)<br />"; 
123             return;
124         }
125
126         var url = "/api/0.5/map?bbox="+bounds.toBBOX();
127         
128         loadGML(url);
129     }
130     function loadGML(url) {
131         $("status").innerHTML = "Loading...";
132         if (!gml) {
133             var style = new OpenLayers.Style();
134             style.addRules([new OpenLayers.Rule( 
135               {'symbolizer': 
136                 {"Polygon": {'fillColor': '#ff0000', 'strokeColor': '#ff0000'},
137                  "Line": {'fillColor': '#ffff00', 'strokeColor': '#000000', strokeOpacity: '0.4'},
138                  "Point": {'fillColor': '#00ff00', 'strokeColor': '#00ff00'}}
139               }
140             )]);
141             gml = new OpenLayers.Layer.GML("Data",url, 
142                     {format: OpenLayers.Format.OSM, formatOptions: {checkTags: true},
143                      maxFeatures: 100, requestSuccess: customDataLoader,
144                      styleMap: new OpenLayers.StyleMap({'default': style, 'select': {'strokeColor': '#0000ff', strokeWidth: 8}})
145                     }
146             );
147             gml.events.register("loadend", gml, dataLoaded );
148             map.addLayer(gml);
149             
150             sf = new OpenLayers.Control.SelectFeature(gml, {'onSelect': onFeatureSelect});
151             sf.handler.stopDown = false;
152             sf.handler.stopUp = false;
153             map.addControl(sf);
154             sf.activate();
155              
156         } else {
157             gml.setUrl(url);
158         }
159
160         currentFeature = null;
161     }
162     function dataLoaded() { 
163         $("status").innerHTML = "Loaded " + this.features.length + " features. (<a href='"+ this.url+"'>API</a>)";
164         
165         objList = document.createElement("ul");
166         for (var i = 0; i < this.features.length; i++) {
167             var feature = this.features[i]; 
168             
169             // Type, for linking
170             var type ="way";
171             if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
172                 type = "node";
173             }   
174             var nice_name = type.substr(0,1).toUpperCase() + type.substr(1,type.length); 
175             var li = document.createElement("li");
176             li.appendChild(document.createTextNode(nice_name + " "));
177             
178             // Link, for viewing in the tab
179             var link = document.createElement("a");
180             link.href =  "/browse/" + type + "/" + feature.osm_id; 
181             var name = feature.attributes.name || feature.osm_id;
182             link.appendChild(document.createTextNode(name));
183             link.feature = feature;
184             link.onclick = OpenLayers.Function.bind(viewFeatureLink, link);   
185             li.appendChild(link);
186
187             objList.appendChild(li);
188         }
189         $("object").innerHTML = "";
190         $("object").appendChild(objList); 
191     }
192     
193     function viewFeatureLink() {
194         var layer = this.feature.layer;
195         for (var i = 0; i < layer.selectedFeatures.length; i++) {
196             var f = layer.selectedFeatures[i]; 
197             layer.drawFeature(f, layer.styleMap.createSymbolizer(f, "default"));
198         }
199         onFeatureSelect(this.feature);
200         map.setCenter(this.feature.geometry.getBounds().getCenterLonLat()); 
201         return false;
202     }
203     
204     function loadObjList() {
205         $("object").innerHTML="";
206         $("object").appendChild(objList);
207         return false;
208     }
209       
210     function onFeatureSelect(feature) {
211         // Unselect previously selected feature
212         if (currentFeature) {
213           currentFeature.layer.drawFeature(
214             currentFeature, currentFeature.layer.styleMap.createSymbolizer(currentFeature, "default")
215           );
216         }
217
218         // Redraw in selected style
219         feature.layer.drawFeature(
220           feature, feature.layer.styleMap.createSymbolizer(feature, "select")
221         );
222
223         // If the current object is the list, don't innerHTML="", since that could clar it.   
224         if ($("object").firstChild == objList) { 
225             $("object").removeChild(objList);
226         } else { 
227             $("object").innerHTML = "";
228         }   
229         
230         // Create a link back to the object list
231         var div = document.createElement("div");
232         var link = document.createElement("a");
233         link.href="#";
234         link.onclick = loadObjList;
235         link.appendChild(document.createTextNode("Back to Object List"));
236         div.appendChild(link)
237         $("object").appendChild(div);    
238         
239         // Now the list of attributes
240         var ul = document.createElement("ul");
241         var type = "way";
242         if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
243             type = "node";
244         }    
245         var li = document.createElement("li");
246         var link = document.createElement("a");   
247         link.href =  "/browse/"+type+"/"+feature.osm_id;
248         link.appendChild(document.createTextNode(feature.osm_id));
249         li.appendChild(link);
250         ul.appendChild(li);
251         for (var key in feature.attributes) {
252             var li = document.createElement("li");
253             var b = document.createElement("b");
254             b.appendChild(document.createTextNode(key));
255             li.appendChild(b);
256             li.appendChild(document.createTextNode(": " + feature.attributes[key]));
257             ul.appendChild(li);
258         }
259         $("object").appendChild(ul);
260         
261         // Stash the currently drawn feature
262         currentFeature = feature; 
263     }   
264     
265     function validateLinks() {
266         var bounds = this.getExtent();
267         bounds = bounds.clone().transform(map.getProjectionObject(), epsg4326);
268
269         if (bounds.getWidth() * bounds.getHeight() > 0.25) {
270           $("use_map").style.display = "none";
271         } else {
272           $("use_map").style.display = "inline";
273         }  
274     }
275     start();
276 EOJ