]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/application.js
Even more map ui js refactor
[rails.git] / app / assets / javascripts / application.js
1 //= require jquery
2 //= require jquery_ujs
3 //= require jquery.timers
4 //= require jquery.cookie
5 //= require augment
6 //= require leaflet
7 //= require leaflet.osm
8 //= require leaflet.locationfilter
9 //= require leaflet.locate
10 //= require leaflet.note
11 //= require i18n/translations
12 //= require oauth
13 //= require osm
14 //= require piwik
15 //= require map
16 //= require menu
17 //= require sidebar
18 //= require leaflet.share
19 //= require richtext
20 //= require resize
21 //= require geocoder
22
23 function zoomPrecision(zoom) {
24     var decimals = Math.pow(10, Math.floor(zoom/3));
25     return function(x) {
26          return Math.round(x * decimals) / decimals;
27     };
28 }
29
30 function normalBounds(bounds) {
31     if (bounds instanceof L.LatLngBounds) return bounds;
32     return new L.LatLngBounds(
33         new L.LatLng(bounds[0][0], bounds[0][1]),
34         new L.LatLng(bounds[1][0], bounds[1][1]));
35 }
36
37 /*
38  * Called as the user scrolls/zooms around to maniplate hrefs of the
39  * view tab and various other links
40  */
41 function updatelinks(loc, zoom, layers, bounds, object) {
42   var toPrecision = zoomPrecision(zoom);
43   bounds = normalBounds(bounds);
44   var node;
45
46   var lat = toPrecision(loc.lat),
47       lon = toPrecision(loc.lon || loc.lng);
48
49   if (bounds) {
50     var minlon = toPrecision(bounds.getWest()),
51         minlat = toPrecision(bounds.getSouth()),
52         maxlon = toPrecision(bounds.getEast()),
53         maxlat = toPrecision(bounds.getNorth());
54   }
55
56   $(".geolink").each(setGeolink);
57   $("#shortlinkanchor").each(setShortlink);
58
59   function setGeolink(index, link) {
60     var args = getArgs(link.href);
61
62     if ($(link).hasClass("llz")) {
63       $.extend(args, {
64           lat: lat,
65           lon: lon,
66           zoom: zoom
67       });
68     } else if (minlon && $(link).hasClass("bbox")) {
69       $.extend(args, {
70           bbox: minlon + "," + minlat + "," + maxlon + "," + maxlat
71       });
72     }
73
74     if (layers && $(link).hasClass("layers")) {
75       args.layers = layers;
76     }
77
78     if (object && $(link).hasClass("object")) {
79       args[object.type] = object.id;
80     }
81
82     var minzoom = $(link).data("minzoom");
83     if (minzoom) {
84         var name = link.id.replace(/anchor$/, "");
85
86         $(link).off("click.minzoom");
87
88         if (zoom >= minzoom) {
89           $(link).attr("title", I18n.t("javascripts.site." + name + "_tooltip"))
90               .removeClass("disabled");
91         } else {
92           $(link).on("click.minzoom", minZoomAlert)
93               .attr("title", I18n.t("javascripts.site." + name + "_disabled_tooltip"))
94               .addClass("disabled");
95         }
96     }
97
98     link.href = setArgs(link.href, args);
99   }
100
101
102   function setShortlink() {
103     var args = getArgs(this.href);
104     var code = makeShortCode(lat, lon, zoom);
105     var prefix = shortlinkPrefix();
106
107     // Add ?{node,way,relation}=id to the arguments
108     if (object) {
109       args[object.type] = object.id;
110     }
111
112     // This is a hack to omit the default mapnik layer from the shortlink.
113     if (layers && layers != "M") {
114       args.layers = layers;
115     } else {
116       delete args.layers;
117     }
118
119     // Here we're assuming that all parameters but ?layers= and
120     // ?{node,way,relation}= can be safely omitted from the shortlink
121     // which encodes lat/lon/zoom. If new URL parameters are added to
122     // the main slippy map this needs to be changed.
123     if (args.layers || object) {
124       this.href = setArgs(prefix + "/go/" + code, args);
125     } else {
126       this.href = prefix + "/go/" + code;
127     }
128   }
129 }
130
131 function minZoomAlert() {
132     alert(I18n.t("javascripts.site." + name + "_zoom_alert")); return false;
133 }
134
135 /*
136  * Get the URL prefix to use for a short link
137  */
138 function shortlinkPrefix() {
139   if (window.location.hostname.match(/^www\.openstreetmap\.org/i)) {
140     return "http://osm.org";
141   } else {
142     return "";
143   }
144 }
145
146 /*
147  * Called to get the arguments from a URL as a hash.
148  */
149 function getArgs(url) {
150   var args = {};
151   var querystart = url.indexOf("?");
152
153   if (querystart >= 0) {
154      var querystring = url.substring(querystart + 1);
155      var queryitems = querystring.split("&");
156
157      for (var i = 0; i < queryitems.length; i++) {
158         if (match = queryitems[i].match(/^(.*)=(.*)$/)) {
159            args[unescape(match[1])] = unescape(match[2]);
160         } else {
161            args[unescape(queryitems[i])] = null;
162         }
163      }
164   }
165
166   return args;
167 }
168
169 /*
170  * Called to set the arguments on a URL from the given hash.
171  */
172 function setArgs(url, args) {
173    var queryitems = [];
174
175    for (arg in args) {
176       if (args[arg] == null) {
177          queryitems.push(escape(arg));
178       } else {
179          queryitems.push(escape(arg) + "=" + escape(args[arg]));
180       }
181    }
182
183    return url.replace(/\?.*$/, "") + "?" + queryitems.join("&");
184 }
185
186 /*
187  * Called to interlace the bits in x and y, making a Morton code.
188  */
189 function interlace(x, y) {
190     x = (x | (x << 8)) & 0x00ff00ff;
191     x = (x | (x << 4)) & 0x0f0f0f0f;
192     x = (x | (x << 2)) & 0x33333333;
193     x = (x | (x << 1)) & 0x55555555;
194
195     y = (y | (y << 8)) & 0x00ff00ff;
196     y = (y | (y << 4)) & 0x0f0f0f0f;
197     y = (y | (y << 2)) & 0x33333333;
198     y = (y | (y << 1)) & 0x55555555;
199
200     return (x << 1) | y;
201 }
202
203 /*
204  * Called to create a short code for the short link.
205  */
206 function makeShortCode(lat, lon, zoom) {
207     char_array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_~";
208     var x = Math.round((lon + 180.0) * ((1 << 30) / 90.0));
209     var y = Math.round((lat +  90.0) * ((1 << 30) / 45.0));
210     // JavaScript only has to keep 32 bits of bitwise operators, so this has to be
211     // done in two parts. each of the parts c1/c2 has 30 bits of the total in it
212     // and drops the last 4 bits of the full 64 bit Morton code.
213     var str = "";
214     var c1 = interlace(x >>> 17, y >>> 17), c2 = interlace((x >>> 2) & 0x7fff, (y >>> 2) & 0x7fff);
215     for (var i = 0; i < Math.ceil((zoom + 8) / 3.0) && i < 5; ++i) {
216         digit = (c1 >> (24 - 6 * i)) & 0x3f;
217         str += char_array.charAt(digit);
218     }
219     for (var i = 5; i < Math.ceil((zoom + 8) / 3.0); ++i) {
220         digit = (c2 >> (24 - 6 * (i - 5))) & 0x3f;
221         str += char_array.charAt(digit);
222     }
223     for (var i = 0; i < ((zoom + 8) % 3); ++i) {
224         str += "-";
225     }
226     return str;
227 }
228
229 /*
230  * Forms which have been cached by rails may have he wrong
231  * authenticity token, so patch up any forms with the correct
232  * token taken from the page header.
233  */
234 $(document).ready(function () {
235   var auth_token = $("meta[name=csrf-token]").attr("content");
236   $("form input[name=authenticity_token]").val(auth_token);
237 });