]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index.js
Move contextmenu callbacks to separate file
[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   L.control.locate({
134     position: position,
135     strings: {
136       title: I18n.t('javascripts.map.locate.title'),
137       popup: I18n.t('javascripts.map.locate.popup')
138     }
139   }).addTo(map);
140
141   var sidebar = L.OSM.sidebar('#map-ui')
142     .addTo(map);
143
144   L.OSM.layers({
145     position: position,
146     layers: map.baseLayers,
147     sidebar: sidebar
148   }).addTo(map);
149
150   L.OSM.key({
151     position: position,
152     sidebar: sidebar
153   }).addTo(map);
154
155   L.OSM.share({
156     position: position,
157     sidebar: sidebar,
158     short: true
159   }).addTo(map);
160
161   L.OSM.note({
162     position: position,
163     sidebar: sidebar
164   }).addTo(map);
165
166   L.OSM.query({
167     position: position,
168     sidebar: sidebar
169   }).addTo(map);
170
171   L.control.scale()
172     .addTo(map);
173
174   if (OSM.STATUS !== 'api_offline' && OSM.STATUS !== 'database_offline') {
175     OSM.initializeNotes(map);
176     if (params.layers.indexOf(map.noteLayer.options.code) >= 0) {
177       map.addLayer(map.noteLayer);
178     }
179
180     OSM.initializeBrowse(map);
181     if (params.layers.indexOf(map.dataLayer.options.code) >= 0) {
182       map.addLayer(map.dataLayer);
183     }
184   }
185
186   var placement = $('html').attr('dir') === 'rtl' ? 'right' : 'left';
187   $('.leaflet-control .control-button').tooltip({placement: placement, container: 'body'});
188
189   var expiry = new Date();
190   expiry.setYear(expiry.getFullYear() + 10);
191
192   map.on('moveend layeradd layerremove', function() {
193     updateLinks(
194       map.getCenter().wrap(),
195       map.getZoom(),
196       map.getLayersCode(),
197       map._object);
198
199     $.removeCookie("_osm_location");
200     $.cookie("_osm_location", OSM.locationCookie(map), { expires: expiry, path: "/" });
201   });
202
203   if ($.cookie('_osm_welcome') === 'hide') {
204     $('.welcome').hide();
205   }
206
207   $('.welcome .close').on('click', function() {
208     $('.welcome').hide();
209     $.cookie("_osm_welcome", 'hide', { expires: expiry });
210   });
211
212   if (OSM.PIWIK) {
213     map.on('layeradd', function (e) {
214       if (e.layer.options) {
215         var goal = OSM.PIWIK.goals[e.layer.options.keyid];
216
217         if (goal) {
218           $('body').trigger('piwikgoal', goal);
219         }
220       }
221     });
222   }
223
224   if (params.bounds) {
225     map.fitBounds(params.bounds);
226   } else {
227     map.setView([params.lat, params.lon], params.zoom);
228   }
229
230   var marker = L.marker([0, 0], {icon: OSM.getUserIcon()});
231
232   if (params.marker) {
233     marker.setLatLng([params.mlat, params.mlon]).addTo(map);
234   }
235
236   $("#homeanchor").on("click", function(e) {
237     e.preventDefault();
238
239     var data = $(this).data(),
240       center = L.latLng(data.lat, data.lon);
241
242     map.setView(center, data.zoom);
243     marker.setLatLng(center).addTo(map);
244   });
245
246   function remoteEditHandler(bbox, object) {
247     var loaded = false,
248         url = document.location.protocol === "https:" ?
249         "https://127.0.0.1:8112/load_and_zoom?" :
250         "http://127.0.0.1:8111/load_and_zoom?",
251         query = {
252           left: bbox.getWest() - 0.0001,
253           top: bbox.getNorth() + 0.0001,
254           right: bbox.getEast() + 0.0001,
255           bottom: bbox.getSouth() - 0.0001
256         };
257
258     if (object) query.select = object.type + object.id;
259
260     var iframe = $('<iframe>')
261         .hide()
262         .appendTo('body')
263         .attr("src", url + querystring.stringify(query))
264         .on('load', function() {
265           $(this).remove();
266           loaded = true;
267         });
268
269     setTimeout(function () {
270       if (!loaded) {
271         alert(I18n.t('site.index.remote_failed'));
272         iframe.remove();
273       }
274     }, 1000);
275
276     return false;
277   }
278
279   $("a[data-editor=remote]").click(function(e) {
280     var params = OSM.mapParams(this.search);
281     remoteEditHandler(map.getBounds(), params.object);
282     e.preventDefault();
283   });
284
285   if (OSM.params().edit_help) {
286     $('#editanchor')
287       .removeAttr('title')
288       .tooltip({
289         placement: 'bottom',
290         title: I18n.t('javascripts.edit_help')
291       })
292       .tooltip('show');
293
294     $('body').one('click', function() {
295       $('#editanchor').tooltip('hide');
296     });
297   }
298
299   OSM.Index = function(map) {
300     var page = {};
301
302     page.pushstate = page.popstate = function() {
303       map.setSidebarOverlaid(true);
304       document.title = I18n.t('layouts.project_name.title');
305     };
306
307     page.load = function() {
308       var params = querystring.parse(location.search.substring(1));
309       if (params.query) {
310         $("#sidebar .search_form input[name=query]").value(params.query);
311       }
312       if (!("autofocus" in document.createElement("input"))) {
313         $("#sidebar .search_form input[name=query]").focus();
314       }
315       return map.getState();
316     };
317
318     return page;
319   };
320
321   OSM.Browse = function(map, type) {
322     var page = {};
323
324     page.pushstate = page.popstate = function(path, id) {
325       OSM.loadSidebarContent(path, function() {
326         addObject(type, id);
327       });
328     };
329
330     page.load = function(path, id) {
331       addObject(type, id, true);
332     };
333
334     function addObject(type, id, center) {
335       map.addObject({type: type, id: parseInt(id)}, function(bounds) {
336         if (!window.location.hash && bounds.isValid() &&
337             (center || !map.getBounds().contains(bounds))) {
338           OSM.router.withoutMoveListener(function () {
339             map.fitBounds(bounds);
340           });
341         }
342       });
343     }
344
345     page.unload = function() {
346       map.removeObject();
347     };
348
349     return page;
350   };
351
352   var history = OSM.History(map);
353
354   OSM.router = OSM.Router(map, {
355     "/":                           OSM.Index(map),
356     "/search":                     OSM.Search(map),
357     "/directions":                 OSM.Directions(map),
358     "/export":                     OSM.Export(map),
359     "/note/new":                   OSM.NewNote(map),
360     "/history/friends":            history,
361     "/history/nearby":             history,
362     "/history":                    history,
363     "/user/:display_name/history": history,
364     "/note/:id":                   OSM.Note(map),
365     "/node/:id(/history)":         OSM.Browse(map, 'node'),
366     "/way/:id(/history)":          OSM.Browse(map, 'way'),
367     "/relation/:id(/history)":     OSM.Browse(map, 'relation'),
368     "/changeset/:id":              OSM.Changeset(map),
369     "/query":                      OSM.Query(map)
370   });
371
372   if (OSM.preferred_editor === "remote" && document.location.pathname === "/edit") {
373     remoteEditHandler(map.getBounds(), params.object);
374     OSM.router.setCurrentPath("/");
375   }
376
377   OSM.router.load();
378
379   $(document).on("click", "a", function(e) {
380     if (e.isDefaultPrevented() || e.isPropagationStopped())
381       return;
382
383     // Open links in a new tab as normal.
384     if (e.which > 1 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey)
385       return;
386
387     // Ignore cross-protocol and cross-origin links.
388     if (location.protocol !== this.protocol || location.host !== this.host)
389       return;
390
391     if (OSM.router.route(this.pathname + this.search + this.hash))
392       e.preventDefault();
393   });
394 });