move data into a layer in the layerswitcher
[rails.git] / app / views / browse / start.rjs
1 page.replace_html :sidebar_title, 'Data'
2 page.replace_html :sidebar_content, :partial => 'start'
3 page << <<EOJ
4     
5     var gml, sf, objList, currentFeature, featureList, mode = "auto", currentBounds, browsing;
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, showData);
24         map.events.triggerEvent("moveend");
25         map.dataLayer.stopBrowse = stopBrowse;
26         browsing = true;
27     }
28
29     function showData() {
30         if (mode == "manual") { return; }
31         if (map.getZoom() >= 15) {
32             useMap();
33         } else {
34             $("status").innerHTML = "Zoom in or Select an area of the map to view.";
35         }    
36     }
37     
38     function stopBrowse() {
39         if (browsing) {
40             browsing = false; 
41             map.dataLayer.stopBrowse = null;
42             if (gml) {
43                 gml.destroy();
44                 gml = null; 
45             } 
46             if (sf) {   
47                 sf.destroy();  
48                 sf = null;
49             } 
50             if (currentFeature) {
51                 currentFeature.destroy(); 
52                 currentFeature = null; 
53             }
54             map.dataLayer.setVisibility(false);
55             map.events.unregister("moveend", map, showData);
56         }    
57     }
58     
59     function startDrag() {
60       $("drag_box").innerHTML='Drag a box on the map to select an area';
61        box.activate(); 
62        return false;
63     };
64     $("drag_box").onclick = startDrag;
65     
66     function useMap() {
67         var bounds = map.getExtent();
68         var projected = bounds.clone().transform(map.getProjectionObject(), epsg4326);
69         if (!currentBounds || !currentBounds.containsBounds(projected)) {
70             var center = bounds.getCenterLonLat();
71             var tileWidth = bounds.getWidth() * 1.2;
72             var tileHeight = bounds.getHeight() * 1.2;
73             var tileBounds =
74                 new OpenLayers.Bounds(center.lon - (tileWidth / 2),
75                                       center.lat - (tileHeight / 2),
76                                       center.lon + (tileWidth / 2),
77                                       center.lat + (tileHeight / 2));
78
79             currentBounds = tileBounds;
80             getData(tileBounds);
81             mode = "auto";
82             $("use_map").style.display="none";
83         }
84         return false;
85     }
86     $("use_map").onclick = useMap;
87     
88     function endDrag(bbox) {
89         var bounds = bbox.getBounds();
90         box.deactivate();
91         currentBounds = bounds;
92         getData(bounds);
93         $("drag_box").innerHTML = "Manually select a different area";
94         mode = "manual";  
95         $("use_map").style.display="inline";
96     }
97     
98     function displayFeatureWarning() {
99         $("status").innerHTML = "";
100         var div = document.createElement("div");
101         var p = document.createElement("p");
102         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.")); 
103         div.appendChild(p);
104         var input = document.createElement("input");
105         input.type = "submit";
106         input.value = "Load Data";
107         input.onclick = loadFeatureList;
108         div.appendChild(input); 
109         $("object").innerHTML="";
110         $("object").appendChild(div);
111     }
112     
113     function loadFeatureList() {
114         gml.addFeatures(featureList);
115         gml.events.triggerEvent("loadend");
116         return false;
117     }    
118
119     function customDataLoader(request) { 
120         if (!browsing) { return; } 
121         var doc = request.responseXML;
122         
123         if (!doc || !doc.documentElement) {
124             doc = request.responseText;
125         }
126         
127         var options = {};
128         
129         OpenLayers.Util.extend(options, this.formatOptions);
130         if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
131             options.externalProjection = this.projection;
132             options.internalProjection = this.map.getProjectionObject();
133         }    
134         
135         var gml = this.format ? new this.format(options) : new OpenLayers.Format.GML(options);
136         var features = gml.read(doc);
137         if (!this.maxFeatures || features.length <= this.maxFeatures) {
138             this.addFeatures(features);
139             this.events.triggerEvent("loadend");
140             featureList = []; 
141         } else {
142             featureList = features;
143             displayFeatureWarning();
144         }
145     }
146
147     function getData(bounds) {
148         
149         bounds.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
150         var size = bounds.getWidth() * bounds.getHeight(); 
151         if (size > 0.25) {
152             $("status").innerHTML = "Unable to load: Bounding box size of " + size + " is too large. (Must be smaller than 0.25)<br />"; 
153             return;
154         }
155
156         var url = "/api/0.5/map?bbox="+bounds.toBBOX();
157         
158         loadGML(url);
159     }
160     function loadGML(url) {
161         $("status").innerHTML = "Loading...";
162         $("object").innerHTML = "";
163         if (!gml) {
164             var style = new OpenLayers.Style();
165             style.addRules([new OpenLayers.Rule( 
166               {'symbolizer': 
167                 {"Polygon": {'fillColor': '#ff0000', 'strokeColor': '#ff0000'},
168                  "Line": {'fillColor': '#ffff00', 'strokeColor': '#000000', strokeOpacity: '0.4'},
169                  "Point": {'fillColor': '#00ff00', 'strokeColor': '#00ff00'}}
170               }
171             )]);
172             gml = new OpenLayers.Layer.GML("Data",url, 
173                     {format: OpenLayers.Format.OSM, formatOptions: {checkTags: true},
174                      maxFeatures: 100, requestSuccess: customDataLoader,
175                      displayInLayerSwitcher: false,
176                      styleMap: new OpenLayers.StyleMap({'default': style, 'select': {'strokeColor': '#0000ff', strokeWidth: 8}})
177                     }
178             );
179             gml.events.register("loadend", gml, dataLoaded );
180             map.addLayer(gml);
181             
182             sf = new OpenLayers.Control.SelectFeature(gml, {'onSelect': onFeatureSelect});
183             sf.handler.stopDown = false;
184             sf.handler.stopUp = false;
185             map.addControl(sf);
186             sf.activate();
187              
188         } else {
189             gml.setUrl(url);
190         }
191
192         currentFeature = null;
193     }
194     function dataLoaded() {
195         if (!browsing) { return; } 
196         $("status").innerHTML = "Loaded " + this.features.length + " features. (<a href='"+ this.url+"'>API</a>)";
197         
198         objList = document.createElement("ul");
199         for (var i = 0; i < this.features.length; i++) {
200             var feature = this.features[i]; 
201             
202             // Type, for linking
203             var type ="way";
204             if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
205                 type = "node";
206             }   
207             var nice_name = type.substr(0,1).toUpperCase() + type.substr(1,type.length); 
208             var li = document.createElement("li");
209             li.appendChild(document.createTextNode(nice_name + " "));
210             
211             // Link, for viewing in the tab
212             var link = document.createElement("a");
213             link.href =  "/browse/" + type + "/" + feature.osm_id; 
214             var name = feature.attributes.name || feature.osm_id;
215             link.appendChild(document.createTextNode(name));
216             link.feature = feature;
217             link.onclick = OpenLayers.Function.bind(viewFeatureLink, link);   
218             li.appendChild(link);
219
220             objList.appendChild(li);
221         }
222         $("object").innerHTML = "";
223         $("object").appendChild(objList); 
224     }
225     
226     function viewFeatureLink() {
227         var layer = this.feature.layer;
228         for (var i = 0; i < layer.selectedFeatures.length; i++) {
229             var f = layer.selectedFeatures[i]; 
230             layer.drawFeature(f, layer.styleMap.createSymbolizer(f, "default"));
231         }
232         onFeatureSelect(this.feature);
233         if (mode != "auto") {
234             map.setCenter(this.feature.geometry.getBounds().getCenterLonLat()); 
235         }
236         return false;
237     }
238     
239     function loadObjList() {
240         $("object").innerHTML="";
241         $("object").appendChild(objList);
242         return false;
243     }
244       
245     function onFeatureSelect(feature) {
246         // Unselect previously selected feature
247         if (currentFeature) {
248           currentFeature.layer.drawFeature(
249             currentFeature, currentFeature.layer.styleMap.createSymbolizer(currentFeature, "default")
250           );
251         }
252
253         // Redraw in selected style
254         feature.layer.drawFeature(
255           feature, feature.layer.styleMap.createSymbolizer(feature, "select")
256         );
257
258         // If the current object is the list, don't innerHTML="", since that could clar it.   
259         if ($("object").firstChild == objList) { 
260             $("object").removeChild(objList);
261         } else { 
262             $("object").innerHTML = "";
263         }   
264         
265         // Create a link back to the object list
266         var div = document.createElement("div");
267         var link = document.createElement("a");
268         link.href="#";
269         link.onclick = loadObjList;
270         link.appendChild(document.createTextNode("Back to Object List"));
271         div.appendChild(link)
272         $("object").appendChild(div);    
273         
274         // Now the list of attributes
275         var ul = document.createElement("ul");
276         var type = "way";
277         if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
278             type = "node";
279         }    
280         var li = document.createElement("li");
281         var link = document.createElement("a");   
282         link.href =  "/browse/"+type+"/"+feature.osm_id;
283         link.appendChild(document.createTextNode(feature.osm_id));
284         li.appendChild(link);
285         ul.appendChild(li);
286         for (var key in feature.attributes) {
287             var li = document.createElement("li");
288             var b = document.createElement("b");
289             b.appendChild(document.createTextNode(key));
290             li.appendChild(b);
291             li.appendChild(document.createTextNode(": " + feature.attributes[key]));
292             ul.appendChild(li);
293         }
294         
295         var li = document.createElement("li");
296         var link = document.createElement("a");   
297         link.href =  "/browse/"+type+"/"+feature.osm_id+"/history";
298         link.appendChild(document.createTextNode("History"));
299         li.appendChild(link);
300         ul.appendChild(li);
301         link.onclick = OpenLayers.Function.bind(loadHistory, {type: type, feature: feature, link: link});
302         $("object").appendChild(ul);
303         
304         
305         // Stash the currently drawn feature
306         currentFeature = feature; 
307     }   
308     function loadHistory() {
309         this.link.href = "";
310         this.link.innerHTML = "Wait...";
311         new Ajax.Request("/api/0.5/"+this.type+"/"+this.feature.osm_id+"/history", {onComplete: OpenLayers.Function.bind(displayHistory, this)});
312         return false;
313     }
314     function displayHistory(request) {
315         if (currentFeature.osm_id != this.feature.osm_id || $("object").firstChild == objList)  { 
316             return false;
317         } 
318         this.link.parentNode.parentNode.removeChild(this.link.parentNode);
319         var doc = request.responseXML;
320         var div = document.createElement("div");
321         var h3 = document.createElement("h3"); 
322         h3.appendChild(document.createTextNode("History"));
323         div.appendChild(h3);
324         var nodes = doc.getElementsByTagName(this.type);
325         var history = document.createElement("ul");  
326         for (var i = nodes.length - 1; i >= 0; i--) {
327             var user = nodes[i].getAttribute("user") || "private user";
328             var timestamp = nodes[i].getAttribute("timestamp");
329             var item = document.createElement("li");
330             item.appendChild(document.createTextNode("Edited by " + user + " at " + timestamp));
331             history.appendChild(item);
332         }
333         div.appendChild(history);
334         var link = document.createElement("a");
335         link.appendChild(document.createTextNode("History"));
336         link.href = "/browse/"+this.type+"/"+this.feature.osm_id+"/history";
337         div.appendChild(link);
338         $("object").appendChild(div); 
339     }
340     
341     start();
342 EOJ