for (var i = 0; i < suggestions.length; i++) {
if (suggestions[i].value.toLowerCase().indexOf(v.toLowerCase()) === 0) {
- var completion = v + suggestions[i].value.substr(v.length);
+ var completion = suggestions[i].value;
idx = i;
input.property('value', completion);
input.node().setSelectionRange(v.length, completion.length);
// ## Getting a request token
var params = timenonce(getAuth(o)),
- url = o.url + '/oauth/request_token';
+ url = o.url + '/oauth/request_token',
+ timer;
params.oauth_signature = ohauth.signature(
o.oauth_secret, '',
return x.join('=');
}).join(','),
popup = window.open('about:blank', 'oauth_window', settings);
+
+
+ timer = setInterval(function() {
+ if (popup.closed) {
+ o.done();
+ clearInterval(timer);
+ callback('not authenticated', null);
+ }
+ }, 100);
}
// Request a request token. When this is complete, the popup
function reqTokenDone(err, xhr) {
o.done();
- if (err) return callback(err);
+ if (err) {
+ if (timer) clearInterval(timer);
+ return callback(err);
+ }
var resp = ohauth.stringQs(xhr.response);
token('oauth_request_token_secret', resp.oauth_token_secret);
var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
// Called by a function in a landing page, in the popup window. The
// window closes itself.
window.authComplete = function(token) {
+ if (timer) clearInterval(timer);
var oauth_token = ohauth.stringQs(token.split('?')[1]);
get_access_token(oauth_token.oauth_token);
delete window.authComplete;
function accessTokenDone(err, xhr) {
o.done();
+ if (timer) clearInterval(timer);
if (err) return callback(err);
var access_token = ohauth.stringQs(xhr.response);
token('oauth_token', access_token.oauth_token);
store.disabled = true
}
store.enabled = !store.disabled
-
+
if (typeof module != 'undefined' && module.exports) { module.exports = store }
else if (typeof define === 'function' && define.amd) { define(store) }
else { win.store = store }
-
+
})(this.window || global);
})(window)
},{"./has-keys":5,"object-keys":6}],7:[function(require,module,exports){
(function(global){/**
* jsHashes - A fast and independent hashing library pure JavaScript implemented (ES3 compliant) for both server and client side
- *
+ *
* @class Hashes
* @author Tomas Aparicio <tomas@rijndael-project.com>
* @license New BSD (see LICENSE file)
*/
(function(){
var Hashes;
-
+
// private helper methods
function utf8Encode(str) {
var x, y, output = '', i = -1, l;
-
+
if (str && str.length) {
l = str.length;
while ((i+=1) < l) {
}
return output;
}
-
+
function utf8Decode(str) {
var i, ac, c1, c2, c3, arr = [], l;
i = ac = c1 = c2 = c3 = 0;
-
+
if (str && str.length) {
l = str.length;
str += '';
-
+
while (i < l) {
c1 = str.charCodeAt(i);
ac += 1;
}
return output;
}
-
+
/**
- * Convert a raw string to an array of big-endian words
+ * Convert a raw string to an array of big-endian words
* Characters >255 have their high-byte silently ignored.
*/
function rstr2binb(input) {
var divisor = encoding.length,
remainders = Array(),
i, q, x, ld, quotient, dividend, output, full_length;
-
+
/* Convert to an array of 16-bit big-endian values, forming the dividend */
dividend = Array(Math.ceil(input.length / 2));
ld = dividend.length;
for (i = 0; i < ld; i+=1) {
dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
}
-
+
/**
* Repeatedly perform a long division. The binary array forms the dividend,
* the length of the encoding is the divisor. Once computed, the quotient
remainders[remainders.length] = x;
dividend = quotient;
}
-
+
/* Convert the remainders to the output string */
output = '';
for (i = remainders.length - 1; i >= 0; i--) {
output += encoding.charAt(remainders[i]);
}
-
+
/* Append leading zero equivalents */
full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
for (i = output.length; i < full_length; i+=1) {
| (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
| (i + 2 < len ? input.charCodeAt(i+2) : 0);
for (j = 0; j < 4; j+=1) {
- if (i * 8 + j * 6 > input.length * 8) {
- output += b64pad;
- } else {
- output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
+ if (i * 8 + j * 6 > input.length * 8) {
+ output += b64pad;
+ } else {
+ output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
}
}
}
}
Hashes = {
- /**
+ /**
* @property {String} version
* @readonly
*/
// public method for encoding
this.encode = function (input) {
var i, j, triplet,
- output = '',
+ output = '',
len = input.length;
pad = pad || '=';
}
}
}
- return output;
+ return output;
};
// public method for decoding
CRC32 : function (str) {
var crc = 0, x = 0, y = 0, table, i, iTop;
str = utf8Encode(str);
-
- table = [
+
+ table = [
'00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
'79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
'84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
'7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
'806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
'60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
- 'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
+ 'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
'5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
'05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
* @class MD5
* @constructor
* @param {Object} [config]
- *
+ *
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* See <http://pajhome.org.uk/crypt/md5> for more infHashes.
*/
- MD5 : function (options) {
+ MD5 : function (options) {
/**
* Private config properties. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
- // privileged (public) methods
- this.hex = function (s) {
+ // privileged (public) methods
+ this.hex = function (s) {
return rstr2hex(rstr(s, utf8), hexcase);
};
- this.b64 = function (s) {
+ this.b64 = function (s) {
return rstr2b64(rstr(s), b64pad);
};
- this.any = function(s, e) {
- return rstr2any(rstr(s, utf8), e);
+ this.any = function(s, e) {
+ return rstr2any(rstr(s, utf8), e);
};
- this.hex_hmac = function (k, d) {
- return rstr2hex(rstr_hmac(k, d), hexcase);
+ this.hex_hmac = function (k, d) {
+ return rstr2hex(rstr_hmac(k, d), hexcase);
};
- this.b64_hmac = function (k, d) {
- return rstr2b64(rstr_hmac(k,d), b64pad);
+ this.b64_hmac = function (k, d) {
+ return rstr2b64(rstr_hmac(k,d), b64pad);
};
- this.any_hmac = function (k, d, e) {
- return rstr2any(rstr_hmac(k, d), e);
+ this.any_hmac = function (k, d, e) {
+ return rstr2any(rstr_hmac(k, d), e);
};
/**
* Perform a simple self-test to see if the VM is working
this.vm_test = function () {
return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
};
- /**
- * Enable/disable uppercase hexadecimal returned string
- * @param {Boolean}
+ /**
+ * Enable/disable uppercase hexadecimal returned string
+ * @param {Boolean}
* @return {Object} this
- */
+ */
this.setUpperCase = function (a) {
if (typeof a === 'boolean' ) {
hexcase = a;
}
return this;
};
- /**
- * Defines a base64 pad string
+ /**
+ * Defines a base64 pad string
* @param {String} Pad
* @return {Object} this
- */
+ */
this.setPad = function (a) {
b64pad = a || b64pad;
return this;
};
- /**
- * Defines a base64 pad string
- * @param {Boolean}
+ /**
+ * Defines a base64 pad string
+ * @param {Boolean}
* @return {Object} [this]
- */
+ */
this.setUTF8 = function (a) {
- if (typeof a === 'boolean') {
+ if (typeof a === 'boolean') {
utf8 = a;
}
return this;
s = (utf8) ? utf8Encode(s): s;
return binl2rstr(binl(rstr2binl(s), s.length * 8));
}
-
+
/**
* Calculate the HMAC-MD5, of a key and some data (raw strings)
*/
key = (utf8) ? utf8Encode(key) : key;
data = (utf8) ? utf8Encode(data) : data;
bkey = rstr2binl(key);
- if (bkey.length > 16) {
- bkey = binl(bkey, key.length * 8);
+ if (bkey.length > 16) {
+ bkey = binl(bkey, key.length * 8);
}
- ipad = Array(16), opad = Array(16);
+ ipad = Array(16), opad = Array(16);
for (i = 0; i < 16; i+=1) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
b = -271733879,
c = -1732584194,
d = 271733878;
-
+
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
* @class Hashes.SHA1
* @param {Object} [config]
* @constructor
- *
+ *
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
* Version 2.2 Copyright Paul Johnston 2000 - 2009.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
// public methods
- this.hex = function (s) {
- return rstr2hex(rstr(s, utf8), hexcase);
+ this.hex = function (s) {
+ return rstr2hex(rstr(s, utf8), hexcase);
};
- this.b64 = function (s) {
+ this.b64 = function (s) {
return rstr2b64(rstr(s, utf8), b64pad);
};
- this.any = function (s, e) {
+ this.any = function (s, e) {
return rstr2any(rstr(s, utf8), e);
};
this.hex_hmac = function (k, d) {
return rstr2hex(rstr_hmac(k, d));
};
- this.b64_hmac = function (k, d) {
- return rstr2b64(rstr_hmac(k, d), b64pad);
+ this.b64_hmac = function (k, d) {
+ return rstr2b64(rstr_hmac(k, d), b64pad);
};
- this.any_hmac = function (k, d, e) {
+ this.any_hmac = function (k, d, e) {
return rstr2any(rstr_hmac(k, d), e);
};
/**
this.vm_test = function () {
return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
};
- /**
- * @description Enable/disable uppercase hexadecimal returned string
- * @param {boolean}
+ /**
+ * @description Enable/disable uppercase hexadecimal returned string
+ * @param {boolean}
* @return {Object} this
* @public
- */
+ */
this.setUpperCase = function (a) {
if (typeof a === 'boolean') {
hexcase = a;
}
return this;
};
- /**
- * @description Defines a base64 pad string
+ /**
+ * @description Defines a base64 pad string
* @param {string} Pad
* @return {Object} this
* @public
- */
+ */
this.setPad = function (a) {
b64pad = a || b64pad;
return this;
};
- /**
- * @description Defines a base64 pad string
- * @param {boolean}
+ /**
+ * @description Defines a base64 pad string
+ * @param {boolean}
* @return {Object} this
* @public
- */
+ */
this.setUTF8 = function (a) {
if (typeof a === 'boolean') {
utf8 = a;
oldc = c;
oldd = d;
olde = e;
-
+
for (j = 0; j < 80; j+=1) {
- if (j < 16) {
- w[j] = x[i + j];
- } else {
- w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
+ if (j < 16) {
+ w[j] = x[i + j];
+ } else {
+ w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
}
t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
/**
* @class Hashes.SHA256
* @param {config}
- *
+ *
* A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
* Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
sha256_K;
/* privileged (public) methods */
- this.hex = function (s) {
- return rstr2hex(rstr(s, utf8));
+ this.hex = function (s) {
+ return rstr2hex(rstr(s, utf8));
};
- this.b64 = function (s) {
+ this.b64 = function (s) {
return rstr2b64(rstr(s, utf8), b64pad);
};
- this.any = function (s, e) {
- return rstr2any(rstr(s, utf8), e);
+ this.any = function (s, e) {
+ return rstr2any(rstr(s, utf8), e);
};
- this.hex_hmac = function (k, d) {
- return rstr2hex(rstr_hmac(k, d));
+ this.hex_hmac = function (k, d) {
+ return rstr2hex(rstr_hmac(k, d));
};
- this.b64_hmac = function (k, d) {
+ this.b64_hmac = function (k, d) {
return rstr2b64(rstr_hmac(k, d), b64pad);
};
- this.any_hmac = function (k, d, e) {
- return rstr2any(rstr_hmac(k, d), e);
+ this.any_hmac = function (k, d, e) {
+ return rstr2any(rstr_hmac(k, d), e);
};
/**
* Perform a simple self-test to see if the VM is working
this.vm_test = function () {
return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
};
- /**
- * Enable/disable uppercase hexadecimal returned string
- * @param {boolean}
+ /**
+ * Enable/disable uppercase hexadecimal returned string
+ * @param {boolean}
* @return {Object} this
* @public
- */
+ */
this.setUpperCase = function (a) {
- if (typeof a === 'boolean') {
+ if (typeof a === 'boolean') {
hexcase = a;
}
return this;
};
- /**
- * @description Defines a base64 pad string
+ /**
+ * @description Defines a base64 pad string
* @param {string} Pad
* @return {Object} this
* @public
- */
+ */
this.setPad = function (a) {
b64pad = a || b64pad;
return this;
};
- /**
- * Defines a base64 pad string
- * @param {boolean}
+ /**
+ * Defines a base64 pad string
+ * @param {boolean}
* @return {Object} this
* @public
- */
+ */
this.setUTF8 = function (a) {
if (typeof a === 'boolean') {
utf8 = a;
}
return this;
};
-
+
// private methods
/**
key = (utf8) ? utf8Encode(key) : key;
data = (utf8) ? utf8Encode(data) : data;
var hash, i = 0,
- bkey = rstr2binb(key),
- ipad = Array(16),
+ bkey = rstr2binb(key),
+ ipad = Array(16),
opad = Array(16);
if (bkey.length > 16) { bkey = binb(bkey, key.length * 8); }
-
+
for (; i < 16; i+=1) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
-
+
hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
return binb2rstr(binb(opad.concat(hash), 512 + 256));
}
-
+
/*
* Main sha256 function, with its support functions
*/
function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));}
function sha256_Gamma0512(x) {return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7));}
function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));}
-
+
sha256_K = [
1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993,
-1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872,
-1866530822, -1538233109, -1090935817, -965641998
];
-
+
function binb(m, l) {
var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
1359893119, -1694144372, 528734635, 1541459225];
var W = new Array(64);
var a, b, c, d, e, f, g, h;
var i, j, T1, T2;
-
+
/* append padding */
m[l >> 5] |= 0x80 << (24 - l % 32);
m[((l + 64 >> 9) << 4) + 15] = l;
-
+
for (i = 0; i < m.length; i += 16)
{
a = HASH[0];
f = HASH[5];
g = HASH[6];
h = HASH[7];
-
+
for (j = 0; j < 64; j+=1)
{
- if (j < 16) {
+ if (j < 16) {
W[j] = m[j + i];
- } else {
+ } else {
W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
sha256_Gamma0256(W[j - 15])), W[j - 16]);
}
-
+
T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
sha256_K[j]), W[j]);
T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
b = a;
a = safe_add(T1, T2);
}
-
+
HASH[0] = safe_add(a, HASH[0]);
HASH[1] = safe_add(b, HASH[1]);
HASH[2] = safe_add(c, HASH[2]);
/**
* @class Hashes.SHA512
* @param {config}
- *
+ *
* A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
* Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
- * See http://pajhome.org.uk/crypt/md5 for details.
+ * See http://pajhome.org.uk/crypt/md5 for details.
*/
SHA512 : function (options) {
/**
sha512_k;
/* privileged (public) methods */
- this.hex = function (s) {
- return rstr2hex(rstr(s));
+ this.hex = function (s) {
+ return rstr2hex(rstr(s));
};
- this.b64 = function (s) {
- return rstr2b64(rstr(s), b64pad);
+ this.b64 = function (s) {
+ return rstr2b64(rstr(s), b64pad);
};
- this.any = function (s, e) {
+ this.any = function (s, e) {
return rstr2any(rstr(s), e);
};
this.hex_hmac = function (k, d) {
return rstr2hex(rstr_hmac(k, d));
};
- this.b64_hmac = function (k, d) {
+ this.b64_hmac = function (k, d) {
return rstr2b64(rstr_hmac(k, d), b64pad);
};
- this.any_hmac = function (k, d, e) {
+ this.any_hmac = function (k, d, e) {
return rstr2any(rstr_hmac(k, d), e);
};
/**
this.vm_test = function () {
return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
};
- /**
- * @description Enable/disable uppercase hexadecimal returned string
- * @param {boolean}
+ /**
+ * @description Enable/disable uppercase hexadecimal returned string
+ * @param {boolean}
* @return {Object} this
* @public
- */
+ */
this.setUpperCase = function (a) {
if (typeof a === 'boolean') {
hexcase = a;
}
return this;
};
- /**
- * @description Defines a base64 pad string
+ /**
+ * @description Defines a base64 pad string
* @param {string} Pad
* @return {Object} this
* @public
- */
+ */
this.setPad = function (a) {
b64pad = a || b64pad;
return this;
};
- /**
- * @description Defines a base64 pad string
- * @param {boolean}
+ /**
+ * @description Defines a base64 pad string
+ * @param {boolean}
* @return {Object} this
* @public
- */
+ */
this.setUTF8 = function (a) {
if (typeof a === 'boolean') {
utf8 = a;
};
/* private methods */
-
+
/**
* Calculate the SHA-512 of a raw string
*/
function rstr_hmac(key, data) {
key = (utf8) ? utf8Encode(key) : key;
data = (utf8) ? utf8Encode(data) : data;
-
- var hash, i = 0,
+
+ var hash, i = 0,
bkey = rstr2binb(key),
ipad = Array(32), opad = Array(32);
if (bkey.length > 32) { bkey = binb(bkey, key.length * 8); }
-
+
for (; i < 32; i+=1) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
-
+
hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
return binb2rstr(binb(opad.concat(hash), 1024 + 512));
}
-
+
/**
* Calculate the SHA-512 of an array of big-endian dwords, and a bit length
*/
new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
];
}
-
+
for (i=0; i<80; i+=1) {
W[i] = new int64(0, 0);
}
-
+
// append padding to the source string. The format is described in the FIPS.
x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
x[((len + 128 >> 10)<< 5) + 31] = len;
int64copy(f, H[5]);
int64copy(g, H[6]);
int64copy(h, H[7]);
-
+
for (j=0; j<16; j+=1) {
W[j].h = x[i + 2*j];
W[j].l = x[i + 2*j + 1];
}
-
+
for (j=16; j<80; j+=1) {
//sigma1
int64rrot(r1, W[j-2], 19);
int64shr(r3, W[j-15], 7);
s0.l = r1.l ^ r2.l ^ r3.l;
s0.h = r1.h ^ r2.h ^ r3.h;
-
+
int64add4(W[j], s1, W[j-7], s0, W[j-16]);
}
-
+
for (j = 0; j < 80; j+=1) {
//Ch
Ch.l = (e.l & f.l) ^ (~e.l & g.l);
Ch.h = (e.h & f.h) ^ (~e.h & g.h);
-
+
//Sigma1
int64rrot(r1, e, 14);
int64rrot(r2, e, 18);
int64revrrot(r3, e, 9);
s1.l = r1.l ^ r2.l ^ r3.l;
s1.h = r1.h ^ r2.h ^ r3.h;
-
+
//Sigma0
int64rrot(r1, a, 28);
int64revrrot(r2, a, 2);
int64revrrot(r3, a, 7);
s0.l = r1.l ^ r2.l ^ r3.l;
s0.h = r1.h ^ r2.h ^ r3.h;
-
+
//Maj
Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
-
+
int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
int64add(T2, s0, Maj);
-
+
int64copy(h, g);
int64copy(g, f);
int64copy(f, e);
int64add(H[6], H[6], g);
int64add(H[7], H[7], h);
}
-
+
//represent the hash as an array of 32-bit dwords
for (i=0; i<8; i+=1) {
hash[2*i] = H[i].h;
}
return hash;
}
-
+
//A constructor for 64-bit numbers
function int64(h, l) {
this.h = h;
this.l = l;
//this.toString = int64toString;
}
-
+
//Copies src into dst, assuming both are 64-bit numbers
function int64copy(dst, src) {
dst.h = src.h;
dst.l = src.l;
}
-
+
//Right-rotates a 64-bit number by shift
//Won't handle cases of shift>=32
//The function revrrot() is for that
dst.l = (x.l >>> shift) | (x.h << (32-shift));
dst.h = (x.h >>> shift) | (x.l << (32-shift));
}
-
+
//Reverses the dwords of the source and then rotates right by shift.
//This is equivalent to rotation by 32+shift
function int64revrrot(dst, x, shift) {
dst.l = (x.h >>> shift) | (x.l << (32-shift));
dst.h = (x.l >>> shift) | (x.h << (32-shift));
}
-
+
//Bitwise-shifts right a 64-bit number by shift
//Won't handle shift>=32, but it's never needed in SHA512
function int64shr(dst, x, shift) {
dst.l = (x.l >>> shift) | (x.h << (32-shift));
dst.h = (x.h >>> shift);
}
-
+
//Adds two 64-bit numbers
//Like the original implementation, does not rely on 32-bit operations
function int64add(dst, x, y) {
dst.l = (w0 & 0xffff) | (w1 << 16);
dst.h = (w2 & 0xffff) | (w3 << 16);
}
-
+
//Same, except with 4 addends. Works faster than adding them one by one.
function int64add4(dst, a, b, c, d) {
var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
dst.l = (w0 & 0xffff) | (w1 << 16);
dst.h = (w2 & 0xffff) | (w3 << 16);
}
-
+
//Same, except with 5 addends
function int64add5(dst, a, b, c, d, e) {
var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
* @class Hashes.RMD160
* @constructor
* @param {Object} [config]
- *
+ *
* A JavaScript implementation of the RIPEMD-160 Algorithm
* Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
/* privileged (public) methods */
this.hex = function (s) {
- return rstr2hex(rstr(s, utf8));
+ return rstr2hex(rstr(s, utf8));
};
this.b64 = function (s) {
return rstr2b64(rstr(s, utf8), b64pad);
};
- this.any = function (s, e) {
+ this.any = function (s, e) {
return rstr2any(rstr(s, utf8), e);
};
- this.hex_hmac = function (k, d) {
+ this.hex_hmac = function (k, d) {
return rstr2hex(rstr_hmac(k, d));
};
- this.b64_hmac = function (k, d) {
+ this.b64_hmac = function (k, d) {
return rstr2b64(rstr_hmac(k, d), b64pad);
};
- this.any_hmac = function (k, d, e) {
- return rstr2any(rstr_hmac(k, d), e);
+ this.any_hmac = function (k, d, e) {
+ return rstr2any(rstr_hmac(k, d), e);
};
/**
* Perform a simple self-test to see if the VM is working
this.vm_test = function () {
return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
};
- /**
- * @description Enable/disable uppercase hexadecimal returned string
- * @param {boolean}
+ /**
+ * @description Enable/disable uppercase hexadecimal returned string
+ * @param {boolean}
* @return {Object} this
* @public
- */
+ */
this.setUpperCase = function (a) {
if (typeof a === 'boolean' ) { hexcase = a; }
return this;
};
- /**
- * @description Defines a base64 pad string
+ /**
+ * @description Defines a base64 pad string
* @param {string} Pad
* @return {Object} this
* @public
- */
+ */
this.setPad = function (a) {
if (typeof a !== 'undefined' ) { b64pad = a; }
return this;
};
- /**
- * @description Defines a base64 pad string
- * @param {boolean}
+ /**
+ * @description Defines a base64 pad string
+ * @param {boolean}
* @return {Object} this
* @public
- */
+ */
this.setUTF8 = function (a) {
if (typeof a === 'boolean') { utf8 = a; }
return this;
bkey = rstr2binl(key),
ipad = Array(16), opad = Array(16);
- if (bkey.length > 16) {
- bkey = binl(bkey, key.length * 8);
+ if (bkey.length > 16) {
+ bkey = binl(bkey, key.length * 8);
}
-
+
for (i = 0; i < 16; i+=1) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
x[len >> 5] |= 0x80 << (len % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
l = x.length;
-
+
for (i = 0; i < l; i+=16) {
A1 = A2 = h0; B1 = B2 = h1; C1 = C2 = h2; D1 = D2 = h3; E1 = E2 = h4;
for (j = 0; j <= 79; j+=1) {
return [h0, h1, h2, h3, h4];
}
- // specific algorithm methods
+ // specific algorithm methods
function rmd160_f(j, x, y, z) {
return ( 0 <= j && j <= 15) ? (x ^ y ^ z) :
(16 <= j && j <= 31) ? (x & y) | (~x & z) :
/**!
* is
* the definitive JavaScript type testing library
- *
+ *
* @copyright 2013 Enrico Marino
* @license MIT
*/
},{}]},{},[1])(1)
});
-;/*
+;
+/*
(c) 2013, Vladimir Agafonkin
RBush, a JavaScript library for high-performance 2D spatial indexing of points and rectangles.
https://github.com/mourner/rbush
}).call(function() {
return this || (typeof window !== 'undefined' ? window : global);
}());
-/* jshint ignore:start */
(function () {
'use strict';
window.iD = function () {
// https://github.com/openstreetmap/iD/issues/772
// http://mathiasbynens.be/notes/localstorage-pattern#comment-9
- try { storage = localStorage; } catch (e) {}
+ try { storage = localStorage; } catch (e) {} // eslint-disable-line no-empty
storage = storage || (function() {
var s = {};
return {
else storage.setItem(k, v);
} catch(e) {
// localstorage quota exceeded
- /* jshint devel:true */
+ /* eslint-disable no-console */
if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
- /* jshint devel:false */
+ /* eslint-enable no-console */
}
};
context.pan = map.pan;
context.zoomIn = map.zoomIn;
context.zoomOut = map.zoomOut;
+ context.zoomInFurther = map.zoomInFurther;
+ context.zoomOutFurther = map.zoomOutFurther;
context.surfaceRect = function() {
// Work around a bug in Firefox.
return d3.rebind(context, dispatch, 'on');
};
-iD.version = '1.7.3';
+iD.version = '1.8.2';
(function() {
var detected = {};
var ua = navigator.userAgent,
m = null;
- m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i); // IE11+
+ m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i); // Edge
if (m !== null) {
- detected.browser = 'msie';
- detected.version = m[1];
+ detected.browser = m[1];
+ detected.version = m[2];
+ }
+ if (!detected.browser) {
+ m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i); // IE11
+ if (m !== null) {
+ detected.browser = 'msie';
+ detected.version = m[1];
+ }
}
if (!detected.browser) {
m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i); // Opera 15+
detected.version = detected.version.split(/\W/).slice(0,2).join('.');
if (detected.browser.toLowerCase() === 'msie') {
+ detected.ie = true;
detected.browser = 'Internet Explorer';
- detected.support = parseFloat(detected.version) > 9;
+ detected.support = parseFloat(detected.version) >= 11;
} else {
+ detected.ie = false;
detected.support = true;
}
// Added due to incomplete svg style support. See #715
detected.opera = (detected.browser.toLowerCase() === 'opera' && parseFloat(detected.version) < 15 );
- detected.locale = navigator.language || navigator.userLanguage || 'en-US';
+ detected.locale = (navigator.languages && navigator.languages.length)
+ ? navigator.languages[0] : (navigator.language || navigator.userLanguage || 'en-US');
detected.filedrop = (window.FileReader && 'ondrop' in window);
return _.omit(parameters, 'geometry', 'debounce');
}
- function shorten(parameters) {
- if (!parameters.query) {
- delete parameters.query;
- } else {
- parameters.query = parameters.query.slice(0, 3);
- }
- return parameters;
- }
-
function popularKeys(parameters) {
var pop_field = 'count_all';
if (parameters.filter) pop_field = 'count_' + parameters.filter;
- return function(d) { return parseFloat(d[pop_field]) > 10000; };
+ return function(d) { return parseFloat(d[pop_field]) > 5000 || d.in_wiki; };
}
function popularValues() {
taginfo.keys = function(parameters, callback) {
var debounce = parameters.debounce;
- parameters = clean(shorten(setSort(parameters)));
+ parameters = clean(setSort(parameters));
request(endpoint + 'keys/all?' +
iD.util.qsString(_.extend({
rp: 10,
taginfo.values = function(parameters, callback) {
var debounce = parameters.debounce;
- parameters = clean(shorten(setSort(setFilter(parameters))));
+ parameters = clean(setSort(setFilter(parameters)));
request(endpoint + 'key/values?' +
iD.util.qsString(_.extend({
rp: 25,
if (parameters.value) path = 'tag/wiki_pages?';
else if (parameters.rtype) path = 'relation/wiki_pages?';
- request(endpoint + path +
- iD.util.qsString(parameters), debounce, callback);
+ request(endpoint + path + iD.util.qsString(parameters), debounce, function(err, d) {
+ if (err) return callback(err);
+ callback(null, d.data);
+ });
};
taginfo.endpoint = function(_) {
};
};
-/* jshint -W103 */
+/* eslint-disable no-proto */
iD.util.getPrototypeOf = Object.getPrototypeOf || function(obj) { return obj.__proto__; };
+/* eslint-enable no-proto */
iD.util.asyncMap = function(inputs, func, callback) {
var remaining = inputs.length,
func(d, function done(err, data) {
errors[i] = err;
results[i] = data;
- remaining --;
+ remaining--;
if (!remaining) callback(errors, results);
});
});
});
};
-iD.geo.polygonIntersectsPolygon = function(outer, inner) {
+iD.geo.polygonIntersectsPolygon = function(outer, inner, checkSegments) {
function testSegments(outer, inner) {
for (var i = 0; i < outer.length - 1; i++) {
for (var j = 0; j < inner.length - 1; j++) {
return false;
}
- return _.some(inner, function(point) {
- return iD.geo.pointInPolygon(point, outer);
- }) || testSegments(outer, inner);
+ function testPoints(outer, inner) {
+ return _.some(inner, function(point) {
+ return iD.geo.pointInPolygon(point, outer);
+ });
+ }
+
+ return testPoints(outer, inner) || (!!checkSegments && testSegments(outer, inner));
};
iD.geo.pathLength = function(path) {
iD.geo.Intersection = function(graph, vertexId) {
var vertex = graph.entity(vertexId),
- highways = [];
+ parentWays = graph.parentWays(vertex),
+ coincident = [],
+ highways = {};
+
+ function addHighway(way, adjacentNodeId) {
+ if (highways[adjacentNodeId]) {
+ coincident.push(adjacentNodeId);
+ } else {
+ highways[adjacentNodeId] = way;
+ }
+ }
// Pre-split ways that would need to be split in
// order to add a restriction. The real split will
// happen when the restriction is added.
- graph.parentWays(vertex).forEach(function(way) {
+ parentWays.forEach(function(way) {
if (!way.tags.highway || way.isArea() || way.isDegenerate())
return;
- if (way.affix(vertexId)) {
- highways.push(way);
- } else {
- var idx = _.indexOf(way.nodes, vertex.id, 1),
- wayA = iD.Way({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, idx + 1)}),
- wayB = iD.Way({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(idx)});
+ var isFirst = (vertexId === way.first()),
+ isLast = (vertexId === way.last()),
+ isAffix = (isFirst || isLast),
+ isClosingNode = (isFirst && isLast);
- graph = graph.replace(wayA);
- graph = graph.replace(wayB);
+ if (isAffix && !isClosingNode) {
+ var index = (isFirst ? 1 : way.nodes.length - 2);
+ addHighway(way, way.nodes[index]);
- highways.push(wayA);
- highways.push(wayB);
+ } else {
+ var splitIndex, wayA, wayB, indexA, indexB;
+ if (isClosingNode) {
+ splitIndex = Math.ceil(way.nodes.length / 2); // split at midpoint
+ wayA = iD.Way({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex)});
+ wayB = iD.Way({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
+ indexA = 1;
+ indexB = way.nodes.length - 2;
+ } else {
+ splitIndex = _.indexOf(way.nodes, vertex.id, 1); // split at vertexid
+ wayA = iD.Way({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex + 1)});
+ wayB = iD.Way({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
+ indexA = splitIndex - 1;
+ indexB = splitIndex + 1;
+ }
+ graph = graph.replace(wayA).replace(wayB);
+ addHighway(wayA, way.nodes[indexA]);
+ addHighway(wayB, way.nodes[indexB]);
}
});
+ // remove any ways from this intersection that are coincident
+ // (i.e. any adjacent node used by more than one intersecting way)
+ coincident.forEach(function (n) {
+ delete highways[n];
+ });
+
+
var intersection = {
highways: highways,
+ ways: _.values(highways),
graph: graph
};
- intersection.turns = function(fromNodeID) {
- if (!fromNodeID)
+ intersection.adjacentNodeId = function(fromWayId) {
+ return _.find(_.keys(highways), function(k) {
+ return highways[k].id === fromWayId;
+ });
+ };
+
+ intersection.turns = function(fromNodeId) {
+ var start = highways[fromNodeId];
+ if (!start)
return [];
- var way = _.find(highways, function(way) { return way.contains(fromNodeID); });
- if (way.first() === vertex.id && way.tags.oneway === 'yes')
+ if (start.first() === vertex.id && start.tags.oneway === 'yes')
return [];
- if (way.last() === vertex.id && way.tags.oneway === '-1')
+ if (start.last() === vertex.id && start.tags.oneway === '-1')
return [];
function withRestriction(turn) {
}
var from = {
- node: way.nodes[way.first() === vertex.id ? 1 : way.nodes.length - 2],
- way: way.id.split(/-(a|b)/)[0]
+ node: fromNodeId,
+ way: start.id.split(/-(a|b)/)[0]
},
- via = {node: vertex.id},
+ via = { node: vertex.id },
turns = [];
- highways.forEach(function(parent) {
- if (parent === way)
+ _.each(highways, function(end, adjacentNodeId) {
+ if (end === start)
return;
- var index = parent.nodes.indexOf(vertex.id);
-
// backward
- if (parent.first() !== vertex.id && parent.tags.oneway !== 'yes') {
+ if (end.first() !== vertex.id && end.tags.oneway !== 'yes') {
turns.push(withRestriction({
from: from,
via: via,
- to: {node: parent.nodes[index - 1], way: parent.id.split(/-(a|b)/)[0]}
+ to: {
+ node: adjacentNodeId,
+ way: end.id.split(/-(a|b)/)[0]
+ }
}));
}
// forward
- if (parent.last() !== vertex.id && parent.tags.oneway !== '-1') {
+ if (end.last() !== vertex.id && end.tags.oneway !== '-1') {
turns.push(withRestriction({
from: from,
via: via,
- to: {node: parent.nodes[index + 1], way: parent.id.split(/-(a|b)/)[0]}
+ to: {
+ node: adjacentNodeId,
+ way: end.id.split(/-(a|b)/)[0]
+ }
}));
}
+
});
// U-turn
- if (way.tags.oneway !== 'yes' && way.tags.oneway !== '-1') {
+ if (start.tags.oneway !== 'yes' && start.tags.oneway !== '-1') {
turns.push(withRestriction({
from: from,
via: via,
}
function reverse(member) {
- return member.tags ? iD.actions.Reverse(member.id)(graph).entity(member.id) : member;
+ return member.tags ? iD.actions.Reverse(member.id, {reverseOneway: true})(graph).entity(member.id) : member;
}
while (array.length) {
var startIndex1 = way.nodes.lastIndexOf(startNode.id),
endIndex1 = way.nodes.lastIndexOf(endNode.id),
wayDirection1 = (endIndex1 - startIndex1);
- if (wayDirection1 < -1) { wayDirection1 = 1;}
+ if (wayDirection1 < -1) { wayDirection1 = 1; }
- /*jshint -W083 */
+ /* eslint-disable no-loop-func */
_.each(_.without(graph.parentWays(keyNodes[i]), way), function(sharedWay) {
if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id),
endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id),
wayDirection2 = (endIndex2 - startIndex2),
insertAt = endIndex2;
- if (wayDirection2 < -1) { wayDirection2 = 1;}
+ if (wayDirection2 < -1) { wayDirection2 = 1; }
if (wayDirection1 !== wayDirection2) {
inBetweenNodes.reverse();
graph = graph.replace(sharedWay);
}
});
- /*jshint +W083 */
+ /* eslint-enable no-loop-func */
}
}
for (var i = 0; i < nodeIds.length - 1; i++) {
var node = graph.entity(nodeIds[i]);
- /*jshint -W083 */
+ /* eslint-disable no-loop-func */
graph.parentWays(node).forEach(function(parent) {
if (!parent.areAdjacent(node.id, survivor.id)) {
graph = graph.replace(parent.replaceNode(node.id, survivor.id));
graph.parentRelations(node).forEach(function(parent) {
graph = graph.replace(parent.replaceMember(node, survivor));
});
- /*jshint +W083 */
+ /* eslint-enable no-loop-func */
survivor = survivor.mergeTags(node.tags);
graph = iD.actions.DeleteNode(node.id)(graph);
return 'not_adjacent';
var nodeIds = _.pluck(joined[0].nodes, 'id').slice(1, -1),
- relation;
+ relation,
+ tags = {},
+ conflicting = false;
joined[0].forEach(function(way) {
var parents = graph.parentRelations(way);
if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; }))
relation = parent;
});
+
+ for (var k in way.tags) {
+ if (!(k in tags)) {
+ tags[k] = way.tags[k];
+ } else if (tags[k] && iD.interestingTag(k) && tags[k] !== way.tags[k]) {
+ conflicting = true;
+ }
+ }
});
if (relation)
return 'restriction';
+
+ if (conflicting)
+ return 'conflicting_tags';
};
return action;
} else if (option === 'force_local' && local) {
target = iD.Entity(local);
- if (remote && remote.visible) {
+ if (remote) {
target = target.update({ version: remote.version });
}
updates.replacements.push(target);
- } else if (option === 'safe' && local && remote) {
+ } else if (option === 'safe' && local && remote && local.version !== remote.version) {
target = iD.Entity(local, { version: remote.version });
if (remote.visible) {
target = mergeLocation(remote, target);
via = graph.entity(turn.via.node),
to = graph.entity(turn.to.way);
+ function isClosingNode(way, nodeId) {
+ return nodeId === way.first() && nodeId === way.last();
+ }
+
function split(toOrFrom) {
var newID = toOrFrom.newID || iD.Way().id;
graph = iD.actions.Split(via.id, [newID])
}
}
- if (!from.affix(via.id)) {
+ if (!from.affix(via.id) || isClosingNode(from, via.id)) {
if (turn.from.node === turn.to.node) {
// U-turn
from = to = split(turn.from)[0];
} else if (turn.from.way === turn.to.way) {
- // Straight-on
+ // Straight-on or circular
var s = split(turn.from);
from = s[0];
to = s[1];
}
}
- if (!to.affix(via.id)) {
+ if (!to.affix(via.id) || isClosingNode(to, via.id)) {
to = split(turn.to)[0];
}
http://wiki.openstreetmap.org/wiki/Route#Members
http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
*/
-iD.actions.Reverse = function(wayId) {
+iD.actions.Reverse = function(wayId, options) {
var replacements = [
[/:right$/, ':left'], [/:left$/, ':right'],
[/:forward$/, ':backward'], [/:backward$/, ':forward']
return value.replace(numeric, function(_, sign) { return sign === '-' ? '' : '-'; });
} else if (key === 'incline' || key === 'direction') {
return {up: 'down', down: 'up'}[value] || value;
+ } else if (options && options.reverseOneway && key === 'oneway') {
+ return {yes: '-1', '1': '-1', '-1': 'yes'}[value] || value;
} else {
return {left: 'right', right: 'left'}[value] || value;
}
};
iD.behavior.Draw = function(context) {
var event = d3.dispatch('move', 'click', 'clickWay',
- 'clickNode', 'undo', 'cancel', 'finish'),
+ 'clickNode', 'undo', 'cancel', 'finish'),
keybinding = d3.keybinding('draw'),
hover = iD.behavior.Hover(context)
.altDisables(true)
function mousedown() {
function point() {
- var p = element.node().parentNode;
+ var p = context.container().node();
return touchId !== null ? d3.touches(p).filter(function(p) {
return p.identifier === touchId;
})[0] : d3.mouse(p);
var element = d3.select(this),
touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null,
- time = +new Date(),
- pos = point();
+ t1 = +new Date(),
+ p1 = point();
element.on('mousemove.draw', null);
d3.select(window).on('mouseup.draw', function() {
+ var t2 = +new Date(),
+ p2 = point(),
+ dist = iD.geo.euclideanDistance(p1, p2);
+
element.on('mousemove.draw', mousemove);
- if (iD.geo.euclideanDistance(pos, point()) < closeTolerance ||
- (iD.geo.euclideanDistance(pos, point()) < tolerance &&
- (+new Date() - time) < 500)) {
+ d3.select(window).on('mouseup.draw', null);
+ if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
// Prevent a quick second click
d3.select(window).on('click.draw-block', function() {
d3.event.stopPropagation();
};
function update() {
+ if (context.inIntro()) return;
var s1 = formatter(context.map());
if (s0 !== s1) location.replace(s0 = s1); // don't recenter the map!
}
};
mode.enter = function() {
- context.connection().authenticate(function() {
- context.ui().sidebar.show(ui);
+ context.connection().authenticate(function(err) {
+ if (err) {
+ cancel();
+ } else {
+ context.ui().sidebar.show(ui);
+ }
});
};
}
}
+ function toggleMenu() {
+ if (d3.select('.radial-menu').empty()) {
+ showMenu();
+ } else {
+ closeMenu();
+ }
+ }
+
mode.selectedIDs = function() {
return selectedIDs;
};
operations.unshift(iD.operations.Delete(selectedIDs, context));
- keybinding.on('⎋', function() {
- context.enter(iD.modes.Browse(context));
- }, true);
+ keybinding
+ .on('⎋', function() { context.enter(iD.modes.Browse(context)); }, true)
+ .on('space', toggleMenu);
operations.forEach(function(operation) {
operation.keys.forEach(function(key) {
return operation;
};
-iD.Connection = function() {
+iD.Connection = function(useHttps) {
+ if (typeof useHttps !== 'boolean') {
+ useHttps = window.location.protocol === 'https:';
+ }
+
var event = d3.dispatch('authenticating', 'authenticated', 'auth', 'loading', 'loaded'),
- url = 'http://www.openstreetmap.org',
+ protocol = useHttps ? 'https:' : 'http:',
+ url = protocol + '//www.openstreetmap.org',
connection = {},
inflight = {},
loadedTiles = {},
tileZoom = 16,
oauth = osmAuth({
- url: 'http://www.openstreetmap.org',
+ url: protocol + '//www.openstreetmap.org',
oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
loading: authenticating,
});
};
+ connection.loadEntityVersion = function(id, version, callback) {
+ var type = iD.Entity.id.type(id),
+ osmID = iD.Entity.id.toOSM(id);
+
+ connection.loadFromURL(
+ url + '/api/0.6/' + type + '/' + osmID + '/' + version,
+ function(err, entities) {
+ if (callback) callback(err, {data: entities});
+ });
+ };
+
connection.loadMultiple = function(ids, callback) {
_.each(_.groupBy(_.uniq(ids), iD.Entity.id.type), function(v, k) {
var type = k + 's',
tag: _.map(tags, function(value, key) {
return { '@k': key, '@v': value };
}),
- '@version': 0.3,
+ '@version': 0.6,
'@generator': 'iD'
}
}
return {
osmChange: {
- '@version': 0.3,
+ '@version': 0.6,
'@generator': 'iD',
'create': nest(changes.created.map(rep), ['node', 'way', 'relation']),
'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']),
created_by: 'iD ' + iD.version,
imagery_used: imageryUsed.join(';').substr(0, 255),
host: (window.location.origin + window.location.pathname).substr(0, 255),
- locale: detected.locale,
+ locale: detected.locale
};
if (comment) {
},
hasInterestingTags: function() {
- return _.keys(this.tags).some(function(key) {
- return key !== 'attribution' &&
- key !== 'created_by' &&
- key !== 'source' &&
- key !== 'odbl' &&
- key.indexOf('tiger:') !== 0;
- });
+ return _.keys(this.tags).some(iD.interestingTag);
},
isHighwayIntersection: function() {
};
},
+ validate: function(changes) {
+ return _(iD.validations)
+ .map(function(fn) { return fn()(changes, stack[index].graph); })
+ .flatten()
+ .value();
+ },
+
hasChanges: function() {
return this.difference().length() > 0;
},
},
toJSON: function() {
- if (stack.length <= 1) return;
+ if (!this.hasChanges()) return;
var allEntities = {},
baseEntities = {},
});
},
- fromJSON: function(json) {
+ fromJSON: function(json, loadChildNodes) {
var h = JSON.parse(json);
iD.Entity.id.next = h.nextIDs;
});
if (h.version === 3) {
- // this merges originals for changed entities into the base of
+ // This merges originals for changed entities into the base of
// the stack even if the current stack doesn't have them (for
// example when iD has been restarted in a different region)
var baseEntities = h.baseEntities.map(function(entity) {
});
stack[0].graph.rebase(baseEntities, _.pluck(stack, 'graph'), true);
tree.rebase(baseEntities, true);
+
+ // When we restore a modified way, we also need to fetch any missing
+ // childnodes that would normally have been downloaded with it.. #2142
+ if (loadChildNodes) {
+ var missing = _(baseEntities)
+ .filter('type', 'way')
+ .pluck('nodes')
+ .flatten()
+ .uniq()
+ .reject(function(n) { return stack[0].graph.hasEntity(n); })
+ .value();
+
+ if (!_.isEmpty(missing)) {
+ var childNodesLoaded = function(err, result) {
+ if (err) return;
+
+ var visible = _.groupBy(result.data, 'visible');
+ if (!_.isEmpty(visible.true)) {
+ stack[0].graph.rebase(visible.true, _.pluck(stack, 'graph'), false);
+ tree.rebase(visible.true, false);
+ }
+
+ // fetch older versions of nodes that were deleted..
+ _.each(visible.false, function(entity) {
+ context.connection()
+ .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
+ });
+ };
+
+ context.connection().loadMultiple(missing, childNodesLoaded);
+ }
+ }
}
stack = h.stack.map(function(d) {
if (!lock.locked()) return;
var json = context.storage(getKey('saved_history'));
- if (json) history.fromJSON(json);
+ if (json) history.fromJSON(json, true);
},
_getKey: getKey
};
}
});
-iD.oneWayTags = {
- 'aerialway': {
- 'chair_lift': true,
- 'mixed_lift': true,
- 't-bar': true,
- 'j-bar': true,
- 'platter': true,
- 'rope_tow': true,
- 'magic_carpet': true,
- 'yes': true
- },
- 'highway': {
- 'motorway': true,
- 'motorway_link': true
- },
- 'junction': {
- 'roundabout': true
- },
- 'man_made': {
- 'piste:halfpipe': true
- },
- 'piste:type': {
- 'downhill': true,
- 'sled': true,
- 'yes': true
- },
- 'waterway': {
- 'river': true,
- 'stream': true
- }
-};
iD.Relation = iD.Entity.relation = function iD_Relation() {
if (!(this instanceof iD_Relation)) {
return (new iD_Relation()).initialize(arguments);
return result;
}
});
+iD.oneWayTags = {
+ 'aerialway': {
+ 'chair_lift': true,
+ 'mixed_lift': true,
+ 't-bar': true,
+ 'j-bar': true,
+ 'platter': true,
+ 'rope_tow': true,
+ 'magic_carpet': true,
+ 'yes': true
+ },
+ 'highway': {
+ 'motorway': true,
+ 'motorway_link': true
+ },
+ 'junction': {
+ 'roundabout': true
+ },
+ 'man_made': {
+ 'piste:halfpipe': true
+ },
+ 'piste:type': {
+ 'downhill': true,
+ 'sled': true,
+ 'yes': true
+ },
+ 'waterway': {
+ 'river': true,
+ 'stream': true
+ }
+};
+
+iD.pavedTags = {
+ 'surface': {
+ 'paved': true,
+ 'asphalt': true,
+ 'concrete': true
+ },
+ 'tracktype': {
+ 'grade1': true
+ }
+};
+
+iD.interestingTag = function (key) {
+ return key !== 'attribution' &&
+ key !== 'created_by' &&
+ key !== 'source' &&
+ key !== 'odbl' &&
+ key.indexOf('tiger:') !== 0;
+
+};
iD.Tree = function(head) {
var rtree = rbush(),
rectangles = {};
reader.onload = function(e) {
gpxLayer.geojson(toGeoJSON.gpx(toDom(e.target.result)));
+ iD.ui.MapInMap.gpxLayer.geojson(toGeoJSON.gpx(toDom(e.target.result)));
background.zoomToGpxLayer();
dispatch.change();
};
return _.union(coords, feature.geometry.type === 'Point' ? [c] : c);
}, []);
- if (!iD.geo.polygonIntersectsPolygon(viewport, coords)) {
+ if (!iD.geo.polygonIntersectsPolygon(viewport, coords, true)) {
var extent = iD.geo.Extent(d3.geo.bounds(gpxLayer.geojson()));
map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
}
background.toggleGpxLayer = function() {
gpxLayer.enable(!gpxLayer.enable());
+ iD.ui.MapInMap.gpxLayer.enable(!iD.ui.MapInMap.gpxLayer.enable());
dispatch.change();
};
};
background.load = function(imagery) {
+ function parseMap(qmap) {
+ if (!qmap) return false;
+ var args = qmap.split('/').map(Number);
+ if (args.length < 3 || args.some(isNaN)) return false;
+ return iD.geo.Extent([args[1], args[2]]);
+ }
+
+ var q = iD.util.stringQs(location.hash.substring(1)),
+ chosen = q.background || q.layer,
+ extent = parseMap(q.map),
+ best;
+
backgroundSources = imagery.map(function(source) {
if (source.type === 'bing') {
return iD.BackgroundSource.Bing(source, dispatch);
backgroundSources.unshift(iD.BackgroundSource.None());
- var q = iD.util.stringQs(location.hash.substring(1)),
- chosen = q.background || q.layer;
+ if (!chosen && extent) {
+ best = this.sources(extent).find(function(s) { return s.best(); });
+ }
if (chosen && chosen.indexOf('custom:') === 0) {
background.baseLayerSource(iD.BackgroundSource.Custom(chosen.replace(/^custom:/, '')));
} else {
- background.baseLayerSource(findSource(chosen) || findSource('Bing') || backgroundSources[1]);
+ background.baseLayerSource(findSource(chosen) || best || findSource('Bing') || backgroundSources[1]);
}
var locator = _.find(backgroundSources, function(d) {
var gpx = q.gpx;
if (gpx) {
d3.text(gpx, function(err, gpxTxt) {
- gpxLayer.geojson(toGeoJSON.gpx(toDom(gpxTxt)));
- dispatch.change();
+ if (!err) {
+ gpxLayer.geojson(toGeoJSON.gpx(toDom(gpxTxt)));
+ iD.ui.MapInMap.gpxLayer.geojson(toGeoJSON.gpx(toDom(gpxTxt)));
+ dispatch.change();
+ }
});
}
};
iD.BackgroundSource = function(data) {
var source = _.clone(data),
offset = [0, 0],
- name = source.name;
+ name = source.name,
+ best = !!source.best;
source.scaleExtent = data.scaleExtent || [0, 20];
source.overzoom = data.overzoom !== false;
return name;
};
+ source.best = function() {
+ return best;
+ };
+
source.imageryUsed = function() {
return source.id || name;
};
source.intersects = function(extent) {
extent = extent.polygon();
return !data.polygon || data.polygon.some(function(polygon) {
- return iD.geo.polygonIntersectsPolygon(polygon, extent);
+ return iD.geo.polygonIntersectsPolygon(polygon, extent, true);
});
};
'cycleway': true,
'bridleway': true,
'steps': true,
- 'pedestrian': true
+ 'pedestrian': true,
+ 'corridor': true
};
var past_futures = {
var dimensions = [1, 1],
dispatch = d3.dispatch('move', 'drawn'),
projection = context.projection,
- roundedProjection = iD.svg.RoundProjection(projection),
zoom = d3.behavior.zoom()
.translate(projection.translate())
.scale(projection.scale() * 2 * Math.PI)
transformStart,
transformed = false,
minzoom = 0,
- points = iD.svg.Points(roundedProjection, context),
- vertices = iD.svg.Vertices(roundedProjection, context),
+ points = iD.svg.Points(projection, context),
+ vertices = iD.svg.Vertices(projection, context),
lines = iD.svg.Lines(projection),
areas = iD.svg.Areas(projection),
- midpoints = iD.svg.Midpoints(roundedProjection, context),
+ midpoints = iD.svg.Midpoints(projection, context),
labels = iD.svg.Labels(projection, context),
supersurface, surface,
mouse,
.scale(d3.event.scale / (2 * Math.PI));
var scale = d3.event.scale / transformStart[0],
- tX = Math.round((d3.event.translate[0] / scale - transformStart[1][0]) * scale),
- tY = Math.round((d3.event.translate[1] / scale - transformStart[1][1]) * scale);
+ tX = (d3.event.translate[0] / scale - transformStart[1][0]) * scale,
+ tY = (d3.event.translate[1] / scale - transformStart[1][1]) * scale;
transformed = true;
iD.util.setTransform(supersurface, tX, tY, scale);
}
function redraw(difference, extent) {
-
if (!surface) return;
clearTimeout(timeoutId);
return redraw();
};
- map.zoomIn = function() { interpolateZoom(~~map.zoom() + 1); };
- map.zoomOut = function() { interpolateZoom(~~map.zoom() - 1); };
+ function zoomIn(integer) {
+ interpolateZoom(~~map.zoom() + integer);
+ }
+
+ function zoomOut(integer) {
+ interpolateZoom(~~map.zoom() - integer);
+ }
+
+ map.zoomIn = function() { zoomIn(1); };
+ map.zoomInFurther = function() { zoomIn(4); };
+
+ map.zoomOut = function() { zoomOut(1); };
+ map.zoomOutFurther = function() { zoomOut(4); };
map.center = function(loc) {
if (!arguments.length) {
enter.append('button')
.on('click', hide)
.append('div')
- .attr('class', 'icon close');
+ .call(iD.svg.Icon('#icon-close'));
enter.append('img');
- var link = enter.append('a')
+ enter
+ .append('a')
.attr('class', 'link')
- .attr('target', '_blank');
-
- link.append('span')
- .attr('class', 'icon icon-pre-text out-link');
-
- link.append('span')
+ .attr('target', '_blank')
+ .call(iD.svg.Icon('#icon-out-link', 'inline'))
+ .append('span')
.text(t('mapillary.view_on_mapillary'));
if (!enable) {
.attr('class', 'image');
enter.append('path')
- .attr('d', 'M 0,-5 l 0,-20 l -5,30 l 10,0 l -5,-30');
+ .attr('class', 'viewfield')
+ .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
+ .attr('d', 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z');
enter.append('circle')
.attr('dx', '0')
.attr('dy', '0')
- .attr('r', '8');
+ .attr('r', '6');
g.attr('transform', transform);
source = d3.functor('');
function tileSizeAtZoom(d, z) {
- return Math.ceil(tileSize * Math.pow(2, z - d[2])) / tileSize;
+ return (tileSize * Math.pow(2, z - d[2])) / tileSize;
}
function atZoom(t, distance) {
}
var pixelOffset = [
- Math.round(source.offset()[0] * Math.pow(2, z)),
- Math.round(source.offset()[1] * Math.pow(2, z))
+ source.offset()[0] * Math.pow(2, z),
+ source.offset()[1] * Math.pow(2, z)
];
function load(d) {
var _ts = tileSize * Math.pow(2, z - d[2]);
var scale = tileSizeAtZoom(d, z);
return 'translate(' +
- (Math.round((d[0] * _ts) - tileOrigin[0]) + pixelOffset[0]) + 'px,' +
- (Math.round((d[1] * _ts) - tileOrigin[1]) + pixelOffset[1]) + 'px)' +
+ ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0]) + 'px,' +
+ ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1]) + 'px)' +
'scale(' + scale + ',' + scale + ')';
}
return background;
};
iD.svg = {
- RoundProjection: function(projection) {
- return function(d) {
- return iD.geo.roundCoords(projection(d));
- };
- },
-
PointTransform: function(projection) {
return function(entity) {
// http://jsperf.com/short-array-join
};
},
- Round: function () {
- return d3.geo.transform({
- point: function(x, y) { return this.stream.point(Math.floor(x), Math.floor(y)); }
- });
- },
-
Path: function(projection, graph, polygon) {
var cache = {},
- round = iD.svg.Round().stream,
clip = d3.geo.clipExtent().extent(projection.clipExtent()).stream,
project = projection.stream,
path = d3.geo.path()
- .projection({stream: function(output) { return polygon ? project(round(output)) : project(clip(round(output))); }});
+ .projection({stream: function(output) { return polygon ? project(output) : project(clip(output)); }});
return function(entity) {
if (entity.id in cache) {
return cache[entity.id];
} else {
- return cache[entity.id] = path(entity.asGeoJSON(graph)); // jshint ignore:line
+ return cache[entity.id] = path(entity.asGeoJSON(graph));
}
};
},
used once globally, since defs IDs must be unique within a document.
*/
iD.svg.Defs = function(context) {
- function autosize(image) {
- var img = document.createElement('img');
- img.src = image.attr('xlink:href');
- img.onload = function() {
- image.attr({
- width: img.width,
- height: img.height
- });
- };
- }
- function SpriteDefinition(id, href, data) {
+ function SVGSpriteDefinition(id, href) {
return function(defs) {
- defs.append('image')
- .attr('id', id)
- .attr('xlink:href', href)
- .call(autosize);
-
- defs.selectAll()
- .data(data)
- .enter().append('use')
- .attr('id', function(d) { return d.key; })
- .attr('transform', function(d) { return 'translate(-' + d.value[0] + ',-' + d.value[1] + ')'; })
- .attr('xlink:href', '#' + id);
+ d3.xml(href, 'image/svg+xml', function(err, svg) {
+ if (err) return;
+ defs.node().appendChild(
+ d3.select(svg.documentElement).attr('id', id).node()
+ );
+ });
};
}
return function (selection) {
var defs = selection.append('defs');
+ // marker
defs.append('marker')
.attr({
id: 'oneway-marker',
refX: 5,
markerWidth: 2,
markerHeight: 2,
+ markerUnits: 'strokeWidth',
orient: 'auto'
})
.append('path')
- .attr('d', 'M 5 3 L 0 3 L 0 2 L 5 2 L 5 0 L 10 2.5 L 5 5 z');
+ .attr('class', 'oneway')
+ .attr('d', 'M 5 3 L 0 3 L 0 2 L 5 2 L 5 0 L 10 2.5 L 5 5 z')
+ .attr('stroke', 'none')
+ .attr('fill', '#000')
+ .attr('opacity', '0.5');
+ // patterns
var patterns = defs.selectAll('pattern')
.data([
// pattern name, pattern image name
return context.imagePath('pattern/' + d[1] + '.png');
});
+ // clip paths
defs.selectAll()
.data([12, 18, 20, 32, 45])
.enter().append('clipPath')
return d;
});
- var maki = [];
- _.forEach(iD.data.featureIcons, function (dimensions, name) {
- if (dimensions['12'] && dimensions['18'] && dimensions['24']) {
- maki.push({key: 'maki-' + name + '-12', value: dimensions['12']});
- maki.push({key: 'maki-' + name + '-18', value: dimensions['18']});
- maki.push({key: 'maki-' + name + '-24', value: dimensions['24']});
- }
- });
-
- defs.call(SpriteDefinition(
- 'sprite',
- context.imagePath('sprite.svg'),
- d3.entries(iD.data.operations)));
+ defs.call(SVGSpriteDefinition(
+ 'iD-sprite',
+ context.imagePath('iD-sprite.svg')));
- defs.call(SpriteDefinition(
+ defs.call(SVGSpriteDefinition(
'maki-sprite',
- context.imagePath('maki-sprite.png'),
- maki));
+ context.imagePath('maki-sprite.svg')));
+ };
+};
+iD.svg.Icon = function(name, svgklass, useklass) {
+ return function (selection) {
+ selection.selectAll('svg')
+ .data([0])
+ .enter()
+ .append('svg')
+ .attr('class', 'icon ' + (svgklass || ''))
+ .append('use')
+ .attr('xlink:href', name)
+ .attr('class', useklass);
};
};
iD.svg.Labels = function(projection, context) {
}
function drawAreaIcons(group, entities, filter, classes, labels) {
-
var icons = group.selectAll('use')
.filter(filter)
.data(entities, iD.Entity.key);
icons.enter()
.append('use')
- .attr('clip-path', 'url(#clip-square-18)')
- .attr('class', 'icon');
+ .attr('class', 'icon areaicon')
+ .attr('width', '18px')
+ .attr('height', '18px');
icons.attr('transform', get(labels, 'transform'))
.attr('xlink:href', function(d) {
- return '#maki-' + context.presets().match(d, context.graph()).icon + '-18';
+ var icon = context.presets().match(d, context.graph()).icon;
+ return '#' + icon + (icon === 'hairdresser' ? '-24': '-18'); // workaround: maki hairdresser-18 broken?
});
function reverse(p) {
var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
- return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > - Math.PI/2);
+ return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2);
}
function lineString(nodes) {
if (!icon && !iD.util.displayName(entity))
continue;
- for (k = 0; k < label_stack.length; k ++) {
+ for (k = 0; k < label_stack.length; k++) {
if (geometry === label_stack[k][0] && entity.tags[label_stack[k][1]]) {
labelable[k].push(entity);
break;
// Try and find a valid label for labellable entities
for (k = 0; k < labelable.length; k++) {
var font_size = font_sizes[k];
- for (i = 0; i < labelable[k].length; i ++) {
+ for (i = 0; i < labelable[k].length; i++) {
entity = labelable[k][i];
var name = iD.util.displayName(entity),
width = name && textWidth(name, font_size),
length = iD.geo.pathLength(nodes);
if (length < width + 20) return;
- for (var i = 0; i < lineOffsets.length; i ++) {
+ for (var i = 0; i < lineOffsets.length; i++) {
var offset = lineOffsets[i],
middle = offset / 100 * length,
start = middle - width/2;
entitywidth = projection(extent[1])[0] - projection(extent[0])[0],
rect;
- if (!centroid || entitywidth < 20) return;
+ if (isNaN(centroid[0]) || entitywidth < 20) return;
var iconX = centroid[0] - (iconSize/2),
iconY = centroid[1] - (iconSize/2),
oneways
.attr('d', function(d) { return d.d; });
+ if (iD.detect().ie) {
+ oneways.each(function() { this.parentNode.insertBefore(this, this); });
+ }
+
oneways.exit()
.remove();
.call(markerPath, 'stroke');
group.append('use')
- .attr('class', 'icon')
.attr('transform', 'translate(-6, -20)')
- .attr('clip-path', 'url(#clip-square-12)');
+ .attr('class', 'icon')
+ .attr('width', '12px')
+ .attr('height', '12px');
groups.attr('transform', iD.svg.PointTransform(projection))
.call(iD.svg.TagClasses());
groups.select('.icon')
.attr('xlink:href', function(entity) {
var preset = context.presets().match(entity, context.graph());
- return preset.icon ? '#maki-' + preset.icon + '-12' : '';
+ return preset.icon ? '#' + preset.icon + '-12' : '';
});
groups.exit()
};
};
iD.svg.TagClasses = function() {
- var primary = [
+ var primaries = [
'building', 'highway', 'railway', 'waterway', 'aeroway',
'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse',
'leisure', 'place'
],
- secondary = [
- 'oneway', 'bridge', 'tunnel', 'construction', 'embankment', 'cutting', 'barrier'
+ statuses = [
+ 'proposed', 'construction', 'disused', 'abandoned', 'dismantled',
+ 'razed', 'demolished', 'obliterated'
+ ],
+ secondaries = [
+ 'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier',
+ 'surface', 'tracktype'
],
tagClassRe = /^tag-/,
tags = function(entity) { return entity.tags; };
+
var tagClasses = function(selection) {
selection.each(function tagClassesEach(entity) {
- var classes, value = this.className;
+ var value = this.className,
+ classes, primary, status;
if (value.baseVal !== undefined) value = value.baseVal;
var t = tags(entity), i, k, v;
- for (i = 0; i < primary.length; i++) {
- k = primary[i];
+ // pick at most one primary classification tag..
+ for (i = 0; i < primaries.length; i++) {
+ k = primaries[i];
v = t[k];
if (!v || v === 'no') continue;
- classes += ' tag-' + k + ' tag-' + k + '-' + v;
+
+ primary = k;
+ if (statuses.indexOf(v) !== -1) { // e.g. `railway=abandoned`
+ status = v;
+ classes += ' tag-' + k;
+ } else {
+ classes += ' tag-' + k + ' tag-' + k + '-' + v;
+ }
+
break;
}
- for (i = 0; i < secondary.length; i++) {
- k = secondary[i];
+ // add at most one status tag, only if relates to primary tag..
+ if (!status) {
+ for (i = 0; i < statuses.length; i++) {
+ k = statuses[i];
+ v = t[k];
+ if (!v || v === 'no') continue;
+
+ if (v === 'yes') { // e.g. `railway=rail + abandoned=yes`
+ status = k;
+ }
+ else if (primary && primary === v) { // e.g. `railway=rail + abandoned=railway`
+ status = k;
+ } else if (!primary && primaries.indexOf(v) !== -1) { // e.g. `abandoned=railway`
+ status = k;
+ primary = v;
+ classes += ' tag-' + v;
+ } // else ignore e.g. `highway=path + abandoned=railway`
+
+ if (status) break;
+ }
+ }
+
+ if (status) {
+ classes += ' tag-status tag-status-' + status;
+ }
+
+ // add any secondary (structure) tags
+ for (i = 0; i < secondaries.length; i++) {
+ k = secondaries[i];
v = t[k];
if (!v || v === 'no') continue;
classes += ' tag-' + k + ' tag-' + k + '-' + v;
}
+ // For highways, look for surface tagging..
+ if (primary === 'highway') {
+ var paved = (t.highway !== 'track');
+ for (k in t) {
+ v = t[k];
+ if (k in iD.pavedTags) {
+ paved = !!iD.pavedTags[k][v];
+ break;
+ }
+ }
+ if (!paved) {
+ classes += ' tag-unpaved';
+ }
+ }
+
classes = classes.trim();
if (classes !== value) {
function icon(turn) {
var u = turn.u ? '-u' : '';
if (!turn.restriction)
- return '#icon-restriction-yes' + u;
+ return '#turn-yes' + u;
var restriction = graph.entity(turn.restriction).tags.restriction;
- return '#icon-restriction-' +
+ return '#turn-' +
(!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
}
.data(turns, key);
// Enter
-
var enter = groups.enter().append('g')
.attr('class', 'turn');
var nEnter = enter.filter(function (turn) { return !turn.u; });
nEnter.append('rect')
- .attr('transform', 'translate(-12, -12)')
- .attr('width', '45')
- .attr('height', '25');
+ .attr('transform', 'translate(-22, -12)')
+ .attr('width', '44')
+ .attr('height', '24');
nEnter.append('use')
- .attr('transform', 'translate(-12, -12)')
- .attr('clip-path', 'url(#clip-square-45)');
+ .attr('transform', 'translate(-22, -12)')
+ .attr('width', '44')
+ .attr('height', '24');
+
var uEnter = enter.filter(function (turn) { return turn.u; });
uEnter.append('use')
.attr('transform', 'translate(-16, -16)')
- .attr('clip-path', 'url(#clip-square-32)');
+ .attr('width', '32')
+ .attr('height', '32');
- // Update
+ // Update
groups
.attr('transform', function (turn) {
var v = graph.entity(turn.via.node),
p = projection(v.loc),
r = turn.u ? 0 : 60;
- return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ')' +
+ return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ') ' +
'rotate(' + a * 180 / Math.PI + ')';
});
groups.select('rect');
groups.select('circle');
- // Exit
+ // Exit
groups.exit()
.remove();
return icons[entity.id];
}
- function classCircle(klass) {
+ function setClass(klass) {
return function(entity) {
this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
};
.attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
enter.append('circle')
- .each(classCircle('shadow'));
+ .each(setClass('shadow'));
enter.append('circle')
- .each(classCircle('stroke'));
+ .each(setClass('stroke'));
// Vertices with icons get a `use`.
enter.filter(function(d) { return icon(d); })
.append('use')
.attr('transform', 'translate(-6, -6)')
- .attr('clip-path', 'url(#clip-square-12)')
- .attr('xlink:href', function(d) { return '#maki-' + icon(d) + '-12'; });
+ .attr('xlink:href', function(d) { return '#' + icon(d) + '-12'; })
+ .attr('width', '12px')
+ .attr('height', '12px')
+ .each(setClass('icon'));
// Vertices with tags get a fill.
enter.filter(function(d) { return d.hasInterestingTags(); })
.append('circle')
- .each(classCircle('fill'));
+ .each(setClass('fill'));
groups
.attr('transform', iD.svg.PointTransform(projection))
hash();
if (!hash.hadHash) {
- map.centerZoom([-77.02271, 38.90085], 20);
+ map.centerZoom([0, 0], 2);
}
container.append('svg')
.attr('class', 'button-wrap col1')
.call(iD.ui.Save(context));
+ bar.append('div')
+ .attr('class', 'full-screen')
+ .call(iD.ui.FullScreen(context));
+
bar.append('div')
.attr('class', 'spinner')
.call(iD.ui.Spinner(context));
.attr('href', 'http://github.com/openstreetmap/iD')
.text(iD.version);
- var bugReport = aboutList.append('li')
- .append('a')
+ var issueLinks = aboutList.append('li');
+
+ issueLinks.append('a')
.attr('target', '_blank')
.attr('tabindex', -1)
- .attr('href', 'https://github.com/openstreetmap/iD/issues');
-
- bugReport.append('span')
- .attr('class','icon bug light');
-
- bugReport.call(bootstrap.tooltip()
+ .attr('href', 'https://github.com/openstreetmap/iD/issues')
+ .call(iD.svg.Icon('#icon-bug', 'light'))
+ .call(bootstrap.tooltip()
.title(t('report_a_bug'))
.placement('top')
);
+ issueLinks.append('a')
+ .attr('target', '_blank')
+ .attr('tabindex', -1)
+ .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating')
+ .call(iD.svg.Icon('#icon-translate', 'light'))
+ .call(bootstrap.tooltip()
+ .title(t('help_translate'))
+ .placement('top')
+ );
+
aboutList.append('li')
.attr('class', 'feature-warning')
.attr('tabindex', -1)
context.history().unlock();
};
+ var mapDimensions = map.dimensions();
+
d3.select(window).on('resize.editor', function() {
+ mapDimensions = m.dimensions();
map.dimensions(m.dimensions());
});
function pan(d) {
return function() {
+ d3.event.preventDefault();
context.pan(d);
};
}
// pan amount
- var pa = 5;
+ var pa = 10;
var keybinding = d3.keybinding('main')
.on('⌫', function() { d3.event.preventDefault(); })
.on('←', pan([pa, 0]))
.on('↑', pan([0, pa]))
.on('→', pan([-pa, 0]))
- .on('↓', pan([0, -pa]));
+ .on('↓', pan([0, -pa]))
+ .on('⇧←', pan([mapDimensions[0], 0]))
+ .on('⇧↑', pan([0, mapDimensions[1]]))
+ .on('⇧→', pan([-mapDimensions[0], 0]))
+ .on('⇧↓', pan([0, -mapDimensions[1]]))
+ .on(iD.ui.cmd('⌘←'), pan([mapDimensions[0], 0]))
+ .on(iD.ui.cmd('⌘↑'), pan([0, mapDimensions[1]]))
+ .on(iD.ui.cmd('⌘→'), pan([-mapDimensions[0], 0]))
+ .on(iD.ui.cmd('⌘↓'), pan([0, -mapDimensions[1]]));
d3.select(document)
.call(keybinding);
// Add thumbnail or dont
if (details.image_url) {
userLink.append('img')
- .attr('class', 'icon icon-pre-text user-icon')
+ .attr('class', 'icon pre-text user-icon')
.attr('src', details.image_url);
} else {
- userLink.append('span')
- .attr('class', 'icon avatar light icon-pre-text');
+ userLink
+ .call(iD.svg.Icon('#icon-avatar', 'pre-text light'));
}
// Add user name
['right', [-1, 0]],
['bottom', [0, 1]]],
opacityDefault = (context.storage('background-opacity') !== null) ?
- (+context.storage('background-opacity')) : 0.5,
+ (+context.storage('background-opacity')) : 1.0,
customTemplate = context.storage('background-custom-template') || '';
// Can be 0 from <1.3.0 use or due to issue #1923.
- if (opacityDefault === 0) opacityDefault = 0.5;
+ if (opacityDefault === 0) opacityDefault = 1.0;
function background(selection) {
+ function sortSources(a, b) {
+ return a.best() ? -1
+ : b.best() ? 1
+ : a.id === 'none' ? 1
+ : b.id === 'none' ? -1
+ : d3.ascending(a, b);
+ }
+
function setOpacity(d) {
var bg = context.container().selectAll('.background-layer')
.transition()
.filter(filter);
var layerLinks = layerList.selectAll('li.layer')
- .data(sources, function(d) { return d.name(); });
+ .data(sources, function(d) { return d.name(); })
+ .sort(sortSources);
var enter = layerLinks.enter()
.insert('li', '.custom_layer')
}
function clickNudge(d) {
-
var timeout = window.setTimeout(function() {
interval = window.setInterval(nudge, 100);
}, 500),
button = selection.append('button')
.attr('tabindex', -1)
.on('click', toggle)
+ .call(iD.svg.Icon('#icon-layers', 'light'))
.call(tooltip),
shown = false;
- button.append('span')
- .attr('class', 'icon layers light');
-
-
var opa = content.append('div')
.attr('class', 'opacity-options-wrapper');
.title(t('background.custom_button'))
.placement('left'))
.on('click', editCustom)
- .append('span')
- .attr('class', 'icon geocode');
+ .call(iD.svg.Icon('#icon-search'));
var label = custom.append('label');
var overlayList = content.append('ul')
.attr('class', 'layer-list');
+ var controls = content.append('div')
+ .attr('class', 'controls-list');
+
+ var minimapLabel = controls
+ .append('label')
+ .call(bootstrap.tooltip()
+ .html(true)
+ .title(iD.ui.tooltipHtml(t('background.minimap.tooltip'), '/'))
+ .placement('top')
+ );
+
+ minimapLabel.classed('minimap-toggle', true)
+ .append('input')
+ .attr('type', 'checkbox')
+ .on('change', function() {
+ iD.ui.MapInMap.toggle();
+ d3.event.preventDefault();
+ });
+
+ minimapLabel.append('span')
+ .text(t('background.minimap.description'));
+
var adjustments = content.append('div')
.attr('class', 'adjustments');
.attr('class', function(d) { return d[0] + ' nudge'; })
.on('mousedown', clickNudge);
- var resetButton = nudgeContainer.append('button')
+ var resetButton = nudgeContainer
+ .append('button')
.attr('class', 'reset disabled')
.on('click', function () {
context.background().offset([0, 0]);
resetButton.classed('disabled', true);
- });
-
- resetButton.append('div')
- .attr('class', 'icon undo');
+ })
+ .call(iD.svg.Icon('#icon-undo'));
context.map()
.on('move.background-update', _.debounce(update, 1000));
// Translate a MacOS key command into the appropriate Windows/Linux equivalent.
// For example, ⌘Z -> Ctrl+Z
iD.ui.cmd = function(code) {
- if (iD.detect().os === 'mac')
+ if (iD.detect().os === 'mac') {
return code;
-
- var replacements = {
- '⌘': 'Ctrl',
- '⇧': 'Shift',
- '⌥': 'Alt',
- '⌫': 'Backspace',
- '⌦': 'Delete'
- }, keys = [];
+ }
if (iD.detect().os === 'win') {
if (code === '⌘⇧Z') return 'Ctrl+Y';
}
+ var result = '',
+ replacements = {
+ '⌘': 'Ctrl',
+ '⇧': 'Shift',
+ '⌥': 'Alt',
+ '⌫': 'Backspace',
+ '⌦': 'Delete'
+ };
+
for (var i = 0; i < code.length; i++) {
if (code[i] in replacements) {
- keys.push(replacements[code[i]]);
+ result += replacements[code[i]] + '+';
} else {
- keys.push(code[i]);
+ result += code[i];
}
}
- return keys.join('+');
+ return result;
};
iD.ui.Commit = function(context) {
- var event = d3.dispatch('cancel', 'save');
+ var dispatch = d3.dispatch('cancel', 'save');
function commit(selection) {
var changes = context.history().changes(),
summary = context.history().difference().summary();
function zoomToEntity(change) {
-
var entity = change.entity;
if (change.changeType !== 'deleted' &&
context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
var header = selection.append('div')
.attr('class', 'header fillL');
- header.append('button')
- .attr('class', 'fr')
- .on('click', event.cancel)
- .append('span')
- .attr('class', 'icon close');
-
header.append('h3')
.text(t('commit.title'));
var body = selection.append('div')
.attr('class', 'body');
+
// Comment Section
var commentSection = body.append('div')
.attr('class', 'modal-section form-field commit-form');
.attr('placeholder', t('commit.description_placeholder'))
.attr('maxlength', 255)
.property('value', context.storage('comment') || '')
- .on('blur.save', function () {
+ .on('input.save', function() {
+ d3.selectAll('.save-section .save-button')
+ .attr('disabled', (this.value.length ? null : true));
+ })
+ .on('blur.save', function() {
context.storage('comment', this.value);
});
commentField.node().select();
+
// Warnings
var warnings = body.selectAll('div.warning-section')
- .data([iD.validate(changes, context.graph())])
+ .data([context.history().validate(changes)])
.enter()
.append('div')
.attr('class', 'modal-section warning-section fillL2')
.on('mouseout', mouseout)
.on('click', warningClick);
- warningLi.append('span')
- .attr('class', 'alert icon icon-pre-text');
+ warningLi
+ .call(iD.svg.Icon('#icon-alert', 'pre-text'));
- warningLi.append('strong').text(function(d) {
- return d.message;
- });
+ warningLi
+ .append('strong').text(function(d) {
+ return d.message;
+ });
warningLi.filter(function(d) { return d.tooltip; })
.call(bootstrap.tooltip()
.placement('top')
);
- // Save Section
+
+ // Upload Explanation
var saveSection = body.append('div')
- .attr('class','modal-section fillL cf');
+ .attr('class','modal-section save-section fillL cf');
var prose = saveSection.append('p')
.attr('class', 'commit-info')
if (user.image_url) {
userLink.append('img')
.attr('src', user.image_url)
- .attr('class', 'icon icon-pre-text user-icon');
+ .attr('class', 'icon pre-text user-icon');
}
userLink.append('a')
prose.html(t('commit.upload_explanation_with_user', {user: userLink.html()}));
});
- // Confirm Button
- var saveButton = saveSection.append('button')
- .attr('class', 'action col6 button')
+
+ // Buttons
+ var buttonSection = saveSection.append('div')
+ .attr('class','buttons fillL cf');
+
+ var saveButton = buttonSection.append('button')
+ .attr('class', 'action col5 button save-button')
+ .attr('disabled', function() {
+ var n = d3.select('.commit-form textarea').node();
+ return (n && n.value.length) ? null : true;
+ })
.on('click.save', function() {
- event.save({
+ dispatch.save({
comment: commentField.node().value
});
});
.attr('class', 'label')
.text(t('commit.save'));
+ var cancelButton = buttonSection.append('button')
+ .attr('class', 'action col5 button cancel-button')
+ .on('click.cancel', function() { dispatch.cancel(); });
+
+ cancelButton.append('span')
+ .attr('class', 'label')
+ .text(t('commit.cancel'));
+
+
+ // Changes
var changeSection = body.selectAll('div.commit-section')
.data([0])
.enter()
.on('mouseout', mouseout)
.on('click', zoomToEntity);
- li.append('span')
- .attr('class', function(d) {
- return d.entity.geometry(d.graph) + ' ' + d.changeType + ' icon icon-pre-text';
- });
+ li.each(function(d) {
+ d3.select(this)
+ .call(iD.svg.Icon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
+ });
li.append('span')
.attr('class', 'change-type')
}
}
- return d3.rebind(commit, event, 'on');
+ return d3.rebind(commit, dispatch, 'on');
};
iD.ui.confirm = function(selection) {
var modal = iD.ui.modal(selection);
.append('button')
.attr('class', 'fr')
.on('click', function() { dispatch.cancel(); })
- .append('span')
- .attr('class', 'icon close');
+ .call(iD.svg.Icon('#icon-close'));
header
.append('h3')
subset = u.slice(0, u.length > limit ? limit - 1 : limit);
selection.html('')
- .append('span')
- .attr('class', 'icon nearby light icon-pre-text');
+ .call(iD.svg.Icon('#icon-nearby', 'pre-text light'));
var userList = d3.select(document.createElement('span'));
$enter.append('button')
.attr('class', 'fr preset-close')
- .append('span')
- .attr('class', 'icon close');
+ .call(iD.svg.Icon('#icon-close'));
$enter.append('h3');
.on('keypress', keypress)
.on('input', inputevent);
- searchWrap.append('span')
- .attr('class', 'icon search');
+ searchWrap
+ .call(iD.svg.Icon('#icon-search', 'pre-text'));
var listWrap = selection.append('div')
.attr('class', 'inspector-body');
.data([0])
.enter().append('button')
.property('disabled', true)
- .attr('class', 'no-results-item');
-
- resultsIndicator.append('span')
- .attr('class', 'icon alert');
+ .attr('class', 'no-results-item')
+ .call(iD.svg.Icon('#icon-alert', 'pre-text'));
resultsIndicator.append('span')
.attr('class', 'entity-name');
var items = list.selectAll('.feature-list-item')
.data(results, function(d) { return d.id; });
- var enter = items.enter().insert('button', '.geocode-item')
+ var enter = items.enter()
+ .insert('button', '.geocode-item')
.attr('class', 'feature-list-item')
.on('mouseover', mouseover)
.on('mouseout', mouseout)
.on('click', click);
- var label = enter.append('div')
+ var label = enter
+ .append('div')
.attr('class', 'label');
- label.append('span')
- .attr('class', function(d) { return d.geometry + ' icon icon-pre-text'; });
+ label.each(function(d) {
+ d3.select(this)
+ .call(iD.svg.Icon('#icon-' + d.geometry, 'pre-text'));
+ });
label.append('span')
.attr('class', 'entity-type')
return modal;
};
+iD.ui.FullScreen = function(context) {
+ var element = context.container().node(),
+ keybinding = d3.keybinding('full-screen');
+ // button;
+
+ function getFullScreenFn() {
+ if (element.requestFullscreen) {
+ return element.requestFullscreen;
+ } else if (element.msRequestFullscreen) {
+ return element.msRequestFullscreen;
+ } else if (element.mozRequestFullScreen) {
+ return element.mozRequestFullScreen;
+ } else if (element.webkitRequestFullscreen) {
+ return element.webkitRequestFullscreen;
+ }
+ }
+
+ function getExitFullScreenFn() {
+ if (document.exitFullscreen) {
+ return document.exitFullscreen;
+ } else if (document.msExitFullscreen) {
+ return document.msExitFullscreen;
+ } else if (document.mozCancelFullScreen) {
+ return document.mozCancelFullScreen;
+ } else if (document.webkitExitFullscreen) {
+ return document.webkitExitFullscreen;
+ }
+ }
+
+ function isFullScreen() {
+ return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement ||
+ document.msFullscreenElement;
+ }
+
+ function isSupported() {
+ return !!getFullScreenFn();
+ }
+
+ function fullScreen() {
+ d3.event.preventDefault();
+ if (!isFullScreen()) {
+ // button.classed('active', true);
+ getFullScreenFn().apply(element);
+ } else {
+ // button.classed('active', false);
+ getExitFullScreenFn().apply(document);
+ }
+ }
+
+ return function() { // selection) {
+ if (!isSupported())
+ return;
+
+ // var tooltip = bootstrap.tooltip()
+ // .placement('left');
+
+ // button = selection.append('button')
+ // .attr('title', t('full_screen'))
+ // .attr('tabindex', -1)
+ // .on('click', fullScreen)
+ // .call(tooltip);
+
+ // button.append('span')
+ // .attr('class', 'icon full-screen');
+
+ keybinding
+ .on('f11', fullScreen)
+ .on(iD.ui.cmd('⌘⇧F'), fullScreen);
+
+ d3.select(document)
+ .call(keybinding);
+ };
+};
iD.ui.Geolocate = function(map) {
function click() {
navigator.geolocation.getCurrentPosition(
return function(selection) {
if (!navigator.geolocation) return;
- var button = selection.append('button')
+ selection.append('button')
.attr('tabindex', -1)
.attr('title', t('geolocate.title'))
.on('click', click)
+ .call(iD.svg.Icon('#icon-geolocate', 'light'))
.call(bootstrap.tooltip()
.placement('left'));
-
- button.append('span')
- .attr('class', 'icon geolocate light');
};
};
iD.ui.Help = function(context) {
.on('click', function() {
clickHelp(docs[i - 1], i - 1);
});
- prevLink.append('span').attr('class', 'icon back blue');
- prevLink.append('span').html(docs[i - 1].title);
+ prevLink.append('span').html('◄ ' + docs[i - 1].title);
}
if (i < docs.length - 1) {
var nextLink = nav.append('a')
.on('click', function() {
clickHelp(docs[i + 1], i + 1);
});
- nextLink.append('span').html(docs[i + 1].title);
- nextLink.append('span').attr('class', 'icon forward blue');
+ nextLink.append('span').html(docs[i + 1].title + ' ►');
}
}
button = selection.append('button')
.attr('tabindex', -1)
.on('click', toggle)
+ .call(iD.svg.Icon('#icon-help', 'light'))
.call(tooltip),
shown = false;
- button.append('span')
- .attr('class', 'icon help light');
-
var toc = pane.append('ul')
.attr('class', 'toc');
return r / 12.56637 * 510065621724000;
}
+ function toLineString(feature) {
+ if (feature.type === 'LineString') return feature;
+
+ var result = { type: 'LineString', coordinates: [] };
+ if (feature.type === 'Polygon') {
+ result.coordinates = feature.coordinates[0];
+ } else if (feature.type === 'MultiPolygon') {
+ result.coordinates = feature.coordinates[0][0];
+ }
+
+ return result;
+ }
+
function displayLength(m) {
var d = m * (imperial ? 3.28084 : 1),
p, unit;
if (hidden()) return;
var resolver = context.graph(),
- selected = context.selectedIDs(),
+ selected = _.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
singular = selected.length === 1 ? selected[0] : null,
extent = iD.geo.Extent(),
entity;
if (geometry === 'line' || geometry === 'area') {
var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()),
feature = entity.asGeoJSON(resolver),
- length = radiansToMeters(d3.geo.length(feature)),
+ length = radiansToMeters(d3.geo.length(toLineString(feature))),
lengthLabel = t('infobox.' + (closed ? 'perimeter' : 'length')),
centroid = d3.geo.centroid(feature);
// Save current map state
var history = context.history().toJSON(),
hash = window.location.hash,
+ center = context.map().center(),
+ zoom = context.map().zoom(),
background = context.background().baseLayerSource(),
opacity = d3.select('.background-layer').style('opacity'),
loadedTiles = context.connection().loadedTiles(),
// Load semi-real data used in intro
context.connection().toggle(false).flush();
context.history().reset();
-
+
introGraph = JSON.parse(iD.introGraph);
for (var key in introGraph) {
introGraph[key] = iD.Entity(introGraph[key]);
context.connection().toggle(true).flush().loadedTiles(loadedTiles);
context.history().reset().merge(d3.values(baseEntities));
context.background().baseLayerSource(background);
- if (history) context.history().fromJSON(history);
+ if (history) context.history().fromJSON(history, false);
+ context.map().centerZoom(center, zoom);
window.location.replace(hash);
context.inIntro(false);
d3.select('#bar button.save').on('click', save);
.attr('class', 'joined')
.selectAll('button.step');
- var entered = buttonwrap.data(steps)
- .enter().append('button')
- .attr('class', 'step')
- .on('click', enter);
+ var entered = buttonwrap
+ .data(steps)
+ .enter()
+ .append('button')
+ .attr('class', 'step')
+ .on('click', enter);
+
+ entered
+ .call(iD.svg.Icon('#icon-apply', 'pre-text'));
+
+ entered
+ .append('label')
+ .text(function(d) { return t(d.title); });
- entered.append('div').attr('class','icon icon-pre-text apply');
- entered.append('label').text(function(d) { return t(d.title); });
enter(steps[0]);
function enter (newStep) {
-
- if (step) {
- step.exit();
- }
+ if (step) { step.exit(); }
context.enter(iD.modes.Browse(context));
button = selection.append('button')
.attr('tabindex', -1)
.on('click', togglePanel)
+ .call(iD.svg.Icon('#icon-data', 'light'))
.call(tooltip),
shown = false;
- button.append('span')
- .attr('class', 'icon data light');
-
content.append('h4')
.text(t('map_data.title'));
d3.event.stopPropagation();
context.background().zoomToGpxLayer();
})
- .append('span')
- .attr('class', 'icon geolocate');
+ .call(iD.svg.Icon('#icon-search'));
gpxLayerItem.append('button')
.attr('class', 'layer-browse')
})
.node().click();
})
- .append('span')
- .attr('class', 'icon geocode');
+ .call(iD.svg.Icon('#icon-geolocate'));
label = gpxLayerItem.append('label')
.call(bootstrap.tooltip()
var key = '/';
function map_in_map(selection) {
+
var backgroundLayer = iD.TileLayer(),
- overlayLayer = iD.TileLayer(),
+ overlayLayers = {},
+ dispatch = d3.dispatch('change'),
+ gpxLayer = iD.GpxLayer(context, dispatch),
projection = iD.geo.RawMercator(),
zoom = d3.behavior.zoom()
.scaleExtent([ztok(0.5), ztok(24)])
transformed = false,
panning = false,
zDiff = 6, // by default, minimap renders at (main zoom - 6)
- tStart, tLast, tCurr, kLast, kCurr, tiles, svg, timeoutId;
+ tStart, tLast, tCurr, kLast, kCurr, tiles, svg, gpx, timeoutId;
+
+ iD.ui.MapInMap.gpxLayer = gpxLayer;
function ztok(z) { return 256 * Math.pow(2, z); }
function ktoz(k) { return Math.log(k) / Math.LN2 - 8; }
zDiff = zMain - zMini;
var scale = kCurr / kLast,
- tX = Math.round((tCurr[0] / scale - tLast[0]) * scale),
- tY = Math.round((tCurr[1] / scale - tLast[1]) * scale);
+ tX = (tCurr[0] / scale - tLast[0]) * scale,
+ tY = (tCurr[1] / scale - tLast[1]) * scale;
iD.util.setTransform(tiles, tX, tY, scale);
iD.util.setTransform(svg, 0, 0, scale);
.append('div')
.attr('class', 'map-in-map-tiles');
-
// redraw background
backgroundLayer
.source(context.background().baseLayerSource())
.call(backgroundLayer);
// redraw overlay
- var overlaySources = context.background().overlayLayerSources(),
- hasOverlay = false;
-
+ var overlaySources = context.background().overlayLayerSources();
+ var activeOverlayLayers = [];
for (var i = 0; i < overlaySources.length; i++) {
if (overlaySources[i].validZoom(zMini)) {
- overlayLayer
+ if (!overlayLayers[i]) overlayLayers[i] = iD.TileLayer();
+ activeOverlayLayers.push(overlayLayers[i]
.source(overlaySources[i])
.projection(projection)
- .dimensions(dMini);
-
- hasOverlay = true;
- break;
+ .dimensions(dMini));
}
}
var overlay = tiles
.selectAll('.map-in-map-overlay')
- .data(hasOverlay ? [0] : []);
+ .data([0]);
overlay.enter()
.append('div')
.attr('class', 'map-in-map-overlay');
- overlay.exit()
+ var overlays = overlay
+ .selectAll('div')
+ .data(activeOverlayLayers, function(d) { return d.source().name(); });
+
+ overlays.enter().append('div');
+ overlays.each(function(layer) {
+ d3.select(this).call(layer);
+ });
+
+ overlays.exit()
.remove();
- if (hasOverlay) {
- overlay
- .call(overlayLayer);
- }
+ // redraw gpx overlay
+ gpxLayer
+ .projection(projection);
+
+ gpx = tiles
+ .selectAll('.map-in-map-gpx')
+ .data([0]);
+
+ gpx.enter()
+ .append('div')
+ .attr('class', 'map-in-map-gpx');
+
+ gpx.call(gpxLayer);
+ gpx.dimensions(dMini);
// redraw bounding box
if (!panning) {
function toggle() {
if (d3.event) d3.event.preventDefault();
+ var label = d3.select('.minimap-toggle');
+
if (hidden()) {
selection
.style('display', 'block')
.duration(200)
.style('opacity', 1);
+ label.classed('active', true)
+ .select('input').property('checked', true);
+
redraw();
} else {
.each('end', function() {
d3.select(this).style('display', 'none');
});
+
+ label.classed('active', false)
+ .select('input').property('checked', false);
}
}
+ iD.ui.MapInMap.toggle = toggle;
selection
.on('mousedown.map-in-map', startMouse)
context
.on('enter.modes', update);
- buttons.append('span')
- .attr('class', function(mode) { return mode.id + ' icon icon-pre-text'; });
+ buttons.each(function(d) {
+ d3.select(this)
+ .call(iD.svg.Icon('#icon-' + d.button, 'pre-text'));
+ });
buttons.append('span')
.attr('class', 'label')
.attr('class', 'zoom-to notice')
.on('click', function() { context.map().zoom(context.minEditableZoom()); });
- button.append('span')
- .attr('class', 'icon zoom-in-invert');
-
- button.append('span')
+ button
+ .call(iD.svg.Icon('#icon-plus', 'pre-text'))
+ .append('span')
.attr('class', 'label')
.text(t('zoom_in_edit'));
wrap.append('button')
.attr('class', 'remove-icon')
- .append('span').attr('class', 'icon delete');
+ .call(iD.svg.Icon('#operation-delete'));
wrap.append('button')
.attr('class', 'modified-icon')
.attr('tabindex', -1)
- .append('div')
- .attr('class', 'icon undo');
+ .call(iD.svg.Icon('#icon-undo'));
// Update
var preset, geometry;
function presetIcon(selection) {
- selection.each(setup);
+ selection.each(render);
}
- function setup() {
+ function render() {
var selection = d3.select(this),
p = preset.apply(this, arguments),
- geom = geometry.apply(this, arguments);
+ geom = geometry.apply(this, arguments),
+ icon = p.icon || (geom === 'line' ? 'other-line' : 'marker-stroked'),
+ maki = iD.data.featureIcons.hasOwnProperty(icon + '-24');
+
+ if (icon === 'dentist') maki = true; // workaround for dentist icon missing in `maki-sprite.json`
+
+ function tag_classes(p) {
+ var s = '';
+ for (var i in p.tags) {
+ s += ' tag-' + i;
+ if (p.tags[i] !== '*') {
+ s += ' tag-' + i + '-' + p.tags[i];
+ }
+ }
+ return s;
+ }
var $fill = selection.selectAll('.preset-icon-fill')
.data([0]);
$fill.enter().append('div');
$fill.attr('class', function() {
- var s = 'preset-icon-fill preset-icon-fill-' + geom;
- for (var i in p.tags) {
- s += ' tag-' + i + ' tag-' + i + '-' + p.tags[i];
- }
- return s;
+ return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p);
+ });
+
+ var $frame = selection.selectAll('.preset-icon-frame')
+ .data([0]);
+
+ $frame.enter()
+ .append('div')
+ .call(iD.svg.Icon('#preset-icon-frame'));
+
+ $frame.attr('class', function() {
+ return 'preset-icon-frame ' + (geom === 'area' ? '' : 'hide');
});
+
var $icon = selection.selectAll('.preset-icon')
.data([0]);
- $icon.enter().append('div');
+ $icon.enter()
+ .append('div')
+ .attr('class', 'preset-icon')
+ .call(iD.svg.Icon(''));
- $icon.attr('class', function() {
- var icon = p.icon || (geom === 'line' ? 'other-line' : 'marker-stroked'),
- klass = 'feature-' + icon + ' preset-icon';
+ $icon
+ .attr('class', 'preset-icon preset-icon-' + (maki ? '32' : '60'));
- var featureicon = iD.data.featureIcons[icon];
- if (featureicon && featureicon[geom]) {
- klass += ' preset-icon-' + geom;
- } else if (icon === 'multipolygon') {
- // Special case (geometry === 'area')
- klass += ' preset-icon-relation';
- }
+ $icon.selectAll('svg')
+ .attr('class', function() {
+ return 'icon ' + icon + tag_classes(p);
+ });
- return klass;
- });
+ $icon.selectAll('use') // workaround: maki parking-24 broken?
+ .attr('href', '#' + icon + (maki ? ( icon === 'parking' ? '-18' : '-24') : ''));
}
presetIcon.preset = function(_) {
.attr('class', 'preset-choose')
.on('click', function() { event.choose(currentPreset); })
.append('span')
- .attr('class', 'icon forward');
+ .html('►');
} else {
messagewrap.append('button')
.attr('class', 'close')
.on('click', function() {
context.enter(iD.modes.Browse(context));
})
- .append('span')
- .attr('class', 'icon close');
+ .call(iD.svg.Icon('#icon-close'));
}
function keydown() {
.on('keypress', keypress)
.on('input', inputevent);
- searchWrap.append('span')
- .attr('class', 'icon search');
+ searchWrap
+ .call(iD.svg.Icon('#icon-search', 'pre-text'));
if (autofocus) {
search.node().focus();
var button = menu.selectAll()
.data(operations)
- .enter().append('g')
+ .enter()
+ .append('g')
+ .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
+ .classed('disabled', function(d) { return d.disabled(); })
.attr('transform', function(d, i) {
- return 'translate(' + r * Math.sin(a0 + i * a) + ',' +
- r * Math.cos(a0 + i * a) + ')';
+ return 'translate(' + iD.geo.roundCoords([
+ r * Math.sin(a0 + i * a),
+ r * Math.cos(a0 + i * a)]).join(',') + ')';
});
button.append('circle')
- .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
.attr('r', 15)
- .classed('disabled', function(d) { return d.disabled(); })
.on('click', click)
.on('mousedown', mousedown)
.on('mouseover', mouseover)
.on('mouseout', mouseout);
button.append('use')
- .attr('transform', 'translate(-10, -10)')
- .attr('clip-path', 'url(#clip-square-20)')
- .attr('xlink:href', function(d) { return '#icon-operation-' + (d.disabled() ? 'disabled-' : '') + d.id; });
+ .attr('transform', 'translate(-10,-10)')
+ .attr('width', '20')
+ .attr('height', '20')
+ .attr('xlink:href', function(d) { return '#operation-' + d.id; });
tooltip = d3.select(document.body)
.append('div')
.attr('tabindex', -1)
.attr('class', 'remove button-input-action member-delete minor')
.on('click', deleteMember)
- .append('span')
- .attr('class', 'icon delete');
+ .call(iD.svg.Icon('#operation-delete'));
$items.exit()
.remove();
.attr('tabindex', -1)
.attr('class', 'remove button-input-action member-delete minor')
.on('click', deleteMembership)
- .append('span')
- .attr('class', 'icon delete');
+ .call(iD.svg.Icon('#operation-delete'));
$items.exit()
.remove();
.attr('tabindex', -1)
.attr('class', 'remove button-input-action member-delete minor')
.on('click', deleteMembership)
- .append('span')
- .attr('class', 'icon delete');
+ .call(iD.svg.Icon('#operation-delete'));
} else {
$list.selectAll('.member-row-new')
var $add = $wrap.selectAll('.add-relation')
.data([0]);
- $add.enter().append('button')
+ $add.enter()
+ .append('button')
.attr('class', 'add-relation')
- .append('span')
- .attr('class', 'icon plus light');
+ .call(iD.svg.Icon('#icon-plus', 'light'));
$wrap.selectAll('.add-relation')
.on('click', function() {
var $newTag = $wrap.selectAll('.add-tag')
.data([0]);
- var $enter = $newTag.enter().append('button')
- .attr('class', 'add-tag');
-
- $enter.append('span')
- .attr('class', 'icon plus light');
+ $newTag.enter()
+ .append('button')
+ .attr('class', 'add-tag')
+ .call(iD.svg.Icon('#icon-plus', 'light'));
$newTag.on('click', addTag);
// Enter
- $enter = $items.enter().append('li')
+ var $enter = $items.enter().append('li')
.attr('class', 'tag-row cf');
$enter.append('div')
$enter.append('button')
.attr('tabindex', -1)
.attr('class', 'remove minor')
- .append('span')
- .attr('class', 'icon delete');
+ .call(iD.svg.Icon('#operation-delete'));
if (context.taginfo()) {
$enter.each(bindTypeahead);
$items.order();
$items.each(function(tag) {
- var reference = iD.ui.TagReference({key: tag.key}, context);
+ var isRelation = (context.entity(id).type === 'relation'),
+ reference;
+ if (isRelation && tag.key === 'type')
+ reference = iD.ui.TagReference({rtype: tag.value}, context);
+ else
+ reference = iD.ui.TagReference({key: tag.key, value: tag.value}, context);
if (state === 'hover') {
reference.showing(false);
.on('click', selectEntity);
// Enter
-
var label = enter.append('div')
- .attr('class', 'label');
-
- label.append('span')
- .attr('class', 'icon icon-pre-text');
+ .attr('class', 'label')
+ .call(iD.svg.Icon('', 'pre-text'));
label.append('span')
.attr('class', 'entity-type');
.attr('class', 'entity-name');
// Update
-
- items.selectAll('.icon')
- .attr('class', function(entity) { return context.geometry(entity.id) + ' icon icon-pre-text'; });
+ items.selectAll('use')
+ .attr('href', function() {
+ var entity = this.parentElement.parentElement.__data__;
+ return '#icon-' + context.geometry(entity.id);
+ });
items.selectAll('.entity-type')
.text(function(entity) { return context.presets().match(entity, context.graph()).name(); });
.text(function(entity) { return iD.util.displayName(entity); });
// Exit
-
items.exit()
.remove();
}
};
};
iD.ui.Success = function(context) {
- var event = d3.dispatch('cancel'),
+ var dispatch = d3.dispatch('cancel'),
changeset;
function success(selection) {
header.append('button')
.attr('class', 'fr')
- .append('span')
- .attr('class', 'icon close')
- .on('click', function() { event.cancel(success); });
+ .on('click', function() { dispatch.cancel(); })
+ .call(iD.svg.Icon('#icon-close'));
header.append('h3')
.text(t('success.just_edited'));
body.selectAll('.button.social')
.data(d3.entries(sharing))
- .enter().append('a')
- .attr('class', function(d) { return 'button social col4 ' + d.key; })
+ .enter()
+ .append('a')
+ .attr('class', 'button social col4')
.attr('target', '_blank')
.attr('href', function(d) { return d.value; })
.call(bootstrap.tooltip()
.title(function(d) { return t('success.' + d.key); })
- .placement('bottom'));
+ .placement('bottom'))
+ .each(function(d) { d3.select(this).call(iD.svg.Icon('#logo-' + d.key, 'social')); });
}
success.changeset = function(_) {
return success;
};
- return d3.rebind(success, event, 'on');
+ return d3.rebind(success, dispatch, 'on');
};
iD.ui.TagReference = function(tag, context) {
var tagReference = {},
loaded,
showing;
- function findLocal(docs) {
+ function findLocal(data) {
var locale = iD.detect().locale.toLowerCase(),
localized;
- localized = _.find(docs, function(d) {
+ localized = _.find(data, function(d) {
return d.lang.toLowerCase() === locale;
});
if (localized) return localized;
// 'en' if the language is 'en-US'
if (locale.indexOf('-') !== -1) {
var first = locale.split('-')[0];
- localized = _.find(docs, function(d) {
+ localized = _.find(data, function(d) {
return d.lang.toLowerCase() === first;
});
if (localized) return localized;
}
// finally fall back to english
- return _.find(docs, function(d) {
+ return _.find(data, function(d) {
return d.lang.toLowerCase() === 'en';
});
}
- function load() {
+ function load(param) {
button.classed('tag-reference-loading', true);
- context.taginfo().docs(tag, function(err, docs) {
- if (!err && docs) {
- docs = findLocal(docs);
+ context.taginfo().docs(param, function show(err, data) {
+ var docs;
+ if (!err && data) {
+ docs = findLocal(data);
}
body.html('');
if (!docs || !docs.description) {
- body.append('p').text(t('inspector.no_documentation_key'));
- show();
+ if (param.hasOwnProperty('value')) {
+ load(_.omit(param, 'value')); // retry with key only
+ } else {
+ body.append('p').text(t('inspector.no_documentation_key'));
+ done();
+ }
return;
}
.append('img')
.attr('class', 'wiki-image')
.attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
- .on('load', function() { show(); })
- .on('error', function() { d3.select(this).remove(); show(); });
+ .on('load', function() { done(); })
+ .on('error', function() { d3.select(this).remove(); done(); });
} else {
- show();
+ done();
}
body
.append('p')
.text(docs.description);
- var wikiLink = body
+ body
.append('a')
.attr('target', '_blank')
- .attr('href', 'http://wiki.openstreetmap.org/wiki/' + docs.title);
-
- wikiLink.append('span')
- .attr('class','icon icon-pre-text out-link');
-
- wikiLink.append('span')
+ .attr('href', 'http://wiki.openstreetmap.org/wiki/' + docs.title)
+ .call(iD.svg.Icon('#icon-out-link', 'inline'))
+ .append('span')
.text(t('inspector.reference'));
});
}
- function show() {
+ function done() {
loaded = true;
button.classed('tag-reference-loading', false);
button = selection.selectAll('.tag-reference-button')
.data([0]);
- var enter = button.enter().append('button')
+ button.enter()
+ .append('button')
+ .attr('class', 'tag-reference-button')
.attr('tabindex', -1)
- .attr('class', 'tag-reference-button');
-
- enter.append('span')
- .attr('class', 'icon inspect');
+ .call(iD.svg.Icon('#icon-inspect'));
button.on('click', function () {
d3.event.stopPropagation();
if (showing) {
hide();
} else if (loaded) {
- show();
+ done();
} else {
if (context.taginfo()) {
- load();
+ load(tag);
}
}
});
};
return tagReference;
-};// toggles the visibility of ui elements, using a combination of the
+};
+// toggles the visibility of ui elements, using a combination of the
// hide class, which sets display=none, and a d3 transition for opacity.
// this will cause blinking when called repeatedly, so check that the
// value actually changes between calls.
.on('click', function(d) { return d.action(); })
.call(tooltip);
- buttons.append('span')
- .attr('class', function(d) { return 'icon ' + d.id; });
+ buttons.each(function(d) {
+ d3.select(this)
+ .call(iD.svg.Icon('#icon-' + d.id));
+ });
var keybinding = d3.keybinding('undo')
.on(commands[0].cmd, function() { d3.event.preventDefault(); commands[0].action(); })
var $link = selection.selectAll('.view-on-osm')
.data([0]);
- var $enter = $link.enter().append('a')
+ $link.enter()
+ .append('a')
.attr('class', 'view-on-osm')
- .attr('target', '_blank');
-
- $enter.append('span')
- .attr('class', 'icon icon-pre-text out-link');
-
- $enter.append('span')
+ .attr('target', '_blank')
+ .call(iD.svg.Icon('#icon-out-link', 'inline'))
+ .append('span')
.text(t('inspector.view_on_osm'));
- $link.attr('href', context.connection().entityURL(entity));
+ $link
+ .attr('href', context.connection().entityURL(entity));
}
viewOnOSM.entityID = function(_) {
iD.ui.Zoom = function(context) {
var zooms = [{
id: 'zoom-in',
+ icon: 'plus',
title: t('zoom.in'),
action: context.zoomIn,
key: '+'
}, {
id: 'zoom-out',
+ icon: 'minus',
title: t('zoom.out'),
action: context.zoomOut,
key: '-'
}];
+ function zoomIn() {
+ d3.event.preventDefault();
+ context.zoomIn();
+ }
+
+ function zoomOut() {
+ d3.event.preventDefault();
+ context.zoomOut();
+ }
+
+ function zoomInFurther() {
+ d3.event.preventDefault();
+ context.zoomInFurther();
+ }
+
+ function zoomOutFurther() {
+ d3.event.preventDefault();
+ context.zoomOutFurther();
+ }
+
+
return function(selection) {
var button = selection.selectAll('button')
.data(zooms)
return iD.ui.tooltipHtml(d.title, d.key);
}));
- button.append('span')
- .attr('class', function(d) { return d.id + ' icon'; });
+ button.each(function(d) {
+ d3.select(this)
+ .call(iD.svg.Icon('#icon-' + d.icon, 'light'));
+ });
var keybinding = d3.keybinding('zoom');
_.each(['=','ffequals','plus','ffplus'], function(key) {
- keybinding.on(key, function() { context.zoomIn(); });
- keybinding.on('⇧' + key, function() { context.zoomIn(); });
+ keybinding.on(key, zoomIn);
+ keybinding.on('⇧' + key, zoomIn);
+ keybinding.on(iD.ui.cmd('⌘' + key), zoomInFurther);
+ keybinding.on(iD.ui.cmd('⌘⇧' + key), zoomInFurther);
});
_.each(['-','ffminus','_','dash'], function(key) {
- keybinding.on(key, function() { context.zoomOut(); });
- keybinding.on('⇧' + key, function() { context.zoomOut(); });
+ keybinding.on(key, zoomOut);
+ keybinding.on('⇧' + key, zoomOut);
+ keybinding.on(iD.ui.cmd('⌘' + key), zoomOutFurther);
+ keybinding.on(iD.ui.cmd('⌘⇧' + key), zoomOutFurther);
});
d3.select(document)
if (type !== 'access') {
options.unshift('yes');
options.push('designated');
+
+ if (type === 'bicycle') {
+ options.push('dismount');
+ }
}
return options.map(function(option) {
return tags.access ? tags.access : field.placeholder();
});
- items.selectAll('#preset-input-access-access')
- .attr('placeholder', 'yes');
+ // items.selectAll('#preset-input-access-access')
+ // .attr('placeholder', 'yes');
- _.forEach(placeholders[tags.highway], function(value, key) {
- items.selectAll('#preset-input-access-' + key)
- .attr('placeholder', function() {
- return (tags.access && (value === 'yes' || value === 'designated')) ? tags.access : value;
- });
+ _.forEach(placeholders[tags.highway], function(v, k) {
+ items.selectAll('#preset-input-access-' + k)
+ .attr('placeholder', function() { return (tags.access || v); });
});
};
var event = d3.dispatch('change'),
optstrings = field.strings && field.strings.options,
optarray = field.options,
+ snake_case = (field.snake_case || (field.snake_case === undefined)),
strings = {},
input;
+ function snake(s) {
+ return s.replace(/\s+/g, '_');
+ }
+
+ function unsnake(s) {
+ return s.replace(/_+/g, ' ');
+ }
+
+ function clean(s) {
+ return s.split(';')
+ .map(function(s) { return s.trim(); })
+ .join(';');
+ }
+
+ function optString() {
+ return _.find(_.keys(strings), function(k) {
+ return strings[k] === input.value();
+ });
+ }
+
function combo(selection) {
var combobox = d3.combobox();
stringsLoaded();
} else if (optarray) {
_.each(optarray, function(k) {
- strings[k] = k.replace(/_+/g, ' ');
+ strings[k] = (snake_case ? unsnake(k) : k);
});
stringsLoaded();
} else if (context.taginfo()) {
context.taginfo().values({key: field.key}, function(err, data) {
if (!err) {
_.each(_.pluck(data, 'value'), function(k) {
- strings[k] = k.replace(/_+/g, ' ');
+ strings[k] = (snake_case ? unsnake(k) : k);
});
stringsLoaded();
}
}
function change() {
- var optstring = _.find(_.keys(strings), function(k) { return strings[k] === input.value(); }),
- value = optstring || (input.value()
- .split(';')
- .map(function(s) { return s.trim(); })
- .join(';')
- .replace(/\s+/g, '_'));
+ var value = optString() || clean(input.value());
- if (field.type === 'typeCombo' && !value) value = 'yes';
+ if (snake_case) {
+ value = snake(value);
+ }
+ if (field.type === 'typeCombo' && !value) {
+ value = 'yes';
+ }
var t = {};
t[field.key] = value || undefined;
combo.tags = function(tags) {
var key = tags[field.key],
+ optstring = optString(),
value = strings[key] || key || '';
- if (field.type === 'typeCombo' && value.toLowerCase() === 'yes') value = '';
+
+ if (field.type === 'typeCombo' && value.toLowerCase() === 'yes') {
+ value = '';
+ }
+ if (!optstring && snake_case) {
+ value = unsnake(value);
+ }
input.value(value);
};
return d3.rebind(combo, event, 'on');
};
+iD.ui.preset.cycleway = function(field) {
+ var event = d3.dispatch('change'),
+ items;
+
+ function cycleway(selection) {
+ var wrap = selection.selectAll('.preset-input-wrap')
+ .data([0]);
+
+ wrap.enter().append('div')
+ .attr('class', 'cf preset-input-wrap')
+ .append('ul');
+
+ items = wrap.select('ul').selectAll('li')
+ .data(field.keys);
+
+ // Enter
+
+ var enter = items.enter().append('li')
+ .attr('class', function(d) { return 'cf preset-cycleway-' + d; });
+
+ enter.append('span')
+ .attr('class', 'col6 label preset-label-cycleway')
+ .attr('for', function(d) { return 'preset-input-cycleway-' + d; })
+ .text(function(d) { return field.t('types.' + d); });
+
+ enter.append('div')
+ .attr('class', 'col6 preset-input-cycleway-wrap')
+ .append('input')
+ .attr('type', 'text')
+ .attr('class', 'preset-input-cycleway')
+ .attr('id', function(d) { return 'preset-input-cycleway-' + d; })
+ .each(function(d) {
+ d3.select(this)
+ .call(d3.combobox()
+ .data(cycleway.options(d)));
+ });
+
+ // Update
+
+ wrap.selectAll('.preset-input-cycleway')
+ .on('change', change)
+ .on('blur', change);
+ }
+
+ function change() {
+ var inputs = d3.selectAll('.preset-input-cycleway')[0],
+ left = d3.select(inputs[0]).value(),
+ right = d3.select(inputs[1]).value(),
+ tag = {};
+ if (left === 'none' || left === '') { left = undefined; }
+ if (right === 'none' || right === '') { right = undefined; }
+
+ // Always set both left and right as changing one can affect the other
+ tag = {
+ cycleway: undefined,
+ 'cycleway:left': left,
+ 'cycleway:right': right
+ };
+
+ // If the left and right tags match, use the cycleway tag to tag both
+ // sides the same way
+ if (left === right) {
+ tag = {
+ cycleway: left,
+ 'cycleway:left': undefined,
+ 'cycleway:right': undefined
+ };
+ }
+
+ event.change(tag);
+ }
+
+ cycleway.options = function() {
+ return d3.keys(field.strings.options).map(function(option) {
+ return {
+ title: field.t('options.' + option + '.description'),
+ value: option
+ };
+ });
+ };
+
+ cycleway.tags = function(tags) {
+ items.selectAll('.preset-input-cycleway')
+ .value(function(d) {
+ // If cycleway is set, always return that
+ if (tags.cycleway) {
+ return tags.cycleway;
+ }
+ return tags[d] || '';
+ })
+ .attr('placeholder', field.placeholder());
+ };
+
+ cycleway.focus = function() {
+ items.selectAll('.preset-input-cycleway')
+ .node().focus();
+ };
+
+ return d3.rebind(cycleway, event, 'on');
+};
iD.ui.preset.text =
iD.ui.preset.number =
iD.ui.preset.tel =
var translateButton = selection.selectAll('.localized-add')
.data([0]);
- translateButton.enter().append('button')
+ translateButton.enter()
+ .append('button')
.attr('class', 'button-input-action localized-add minor')
+ .call(iD.svg.Icon('#icon-plus'))
.call(bootstrap.tooltip()
.title(t('translate.translate'))
- .placement('left'))
- .append('span')
- .attr('class', 'icon plus');
+ .placement('left'));
translateButton
.on('click', addBlank);
.style('max-height','0px')
.remove();
})
- .append('span').attr('class', 'icon delete');
+ .call(iD.svg.Icon('#operation-delete'));
wrap.append('input')
.attr('class', 'localized-lang')
input.value(tags[field.key] || '');
- var postfixed = [];
- for (var i in tags) {
- var m = i.match(new RegExp(field.key + ':([a-zA-Z_-]+)$'));
- if (m && m[1]) {
- postfixed.push({ lang: m[1], value: tags[i]});
+ var postfixed = [], k, m;
+ for (k in tags) {
+ m = k.match(/^(.*):([a-zA-Z_-]+)$/);
+ if (m && m[1] === field.key && m[2]) {
+ postfixed.push({ lang: m[2], value: tags[k] });
}
}
surface
.call(vertices, graph, [vertex], filter, extent, z)
- .call(lines, graph, intersection.highways, filter)
+ .call(lines, graph, intersection.ways, filter)
.call(turns, graph, intersection.turns(fromNodeID));
surface
if (fromNodeID) {
surface
- .selectAll('.' + _.find(intersection.highways, function(way) { return way.contains(fromNodeID); }).id)
+ .selectAll('.' + intersection.highways[fromNodeID].id)
.classed('selected', true);
}
function click() {
var datum = d3.event.target.__data__;
if (datum instanceof iD.Entity) {
- fromNodeID = datum.nodes[(datum.first() === vertexID) ? 1 : datum.nodes.length - 2];
+ fromNodeID = intersection.adjacentNodeId(datum.id);
render();
} else if (datum instanceof iD.geo.Turn) {
if (datum.restriction) {
link.enter().append('a')
.attr('class', 'wiki-link button-input-action minor')
.attr('target', '_blank')
- .append('span')
- .attr('class', 'icon out-link');
+ .call(iD.svg.Icon('#icon-out-link', 'inline'));
}
function language() {
var value = lang.value().toLowerCase();
+ var locale = iD.detect().locale.toLowerCase();
+ var localeLanguage;
return _.find(iD.data.wikipedia, function(d) {
+ if (d[2] === locale) localeLanguage = d;
return d[0].toLowerCase() === value ||
d[1].toLowerCase() === value ||
- d[2].toLowerCase() === value;
- }) || iD.data.wikipedia[0];
+ d[2] === value;
+ }) || localeLanguage || ['English', 'English', 'en'];
}
function changeLang() {
function change() {
var value = title.value(),
- m = value.match(/https?:\/\/([a-z]+)\.wikipedia\.org\/wiki\/(.+)/),
- l = m && _.find(iD.data.wikipedia, function(d) { return m[1] === d[2]; });
+ m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
+ l = m && _.find(iD.data.wikipedia, function(d) { return m[1] === d[2]; }),
+ anchor;
if (l) {
// Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
- value = m[2].replace(/_/g, ' ');
+ value = decodeURIComponent(m[2]).replace(/_/g, ' ');
+ if (m[3]) {
+ try {
+ // Best-effort `anchordecode:` implementation
+ anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
+ } catch (e) {
+ anchor = decodeURIComponent(m[3]);
+ }
+ value += '#' + anchor.replace(/_/g, ' ');
+ }
value = value.slice(0, 1).toUpperCase() + value.slice(1);
lang.value(l[1]);
title.value(value);
i.tags = function(tags) {
var value = tags[field.key] || '',
- m = value.match(/([^:]+):(.+)/),
- l = m && _.find(iD.data.wikipedia, function(d) { return m[1] === d[2]; });
+ m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
+ l = m && _.find(iD.data.wikipedia, function(d) { return m[1] === d[2]; }),
+ anchor = m && m[3];
// value in correct format
if (l) {
lang.value(l[1]);
- title.value(m[2]);
- link.attr('href', 'http://' + m[1] + '.wikipedia.org/wiki/' + m[2]);
+ title.value(m[2] + (anchor ? ('#' + anchor) : ''));
+ if (anchor) {
+ try {
+ // Best-effort `anchorencode:` implementation
+ anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
+ } catch (e) {
+ anchor = anchor.replace(/ /g, '_');
+ }
+ }
+ link.attr('href', 'http://' + m[1] + '.wikipedia.org/wiki/' +
+ m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''));
// unrecognized value format
} else {
value = value.toLowerCase();
var searchable = _.filter(collection, function(a) {
- return a.searchable !== false && a.suggestion !== true;
- }),
- suggestions = _.filter(collection, function(a) {
- return a.suggestion === true;
- });
+ return a.searchable !== false && a.suggestion !== true;
+ }),
+ suggestions = _.filter(collection, function(a) {
+ return a.suggestion === true;
+ });
+
+ function leading(a) {
+ var index = a.indexOf(value);
+ return index === 0 || a[index - 1] === ' ';
+ }
// matches value to preset.name
var leading_name = _.filter(searchable, function(a) {
// matches value to preset.terms values
var leading_terms = _.filter(searchable, function(a) {
- return _.any(a.terms() || [], leading);
- });
+ return _.any(a.terms() || [], leading);
+ });
+
+ // matches value to preset.tags values
+ var leading_tag_values = _.filter(searchable, function(a) {
+ return _.any(_.without(_.values(a.tags || {}), '*'), leading);
+ });
- function leading(a) {
- var index = a.indexOf(value);
- return index === 0 || a[index - 1] === ' ';
- }
// finds close matches to value in preset.name
var levenstein_name = searchable.map(function(a) {
var results = leading_name.concat(
leading_terms,
+ leading_tag_values,
leading_suggestions.slice(0, maxSuggestionResults+5),
levenstein_name,
leventstein_terms,
};
preset.terms = function() {
- return preset.t('terms', {'default': ''}).split(',');
+ return preset.t('terms', {'default': ''}).toLowerCase().trim().split(/\s*,+\s*/);
};
preset.isFallback = function() {
for (var f in preset.fields) {
var field = preset.fields[f];
- if (field.matchGeometry(geometry) && field['default'] === tags[field.key]) {
+ if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
delete tags[field.key];
}
}
for (var f in preset.fields) {
var field = preset.fields[f];
- if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field['default']) {
- tags[field.key] = field['default'];
+ if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
+ tags[field.key] = field.default;
}
}
return preset;
};
-iD.validate = function(changes, graph) {
- var warnings = [];
+iD.validations = {};
+iD.validations.DeprecatedTag = function() {
+
+ var validation = function(changes) {
+ var warnings = [];
+ for (var i = 0; i < changes.created.length; i++) {
+ var change = changes.created[i],
+ deprecatedTags = change.deprecatedTags();
+
+ if (!_.isEmpty(deprecatedTags)) {
+ var tags = iD.util.tagText({ tags: deprecatedTags });
+ warnings.push({
+ id: 'deprecated_tags',
+ message: t('validations.deprecated_tags', { tags: tags }),
+ entity: change
+ });
+ }
+ }
+ return warnings;
+ };
+
+ return validation;
+};
+iD.validations.ManyDeletions = function() {
+ var threshold = 100;
+
+ var validation = function(changes) {
+ var warnings = [];
+ if (changes.deleted.length > threshold) {
+ warnings.push({
+ id: 'many_deletions',
+ message: t('validations.many_deletions', { n: changes.deleted.length })
+ });
+ }
+ return warnings;
+ };
+
+ return validation;
+};
+iD.validations.MissingTag = function() {
+
+ var validation = function(changes, graph) {
+ var warnings = [];
+ for (var i = 0; i < changes.created.length; i++) {
+ var change = changes.created[i],
+ geometry = change.geometry(graph);
+
+ if ((geometry === 'point' || geometry === 'line' || geometry === 'area') && !change.isUsed(graph)) {
+ warnings.push({
+ id: 'missing_tag',
+ message: t('validations.untagged_' + geometry),
+ tooltip: t('validations.untagged_' + geometry + '_tooltip'),
+ entity: change
+ });
+ }
+ }
+ return warnings;
+ };
+
+ return validation;
+};
+iD.validations.TagSuggestsArea = function() {
// https://github.com/openstreetmap/josm/blob/mirror/src/org/
// openstreetmap/josm/data/validation/tests/UnclosedWays.java#L80
- function tagSuggestsArea(change) {
- if (_.isEmpty(change.tags)) return false;
- var tags = change.tags;
+ function tagSuggestsArea(tags) {
+ if (_.isEmpty(tags)) return false;
+
var presence = ['landuse', 'amenities', 'tourism', 'shop'];
for (var i = 0; i < presence.length; i++) {
if (tags[presence[i]] !== undefined) {
return presence[i] + '=' + tags[presence[i]];
}
}
- if (tags.building && tags.building === 'yes') return 'building=yes';
- }
- if (changes.deleted.length > 100) {
- warnings.push({
- message: t('validations.many_deletions', { n: changes.deleted.length })
- });
+ if (tags.building && tags.building === 'yes') return 'building=yes';
}
- for (var i = 0; i < changes.created.length; i++) {
- var change = changes.created[i],
- geometry = change.geometry(graph);
-
- if ((geometry === 'point' || geometry === 'line' || geometry === 'area') && !change.isUsed(graph)) {
- warnings.push({
- message: t('validations.untagged_' + geometry),
- tooltip: t('validations.untagged_' + geometry + '_tooltip'),
- entity: change
- });
- }
-
- var deprecatedTags = change.deprecatedTags();
- if (!_.isEmpty(deprecatedTags)) {
- warnings.push({
- message: t('validations.deprecated_tags', {
- tags: iD.util.tagText({ tags: deprecatedTags })
- }), entity: change });
- }
+ var validation = function(changes, graph) {
+ var warnings = [];
+ for (var i = 0; i < changes.created.length; i++) {
+ var change = changes.created[i],
+ geometry = change.geometry(graph),
+ suggestion = (geometry === 'line' ? tagSuggestsArea(change.tags) : undefined);
- if (geometry === 'line' && tagSuggestsArea(change)) {
- warnings.push({
- message: t('validations.tag_suggests_area', {tag: tagSuggestsArea(change)}),
- entity: change
- });
+ if (suggestion) {
+ warnings.push({
+ id: 'tag_suggests_area',
+ message: t('validations.tag_suggests_area', { tag: suggestion }),
+ entity: change
+ });
+ }
}
- }
+ return warnings;
+ };
- return warnings;
+ return validation;
};
-/* jshint ignore:start */
})();
window.locale = { _current: 'en' };
"yh:STRUCTURE",
"yh:TOTYUMONO",
"yh:TYPE",
+ "yh:WIDTH",
"yh:WIDTH_RANK",
"SK53_bulk:load"
],
"wikipedia": [
[
- "English",
- "English",
- "en"
+ "Abkhazian",
+ "Аҧсшәа",
+ "ab"
],
[
- "German",
- "Deutsch",
- "de"
+ "Achinese",
+ "Acèh",
+ "ace"
],
[
- "Dutch",
- "Nederlands",
- "nl"
+ "Afrikaans",
+ "Afrikaans",
+ "af"
],
[
- "French",
- "Français",
- "fr"
+ "Akan",
+ "Akan",
+ "ak"
],
[
- "Italian",
- "Italiano",
- "it"
+ "Alemannisch",
+ "Alemannisch",
+ "als"
],
[
- "Russian",
- "Русский",
- "ru"
+ "Amharic",
+ "አማርኛ",
+ "am"
],
[
- "Spanish",
- "Español",
- "es"
+ "Aragonese",
+ "aragonés",
+ "an"
],
[
- "Polish",
- "Polski",
- "pl"
+ "Old English",
+ "Ænglisc",
+ "ang"
],
[
- "Swedish",
- "Svenska",
- "sv"
+ "Arabic",
+ "العربية",
+ "ar"
],
[
- "Japanese",
- "日本語",
- "ja"
+ "Aramaic",
+ "ܐܪܡܝܐ",
+ "arc"
],
[
- "Portuguese",
- "Português",
- "pt"
+ "Egyptian Arabic",
+ "مصرى",
+ "arz"
],
[
- "Chinese",
- "中文",
- "zh"
+ "Assamese",
+ "অসমীয়া",
+ "as"
],
[
- "Vietnamese",
- "Tiếng Việt",
- "vi"
+ "Asturian",
+ "asturianu",
+ "ast"
],
[
- "Ukrainian",
- "УкÑ\80аÑ\97нÑ\81Ñ\8cка",
- "uk"
+ "Avaric",
+ "аваÑ\80",
+ "av"
],
[
- "Catalan",
- "Català",
- "ca"
+ "Aymara",
+ "Aymar aru",
+ "ay"
],
[
- "Norwegian (Bokmål)",
- "Norsk (Bokmål)",
- "no"
+ "Azerbaijani",
+ "azərbaycanca",
+ "az"
],
[
- "Waray-Waray",
- "Winaray",
- "war"
+ "South Azerbaijani",
+ "تۆرکجه",
+ "azb"
],
[
- "Cebuano",
- "Sinugboanong Binisaya",
- "ceb"
+ "Bashkir",
+ "башҡортса",
+ "ba"
],
[
- "Finnish",
- "Suomi",
- "fi"
+ "Bavarian",
+ "Boarisch",
+ "bar"
],
[
- "Persian",
- "فارسی",
- "fa"
+ "Samogitian",
+ "žemaitėška",
+ "bat-smg"
],
[
- "Czech",
- "Čeština",
- "cs"
+ "Bikol Central",
+ "Bikol Central",
+ "bcl"
],
[
- "Hungarian",
- "Magyar",
- "hu"
+ "Belarusian",
+ "беларуская",
+ "be"
],
[
- "Korean",
- "한국어",
- "ko"
+ "беларуская (тарашкевіца)",
+ "беларуская (тарашкевіца)",
+ "be-x-old"
],
[
- "Romanian",
- "Română",
- "ro"
+ "Bulgarian",
+ "български",
+ "bg"
],
[
- "Arabic",
- "العربية",
- "ar"
+ "भोजपुरी",
+ "भोजपुरी",
+ "bh"
],
[
- "Turkish",
- "Türkçe",
- "tr"
+ "Bislama",
+ "Bislama",
+ "bi"
],
[
- "Indonesian",
- "Bahasa Indonesia",
- "id"
+ "Banjar",
+ "Bahasa Banjar",
+ "bjn"
],
[
- "Kazakh",
- "Қазақша",
- "kk"
+ "Bambara",
+ "bamanankan",
+ "bm"
],
[
- "Malay",
- "Bahasa Melayu",
- "ms"
+ "Bengali",
+ "বাংলা",
+ "bn"
],
[
- "Serbian",
- "Српски / Srpski",
- "sr"
+ "Tibetan",
+ "བོད་ཡིག",
+ "bo"
],
[
- "Slovak",
- "Slovenčina",
- "sk"
+ "Bishnupriya",
+ "বিষ্ণুপ্রিয়া মণিপুরী",
+ "bpy"
],
[
- "Esperanto",
- "Esperanto",
- "eo"
+ "Breton",
+ "brezhoneg",
+ "br"
],
[
- "Danish",
- "Dansk",
- "da"
+ "Bosnian",
+ "bosanski",
+ "bs"
],
[
- "Lithuanian",
- "Lietuvių",
- "lt"
+ "Buginese",
+ "ᨅᨔ ᨕᨘᨁᨗ",
+ "bug"
],
[
- "Basque",
- "Euskara",
- "eu"
+ "буряад",
+ "буряад",
+ "bxr"
],
[
- "Bulgarian",
- "Български",
- "bg"
+ "Catalan",
+ "català",
+ "ca"
],
[
- "Hebrew",
- "עברית",
- "he"
+ "Chavacano de Zamboanga",
+ "Chavacano de Zamboanga",
+ "cbk-zam"
],
[
- "Slovenian",
- "Slovenščina",
- "sl"
+ "Min Dong Chinese",
+ "Mìng-dĕ̤ng-ngṳ̄",
+ "cdo"
],
[
- "Croatian",
- "Hrvatski",
- "hr"
+ "Chechen",
+ "нохчийн",
+ "ce"
],
[
- "Volapük",
- "Volapük",
- "vo"
+ "Cebuano",
+ "Cebuano",
+ "ceb"
],
[
- "Estonian",
- "Eesti",
- "et"
+ "Chamorro",
+ "Chamoru",
+ "ch"
],
[
- "Hindi",
- "हिन्दी",
- "hi"
+ "Cherokee",
+ "ᏣᎳᎩ",
+ "chr"
],
[
- "Uzbek",
- "O‘zbek",
- "uz"
+ "Cheyenne",
+ "Tsetsêhestâhese",
+ "chy"
],
[
- "Galician",
- "Galego",
- "gl"
+ "Central Kurdish",
+ "کوردیی ناوەندی",
+ "ckb"
],
[
- "Norwegian (Nynorsk)",
- "Nynorsk",
- "nn"
+ "Corsican",
+ "corsu",
+ "co"
],
[
- "Simple English",
- "Simple English",
- "simple"
+ "Cree",
+ "Nēhiyawēwin / ᓀᐦᐃᔭᐍᐏᐣ",
+ "cr"
],
[
- "Azerbaijani",
- "Azərbaycanca",
- "az"
+ "Crimean Turkish",
+ "qırımtatarca",
+ "crh"
],
[
- "Latin",
- "Latina",
- "la"
+ "Czech",
+ "čeština",
+ "cs"
],
[
- "Greek",
- "Ελληνικά",
- "el"
+ "Kashubian",
+ "kaszëbsczi",
+ "csb"
],
[
- "Thai",
- "ไทย",
- "th"
+ "Church Slavic",
+ "словѣньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ",
+ "cu"
],
[
- "Serbo-Croatian",
- "Srpskohrvatski / Српскохрватски",
- "sh"
+ "Chuvash",
+ "Чӑвашла",
+ "cv"
],
[
- "Georgian",
- "ქართული",
- "ka"
+ "Welsh",
+ "Cymraeg",
+ "cy"
],
[
- "Occitan",
- "Occitan",
- "oc"
+ "Danish",
+ "dansk",
+ "da"
],
[
- "Macedonian",
- "Македонски",
- "mk"
+ "German",
+ "Deutsch",
+ "de"
],
[
- "Newar / Nepal Bhasa",
- "नेपाल भाषा",
- "new"
+ "Zazaki",
+ "Zazaki",
+ "diq"
],
[
- "Tagalog",
- "Tagalog",
- "tl"
+ "Lower Sorbian",
+ "dolnoserbski",
+ "dsb"
],
[
- "Piedmontese",
- "Piemontèis",
- "pms"
+ "Divehi",
+ "ދިވެހިބަސް",
+ "dv"
],
[
- "Belarusian",
- "Беларуская",
- "be"
+ "Dzongkha",
+ "ཇོང་ཁ",
+ "dz"
],
[
- "Haitian",
- "Krèyol ayisyen",
- "ht"
+ "Ewe",
+ "eʋegbe",
+ "ee"
],
[
- "Tamil",
- "தமிழ்",
- "ta"
- ],
- [
- "Telugu",
- "తెలుగు",
- "te"
- ],
- [
- "Belarusian (Taraškievica)",
- "Беларуская (тарашкевіца)",
- "be-x-old"
- ],
- [
- "Latvian",
- "Latviešu",
- "lv"
- ],
- [
- "Breton",
- "Brezhoneg",
- "br"
+ "Greek",
+ "Ελληνικά",
+ "el"
],
[
- "Malagasy",
- "Malagasy",
- "mg"
+ "Emiliano-Romagnolo",
+ "emiliàn e rumagnòl",
+ "eml"
],
[
- "Albanian",
- "Shqip",
- "sq"
+ "English",
+ "English",
+ "en"
],
[
- "Armenian",
- "Հայերեն",
- "hy"
+ "Esperanto",
+ "Esperanto",
+ "eo"
],
[
- "Tatar",
- "Tatarça / Татарча",
- "tt"
+ "Spanish",
+ "español",
+ "es"
],
[
- "Javanese",
- "Basa Jawa",
- "jv"
+ "Estonian",
+ "eesti",
+ "et"
],
[
- "Welsh",
- "Cymraeg",
- "cy"
+ "Basque",
+ "euskara",
+ "eu"
],
[
- "Marathi",
- "मराठी",
- "mr"
+ "Extremaduran",
+ "estremeñu",
+ "ext"
],
[
- "Luxembourgish",
- "Lëtzebuergesch",
- "lb"
+ "Persian",
+ "فارسی",
+ "fa"
],
[
- "Icelandic",
- "Íslenska",
- "is"
+ "Fulah",
+ "Fulfulde",
+ "ff"
],
[
- "Bosnian",
- "Bosanski",
- "bs"
+ "Finnish",
+ "suomi",
+ "fi"
],
[
- "Burmese",
- "မြန်မာဘာသာ",
- "my"
+ "Võro",
+ "Võro",
+ "fiu-vro"
],
[
- "Yoruba",
- "Yorùbá",
- "yo"
+ "Fijian",
+ "Na Vosa Vakaviti",
+ "fj"
],
[
- "Bashkir",
- "Башҡорт",
- "ba"
+ "Faroese",
+ "føroyskt",
+ "fo"
],
[
- "Malayalam",
- "മലയാളം",
- "ml"
+ "French",
+ "français",
+ "fr"
],
[
- "Aragonese",
- "Aragonés",
- "an"
+ "Arpitan",
+ "arpetan",
+ "frp"
],
[
- "Lombard",
- "Lumbaart",
- "lmo"
+ "Northern Frisian",
+ "Nordfriisk",
+ "frr"
],
[
- "Afrikaans",
- "Afrikaans",
- "af"
+ "Friulian",
+ "furlan",
+ "fur"
],
[
- "West Frisian",
+ "Western Frisian",
"Frysk",
"fy"
],
[
- "Western Panjabi",
- "شاہ مکھی پنجابی (Shāhmukhī Pañjābī)",
- "pnb"
+ "Irish",
+ "Gaeilge",
+ "ga"
],
[
- "Bengali",
- "বাংলা",
- "bn"
+ "Gagauz",
+ "Gagauz",
+ "gag"
],
[
- "Swahili",
- "Kiswahili",
- "sw"
+ "Gan Chinese",
+ "贛語",
+ "gan"
],
[
- "Bishnupriya Manipuri",
- "ইমার ঠার/বিষ্ণুপ্রিয়া মণিপুরী",
- "bpy"
+ "Scottish Gaelic",
+ "Gàidhlig",
+ "gd"
],
[
- "Ido",
- "Ido",
- "io"
+ "Galician",
+ "galego",
+ "gl"
],
[
- "Kirghiz",
- "Кыргызча",
- "ky"
+ "Gilaki",
+ "گیلکی",
+ "glk"
],
[
- "Urdu",
- "اردو",
- "ur"
+ "Guarani",
+ "Avañe'ẽ",
+ "gn"
],
[
- "Nepali",
- "नà¥\87पालà¥\80",
- "ne"
+ "Goan Konkani",
+ "à¤\97à¥\8bवा à¤\95à¥\8bà¤\82à¤\95णà¥\80 / Gova Konknni",
+ "gom"
],
[
- "Sicilian",
- "Sicilianu",
- "scn"
+ "Gothic",
+ "𐌲𐌿𐍄𐌹𐍃𐌺",
+ "got"
],
[
"Gujarati",
"gu"
],
[
- "Cantonese",
- "粵語",
- "zh-yue"
+ "Manx",
+ "Gaelg",
+ "gv"
],
[
- "Low Saxon",
- "Plattdüütsch",
- "nds"
+ "Hausa",
+ "Hausa",
+ "ha"
],
[
- "Kurdish",
- "Kurdî / كوردی",
- "ku"
+ "Hakka Chinese",
+ "客家語/Hak-kâ-ngî",
+ "hak"
],
[
- "Irish",
- "Gaeilge",
- "ga"
+ "Hawaiian",
+ "Hawai`i",
+ "haw"
],
[
- "Asturian",
- "Asturianu",
- "ast"
+ "Hebrew",
+ "עברית",
+ "he"
],
[
- "Quechua",
- "Runa Simi",
- "qu"
+ "Hindi",
+ "हिन्दी",
+ "hi"
],
[
- "Sundanese",
- "Basa Sunda",
- "su"
+ "Fiji Hindi",
+ "Fiji Hindi",
+ "hif"
],
[
- "Chuvash",
- "Чăваш",
- "cv"
+ "Croatian",
+ "hrvatski",
+ "hr"
],
[
- "Scots",
- "Scots",
- "sco"
+ "Upper Sorbian",
+ "hornjoserbsce",
+ "hsb"
],
[
- "Interlingua",
- "Interlingua",
- "ia"
+ "Haitian",
+ "Kreyòl ayisyen",
+ "ht"
],
[
- "Alemannic",
- "Alemannisch",
- "als"
+ "Hungarian",
+ "magyar",
+ "hu"
],
[
- "Buginese",
- "Basa Ugi",
- "bug"
+ "Armenian",
+ "Հայերեն",
+ "hy"
],
[
- "Neapolitan",
- "Nnapulitano",
- "nap"
+ "Interlingua",
+ "interlingua",
+ "ia"
],
[
- "Samogitian",
- "Žemaitėška",
- "bat-smg"
+ "Indonesian",
+ "Bahasa Indonesia",
+ "id"
],
[
- "Kannada",
- "ಕನ್ನಡ",
- "kn"
+ "Interlingue",
+ "Interlingue",
+ "ie"
],
[
- "Banyumasan",
- "Basa Banyumasan",
- "map-bms"
+ "Igbo",
+ "Igbo",
+ "ig"
],
[
- "Walloon",
- "Walon",
- "wa"
+ "Inupiaq",
+ "Iñupiak",
+ "ik"
],
[
- "Amharic",
- "አማርኛ",
- "am"
+ "Iloko",
+ "Ilokano",
+ "ilo"
],
[
- "Sorani",
- "Soranî / کوردی",
- "ckb"
+ "Ido",
+ "Ido",
+ "io"
],
[
- "Scottish Gaelic",
- "Gàidhlig",
- "gd"
+ "Icelandic",
+ "íslenska",
+ "is"
],
[
- "Fiji Hindi",
- "Fiji Hindi",
- "hif"
+ "Italian",
+ "italiano",
+ "it"
],
[
- "Min Nan",
- "Bân-lâm-gú",
- "zh-min-nan"
+ "Inuktitut",
+ "ᐃᓄᒃᑎᑐᑦ/inuktitut",
+ "iu"
],
[
- "Tajik",
- "Тоҷикӣ",
- "tg"
+ "Japanese",
+ "日本語",
+ "ja"
],
[
- "Mazandarani",
- "مَزِروني",
- "mzn"
+ "Lojban",
+ "Lojban",
+ "jbo"
],
[
- "Egyptian Arabic",
- "مصرى (Maṣrī)",
- "arz"
+ "Javanese",
+ "Basa Jawa",
+ "jv"
],
[
- "Yiddish",
- "ייִדיש",
- "yi"
+ "Georgian",
+ "ქართული",
+ "ka"
],
[
- "Venetian",
- "Vèneto",
- "vec"
+ "Kara-Kalpak",
+ "Qaraqalpaqsha",
+ "kaa"
],
[
- "Mongolian",
- "Монгол",
- "mn"
+ "Kabyle",
+ "Taqbaylit",
+ "kab"
],
[
- "Tarantino",
- "Tarandíne",
- "roa-tara"
+ "Kabardian",
+ "Адыгэбзэ",
+ "kbd"
],
[
- "Sanskrit",
- "संस्कृतम्",
- "sa"
+ "Kongo",
+ "Kongo",
+ "kg"
],
[
- "Nahuatl",
- "Nāhuatl",
- "nah"
+ "Kikuyu",
+ "Gĩkũyũ",
+ "ki"
],
[
- "Ossetian",
- "Иронау",
- "os"
+ "Kazakh",
+ "қазақша",
+ "kk"
],
[
- "Sakha",
- "Саха тыла (Saxa Tyla)",
- "sah"
+ "Kalaallisut",
+ "kalaallisut",
+ "kl"
],
[
- "Kapampangan",
- "Kapampangan",
- "pam"
+ "Khmer",
+ "ភាសាខ្មែរ",
+ "km"
],
[
- "Upper Sorbian",
- "Hornjoserbsce",
- "hsb"
+ "Kannada",
+ "ಕನ್ನಡ",
+ "kn"
],
[
- "Sinhalese",
- "සිංහල",
- "si"
+ "Korean",
+ "한국어",
+ "ko"
],
[
- "Northern Sami",
- "Sámegiella",
- "se"
+ "Komi-Permyak",
+ "Перем Коми",
+ "koi"
],
[
- "Limburgish",
- "Limburgs",
- "li"
+ "Karachay-Balkar",
+ "къарачай-малкъар",
+ "krc"
],
[
- "Maori",
- "Māori",
- "mi"
+ "Kashmiri",
+ "कॉशुर / کٲشُر",
+ "ks"
],
[
- "Bavarian",
- "Boarisch",
- "bar"
+ "Colognian",
+ "Ripoarisch",
+ "ksh"
],
[
- "Corsican",
- "Corsu",
- "co"
+ "Kurdish",
+ "Kurdî",
+ "ku"
],
[
- "Ilokano",
- "Ilokano",
- "ilo"
+ "Komi",
+ "коми",
+ "kv"
],
[
- "Gan",
- "贛語",
- "gan"
+ "Cornish",
+ "kernowek",
+ "kw"
],
[
- "Tibetan",
- "བོད་སྐད",
- "bo"
+ "Kyrgyz",
+ "Кыргызча",
+ "ky"
],
[
- "Gilaki",
- "گیلکی",
- "glk"
+ "Latin",
+ "Latina",
+ "la"
],
[
- "Faroese",
- "Føroyskt",
- "fo"
+ "Ladino",
+ "Ladino",
+ "lad"
],
[
- "Rusyn",
- "русиньскый язык",
- "rue"
+ "Luxembourgish",
+ "Lëtzebuergesch",
+ "lb"
],
[
- "Punjabi",
- "ਪੰਜਾਬੀ",
- "pa"
+ "лакку",
+ "лакку",
+ "lbe"
],
[
- "Central_Bicolano",
- "Bikol",
- "bcl"
+ "Lezghian",
+ "лезги",
+ "lez"
],
[
- "Hill Mari",
- "Кырык Мары (Kyryk Mary) ",
- "mrj"
+ "Ganda",
+ "Luganda",
+ "lg"
],
[
- "Võro",
- "Võro",
- "fiu-vro"
+ "Limburgish",
+ "Limburgs",
+ "li"
],
[
- "Dutch Low Saxon",
- "Nedersaksisch",
- "nds-nl"
+ "Ligurian",
+ "Ligure",
+ "lij"
],
[
- "Turkmen",
- "تركمن / Туркмен",
- "tk"
+ "Lombard",
+ "lumbaart",
+ "lmo"
],
[
- "Pashto",
- "پښتو",
- "ps"
+ "Lingala",
+ "lingála",
+ "ln"
],
[
- "West Flemish",
- "West-Vlams",
- "vls"
+ "Lao",
+ "ລາວ",
+ "lo"
],
[
- "Mingrelian",
- "მარგალური (Margaluri)",
- "xmf"
+ "Northern Luri",
+ "لۊری شومالی",
+ "lrc"
],
[
- "Manx",
- "Gaelg",
- "gv"
+ "Lithuanian",
+ "lietuvių",
+ "lt"
],
[
- "Zazaki",
- "Zazaki",
- "diq"
+ "Latgalian",
+ "latgaļu",
+ "ltg"
],
[
- "Pangasinan",
- "Pangasinan",
- "pag"
+ "Latvian",
+ "latviešu",
+ "lv"
],
[
- "Komi",
- "Коми",
- "kv"
+ "Maithili",
+ "मैथिली",
+ "mai"
],
[
- "Zeelandic",
- "Zeêuws",
- "zea"
+ "Basa Banyumasan",
+ "Basa Banyumasan",
+ "map-bms"
],
[
- "Divehi",
- "ދިވެހިބަސް",
- "dv"
+ "Moksha",
+ "мокшень",
+ "mdf"
],
[
- "Oriya",
- "ଓଡ଼ିଆ",
- "or"
+ "Malagasy",
+ "Malagasy",
+ "mg"
],
[
- "Khmer",
- "ភាសាខ្មែរ",
- "km"
+ "Eastern Mari",
+ "олык марий",
+ "mhr"
],
[
- "Norman",
- "Nouormand/Normaund",
- "nrm"
+ "Maori",
+ "Māori",
+ "mi"
],
[
- "Romansh",
- "Rumantsch",
- "rm"
+ "Minangkabau",
+ "Baso Minangkabau",
+ "min"
],
[
- "Komi-Permyak",
- "Ð\9fеÑ\80ем Ð\9aоми (Perem Komi)",
- "koi"
+ "Macedonian",
+ "македонÑ\81ки",
+ "mk"
],
[
- "Udmurt",
- "Удмурт кыл",
- "udm"
+ "Malayalam",
+ "മലയാളം",
+ "ml"
],
[
- "Meadow Mari",
- "Ð\9eлÑ\8bк Ð\9cаÑ\80ий (Olyk Marij)",
- "mhr"
+ "Mongolian",
+ "монгол",
+ "mn"
],
[
- "Ladino",
- "Dzhudezmo",
- "lad"
+ "Marathi",
+ "मराठी",
+ "mr"
],
[
- "North Frisian",
- "Nordfriisk",
- "frr"
+ "Western Mari",
+ "кырык мары",
+ "mrj"
],
[
- "Kashubian",
- "Kaszëbsczi",
- "csb"
+ "Malay",
+ "Bahasa Melayu",
+ "ms"
],
[
- "Ligurian",
- "Líguru",
- "lij"
+ "Maltese",
+ "Malti",
+ "mt"
],
[
- "Wu",
- "吴语",
- "wuu"
+ "Mirandese",
+ "Mirandés",
+ "mwl"
],
[
- "Friulian",
- "Furlan",
- "fur"
+ "Burmese",
+ "မြန်မာဘာသာ",
+ "my"
],
[
- "Vepsian",
- "Vepsän",
- "vep"
+ "Erzya",
+ "эрзянь",
+ "myv"
],
[
- "Classical Chinese",
- "古文 / 文言文",
- "zh-classical"
+ "Mazanderani",
+ "مازِرونی",
+ "mzn"
],
[
- "Uyghur",
- "ئۇيغۇر تىلى",
- "ug"
+ "Nauru",
+ "Dorerin Naoero",
+ "na"
],
[
- "Saterland Frisian",
- "Seeltersk",
- "stq"
+ "Nāhuatl",
+ "Nāhuatl",
+ "nah"
],
[
- "Sardinian",
- "Sardu",
- "sc"
+ "Neapolitan",
+ "Napulitano",
+ "nap"
],
[
- "Aromanian",
- "Armãneashce",
- "roa-rup"
+ "Low German",
+ "Plattdüütsch",
+ "nds"
],
[
- "Pali",
- "पाऴि",
- "pi"
+ "Low Saxon (Netherlands)",
+ "Nedersaksies",
+ "nds-nl"
],
[
- "Somali",
- "Soomaaliga",
- "so"
+ "Nepali",
+ "नेपाली",
+ "ne"
],
[
- "Bihari",
- "à¤à¥\8bà¤\9cपà¥\81रà¥\80",
- "bh"
+ "Newari",
+ "नà¥\87पाल à¤à¤¾à¤·à¤¾",
+ "new"
],
[
- "Maltese",
- "Malti",
- "mt"
+ "Dutch",
+ "Nederlands",
+ "nl"
],
[
- "Aymara",
- "Aymar",
- "ay"
+ "Norwegian Nynorsk",
+ "norsk nynorsk",
+ "nn"
],
[
- "Ripuarian",
- "Ripoarisch",
- "ksh"
+ "Norwegian",
+ "norsk bokmål",
+ "no"
],
[
"Novial",
"nov"
],
[
- "Anglo-Saxon",
- "Englisc",
- "ang"
+ "Nouormand",
+ "Nouormand",
+ "nrm"
],
[
- "Cornish",
- "Kernewek/Karnuack",
- "kw"
+ "Northern Sotho",
+ "Sesotho sa Leboa",
+ "nso"
],
[
"Navajo",
"nv"
],
[
- "Picard",
- "Picard",
- "pcd"
- ],
- [
- "Hakka",
- "Hak-kâ-fa / 客家話",
- "hak"
+ "Nyanja",
+ "Chi-Chewa",
+ "ny"
],
[
- "Guarani",
- "Avañe'ẽ",
- "gn"
+ "Occitan",
+ "occitan",
+ "oc"
],
[
- "Extremaduran",
- "Estremeñu",
- "ext"
+ "Oromo",
+ "Oromoo",
+ "om"
],
[
- "Franco-Provençal/Arpitan",
- "Arpitan",
- "frp"
+ "Oriya",
+ "ଓଡ଼ିଆ",
+ "or"
],
[
- "Assamese",
- "অসমীয়া",
- "as"
+ "Ossetic",
+ "Ирон",
+ "os"
],
[
- "Silesian",
- "Ślůnski",
- "szl"
+ "Punjabi",
+ "ਪੰਜਾਬੀ",
+ "pa"
],
[
- "Gagauz",
- "Gagauz",
- "gag"
+ "Pangasinan",
+ "Pangasinan",
+ "pag"
],
[
- "Interlingue",
- "Interlingue",
- "ie"
+ "Pampanga",
+ "Kapampangan",
+ "pam"
],
[
- "Lingala",
- "Lingala",
- "ln"
+ "Papiamento",
+ "Papiamentu",
+ "pap"
],
[
- "Emilian-Romagnol",
- "Emiliàn e rumagnòl",
- "eml"
+ "Picard",
+ "Picard",
+ "pcd"
],
[
- "Chechen",
- "Нохчийн",
- "ce"
+ "Pennsylvania German",
+ "Deitsch",
+ "pdc"
],
[
- "Kalmyk",
- "Хальмг",
- "xal"
+ "Palatine German",
+ "Pälzisch",
+ "pfl"
],
[
- "Palatinate German",
- "Pfälzisch",
- "pfl"
+ "Pali",
+ "पालि",
+ "pi"
],
[
- "Hawaiian",
- "Hawai`i",
- "haw"
+ "Norfuk / Pitkern",
+ "Norfuk / Pitkern",
+ "pih"
],
[
- "Karachay-Balkar",
- "Къарачай-Малкъар (Qarachay-Malqar)",
- "krc"
+ "Polish",
+ "polski",
+ "pl"
],
[
- "Pennsylvania German",
- "Deitsch",
- "pdc"
+ "Piedmontese",
+ "Piemontèis",
+ "pms"
],
[
- "Kinyarwanda",
- "Ikinyarwanda",
- "rw"
+ "Western Punjabi",
+ "پنجابی",
+ "pnb"
],
[
- "Crimean Tatar",
- "Qırımtatarca",
- "crh"
+ "Pontic",
+ "Ποντιακά",
+ "pnt"
],
[
- "Acehnese",
- "Bahsa Acèh",
- "ace"
+ "Pashto",
+ "پښتو",
+ "ps"
],
[
- "Tongan",
- "faka Tonga",
- "to"
+ "Portuguese",
+ "português",
+ "pt"
],
[
- "Greenlandic",
- "Kalaallisut",
- "kl"
+ "Quechua",
+ "Runa Simi",
+ "qu"
],
[
- "Lower Sorbian",
- "Dolnoserbski",
- "dsb"
+ "Romansh",
+ "rumantsch",
+ "rm"
],
[
- "Aramaic",
- "ܐܪܡܝܐ",
- "arc"
+ "Romani",
+ "Romani",
+ "rmy"
],
[
- "Erzya",
- "Эрзянь (Erzjanj Kelj)",
- "myv"
+ "Rundi",
+ "Kirundi",
+ "rn"
],
[
- "Lezgian",
- "Лезги чІал (Lezgi č’al)",
- "lez"
+ "Romanian",
+ "română",
+ "ro"
],
[
- "Banjar",
- "Bahasa Banjar",
- "bjn"
+ "Aromanian",
+ "armãneashti",
+ "roa-rup"
],
[
- "Shona",
- "chiShona",
- "sn"
+ "tarandíne",
+ "tarandíne",
+ "roa-tara"
],
[
- "Papiamentu",
- "Papiamentu",
- "pap"
+ "Russian",
+ "русский",
+ "ru"
],
[
- "Kabyle",
- "Taqbaylit",
- "kab"
+ "Rusyn",
+ "русиньскый",
+ "rue"
],
[
- "Tok Pisin",
- "Tok Pisin",
- "tpi"
+ "Kinyarwanda",
+ "Kinyarwanda",
+ "rw"
],
[
- "Lak",
- "Лакку",
- "lbe"
+ "Sanskrit",
+ "संस्कृतम्",
+ "sa"
],
[
- "Buryat (Russia)",
- "Буряад",
- "bxr"
+ "Sakha",
+ "саха тыла",
+ "sah"
],
[
- "Lojban",
- "Lojban",
- "jbo"
+ "Sardinian",
+ "sardu",
+ "sc"
],
[
- "Wolof",
- "Wolof",
- "wo"
+ "Sicilian",
+ "sicilianu",
+ "scn"
],
[
- "Moksha",
- "Мокшень (Mokshanj Kälj)",
- "mdf"
+ "Scots",
+ "Scots",
+ "sco"
],
[
- "Zamboanga Chavacano",
- "Chavacano de Zamboanga",
- "cbk-zam"
+ "Sindhi",
+ "سنڌي",
+ "sd"
],
[
- "Avar",
- "Авар",
- "av"
+ "Northern Sami",
+ "sámegiella",
+ "se"
],
[
- "Sranan",
- "Sranantongo",
- "srn"
+ "Sango",
+ "Sängö",
+ "sg"
],
[
- "Mirandese",
- "Mirandés",
- "mwl"
+ "Serbo-Croatian",
+ "srpskohrvatski / српскохрватски",
+ "sh"
],
[
- "Kabardian Circassian",
- "Адыгэбзэ (Adighabze)",
- "kbd"
+ "Sinhala",
+ "සිංහල",
+ "si"
],
[
- "Tahitian",
- "Reo Mā`ohi",
- "ty"
+ "Simple English",
+ "Simple English",
+ "simple"
],
[
- "Lao",
- "ລາວ",
- "lo"
+ "Slovak",
+ "slovenčina",
+ "sk"
],
[
- "Abkhazian",
- "Аҧсуа",
- "ab"
+ "Slovenian",
+ "slovenščina",
+ "sl"
],
[
- "Tetum",
- "Tetun",
- "tet"
+ "Samoan",
+ "Gagana Samoa",
+ "sm"
],
[
- "Latgalian",
- "Latgaļu",
- "ltg"
+ "Shona",
+ "chiShona",
+ "sn"
],
[
- "Nauruan",
- "dorerin Naoero",
- "na"
+ "Somali",
+ "Soomaaliga",
+ "so"
],
[
- "Kongo",
- "KiKongo",
- "kg"
+ "Albanian",
+ "shqip",
+ "sq"
],
[
- "Igbo",
- "Igbo",
- "ig"
+ "Serbian",
+ "српски / srpski",
+ "sr"
],
[
- "Northern Sotho",
- "Sesotho sa Leboa",
- "nso"
+ "Sranan Tongo",
+ "Sranantongo",
+ "srn"
],
[
- "Zhuang",
- "Cuengh",
- "za"
+ "Swati",
+ "SiSwati",
+ "ss"
],
[
- "Karakalpak",
- "Qaraqalpaqsha",
- "kaa"
+ "Southern Sotho",
+ "Sesotho",
+ "st"
],
[
- "Zulu",
- "isiZulu",
- "zu"
+ "Saterland Frisian",
+ "Seeltersk",
+ "stq"
],
[
- "Cheyenne",
- "Tsetsêhestâhese",
- "chy"
+ "Sundanese",
+ "Basa Sunda",
+ "su"
],
[
- "Romani",
- "romani - रोमानी",
- "rmy"
+ "Swedish",
+ "svenska",
+ "sv"
],
[
- "Old Church Slavonic",
- "Словѣньскъ",
- "cu"
+ "Swahili",
+ "Kiswahili",
+ "sw"
],
[
- "Tswana",
- "Setswana",
- "tn"
+ "Silesian",
+ "ślůnski",
+ "szl"
],
[
- "Cherokee",
- "ᏣᎳᎩ",
- "chr"
+ "Tamil",
+ "தமிழ்",
+ "ta"
],
[
- "Bislama",
- "Bislama",
- "bi"
+ "Telugu",
+ "తెలుగు",
+ "te"
],
[
- "Min Dong",
- "Mìng-dĕ̤ng-ngṳ̄",
- "cdo"
+ "Tetum",
+ "tetun",
+ "tet"
],
[
- "Gothic",
- "𐌲𐌿𐍄𐌹𐍃𐌺",
- "got"
+ "Tajik",
+ "тоҷикӣ",
+ "tg"
],
[
- "Samoan",
- "Gagana Samoa",
- "sm"
+ "Thai",
+ "ไทย",
+ "th"
],
[
- "Moldovan",
- "Молдовеняскэ",
- "mo"
+ "Tigrinya",
+ "ትግርኛ",
+ "ti"
],
[
- "Bambara",
- "Bamanankan",
- "bm"
+ "Turkmen",
+ "Türkmençe",
+ "tk"
],
[
- "Inuktitut",
- "ᐃᓄᒃᑎᑐᑦ",
- "iu"
+ "Tagalog",
+ "Tagalog",
+ "tl"
],
[
- "Norfolk",
- "Norfuk",
- "pih"
+ "Tswana",
+ "Setswana",
+ "tn"
],
[
- "Pontic",
- "Ποντιακά",
- "pnt"
+ "Tongan",
+ "lea faka-Tonga",
+ "to"
],
[
- "Sindhi",
- "سنڌي، سندھی ، सिन्ध",
- "sd"
+ "Tok Pisin",
+ "Tok Pisin",
+ "tpi"
],
[
- "Swati",
- "SiSwati",
- "ss"
+ "Turkish",
+ "Türkçe",
+ "tr"
],
[
- "Kikuyu",
- "Gĩkũyũ",
- "ki"
+ "Tsonga",
+ "Xitsonga",
+ "ts"
],
[
- "Ewe",
- "Eʋegbe",
- "ee"
+ "Tatar",
+ "татарча/tatarça",
+ "tt"
],
[
- "Hausa",
- "هَوُسَ",
- "ha"
+ "Tumbuka",
+ "chiTumbuka",
+ "tum"
],
[
- "Oromo",
- "Oromoo",
- "om"
+ "Twi",
+ "Twi",
+ "tw"
],
[
- "Fijian",
- "Na Vosa Vakaviti",
- "fj"
+ "Tahitian",
+ "reo tahiti",
+ "ty"
],
[
- "Tigrinya",
- "ትግርኛ",
- "ti"
+ "Tuvinian",
+ "тыва дыл",
+ "tyv"
],
[
- "Tsonga",
- "Xitsonga",
- "ts"
+ "Udmurt",
+ "удмурт",
+ "udm"
],
[
- "Kashmiri",
- "कश्मीरी / كشميري",
- "ks"
+ "Uyghur",
+ "ئۇيغۇرچە / Uyghurche",
+ "ug"
],
[
- "Venda",
- "Tshivenda",
- "ve"
+ "Ukrainian",
+ "українська",
+ "uk"
],
[
- "Sango",
- "Sängö",
- "sg"
+ "Urdu",
+ "اردو",
+ "ur"
],
[
- "Kirundi",
- "Kirundi",
- "rn"
+ "Uzbek",
+ "oʻzbekcha/ўзбекча",
+ "uz"
],
[
- "Sesotho",
- "Sesotho",
- "st"
+ "Venda",
+ "Tshivenda",
+ "ve"
],
[
- "Dzongkha",
- "ཇོང་ཁ",
- "dz"
+ "Venetian",
+ "vèneto",
+ "vec"
],
[
- "Cree",
- "Nehiyaw",
- "cr"
+ "Veps",
+ "vepsän kel’",
+ "vep"
],
[
- "Akan",
- "Akana",
- "ak"
+ "Vietnamese",
+ "Tiếng Việt",
+ "vi"
],
[
- "Tumbuka",
- "chiTumbuka",
- "tum"
+ "West Flemish",
+ "West-Vlams",
+ "vls"
],
[
- "Luganda",
- "Luganda",
- "lg"
+ "Volapük",
+ "Volapük",
+ "vo"
],
[
- "Chichewa",
- "Chi-Chewa",
- "ny"
+ "Walloon",
+ "walon",
+ "wa"
],
[
- "Fula",
- "Fulfulde",
- "ff"
+ "Waray",
+ "Winaray",
+ "war"
],
[
- "Inupiak",
- "Iñupiak",
- "ik"
+ "Wolof",
+ "Wolof",
+ "wo"
],
[
- "Chamorro",
- "Chamoru",
- "ch"
+ "Wu Chinese",
+ "吴语",
+ "wuu"
],
[
- "Twi",
- "Twi",
- "tw"
+ "Kalmyk",
+ "хальмг",
+ "xal"
],
[
"Xhosa",
"xh"
],
[
- "Ndonga",
- "Oshiwambo",
- "ng"
+ "Mingrelian",
+ "მარგალური",
+ "xmf"
],
[
- "Sichuan Yi",
- "ꆇꉙ",
- "ii"
+ "Yiddish",
+ "ייִדיש",
+ "yi"
],
[
- "Choctaw",
- "Choctaw",
- "cho"
+ "Yoruba",
+ "Yorùbá",
+ "yo"
],
[
- "Marshallese",
- "Ebon",
- "mh"
+ "Zhuang",
+ "Vahcuengh",
+ "za"
],
[
- "Afar",
- "Afar",
- "aa"
+ "Zeelandic",
+ "Zeêuws",
+ "zea"
],
[
- "Kuanyama",
- "Kuanyama",
- "kj"
+ "Chinese",
+ "中文",
+ "zh"
],
[
- "Hiri Motu",
- "Hiri Motu",
- "ho"
+ "Classical Chinese",
+ "文言",
+ "zh-classical"
],
[
- "Muscogee",
- "Muskogee",
- "mus"
+ "Chinese (Min Nan)",
+ "Bân-lâm-gú",
+ "zh-min-nan"
],
[
- "Kanuri",
- "Kanuri",
- "kr"
+ "Cantonese",
+ "粵語",
+ "zh-yue"
],
[
- "Herero",
- "Otsiherero",
- "hz"
+ "Zulu",
+ "isiZulu",
+ "zu"
]
],
"imperial": {
56.682278
],
[
- -131.830424,
- 56.664759
- ],
- [
- -131.826574,
- 56.644606
- ],
- [
- -131.832103,
- 56.603368
- ],
- [
- -131.825592,
- 56.593343
- ],
- [
- -131.799108,
- 56.587658
- ],
- [
- -131.692293,
- 56.585074
- ],
- [
- -131.585891,
- 56.595048
- ],
- [
- -131.560363,
- 56.594066
- ],
- [
- -131.536437,
- 56.585229
- ],
- [
- -131.491659,
- 56.560166
- ],
- [
- -131.345699,
- 56.503271
- ],
- [
- -131.215604,
- 56.45255
- ],
- [
- -131.100546,
- 56.407669
- ],
- [
- -131.016934,
- 56.38705
- ],
- [
- -130.839089,
- 56.372452
- ],
- [
- -130.760334,
- 56.345192
- ],
- [
- -130.645768,
- 56.261942
- ],
- [
- -130.602256,
- 56.247059
- ],
- [
- -130.495518,
- 56.232434
- ],
- [
- -130.47229,
- 56.22489
- ],
- [
- -130.458053,
- 56.210653
- ],
- [
- -130.427926,
- 56.143964
- ],
- [
- -130.418159,
- 56.129702
- ],
- [
- -130.403974,
- 56.121898
- ],
- [
- -130.290311,
- 56.10097
- ],
- [
- -130.243156,
- 56.092391
- ],
- [
- -130.211246,
- 56.089962
- ],
- [
- -130.116756,
- 56.105646
- ],
- [
- -130.094328,
- 56.101486
- ],
- [
- -130.071539,
- 56.084123
- ],
- [
- -130.039319,
- 56.045521
- ],
- [
- -130.026632,
- 56.024101
- ],
- [
- -130.01901,
- 56.002216
- ],
- [
- -130.014695,
- 55.963252
- ],
- [
- -130.016788,
- 55.918913
- ],
- [
- -130.019612,
- 55.907978
- ],
- [
- -130.019618,
- 55.907952
- ],
- [
- -130.022817,
- 55.901353
- ],
- [
- -130.049387,
- 55.871405
- ],
- [
- -130.104726,
- 55.825263
- ],
- [
- -130.136627,
- 55.806464
- ],
- [
- -130.148834,
- 55.795356
- ],
- [
- -130.163482,
- 55.771145
- ],
- [
- -130.167307,
- 55.766262
- ],
- [
- -130.170806,
- 55.759833
- ],
- [
- -130.173655,
- 55.749498
- ],
- [
- -130.170806,
- 55.740953
- ],
- [
- -130.163808,
- 55.734565
- ],
- [
- -130.160064,
- 55.727118
- ],
- [
- -130.167388,
- 55.715399
- ],
- [
- -130.155914,
- 55.700141
- ],
- [
- -130.142893,
- 55.689521
- ],
- [
- -130.131825,
- 55.676581
- ],
- [
- -130.126454,
- 55.653998
- ],
- [
- -130.12857,
- 55.63642
- ],
- [
- -130.135121,
- 55.619127
- ],
- [
- -130.153147,
- 55.58511
- ],
- [
- -130.148671,
- 55.578192
- ],
- [
- -130.146881,
- 55.569322
- ],
- [
- -130.146962,
- 55.547187
- ],
- [
- -130.112172,
- 55.509345
- ],
- [
- -130.101674,
- 55.481147
- ],
- [
- -130.095082,
- 55.472113
- ],
- [
- -130.065419,
- 55.446112
- ],
- [
- -130.057525,
- 55.434882
- ],
- [
- -130.052561,
- 55.414008
- ],
- [
- -130.054311,
- 55.366645
- ],
- [
- -130.05012,
- 55.345445
- ],
- [
- -130.039296,
- 55.330756
- ],
- [
- -129.989247,
- 55.284003
- ],
- [
- -130.031239,
- 55.26435
- ],
- [
- -130.050038,
- 55.252875
- ],
- [
- -130.067494,
- 55.239
- ],
- [
- -130.078236,
- 55.233791
- ],
- [
- -130.100494,
- 55.230292
- ],
- [
- -130.104726,
- 55.225653
- ],
- [
- -130.105702,
- 55.211127
- ],
- [
- -130.10912,
- 55.200751
- ],
- [
- -130.115793,
- 55.191596
- ],
- [
- -130.126454,
- 55.180976
- ],
- [
- -130.151967,
- 55.163275
- ],
- [
- -130.159983,
- 55.153713
- ],
- [
- -130.167592,
- 55.129584
- ],
- [
- -130.173695,
- 55.117743
- ],
- [
- -130.200266,
- 55.104153
- ],
- [
- -130.211781,
- 55.084133
- ],
- [
- -130.228871,
- 55.04385
- ],
- [
- -130.238678,
- 55.03441
- ],
- [
- -130.261342,
- 55.022895
- ],
- [
- -130.269846,
- 55.016547
- ],
- [
- -130.275706,
- 55.006985
- ],
- [
- -130.286366,
- 54.983222
- ],
- [
- -130.294342,
- 54.971869
- ],
- [
- -130.326568,
- 54.952094
- ],
- [
- -130.335561,
- 54.938707
- ],
- [
- -130.365387,
- 54.907294
- ],
- [
- -130.385243,
- 54.896552
- ],
- [
- -130.430816,
- 54.881252
- ],
- [
- -130.488759,
- 54.844184
- ],
- [
- -130.580312,
- 54.806383
- ],
- [
- -130.597485,
- 54.803391
- ],
- [
- -130.71074,
- 54.733215
- ],
- [
- -131.160718,
- 54.787192
- ]
- ]
- ]
- ]
- }
- }
- ]
- },
- "featureIcons": {
- "circle-stroked": {
- "12": [
- 42,
- 0
- ],
- "18": [
- 24,
- 0
- ],
- "24": [
- 0,
- 0
- ]
- },
- "circle": {
- "12": [
- 96,
- 0
- ],
- "18": [
- 78,
- 0
- ],
- "24": [
- 54,
- 0
- ]
- },
- "square-stroked": {
- "12": [
- 150,
- 0
- ],
- "18": [
- 132,
- 0
- ],
- "24": [
- 108,
- 0
- ]
- },
- "square": {
- "12": [
- 204,
- 0
- ],
- "18": [
- 186,
- 0
- ],
- "24": [
- 162,
- 0
- ]
- },
- "triangle-stroked": {
- "12": [
- 258,
- 0
- ],
- "18": [
- 240,
- 0
- ],
- "24": [
- 216,
- 0
- ]
- },
- "triangle": {
- "12": [
- 42,
- 24
- ],
- "18": [
- 24,
- 24
- ],
- "24": [
- 0,
- 24
- ]
- },
- "star-stroked": {
- "12": [
- 96,
- 24
- ],
- "18": [
- 78,
- 24
- ],
- "24": [
- 54,
- 24
- ]
- },
- "star": {
- "12": [
- 150,
- 24
- ],
- "18": [
- 132,
- 24
- ],
- "24": [
- 108,
- 24
- ]
- },
- "cross": {
- "12": [
- 204,
- 24
- ],
- "18": [
- 186,
- 24
- ],
- "24": [
- 162,
- 24
- ]
- },
- "marker-stroked": {
- "12": [
- 258,
- 24
- ],
- "18": [
- 240,
- 24
- ],
- "24": [
- 216,
- 24
- ]
- },
- "marker": {
- "12": [
- 42,
- 48
- ],
- "18": [
- 24,
- 48
- ],
- "24": [
- 0,
- 48
- ]
- },
- "religious-jewish": {
- "12": [
- 96,
- 48
- ],
- "18": [
- 78,
- 48
- ],
- "24": [
- 54,
- 48
- ]
- },
- "religious-christian": {
- "12": [
- 150,
- 48
- ],
- "18": [
- 132,
- 48
- ],
- "24": [
- 108,
- 48
- ]
- },
- "religious-muslim": {
- "12": [
- 204,
- 48
- ],
- "18": [
- 186,
- 48
- ],
- "24": [
- 162,
- 48
- ]
- },
- "cemetery": {
- "12": [
- 258,
- 48
- ],
- "18": [
- 240,
- 48
- ],
- "24": [
- 216,
- 48
- ]
- },
- "rocket": {
- "12": [
- 42,
- 72
- ],
- "18": [
- 24,
- 72
- ],
- "24": [
- 0,
- 72
- ]
- },
- "airport": {
- "12": [
- 96,
- 72
- ],
- "18": [
- 78,
- 72
- ],
- "24": [
- 54,
- 72
- ]
- },
- "heliport": {
- "12": [
- 150,
- 72
- ],
- "18": [
- 132,
- 72
- ],
- "24": [
- 108,
- 72
- ]
- },
- "rail": {
- "12": [
- 204,
- 72
- ],
- "18": [
- 186,
- 72
- ],
- "24": [
- 162,
- 72
- ]
- },
- "rail-metro": {
- "12": [
- 258,
- 72
- ],
- "18": [
- 240,
- 72
- ],
- "24": [
- 216,
- 72
- ]
- },
- "rail-light": {
- "12": [
- 42,
- 96
- ],
- "18": [
- 24,
- 96
- ],
- "24": [
- 0,
- 96
- ]
- },
- "bus": {
- "12": [
- 96,
- 96
- ],
- "18": [
- 78,
- 96
- ],
- "24": [
- 54,
- 96
- ]
- },
- "fuel": {
- "12": [
- 150,
- 96
- ],
- "18": [
- 132,
- 96
- ],
- "24": [
- 108,
- 96
- ]
- },
- "parking": {
- "12": [
- 204,
- 96
- ],
- "18": [
- 186,
- 96
- ],
- "24": [
- 162,
- 96
- ]
- },
- "parking-garage": {
- "12": [
- 258,
- 96
- ],
- "18": [
- 240,
- 96
- ],
- "24": [
- 216,
- 96
- ]
- },
- "airfield": {
- "12": [
- 42,
- 120
- ],
- "18": [
- 24,
- 120
- ],
- "24": [
- 0,
- 120
- ]
- },
- "roadblock": {
- "12": [
- 96,
- 120
- ],
- "18": [
- 78,
- 120
- ],
- "24": [
- 54,
- 120
- ]
- },
- "ferry": {
- "12": [
- 150,
- 120
- ],
- "18": [
- 132,
- 120
- ],
- "24": [
- 108,
- 120
- ],
- "line": [
- 2240,
- 25
- ]
- },
- "harbor": {
- "12": [
- 204,
- 120
- ],
- "18": [
- 186,
- 120
- ],
- "24": [
- 162,
- 120
- ]
- },
- "bicycle": {
- "12": [
- 258,
- 120
- ],
- "18": [
- 240,
- 120
- ],
- "24": [
- 216,
- 120
- ]
- },
- "park": {
- "12": [
- 42,
- 144
- ],
- "18": [
- 24,
- 144
- ],
- "24": [
- 0,
- 144
- ]
- },
- "park2": {
- "12": [
- 96,
- 144
- ],
- "18": [
- 78,
- 144
- ],
- "24": [
- 54,
- 144
- ]
- },
- "museum": {
- "12": [
- 150,
- 144
- ],
- "18": [
- 132,
- 144
- ],
- "24": [
- 108,
- 144
- ]
- },
- "lodging": {
- "12": [
- 204,
- 144
- ],
- "18": [
- 186,
- 144
- ],
- "24": [
- 162,
- 144
- ]
- },
- "monument": {
- "12": [
- 258,
- 144
- ],
- "18": [
- 240,
- 144
- ],
- "24": [
- 216,
- 144
- ]
- },
- "zoo": {
- "12": [
- 42,
- 168
- ],
- "18": [
- 24,
- 168
- ],
- "24": [
- 0,
- 168
- ]
- },
- "garden": {
- "12": [
- 96,
- 168
- ],
- "18": [
- 78,
- 168
- ],
- "24": [
- 54,
- 168
- ]
- },
- "campsite": {
- "12": [
- 150,
- 168
- ],
- "18": [
- 132,
- 168
- ],
- "24": [
- 108,
- 168
- ]
- },
- "theatre": {
- "12": [
- 204,
- 168
- ],
- "18": [
- 186,
- 168
- ],
- "24": [
- 162,
- 168
- ]
- },
- "art-gallery": {
- "12": [
- 258,
- 168
- ],
- "18": [
- 240,
- 168
- ],
- "24": [
- 216,
- 168
- ]
- },
- "pitch": {
- "12": [
- 42,
- 192
- ],
- "18": [
- 24,
- 192
- ],
- "24": [
- 0,
- 192
- ]
- },
- "soccer": {
- "12": [
- 96,
- 192
- ],
- "18": [
- 78,
- 192
- ],
- "24": [
- 54,
- 192
- ]
- },
- "america-football": {
- "12": [
- 150,
- 192
- ],
- "18": [
- 132,
- 192
- ],
- "24": [
- 108,
- 192
- ]
- },
- "tennis": {
- "12": [
- 204,
- 192
- ],
- "18": [
- 186,
- 192
- ],
- "24": [
- 162,
- 192
- ]
- },
- "basketball": {
- "12": [
- 258,
- 192
- ],
- "18": [
- 240,
- 192
- ],
- "24": [
- 216,
- 192
- ]
- },
- "baseball": {
- "12": [
- 42,
- 216
- ],
- "18": [
- 24,
- 216
- ],
- "24": [
- 0,
- 216
- ]
- },
- "golf": {
- "12": [
- 96,
- 216
- ],
- "18": [
- 78,
- 216
- ],
- "24": [
- 54,
- 216
- ]
- },
- "swimming": {
- "12": [
- 150,
- 216
- ],
- "18": [
- 132,
- 216
- ],
- "24": [
- 108,
- 216
- ]
- },
- "cricket": {
- "12": [
- 204,
- 216
- ],
- "18": [
- 186,
- 216
- ],
- "24": [
- 162,
- 216
- ]
- },
- "skiing": {
- "12": [
- 258,
- 216
- ],
- "18": [
- 240,
- 216
- ],
- "24": [
- 216,
- 216
- ]
- },
- "school": {
- "12": [
- 42,
- 240
- ],
- "18": [
- 24,
- 240
- ],
- "24": [
- 0,
- 240
- ]
- },
- "college": {
- "12": [
- 96,
- 240
- ],
- "18": [
- 78,
- 240
- ],
- "24": [
- 54,
- 240
- ]
- },
- "library": {
- "12": [
- 150,
- 240
- ],
- "18": [
- 132,
- 240
- ],
- "24": [
- 108,
- 240
- ]
- },
- "post": {
- "12": [
- 204,
- 240
- ],
- "18": [
- 186,
- 240
- ],
- "24": [
- 162,
- 240
- ]
- },
- "fire-station": {
- "12": [
- 258,
- 240
- ],
- "18": [
- 240,
- 240
- ],
- "24": [
- 216,
- 240
- ]
- },
- "town-hall": {
- "12": [
- 42,
- 264
- ],
- "18": [
- 24,
- 264
- ],
- "24": [
- 0,
- 264
- ]
- },
- "police": {
- "12": [
- 96,
- 264
- ],
- "18": [
- 78,
- 264
- ],
- "24": [
- 54,
- 264
- ]
- },
- "prison": {
- "12": [
- 150,
- 264
- ],
- "18": [
- 132,
- 264
- ],
- "24": [
- 108,
- 264
- ]
- },
- "embassy": {
- "12": [
- 204,
- 264
- ],
- "18": [
- 186,
- 264
- ],
- "24": [
- 162,
- 264
- ]
- },
- "beer": {
- "12": [
- 258,
- 264
- ],
- "18": [
- 240,
- 264
- ],
- "24": [
- 216,
- 264
- ]
- },
- "restaurant": {
- "12": [
- 42,
- 288
- ],
- "18": [
- 24,
- 288
- ],
- "24": [
- 0,
- 288
- ]
- },
- "cafe": {
- "12": [
- 96,
- 288
- ],
- "18": [
- 78,
- 288
- ],
- "24": [
- 54,
- 288
- ]
- },
- "shop": {
- "12": [
- 150,
- 288
- ],
- "18": [
- 132,
- 288
- ],
- "24": [
- 108,
- 288
- ]
- },
- "fast-food": {
- "12": [
- 204,
- 288
- ],
- "18": [
- 186,
- 288
- ],
- "24": [
- 162,
- 288
- ]
- },
- "bar": {
- "12": [
- 258,
- 288
- ],
- "18": [
- 240,
- 288
- ],
- "24": [
- 216,
- 288
- ]
- },
- "bank": {
- "12": [
- 42,
- 312
- ],
- "18": [
- 24,
- 312
- ],
- "24": [
- 0,
- 312
- ]
- },
- "grocery": {
- "12": [
- 96,
- 312
- ],
- "18": [
- 78,
- 312
- ],
- "24": [
- 54,
- 312
- ]
- },
- "cinema": {
- "12": [
- 150,
- 312
- ],
- "18": [
- 132,
- 312
- ],
- "24": [
- 108,
- 312
- ]
- },
- "pharmacy": {
- "12": [
- 204,
- 312
- ],
- "18": [
- 186,
- 312
- ],
- "24": [
- 162,
- 312
- ]
- },
- "hospital": {
- "12": [
- 258,
- 312
- ],
- "18": [
- 240,
- 312
- ],
- "24": [
- 216,
- 312
- ]
- },
- "danger": {
- "12": [
- 42,
- 336
- ],
- "18": [
- 24,
- 336
- ],
- "24": [
- 0,
- 336
- ]
- },
- "industrial": {
- "12": [
- 96,
- 336
- ],
- "18": [
- 78,
- 336
- ],
- "24": [
- 54,
- 336
- ]
- },
- "warehouse": {
- "12": [
- 150,
- 336
- ],
- "18": [
- 132,
- 336
- ],
- "24": [
- 108,
- 336
- ]
- },
- "commercial": {
- "12": [
- 204,
- 336
- ],
- "18": [
- 186,
- 336
- ],
- "24": [
- 162,
- 336
- ]
- },
- "building": {
- "12": [
- 258,
- 336
- ],
- "18": [
- 240,
- 336
- ],
- "24": [
- 216,
- 336
- ]
- },
- "place-of-worship": {
- "12": [
- 42,
- 360
- ],
- "18": [
- 24,
- 360
- ],
- "24": [
- 0,
- 360
- ]
- },
- "alcohol-shop": {
- "12": [
- 96,
- 360
- ],
- "18": [
- 78,
- 360
- ],
- "24": [
- 54,
- 360
- ]
- },
- "logging": {
- "12": [
- 150,
- 360
- ],
- "18": [
- 132,
- 360
- ],
- "24": [
- 108,
- 360
- ]
- },
- "oil-well": {
- "12": [
- 204,
- 360
- ],
- "18": [
- 186,
- 360
- ],
- "24": [
- 162,
- 360
- ]
- },
- "slaughterhouse": {
- "12": [
- 258,
- 360
- ],
- "18": [
- 240,
- 360
- ],
- "24": [
- 216,
- 360
- ]
- },
- "dam": {
- "12": [
- 42,
- 384
- ],
- "18": [
- 24,
- 384
- ],
- "24": [
- 0,
- 384
- ]
- },
- "water": {
- "12": [
- 96,
- 384
- ],
- "18": [
- 78,
- 384
- ],
- "24": [
- 54,
- 384
- ]
- },
- "wetland": {
- "12": [
- 150,
- 384
- ],
- "18": [
- 132,
- 384
- ],
- "24": [
- 108,
- 384
- ]
- },
- "disability": {
- "12": [
- 204,
- 384
- ],
- "18": [
- 186,
- 384
- ],
- "24": [
- 162,
- 384
- ]
- },
- "telephone": {
- "12": [
- 258,
- 384
- ],
- "18": [
- 240,
- 384
- ],
- "24": [
- 216,
- 384
- ]
- },
- "emergency-telephone": {
- "12": [
- 42,
- 408
- ],
- "18": [
- 24,
- 408
- ],
- "24": [
- 0,
- 408
- ]
- },
- "toilets": {
- "12": [
- 96,
- 408
- ],
- "18": [
- 78,
- 408
- ],
- "24": [
- 54,
- 408
- ]
- },
- "waste-basket": {
- "12": [
- 150,
- 408
- ],
- "18": [
- 132,
- 408
- ],
- "24": [
- 108,
- 408
- ]
- },
- "music": {
- "12": [
- 204,
- 408
- ],
- "18": [
- 186,
- 408
- ],
- "24": [
- 162,
- 408
- ]
- },
- "land-use": {
- "12": [
- 258,
- 408
- ],
- "18": [
- 240,
- 408
- ],
- "24": [
- 216,
- 408
- ]
- },
- "city": {
- "12": [
- 42,
- 432
- ],
- "18": [
- 24,
- 432
- ],
- "24": [
- 0,
- 432
- ]
- },
- "town": {
- "12": [
- 96,
- 432
- ],
- "18": [
- 78,
- 432
- ],
- "24": [
- 54,
- 432
- ]
- },
- "village": {
- "12": [
- 150,
- 432
- ],
- "18": [
- 132,
- 432
- ],
- "24": [
- 108,
- 432
- ]
- },
- "farm": {
- "12": [
- 204,
- 432
- ],
- "18": [
- 186,
- 432
- ],
- "24": [
- 162,
- 432
- ]
- },
- "bakery": {
- "12": [
- 258,
- 432
- ],
- "18": [
- 240,
- 432
- ],
- "24": [
- 216,
- 432
- ]
- },
- "dog-park": {
- "12": [
- 42,
- 456
- ],
- "18": [
- 24,
- 456
- ],
- "24": [
- 0,
- 456
- ]
- },
- "lighthouse": {
- "12": [
- 96,
- 456
- ],
- "18": [
- 78,
- 456
- ],
- "24": [
- 54,
- 456
- ]
- },
- "clothing-store": {
- "12": [
- 150,
- 456
- ],
- "18": [
- 132,
- 456
- ],
- "24": [
- 108,
- 456
- ]
- },
- "polling-place": {
- "12": [
- 204,
- 456
- ],
- "18": [
- 186,
- 456
- ],
- "24": [
- 162,
- 456
- ]
- },
- "playground": {
- "12": [
- 258,
- 456
- ],
- "18": [
- 240,
- 456
- ],
- "24": [
- 216,
- 456
- ]
- },
- "entrance": {
- "12": [
- 42,
- 480
- ],
- "18": [
- 24,
- 480
- ],
- "24": [
- 0,
- 480
- ]
- },
- "heart": {
- "12": [
- 96,
- 480
- ],
- "18": [
- 78,
- 480
- ],
- "24": [
- 54,
- 480
- ]
- },
- "london-underground": {
- "12": [
- 150,
- 480
- ],
- "18": [
- 132,
- 480
- ],
- "24": [
- 108,
- 480
- ]
- },
- "minefield": {
- "12": [
- 204,
- 480
- ],
- "18": [
- 186,
- 480
- ],
- "24": [
- 162,
- 480
- ]
- },
- "rail-underground": {
- "12": [
- 258,
- 480
- ],
- "18": [
- 240,
- 480
- ],
- "24": [
- 216,
- 480
- ]
- },
- "rail-above": {
- "12": [
- 42,
- 504
- ],
- "18": [
- 24,
- 504
- ],
- "24": [
- 0,
- 504
- ]
- },
- "camera": {
- "12": [
- 96,
- 504
- ],
- "18": [
- 78,
- 504
- ],
- "24": [
- 54,
- 504
- ]
- },
- "laundry": {
- "12": [
- 150,
- 504
- ],
- "18": [
- 132,
- 504
- ],
- "24": [
- 108,
- 504
- ]
- },
- "car": {
- "12": [
- 204,
- 504
- ],
- "18": [
- 186,
- 504
- ],
- "24": [
- 162,
- 504
- ]
- },
- "suitcase": {
- "12": [
- 258,
- 504
- ],
- "18": [
- 240,
- 504
- ],
- "24": [
- 216,
- 504
- ]
- },
- "hairdresser": {
- "12": [
- 42,
- 528
- ],
- "18": [
- 24,
- 528
- ],
- "24": [
- 0,
- 528
- ]
- },
- "chemist": {
- "12": [
- 96,
- 528
- ],
- "18": [
- 78,
- 528
- ],
- "24": [
- 54,
- 528
- ]
- },
- "mobilephone": {
- "12": [
- 150,
- 528
- ],
- "18": [
- 132,
- 528
- ],
- "24": [
- 108,
- 528
- ]
- },
- "scooter": {
- "12": [
- 204,
- 528
- ],
- "18": [
- 186,
- 528
- ],
- "24": [
- 162,
- 528
- ]
- },
- "gift": {
- "12": [
- 258,
- 528
- ],
- "18": [
- 240,
- 528
- ],
- "24": [
- 216,
- 528
- ]
- },
- "ice-cream": {
- "12": [
- 42,
- 552
- ],
- "18": [
- 24,
- 552
- ],
- "24": [
- 0,
- 552
- ]
- },
- "highway-motorway": {
- "line": [
- 20,
- 25
- ]
- },
- "highway-trunk": {
- "line": [
- 80,
- 25
- ]
- },
- "highway-primary": {
- "line": [
- 140,
- 25
- ]
- },
- "highway-secondary": {
- "line": [
- 200,
- 25
- ]
- },
- "highway-tertiary": {
- "line": [
- 260,
- 25
- ]
- },
- "highway-motorway-link": {
- "line": [
- 320,
- 25
- ]
- },
- "highway-trunk-link": {
- "line": [
- 380,
- 25
- ]
- },
- "highway-primary-link": {
- "line": [
- 440,
- 25
- ]
- },
- "highway-secondary-link": {
- "line": [
- 500,
- 25
- ]
- },
- "highway-tertiary-link": {
- "line": [
- 560,
- 25
- ]
- },
- "highway-residential": {
- "line": [
- 620,
- 25
- ]
- },
- "highway-unclassified": {
- "line": [
- 680,
- 25
- ]
- },
- "highway-service": {
- "line": [
- 740,
- 25
- ]
- },
- "highway-road": {
- "line": [
- 800,
- 25
- ]
- },
- "highway-track": {
- "line": [
- 860,
- 25
- ]
- },
- "highway-living-street": {
- "line": [
- 920,
- 25
- ]
- },
- "highway-path": {
- "line": [
- 980,
- 25
- ]
- },
- "highway-cycleway": {
- "line": [
- 1040,
- 25
- ]
- },
- "highway-footway": {
- "line": [
- 1100,
- 25
- ]
- },
- "highway-bridleway": {
- "line": [
- 1160,
- 25
- ]
- },
- "highway-steps": {
- "line": [
- 1220,
- 25
- ]
- },
- "railway-rail": {
- "line": [
- 1280,
- 25
- ]
- },
- "railway-disused": {
- "line": [
- 1340,
- 25
- ]
- },
- "railway-abandoned": {
- "line": [
- 1400,
- 25
- ]
- },
- "railway-subway": {
- "line": [
- 1460,
- 25
- ]
- },
- "railway-light-rail": {
- "line": [
- 1520,
- 25
- ]
- },
- "railway-monorail": {
- "line": [
- 1580,
- 25
- ]
- },
- "waterway-river": {
- "line": [
- 1640,
- 25
- ]
- },
- "waterway-stream": {
- "line": [
- 1700,
- 25
- ]
- },
- "waterway-canal": {
- "line": [
- 1760,
- 25
- ]
- },
- "waterway-ditch": {
- "line": [
- 1820,
- 25
- ]
- },
- "power-line": {
- "line": [
- 1880,
- 25
- ]
- },
- "other-line": {
- "line": [
- 1940,
- 25
- ]
- },
- "category-roads": {
- "line": [
- 2000,
- 25
- ]
- },
- "category-rail": {
- "line": [
- 2060,
- 25
- ]
- },
- "category-path": {
- "line": [
- 2120,
- 25
- ]
- },
- "category-water": {
- "line": [
- 2180,
- 25
- ]
- },
- "pipeline": {
- "line": [
- 2300,
- 25
- ]
- },
- "relation": {
- "relation": [
- 20,
- 25
- ]
- },
- "restriction": {
- "relation": [
- 80,
- 25
- ]
- },
- "multipolygon": {
- "relation": [
- 141,
- 25
- ]
- },
- "boundary": {
- "relation": [
- 200,
- 25
- ]
- },
- "route": {
- "relation": [
- 260,
- 25
- ]
- },
- "route-road": {
- "relation": [
- 320,
- 25
- ]
- },
- "route-bicycle": {
- "relation": [
- 380,
- 25
- ]
- },
- "route-foot": {
- "relation": [
- 440,
- 25
- ]
- },
- "route-bus": {
- "relation": [
- 500,
- 25
- ]
- },
- "route-train": {
- "relation": [
- 560,
- 25
- ]
- },
- "route-detour": {
- "relation": [
- 620,
- 25
- ]
- },
- "route-tram": {
- "relation": [
- 680,
- 25
- ]
- },
- "route-ferry": {
- "relation": [
- 740,
- 25
- ]
- },
- "route-power": {
- "relation": [
- 800,
- 25
- ]
- },
- "route-pipeline": {
- "relation": [
- 860,
- 25
- ]
- },
- "route-master": {
- "relation": [
- 920,
- 25
- ]
- },
- "restriction-no-straight-on": {
- "relation": [
- 980,
- 25
- ]
- },
- "restriction-no-u-turn": {
- "relation": [
- 1040,
- 25
- ]
- },
- "restriction-no-left-turn": {
- "relation": [
- 1100,
- 25
- ]
- },
- "restriction-no-right-turn": {
- "relation": [
- 1160,
- 25
- ]
- },
- "restriction-only-straight-on": {
- "relation": [
- 1220,
- 25
- ]
- },
- "restriction-only-left-turn": {
- "relation": [
- 1280,
- 25
- ]
- },
- "restriction-only-right-turn": {
- "relation": [
- 1340,
- 25
- ]
- }
- },
- "operations": {
- "icon-operation-delete": [
- 0,
- 140
- ],
- "icon-operation-circularize": [
- 20,
- 140
- ],
- "icon-operation-straighten": [
- 40,
- 140
- ],
- "icon-operation-split": [
- 60,
- 140
- ],
- "icon-operation-disconnect": [
- 80,
- 140
- ],
- "icon-operation-reverse": [
- 100,
- 140
- ],
- "icon-operation-move": [
- 120,
- 140
- ],
- "icon-operation-merge": [
- 140,
- 140
- ],
- "icon-operation-orthogonalize": [
- 160,
- 140
- ],
- "icon-operation-rotate": [
- 180,
- 140
- ],
- "icon-operation-simplify": [
- 200,
- 140
- ],
- "icon-operation-continue": [
- 220,
- 140
- ],
- "icon-operation-disabled-delete": [
- 0,
- 160
- ],
- "icon-operation-disabled-circularize": [
- 20,
- 160
- ],
- "icon-operation-disabled-straighten": [
- 40,
- 160
- ],
- "icon-operation-disabled-split": [
- 60,
- 160
- ],
- "icon-operation-disabled-disconnect": [
- 80,
- 160
- ],
- "icon-operation-disabled-reverse": [
- 100,
- 160
- ],
- "icon-operation-disabled-move": [
- 120,
- 160
- ],
- "icon-operation-disabled-merge": [
- 140,
- 160
- ],
- "icon-operation-disabled-orthogonalize": [
- 160,
- 160
- ],
- "icon-operation-disabled-rotate": [
- 180,
- 160
- ],
- "icon-operation-disabled-simplify": [
- 200,
- 160
- ],
- "icon-operation-disabled-continue": [
- 220,
- 160
- ],
- "icon-restriction-yes": [
- 50,
- 80
- ],
- "icon-restriction-no": [
- 95,
- 80
- ],
- "icon-restriction-only": [
- 140,
- 80
- ],
- "icon-restriction-yes-u": [
- 185,
- 80
- ],
- "icon-restriction-no-u": [
- 230,
- 80
- ],
- "icon-restriction-only-u": [
- 275,
- 80
+ -131.830424,
+ 56.664759
+ ],
+ [
+ -131.826574,
+ 56.644606
+ ],
+ [
+ -131.832103,
+ 56.603368
+ ],
+ [
+ -131.825592,
+ 56.593343
+ ],
+ [
+ -131.799108,
+ 56.587658
+ ],
+ [
+ -131.692293,
+ 56.585074
+ ],
+ [
+ -131.585891,
+ 56.595048
+ ],
+ [
+ -131.560363,
+ 56.594066
+ ],
+ [
+ -131.536437,
+ 56.585229
+ ],
+ [
+ -131.491659,
+ 56.560166
+ ],
+ [
+ -131.345699,
+ 56.503271
+ ],
+ [
+ -131.215604,
+ 56.45255
+ ],
+ [
+ -131.100546,
+ 56.407669
+ ],
+ [
+ -131.016934,
+ 56.38705
+ ],
+ [
+ -130.839089,
+ 56.372452
+ ],
+ [
+ -130.760334,
+ 56.345192
+ ],
+ [
+ -130.645768,
+ 56.261942
+ ],
+ [
+ -130.602256,
+ 56.247059
+ ],
+ [
+ -130.495518,
+ 56.232434
+ ],
+ [
+ -130.47229,
+ 56.22489
+ ],
+ [
+ -130.458053,
+ 56.210653
+ ],
+ [
+ -130.427926,
+ 56.143964
+ ],
+ [
+ -130.418159,
+ 56.129702
+ ],
+ [
+ -130.403974,
+ 56.121898
+ ],
+ [
+ -130.290311,
+ 56.10097
+ ],
+ [
+ -130.243156,
+ 56.092391
+ ],
+ [
+ -130.211246,
+ 56.089962
+ ],
+ [
+ -130.116756,
+ 56.105646
+ ],
+ [
+ -130.094328,
+ 56.101486
+ ],
+ [
+ -130.071539,
+ 56.084123
+ ],
+ [
+ -130.039319,
+ 56.045521
+ ],
+ [
+ -130.026632,
+ 56.024101
+ ],
+ [
+ -130.01901,
+ 56.002216
+ ],
+ [
+ -130.014695,
+ 55.963252
+ ],
+ [
+ -130.016788,
+ 55.918913
+ ],
+ [
+ -130.019612,
+ 55.907978
+ ],
+ [
+ -130.019618,
+ 55.907952
+ ],
+ [
+ -130.022817,
+ 55.901353
+ ],
+ [
+ -130.049387,
+ 55.871405
+ ],
+ [
+ -130.104726,
+ 55.825263
+ ],
+ [
+ -130.136627,
+ 55.806464
+ ],
+ [
+ -130.148834,
+ 55.795356
+ ],
+ [
+ -130.163482,
+ 55.771145
+ ],
+ [
+ -130.167307,
+ 55.766262
+ ],
+ [
+ -130.170806,
+ 55.759833
+ ],
+ [
+ -130.173655,
+ 55.749498
+ ],
+ [
+ -130.170806,
+ 55.740953
+ ],
+ [
+ -130.163808,
+ 55.734565
+ ],
+ [
+ -130.160064,
+ 55.727118
+ ],
+ [
+ -130.167388,
+ 55.715399
+ ],
+ [
+ -130.155914,
+ 55.700141
+ ],
+ [
+ -130.142893,
+ 55.689521
+ ],
+ [
+ -130.131825,
+ 55.676581
+ ],
+ [
+ -130.126454,
+ 55.653998
+ ],
+ [
+ -130.12857,
+ 55.63642
+ ],
+ [
+ -130.135121,
+ 55.619127
+ ],
+ [
+ -130.153147,
+ 55.58511
+ ],
+ [
+ -130.148671,
+ 55.578192
+ ],
+ [
+ -130.146881,
+ 55.569322
+ ],
+ [
+ -130.146962,
+ 55.547187
+ ],
+ [
+ -130.112172,
+ 55.509345
+ ],
+ [
+ -130.101674,
+ 55.481147
+ ],
+ [
+ -130.095082,
+ 55.472113
+ ],
+ [
+ -130.065419,
+ 55.446112
+ ],
+ [
+ -130.057525,
+ 55.434882
+ ],
+ [
+ -130.052561,
+ 55.414008
+ ],
+ [
+ -130.054311,
+ 55.366645
+ ],
+ [
+ -130.05012,
+ 55.345445
+ ],
+ [
+ -130.039296,
+ 55.330756
+ ],
+ [
+ -129.989247,
+ 55.284003
+ ],
+ [
+ -130.031239,
+ 55.26435
+ ],
+ [
+ -130.050038,
+ 55.252875
+ ],
+ [
+ -130.067494,
+ 55.239
+ ],
+ [
+ -130.078236,
+ 55.233791
+ ],
+ [
+ -130.100494,
+ 55.230292
+ ],
+ [
+ -130.104726,
+ 55.225653
+ ],
+ [
+ -130.105702,
+ 55.211127
+ ],
+ [
+ -130.10912,
+ 55.200751
+ ],
+ [
+ -130.115793,
+ 55.191596
+ ],
+ [
+ -130.126454,
+ 55.180976
+ ],
+ [
+ -130.151967,
+ 55.163275
+ ],
+ [
+ -130.159983,
+ 55.153713
+ ],
+ [
+ -130.167592,
+ 55.129584
+ ],
+ [
+ -130.173695,
+ 55.117743
+ ],
+ [
+ -130.200266,
+ 55.104153
+ ],
+ [
+ -130.211781,
+ 55.084133
+ ],
+ [
+ -130.228871,
+ 55.04385
+ ],
+ [
+ -130.238678,
+ 55.03441
+ ],
+ [
+ -130.261342,
+ 55.022895
+ ],
+ [
+ -130.269846,
+ 55.016547
+ ],
+ [
+ -130.275706,
+ 55.006985
+ ],
+ [
+ -130.286366,
+ 54.983222
+ ],
+ [
+ -130.294342,
+ 54.971869
+ ],
+ [
+ -130.326568,
+ 54.952094
+ ],
+ [
+ -130.335561,
+ 54.938707
+ ],
+ [
+ -130.365387,
+ 54.907294
+ ],
+ [
+ -130.385243,
+ 54.896552
+ ],
+ [
+ -130.430816,
+ 54.881252
+ ],
+ [
+ -130.488759,
+ 54.844184
+ ],
+ [
+ -130.580312,
+ 54.806383
+ ],
+ [
+ -130.597485,
+ 54.803391
+ ],
+ [
+ -130.71074,
+ 54.733215
+ ],
+ [
+ -131.160718,
+ 54.787192
+ ]
+ ]
+ ]
+ ]
+ }
+ }
]
},
+ "featureIcons": {
+ "circle-stroked-24": {
+ "x": 0,
+ "y": 0,
+ "width": 24,
+ "height": 24
+ },
+ "circle-stroked-18": {
+ "x": 24,
+ "y": 0,
+ "width": 18,
+ "height": 18
+ },
+ "circle-stroked-12": {
+ "x": 42,
+ "y": 0,
+ "width": 12,
+ "height": 12
+ },
+ "circle-24": {
+ "x": 54,
+ "y": 0,
+ "width": 24,
+ "height": 24
+ },
+ "circle-18": {
+ "x": 78,
+ "y": 0,
+ "width": 18,
+ "height": 18
+ },
+ "circle-12": {
+ "x": 96,
+ "y": 0,
+ "width": 12,
+ "height": 12
+ },
+ "square-stroked-24": {
+ "x": 108,
+ "y": 0,
+ "width": 24,
+ "height": 24
+ },
+ "square-stroked-18": {
+ "x": 132,
+ "y": 0,
+ "width": 18,
+ "height": 18
+ },
+ "square-stroked-12": {
+ "x": 150,
+ "y": 0,
+ "width": 12,
+ "height": 12
+ },
+ "square-24": {
+ "x": 162,
+ "y": 0,
+ "width": 24,
+ "height": 24
+ },
+ "square-18": {
+ "x": 186,
+ "y": 0,
+ "width": 18,
+ "height": 18
+ },
+ "square-12": {
+ "x": 204,
+ "y": 0,
+ "width": 12,
+ "height": 12
+ },
+ "triangle-stroked-24": {
+ "x": 216,
+ "y": 0,
+ "width": 24,
+ "height": 24
+ },
+ "triangle-stroked-18": {
+ "x": 240,
+ "y": 0,
+ "width": 18,
+ "height": 18
+ },
+ "triangle-stroked-12": {
+ "x": 258,
+ "y": 0,
+ "width": 12,
+ "height": 12
+ },
+ "triangle-24": {
+ "x": 0,
+ "y": 24,
+ "width": 24,
+ "height": 24
+ },
+ "triangle-18": {
+ "x": 24,
+ "y": 24,
+ "width": 18,
+ "height": 18
+ },
+ "triangle-12": {
+ "x": 42,
+ "y": 24,
+ "width": 12,
+ "height": 12
+ },
+ "star-stroked-24": {
+ "x": 54,
+ "y": 24,
+ "width": 24,
+ "height": 24
+ },
+ "star-stroked-18": {
+ "x": 78,
+ "y": 24,
+ "width": 18,
+ "height": 18
+ },
+ "star-stroked-12": {
+ "x": 96,
+ "y": 24,
+ "width": 12,
+ "height": 12
+ },
+ "star-24": {
+ "x": 108,
+ "y": 24,
+ "width": 24,
+ "height": 24
+ },
+ "star-18": {
+ "x": 132,
+ "y": 24,
+ "width": 18,
+ "height": 18
+ },
+ "star-12": {
+ "x": 150,
+ "y": 24,
+ "width": 12,
+ "height": 12
+ },
+ "cross-24": {
+ "x": 162,
+ "y": 24,
+ "width": 24,
+ "height": 24
+ },
+ "cross-18": {
+ "x": 186,
+ "y": 24,
+ "width": 18,
+ "height": 18
+ },
+ "cross-12": {
+ "x": 204,
+ "y": 24,
+ "width": 12,
+ "height": 12
+ },
+ "marker-stroked-24": {
+ "x": 216,
+ "y": 24,
+ "width": 24,
+ "height": 24
+ },
+ "marker-stroked-18": {
+ "x": 240,
+ "y": 24,
+ "width": 18,
+ "height": 18
+ },
+ "marker-stroked-12": {
+ "x": 258,
+ "y": 24,
+ "width": 12,
+ "height": 12
+ },
+ "marker-24": {
+ "x": 0,
+ "y": 48,
+ "width": 24,
+ "height": 24
+ },
+ "marker-18": {
+ "x": 24,
+ "y": 48,
+ "width": 18,
+ "height": 18
+ },
+ "marker-12": {
+ "x": 42,
+ "y": 48,
+ "width": 12,
+ "height": 12
+ },
+ "religious-jewish-24": {
+ "x": 54,
+ "y": 48,
+ "width": 24,
+ "height": 24
+ },
+ "religious-jewish-18": {
+ "x": 78,
+ "y": 48,
+ "width": 18,
+ "height": 18
+ },
+ "religious-jewish-12": {
+ "x": 96,
+ "y": 48,
+ "width": 12,
+ "height": 12
+ },
+ "religious-christian-24": {
+ "x": 108,
+ "y": 48,
+ "width": 24,
+ "height": 24
+ },
+ "religious-christian-18": {
+ "x": 132,
+ "y": 48,
+ "width": 18,
+ "height": 18
+ },
+ "religious-christian-12": {
+ "x": 150,
+ "y": 48,
+ "width": 12,
+ "height": 12
+ },
+ "religious-muslim-24": {
+ "x": 162,
+ "y": 48,
+ "width": 24,
+ "height": 24
+ },
+ "religious-muslim-18": {
+ "x": 186,
+ "y": 48,
+ "width": 18,
+ "height": 18
+ },
+ "religious-muslim-12": {
+ "x": 204,
+ "y": 48,
+ "width": 12,
+ "height": 12
+ },
+ "cemetery-24": {
+ "x": 216,
+ "y": 48,
+ "width": 24,
+ "height": 24
+ },
+ "cemetery-18": {
+ "x": 240,
+ "y": 48,
+ "width": 18,
+ "height": 18
+ },
+ "cemetery-12": {
+ "x": 258,
+ "y": 48,
+ "width": 12,
+ "height": 12
+ },
+ "rocket-24": {
+ "x": 0,
+ "y": 72,
+ "width": 24,
+ "height": 24
+ },
+ "rocket-18": {
+ "x": 24,
+ "y": 72,
+ "width": 18,
+ "height": 18
+ },
+ "rocket-12": {
+ "x": 42,
+ "y": 72,
+ "width": 12,
+ "height": 12
+ },
+ "airport-24": {
+ "x": 54,
+ "y": 72,
+ "width": 24,
+ "height": 24
+ },
+ "airport-18": {
+ "x": 78,
+ "y": 72,
+ "width": 18,
+ "height": 18
+ },
+ "airport-12": {
+ "x": 96,
+ "y": 72,
+ "width": 12,
+ "height": 12
+ },
+ "heliport-24": {
+ "x": 108,
+ "y": 72,
+ "width": 24,
+ "height": 24
+ },
+ "heliport-18": {
+ "x": 132,
+ "y": 72,
+ "width": 18,
+ "height": 18
+ },
+ "heliport-12": {
+ "x": 150,
+ "y": 72,
+ "width": 12,
+ "height": 12
+ },
+ "rail-24": {
+ "x": 162,
+ "y": 72,
+ "width": 24,
+ "height": 24
+ },
+ "rail-18": {
+ "x": 186,
+ "y": 72,
+ "width": 18,
+ "height": 18
+ },
+ "rail-12": {
+ "x": 204,
+ "y": 72,
+ "width": 12,
+ "height": 12
+ },
+ "rail-metro-24": {
+ "x": 216,
+ "y": 72,
+ "width": 24,
+ "height": 24
+ },
+ "rail-metro-18": {
+ "x": 240,
+ "y": 72,
+ "width": 18,
+ "height": 18
+ },
+ "rail-metro-12": {
+ "x": 258,
+ "y": 72,
+ "width": 12,
+ "height": 12
+ },
+ "rail-light-24": {
+ "x": 0,
+ "y": 96,
+ "width": 24,
+ "height": 24
+ },
+ "rail-light-18": {
+ "x": 24,
+ "y": 96,
+ "width": 18,
+ "height": 18
+ },
+ "rail-light-12": {
+ "x": 42,
+ "y": 96,
+ "width": 12,
+ "height": 12
+ },
+ "bus-24": {
+ "x": 54,
+ "y": 96,
+ "width": 24,
+ "height": 24
+ },
+ "bus-18": {
+ "x": 78,
+ "y": 96,
+ "width": 18,
+ "height": 18
+ },
+ "bus-12": {
+ "x": 96,
+ "y": 96,
+ "width": 12,
+ "height": 12
+ },
+ "fuel-24": {
+ "x": 108,
+ "y": 96,
+ "width": 24,
+ "height": 24
+ },
+ "fuel-18": {
+ "x": 132,
+ "y": 96,
+ "width": 18,
+ "height": 18
+ },
+ "fuel-12": {
+ "x": 150,
+ "y": 96,
+ "width": 12,
+ "height": 12
+ },
+ "parking-24": {
+ "x": 162,
+ "y": 96,
+ "width": 24,
+ "height": 24
+ },
+ "parking-18": {
+ "x": 186,
+ "y": 96,
+ "width": 18,
+ "height": 18
+ },
+ "parking-12": {
+ "x": 204,
+ "y": 96,
+ "width": 12,
+ "height": 12
+ },
+ "parking-garage-24": {
+ "x": 216,
+ "y": 96,
+ "width": 24,
+ "height": 24
+ },
+ "parking-garage-18": {
+ "x": 240,
+ "y": 96,
+ "width": 18,
+ "height": 18
+ },
+ "parking-garage-12": {
+ "x": 258,
+ "y": 96,
+ "width": 12,
+ "height": 12
+ },
+ "airfield-24": {
+ "x": 0,
+ "y": 120,
+ "width": 24,
+ "height": 24
+ },
+ "airfield-18": {
+ "x": 24,
+ "y": 120,
+ "width": 18,
+ "height": 18
+ },
+ "airfield-12": {
+ "x": 42,
+ "y": 120,
+ "width": 12,
+ "height": 12
+ },
+ "roadblock-24": {
+ "x": 54,
+ "y": 120,
+ "width": 24,
+ "height": 24
+ },
+ "roadblock-18": {
+ "x": 78,
+ "y": 120,
+ "width": 18,
+ "height": 18
+ },
+ "roadblock-12": {
+ "x": 96,
+ "y": 120,
+ "width": 12,
+ "height": 12
+ },
+ "ferry-24": {
+ "x": 108,
+ "y": 120,
+ "width": 24,
+ "height": 24
+ },
+ "ferry-18": {
+ "x": 132,
+ "y": 120,
+ "width": 18,
+ "height": 18
+ },
+ "ferry-12": {
+ "x": 150,
+ "y": 120,
+ "width": 12,
+ "height": 12
+ },
+ "harbor-24": {
+ "x": 162,
+ "y": 120,
+ "width": 24,
+ "height": 24
+ },
+ "harbor-18": {
+ "x": 186,
+ "y": 120,
+ "width": 18,
+ "height": 18
+ },
+ "harbor-12": {
+ "x": 204,
+ "y": 120,
+ "width": 12,
+ "height": 12
+ },
+ "bicycle-24": {
+ "x": 216,
+ "y": 120,
+ "width": 24,
+ "height": 24
+ },
+ "bicycle-18": {
+ "x": 240,
+ "y": 120,
+ "width": 18,
+ "height": 18
+ },
+ "bicycle-12": {
+ "x": 258,
+ "y": 120,
+ "width": 12,
+ "height": 12
+ },
+ "park-24": {
+ "x": 0,
+ "y": 144,
+ "width": 24,
+ "height": 24
+ },
+ "park-18": {
+ "x": 24,
+ "y": 144,
+ "width": 18,
+ "height": 18
+ },
+ "park-12": {
+ "x": 42,
+ "y": 144,
+ "width": 12,
+ "height": 12
+ },
+ "park2-24": {
+ "x": 54,
+ "y": 144,
+ "width": 24,
+ "height": 24
+ },
+ "park2-18": {
+ "x": 78,
+ "y": 144,
+ "width": 18,
+ "height": 18
+ },
+ "park2-12": {
+ "x": 96,
+ "y": 144,
+ "width": 12,
+ "height": 12
+ },
+ "museum-24": {
+ "x": 108,
+ "y": 144,
+ "width": 24,
+ "height": 24
+ },
+ "museum-18": {
+ "x": 132,
+ "y": 144,
+ "width": 18,
+ "height": 18
+ },
+ "museum-12": {
+ "x": 150,
+ "y": 144,
+ "width": 12,
+ "height": 12
+ },
+ "lodging-24": {
+ "x": 162,
+ "y": 144,
+ "width": 24,
+ "height": 24
+ },
+ "lodging-18": {
+ "x": 186,
+ "y": 144,
+ "width": 18,
+ "height": 18
+ },
+ "lodging-12": {
+ "x": 204,
+ "y": 144,
+ "width": 12,
+ "height": 12
+ },
+ "monument-24": {
+ "x": 216,
+ "y": 144,
+ "width": 24,
+ "height": 24
+ },
+ "monument-18": {
+ "x": 240,
+ "y": 144,
+ "width": 18,
+ "height": 18
+ },
+ "monument-12": {
+ "x": 258,
+ "y": 144,
+ "width": 12,
+ "height": 12
+ },
+ "zoo-24": {
+ "x": 0,
+ "y": 168,
+ "width": 24,
+ "height": 24
+ },
+ "zoo-18": {
+ "x": 24,
+ "y": 168,
+ "width": 18,
+ "height": 18
+ },
+ "zoo-12": {
+ "x": 42,
+ "y": 168,
+ "width": 12,
+ "height": 12
+ },
+ "garden-24": {
+ "x": 54,
+ "y": 168,
+ "width": 24,
+ "height": 24
+ },
+ "garden-18": {
+ "x": 78,
+ "y": 168,
+ "width": 18,
+ "height": 18
+ },
+ "garden-12": {
+ "x": 96,
+ "y": 168,
+ "width": 12,
+ "height": 12
+ },
+ "campsite-24": {
+ "x": 108,
+ "y": 168,
+ "width": 24,
+ "height": 24
+ },
+ "campsite-18": {
+ "x": 132,
+ "y": 168,
+ "width": 18,
+ "height": 18
+ },
+ "campsite-12": {
+ "x": 150,
+ "y": 168,
+ "width": 12,
+ "height": 12
+ },
+ "theatre-24": {
+ "x": 162,
+ "y": 168,
+ "width": 24,
+ "height": 24
+ },
+ "theatre-18": {
+ "x": 186,
+ "y": 168,
+ "width": 18,
+ "height": 18
+ },
+ "theatre-12": {
+ "x": 204,
+ "y": 168,
+ "width": 12,
+ "height": 12
+ },
+ "art-gallery-24": {
+ "x": 216,
+ "y": 168,
+ "width": 24,
+ "height": 24
+ },
+ "art-gallery-18": {
+ "x": 240,
+ "y": 168,
+ "width": 18,
+ "height": 18
+ },
+ "art-gallery-12": {
+ "x": 258,
+ "y": 168,
+ "width": 12,
+ "height": 12
+ },
+ "pitch-24": {
+ "x": 0,
+ "y": 192,
+ "width": 24,
+ "height": 24
+ },
+ "pitch-18": {
+ "x": 24,
+ "y": 192,
+ "width": 18,
+ "height": 18
+ },
+ "pitch-12": {
+ "x": 42,
+ "y": 192,
+ "width": 12,
+ "height": 12
+ },
+ "soccer-24": {
+ "x": 54,
+ "y": 192,
+ "width": 24,
+ "height": 24
+ },
+ "soccer-18": {
+ "x": 78,
+ "y": 192,
+ "width": 18,
+ "height": 18
+ },
+ "soccer-12": {
+ "x": 96,
+ "y": 192,
+ "width": 12,
+ "height": 12
+ },
+ "america-football-24": {
+ "x": 108,
+ "y": 192,
+ "width": 24,
+ "height": 24
+ },
+ "america-football-18": {
+ "x": 132,
+ "y": 192,
+ "width": 18,
+ "height": 18
+ },
+ "america-football-12": {
+ "x": 150,
+ "y": 192,
+ "width": 12,
+ "height": 12
+ },
+ "tennis-24": {
+ "x": 162,
+ "y": 192,
+ "width": 24,
+ "height": 24
+ },
+ "tennis-18": {
+ "x": 186,
+ "y": 192,
+ "width": 18,
+ "height": 18
+ },
+ "tennis-12": {
+ "x": 204,
+ "y": 192,
+ "width": 12,
+ "height": 12
+ },
+ "basketball-24": {
+ "x": 216,
+ "y": 192,
+ "width": 24,
+ "height": 24
+ },
+ "basketball-18": {
+ "x": 240,
+ "y": 192,
+ "width": 18,
+ "height": 18
+ },
+ "basketball-12": {
+ "x": 258,
+ "y": 192,
+ "width": 12,
+ "height": 12
+ },
+ "baseball-24": {
+ "x": 0,
+ "y": 216,
+ "width": 24,
+ "height": 24
+ },
+ "baseball-18": {
+ "x": 24,
+ "y": 216,
+ "width": 18,
+ "height": 18
+ },
+ "baseball-12": {
+ "x": 42,
+ "y": 216,
+ "width": 12,
+ "height": 12
+ },
+ "golf-24": {
+ "x": 54,
+ "y": 216,
+ "width": 24,
+ "height": 24
+ },
+ "golf-18": {
+ "x": 78,
+ "y": 216,
+ "width": 18,
+ "height": 18
+ },
+ "golf-12": {
+ "x": 96,
+ "y": 216,
+ "width": 12,
+ "height": 12
+ },
+ "swimming-24": {
+ "x": 108,
+ "y": 216,
+ "width": 24,
+ "height": 24
+ },
+ "swimming-18": {
+ "x": 132,
+ "y": 216,
+ "width": 18,
+ "height": 18
+ },
+ "swimming-12": {
+ "x": 150,
+ "y": 216,
+ "width": 12,
+ "height": 12
+ },
+ "cricket-24": {
+ "x": 162,
+ "y": 216,
+ "width": 24,
+ "height": 24
+ },
+ "cricket-18": {
+ "x": 186,
+ "y": 216,
+ "width": 18,
+ "height": 18
+ },
+ "cricket-12": {
+ "x": 204,
+ "y": 216,
+ "width": 12,
+ "height": 12
+ },
+ "skiing-24": {
+ "x": 216,
+ "y": 216,
+ "width": 24,
+ "height": 24
+ },
+ "skiing-18": {
+ "x": 240,
+ "y": 216,
+ "width": 18,
+ "height": 18
+ },
+ "skiing-12": {
+ "x": 258,
+ "y": 216,
+ "width": 12,
+ "height": 12
+ },
+ "school-24": {
+ "x": 0,
+ "y": 240,
+ "width": 24,
+ "height": 24
+ },
+ "school-18": {
+ "x": 24,
+ "y": 240,
+ "width": 18,
+ "height": 18
+ },
+ "school-12": {
+ "x": 42,
+ "y": 240,
+ "width": 12,
+ "height": 12
+ },
+ "college-24": {
+ "x": 54,
+ "y": 240,
+ "width": 24,
+ "height": 24
+ },
+ "college-18": {
+ "x": 78,
+ "y": 240,
+ "width": 18,
+ "height": 18
+ },
+ "college-12": {
+ "x": 96,
+ "y": 240,
+ "width": 12,
+ "height": 12
+ },
+ "library-24": {
+ "x": 108,
+ "y": 240,
+ "width": 24,
+ "height": 24
+ },
+ "library-18": {
+ "x": 132,
+ "y": 240,
+ "width": 18,
+ "height": 18
+ },
+ "library-12": {
+ "x": 150,
+ "y": 240,
+ "width": 12,
+ "height": 12
+ },
+ "post-24": {
+ "x": 162,
+ "y": 240,
+ "width": 24,
+ "height": 24
+ },
+ "post-18": {
+ "x": 186,
+ "y": 240,
+ "width": 18,
+ "height": 18
+ },
+ "post-12": {
+ "x": 204,
+ "y": 240,
+ "width": 12,
+ "height": 12
+ },
+ "fire-station-24": {
+ "x": 216,
+ "y": 240,
+ "width": 24,
+ "height": 24
+ },
+ "fire-station-18": {
+ "x": 240,
+ "y": 240,
+ "width": 18,
+ "height": 18
+ },
+ "fire-station-12": {
+ "x": 258,
+ "y": 240,
+ "width": 12,
+ "height": 12
+ },
+ "town-hall-24": {
+ "x": 0,
+ "y": 264,
+ "width": 24,
+ "height": 24
+ },
+ "town-hall-18": {
+ "x": 24,
+ "y": 264,
+ "width": 18,
+ "height": 18
+ },
+ "town-hall-12": {
+ "x": 42,
+ "y": 264,
+ "width": 12,
+ "height": 12
+ },
+ "police-24": {
+ "x": 54,
+ "y": 264,
+ "width": 24,
+ "height": 24
+ },
+ "police-18": {
+ "x": 78,
+ "y": 264,
+ "width": 18,
+ "height": 18
+ },
+ "police-12": {
+ "x": 96,
+ "y": 264,
+ "width": 12,
+ "height": 12
+ },
+ "prison-24": {
+ "x": 108,
+ "y": 264,
+ "width": 24,
+ "height": 24
+ },
+ "prison-18": {
+ "x": 132,
+ "y": 264,
+ "width": 18,
+ "height": 18
+ },
+ "prison-12": {
+ "x": 150,
+ "y": 264,
+ "width": 12,
+ "height": 12
+ },
+ "embassy-24": {
+ "x": 162,
+ "y": 264,
+ "width": 24,
+ "height": 24
+ },
+ "embassy-18": {
+ "x": 186,
+ "y": 264,
+ "width": 18,
+ "height": 18
+ },
+ "embassy-12": {
+ "x": 204,
+ "y": 264,
+ "width": 12,
+ "height": 12
+ },
+ "beer-24": {
+ "x": 216,
+ "y": 264,
+ "width": 24,
+ "height": 24
+ },
+ "beer-18": {
+ "x": 240,
+ "y": 264,
+ "width": 18,
+ "height": 18
+ },
+ "beer-12": {
+ "x": 258,
+ "y": 264,
+ "width": 12,
+ "height": 12
+ },
+ "restaurant-24": {
+ "x": 0,
+ "y": 288,
+ "width": 24,
+ "height": 24
+ },
+ "restaurant-18": {
+ "x": 24,
+ "y": 288,
+ "width": 18,
+ "height": 18
+ },
+ "restaurant-12": {
+ "x": 42,
+ "y": 288,
+ "width": 12,
+ "height": 12
+ },
+ "cafe-24": {
+ "x": 54,
+ "y": 288,
+ "width": 24,
+ "height": 24
+ },
+ "cafe-18": {
+ "x": 78,
+ "y": 288,
+ "width": 18,
+ "height": 18
+ },
+ "cafe-12": {
+ "x": 96,
+ "y": 288,
+ "width": 12,
+ "height": 12
+ },
+ "shop-24": {
+ "x": 108,
+ "y": 288,
+ "width": 24,
+ "height": 24
+ },
+ "shop-18": {
+ "x": 132,
+ "y": 288,
+ "width": 18,
+ "height": 18
+ },
+ "shop-12": {
+ "x": 150,
+ "y": 288,
+ "width": 12,
+ "height": 12
+ },
+ "fast-food-24": {
+ "x": 162,
+ "y": 288,
+ "width": 24,
+ "height": 24
+ },
+ "fast-food-18": {
+ "x": 186,
+ "y": 288,
+ "width": 18,
+ "height": 18
+ },
+ "fast-food-12": {
+ "x": 204,
+ "y": 288,
+ "width": 12,
+ "height": 12
+ },
+ "bar-24": {
+ "x": 216,
+ "y": 288,
+ "width": 24,
+ "height": 24
+ },
+ "bar-18": {
+ "x": 240,
+ "y": 288,
+ "width": 18,
+ "height": 18
+ },
+ "bar-12": {
+ "x": 258,
+ "y": 288,
+ "width": 12,
+ "height": 12
+ },
+ "bank-24": {
+ "x": 0,
+ "y": 312,
+ "width": 24,
+ "height": 24
+ },
+ "bank-18": {
+ "x": 24,
+ "y": 312,
+ "width": 18,
+ "height": 18
+ },
+ "bank-12": {
+ "x": 42,
+ "y": 312,
+ "width": 12,
+ "height": 12
+ },
+ "grocery-24": {
+ "x": 54,
+ "y": 312,
+ "width": 24,
+ "height": 24
+ },
+ "grocery-18": {
+ "x": 78,
+ "y": 312,
+ "width": 18,
+ "height": 18
+ },
+ "grocery-12": {
+ "x": 96,
+ "y": 312,
+ "width": 12,
+ "height": 12
+ },
+ "cinema-24": {
+ "x": 108,
+ "y": 312,
+ "width": 24,
+ "height": 24
+ },
+ "cinema-18": {
+ "x": 132,
+ "y": 312,
+ "width": 18,
+ "height": 18
+ },
+ "cinema-12": {
+ "x": 150,
+ "y": 312,
+ "width": 12,
+ "height": 12
+ },
+ "pharmacy-24": {
+ "x": 162,
+ "y": 312,
+ "width": 24,
+ "height": 24
+ },
+ "pharmacy-18": {
+ "x": 186,
+ "y": 312,
+ "width": 18,
+ "height": 18
+ },
+ "pharmacy-12": {
+ "x": 204,
+ "y": 312,
+ "width": 12,
+ "height": 12
+ },
+ "hospital-24": {
+ "x": 216,
+ "y": 312,
+ "width": 24,
+ "height": 24
+ },
+ "hospital-18": {
+ "x": 240,
+ "y": 312,
+ "width": 18,
+ "height": 18
+ },
+ "hospital-12": {
+ "x": 258,
+ "y": 312,
+ "width": 12,
+ "height": 12
+ },
+ "danger-24": {
+ "x": 0,
+ "y": 336,
+ "width": 24,
+ "height": 24
+ },
+ "danger-18": {
+ "x": 24,
+ "y": 336,
+ "width": 18,
+ "height": 18
+ },
+ "danger-12": {
+ "x": 42,
+ "y": 336,
+ "width": 12,
+ "height": 12
+ },
+ "industrial-24": {
+ "x": 54,
+ "y": 336,
+ "width": 24,
+ "height": 24
+ },
+ "industrial-18": {
+ "x": 78,
+ "y": 336,
+ "width": 18,
+ "height": 18
+ },
+ "industrial-12": {
+ "x": 96,
+ "y": 336,
+ "width": 12,
+ "height": 12
+ },
+ "warehouse-24": {
+ "x": 108,
+ "y": 336,
+ "width": 24,
+ "height": 24
+ },
+ "warehouse-18": {
+ "x": 132,
+ "y": 336,
+ "width": 18,
+ "height": 18
+ },
+ "warehouse-12": {
+ "x": 150,
+ "y": 336,
+ "width": 12,
+ "height": 12
+ },
+ "commercial-24": {
+ "x": 162,
+ "y": 336,
+ "width": 24,
+ "height": 24
+ },
+ "commercial-18": {
+ "x": 186,
+ "y": 336,
+ "width": 18,
+ "height": 18
+ },
+ "commercial-12": {
+ "x": 204,
+ "y": 336,
+ "width": 12,
+ "height": 12
+ },
+ "building-24": {
+ "x": 216,
+ "y": 336,
+ "width": 24,
+ "height": 24
+ },
+ "building-18": {
+ "x": 240,
+ "y": 336,
+ "width": 18,
+ "height": 18
+ },
+ "building-12": {
+ "x": 258,
+ "y": 336,
+ "width": 12,
+ "height": 12
+ },
+ "place-of-worship-24": {
+ "x": 0,
+ "y": 360,
+ "width": 24,
+ "height": 24
+ },
+ "place-of-worship-18": {
+ "x": 24,
+ "y": 360,
+ "width": 18,
+ "height": 18
+ },
+ "place-of-worship-12": {
+ "x": 42,
+ "y": 360,
+ "width": 12,
+ "height": 12
+ },
+ "alcohol-shop-24": {
+ "x": 54,
+ "y": 360,
+ "width": 24,
+ "height": 24
+ },
+ "alcohol-shop-18": {
+ "x": 78,
+ "y": 360,
+ "width": 18,
+ "height": 18
+ },
+ "alcohol-shop-12": {
+ "x": 96,
+ "y": 360,
+ "width": 12,
+ "height": 12
+ },
+ "logging-24": {
+ "x": 108,
+ "y": 360,
+ "width": 24,
+ "height": 24
+ },
+ "logging-18": {
+ "x": 132,
+ "y": 360,
+ "width": 18,
+ "height": 18
+ },
+ "logging-12": {
+ "x": 150,
+ "y": 360,
+ "width": 12,
+ "height": 12
+ },
+ "oil-well-24": {
+ "x": 162,
+ "y": 360,
+ "width": 24,
+ "height": 24
+ },
+ "oil-well-18": {
+ "x": 186,
+ "y": 360,
+ "width": 18,
+ "height": 18
+ },
+ "oil-well-12": {
+ "x": 204,
+ "y": 360,
+ "width": 12,
+ "height": 12
+ },
+ "slaughterhouse-24": {
+ "x": 216,
+ "y": 360,
+ "width": 24,
+ "height": 24
+ },
+ "slaughterhouse-18": {
+ "x": 240,
+ "y": 360,
+ "width": 18,
+ "height": 18
+ },
+ "slaughterhouse-12": {
+ "x": 258,
+ "y": 360,
+ "width": 12,
+ "height": 12
+ },
+ "dam-24": {
+ "x": 0,
+ "y": 384,
+ "width": 24,
+ "height": 24
+ },
+ "dam-18": {
+ "x": 24,
+ "y": 384,
+ "width": 18,
+ "height": 18
+ },
+ "dam-12": {
+ "x": 42,
+ "y": 384,
+ "width": 12,
+ "height": 12
+ },
+ "water-24": {
+ "x": 54,
+ "y": 384,
+ "width": 24,
+ "height": 24
+ },
+ "water-18": {
+ "x": 78,
+ "y": 384,
+ "width": 18,
+ "height": 18
+ },
+ "water-12": {
+ "x": 96,
+ "y": 384,
+ "width": 12,
+ "height": 12
+ },
+ "wetland-24": {
+ "x": 108,
+ "y": 384,
+ "width": 24,
+ "height": 24
+ },
+ "wetland-18": {
+ "x": 132,
+ "y": 384,
+ "width": 18,
+ "height": 18
+ },
+ "wetland-12": {
+ "x": 150,
+ "y": 384,
+ "width": 12,
+ "height": 12
+ },
+ "disability-24": {
+ "x": 162,
+ "y": 384,
+ "width": 24,
+ "height": 24
+ },
+ "disability-18": {
+ "x": 186,
+ "y": 384,
+ "width": 18,
+ "height": 18
+ },
+ "disability-12": {
+ "x": 204,
+ "y": 384,
+ "width": 12,
+ "height": 12
+ },
+ "telephone-24": {
+ "x": 216,
+ "y": 384,
+ "width": 24,
+ "height": 24
+ },
+ "telephone-18": {
+ "x": 240,
+ "y": 384,
+ "width": 18,
+ "height": 18
+ },
+ "telephone-12": {
+ "x": 258,
+ "y": 384,
+ "width": 12,
+ "height": 12
+ },
+ "emergency-telephone-24": {
+ "x": 0,
+ "y": 408,
+ "width": 24,
+ "height": 24
+ },
+ "emergency-telephone-18": {
+ "x": 24,
+ "y": 408,
+ "width": 18,
+ "height": 18
+ },
+ "emergency-telephone-12": {
+ "x": 42,
+ "y": 408,
+ "width": 12,
+ "height": 12
+ },
+ "toilets-24": {
+ "x": 54,
+ "y": 408,
+ "width": 24,
+ "height": 24
+ },
+ "toilets-18": {
+ "x": 78,
+ "y": 408,
+ "width": 18,
+ "height": 18
+ },
+ "toilets-12": {
+ "x": 96,
+ "y": 408,
+ "width": 12,
+ "height": 12
+ },
+ "waste-basket-24": {
+ "x": 108,
+ "y": 408,
+ "width": 24,
+ "height": 24
+ },
+ "waste-basket-18": {
+ "x": 132,
+ "y": 408,
+ "width": 18,
+ "height": 18
+ },
+ "waste-basket-12": {
+ "x": 150,
+ "y": 408,
+ "width": 12,
+ "height": 12
+ },
+ "music-24": {
+ "x": 162,
+ "y": 408,
+ "width": 24,
+ "height": 24
+ },
+ "music-18": {
+ "x": 186,
+ "y": 408,
+ "width": 18,
+ "height": 18
+ },
+ "music-12": {
+ "x": 204,
+ "y": 408,
+ "width": 12,
+ "height": 12
+ },
+ "land-use-24": {
+ "x": 216,
+ "y": 408,
+ "width": 24,
+ "height": 24
+ },
+ "land-use-18": {
+ "x": 240,
+ "y": 408,
+ "width": 18,
+ "height": 18
+ },
+ "land-use-12": {
+ "x": 258,
+ "y": 408,
+ "width": 12,
+ "height": 12
+ },
+ "city-24": {
+ "x": 0,
+ "y": 432,
+ "width": 24,
+ "height": 24
+ },
+ "city-18": {
+ "x": 24,
+ "y": 432,
+ "width": 18,
+ "height": 18
+ },
+ "city-12": {
+ "x": 42,
+ "y": 432,
+ "width": 12,
+ "height": 12
+ },
+ "town-24": {
+ "x": 54,
+ "y": 432,
+ "width": 24,
+ "height": 24
+ },
+ "town-18": {
+ "x": 78,
+ "y": 432,
+ "width": 18,
+ "height": 18
+ },
+ "town-12": {
+ "x": 96,
+ "y": 432,
+ "width": 12,
+ "height": 12
+ },
+ "village-24": {
+ "x": 108,
+ "y": 432,
+ "width": 24,
+ "height": 24
+ },
+ "village-18": {
+ "x": 132,
+ "y": 432,
+ "width": 18,
+ "height": 18
+ },
+ "village-12": {
+ "x": 150,
+ "y": 432,
+ "width": 12,
+ "height": 12
+ },
+ "farm-24": {
+ "x": 162,
+ "y": 432,
+ "width": 24,
+ "height": 24
+ },
+ "farm-18": {
+ "x": 186,
+ "y": 432,
+ "width": 18,
+ "height": 18
+ },
+ "farm-12": {
+ "x": 204,
+ "y": 432,
+ "width": 12,
+ "height": 12
+ },
+ "bakery-24": {
+ "x": 216,
+ "y": 432,
+ "width": 24,
+ "height": 24
+ },
+ "bakery-18": {
+ "x": 240,
+ "y": 432,
+ "width": 18,
+ "height": 18
+ },
+ "bakery-12": {
+ "x": 258,
+ "y": 432,
+ "width": 12,
+ "height": 12
+ },
+ "dog-park-24": {
+ "x": 0,
+ "y": 456,
+ "width": 24,
+ "height": 24
+ },
+ "dog-park-18": {
+ "x": 24,
+ "y": 456,
+ "width": 18,
+ "height": 18
+ },
+ "dog-park-12": {
+ "x": 42,
+ "y": 456,
+ "width": 12,
+ "height": 12
+ },
+ "lighthouse-24": {
+ "x": 54,
+ "y": 456,
+ "width": 24,
+ "height": 24
+ },
+ "lighthouse-18": {
+ "x": 78,
+ "y": 456,
+ "width": 18,
+ "height": 18
+ },
+ "lighthouse-12": {
+ "x": 96,
+ "y": 456,
+ "width": 12,
+ "height": 12
+ },
+ "clothing-store-24": {
+ "x": 108,
+ "y": 456,
+ "width": 24,
+ "height": 24
+ },
+ "clothing-store-18": {
+ "x": 132,
+ "y": 456,
+ "width": 18,
+ "height": 18
+ },
+ "clothing-store-12": {
+ "x": 150,
+ "y": 456,
+ "width": 12,
+ "height": 12
+ },
+ "polling-place-24": {
+ "x": 162,
+ "y": 456,
+ "width": 24,
+ "height": 24
+ },
+ "polling-place-18": {
+ "x": 186,
+ "y": 456,
+ "width": 18,
+ "height": 18
+ },
+ "polling-place-12": {
+ "x": 204,
+ "y": 456,
+ "width": 12,
+ "height": 12
+ },
+ "playground-24": {
+ "x": 216,
+ "y": 456,
+ "width": 24,
+ "height": 24
+ },
+ "playground-18": {
+ "x": 240,
+ "y": 456,
+ "width": 18,
+ "height": 18
+ },
+ "playground-12": {
+ "x": 258,
+ "y": 456,
+ "width": 12,
+ "height": 12
+ },
+ "entrance-24": {
+ "x": 0,
+ "y": 480,
+ "width": 24,
+ "height": 24
+ },
+ "entrance-18": {
+ "x": 24,
+ "y": 480,
+ "width": 18,
+ "height": 18
+ },
+ "entrance-12": {
+ "x": 42,
+ "y": 480,
+ "width": 12,
+ "height": 12
+ },
+ "heart-24": {
+ "x": 54,
+ "y": 480,
+ "width": 24,
+ "height": 24
+ },
+ "heart-18": {
+ "x": 78,
+ "y": 480,
+ "width": 18,
+ "height": 18
+ },
+ "heart-12": {
+ "x": 96,
+ "y": 480,
+ "width": 12,
+ "height": 12
+ },
+ "london-underground-24": {
+ "x": 108,
+ "y": 480,
+ "width": 24,
+ "height": 24
+ },
+ "london-underground-18": {
+ "x": 132,
+ "y": 480,
+ "width": 18,
+ "height": 18
+ },
+ "london-underground-12": {
+ "x": 150,
+ "y": 480,
+ "width": 12,
+ "height": 12
+ },
+ "minefield-24": {
+ "x": 162,
+ "y": 480,
+ "width": 24,
+ "height": 24
+ },
+ "minefield-18": {
+ "x": 186,
+ "y": 480,
+ "width": 18,
+ "height": 18
+ },
+ "minefield-12": {
+ "x": 204,
+ "y": 480,
+ "width": 12,
+ "height": 12
+ },
+ "rail-underground-24": {
+ "x": 216,
+ "y": 480,
+ "width": 24,
+ "height": 24
+ },
+ "rail-underground-18": {
+ "x": 240,
+ "y": 480,
+ "width": 18,
+ "height": 18
+ },
+ "rail-underground-12": {
+ "x": 258,
+ "y": 480,
+ "width": 12,
+ "height": 12
+ },
+ "rail-above-24": {
+ "x": 0,
+ "y": 504,
+ "width": 24,
+ "height": 24
+ },
+ "rail-above-18": {
+ "x": 24,
+ "y": 504,
+ "width": 18,
+ "height": 18
+ },
+ "rail-above-12": {
+ "x": 42,
+ "y": 504,
+ "width": 12,
+ "height": 12
+ },
+ "camera-24": {
+ "x": 54,
+ "y": 504,
+ "width": 24,
+ "height": 24
+ },
+ "camera-18": {
+ "x": 78,
+ "y": 504,
+ "width": 18,
+ "height": 18
+ },
+ "camera-12": {
+ "x": 96,
+ "y": 504,
+ "width": 12,
+ "height": 12
+ },
+ "laundry-24": {
+ "x": 108,
+ "y": 504,
+ "width": 24,
+ "height": 24
+ },
+ "laundry-18": {
+ "x": 132,
+ "y": 504,
+ "width": 18,
+ "height": 18
+ },
+ "laundry-12": {
+ "x": 150,
+ "y": 504,
+ "width": 12,
+ "height": 12
+ },
+ "car-24": {
+ "x": 162,
+ "y": 504,
+ "width": 24,
+ "height": 24
+ },
+ "car-18": {
+ "x": 186,
+ "y": 504,
+ "width": 18,
+ "height": 18
+ },
+ "car-12": {
+ "x": 204,
+ "y": 504,
+ "width": 12,
+ "height": 12
+ },
+ "suitcase-24": {
+ "x": 216,
+ "y": 504,
+ "width": 24,
+ "height": 24
+ },
+ "suitcase-18": {
+ "x": 240,
+ "y": 504,
+ "width": 18,
+ "height": 18
+ },
+ "suitcase-12": {
+ "x": 258,
+ "y": 504,
+ "width": 12,
+ "height": 12
+ },
+ "hairdresser-24": {
+ "x": 0,
+ "y": 528,
+ "width": 24,
+ "height": 24
+ },
+ "hairdresser-18": {
+ "x": 24,
+ "y": 528,
+ "width": 18,
+ "height": 18
+ },
+ "hairdresser-12": {
+ "x": 42,
+ "y": 528,
+ "width": 12,
+ "height": 12
+ },
+ "chemist-24": {
+ "x": 54,
+ "y": 528,
+ "width": 24,
+ "height": 24
+ },
+ "chemist-18": {
+ "x": 78,
+ "y": 528,
+ "width": 18,
+ "height": 18
+ },
+ "chemist-12": {
+ "x": 96,
+ "y": 528,
+ "width": 12,
+ "height": 12
+ },
+ "mobilephone-24": {
+ "x": 108,
+ "y": 528,
+ "width": 24,
+ "height": 24
+ },
+ "mobilephone-18": {
+ "x": 132,
+ "y": 528,
+ "width": 18,
+ "height": 18
+ },
+ "mobilephone-12": {
+ "x": 150,
+ "y": 528,
+ "width": 12,
+ "height": 12
+ },
+ "scooter-24": {
+ "x": 162,
+ "y": 528,
+ "width": 24,
+ "height": 24
+ },
+ "scooter-18": {
+ "x": 186,
+ "y": 528,
+ "width": 18,
+ "height": 18
+ },
+ "scooter-12": {
+ "x": 204,
+ "y": 528,
+ "width": 12,
+ "height": 12
+ },
+ "gift-24": {
+ "x": 216,
+ "y": 528,
+ "width": 24,
+ "height": 24
+ },
+ "gift-18": {
+ "x": 240,
+ "y": 528,
+ "width": 18,
+ "height": 18
+ },
+ "gift-12": {
+ "x": 258,
+ "y": 528,
+ "width": 12,
+ "height": 12
+ },
+ "ice-cream-24": {
+ "x": 0,
+ "y": 552,
+ "width": 24,
+ "height": 24
+ },
+ "ice-cream-18": {
+ "x": 24,
+ "y": 552,
+ "width": 18,
+ "height": 18
+ },
+ "ice-cream-12": {
+ "x": 42,
+ "y": 552,
+ "width": 12,
+ "height": 12
+ }
+ },
"locales": [
"af",
+ "sq",
"ar",
"ar-AA",
"hy",
"gl",
"de",
"el",
- "hi-IN",
"hu",
"is",
"id",
"pl",
"pt",
"pt-BR",
- "ro-RO",
+ "ro",
"ru",
"sc",
"sr",
},
"merge": {
"title": "Merge",
- "description": "Merge these lines.",
+ "description": "Merge these features.",
"key": "C",
- "annotation": "Merged {n} lines.",
+ "annotation": "Merged {n} features.",
"not_eligible": "These features can't be merged.",
- "not_adjacent": "These lines can't be merged because they aren't connected.",
- "restriction": "These lines can't be merged because at least one is a member of a \"{relation}\" relation.",
- "incomplete_relation": "These features can't be merged because at least one hasn't been fully downloaded."
+ "not_adjacent": "These features can't be merged because they aren't connected.",
+ "restriction": "These features can't be merged because at least one is a member of a \"{relation}\" relation.",
+ "incomplete_relation": "These features can't be merged because at least one hasn't been fully downloaded.",
+ "conflicting_tags": "These features can't be merged because some of their tags have conflicting values."
},
"move": {
"title": "Move",
"nothing": "Nothing to redo."
},
"tooltip_keyhint": "Shortcut:",
- "browser_notice": "This editor is supported in Firefox, Chrome, Safari, Opera, and Internet Explorer 9 and above. Please upgrade your browser or use Potlatch 2 to edit the map.",
+ "browser_notice": "This editor is supported in Firefox, Chrome, Safari, Opera, and Internet Explorer 11 and above. Please upgrade your browser or use Potlatch 2 to edit the map.",
"translate": {
"translate": "Translate",
"localized_translation_label": "Multilingual name",
"zoom_in_edit": "Zoom in to Edit",
"logout": "logout",
"loading_auth": "Connecting to OpenStreetMap...",
- "report_a_bug": "report a bug",
+ "report_a_bug": "Report a bug",
+ "help_translate": "Help translate",
"feature_info": {
"hidden_warning": "{count} hidden features",
"hidden_details": "These features are currently hidden: {details}"
"custom_button": "Edit custom background",
"custom_prompt": "Enter a tile URL template. Valid tokens are {z}, {x}, {y} for Z/X/Y scheme and {u} for quadtile scheme.",
"fix_misalignment": "Fix alignment",
- "reset": "reset"
+ "reset": "reset",
+ "minimap": {
+ "description": "Minimap",
+ "tooltip": "Show a zoomed out map to help locate the area currently displayed."
+ }
},
"map_data": {
"title": "Map Data",
"out": "Zoom Out"
},
"cannot_zoom": "Cannot zoom out further in current mode.",
+ "full_screen": "Toggle Full Screen",
"gpx": {
"local_layer": "Local GPX file",
"drag_drop": "Drag and drop a .gpx file on the page, or click the button to the right to browse",
"help": {
"title": "Help",
"help": "# Help\n\nThis is an editor for [OpenStreetMap](http://www.openstreetmap.org/), the\nfree and editable map of the world. You can use it to add and update\ndata in your area, making an open-source and open-data map of the world\nbetter for everyone.\n\nEdits that you make on this map will be visible to everyone who uses\nOpenStreetMap. In order to make an edit, you'll need to\n[log in](https://www.openstreetmap.org/login).\n\nThe [iD editor](http://ideditor.com/) is a collaborative project with [source\ncode available on GitHub](https://github.com/openstreetmap/iD).\n",
- "editing_saving": "# Editing & Saving\n\nThis editor is designed to work primarily online, and you're accessing\nit through a website right now.\n\n### Selecting Features\n\nTo select a map feature, like a road or point of interest, click\non it on the map. This will highlight the selected feature, open a panel with\ndetails about it, and show a menu of things you can do with the feature.\n\nTo select multiple features, hold down the 'Shift' key. Then either click\non the features you want to select, or drag on the map to draw a rectangle.\nThis will draw a box and select all the points within it.\n\n### Saving Edits\n\nWhen you make changes like editing roads, buildings, and places, these are\nstored locally until you save them to the server. Don't worry if you make\na mistake - you can undo changes by clicking the undo button, and redo\nchanges by clicking the redo button.\n\nClick 'Save' to finish a group of edits - for instance, if you've completed\nan area of town and would like to start on a new area. You'll have a chance\nto review what you've done, and the editor supplies helpful suggestions\nand warnings if something doesn't seem right about the changes.\n\nIf everything looks good, you can enter a short comment explaining the change\nyou made, and click 'Save' again to post the changes\nto [OpenStreetMap.org](http://www.openstreetmap.org/), where they are visible\nto all other users and available for others to build and improve upon.\n\nIf you can't finish your edits in one sitting, you can leave the editor\nwindow and come back (on the same browser and computer), and the\neditor application will offer to restore your work.\n",
+ "editing_saving": "# Editing & Saving\n\nThis editor is designed to work primarily online, and you're accessing\nit through a website right now.\n\n### Selecting Features\n\nTo select a map feature, like a road or point of interest, click\non it on the map. This will highlight the selected feature, open a panel with\ndetails about it, and show a menu of things you can do with the feature.\n\nTo select multiple features, hold down the 'Shift' key. Then either click\non the features you want to select, or drag on the map to draw a rectangle.\nThis will draw a box and select all the points within it.\n\n### Saving Edits\n\nWhen you make changes like editing roads, buildings, and places, these are\nstored locally until you save them to the server. Don't worry if you make\na mistake - you can undo changes by clicking the undo button, and redo\nchanges by clicking the redo button.\n\nClick 'Save' to finish a group of edits - for instance, if you've completed\nan area of town and would like to start on a new area. You'll have a chance\nto review what you've done, and the editor supplies helpful suggestions\nand warnings if something doesn't seem right about the changes.\n\nIf everything looks good, you can enter a short comment explaining the change\nyou made, and click 'Save' again to post the changes\nto [OpenStreetMap.org](http://www.openstreetmap.org/), where they are visible\nto all other users and available for others to build and improve upon.\n\nIf you can't finish your edits in one sitting, you can leave the editor\nwindow and come back (on the same browser and computer), and the\neditor application will offer to restore your work.\n\n### Using the editor\n\nA list of available keyboard shortcuts can be found [here](http://wiki.openstreetmap.org/wiki/ID/Shortcuts).\n",
"roads": "# Roads\n\nYou can create, fix, and delete roads with this editor. Roads can be all\nkinds: paths, highways, trails, cycleways, and more - any often-crossed\nsegment should be mappable.\n\n### Selecting\n\nClick on a road to select it. An outline should become visible, along\nwith a small tools menu on the map and a sidebar showing more information\nabout the road.\n\n### Modifying\n\nOften you'll see roads that aren't aligned to the imagery behind them\nor to a GPS track. You can adjust these roads so they are in the correct\nplace.\n\nFirst click on the road you want to change. This will highlight it and show\ncontrol points along it that you can drag to better locations. If\nyou want to add new control points for more detail, double-click a part\nof the road without a node, and one will be added.\n\nIf the road connects to another road, but doesn't properly connect on\nthe map, you can drag one of its control points onto the other road in\norder to join them. Having roads connect is important for the map\nand essential for providing driving directions.\n\nYou can also click the 'Move' tool or press the `M` shortcut key to move the entire road at\none time, and then click again to save that movement.\n\n### Deleting\n\nIf a road is entirely incorrect - you can see that it doesn't exist in satellite\nimagery and ideally have confirmed locally that it's not present - you can delete\nit, which removes it from the map. Be cautious when deleting features -\nlike any other edit, the results are seen by everyone and satellite imagery\nis often out of date, so the road could simply be newly built.\n\nYou can delete a road by clicking on it to select it, then clicking the\ntrash can icon or pressing the 'Delete' key.\n\n### Creating\n\nFound somewhere there should be a road but there isn't? Click the 'Line'\nicon in the top-left of the editor or press the shortcut key `2` to start drawing\na line.\n\nClick on the start of the road on the map to start drawing. If the road\nbranches off from an existing road, start by clicking on the place where they connect.\n\nThen click on points along the road so that it follows the right path, according\nto satellite imagery or GPS. If the road you are drawing crosses another road, connect\nit by clicking on the intersection point. When you're done drawing, double-click\nor press 'Return' or 'Enter' on your keyboard.\n",
- "gps": "# GPS\n\nGPS data is the most trusted source of data for OpenStreetMap. This editor\nsupports local traces - `.gpx` files on your local computer. You can collect\nthis kind of GPS trace with a number of smartphone applications as well as\npersonal GPS hardware.\n\nFor information on how to perform a GPS survey, read\n[Surveying with a GPS](http://learnosm.org/en/beginner/using-gps/).\n\nTo use a GPX track for mapping, drag and drop the GPX file onto the map\neditor. If it's recognized, it will be added to the map as a bright purple\nline. Click on the 'Map Data' menu on the right side to enable,\ndisable, or zoom to this new GPX-powered layer.\n\nThe GPX track isn't directly uploaded to OpenStreetMap - the best way to\nuse it is to draw on the map, using it as a guide for the new features that\nyou add, and also to [upload it to OpenStreetMap](http://www.openstreetmap.org/trace/create)\nfor other users to use.\n",
+ "gps": "# GPS\n\nCollected GPS traces are one valuable source of data for OpenStreetMap. This editor\nsupports local traces - `.gpx` files on your local computer. You can collect\nthis kind of GPS trace with a number of smartphone applications as well as\npersonal GPS hardware.\n\nFor information on how to perform a GPS survey, read\n[Mapping with a smartphone, GPS, or paper](http://learnosm.org/en/mobile-mapping/).\n\nTo use a GPX track for mapping, drag and drop the GPX file onto the map\neditor. If it's recognized, it will be added to the map as a bright purple\nline. Click on the 'Map Data' menu on the right side to enable,\ndisable, or zoom to this new GPX-powered layer.\n\nThe GPX track isn't directly uploaded to OpenStreetMap - the best way to\nuse it is to draw on the map, using it as a guide for the new features that\nyou add, and also to [upload it to OpenStreetMap](http://www.openstreetmap.org/trace/create)\nfor other users to use.\n",
"imagery": "# Imagery\n\nAerial imagery is an important resource for mapping. A combination of\nairplane flyovers, satellite views, and freely-compiled sources are available\nin the editor under the 'Background Settings' menu on the right.\n\nBy default a [Bing Maps](http://www.bing.com/maps/) satellite layer is\npresented in the editor, but as you pan and zoom the map to new geographical\nareas, new sources will become available. Some countries, like the United\nStates, France, and Denmark have very high-quality imagery available for some areas.\n\nImagery is sometimes offset from the map data because of a mistake on the\nimagery provider's side. If you see a lot of roads shifted from the background,\ndon't immediately move them all to match the background. Instead you can adjust\nthe imagery so that it matches the existing data by clicking 'Fix alignment' at\nthe bottom of the Background Settings UI.\n",
"addresses": "# Addresses\n\nAddresses are some of the most useful information for the map.\n\nAlthough addresses are often represented as parts of streets, in OpenStreetMap\nthey're recorded as attributes of buildings and places along streets.\n\nYou can add address information to places mapped as building outlines\nas well as those mapped as single points. The optimal source of address\ndata is from an on-the-ground survey or personal knowledge - as with any\nother feature, copying from commercial sources like Google Maps is strictly\nforbidden.\n",
- "inspector": "# Using the Inspector\n\nThe inspector is the section on the left side of the page that allows you to\nedit the details of the selected feature.\n\n### Selecting a Feature Type\n\nAfter you add a point, line, or area, you can choose what type of feature it\nis, like whether it's a highway or residential road, supermarket or cafe.\nThe inspector will display buttons for common feature types, and you can\nfind others by typing what you're looking for in the search box.\n\nClick the 'i' in the bottom-right-hand corner of a feature type button to\nlearn more about it. Click a button to choose that type.\n\n### Using Forms and Editing Tags\n\nAfter you choose a feature type, or when you select a feature that already\nhas a type assigned, the inspector will display fields with details about\nthe feature like its name and address.\n\nBelow the fields you see, you can click icons to add other details,\nlike [Wikipedia](http://www.wikipedia.org/) information, wheelchair\naccess, and more.\n\nAt the bottom of the inspector, click 'Additional tags' to add arbitrary\nother tags to the element. [Taginfo](http://taginfo.openstreetmap.org/) is a\ngreat resource for learn more about popular tag combinations.\n\nChanges you make in the inspector are automatically applied to the map.\nYou can undo them at any time by clicking the 'Undo' button.\n",
+ "inspector": "# Using the Inspector\n\nThe inspector is the section on the left side of the page that allows you to\nedit the details of the selected feature.\n\n### Selecting a Feature Type\n\nAfter you add a point, line, or area, you can choose what type of feature it\nis, like whether it's a highway or residential road, supermarket or cafe.\nThe inspector will display buttons for common feature types, and you can\nfind others by typing what you're looking for in the search box.\n\nClick the 'i' in the bottom-right-hand corner of a feature type button to\nlearn more about it. Click a button to choose that type.\n\n### Using Forms and Editing Tags\n\nAfter you choose a feature type, or when you select a feature that already\nhas a type assigned, the inspector will display fields with details about\nthe feature like its name and address.\n\nBelow the fields you see, you can click the 'Add field' dropdown to add\nother details, like a Wikipedia link, wheelchair access, and more.\n\nAt the bottom of the inspector, click 'Additional tags' to add arbitrary\nother tags to the element. [Taginfo](http://taginfo.openstreetmap.org/) is a\ngreat resource for learn more about popular tag combinations.\n\nChanges you make in the inspector are automatically applied to the map.\nYou can undo them at any time by clicking the 'Undo' button.\n",
"buildings": "# Buildings\n\nOpenStreetMap is the world's largest database of buildings. You can create\nand improve this database.\n\n### Selecting\n\nYou can select a building by clicking on its border. This will highlight the\nbuilding and open a small tools menu and a sidebar showing more information\nabout the building.\n\n### Modifying\n\nSometimes buildings are incorrectly placed or have incorrect tags.\n\nTo move an entire building, select it, then click the 'Move' tool. Move your\nmouse to shift the building, and click when it's correctly placed.\n\nTo fix the specific shape of a building, click and drag the nodes that form\nits border into better places.\n\n### Creating\n\nOne of the main questions around adding buildings to the map is that\nOpenStreetMap records buildings both as shapes and points. The rule of thumb\nis to _map a building as a shape whenever possible_, and map companies, homes,\namenities, and other things that operate out of buildings as points placed\nwithin the building shape.\n\nStart drawing a building as a shape by clicking the 'Area' button in the top\nleft of the interface, and end it either by pressing 'Return' on your keyboard\nor clicking on the first node drawn to close the shape.\n\n### Deleting\n\nIf a building is entirely incorrect - you can see that it doesn't exist in satellite\nimagery and ideally have confirmed locally that it's not present - you can delete\nit, which removes it from the map. Be cautious when deleting features -\nlike any other edit, the results are seen by everyone and satellite imagery\nis often out of date, so the building could simply be newly built.\n\nYou can delete a building by clicking on it to select it, then clicking the\ntrash can icon or pressing the 'Delete' key.\n",
"relations": "# Relations\n\nA relation is a special type of feature in OpenStreetMap that groups together\nother features. For example, two common types of relations are *route relations*,\nwhich group together sections of road that belong to a specific freeway or\nhighway, and *multipolygons*, which group together several lines that define\na complex area (one with several pieces or holes in it like a donut).\n\nThe group of features in a relation are called *members*. In the sidebar, you can\nsee which relations a feature is a member of, and click on a relation there\nto select the it. When the relation is selected, you can see all of its\nmembers listed in the sidebar and highlighted on the map.\n\nFor the most part, iD will take care of maintaining relations automatically\nwhile you edit. The main thing you should be aware of is that if you delete a\nsection of road to redraw it more accurately, you should make sure that the\nnew section is a member of the same relations as the original.\n\n## Editing Relations\n\nIf you want to edit relations, here are the basics.\n\nTo add a feature to a relation, select the feature, click the \"+\" button in the\n\"All relations\" section of the sidebar, and select or type the name of the relation.\n\nTo create a new relation, select the first feature that should be a member,\nclick the \"+\" button in the \"All relations\" section, and select \"New relation...\".\n\nTo remove a feature from a relation, select the feature and click the trash\nbutton next to the relation you want to remove it from.\n\nYou can create multipolygons with holes using the \"Merge\" tool. Draw two areas (inner\nand outer), hold the Shift key and click on each of them to select them both, and then\nclick the \"Merge\" (+) button.\n"
},
},
"fields": {
"access": {
- "label": "Access",
- "placeholder": "Unknown",
+ "label": "Allowed Access",
+ "placeholder": "Not Specified",
"types": {
- "access": "General",
+ "access": "All",
"foot": "Foot",
"motor_vehicle": "Motor Vehicles",
"bicycle": "Bicycles",
"destination": {
"title": "Destination",
"description": "Access permitted only to reach a destination"
+ },
+ "dismount": {
+ "title": "Dismount",
+ "description": "Access permitted but rider must dismount"
}
}
},
"access_simple": {
- "label": "Access",
+ "label": "Allowed Access",
"placeholder": "yes"
},
"access_toilets": {
"placeholders": {
"housename": "Housename",
"housenumber": "123",
+ "conscriptionnumber": "123",
"street": "Street",
"city": "City",
"postcode": "Postcode",
"amenity": {
"label": "Type"
},
+ "area/highway": {
+ "label": "Type"
+ },
"artist": {
"label": "Artist"
},
"cuisine": {
"label": "Cuisine"
},
+ "cycleway": {
+ "label": "Bike Lanes",
+ "placeholder": "none",
+ "types": {
+ "cycleway:left": "Left side",
+ "cycleway:right": "Right side"
+ },
+ "options": {
+ "none": {
+ "title": "None",
+ "description": "No bike lane"
+ },
+ "lane": {
+ "title": "Standard bike lane",
+ "description": "A bike lane separated from auto traffic by a painted line"
+ },
+ "shared_lane": {
+ "title": "Shared bike lane",
+ "description": "A bike lane with no separation from auto traffic"
+ },
+ "track": {
+ "title": "Bike track",
+ "description": "A bike lane separated from traffic by a physical barrier"
+ },
+ "share_busway": {
+ "title": "Bike lane shared with bus",
+ "description": "A bike lane shared with a bus lane"
+ },
+ "opposite_lane": {
+ "title": "Opposite bike lane",
+ "description": "A bike lane that travels in the opposite direction of traffic"
+ },
+ "opposite": {
+ "title": "Contraflow bike lane",
+ "description": "A bike lane that travels in both directions on a one-way street"
+ }
+ }
+ },
"delivery": {
"label": "Delivery"
},
"label": "Handicap",
"placeholder": "1-18"
},
+ "handrail": {
+ "label": "Handrail"
+ },
"highway": {
"label": "Type"
},
"mixed": "Mixed"
}
},
+ "leaf_cycle_singular": {
+ "label": "Leaf Cycle",
+ "options": {
+ "evergreen": "Evergreen",
+ "deciduous": "Deciduous",
+ "semi_evergreen": "Semi-Evergreen",
+ "semi_deciduous": "Semi-Deciduous"
+ }
+ },
"leaf_type": {
"label": "Leaf Type",
"options": {
"leafless": "Leafless"
}
},
+ "leaf_type_singular": {
+ "label": "Leaf Type",
+ "options": {
+ "broadleaved": "Broadleaved",
+ "needleleaved": "Needleleaved",
+ "leafless": "Leafless"
+ }
+ },
"leisure": {
"label": "Type"
},
"length": {
"label": "Length (Meters)"
},
+ "level": {
+ "label": "Level"
+ },
"levels": {
"label": "Levels",
"placeholder": "2, 4, 6..."
"label": "Speed Limit",
"placeholder": "40, 50, 60..."
},
+ "maxstay": {
+ "label": "Max Stay"
+ },
"mtb/scale": {
"label": "Mountain Biking Difficulty",
"placeholder": "0, 1, 2, 3...",
"recycling/glass": {
"label": "Accepts Glass"
},
+ "recycling/glass_bottles": {
+ "label": "Accepts Glass Bottles"
+ },
"recycling/paper": {
"label": "Accepts Paper"
},
+ "recycling/plastic": {
+ "label": "Accepts Plastic"
+ },
+ "recycling/type": {
+ "label": "Recycling Type",
+ "options": {
+ "container": "Container",
+ "centre": "Recycling Center"
+ }
+ },
"ref": {
"label": "Reference"
},
"grade5": "Soft: soil/sand/grass"
}
},
+ "traffic_signals": {
+ "label": "Type"
+ },
"trail_visibility": {
"label": "Trail Visibility",
"placeholder": "Excellent, Good, Bad...",
"name": "Car Wash",
"terms": ""
},
+ "amenity/casino": {
+ "name": "Casino",
+ "terms": "gambling,roulette,craps,poker,blackjack"
+ },
"amenity/charging_station": {
"name": "Charging Station",
"terms": "EV,Electric Vehicle,Supercharger"
"name": "Marketplace",
"terms": ""
},
+ "amenity/motorcycle_parking": {
+ "name": "Motorcycle Parking",
+ "terms": ""
+ },
"amenity/nightclub": {
"name": "Nightclub",
"terms": "disco*,night club,dancing,dance club"
"name": "University Grounds",
"terms": "college"
},
- "amenity/vending_machine": {
+ "amenity/vending_machine/cigarettes": {
+ "name": "Cigarette Vending Machine",
+ "terms": "cigarette"
+ },
+ "amenity/vending_machine/condoms": {
+ "name": "Condom Vending Machine",
+ "terms": "condom"
+ },
+ "amenity/vending_machine/drinks": {
+ "name": "Drink Vending Machine",
+ "terms": "drink,soda,beverage,juice,pop"
+ },
+ "amenity/vending_machine/excrement_bags": {
+ "name": "Excrement Bag Vending Machine",
+ "terms": "excrement bags,poop,dog,animal"
+ },
+ "amenity/vending_machine/news_papers": {
+ "name": "Newspaper Vending Machine",
+ "terms": "newspaper"
+ },
+ "amenity/vending_machine/parcel_pickup_dropoff": {
+ "name": "Parcel Pickup/Dropoff Vending Machine",
+ "terms": "parcel,mail,pickup"
+ },
+ "amenity/vending_machine/parking_tickets": {
+ "name": "Parking Ticket Vending Machine",
+ "terms": "parking,ticket"
+ },
+ "amenity/vending_machine/public_transport_tickets": {
+ "name": "Transit Ticket Vending Machine",
+ "terms": "bus,train,ferry,rail,ticket,transportation"
+ },
+ "amenity/vending_machine/sweets": {
+ "name": "Snack Vending Machine",
+ "terms": "candy,gum,chip,pretzel,cookie,cracker"
+ },
+ "amenity/vending_machine/vending_machine": {
"name": "Vending Machine",
- "terms": "snack,soda,ticket"
+ "terms": ""
},
"amenity/veterinary": {
"name": "Veterinary",
"name": "Area",
"terms": ""
},
+ "area/highway": {
+ "name": "Road Surface",
+ "terms": ""
+ },
"barrier": {
"name": "Barrier",
"terms": ""
"terms": ""
},
"building/cathedral": {
- "name": "Cathedral",
+ "name": "Cathedral Building",
"terms": ""
},
"building/chapel": {
- "name": "Chapel",
+ "name": "Chapel Building",
"terms": ""
},
"building/church": {
- "name": "Church",
+ "name": "Church Building",
"terms": ""
},
"building/college": {
"terms": ""
},
"building/detached": {
- "name": "Detached Home",
- "terms": ""
+ "name": "Detached House",
+ "terms": "home,single,family,residence,dwelling"
},
"building/dormitory": {
"name": "Dormitory",
},
"building/house": {
"name": "House",
- "terms": ""
+ "terms": "home,family,residence,dwelling"
},
"building/hut": {
"name": "Hut",
"name": "School Building",
"terms": "academy,elementary school,middle school,high school"
},
+ "building/semidetached_house": {
+ "name": "Semi-Detached House",
+ "terms": "home,double,duplex,twin,family,residence,dwelling"
+ },
"building/shed": {
"name": "Shed",
"terms": ""
},
"building/terrace": {
"name": "Row Houses",
- "terms": ""
+ "terms": "home,terrace,brownstone,family,residence,dwelling"
},
"building/train_station": {
"name": "Train Station",
"terms": ""
},
"footway/crossing": {
- "name": "Crossing",
+ "name": "Street Crossing",
"terms": ""
},
"footway/crosswalk": {
- "name": "Crosswalk",
+ "name": "Pedestrian Crosswalk",
"terms": "zebra crossing"
},
"footway/sidewalk": {
"name": "Bus Stop",
"terms": ""
},
+ "highway/corridor": {
+ "name": "Indoor Corridor",
+ "terms": "gallery,hall,hallway,indoor,passage,passageway"
+ },
"highway/crossing": {
- "name": "Crossing",
+ "name": "Street Crossing",
"terms": ""
},
"highway/crosswalk": {
- "name": "Crosswalk",
+ "name": "Pedestrian Crosswalk",
"terms": "zebra crossing"
},
"highway/cycleway": {
"terms": "hike,hiking,trackway,trail,walk"
},
"highway/pedestrian": {
- "name": "Pedestrian",
+ "name": "Pedestrian Street",
"terms": ""
},
"highway/primary": {
"terms": ""
},
"landuse": {
- "name": "Landuse",
+ "name": "Land Use",
"terms": ""
},
"landuse/allotments": {
- "name": "Allotments",
- "terms": ""
+ "name": "Community Garden",
+ "terms": "allotment,garden"
},
"landuse/basin": {
"name": "Basin",
"name": "Orchard",
"terms": ""
},
+ "landuse/plant_nursery": {
+ "name": "Plant Nursery",
+ "terms": "vivero"
+ },
"landuse/quarry": {
"name": "Quarry",
"terms": ""
"name": "Leisure",
"terms": ""
},
+ "leisure/adult_gaming_centre": {
+ "name": "Adult Gaming Center",
+ "terms": "gambling,slot machine"
+ },
+ "leisure/bowling_alley": {
+ "name": "Bowling Alley",
+ "terms": ""
+ },
"leisure/common": {
"name": "Common",
"terms": "open space"
"name": "Basketball Court",
"terms": ""
},
+ "leisure/pitch/rugby_league": {
+ "name": "Rugby League Field",
+ "terms": ""
+ },
+ "leisure/pitch/rugby_union": {
+ "name": "Rugby Union Field",
+ "terms": ""
+ },
"leisure/pitch/skateboard": {
"name": "Skate Park",
"terms": ""
"name": "Man Made",
"terms": ""
},
+ "man_made/adit": {
+ "name": "Adit",
+ "terms": "entrance,underground,mine,cave"
+ },
"man_made/breakwater": {
"name": "Breakwater",
"terms": ""
"name": "Bunker",
"terms": ""
},
+ "military/checkpoint": {
+ "name": "Checkpoint",
+ "terms": ""
+ },
+ "military/danger_area": {
+ "name": "Danger Area",
+ "terms": ""
+ },
+ "military/naval_base": {
+ "name": "Naval Base",
+ "terms": ""
+ },
+ "military/obstacle_course": {
+ "name": "Obstacle Course",
+ "terms": ""
+ },
"military/range": {
"name": "Military Range",
"terms": ""
},
+ "military/training_area": {
+ "name": "Training area",
+ "terms": ""
+ },
"natural": {
"name": "Natural",
"terms": ""
},
"natural/cave_entrance": {
"name": "Cave Entrance",
- "terms": ""
+ "terms": "cavern,hollow,grotto,shelter,cavity"
},
"natural/cliff": {
"name": "Cliff",
"name": "Peak",
"terms": "acme,aiguille,alp,climax,crest,crown,hill,mount,mountain,pinnacle,summit,tip,top"
},
+ "natural/saddle": {
+ "name": "Saddle",
+ "terms": "pass,mountain pass,top"
+ },
"natural/scree": {
"name": "Scree",
"terms": "loose rocks"
},
"natural/scrub": {
"name": "Scrub",
- "terms": ""
+ "terms": "bush,shrubs"
},
"natural/spring": {
"name": "Spring",
"name": "Tree",
"terms": ""
},
+ "natural/tree_row": {
+ "name": "Tree row",
+ "terms": ""
+ },
+ "natural/volcano": {
+ "name": "Volcano",
+ "terms": "mountain,crater"
+ },
"natural/water": {
"name": "Water",
"terms": ""
"terms": "break,interrupt,rest,wait,interruption"
},
"railway/level_crossing": {
- "name": "Level Crossing",
- "terms": "crossing,railroad crossing,railway crossing,grade crossing,road through railroad,train crossing"
+ "name": "Railway Crossing",
+ "terms": "crossing,railroad crossing,level crossing,grade crossing,road through railroad,train crossing"
},
"railway/monorail": {
"name": "Monorail",
],
[
"city"
+ ],
+ [
+ "postcode"
]
]
},