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