]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index.js
0962908064ba7c1bae8797f3a8aa7f5306577e75
[rails.git] / app / assets / javascripts / index.js
1 //= require_self
2 //= require leaflet.sidebar
3 //= require leaflet.locate
4 //= require leaflet.layers
5 //= require leaflet.key
6 //= require leaflet.note
7 //= require leaflet.share
8 //= require leaflet.polyline
9 //= require leaflet.query
10 //= require leaflet.contextmenu
11 //= require index/contextmenu
12 //= require index/search
13 //= require index/browse
14 //= require index/export
15 //= require index/notes
16 //= require index/history
17 //= require index/note
18 //= require index/new_note
19 //= require index/directions
20 //= require index/changeset
21 //= require index/query
22 //= require router
23
24 $(document).ready(function () {
25   var loaderTimeout;
26
27   OSM.loadSidebarContent = function(path, callback) {
28     map.setSidebarOverlaid(false);
29
30     clearTimeout(loaderTimeout);
31
32     loaderTimeout = setTimeout(function() {
33       $('#sidebar_loader').show();
34     }, 200);
35
36     // IE<10 doesn't respect Vary: X-Requested-With header, so
37     // prevent caching the XHR response as a full-page URL.
38     if (path.indexOf('?') >= 0) {
39       path += '&xhr=1';
40     } else {
41       path += '?xhr=1';
42     }
43
44     $('#sidebar_content')
45       .empty();
46
47     $.ajax({
48       url: path,
49       dataType: "html",
50       complete: function(xhr) {
51         clearTimeout(loaderTimeout);
52         $('#flash').empty();
53         $('#sidebar_loader').hide();
54
55         var content = $(xhr.responseText);
56
57         if (xhr.getResponseHeader('X-Page-Title')) {
58           var title = xhr.getResponseHeader('X-Page-Title');
59           document.title = decodeURIComponent(title);
60         }
61
62         $('head')
63           .find('link[type="application/atom+xml"]')
64           .remove();
65
66         $('head')
67           .append(content.filter('link[type="application/atom+xml"]'));
68
69         $('#sidebar_content').html(content.not('link[type="application/atom+xml"]'));
70
71         if (callback) {
72           callback();
73         }
74       }
75     });
76   };
77
78   var params = OSM.mapParams();
79
80   // TODO internationalisation of the context menu strings
81   var map = new L.OSM.Map("map", {
82     zoomControl: false,
83     layerControl: false,
84     contextmenu: true,
85     contextmenuWidth: 140,
86     contextmenuItems: [{
87         text: 'Directions from here',
88         callback: function(e){ context_directionsfrom(e, map); }
89     }, {
90         text: 'Directions to here',
91         callback: function(e){ context_directionsto(e, map); }
92     }, '-', {
93         text: 'Add a note here',
94         callback: function(e){ context_addnote(e, map); }
95     }, {
96         text: 'Show address',
97         callback: function(e){ context_describe(e, map); }
98     }, {
99         text: 'Query features',
100         callback: function(e){ context_queryhere(e, map); }
101     }, {
102         text: 'Centre map here',
103         callback: function(e){ context_centrehere(e, map); }
104     }]
105   });
106
107   $(document).on('mousedown', function(e){
108     if(e.shiftKey){
109       map.contextmenu.disable(); // on firefox, shift disables our contextmenu. we explicitly do this for all browsers.
110     }else{
111       map.contextmenu.enable();
112       // we also decide whether to disable some options that only like high zoom
113       map.contextmenu.setDisabled(3, map.getZoom() < 12);
114       map.contextmenu.setDisabled(5, map.getZoom() < 14);
115     }
116   });
117
118   map.attributionControl.setPrefix('');
119
120   map.updateLayers(params.layers);
121
122   map.on("baselayerchange", function (e) {
123     if (map.getZoom() > e.layer.options.maxZoom) {
124       map.setView(map.getCenter(), e.layer.options.maxZoom, { reset: true });
125     }
126   });
127
128   var position = $('html').attr('dir') === 'rtl' ? 'topleft' : 'topright';
129
130   L.OSM.zoom({position: position})
131     .addTo(map);
132
133   var locate = L.control.locate({
134     position: position,
135     icon: 'icon geolocate',
136     iconLoading: 'icon geolocate',
137     strings: {
138       title: I18n.t('javascripts.map.locate.title'),
139       popup: I18n.t('javascripts.map.locate.popup')
140     }
141   }).addTo(map);
142
143   var locateContainer = locate.getContainer();
144
145   $(locateContainer)
146     .removeClass('leaflet-control-locate leaflet-bar')
147     .addClass('control-locate')
148     .children("a")
149     .removeClass('leaflet-bar-part leaflet-bar-part-single')
150     .addClass('control-button');
151
152   var sidebar = L.OSM.sidebar('#map-ui')
153     .addTo(map);
154
155   L.OSM.layers({
156     position: position,
157     layers: map.baseLayers,
158     sidebar: sidebar
159   }).addTo(map);
160
161   L.OSM.key({
162     position: position,
163     sidebar: sidebar
164   }).addTo(map);
165
166   L.OSM.share({
167     position: position,
168     sidebar: sidebar,
169     short: true
170   }).addTo(map);
171
172   L.OSM.note({
173     position: position,
174     sidebar: sidebar
175   }).addTo(map);
176
177   L.OSM.query({
178     position: position,
179     sidebar: sidebar
180   }).addTo(map);
181
182   L.control.scale()
183     .addTo(map);
184
185   if (OSM.STATUS !== 'api_offline' && OSM.STATUS !== 'database_offline') {
186     OSM.initializeNotes(map);
187     if (params.layers.indexOf(map.noteLayer.options.code) >= 0) {
188       map.addLayer(map.noteLayer);
189     }
190
191     OSM.initializeBrowse(map);
192     if (params.layers.indexOf(map.dataLayer.options.code) >= 0) {
193       map.addLayer(map.dataLayer);
194     }
195
196     if (params.layers.indexOf(map.gpsLayer.options.code) >= 0) {
197       map.addLayer(map.gpsLayer);
198     }
199   }
200
201   var placement = $('html').attr('dir') === 'rtl' ? 'right' : 'left';
202   $('.leaflet-control .control-button').tooltip({placement: placement, container: 'body'});
203
204   var expiry = new Date();
205   expiry.setYear(expiry.getFullYear() + 10);
206
207   map.on('moveend layeradd layerremove', function() {
208     updateLinks(
209       map.getCenter().wrap(),
210       map.getZoom(),
211       map.getLayersCode(),
212       map._object);
213
214     $.removeCookie('_osm_location');
215     $.cookie('_osm_location', OSM.locationCookie(map), { expires: expiry, path: '/' });
216   });
217
218   if ($.cookie('_osm_welcome') === 'hide') {
219     $('.welcome').hide();
220   }
221
222   $('.welcome .close-wrap').on('click', function() {
223     $('.welcome').hide();
224     $.cookie('_osm_welcome', 'hide', { expires: expiry, path: '/' });
225   });
226
227   var bannerExpiry = new Date();
228   bannerExpiry.setYear(bannerExpiry.getFullYear() + 1);
229
230   $('#banner .close-wrap').on('click', function(e) {
231     var cookieId = e.target.id;
232     $('#banner').hide();
233     e.preventDefault();
234     if (cookieId) {
235       $.cookie(cookieId, 'hide', { expires: bannerExpiry, path: '/' });
236     }
237   });
238
239   if (OSM.PIWIK) {
240     map.on('layeradd', function (e) {
241       if (e.layer.options) {
242         var goal = OSM.PIWIK.goals[e.layer.options.keyid];
243
244         if (goal) {
245           $('body').trigger('piwikgoal', goal);
246         }
247       }
248     });
249   }
250
251   if (params.bounds) {
252     map.fitBounds(params.bounds);
253   } else {
254     map.setView([params.lat, params.lon], params.zoom);
255   }
256
257   if (params.marker) {
258     L.marker([params.mlat, params.mlon]).addTo(map);
259   }
260
261   $("#homeanchor").on("click", function(e) {
262     e.preventDefault();
263
264     var data = $(this).data(),
265       center = L.latLng(data.lat, data.lon);
266
267     map.setView(center, data.zoom);
268     L.marker(center, {icon: OSM.getUserIcon()}).addTo(map);
269   });
270
271   function remoteEditHandler(bbox, object) {
272     var loaded = false,
273         url = document.location.protocol === "https:" ?
274         "https://127.0.0.1:8112/load_and_zoom?" :
275         "http://127.0.0.1:8111/load_and_zoom?",
276         query = {
277           left: bbox.getWest() - 0.0001,
278           top: bbox.getNorth() + 0.0001,
279           right: bbox.getEast() + 0.0001,
280           bottom: bbox.getSouth() - 0.0001
281         };
282
283     if (object) query.select = object.type + object.id;
284
285     var iframe = $('<iframe>')
286         .hide()
287         .appendTo('body')
288         .attr("src", url + querystring.stringify(query))
289         .on('load', function() {
290           $(this).remove();
291           loaded = true;
292         });
293
294     setTimeout(function () {
295       if (!loaded) {
296         alert(I18n.t('site.index.remote_failed'));
297         iframe.remove();
298       }
299     }, 1000);
300
301     return false;
302   }
303
304   $("a[data-editor=remote]").click(function(e) {
305     var params = OSM.mapParams(this.search);
306     remoteEditHandler(map.getBounds(), params.object);
307     e.preventDefault();
308   });
309
310   if (OSM.params().edit_help) {
311     $('#editanchor')
312       .removeAttr('title')
313       .tooltip({
314         placement: 'bottom',
315         title: I18n.t('javascripts.edit_help')
316       })
317       .tooltip('show');
318
319     $('body').one('click', function() {
320       $('#editanchor').tooltip('hide');
321     });
322   }
323
324   OSM.Index = function(map) {
325     var page = {};
326
327     page.pushstate = page.popstate = function() {
328       map.setSidebarOverlaid(true);
329       document.title = I18n.t('layouts.project_name.title');
330     };
331
332     page.load = function() {
333       var params = querystring.parse(location.search.substring(1));
334       if (params.query) {
335         $("#sidebar .search_form input[name=query]").value(params.query);
336       }
337       if (!("autofocus" in document.createElement("input"))) {
338         $("#sidebar .search_form input[name=query]").focus();
339       }
340       return map.getState();
341     };
342
343     return page;
344   };
345
346   OSM.Browse = function(map, type) {
347     var page = {};
348
349     page.pushstate = page.popstate = function(path, id) {
350       OSM.loadSidebarContent(path, function() {
351         addObject(type, id);
352       });
353     };
354
355     page.load = function(path, id) {
356       addObject(type, id, true);
357     };
358
359     function addObject(type, id, center) {
360       map.addObject({type: type, id: parseInt(id)}, function(bounds) {
361         if (!window.location.hash && bounds.isValid() &&
362             (center || !map.getBounds().contains(bounds))) {
363           OSM.router.withoutMoveListener(function () {
364             map.fitBounds(bounds);
365           });
366         }
367       });
368     }
369
370     page.unload = function() {
371       map.removeObject();
372     };
373
374     return page;
375   };
376
377   var history = OSM.History(map);
378
379   OSM.router = OSM.Router(map, {
380     "/":                           OSM.Index(map),
381     "/search":                     OSM.Search(map),
382     "/directions":                 OSM.Directions(map),
383     "/export":                     OSM.Export(map),
384     "/note/new":                   OSM.NewNote(map),
385     "/history/friends":            history,
386     "/history/nearby":             history,
387     "/history":                    history,
388     "/user/:display_name/history": history,
389     "/note/:id":                   OSM.Note(map),
390     "/node/:id(/history)":         OSM.Browse(map, 'node'),
391     "/way/:id(/history)":          OSM.Browse(map, 'way'),
392     "/relation/:id(/history)":     OSM.Browse(map, 'relation'),
393     "/changeset/:id":              OSM.Changeset(map),
394     "/query":                      OSM.Query(map)
395   });
396
397   if (OSM.preferred_editor === "remote" && document.location.pathname === "/edit") {
398     remoteEditHandler(map.getBounds(), params.object);
399     OSM.router.setCurrentPath("/");
400   }
401
402   OSM.router.load();
403
404   $(document).on("click", "a", function(e) {
405     if (e.isDefaultPrevented() || e.isPropagationStopped())
406       return;
407
408     // Open links in a new tab as normal.
409     if (e.which > 1 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey)
410       return;
411
412     // Ignore cross-protocol and cross-origin links.
413     if (location.protocol !== this.protocol || location.host !== this.host)
414       return;
415
416     if (OSM.router.route(this.pathname + this.search + this.hash))
417       e.preventDefault();
418   });
419 });