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