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