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