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