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