]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index/browse.js
Use jQuery chaining
[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   var areasHidden = false;
7
8   var dataLayer = new L.OSM.DataLayer(null, {
9     styles: {
10       way: {
11         weight: 3,
12         color: "#000000",
13         opacity: 0.4
14       },
15       area: {
16         weight: 3,
17         color: "#ff0000"
18       },
19       node: {
20         color: "#00ff00"
21       }
22     }
23   });
24
25   dataLayer.isWayArea = function () {
26     return !areasHidden && L.OSM.DataLayer.prototype.isWayArea.apply(this, arguments);
27   };
28
29   if (OSM.STATUS != 'api_offline' && OSM.STATUS != 'database_offline') {
30     map.layersControl.addOverlay(dataLayer, I18n.t("browse.start_rjs.data_layer_name"));
31   }
32
33   map.on('layeradd', function (e) {
34     if (e.layer === dataLayer) {
35       $.ajax({ url: "/browse/start", success: function (sidebarHtml) {
36         startBrowse(sidebarHtml);
37       }});
38     }
39   });
40
41   map.on('layerremove', function (e) {
42     if (e.layer === dataLayer) {
43       closeSidebar();
44     }
45   });
46
47   function startBrowse(sidebarHtml) {
48     var browseBounds;
49     var layersById;
50     var selectedLayer;
51     var browseObjectList;
52
53     var locationFilter = new L.LocationFilter({
54       enableButton: false,
55       adjustButton: false
56     }).addTo(map);
57
58     locationFilter.on("change", getData);
59
60     $("#sidebar_title").html(I18n.t('browse.start_rjs.data_frame_title'));
61     $("#sidebar_content").html(sidebarHtml);
62
63     openSidebar();
64
65     map.on("moveend", updateData);
66     updateData();
67
68     $("#browse_filter_toggle").toggle(enableFilter, disableFilter);
69
70     $("#browse_hide_areas_box").html(I18n.t('browse.start_rjs.hide_areas'));
71     $("#browse_hide_areas_box").toggle(hideAreas, showAreas);
72
73     function updateData() {
74       if (!locationFilter.isEnabled()) {
75         if (map.getZoom() >= 15) {
76           var bounds = map.getBounds();
77           if (!browseBounds || !browseBounds.contains(bounds)) {
78             browseBounds = bounds;
79             getData();
80           }
81         } else {
82           setStatus(I18n.t('browse.start_rjs.zoom_or_select'));
83         }
84       }
85     }
86
87     $("#sidebar").one("closed", function () {
88       map.removeLayer(dataLayer);
89       map.removeLayer(locationFilter);
90       map.off("moveend", updateData);
91       locationFilter.off("change", getData);
92     });
93
94     function enableFilter() {
95       $("#browse_filter_toggle").html(I18n.t('browse.start_rjs.view_data'));
96       locationFilter.setBounds(map.getBounds().pad(-0.2));
97       locationFilter.enable();
98       getData();
99     }
100
101     function disableFilter() {
102       $("#browse_filter_toggle").html(I18n.t('browse.start_rjs.manually_select'));
103       locationFilter.disable();
104       getData();
105     }
106
107     function hideAreas() {
108       $("#browse_hide_areas_box").html(I18n.t('browse.start_rjs.show_areas'));
109       areasHidden = true;
110       getData();
111     }
112
113     function showAreas() {
114       $("#browse_hide_areas_box").html(I18n.t('browse.start_rjs.hide_areas'));
115       areasHidden = false;
116       getData();
117     }
118
119     function displayFeatureWarning(count, limit, callback) {
120       clearStatus();
121
122       var div = document.createElement("div");
123
124       var p = document.createElement("p");
125       p.appendChild(document.createTextNode(I18n.t("browse.start_rjs.loaded_an_area_with_num_features", { num_features: count, max_features: limit })));
126       div.appendChild(p);
127
128       var input = document.createElement("input");
129       input.type = "submit";
130       input.value = I18n.t('browse.start_rjs.load_data');
131       input.onclick = callback;
132       div.appendChild(input);
133
134       $("#browse_content").html("");
135       $("#browse_content").append(div);
136     }
137
138     function getData() {
139       var bounds = locationFilter.isEnabled() ? locationFilter.getBounds() : map.getBounds();
140       var size = bounds.getSize();
141
142       if (size > OSM.MAX_REQUEST_AREA) {
143         setStatus(I18n.t("browse.start_rjs.unable_to_load_size", { max_bbox_size: OSM.MAX_REQUEST_AREA, bbox_size: size }));
144         return;
145       }
146
147       setStatus(I18n.t('browse.start_rjs.loading'));
148
149       var url = "/api/" + OSM.API_VERSION + "/map?bbox=" + bounds.toBBOX();
150
151       /*
152        * Modern browsers are quite happy showing far more than 100 features in
153        * the data browser, so increase the limit to 2000 by default, but keep
154        * it restricted to 500 for IE8 and 100 for older IEs.
155        */
156       var maxFeatures = 2000;
157
158       /*@cc_on
159         if (navigator.appVersion < 8) {
160           maxFeatures = 100;
161         } else if (navigator.appVersion < 9) {
162           maxFeatures = 500;
163         }
164       @*/
165
166       $.ajax({
167         url: url,
168         success: function (xml) {
169           clearStatus();
170
171           $("#browse_content").empty();
172           dataLayer.clearLayers();
173           selectedLayer = null;
174
175           var features = dataLayer.buildFeatures(xml);
176
177           function addFeatures() {
178             dataLayer.addData(features);
179
180             layersById = {};
181
182             dataLayer.eachLayer(function (layer) {
183               var feature = layer.feature;
184               layersById[feature.id] = layer;
185               $.extend(feature, {
186                 typeName: featureTypeName(feature),
187                 url: "/browse/" + feature.type + "/" + feature.id,
188                 name: featureName(feature)
189               });
190             });
191
192             browseObjectList = $(JST["templates/browse/feature_list"]({
193               features: features,
194               url: url
195             }))[0];
196
197             loadObjectList();
198           }
199
200           if (features.length < maxFeatures) {
201             addFeatures();
202           } else {
203             displayFeatureWarning(features.length, maxFeatures, addFeatures);
204           }
205         }
206       });
207     }
208
209     function viewFeatureLink() {
210       var layer = layersById[$(this).data("feature-id")];
211
212       onSelect(layer);
213
214       if (locationFilter.isEnabled()) {
215         map.panTo(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 });