Merge branch 'master' into openid
[rails.git] / app / views / browse / start.rjs
1 page.replace_html :sidebar_title, t('browse.start_rjs.data_frame_title')
2 page.replace_html :sidebar_content, :partial => 'start'
3 page << <<EOJ
4   var browseBoxControl;
5   var browseMode = "auto";
6   var browseBounds;
7   var browseFeatureList;
8   var browseActiveFeature;
9   var browseDataLayer;
10   var browseSelectControl;
11   var browseObjectList;
12
13   OpenLayers.Feature.Vector.style['default'].strokeWidth = 3;
14   OpenLayers.Feature.Vector.style['default'].cursor = "pointer";
15     
16   function startBrowse() {
17     map.dataLayer.active = true;
18
19     openSidebar({ onclose: stopBrowse });
20
21     var vectors = new OpenLayers.Layer.Vector();
22     
23     browseBoxControl = new OpenLayers.Control.DrawFeature(vectors, OpenLayers.Handler.RegularPolygon, { 
24       handlerOptions: {
25         sides: 4,
26         snapAngle: 90,
27         irregular: true,
28         persist: true,
29         callbacks: { done: endDrag }
30       }
31     });
32     map.addControl(browseBoxControl);
33
34     map.events.register("moveend", map, showData);
35     map.events.triggerEvent("moveend");
36   }
37
38   function showData() {
39     if (browseMode == "auto") {
40       if (map.getZoom() >= 15) {
41           useMap();
42       } else {
43           setStatus("#{I18n.t('browse.start_rjs.zoom_or_select')}");
44       }    
45     }
46   }
47
48   function stopBrowse() {
49     if (map.dataLayer.active) {
50       map.dataLayer.active = false;
51
52       if (browseSelectControl) {   
53         browseSelectControl.destroy();  
54         browseSelectControl = null;
55       } 
56
57       if (browseBoxControl) {
58         browseBoxControl.destroy();
59         browseBoxControl = null;
60       }         
61
62       if (browseActiveFeature) {
63         browseActiveFeature.destroy(); 
64         browseActiveFeature = null; 
65       }
66
67       if (browseDataLayer) {
68         browseDataLayer.destroy();
69         browseDataLayer = null; 
70       } 
71
72       map.dataLayer.setVisibility(false);
73       map.events.unregister("moveend", map, showData);
74     }    
75   }
76
77   function startDrag() {
78     $("browse_select_box").innerHTML="#{I18n.t('browse.start_rjs.drag_a_box')}";
79
80     browseBoxControl.activate();
81
82     return false;
83   };
84
85   $("browse_select_box").onclick = startDrag;
86
87   function useMap() {
88     var bounds = map.getExtent();
89     var projected = bounds.clone().transform(map.getProjectionObject(), epsg4326);
90
91     if (!browseBounds || !browseBounds.containsBounds(projected)) {
92       var center = bounds.getCenterLonLat();
93       var tileWidth = bounds.getWidth() * 1.2;
94       var tileHeight = bounds.getHeight() * 1.2;
95       var tileBounds = new OpenLayers.Bounds(center.lon - (tileWidth / 2),
96                                              center.lat - (tileHeight / 2),
97                                              center.lon + (tileWidth / 2),
98                                              center.lat + (tileHeight / 2));
99
100       browseBounds = tileBounds;
101       getData(tileBounds);
102
103       browseMode = "auto";
104
105       $("browse_select_view").style.display = "none";
106     }
107
108     return false;
109   }
110
111   $("browse_select_view").onclick = useMap;
112
113   function endDrag(bbox) {
114     var bounds = bbox.getBounds();
115     var projected = bounds.clone().transform(map.getProjectionObject(), epsg4326);
116
117     browseBoxControl.deactivate();
118     browseBounds = projected;
119     getData(bounds);
120
121     browseMode = "manual";  
122
123     $("browse_select_box").innerHTML = "#{I18n.t('browse.start_rjs.manually_select')}";
124     $("browse_select_view").style.display = "inline";
125   }
126
127   function displayFeatureWarning() {
128     clearStatus();
129
130     var div = document.createElement("div");
131
132     var p = document.createElement("p");
133     p.appendChild(document.createTextNode(i18n("#{I18n.t('browse.start_rjs.loaded_an_area_with_num_features')}", { num_features: browseFeatureList.length })));
134     div.appendChild(p);
135
136     var input = document.createElement("input");
137     input.type = "submit";
138     input.value = "#{I18n.t('browse.start_rjs.load_data')}";
139     input.onclick = loadFeatureList;
140     div.appendChild(input); 
141
142     $("browse_content").innerHTML = "";
143     $("browse_content").appendChild(div);
144   }
145
146   function loadFeatureList() {
147     browseDataLayer.addFeatures(browseFeatureList);
148     browseDataLayer.events.triggerEvent("loadend");
149
150     browseFeatureList = []; 
151
152     return false;
153   }    
154
155   function customDataLoader(request) {
156     if (this.map.dataLayer.active) {
157       var doc = request.responseXML;
158
159       if (!doc || !doc.documentElement) {
160         doc = request.responseText;
161       }
162
163       var options = {};
164
165       OpenLayers.Util.extend(options, this.formatOptions);
166
167       if (this.map && !this.projection.equals(this.map.getProjectionObject())) {
168         options.externalProjection = this.projection;
169         options.internalProjection = this.map.getProjectionObject();
170       }    
171
172       var gml = this.format ? new this.format(options) : new OpenLayers.Format.GML(options);
173
174       browseFeatureList = gml.read(doc);
175
176       if (!this.maxFeatures || browseFeatureList.length <= this.maxFeatures) {
177         loadFeatureList();
178       } else {
179         displayFeatureWarning();
180       }
181     }
182   }
183
184   function getData(bounds) {
185     var projected = bounds.clone().transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
186     var size = projected.getWidth() * projected.getHeight();
187
188     if (size > #{MAX_REQUEST_AREA}) {
189       setStatus(i18n("#{I18n.t('browse.start_rjs.unable_to_load_size', :max_bbox_size => MAX_REQUEST_AREA)}", { bbox_size: size }));
190     } else {
191       loadGML("/api/#{API_VERSION}/map?bbox=" + projected.toBBOX());
192     }
193   }
194
195   function loadGML(url) {
196     setStatus("#{I18n.t('browse.start_rjs.loading')}");
197     $("browse_content").innerHTML = "";
198
199     if (!browseDataLayer) {
200       var style = new OpenLayers.Style();
201
202       style.addRules([new OpenLayers.Rule({
203         symbolizer: {
204           Polygon: { fillColor: '#ff0000', strokeColor: '#ff0000' },
205           Line: { fillColor: '#ffff00', strokeColor: '#000000', strokeOpacity: '0.4' },
206           Point: { fillColor: '#00ff00', strokeColor: '#00ff00' }
207         }
208       })]);
209
210       browseDataLayer = new OpenLayers.Layer.GML("Data", url, {
211         format: OpenLayers.Format.OSM,
212         formatOptions: {
213           checkTags: true, 
214           interestingTagsExclude: ['source','source_ref','source:ref','history','attribution','created_by','tiger:county','tiger:tlid','tiger:upload_uuid']
215         },
216         maxFeatures: 100,
217         requestSuccess: customDataLoader,
218         displayInLayerSwitcher: false,
219         styleMap: new OpenLayers.StyleMap({
220           'default': style,
221           'select': { strokeColor: '#0000ff', strokeWidth: 8 }
222         })
223       });
224       browseDataLayer.events.register("loadend", browseDataLayer, dataLoaded );
225       map.addLayer(browseDataLayer);
226             
227       browseSelectControl = new OpenLayers.Control.SelectFeature(browseDataLayer, { onSelect: onFeatureSelect });
228       browseSelectControl.handlers.feature.stopDown = false;
229       browseSelectControl.handlers.feature.stopUp = false;
230       map.addControl(browseSelectControl);
231       browseSelectControl.activate();
232     } else {
233       browseDataLayer.setUrl(url);
234     }
235
236     browseActiveFeature = null;
237   }
238
239   function dataLoaded() {
240     if (this.map.dataLayer.active) {
241       clearStatus();
242
243       browseObjectList = document.createElement("div")
244
245       var heading = document.createElement("p");
246       heading.className = "browse_heading";
247       heading.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.object_list.heading')}"));
248       browseObjectList.appendChild(heading);
249
250       var list = document.createElement("ul");
251
252       for (var i = 0; i < this.features.length; i++) {
253         var feature = this.features[i]; 
254             
255         // Type, for linking
256         var type = featureType(feature);
257         var typeName = featureTypeName(feature);
258         var li = document.createElement("li");
259         li.appendChild(document.createTextNode(typeName + " "));
260             
261         // Link, for viewing in the tab
262         var link = document.createElement("a");
263         link.href =  "/browse/" + type + "/" + feature.osm_id; 
264         var name = featureName(feature);
265         link.appendChild(document.createTextNode(name));
266         link.feature = feature;
267         link.onclick = OpenLayers.Function.bind(viewFeatureLink, link);   
268         li.appendChild(link);
269
270         list.appendChild(li);
271       }
272
273       browseObjectList.appendChild(list)
274
275       var link = document.createElement("a");
276       link.href = this.url;
277       link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.object_list.api')}"));
278       browseObjectList.appendChild(link);
279
280       $("browse_content").innerHTML = "";
281       $("browse_content").appendChild(browseObjectList); 
282     }
283   }
284     
285   function viewFeatureLink() {
286     var layer = this.feature.layer;
287
288     for (var i = 0; i < layer.selectedFeatures.length; i++) {
289       var f = layer.selectedFeatures[i]; 
290       layer.drawFeature(f, layer.styleMap.createSymbolizer(f, "default"));
291     }
292
293     onFeatureSelect(this.feature);
294
295     if (browseMode != "auto") {
296       map.setCenter(this.feature.geometry.getBounds().getCenterLonLat()); 
297     }
298
299     return false;
300   }
301     
302   function loadObjectList() {
303     $("browse_content").innerHTML="";
304     $("browse_content").appendChild(browseObjectList);
305
306     return false;
307   }
308       
309   function onFeatureSelect(feature) {
310     // Unselect previously selected feature
311     if (browseActiveFeature) {
312       browseActiveFeature.layer.drawFeature(
313         browseActiveFeature, 
314         browseActiveFeature.layer.styleMap.createSymbolizer(browseActiveFeature, "default")
315       );
316     }
317
318     // Redraw in selected style
319     feature.layer.drawFeature(
320       feature, feature.layer.styleMap.createSymbolizer(feature, "select")
321     );
322
323     // If the current object is the list, don't innerHTML="", since that could clear it.
324     if ($("browse_content").firstChild == browseObjectList) { 
325       $("browse_content").removeChild(browseObjectList);
326     } else { 
327       $("browse_content").innerHTML = "";
328     }   
329         
330     // Create a link back to the object list
331     var div = document.createElement("div");
332     div.style.textAlign = "center";
333     div.style.marginBottom = "20px";
334     $("browse_content").appendChild(div);
335     var link = document.createElement("a");
336     link.href = "#";
337     link.onclick = loadObjectList;
338     link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.object_list.back')}"));
339     div.appendChild(link);
340
341     var table = document.createElement("table");
342     table.width = "100%";
343     table.className = "browse_heading";
344     $("browse_content").appendChild(table);
345
346     var tr = document.createElement("tr");
347     table.appendChild(tr);
348
349     var heading = document.createElement("td");
350     heading.appendChild(document.createTextNode(featureNameSelect(feature)));
351     tr.appendChild(heading);
352
353     var td = document.createElement("td");
354     td.align = "right";
355     tr.appendChild(td);
356
357     var type = featureType(feature);
358     var link = document.createElement("a");   
359     link.href = "/browse/" + type + "/" + feature.osm_id;
360     link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.object_list.details')}"));
361     td.appendChild(link);
362
363     var div = document.createElement("div");
364     div.className = "browse_details";
365
366     $("browse_content").appendChild(div);
367
368     // Now the list of attributes
369     var ul = document.createElement("ul");
370     for (var key in feature.attributes) {
371       var li = document.createElement("li");
372       var b = document.createElement("b");
373       b.appendChild(document.createTextNode(key));
374       li.appendChild(b);
375       li.appendChild(document.createTextNode(": " + feature.attributes[key]));
376       ul.appendChild(li);
377     }
378         
379     div.appendChild(ul);
380         
381     var link = document.createElement("a");   
382     link.href =  "/browse/" + type + "/" + feature.osm_id + "/history";
383     link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.show_history')}"));
384     link.onclick = OpenLayers.Function.bind(loadHistory, {
385       type: type, feature: feature, link: link
386     });
387         
388     div.appendChild(link);
389
390     // Stash the currently drawn feature
391     browseActiveFeature = feature; 
392   }   
393
394   function loadHistory() {
395     this.link.href = "";
396     this.link.innerHTML = "#{I18n.t('browse.start_rjs.wait')}";
397
398     new Ajax.Request("/api/#{API_VERSION}/" + this.type + "/" + this.feature.osm_id + "/history", {
399       onComplete: OpenLayers.Function.bind(displayHistory, this)
400     });
401
402     return false;
403   }
404
405   function displayHistory(request) {
406     if (browseActiveFeature.osm_id != this.feature.osm_id || $("browse_content").firstChild == browseObjectList)  { 
407         return false;
408     } 
409
410     this.link.parentNode.removeChild(this.link);
411
412     var doc = request.responseXML;
413
414     var table = document.createElement("table");
415     table.width = "100%";
416     table.className = "browse_heading";
417     $("browse_content").appendChild(table);
418
419     var tr = document.createElement("tr");
420     table.appendChild(tr);
421
422     var heading = document.createElement("td");
423     heading.appendChild(document.createTextNode(i18n("#{I18n.t('browse.start_rjs.history_for_feature')}", { feature: featureNameHistory(this.feature) })));
424     tr.appendChild(heading);
425
426     var td = document.createElement("td");
427     td.align = "right";
428     tr.appendChild(td);
429
430     var link = document.createElement("a");   
431     link.href = "/browse/" + this.type + "/" + this.feature.osm_id + "/history";
432     link.appendChild(document.createTextNode("#{I18n.t('browse.start_rjs.details')}"));
433     td.appendChild(link);
434
435     var div = document.createElement("div");
436     div.className = "browse_details";
437
438     var nodes = doc.getElementsByTagName(this.type);
439     var history = document.createElement("ul");  
440     for (var i = nodes.length - 1; i >= 0; i--) {
441       var user = nodes[i].getAttribute("user") || "#{I18n.t('browse.start_rjs.private_user')}";
442       var timestamp = nodes[i].getAttribute("timestamp");
443       var item = document.createElement("li");
444       item.appendChild(document.createTextNode(i18n("#{I18n.t('browse.start_rjs.edited_by_user_at_timestamp')}", { user: user, timestamp: timestamp })));
445       history.appendChild(item);
446     }
447     div.appendChild(history);
448
449     $("browse_content").appendChild(div); 
450   }
451
452   function featureType(feature) {
453     if (feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
454       return "node";
455     } else {
456       return "way";
457     }
458   }
459
460   function featureTypeName(feature) {
461     if (featureType(feature) == "node") {
462       return "#{I18n.t('browse.start_rjs.object_list.type.node')}";
463     } else if (featureType(feature) == "way") {
464       return "#{I18n.t('browse.start_rjs.object_list.type.way')}";
465     }
466   }
467
468   function featureName(feature) {
469     if (feature.attributes['name:#{I18n.locale}']) {
470       return feature.attributes['name:#{I18n.locale}'];
471     } else if (feature.attributes.name) {
472       return feature.attributes.name;
473     } else {
474       return feature.osm_id;
475     }
476   }
477
478   function featureNameSelect(feature) {
479     if (feature.attributes['name:#{I18n.locale}']) {
480       return feature.attributes['name:#{I18n.locale}'];
481     } else if (feature.attributes.name) {
482       return feature.attributes.name;
483     } else if (featureType(feature) == "node") {
484       return i18n("#{I18n.t('browse.start_rjs.object_list.selected.type.node')}", { id: feature.osm_id });
485     } else if (featureType(feature) == "way") {
486       return i18n("#{I18n.t('browse.start_rjs.object_list.selected.type.way')}", { id: feature.osm_id });
487     }
488   }
489
490   function featureNameHistory(feature) {
491     if (feature.attributes['name:#{I18n.locale}']) {
492       return feature.attributes['name:#{I18n.locale}'];
493     } else if (feature.attributes.name) {
494       return feature.attributes.name;
495     } else if (featureType(feature) == "node") {
496       return i18n("#{I18n.t('browse.start_rjs.object_list.history.type.node')}", { id: feature.osm_id });
497     } else if (featureType(feature) == "way") {
498       return i18n("#{I18n.t('browse.start_rjs.object_list.history.type.way')}", { id: feature.osm_id });
499     }
500   }
501
502   function setStatus(status) {
503     $("browse_status").innerHTML = status;
504     $("browse_status").style.display = "block";
505   }
506   
507   function clearStatus() {
508     $("browse_status").innerHTML = "";
509     $("browse_status").style.display = "none";
510   }
511
512   startBrowse();
513 EOJ