]> git.openstreetmap.org Git - rails.git/blob - public/javascripts/site.js
Merge branch 'master' into openid
[rails.git] / public / javascripts / site.js
1 /*
2  * Called as the user scrolls/zooms around to aniplate hrefs of the
3  * view tab and various other links
4  */
5 function updatelinks(lon,lat,zoom,layers,minlon,minlat,maxlon,maxlat,objtype,objid) {
6   var decimals = Math.pow(10, Math.floor(zoom/3));
7   var node;
8
9   lat = Math.round(lat * decimals) / decimals;
10   lon = Math.round(lon * decimals) / decimals;
11
12   node = $("permalinkanchor");
13   if (node) {
14     var args = getArgs(node.href);
15     args["lat"] = lat;
16     args["lon"] = lon;
17     args["zoom"] = zoom;
18     if (layers) {
19       args["layers"] = layers;
20     }
21     if (objtype && objid) {
22       args[objtype] = objid;
23     }
24     node.href = setArgs(node.href, args);
25   }
26
27   node = $("viewanchor");
28   if (node) {
29     var args = getArgs(node.href);
30     args["lat"] = lat;
31     args["lon"] = lon;
32     args["zoom"] = zoom;
33     if (layers) {
34       args["layers"] = layers;
35     }
36     node.href = setArgs(node.href, args);
37   }
38
39   node = $("exportanchor");
40   if (node) {
41     var args = getArgs(node.href);
42     args["lat"] = lat;
43     args["lon"] = lon;
44     args["zoom"] = zoom;
45     if (layers) {
46       args["layers"] = layers;
47     }
48     node.href = setArgs(node.href, args);
49   }
50
51   node = $("editanchor");
52   if (node) {
53     if (zoom >= 13) {
54       var args = new Object();
55       args.lat = lat;
56       args.lon = lon;
57       args.zoom = zoom;
58       if (objtype && objid) {
59         args[objtype] = objid;
60       }
61       node.href = setArgs("/edit", args);
62       node.title = i18n("javascripts.site.edit_tooltip");
63       node.removeClassName("disabled");
64     } else {
65       node.href = 'javascript:alert(i18n("javascripts.site.edit_zoom_alert"));';
66       node.title = i18n("javascripts.site.edit_disabled_tooltip");
67       node.addClassName("disabled");
68     }
69   }
70
71   node = $("potlatchanchor");
72   if (node) {
73     var args = new Object();
74     args.editor = "potlatch";
75     args.lat = lat;
76     args.lon = lon;
77     args.zoom = zoom;
78     if (objtype && objid) {
79       args[objtype] = objid;
80     }
81     node.href = setArgs("/edit", args);
82   }
83
84   node = $("potlatch2anchor");
85   if (node) {
86     var args = new Object();
87     args.editor = "potlatch2";
88     args.lat = lat;
89     args.lon = lon;
90     args.zoom = zoom;
91     if (objtype && objid) {
92       args[objtype] = objid;
93     }
94     node.href = setArgs("/edit", args);
95   }
96
97   node = $("josmanchor");
98   if (node) {
99     var args = new Object();
100     args.editor = "josm";
101     args.lat = lat;
102     args.lon = lon;
103     args.zoom = zoom;
104     if (objtype && objid) {
105       args[objtype] = objid;
106     }
107     node.href = setArgs("/edit", args);
108   }
109
110   node = $("historyanchor");
111   if (node) {
112     if (zoom >= 11) {
113       var args = new Object();
114       //set bbox param from 'extents' object
115       if (typeof minlon == "number" &&
116           typeof minlat == "number" &&
117           typeof maxlon == "number" &&
118           typeof maxlat == "number") {
119
120         minlon = Math.round(minlon * decimals) / decimals;
121         minlat = Math.round(minlat * decimals) / decimals;
122         maxlon = Math.round(maxlon * decimals) / decimals;
123         maxlat = Math.round(maxlat * decimals) / decimals;
124         args.bbox = minlon + "," + minlat + "," + maxlon + "," + maxlat;
125       }
126
127       node.href = setArgs("/history", args);
128       node.title = i18n("javascripts.site.history_tooltip");
129       node.removeClassName("disabled");
130     } else {
131       node.href = 'javascript:alert(i18n("javascripts.site.history_zoom_alert"));';
132       node.title = i18n("javascripts.site.history_disabled_tooltip");
133       node.addClassName("disabled");
134     }
135   }
136
137   node = $("shortlinkanchor");
138   if (node) {
139     var args = getArgs(node.href);
140     var code = makeShortCode(lat, lon, zoom);
141     var prefix = shortlinkPrefix();
142
143     // Add ?{node,way,relation}=id to the arguments
144     if (objtype && objid) {
145       args[objtype] = objid;
146     }
147
148     // This is a hack to omit the default mapnik layer from the shortlink.
149     if (layers && layers != "M") {
150       args["layers"] = layers;
151     }
152     else {
153       delete args["layers"];
154     }
155
156     // Here we're assuming that all parameters but ?layers= and
157     // ?{node,way,relation}= can be safely omitted from the shortlink
158     // which encodes lat/lon/zoom. If new URL parameters are added to
159     // the main slippy map this needs to be changed.
160     if (args["layers"] || args[objtype]) {
161       node.href = setArgs(prefix + "/go/" + code, args);
162     } else {
163       node.href = prefix + "/go/" + code;
164     }
165   }
166 }
167
168 /*
169  * Get the URL prefix to use for a short link
170  */
171 function shortlinkPrefix() {
172   if (window.location.hostname.match(/^www\.openstreetmap\.org/i)) {
173     return "http://osm.org";
174   } else {
175     return "";
176   }
177 }
178
179 /*
180  * Called to get the arguments from a URL as a hash.
181  */
182 function getArgs(url) {
183   var args = new Object();
184   var querystart = url.indexOf("?");
185
186   if (querystart >= 0) {
187      var querystring = url.substring(querystart + 1);
188      var queryitems = querystring.split("&");
189
190      for (var i = 0; i < queryitems.length; i++) {
191         if (match = queryitems[i].match(/^(.*)=(.*)$/)) {
192            args[unescape(match[1])] = unescape(match[2]);
193         } else {
194            args[unescape(queryitems[i])] = null
195         }
196      }
197   }
198
199   return args;
200 }
201
202 /*
203  * Called to set the arguments on a URL from the given hash.
204  */
205 function setArgs(url, args) {
206    var queryitems = new Array();
207
208    for (arg in args)
209    {
210       if (args[arg] == null) {
211          queryitems.push(escape(arg));
212       } else {
213          queryitems.push(escape(arg) + "=" + escape(args[arg]));
214       }
215    }
216
217    return url.replace(/\?.*$/, "") + "?" + queryitems.join("&");
218 }
219
220 /*
221  * Called to get a CSS property for an element.
222  */
223 function getStyle(el, property) {
224   var style;
225
226   if (el.currentStyle) {
227     style = el.currentStyle[property];
228   } else if( window.getComputedStyle ) {
229     style = document.defaultView.getComputedStyle(el,null).getPropertyValue(property);
230   } else {
231     style = el.style[property];
232   }
233
234   return style;
235 }
236
237 /*
238  * Called to interpolate JavaScript variables in strings using a
239  * similar syntax to rails I18n string interpolation - the only
240  * difference is that [[foo]] is the placeholder syntax instead
241  * of {{foo}} which allows the same string to be processed by both
242  * rails and then later by javascript.
243  */
244 function i18n(string, keys) {
245   string = i18n_strings[string] || string
246
247   for (var key in keys) {
248     var re_key = '\\[\\[' + key + '\\]\\]';
249     var re = new RegExp(re_key, "g");
250
251     string = string.replace(re, keys[key]);
252   }
253
254   return string;
255 }
256
257 /*
258  * Called to interlace the bits in x and y, making a Morton code.
259  */
260 function interlace(x, y) {
261     x = (x | (x << 8)) & 0x00ff00ff;
262     x = (x | (x << 4)) & 0x0f0f0f0f;
263     x = (x | (x << 2)) & 0x33333333;
264     x = (x | (x << 1)) & 0x55555555;
265
266     y = (y | (y << 8)) & 0x00ff00ff;
267     y = (y | (y << 4)) & 0x0f0f0f0f;
268     y = (y | (y << 2)) & 0x33333333;
269     y = (y | (y << 1)) & 0x55555555;
270
271     return (x << 1) | y;
272 }
273
274 /*
275  * Called to create a short code for the short link.
276  */
277 function makeShortCode(lat, lon, zoom) {
278     char_array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@";
279     var x = Math.round((lon + 180.0) * ((1 << 30) / 90.0));
280     var y = Math.round((lat +  90.0) * ((1 << 30) / 45.0));
281     // JavaScript only has to keep 32 bits of bitwise operators, so this has to be
282     // done in two parts. each of the parts c1/c2 has 30 bits of the total in it
283     // and drops the last 4 bits of the full 64 bit Morton code.
284     var str = "";
285     var c1 = interlace(x >>> 17, y >>> 17), c2 = interlace((x >>> 2) & 0x7fff, (y >>> 2) & 0x7fff);
286     for (var i = 0; i < Math.ceil((zoom + 8) / 3.0) && i < 5; ++i) {
287         digit = (c1 >> (24 - 6 * i)) & 0x3f;
288         str += char_array.charAt(digit);
289     }
290     for (var i = 5; i < Math.ceil((zoom + 8) / 3.0); ++i) {
291         digit = (c2 >> (24 - 6 * (i - 5))) & 0x3f;
292         str += char_array.charAt(digit);
293     }
294     for (var i = 0; i < ((zoom + 8) % 3); ++i) {
295         str += "-";
296     }
297     return str;
298 }