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