5bf5246d67628e670acc891bd178f82630b80ac2
[rails.git] / app / assets / javascripts / index / browse.js
1 //= require templates/browse/feature
2 //= require templates/browse/feature_list
3 //= require templates/browse/feature_history
4
5 $(document).ready(function () {
6   $("#show_data").click(function (e) {
7     $.ajax({ url: $(this).attr('href'), success: function (sidebarHtml) {
8       startBrowse(sidebarHtml);
9     }});
10     e.preventDefault();
11   });
12
13   function startBrowse(sidebarHtml) {
14     var browseMode = "auto";
15     var browseBounds;
16     var layersById;
17     var selectedLayer;
18     var browseObjectList;
19     var areasHidden = false;
20
21     var dataLayer = new L.OSM(null, {
22       styles: {
23         way: {
24           weight: 3,
25           color: "#000000",
26           opacity: 0.4
27         },
28         area: {
29           weight: 3,
30           color: "#ff0000"
31         },
32         node: {
33           color: "#00ff00"
34         }
35       }
36     });
37
38     dataLayer.addTo(map);
39
40     dataLayer.isWayArea = function () {
41       return !areasHidden && L.OSM.prototype.isWayArea.apply(this, arguments);
42     };
43
44     var drawHandler = new L.Rectangle.Draw(map, {title: I18n.t('browse.start_rjs.drag_a_box')});
45     map.on('draw:rectangle-created', endDrag);
46
47     $("#sidebar_title").html(I18n.t('browse.start_rjs.data_frame_title'));
48     $("#sidebar_content").html(sidebarHtml);
49
50     openSidebar();
51
52     map.on("moveend", updateData);
53     updateData();
54
55     $("#browse_select_view").click(useMap);
56
57     $("#browse_hide_areas_box").html(I18n.t('browse.start_rjs.hide_areas'));
58     $("#browse_hide_areas_box").toggle(hideAreas, showAreas);
59
60     function updateData() {
61       if (browseMode == "auto") {
62         if (map.getZoom() >= 15) {
63           useMap();
64         } else {
65           setStatus(I18n.t('browse.start_rjs.zoom_or_select'));
66         }
67       }
68     }
69
70     $("#sidebar").one("closed", function () {
71       map.removeLayer(dataLayer);
72       map.off("moveend", updateData);
73       map.off('draw:rectangle-created', endDrag);
74       drawHandler.disable();
75     });
76
77     $("#browse_select_box").click(function () {
78       $("#browse_select_box").html(I18n.t('browse.start_rjs.drag_a_box'));
79
80       drawHandler.enable();
81
82       return false;
83     });
84
85     function useMap() {
86       var bounds = map.getBounds();
87
88       if (!browseBounds || !browseBounds.contains(bounds)) {
89         browseBounds = bounds;
90         browseMode = "auto";
91
92         getData();
93
94         $("#browse_select_view").hide();
95       }
96
97       return false;
98     }
99
100     function hideAreas() {
101       $("#browse_hide_areas_box").html(I18n.t('browse.start_rjs.show_areas'));
102
103       areasHidden = true;
104
105       getData();
106     }
107
108     function showAreas() {
109       $("#browse_hide_areas_box").html(I18n.t('browse.start_rjs.hide_areas'));
110
111       areasHidden = false;
112
113       getData();
114     }
115
116     function endDrag(e) {
117       browseBounds = e.rect.getBounds();
118       browseMode = "manual";
119
120       getData();
121
122       $("#browse_select_box").html(I18n.t('browse.start_rjs.manually_select'));
123       $("#browse_select_view").show();
124
125       drawHandler.disable();
126     }
127
128     function displayFeatureWarning(count, limit, callback) {
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_with_num_features", { num_features: count, max_features: limit })));
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 = callback;
141       div.appendChild(input);
142
143       $("#browse_content").html("");
144       $("#browse_content").append(div);
145     }
146
147     function getData() {
148       var size = browseBounds.getSize();
149
150       if (size > OSM.MAX_REQUEST_AREA) {
151         setStatus(I18n.t("browse.start_rjs.unable_to_load_size", { max_bbox_size: OSM.MAX_REQUEST_AREA, bbox_size: size }));
152         return;
153       }
154
155       setStatus(I18n.t('browse.start_rjs.loading'));
156
157       $("#browse_content").empty();
158       dataLayer.clearLayers();
159       selectedLayer = null;
160
161       var url = "/api/" + OSM.API_VERSION + "/map?bbox=" + browseBounds.toBBOX();
162
163       /*
164        * Modern browsers are quite happy showing far more than 100 features in
165        * the data browser, so increase the limit to 2000 by default, but keep
166        * it restricted to 500 for IE8 and 100 for older IEs.
167        */
168       var maxFeatures = 2000;
169
170       /*@cc_on
171         if (navigator.appVersion < 8) {
172           maxFeatures = 100;
173         } else if (navigator.appVersion < 9) {
174           maxFeatures = 500;
175         }
176       @*/
177
178       $.ajax({
179         url: url,
180         success: function (xml) {
181           clearStatus();
182
183           dataLayer.addData(xml);
184
185           layersById = {};
186           var features = [];
187
188           dataLayer.eachLayer(function (layer) {
189             var feature = layer.feature;
190             layersById[feature.id] = layer;
191             features.push({
192               typeName: featureTypeName(feature),
193               url: "/browse/" + feature.type + "/" + feature.id,
194               name: featureName(feature),
195               id: feature.id
196             });
197           });
198
199           browseObjectList = $(JST["templates/browse/feature_list"]({
200             features: features,
201             url: url
202           }))[0];
203
204           loadObjectList();
205         }
206       });
207     }
208
209     function viewFeatureLink() {
210       var layer = layersById[$(this).data("feature-id")];
211
212       onSelect(layer);
213
214       if (browseMode != "auto") {
215         map.setCenter(layer.getBounds().getCenter());
216       }
217
218       return false;
219     }
220
221     function loadObjectList() {
222       $("#browse_content").html(browseObjectList);
223       $("#browse_content").find("a[data-feature-id]").click(viewFeatureLink);
224
225       return false;
226     }
227
228     function onSelect(layer) {
229       // Unselect previously selected feature
230       if (selectedLayer) {
231         selectedLayer.setStyle(selectedLayer.originalStyle);
232       }
233
234       // Redraw in selected style
235       layer.originalStyle = layer.options;
236       layer.setStyle({color: '#0000ff', weight: 8});
237
238       // If the current object is the list, don't innerHTML="", since that could clear it.
239       if ($("#browse_content").firstChild == browseObjectList) {
240         $("#browse_content").removeChild(browseObjectList);
241       } else {
242         $("#browse_content").empty();
243       }
244
245       var feature = layer.feature;
246
247       $("#browse_content").html(JST["templates/browse/feature"]({
248         name: featureNameSelect(feature),
249         url: "/browse/" + feature.type + "/" + feature.id,
250         attributes: feature.tags
251       }));
252
253       $("#browse_content").find("a.browse_show_list").click(loadObjectList);
254       $("#browse_content").find("a.browse_show_history").click(loadHistory);
255
256       // Stash the currently drawn feature
257       selectedLayer = layer;
258     }
259
260     dataLayer.on("click", function (e) {
261       onSelect(e.layer);
262     });
263
264     function loadHistory() {
265       $(this).attr("href", "").text(I18n.t('browse.start_rjs.wait'));
266
267       var feature = selectedLayer.feature;
268
269       $.ajax({
270         url: "/api/" + OSM.API_VERSION + "/" + feature.type + "/" + feature.id + "/history",
271         success: function (xml) {
272           if (selectedLayer.feature != feature || $("#browse_content").firstChild == browseObjectList) {
273             return;
274           }
275
276           $(this).remove();
277
278           var history = [];
279           var nodes = xml.getElementsByTagName(feature.type);
280           for (var i = nodes.length - 1; i >= 0; i--) {
281             history.push({
282               user: nodes[i].getAttribute("user") || I18n.t('browse.start_rjs.private_user'),
283               timestamp: nodes[i].getAttribute("timestamp")
284             });
285           }
286
287           $("#browse_content").append(JST["templates/browse/feature_history"]({
288             name: featureNameHistory(feature),
289             url: "/browse/" + feature.type + "/" + feature.id,
290             history: history
291           }));
292         }.bind(this)
293       });
294
295       return false;
296     }
297
298     function featureTypeName(feature) {
299       return I18n.t('browse.start_rjs.object_list.type.' + feature.type);
300     }
301
302     function featureName(feature) {
303       return feature.tags['name:' + $('html').attr('lang')] ||
304         feature.tags.name ||
305         feature.id;
306     }
307
308     function featureNameSelect(feature) {
309       return feature.tags['name:' + $('html').attr('lang')] ||
310         feature.tags.name ||
311         I18n.t("browse.start_rjs.object_list.selected.type." + feature.type, { id: feature.id });
312     }
313
314     function featureNameHistory(feature) {
315       return feature.tags['name:' + $('html').attr('lang')] ||
316         feature.tags.name ||
317         I18n.t("browse.start_rjs.object_list.history.type." + feature.type, { id: feature.id });
318     }
319
320     function setStatus(status) {
321       $("#browse_status").html(status);
322       $("#browse_status").show();
323     }
324
325     function clearStatus() {
326       $("#browse_status").html("");
327       $("#browse_status").hide();
328     }
329   }
330 });