3 var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
5 var check = function (it) {
6 return it && it.Math == Math && it;
9 // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
11 // eslint-disable-next-line es/no-global-this -- safe
12 check(typeof globalThis == 'object' && globalThis) ||
13 check(typeof window == 'object' && window) ||
14 // eslint-disable-next-line no-restricted-globals -- safe
15 check(typeof self == 'object' && self) ||
16 check(typeof commonjsGlobal == 'object' && commonjsGlobal) ||
17 // eslint-disable-next-line no-new-func -- fallback
18 (function () { return this; })() || Function('return this')();
20 var objectGetOwnPropertyDescriptor = {};
22 var fails$V = function (exec) {
30 var fails$U = fails$V;
32 // Detect IE8's incomplete defineProperty implementation
33 var descriptors = !fails$U(function () {
34 // eslint-disable-next-line es/no-object-defineproperty -- required for testing
35 return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7;
38 var fails$T = fails$V;
40 var functionBindNative = !fails$T(function () {
41 var test = (function () { /* empty */ }).bind();
42 // eslint-disable-next-line no-prototype-builtins -- safe
43 return typeof test != 'function' || test.hasOwnProperty('prototype');
46 var NATIVE_BIND$4 = functionBindNative;
48 var call$q = Function.prototype.call;
50 var functionCall = NATIVE_BIND$4 ? call$q.bind(call$q) : function () {
51 return call$q.apply(call$q, arguments);
54 var objectPropertyIsEnumerable = {};
56 var $propertyIsEnumerable$2 = {}.propertyIsEnumerable;
57 // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
58 var getOwnPropertyDescriptor$5 = Object.getOwnPropertyDescriptor;
61 var NASHORN_BUG = getOwnPropertyDescriptor$5 && !$propertyIsEnumerable$2.call({ 1: 2 }, 1);
63 // `Object.prototype.propertyIsEnumerable` method implementation
64 // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
65 objectPropertyIsEnumerable.f = NASHORN_BUG ? function propertyIsEnumerable(V) {
66 var descriptor = getOwnPropertyDescriptor$5(this, V);
67 return !!descriptor && descriptor.enumerable;
68 } : $propertyIsEnumerable$2;
70 var createPropertyDescriptor$7 = function (bitmap, value) {
72 enumerable: !(bitmap & 1),
73 configurable: !(bitmap & 2),
74 writable: !(bitmap & 4),
79 var NATIVE_BIND$3 = functionBindNative;
81 var FunctionPrototype$3 = Function.prototype;
82 var bind$g = FunctionPrototype$3.bind;
83 var call$p = FunctionPrototype$3.call;
84 var uncurryThis$Y = NATIVE_BIND$3 && bind$g.bind(call$p, call$p);
86 var functionUncurryThis = NATIVE_BIND$3 ? function (fn) {
87 return fn && uncurryThis$Y(fn);
89 return fn && function () {
90 return call$p.apply(fn, arguments);
94 var uncurryThis$X = functionUncurryThis;
96 var toString$n = uncurryThis$X({}.toString);
97 var stringSlice$c = uncurryThis$X(''.slice);
99 var classofRaw$1 = function (it) {
100 return stringSlice$c(toString$n(it), 8, -1);
103 var global$1n = global$1o;
104 var uncurryThis$W = functionUncurryThis;
105 var fails$S = fails$V;
106 var classof$e = classofRaw$1;
108 var Object$5 = global$1n.Object;
109 var split$4 = uncurryThis$W(''.split);
111 // fallback for non-array-like ES3 and non-enumerable old V8 strings
112 var indexedObject = fails$S(function () {
113 // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
114 // eslint-disable-next-line no-prototype-builtins -- safe
115 return !Object$5('z').propertyIsEnumerable(0);
117 return classof$e(it) == 'String' ? split$4(it, '') : Object$5(it);
120 var global$1m = global$1o;
122 var TypeError$p = global$1m.TypeError;
124 // `RequireObjectCoercible` abstract operation
125 // https://tc39.es/ecma262/#sec-requireobjectcoercible
126 var requireObjectCoercible$e = function (it) {
127 if (it == undefined) throw TypeError$p("Can't call method on " + it);
131 // toObject with fallback for non-array-like ES3 strings
132 var IndexedObject$4 = indexedObject;
133 var requireObjectCoercible$d = requireObjectCoercible$e;
135 var toIndexedObject$d = function (it) {
136 return IndexedObject$4(requireObjectCoercible$d(it));
139 // `IsCallable` abstract operation
140 // https://tc39.es/ecma262/#sec-iscallable
141 var isCallable$r = function (argument) {
142 return typeof argument == 'function';
145 var isCallable$q = isCallable$r;
147 var isObject$s = function (it) {
148 return typeof it == 'object' ? it !== null : isCallable$q(it);
151 var global$1l = global$1o;
152 var isCallable$p = isCallable$r;
154 var aFunction = function (argument) {
155 return isCallable$p(argument) ? argument : undefined;
158 var getBuiltIn$b = function (namespace, method) {
159 return arguments.length < 2 ? aFunction(global$1l[namespace]) : global$1l[namespace] && global$1l[namespace][method];
162 var uncurryThis$V = functionUncurryThis;
164 var objectIsPrototypeOf = uncurryThis$V({}.isPrototypeOf);
166 var getBuiltIn$a = getBuiltIn$b;
168 var engineUserAgent = getBuiltIn$a('navigator', 'userAgent') || '';
170 var global$1k = global$1o;
171 var userAgent$7 = engineUserAgent;
173 var process$4 = global$1k.process;
174 var Deno = global$1k.Deno;
175 var versions = process$4 && process$4.versions || Deno && Deno.version;
176 var v8 = versions && versions.v8;
177 var match, version$1;
180 match = v8.split('.');
181 // in old Chrome, versions of V8 isn't V8 = Chrome / 10
182 // but their correct versions are not interesting for us
183 version$1 = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]);
186 // BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
187 // so check `userAgent` even if `.v8` exists, but 0
188 if (!version$1 && userAgent$7) {
189 match = userAgent$7.match(/Edge\/(\d+)/);
190 if (!match || match[1] >= 74) {
191 match = userAgent$7.match(/Chrome\/(\d+)/);
192 if (match) version$1 = +match[1];
196 var engineV8Version = version$1;
198 /* eslint-disable es/no-symbol -- required for testing */
200 var V8_VERSION$3 = engineV8Version;
201 var fails$R = fails$V;
203 // eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing
204 var nativeSymbol = !!Object.getOwnPropertySymbols && !fails$R(function () {
205 var symbol = Symbol();
206 // Chrome 38 Symbol has incorrect toString conversion
207 // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
208 return !String(symbol) || !(Object(symbol) instanceof Symbol) ||
209 // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
210 !Symbol.sham && V8_VERSION$3 && V8_VERSION$3 < 41;
213 /* eslint-disable es/no-symbol -- required for testing */
215 var NATIVE_SYMBOL$3 = nativeSymbol;
217 var useSymbolAsUid = NATIVE_SYMBOL$3
219 && typeof Symbol.iterator == 'symbol';
221 var global$1j = global$1o;
222 var getBuiltIn$9 = getBuiltIn$b;
223 var isCallable$o = isCallable$r;
224 var isPrototypeOf$9 = objectIsPrototypeOf;
225 var USE_SYMBOL_AS_UID$1 = useSymbolAsUid;
227 var Object$4 = global$1j.Object;
229 var isSymbol$6 = USE_SYMBOL_AS_UID$1 ? function (it) {
230 return typeof it == 'symbol';
232 var $Symbol = getBuiltIn$9('Symbol');
233 return isCallable$o($Symbol) && isPrototypeOf$9($Symbol.prototype, Object$4(it));
236 var global$1i = global$1o;
238 var String$6 = global$1i.String;
240 var tryToString$5 = function (argument) {
242 return String$6(argument);
248 var global$1h = global$1o;
249 var isCallable$n = isCallable$r;
250 var tryToString$4 = tryToString$5;
252 var TypeError$o = global$1h.TypeError;
254 // `Assert: IsCallable(argument) is true`
255 var aCallable$a = function (argument) {
256 if (isCallable$n(argument)) return argument;
257 throw TypeError$o(tryToString$4(argument) + ' is not a function');
260 var aCallable$9 = aCallable$a;
262 // `GetMethod` abstract operation
263 // https://tc39.es/ecma262/#sec-getmethod
264 var getMethod$7 = function (V, P) {
266 return func == null ? undefined : aCallable$9(func);
269 var global$1g = global$1o;
270 var call$o = functionCall;
271 var isCallable$m = isCallable$r;
272 var isObject$r = isObject$s;
274 var TypeError$n = global$1g.TypeError;
276 // `OrdinaryToPrimitive` abstract operation
277 // https://tc39.es/ecma262/#sec-ordinarytoprimitive
278 var ordinaryToPrimitive$1 = function (input, pref) {
280 if (pref === 'string' && isCallable$m(fn = input.toString) && !isObject$r(val = call$o(fn, input))) return val;
281 if (isCallable$m(fn = input.valueOf) && !isObject$r(val = call$o(fn, input))) return val;
282 if (pref !== 'string' && isCallable$m(fn = input.toString) && !isObject$r(val = call$o(fn, input))) return val;
283 throw TypeError$n("Can't convert object to primitive value");
286 var shared$5 = {exports: {}};
290 var global$1f = global$1o;
292 // eslint-disable-next-line es/no-object-defineproperty -- safe
293 var defineProperty$d = Object.defineProperty;
295 var setGlobal$3 = function (key, value) {
297 defineProperty$d(global$1f, key, { value: value, configurable: true, writable: true });
299 global$1f[key] = value;
303 var global$1e = global$1o;
304 var setGlobal$2 = setGlobal$3;
306 var SHARED = '__core-js_shared__';
307 var store$4 = global$1e[SHARED] || setGlobal$2(SHARED, {});
309 var sharedStore = store$4;
311 var store$3 = sharedStore;
313 (shared$5.exports = function (key, value) {
314 return store$3[key] || (store$3[key] = value !== undefined ? value : {});
315 })('versions', []).push({
318 copyright: '© 2014-2022 Denis Pushkarev (zloirock.ru)',
319 license: 'https://github.com/zloirock/core-js/blob/v3.21.0/LICENSE',
320 source: 'https://github.com/zloirock/core-js'
323 var global$1d = global$1o;
324 var requireObjectCoercible$c = requireObjectCoercible$e;
326 var Object$3 = global$1d.Object;
328 // `ToObject` abstract operation
329 // https://tc39.es/ecma262/#sec-toobject
330 var toObject$i = function (argument) {
331 return Object$3(requireObjectCoercible$c(argument));
334 var uncurryThis$U = functionUncurryThis;
335 var toObject$h = toObject$i;
337 var hasOwnProperty$3 = uncurryThis$U({}.hasOwnProperty);
339 // `HasOwnProperty` abstract operation
340 // https://tc39.es/ecma262/#sec-hasownproperty
341 var hasOwnProperty_1 = Object.hasOwn || function hasOwn(it, key) {
342 return hasOwnProperty$3(toObject$h(it), key);
345 var uncurryThis$T = functionUncurryThis;
348 var postfix = Math.random();
349 var toString$m = uncurryThis$T(1.0.toString);
351 var uid$5 = function (key) {
352 return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString$m(++id$2 + postfix, 36);
355 var global$1c = global$1o;
356 var shared$4 = shared$5.exports;
357 var hasOwn$l = hasOwnProperty_1;
359 var NATIVE_SYMBOL$2 = nativeSymbol;
360 var USE_SYMBOL_AS_UID = useSymbolAsUid;
362 var WellKnownSymbolsStore$1 = shared$4('wks');
363 var Symbol$3 = global$1c.Symbol;
364 var symbolFor = Symbol$3 && Symbol$3['for'];
365 var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol$3 : Symbol$3 && Symbol$3.withoutSetter || uid$4;
367 var wellKnownSymbol$t = function (name) {
368 if (!hasOwn$l(WellKnownSymbolsStore$1, name) || !(NATIVE_SYMBOL$2 || typeof WellKnownSymbolsStore$1[name] == 'string')) {
369 var description = 'Symbol.' + name;
370 if (NATIVE_SYMBOL$2 && hasOwn$l(Symbol$3, name)) {
371 WellKnownSymbolsStore$1[name] = Symbol$3[name];
372 } else if (USE_SYMBOL_AS_UID && symbolFor) {
373 WellKnownSymbolsStore$1[name] = symbolFor(description);
375 WellKnownSymbolsStore$1[name] = createWellKnownSymbol(description);
377 } return WellKnownSymbolsStore$1[name];
380 var global$1b = global$1o;
381 var call$n = functionCall;
382 var isObject$q = isObject$s;
383 var isSymbol$5 = isSymbol$6;
384 var getMethod$6 = getMethod$7;
385 var ordinaryToPrimitive = ordinaryToPrimitive$1;
386 var wellKnownSymbol$s = wellKnownSymbol$t;
388 var TypeError$m = global$1b.TypeError;
389 var TO_PRIMITIVE$1 = wellKnownSymbol$s('toPrimitive');
391 // `ToPrimitive` abstract operation
392 // https://tc39.es/ecma262/#sec-toprimitive
393 var toPrimitive$3 = function (input, pref) {
394 if (!isObject$q(input) || isSymbol$5(input)) return input;
395 var exoticToPrim = getMethod$6(input, TO_PRIMITIVE$1);
398 if (pref === undefined) pref = 'default';
399 result = call$n(exoticToPrim, input, pref);
400 if (!isObject$q(result) || isSymbol$5(result)) return result;
401 throw TypeError$m("Can't convert object to primitive value");
403 if (pref === undefined) pref = 'number';
404 return ordinaryToPrimitive(input, pref);
407 var toPrimitive$2 = toPrimitive$3;
408 var isSymbol$4 = isSymbol$6;
410 // `ToPropertyKey` abstract operation
411 // https://tc39.es/ecma262/#sec-topropertykey
412 var toPropertyKey$5 = function (argument) {
413 var key = toPrimitive$2(argument, 'string');
414 return isSymbol$4(key) ? key : key + '';
417 var global$1a = global$1o;
418 var isObject$p = isObject$s;
420 var document$3 = global$1a.document;
421 // typeof document.createElement is 'object' in old IE
422 var EXISTS$1 = isObject$p(document$3) && isObject$p(document$3.createElement);
424 var documentCreateElement$2 = function (it) {
425 return EXISTS$1 ? document$3.createElement(it) : {};
428 var DESCRIPTORS$p = descriptors;
429 var fails$Q = fails$V;
430 var createElement$1 = documentCreateElement$2;
432 // Thanks to IE8 for its funny defineProperty
433 var ie8DomDefine = !DESCRIPTORS$p && !fails$Q(function () {
434 // eslint-disable-next-line es/no-object-defineproperty -- required for testing
435 return Object.defineProperty(createElement$1('div'), 'a', {
436 get: function () { return 7; }
440 var DESCRIPTORS$o = descriptors;
441 var call$m = functionCall;
442 var propertyIsEnumerableModule$2 = objectPropertyIsEnumerable;
443 var createPropertyDescriptor$6 = createPropertyDescriptor$7;
444 var toIndexedObject$c = toIndexedObject$d;
445 var toPropertyKey$4 = toPropertyKey$5;
446 var hasOwn$k = hasOwnProperty_1;
447 var IE8_DOM_DEFINE$1 = ie8DomDefine;
449 // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
450 var $getOwnPropertyDescriptor$2 = Object.getOwnPropertyDescriptor;
452 // `Object.getOwnPropertyDescriptor` method
453 // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
454 objectGetOwnPropertyDescriptor.f = DESCRIPTORS$o ? $getOwnPropertyDescriptor$2 : function getOwnPropertyDescriptor(O, P) {
455 O = toIndexedObject$c(O);
456 P = toPropertyKey$4(P);
457 if (IE8_DOM_DEFINE$1) try {
458 return $getOwnPropertyDescriptor$2(O, P);
459 } catch (error) { /* empty */ }
460 if (hasOwn$k(O, P)) return createPropertyDescriptor$6(!call$m(propertyIsEnumerableModule$2.f, O, P), O[P]);
463 var objectDefineProperty = {};
465 var DESCRIPTORS$n = descriptors;
466 var fails$P = fails$V;
469 // https://bugs.chromium.org/p/v8/issues/detail?id=3334
470 var v8PrototypeDefineBug = DESCRIPTORS$n && fails$P(function () {
471 // eslint-disable-next-line es/no-object-defineproperty -- required for testing
472 return Object.defineProperty(function () { /* empty */ }, 'prototype', {
478 var global$19 = global$1o;
479 var isObject$o = isObject$s;
481 var String$5 = global$19.String;
482 var TypeError$l = global$19.TypeError;
484 // `Assert: Type(argument) is Object`
485 var anObject$n = function (argument) {
486 if (isObject$o(argument)) return argument;
487 throw TypeError$l(String$5(argument) + ' is not an object');
490 var global$18 = global$1o;
491 var DESCRIPTORS$m = descriptors;
492 var IE8_DOM_DEFINE = ie8DomDefine;
493 var V8_PROTOTYPE_DEFINE_BUG$1 = v8PrototypeDefineBug;
494 var anObject$m = anObject$n;
495 var toPropertyKey$3 = toPropertyKey$5;
497 var TypeError$k = global$18.TypeError;
498 // eslint-disable-next-line es/no-object-defineproperty -- safe
499 var $defineProperty$1 = Object.defineProperty;
500 // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
501 var $getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor;
502 var ENUMERABLE = 'enumerable';
503 var CONFIGURABLE$1 = 'configurable';
504 var WRITABLE = 'writable';
506 // `Object.defineProperty` method
507 // https://tc39.es/ecma262/#sec-object.defineproperty
508 objectDefineProperty.f = DESCRIPTORS$m ? V8_PROTOTYPE_DEFINE_BUG$1 ? function defineProperty(O, P, Attributes) {
510 P = toPropertyKey$3(P);
511 anObject$m(Attributes);
512 if (typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) {
513 var current = $getOwnPropertyDescriptor$1(O, P);
514 if (current && current[WRITABLE]) {
515 O[P] = Attributes.value;
517 configurable: CONFIGURABLE$1 in Attributes ? Attributes[CONFIGURABLE$1] : current[CONFIGURABLE$1],
518 enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE],
522 } return $defineProperty$1(O, P, Attributes);
523 } : $defineProperty$1 : function defineProperty(O, P, Attributes) {
525 P = toPropertyKey$3(P);
526 anObject$m(Attributes);
527 if (IE8_DOM_DEFINE) try {
528 return $defineProperty$1(O, P, Attributes);
529 } catch (error) { /* empty */ }
530 if ('get' in Attributes || 'set' in Attributes) throw TypeError$k('Accessors not supported');
531 if ('value' in Attributes) O[P] = Attributes.value;
535 var DESCRIPTORS$l = descriptors;
536 var definePropertyModule$7 = objectDefineProperty;
537 var createPropertyDescriptor$5 = createPropertyDescriptor$7;
539 var createNonEnumerableProperty$b = DESCRIPTORS$l ? function (object, key, value) {
540 return definePropertyModule$7.f(object, key, createPropertyDescriptor$5(1, value));
541 } : function (object, key, value) {
546 var redefine$h = {exports: {}};
548 var uncurryThis$S = functionUncurryThis;
549 var isCallable$l = isCallable$r;
550 var store$2 = sharedStore;
552 var functionToString$1 = uncurryThis$S(Function.toString);
554 // this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper
555 if (!isCallable$l(store$2.inspectSource)) {
556 store$2.inspectSource = function (it) {
557 return functionToString$1(it);
561 var inspectSource$4 = store$2.inspectSource;
563 var global$17 = global$1o;
564 var isCallable$k = isCallable$r;
565 var inspectSource$3 = inspectSource$4;
567 var WeakMap$1 = global$17.WeakMap;
569 var nativeWeakMap = isCallable$k(WeakMap$1) && /native code/.test(inspectSource$3(WeakMap$1));
571 var shared$3 = shared$5.exports;
574 var keys$3 = shared$3('keys');
576 var sharedKey$4 = function (key) {
577 return keys$3[key] || (keys$3[key] = uid$3(key));
580 var hiddenKeys$6 = {};
582 var NATIVE_WEAK_MAP = nativeWeakMap;
583 var global$16 = global$1o;
584 var uncurryThis$R = functionUncurryThis;
585 var isObject$n = isObject$s;
586 var createNonEnumerableProperty$a = createNonEnumerableProperty$b;
587 var hasOwn$j = hasOwnProperty_1;
588 var shared$2 = sharedStore;
589 var sharedKey$3 = sharedKey$4;
590 var hiddenKeys$5 = hiddenKeys$6;
592 var OBJECT_ALREADY_INITIALIZED = 'Object already initialized';
593 var TypeError$j = global$16.TypeError;
594 var WeakMap = global$16.WeakMap;
595 var set$4, get$5, has;
597 var enforce = function (it) {
598 return has(it) ? get$5(it) : set$4(it, {});
601 var getterFor = function (TYPE) {
602 return function (it) {
604 if (!isObject$n(it) || (state = get$5(it)).type !== TYPE) {
605 throw TypeError$j('Incompatible receiver, ' + TYPE + ' required');
610 if (NATIVE_WEAK_MAP || shared$2.state) {
611 var store$1 = shared$2.state || (shared$2.state = new WeakMap());
612 var wmget = uncurryThis$R(store$1.get);
613 var wmhas = uncurryThis$R(store$1.has);
614 var wmset = uncurryThis$R(store$1.set);
615 set$4 = function (it, metadata) {
616 if (wmhas(store$1, it)) throw new TypeError$j(OBJECT_ALREADY_INITIALIZED);
617 metadata.facade = it;
618 wmset(store$1, it, metadata);
621 get$5 = function (it) {
622 return wmget(store$1, it) || {};
624 has = function (it) {
625 return wmhas(store$1, it);
628 var STATE = sharedKey$3('state');
629 hiddenKeys$5[STATE] = true;
630 set$4 = function (it, metadata) {
631 if (hasOwn$j(it, STATE)) throw new TypeError$j(OBJECT_ALREADY_INITIALIZED);
632 metadata.facade = it;
633 createNonEnumerableProperty$a(it, STATE, metadata);
636 get$5 = function (it) {
637 return hasOwn$j(it, STATE) ? it[STATE] : {};
639 has = function (it) {
640 return hasOwn$j(it, STATE);
644 var internalState = {
652 var DESCRIPTORS$k = descriptors;
653 var hasOwn$i = hasOwnProperty_1;
655 var FunctionPrototype$2 = Function.prototype;
656 // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
657 var getDescriptor = DESCRIPTORS$k && Object.getOwnPropertyDescriptor;
659 var EXISTS = hasOwn$i(FunctionPrototype$2, 'name');
660 // additional protection from minified / mangled / dropped function names
661 var PROPER = EXISTS && (function something() { /* empty */ }).name === 'something';
662 var CONFIGURABLE = EXISTS && (!DESCRIPTORS$k || (DESCRIPTORS$k && getDescriptor(FunctionPrototype$2, 'name').configurable));
667 CONFIGURABLE: CONFIGURABLE
670 var global$15 = global$1o;
671 var isCallable$j = isCallable$r;
672 var hasOwn$h = hasOwnProperty_1;
673 var createNonEnumerableProperty$9 = createNonEnumerableProperty$b;
674 var setGlobal$1 = setGlobal$3;
675 var inspectSource$2 = inspectSource$4;
676 var InternalStateModule$9 = internalState;
677 var CONFIGURABLE_FUNCTION_NAME$2 = functionName.CONFIGURABLE;
679 var getInternalState$7 = InternalStateModule$9.get;
680 var enforceInternalState$1 = InternalStateModule$9.enforce;
681 var TEMPLATE = String(String).split('String');
683 (redefine$h.exports = function (O, key, value, options) {
684 var unsafe = options ? !!options.unsafe : false;
685 var simple = options ? !!options.enumerable : false;
686 var noTargetGet = options ? !!options.noTargetGet : false;
687 var name = options && options.name !== undefined ? options.name : key;
689 if (isCallable$j(value)) {
690 if (String(name).slice(0, 7) === 'Symbol(') {
691 name = '[' + String(name).replace(/^Symbol\(([^)]*)\)/, '$1') + ']';
693 if (!hasOwn$h(value, 'name') || (CONFIGURABLE_FUNCTION_NAME$2 && value.name !== name)) {
694 createNonEnumerableProperty$9(value, 'name', name);
696 state = enforceInternalState$1(value);
698 state.source = TEMPLATE.join(typeof name == 'string' ? name : '');
701 if (O === global$15) {
702 if (simple) O[key] = value;
703 else setGlobal$1(key, value);
705 } else if (!unsafe) {
707 } else if (!noTargetGet && O[key]) {
710 if (simple) O[key] = value;
711 else createNonEnumerableProperty$9(O, key, value);
712 // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
713 })(Function.prototype, 'toString', function toString() {
714 return isCallable$j(this) && getInternalState$7(this).source || inspectSource$2(this);
717 var objectGetOwnPropertyNames = {};
719 var ceil$1 = Math.ceil;
720 var floor$8 = Math.floor;
722 // `ToIntegerOrInfinity` abstract operation
723 // https://tc39.es/ecma262/#sec-tointegerorinfinity
724 var toIntegerOrInfinity$b = function (argument) {
725 var number = +argument;
726 // eslint-disable-next-line no-self-compare -- safe
727 return number !== number || number === 0 ? 0 : (number > 0 ? floor$8 : ceil$1)(number);
730 var toIntegerOrInfinity$a = toIntegerOrInfinity$b;
732 var max$5 = Math.max;
733 var min$9 = Math.min;
735 // Helper for a popular repeating case of the spec:
736 // Let integer be ? ToInteger(index).
737 // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
738 var toAbsoluteIndex$9 = function (index, length) {
739 var integer = toIntegerOrInfinity$a(index);
740 return integer < 0 ? max$5(integer + length, 0) : min$9(integer, length);
743 var toIntegerOrInfinity$9 = toIntegerOrInfinity$b;
745 var min$8 = Math.min;
747 // `ToLength` abstract operation
748 // https://tc39.es/ecma262/#sec-tolength
749 var toLength$c = function (argument) {
750 return argument > 0 ? min$8(toIntegerOrInfinity$9(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
753 var toLength$b = toLength$c;
755 // `LengthOfArrayLike` abstract operation
756 // https://tc39.es/ecma262/#sec-lengthofarraylike
757 var lengthOfArrayLike$i = function (obj) {
758 return toLength$b(obj.length);
761 var toIndexedObject$b = toIndexedObject$d;
762 var toAbsoluteIndex$8 = toAbsoluteIndex$9;
763 var lengthOfArrayLike$h = lengthOfArrayLike$i;
765 // `Array.prototype.{ indexOf, includes }` methods implementation
766 var createMethod$6 = function (IS_INCLUDES) {
767 return function ($this, el, fromIndex) {
768 var O = toIndexedObject$b($this);
769 var length = lengthOfArrayLike$h(O);
770 var index = toAbsoluteIndex$8(fromIndex, length);
772 // Array#includes uses SameValueZero equality algorithm
773 // eslint-disable-next-line no-self-compare -- NaN check
774 if (IS_INCLUDES && el != el) while (length > index) {
776 // eslint-disable-next-line no-self-compare -- NaN check
777 if (value != value) return true;
778 // Array#indexOf ignores holes, Array#includes - not
779 } else for (;length > index; index++) {
780 if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
781 } return !IS_INCLUDES && -1;
785 var arrayIncludes = {
786 // `Array.prototype.includes` method
787 // https://tc39.es/ecma262/#sec-array.prototype.includes
788 includes: createMethod$6(true),
789 // `Array.prototype.indexOf` method
790 // https://tc39.es/ecma262/#sec-array.prototype.indexof
791 indexOf: createMethod$6(false)
794 var uncurryThis$Q = functionUncurryThis;
795 var hasOwn$g = hasOwnProperty_1;
796 var toIndexedObject$a = toIndexedObject$d;
797 var indexOf$1 = arrayIncludes.indexOf;
798 var hiddenKeys$4 = hiddenKeys$6;
800 var push$a = uncurryThis$Q([].push);
802 var objectKeysInternal = function (object, names) {
803 var O = toIndexedObject$a(object);
807 for (key in O) !hasOwn$g(hiddenKeys$4, key) && hasOwn$g(O, key) && push$a(result, key);
808 // Don't enum bug & hidden keys
809 while (names.length > i) if (hasOwn$g(O, key = names[i++])) {
810 ~indexOf$1(result, key) || push$a(result, key);
815 // IE8- don't enum bug keys
816 var enumBugKeys$3 = [
820 'propertyIsEnumerable',
826 var internalObjectKeys$1 = objectKeysInternal;
827 var enumBugKeys$2 = enumBugKeys$3;
829 var hiddenKeys$3 = enumBugKeys$2.concat('length', 'prototype');
831 // `Object.getOwnPropertyNames` method
832 // https://tc39.es/ecma262/#sec-object.getownpropertynames
833 // eslint-disable-next-line es/no-object-getownpropertynames -- safe
834 objectGetOwnPropertyNames.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
835 return internalObjectKeys$1(O, hiddenKeys$3);
838 var objectGetOwnPropertySymbols = {};
840 // eslint-disable-next-line es/no-object-getownpropertysymbols -- safe
841 objectGetOwnPropertySymbols.f = Object.getOwnPropertySymbols;
843 var getBuiltIn$8 = getBuiltIn$b;
844 var uncurryThis$P = functionUncurryThis;
845 var getOwnPropertyNamesModule$2 = objectGetOwnPropertyNames;
846 var getOwnPropertySymbolsModule$2 = objectGetOwnPropertySymbols;
847 var anObject$l = anObject$n;
849 var concat$3 = uncurryThis$P([].concat);
851 // all object keys, includes non-enumerable and symbols
852 var ownKeys$1 = getBuiltIn$8('Reflect', 'ownKeys') || function ownKeys(it) {
853 var keys = getOwnPropertyNamesModule$2.f(anObject$l(it));
854 var getOwnPropertySymbols = getOwnPropertySymbolsModule$2.f;
855 return getOwnPropertySymbols ? concat$3(keys, getOwnPropertySymbols(it)) : keys;
858 var hasOwn$f = hasOwnProperty_1;
859 var ownKeys = ownKeys$1;
860 var getOwnPropertyDescriptorModule$3 = objectGetOwnPropertyDescriptor;
861 var definePropertyModule$6 = objectDefineProperty;
863 var copyConstructorProperties$2 = function (target, source, exceptions) {
864 var keys = ownKeys(source);
865 var defineProperty = definePropertyModule$6.f;
866 var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule$3.f;
867 for (var i = 0; i < keys.length; i++) {
869 if (!hasOwn$f(target, key) && !(exceptions && hasOwn$f(exceptions, key))) {
870 defineProperty(target, key, getOwnPropertyDescriptor(source, key));
875 var fails$O = fails$V;
876 var isCallable$i = isCallable$r;
878 var replacement = /#|\.prototype\./;
880 var isForced$5 = function (feature, detection) {
881 var value = data[normalize$1(feature)];
882 return value == POLYFILL ? true
883 : value == NATIVE ? false
884 : isCallable$i(detection) ? fails$O(detection)
888 var normalize$1 = isForced$5.normalize = function (string) {
889 return String(string).replace(replacement, '.').toLowerCase();
892 var data = isForced$5.data = {};
893 var NATIVE = isForced$5.NATIVE = 'N';
894 var POLYFILL = isForced$5.POLYFILL = 'P';
896 var isForced_1 = isForced$5;
898 var global$14 = global$1o;
899 var getOwnPropertyDescriptor$4 = objectGetOwnPropertyDescriptor.f;
900 var createNonEnumerableProperty$8 = createNonEnumerableProperty$b;
901 var redefine$g = redefine$h.exports;
902 var setGlobal = setGlobal$3;
903 var copyConstructorProperties$1 = copyConstructorProperties$2;
904 var isForced$4 = isForced_1;
907 options.target - name of the target object
908 options.global - target is the global object
909 options.stat - export as static methods of target
910 options.proto - export as prototype methods of target
911 options.real - real prototype method for the `pure` version
912 options.forced - export even if the native feature is available
913 options.bind - bind methods to the target, required for the `pure` version
914 options.wrap - wrap constructors to preventing global pollution, required for the `pure` version
915 options.unsafe - use the simple assignment of property instead of delete + defineProperty
916 options.sham - add a flag to not completely full polyfills
917 options.enumerable - export as enumerable property
918 options.noTargetGet - prevent calling a getter on target
919 options.name - the .name of the function if it does not match the key
921 var _export = function (options, source) {
922 var TARGET = options.target;
923 var GLOBAL = options.global;
924 var STATIC = options.stat;
925 var FORCED, target, key, targetProperty, sourceProperty, descriptor;
929 target = global$14[TARGET] || setGlobal(TARGET, {});
931 target = (global$14[TARGET] || {}).prototype;
933 if (target) for (key in source) {
934 sourceProperty = source[key];
935 if (options.noTargetGet) {
936 descriptor = getOwnPropertyDescriptor$4(target, key);
937 targetProperty = descriptor && descriptor.value;
938 } else targetProperty = target[key];
939 FORCED = isForced$4(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
940 // contained in target
941 if (!FORCED && targetProperty !== undefined) {
942 if (typeof sourceProperty == typeof targetProperty) continue;
943 copyConstructorProperties$1(sourceProperty, targetProperty);
945 // add a flag to not completely full polyfills
946 if (options.sham || (targetProperty && targetProperty.sham)) {
947 createNonEnumerableProperty$8(sourceProperty, 'sham', true);
950 redefine$g(target, key, sourceProperty, options);
955 var global$13 = global$1o;
956 var uncurryThis$O = functionUncurryThis;
958 var Date$1 = global$13.Date;
959 var getTime$2 = uncurryThis$O(Date$1.prototype.getTime);
962 // https://tc39.es/ecma262/#sec-date.now
963 $$1e({ target: 'Date', stat: true }, {
964 now: function now() {
965 return getTime$2(new Date$1());
969 var uncurryThis$N = functionUncurryThis;
970 var redefine$f = redefine$h.exports;
972 var DatePrototype$1 = Date.prototype;
973 var INVALID_DATE = 'Invalid Date';
974 var TO_STRING$1 = 'toString';
975 var un$DateToString = uncurryThis$N(DatePrototype$1[TO_STRING$1]);
976 var getTime$1 = uncurryThis$N(DatePrototype$1.getTime);
978 // `Date.prototype.toString` method
979 // https://tc39.es/ecma262/#sec-date.prototype.tostring
980 if (String(new Date(NaN)) != INVALID_DATE) {
981 redefine$f(DatePrototype$1, TO_STRING$1, function toString() {
982 var value = getTime$1(this);
983 // eslint-disable-next-line no-self-compare -- NaN check
984 return value === value ? un$DateToString(this) : INVALID_DATE;
988 function _typeof(obj) {
989 "@babel/helpers - typeof";
991 return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
994 return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
998 function _classCallCheck$1(instance, Constructor) {
999 if (!(instance instanceof Constructor)) {
1000 throw new TypeError("Cannot call a class as a function");
1004 function _defineProperties$1(target, props) {
1005 for (var i = 0; i < props.length; i++) {
1006 var descriptor = props[i];
1007 descriptor.enumerable = descriptor.enumerable || false;
1008 descriptor.configurable = true;
1009 if ("value" in descriptor) descriptor.writable = true;
1010 Object.defineProperty(target, descriptor.key, descriptor);
1014 function _createClass$1(Constructor, protoProps, staticProps) {
1015 if (protoProps) _defineProperties$1(Constructor.prototype, protoProps);
1016 if (staticProps) _defineProperties$1(Constructor, staticProps);
1017 Object.defineProperty(Constructor, "prototype", {
1023 function _defineProperty(obj, key, value) {
1025 Object.defineProperty(obj, key, {
1038 function _slicedToArray(arr, i) {
1039 return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
1042 function _toConsumableArray(arr) {
1043 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
1046 function _arrayWithoutHoles(arr) {
1047 if (Array.isArray(arr)) return _arrayLikeToArray(arr);
1050 function _arrayWithHoles(arr) {
1051 if (Array.isArray(arr)) return arr;
1054 function _iterableToArray(iter) {
1055 if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
1058 function _iterableToArrayLimit(arr, i) {
1059 var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
1061 if (_i == null) return;
1069 for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
1070 _arr.push(_s.value);
1072 if (i && _arr.length === i) break;
1079 if (!_n && _i["return"] != null) _i["return"]();
1088 function _unsupportedIterableToArray(o, minLen) {
1090 if (typeof o === "string") return _arrayLikeToArray(o, minLen);
1091 var n = Object.prototype.toString.call(o).slice(8, -1);
1092 if (n === "Object" && o.constructor) n = o.constructor.name;
1093 if (n === "Map" || n === "Set") return Array.from(o);
1094 if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
1097 function _arrayLikeToArray(arr, len) {
1098 if (len == null || len > arr.length) len = arr.length;
1100 for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
1105 function _nonIterableSpread() {
1106 throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1109 function _nonIterableRest() {
1110 throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1113 function _createForOfIteratorHelper(o, allowArrayLike) {
1114 var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
1117 if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
1121 var F = function () {};
1126 if (i >= o.length) return {
1141 throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1144 var normalCompletion = true,
1152 var step = it.next();
1153 normalCompletion = step.done;
1162 if (!normalCompletion && it.return != null) it.return();
1164 if (didErr) throw err;
1171 var global$12 = global$1o;
1173 // `globalThis` object
1174 // https://tc39.es/ecma262/#sec-globalthis
1175 $$1d({ global: true }, {
1176 globalThis: global$12
1179 var global$11 = global$1o;
1181 var path$1 = global$11;
1183 var wellKnownSymbolWrapped = {};
1185 var wellKnownSymbol$r = wellKnownSymbol$t;
1187 wellKnownSymbolWrapped.f = wellKnownSymbol$r;
1190 var hasOwn$e = hasOwnProperty_1;
1191 var wrappedWellKnownSymbolModule$1 = wellKnownSymbolWrapped;
1192 var defineProperty$c = objectDefineProperty.f;
1194 var defineWellKnownSymbol$4 = function (NAME) {
1195 var Symbol = path.Symbol || (path.Symbol = {});
1196 if (!hasOwn$e(Symbol, NAME)) defineProperty$c(Symbol, NAME, {
1197 value: wrappedWellKnownSymbolModule$1.f(NAME)
1201 var defineWellKnownSymbol$3 = defineWellKnownSymbol$4;
1203 // `Symbol.iterator` well-known symbol
1204 // https://tc39.es/ecma262/#sec-symbol.iterator
1205 defineWellKnownSymbol$3('iterator');
1207 var objectDefineProperties = {};
1209 var internalObjectKeys = objectKeysInternal;
1210 var enumBugKeys$1 = enumBugKeys$3;
1212 // `Object.keys` method
1213 // https://tc39.es/ecma262/#sec-object.keys
1214 // eslint-disable-next-line es/no-object-keys -- safe
1215 var objectKeys$4 = Object.keys || function keys(O) {
1216 return internalObjectKeys(O, enumBugKeys$1);
1219 var DESCRIPTORS$j = descriptors;
1220 var V8_PROTOTYPE_DEFINE_BUG = v8PrototypeDefineBug;
1221 var definePropertyModule$5 = objectDefineProperty;
1222 var anObject$k = anObject$n;
1223 var toIndexedObject$9 = toIndexedObject$d;
1224 var objectKeys$3 = objectKeys$4;
1226 // `Object.defineProperties` method
1227 // https://tc39.es/ecma262/#sec-object.defineproperties
1228 // eslint-disable-next-line es/no-object-defineproperties -- safe
1229 objectDefineProperties.f = DESCRIPTORS$j && !V8_PROTOTYPE_DEFINE_BUG ? Object.defineProperties : function defineProperties(O, Properties) {
1231 var props = toIndexedObject$9(Properties);
1232 var keys = objectKeys$3(Properties);
1233 var length = keys.length;
1236 while (length > index) definePropertyModule$5.f(O, key = keys[index++], props[key]);
1240 var getBuiltIn$7 = getBuiltIn$b;
1242 var html$2 = getBuiltIn$7('document', 'documentElement');
1244 /* global ActiveXObject -- old IE, WSH */
1246 var anObject$j = anObject$n;
1247 var definePropertiesModule$1 = objectDefineProperties;
1248 var enumBugKeys = enumBugKeys$3;
1249 var hiddenKeys$2 = hiddenKeys$6;
1250 var html$1 = html$2;
1251 var documentCreateElement$1 = documentCreateElement$2;
1252 var sharedKey$2 = sharedKey$4;
1256 var PROTOTYPE$2 = 'prototype';
1257 var SCRIPT = 'script';
1258 var IE_PROTO$1 = sharedKey$2('IE_PROTO');
1260 var EmptyConstructor = function () { /* empty */ };
1262 var scriptTag = function (content) {
1263 return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT;
1266 // Create object with fake `null` prototype: use ActiveX Object with cleared prototype
1267 var NullProtoObjectViaActiveX = function (activeXDocument) {
1268 activeXDocument.write(scriptTag(''));
1269 activeXDocument.close();
1270 var temp = activeXDocument.parentWindow.Object;
1271 activeXDocument = null; // avoid memory leak
1275 // Create object with fake `null` prototype: use iframe Object with cleared prototype
1276 var NullProtoObjectViaIFrame = function () {
1277 // Thrash, waste and sodomy: IE GC bug
1278 var iframe = documentCreateElement$1('iframe');
1279 var JS = 'java' + SCRIPT + ':';
1281 iframe.style.display = 'none';
1282 html$1.appendChild(iframe);
1283 // https://github.com/zloirock/core-js/issues/475
1284 iframe.src = String(JS);
1285 iframeDocument = iframe.contentWindow.document;
1286 iframeDocument.open();
1287 iframeDocument.write(scriptTag('document.F=Object'));
1288 iframeDocument.close();
1289 return iframeDocument.F;
1292 // Check for document.domain and active x support
1293 // No need to use active x approach when document.domain is not set
1294 // see https://github.com/es-shims/es5-shim/issues/150
1295 // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346
1297 var activeXDocument;
1298 var NullProtoObject = function () {
1300 activeXDocument = new ActiveXObject('htmlfile');
1301 } catch (error) { /* ignore */ }
1302 NullProtoObject = typeof document != 'undefined'
1303 ? document.domain && activeXDocument
1304 ? NullProtoObjectViaActiveX(activeXDocument) // old IE
1305 : NullProtoObjectViaIFrame()
1306 : NullProtoObjectViaActiveX(activeXDocument); // WSH
1307 var length = enumBugKeys.length;
1308 while (length--) delete NullProtoObject[PROTOTYPE$2][enumBugKeys[length]];
1309 return NullProtoObject();
1312 hiddenKeys$2[IE_PROTO$1] = true;
1314 // `Object.create` method
1315 // https://tc39.es/ecma262/#sec-object.create
1316 var objectCreate = Object.create || function create(O, Properties) {
1319 EmptyConstructor[PROTOTYPE$2] = anObject$j(O);
1320 result = new EmptyConstructor();
1321 EmptyConstructor[PROTOTYPE$2] = null;
1322 // add "__proto__" for Object.getPrototypeOf polyfill
1323 result[IE_PROTO$1] = O;
1324 } else result = NullProtoObject();
1325 return Properties === undefined ? result : definePropertiesModule$1.f(result, Properties);
1328 var wellKnownSymbol$q = wellKnownSymbol$t;
1329 var create$a = objectCreate;
1330 var definePropertyModule$4 = objectDefineProperty;
1332 var UNSCOPABLES = wellKnownSymbol$q('unscopables');
1333 var ArrayPrototype$1 = Array.prototype;
1335 // Array.prototype[@@unscopables]
1336 // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
1337 if (ArrayPrototype$1[UNSCOPABLES] == undefined) {
1338 definePropertyModule$4.f(ArrayPrototype$1, UNSCOPABLES, {
1340 value: create$a(null)
1344 // add a key to Array.prototype[@@unscopables]
1345 var addToUnscopables$6 = function (key) {
1346 ArrayPrototype$1[UNSCOPABLES][key] = true;
1351 var fails$N = fails$V;
1353 var correctPrototypeGetter = !fails$N(function () {
1354 function F() { /* empty */ }
1355 F.prototype.constructor = null;
1356 // eslint-disable-next-line es/no-object-getprototypeof -- required for testing
1357 return Object.getPrototypeOf(new F()) !== F.prototype;
1360 var global$10 = global$1o;
1361 var hasOwn$d = hasOwnProperty_1;
1362 var isCallable$h = isCallable$r;
1363 var toObject$g = toObject$i;
1364 var sharedKey$1 = sharedKey$4;
1365 var CORRECT_PROTOTYPE_GETTER$1 = correctPrototypeGetter;
1367 var IE_PROTO = sharedKey$1('IE_PROTO');
1368 var Object$2 = global$10.Object;
1369 var ObjectPrototype$4 = Object$2.prototype;
1371 // `Object.getPrototypeOf` method
1372 // https://tc39.es/ecma262/#sec-object.getprototypeof
1373 var objectGetPrototypeOf = CORRECT_PROTOTYPE_GETTER$1 ? Object$2.getPrototypeOf : function (O) {
1374 var object = toObject$g(O);
1375 if (hasOwn$d(object, IE_PROTO)) return object[IE_PROTO];
1376 var constructor = object.constructor;
1377 if (isCallable$h(constructor) && object instanceof constructor) {
1378 return constructor.prototype;
1379 } return object instanceof Object$2 ? ObjectPrototype$4 : null;
1382 var fails$M = fails$V;
1383 var isCallable$g = isCallable$r;
1384 var getPrototypeOf$4 = objectGetPrototypeOf;
1385 var redefine$e = redefine$h.exports;
1386 var wellKnownSymbol$p = wellKnownSymbol$t;
1388 var ITERATOR$a = wellKnownSymbol$p('iterator');
1389 var BUGGY_SAFARI_ITERATORS$1 = false;
1391 // `%IteratorPrototype%` object
1392 // https://tc39.es/ecma262/#sec-%iteratorprototype%-object
1393 var IteratorPrototype$2, PrototypeOfArrayIteratorPrototype, arrayIterator;
1395 /* eslint-disable es/no-array-prototype-keys -- safe */
1397 arrayIterator = [].keys();
1398 // Safari 8 has buggy iterators w/o `next`
1399 if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS$1 = true;
1401 PrototypeOfArrayIteratorPrototype = getPrototypeOf$4(getPrototypeOf$4(arrayIterator));
1402 if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype$2 = PrototypeOfArrayIteratorPrototype;
1406 var NEW_ITERATOR_PROTOTYPE = IteratorPrototype$2 == undefined || fails$M(function () {
1408 // FF44- legacy iterators case
1409 return IteratorPrototype$2[ITERATOR$a].call(test) !== test;
1412 if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype$2 = {};
1414 // `%IteratorPrototype%[@@iterator]()` method
1415 // https://tc39.es/ecma262/#sec-%iteratorprototype%-@@iterator
1416 if (!isCallable$g(IteratorPrototype$2[ITERATOR$a])) {
1417 redefine$e(IteratorPrototype$2, ITERATOR$a, function () {
1422 var iteratorsCore = {
1423 IteratorPrototype: IteratorPrototype$2,
1424 BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS$1
1427 var defineProperty$b = objectDefineProperty.f;
1428 var hasOwn$c = hasOwnProperty_1;
1429 var wellKnownSymbol$o = wellKnownSymbol$t;
1431 var TO_STRING_TAG$4 = wellKnownSymbol$o('toStringTag');
1433 var setToStringTag$a = function (target, TAG, STATIC) {
1434 if (target && !STATIC) target = target.prototype;
1435 if (target && !hasOwn$c(target, TO_STRING_TAG$4)) {
1436 defineProperty$b(target, TO_STRING_TAG$4, { configurable: true, value: TAG });
1440 var IteratorPrototype$1 = iteratorsCore.IteratorPrototype;
1441 var create$9 = objectCreate;
1442 var createPropertyDescriptor$4 = createPropertyDescriptor$7;
1443 var setToStringTag$9 = setToStringTag$a;
1444 var Iterators$4 = iterators;
1446 var returnThis$1 = function () { return this; };
1448 var createIteratorConstructor$2 = function (IteratorConstructor, NAME, next, ENUMERABLE_NEXT) {
1449 var TO_STRING_TAG = NAME + ' Iterator';
1450 IteratorConstructor.prototype = create$9(IteratorPrototype$1, { next: createPropertyDescriptor$4(+!ENUMERABLE_NEXT, next) });
1451 setToStringTag$9(IteratorConstructor, TO_STRING_TAG, false);
1452 Iterators$4[TO_STRING_TAG] = returnThis$1;
1453 return IteratorConstructor;
1456 var global$$ = global$1o;
1457 var isCallable$f = isCallable$r;
1459 var String$4 = global$$.String;
1460 var TypeError$i = global$$.TypeError;
1462 var aPossiblePrototype$1 = function (argument) {
1463 if (typeof argument == 'object' || isCallable$f(argument)) return argument;
1464 throw TypeError$i("Can't set " + String$4(argument) + ' as a prototype');
1467 /* eslint-disable no-proto -- safe */
1469 var uncurryThis$M = functionUncurryThis;
1470 var anObject$i = anObject$n;
1471 var aPossiblePrototype = aPossiblePrototype$1;
1473 // `Object.setPrototypeOf` method
1474 // https://tc39.es/ecma262/#sec-object.setprototypeof
1475 // Works with __proto__ only. Old v8 can't work with null proto objects.
1476 // eslint-disable-next-line es/no-object-setprototypeof -- safe
1477 var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () {
1478 var CORRECT_SETTER = false;
1482 // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
1483 setter = uncurryThis$M(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set);
1485 CORRECT_SETTER = test instanceof Array;
1486 } catch (error) { /* empty */ }
1487 return function setPrototypeOf(O, proto) {
1489 aPossiblePrototype(proto);
1490 if (CORRECT_SETTER) setter(O, proto);
1491 else O.__proto__ = proto;
1497 var call$l = functionCall;
1498 var FunctionName$1 = functionName;
1499 var isCallable$e = isCallable$r;
1500 var createIteratorConstructor$1 = createIteratorConstructor$2;
1501 var getPrototypeOf$3 = objectGetPrototypeOf;
1502 var setPrototypeOf$6 = objectSetPrototypeOf;
1503 var setToStringTag$8 = setToStringTag$a;
1504 var createNonEnumerableProperty$7 = createNonEnumerableProperty$b;
1505 var redefine$d = redefine$h.exports;
1506 var wellKnownSymbol$n = wellKnownSymbol$t;
1507 var Iterators$3 = iterators;
1508 var IteratorsCore = iteratorsCore;
1510 var PROPER_FUNCTION_NAME$3 = FunctionName$1.PROPER;
1511 var CONFIGURABLE_FUNCTION_NAME$1 = FunctionName$1.CONFIGURABLE;
1512 var IteratorPrototype = IteratorsCore.IteratorPrototype;
1513 var BUGGY_SAFARI_ITERATORS = IteratorsCore.BUGGY_SAFARI_ITERATORS;
1514 var ITERATOR$9 = wellKnownSymbol$n('iterator');
1516 var VALUES = 'values';
1517 var ENTRIES = 'entries';
1519 var returnThis = function () { return this; };
1521 var defineIterator$3 = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {
1522 createIteratorConstructor$1(IteratorConstructor, NAME, next);
1524 var getIterationMethod = function (KIND) {
1525 if (KIND === DEFAULT && defaultIterator) return defaultIterator;
1526 if (!BUGGY_SAFARI_ITERATORS && KIND in IterablePrototype) return IterablePrototype[KIND];
1528 case KEYS: return function keys() { return new IteratorConstructor(this, KIND); };
1529 case VALUES: return function values() { return new IteratorConstructor(this, KIND); };
1530 case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); };
1531 } return function () { return new IteratorConstructor(this); };
1534 var TO_STRING_TAG = NAME + ' Iterator';
1535 var INCORRECT_VALUES_NAME = false;
1536 var IterablePrototype = Iterable.prototype;
1537 var nativeIterator = IterablePrototype[ITERATOR$9]
1538 || IterablePrototype['@@iterator']
1539 || DEFAULT && IterablePrototype[DEFAULT];
1540 var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT);
1541 var anyNativeIterator = NAME == 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
1542 var CurrentIteratorPrototype, methods, KEY;
1545 if (anyNativeIterator) {
1546 CurrentIteratorPrototype = getPrototypeOf$3(anyNativeIterator.call(new Iterable()));
1547 if (CurrentIteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) {
1548 if (getPrototypeOf$3(CurrentIteratorPrototype) !== IteratorPrototype) {
1549 if (setPrototypeOf$6) {
1550 setPrototypeOf$6(CurrentIteratorPrototype, IteratorPrototype);
1551 } else if (!isCallable$e(CurrentIteratorPrototype[ITERATOR$9])) {
1552 redefine$d(CurrentIteratorPrototype, ITERATOR$9, returnThis);
1555 // Set @@toStringTag to native iterators
1556 setToStringTag$8(CurrentIteratorPrototype, TO_STRING_TAG, true);
1560 // fix Array.prototype.{ values, @@iterator }.name in V8 / FF
1561 if (PROPER_FUNCTION_NAME$3 && DEFAULT == VALUES && nativeIterator && nativeIterator.name !== VALUES) {
1562 if (CONFIGURABLE_FUNCTION_NAME$1) {
1563 createNonEnumerableProperty$7(IterablePrototype, 'name', VALUES);
1565 INCORRECT_VALUES_NAME = true;
1566 defaultIterator = function values() { return call$l(nativeIterator, this); };
1570 // export additional methods
1573 values: getIterationMethod(VALUES),
1574 keys: IS_SET ? defaultIterator : getIterationMethod(KEYS),
1575 entries: getIterationMethod(ENTRIES)
1577 if (FORCED) for (KEY in methods) {
1578 if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
1579 redefine$d(IterablePrototype, KEY, methods[KEY]);
1581 } else $$1c({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);
1585 if (IterablePrototype[ITERATOR$9] !== defaultIterator) {
1586 redefine$d(IterablePrototype, ITERATOR$9, defaultIterator, { name: DEFAULT });
1588 Iterators$3[NAME] = defaultIterator;
1593 var toIndexedObject$8 = toIndexedObject$d;
1594 var addToUnscopables$5 = addToUnscopables$6;
1595 var Iterators$2 = iterators;
1596 var InternalStateModule$8 = internalState;
1597 var defineProperty$a = objectDefineProperty.f;
1598 var defineIterator$2 = defineIterator$3;
1599 var DESCRIPTORS$i = descriptors;
1601 var ARRAY_ITERATOR = 'Array Iterator';
1602 var setInternalState$8 = InternalStateModule$8.set;
1603 var getInternalState$6 = InternalStateModule$8.getterFor(ARRAY_ITERATOR);
1605 // `Array.prototype.entries` method
1606 // https://tc39.es/ecma262/#sec-array.prototype.entries
1607 // `Array.prototype.keys` method
1608 // https://tc39.es/ecma262/#sec-array.prototype.keys
1609 // `Array.prototype.values` method
1610 // https://tc39.es/ecma262/#sec-array.prototype.values
1611 // `Array.prototype[@@iterator]` method
1612 // https://tc39.es/ecma262/#sec-array.prototype-@@iterator
1613 // `CreateArrayIterator` internal method
1614 // https://tc39.es/ecma262/#sec-createarrayiterator
1615 var es_array_iterator = defineIterator$2(Array, 'Array', function (iterated, kind) {
1616 setInternalState$8(this, {
1617 type: ARRAY_ITERATOR,
1618 target: toIndexedObject$8(iterated), // target
1619 index: 0, // next index
1622 // `%ArrayIteratorPrototype%.next` method
1623 // https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next
1625 var state = getInternalState$6(this);
1626 var target = state.target;
1627 var kind = state.kind;
1628 var index = state.index++;
1629 if (!target || index >= target.length) {
1630 state.target = undefined;
1631 return { value: undefined, done: true };
1633 if (kind == 'keys') return { value: index, done: false };
1634 if (kind == 'values') return { value: target[index], done: false };
1635 return { value: [index, target[index]], done: false };
1638 // argumentsList[@@iterator] is %ArrayProto_values%
1639 // https://tc39.es/ecma262/#sec-createunmappedargumentsobject
1640 // https://tc39.es/ecma262/#sec-createmappedargumentsobject
1641 var values = Iterators$2.Arguments = Iterators$2.Array;
1643 // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
1644 addToUnscopables$5('keys');
1645 addToUnscopables$5('values');
1646 addToUnscopables$5('entries');
1648 // V8 ~ Chrome 45- bug
1649 if (DESCRIPTORS$i && values.name !== 'values') try {
1650 defineProperty$a(values, 'name', { value: 'values' });
1651 } catch (error) { /* empty */ }
1653 var wellKnownSymbol$m = wellKnownSymbol$t;
1655 var TO_STRING_TAG$3 = wellKnownSymbol$m('toStringTag');
1658 test$2[TO_STRING_TAG$3] = 'z';
1660 var toStringTagSupport = String(test$2) === '[object z]';
1662 var global$_ = global$1o;
1663 var TO_STRING_TAG_SUPPORT$2 = toStringTagSupport;
1664 var isCallable$d = isCallable$r;
1665 var classofRaw = classofRaw$1;
1666 var wellKnownSymbol$l = wellKnownSymbol$t;
1668 var TO_STRING_TAG$2 = wellKnownSymbol$l('toStringTag');
1669 var Object$1 = global$_.Object;
1672 var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) == 'Arguments';
1674 // fallback for IE11 Script Access Denied error
1675 var tryGet = function (it, key) {
1678 } catch (error) { /* empty */ }
1681 // getting tag from ES6+ `Object.prototype.toString`
1682 var classof$d = TO_STRING_TAG_SUPPORT$2 ? classofRaw : function (it) {
1684 return it === undefined ? 'Undefined' : it === null ? 'Null'
1685 // @@toStringTag case
1686 : typeof (tag = tryGet(O = Object$1(it), TO_STRING_TAG$2)) == 'string' ? tag
1688 : CORRECT_ARGUMENTS ? classofRaw(O)
1689 // ES3 arguments fallback
1690 : (result = classofRaw(O)) == 'Object' && isCallable$d(O.callee) ? 'Arguments' : result;
1693 var TO_STRING_TAG_SUPPORT$1 = toStringTagSupport;
1694 var classof$c = classof$d;
1696 // `Object.prototype.toString` method implementation
1697 // https://tc39.es/ecma262/#sec-object.prototype.tostring
1698 var objectToString$1 = TO_STRING_TAG_SUPPORT$1 ? {}.toString : function toString() {
1699 return '[object ' + classof$c(this) + ']';
1702 var TO_STRING_TAG_SUPPORT = toStringTagSupport;
1703 var redefine$c = redefine$h.exports;
1704 var toString$l = objectToString$1;
1706 // `Object.prototype.toString` method
1707 // https://tc39.es/ecma262/#sec-object.prototype.tostring
1708 if (!TO_STRING_TAG_SUPPORT) {
1709 redefine$c(Object.prototype, 'toString', toString$l, { unsafe: true });
1712 var global$Z = global$1o;
1713 var classof$b = classof$d;
1715 var String$3 = global$Z.String;
1717 var toString$k = function (argument) {
1718 if (classof$b(argument) === 'Symbol') throw TypeError('Cannot convert a Symbol value to a string');
1719 return String$3(argument);
1722 var uncurryThis$L = functionUncurryThis;
1723 var toIntegerOrInfinity$8 = toIntegerOrInfinity$b;
1724 var toString$j = toString$k;
1725 var requireObjectCoercible$b = requireObjectCoercible$e;
1727 var charAt$8 = uncurryThis$L(''.charAt);
1728 var charCodeAt$2 = uncurryThis$L(''.charCodeAt);
1729 var stringSlice$b = uncurryThis$L(''.slice);
1731 var createMethod$5 = function (CONVERT_TO_STRING) {
1732 return function ($this, pos) {
1733 var S = toString$j(requireObjectCoercible$b($this));
1734 var position = toIntegerOrInfinity$8(pos);
1735 var size = S.length;
1737 if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
1738 first = charCodeAt$2(S, position);
1739 return first < 0xD800 || first > 0xDBFF || position + 1 === size
1740 || (second = charCodeAt$2(S, position + 1)) < 0xDC00 || second > 0xDFFF
1742 ? charAt$8(S, position)
1745 ? stringSlice$b(S, position, position + 2)
1746 : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
1750 var stringMultibyte = {
1751 // `String.prototype.codePointAt` method
1752 // https://tc39.es/ecma262/#sec-string.prototype.codepointat
1753 codeAt: createMethod$5(false),
1754 // `String.prototype.at` method
1755 // https://github.com/mathiasbynens/String.prototype.at
1756 charAt: createMethod$5(true)
1759 var charAt$7 = stringMultibyte.charAt;
1760 var toString$i = toString$k;
1761 var InternalStateModule$7 = internalState;
1762 var defineIterator$1 = defineIterator$3;
1764 var STRING_ITERATOR = 'String Iterator';
1765 var setInternalState$7 = InternalStateModule$7.set;
1766 var getInternalState$5 = InternalStateModule$7.getterFor(STRING_ITERATOR);
1768 // `String.prototype[@@iterator]` method
1769 // https://tc39.es/ecma262/#sec-string.prototype-@@iterator
1770 defineIterator$1(String, 'String', function (iterated) {
1771 setInternalState$7(this, {
1772 type: STRING_ITERATOR,
1773 string: toString$i(iterated),
1776 // `%StringIteratorPrototype%.next` method
1777 // https://tc39.es/ecma262/#sec-%stringiteratorprototype%.next
1778 }, function next() {
1779 var state = getInternalState$5(this);
1780 var string = state.string;
1781 var index = state.index;
1783 if (index >= string.length) return { value: undefined, done: true };
1784 point = charAt$7(string, index);
1785 state.index += point.length;
1786 return { value: point, done: false };
1789 // iterable DOM collections
1790 // flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods
1791 var domIterables = {
1793 CSSStyleDeclaration: 0,
1799 DataTransferItemList: 0,
1801 HTMLAllCollection: 0,
1804 HTMLSelectElement: 0,
1809 PaintRequestList: 0,
1817 SVGTransformList: 0,
1818 SourceBufferList: 0,
1820 TextTrackCueList: 0,
1825 // in old WebKit versions, `element.classList` is not an instance of global `DOMTokenList`
1826 var documentCreateElement = documentCreateElement$2;
1828 var classList$1 = documentCreateElement('span').classList;
1829 var DOMTokenListPrototype$2 = classList$1 && classList$1.constructor && classList$1.constructor.prototype;
1831 var domTokenListPrototype = DOMTokenListPrototype$2 === Object.prototype ? undefined : DOMTokenListPrototype$2;
1833 var global$Y = global$1o;
1834 var DOMIterables$1 = domIterables;
1835 var DOMTokenListPrototype$1 = domTokenListPrototype;
1836 var ArrayIteratorMethods = es_array_iterator;
1837 var createNonEnumerableProperty$6 = createNonEnumerableProperty$b;
1838 var wellKnownSymbol$k = wellKnownSymbol$t;
1840 var ITERATOR$8 = wellKnownSymbol$k('iterator');
1841 var TO_STRING_TAG$1 = wellKnownSymbol$k('toStringTag');
1842 var ArrayValues = ArrayIteratorMethods.values;
1844 var handlePrototype$1 = function (CollectionPrototype, COLLECTION_NAME) {
1845 if (CollectionPrototype) {
1846 // some Chrome versions have non-configurable methods on DOMTokenList
1847 if (CollectionPrototype[ITERATOR$8] !== ArrayValues) try {
1848 createNonEnumerableProperty$6(CollectionPrototype, ITERATOR$8, ArrayValues);
1850 CollectionPrototype[ITERATOR$8] = ArrayValues;
1852 if (!CollectionPrototype[TO_STRING_TAG$1]) {
1853 createNonEnumerableProperty$6(CollectionPrototype, TO_STRING_TAG$1, COLLECTION_NAME);
1855 if (DOMIterables$1[COLLECTION_NAME]) for (var METHOD_NAME in ArrayIteratorMethods) {
1856 // some Chrome versions have non-configurable methods on DOMTokenList
1857 if (CollectionPrototype[METHOD_NAME] !== ArrayIteratorMethods[METHOD_NAME]) try {
1858 createNonEnumerableProperty$6(CollectionPrototype, METHOD_NAME, ArrayIteratorMethods[METHOD_NAME]);
1860 CollectionPrototype[METHOD_NAME] = ArrayIteratorMethods[METHOD_NAME];
1866 for (var COLLECTION_NAME$1 in DOMIterables$1) {
1867 handlePrototype$1(global$Y[COLLECTION_NAME$1] && global$Y[COLLECTION_NAME$1].prototype, COLLECTION_NAME$1);
1870 handlePrototype$1(DOMTokenListPrototype$1, 'DOMTokenList');
1872 var NATIVE_BIND$2 = functionBindNative;
1874 var FunctionPrototype$1 = Function.prototype;
1875 var apply$9 = FunctionPrototype$1.apply;
1876 var call$k = FunctionPrototype$1.call;
1878 // eslint-disable-next-line es/no-reflect -- safe
1879 var functionApply = typeof Reflect == 'object' && Reflect.apply || (NATIVE_BIND$2 ? call$k.bind(apply$9) : function () {
1880 return call$k.apply(apply$9, arguments);
1883 var classof$a = classofRaw$1;
1885 // `IsArray` abstract operation
1886 // https://tc39.es/ecma262/#sec-isarray
1887 // eslint-disable-next-line es/no-array-isarray -- safe
1888 var isArray$8 = Array.isArray || function isArray(argument) {
1889 return classof$a(argument) == 'Array';
1892 var objectGetOwnPropertyNamesExternal = {};
1894 var toPropertyKey$2 = toPropertyKey$5;
1895 var definePropertyModule$3 = objectDefineProperty;
1896 var createPropertyDescriptor$3 = createPropertyDescriptor$7;
1898 var createProperty$5 = function (object, key, value) {
1899 var propertyKey = toPropertyKey$2(key);
1900 if (propertyKey in object) definePropertyModule$3.f(object, propertyKey, createPropertyDescriptor$3(0, value));
1901 else object[propertyKey] = value;
1904 var global$X = global$1o;
1905 var toAbsoluteIndex$7 = toAbsoluteIndex$9;
1906 var lengthOfArrayLike$g = lengthOfArrayLike$i;
1907 var createProperty$4 = createProperty$5;
1909 var Array$7 = global$X.Array;
1910 var max$4 = Math.max;
1912 var arraySliceSimple = function (O, start, end) {
1913 var length = lengthOfArrayLike$g(O);
1914 var k = toAbsoluteIndex$7(start, length);
1915 var fin = toAbsoluteIndex$7(end === undefined ? length : end, length);
1916 var result = Array$7(max$4(fin - k, 0));
1917 for (var n = 0; k < fin; k++, n++) createProperty$4(result, n, O[k]);
1922 /* eslint-disable es/no-object-getownpropertynames -- safe */
1924 var classof$9 = classofRaw$1;
1925 var toIndexedObject$7 = toIndexedObject$d;
1926 var $getOwnPropertyNames$1 = objectGetOwnPropertyNames.f;
1927 var arraySlice$c = arraySliceSimple;
1929 var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames
1930 ? Object.getOwnPropertyNames(window) : [];
1932 var getWindowNames = function (it) {
1934 return $getOwnPropertyNames$1(it);
1936 return arraySlice$c(windowNames);
1940 // fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
1941 objectGetOwnPropertyNamesExternal.f = function getOwnPropertyNames(it) {
1942 return windowNames && classof$9(it) == 'Window'
1943 ? getWindowNames(it)
1944 : $getOwnPropertyNames$1(toIndexedObject$7(it));
1947 var uncurryThis$K = functionUncurryThis;
1949 var arraySlice$b = uncurryThis$K([].slice);
1951 var uncurryThis$J = functionUncurryThis;
1952 var aCallable$8 = aCallable$a;
1953 var NATIVE_BIND$1 = functionBindNative;
1955 var bind$f = uncurryThis$J(uncurryThis$J.bind);
1957 // optional / simple context binding
1958 var functionBindContext = function (fn, that) {
1960 return that === undefined ? fn : NATIVE_BIND$1 ? bind$f(fn, that) : function (/* ...args */) {
1961 return fn.apply(that, arguments);
1965 var uncurryThis$I = functionUncurryThis;
1966 var fails$L = fails$V;
1967 var isCallable$c = isCallable$r;
1968 var classof$8 = classof$d;
1969 var getBuiltIn$6 = getBuiltIn$b;
1970 var inspectSource$1 = inspectSource$4;
1972 var noop$2 = function () { /* empty */ };
1974 var construct$1 = getBuiltIn$6('Reflect', 'construct');
1975 var constructorRegExp = /^\s*(?:class|function)\b/;
1976 var exec$6 = uncurryThis$I(constructorRegExp.exec);
1977 var INCORRECT_TO_STRING = !constructorRegExp.exec(noop$2);
1979 var isConstructorModern = function isConstructor(argument) {
1980 if (!isCallable$c(argument)) return false;
1982 construct$1(noop$2, empty$1, argument);
1989 var isConstructorLegacy = function isConstructor(argument) {
1990 if (!isCallable$c(argument)) return false;
1991 switch (classof$8(argument)) {
1992 case 'AsyncFunction':
1993 case 'GeneratorFunction':
1994 case 'AsyncGeneratorFunction': return false;
1997 // we can't check .prototype since constructors produced by .bind haven't it
1998 // `Function#toString` throws on some built-it function in some legacy engines
1999 // (for example, `DOMQuad` and similar in FF41-)
2000 return INCORRECT_TO_STRING || !!exec$6(constructorRegExp, inspectSource$1(argument));
2006 isConstructorLegacy.sham = true;
2008 // `IsConstructor` abstract operation
2009 // https://tc39.es/ecma262/#sec-isconstructor
2010 var isConstructor$4 = !construct$1 || fails$L(function () {
2012 return isConstructorModern(isConstructorModern.call)
2013 || !isConstructorModern(Object)
2014 || !isConstructorModern(function () { called = true; })
2016 }) ? isConstructorLegacy : isConstructorModern;
2018 var global$W = global$1o;
2019 var isArray$7 = isArray$8;
2020 var isConstructor$3 = isConstructor$4;
2021 var isObject$m = isObject$s;
2022 var wellKnownSymbol$j = wellKnownSymbol$t;
2024 var SPECIES$6 = wellKnownSymbol$j('species');
2025 var Array$6 = global$W.Array;
2027 // a part of `ArraySpeciesCreate` abstract operation
2028 // https://tc39.es/ecma262/#sec-arrayspeciescreate
2029 var arraySpeciesConstructor$1 = function (originalArray) {
2031 if (isArray$7(originalArray)) {
2032 C = originalArray.constructor;
2033 // cross-realm fallback
2034 if (isConstructor$3(C) && (C === Array$6 || isArray$7(C.prototype))) C = undefined;
2035 else if (isObject$m(C)) {
2037 if (C === null) C = undefined;
2039 } return C === undefined ? Array$6 : C;
2042 var arraySpeciesConstructor = arraySpeciesConstructor$1;
2044 // `ArraySpeciesCreate` abstract operation
2045 // https://tc39.es/ecma262/#sec-arrayspeciescreate
2046 var arraySpeciesCreate$4 = function (originalArray, length) {
2047 return new (arraySpeciesConstructor(originalArray))(length === 0 ? 0 : length);
2050 var bind$e = functionBindContext;
2051 var uncurryThis$H = functionUncurryThis;
2052 var IndexedObject$3 = indexedObject;
2053 var toObject$f = toObject$i;
2054 var lengthOfArrayLike$f = lengthOfArrayLike$i;
2055 var arraySpeciesCreate$3 = arraySpeciesCreate$4;
2057 var push$9 = uncurryThis$H([].push);
2059 // `Array.prototype.{ forEach, map, filter, some, every, find, findIndex, filterReject }` methods implementation
2060 var createMethod$4 = function (TYPE) {
2061 var IS_MAP = TYPE == 1;
2062 var IS_FILTER = TYPE == 2;
2063 var IS_SOME = TYPE == 3;
2064 var IS_EVERY = TYPE == 4;
2065 var IS_FIND_INDEX = TYPE == 6;
2066 var IS_FILTER_REJECT = TYPE == 7;
2067 var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
2068 return function ($this, callbackfn, that, specificCreate) {
2069 var O = toObject$f($this);
2070 var self = IndexedObject$3(O);
2071 var boundFunction = bind$e(callbackfn, that);
2072 var length = lengthOfArrayLike$f(self);
2074 var create = specificCreate || arraySpeciesCreate$3;
2075 var target = IS_MAP ? create($this, length) : IS_FILTER || IS_FILTER_REJECT ? create($this, 0) : undefined;
2077 for (;length > index; index++) if (NO_HOLES || index in self) {
2078 value = self[index];
2079 result = boundFunction(value, index, O);
2081 if (IS_MAP) target[index] = result; // map
2082 else if (result) switch (TYPE) {
2083 case 3: return true; // some
2084 case 5: return value; // find
2085 case 6: return index; // findIndex
2086 case 2: push$9(target, value); // filter
2087 } else switch (TYPE) {
2088 case 4: return false; // every
2089 case 7: push$9(target, value); // filterReject
2093 return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target;
2097 var arrayIteration = {
2098 // `Array.prototype.forEach` method
2099 // https://tc39.es/ecma262/#sec-array.prototype.foreach
2100 forEach: createMethod$4(0),
2101 // `Array.prototype.map` method
2102 // https://tc39.es/ecma262/#sec-array.prototype.map
2103 map: createMethod$4(1),
2104 // `Array.prototype.filter` method
2105 // https://tc39.es/ecma262/#sec-array.prototype.filter
2106 filter: createMethod$4(2),
2107 // `Array.prototype.some` method
2108 // https://tc39.es/ecma262/#sec-array.prototype.some
2109 some: createMethod$4(3),
2110 // `Array.prototype.every` method
2111 // https://tc39.es/ecma262/#sec-array.prototype.every
2112 every: createMethod$4(4),
2113 // `Array.prototype.find` method
2114 // https://tc39.es/ecma262/#sec-array.prototype.find
2115 find: createMethod$4(5),
2116 // `Array.prototype.findIndex` method
2117 // https://tc39.es/ecma262/#sec-array.prototype.findIndex
2118 findIndex: createMethod$4(6),
2119 // `Array.prototype.filterReject` method
2120 // https://github.com/tc39/proposal-array-filtering
2121 filterReject: createMethod$4(7)
2125 var global$V = global$1o;
2126 var getBuiltIn$5 = getBuiltIn$b;
2127 var apply$8 = functionApply;
2128 var call$j = functionCall;
2129 var uncurryThis$G = functionUncurryThis;
2130 var DESCRIPTORS$h = descriptors;
2131 var NATIVE_SYMBOL$1 = nativeSymbol;
2132 var fails$K = fails$V;
2133 var hasOwn$b = hasOwnProperty_1;
2134 var isArray$6 = isArray$8;
2135 var isCallable$b = isCallable$r;
2136 var isObject$l = isObject$s;
2137 var isPrototypeOf$8 = objectIsPrototypeOf;
2138 var isSymbol$3 = isSymbol$6;
2139 var anObject$h = anObject$n;
2140 var toObject$e = toObject$i;
2141 var toIndexedObject$6 = toIndexedObject$d;
2142 var toPropertyKey$1 = toPropertyKey$5;
2143 var $toString$3 = toString$k;
2144 var createPropertyDescriptor$2 = createPropertyDescriptor$7;
2145 var nativeObjectCreate = objectCreate;
2146 var objectKeys$2 = objectKeys$4;
2147 var getOwnPropertyNamesModule$1 = objectGetOwnPropertyNames;
2148 var getOwnPropertyNamesExternal = objectGetOwnPropertyNamesExternal;
2149 var getOwnPropertySymbolsModule$1 = objectGetOwnPropertySymbols;
2150 var getOwnPropertyDescriptorModule$2 = objectGetOwnPropertyDescriptor;
2151 var definePropertyModule$2 = objectDefineProperty;
2152 var definePropertiesModule = objectDefineProperties;
2153 var propertyIsEnumerableModule$1 = objectPropertyIsEnumerable;
2154 var arraySlice$a = arraySlice$b;
2155 var redefine$b = redefine$h.exports;
2156 var shared$1 = shared$5.exports;
2157 var sharedKey = sharedKey$4;
2158 var hiddenKeys$1 = hiddenKeys$6;
2160 var wellKnownSymbol$i = wellKnownSymbol$t;
2161 var wrappedWellKnownSymbolModule = wellKnownSymbolWrapped;
2162 var defineWellKnownSymbol$2 = defineWellKnownSymbol$4;
2163 var setToStringTag$7 = setToStringTag$a;
2164 var InternalStateModule$6 = internalState;
2165 var $forEach$2 = arrayIteration.forEach;
2167 var HIDDEN = sharedKey('hidden');
2168 var SYMBOL = 'Symbol';
2169 var PROTOTYPE$1 = 'prototype';
2170 var TO_PRIMITIVE = wellKnownSymbol$i('toPrimitive');
2172 var setInternalState$6 = InternalStateModule$6.set;
2173 var getInternalState$4 = InternalStateModule$6.getterFor(SYMBOL);
2175 var ObjectPrototype$3 = Object[PROTOTYPE$1];
2176 var $Symbol = global$V.Symbol;
2177 var SymbolPrototype$1 = $Symbol && $Symbol[PROTOTYPE$1];
2178 var TypeError$h = global$V.TypeError;
2179 var QObject = global$V.QObject;
2180 var $stringify = getBuiltIn$5('JSON', 'stringify');
2181 var nativeGetOwnPropertyDescriptor$2 = getOwnPropertyDescriptorModule$2.f;
2182 var nativeDefineProperty$1 = definePropertyModule$2.f;
2183 var nativeGetOwnPropertyNames = getOwnPropertyNamesExternal.f;
2184 var nativePropertyIsEnumerable = propertyIsEnumerableModule$1.f;
2185 var push$8 = uncurryThis$G([].push);
2187 var AllSymbols = shared$1('symbols');
2188 var ObjectPrototypeSymbols = shared$1('op-symbols');
2189 var StringToSymbolRegistry = shared$1('string-to-symbol-registry');
2190 var SymbolToStringRegistry = shared$1('symbol-to-string-registry');
2191 var WellKnownSymbolsStore = shared$1('wks');
2193 // Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173
2194 var USE_SETTER = !QObject || !QObject[PROTOTYPE$1] || !QObject[PROTOTYPE$1].findChild;
2196 // fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687
2197 var setSymbolDescriptor = DESCRIPTORS$h && fails$K(function () {
2198 return nativeObjectCreate(nativeDefineProperty$1({}, 'a', {
2199 get: function () { return nativeDefineProperty$1(this, 'a', { value: 7 }).a; }
2201 }) ? function (O, P, Attributes) {
2202 var ObjectPrototypeDescriptor = nativeGetOwnPropertyDescriptor$2(ObjectPrototype$3, P);
2203 if (ObjectPrototypeDescriptor) delete ObjectPrototype$3[P];
2204 nativeDefineProperty$1(O, P, Attributes);
2205 if (ObjectPrototypeDescriptor && O !== ObjectPrototype$3) {
2206 nativeDefineProperty$1(ObjectPrototype$3, P, ObjectPrototypeDescriptor);
2208 } : nativeDefineProperty$1;
2210 var wrap$2 = function (tag, description) {
2211 var symbol = AllSymbols[tag] = nativeObjectCreate(SymbolPrototype$1);
2212 setInternalState$6(symbol, {
2215 description: description
2217 if (!DESCRIPTORS$h) symbol.description = description;
2221 var $defineProperty = function defineProperty(O, P, Attributes) {
2222 if (O === ObjectPrototype$3) $defineProperty(ObjectPrototypeSymbols, P, Attributes);
2224 var key = toPropertyKey$1(P);
2225 anObject$h(Attributes);
2226 if (hasOwn$b(AllSymbols, key)) {
2227 if (!Attributes.enumerable) {
2228 if (!hasOwn$b(O, HIDDEN)) nativeDefineProperty$1(O, HIDDEN, createPropertyDescriptor$2(1, {}));
2229 O[HIDDEN][key] = true;
2231 if (hasOwn$b(O, HIDDEN) && O[HIDDEN][key]) O[HIDDEN][key] = false;
2232 Attributes = nativeObjectCreate(Attributes, { enumerable: createPropertyDescriptor$2(0, false) });
2233 } return setSymbolDescriptor(O, key, Attributes);
2234 } return nativeDefineProperty$1(O, key, Attributes);
2237 var $defineProperties = function defineProperties(O, Properties) {
2239 var properties = toIndexedObject$6(Properties);
2240 var keys = objectKeys$2(properties).concat($getOwnPropertySymbols(properties));
2241 $forEach$2(keys, function (key) {
2242 if (!DESCRIPTORS$h || call$j($propertyIsEnumerable$1, properties, key)) $defineProperty(O, key, properties[key]);
2247 var $create = function create(O, Properties) {
2248 return Properties === undefined ? nativeObjectCreate(O) : $defineProperties(nativeObjectCreate(O), Properties);
2251 var $propertyIsEnumerable$1 = function propertyIsEnumerable(V) {
2252 var P = toPropertyKey$1(V);
2253 var enumerable = call$j(nativePropertyIsEnumerable, this, P);
2254 if (this === ObjectPrototype$3 && hasOwn$b(AllSymbols, P) && !hasOwn$b(ObjectPrototypeSymbols, P)) return false;
2255 return enumerable || !hasOwn$b(this, P) || !hasOwn$b(AllSymbols, P) || hasOwn$b(this, HIDDEN) && this[HIDDEN][P]
2256 ? enumerable : true;
2259 var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(O, P) {
2260 var it = toIndexedObject$6(O);
2261 var key = toPropertyKey$1(P);
2262 if (it === ObjectPrototype$3 && hasOwn$b(AllSymbols, key) && !hasOwn$b(ObjectPrototypeSymbols, key)) return;
2263 var descriptor = nativeGetOwnPropertyDescriptor$2(it, key);
2264 if (descriptor && hasOwn$b(AllSymbols, key) && !(hasOwn$b(it, HIDDEN) && it[HIDDEN][key])) {
2265 descriptor.enumerable = true;
2270 var $getOwnPropertyNames = function getOwnPropertyNames(O) {
2271 var names = nativeGetOwnPropertyNames(toIndexedObject$6(O));
2273 $forEach$2(names, function (key) {
2274 if (!hasOwn$b(AllSymbols, key) && !hasOwn$b(hiddenKeys$1, key)) push$8(result, key);
2279 var $getOwnPropertySymbols = function getOwnPropertySymbols(O) {
2280 var IS_OBJECT_PROTOTYPE = O === ObjectPrototype$3;
2281 var names = nativeGetOwnPropertyNames(IS_OBJECT_PROTOTYPE ? ObjectPrototypeSymbols : toIndexedObject$6(O));
2283 $forEach$2(names, function (key) {
2284 if (hasOwn$b(AllSymbols, key) && (!IS_OBJECT_PROTOTYPE || hasOwn$b(ObjectPrototype$3, key))) {
2285 push$8(result, AllSymbols[key]);
2291 // `Symbol` constructor
2292 // https://tc39.es/ecma262/#sec-symbol-constructor
2293 if (!NATIVE_SYMBOL$1) {
2294 $Symbol = function Symbol() {
2295 if (isPrototypeOf$8(SymbolPrototype$1, this)) throw TypeError$h('Symbol is not a constructor');
2296 var description = !arguments.length || arguments[0] === undefined ? undefined : $toString$3(arguments[0]);
2297 var tag = uid$2(description);
2298 var setter = function (value) {
2299 if (this === ObjectPrototype$3) call$j(setter, ObjectPrototypeSymbols, value);
2300 if (hasOwn$b(this, HIDDEN) && hasOwn$b(this[HIDDEN], tag)) this[HIDDEN][tag] = false;
2301 setSymbolDescriptor(this, tag, createPropertyDescriptor$2(1, value));
2303 if (DESCRIPTORS$h && USE_SETTER) setSymbolDescriptor(ObjectPrototype$3, tag, { configurable: true, set: setter });
2304 return wrap$2(tag, description);
2307 SymbolPrototype$1 = $Symbol[PROTOTYPE$1];
2309 redefine$b(SymbolPrototype$1, 'toString', function toString() {
2310 return getInternalState$4(this).tag;
2313 redefine$b($Symbol, 'withoutSetter', function (description) {
2314 return wrap$2(uid$2(description), description);
2317 propertyIsEnumerableModule$1.f = $propertyIsEnumerable$1;
2318 definePropertyModule$2.f = $defineProperty;
2319 definePropertiesModule.f = $defineProperties;
2320 getOwnPropertyDescriptorModule$2.f = $getOwnPropertyDescriptor;
2321 getOwnPropertyNamesModule$1.f = getOwnPropertyNamesExternal.f = $getOwnPropertyNames;
2322 getOwnPropertySymbolsModule$1.f = $getOwnPropertySymbols;
2324 wrappedWellKnownSymbolModule.f = function (name) {
2325 return wrap$2(wellKnownSymbol$i(name), name);
2328 if (DESCRIPTORS$h) {
2329 // https://github.com/tc39/proposal-Symbol-description
2330 nativeDefineProperty$1(SymbolPrototype$1, 'description', {
2332 get: function description() {
2333 return getInternalState$4(this).description;
2337 redefine$b(ObjectPrototype$3, 'propertyIsEnumerable', $propertyIsEnumerable$1, { unsafe: true });
2342 $$1b({ global: true, wrap: true, forced: !NATIVE_SYMBOL$1, sham: !NATIVE_SYMBOL$1 }, {
2346 $forEach$2(objectKeys$2(WellKnownSymbolsStore), function (name) {
2347 defineWellKnownSymbol$2(name);
2350 $$1b({ target: SYMBOL, stat: true, forced: !NATIVE_SYMBOL$1 }, {
2351 // `Symbol.for` method
2352 // https://tc39.es/ecma262/#sec-symbol.for
2353 'for': function (key) {
2354 var string = $toString$3(key);
2355 if (hasOwn$b(StringToSymbolRegistry, string)) return StringToSymbolRegistry[string];
2356 var symbol = $Symbol(string);
2357 StringToSymbolRegistry[string] = symbol;
2358 SymbolToStringRegistry[symbol] = string;
2361 // `Symbol.keyFor` method
2362 // https://tc39.es/ecma262/#sec-symbol.keyfor
2363 keyFor: function keyFor(sym) {
2364 if (!isSymbol$3(sym)) throw TypeError$h(sym + ' is not a symbol');
2365 if (hasOwn$b(SymbolToStringRegistry, sym)) return SymbolToStringRegistry[sym];
2367 useSetter: function () { USE_SETTER = true; },
2368 useSimple: function () { USE_SETTER = false; }
2371 $$1b({ target: 'Object', stat: true, forced: !NATIVE_SYMBOL$1, sham: !DESCRIPTORS$h }, {
2372 // `Object.create` method
2373 // https://tc39.es/ecma262/#sec-object.create
2375 // `Object.defineProperty` method
2376 // https://tc39.es/ecma262/#sec-object.defineproperty
2377 defineProperty: $defineProperty,
2378 // `Object.defineProperties` method
2379 // https://tc39.es/ecma262/#sec-object.defineproperties
2380 defineProperties: $defineProperties,
2381 // `Object.getOwnPropertyDescriptor` method
2382 // https://tc39.es/ecma262/#sec-object.getownpropertydescriptors
2383 getOwnPropertyDescriptor: $getOwnPropertyDescriptor
2386 $$1b({ target: 'Object', stat: true, forced: !NATIVE_SYMBOL$1 }, {
2387 // `Object.getOwnPropertyNames` method
2388 // https://tc39.es/ecma262/#sec-object.getownpropertynames
2389 getOwnPropertyNames: $getOwnPropertyNames,
2390 // `Object.getOwnPropertySymbols` method
2391 // https://tc39.es/ecma262/#sec-object.getownpropertysymbols
2392 getOwnPropertySymbols: $getOwnPropertySymbols
2395 // Chrome 38 and 39 `Object.getOwnPropertySymbols` fails on primitives
2396 // https://bugs.chromium.org/p/v8/issues/detail?id=3443
2397 $$1b({ target: 'Object', stat: true, forced: fails$K(function () { getOwnPropertySymbolsModule$1.f(1); }) }, {
2398 getOwnPropertySymbols: function getOwnPropertySymbols(it) {
2399 return getOwnPropertySymbolsModule$1.f(toObject$e(it));
2403 // `JSON.stringify` method behavior with symbols
2404 // https://tc39.es/ecma262/#sec-json.stringify
2406 var FORCED_JSON_STRINGIFY = !NATIVE_SYMBOL$1 || fails$K(function () {
2407 var symbol = $Symbol();
2408 // MS Edge converts symbol values to JSON as {}
2409 return $stringify([symbol]) != '[null]'
2410 // WebKit converts symbol values to JSON as null
2411 || $stringify({ a: symbol }) != '{}'
2412 // V8 throws on boxed symbols
2413 || $stringify(Object(symbol)) != '{}';
2416 $$1b({ target: 'JSON', stat: true, forced: FORCED_JSON_STRINGIFY }, {
2417 // eslint-disable-next-line no-unused-vars -- required for `.length`
2418 stringify: function stringify(it, replacer, space) {
2419 var args = arraySlice$a(arguments);
2420 var $replacer = replacer;
2421 if (!isObject$l(replacer) && it === undefined || isSymbol$3(it)) return; // IE8 returns string on undefined
2422 if (!isArray$6(replacer)) replacer = function (key, value) {
2423 if (isCallable$b($replacer)) value = call$j($replacer, this, key, value);
2424 if (!isSymbol$3(value)) return value;
2427 return apply$8($stringify, null, args);
2432 // `Symbol.prototype[@@toPrimitive]` method
2433 // https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
2434 if (!SymbolPrototype$1[TO_PRIMITIVE]) {
2435 var valueOf = SymbolPrototype$1.valueOf;
2436 // eslint-disable-next-line no-unused-vars -- required for .length
2437 redefine$b(SymbolPrototype$1, TO_PRIMITIVE, function (hint) {
2438 // TODO: improve hint logic
2439 return call$j(valueOf, this);
2442 // `Symbol.prototype[@@toStringTag]` property
2443 // https://tc39.es/ecma262/#sec-symbol.prototype-@@tostringtag
2444 setToStringTag$7($Symbol, SYMBOL);
2446 hiddenKeys$1[HIDDEN] = true;
2449 var DESCRIPTORS$g = descriptors;
2450 var global$U = global$1o;
2451 var uncurryThis$F = functionUncurryThis;
2452 var hasOwn$a = hasOwnProperty_1;
2453 var isCallable$a = isCallable$r;
2454 var isPrototypeOf$7 = objectIsPrototypeOf;
2455 var toString$h = toString$k;
2456 var defineProperty$9 = objectDefineProperty.f;
2457 var copyConstructorProperties = copyConstructorProperties$2;
2459 var NativeSymbol = global$U.Symbol;
2460 var SymbolPrototype = NativeSymbol && NativeSymbol.prototype;
2462 if (DESCRIPTORS$g && isCallable$a(NativeSymbol) && (!('description' in SymbolPrototype) ||
2464 NativeSymbol().description !== undefined
2466 var EmptyStringDescriptionStore = {};
2467 // wrap Symbol constructor for correct work with undefined description
2468 var SymbolWrapper = function Symbol() {
2469 var description = arguments.length < 1 || arguments[0] === undefined ? undefined : toString$h(arguments[0]);
2470 var result = isPrototypeOf$7(SymbolPrototype, this)
2471 ? new NativeSymbol(description)
2472 // in Edge 13, String(Symbol(undefined)) === 'Symbol(undefined)'
2473 : description === undefined ? NativeSymbol() : NativeSymbol(description);
2474 if (description === '') EmptyStringDescriptionStore[result] = true;
2478 copyConstructorProperties(SymbolWrapper, NativeSymbol);
2479 SymbolWrapper.prototype = SymbolPrototype;
2480 SymbolPrototype.constructor = SymbolWrapper;
2482 var NATIVE_SYMBOL = String(NativeSymbol('test')) == 'Symbol(test)';
2483 var symbolToString$1 = uncurryThis$F(SymbolPrototype.toString);
2484 var symbolValueOf = uncurryThis$F(SymbolPrototype.valueOf);
2485 var regexp = /^Symbol\((.*)\)[^)]+$/;
2486 var replace$8 = uncurryThis$F(''.replace);
2487 var stringSlice$a = uncurryThis$F(''.slice);
2489 defineProperty$9(SymbolPrototype, 'description', {
2491 get: function description() {
2492 var symbol = symbolValueOf(this);
2493 var string = symbolToString$1(symbol);
2494 if (hasOwn$a(EmptyStringDescriptionStore, symbol)) return '';
2495 var desc = NATIVE_SYMBOL ? stringSlice$a(string, 7, -1) : replace$8(string, regexp, '$1');
2496 return desc === '' ? undefined : desc;
2500 $$1a({ global: true, forced: true }, {
2501 Symbol: SymbolWrapper
2505 // eslint-disable-next-line es/no-typed-arrays -- safe
2506 var arrayBufferNative = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined';
2508 var redefine$a = redefine$h.exports;
2510 var redefineAll$4 = function (target, src, options) {
2511 for (var key in src) redefine$a(target, key, src[key], options);
2515 var global$T = global$1o;
2516 var isPrototypeOf$6 = objectIsPrototypeOf;
2518 var TypeError$g = global$T.TypeError;
2520 var anInstance$7 = function (it, Prototype) {
2521 if (isPrototypeOf$6(Prototype, it)) return it;
2522 throw TypeError$g('Incorrect invocation');
2525 var global$S = global$1o;
2526 var toIntegerOrInfinity$7 = toIntegerOrInfinity$b;
2527 var toLength$a = toLength$c;
2529 var RangeError$b = global$S.RangeError;
2531 // `ToIndex` abstract operation
2532 // https://tc39.es/ecma262/#sec-toindex
2533 var toIndex$2 = function (it) {
2534 if (it === undefined) return 0;
2535 var number = toIntegerOrInfinity$7(it);
2536 var length = toLength$a(number);
2537 if (number !== length) throw RangeError$b('Wrong length or index');
2541 // IEEE754 conversions based on https://github.com/feross/ieee754
2542 var global$R = global$1o;
2544 var Array$5 = global$R.Array;
2545 var abs$4 = Math.abs;
2546 var pow$2 = Math.pow;
2547 var floor$7 = Math.floor;
2548 var log$2 = Math.log;
2551 var pack = function (number, mantissaLength, bytes) {
2552 var buffer = Array$5(bytes);
2553 var exponentLength = bytes * 8 - mantissaLength - 1;
2554 var eMax = (1 << exponentLength) - 1;
2555 var eBias = eMax >> 1;
2556 var rt = mantissaLength === 23 ? pow$2(2, -24) - pow$2(2, -77) : 0;
2557 var sign = number < 0 || number === 0 && 1 / number < 0 ? 1 : 0;
2559 var exponent, mantissa, c;
2560 number = abs$4(number);
2561 // eslint-disable-next-line no-self-compare -- NaN check
2562 if (number != number || number === Infinity) {
2563 // eslint-disable-next-line no-self-compare -- NaN check
2564 mantissa = number != number ? 1 : 0;
2567 exponent = floor$7(log$2(number) / LN2);
2568 c = pow$2(2, -exponent);
2569 if (number * c < 1) {
2573 if (exponent + eBias >= 1) {
2576 number += rt * pow$2(2, 1 - eBias);
2578 if (number * c >= 2) {
2582 if (exponent + eBias >= eMax) {
2585 } else if (exponent + eBias >= 1) {
2586 mantissa = (number * c - 1) * pow$2(2, mantissaLength);
2587 exponent = exponent + eBias;
2589 mantissa = number * pow$2(2, eBias - 1) * pow$2(2, mantissaLength);
2593 while (mantissaLength >= 8) {
2594 buffer[index++] = mantissa & 255;
2596 mantissaLength -= 8;
2598 exponent = exponent << mantissaLength | mantissa;
2599 exponentLength += mantissaLength;
2600 while (exponentLength > 0) {
2601 buffer[index++] = exponent & 255;
2603 exponentLength -= 8;
2605 buffer[--index] |= sign * 128;
2609 var unpack = function (buffer, mantissaLength) {
2610 var bytes = buffer.length;
2611 var exponentLength = bytes * 8 - mantissaLength - 1;
2612 var eMax = (1 << exponentLength) - 1;
2613 var eBias = eMax >> 1;
2614 var nBits = exponentLength - 7;
2615 var index = bytes - 1;
2616 var sign = buffer[index--];
2617 var exponent = sign & 127;
2621 exponent = exponent * 256 + buffer[index--];
2624 mantissa = exponent & (1 << -nBits) - 1;
2625 exponent >>= -nBits;
2626 nBits += mantissaLength;
2628 mantissa = mantissa * 256 + buffer[index--];
2631 if (exponent === 0) {
2632 exponent = 1 - eBias;
2633 } else if (exponent === eMax) {
2634 return mantissa ? NaN : sign ? -Infinity : Infinity;
2636 mantissa = mantissa + pow$2(2, mantissaLength);
2637 exponent = exponent - eBias;
2638 } return (sign ? -1 : 1) * mantissa * pow$2(2, exponent - mantissaLength);
2646 var toObject$d = toObject$i;
2647 var toAbsoluteIndex$6 = toAbsoluteIndex$9;
2648 var lengthOfArrayLike$e = lengthOfArrayLike$i;
2650 // `Array.prototype.fill` method implementation
2651 // https://tc39.es/ecma262/#sec-array.prototype.fill
2652 var arrayFill$1 = function fill(value /* , start = 0, end = @length */) {
2653 var O = toObject$d(this);
2654 var length = lengthOfArrayLike$e(O);
2655 var argumentsLength = arguments.length;
2656 var index = toAbsoluteIndex$6(argumentsLength > 1 ? arguments[1] : undefined, length);
2657 var end = argumentsLength > 2 ? arguments[2] : undefined;
2658 var endPos = end === undefined ? length : toAbsoluteIndex$6(end, length);
2659 while (endPos > index) O[index++] = value;
2663 var global$Q = global$1o;
2664 var uncurryThis$E = functionUncurryThis;
2665 var DESCRIPTORS$f = descriptors;
2666 var NATIVE_ARRAY_BUFFER$2 = arrayBufferNative;
2667 var FunctionName = functionName;
2668 var createNonEnumerableProperty$5 = createNonEnumerableProperty$b;
2669 var redefineAll$3 = redefineAll$4;
2670 var fails$J = fails$V;
2671 var anInstance$6 = anInstance$7;
2672 var toIntegerOrInfinity$6 = toIntegerOrInfinity$b;
2673 var toLength$9 = toLength$c;
2674 var toIndex$1 = toIndex$2;
2675 var IEEE754 = ieee754$2;
2676 var getPrototypeOf$2 = objectGetPrototypeOf;
2677 var setPrototypeOf$5 = objectSetPrototypeOf;
2678 var getOwnPropertyNames$4 = objectGetOwnPropertyNames.f;
2679 var defineProperty$8 = objectDefineProperty.f;
2680 var arrayFill = arrayFill$1;
2681 var arraySlice$9 = arraySliceSimple;
2682 var setToStringTag$6 = setToStringTag$a;
2683 var InternalStateModule$5 = internalState;
2685 var PROPER_FUNCTION_NAME$2 = FunctionName.PROPER;
2686 var CONFIGURABLE_FUNCTION_NAME = FunctionName.CONFIGURABLE;
2687 var getInternalState$3 = InternalStateModule$5.get;
2688 var setInternalState$5 = InternalStateModule$5.set;
2689 var ARRAY_BUFFER$1 = 'ArrayBuffer';
2690 var DATA_VIEW = 'DataView';
2691 var PROTOTYPE = 'prototype';
2692 var WRONG_LENGTH$1 = 'Wrong length';
2693 var WRONG_INDEX = 'Wrong index';
2694 var NativeArrayBuffer$1 = global$Q[ARRAY_BUFFER$1];
2695 var $ArrayBuffer = NativeArrayBuffer$1;
2696 var ArrayBufferPrototype$1 = $ArrayBuffer && $ArrayBuffer[PROTOTYPE];
2697 var $DataView = global$Q[DATA_VIEW];
2698 var DataViewPrototype$1 = $DataView && $DataView[PROTOTYPE];
2699 var ObjectPrototype$2 = Object.prototype;
2700 var Array$4 = global$Q.Array;
2701 var RangeError$a = global$Q.RangeError;
2702 var fill$1 = uncurryThis$E(arrayFill);
2703 var reverse = uncurryThis$E([].reverse);
2705 var packIEEE754 = IEEE754.pack;
2706 var unpackIEEE754 = IEEE754.unpack;
2708 var packInt8 = function (number) {
2709 return [number & 0xFF];
2712 var packInt16 = function (number) {
2713 return [number & 0xFF, number >> 8 & 0xFF];
2716 var packInt32 = function (number) {
2717 return [number & 0xFF, number >> 8 & 0xFF, number >> 16 & 0xFF, number >> 24 & 0xFF];
2720 var unpackInt32 = function (buffer) {
2721 return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
2724 var packFloat32 = function (number) {
2725 return packIEEE754(number, 23, 4);
2728 var packFloat64 = function (number) {
2729 return packIEEE754(number, 52, 8);
2732 var addGetter$1 = function (Constructor, key) {
2733 defineProperty$8(Constructor[PROTOTYPE], key, { get: function () { return getInternalState$3(this)[key]; } });
2736 var get$4 = function (view, count, index, isLittleEndian) {
2737 var intIndex = toIndex$1(index);
2738 var store = getInternalState$3(view);
2739 if (intIndex + count > store.byteLength) throw RangeError$a(WRONG_INDEX);
2740 var bytes = getInternalState$3(store.buffer).bytes;
2741 var start = intIndex + store.byteOffset;
2742 var pack = arraySlice$9(bytes, start, start + count);
2743 return isLittleEndian ? pack : reverse(pack);
2746 var set$3 = function (view, count, index, conversion, value, isLittleEndian) {
2747 var intIndex = toIndex$1(index);
2748 var store = getInternalState$3(view);
2749 if (intIndex + count > store.byteLength) throw RangeError$a(WRONG_INDEX);
2750 var bytes = getInternalState$3(store.buffer).bytes;
2751 var start = intIndex + store.byteOffset;
2752 var pack = conversion(+value);
2753 for (var i = 0; i < count; i++) bytes[start + i] = pack[isLittleEndian ? i : count - i - 1];
2756 if (!NATIVE_ARRAY_BUFFER$2) {
2757 $ArrayBuffer = function ArrayBuffer(length) {
2758 anInstance$6(this, ArrayBufferPrototype$1);
2759 var byteLength = toIndex$1(length);
2760 setInternalState$5(this, {
2761 bytes: fill$1(Array$4(byteLength), 0),
2762 byteLength: byteLength
2764 if (!DESCRIPTORS$f) this.byteLength = byteLength;
2767 ArrayBufferPrototype$1 = $ArrayBuffer[PROTOTYPE];
2769 $DataView = function DataView(buffer, byteOffset, byteLength) {
2770 anInstance$6(this, DataViewPrototype$1);
2771 anInstance$6(buffer, ArrayBufferPrototype$1);
2772 var bufferLength = getInternalState$3(buffer).byteLength;
2773 var offset = toIntegerOrInfinity$6(byteOffset);
2774 if (offset < 0 || offset > bufferLength) throw RangeError$a('Wrong offset');
2775 byteLength = byteLength === undefined ? bufferLength - offset : toLength$9(byteLength);
2776 if (offset + byteLength > bufferLength) throw RangeError$a(WRONG_LENGTH$1);
2777 setInternalState$5(this, {
2779 byteLength: byteLength,
2782 if (!DESCRIPTORS$f) {
2783 this.buffer = buffer;
2784 this.byteLength = byteLength;
2785 this.byteOffset = offset;
2789 DataViewPrototype$1 = $DataView[PROTOTYPE];
2791 if (DESCRIPTORS$f) {
2792 addGetter$1($ArrayBuffer, 'byteLength');
2793 addGetter$1($DataView, 'buffer');
2794 addGetter$1($DataView, 'byteLength');
2795 addGetter$1($DataView, 'byteOffset');
2798 redefineAll$3(DataViewPrototype$1, {
2799 getInt8: function getInt8(byteOffset) {
2800 return get$4(this, 1, byteOffset)[0] << 24 >> 24;
2802 getUint8: function getUint8(byteOffset) {
2803 return get$4(this, 1, byteOffset)[0];
2805 getInt16: function getInt16(byteOffset /* , littleEndian */) {
2806 var bytes = get$4(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : undefined);
2807 return (bytes[1] << 8 | bytes[0]) << 16 >> 16;
2809 getUint16: function getUint16(byteOffset /* , littleEndian */) {
2810 var bytes = get$4(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : undefined);
2811 return bytes[1] << 8 | bytes[0];
2813 getInt32: function getInt32(byteOffset /* , littleEndian */) {
2814 return unpackInt32(get$4(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined));
2816 getUint32: function getUint32(byteOffset /* , littleEndian */) {
2817 return unpackInt32(get$4(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined)) >>> 0;
2819 getFloat32: function getFloat32(byteOffset /* , littleEndian */) {
2820 return unpackIEEE754(get$4(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined), 23);
2822 getFloat64: function getFloat64(byteOffset /* , littleEndian */) {
2823 return unpackIEEE754(get$4(this, 8, byteOffset, arguments.length > 1 ? arguments[1] : undefined), 52);
2825 setInt8: function setInt8(byteOffset, value) {
2826 set$3(this, 1, byteOffset, packInt8, value);
2828 setUint8: function setUint8(byteOffset, value) {
2829 set$3(this, 1, byteOffset, packInt8, value);
2831 setInt16: function setInt16(byteOffset, value /* , littleEndian */) {
2832 set$3(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : undefined);
2834 setUint16: function setUint16(byteOffset, value /* , littleEndian */) {
2835 set$3(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : undefined);
2837 setInt32: function setInt32(byteOffset, value /* , littleEndian */) {
2838 set$3(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : undefined);
2840 setUint32: function setUint32(byteOffset, value /* , littleEndian */) {
2841 set$3(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : undefined);
2843 setFloat32: function setFloat32(byteOffset, value /* , littleEndian */) {
2844 set$3(this, 4, byteOffset, packFloat32, value, arguments.length > 2 ? arguments[2] : undefined);
2846 setFloat64: function setFloat64(byteOffset, value /* , littleEndian */) {
2847 set$3(this, 8, byteOffset, packFloat64, value, arguments.length > 2 ? arguments[2] : undefined);
2851 var INCORRECT_ARRAY_BUFFER_NAME = PROPER_FUNCTION_NAME$2 && NativeArrayBuffer$1.name !== ARRAY_BUFFER$1;
2852 /* eslint-disable no-new -- required for testing */
2853 if (!fails$J(function () {
2854 NativeArrayBuffer$1(1);
2855 }) || !fails$J(function () {
2856 new NativeArrayBuffer$1(-1);
2857 }) || fails$J(function () {
2858 new NativeArrayBuffer$1();
2859 new NativeArrayBuffer$1(1.5);
2860 new NativeArrayBuffer$1(NaN);
2861 return INCORRECT_ARRAY_BUFFER_NAME && !CONFIGURABLE_FUNCTION_NAME;
2863 /* eslint-enable no-new -- required for testing */
2864 $ArrayBuffer = function ArrayBuffer(length) {
2865 anInstance$6(this, ArrayBufferPrototype$1);
2866 return new NativeArrayBuffer$1(toIndex$1(length));
2869 $ArrayBuffer[PROTOTYPE] = ArrayBufferPrototype$1;
2871 for (var keys$2 = getOwnPropertyNames$4(NativeArrayBuffer$1), j$2 = 0, key$1; keys$2.length > j$2;) {
2872 if (!((key$1 = keys$2[j$2++]) in $ArrayBuffer)) {
2873 createNonEnumerableProperty$5($ArrayBuffer, key$1, NativeArrayBuffer$1[key$1]);
2877 ArrayBufferPrototype$1.constructor = $ArrayBuffer;
2878 } else if (INCORRECT_ARRAY_BUFFER_NAME && CONFIGURABLE_FUNCTION_NAME) {
2879 createNonEnumerableProperty$5(NativeArrayBuffer$1, 'name', ARRAY_BUFFER$1);
2882 // WebKit bug - the same parent prototype for typed arrays and data view
2883 if (setPrototypeOf$5 && getPrototypeOf$2(DataViewPrototype$1) !== ObjectPrototype$2) {
2884 setPrototypeOf$5(DataViewPrototype$1, ObjectPrototype$2);
2887 // iOS Safari 7.x bug
2888 var testView = new $DataView(new $ArrayBuffer(2));
2889 var $setInt8 = uncurryThis$E(DataViewPrototype$1.setInt8);
2890 testView.setInt8(0, 2147483648);
2891 testView.setInt8(1, 2147483649);
2892 if (testView.getInt8(0) || !testView.getInt8(1)) redefineAll$3(DataViewPrototype$1, {
2893 setInt8: function setInt8(byteOffset, value) {
2894 $setInt8(this, byteOffset, value << 24 >> 24);
2896 setUint8: function setUint8(byteOffset, value) {
2897 $setInt8(this, byteOffset, value << 24 >> 24);
2899 }, { unsafe: true });
2902 setToStringTag$6($ArrayBuffer, ARRAY_BUFFER$1);
2903 setToStringTag$6($DataView, DATA_VIEW);
2906 ArrayBuffer: $ArrayBuffer,
2910 var global$P = global$1o;
2911 var isConstructor$2 = isConstructor$4;
2912 var tryToString$3 = tryToString$5;
2914 var TypeError$f = global$P.TypeError;
2916 // `Assert: IsConstructor(argument) is true`
2917 var aConstructor$3 = function (argument) {
2918 if (isConstructor$2(argument)) return argument;
2919 throw TypeError$f(tryToString$3(argument) + ' is not a constructor');
2922 var anObject$g = anObject$n;
2923 var aConstructor$2 = aConstructor$3;
2924 var wellKnownSymbol$h = wellKnownSymbol$t;
2926 var SPECIES$5 = wellKnownSymbol$h('species');
2928 // `SpeciesConstructor` abstract operation
2929 // https://tc39.es/ecma262/#sec-speciesconstructor
2930 var speciesConstructor$5 = function (O, defaultConstructor) {
2931 var C = anObject$g(O).constructor;
2933 return C === undefined || (S = anObject$g(C)[SPECIES$5]) == undefined ? defaultConstructor : aConstructor$2(S);
2937 var uncurryThis$D = functionUncurryThis;
2938 var fails$I = fails$V;
2939 var ArrayBufferModule$2 = arrayBuffer;
2940 var anObject$f = anObject$n;
2941 var toAbsoluteIndex$5 = toAbsoluteIndex$9;
2942 var toLength$8 = toLength$c;
2943 var speciesConstructor$4 = speciesConstructor$5;
2945 var ArrayBuffer$4 = ArrayBufferModule$2.ArrayBuffer;
2946 var DataView$2 = ArrayBufferModule$2.DataView;
2947 var DataViewPrototype = DataView$2.prototype;
2948 var un$ArrayBufferSlice = uncurryThis$D(ArrayBuffer$4.prototype.slice);
2949 var getUint8 = uncurryThis$D(DataViewPrototype.getUint8);
2950 var setUint8 = uncurryThis$D(DataViewPrototype.setUint8);
2952 var INCORRECT_SLICE = fails$I(function () {
2953 return !new ArrayBuffer$4(2).slice(1, undefined).byteLength;
2956 // `ArrayBuffer.prototype.slice` method
2957 // https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice
2958 $$19({ target: 'ArrayBuffer', proto: true, unsafe: true, forced: INCORRECT_SLICE }, {
2959 slice: function slice(start, end) {
2960 if (un$ArrayBufferSlice && end === undefined) {
2961 return un$ArrayBufferSlice(anObject$f(this), start); // FF fix
2963 var length = anObject$f(this).byteLength;
2964 var first = toAbsoluteIndex$5(start, length);
2965 var fin = toAbsoluteIndex$5(end === undefined ? length : end, length);
2966 var result = new (speciesConstructor$4(this, ArrayBuffer$4))(toLength$8(fin - first));
2967 var viewSource = new DataView$2(this);
2968 var viewTarget = new DataView$2(result);
2970 while (first < fin) {
2971 setUint8(viewTarget, index++, getUint8(viewSource, first++));
2977 var ArrayBufferModule$1 = arrayBuffer;
2978 var NATIVE_ARRAY_BUFFER$1 = arrayBufferNative;
2980 // `DataView` constructor
2981 // https://tc39.es/ecma262/#sec-dataview-constructor
2982 $$18({ global: true, forced: !NATIVE_ARRAY_BUFFER$1 }, {
2983 DataView: ArrayBufferModule$1.DataView
2986 var NATIVE_ARRAY_BUFFER = arrayBufferNative;
2987 var DESCRIPTORS$e = descriptors;
2988 var global$O = global$1o;
2989 var isCallable$9 = isCallable$r;
2990 var isObject$k = isObject$s;
2991 var hasOwn$9 = hasOwnProperty_1;
2992 var classof$7 = classof$d;
2993 var tryToString$2 = tryToString$5;
2994 var createNonEnumerableProperty$4 = createNonEnumerableProperty$b;
2995 var redefine$9 = redefine$h.exports;
2996 var defineProperty$7 = objectDefineProperty.f;
2997 var isPrototypeOf$5 = objectIsPrototypeOf;
2998 var getPrototypeOf$1 = objectGetPrototypeOf;
2999 var setPrototypeOf$4 = objectSetPrototypeOf;
3000 var wellKnownSymbol$g = wellKnownSymbol$t;
3003 var Int8Array$4 = global$O.Int8Array;
3004 var Int8ArrayPrototype$1 = Int8Array$4 && Int8Array$4.prototype;
3005 var Uint8ClampedArray$1 = global$O.Uint8ClampedArray;
3006 var Uint8ClampedArrayPrototype = Uint8ClampedArray$1 && Uint8ClampedArray$1.prototype;
3007 var TypedArray$1 = Int8Array$4 && getPrototypeOf$1(Int8Array$4);
3008 var TypedArrayPrototype$2 = Int8ArrayPrototype$1 && getPrototypeOf$1(Int8ArrayPrototype$1);
3009 var ObjectPrototype$1 = Object.prototype;
3010 var TypeError$e = global$O.TypeError;
3012 var TO_STRING_TAG = wellKnownSymbol$g('toStringTag');
3013 var TYPED_ARRAY_TAG$1 = uid$1('TYPED_ARRAY_TAG');
3014 var TYPED_ARRAY_CONSTRUCTOR$2 = uid$1('TYPED_ARRAY_CONSTRUCTOR');
3015 // Fixing native typed arrays in Opera Presto crashes the browser, see #595
3016 var NATIVE_ARRAY_BUFFER_VIEWS$3 = NATIVE_ARRAY_BUFFER && !!setPrototypeOf$4 && classof$7(global$O.opera) !== 'Opera';
3017 var TYPED_ARRAY_TAG_REQUIRED = false;
3018 var NAME$1, Constructor, Prototype;
3020 var TypedArrayConstructorsList = {
3023 Uint8ClampedArray: 1,
3032 var BigIntArrayConstructorsList = {
3037 var isView = function isView(it) {
3038 if (!isObject$k(it)) return false;
3039 var klass = classof$7(it);
3040 return klass === 'DataView'
3041 || hasOwn$9(TypedArrayConstructorsList, klass)
3042 || hasOwn$9(BigIntArrayConstructorsList, klass);
3045 var isTypedArray$1 = function (it) {
3046 if (!isObject$k(it)) return false;
3047 var klass = classof$7(it);
3048 return hasOwn$9(TypedArrayConstructorsList, klass)
3049 || hasOwn$9(BigIntArrayConstructorsList, klass);
3052 var aTypedArray$m = function (it) {
3053 if (isTypedArray$1(it)) return it;
3054 throw TypeError$e('Target is not a typed array');
3057 var aTypedArrayConstructor$3 = function (C) {
3058 if (isCallable$9(C) && (!setPrototypeOf$4 || isPrototypeOf$5(TypedArray$1, C))) return C;
3059 throw TypeError$e(tryToString$2(C) + ' is not a typed array constructor');
3062 var exportTypedArrayMethod$n = function (KEY, property, forced, options) {
3063 if (!DESCRIPTORS$e) return;
3064 if (forced) for (var ARRAY in TypedArrayConstructorsList) {
3065 var TypedArrayConstructor = global$O[ARRAY];
3066 if (TypedArrayConstructor && hasOwn$9(TypedArrayConstructor.prototype, KEY)) try {
3067 delete TypedArrayConstructor.prototype[KEY];
3069 // old WebKit bug - some methods are non-configurable
3071 TypedArrayConstructor.prototype[KEY] = property;
3072 } catch (error2) { /* empty */ }
3075 if (!TypedArrayPrototype$2[KEY] || forced) {
3076 redefine$9(TypedArrayPrototype$2, KEY, forced ? property
3077 : NATIVE_ARRAY_BUFFER_VIEWS$3 && Int8ArrayPrototype$1[KEY] || property, options);
3081 var exportTypedArrayStaticMethod$1 = function (KEY, property, forced) {
3082 var ARRAY, TypedArrayConstructor;
3083 if (!DESCRIPTORS$e) return;
3084 if (setPrototypeOf$4) {
3085 if (forced) for (ARRAY in TypedArrayConstructorsList) {
3086 TypedArrayConstructor = global$O[ARRAY];
3087 if (TypedArrayConstructor && hasOwn$9(TypedArrayConstructor, KEY)) try {
3088 delete TypedArrayConstructor[KEY];
3089 } catch (error) { /* empty */ }
3091 if (!TypedArray$1[KEY] || forced) {
3092 // V8 ~ Chrome 49-50 `%TypedArray%` methods are non-writable non-configurable
3094 return redefine$9(TypedArray$1, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS$3 && TypedArray$1[KEY] || property);
3095 } catch (error) { /* empty */ }
3098 for (ARRAY in TypedArrayConstructorsList) {
3099 TypedArrayConstructor = global$O[ARRAY];
3100 if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) {
3101 redefine$9(TypedArrayConstructor, KEY, property);
3106 for (NAME$1 in TypedArrayConstructorsList) {
3107 Constructor = global$O[NAME$1];
3108 Prototype = Constructor && Constructor.prototype;
3109 if (Prototype) createNonEnumerableProperty$4(Prototype, TYPED_ARRAY_CONSTRUCTOR$2, Constructor);
3110 else NATIVE_ARRAY_BUFFER_VIEWS$3 = false;
3113 for (NAME$1 in BigIntArrayConstructorsList) {
3114 Constructor = global$O[NAME$1];
3115 Prototype = Constructor && Constructor.prototype;
3116 if (Prototype) createNonEnumerableProperty$4(Prototype, TYPED_ARRAY_CONSTRUCTOR$2, Constructor);
3119 // WebKit bug - typed arrays constructors prototype is Object.prototype
3120 if (!NATIVE_ARRAY_BUFFER_VIEWS$3 || !isCallable$9(TypedArray$1) || TypedArray$1 === Function.prototype) {
3121 // eslint-disable-next-line no-shadow -- safe
3122 TypedArray$1 = function TypedArray() {
3123 throw TypeError$e('Incorrect invocation');
3125 if (NATIVE_ARRAY_BUFFER_VIEWS$3) for (NAME$1 in TypedArrayConstructorsList) {
3126 if (global$O[NAME$1]) setPrototypeOf$4(global$O[NAME$1], TypedArray$1);
3130 if (!NATIVE_ARRAY_BUFFER_VIEWS$3 || !TypedArrayPrototype$2 || TypedArrayPrototype$2 === ObjectPrototype$1) {
3131 TypedArrayPrototype$2 = TypedArray$1.prototype;
3132 if (NATIVE_ARRAY_BUFFER_VIEWS$3) for (NAME$1 in TypedArrayConstructorsList) {
3133 if (global$O[NAME$1]) setPrototypeOf$4(global$O[NAME$1].prototype, TypedArrayPrototype$2);
3137 // WebKit bug - one more object in Uint8ClampedArray prototype chain
3138 if (NATIVE_ARRAY_BUFFER_VIEWS$3 && getPrototypeOf$1(Uint8ClampedArrayPrototype) !== TypedArrayPrototype$2) {
3139 setPrototypeOf$4(Uint8ClampedArrayPrototype, TypedArrayPrototype$2);
3142 if (DESCRIPTORS$e && !hasOwn$9(TypedArrayPrototype$2, TO_STRING_TAG)) {
3143 TYPED_ARRAY_TAG_REQUIRED = true;
3144 defineProperty$7(TypedArrayPrototype$2, TO_STRING_TAG, { get: function () {
3145 return isObject$k(this) ? this[TYPED_ARRAY_TAG$1] : undefined;
3147 for (NAME$1 in TypedArrayConstructorsList) if (global$O[NAME$1]) {
3148 createNonEnumerableProperty$4(global$O[NAME$1], TYPED_ARRAY_TAG$1, NAME$1);
3152 var arrayBufferViewCore = {
3153 NATIVE_ARRAY_BUFFER_VIEWS: NATIVE_ARRAY_BUFFER_VIEWS$3,
3154 TYPED_ARRAY_CONSTRUCTOR: TYPED_ARRAY_CONSTRUCTOR$2,
3155 TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQUIRED && TYPED_ARRAY_TAG$1,
3156 aTypedArray: aTypedArray$m,
3157 aTypedArrayConstructor: aTypedArrayConstructor$3,
3158 exportTypedArrayMethod: exportTypedArrayMethod$n,
3159 exportTypedArrayStaticMethod: exportTypedArrayStaticMethod$1,
3161 isTypedArray: isTypedArray$1,
3162 TypedArray: TypedArray$1,
3163 TypedArrayPrototype: TypedArrayPrototype$2
3167 var ArrayBufferViewCore$o = arrayBufferViewCore;
3169 var NATIVE_ARRAY_BUFFER_VIEWS$2 = ArrayBufferViewCore$o.NATIVE_ARRAY_BUFFER_VIEWS;
3171 // `ArrayBuffer.isView` method
3172 // https://tc39.es/ecma262/#sec-arraybuffer.isview
3173 $$17({ target: 'ArrayBuffer', stat: true, forced: !NATIVE_ARRAY_BUFFER_VIEWS$2 }, {
3174 isView: ArrayBufferViewCore$o.isView
3177 var getBuiltIn$4 = getBuiltIn$b;
3178 var definePropertyModule$1 = objectDefineProperty;
3179 var wellKnownSymbol$f = wellKnownSymbol$t;
3180 var DESCRIPTORS$d = descriptors;
3182 var SPECIES$4 = wellKnownSymbol$f('species');
3184 var setSpecies$5 = function (CONSTRUCTOR_NAME) {
3185 var Constructor = getBuiltIn$4(CONSTRUCTOR_NAME);
3186 var defineProperty = definePropertyModule$1.f;
3188 if (DESCRIPTORS$d && Constructor && !Constructor[SPECIES$4]) {
3189 defineProperty(Constructor, SPECIES$4, {
3191 get: function () { return this; }
3197 var global$N = global$1o;
3198 var arrayBufferModule = arrayBuffer;
3199 var setSpecies$4 = setSpecies$5;
3201 var ARRAY_BUFFER = 'ArrayBuffer';
3202 var ArrayBuffer$3 = arrayBufferModule[ARRAY_BUFFER];
3203 var NativeArrayBuffer = global$N[ARRAY_BUFFER];
3205 // `ArrayBuffer` constructor
3206 // https://tc39.es/ecma262/#sec-arraybuffer-constructor
3207 $$16({ global: true, forced: NativeArrayBuffer !== ArrayBuffer$3 }, {
3208 ArrayBuffer: ArrayBuffer$3
3211 setSpecies$4(ARRAY_BUFFER);
3213 var fails$H = fails$V;
3215 var arrayMethodIsStrict$9 = function (METHOD_NAME, argument) {
3216 var method = [][METHOD_NAME];
3217 return !!method && fails$H(function () {
3218 // eslint-disable-next-line no-useless-call,no-throw-literal -- required for testing
3219 method.call(null, argument || function () { throw 1; }, 1);
3223 /* eslint-disable es/no-array-prototype-indexof -- required for testing */
3225 var uncurryThis$C = functionUncurryThis;
3226 var $IndexOf = arrayIncludes.indexOf;
3227 var arrayMethodIsStrict$8 = arrayMethodIsStrict$9;
3229 var un$IndexOf = uncurryThis$C([].indexOf);
3231 var NEGATIVE_ZERO$1 = !!un$IndexOf && 1 / un$IndexOf([1], 1, -0) < 0;
3232 var STRICT_METHOD$8 = arrayMethodIsStrict$8('indexOf');
3234 // `Array.prototype.indexOf` method
3235 // https://tc39.es/ecma262/#sec-array.prototype.indexof
3236 $$15({ target: 'Array', proto: true, forced: NEGATIVE_ZERO$1 || !STRICT_METHOD$8 }, {
3237 indexOf: function indexOf(searchElement /* , fromIndex = 0 */) {
3238 var fromIndex = arguments.length > 1 ? arguments[1] : undefined;
3239 return NEGATIVE_ZERO$1
3241 ? un$IndexOf(this, searchElement, fromIndex) || 0
3242 : $IndexOf(this, searchElement, fromIndex);
3246 var anObject$e = anObject$n;
3248 // `RegExp.prototype.flags` getter implementation
3249 // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
3250 var regexpFlags$1 = function () {
3251 var that = anObject$e(this);
3253 if (that.global) result += 'g';
3254 if (that.ignoreCase) result += 'i';
3255 if (that.multiline) result += 'm';
3256 if (that.dotAll) result += 's';
3257 if (that.unicode) result += 'u';
3258 if (that.sticky) result += 'y';
3262 var fails$G = fails$V;
3263 var global$M = global$1o;
3265 // babel-minify and Closure Compiler transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError
3266 var $RegExp$2 = global$M.RegExp;
3268 var UNSUPPORTED_Y$3 = fails$G(function () {
3269 var re = $RegExp$2('a', 'y');
3271 return re.exec('abcd') != null;
3275 // https://github.com/zloirock/core-js/issues/1008
3276 var MISSED_STICKY$1 = UNSUPPORTED_Y$3 || fails$G(function () {
3277 return !$RegExp$2('a', 'y').sticky;
3280 var BROKEN_CARET = UNSUPPORTED_Y$3 || fails$G(function () {
3281 // https://bugzilla.mozilla.org/show_bug.cgi?id=773687
3282 var re = $RegExp$2('^r', 'gy');
3284 return re.exec('str') != null;
3287 var regexpStickyHelpers = {
3288 BROKEN_CARET: BROKEN_CARET,
3289 MISSED_STICKY: MISSED_STICKY$1,
3290 UNSUPPORTED_Y: UNSUPPORTED_Y$3
3293 var fails$F = fails$V;
3294 var global$L = global$1o;
3296 // babel-minify and Closure Compiler transpiles RegExp('.', 's') -> /./s and it causes SyntaxError
3297 var $RegExp$1 = global$L.RegExp;
3299 var regexpUnsupportedDotAll = fails$F(function () {
3300 var re = $RegExp$1('.', 's');
3301 return !(re.dotAll && re.exec('\n') && re.flags === 's');
3304 var fails$E = fails$V;
3305 var global$K = global$1o;
3307 // babel-minify and Closure Compiler transpiles RegExp('(?<a>b)', 'g') -> /(?<a>b)/g and it causes SyntaxError
3308 var $RegExp = global$K.RegExp;
3310 var regexpUnsupportedNcg = fails$E(function () {
3311 var re = $RegExp('(?<a>b)', 'g');
3312 return re.exec('b').groups.a !== 'b' ||
3313 'b'.replace(re, '$<a>c') !== 'bc';
3316 /* eslint-disable regexp/no-empty-capturing-group, regexp/no-empty-group, regexp/no-lazy-ends -- testing */
3317 /* eslint-disable regexp/no-useless-quantifier -- testing */
3318 var call$i = functionCall;
3319 var uncurryThis$B = functionUncurryThis;
3320 var toString$g = toString$k;
3321 var regexpFlags = regexpFlags$1;
3322 var stickyHelpers$2 = regexpStickyHelpers;
3323 var shared = shared$5.exports;
3324 var create$8 = objectCreate;
3325 var getInternalState$2 = internalState.get;
3326 var UNSUPPORTED_DOT_ALL$1 = regexpUnsupportedDotAll;
3327 var UNSUPPORTED_NCG$1 = regexpUnsupportedNcg;
3329 var nativeReplace = shared('native-string-replace', String.prototype.replace);
3330 var nativeExec = RegExp.prototype.exec;
3331 var patchedExec = nativeExec;
3332 var charAt$6 = uncurryThis$B(''.charAt);
3333 var indexOf = uncurryThis$B(''.indexOf);
3334 var replace$7 = uncurryThis$B(''.replace);
3335 var stringSlice$9 = uncurryThis$B(''.slice);
3337 var UPDATES_LAST_INDEX_WRONG = (function () {
3340 call$i(nativeExec, re1, 'a');
3341 call$i(nativeExec, re2, 'a');
3342 return re1.lastIndex !== 0 || re2.lastIndex !== 0;
3345 var UNSUPPORTED_Y$2 = stickyHelpers$2.BROKEN_CARET;
3347 // nonparticipating capturing group, copied from es5-shim's String#split patch.
3348 var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;
3350 var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y$2 || UNSUPPORTED_DOT_ALL$1 || UNSUPPORTED_NCG$1;
3353 patchedExec = function exec(string) {
3355 var state = getInternalState$2(re);
3356 var str = toString$g(string);
3357 var raw = state.raw;
3358 var result, reCopy, lastIndex, match, i, object, group;
3361 raw.lastIndex = re.lastIndex;
3362 result = call$i(patchedExec, raw, str);
3363 re.lastIndex = raw.lastIndex;
3367 var groups = state.groups;
3368 var sticky = UNSUPPORTED_Y$2 && re.sticky;
3369 var flags = call$i(regexpFlags, re);
3370 var source = re.source;
3375 flags = replace$7(flags, 'y', '');
3376 if (indexOf(flags, 'g') === -1) {
3380 strCopy = stringSlice$9(str, re.lastIndex);
3381 // Support anchored sticky behavior.
3382 if (re.lastIndex > 0 && (!re.multiline || re.multiline && charAt$6(str, re.lastIndex - 1) !== '\n')) {
3383 source = '(?: ' + source + ')';
3384 strCopy = ' ' + strCopy;
3387 // ^(? + rx + ) is needed, in combination with some str slicing, to
3388 // simulate the 'y' flag.
3389 reCopy = new RegExp('^(?:' + source + ')', flags);
3392 if (NPCG_INCLUDED) {
3393 reCopy = new RegExp('^' + source + '$(?!\\s)', flags);
3395 if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex;
3397 match = call$i(nativeExec, sticky ? reCopy : re, strCopy);
3401 match.input = stringSlice$9(match.input, charsAdded);
3402 match[0] = stringSlice$9(match[0], charsAdded);
3403 match.index = re.lastIndex;
3404 re.lastIndex += match[0].length;
3405 } else re.lastIndex = 0;
3406 } else if (UPDATES_LAST_INDEX_WRONG && match) {
3407 re.lastIndex = re.global ? match.index + match[0].length : lastIndex;
3409 if (NPCG_INCLUDED && match && match.length > 1) {
3410 // Fix browsers whose `exec` methods don't consistently return `undefined`
3411 // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/
3412 call$i(nativeReplace, match[0], reCopy, function () {
3413 for (i = 1; i < arguments.length - 2; i++) {
3414 if (arguments[i] === undefined) match[i] = undefined;
3419 if (match && groups) {
3420 match.groups = object = create$8(null);
3421 for (i = 0; i < groups.length; i++) {
3423 object[group[0]] = match[group[1]];
3431 var regexpExec$3 = patchedExec;
3434 var exec$5 = regexpExec$3;
3436 // `RegExp.prototype.exec` method
3437 // https://tc39.es/ecma262/#sec-regexp.prototype.exec
3438 $$14({ target: 'RegExp', proto: true, forced: /./.exec !== exec$5 }, {
3442 var fails$D = fails$V;
3443 var wellKnownSymbol$e = wellKnownSymbol$t;
3444 var V8_VERSION$2 = engineV8Version;
3446 var SPECIES$3 = wellKnownSymbol$e('species');
3448 var arrayMethodHasSpeciesSupport$5 = function (METHOD_NAME) {
3449 // We can't use this feature detection in V8 since it causes
3450 // deoptimization and serious performance degradation
3451 // https://github.com/zloirock/core-js/issues/677
3452 return V8_VERSION$2 >= 51 || !fails$D(function () {
3454 var constructor = array.constructor = {};
3455 constructor[SPECIES$3] = function () {
3458 return array[METHOD_NAME](Boolean).foo !== 1;
3463 var $map$1 = arrayIteration.map;
3464 var arrayMethodHasSpeciesSupport$4 = arrayMethodHasSpeciesSupport$5;
3466 var HAS_SPECIES_SUPPORT$3 = arrayMethodHasSpeciesSupport$4('map');
3468 // `Array.prototype.map` method
3469 // https://tc39.es/ecma262/#sec-array.prototype.map
3470 // with adding support of @@species
3471 $$13({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$3 }, {
3472 map: function map(callbackfn /* , thisArg */) {
3473 return $map$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
3477 var $forEach$1 = arrayIteration.forEach;
3478 var arrayMethodIsStrict$7 = arrayMethodIsStrict$9;
3480 var STRICT_METHOD$7 = arrayMethodIsStrict$7('forEach');
3482 // `Array.prototype.forEach` method implementation
3483 // https://tc39.es/ecma262/#sec-array.prototype.foreach
3484 var arrayForEach = !STRICT_METHOD$7 ? function forEach(callbackfn /* , thisArg */) {
3485 return $forEach$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
3486 // eslint-disable-next-line es/no-array-prototype-foreach -- safe
3490 var forEach$3 = arrayForEach;
3492 // `Array.prototype.forEach` method
3493 // https://tc39.es/ecma262/#sec-array.prototype.foreach
3494 // eslint-disable-next-line es/no-array-prototype-foreach -- safe
3495 $$12({ target: 'Array', proto: true, forced: [].forEach != forEach$3 }, {
3499 var global$J = global$1o;
3500 var DOMIterables = domIterables;
3501 var DOMTokenListPrototype = domTokenListPrototype;
3502 var forEach$2 = arrayForEach;
3503 var createNonEnumerableProperty$3 = createNonEnumerableProperty$b;
3505 var handlePrototype = function (CollectionPrototype) {
3506 // some Chrome versions have non-configurable methods on DOMTokenList
3507 if (CollectionPrototype && CollectionPrototype.forEach !== forEach$2) try {
3508 createNonEnumerableProperty$3(CollectionPrototype, 'forEach', forEach$2);
3510 CollectionPrototype.forEach = forEach$2;
3514 for (var COLLECTION_NAME in DOMIterables) {
3515 if (DOMIterables[COLLECTION_NAME]) {
3516 handlePrototype(global$J[COLLECTION_NAME] && global$J[COLLECTION_NAME].prototype);
3520 handlePrototype(DOMTokenListPrototype);
3523 var isArray$5 = isArray$8;
3525 // `Array.isArray` method
3526 // https://tc39.es/ecma262/#sec-array.isarray
3527 $$11({ target: 'Array', stat: true }, {
3532 var fails$C = fails$V;
3533 var getOwnPropertyNames$3 = objectGetOwnPropertyNamesExternal.f;
3535 // eslint-disable-next-line es/no-object-getownpropertynames -- required for testing
3536 var FAILS_ON_PRIMITIVES$5 = fails$C(function () { return !Object.getOwnPropertyNames(1); });
3538 // `Object.getOwnPropertyNames` method
3539 // https://tc39.es/ecma262/#sec-object.getownpropertynames
3540 $$10({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$5 }, {
3541 getOwnPropertyNames: getOwnPropertyNames$3
3544 var global$I = global$1o;
3546 var nativePromiseConstructor = global$I.Promise;
3548 var wellKnownSymbol$d = wellKnownSymbol$t;
3549 var Iterators$1 = iterators;
3551 var ITERATOR$7 = wellKnownSymbol$d('iterator');
3552 var ArrayPrototype = Array.prototype;
3554 // check on default Array iterator
3555 var isArrayIteratorMethod$3 = function (it) {
3556 return it !== undefined && (Iterators$1.Array === it || ArrayPrototype[ITERATOR$7] === it);
3559 var classof$6 = classof$d;
3560 var getMethod$5 = getMethod$7;
3561 var Iterators = iterators;
3562 var wellKnownSymbol$c = wellKnownSymbol$t;
3564 var ITERATOR$6 = wellKnownSymbol$c('iterator');
3566 var getIteratorMethod$5 = function (it) {
3567 if (it != undefined) return getMethod$5(it, ITERATOR$6)
3568 || getMethod$5(it, '@@iterator')
3569 || Iterators[classof$6(it)];
3572 var global$H = global$1o;
3573 var call$h = functionCall;
3574 var aCallable$7 = aCallable$a;
3575 var anObject$d = anObject$n;
3576 var tryToString$1 = tryToString$5;
3577 var getIteratorMethod$4 = getIteratorMethod$5;
3579 var TypeError$d = global$H.TypeError;
3581 var getIterator$4 = function (argument, usingIterator) {
3582 var iteratorMethod = arguments.length < 2 ? getIteratorMethod$4(argument) : usingIterator;
3583 if (aCallable$7(iteratorMethod)) return anObject$d(call$h(iteratorMethod, argument));
3584 throw TypeError$d(tryToString$1(argument) + ' is not iterable');
3587 var call$g = functionCall;
3588 var anObject$c = anObject$n;
3589 var getMethod$4 = getMethod$7;
3591 var iteratorClose$2 = function (iterator, kind, value) {
3592 var innerResult, innerError;
3593 anObject$c(iterator);
3595 innerResult = getMethod$4(iterator, 'return');
3597 if (kind === 'throw') throw value;
3600 innerResult = call$g(innerResult, iterator);
3603 innerResult = error;
3605 if (kind === 'throw') throw value;
3606 if (innerError) throw innerResult;
3607 anObject$c(innerResult);
3611 var global$G = global$1o;
3612 var bind$d = functionBindContext;
3613 var call$f = functionCall;
3614 var anObject$b = anObject$n;
3615 var tryToString = tryToString$5;
3616 var isArrayIteratorMethod$2 = isArrayIteratorMethod$3;
3617 var lengthOfArrayLike$d = lengthOfArrayLike$i;
3618 var isPrototypeOf$4 = objectIsPrototypeOf;
3619 var getIterator$3 = getIterator$4;
3620 var getIteratorMethod$3 = getIteratorMethod$5;
3621 var iteratorClose$1 = iteratorClose$2;
3623 var TypeError$c = global$G.TypeError;
3625 var Result = function (stopped, result) {
3626 this.stopped = stopped;
3627 this.result = result;
3630 var ResultPrototype = Result.prototype;
3632 var iterate$3 = function (iterable, unboundFunction, options) {
3633 var that = options && options.that;
3634 var AS_ENTRIES = !!(options && options.AS_ENTRIES);
3635 var IS_ITERATOR = !!(options && options.IS_ITERATOR);
3636 var INTERRUPTED = !!(options && options.INTERRUPTED);
3637 var fn = bind$d(unboundFunction, that);
3638 var iterator, iterFn, index, length, result, next, step;
3640 var stop = function (condition) {
3641 if (iterator) iteratorClose$1(iterator, 'normal', condition);
3642 return new Result(true, condition);
3645 var callFn = function (value) {
3648 return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]);
3649 } return INTERRUPTED ? fn(value, stop) : fn(value);
3653 iterator = iterable;
3655 iterFn = getIteratorMethod$3(iterable);
3656 if (!iterFn) throw TypeError$c(tryToString(iterable) + ' is not iterable');
3657 // optimisation for array iterators
3658 if (isArrayIteratorMethod$2(iterFn)) {
3659 for (index = 0, length = lengthOfArrayLike$d(iterable); length > index; index++) {
3660 result = callFn(iterable[index]);
3661 if (result && isPrototypeOf$4(ResultPrototype, result)) return result;
3662 } return new Result(false);
3664 iterator = getIterator$3(iterable, iterFn);
3667 next = iterator.next;
3668 while (!(step = call$f(next, iterator)).done) {
3670 result = callFn(step.value);
3672 iteratorClose$1(iterator, 'throw', error);
3674 if (typeof result == 'object' && result && isPrototypeOf$4(ResultPrototype, result)) return result;
3675 } return new Result(false);
3678 var wellKnownSymbol$b = wellKnownSymbol$t;
3680 var ITERATOR$5 = wellKnownSymbol$b('iterator');
3681 var SAFE_CLOSING = false;
3685 var iteratorWithReturn = {
3687 return { done: !!called++ };
3689 'return': function () {
3690 SAFE_CLOSING = true;
3693 iteratorWithReturn[ITERATOR$5] = function () {
3696 // eslint-disable-next-line es/no-array-from, no-throw-literal -- required for testing
3697 Array.from(iteratorWithReturn, function () { throw 2; });
3698 } catch (error) { /* empty */ }
3700 var checkCorrectnessOfIteration$4 = function (exec, SKIP_CLOSING) {
3701 if (!SKIP_CLOSING && !SAFE_CLOSING) return false;
3702 var ITERATION_SUPPORT = false;
3705 object[ITERATOR$5] = function () {
3708 return { done: ITERATION_SUPPORT = true };
3713 } catch (error) { /* empty */ }
3714 return ITERATION_SUPPORT;
3717 var global$F = global$1o;
3719 var TypeError$b = global$F.TypeError;
3721 var validateArgumentsLength$4 = function (passed, required) {
3722 if (passed < required) throw TypeError$b('Not enough arguments');
3726 var userAgent$6 = engineUserAgent;
3728 var engineIsIos = /(?:ipad|iphone|ipod).*applewebkit/i.test(userAgent$6);
3730 var classof$5 = classofRaw$1;
3731 var global$E = global$1o;
3733 var engineIsNode = classof$5(global$E.process) == 'process';
3735 var global$D = global$1o;
3736 var apply$7 = functionApply;
3737 var bind$c = functionBindContext;
3738 var isCallable$8 = isCallable$r;
3739 var hasOwn$8 = hasOwnProperty_1;
3740 var fails$B = fails$V;
3742 var arraySlice$8 = arraySlice$b;
3743 var createElement = documentCreateElement$2;
3744 var validateArgumentsLength$3 = validateArgumentsLength$4;
3745 var IS_IOS$1 = engineIsIos;
3746 var IS_NODE$4 = engineIsNode;
3748 var set$2 = global$D.setImmediate;
3749 var clear = global$D.clearImmediate;
3750 var process$3 = global$D.process;
3751 var Dispatch$1 = global$D.Dispatch;
3752 var Function$3 = global$D.Function;
3753 var MessageChannel = global$D.MessageChannel;
3754 var String$2 = global$D.String;
3757 var ONREADYSTATECHANGE = 'onreadystatechange';
3758 var location$1, defer, channel, port;
3761 // Deno throws a ReferenceError on `location` access without `--location` flag
3762 location$1 = global$D.location;
3763 } catch (error) { /* empty */ }
3765 var run = function (id) {
3766 if (hasOwn$8(queue$1, id)) {
3767 var fn = queue$1[id];
3773 var runner = function (id) {
3774 return function () {
3779 var listener = function (event) {
3783 var post = function (id) {
3784 // old engines have not location.origin
3785 global$D.postMessage(String$2(id), location$1.protocol + '//' + location$1.host);
3788 // Node.js 0.9+ & IE10+ has setImmediate, otherwise:
3789 if (!set$2 || !clear) {
3790 set$2 = function setImmediate(handler) {
3791 validateArgumentsLength$3(arguments.length, 1);
3792 var fn = isCallable$8(handler) ? handler : Function$3(handler);
3793 var args = arraySlice$8(arguments, 1);
3794 queue$1[++counter] = function () {
3795 apply$7(fn, undefined, args);
3800 clear = function clearImmediate(id) {
3805 defer = function (id) {
3806 process$3.nextTick(runner(id));
3808 // Sphere (JS game engine) Dispatch API
3809 } else if (Dispatch$1 && Dispatch$1.now) {
3810 defer = function (id) {
3811 Dispatch$1.now(runner(id));
3813 // Browsers with MessageChannel, includes WebWorkers
3814 // except iOS - https://github.com/zloirock/core-js/issues/624
3815 } else if (MessageChannel && !IS_IOS$1) {
3816 channel = new MessageChannel();
3817 port = channel.port2;
3818 channel.port1.onmessage = listener;
3819 defer = bind$c(port.postMessage, port);
3820 // Browsers with postMessage, skip WebWorkers
3821 // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
3823 global$D.addEventListener &&
3824 isCallable$8(global$D.postMessage) &&
3825 !global$D.importScripts &&
3826 location$1 && location$1.protocol !== 'file:' &&
3830 global$D.addEventListener('message', listener, false);
3832 } else if (ONREADYSTATECHANGE in createElement('script')) {
3833 defer = function (id) {
3834 html.appendChild(createElement('script'))[ONREADYSTATECHANGE] = function () {
3835 html.removeChild(this);
3839 // Rest old browsers
3841 defer = function (id) {
3842 setTimeout(runner(id), 0);
3852 var userAgent$5 = engineUserAgent;
3853 var global$C = global$1o;
3855 var engineIsIosPebble = /ipad|iphone|ipod/i.test(userAgent$5) && global$C.Pebble !== undefined;
3857 var userAgent$4 = engineUserAgent;
3859 var engineIsWebosWebkit = /web0s(?!.*chrome)/i.test(userAgent$4);
3861 var global$B = global$1o;
3862 var bind$b = functionBindContext;
3863 var getOwnPropertyDescriptor$3 = objectGetOwnPropertyDescriptor.f;
3864 var macrotask = task$1.set;
3865 var IS_IOS = engineIsIos;
3866 var IS_IOS_PEBBLE = engineIsIosPebble;
3867 var IS_WEBOS_WEBKIT = engineIsWebosWebkit;
3868 var IS_NODE$3 = engineIsNode;
3870 var MutationObserver = global$B.MutationObserver || global$B.WebKitMutationObserver;
3871 var document$2 = global$B.document;
3872 var process$2 = global$B.process;
3873 var Promise$1 = global$B.Promise;
3874 // Node.js 11 shows ExperimentalWarning on getting `queueMicrotask`
3875 var queueMicrotaskDescriptor = getOwnPropertyDescriptor$3(global$B, 'queueMicrotask');
3876 var queueMicrotask = queueMicrotaskDescriptor && queueMicrotaskDescriptor.value;
3878 var flush, head, last, notify$1, toggle, node, promise, then;
3880 // modern engines have queueMicrotask method
3881 if (!queueMicrotask) {
3882 flush = function () {
3884 if (IS_NODE$3 && (parent = process$2.domain)) parent.exit();
3891 if (head) notify$1();
3892 else last = undefined;
3896 if (parent) parent.enter();
3899 // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339
3900 // also except WebOS Webkit https://github.com/zloirock/core-js/issues/898
3901 if (!IS_IOS && !IS_NODE$3 && !IS_WEBOS_WEBKIT && MutationObserver && document$2) {
3903 node = document$2.createTextNode('');
3904 new MutationObserver(flush).observe(node, { characterData: true });
3905 notify$1 = function () {
3906 node.data = toggle = !toggle;
3908 // environments with maybe non-completely correct, but existent Promise
3909 } else if (!IS_IOS_PEBBLE && Promise$1 && Promise$1.resolve) {
3910 // Promise.resolve without an argument throws an error in LG WebOS 2
3911 promise = Promise$1.resolve(undefined);
3912 // workaround of WebKit ~ iOS Safari 10.1 bug
3913 promise.constructor = Promise$1;
3914 then = bind$b(promise.then, promise);
3915 notify$1 = function () {
3918 // Node.js without promises
3919 } else if (IS_NODE$3) {
3920 notify$1 = function () {
3921 process$2.nextTick(flush);
3923 // for other environments - macrotask based on:
3926 // - window.postMessag
3927 // - onreadystatechange
3930 // strange IE + webpack dev server bug - use .bind(global)
3931 macrotask = bind$b(macrotask, global$B);
3932 notify$1 = function () {
3938 var microtask$1 = queueMicrotask || function (fn) {
3939 var task = { fn: fn, next: undefined };
3940 if (last) last.next = task;
3947 var newPromiseCapability$2 = {};
3949 var aCallable$6 = aCallable$a;
3951 var PromiseCapability = function (C) {
3952 var resolve, reject;
3953 this.promise = new C(function ($$resolve, $$reject) {
3954 if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');
3955 resolve = $$resolve;
3958 this.resolve = aCallable$6(resolve);
3959 this.reject = aCallable$6(reject);
3962 // `NewPromiseCapability` abstract operation
3963 // https://tc39.es/ecma262/#sec-newpromisecapability
3964 newPromiseCapability$2.f = function (C) {
3965 return new PromiseCapability(C);
3968 var anObject$a = anObject$n;
3969 var isObject$j = isObject$s;
3970 var newPromiseCapability$1 = newPromiseCapability$2;
3972 var promiseResolve$2 = function (C, x) {
3974 if (isObject$j(x) && x.constructor === C) return x;
3975 var promiseCapability = newPromiseCapability$1.f(C);
3976 var resolve = promiseCapability.resolve;
3978 return promiseCapability.promise;
3981 var global$A = global$1o;
3983 var hostReportErrors$1 = function (a, b) {
3984 var console = global$A.console;
3985 if (console && console.error) {
3986 arguments.length == 1 ? console.error(a) : console.error(a, b);
3990 var perform$1 = function (exec) {
3992 return { error: false, value: exec() };
3994 return { error: true, value: error };
3998 var Queue$1 = function () {
4003 Queue$1.prototype = {
4004 add: function (item) {
4005 var entry = { item: item, next: null };
4006 if (this.head) this.tail.next = entry;
4007 else this.head = entry;
4011 var entry = this.head;
4013 this.head = entry.next;
4014 if (this.tail === entry) this.tail = null;
4020 var queue = Queue$1;
4022 var engineIsBrowser = typeof window == 'object';
4025 var global$z = global$1o;
4026 var getBuiltIn$3 = getBuiltIn$b;
4027 var call$e = functionCall;
4028 var NativePromise$1 = nativePromiseConstructor;
4029 var redefine$8 = redefine$h.exports;
4030 var redefineAll$2 = redefineAll$4;
4031 var setPrototypeOf$3 = objectSetPrototypeOf;
4032 var setToStringTag$5 = setToStringTag$a;
4033 var setSpecies$3 = setSpecies$5;
4034 var aCallable$5 = aCallable$a;
4035 var isCallable$7 = isCallable$r;
4036 var isObject$i = isObject$s;
4037 var anInstance$5 = anInstance$7;
4038 var inspectSource = inspectSource$4;
4039 var iterate$2 = iterate$3;
4040 var checkCorrectnessOfIteration$3 = checkCorrectnessOfIteration$4;
4041 var speciesConstructor$3 = speciesConstructor$5;
4042 var task = task$1.set;
4043 var microtask = microtask$1;
4044 var promiseResolve$1 = promiseResolve$2;
4045 var hostReportErrors = hostReportErrors$1;
4046 var newPromiseCapabilityModule = newPromiseCapability$2;
4047 var perform = perform$1;
4049 var InternalStateModule$4 = internalState;
4050 var isForced$3 = isForced_1;
4051 var wellKnownSymbol$a = wellKnownSymbol$t;
4052 var IS_BROWSER = engineIsBrowser;
4053 var IS_NODE$2 = engineIsNode;
4054 var V8_VERSION$1 = engineV8Version;
4056 var SPECIES$2 = wellKnownSymbol$a('species');
4057 var PROMISE = 'Promise';
4059 var getInternalState$1 = InternalStateModule$4.getterFor(PROMISE);
4060 var setInternalState$4 = InternalStateModule$4.set;
4061 var getInternalPromiseState = InternalStateModule$4.getterFor(PROMISE);
4062 var NativePromisePrototype = NativePromise$1 && NativePromise$1.prototype;
4063 var PromiseConstructor = NativePromise$1;
4064 var PromisePrototype = NativePromisePrototype;
4065 var TypeError$a = global$z.TypeError;
4066 var document$1 = global$z.document;
4067 var process$1 = global$z.process;
4068 var newPromiseCapability = newPromiseCapabilityModule.f;
4069 var newGenericPromiseCapability = newPromiseCapability;
4071 var DISPATCH_EVENT = !!(document$1 && document$1.createEvent && global$z.dispatchEvent);
4072 var NATIVE_REJECTION_EVENT = isCallable$7(global$z.PromiseRejectionEvent);
4073 var UNHANDLED_REJECTION = 'unhandledrejection';
4074 var REJECTION_HANDLED = 'rejectionhandled';
4080 var SUBCLASSING = false;
4082 var Internal, OwnPromiseCapability, PromiseWrapper, nativeThen;
4084 var FORCED$g = isForced$3(PROMISE, function () {
4085 var PROMISE_CONSTRUCTOR_SOURCE = inspectSource(PromiseConstructor);
4086 var GLOBAL_CORE_JS_PROMISE = PROMISE_CONSTRUCTOR_SOURCE !== String(PromiseConstructor);
4087 // V8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables
4088 // https://bugs.chromium.org/p/chromium/issues/detail?id=830565
4089 // We can't detect it synchronously, so just check versions
4090 if (!GLOBAL_CORE_JS_PROMISE && V8_VERSION$1 === 66) return true;
4091 // We can't use @@species feature detection in V8 since it causes
4092 // deoptimization and performance degradation
4093 // https://github.com/zloirock/core-js/issues/679
4094 if (V8_VERSION$1 >= 51 && /native code/.test(PROMISE_CONSTRUCTOR_SOURCE)) return false;
4095 // Detect correctness of subclassing with @@species support
4096 var promise = new PromiseConstructor(function (resolve) { resolve(1); });
4097 var FakePromise = function (exec) {
4098 exec(function () { /* empty */ }, function () { /* empty */ });
4100 var constructor = promise.constructor = {};
4101 constructor[SPECIES$2] = FakePromise;
4102 SUBCLASSING = promise.then(function () { /* empty */ }) instanceof FakePromise;
4103 if (!SUBCLASSING) return true;
4104 // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test
4105 return !GLOBAL_CORE_JS_PROMISE && IS_BROWSER && !NATIVE_REJECTION_EVENT;
4108 var INCORRECT_ITERATION$1 = FORCED$g || !checkCorrectnessOfIteration$3(function (iterable) {
4109 PromiseConstructor.all(iterable)['catch'](function () { /* empty */ });
4113 var isThenable = function (it) {
4115 return isObject$i(it) && isCallable$7(then = it.then) ? then : false;
4118 var callReaction = function (reaction, state) {
4119 var value = state.value;
4120 var ok = state.state == FULFILLED;
4121 var handler = ok ? reaction.ok : reaction.fail;
4122 var resolve = reaction.resolve;
4123 var reject = reaction.reject;
4124 var domain = reaction.domain;
4125 var result, then, exited;
4129 if (state.rejection === UNHANDLED) onHandleUnhandled(state);
4130 state.rejection = HANDLED;
4132 if (handler === true) result = value;
4134 if (domain) domain.enter();
4135 result = handler(value); // can throw
4141 if (result === reaction.promise) {
4142 reject(TypeError$a('Promise-chain cycle'));
4143 } else if (then = isThenable(result)) {
4144 call$e(then, result, resolve, reject);
4145 } else resolve(result);
4146 } else reject(value);
4148 if (domain && !exited) domain.exit();
4153 var notify = function (state, isReject) {
4154 if (state.notified) return;
4155 state.notified = true;
4156 microtask(function () {
4157 var reactions = state.reactions;
4159 while (reaction = reactions.get()) {
4160 callReaction(reaction, state);
4162 state.notified = false;
4163 if (isReject && !state.rejection) onUnhandled(state);
4167 var dispatchEvent$1 = function (name, promise, reason) {
4169 if (DISPATCH_EVENT) {
4170 event = document$1.createEvent('Event');
4171 event.promise = promise;
4172 event.reason = reason;
4173 event.initEvent(name, false, true);
4174 global$z.dispatchEvent(event);
4175 } else event = { promise: promise, reason: reason };
4176 if (!NATIVE_REJECTION_EVENT && (handler = global$z['on' + name])) handler(event);
4177 else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason);
4180 var onUnhandled = function (state) {
4181 call$e(task, global$z, function () {
4182 var promise = state.facade;
4183 var value = state.value;
4184 var IS_UNHANDLED = isUnhandled(state);
4187 result = perform(function () {
4189 process$1.emit('unhandledRejection', value, promise);
4190 } else dispatchEvent$1(UNHANDLED_REJECTION, promise, value);
4192 // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
4193 state.rejection = IS_NODE$2 || isUnhandled(state) ? UNHANDLED : HANDLED;
4194 if (result.error) throw result.value;
4199 var isUnhandled = function (state) {
4200 return state.rejection !== HANDLED && !state.parent;
4203 var onHandleUnhandled = function (state) {
4204 call$e(task, global$z, function () {
4205 var promise = state.facade;
4207 process$1.emit('rejectionHandled', promise);
4208 } else dispatchEvent$1(REJECTION_HANDLED, promise, state.value);
4212 var bind$a = function (fn, state, unwrap) {
4213 return function (value) {
4214 fn(state, value, unwrap);
4218 var internalReject = function (state, value, unwrap) {
4219 if (state.done) return;
4221 if (unwrap) state = unwrap;
4222 state.value = value;
4223 state.state = REJECTED;
4224 notify(state, true);
4227 var internalResolve = function (state, value, unwrap) {
4228 if (state.done) return;
4230 if (unwrap) state = unwrap;
4232 if (state.facade === value) throw TypeError$a("Promise can't be resolved itself");
4233 var then = isThenable(value);
4235 microtask(function () {
4236 var wrapper = { done: false };
4239 bind$a(internalResolve, wrapper, state),
4240 bind$a(internalReject, wrapper, state)
4243 internalReject(wrapper, error, state);
4247 state.value = value;
4248 state.state = FULFILLED;
4249 notify(state, false);
4252 internalReject({ done: false }, error, state);
4256 // constructor polyfill
4258 // 25.4.3.1 Promise(executor)
4259 PromiseConstructor = function Promise(executor) {
4260 anInstance$5(this, PromisePrototype);
4261 aCallable$5(executor);
4262 call$e(Internal, this);
4263 var state = getInternalState$1(this);
4265 executor(bind$a(internalResolve, state), bind$a(internalReject, state));
4267 internalReject(state, error);
4270 PromisePrototype = PromiseConstructor.prototype;
4271 // eslint-disable-next-line no-unused-vars -- required for `.length`
4272 Internal = function Promise(executor) {
4273 setInternalState$4(this, {
4278 reactions: new Queue(),
4284 Internal.prototype = redefineAll$2(PromisePrototype, {
4285 // `Promise.prototype.then` method
4286 // https://tc39.es/ecma262/#sec-promise.prototype.then
4287 // eslint-disable-next-line unicorn/no-thenable -- safe
4288 then: function then(onFulfilled, onRejected) {
4289 var state = getInternalPromiseState(this);
4290 var reaction = newPromiseCapability(speciesConstructor$3(this, PromiseConstructor));
4291 state.parent = true;
4292 reaction.ok = isCallable$7(onFulfilled) ? onFulfilled : true;
4293 reaction.fail = isCallable$7(onRejected) && onRejected;
4294 reaction.domain = IS_NODE$2 ? process$1.domain : undefined;
4295 if (state.state == PENDING) state.reactions.add(reaction);
4296 else microtask(function () {
4297 callReaction(reaction, state);
4299 return reaction.promise;
4301 // `Promise.prototype.catch` method
4302 // https://tc39.es/ecma262/#sec-promise.prototype.catch
4303 'catch': function (onRejected) {
4304 return this.then(undefined, onRejected);
4307 OwnPromiseCapability = function () {
4308 var promise = new Internal();
4309 var state = getInternalState$1(promise);
4310 this.promise = promise;
4311 this.resolve = bind$a(internalResolve, state);
4312 this.reject = bind$a(internalReject, state);
4314 newPromiseCapabilityModule.f = newPromiseCapability = function (C) {
4315 return C === PromiseConstructor || C === PromiseWrapper
4316 ? new OwnPromiseCapability(C)
4317 : newGenericPromiseCapability(C);
4320 if (isCallable$7(NativePromise$1) && NativePromisePrototype !== Object.prototype) {
4321 nativeThen = NativePromisePrototype.then;
4324 // make `Promise#then` return a polyfilled `Promise` for native promise-based APIs
4325 redefine$8(NativePromisePrototype, 'then', function then(onFulfilled, onRejected) {
4327 return new PromiseConstructor(function (resolve, reject) {
4328 call$e(nativeThen, that, resolve, reject);
4329 }).then(onFulfilled, onRejected);
4330 // https://github.com/zloirock/core-js/issues/640
4331 }, { unsafe: true });
4333 // makes sure that native promise-based APIs `Promise#catch` properly works with patched `Promise#then`
4334 redefine$8(NativePromisePrototype, 'catch', PromisePrototype['catch'], { unsafe: true });
4337 // make `.constructor === Promise` work for native promise-based APIs
4339 delete NativePromisePrototype.constructor;
4340 } catch (error) { /* empty */ }
4342 // make `instanceof Promise` work for native promise-based APIs
4343 if (setPrototypeOf$3) {
4344 setPrototypeOf$3(NativePromisePrototype, PromisePrototype);
4349 $$$({ global: true, wrap: true, forced: FORCED$g }, {
4350 Promise: PromiseConstructor
4353 setToStringTag$5(PromiseConstructor, PROMISE, false);
4354 setSpecies$3(PROMISE);
4356 PromiseWrapper = getBuiltIn$3(PROMISE);
4359 $$$({ target: PROMISE, stat: true, forced: FORCED$g }, {
4360 // `Promise.reject` method
4361 // https://tc39.es/ecma262/#sec-promise.reject
4362 reject: function reject(r) {
4363 var capability = newPromiseCapability(this);
4364 call$e(capability.reject, undefined, r);
4365 return capability.promise;
4369 $$$({ target: PROMISE, stat: true, forced: FORCED$g }, {
4370 // `Promise.resolve` method
4371 // https://tc39.es/ecma262/#sec-promise.resolve
4372 resolve: function resolve(x) {
4373 return promiseResolve$1(this, x);
4377 $$$({ target: PROMISE, stat: true, forced: INCORRECT_ITERATION$1 }, {
4378 // `Promise.all` method
4379 // https://tc39.es/ecma262/#sec-promise.all
4380 all: function all(iterable) {
4382 var capability = newPromiseCapability(C);
4383 var resolve = capability.resolve;
4384 var reject = capability.reject;
4385 var result = perform(function () {
4386 var $promiseResolve = aCallable$5(C.resolve);
4390 iterate$2(iterable, function (promise) {
4391 var index = counter++;
4392 var alreadyCalled = false;
4394 call$e($promiseResolve, C, promise).then(function (value) {
4395 if (alreadyCalled) return;
4396 alreadyCalled = true;
4397 values[index] = value;
4398 --remaining || resolve(values);
4401 --remaining || resolve(values);
4403 if (result.error) reject(result.value);
4404 return capability.promise;
4406 // `Promise.race` method
4407 // https://tc39.es/ecma262/#sec-promise.race
4408 race: function race(iterable) {
4410 var capability = newPromiseCapability(C);
4411 var reject = capability.reject;
4412 var result = perform(function () {
4413 var $promiseResolve = aCallable$5(C.resolve);
4414 iterate$2(iterable, function (promise) {
4415 call$e($promiseResolve, C, promise).then(capability.resolve, reject);
4418 if (result.error) reject(result.value);
4419 return capability.promise;
4423 var typedArrayConstructor = {exports: {}};
4425 /* eslint-disable no-new -- required for testing */
4427 var global$y = global$1o;
4428 var fails$A = fails$V;
4429 var checkCorrectnessOfIteration$2 = checkCorrectnessOfIteration$4;
4430 var NATIVE_ARRAY_BUFFER_VIEWS$1 = arrayBufferViewCore.NATIVE_ARRAY_BUFFER_VIEWS;
4432 var ArrayBuffer$2 = global$y.ArrayBuffer;
4433 var Int8Array$3 = global$y.Int8Array;
4435 var typedArrayConstructorsRequireWrappers = !NATIVE_ARRAY_BUFFER_VIEWS$1 || !fails$A(function () {
4437 }) || !fails$A(function () {
4438 new Int8Array$3(-1);
4439 }) || !checkCorrectnessOfIteration$2(function (iterable) {
4441 new Int8Array$3(null);
4442 new Int8Array$3(1.5);
4443 new Int8Array$3(iterable);
4444 }, true) || fails$A(function () {
4445 // Safari (11+) bug - a reason why even Safari 13 should load a typed array polyfill
4446 return new Int8Array$3(new ArrayBuffer$2(2), 1, undefined).length !== 1;
4449 var isObject$h = isObject$s;
4451 var floor$6 = Math.floor;
4453 // `IsIntegralNumber` abstract operation
4454 // https://tc39.es/ecma262/#sec-isintegralnumber
4455 // eslint-disable-next-line es/no-number-isinteger -- safe
4456 var isIntegralNumber$1 = Number.isInteger || function isInteger(it) {
4457 return !isObject$h(it) && isFinite(it) && floor$6(it) === it;
4460 var global$x = global$1o;
4461 var toIntegerOrInfinity$5 = toIntegerOrInfinity$b;
4463 var RangeError$9 = global$x.RangeError;
4465 var toPositiveInteger$1 = function (it) {
4466 var result = toIntegerOrInfinity$5(it);
4467 if (result < 0) throw RangeError$9("The argument can't be less than 0");
4471 var global$w = global$1o;
4472 var toPositiveInteger = toPositiveInteger$1;
4474 var RangeError$8 = global$w.RangeError;
4476 var toOffset$2 = function (it, BYTES) {
4477 var offset = toPositiveInteger(it);
4478 if (offset % BYTES) throw RangeError$8('Wrong offset');
4482 var bind$9 = functionBindContext;
4483 var call$d = functionCall;
4484 var aConstructor$1 = aConstructor$3;
4485 var toObject$c = toObject$i;
4486 var lengthOfArrayLike$c = lengthOfArrayLike$i;
4487 var getIterator$2 = getIterator$4;
4488 var getIteratorMethod$2 = getIteratorMethod$5;
4489 var isArrayIteratorMethod$1 = isArrayIteratorMethod$3;
4490 var aTypedArrayConstructor$2 = arrayBufferViewCore.aTypedArrayConstructor;
4492 var typedArrayFrom$2 = function from(source /* , mapfn, thisArg */) {
4493 var C = aConstructor$1(this);
4494 var O = toObject$c(source);
4495 var argumentsLength = arguments.length;
4496 var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
4497 var mapping = mapfn !== undefined;
4498 var iteratorMethod = getIteratorMethod$2(O);
4499 var i, length, result, step, iterator, next;
4500 if (iteratorMethod && !isArrayIteratorMethod$1(iteratorMethod)) {
4501 iterator = getIterator$2(O, iteratorMethod);
4502 next = iterator.next;
4504 while (!(step = call$d(next, iterator)).done) {
4508 if (mapping && argumentsLength > 2) {
4509 mapfn = bind$9(mapfn, arguments[2]);
4511 length = lengthOfArrayLike$c(O);
4512 result = new (aTypedArrayConstructor$2(C))(length);
4513 for (i = 0; length > i; i++) {
4514 result[i] = mapping ? mapfn(O[i], i) : O[i];
4519 var isCallable$6 = isCallable$r;
4520 var isObject$g = isObject$s;
4521 var setPrototypeOf$2 = objectSetPrototypeOf;
4523 // makes subclassing work correct for wrapped built-ins
4524 var inheritIfRequired$4 = function ($this, dummy, Wrapper) {
4525 var NewTarget, NewTargetPrototype;
4527 // it can work only with native `setPrototypeOf`
4529 // we haven't completely correct pre-ES6 way for getting `new.target`, so use this
4530 isCallable$6(NewTarget = dummy.constructor) &&
4531 NewTarget !== Wrapper &&
4532 isObject$g(NewTargetPrototype = NewTarget.prototype) &&
4533 NewTargetPrototype !== Wrapper.prototype
4534 ) setPrototypeOf$2($this, NewTargetPrototype);
4539 var global$v = global$1o;
4540 var call$c = functionCall;
4541 var DESCRIPTORS$c = descriptors;
4542 var TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS$1 = typedArrayConstructorsRequireWrappers;
4543 var ArrayBufferViewCore$n = arrayBufferViewCore;
4544 var ArrayBufferModule = arrayBuffer;
4545 var anInstance$4 = anInstance$7;
4546 var createPropertyDescriptor$1 = createPropertyDescriptor$7;
4547 var createNonEnumerableProperty$2 = createNonEnumerableProperty$b;
4548 var isIntegralNumber = isIntegralNumber$1;
4549 var toLength$7 = toLength$c;
4550 var toIndex = toIndex$2;
4551 var toOffset$1 = toOffset$2;
4552 var toPropertyKey = toPropertyKey$5;
4553 var hasOwn$7 = hasOwnProperty_1;
4554 var classof$4 = classof$d;
4555 var isObject$f = isObject$s;
4556 var isSymbol$2 = isSymbol$6;
4557 var create$7 = objectCreate;
4558 var isPrototypeOf$3 = objectIsPrototypeOf;
4559 var setPrototypeOf$1 = objectSetPrototypeOf;
4560 var getOwnPropertyNames$2 = objectGetOwnPropertyNames.f;
4561 var typedArrayFrom$1 = typedArrayFrom$2;
4562 var forEach$1 = arrayIteration.forEach;
4563 var setSpecies$2 = setSpecies$5;
4564 var definePropertyModule = objectDefineProperty;
4565 var getOwnPropertyDescriptorModule$1 = objectGetOwnPropertyDescriptor;
4566 var InternalStateModule$3 = internalState;
4567 var inheritIfRequired$3 = inheritIfRequired$4;
4569 var getInternalState = InternalStateModule$3.get;
4570 var setInternalState$3 = InternalStateModule$3.set;
4571 var nativeDefineProperty = definePropertyModule.f;
4572 var nativeGetOwnPropertyDescriptor$1 = getOwnPropertyDescriptorModule$1.f;
4573 var round = Math.round;
4574 var RangeError$7 = global$v.RangeError;
4575 var ArrayBuffer$1 = ArrayBufferModule.ArrayBuffer;
4576 var ArrayBufferPrototype = ArrayBuffer$1.prototype;
4577 var DataView$1 = ArrayBufferModule.DataView;
4578 var NATIVE_ARRAY_BUFFER_VIEWS = ArrayBufferViewCore$n.NATIVE_ARRAY_BUFFER_VIEWS;
4579 var TYPED_ARRAY_CONSTRUCTOR$1 = ArrayBufferViewCore$n.TYPED_ARRAY_CONSTRUCTOR;
4580 var TYPED_ARRAY_TAG = ArrayBufferViewCore$n.TYPED_ARRAY_TAG;
4581 var TypedArray = ArrayBufferViewCore$n.TypedArray;
4582 var TypedArrayPrototype$1 = ArrayBufferViewCore$n.TypedArrayPrototype;
4583 var aTypedArrayConstructor$1 = ArrayBufferViewCore$n.aTypedArrayConstructor;
4584 var isTypedArray = ArrayBufferViewCore$n.isTypedArray;
4585 var BYTES_PER_ELEMENT = 'BYTES_PER_ELEMENT';
4586 var WRONG_LENGTH = 'Wrong length';
4588 var fromList = function (C, list) {
4589 aTypedArrayConstructor$1(C);
4591 var length = list.length;
4592 var result = new C(length);
4593 while (length > index) result[index] = list[index++];
4597 var addGetter = function (it, key) {
4598 nativeDefineProperty(it, key, { get: function () {
4599 return getInternalState(this)[key];
4603 var isArrayBuffer = function (it) {
4605 return isPrototypeOf$3(ArrayBufferPrototype, it) || (klass = classof$4(it)) == 'ArrayBuffer' || klass == 'SharedArrayBuffer';
4608 var isTypedArrayIndex = function (target, key) {
4609 return isTypedArray(target)
4612 && isIntegralNumber(+key)
4616 var wrappedGetOwnPropertyDescriptor = function getOwnPropertyDescriptor(target, key) {
4617 key = toPropertyKey(key);
4618 return isTypedArrayIndex(target, key)
4619 ? createPropertyDescriptor$1(2, target[key])
4620 : nativeGetOwnPropertyDescriptor$1(target, key);
4623 var wrappedDefineProperty = function defineProperty(target, key, descriptor) {
4624 key = toPropertyKey(key);
4625 if (isTypedArrayIndex(target, key)
4626 && isObject$f(descriptor)
4627 && hasOwn$7(descriptor, 'value')
4628 && !hasOwn$7(descriptor, 'get')
4629 && !hasOwn$7(descriptor, 'set')
4630 // TODO: add validation descriptor w/o calling accessors
4631 && !descriptor.configurable
4632 && (!hasOwn$7(descriptor, 'writable') || descriptor.writable)
4633 && (!hasOwn$7(descriptor, 'enumerable') || descriptor.enumerable)
4635 target[key] = descriptor.value;
4637 } return nativeDefineProperty(target, key, descriptor);
4640 if (DESCRIPTORS$c) {
4641 if (!NATIVE_ARRAY_BUFFER_VIEWS) {
4642 getOwnPropertyDescriptorModule$1.f = wrappedGetOwnPropertyDescriptor;
4643 definePropertyModule.f = wrappedDefineProperty;
4644 addGetter(TypedArrayPrototype$1, 'buffer');
4645 addGetter(TypedArrayPrototype$1, 'byteOffset');
4646 addGetter(TypedArrayPrototype$1, 'byteLength');
4647 addGetter(TypedArrayPrototype$1, 'length');
4650 $$_({ target: 'Object', stat: true, forced: !NATIVE_ARRAY_BUFFER_VIEWS }, {
4651 getOwnPropertyDescriptor: wrappedGetOwnPropertyDescriptor,
4652 defineProperty: wrappedDefineProperty
4655 typedArrayConstructor.exports = function (TYPE, wrapper, CLAMPED) {
4656 var BYTES = TYPE.match(/\d+$/)[0] / 8;
4657 var CONSTRUCTOR_NAME = TYPE + (CLAMPED ? 'Clamped' : '') + 'Array';
4658 var GETTER = 'get' + TYPE;
4659 var SETTER = 'set' + TYPE;
4660 var NativeTypedArrayConstructor = global$v[CONSTRUCTOR_NAME];
4661 var TypedArrayConstructor = NativeTypedArrayConstructor;
4662 var TypedArrayConstructorPrototype = TypedArrayConstructor && TypedArrayConstructor.prototype;
4665 var getter = function (that, index) {
4666 var data = getInternalState(that);
4667 return data.view[GETTER](index * BYTES + data.byteOffset, true);
4670 var setter = function (that, index, value) {
4671 var data = getInternalState(that);
4672 if (CLAMPED) value = (value = round(value)) < 0 ? 0 : value > 0xFF ? 0xFF : value & 0xFF;
4673 data.view[SETTER](index * BYTES + data.byteOffset, value, true);
4676 var addElement = function (that, index) {
4677 nativeDefineProperty(that, index, {
4679 return getter(this, index);
4681 set: function (value) {
4682 return setter(this, index, value);
4688 if (!NATIVE_ARRAY_BUFFER_VIEWS) {
4689 TypedArrayConstructor = wrapper(function (that, data, offset, $length) {
4690 anInstance$4(that, TypedArrayConstructorPrototype);
4693 var buffer, byteLength, length;
4694 if (!isObject$f(data)) {
4695 length = toIndex(data);
4696 byteLength = length * BYTES;
4697 buffer = new ArrayBuffer$1(byteLength);
4698 } else if (isArrayBuffer(data)) {
4700 byteOffset = toOffset$1(offset, BYTES);
4701 var $len = data.byteLength;
4702 if ($length === undefined) {
4703 if ($len % BYTES) throw RangeError$7(WRONG_LENGTH);
4704 byteLength = $len - byteOffset;
4705 if (byteLength < 0) throw RangeError$7(WRONG_LENGTH);
4707 byteLength = toLength$7($length) * BYTES;
4708 if (byteLength + byteOffset > $len) throw RangeError$7(WRONG_LENGTH);
4710 length = byteLength / BYTES;
4711 } else if (isTypedArray(data)) {
4712 return fromList(TypedArrayConstructor, data);
4714 return call$c(typedArrayFrom$1, TypedArrayConstructor, data);
4716 setInternalState$3(that, {
4718 byteOffset: byteOffset,
4719 byteLength: byteLength,
4721 view: new DataView$1(buffer)
4723 while (index < length) addElement(that, index++);
4726 if (setPrototypeOf$1) setPrototypeOf$1(TypedArrayConstructor, TypedArray);
4727 TypedArrayConstructorPrototype = TypedArrayConstructor.prototype = create$7(TypedArrayPrototype$1);
4728 } else if (TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS$1) {
4729 TypedArrayConstructor = wrapper(function (dummy, data, typedArrayOffset, $length) {
4730 anInstance$4(dummy, TypedArrayConstructorPrototype);
4731 return inheritIfRequired$3(function () {
4732 if (!isObject$f(data)) return new NativeTypedArrayConstructor(toIndex(data));
4733 if (isArrayBuffer(data)) return $length !== undefined
4734 ? new NativeTypedArrayConstructor(data, toOffset$1(typedArrayOffset, BYTES), $length)
4735 : typedArrayOffset !== undefined
4736 ? new NativeTypedArrayConstructor(data, toOffset$1(typedArrayOffset, BYTES))
4737 : new NativeTypedArrayConstructor(data);
4738 if (isTypedArray(data)) return fromList(TypedArrayConstructor, data);
4739 return call$c(typedArrayFrom$1, TypedArrayConstructor, data);
4740 }(), dummy, TypedArrayConstructor);
4743 if (setPrototypeOf$1) setPrototypeOf$1(TypedArrayConstructor, TypedArray);
4744 forEach$1(getOwnPropertyNames$2(NativeTypedArrayConstructor), function (key) {
4745 if (!(key in TypedArrayConstructor)) {
4746 createNonEnumerableProperty$2(TypedArrayConstructor, key, NativeTypedArrayConstructor[key]);
4749 TypedArrayConstructor.prototype = TypedArrayConstructorPrototype;
4752 if (TypedArrayConstructorPrototype.constructor !== TypedArrayConstructor) {
4753 createNonEnumerableProperty$2(TypedArrayConstructorPrototype, 'constructor', TypedArrayConstructor);
4756 createNonEnumerableProperty$2(TypedArrayConstructorPrototype, TYPED_ARRAY_CONSTRUCTOR$1, TypedArrayConstructor);
4758 if (TYPED_ARRAY_TAG) {
4759 createNonEnumerableProperty$2(TypedArrayConstructorPrototype, TYPED_ARRAY_TAG, CONSTRUCTOR_NAME);
4762 exported[CONSTRUCTOR_NAME] = TypedArrayConstructor;
4765 global: true, forced: TypedArrayConstructor != NativeTypedArrayConstructor, sham: !NATIVE_ARRAY_BUFFER_VIEWS
4768 if (!(BYTES_PER_ELEMENT in TypedArrayConstructor)) {
4769 createNonEnumerableProperty$2(TypedArrayConstructor, BYTES_PER_ELEMENT, BYTES);
4772 if (!(BYTES_PER_ELEMENT in TypedArrayConstructorPrototype)) {
4773 createNonEnumerableProperty$2(TypedArrayConstructorPrototype, BYTES_PER_ELEMENT, BYTES);
4776 setSpecies$2(CONSTRUCTOR_NAME);
4778 } else typedArrayConstructor.exports = function () { /* empty */ };
4780 var createTypedArrayConstructor$1 = typedArrayConstructor.exports;
4782 // `Uint8Array` constructor
4783 // https://tc39.es/ecma262/#sec-typedarray-objects
4784 createTypedArrayConstructor$1('Uint8', function (init) {
4785 return function Uint8Array(data, byteOffset, length) {
4786 return init(this, data, byteOffset, length);
4790 var toObject$b = toObject$i;
4791 var toAbsoluteIndex$4 = toAbsoluteIndex$9;
4792 var lengthOfArrayLike$b = lengthOfArrayLike$i;
4794 var min$7 = Math.min;
4796 // `Array.prototype.copyWithin` method implementation
4797 // https://tc39.es/ecma262/#sec-array.prototype.copywithin
4798 // eslint-disable-next-line es/no-array-prototype-copywithin -- safe
4799 var arrayCopyWithin = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) {
4800 var O = toObject$b(this);
4801 var len = lengthOfArrayLike$b(O);
4802 var to = toAbsoluteIndex$4(target, len);
4803 var from = toAbsoluteIndex$4(start, len);
4804 var end = arguments.length > 2 ? arguments[2] : undefined;
4805 var count = min$7((end === undefined ? len : toAbsoluteIndex$4(end, len)) - from, len - to);
4807 if (from < to && to < from + count) {
4812 while (count-- > 0) {
4813 if (from in O) O[to] = O[from];
4820 var uncurryThis$A = functionUncurryThis;
4821 var ArrayBufferViewCore$m = arrayBufferViewCore;
4822 var $ArrayCopyWithin = arrayCopyWithin;
4824 var u$ArrayCopyWithin = uncurryThis$A($ArrayCopyWithin);
4825 var aTypedArray$l = ArrayBufferViewCore$m.aTypedArray;
4826 var exportTypedArrayMethod$m = ArrayBufferViewCore$m.exportTypedArrayMethod;
4828 // `%TypedArray%.prototype.copyWithin` method
4829 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.copywithin
4830 exportTypedArrayMethod$m('copyWithin', function copyWithin(target, start /* , end */) {
4831 return u$ArrayCopyWithin(aTypedArray$l(this), target, start, arguments.length > 2 ? arguments[2] : undefined);
4834 var ArrayBufferViewCore$l = arrayBufferViewCore;
4835 var $every$1 = arrayIteration.every;
4837 var aTypedArray$k = ArrayBufferViewCore$l.aTypedArray;
4838 var exportTypedArrayMethod$l = ArrayBufferViewCore$l.exportTypedArrayMethod;
4840 // `%TypedArray%.prototype.every` method
4841 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.every
4842 exportTypedArrayMethod$l('every', function every(callbackfn /* , thisArg */) {
4843 return $every$1(aTypedArray$k(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
4846 var ArrayBufferViewCore$k = arrayBufferViewCore;
4847 var call$b = functionCall;
4848 var $fill = arrayFill$1;
4850 var aTypedArray$j = ArrayBufferViewCore$k.aTypedArray;
4851 var exportTypedArrayMethod$k = ArrayBufferViewCore$k.exportTypedArrayMethod;
4853 // `%TypedArray%.prototype.fill` method
4854 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.fill
4855 exportTypedArrayMethod$k('fill', function fill(value /* , start, end */) {
4856 var length = arguments.length;
4859 aTypedArray$j(this),
4861 length > 1 ? arguments[1] : undefined,
4862 length > 2 ? arguments[2] : undefined
4866 var lengthOfArrayLike$a = lengthOfArrayLike$i;
4868 var arrayFromConstructorAndList$1 = function (Constructor, list) {
4870 var length = lengthOfArrayLike$a(list);
4871 var result = new Constructor(length);
4872 while (length > index) result[index] = list[index++];
4876 var ArrayBufferViewCore$j = arrayBufferViewCore;
4877 var speciesConstructor$2 = speciesConstructor$5;
4879 var TYPED_ARRAY_CONSTRUCTOR = ArrayBufferViewCore$j.TYPED_ARRAY_CONSTRUCTOR;
4880 var aTypedArrayConstructor = ArrayBufferViewCore$j.aTypedArrayConstructor;
4882 // a part of `TypedArraySpeciesCreate` abstract operation
4883 // https://tc39.es/ecma262/#typedarray-species-create
4884 var typedArraySpeciesConstructor$4 = function (originalArray) {
4885 return aTypedArrayConstructor(speciesConstructor$2(originalArray, originalArray[TYPED_ARRAY_CONSTRUCTOR]));
4888 var arrayFromConstructorAndList = arrayFromConstructorAndList$1;
4889 var typedArraySpeciesConstructor$3 = typedArraySpeciesConstructor$4;
4891 var typedArrayFromSpeciesAndList = function (instance, list) {
4892 return arrayFromConstructorAndList(typedArraySpeciesConstructor$3(instance), list);
4895 var ArrayBufferViewCore$i = arrayBufferViewCore;
4896 var $filter$1 = arrayIteration.filter;
4897 var fromSpeciesAndList = typedArrayFromSpeciesAndList;
4899 var aTypedArray$i = ArrayBufferViewCore$i.aTypedArray;
4900 var exportTypedArrayMethod$j = ArrayBufferViewCore$i.exportTypedArrayMethod;
4902 // `%TypedArray%.prototype.filter` method
4903 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.filter
4904 exportTypedArrayMethod$j('filter', function filter(callbackfn /* , thisArg */) {
4905 var list = $filter$1(aTypedArray$i(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
4906 return fromSpeciesAndList(this, list);
4909 var ArrayBufferViewCore$h = arrayBufferViewCore;
4910 var $find$1 = arrayIteration.find;
4912 var aTypedArray$h = ArrayBufferViewCore$h.aTypedArray;
4913 var exportTypedArrayMethod$i = ArrayBufferViewCore$h.exportTypedArrayMethod;
4915 // `%TypedArray%.prototype.find` method
4916 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.find
4917 exportTypedArrayMethod$i('find', function find(predicate /* , thisArg */) {
4918 return $find$1(aTypedArray$h(this), predicate, arguments.length > 1 ? arguments[1] : undefined);
4921 var ArrayBufferViewCore$g = arrayBufferViewCore;
4922 var $findIndex$1 = arrayIteration.findIndex;
4924 var aTypedArray$g = ArrayBufferViewCore$g.aTypedArray;
4925 var exportTypedArrayMethod$h = ArrayBufferViewCore$g.exportTypedArrayMethod;
4927 // `%TypedArray%.prototype.findIndex` method
4928 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.findindex
4929 exportTypedArrayMethod$h('findIndex', function findIndex(predicate /* , thisArg */) {
4930 return $findIndex$1(aTypedArray$g(this), predicate, arguments.length > 1 ? arguments[1] : undefined);
4933 var ArrayBufferViewCore$f = arrayBufferViewCore;
4934 var $forEach = arrayIteration.forEach;
4936 var aTypedArray$f = ArrayBufferViewCore$f.aTypedArray;
4937 var exportTypedArrayMethod$g = ArrayBufferViewCore$f.exportTypedArrayMethod;
4939 // `%TypedArray%.prototype.forEach` method
4940 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.foreach
4941 exportTypedArrayMethod$g('forEach', function forEach(callbackfn /* , thisArg */) {
4942 $forEach(aTypedArray$f(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
4945 var ArrayBufferViewCore$e = arrayBufferViewCore;
4946 var $includes$1 = arrayIncludes.includes;
4948 var aTypedArray$e = ArrayBufferViewCore$e.aTypedArray;
4949 var exportTypedArrayMethod$f = ArrayBufferViewCore$e.exportTypedArrayMethod;
4951 // `%TypedArray%.prototype.includes` method
4952 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.includes
4953 exportTypedArrayMethod$f('includes', function includes(searchElement /* , fromIndex */) {
4954 return $includes$1(aTypedArray$e(this), searchElement, arguments.length > 1 ? arguments[1] : undefined);
4957 var ArrayBufferViewCore$d = arrayBufferViewCore;
4958 var $indexOf = arrayIncludes.indexOf;
4960 var aTypedArray$d = ArrayBufferViewCore$d.aTypedArray;
4961 var exportTypedArrayMethod$e = ArrayBufferViewCore$d.exportTypedArrayMethod;
4963 // `%TypedArray%.prototype.indexOf` method
4964 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.indexof
4965 exportTypedArrayMethod$e('indexOf', function indexOf(searchElement /* , fromIndex */) {
4966 return $indexOf(aTypedArray$d(this), searchElement, arguments.length > 1 ? arguments[1] : undefined);
4969 var global$u = global$1o;
4970 var fails$z = fails$V;
4971 var uncurryThis$z = functionUncurryThis;
4972 var ArrayBufferViewCore$c = arrayBufferViewCore;
4973 var ArrayIterators = es_array_iterator;
4974 var wellKnownSymbol$9 = wellKnownSymbol$t;
4976 var ITERATOR$4 = wellKnownSymbol$9('iterator');
4977 var Uint8Array$2 = global$u.Uint8Array;
4978 var arrayValues = uncurryThis$z(ArrayIterators.values);
4979 var arrayKeys = uncurryThis$z(ArrayIterators.keys);
4980 var arrayEntries = uncurryThis$z(ArrayIterators.entries);
4981 var aTypedArray$c = ArrayBufferViewCore$c.aTypedArray;
4982 var exportTypedArrayMethod$d = ArrayBufferViewCore$c.exportTypedArrayMethod;
4983 var TypedArrayPrototype = Uint8Array$2 && Uint8Array$2.prototype;
4985 var GENERIC = !fails$z(function () {
4986 TypedArrayPrototype[ITERATOR$4].call([1]);
4989 var ITERATOR_IS_VALUES = !!TypedArrayPrototype
4990 && TypedArrayPrototype.values
4991 && TypedArrayPrototype[ITERATOR$4] === TypedArrayPrototype.values
4992 && TypedArrayPrototype.values.name === 'values';
4994 var typedArrayValues = function values() {
4995 return arrayValues(aTypedArray$c(this));
4998 // `%TypedArray%.prototype.entries` method
4999 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.entries
5000 exportTypedArrayMethod$d('entries', function entries() {
5001 return arrayEntries(aTypedArray$c(this));
5003 // `%TypedArray%.prototype.keys` method
5004 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.keys
5005 exportTypedArrayMethod$d('keys', function keys() {
5006 return arrayKeys(aTypedArray$c(this));
5008 // `%TypedArray%.prototype.values` method
5009 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.values
5010 exportTypedArrayMethod$d('values', typedArrayValues, GENERIC || !ITERATOR_IS_VALUES, { name: 'values' });
5011 // `%TypedArray%.prototype[@@iterator]` method
5012 // https://tc39.es/ecma262/#sec-%typedarray%.prototype-@@iterator
5013 exportTypedArrayMethod$d(ITERATOR$4, typedArrayValues, GENERIC || !ITERATOR_IS_VALUES, { name: 'values' });
5015 var ArrayBufferViewCore$b = arrayBufferViewCore;
5016 var uncurryThis$y = functionUncurryThis;
5018 var aTypedArray$b = ArrayBufferViewCore$b.aTypedArray;
5019 var exportTypedArrayMethod$c = ArrayBufferViewCore$b.exportTypedArrayMethod;
5020 var $join = uncurryThis$y([].join);
5022 // `%TypedArray%.prototype.join` method
5023 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.join
5024 exportTypedArrayMethod$c('join', function join(separator) {
5025 return $join(aTypedArray$b(this), separator);
5028 /* eslint-disable es/no-array-prototype-lastindexof -- safe */
5029 var apply$6 = functionApply;
5030 var toIndexedObject$5 = toIndexedObject$d;
5031 var toIntegerOrInfinity$4 = toIntegerOrInfinity$b;
5032 var lengthOfArrayLike$9 = lengthOfArrayLike$i;
5033 var arrayMethodIsStrict$6 = arrayMethodIsStrict$9;
5035 var min$6 = Math.min;
5036 var $lastIndexOf$1 = [].lastIndexOf;
5037 var NEGATIVE_ZERO = !!$lastIndexOf$1 && 1 / [1].lastIndexOf(1, -0) < 0;
5038 var STRICT_METHOD$6 = arrayMethodIsStrict$6('lastIndexOf');
5039 var FORCED$f = NEGATIVE_ZERO || !STRICT_METHOD$6;
5041 // `Array.prototype.lastIndexOf` method implementation
5042 // https://tc39.es/ecma262/#sec-array.prototype.lastindexof
5043 var arrayLastIndexOf = FORCED$f ? function lastIndexOf(searchElement /* , fromIndex = @[*-1] */) {
5045 if (NEGATIVE_ZERO) return apply$6($lastIndexOf$1, this, arguments) || 0;
5046 var O = toIndexedObject$5(this);
5047 var length = lengthOfArrayLike$9(O);
5048 var index = length - 1;
5049 if (arguments.length > 1) index = min$6(index, toIntegerOrInfinity$4(arguments[1]));
5050 if (index < 0) index = length + index;
5051 for (;index >= 0; index--) if (index in O && O[index] === searchElement) return index || 0;
5055 var ArrayBufferViewCore$a = arrayBufferViewCore;
5056 var apply$5 = functionApply;
5057 var $lastIndexOf = arrayLastIndexOf;
5059 var aTypedArray$a = ArrayBufferViewCore$a.aTypedArray;
5060 var exportTypedArrayMethod$b = ArrayBufferViewCore$a.exportTypedArrayMethod;
5062 // `%TypedArray%.prototype.lastIndexOf` method
5063 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.lastindexof
5064 exportTypedArrayMethod$b('lastIndexOf', function lastIndexOf(searchElement /* , fromIndex */) {
5065 var length = arguments.length;
5066 return apply$5($lastIndexOf, aTypedArray$a(this), length > 1 ? [searchElement, arguments[1]] : [searchElement]);
5069 var ArrayBufferViewCore$9 = arrayBufferViewCore;
5070 var $map = arrayIteration.map;
5071 var typedArraySpeciesConstructor$2 = typedArraySpeciesConstructor$4;
5073 var aTypedArray$9 = ArrayBufferViewCore$9.aTypedArray;
5074 var exportTypedArrayMethod$a = ArrayBufferViewCore$9.exportTypedArrayMethod;
5076 // `%TypedArray%.prototype.map` method
5077 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.map
5078 exportTypedArrayMethod$a('map', function map(mapfn /* , thisArg */) {
5079 return $map(aTypedArray$9(this), mapfn, arguments.length > 1 ? arguments[1] : undefined, function (O, length) {
5080 return new (typedArraySpeciesConstructor$2(O))(length);
5084 var global$t = global$1o;
5085 var aCallable$4 = aCallable$a;
5086 var toObject$a = toObject$i;
5087 var IndexedObject$2 = indexedObject;
5088 var lengthOfArrayLike$8 = lengthOfArrayLike$i;
5090 var TypeError$9 = global$t.TypeError;
5092 // `Array.prototype.{ reduce, reduceRight }` methods implementation
5093 var createMethod$3 = function (IS_RIGHT) {
5094 return function (that, callbackfn, argumentsLength, memo) {
5095 aCallable$4(callbackfn);
5096 var O = toObject$a(that);
5097 var self = IndexedObject$2(O);
5098 var length = lengthOfArrayLike$8(O);
5099 var index = IS_RIGHT ? length - 1 : 0;
5100 var i = IS_RIGHT ? -1 : 1;
5101 if (argumentsLength < 2) while (true) {
5102 if (index in self) {
5108 if (IS_RIGHT ? index < 0 : length <= index) {
5109 throw TypeError$9('Reduce of empty array with no initial value');
5112 for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) {
5113 memo = callbackfn(memo, self[index], index, O);
5120 // `Array.prototype.reduce` method
5121 // https://tc39.es/ecma262/#sec-array.prototype.reduce
5122 left: createMethod$3(false),
5123 // `Array.prototype.reduceRight` method
5124 // https://tc39.es/ecma262/#sec-array.prototype.reduceright
5125 right: createMethod$3(true)
5128 var ArrayBufferViewCore$8 = arrayBufferViewCore;
5129 var $reduce$1 = arrayReduce.left;
5131 var aTypedArray$8 = ArrayBufferViewCore$8.aTypedArray;
5132 var exportTypedArrayMethod$9 = ArrayBufferViewCore$8.exportTypedArrayMethod;
5134 // `%TypedArray%.prototype.reduce` method
5135 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduce
5136 exportTypedArrayMethod$9('reduce', function reduce(callbackfn /* , initialValue */) {
5137 var length = arguments.length;
5138 return $reduce$1(aTypedArray$8(this), callbackfn, length, length > 1 ? arguments[1] : undefined);
5141 var ArrayBufferViewCore$7 = arrayBufferViewCore;
5142 var $reduceRight$1 = arrayReduce.right;
5144 var aTypedArray$7 = ArrayBufferViewCore$7.aTypedArray;
5145 var exportTypedArrayMethod$8 = ArrayBufferViewCore$7.exportTypedArrayMethod;
5147 // `%TypedArray%.prototype.reduceRicht` method
5148 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduceright
5149 exportTypedArrayMethod$8('reduceRight', function reduceRight(callbackfn /* , initialValue */) {
5150 var length = arguments.length;
5151 return $reduceRight$1(aTypedArray$7(this), callbackfn, length, length > 1 ? arguments[1] : undefined);
5154 var ArrayBufferViewCore$6 = arrayBufferViewCore;
5156 var aTypedArray$6 = ArrayBufferViewCore$6.aTypedArray;
5157 var exportTypedArrayMethod$7 = ArrayBufferViewCore$6.exportTypedArrayMethod;
5158 var floor$5 = Math.floor;
5160 // `%TypedArray%.prototype.reverse` method
5161 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.reverse
5162 exportTypedArrayMethod$7('reverse', function reverse() {
5164 var length = aTypedArray$6(that).length;
5165 var middle = floor$5(length / 2);
5168 while (index < middle) {
5169 value = that[index];
5170 that[index++] = that[--length];
5171 that[length] = value;
5175 var global$s = global$1o;
5176 var call$a = functionCall;
5177 var ArrayBufferViewCore$5 = arrayBufferViewCore;
5178 var lengthOfArrayLike$7 = lengthOfArrayLike$i;
5179 var toOffset = toOffset$2;
5180 var toIndexedObject$4 = toObject$i;
5181 var fails$y = fails$V;
5183 var RangeError$6 = global$s.RangeError;
5184 var Int8Array$2 = global$s.Int8Array;
5185 var Int8ArrayPrototype = Int8Array$2 && Int8Array$2.prototype;
5186 var $set = Int8ArrayPrototype && Int8ArrayPrototype.set;
5187 var aTypedArray$5 = ArrayBufferViewCore$5.aTypedArray;
5188 var exportTypedArrayMethod$6 = ArrayBufferViewCore$5.exportTypedArrayMethod;
5190 var WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS = !fails$y(function () {
5191 // eslint-disable-next-line es/no-typed-arrays -- required for testing
5192 var array = new Uint8ClampedArray(2);
5193 call$a($set, array, { length: 1, 0: 3 }, 1);
5194 return array[1] !== 3;
5197 // https://bugs.chromium.org/p/v8/issues/detail?id=11294 and other
5198 var TO_OBJECT_BUG = WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS && ArrayBufferViewCore$5.NATIVE_ARRAY_BUFFER_VIEWS && fails$y(function () {
5199 var array = new Int8Array$2(2);
5202 return array[0] !== 0 || array[1] !== 2;
5205 // `%TypedArray%.prototype.set` method
5206 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.set
5207 exportTypedArrayMethod$6('set', function set(arrayLike /* , offset */) {
5208 aTypedArray$5(this);
5209 var offset = toOffset(arguments.length > 1 ? arguments[1] : undefined, 1);
5210 var src = toIndexedObject$4(arrayLike);
5211 if (WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS) return call$a($set, this, src, offset);
5212 var length = this.length;
5213 var len = lengthOfArrayLike$7(src);
5215 if (len + offset > length) throw RangeError$6('Wrong length');
5216 while (index < len) this[offset + index] = src[index++];
5217 }, !WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS || TO_OBJECT_BUG);
5219 var ArrayBufferViewCore$4 = arrayBufferViewCore;
5220 var typedArraySpeciesConstructor$1 = typedArraySpeciesConstructor$4;
5221 var fails$x = fails$V;
5222 var arraySlice$7 = arraySlice$b;
5224 var aTypedArray$4 = ArrayBufferViewCore$4.aTypedArray;
5225 var exportTypedArrayMethod$5 = ArrayBufferViewCore$4.exportTypedArrayMethod;
5227 var FORCED$e = fails$x(function () {
5228 // eslint-disable-next-line es/no-typed-arrays -- required for testing
5229 new Int8Array(1).slice();
5232 // `%TypedArray%.prototype.slice` method
5233 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.slice
5234 exportTypedArrayMethod$5('slice', function slice(start, end) {
5235 var list = arraySlice$7(aTypedArray$4(this), start, end);
5236 var C = typedArraySpeciesConstructor$1(this);
5238 var length = list.length;
5239 var result = new C(length);
5240 while (length > index) result[index] = list[index++];
5244 var ArrayBufferViewCore$3 = arrayBufferViewCore;
5245 var $some$1 = arrayIteration.some;
5247 var aTypedArray$3 = ArrayBufferViewCore$3.aTypedArray;
5248 var exportTypedArrayMethod$4 = ArrayBufferViewCore$3.exportTypedArrayMethod;
5250 // `%TypedArray%.prototype.some` method
5251 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.some
5252 exportTypedArrayMethod$4('some', function some(callbackfn /* , thisArg */) {
5253 return $some$1(aTypedArray$3(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
5256 var arraySlice$6 = arraySliceSimple;
5258 var floor$4 = Math.floor;
5260 var mergeSort = function (array, comparefn) {
5261 var length = array.length;
5262 var middle = floor$4(length / 2);
5263 return length < 8 ? insertionSort(array, comparefn) : merge$5(
5265 mergeSort(arraySlice$6(array, 0, middle), comparefn),
5266 mergeSort(arraySlice$6(array, middle), comparefn),
5271 var insertionSort = function (array, comparefn) {
5272 var length = array.length;
5276 while (i < length) {
5279 while (j && comparefn(array[j - 1], element) > 0) {
5280 array[j] = array[--j];
5282 if (j !== i++) array[j] = element;
5286 var merge$5 = function (array, left, right, comparefn) {
5287 var llength = left.length;
5288 var rlength = right.length;
5292 while (lindex < llength || rindex < rlength) {
5293 array[lindex + rindex] = (lindex < llength && rindex < rlength)
5294 ? comparefn(left[lindex], right[rindex]) <= 0 ? left[lindex++] : right[rindex++]
5295 : lindex < llength ? left[lindex++] : right[rindex++];
5299 var arraySort$1 = mergeSort;
5301 var userAgent$3 = engineUserAgent;
5303 var firefox = userAgent$3.match(/firefox\/(\d+)/i);
5305 var engineFfVersion = !!firefox && +firefox[1];
5307 var UA = engineUserAgent;
5309 var engineIsIeOrEdge = /MSIE|Trident/.test(UA);
5311 var userAgent$2 = engineUserAgent;
5313 var webkit = userAgent$2.match(/AppleWebKit\/(\d+)\./);
5315 var engineWebkitVersion = !!webkit && +webkit[1];
5317 var global$r = global$1o;
5318 var uncurryThis$x = functionUncurryThis;
5319 var fails$w = fails$V;
5320 var aCallable$3 = aCallable$a;
5321 var internalSort$1 = arraySort$1;
5322 var ArrayBufferViewCore$2 = arrayBufferViewCore;
5323 var FF$1 = engineFfVersion;
5324 var IE_OR_EDGE$1 = engineIsIeOrEdge;
5325 var V8$1 = engineV8Version;
5326 var WEBKIT$1 = engineWebkitVersion;
5328 var Array$3 = global$r.Array;
5329 var aTypedArray$2 = ArrayBufferViewCore$2.aTypedArray;
5330 var exportTypedArrayMethod$3 = ArrayBufferViewCore$2.exportTypedArrayMethod;
5331 var Uint16Array = global$r.Uint16Array;
5332 var un$Sort$1 = Uint16Array && uncurryThis$x(Uint16Array.prototype.sort);
5335 var ACCEPT_INCORRECT_ARGUMENTS = !!un$Sort$1 && !(fails$w(function () {
5336 un$Sort$1(new Uint16Array(2), null);
5337 }) && fails$w(function () {
5338 un$Sort$1(new Uint16Array(2), {});
5341 var STABLE_SORT$1 = !!un$Sort$1 && !fails$w(function () {
5342 // feature detection can be too slow, so check engines versions
5343 if (V8$1) return V8$1 < 74;
5344 if (FF$1) return FF$1 < 67;
5345 if (IE_OR_EDGE$1) return true;
5346 if (WEBKIT$1) return WEBKIT$1 < 602;
5348 var array = new Uint16Array(516);
5349 var expected = Array$3(516);
5352 for (index = 0; index < 516; index++) {
5354 array[index] = 515 - index;
5355 expected[index] = index - 2 * mod + 3;
5358 un$Sort$1(array, function (a, b) {
5359 return (a / 4 | 0) - (b / 4 | 0);
5362 for (index = 0; index < 516; index++) {
5363 if (array[index] !== expected[index]) return true;
5367 var getSortCompare$1 = function (comparefn) {
5368 return function (x, y) {
5369 if (comparefn !== undefined) return +comparefn(x, y) || 0;
5370 // eslint-disable-next-line no-self-compare -- NaN check
5371 if (y !== y) return -1;
5372 // eslint-disable-next-line no-self-compare -- NaN check
5373 if (x !== x) return 1;
5374 if (x === 0 && y === 0) return 1 / x > 0 && 1 / y < 0 ? 1 : -1;
5379 // `%TypedArray%.prototype.sort` method
5380 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort
5381 exportTypedArrayMethod$3('sort', function sort(comparefn) {
5382 if (comparefn !== undefined) aCallable$3(comparefn);
5383 if (STABLE_SORT$1) return un$Sort$1(this, comparefn);
5385 return internalSort$1(aTypedArray$2(this), getSortCompare$1(comparefn));
5386 }, !STABLE_SORT$1 || ACCEPT_INCORRECT_ARGUMENTS);
5388 var ArrayBufferViewCore$1 = arrayBufferViewCore;
5389 var toLength$6 = toLength$c;
5390 var toAbsoluteIndex$3 = toAbsoluteIndex$9;
5391 var typedArraySpeciesConstructor = typedArraySpeciesConstructor$4;
5393 var aTypedArray$1 = ArrayBufferViewCore$1.aTypedArray;
5394 var exportTypedArrayMethod$2 = ArrayBufferViewCore$1.exportTypedArrayMethod;
5396 // `%TypedArray%.prototype.subarray` method
5397 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.subarray
5398 exportTypedArrayMethod$2('subarray', function subarray(begin, end) {
5399 var O = aTypedArray$1(this);
5400 var length = O.length;
5401 var beginIndex = toAbsoluteIndex$3(begin, length);
5402 var C = typedArraySpeciesConstructor(O);
5405 O.byteOffset + beginIndex * O.BYTES_PER_ELEMENT,
5406 toLength$6((end === undefined ? length : toAbsoluteIndex$3(end, length)) - beginIndex)
5410 var global$q = global$1o;
5411 var apply$4 = functionApply;
5412 var ArrayBufferViewCore = arrayBufferViewCore;
5413 var fails$v = fails$V;
5414 var arraySlice$5 = arraySlice$b;
5416 var Int8Array$1 = global$q.Int8Array;
5417 var aTypedArray = ArrayBufferViewCore.aTypedArray;
5418 var exportTypedArrayMethod$1 = ArrayBufferViewCore.exportTypedArrayMethod;
5419 var $toLocaleString = [].toLocaleString;
5421 // iOS Safari 6.x fails here
5422 var TO_LOCALE_STRING_BUG = !!Int8Array$1 && fails$v(function () {
5423 $toLocaleString.call(new Int8Array$1(1));
5426 var FORCED$d = fails$v(function () {
5427 return [1, 2].toLocaleString() != new Int8Array$1([1, 2]).toLocaleString();
5428 }) || !fails$v(function () {
5429 Int8Array$1.prototype.toLocaleString.call([1, 2]);
5432 // `%TypedArray%.prototype.toLocaleString` method
5433 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.tolocalestring
5434 exportTypedArrayMethod$1('toLocaleString', function toLocaleString() {
5437 TO_LOCALE_STRING_BUG ? arraySlice$5(aTypedArray(this)) : aTypedArray(this),
5438 arraySlice$5(arguments)
5442 var exportTypedArrayMethod = arrayBufferViewCore.exportTypedArrayMethod;
5443 var fails$u = fails$V;
5444 var global$p = global$1o;
5445 var uncurryThis$w = functionUncurryThis;
5447 var Uint8Array$1 = global$p.Uint8Array;
5448 var Uint8ArrayPrototype = Uint8Array$1 && Uint8Array$1.prototype || {};
5449 var arrayToString = [].toString;
5450 var join$5 = uncurryThis$w([].join);
5452 if (fails$u(function () { arrayToString.call({}); })) {
5453 arrayToString = function toString() {
5454 return join$5(this);
5458 var IS_NOT_ARRAY_METHOD = Uint8ArrayPrototype.toString != arrayToString;
5460 // `%TypedArray%.prototype.toString` method
5461 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.tostring
5462 exportTypedArrayMethod('toString', arrayToString, IS_NOT_ARRAY_METHOD);
5465 var uncurryThis$v = functionUncurryThis;
5466 var IndexedObject$1 = indexedObject;
5467 var toIndexedObject$3 = toIndexedObject$d;
5468 var arrayMethodIsStrict$5 = arrayMethodIsStrict$9;
5470 var un$Join = uncurryThis$v([].join);
5472 var ES3_STRINGS = IndexedObject$1 != Object;
5473 var STRICT_METHOD$5 = arrayMethodIsStrict$5('join', ',');
5475 // `Array.prototype.join` method
5476 // https://tc39.es/ecma262/#sec-array.prototype.join
5477 $$Z({ target: 'Array', proto: true, forced: ES3_STRINGS || !STRICT_METHOD$5 }, {
5478 join: function join(separator) {
5479 return un$Join(toIndexedObject$3(this), separator === undefined ? ',' : separator);
5484 var global$o = global$1o;
5485 var isArray$4 = isArray$8;
5486 var isConstructor$1 = isConstructor$4;
5487 var isObject$e = isObject$s;
5488 var toAbsoluteIndex$2 = toAbsoluteIndex$9;
5489 var lengthOfArrayLike$6 = lengthOfArrayLike$i;
5490 var toIndexedObject$2 = toIndexedObject$d;
5491 var createProperty$3 = createProperty$5;
5492 var wellKnownSymbol$8 = wellKnownSymbol$t;
5493 var arrayMethodHasSpeciesSupport$3 = arrayMethodHasSpeciesSupport$5;
5494 var un$Slice = arraySlice$b;
5496 var HAS_SPECIES_SUPPORT$2 = arrayMethodHasSpeciesSupport$3('slice');
5498 var SPECIES$1 = wellKnownSymbol$8('species');
5499 var Array$2 = global$o.Array;
5500 var max$3 = Math.max;
5502 // `Array.prototype.slice` method
5503 // https://tc39.es/ecma262/#sec-array.prototype.slice
5504 // fallback for not array-like ES3 strings and DOM objects
5505 $$Y({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$2 }, {
5506 slice: function slice(start, end) {
5507 var O = toIndexedObject$2(this);
5508 var length = lengthOfArrayLike$6(O);
5509 var k = toAbsoluteIndex$2(start, length);
5510 var fin = toAbsoluteIndex$2(end === undefined ? length : end, length);
5511 // inline `ArraySpeciesCreate` for usage native `Array#slice` where it's possible
5512 var Constructor, result, n;
5514 Constructor = O.constructor;
5515 // cross-realm fallback
5516 if (isConstructor$1(Constructor) && (Constructor === Array$2 || isArray$4(Constructor.prototype))) {
5517 Constructor = undefined;
5518 } else if (isObject$e(Constructor)) {
5519 Constructor = Constructor[SPECIES$1];
5520 if (Constructor === null) Constructor = undefined;
5522 if (Constructor === Array$2 || Constructor === undefined) {
5523 return un$Slice(O, k, fin);
5526 result = new (Constructor === undefined ? Array$2 : Constructor)(max$3(fin - k, 0));
5527 for (n = 0; k < fin; k++, n++) if (k in O) createProperty$3(result, n, O[k]);
5533 var fails$t = fails$V;
5534 var wellKnownSymbol$7 = wellKnownSymbol$t;
5535 var IS_PURE = isPure;
5537 var ITERATOR$3 = wellKnownSymbol$7('iterator');
5539 var nativeUrl = !fails$t(function () {
5540 // eslint-disable-next-line unicorn/relative-url-style -- required for testing
5541 var url = new URL('b?a=1&b=2&c=3', 'http://a');
5542 var searchParams = url.searchParams;
5544 url.pathname = 'c%20d';
5545 searchParams.forEach(function (value, key) {
5546 searchParams['delete']('b');
5547 result += key + value;
5549 return (IS_PURE && !url.toJSON)
5550 || !searchParams.sort
5551 || url.href !== 'http://a/c%20d?a=1&c=3'
5552 || searchParams.get('c') !== '3'
5553 || String(new URLSearchParams('?a=1')) !== 'a=1'
5554 || !searchParams[ITERATOR$3]
5556 || new URL('https://a@b').username !== 'a'
5557 || new URLSearchParams(new URLSearchParams('a=b')).get('a') !== 'b'
5558 // not punycoded in Edge
5559 || new URL('http://тест').host !== 'xn--e1aybc'
5560 // not escaped in Chrome 62-
5561 || new URL('http://a#б').hash !== '#%D0%B1'
5562 // fails in Chrome 66-
5563 || result !== 'a1c3'
5565 || new URL('http://x', undefined).host !== 'x';
5568 // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env`
5571 var global$n = global$1o;
5572 var getBuiltIn$2 = getBuiltIn$b;
5573 var call$9 = functionCall;
5574 var uncurryThis$u = functionUncurryThis;
5575 var USE_NATIVE_URL$1 = nativeUrl;
5576 var redefine$7 = redefine$h.exports;
5577 var redefineAll$1 = redefineAll$4;
5578 var setToStringTag$4 = setToStringTag$a;
5579 var createIteratorConstructor = createIteratorConstructor$2;
5580 var InternalStateModule$2 = internalState;
5581 var anInstance$3 = anInstance$7;
5582 var isCallable$5 = isCallable$r;
5583 var hasOwn$6 = hasOwnProperty_1;
5584 var bind$8 = functionBindContext;
5585 var classof$3 = classof$d;
5586 var anObject$9 = anObject$n;
5587 var isObject$d = isObject$s;
5588 var $toString$2 = toString$k;
5589 var create$6 = objectCreate;
5590 var createPropertyDescriptor = createPropertyDescriptor$7;
5591 var getIterator$1 = getIterator$4;
5592 var getIteratorMethod$1 = getIteratorMethod$5;
5593 var validateArgumentsLength$2 = validateArgumentsLength$4;
5594 var wellKnownSymbol$6 = wellKnownSymbol$t;
5595 var arraySort = arraySort$1;
5597 var ITERATOR$2 = wellKnownSymbol$6('iterator');
5598 var URL_SEARCH_PARAMS = 'URLSearchParams';
5599 var URL_SEARCH_PARAMS_ITERATOR = URL_SEARCH_PARAMS + 'Iterator';
5600 var setInternalState$2 = InternalStateModule$2.set;
5601 var getInternalParamsState = InternalStateModule$2.getterFor(URL_SEARCH_PARAMS);
5602 var getInternalIteratorState = InternalStateModule$2.getterFor(URL_SEARCH_PARAMS_ITERATOR);
5604 var n$Fetch = getBuiltIn$2('fetch');
5605 var N$Request = getBuiltIn$2('Request');
5606 var Headers$1 = getBuiltIn$2('Headers');
5607 var RequestPrototype = N$Request && N$Request.prototype;
5608 var HeadersPrototype = Headers$1 && Headers$1.prototype;
5609 var RegExp$1 = global$n.RegExp;
5610 var TypeError$8 = global$n.TypeError;
5611 var decodeURIComponent$1 = global$n.decodeURIComponent;
5612 var encodeURIComponent$1 = global$n.encodeURIComponent;
5613 var charAt$5 = uncurryThis$u(''.charAt);
5614 var join$4 = uncurryThis$u([].join);
5615 var push$7 = uncurryThis$u([].push);
5616 var replace$6 = uncurryThis$u(''.replace);
5617 var shift$1 = uncurryThis$u([].shift);
5618 var splice = uncurryThis$u([].splice);
5619 var split$3 = uncurryThis$u(''.split);
5620 var stringSlice$8 = uncurryThis$u(''.slice);
5623 var sequences = Array(4);
5625 var percentSequence = function (bytes) {
5626 return sequences[bytes - 1] || (sequences[bytes - 1] = RegExp$1('((?:%[\\da-f]{2}){' + bytes + '})', 'gi'));
5629 var percentDecode = function (sequence) {
5631 return decodeURIComponent$1(sequence);
5637 var deserialize = function (it) {
5638 var result = replace$6(it, plus, ' ');
5641 return decodeURIComponent$1(result);
5644 result = replace$6(result, percentSequence(bytes--), percentDecode);
5650 var find$1 = /[!'()~]|%20/g;
5652 var replacements = {
5661 var replacer = function (match) {
5662 return replacements[match];
5665 var serialize = function (it) {
5666 return replace$6(encodeURIComponent$1(it), find$1, replacer);
5669 var URLSearchParamsIterator = createIteratorConstructor(function Iterator(params, kind) {
5670 setInternalState$2(this, {
5671 type: URL_SEARCH_PARAMS_ITERATOR,
5672 iterator: getIterator$1(getInternalParamsState(params).entries),
5675 }, 'Iterator', function next() {
5676 var state = getInternalIteratorState(this);
5677 var kind = state.kind;
5678 var step = state.iterator.next();
5679 var entry = step.value;
5681 step.value = kind === 'keys' ? entry.key : kind === 'values' ? entry.value : [entry.key, entry.value];
5685 var URLSearchParamsState = function (init) {
5689 if (init !== undefined) {
5690 if (isObject$d(init)) this.parseObject(init);
5691 else this.parseQuery(typeof init == 'string' ? charAt$5(init, 0) === '?' ? stringSlice$8(init, 1) : init : $toString$2(init));
5695 URLSearchParamsState.prototype = {
5696 type: URL_SEARCH_PARAMS,
5697 bindURL: function (url) {
5701 parseObject: function (object) {
5702 var iteratorMethod = getIteratorMethod$1(object);
5703 var iterator, next, step, entryIterator, entryNext, first, second;
5705 if (iteratorMethod) {
5706 iterator = getIterator$1(object, iteratorMethod);
5707 next = iterator.next;
5708 while (!(step = call$9(next, iterator)).done) {
5709 entryIterator = getIterator$1(anObject$9(step.value));
5710 entryNext = entryIterator.next;
5712 (first = call$9(entryNext, entryIterator)).done ||
5713 (second = call$9(entryNext, entryIterator)).done ||
5714 !call$9(entryNext, entryIterator).done
5715 ) throw TypeError$8('Expected sequence with length 2');
5716 push$7(this.entries, { key: $toString$2(first.value), value: $toString$2(second.value) });
5718 } else for (var key in object) if (hasOwn$6(object, key)) {
5719 push$7(this.entries, { key: key, value: $toString$2(object[key]) });
5722 parseQuery: function (query) {
5724 var attributes = split$3(query, '&');
5726 var attribute, entry;
5727 while (index < attributes.length) {
5728 attribute = attributes[index++];
5729 if (attribute.length) {
5730 entry = split$3(attribute, '=');
5731 push$7(this.entries, {
5732 key: deserialize(shift$1(entry)),
5733 value: deserialize(join$4(entry, '='))
5739 serialize: function () {
5740 var entries = this.entries;
5744 while (index < entries.length) {
5745 entry = entries[index++];
5746 push$7(result, serialize(entry.key) + '=' + serialize(entry.value));
5747 } return join$4(result, '&');
5749 update: function () {
5750 this.entries.length = 0;
5751 this.parseQuery(this.url.query);
5753 updateURL: function () {
5754 if (this.url) this.url.update();
5758 // `URLSearchParams` constructor
5759 // https://url.spec.whatwg.org/#interface-urlsearchparams
5760 var URLSearchParamsConstructor = function URLSearchParams(/* init */) {
5761 anInstance$3(this, URLSearchParamsPrototype);
5762 var init = arguments.length > 0 ? arguments[0] : undefined;
5763 setInternalState$2(this, new URLSearchParamsState(init));
5766 var URLSearchParamsPrototype = URLSearchParamsConstructor.prototype;
5768 redefineAll$1(URLSearchParamsPrototype, {
5769 // `URLSearchParams.prototype.append` method
5770 // https://url.spec.whatwg.org/#dom-urlsearchparams-append
5771 append: function append(name, value) {
5772 validateArgumentsLength$2(arguments.length, 2);
5773 var state = getInternalParamsState(this);
5774 push$7(state.entries, { key: $toString$2(name), value: $toString$2(value) });
5777 // `URLSearchParams.prototype.delete` method
5778 // https://url.spec.whatwg.org/#dom-urlsearchparams-delete
5779 'delete': function (name) {
5780 validateArgumentsLength$2(arguments.length, 1);
5781 var state = getInternalParamsState(this);
5782 var entries = state.entries;
5783 var key = $toString$2(name);
5785 while (index < entries.length) {
5786 if (entries[index].key === key) splice(entries, index, 1);
5791 // `URLSearchParams.prototype.get` method
5792 // https://url.spec.whatwg.org/#dom-urlsearchparams-get
5793 get: function get(name) {
5794 validateArgumentsLength$2(arguments.length, 1);
5795 var entries = getInternalParamsState(this).entries;
5796 var key = $toString$2(name);
5798 for (; index < entries.length; index++) {
5799 if (entries[index].key === key) return entries[index].value;
5803 // `URLSearchParams.prototype.getAll` method
5804 // https://url.spec.whatwg.org/#dom-urlsearchparams-getall
5805 getAll: function getAll(name) {
5806 validateArgumentsLength$2(arguments.length, 1);
5807 var entries = getInternalParamsState(this).entries;
5808 var key = $toString$2(name);
5811 for (; index < entries.length; index++) {
5812 if (entries[index].key === key) push$7(result, entries[index].value);
5816 // `URLSearchParams.prototype.has` method
5817 // https://url.spec.whatwg.org/#dom-urlsearchparams-has
5818 has: function has(name) {
5819 validateArgumentsLength$2(arguments.length, 1);
5820 var entries = getInternalParamsState(this).entries;
5821 var key = $toString$2(name);
5823 while (index < entries.length) {
5824 if (entries[index++].key === key) return true;
5828 // `URLSearchParams.prototype.set` method
5829 // https://url.spec.whatwg.org/#dom-urlsearchparams-set
5830 set: function set(name, value) {
5831 validateArgumentsLength$2(arguments.length, 1);
5832 var state = getInternalParamsState(this);
5833 var entries = state.entries;
5835 var key = $toString$2(name);
5836 var val = $toString$2(value);
5839 for (; index < entries.length; index++) {
5840 entry = entries[index];
5841 if (entry.key === key) {
5842 if (found) splice(entries, index--, 1);
5849 if (!found) push$7(entries, { key: key, value: val });
5852 // `URLSearchParams.prototype.sort` method
5853 // https://url.spec.whatwg.org/#dom-urlsearchparams-sort
5854 sort: function sort() {
5855 var state = getInternalParamsState(this);
5856 arraySort(state.entries, function (a, b) {
5857 return a.key > b.key ? 1 : -1;
5861 // `URLSearchParams.prototype.forEach` method
5862 forEach: function forEach(callback /* , thisArg */) {
5863 var entries = getInternalParamsState(this).entries;
5864 var boundFunction = bind$8(callback, arguments.length > 1 ? arguments[1] : undefined);
5867 while (index < entries.length) {
5868 entry = entries[index++];
5869 boundFunction(entry.value, entry.key, this);
5872 // `URLSearchParams.prototype.keys` method
5873 keys: function keys() {
5874 return new URLSearchParamsIterator(this, 'keys');
5876 // `URLSearchParams.prototype.values` method
5877 values: function values() {
5878 return new URLSearchParamsIterator(this, 'values');
5880 // `URLSearchParams.prototype.entries` method
5881 entries: function entries() {
5882 return new URLSearchParamsIterator(this, 'entries');
5884 }, { enumerable: true });
5886 // `URLSearchParams.prototype[@@iterator]` method
5887 redefine$7(URLSearchParamsPrototype, ITERATOR$2, URLSearchParamsPrototype.entries, { name: 'entries' });
5889 // `URLSearchParams.prototype.toString` method
5890 // https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior
5891 redefine$7(URLSearchParamsPrototype, 'toString', function toString() {
5892 return getInternalParamsState(this).serialize();
5893 }, { enumerable: true });
5895 setToStringTag$4(URLSearchParamsConstructor, URL_SEARCH_PARAMS);
5897 $$X({ global: true, forced: !USE_NATIVE_URL$1 }, {
5898 URLSearchParams: URLSearchParamsConstructor
5901 // Wrap `fetch` and `Request` for correct work with polyfilled `URLSearchParams`
5902 if (!USE_NATIVE_URL$1 && isCallable$5(Headers$1)) {
5903 var headersHas = uncurryThis$u(HeadersPrototype.has);
5904 var headersSet = uncurryThis$u(HeadersPrototype.set);
5906 var wrapRequestOptions = function (init) {
5907 if (isObject$d(init)) {
5908 var body = init.body;
5910 if (classof$3(body) === URL_SEARCH_PARAMS) {
5911 headers = init.headers ? new Headers$1(init.headers) : new Headers$1();
5912 if (!headersHas(headers, 'content-type')) {
5913 headersSet(headers, 'content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
5915 return create$6(init, {
5916 body: createPropertyDescriptor(0, $toString$2(body)),
5917 headers: createPropertyDescriptor(0, headers)
5923 if (isCallable$5(n$Fetch)) {
5924 $$X({ global: true, enumerable: true, forced: true }, {
5925 fetch: function fetch(input /* , init */) {
5926 return n$Fetch(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {});
5931 if (isCallable$5(N$Request)) {
5932 var RequestConstructor = function Request(input /* , init */) {
5933 anInstance$3(this, RequestPrototype);
5934 return new N$Request(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {});
5937 RequestPrototype.constructor = RequestConstructor;
5938 RequestConstructor.prototype = RequestPrototype;
5940 $$X({ global: true, forced: true }, {
5941 Request: RequestConstructor
5946 var web_urlSearchParams = {
5947 URLSearchParams: URLSearchParamsConstructor,
5948 getState: getInternalParamsState
5951 var uncurryThis$t = functionUncurryThis;
5952 var PROPER_FUNCTION_NAME$1 = functionName.PROPER;
5953 var redefine$6 = redefine$h.exports;
5954 var anObject$8 = anObject$n;
5955 var isPrototypeOf$2 = objectIsPrototypeOf;
5956 var $toString$1 = toString$k;
5957 var fails$s = fails$V;
5958 var regExpFlags$2 = regexpFlags$1;
5960 var TO_STRING = 'toString';
5961 var RegExpPrototype$3 = RegExp.prototype;
5962 var n$ToString = RegExpPrototype$3[TO_STRING];
5963 var getFlags$1 = uncurryThis$t(regExpFlags$2);
5965 var NOT_GENERIC = fails$s(function () { return n$ToString.call({ source: 'a', flags: 'b' }) != '/a/b'; });
5966 // FF44- RegExp#toString has a wrong name
5967 var INCORRECT_NAME = PROPER_FUNCTION_NAME$1 && n$ToString.name != TO_STRING;
5969 // `RegExp.prototype.toString` method
5970 // https://tc39.es/ecma262/#sec-regexp.prototype.tostring
5971 if (NOT_GENERIC || INCORRECT_NAME) {
5972 redefine$6(RegExp.prototype, TO_STRING, function toString() {
5973 var R = anObject$8(this);
5974 var p = $toString$1(R.source);
5976 var f = $toString$1(rf === undefined && isPrototypeOf$2(RegExpPrototype$3, R) && !('flags' in RegExpPrototype$3) ? getFlags$1(R) : rf);
5977 return '/' + p + '/' + f;
5978 }, { unsafe: true });
5981 // TODO: Remove from `core-js@4` since it's moved to entry points
5983 var uncurryThis$s = functionUncurryThis;
5984 var redefine$5 = redefine$h.exports;
5985 var regexpExec$2 = regexpExec$3;
5986 var fails$r = fails$V;
5987 var wellKnownSymbol$5 = wellKnownSymbol$t;
5988 var createNonEnumerableProperty$1 = createNonEnumerableProperty$b;
5990 var SPECIES = wellKnownSymbol$5('species');
5991 var RegExpPrototype$2 = RegExp.prototype;
5993 var fixRegexpWellKnownSymbolLogic = function (KEY, exec, FORCED, SHAM) {
5994 var SYMBOL = wellKnownSymbol$5(KEY);
5996 var DELEGATES_TO_SYMBOL = !fails$r(function () {
5997 // String methods call symbol-named RegEp methods
5999 O[SYMBOL] = function () { return 7; };
6000 return ''[KEY](O) != 7;
6003 var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails$r(function () {
6004 // Symbol-named RegExp methods call .exec
6005 var execCalled = false;
6008 if (KEY === 'split') {
6009 // We can't use real regex here since it causes deoptimization
6010 // and serious performance degradation in V8
6011 // https://github.com/zloirock/core-js/issues/306
6013 // RegExp[@@split] doesn't call the regex's exec method, but first creates
6014 // a new one. We need to return the patched regex when creating the new one.
6015 re.constructor = {};
6016 re.constructor[SPECIES] = function () { return re; };
6018 re[SYMBOL] = /./[SYMBOL];
6021 re.exec = function () { execCalled = true; return null; };
6028 !DELEGATES_TO_SYMBOL ||
6029 !DELEGATES_TO_EXEC ||
6032 var uncurriedNativeRegExpMethod = uncurryThis$s(/./[SYMBOL]);
6033 var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) {
6034 var uncurriedNativeMethod = uncurryThis$s(nativeMethod);
6035 var $exec = regexp.exec;
6036 if ($exec === regexpExec$2 || $exec === RegExpPrototype$2.exec) {
6037 if (DELEGATES_TO_SYMBOL && !forceStringMethod) {
6038 // The native String method already delegates to @@method (this
6039 // polyfilled function), leasing to infinite recursion.
6040 // We avoid it by directly calling the native @@method method.
6041 return { done: true, value: uncurriedNativeRegExpMethod(regexp, str, arg2) };
6043 return { done: true, value: uncurriedNativeMethod(str, regexp, arg2) };
6045 return { done: false };
6048 redefine$5(String.prototype, KEY, methods[0]);
6049 redefine$5(RegExpPrototype$2, SYMBOL, methods[1]);
6052 if (SHAM) createNonEnumerableProperty$1(RegExpPrototype$2[SYMBOL], 'sham', true);
6055 var charAt$4 = stringMultibyte.charAt;
6057 // `AdvanceStringIndex` abstract operation
6058 // https://tc39.es/ecma262/#sec-advancestringindex
6059 var advanceStringIndex$3 = function (S, index, unicode) {
6060 return index + (unicode ? charAt$4(S, index).length : 1);
6063 var uncurryThis$r = functionUncurryThis;
6064 var toObject$9 = toObject$i;
6066 var floor$3 = Math.floor;
6067 var charAt$3 = uncurryThis$r(''.charAt);
6068 var replace$5 = uncurryThis$r(''.replace);
6069 var stringSlice$7 = uncurryThis$r(''.slice);
6070 var SUBSTITUTION_SYMBOLS = /\$([$&'`]|\d{1,2}|<[^>]*>)/g;
6071 var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&'`]|\d{1,2})/g;
6073 // `GetSubstitution` abstract operation
6074 // https://tc39.es/ecma262/#sec-getsubstitution
6075 var getSubstitution$1 = function (matched, str, position, captures, namedCaptures, replacement) {
6076 var tailPos = position + matched.length;
6077 var m = captures.length;
6078 var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;
6079 if (namedCaptures !== undefined) {
6080 namedCaptures = toObject$9(namedCaptures);
6081 symbols = SUBSTITUTION_SYMBOLS;
6083 return replace$5(replacement, symbols, function (match, ch) {
6085 switch (charAt$3(ch, 0)) {
6086 case '$': return '$';
6087 case '&': return matched;
6088 case '`': return stringSlice$7(str, 0, position);
6089 case "'": return stringSlice$7(str, tailPos);
6091 capture = namedCaptures[stringSlice$7(ch, 1, -1)];
6095 if (n === 0) return match;
6097 var f = floor$3(n / 10);
6098 if (f === 0) return match;
6099 if (f <= m) return captures[f - 1] === undefined ? charAt$3(ch, 1) : captures[f - 1] + charAt$3(ch, 1);
6102 capture = captures[n - 1];
6104 return capture === undefined ? '' : capture;
6108 var global$m = global$1o;
6109 var call$8 = functionCall;
6110 var anObject$7 = anObject$n;
6111 var isCallable$4 = isCallable$r;
6112 var classof$2 = classofRaw$1;
6113 var regexpExec$1 = regexpExec$3;
6115 var TypeError$7 = global$m.TypeError;
6117 // `RegExpExec` abstract operation
6118 // https://tc39.es/ecma262/#sec-regexpexec
6119 var regexpExecAbstract = function (R, S) {
6121 if (isCallable$4(exec)) {
6122 var result = call$8(exec, R, S);
6123 if (result !== null) anObject$7(result);
6126 if (classof$2(R) === 'RegExp') return call$8(regexpExec$1, R, S);
6127 throw TypeError$7('RegExp#exec called on incompatible receiver');
6130 var apply$3 = functionApply;
6131 var call$7 = functionCall;
6132 var uncurryThis$q = functionUncurryThis;
6133 var fixRegExpWellKnownSymbolLogic$3 = fixRegexpWellKnownSymbolLogic;
6134 var fails$q = fails$V;
6135 var anObject$6 = anObject$n;
6136 var isCallable$3 = isCallable$r;
6137 var toIntegerOrInfinity$3 = toIntegerOrInfinity$b;
6138 var toLength$5 = toLength$c;
6139 var toString$f = toString$k;
6140 var requireObjectCoercible$a = requireObjectCoercible$e;
6141 var advanceStringIndex$2 = advanceStringIndex$3;
6142 var getMethod$3 = getMethod$7;
6143 var getSubstitution = getSubstitution$1;
6144 var regExpExec$3 = regexpExecAbstract;
6145 var wellKnownSymbol$4 = wellKnownSymbol$t;
6147 var REPLACE = wellKnownSymbol$4('replace');
6148 var max$2 = Math.max;
6149 var min$5 = Math.min;
6150 var concat$2 = uncurryThis$q([].concat);
6151 var push$6 = uncurryThis$q([].push);
6152 var stringIndexOf$2 = uncurryThis$q(''.indexOf);
6153 var stringSlice$6 = uncurryThis$q(''.slice);
6155 var maybeToString = function (it) {
6156 return it === undefined ? it : String(it);
6159 // IE <= 11 replaces $0 with the whole match, as if it was $&
6160 // https://stackoverflow.com/questions/6024666/getting-ie-to-replace-a-regex-with-the-literal-string-0
6161 var REPLACE_KEEPS_$0 = (function () {
6162 // eslint-disable-next-line regexp/prefer-escape-replacement-dollar-char -- required for testing
6163 return 'a'.replace(/./, '$0') === '$0';
6166 // Safari <= 13.0.3(?) substitutes nth capture where n>m with an empty string
6167 var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = (function () {
6169 return /./[REPLACE]('a', '$0') === '';
6174 var REPLACE_SUPPORTS_NAMED_GROUPS = !fails$q(function () {
6176 re.exec = function () {
6178 result.groups = { a: '7' };
6181 // eslint-disable-next-line regexp/no-useless-dollar-replacements -- false positive
6182 return ''.replace(re, '$<a>') !== '7';
6186 fixRegExpWellKnownSymbolLogic$3('replace', function (_, nativeReplace, maybeCallNative) {
6187 var UNSAFE_SUBSTITUTE = REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE ? '$' : '$0';
6190 // `String.prototype.replace` method
6191 // https://tc39.es/ecma262/#sec-string.prototype.replace
6192 function replace(searchValue, replaceValue) {
6193 var O = requireObjectCoercible$a(this);
6194 var replacer = searchValue == undefined ? undefined : getMethod$3(searchValue, REPLACE);
6196 ? call$7(replacer, searchValue, O, replaceValue)
6197 : call$7(nativeReplace, toString$f(O), searchValue, replaceValue);
6199 // `RegExp.prototype[@@replace]` method
6200 // https://tc39.es/ecma262/#sec-regexp.prototype-@@replace
6201 function (string, replaceValue) {
6202 var rx = anObject$6(this);
6203 var S = toString$f(string);
6206 typeof replaceValue == 'string' &&
6207 stringIndexOf$2(replaceValue, UNSAFE_SUBSTITUTE) === -1 &&
6208 stringIndexOf$2(replaceValue, '$<') === -1
6210 var res = maybeCallNative(nativeReplace, rx, S, replaceValue);
6211 if (res.done) return res.value;
6214 var functionalReplace = isCallable$3(replaceValue);
6215 if (!functionalReplace) replaceValue = toString$f(replaceValue);
6217 var global = rx.global;
6219 var fullUnicode = rx.unicode;
6224 var result = regExpExec$3(rx, S);
6225 if (result === null) break;
6227 push$6(results, result);
6230 var matchStr = toString$f(result[0]);
6231 if (matchStr === '') rx.lastIndex = advanceStringIndex$2(S, toLength$5(rx.lastIndex), fullUnicode);
6234 var accumulatedResult = '';
6235 var nextSourcePosition = 0;
6236 for (var i = 0; i < results.length; i++) {
6237 result = results[i];
6239 var matched = toString$f(result[0]);
6240 var position = max$2(min$5(toIntegerOrInfinity$3(result.index), S.length), 0);
6242 // NOTE: This is equivalent to
6243 // captures = result.slice(1).map(maybeToString)
6244 // but for some reason `nativeSlice.call(result, 1, result.length)` (called in
6245 // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and
6246 // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it.
6247 for (var j = 1; j < result.length; j++) push$6(captures, maybeToString(result[j]));
6248 var namedCaptures = result.groups;
6249 if (functionalReplace) {
6250 var replacerArgs = concat$2([matched], captures, position, S);
6251 if (namedCaptures !== undefined) push$6(replacerArgs, namedCaptures);
6252 var replacement = toString$f(apply$3(replaceValue, undefined, replacerArgs));
6254 replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue);
6256 if (position >= nextSourcePosition) {
6257 accumulatedResult += stringSlice$6(S, nextSourcePosition, position) + replacement;
6258 nextSourcePosition = position + matched.length;
6261 return accumulatedResult + stringSlice$6(S, nextSourcePosition);
6264 }, !REPLACE_SUPPORTS_NAMED_GROUPS || !REPLACE_KEEPS_$0 || REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE);
6266 var isObject$c = isObject$s;
6267 var classof$1 = classofRaw$1;
6268 var wellKnownSymbol$3 = wellKnownSymbol$t;
6270 var MATCH$2 = wellKnownSymbol$3('match');
6272 // `IsRegExp` abstract operation
6273 // https://tc39.es/ecma262/#sec-isregexp
6274 var isRegexp = function (it) {
6276 return isObject$c(it) && ((isRegExp = it[MATCH$2]) !== undefined ? !!isRegExp : classof$1(it) == 'RegExp');
6279 var apply$2 = functionApply;
6280 var call$6 = functionCall;
6281 var uncurryThis$p = functionUncurryThis;
6282 var fixRegExpWellKnownSymbolLogic$2 = fixRegexpWellKnownSymbolLogic;
6283 var isRegExp$2 = isRegexp;
6284 var anObject$5 = anObject$n;
6285 var requireObjectCoercible$9 = requireObjectCoercible$e;
6286 var speciesConstructor$1 = speciesConstructor$5;
6287 var advanceStringIndex$1 = advanceStringIndex$3;
6288 var toLength$4 = toLength$c;
6289 var toString$e = toString$k;
6290 var getMethod$2 = getMethod$7;
6291 var arraySlice$4 = arraySliceSimple;
6292 var callRegExpExec = regexpExecAbstract;
6293 var regexpExec = regexpExec$3;
6294 var stickyHelpers$1 = regexpStickyHelpers;
6295 var fails$p = fails$V;
6297 var UNSUPPORTED_Y$1 = stickyHelpers$1.UNSUPPORTED_Y;
6298 var MAX_UINT32 = 0xFFFFFFFF;
6299 var min$4 = Math.min;
6300 var $push = [].push;
6301 var exec$4 = uncurryThis$p(/./.exec);
6302 var push$5 = uncurryThis$p($push);
6303 var stringSlice$5 = uncurryThis$p(''.slice);
6305 // Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec
6306 // Weex JS has frozen built-in prototypes, so use try / catch wrapper
6307 var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = !fails$p(function () {
6308 // eslint-disable-next-line regexp/no-empty-group -- required for testing
6310 var originalExec = re.exec;
6311 re.exec = function () { return originalExec.apply(this, arguments); };
6312 var result = 'ab'.split(re);
6313 return result.length !== 2 || result[0] !== 'a' || result[1] !== 'b';
6317 fixRegExpWellKnownSymbolLogic$2('split', function (SPLIT, nativeSplit, maybeCallNative) {
6320 'abbc'.split(/(b)*/)[1] == 'c' ||
6321 // eslint-disable-next-line regexp/no-empty-group -- required for testing
6322 'test'.split(/(?:)/, -1).length != 4 ||
6323 'ab'.split(/(?:ab)*/).length != 2 ||
6324 '.'.split(/(.?)(.?)/).length != 4 ||
6325 // eslint-disable-next-line regexp/no-empty-capturing-group, regexp/no-empty-group -- required for testing
6326 '.'.split(/()()/).length > 1 ||
6327 ''.split(/.?/).length
6329 // based on es5-shim implementation, need to rework it
6330 internalSplit = function (separator, limit) {
6331 var string = toString$e(requireObjectCoercible$9(this));
6332 var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
6333 if (lim === 0) return [];
6334 if (separator === undefined) return [string];
6335 // If `separator` is not a regex, use native split
6336 if (!isRegExp$2(separator)) {
6337 return call$6(nativeSplit, string, separator, lim);
6340 var flags = (separator.ignoreCase ? 'i' : '') +
6341 (separator.multiline ? 'm' : '') +
6342 (separator.unicode ? 'u' : '') +
6343 (separator.sticky ? 'y' : '');
6344 var lastLastIndex = 0;
6345 // Make `global` and avoid `lastIndex` issues by working with a copy
6346 var separatorCopy = new RegExp(separator.source, flags + 'g');
6347 var match, lastIndex, lastLength;
6348 while (match = call$6(regexpExec, separatorCopy, string)) {
6349 lastIndex = separatorCopy.lastIndex;
6350 if (lastIndex > lastLastIndex) {
6351 push$5(output, stringSlice$5(string, lastLastIndex, match.index));
6352 if (match.length > 1 && match.index < string.length) apply$2($push, output, arraySlice$4(match, 1));
6353 lastLength = match[0].length;
6354 lastLastIndex = lastIndex;
6355 if (output.length >= lim) break;
6357 if (separatorCopy.lastIndex === match.index) separatorCopy.lastIndex++; // Avoid an infinite loop
6359 if (lastLastIndex === string.length) {
6360 if (lastLength || !exec$4(separatorCopy, '')) push$5(output, '');
6361 } else push$5(output, stringSlice$5(string, lastLastIndex));
6362 return output.length > lim ? arraySlice$4(output, 0, lim) : output;
6365 } else if ('0'.split(undefined, 0).length) {
6366 internalSplit = function (separator, limit) {
6367 return separator === undefined && limit === 0 ? [] : call$6(nativeSplit, this, separator, limit);
6369 } else internalSplit = nativeSplit;
6372 // `String.prototype.split` method
6373 // https://tc39.es/ecma262/#sec-string.prototype.split
6374 function split(separator, limit) {
6375 var O = requireObjectCoercible$9(this);
6376 var splitter = separator == undefined ? undefined : getMethod$2(separator, SPLIT);
6378 ? call$6(splitter, separator, O, limit)
6379 : call$6(internalSplit, toString$e(O), separator, limit);
6381 // `RegExp.prototype[@@split]` method
6382 // https://tc39.es/ecma262/#sec-regexp.prototype-@@split
6384 // NOTE: This cannot be properly polyfilled in engines that don't support
6386 function (string, limit) {
6387 var rx = anObject$5(this);
6388 var S = toString$e(string);
6389 var res = maybeCallNative(internalSplit, rx, S, limit, internalSplit !== nativeSplit);
6391 if (res.done) return res.value;
6393 var C = speciesConstructor$1(rx, RegExp);
6395 var unicodeMatching = rx.unicode;
6396 var flags = (rx.ignoreCase ? 'i' : '') +
6397 (rx.multiline ? 'm' : '') +
6398 (rx.unicode ? 'u' : '') +
6399 (UNSUPPORTED_Y$1 ? 'g' : 'y');
6401 // ^(? + rx + ) is needed, in combination with some S slicing, to
6402 // simulate the 'y' flag.
6403 var splitter = new C(UNSUPPORTED_Y$1 ? '^(?:' + rx.source + ')' : rx, flags);
6404 var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
6405 if (lim === 0) return [];
6406 if (S.length === 0) return callRegExpExec(splitter, S) === null ? [S] : [];
6410 while (q < S.length) {
6411 splitter.lastIndex = UNSUPPORTED_Y$1 ? 0 : q;
6412 var z = callRegExpExec(splitter, UNSUPPORTED_Y$1 ? stringSlice$5(S, q) : S);
6416 (e = min$4(toLength$4(splitter.lastIndex + (UNSUPPORTED_Y$1 ? q : 0)), S.length)) === p
6418 q = advanceStringIndex$1(S, q, unicodeMatching);
6420 push$5(A, stringSlice$5(S, p, q));
6421 if (A.length === lim) return A;
6422 for (var i = 1; i <= z.length - 1; i++) {
6424 if (A.length === lim) return A;
6429 push$5(A, stringSlice$5(S, p));
6433 }, !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC, UNSUPPORTED_Y$1);
6435 // a string of all valid unicode whitespaces
6436 var whitespaces$4 = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002' +
6437 '\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF';
6439 var uncurryThis$o = functionUncurryThis;
6440 var requireObjectCoercible$8 = requireObjectCoercible$e;
6441 var toString$d = toString$k;
6442 var whitespaces$3 = whitespaces$4;
6444 var replace$4 = uncurryThis$o(''.replace);
6445 var whitespace = '[' + whitespaces$3 + ']';
6446 var ltrim = RegExp('^' + whitespace + whitespace + '*');
6447 var rtrim$2 = RegExp(whitespace + whitespace + '*$');
6449 // `String.prototype.{ trim, trimStart, trimEnd, trimLeft, trimRight }` methods implementation
6450 var createMethod$2 = function (TYPE) {
6451 return function ($this) {
6452 var string = toString$d(requireObjectCoercible$8($this));
6453 if (TYPE & 1) string = replace$4(string, ltrim, '');
6454 if (TYPE & 2) string = replace$4(string, rtrim$2, '');
6460 // `String.prototype.{ trimLeft, trimStart }` methods
6461 // https://tc39.es/ecma262/#sec-string.prototype.trimstart
6462 start: createMethod$2(1),
6463 // `String.prototype.{ trimRight, trimEnd }` methods
6464 // https://tc39.es/ecma262/#sec-string.prototype.trimend
6465 end: createMethod$2(2),
6466 // `String.prototype.trim` method
6467 // https://tc39.es/ecma262/#sec-string.prototype.trim
6468 trim: createMethod$2(3)
6471 var PROPER_FUNCTION_NAME = functionName.PROPER;
6472 var fails$o = fails$V;
6473 var whitespaces$2 = whitespaces$4;
6475 var non = '\u200B\u0085\u180E';
6477 // check that a method works with the correct list
6478 // of whitespaces and has a correct name
6479 var stringTrimForced = function (METHOD_NAME) {
6480 return fails$o(function () {
6481 return !!whitespaces$2[METHOD_NAME]()
6482 || non[METHOD_NAME]() !== non
6483 || (PROPER_FUNCTION_NAME && whitespaces$2[METHOD_NAME].name !== METHOD_NAME);
6488 var $trim = stringTrim.trim;
6489 var forcedStringTrimMethod$2 = stringTrimForced;
6491 // `String.prototype.trim` method
6492 // https://tc39.es/ecma262/#sec-string.prototype.trim
6493 $$W({ target: 'String', proto: true, forced: forcedStringTrimMethod$2('trim') }, {
6494 trim: function trim() {
6499 var DESCRIPTORS$b = descriptors;
6500 var FUNCTION_NAME_EXISTS = functionName.EXISTS;
6501 var uncurryThis$n = functionUncurryThis;
6502 var defineProperty$6 = objectDefineProperty.f;
6504 var FunctionPrototype = Function.prototype;
6505 var functionToString = uncurryThis$n(FunctionPrototype.toString);
6506 var nameRE = /function\b(?:\s|\/\*[\S\s]*?\*\/|\/\/[^\n\r]*[\n\r]+)*([^\s(/]*)/;
6507 var regExpExec$2 = uncurryThis$n(nameRE.exec);
6510 // Function instances `.name` property
6511 // https://tc39.es/ecma262/#sec-function-instances-name
6512 if (DESCRIPTORS$b && !FUNCTION_NAME_EXISTS) {
6513 defineProperty$6(FunctionPrototype, NAME, {
6517 return regExpExec$2(nameRE, functionToString(this))[1];
6526 var DESCRIPTORS$a = descriptors;
6527 var create$5 = objectCreate;
6529 // `Object.create` method
6530 // https://tc39.es/ecma262/#sec-object.create
6531 $$V({ target: 'Object', stat: true, sham: !DESCRIPTORS$a }, {
6536 var global$l = global$1o;
6537 var apply$1 = functionApply;
6538 var isCallable$2 = isCallable$r;
6539 var userAgent$1 = engineUserAgent;
6540 var arraySlice$3 = arraySlice$b;
6541 var validateArgumentsLength$1 = validateArgumentsLength$4;
6543 var MSIE = /MSIE .\./.test(userAgent$1); // <- dirty ie9- check
6544 var Function$2 = global$l.Function;
6546 var wrap$1 = function (scheduler) {
6547 return function (handler, timeout /* , ...arguments */) {
6548 var boundArgs = validateArgumentsLength$1(arguments.length, 1) > 2;
6549 var fn = isCallable$2(handler) ? handler : Function$2(handler);
6550 var args = boundArgs ? arraySlice$3(arguments, 2) : undefined;
6551 return scheduler(boundArgs ? function () {
6552 apply$1(fn, this, args);
6557 // ie9- setTimeout & setInterval additional parameters fix
6558 // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
6559 $$U({ global: true, bind: true, forced: MSIE }, {
6560 // `setTimeout` method
6561 // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout
6562 setTimeout: wrap$1(global$l.setTimeout),
6563 // `setInterval` method
6564 // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
6565 setInterval: wrap$1(global$l.setInterval)
6568 var global$k = typeof globalThis !== 'undefined' && globalThis || typeof self !== 'undefined' && self || typeof global$k !== 'undefined' && global$k;
6570 searchParams: 'URLSearchParams' in global$k,
6571 iterable: 'Symbol' in global$k && 'iterator' in Symbol,
6572 blob: 'FileReader' in global$k && 'Blob' in global$k && function () {
6580 formData: 'FormData' in global$k,
6581 arrayBuffer: 'ArrayBuffer' in global$k
6584 function isDataView(obj) {
6585 return obj && DataView.prototype.isPrototypeOf(obj);
6588 if (support.arrayBuffer) {
6589 var viewClasses = ['[object Int8Array]', '[object Uint8Array]', '[object Uint8ClampedArray]', '[object Int16Array]', '[object Uint16Array]', '[object Int32Array]', '[object Uint32Array]', '[object Float32Array]', '[object Float64Array]'];
6591 var isArrayBufferView = ArrayBuffer.isView || function (obj) {
6592 return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1;
6596 function normalizeName(name) {
6597 if (typeof name !== 'string') {
6598 name = String(name);
6601 if (/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(name) || name === '') {
6602 throw new TypeError('Invalid character in header field name: "' + name + '"');
6605 return name.toLowerCase();
6608 function normalizeValue(value) {
6609 if (typeof value !== 'string') {
6610 value = String(value);
6614 } // Build a destructive iterator for the value list
6617 function iteratorFor(items) {
6619 next: function next() {
6620 var value = items.shift();
6622 done: value === undefined,
6628 if (support.iterable) {
6629 iterator[Symbol.iterator] = function () {
6637 function Headers(headers) {
6640 if (headers instanceof Headers) {
6641 headers.forEach(function (value, name) {
6642 this.append(name, value);
6644 } else if (Array.isArray(headers)) {
6645 headers.forEach(function (header) {
6646 this.append(header[0], header[1]);
6648 } else if (headers) {
6649 Object.getOwnPropertyNames(headers).forEach(function (name) {
6650 this.append(name, headers[name]);
6655 Headers.prototype.append = function (name, value) {
6656 name = normalizeName(name);
6657 value = normalizeValue(value);
6658 var oldValue = this.map[name];
6659 this.map[name] = oldValue ? oldValue + ', ' + value : value;
6662 Headers.prototype['delete'] = function (name) {
6663 delete this.map[normalizeName(name)];
6666 Headers.prototype.get = function (name) {
6667 name = normalizeName(name);
6668 return this.has(name) ? this.map[name] : null;
6671 Headers.prototype.has = function (name) {
6672 return this.map.hasOwnProperty(normalizeName(name));
6675 Headers.prototype.set = function (name, value) {
6676 this.map[normalizeName(name)] = normalizeValue(value);
6679 Headers.prototype.forEach = function (callback, thisArg) {
6680 for (var name in this.map) {
6681 if (this.map.hasOwnProperty(name)) {
6682 callback.call(thisArg, this.map[name], name, this);
6687 Headers.prototype.keys = function () {
6689 this.forEach(function (value, name) {
6692 return iteratorFor(items);
6695 Headers.prototype.values = function () {
6697 this.forEach(function (value) {
6700 return iteratorFor(items);
6703 Headers.prototype.entries = function () {
6705 this.forEach(function (value, name) {
6706 items.push([name, value]);
6708 return iteratorFor(items);
6711 if (support.iterable) {
6712 Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
6715 function consumed(body) {
6716 if (body.bodyUsed) {
6717 return Promise.reject(new TypeError('Already read'));
6720 body.bodyUsed = true;
6723 function fileReaderReady(reader) {
6724 return new Promise(function (resolve, reject) {
6725 reader.onload = function () {
6726 resolve(reader.result);
6729 reader.onerror = function () {
6730 reject(reader.error);
6735 function readBlobAsArrayBuffer(blob) {
6736 var reader = new FileReader();
6737 var promise = fileReaderReady(reader);
6738 reader.readAsArrayBuffer(blob);
6742 function readBlobAsText(blob) {
6743 var reader = new FileReader();
6744 var promise = fileReaderReady(reader);
6745 reader.readAsText(blob);
6749 function readArrayBufferAsText(buf) {
6750 var view = new Uint8Array(buf);
6751 var chars = new Array(view.length);
6753 for (var i = 0; i < view.length; i++) {
6754 chars[i] = String.fromCharCode(view[i]);
6757 return chars.join('');
6760 function bufferClone(buf) {
6762 return buf.slice(0);
6764 var view = new Uint8Array(buf.byteLength);
6765 view.set(new Uint8Array(buf));
6771 this.bodyUsed = false;
6773 this._initBody = function (body) {
6775 fetch-mock wraps the Response object in an ES6 Proxy to
6776 provide useful test harness features such as flush. However, on
6777 ES5 browsers without fetch or Proxy support pollyfills must be used;
6778 the proxy-pollyfill is unable to proxy an attribute unless it exists
6779 on the object before the Proxy is created. This change ensures
6780 Response.bodyUsed exists on the instance, while maintaining the
6781 semantic of setting Request.bodyUsed in the constructor before
6782 _initBody is called.
6784 this.bodyUsed = this.bodyUsed;
6785 this._bodyInit = body;
6788 this._bodyText = '';
6789 } else if (typeof body === 'string') {
6790 this._bodyText = body;
6791 } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
6792 this._bodyBlob = body;
6793 } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
6794 this._bodyFormData = body;
6795 } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
6796 this._bodyText = body.toString();
6797 } else if (support.arrayBuffer && support.blob && isDataView(body)) {
6798 this._bodyArrayBuffer = bufferClone(body.buffer); // IE 10-11 can't handle a DataView body.
6800 this._bodyInit = new Blob([this._bodyArrayBuffer]);
6801 } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
6802 this._bodyArrayBuffer = bufferClone(body);
6804 this._bodyText = body = Object.prototype.toString.call(body);
6807 if (!this.headers.get('content-type')) {
6808 if (typeof body === 'string') {
6809 this.headers.set('content-type', 'text/plain;charset=UTF-8');
6810 } else if (this._bodyBlob && this._bodyBlob.type) {
6811 this.headers.set('content-type', this._bodyBlob.type);
6812 } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
6813 this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
6819 this.blob = function () {
6820 var rejected = consumed(this);
6826 if (this._bodyBlob) {
6827 return Promise.resolve(this._bodyBlob);
6828 } else if (this._bodyArrayBuffer) {
6829 return Promise.resolve(new Blob([this._bodyArrayBuffer]));
6830 } else if (this._bodyFormData) {
6831 throw new Error('could not read FormData body as blob');
6833 return Promise.resolve(new Blob([this._bodyText]));
6837 this.arrayBuffer = function () {
6838 if (this._bodyArrayBuffer) {
6839 var isConsumed = consumed(this);
6845 if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
6846 return Promise.resolve(this._bodyArrayBuffer.buffer.slice(this._bodyArrayBuffer.byteOffset, this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength));
6848 return Promise.resolve(this._bodyArrayBuffer);
6851 return this.blob().then(readBlobAsArrayBuffer);
6856 this.text = function () {
6857 var rejected = consumed(this);
6863 if (this._bodyBlob) {
6864 return readBlobAsText(this._bodyBlob);
6865 } else if (this._bodyArrayBuffer) {
6866 return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer));
6867 } else if (this._bodyFormData) {
6868 throw new Error('could not read FormData body as text');
6870 return Promise.resolve(this._bodyText);
6874 if (support.formData) {
6875 this.formData = function () {
6876 return this.text().then(decode);
6880 this.json = function () {
6881 return this.text().then(JSON.parse);
6885 } // HTTP methods whose capitalization should be normalized
6888 var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'];
6890 function normalizeMethod(method) {
6891 var upcased = method.toUpperCase();
6892 return methods.indexOf(upcased) > -1 ? upcased : method;
6895 function Request(input, options) {
6896 if (!(this instanceof Request)) {
6897 throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');
6900 options = options || {};
6901 var body = options.body;
6903 if (input instanceof Request) {
6904 if (input.bodyUsed) {
6905 throw new TypeError('Already read');
6908 this.url = input.url;
6909 this.credentials = input.credentials;
6911 if (!options.headers) {
6912 this.headers = new Headers(input.headers);
6915 this.method = input.method;
6916 this.mode = input.mode;
6917 this.signal = input.signal;
6919 if (!body && input._bodyInit != null) {
6920 body = input._bodyInit;
6921 input.bodyUsed = true;
6924 this.url = String(input);
6927 this.credentials = options.credentials || this.credentials || 'same-origin';
6929 if (options.headers || !this.headers) {
6930 this.headers = new Headers(options.headers);
6933 this.method = normalizeMethod(options.method || this.method || 'GET');
6934 this.mode = options.mode || this.mode || null;
6935 this.signal = options.signal || this.signal;
6936 this.referrer = null;
6938 if ((this.method === 'GET' || this.method === 'HEAD') && body) {
6939 throw new TypeError('Body not allowed for GET or HEAD requests');
6942 this._initBody(body);
6944 if (this.method === 'GET' || this.method === 'HEAD') {
6945 if (options.cache === 'no-store' || options.cache === 'no-cache') {
6946 // Search for a '_' parameter in the query string
6947 var reParamSearch = /([?&])_=[^&]*/;
6949 if (reParamSearch.test(this.url)) {
6950 // If it already exists then set the value with the current time
6951 this.url = this.url.replace(reParamSearch, '$1_=' + new Date().getTime());
6953 // Otherwise add a new '_' parameter to the end with the current time
6954 var reQueryString = /\?/;
6955 this.url += (reQueryString.test(this.url) ? '&' : '?') + '_=' + new Date().getTime();
6961 Request.prototype.clone = function () {
6962 return new Request(this, {
6963 body: this._bodyInit
6967 function decode(body) {
6968 var form = new FormData();
6969 body.trim().split('&').forEach(function (bytes) {
6971 var split = bytes.split('=');
6972 var name = split.shift().replace(/\+/g, ' ');
6973 var value = split.join('=').replace(/\+/g, ' ');
6974 form.append(decodeURIComponent(name), decodeURIComponent(value));
6980 function parseHeaders(rawHeaders) {
6981 var headers = new Headers(); // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
6982 // https://tools.ietf.org/html/rfc7230#section-3.2
6984 var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' '); // Avoiding split via regex to work around a common IE11 bug with the core-js 3.6.0 regex polyfill
6985 // https://github.com/github/fetch/issues/748
6986 // https://github.com/zloirock/core-js/issues/751
6988 preProcessedHeaders.split('\r').map(function (header) {
6989 return header.indexOf('\n') === 0 ? header.substr(1, header.length) : header;
6990 }).forEach(function (line) {
6991 var parts = line.split(':');
6992 var key = parts.shift().trim();
6995 var value = parts.join(':').trim();
6996 headers.append(key, value);
7002 Body.call(Request.prototype);
7003 function Response(bodyInit, options) {
7004 if (!(this instanceof Response)) {
7005 throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');
7012 this.type = 'default';
7013 this.status = options.status === undefined ? 200 : options.status;
7014 this.ok = this.status >= 200 && this.status < 300;
7015 this.statusText = options.statusText === undefined ? '' : '' + options.statusText;
7016 this.headers = new Headers(options.headers);
7017 this.url = options.url || '';
7019 this._initBody(bodyInit);
7021 Body.call(Response.prototype);
7023 Response.prototype.clone = function () {
7024 return new Response(this._bodyInit, {
7025 status: this.status,
7026 statusText: this.statusText,
7027 headers: new Headers(this.headers),
7032 Response.error = function () {
7033 var response = new Response(null, {
7037 response.type = 'error';
7041 var redirectStatuses = [301, 302, 303, 307, 308];
7043 Response.redirect = function (url, status) {
7044 if (redirectStatuses.indexOf(status) === -1) {
7045 throw new RangeError('Invalid status code');
7048 return new Response(null, {
7056 var DOMException$1 = global$k.DOMException;
7059 new DOMException$1();
7061 DOMException$1 = function DOMException(message, name) {
7062 this.message = message;
7064 var error = Error(message);
7065 this.stack = error.stack;
7068 DOMException$1.prototype = Object.create(Error.prototype);
7069 DOMException$1.prototype.constructor = DOMException$1;
7072 function fetch$1(input, init) {
7073 return new Promise(function (resolve, reject) {
7074 var request = new Request(input, init);
7076 if (request.signal && request.signal.aborted) {
7077 return reject(new DOMException$1('Aborted', 'AbortError'));
7080 var xhr = new XMLHttpRequest();
7082 function abortXhr() {
7086 xhr.onload = function () {
7089 statusText: xhr.statusText,
7090 headers: parseHeaders(xhr.getAllResponseHeaders() || '')
7092 options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL');
7093 var body = 'response' in xhr ? xhr.response : xhr.responseText;
7094 setTimeout(function () {
7095 resolve(new Response(body, options));
7099 xhr.onerror = function () {
7100 setTimeout(function () {
7101 reject(new TypeError('Network request failed'));
7105 xhr.ontimeout = function () {
7106 setTimeout(function () {
7107 reject(new TypeError('Network request failed'));
7111 xhr.onabort = function () {
7112 setTimeout(function () {
7113 reject(new DOMException$1('Aborted', 'AbortError'));
7117 function fixUrl(url) {
7119 return url === '' && global$k.location.href ? global$k.location.href : url;
7125 xhr.open(request.method, fixUrl(request.url), true);
7127 if (request.credentials === 'include') {
7128 xhr.withCredentials = true;
7129 } else if (request.credentials === 'omit') {
7130 xhr.withCredentials = false;
7133 if ('responseType' in xhr) {
7135 xhr.responseType = 'blob';
7136 } else if (support.arrayBuffer && request.headers.get('Content-Type') && request.headers.get('Content-Type').indexOf('application/octet-stream') !== -1) {
7137 xhr.responseType = 'arraybuffer';
7141 if (init && _typeof(init.headers) === 'object' && !(init.headers instanceof Headers)) {
7142 Object.getOwnPropertyNames(init.headers).forEach(function (name) {
7143 xhr.setRequestHeader(name, normalizeValue(init.headers[name]));
7146 request.headers.forEach(function (value, name) {
7147 xhr.setRequestHeader(name, value);
7151 if (request.signal) {
7152 request.signal.addEventListener('abort', abortXhr);
7154 xhr.onreadystatechange = function () {
7155 // DONE (success or failure)
7156 if (xhr.readyState === 4) {
7157 request.signal.removeEventListener('abort', abortXhr);
7162 xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit);
7165 fetch$1.polyfill = true;
7167 if (!global$k.fetch) {
7168 global$k.fetch = fetch$1;
7169 global$k.Headers = Headers;
7170 global$k.Request = Request;
7171 global$k.Response = Response;
7175 var DESCRIPTORS$9 = descriptors;
7176 var defineProperty$5 = objectDefineProperty.f;
7178 // `Object.defineProperty` method
7179 // https://tc39.es/ecma262/#sec-object.defineproperty
7180 // eslint-disable-next-line es/no-object-defineproperty -- safe
7181 $$T({ target: 'Object', stat: true, forced: Object.defineProperty !== defineProperty$5, sham: !DESCRIPTORS$9 }, {
7182 defineProperty: defineProperty$5
7186 var setPrototypeOf = objectSetPrototypeOf;
7188 // `Object.setPrototypeOf` method
7189 // https://tc39.es/ecma262/#sec-object.setprototypeof
7190 $$S({ target: 'Object', stat: true }, {
7191 setPrototypeOf: setPrototypeOf
7195 var fails$n = fails$V;
7196 var toObject$8 = toObject$i;
7197 var nativeGetPrototypeOf = objectGetPrototypeOf;
7198 var CORRECT_PROTOTYPE_GETTER = correctPrototypeGetter;
7200 var FAILS_ON_PRIMITIVES$4 = fails$n(function () { nativeGetPrototypeOf(1); });
7202 // `Object.getPrototypeOf` method
7203 // https://tc39.es/ecma262/#sec-object.getprototypeof
7204 $$R({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$4, sham: !CORRECT_PROTOTYPE_GETTER }, {
7205 getPrototypeOf: function getPrototypeOf(it) {
7206 return nativeGetPrototypeOf(toObject$8(it));
7210 var global$j = global$1o;
7211 var uncurryThis$m = functionUncurryThis;
7212 var aCallable$2 = aCallable$a;
7213 var isObject$b = isObject$s;
7214 var hasOwn$5 = hasOwnProperty_1;
7215 var arraySlice$2 = arraySlice$b;
7216 var NATIVE_BIND = functionBindNative;
7218 var Function$1 = global$j.Function;
7219 var concat$1 = uncurryThis$m([].concat);
7220 var join$3 = uncurryThis$m([].join);
7223 var construct = function (C, argsLength, args) {
7224 if (!hasOwn$5(factories, argsLength)) {
7225 for (var list = [], i = 0; i < argsLength; i++) list[i] = 'a[' + i + ']';
7226 factories[argsLength] = Function$1('C,a', 'return new C(' + join$3(list, ',') + ')');
7227 } return factories[argsLength](C, args);
7230 // `Function.prototype.bind` method implementation
7231 // https://tc39.es/ecma262/#sec-function.prototype.bind
7232 var functionBind = NATIVE_BIND ? Function$1.bind : function bind(that /* , ...args */) {
7233 var F = aCallable$2(this);
7234 var Prototype = F.prototype;
7235 var partArgs = arraySlice$2(arguments, 1);
7236 var boundFunction = function bound(/* args... */) {
7237 var args = concat$1(partArgs, arraySlice$2(arguments));
7238 return this instanceof boundFunction ? construct(F, args.length, args) : F.apply(that, args);
7240 if (isObject$b(Prototype)) boundFunction.prototype = Prototype;
7241 return boundFunction;
7245 var getBuiltIn$1 = getBuiltIn$b;
7246 var apply = functionApply;
7247 var bind$7 = functionBind;
7248 var aConstructor = aConstructor$3;
7249 var anObject$4 = anObject$n;
7250 var isObject$a = isObject$s;
7251 var create$4 = objectCreate;
7252 var fails$m = fails$V;
7254 var nativeConstruct = getBuiltIn$1('Reflect', 'construct');
7255 var ObjectPrototype = Object.prototype;
7256 var push$4 = [].push;
7258 // `Reflect.construct` method
7259 // https://tc39.es/ecma262/#sec-reflect.construct
7260 // MS Edge supports only 2 arguments and argumentsList argument is optional
7261 // FF Nightly sets third argument as `new.target`, but does not create `this` from it
7262 var NEW_TARGET_BUG = fails$m(function () {
7263 function F() { /* empty */ }
7264 return !(nativeConstruct(function () { /* empty */ }, [], F) instanceof F);
7267 var ARGS_BUG = !fails$m(function () {
7268 nativeConstruct(function () { /* empty */ });
7271 var FORCED$c = NEW_TARGET_BUG || ARGS_BUG;
7273 $$Q({ target: 'Reflect', stat: true, forced: FORCED$c, sham: FORCED$c }, {
7274 construct: function construct(Target, args /* , newTarget */) {
7275 aConstructor(Target);
7277 var newTarget = arguments.length < 3 ? Target : aConstructor(arguments[2]);
7278 if (ARGS_BUG && !NEW_TARGET_BUG) return nativeConstruct(Target, args, newTarget);
7279 if (Target == newTarget) {
7280 // w/o altered newTarget, optimization for 0-4 arguments
7281 switch (args.length) {
7282 case 0: return new Target();
7283 case 1: return new Target(args[0]);
7284 case 2: return new Target(args[0], args[1]);
7285 case 3: return new Target(args[0], args[1], args[2]);
7286 case 4: return new Target(args[0], args[1], args[2], args[3]);
7288 // w/o altered newTarget, lot of arguments case
7290 apply(push$4, $args, args);
7291 return new (apply(bind$7, Target, $args))();
7293 // with altered newTarget, not support built-in constructors
7294 var proto = newTarget.prototype;
7295 var instance = create$4(isObject$a(proto) ? proto : ObjectPrototype);
7296 var result = apply(Target, instance, args);
7297 return isObject$a(result) ? result : instance;
7301 var hasOwn$4 = hasOwnProperty_1;
7303 var isDataDescriptor$1 = function (descriptor) {
7304 return descriptor !== undefined && (hasOwn$4(descriptor, 'value') || hasOwn$4(descriptor, 'writable'));
7308 var call$5 = functionCall;
7309 var isObject$9 = isObject$s;
7310 var anObject$3 = anObject$n;
7311 var isDataDescriptor = isDataDescriptor$1;
7312 var getOwnPropertyDescriptorModule = objectGetOwnPropertyDescriptor;
7313 var getPrototypeOf = objectGetPrototypeOf;
7315 // `Reflect.get` method
7316 // https://tc39.es/ecma262/#sec-reflect.get
7317 function get$3(target, propertyKey /* , receiver */) {
7318 var receiver = arguments.length < 3 ? target : arguments[2];
7319 var descriptor, prototype;
7320 if (anObject$3(target) === receiver) return target[propertyKey];
7321 descriptor = getOwnPropertyDescriptorModule.f(target, propertyKey);
7322 if (descriptor) return isDataDescriptor(descriptor)
7324 : descriptor.get === undefined ? undefined : call$5(descriptor.get, receiver);
7325 if (isObject$9(prototype = getPrototypeOf(target))) return get$3(prototype, propertyKey, receiver);
7328 $$P({ target: 'Reflect', stat: true }, {
7333 var fails$l = fails$V;
7334 var toIndexedObject$1 = toIndexedObject$d;
7335 var nativeGetOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
7336 var DESCRIPTORS$8 = descriptors;
7338 var FAILS_ON_PRIMITIVES$3 = fails$l(function () { nativeGetOwnPropertyDescriptor(1); });
7339 var FORCED$b = !DESCRIPTORS$8 || FAILS_ON_PRIMITIVES$3;
7341 // `Object.getOwnPropertyDescriptor` method
7342 // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
7343 $$O({ target: 'Object', stat: true, forced: FORCED$b, sham: !DESCRIPTORS$8 }, {
7344 getOwnPropertyDescriptor: function getOwnPropertyDescriptor(it, key) {
7345 return nativeGetOwnPropertyDescriptor(toIndexedObject$1(it), key);
7350 var global$i = global$1o;
7351 var toAbsoluteIndex$1 = toAbsoluteIndex$9;
7352 var toIntegerOrInfinity$2 = toIntegerOrInfinity$b;
7353 var lengthOfArrayLike$5 = lengthOfArrayLike$i;
7354 var toObject$7 = toObject$i;
7355 var arraySpeciesCreate$2 = arraySpeciesCreate$4;
7356 var createProperty$2 = createProperty$5;
7357 var arrayMethodHasSpeciesSupport$2 = arrayMethodHasSpeciesSupport$5;
7359 var HAS_SPECIES_SUPPORT$1 = arrayMethodHasSpeciesSupport$2('splice');
7361 var TypeError$6 = global$i.TypeError;
7362 var max$1 = Math.max;
7363 var min$3 = Math.min;
7364 var MAX_SAFE_INTEGER$1 = 0x1FFFFFFFFFFFFF;
7365 var MAXIMUM_ALLOWED_LENGTH_EXCEEDED = 'Maximum allowed length exceeded';
7367 // `Array.prototype.splice` method
7368 // https://tc39.es/ecma262/#sec-array.prototype.splice
7369 // with adding support of @@species
7370 $$N({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$1 }, {
7371 splice: function splice(start, deleteCount /* , ...items */) {
7372 var O = toObject$7(this);
7373 var len = lengthOfArrayLike$5(O);
7374 var actualStart = toAbsoluteIndex$1(start, len);
7375 var argumentsLength = arguments.length;
7376 var insertCount, actualDeleteCount, A, k, from, to;
7377 if (argumentsLength === 0) {
7378 insertCount = actualDeleteCount = 0;
7379 } else if (argumentsLength === 1) {
7381 actualDeleteCount = len - actualStart;
7383 insertCount = argumentsLength - 2;
7384 actualDeleteCount = min$3(max$1(toIntegerOrInfinity$2(deleteCount), 0), len - actualStart);
7386 if (len + insertCount - actualDeleteCount > MAX_SAFE_INTEGER$1) {
7387 throw TypeError$6(MAXIMUM_ALLOWED_LENGTH_EXCEEDED);
7389 A = arraySpeciesCreate$2(O, actualDeleteCount);
7390 for (k = 0; k < actualDeleteCount; k++) {
7391 from = actualStart + k;
7392 if (from in O) createProperty$2(A, k, O[from]);
7394 A.length = actualDeleteCount;
7395 if (insertCount < actualDeleteCount) {
7396 for (k = actualStart; k < len - actualDeleteCount; k++) {
7397 from = k + actualDeleteCount;
7398 to = k + insertCount;
7399 if (from in O) O[to] = O[from];
7402 for (k = len; k > len - actualDeleteCount + insertCount; k--) delete O[k - 1];
7403 } else if (insertCount > actualDeleteCount) {
7404 for (k = len - actualDeleteCount; k > actualStart; k--) {
7405 from = k + actualDeleteCount - 1;
7406 to = k + insertCount - 1;
7407 if (from in O) O[to] = O[from];
7411 for (k = 0; k < insertCount; k++) {
7412 O[k + actualStart] = arguments[k + 2];
7414 O.length = len - actualDeleteCount + insertCount;
7419 var defineWellKnownSymbol$1 = defineWellKnownSymbol$4;
7421 // `Symbol.toStringTag` well-known symbol
7422 // https://tc39.es/ecma262/#sec-symbol.tostringtag
7423 defineWellKnownSymbol$1('toStringTag');
7425 var global$h = global$1o;
7426 var setToStringTag$3 = setToStringTag$a;
7428 // JSON[@@toStringTag] property
7429 // https://tc39.es/ecma262/#sec-json-@@tostringtag
7430 setToStringTag$3(global$h.JSON, 'JSON', true);
7432 var setToStringTag$2 = setToStringTag$a;
7434 // Math[@@toStringTag] property
7435 // https://tc39.es/ecma262/#sec-math-@@tostringtag
7436 setToStringTag$2(Math, 'Math', true);
7438 (function (factory) {
7442 function _classCallCheck(instance, Constructor) {
7443 if (!(instance instanceof Constructor)) {
7444 throw new TypeError("Cannot call a class as a function");
7448 function _defineProperties(target, props) {
7449 for (var i = 0; i < props.length; i++) {
7450 var descriptor = props[i];
7451 descriptor.enumerable = descriptor.enumerable || false;
7452 descriptor.configurable = true;
7453 if ("value" in descriptor) descriptor.writable = true;
7454 Object.defineProperty(target, descriptor.key, descriptor);
7458 function _createClass(Constructor, protoProps, staticProps) {
7459 if (protoProps) _defineProperties(Constructor.prototype, protoProps);
7460 if (staticProps) _defineProperties(Constructor, staticProps);
7464 function _inherits(subClass, superClass) {
7465 if (typeof superClass !== "function" && superClass !== null) {
7466 throw new TypeError("Super expression must either be null or a function");
7469 subClass.prototype = Object.create(superClass && superClass.prototype, {
7476 if (superClass) _setPrototypeOf(subClass, superClass);
7479 function _getPrototypeOf(o) {
7480 _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
7481 return o.__proto__ || Object.getPrototypeOf(o);
7483 return _getPrototypeOf(o);
7486 function _setPrototypeOf(o, p) {
7487 _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
7492 return _setPrototypeOf(o, p);
7495 function _isNativeReflectConstruct() {
7496 if (typeof Reflect === "undefined" || !Reflect.construct) return false;
7497 if (Reflect.construct.sham) return false;
7498 if (typeof Proxy === "function") return true;
7501 Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
7508 function _assertThisInitialized(self) {
7509 if (self === void 0) {
7510 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
7516 function _possibleConstructorReturn(self, call) {
7517 if (call && (_typeof(call) === "object" || typeof call === "function")) {
7521 return _assertThisInitialized(self);
7524 function _createSuper(Derived) {
7525 var hasNativeReflectConstruct = _isNativeReflectConstruct();
7527 return function _createSuperInternal() {
7528 var Super = _getPrototypeOf(Derived),
7531 if (hasNativeReflectConstruct) {
7532 var NewTarget = _getPrototypeOf(this).constructor;
7534 result = Reflect.construct(Super, arguments, NewTarget);
7536 result = Super.apply(this, arguments);
7539 return _possibleConstructorReturn(this, result);
7543 function _superPropBase(object, property) {
7544 while (!Object.prototype.hasOwnProperty.call(object, property)) {
7545 object = _getPrototypeOf(object);
7546 if (object === null) break;
7552 function _get(target, property, receiver) {
7553 if (typeof Reflect !== "undefined" && Reflect.get) {
7556 _get = function _get(target, property, receiver) {
7557 var base = _superPropBase(target, property);
7560 var desc = Object.getOwnPropertyDescriptor(base, property);
7563 return desc.get.call(receiver);
7570 return _get(target, property, receiver || target);
7573 var Emitter = /*#__PURE__*/function () {
7574 function Emitter() {
7575 _classCallCheck(this, Emitter);
7577 Object.defineProperty(this, 'listeners', {
7584 _createClass(Emitter, [{
7585 key: "addEventListener",
7586 value: function addEventListener(type, callback, options) {
7587 if (!(type in this.listeners)) {
7588 this.listeners[type] = [];
7591 this.listeners[type].push({
7597 key: "removeEventListener",
7598 value: function removeEventListener(type, callback) {
7599 if (!(type in this.listeners)) {
7603 var stack = this.listeners[type];
7605 for (var i = 0, l = stack.length; i < l; i++) {
7606 if (stack[i].callback === callback) {
7613 key: "dispatchEvent",
7614 value: function dispatchEvent(event) {
7615 if (!(event.type in this.listeners)) {
7619 var stack = this.listeners[event.type];
7620 var stackToCall = stack.slice();
7622 for (var i = 0, l = stackToCall.length; i < l; i++) {
7623 var listener = stackToCall[i];
7626 listener.callback.call(this, event);
7628 Promise.resolve().then(function () {
7633 if (listener.options && listener.options.once) {
7634 this.removeEventListener(event.type, listener.callback);
7638 return !event.defaultPrevented;
7645 var AbortSignal = /*#__PURE__*/function (_Emitter) {
7646 _inherits(AbortSignal, _Emitter);
7648 var _super = _createSuper(AbortSignal);
7650 function AbortSignal() {
7653 _classCallCheck(this, AbortSignal);
7655 _this = _super.call(this); // Some versions of babel does not transpile super() correctly for IE <= 10, if the parent
7656 // constructor has failed to run, then "this.listeners" will still be undefined and then we call
7657 // the parent constructor directly instead as a workaround. For general details, see babel bug:
7658 // https://github.com/babel/babel/issues/3041
7659 // This hack was added as a fix for the issue described here:
7660 // https://github.com/Financial-Times/polyfill-library/pull/59#issuecomment-477558042
7662 if (!_this.listeners) {
7663 Emitter.call(_assertThisInitialized(_this));
7664 } // Compared to assignment, Object.defineProperty makes properties non-enumerable by default and
7665 // we want Object.keys(new AbortController().signal) to be [] for compat with the native impl
7668 Object.defineProperty(_assertThisInitialized(_this), 'aborted', {
7673 Object.defineProperty(_assertThisInitialized(_this), 'onabort', {
7681 _createClass(AbortSignal, [{
7683 value: function toString() {
7684 return '[object AbortSignal]';
7687 key: "dispatchEvent",
7688 value: function dispatchEvent(event) {
7689 if (event.type === 'abort') {
7690 this.aborted = true;
7692 if (typeof this.onabort === 'function') {
7693 this.onabort.call(this, event);
7697 _get(_getPrototypeOf(AbortSignal.prototype), "dispatchEvent", this).call(this, event);
7704 var AbortController = /*#__PURE__*/function () {
7705 function AbortController() {
7706 _classCallCheck(this, AbortController); // Compared to assignment, Object.defineProperty makes properties non-enumerable by default and
7707 // we want Object.keys(new AbortController()) to be [] for compat with the native impl
7710 Object.defineProperty(this, 'signal', {
7711 value: new AbortSignal(),
7717 _createClass(AbortController, [{
7719 value: function abort() {
7723 event = new Event('abort');
7725 if (typeof document !== 'undefined') {
7726 if (!document.createEvent) {
7727 // For Internet Explorer 8:
7728 event = document.createEventObject();
7729 event.type = 'abort';
7731 // For Internet Explorer 11:
7732 event = document.createEvent('Event');
7733 event.initEvent('abort', false, false);
7736 // Fallback where document isn't available:
7745 this.signal.dispatchEvent(event);
7749 value: function toString() {
7750 return '[object AbortController]';
7754 return AbortController;
7757 if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
7758 // These are necessary to make sure that we get correct output for:
7759 // Object.prototype.toString.call(new AbortController())
7760 AbortController.prototype[Symbol.toStringTag] = 'AbortController';
7761 AbortSignal.prototype[Symbol.toStringTag] = 'AbortSignal';
7764 function polyfillNeeded(self) {
7765 if (self.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL) {
7766 console.log('__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill');
7768 } // Note that the "unfetch" minimal fetch polyfill defines fetch() without
7769 // defining window.Request, and this polyfill need to work on top of unfetch
7770 // so the below feature detection needs the !self.AbortController part.
7771 // The Request.prototype check is also needed because Safari versions 11.1.2
7772 // up to and including 12.1.x has a window.AbortController present but still
7773 // does NOT correctly implement abortable fetch:
7774 // https://bugs.webkit.org/show_bug.cgi?id=174980#c2
7777 return typeof self.Request === 'function' && !self.Request.prototype.hasOwnProperty('signal') || !self.AbortController;
7780 * Note: the "fetch.Request" default value is available for fetch imported from
7781 * the "node-fetch" package and not in browsers. This is OK since browsers
7782 * will be importing umd-polyfill.js from that path "self" is passed the
7783 * decorator so the default value will not be used (because browsers that define
7784 * fetch also has Request). One quirky setup where self.fetch exists but
7785 * self.Request does not is when the "unfetch" minimal fetch polyfill is used
7786 * on top of IE11; for this case the browser will try to use the fetch.Request
7787 * default value which in turn will be undefined but then then "if (Request)"
7788 * will ensure that you get a patched fetch but still no Request (as expected).
7789 * @param {fetch, Request = fetch.Request}
7790 * @returns {fetch: abortableFetch, Request: AbortableRequest}
7794 function abortableFetchDecorator(patchTargets) {
7795 if ('function' === typeof patchTargets) {
7801 var _patchTargets = patchTargets,
7802 fetch = _patchTargets.fetch,
7803 _patchTargets$Request = _patchTargets.Request,
7804 NativeRequest = _patchTargets$Request === void 0 ? fetch.Request : _patchTargets$Request,
7805 NativeAbortController = _patchTargets.AbortController,
7806 _patchTargets$__FORCE = _patchTargets.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL,
7807 __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL = _patchTargets$__FORCE === void 0 ? false : _patchTargets$__FORCE;
7809 if (!polyfillNeeded({
7811 Request: NativeRequest,
7812 AbortController: NativeAbortController,
7813 __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL: __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL
7821 var Request = NativeRequest; // Note that the "unfetch" minimal fetch polyfill defines fetch() without
7822 // defining window.Request, and this polyfill need to work on top of unfetch
7823 // hence we only patch it if it's available. Also we don't patch it if signal
7824 // is already available on the Request prototype because in this case support
7825 // is present and the patching below can cause a crash since it assigns to
7826 // request.signal which is technically a read-only property. This latter error
7827 // happens when you run the main5.js node-fetch example in the repo
7828 // "abortcontroller-polyfill-examples". The exact error is:
7829 // request.signal = init.signal;
7831 // TypeError: Cannot set property signal of #<Request> which has only a getter
7833 if (Request && !Request.prototype.hasOwnProperty('signal') || __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL) {
7834 Request = function Request(input, init) {
7837 if (init && init.signal) {
7838 signal = init.signal; // Never pass init.signal to the native Request implementation when the polyfill has
7839 // been installed because if we're running on top of a browser with a
7840 // working native AbortController (i.e. the polyfill was installed due to
7841 // __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL being set), then passing our
7842 // fake AbortSignal to the native fetch will trigger:
7843 // TypeError: Failed to construct 'Request': member signal is not of type AbortSignal.
7848 var request = new NativeRequest(input, init);
7851 Object.defineProperty(request, 'signal', {
7862 Request.prototype = NativeRequest.prototype;
7865 var realFetch = fetch;
7867 var abortableFetch = function abortableFetch(input, init) {
7868 var signal = Request && Request.prototype.isPrototypeOf(input) ? input.signal : init ? init.signal : undefined;
7874 abortError = new DOMException('Aborted', 'AbortError');
7876 // IE 11 does not support calling the DOMException constructor, use a
7877 // regular error object on it instead.
7878 abortError = new Error('Aborted');
7879 abortError.name = 'AbortError';
7880 } // Return early if already aborted, thus avoiding making an HTTP request
7883 if (signal.aborted) {
7884 return Promise.reject(abortError);
7885 } // Turn an event into a promise, reject it once `abort` is dispatched
7888 var cancellation = new Promise(function (_, reject) {
7889 signal.addEventListener('abort', function () {
7890 return reject(abortError);
7896 if (init && init.signal) {
7897 // Never pass .signal to the native implementation when the polyfill has
7898 // been installed because if we're running on top of a browser with a
7899 // working native AbortController (i.e. the polyfill was installed due to
7900 // __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL being set), then passing our
7901 // fake AbortSignal to the native fetch will trigger:
7902 // TypeError: Failed to execute 'fetch' on 'Window': member signal is not of type AbortSignal.
7904 } // Return the fastest promise (don't need to wait for request to finish)
7907 return Promise.race([cancellation, realFetch(input, init)]);
7910 return realFetch(input, init);
7914 fetch: abortableFetch,
7920 if (!polyfillNeeded(self)) {
7925 console.warn('fetch() is not available, cannot install abortcontroller-polyfill');
7929 var _abortableFetch = abortableFetchDecorator(self),
7930 fetch = _abortableFetch.fetch,
7931 Request = _abortableFetch.Request;
7934 self.Request = Request;
7935 Object.defineProperty(self, 'AbortController', {
7939 value: AbortController
7941 Object.defineProperty(self, 'AbortSignal', {
7947 })(typeof self !== 'undefined' ? self : commonjsGlobal);
7950 function actionAddEntity(way) {
7951 return function (graph) {
7952 return graph.replace(way);
7957 var global$g = global$1o;
7958 var fails$k = fails$V;
7959 var isArray$3 = isArray$8;
7960 var isObject$8 = isObject$s;
7961 var toObject$6 = toObject$i;
7962 var lengthOfArrayLike$4 = lengthOfArrayLike$i;
7963 var createProperty$1 = createProperty$5;
7964 var arraySpeciesCreate$1 = arraySpeciesCreate$4;
7965 var arrayMethodHasSpeciesSupport$1 = arrayMethodHasSpeciesSupport$5;
7966 var wellKnownSymbol$2 = wellKnownSymbol$t;
7967 var V8_VERSION = engineV8Version;
7969 var IS_CONCAT_SPREADABLE = wellKnownSymbol$2('isConcatSpreadable');
7970 var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF;
7971 var MAXIMUM_ALLOWED_INDEX_EXCEEDED = 'Maximum allowed index exceeded';
7972 var TypeError$5 = global$g.TypeError;
7974 // We can't use this feature detection in V8 since it causes
7975 // deoptimization and serious performance degradation
7976 // https://github.com/zloirock/core-js/issues/679
7977 var IS_CONCAT_SPREADABLE_SUPPORT = V8_VERSION >= 51 || !fails$k(function () {
7979 array[IS_CONCAT_SPREADABLE] = false;
7980 return array.concat()[0] !== array;
7983 var SPECIES_SUPPORT = arrayMethodHasSpeciesSupport$1('concat');
7985 var isConcatSpreadable = function (O) {
7986 if (!isObject$8(O)) return false;
7987 var spreadable = O[IS_CONCAT_SPREADABLE];
7988 return spreadable !== undefined ? !!spreadable : isArray$3(O);
7991 var FORCED$a = !IS_CONCAT_SPREADABLE_SUPPORT || !SPECIES_SUPPORT;
7993 // `Array.prototype.concat` method
7994 // https://tc39.es/ecma262/#sec-array.prototype.concat
7995 // with adding support of @@isConcatSpreadable and @@species
7996 $$M({ target: 'Array', proto: true, forced: FORCED$a }, {
7997 // eslint-disable-next-line no-unused-vars -- required for `.length`
7998 concat: function concat(arg) {
7999 var O = toObject$6(this);
8000 var A = arraySpeciesCreate$1(O, 0);
8002 var i, k, length, len, E;
8003 for (i = -1, length = arguments.length; i < length; i++) {
8004 E = i === -1 ? O : arguments[i];
8005 if (isConcatSpreadable(E)) {
8006 len = lengthOfArrayLike$4(E);
8007 if (n + len > MAX_SAFE_INTEGER) throw TypeError$5(MAXIMUM_ALLOWED_INDEX_EXCEEDED);
8008 for (k = 0; k < len; k++, n++) if (k in E) createProperty$1(A, n, E[k]);
8010 if (n >= MAX_SAFE_INTEGER) throw TypeError$5(MAXIMUM_ALLOWED_INDEX_EXCEEDED);
8011 createProperty$1(A, n++, E);
8019 var DESCRIPTORS$7 = descriptors;
8020 var uncurryThis$l = functionUncurryThis;
8021 var call$4 = functionCall;
8022 var fails$j = fails$V;
8023 var objectKeys$1 = objectKeys$4;
8024 var getOwnPropertySymbolsModule = objectGetOwnPropertySymbols;
8025 var propertyIsEnumerableModule = objectPropertyIsEnumerable;
8026 var toObject$5 = toObject$i;
8027 var IndexedObject = indexedObject;
8029 // eslint-disable-next-line es/no-object-assign -- safe
8030 var $assign = Object.assign;
8031 // eslint-disable-next-line es/no-object-defineproperty -- required for testing
8032 var defineProperty$4 = Object.defineProperty;
8033 var concat = uncurryThis$l([].concat);
8035 // `Object.assign` method
8036 // https://tc39.es/ecma262/#sec-object.assign
8037 var objectAssign = !$assign || fails$j(function () {
8038 // should have correct order of operations (Edge bug)
8039 if (DESCRIPTORS$7 && $assign({ b: 1 }, $assign(defineProperty$4({}, 'a', {
8042 defineProperty$4(this, 'b', {
8047 }), { b: 2 })).b !== 1) return true;
8048 // should work with symbols and should have deterministic property order (V8 bug)
8051 // eslint-disable-next-line es/no-symbol -- safe
8052 var symbol = Symbol();
8053 var alphabet = 'abcdefghijklmnopqrst';
8055 alphabet.split('').forEach(function (chr) { B[chr] = chr; });
8056 return $assign({}, A)[symbol] != 7 || objectKeys$1($assign({}, B)).join('') != alphabet;
8057 }) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length`
8058 var T = toObject$5(target);
8059 var argumentsLength = arguments.length;
8061 var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
8062 var propertyIsEnumerable = propertyIsEnumerableModule.f;
8063 while (argumentsLength > index) {
8064 var S = IndexedObject(arguments[index++]);
8065 var keys = getOwnPropertySymbols ? concat(objectKeys$1(S), getOwnPropertySymbols(S)) : objectKeys$1(S);
8066 var length = keys.length;
8069 while (length > j) {
8071 if (!DESCRIPTORS$7 || call$4(propertyIsEnumerable, S, key)) T[key] = S[key];
8077 var assign$2 = objectAssign;
8079 // `Object.assign` method
8080 // https://tc39.es/ecma262/#sec-object.assign
8081 // eslint-disable-next-line es/no-object-assign -- required for testing
8082 $$L({ target: 'Object', stat: true, forced: Object.assign !== assign$2 }, {
8087 var $filter = arrayIteration.filter;
8088 var arrayMethodHasSpeciesSupport = arrayMethodHasSpeciesSupport$5;
8090 var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('filter');
8092 // `Array.prototype.filter` method
8093 // https://tc39.es/ecma262/#sec-array.prototype.filter
8094 // with adding support of @@species
8095 $$K({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, {
8096 filter: function filter(callbackfn /* , thisArg */) {
8097 return $filter(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
8102 var toObject$4 = toObject$i;
8103 var nativeKeys = objectKeys$4;
8104 var fails$i = fails$V;
8106 var FAILS_ON_PRIMITIVES$2 = fails$i(function () { nativeKeys(1); });
8108 // `Object.keys` method
8109 // https://tc39.es/ecma262/#sec-object.keys
8110 $$J({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$2 }, {
8111 keys: function keys(it) {
8112 return nativeKeys(toObject$4(it));
8117 var uncurryThis$k = functionUncurryThis;
8118 var isArray$2 = isArray$8;
8120 var un$Reverse = uncurryThis$k([].reverse);
8121 var test$1 = [1, 2];
8123 // `Array.prototype.reverse` method
8124 // https://tc39.es/ecma262/#sec-array.prototype.reverse
8125 // fix for Safari 12.0 bug
8126 // https://bugs.webkit.org/show_bug.cgi?id=188794
8127 $$I({ target: 'Array', proto: true, forced: String(test$1) === String(test$1.reverse()) }, {
8128 reverse: function reverse() {
8129 // eslint-disable-next-line no-self-assign -- dirty hack
8130 if (isArray$2(this)) this.length = this.length;
8131 return un$Reverse(this);
8135 var global$f = global$1o;
8136 var fails$h = fails$V;
8137 var uncurryThis$j = functionUncurryThis;
8138 var toString$c = toString$k;
8139 var trim$4 = stringTrim.trim;
8140 var whitespaces$1 = whitespaces$4;
8142 var charAt$2 = uncurryThis$j(''.charAt);
8143 var n$ParseFloat = global$f.parseFloat;
8144 var Symbol$2 = global$f.Symbol;
8145 var ITERATOR$1 = Symbol$2 && Symbol$2.iterator;
8146 var FORCED$9 = 1 / n$ParseFloat(whitespaces$1 + '-0') !== -Infinity
8147 // MS Edge 18- broken with boxed symbols
8148 || (ITERATOR$1 && !fails$h(function () { n$ParseFloat(Object(ITERATOR$1)); }));
8150 // `parseFloat` method
8151 // https://tc39.es/ecma262/#sec-parsefloat-string
8152 var numberParseFloat = FORCED$9 ? function parseFloat(string) {
8153 var trimmedString = trim$4(toString$c(string));
8154 var result = n$ParseFloat(trimmedString);
8155 return result === 0 && charAt$2(trimmedString, 0) == '-' ? -0 : result;
8159 var $parseFloat = numberParseFloat;
8161 // `parseFloat` method
8162 // https://tc39.es/ecma262/#sec-parsefloat-string
8163 $$H({ global: true, forced: parseFloat != $parseFloat }, {
8164 parseFloat: $parseFloat
8168 Order the nodes of a way in reverse order and reverse any direction dependent tags
8169 other than `oneway`. (We assume that correcting a backwards oneway is the primary
8170 reason for reversing a way.)
8172 In addition, numeric-valued `incline` tags are negated.
8174 The JOSM implementation was used as a guide, but transformations that were of unclear benefit
8175 or adjusted tags that don't seem to be used in practice were omitted.
8178 http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
8179 http://wiki.openstreetmap.org/wiki/Key:direction#Steps
8180 http://wiki.openstreetmap.org/wiki/Key:incline
8181 http://wiki.openstreetmap.org/wiki/Route#Members
8182 http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
8183 http://wiki.openstreetmap.org/wiki/Tag:highway%3Dstop
8184 http://wiki.openstreetmap.org/wiki/Key:traffic_sign#On_a_way_or_area
8186 function actionReverse(entityID, options) {
8187 var ignoreKey = /^.*(_|:)?(description|name|note|website|ref|source|comment|watch|attribution)(_|:)?/;
8188 var numeric = /^([+\-]?)(?=[\d.])/;
8189 var directionKey = /direction$/;
8190 var turn_lanes = /^turn:lanes:?/;
8191 var keyReplacements = [[/:right$/, ':left'], [/:left$/, ':right'], [/:forward$/, ':backward'], [/:backward$/, ':forward'], [/:right:/, ':left:'], [/:left:/, ':right:'], [/:forward:/, ':backward:'], [/:backward:/, ':forward:']];
8192 var valueReplacements = {
8197 forward: 'backward',
8198 backward: 'forward',
8199 forwards: 'backward',
8200 backwards: 'forward'
8202 var roleReplacements = {
8203 forward: 'backward',
8204 backward: 'forward',
8205 forwards: 'backward',
8206 backwards: 'forward'
8208 var onewayReplacements = {
8213 var compassReplacements = {
8232 function reverseKey(key) {
8233 for (var i = 0; i < keyReplacements.length; ++i) {
8234 var replacement = keyReplacements[i];
8236 if (replacement[0].test(key)) {
8237 return key.replace(replacement[0], replacement[1]);
8244 function reverseValue(key, value, includeAbsolute) {
8245 if (ignoreKey.test(key)) return value; // Turn lanes are left/right to key (not way) direction - #5674
8247 if (turn_lanes.test(key)) {
8249 } else if (key === 'incline' && numeric.test(value)) {
8250 return value.replace(numeric, function (_, sign) {
8251 return sign === '-' ? '' : '-';
8253 } else if (options && options.reverseOneway && key === 'oneway') {
8254 return onewayReplacements[value] || value;
8255 } else if (includeAbsolute && directionKey.test(key)) {
8256 if (compassReplacements[value]) return compassReplacements[value];
8257 var degrees = parseFloat(value);
8259 if (typeof degrees === 'number' && !isNaN(degrees)) {
8260 if (degrees < 180) {
8266 return degrees.toString();
8270 return valueReplacements[value] || value;
8271 } // Reverse the direction of tags attached to the nodes - #3076
8274 function reverseNodeTags(graph, nodeIDs) {
8275 for (var i = 0; i < nodeIDs.length; i++) {
8276 var node = graph.hasEntity(nodeIDs[i]);
8277 if (!node || !Object.keys(node.tags).length) continue;
8280 for (var key in node.tags) {
8281 tags[reverseKey(key)] = reverseValue(key, node.tags[key], node.id === entityID);
8284 graph = graph.replace(node.update({
8292 function reverseWay(graph, way) {
8293 var nodes = way.nodes.slice().reverse();
8297 for (var key in way.tags) {
8298 tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
8301 graph.parentRelations(way).forEach(function (relation) {
8302 relation.members.forEach(function (member, index) {
8303 if (member.id === way.id && (role = roleReplacements[member.role])) {
8304 relation = relation.updateMember({
8307 graph = graph.replace(relation);
8310 }); // Reverse any associated directions on nodes on the way and then replace
8311 // the way itself with the reversed node ids and updated way tags
8313 return reverseNodeTags(graph, nodes).replace(way.update({
8319 var action = function action(graph) {
8320 var entity = graph.entity(entityID);
8322 if (entity.type === 'way') {
8323 return reverseWay(graph, entity);
8326 return reverseNodeTags(graph, [entityID]);
8329 action.disabled = function (graph) {
8330 var entity = graph.hasEntity(entityID);
8331 if (!entity || entity.type === 'way') return false;
8333 for (var key in entity.tags) {
8334 var value = entity.tags[key];
8336 if (reverseKey(key) !== key || reverseValue(key, value, true) !== value) {
8341 return 'nondirectional_node';
8344 action.entityID = function () {
8351 function osmIsInterestingTag(key) {
8352 return key !== 'attribution' && key !== 'created_by' && key !== 'source' && key !== 'odbl' && key.indexOf('source:') !== 0 && key.indexOf('source_ref') !== 0 && // purposely exclude colon
8353 key.indexOf('tiger:') !== 0;
8355 var osmAreaKeys = {};
8356 function osmSetAreaKeys(value) {
8357 osmAreaKeys = value;
8358 } // returns an object with the tag from `tags` that implies an area geometry, if any
8360 function osmTagSuggestingArea(tags) {
8361 if (tags.area === 'yes') return {
8364 if (tags.area === 'no') return null; // `highway` and `railway` are typically linear features, but there
8365 // are a few exceptions that should be treated as areas, even in the
8366 // absence of a proper `area=yes` or `areaKeys` tag.. see #4194
8381 var returnTags = {};
8383 for (var key in tags) {
8384 if (key in osmAreaKeys && !(tags[key] in osmAreaKeys[key])) {
8385 returnTags[key] = tags[key];
8389 if (key in lineKeys && tags[key] in lineKeys[key]) {
8390 returnTags[key] = tags[key];
8396 } // Tags that indicate a node can be a standalone point
8397 // e.g. { amenity: { bar: true, parking: true, ... } ... }
8399 var osmPointTags = {};
8400 function osmSetPointTags(value) {
8401 osmPointTags = value;
8402 } // Tags that indicate a node can be part of a way
8403 // e.g. { amenity: { parking: true, ... }, highway: { stop: true ... } ... }
8405 var osmVertexTags = {};
8406 function osmSetVertexTags(value) {
8407 osmVertexTags = value;
8409 function osmNodeGeometriesForTags(nodeTags) {
8410 var geometries = {};
8412 for (var key in nodeTags) {
8413 if (osmPointTags[key] && (osmPointTags[key]['*'] || osmPointTags[key][nodeTags[key]])) {
8414 geometries.point = true;
8417 if (osmVertexTags[key] && (osmVertexTags[key]['*'] || osmVertexTags[key][nodeTags[key]])) {
8418 geometries.vertex = true;
8419 } // break early if both are already supported
8422 if (geometries.point && geometries.vertex) break;
8427 var osmOneWayTags = {
8432 'magic_carpet': true,
8447 'goods_conveyor': true,
8448 'piste:halfpipe': true
8456 'separation_lane': true,
8457 'separation_roundabout': true
8466 'tidal_channel': true
8468 }; // solid and smooth surfaces akin to the assumed default road surface in OSM
8470 var osmPavedTags = {
8475 'concrete:lanes': true,
8476 'concrete:plates': true
8481 }; // solid, if somewhat uncommon surfaces with a high range of smoothness
8483 var osmSemipavedTags = {
8485 'cobblestone': true,
8486 'cobblestone:flattened': true,
8487 'unhewn_cobblestone': true,
8489 'paving_stones': true,
8494 var osmRightSideIsInsideTags = {
8497 'coastline': 'coastline'
8500 'retaining_wall': true,
8511 }; // "highway" tag values for pedestrian or vehicle right-of-ways that make up the routable network
8512 // (does not include `raceway`)
8514 var osmRoutableHighwayTagValues = {
8521 motorway_link: true,
8524 secondary_link: true,
8525 tertiary_link: true,
8530 living_street: true,
8539 }; // "highway" tag values that generally do not allow motor vehicles
8541 var osmPathHighwayTagValues = {
8549 }; // "railway" tag values representing existing railroad tracks (purposely does not include 'abandoned')
8551 var osmRailwayTrackTagValues = {
8562 }; // "waterway" tag values for line features representing water flow
8564 var osmFlowingWaterwayTagValues = {
8574 var global$e = global$1o;
8575 var fails$g = fails$V;
8576 var uncurryThis$i = functionUncurryThis;
8577 var toString$b = toString$k;
8578 var trim$3 = stringTrim.trim;
8579 var whitespaces = whitespaces$4;
8581 var $parseInt$1 = global$e.parseInt;
8582 var Symbol$1 = global$e.Symbol;
8583 var ITERATOR = Symbol$1 && Symbol$1.iterator;
8584 var hex$2 = /^[+-]?0x/i;
8585 var exec$3 = uncurryThis$i(hex$2.exec);
8586 var FORCED$8 = $parseInt$1(whitespaces + '08') !== 8 || $parseInt$1(whitespaces + '0x16') !== 22
8587 // MS Edge 18- broken with boxed symbols
8588 || (ITERATOR && !fails$g(function () { $parseInt$1(Object(ITERATOR)); }));
8590 // `parseInt` method
8591 // https://tc39.es/ecma262/#sec-parseint-string-radix
8592 var numberParseInt = FORCED$8 ? function parseInt(string, radix) {
8593 var S = trim$3(toString$b(string));
8594 return $parseInt$1(S, (radix >>> 0) || (exec$3(hex$2, S) ? 16 : 10));
8598 var $parseInt = numberParseInt;
8600 // `parseInt` method
8601 // https://tc39.es/ecma262/#sec-parseint-string-radix
8602 $$G({ global: true, forced: parseInt != $parseInt }, {
8606 var internalMetadata = {exports: {}};
8608 // FF26- bug: ArrayBuffers are non-extensible, but Object.isExtensible does not report it
8609 var fails$f = fails$V;
8611 var arrayBufferNonExtensible = fails$f(function () {
8612 if (typeof ArrayBuffer == 'function') {
8613 var buffer = new ArrayBuffer(8);
8614 // eslint-disable-next-line es/no-object-isextensible, es/no-object-defineproperty -- safe
8615 if (Object.isExtensible(buffer)) Object.defineProperty(buffer, 'a', { value: 8 });
8619 var fails$e = fails$V;
8620 var isObject$7 = isObject$s;
8621 var classof = classofRaw$1;
8622 var ARRAY_BUFFER_NON_EXTENSIBLE = arrayBufferNonExtensible;
8624 // eslint-disable-next-line es/no-object-isextensible -- safe
8625 var $isExtensible = Object.isExtensible;
8626 var FAILS_ON_PRIMITIVES$1 = fails$e(function () { $isExtensible(1); });
8628 // `Object.isExtensible` method
8629 // https://tc39.es/ecma262/#sec-object.isextensible
8630 var objectIsExtensible = (FAILS_ON_PRIMITIVES$1 || ARRAY_BUFFER_NON_EXTENSIBLE) ? function isExtensible(it) {
8631 if (!isObject$7(it)) return false;
8632 if (ARRAY_BUFFER_NON_EXTENSIBLE && classof(it) == 'ArrayBuffer') return false;
8633 return $isExtensible ? $isExtensible(it) : true;
8636 var fails$d = fails$V;
8638 var freezing = !fails$d(function () {
8639 // eslint-disable-next-line es/no-object-isextensible, es/no-object-preventextensions -- required for testing
8640 return Object.isExtensible(Object.preventExtensions({}));
8644 var uncurryThis$h = functionUncurryThis;
8645 var hiddenKeys = hiddenKeys$6;
8646 var isObject$6 = isObject$s;
8647 var hasOwn$3 = hasOwnProperty_1;
8648 var defineProperty$3 = objectDefineProperty.f;
8649 var getOwnPropertyNamesModule = objectGetOwnPropertyNames;
8650 var getOwnPropertyNamesExternalModule = objectGetOwnPropertyNamesExternal;
8651 var isExtensible = objectIsExtensible;
8653 var FREEZING$1 = freezing;
8655 var REQUIRED = false;
8656 var METADATA = uid('meta');
8659 var setMetadata = function (it) {
8660 defineProperty$3(it, METADATA, { value: {
8661 objectID: 'O' + id$1++, // object ID
8662 weakData: {} // weak collections IDs
8666 var fastKey$1 = function (it, create) {
8667 // return a primitive with prefix
8668 if (!isObject$6(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
8669 if (!hasOwn$3(it, METADATA)) {
8670 // can't set metadata to uncaught frozen object
8671 if (!isExtensible(it)) return 'F';
8672 // not necessary to add metadata
8673 if (!create) return 'E';
8674 // add missing metadata
8677 } return it[METADATA].objectID;
8680 var getWeakData = function (it, create) {
8681 if (!hasOwn$3(it, METADATA)) {
8682 // can't set metadata to uncaught frozen object
8683 if (!isExtensible(it)) return true;
8684 // not necessary to add metadata
8685 if (!create) return false;
8686 // add missing metadata
8688 // return the store of weak collections IDs
8689 } return it[METADATA].weakData;
8692 // add metadata on freeze-family methods calling
8693 var onFreeze$1 = function (it) {
8694 if (FREEZING$1 && REQUIRED && isExtensible(it) && !hasOwn$3(it, METADATA)) setMetadata(it);
8698 var enable = function () {
8699 meta.enable = function () { /* empty */ };
8701 var getOwnPropertyNames = getOwnPropertyNamesModule.f;
8702 var splice = uncurryThis$h([].splice);
8706 // prevent exposing of metadata key
8707 if (getOwnPropertyNames(test).length) {
8708 getOwnPropertyNamesModule.f = function (it) {
8709 var result = getOwnPropertyNames(it);
8710 for (var i = 0, length = result.length; i < length; i++) {
8711 if (result[i] === METADATA) {
8712 splice(result, i, 1);
8718 $$F({ target: 'Object', stat: true, forced: true }, {
8719 getOwnPropertyNames: getOwnPropertyNamesExternalModule.f
8724 var meta = internalMetadata.exports = {
8727 getWeakData: getWeakData,
8728 onFreeze: onFreeze$1
8731 hiddenKeys[METADATA] = true;
8734 var global$d = global$1o;
8735 var uncurryThis$g = functionUncurryThis;
8736 var isForced$2 = isForced_1;
8737 var redefine$4 = redefine$h.exports;
8738 var InternalMetadataModule = internalMetadata.exports;
8739 var iterate$1 = iterate$3;
8740 var anInstance$2 = anInstance$7;
8741 var isCallable$1 = isCallable$r;
8742 var isObject$5 = isObject$s;
8743 var fails$c = fails$V;
8744 var checkCorrectnessOfIteration$1 = checkCorrectnessOfIteration$4;
8745 var setToStringTag$1 = setToStringTag$a;
8746 var inheritIfRequired$2 = inheritIfRequired$4;
8748 var collection$2 = function (CONSTRUCTOR_NAME, wrapper, common) {
8749 var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1;
8750 var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1;
8751 var ADDER = IS_MAP ? 'set' : 'add';
8752 var NativeConstructor = global$d[CONSTRUCTOR_NAME];
8753 var NativePrototype = NativeConstructor && NativeConstructor.prototype;
8754 var Constructor = NativeConstructor;
8757 var fixMethod = function (KEY) {
8758 var uncurriedNativeMethod = uncurryThis$g(NativePrototype[KEY]);
8759 redefine$4(NativePrototype, KEY,
8760 KEY == 'add' ? function add(value) {
8761 uncurriedNativeMethod(this, value === 0 ? 0 : value);
8763 } : KEY == 'delete' ? function (key) {
8764 return IS_WEAK && !isObject$5(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
8765 } : KEY == 'get' ? function get(key) {
8766 return IS_WEAK && !isObject$5(key) ? undefined : uncurriedNativeMethod(this, key === 0 ? 0 : key);
8767 } : KEY == 'has' ? function has(key) {
8768 return IS_WEAK && !isObject$5(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
8769 } : function set(key, value) {
8770 uncurriedNativeMethod(this, key === 0 ? 0 : key, value);
8776 var REPLACE = isForced$2(
8778 !isCallable$1(NativeConstructor) || !(IS_WEAK || NativePrototype.forEach && !fails$c(function () {
8779 new NativeConstructor().entries().next();
8784 // create collection constructor
8785 Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER);
8786 InternalMetadataModule.enable();
8787 } else if (isForced$2(CONSTRUCTOR_NAME, true)) {
8788 var instance = new Constructor();
8789 // early implementations not supports chaining
8790 var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;
8791 // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false
8792 var THROWS_ON_PRIMITIVES = fails$c(function () { instance.has(1); });
8793 // most early implementations doesn't supports iterables, most modern - not close it correctly
8794 // eslint-disable-next-line no-new -- required for testing
8795 var ACCEPT_ITERABLES = checkCorrectnessOfIteration$1(function (iterable) { new NativeConstructor(iterable); });
8796 // for early implementations -0 and +0 not the same
8797 var BUGGY_ZERO = !IS_WEAK && fails$c(function () {
8798 // V8 ~ Chromium 42- fails only with 5+ elements
8799 var $instance = new NativeConstructor();
8801 while (index--) $instance[ADDER](index, index);
8802 return !$instance.has(-0);
8805 if (!ACCEPT_ITERABLES) {
8806 Constructor = wrapper(function (dummy, iterable) {
8807 anInstance$2(dummy, NativePrototype);
8808 var that = inheritIfRequired$2(new NativeConstructor(), dummy, Constructor);
8809 if (iterable != undefined) iterate$1(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
8812 Constructor.prototype = NativePrototype;
8813 NativePrototype.constructor = Constructor;
8816 if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
8817 fixMethod('delete');
8819 IS_MAP && fixMethod('get');
8822 if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
8824 // weak collections should not contains .clear method
8825 if (IS_WEAK && NativePrototype.clear) delete NativePrototype.clear;
8828 exported[CONSTRUCTOR_NAME] = Constructor;
8829 $$E({ global: true, forced: Constructor != NativeConstructor }, exported);
8831 setToStringTag$1(Constructor, CONSTRUCTOR_NAME);
8833 if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP);
8838 var defineProperty$2 = objectDefineProperty.f;
8839 var create$3 = objectCreate;
8840 var redefineAll = redefineAll$4;
8841 var bind$6 = functionBindContext;
8842 var anInstance$1 = anInstance$7;
8843 var iterate = iterate$3;
8844 var defineIterator = defineIterator$3;
8845 var setSpecies$1 = setSpecies$5;
8846 var DESCRIPTORS$6 = descriptors;
8847 var fastKey = internalMetadata.exports.fastKey;
8848 var InternalStateModule$1 = internalState;
8850 var setInternalState$1 = InternalStateModule$1.set;
8851 var internalStateGetterFor = InternalStateModule$1.getterFor;
8853 var collectionStrong$2 = {
8854 getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
8855 var Constructor = wrapper(function (that, iterable) {
8856 anInstance$1(that, Prototype);
8857 setInternalState$1(that, {
8858 type: CONSTRUCTOR_NAME,
8859 index: create$3(null),
8864 if (!DESCRIPTORS$6) that.size = 0;
8865 if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
8868 var Prototype = Constructor.prototype;
8870 var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
8872 var define = function (that, key, value) {
8873 var state = getInternalState(that);
8874 var entry = getEntry(that, key);
8875 var previous, index;
8876 // change existing entry
8878 entry.value = value;
8881 state.last = entry = {
8882 index: index = fastKey(key, true),
8885 previous: previous = state.last,
8889 if (!state.first) state.first = entry;
8890 if (previous) previous.next = entry;
8891 if (DESCRIPTORS$6) state.size++;
8894 if (index !== 'F') state.index[index] = entry;
8898 var getEntry = function (that, key) {
8899 var state = getInternalState(that);
8901 var index = fastKey(key);
8903 if (index !== 'F') return state.index[index];
8904 // frozen object case
8905 for (entry = state.first; entry; entry = entry.next) {
8906 if (entry.key == key) return entry;
8910 redefineAll(Prototype, {
8911 // `{ Map, Set }.prototype.clear()` methods
8912 // https://tc39.es/ecma262/#sec-map.prototype.clear
8913 // https://tc39.es/ecma262/#sec-set.prototype.clear
8914 clear: function clear() {
8916 var state = getInternalState(that);
8917 var data = state.index;
8918 var entry = state.first;
8920 entry.removed = true;
8921 if (entry.previous) entry.previous = entry.previous.next = undefined;
8922 delete data[entry.index];
8925 state.first = state.last = undefined;
8926 if (DESCRIPTORS$6) state.size = 0;
8929 // `{ Map, Set }.prototype.delete(key)` methods
8930 // https://tc39.es/ecma262/#sec-map.prototype.delete
8931 // https://tc39.es/ecma262/#sec-set.prototype.delete
8932 'delete': function (key) {
8934 var state = getInternalState(that);
8935 var entry = getEntry(that, key);
8937 var next = entry.next;
8938 var prev = entry.previous;
8939 delete state.index[entry.index];
8940 entry.removed = true;
8941 if (prev) prev.next = next;
8942 if (next) next.previous = prev;
8943 if (state.first == entry) state.first = next;
8944 if (state.last == entry) state.last = prev;
8945 if (DESCRIPTORS$6) state.size--;
8949 // `{ Map, Set }.prototype.forEach(callbackfn, thisArg = undefined)` methods
8950 // https://tc39.es/ecma262/#sec-map.prototype.foreach
8951 // https://tc39.es/ecma262/#sec-set.prototype.foreach
8952 forEach: function forEach(callbackfn /* , that = undefined */) {
8953 var state = getInternalState(this);
8954 var boundFunction = bind$6(callbackfn, arguments.length > 1 ? arguments[1] : undefined);
8956 while (entry = entry ? entry.next : state.first) {
8957 boundFunction(entry.value, entry.key, this);
8958 // revert to the last existing entry
8959 while (entry && entry.removed) entry = entry.previous;
8962 // `{ Map, Set}.prototype.has(key)` methods
8963 // https://tc39.es/ecma262/#sec-map.prototype.has
8964 // https://tc39.es/ecma262/#sec-set.prototype.has
8965 has: function has(key) {
8966 return !!getEntry(this, key);
8970 redefineAll(Prototype, IS_MAP ? {
8971 // `Map.prototype.get(key)` method
8972 // https://tc39.es/ecma262/#sec-map.prototype.get
8973 get: function get(key) {
8974 var entry = getEntry(this, key);
8975 return entry && entry.value;
8977 // `Map.prototype.set(key, value)` method
8978 // https://tc39.es/ecma262/#sec-map.prototype.set
8979 set: function set(key, value) {
8980 return define(this, key === 0 ? 0 : key, value);
8983 // `Set.prototype.add(value)` method
8984 // https://tc39.es/ecma262/#sec-set.prototype.add
8985 add: function add(value) {
8986 return define(this, value = value === 0 ? 0 : value, value);
8989 if (DESCRIPTORS$6) defineProperty$2(Prototype, 'size', {
8991 return getInternalState(this).size;
8996 setStrong: function (Constructor, CONSTRUCTOR_NAME, IS_MAP) {
8997 var ITERATOR_NAME = CONSTRUCTOR_NAME + ' Iterator';
8998 var getInternalCollectionState = internalStateGetterFor(CONSTRUCTOR_NAME);
8999 var getInternalIteratorState = internalStateGetterFor(ITERATOR_NAME);
9000 // `{ Map, Set }.prototype.{ keys, values, entries, @@iterator }()` methods
9001 // https://tc39.es/ecma262/#sec-map.prototype.entries
9002 // https://tc39.es/ecma262/#sec-map.prototype.keys
9003 // https://tc39.es/ecma262/#sec-map.prototype.values
9004 // https://tc39.es/ecma262/#sec-map.prototype-@@iterator
9005 // https://tc39.es/ecma262/#sec-set.prototype.entries
9006 // https://tc39.es/ecma262/#sec-set.prototype.keys
9007 // https://tc39.es/ecma262/#sec-set.prototype.values
9008 // https://tc39.es/ecma262/#sec-set.prototype-@@iterator
9009 defineIterator(Constructor, CONSTRUCTOR_NAME, function (iterated, kind) {
9010 setInternalState$1(this, {
9011 type: ITERATOR_NAME,
9013 state: getInternalCollectionState(iterated),
9018 var state = getInternalIteratorState(this);
9019 var kind = state.kind;
9020 var entry = state.last;
9021 // revert to the last existing entry
9022 while (entry && entry.removed) entry = entry.previous;
9024 if (!state.target || !(state.last = entry = entry ? entry.next : state.state.first)) {
9025 // or finish the iteration
9026 state.target = undefined;
9027 return { value: undefined, done: true };
9029 // return step by kind
9030 if (kind == 'keys') return { value: entry.key, done: false };
9031 if (kind == 'values') return { value: entry.value, done: false };
9032 return { value: [entry.key, entry.value], done: false };
9033 }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);
9035 // `{ Map, Set }.prototype[@@species]` accessors
9036 // https://tc39.es/ecma262/#sec-get-map-@@species
9037 // https://tc39.es/ecma262/#sec-get-set-@@species
9038 setSpecies$1(CONSTRUCTOR_NAME);
9042 var collection$1 = collection$2;
9043 var collectionStrong$1 = collectionStrong$2;
9045 // `Set` constructor
9046 // https://tc39.es/ecma262/#sec-set-objects
9047 collection$1('Set', function (init) {
9048 return function Set() { return init(this, arguments.length ? arguments[0] : undefined); };
9049 }, collectionStrong$1);
9051 function d3_ascending (a, b) {
9052 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
9055 function d3_bisector (f) {
9059 if (f.length === 1) {
9060 delta = function delta(d, x) {
9064 compare = ascendingComparator(f);
9067 function left(a, x, lo, hi) {
9068 if (lo == null) lo = 0;
9069 if (hi == null) hi = a.length;
9072 var mid = lo + hi >>> 1;
9073 if (compare(a[mid], x) < 0) lo = mid + 1;else hi = mid;
9079 function right(a, x, lo, hi) {
9080 if (lo == null) lo = 0;
9081 if (hi == null) hi = a.length;
9084 var mid = lo + hi >>> 1;
9085 if (compare(a[mid], x) > 0) hi = mid;else lo = mid + 1;
9091 function center(a, x, lo, hi) {
9092 if (lo == null) lo = 0;
9093 if (hi == null) hi = a.length;
9094 var i = left(a, x, lo, hi - 1);
9095 return i > lo && delta(a[i - 1], x) > -delta(a[i], x) ? i - 1 : i;
9105 function ascendingComparator(f) {
9106 return function (d, x) {
9107 return d3_ascending(f(d), x);
9111 var defineWellKnownSymbol = defineWellKnownSymbol$4;
9113 // `Symbol.asyncIterator` well-known symbol
9114 // https://tc39.es/ecma262/#sec-symbol.asynciterator
9115 defineWellKnownSymbol('asyncIterator');
9117 var runtime = {exports: {}};
9119 (function (module) {
9120 var runtime = function (exports) {
9122 var Op = Object.prototype;
9123 var hasOwn = Op.hasOwnProperty;
9124 var undefined$1; // More compressible than void 0.
9126 var $Symbol = typeof Symbol === "function" ? Symbol : {};
9127 var iteratorSymbol = $Symbol.iterator || "@@iterator";
9128 var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
9129 var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
9131 function define(obj, key, value) {
9132 Object.defineProperty(obj, key, {
9142 // IE 8 has a broken Object.defineProperty that only works on DOM objects.
9145 define = function define(obj, key, value) {
9146 return obj[key] = value;
9150 function wrap(innerFn, outerFn, self, tryLocsList) {
9151 // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.
9152 var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
9153 var generator = Object.create(protoGenerator.prototype);
9154 var context = new Context(tryLocsList || []); // The ._invoke method unifies the implementations of the .next,
9155 // .throw, and .return methods.
9157 generator._invoke = makeInvokeMethod(innerFn, self, context);
9161 exports.wrap = wrap; // Try/catch helper to minimize deoptimizations. Returns a completion
9162 // record like context.tryEntries[i].completion. This interface could
9163 // have been (and was previously) designed to take a closure to be
9164 // invoked without arguments, but in all the cases we care about we
9165 // already have an existing method we want to call, so there's no need
9166 // to create a new function object. We can even get away with assuming
9167 // the method takes exactly one argument, since that happens to be true
9168 // in every case, so we don't have to touch the arguments object. The
9169 // only additional allocation required is the completion record, which
9170 // has a stable shape and so hopefully should be cheap to allocate.
9172 function tryCatch(fn, obj, arg) {
9176 arg: fn.call(obj, arg)
9186 var GenStateSuspendedStart = "suspendedStart";
9187 var GenStateSuspendedYield = "suspendedYield";
9188 var GenStateExecuting = "executing";
9189 var GenStateCompleted = "completed"; // Returning this object from the innerFn has the same effect as
9190 // breaking out of the dispatch switch statement.
9192 var ContinueSentinel = {}; // Dummy constructor functions that we use as the .constructor and
9193 // .constructor.prototype properties for functions that return Generator
9194 // objects. For full spec compliance, you may wish to configure your
9195 // minifier not to mangle the names of these two functions.
9197 function Generator() {}
9199 function GeneratorFunction() {}
9201 function GeneratorFunctionPrototype() {} // This is a polyfill for %IteratorPrototype% for environments that
9202 // don't natively support it.
9205 var IteratorPrototype = {};
9206 define(IteratorPrototype, iteratorSymbol, function () {
9209 var getProto = Object.getPrototypeOf;
9210 var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
9212 if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
9213 // This environment has a native %IteratorPrototype%; use it instead
9215 IteratorPrototype = NativeIteratorPrototype;
9218 var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
9219 GeneratorFunction.prototype = GeneratorFunctionPrototype;
9220 define(Gp, "constructor", GeneratorFunctionPrototype);
9221 define(GeneratorFunctionPrototype, "constructor", GeneratorFunction);
9222 GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"); // Helper for defining the .next, .throw, and .return methods of the
9223 // Iterator interface in terms of a single ._invoke method.
9225 function defineIteratorMethods(prototype) {
9226 ["next", "throw", "return"].forEach(function (method) {
9227 define(prototype, method, function (arg) {
9228 return this._invoke(method, arg);
9233 exports.isGeneratorFunction = function (genFun) {
9234 var ctor = typeof genFun === "function" && genFun.constructor;
9235 return ctor ? ctor === GeneratorFunction || // For the native GeneratorFunction constructor, the best we can
9236 // do is to check its .name property.
9237 (ctor.displayName || ctor.name) === "GeneratorFunction" : false;
9240 exports.mark = function (genFun) {
9241 if (Object.setPrototypeOf) {
9242 Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
9244 genFun.__proto__ = GeneratorFunctionPrototype;
9245 define(genFun, toStringTagSymbol, "GeneratorFunction");
9248 genFun.prototype = Object.create(Gp);
9250 }; // Within the body of any async function, `await x` is transformed to
9251 // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
9252 // `hasOwn.call(value, "__await")` to determine if the yielded value is
9253 // meant to be awaited.
9256 exports.awrap = function (arg) {
9262 function AsyncIterator(generator, PromiseImpl) {
9263 function invoke(method, arg, resolve, reject) {
9264 var record = tryCatch(generator[method], generator, arg);
9266 if (record.type === "throw") {
9269 var result = record.arg;
9270 var value = result.value;
9272 if (value && _typeof(value) === "object" && hasOwn.call(value, "__await")) {
9273 return PromiseImpl.resolve(value.__await).then(function (value) {
9274 invoke("next", value, resolve, reject);
9276 invoke("throw", err, resolve, reject);
9280 return PromiseImpl.resolve(value).then(function (unwrapped) {
9281 // When a yielded Promise is resolved, its final value becomes
9282 // the .value of the Promise<{value,done}> result for the
9283 // current iteration.
9284 result.value = unwrapped;
9286 }, function (error) {
9287 // If a rejected Promise was yielded, throw the rejection back
9288 // into the async generator function so it can be handled there.
9289 return invoke("throw", error, resolve, reject);
9294 var previousPromise;
9296 function enqueue(method, arg) {
9297 function callInvokeWithMethodAndArg() {
9298 return new PromiseImpl(function (resolve, reject) {
9299 invoke(method, arg, resolve, reject);
9303 return previousPromise = // If enqueue has been called before, then we want to wait until
9304 // all previous Promises have been resolved before calling invoke,
9305 // so that results are always delivered in the correct order. If
9306 // enqueue has not been called before, then it is important to
9307 // call invoke immediately, without waiting on a callback to fire,
9308 // so that the async generator function has the opportunity to do
9309 // any necessary setup in a predictable way. This predictability
9310 // is why the Promise constructor synchronously invokes its
9311 // executor callback, and why async functions synchronously
9312 // execute code before the first await. Since we implement simple
9313 // async functions in terms of async generators, it is especially
9314 // important to get this right, even though it requires care.
9315 previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, // Avoid propagating failures to Promises returned by later
9316 // invocations of the iterator.
9317 callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
9318 } // Define the unified helper method that is used to implement .next,
9319 // .throw, and .return (see defineIteratorMethods).
9322 this._invoke = enqueue;
9325 defineIteratorMethods(AsyncIterator.prototype);
9326 define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
9329 exports.AsyncIterator = AsyncIterator; // Note that simple async functions are implemented on top of
9330 // AsyncIterator objects; they just return a Promise for the value of
9331 // the final result produced by the iterator.
9333 exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
9334 if (PromiseImpl === void 0) PromiseImpl = Promise;
9335 var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
9336 return exports.isGeneratorFunction(outerFn) ? iter // If outerFn is a generator, return the full iterator.
9337 : iter.next().then(function (result) {
9338 return result.done ? result.value : iter.next();
9342 function makeInvokeMethod(innerFn, self, context) {
9343 var state = GenStateSuspendedStart;
9344 return function invoke(method, arg) {
9345 if (state === GenStateExecuting) {
9346 throw new Error("Generator is already running");
9349 if (state === GenStateCompleted) {
9350 if (method === "throw") {
9352 } // Be forgiving, per 25.3.3.3.3 of the spec:
9353 // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
9356 return doneResult();
9359 context.method = method;
9363 var delegate = context.delegate;
9366 var delegateResult = maybeInvokeDelegate(delegate, context);
9368 if (delegateResult) {
9369 if (delegateResult === ContinueSentinel) continue;
9370 return delegateResult;
9374 if (context.method === "next") {
9375 // Setting context._sent for legacy support of Babel's
9376 // function.sent implementation.
9377 context.sent = context._sent = context.arg;
9378 } else if (context.method === "throw") {
9379 if (state === GenStateSuspendedStart) {
9380 state = GenStateCompleted;
9384 context.dispatchException(context.arg);
9385 } else if (context.method === "return") {
9386 context.abrupt("return", context.arg);
9389 state = GenStateExecuting;
9390 var record = tryCatch(innerFn, self, context);
9392 if (record.type === "normal") {
9393 // If an exception is thrown from innerFn, we leave state ===
9394 // GenStateExecuting and loop back for another invocation.
9395 state = context.done ? GenStateCompleted : GenStateSuspendedYield;
9397 if (record.arg === ContinueSentinel) {
9405 } else if (record.type === "throw") {
9406 state = GenStateCompleted; // Dispatch the exception by looping back around to the
9407 // context.dispatchException(context.arg) call above.
9409 context.method = "throw";
9410 context.arg = record.arg;
9414 } // Call delegate.iterator[context.method](context.arg) and handle the
9415 // result, either by returning a { value, done } result from the
9416 // delegate iterator, or by modifying context.method and context.arg,
9417 // setting context.delegate to null, and returning the ContinueSentinel.
9420 function maybeInvokeDelegate(delegate, context) {
9421 var method = delegate.iterator[context.method];
9423 if (method === undefined$1) {
9424 // A .throw or .return when the delegate iterator has no .throw
9425 // method always terminates the yield* loop.
9426 context.delegate = null;
9428 if (context.method === "throw") {
9429 // Note: ["return"] must be used for ES3 parsing compatibility.
9430 if (delegate.iterator["return"]) {
9431 // If the delegate iterator has a return method, give it a
9432 // chance to clean up.
9433 context.method = "return";
9434 context.arg = undefined$1;
9435 maybeInvokeDelegate(delegate, context);
9437 if (context.method === "throw") {
9438 // If maybeInvokeDelegate(context) changed context.method from
9439 // "return" to "throw", let that override the TypeError below.
9440 return ContinueSentinel;
9444 context.method = "throw";
9445 context.arg = new TypeError("The iterator does not provide a 'throw' method");
9448 return ContinueSentinel;
9451 var record = tryCatch(method, delegate.iterator, context.arg);
9453 if (record.type === "throw") {
9454 context.method = "throw";
9455 context.arg = record.arg;
9456 context.delegate = null;
9457 return ContinueSentinel;
9460 var info = record.arg;
9463 context.method = "throw";
9464 context.arg = new TypeError("iterator result is not an object");
9465 context.delegate = null;
9466 return ContinueSentinel;
9470 // Assign the result of the finished delegate to the temporary
9471 // variable specified by delegate.resultName (see delegateYield).
9472 context[delegate.resultName] = info.value; // Resume execution at the desired location (see delegateYield).
9474 context.next = delegate.nextLoc; // If context.method was "throw" but the delegate handled the
9475 // exception, let the outer generator proceed normally. If
9476 // context.method was "next", forget context.arg since it has been
9477 // "consumed" by the delegate iterator. If context.method was
9478 // "return", allow the original .return call to continue in the
9481 if (context.method !== "return") {
9482 context.method = "next";
9483 context.arg = undefined$1;
9486 // Re-yield the result returned by the delegate method.
9488 } // The delegate iterator is finished, so forget it and continue with
9489 // the outer generator.
9492 context.delegate = null;
9493 return ContinueSentinel;
9494 } // Define Generator.prototype.{next,throw,return} in terms of the
9495 // unified ._invoke helper method.
9498 defineIteratorMethods(Gp);
9499 define(Gp, toStringTagSymbol, "Generator"); // A Generator should always return itself as the iterator object when the
9500 // @@iterator function is called on it. Some browsers' implementations of the
9501 // iterator prototype chain incorrectly implement this, causing the Generator
9502 // object to not be returned from this call. This ensures that doesn't happen.
9503 // See https://github.com/facebook/regenerator/issues/274 for more details.
9505 define(Gp, iteratorSymbol, function () {
9508 define(Gp, "toString", function () {
9509 return "[object Generator]";
9512 function pushTryEntry(locs) {
9518 entry.catchLoc = locs[1];
9522 entry.finallyLoc = locs[2];
9523 entry.afterLoc = locs[3];
9526 this.tryEntries.push(entry);
9529 function resetTryEntry(entry) {
9530 var record = entry.completion || {};
9531 record.type = "normal";
9533 entry.completion = record;
9536 function Context(tryLocsList) {
9537 // The root entry object (effectively a try statement without a catch
9538 // or a finally block) gives us a place to store values thrown from
9539 // locations where there is no enclosing try statement.
9540 this.tryEntries = [{
9543 tryLocsList.forEach(pushTryEntry, this);
9547 exports.keys = function (object) {
9550 for (var key in object) {
9554 keys.reverse(); // Rather than returning an object with a next method, we keep
9555 // things simple and return the next function itself.
9557 return function next() {
9558 while (keys.length) {
9559 var key = keys.pop();
9561 if (key in object) {
9566 } // To avoid creating an additional object, we just hang the .value
9567 // and .done properties off the next function object itself. This
9568 // also ensures that the minifier will not anonymize the function.
9576 function values(iterable) {
9578 var iteratorMethod = iterable[iteratorSymbol];
9580 if (iteratorMethod) {
9581 return iteratorMethod.call(iterable);
9584 if (typeof iterable.next === "function") {
9588 if (!isNaN(iterable.length)) {
9590 next = function next() {
9591 while (++i < iterable.length) {
9592 if (hasOwn.call(iterable, i)) {
9593 next.value = iterable[i];
9599 next.value = undefined$1;
9604 return next.next = next;
9606 } // Return an iterator with no values.
9614 exports.values = values;
9616 function doneResult() {
9623 Context.prototype = {
9624 constructor: Context,
9625 reset: function reset(skipTempReset) {
9627 this.next = 0; // Resetting context._sent for legacy support of Babel's
9628 // function.sent implementation.
9630 this.sent = this._sent = undefined$1;
9632 this.delegate = null;
9633 this.method = "next";
9634 this.arg = undefined$1;
9635 this.tryEntries.forEach(resetTryEntry);
9637 if (!skipTempReset) {
9638 for (var name in this) {
9639 // Not sure about the optimal order of these conditions:
9640 if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) {
9641 this[name] = undefined$1;
9646 stop: function stop() {
9648 var rootEntry = this.tryEntries[0];
9649 var rootRecord = rootEntry.completion;
9651 if (rootRecord.type === "throw") {
9652 throw rootRecord.arg;
9657 dispatchException: function dispatchException(exception) {
9664 function handle(loc, caught) {
9665 record.type = "throw";
9666 record.arg = exception;
9670 // If the dispatched exception was caught by a catch block,
9671 // then let that catch block handle the exception normally.
9672 context.method = "next";
9673 context.arg = undefined$1;
9679 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
9680 var entry = this.tryEntries[i];
9681 var record = entry.completion;
9683 if (entry.tryLoc === "root") {
9684 // Exception thrown outside of any try block that could handle
9685 // it, so set the completion value of the entire function to
9686 // throw the exception.
9687 return handle("end");
9690 if (entry.tryLoc <= this.prev) {
9691 var hasCatch = hasOwn.call(entry, "catchLoc");
9692 var hasFinally = hasOwn.call(entry, "finallyLoc");
9694 if (hasCatch && hasFinally) {
9695 if (this.prev < entry.catchLoc) {
9696 return handle(entry.catchLoc, true);
9697 } else if (this.prev < entry.finallyLoc) {
9698 return handle(entry.finallyLoc);
9700 } else if (hasCatch) {
9701 if (this.prev < entry.catchLoc) {
9702 return handle(entry.catchLoc, true);
9704 } else if (hasFinally) {
9705 if (this.prev < entry.finallyLoc) {
9706 return handle(entry.finallyLoc);
9709 throw new Error("try statement without catch or finally");
9714 abrupt: function abrupt(type, arg) {
9715 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
9716 var entry = this.tryEntries[i];
9718 if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
9719 var finallyEntry = entry;
9724 if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) {
9725 // Ignore the finally entry if control is not jumping to a
9726 // location outside the try/catch block.
9727 finallyEntry = null;
9730 var record = finallyEntry ? finallyEntry.completion : {};
9735 this.method = "next";
9736 this.next = finallyEntry.finallyLoc;
9737 return ContinueSentinel;
9740 return this.complete(record);
9742 complete: function complete(record, afterLoc) {
9743 if (record.type === "throw") {
9747 if (record.type === "break" || record.type === "continue") {
9748 this.next = record.arg;
9749 } else if (record.type === "return") {
9750 this.rval = this.arg = record.arg;
9751 this.method = "return";
9753 } else if (record.type === "normal" && afterLoc) {
9754 this.next = afterLoc;
9757 return ContinueSentinel;
9759 finish: function finish(finallyLoc) {
9760 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
9761 var entry = this.tryEntries[i];
9763 if (entry.finallyLoc === finallyLoc) {
9764 this.complete(entry.completion, entry.afterLoc);
9765 resetTryEntry(entry);
9766 return ContinueSentinel;
9770 "catch": function _catch(tryLoc) {
9771 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
9772 var entry = this.tryEntries[i];
9774 if (entry.tryLoc === tryLoc) {
9775 var record = entry.completion;
9777 if (record.type === "throw") {
9778 var thrown = record.arg;
9779 resetTryEntry(entry);
9784 } // The context.catch method must only be called with a location
9785 // argument that corresponds to a known catch block.
9788 throw new Error("illegal catch attempt");
9790 delegateYield: function delegateYield(iterable, resultName, nextLoc) {
9792 iterator: values(iterable),
9793 resultName: resultName,
9797 if (this.method === "next") {
9798 // Deliberately forget the last sent value so that we don't
9799 // accidentally pass it on to the delegate.
9800 this.arg = undefined$1;
9803 return ContinueSentinel;
9805 }; // Regardless of whether this script is executing as a CommonJS module
9806 // or not, return the runtime object so that we can declare the variable
9807 // regeneratorRuntime in the outer scope, which allows this module to be
9808 // injected easily by `bin/regenerator --include-runtime script.js`.
9811 }( // If this script is executing as a CommonJS module, use module.exports
9812 // as the regeneratorRuntime namespace. Otherwise create a new empty
9813 // object. Either way, the resulting object will be used to initialize
9814 // the regeneratorRuntime variable at the top of this file.
9818 regeneratorRuntime = runtime;
9819 } catch (accidentalStrictMode) {
9820 // This module should not be running in strict mode, so the above
9821 // assignment should always work unless something is misconfigured. Just
9822 // in case runtime.js accidentally runs in strict mode, in modern engines
9823 // we can explicitly access globalThis. In older engines we can escape
9824 // strict mode using a global Function call. This could conceivably fail
9825 // if a Content Security Policy forbids using Function, but in that case
9826 // the proper solution is to fix the accidental strict mode problem. If
9827 // you've misconfigured your bundler to force strict mode and applied a
9828 // CSP to forbid Function, and you're not willing to fix either of those
9829 // problems, please detail your unique predicament in a GitHub issue.
9830 if ((typeof globalThis === "undefined" ? "undefined" : _typeof(globalThis)) === "object") {
9831 globalThis.regeneratorRuntime = runtime;
9833 Function("r", "regeneratorRuntime = r")(runtime);
9838 var _marked$3 = /*#__PURE__*/regeneratorRuntime.mark(numbers);
9840 function number$1 (x) {
9841 return x === null ? NaN : +x;
9843 function numbers(values, valueof) {
9844 var _iterator, _step, value, index, _iterator2, _step2, _value;
9846 return regeneratorRuntime.wrap(function numbers$(_context) {
9848 switch (_context.prev = _context.next) {
9850 if (!(valueof === undefined)) {
9855 _iterator = _createForOfIteratorHelper(values);
9861 if ((_step = _iterator.n()).done) {
9866 value = _step.value;
9868 if (!(value != null && (value = +value) >= value)) {
9886 _context.t0 = _context["catch"](2);
9888 _iterator.e(_context.t0);
9895 return _context.finish(16);
9903 _iterator2 = _createForOfIteratorHelper(values);
9909 if ((_step2 = _iterator2.n()).done) {
9914 _value = _step2.value;
9916 if (!((_value = valueof(_value, ++index, values)) != null && (_value = +_value) >= _value)) {
9934 _context.t1 = _context["catch"](23);
9936 _iterator2.e(_context.t1);
9943 return _context.finish(37);
9947 return _context.stop();
9950 }, _marked$3, null, [[2, 13, 16, 19], [23, 34, 37, 40]]);
9953 var ascendingBisect = d3_bisector(d3_ascending);
9954 var bisectRight = ascendingBisect.right;
9955 d3_bisector(number$1).center;
9957 var anObject$2 = anObject$n;
9958 var iteratorClose = iteratorClose$2;
9960 // call something on iterator step with safe closing on error
9961 var callWithSafeIterationClosing$1 = function (iterator, fn, value, ENTRIES) {
9963 return ENTRIES ? fn(anObject$2(value)[0], value[1]) : fn(value);
9965 iteratorClose(iterator, 'throw', error);
9969 var global$c = global$1o;
9970 var bind$5 = functionBindContext;
9971 var call$3 = functionCall;
9972 var toObject$3 = toObject$i;
9973 var callWithSafeIterationClosing = callWithSafeIterationClosing$1;
9974 var isArrayIteratorMethod = isArrayIteratorMethod$3;
9975 var isConstructor = isConstructor$4;
9976 var lengthOfArrayLike$3 = lengthOfArrayLike$i;
9977 var createProperty = createProperty$5;
9978 var getIterator = getIterator$4;
9979 var getIteratorMethod = getIteratorMethod$5;
9981 var Array$1 = global$c.Array;
9983 // `Array.from` method implementation
9984 // https://tc39.es/ecma262/#sec-array.from
9985 var arrayFrom$1 = function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {
9986 var O = toObject$3(arrayLike);
9987 var IS_CONSTRUCTOR = isConstructor(this);
9988 var argumentsLength = arguments.length;
9989 var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
9990 var mapping = mapfn !== undefined;
9991 if (mapping) mapfn = bind$5(mapfn, argumentsLength > 2 ? arguments[2] : undefined);
9992 var iteratorMethod = getIteratorMethod(O);
9994 var length, result, step, iterator, next, value;
9995 // if the target is not iterable or it's an array with the default iterator - use a simple case
9996 if (iteratorMethod && !(this == Array$1 && isArrayIteratorMethod(iteratorMethod))) {
9997 iterator = getIterator(O, iteratorMethod);
9998 next = iterator.next;
9999 result = IS_CONSTRUCTOR ? new this() : [];
10000 for (;!(step = call$3(next, iterator)).done; index++) {
10001 value = mapping ? callWithSafeIterationClosing(iterator, mapfn, [step.value, index], true) : step.value;
10002 createProperty(result, index, value);
10005 length = lengthOfArrayLike$3(O);
10006 result = IS_CONSTRUCTOR ? new this(length) : Array$1(length);
10007 for (;length > index; index++) {
10008 value = mapping ? mapfn(O[index], index) : O[index];
10009 createProperty(result, index, value);
10012 result.length = index;
10017 var from = arrayFrom$1;
10018 var checkCorrectnessOfIteration = checkCorrectnessOfIteration$4;
10020 var INCORRECT_ITERATION = !checkCorrectnessOfIteration(function (iterable) {
10021 // eslint-disable-next-line es/no-array-from -- required for testing
10022 Array.from(iterable);
10025 // `Array.from` method
10026 // https://tc39.es/ecma262/#sec-array.from
10027 $$D({ target: 'Array', stat: true, forced: INCORRECT_ITERATION }, {
10032 var fill = arrayFill$1;
10033 var addToUnscopables$4 = addToUnscopables$6;
10035 // `Array.prototype.fill` method
10036 // https://tc39.es/ecma262/#sec-array.prototype.fill
10037 $$C({ target: 'Array', proto: true }, {
10041 // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
10042 addToUnscopables$4('fill');
10045 var $some = arrayIteration.some;
10046 var arrayMethodIsStrict$4 = arrayMethodIsStrict$9;
10048 var STRICT_METHOD$4 = arrayMethodIsStrict$4('some');
10050 // `Array.prototype.some` method
10051 // https://tc39.es/ecma262/#sec-array.prototype.some
10052 $$B({ target: 'Array', proto: true, forced: !STRICT_METHOD$4 }, {
10053 some: function some(callbackfn /* , thisArg */) {
10054 return $some(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
10058 var TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS = typedArrayConstructorsRequireWrappers;
10059 var exportTypedArrayStaticMethod = arrayBufferViewCore.exportTypedArrayStaticMethod;
10060 var typedArrayFrom = typedArrayFrom$2;
10062 // `%TypedArray%.from` method
10063 // https://tc39.es/ecma262/#sec-%typedarray%.from
10064 exportTypedArrayStaticMethod('from', typedArrayFrom, TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS);
10066 var createTypedArrayConstructor = typedArrayConstructor.exports;
10068 // `Float64Array` constructor
10069 // https://tc39.es/ecma262/#sec-typedarray-objects
10070 createTypedArrayConstructor('Float64', function (init) {
10071 return function Float64Array(data, byteOffset, length) {
10072 return init(this, data, byteOffset, length);
10076 function d3_descending (a, b) {
10077 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
10080 // https://github.com/python/cpython/blob/a74eea238f5baba15797e2e8b570d153bc8690a7/Modules/mathmodule.c#L1423
10081 var Adder = /*#__PURE__*/function () {
10083 _classCallCheck$1(this, Adder);
10085 this._partials = new Float64Array(32);
10089 _createClass$1(Adder, [{
10091 value: function add(x) {
10092 var p = this._partials;
10095 for (var j = 0; j < this._n && j < 32; j++) {
10098 lo = Math.abs(x) < Math.abs(y) ? x - (hi - y) : y - (hi - x);
10099 if (lo) p[i++] = lo;
10109 value: function valueOf() {
10110 var p = this._partials;
10128 if (n > 0 && (lo < 0 && p[n - 1] < 0 || lo > 0 && p[n - 1] > 0)) {
10131 if (y == x - hi) hi = x;
10143 var DESCRIPTORS$5 = descriptors;
10144 var defineProperties$1 = objectDefineProperties.f;
10146 // `Object.defineProperties` method
10147 // https://tc39.es/ecma262/#sec-object.defineproperties
10148 // eslint-disable-next-line es/no-object-defineproperties -- safe
10149 $$A({ target: 'Object', stat: true, forced: Object.defineProperties !== defineProperties$1, sham: !DESCRIPTORS$5 }, {
10150 defineProperties: defineProperties$1
10153 var collection = collection$2;
10154 var collectionStrong = collectionStrong$2;
10156 // `Map` constructor
10157 // https://tc39.es/ecma262/#sec-map-objects
10158 collection('Map', function (init) {
10159 return function Map() { return init(this, arguments.length ? arguments[0] : undefined); };
10160 }, collectionStrong);
10163 var uncurryThis$f = functionUncurryThis;
10164 var aCallable$1 = aCallable$a;
10165 var toObject$2 = toObject$i;
10166 var lengthOfArrayLike$2 = lengthOfArrayLike$i;
10167 var toString$a = toString$k;
10168 var fails$b = fails$V;
10169 var internalSort = arraySort$1;
10170 var arrayMethodIsStrict$3 = arrayMethodIsStrict$9;
10171 var FF = engineFfVersion;
10172 var IE_OR_EDGE = engineIsIeOrEdge;
10173 var V8 = engineV8Version;
10174 var WEBKIT = engineWebkitVersion;
10177 var un$Sort = uncurryThis$f(test.sort);
10178 var push$3 = uncurryThis$f(test.push);
10181 var FAILS_ON_UNDEFINED = fails$b(function () {
10182 test.sort(undefined);
10185 var FAILS_ON_NULL = fails$b(function () {
10189 var STRICT_METHOD$3 = arrayMethodIsStrict$3('sort');
10191 var STABLE_SORT = !fails$b(function () {
10192 // feature detection can be too slow, so check engines versions
10193 if (V8) return V8 < 70;
10194 if (FF && FF > 3) return;
10195 if (IE_OR_EDGE) return true;
10196 if (WEBKIT) return WEBKIT < 603;
10199 var code, chr, value, index;
10201 // generate an array with more 512 elements (Chakra and old V8 fails only in this case)
10202 for (code = 65; code < 76; code++) {
10203 chr = String.fromCharCode(code);
10206 case 66: case 69: case 70: case 72: value = 3; break;
10207 case 68: case 71: value = 4; break;
10208 default: value = 2;
10211 for (index = 0; index < 47; index++) {
10212 test.push({ k: chr + index, v: value });
10216 test.sort(function (a, b) { return b.v - a.v; });
10218 for (index = 0; index < test.length; index++) {
10219 chr = test[index].k.charAt(0);
10220 if (result.charAt(result.length - 1) !== chr) result += chr;
10223 return result !== 'DGBEFHACIJK';
10226 var FORCED$7 = FAILS_ON_UNDEFINED || !FAILS_ON_NULL || !STRICT_METHOD$3 || !STABLE_SORT;
10228 var getSortCompare = function (comparefn) {
10229 return function (x, y) {
10230 if (y === undefined) return -1;
10231 if (x === undefined) return 1;
10232 if (comparefn !== undefined) return +comparefn(x, y) || 0;
10233 return toString$a(x) > toString$a(y) ? 1 : -1;
10237 // `Array.prototype.sort` method
10238 // https://tc39.es/ecma262/#sec-array.prototype.sort
10239 $$z({ target: 'Array', proto: true, forced: FORCED$7 }, {
10240 sort: function sort(comparefn) {
10241 if (comparefn !== undefined) aCallable$1(comparefn);
10243 var array = toObject$2(this);
10245 if (STABLE_SORT) return comparefn === undefined ? un$Sort(array) : un$Sort(array, comparefn);
10248 var arrayLength = lengthOfArrayLike$2(array);
10249 var itemsLength, index;
10251 for (index = 0; index < arrayLength; index++) {
10252 if (index in array) push$3(items, array[index]);
10255 internalSort(items, getSortCompare(comparefn));
10257 itemsLength = items.length;
10260 while (index < itemsLength) array[index] = items[index++];
10261 while (index < arrayLength) delete array[index++];
10267 var e10 = Math.sqrt(50),
10268 e5 = Math.sqrt(10),
10270 function ticks (start, stop, count) {
10276 stop = +stop, start = +start, count = +count;
10277 if (start === stop && count > 0) return [start];
10278 if (reverse = stop < start) n = start, start = stop, stop = n;
10279 if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return [];
10282 var r0 = Math.round(start / step),
10283 r1 = Math.round(stop / step);
10284 if (r0 * step < start) ++r0;
10285 if (r1 * step > stop) --r1;
10286 ticks = new Array(n = r1 - r0 + 1);
10289 ticks[i] = (r0 + i) * step;
10294 var _r = Math.round(start * step),
10295 _r2 = Math.round(stop * step);
10297 if (_r / step < start) ++_r;
10298 if (_r2 / step > stop) --_r2;
10299 ticks = new Array(n = _r2 - _r + 1);
10302 ticks[i] = (_r + i) / step;
10306 if (reverse) ticks.reverse();
10309 function tickIncrement(start, stop, count) {
10310 var step = (stop - start) / Math.max(0, count),
10311 power = Math.floor(Math.log(step) / Math.LN10),
10312 error = step / Math.pow(10, power);
10313 return power >= 0 ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1);
10315 function tickStep(start, stop, count) {
10316 var step0 = Math.abs(stop - start) / Math.max(0, count),
10317 step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
10318 error = step0 / step1;
10319 if (error >= e10) step1 *= 10;else if (error >= e5) step1 *= 5;else if (error >= e2) step1 *= 2;
10320 return stop < start ? -step1 : step1;
10323 function max(values, valueof) {
10326 if (valueof === undefined) {
10327 var _iterator = _createForOfIteratorHelper(values),
10331 for (_iterator.s(); !(_step = _iterator.n()).done;) {
10332 var value = _step.value;
10334 if (value != null && (max < value || max === undefined && value >= value)) {
10346 var _iterator2 = _createForOfIteratorHelper(values),
10350 for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
10351 var _value = _step2.value;
10353 if ((_value = valueof(_value, ++index, values)) != null && (max < _value || max === undefined && _value >= _value)) {
10367 function min$2(values, valueof) {
10370 if (valueof === undefined) {
10371 var _iterator = _createForOfIteratorHelper(values),
10375 for (_iterator.s(); !(_step = _iterator.n()).done;) {
10376 var value = _step.value;
10378 if (value != null && (min > value || min === undefined && value >= value)) {
10390 var _iterator2 = _createForOfIteratorHelper(values),
10394 for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
10395 var _value = _step2.value;
10397 if ((_value = valueof(_value, ++index, values)) != null && (min > _value || min === undefined && _value >= _value)) {
10411 // ISC license, Copyright 2018 Vladimir Agafonkin.
10413 function quickselect$3(array, k) {
10414 var left = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
10415 var right = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : array.length - 1;
10416 var compare = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : d3_ascending;
10418 while (right > left) {
10419 if (right - left > 600) {
10420 var n = right - left + 1;
10421 var m = k - left + 1;
10422 var z = Math.log(n);
10423 var s = 0.5 * Math.exp(2 * z / 3);
10424 var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
10425 var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
10426 var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
10427 quickselect$3(array, k, newLeft, newRight, compare);
10433 swap$1(array, left, k);
10434 if (compare(array[right], t) > 0) swap$1(array, left, right);
10437 swap$1(array, i, j), ++i, --j;
10439 while (compare(array[i], t) < 0) {
10443 while (compare(array[j], t) > 0) {
10448 if (compare(array[left], t) === 0) swap$1(array, left, j);else ++j, swap$1(array, j, right);
10449 if (j <= k) left = j + 1;
10450 if (k <= j) right = j - 1;
10456 function swap$1(array, i, j) {
10458 array[i] = array[j];
10462 function quantile(values, p, valueof) {
10463 values = Float64Array.from(numbers(values, valueof));
10464 if (!(n = values.length)) return;
10465 if ((p = +p) <= 0 || n < 2) return min$2(values);
10466 if (p >= 1) return max(values);
10469 i0 = Math.floor(i),
10470 value0 = max(quickselect$3(values, i0).subarray(0, i0 + 1)),
10471 value1 = min$2(values.subarray(i0 + 1));
10472 return value0 + (value1 - value0) * (i - i0);
10475 function d3_median (values, valueof) {
10476 return quantile(values, 0.5, valueof);
10479 var _marked$2 = /*#__PURE__*/regeneratorRuntime.mark(flatten);
10481 function flatten(arrays) {
10482 var _iterator, _step, array;
10484 return regeneratorRuntime.wrap(function flatten$(_context) {
10486 switch (_context.prev = _context.next) {
10488 _iterator = _createForOfIteratorHelper(arrays);
10494 if ((_step = _iterator.n()).done) {
10499 array = _step.value;
10500 return _context.delegateYield(array, "t0", 6);
10507 _context.next = 13;
10511 _context.prev = 10;
10512 _context.t1 = _context["catch"](1);
10514 _iterator.e(_context.t1);
10517 _context.prev = 13;
10521 return _context.finish(13);
10525 return _context.stop();
10528 }, _marked$2, null, [[1, 10, 13, 16]]);
10531 function merge$4(arrays) {
10532 return Array.from(flatten(arrays));
10535 function range$1 (start, stop, step) {
10536 start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
10538 n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
10539 range = new Array(n);
10542 range[i] = start + i * step;
10548 // `SameValue` abstract operation
10549 // https://tc39.es/ecma262/#sec-samevalue
10550 // eslint-disable-next-line es/no-object-is -- safe
10551 var sameValue$1 = Object.is || function is(x, y) {
10552 // eslint-disable-next-line no-self-compare -- NaN check
10553 return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;
10558 // eslint-disable-next-line es/no-math-hypot -- required for testing
10559 var $hypot = Math.hypot;
10560 var abs$3 = Math.abs;
10561 var sqrt$1 = Math.sqrt;
10564 // https://bugs.chromium.org/p/v8/issues/detail?id=9546
10565 var BUGGY = !!$hypot && $hypot(Infinity, NaN) !== Infinity;
10567 // `Math.hypot` method
10568 // https://tc39.es/ecma262/#sec-math.hypot
10569 $$y({ target: 'Math', stat: true, forced: BUGGY }, {
10570 // eslint-disable-next-line no-unused-vars -- required for `.length`
10571 hypot: function hypot(value1, value2) {
10574 var aLen = arguments.length;
10578 arg = abs$3(arguments[i++]);
10581 sum = sum * div * div + 1;
10583 } else if (arg > 0) {
10588 return larg === Infinity ? Infinity : larg * sqrt$1(sum);
10592 // `Math.sign` method implementation
10593 // https://tc39.es/ecma262/#sec-math.sign
10594 // eslint-disable-next-line es/no-math-sign -- safe
10595 var mathSign = Math.sign || function sign(x) {
10596 // eslint-disable-next-line no-self-compare -- NaN check
10597 return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1;
10601 var sign$1 = mathSign;
10603 // `Math.sign` method
10604 // https://tc39.es/ecma262/#sec-math.sign
10605 $$x({ target: 'Math', stat: true }, {
10609 var epsilon$1 = 1e-6;
10610 var epsilon2$1 = 1e-12;
10612 var halfPi = pi / 2;
10613 var quarterPi = pi / 4;
10615 var degrees$1 = 180 / pi;
10616 var radians = pi / 180;
10617 var abs$2 = Math.abs;
10618 var atan = Math.atan;
10619 var atan2 = Math.atan2;
10620 var cos = Math.cos;
10621 var exp$2 = Math.exp;
10622 var log$1 = Math.log;
10623 var sin = Math.sin;
10624 var sign = Math.sign || function (x) {
10625 return x > 0 ? 1 : x < 0 ? -1 : 0;
10627 var sqrt = Math.sqrt;
10628 var tan = Math.tan;
10630 return x > 1 ? 0 : x < -1 ? pi : Math.acos(x);
10633 return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x);
10636 function noop$1() {}
10638 function streamGeometry(geometry, stream) {
10639 if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
10640 streamGeometryType[geometry.type](geometry, stream);
10644 var streamObjectType = {
10645 Feature: function Feature(object, stream) {
10646 streamGeometry(object.geometry, stream);
10648 FeatureCollection: function FeatureCollection(object, stream) {
10649 var features = object.features,
10651 n = features.length;
10654 streamGeometry(features[i].geometry, stream);
10658 var streamGeometryType = {
10659 Sphere: function Sphere(object, stream) {
10662 Point: function Point(object, stream) {
10663 object = object.coordinates;
10664 stream.point(object[0], object[1], object[2]);
10666 MultiPoint: function MultiPoint(object, stream) {
10667 var coordinates = object.coordinates,
10669 n = coordinates.length;
10672 object = coordinates[i], stream.point(object[0], object[1], object[2]);
10675 LineString: function LineString(object, stream) {
10676 streamLine(object.coordinates, stream, 0);
10678 MultiLineString: function MultiLineString(object, stream) {
10679 var coordinates = object.coordinates,
10681 n = coordinates.length;
10684 streamLine(coordinates[i], stream, 0);
10687 Polygon: function Polygon(object, stream) {
10688 streamPolygon(object.coordinates, stream);
10690 MultiPolygon: function MultiPolygon(object, stream) {
10691 var coordinates = object.coordinates,
10693 n = coordinates.length;
10696 streamPolygon(coordinates[i], stream);
10699 GeometryCollection: function GeometryCollection(object, stream) {
10700 var geometries = object.geometries,
10702 n = geometries.length;
10705 streamGeometry(geometries[i], stream);
10710 function streamLine(coordinates, stream, closed) {
10712 n = coordinates.length - closed,
10714 stream.lineStart();
10717 coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
10723 function streamPolygon(coordinates, stream) {
10725 n = coordinates.length;
10726 stream.polygonStart();
10729 streamLine(coordinates[i], stream, 1);
10732 stream.polygonEnd();
10735 function d3_geoStream (object, stream) {
10736 if (object && streamObjectType.hasOwnProperty(object.type)) {
10737 streamObjectType[object.type](object, stream);
10739 streamGeometry(object, stream);
10743 var areaRingSum$1 = new Adder(); // hello?
10745 var areaSum$1 = new Adder(),
10751 var areaStream$1 = {
10755 polygonStart: function polygonStart() {
10756 areaRingSum$1 = new Adder();
10757 areaStream$1.lineStart = areaRingStart$1;
10758 areaStream$1.lineEnd = areaRingEnd$1;
10760 polygonEnd: function polygonEnd() {
10761 var areaRing = +areaRingSum$1;
10762 areaSum$1.add(areaRing < 0 ? tau + areaRing : areaRing);
10763 this.lineStart = this.lineEnd = this.point = noop$1;
10765 sphere: function sphere() {
10766 areaSum$1.add(tau);
10770 function areaRingStart$1() {
10771 areaStream$1.point = areaPointFirst$1;
10774 function areaRingEnd$1() {
10775 areaPoint$1(lambda00$1, phi00$1);
10778 function areaPointFirst$1(lambda, phi) {
10779 areaStream$1.point = areaPoint$1;
10780 lambda00$1 = lambda, phi00$1 = phi;
10781 lambda *= radians, phi *= radians;
10782 lambda0$2 = lambda, cosPhi0$1 = cos(phi = phi / 2 + quarterPi), sinPhi0$1 = sin(phi);
10785 function areaPoint$1(lambda, phi) {
10786 lambda *= radians, phi *= radians;
10787 phi = phi / 2 + quarterPi; // half the angular distance from south pole
10788 // Spherical excess E for a spherical triangle with vertices: south pole,
10789 // previous point, current point. Uses a formula derived from Cagnoli’s
10790 // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
10792 var dLambda = lambda - lambda0$2,
10793 sdLambda = dLambda >= 0 ? 1 : -1,
10794 adLambda = sdLambda * dLambda,
10797 k = sinPhi0$1 * sinPhi,
10798 u = cosPhi0$1 * cosPhi + k * cos(adLambda),
10799 v = k * sdLambda * sin(adLambda);
10800 areaRingSum$1.add(atan2(v, u)); // Advance the previous points.
10802 lambda0$2 = lambda, cosPhi0$1 = cosPhi, sinPhi0$1 = sinPhi;
10805 function d3_geoArea (object) {
10806 areaSum$1 = new Adder();
10807 d3_geoStream(object, areaStream$1);
10808 return areaSum$1 * 2;
10811 function spherical(cartesian) {
10812 return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])];
10814 function cartesian(spherical) {
10815 var lambda = spherical[0],
10816 phi = spherical[1],
10818 return [cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi)];
10820 function cartesianDot(a, b) {
10821 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
10823 function cartesianCross(a, b) {
10824 return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
10827 function cartesianAddInPlace(a, b) {
10828 a[0] += b[0], a[1] += b[1], a[2] += b[2];
10830 function cartesianScale(vector, k) {
10831 return [vector[0] * k, vector[1] * k, vector[2] * k];
10834 function cartesianNormalizeInPlace(d) {
10835 var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
10836 d[0] /= l, d[1] /= l, d[2] /= l;
10839 var lambda0$1, phi0, lambda1, phi1, // bounds
10840 lambda2, // previous lambda-coordinate
10841 lambda00, phi00, // first point
10842 p0, // previous 3D point
10843 deltaSum, ranges, range;
10844 var boundsStream$1 = {
10845 point: boundsPoint$1,
10846 lineStart: boundsLineStart,
10847 lineEnd: boundsLineEnd,
10848 polygonStart: function polygonStart() {
10849 boundsStream$1.point = boundsRingPoint;
10850 boundsStream$1.lineStart = boundsRingStart;
10851 boundsStream$1.lineEnd = boundsRingEnd;
10852 deltaSum = new Adder();
10853 areaStream$1.polygonStart();
10855 polygonEnd: function polygonEnd() {
10856 areaStream$1.polygonEnd();
10857 boundsStream$1.point = boundsPoint$1;
10858 boundsStream$1.lineStart = boundsLineStart;
10859 boundsStream$1.lineEnd = boundsLineEnd;
10860 if (areaRingSum$1 < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);else if (deltaSum > epsilon$1) phi1 = 90;else if (deltaSum < -epsilon$1) phi0 = -90;
10861 range[0] = lambda0$1, range[1] = lambda1;
10863 sphere: function sphere() {
10864 lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);
10868 function boundsPoint$1(lambda, phi) {
10869 ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
10870 if (phi < phi0) phi0 = phi;
10871 if (phi > phi1) phi1 = phi;
10874 function linePoint(lambda, phi) {
10875 var p = cartesian([lambda * radians, phi * radians]);
10878 var normal = cartesianCross(p0, p),
10879 equatorial = [normal[1], -normal[0], 0],
10880 inflection = cartesianCross(equatorial, normal);
10881 cartesianNormalizeInPlace(inflection);
10882 inflection = spherical(inflection);
10883 var delta = lambda - lambda2,
10884 sign = delta > 0 ? 1 : -1,
10885 lambdai = inflection[0] * degrees$1 * sign,
10887 antimeridian = abs$2(delta) > 180;
10889 if (antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) {
10890 phii = inflection[1] * degrees$1;
10891 if (phii > phi1) phi1 = phii;
10892 } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) {
10893 phii = -inflection[1] * degrees$1;
10894 if (phii < phi0) phi0 = phii;
10896 if (phi < phi0) phi0 = phi;
10897 if (phi > phi1) phi1 = phi;
10900 if (antimeridian) {
10901 if (lambda < lambda2) {
10902 if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
10904 if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
10907 if (lambda1 >= lambda0$1) {
10908 if (lambda < lambda0$1) lambda0$1 = lambda;
10909 if (lambda > lambda1) lambda1 = lambda;
10911 if (lambda > lambda2) {
10912 if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
10914 if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
10919 ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
10922 if (phi < phi0) phi0 = phi;
10923 if (phi > phi1) phi1 = phi;
10924 p0 = p, lambda2 = lambda;
10927 function boundsLineStart() {
10928 boundsStream$1.point = linePoint;
10931 function boundsLineEnd() {
10932 range[0] = lambda0$1, range[1] = lambda1;
10933 boundsStream$1.point = boundsPoint$1;
10937 function boundsRingPoint(lambda, phi) {
10939 var delta = lambda - lambda2;
10940 deltaSum.add(abs$2(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
10942 lambda00 = lambda, phi00 = phi;
10945 areaStream$1.point(lambda, phi);
10946 linePoint(lambda, phi);
10949 function boundsRingStart() {
10950 areaStream$1.lineStart();
10953 function boundsRingEnd() {
10954 boundsRingPoint(lambda00, phi00);
10955 areaStream$1.lineEnd();
10956 if (abs$2(deltaSum) > epsilon$1) lambda0$1 = -(lambda1 = 180);
10957 range[0] = lambda0$1, range[1] = lambda1;
10959 } // Finds the left-right distance between two longitudes.
10960 // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
10961 // the distance between ±180° to be 360°.
10964 function angle(lambda0, lambda1) {
10965 return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
10968 function rangeCompare(a, b) {
10969 return a[0] - b[0];
10972 function rangeContains(range, x) {
10973 return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
10976 function d3_geoBounds (feature) {
10977 var i, n, a, b, merged, deltaMax, delta;
10978 phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity);
10980 d3_geoStream(feature, boundsStream$1); // First, sort ranges by their minimum longitudes.
10982 if (n = ranges.length) {
10983 ranges.sort(rangeCompare); // Then, merge any ranges that overlap.
10985 for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
10988 if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
10989 if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
10990 if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
10992 merged.push(a = b);
10994 } // Finally, find the largest gap between the merged ranges.
10995 // The final bounding box will be the inverse of this gap.
10998 for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
11000 if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1];
11004 ranges = range = null;
11005 return lambda0$1 === Infinity || phi0 === Infinity ? [[NaN, NaN], [NaN, NaN]] : [[lambda0$1, phi0], [lambda1, phi1]];
11008 function compose (a, b) {
11009 function compose(x, y) {
11010 return x = a(x, y), b(x[0], x[1]);
11013 if (a.invert && b.invert) compose.invert = function (x, y) {
11014 return x = b.invert(x, y), x && a.invert(x[0], x[1]);
11019 function rotationIdentity(lambda, phi) {
11020 return [abs$2(lambda) > pi ? lambda + Math.round(-lambda / tau) * tau : lambda, phi];
11023 rotationIdentity.invert = rotationIdentity;
11024 function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
11025 return (deltaLambda %= tau) ? deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) : rotationLambda(deltaLambda) : deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) : rotationIdentity;
11028 function forwardRotationLambda(deltaLambda) {
11029 return function (lambda, phi) {
11030 return lambda += deltaLambda, [lambda > pi ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi];
11034 function rotationLambda(deltaLambda) {
11035 var rotation = forwardRotationLambda(deltaLambda);
11036 rotation.invert = forwardRotationLambda(-deltaLambda);
11040 function rotationPhiGamma(deltaPhi, deltaGamma) {
11041 var cosDeltaPhi = cos(deltaPhi),
11042 sinDeltaPhi = sin(deltaPhi),
11043 cosDeltaGamma = cos(deltaGamma),
11044 sinDeltaGamma = sin(deltaGamma);
11046 function rotation(lambda, phi) {
11047 var cosPhi = cos(phi),
11048 x = cos(lambda) * cosPhi,
11049 y = sin(lambda) * cosPhi,
11051 k = z * cosDeltaPhi + x * sinDeltaPhi;
11052 return [atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), asin(k * cosDeltaGamma + y * sinDeltaGamma)];
11055 rotation.invert = function (lambda, phi) {
11056 var cosPhi = cos(phi),
11057 x = cos(lambda) * cosPhi,
11058 y = sin(lambda) * cosPhi,
11060 k = z * cosDeltaGamma - y * sinDeltaGamma;
11061 return [atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), asin(k * cosDeltaPhi - x * sinDeltaPhi)];
11067 function rotation (rotate) {
11068 rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0);
11070 function forward(coordinates) {
11071 coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians);
11072 return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
11075 forward.invert = function (coordinates) {
11076 coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians);
11077 return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
11083 function circleStream(stream, radius, delta, direction, t0, t1) {
11084 if (!delta) return;
11085 var cosRadius = cos(radius),
11086 sinRadius = sin(radius),
11087 step = direction * delta;
11090 t0 = radius + direction * tau;
11091 t1 = radius - step / 2;
11093 t0 = circleRadius(cosRadius, t0);
11094 t1 = circleRadius(cosRadius, t1);
11095 if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau;
11098 for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
11099 point = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(t)]);
11100 stream.point(point[0], point[1]);
11102 } // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
11104 function circleRadius(cosRadius, point) {
11105 point = cartesian(point), point[0] -= cosRadius;
11106 cartesianNormalizeInPlace(point);
11107 var radius = acos(-point[1]);
11108 return ((-point[2] < 0 ? -radius : radius) + tau - epsilon$1) % tau;
11111 function clipBuffer () {
11115 point: function point(x, y, m) {
11116 line.push([x, y, m]);
11118 lineStart: function lineStart() {
11119 lines.push(line = []);
11122 rejoin: function rejoin() {
11123 if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
11125 result: function result() {
11126 var result = lines;
11134 function pointEqual (a, b) {
11135 return abs$2(a[0] - b[0]) < epsilon$1 && abs$2(a[1] - b[1]) < epsilon$1;
11138 function Intersection(point, points, other, entry) {
11141 this.o = other; // another intersection
11143 this.e = entry; // is an entry?
11145 this.v = false; // visited
11147 this.n = this.p = null; // next & previous
11148 } // A generalized polygon clipping algorithm: given a polygon that has been cut
11149 // into its visible line segments, and rejoins the segments by interpolating
11150 // along the clip edge.
11153 function clipRejoin (segments, compareIntersection, startInside, interpolate, stream) {
11158 segments.forEach(function (segment) {
11159 if ((n = segment.length - 1) <= 0) return;
11165 if (pointEqual(p0, p1)) {
11166 if (!p0[2] && !p1[2]) {
11167 stream.lineStart();
11169 for (i = 0; i < n; ++i) {
11170 stream.point((p0 = segment[i])[0], p0[1]);
11175 } // handle degenerate cases by moving the point
11178 p1[0] += 2 * epsilon$1;
11181 subject.push(x = new Intersection(p0, segment, null, true));
11182 clip.push(x.o = new Intersection(p0, null, x, false));
11183 subject.push(x = new Intersection(p1, segment, null, false));
11184 clip.push(x.o = new Intersection(p1, null, x, true));
11186 if (!subject.length) return;
11187 clip.sort(compareIntersection);
11191 for (i = 0, n = clip.length; i < n; ++i) {
11192 clip[i].e = startInside = !startInside;
11195 var start = subject[0],
11200 // Find first unvisited intersection.
11201 var current = start,
11204 while (current.v) {
11205 if ((current = current.n) === start) return;
11208 points = current.z;
11209 stream.lineStart();
11212 current.v = current.o.v = true;
11216 for (i = 0, n = points.length; i < n; ++i) {
11217 stream.point((point = points[i])[0], point[1]);
11220 interpolate(current.x, current.n.x, 1, stream);
11223 current = current.n;
11226 points = current.p.z;
11228 for (i = points.length - 1; i >= 0; --i) {
11229 stream.point((point = points[i])[0], point[1]);
11232 interpolate(current.x, current.p.x, -1, stream);
11235 current = current.p;
11238 current = current.o;
11239 points = current.z;
11240 isSubject = !isSubject;
11241 } while (!current.v);
11247 function link(array) {
11248 if (!(n = array.length)) return;
11255 a.n = b = array[i];
11260 a.n = b = array[0];
11264 function longitude(point) {
11265 if (abs$2(point[0]) <= pi) return point[0];else return sign(point[0]) * ((abs$2(point[0]) + pi) % tau - pi);
11268 function polygonContains (polygon, point) {
11269 var lambda = longitude(point),
11272 normal = [sin(lambda), -cos(lambda), 0],
11275 var sum = new Adder();
11276 if (sinPhi === 1) phi = halfPi + epsilon$1;else if (sinPhi === -1) phi = -halfPi - epsilon$1;
11278 for (var i = 0, n = polygon.length; i < n; ++i) {
11279 if (!(m = (ring = polygon[i]).length)) continue;
11282 point0 = ring[m - 1],
11283 lambda0 = longitude(point0),
11284 phi0 = point0[1] / 2 + quarterPi,
11285 sinPhi0 = sin(phi0),
11286 cosPhi0 = cos(phi0);
11288 for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
11289 var point1 = ring[j],
11290 lambda1 = longitude(point1),
11291 phi1 = point1[1] / 2 + quarterPi,
11292 sinPhi1 = sin(phi1),
11293 cosPhi1 = cos(phi1),
11294 delta = lambda1 - lambda0,
11295 sign = delta >= 0 ? 1 : -1,
11296 absDelta = sign * delta,
11297 antimeridian = absDelta > pi,
11298 k = sinPhi0 * sinPhi1;
11299 sum.add(atan2(k * sign * sin(absDelta), cosPhi0 * cosPhi1 + k * cos(absDelta)));
11300 angle += antimeridian ? delta + sign * tau : delta; // Are the longitudes either side of the point’s meridian (lambda),
11301 // and are the latitudes smaller than the parallel (phi)?
11303 if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
11304 var arc = cartesianCross(cartesian(point0), cartesian(point1));
11305 cartesianNormalizeInPlace(arc);
11306 var intersection = cartesianCross(normal, arc);
11307 cartesianNormalizeInPlace(intersection);
11308 var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]);
11310 if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
11311 winding += antimeridian ^ delta >= 0 ? 1 : -1;
11315 } // First, determine whether the South pole is inside or outside:
11317 // It is inside if:
11318 // * the polygon winds around it in a clockwise direction.
11319 // * the polygon does not (cumulatively) wind around it, but has a negative
11320 // (counter-clockwise) area.
11322 // Second, count the (signed) number of times a segment crosses a lambda
11323 // from the point to the South pole. If it is zero, then the point is the
11324 // same side as the South pole.
11327 return (angle < -epsilon$1 || angle < epsilon$1 && sum < -epsilon2$1) ^ winding & 1;
11330 function clip (pointVisible, clipLine, interpolate, start) {
11331 return function (sink) {
11332 var line = clipLine(sink),
11333 ringBuffer = clipBuffer(),
11334 ringSink = clipLine(ringBuffer),
11335 polygonStarted = false,
11341 lineStart: lineStart,
11343 polygonStart: function polygonStart() {
11344 clip.point = pointRing;
11345 clip.lineStart = ringStart;
11346 clip.lineEnd = ringEnd;
11350 polygonEnd: function polygonEnd() {
11351 clip.point = point;
11352 clip.lineStart = lineStart;
11353 clip.lineEnd = lineEnd;
11354 segments = merge$4(segments);
11355 var startInside = polygonContains(polygon, start);
11357 if (segments.length) {
11358 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
11359 clipRejoin(segments, compareIntersection, startInside, interpolate, sink);
11360 } else if (startInside) {
11361 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
11363 interpolate(null, null, 1, sink);
11367 if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
11368 segments = polygon = null;
11370 sphere: function sphere() {
11371 sink.polygonStart();
11373 interpolate(null, null, 1, sink);
11379 function point(lambda, phi) {
11380 if (pointVisible(lambda, phi)) sink.point(lambda, phi);
11383 function pointLine(lambda, phi) {
11384 line.point(lambda, phi);
11387 function lineStart() {
11388 clip.point = pointLine;
11392 function lineEnd() {
11393 clip.point = point;
11397 function pointRing(lambda, phi) {
11398 ring.push([lambda, phi]);
11399 ringSink.point(lambda, phi);
11402 function ringStart() {
11403 ringSink.lineStart();
11407 function ringEnd() {
11408 pointRing(ring[0][0], ring[0][1]);
11409 ringSink.lineEnd();
11410 var clean = ringSink.clean(),
11411 ringSegments = ringBuffer.result(),
11413 n = ringSegments.length,
11418 polygon.push(ring);
11420 if (!n) return; // No intersections.
11423 segment = ringSegments[0];
11425 if ((m = segment.length - 1) > 0) {
11426 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
11429 for (i = 0; i < m; ++i) {
11430 sink.point((point = segment[i])[0], point[1]);
11437 } // Rejoin connected segments.
11438 // TODO reuse ringBuffer.rejoin()?
11441 if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
11442 segments.push(ringSegments.filter(validSegment));
11449 function validSegment(segment) {
11450 return segment.length > 1;
11451 } // Intersections are sorted along the clip edge. For both antimeridian cutting
11452 // and circle clipping, the same comparison is used.
11455 function compareIntersection(a, b) {
11456 return ((a = a.x)[0] < 0 ? a[1] - halfPi - epsilon$1 : halfPi - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfPi - epsilon$1 : halfPi - b[1]);
11459 var clipAntimeridian = clip(function () {
11461 }, clipAntimeridianLine, clipAntimeridianInterpolate, [-pi, -halfPi]); // Takes a line and cuts into visible segments. Return values: 0 - there were
11462 // intersections or the line was empty; 1 - no intersections; 2 - there were
11463 // intersections, and the first and last segments should be rejoined.
11465 function clipAntimeridianLine(stream) {
11469 _clean; // no intersections
11473 lineStart: function lineStart() {
11474 stream.lineStart();
11477 point: function point(lambda1, phi1) {
11478 var sign1 = lambda1 > 0 ? pi : -pi,
11479 delta = abs$2(lambda1 - lambda0);
11481 if (abs$2(delta - pi) < epsilon$1) {
11482 // line crosses a pole
11483 stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi : -halfPi);
11484 stream.point(sign0, phi0);
11486 stream.lineStart();
11487 stream.point(sign1, phi0);
11488 stream.point(lambda1, phi0);
11490 } else if (sign0 !== sign1 && delta >= pi) {
11491 // line crosses antimeridian
11492 if (abs$2(lambda0 - sign0) < epsilon$1) lambda0 -= sign0 * epsilon$1; // handle degeneracies
11494 if (abs$2(lambda1 - sign1) < epsilon$1) lambda1 -= sign1 * epsilon$1;
11495 phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
11496 stream.point(sign0, phi0);
11498 stream.lineStart();
11499 stream.point(sign1, phi0);
11503 stream.point(lambda0 = lambda1, phi0 = phi1);
11506 lineEnd: function lineEnd() {
11508 lambda0 = phi0 = NaN;
11510 clean: function clean() {
11511 return 2 - _clean; // if intersections, rejoin first and last segments
11516 function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
11519 sinLambda0Lambda1 = sin(lambda0 - lambda1);
11520 return abs$2(sinLambda0Lambda1) > epsilon$1 ? atan((sin(phi0) * (cosPhi1 = cos(phi1)) * sin(lambda1) - sin(phi1) * (cosPhi0 = cos(phi0)) * sin(lambda0)) / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) : (phi0 + phi1) / 2;
11523 function clipAntimeridianInterpolate(from, to, direction, stream) {
11526 if (from == null) {
11527 phi = direction * halfPi;
11528 stream.point(-pi, phi);
11529 stream.point(0, phi);
11530 stream.point(pi, phi);
11531 stream.point(pi, 0);
11532 stream.point(pi, -phi);
11533 stream.point(0, -phi);
11534 stream.point(-pi, -phi);
11535 stream.point(-pi, 0);
11536 stream.point(-pi, phi);
11537 } else if (abs$2(from[0] - to[0]) > epsilon$1) {
11538 var lambda = from[0] < to[0] ? pi : -pi;
11539 phi = direction * lambda / 2;
11540 stream.point(-lambda, phi);
11541 stream.point(0, phi);
11542 stream.point(lambda, phi);
11544 stream.point(to[0], to[1]);
11548 function clipCircle (radius) {
11549 var cr = cos(radius),
11550 delta = 6 * radians,
11551 smallRadius = cr > 0,
11552 notHemisphere = abs$2(cr) > epsilon$1; // TODO optimise for this common case
11554 function interpolate(from, to, direction, stream) {
11555 circleStream(stream, radius, delta, direction, from, to);
11558 function visible(lambda, phi) {
11559 return cos(lambda) * cos(phi) > cr;
11560 } // Takes a line and cuts into visible segments. Return values used for polygon
11561 // clipping: 0 - there were intersections or the line was empty; 1 - no
11562 // intersections 2 - there were intersections, and the first and last segments
11563 // should be rejoined.
11566 function clipLine(stream) {
11567 var point0, // previous point
11568 c0, // code for previous point
11569 v0, // visibility of previous point
11570 v00, // visibility of first point
11571 _clean; // no intersections
11575 lineStart: function lineStart() {
11579 point: function point(lambda, phi) {
11580 var point1 = [lambda, phi],
11582 v = visible(lambda, phi),
11583 c = smallRadius ? v ? 0 : code(lambda, phi) : v ? code(lambda + (lambda < 0 ? pi : -pi), phi) : 0;
11584 if (!point0 && (v00 = v0 = v)) stream.lineStart();
11587 point2 = intersect(point0, point1);
11588 if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2)) point1[2] = 1;
11595 // outside going in
11596 stream.lineStart();
11597 point2 = intersect(point1, point0);
11598 stream.point(point2[0], point2[1]);
11600 // inside going out
11601 point2 = intersect(point0, point1);
11602 stream.point(point2[0], point2[1], 2);
11607 } else if (notHemisphere && point0 && smallRadius ^ v) {
11608 var t; // If the codes for two points are different, or are both zero,
11609 // and there this segment intersects with the small circle.
11611 if (!(c & c0) && (t = intersect(point1, point0, true))) {
11615 stream.lineStart();
11616 stream.point(t[0][0], t[0][1]);
11617 stream.point(t[1][0], t[1][1]);
11620 stream.point(t[1][0], t[1][1]);
11622 stream.lineStart();
11623 stream.point(t[0][0], t[0][1], 3);
11628 if (v && (!point0 || !pointEqual(point0, point1))) {
11629 stream.point(point1[0], point1[1]);
11632 point0 = point1, v0 = v, c0 = c;
11634 lineEnd: function lineEnd() {
11635 if (v0) stream.lineEnd();
11638 // Rejoin first and last segments if there were intersections and the first
11639 // and last points were visible.
11640 clean: function clean() {
11641 return _clean | (v00 && v0) << 1;
11644 } // Intersects the great circle between a and b with the clip circle.
11647 function intersect(a, b, two) {
11648 var pa = cartesian(a),
11649 pb = cartesian(b); // We have two planes, n1.p = d1 and n2.p = d2.
11650 // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
11652 var n1 = [1, 0, 0],
11654 n2 = cartesianCross(pa, pb),
11655 n2n2 = cartesianDot(n2, n2),
11657 // cartesianDot(n1, n2),
11658 determinant = n2n2 - n1n2 * n1n2; // Two polar points.
11660 if (!determinant) return !two && a;
11661 var c1 = cr * n2n2 / determinant,
11662 c2 = -cr * n1n2 / determinant,
11663 n1xn2 = cartesianCross(n1, n2),
11664 A = cartesianScale(n1, c1),
11665 B = cartesianScale(n2, c2);
11666 cartesianAddInPlace(A, B); // Solve |p(t)|^2 = 1.
11669 w = cartesianDot(A, u),
11670 uu = cartesianDot(u, u),
11671 t2 = w * w - uu * (cartesianDot(A, A) - 1);
11672 if (t2 < 0) return;
11674 q = cartesianScale(u, (-w - t) / uu);
11675 cartesianAddInPlace(q, A);
11677 if (!two) return q; // Two intersection points.
11679 var lambda0 = a[0],
11684 if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;
11685 var delta = lambda1 - lambda0,
11686 polar = abs$2(delta - pi) < epsilon$1,
11687 meridian = polar || delta < epsilon$1;
11688 if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z; // Check that the first point is between a and b.
11690 if (meridian ? polar ? phi0 + phi1 > 0 ^ q[1] < (abs$2(q[0] - lambda0) < epsilon$1 ? phi0 : phi1) : phi0 <= q[1] && q[1] <= phi1 : delta > pi ^ (lambda0 <= q[0] && q[0] <= lambda1)) {
11691 var q1 = cartesianScale(u, (-w + t) / uu);
11692 cartesianAddInPlace(q1, A);
11693 return [q, spherical(q1)];
11695 } // Generates a 4-bit vector representing the location of a point relative to
11696 // the small circle's bounding box.
11699 function code(lambda, phi) {
11700 var r = smallRadius ? radius : pi - radius,
11702 if (lambda < -r) code |= 1; // left
11703 else if (lambda > r) code |= 2; // right
11705 if (phi < -r) code |= 4; // below
11706 else if (phi > r) code |= 8; // above
11711 return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi, radius - pi]);
11714 function clipLine (a, b, x0, y0, x1, y1) {
11725 if (!dx && r > 0) return;
11729 if (r < t0) return;
11730 if (r < t1) t1 = r;
11731 } else if (dx > 0) {
11732 if (r > t1) return;
11733 if (r > t0) t0 = r;
11737 if (!dx && r < 0) return;
11741 if (r > t1) return;
11742 if (r > t0) t0 = r;
11743 } else if (dx > 0) {
11744 if (r < t0) return;
11745 if (r < t1) t1 = r;
11749 if (!dy && r > 0) return;
11753 if (r < t0) return;
11754 if (r < t1) t1 = r;
11755 } else if (dy > 0) {
11756 if (r > t1) return;
11757 if (r > t0) t0 = r;
11761 if (!dy && r < 0) return;
11765 if (r > t1) return;
11766 if (r > t0) t0 = r;
11767 } else if (dy > 0) {
11768 if (r < t0) return;
11769 if (r < t1) t1 = r;
11772 if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
11773 if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
11778 clipMin = -clipMax; // TODO Use d3-polygon’s polygonContains here for the ring check?
11779 // TODO Eliminate duplicate buffering in clipBuffer and polygon.push?
11781 function clipRectangle(x0, y0, x1, y1) {
11782 function visible(x, y) {
11783 return x0 <= x && x <= x1 && y0 <= y && y <= y1;
11786 function interpolate(from, to, direction, stream) {
11790 if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoint(from, to) < 0 ^ direction > 0) {
11792 stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
11793 } while ((a = (a + direction + 4) % 4) !== a1);
11795 stream.point(to[0], to[1]);
11799 function corner(p, direction) {
11800 return abs$2(p[0] - x0) < epsilon$1 ? direction > 0 ? 0 : 3 : abs$2(p[0] - x1) < epsilon$1 ? direction > 0 ? 2 : 1 : abs$2(p[1] - y0) < epsilon$1 ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon
11803 function compareIntersection(a, b) {
11804 return comparePoint(a.x, b.x);
11807 function comparePoint(a, b) {
11808 var ca = corner(a, 1),
11810 return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];
11813 return function (stream) {
11814 var activeStream = stream,
11815 bufferStream = clipBuffer(),
11831 lineStart: lineStart,
11833 polygonStart: polygonStart,
11834 polygonEnd: polygonEnd
11837 function point(x, y) {
11838 if (visible(x, y)) activeStream.point(x, y);
11841 function polygonInside() {
11844 for (var i = 0, n = polygon.length; i < n; ++i) {
11845 for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
11846 a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
11849 if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding;
11851 if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding;
11857 } // Buffer geometry within a polygon and then clip it en masse.
11860 function polygonStart() {
11861 activeStream = bufferStream, segments = [], polygon = [], clean = true;
11864 function polygonEnd() {
11865 var startInside = polygonInside(),
11866 cleanInside = clean && startInside,
11867 visible = (segments = merge$4(segments)).length;
11869 if (cleanInside || visible) {
11870 stream.polygonStart();
11873 stream.lineStart();
11874 interpolate(null, null, 1, stream);
11879 clipRejoin(segments, compareIntersection, startInside, interpolate, stream);
11882 stream.polygonEnd();
11885 activeStream = stream, segments = polygon = ring = null;
11888 function lineStart() {
11889 clipStream.point = linePoint;
11890 if (polygon) polygon.push(ring = []);
11894 } // TODO rather than special-case polygons, simply handle them separately.
11895 // Ideally, coincident intersection points should be jittered to avoid
11896 // clipping issues.
11899 function lineEnd() {
11901 linePoint(x__, y__);
11902 if (v__ && v_) bufferStream.rejoin();
11903 segments.push(bufferStream.result());
11906 clipStream.point = point;
11907 if (v_) activeStream.lineEnd();
11910 function linePoint(x, y) {
11911 var v = visible(x, y);
11912 if (polygon) ring.push([x, y]);
11915 x__ = x, y__ = y, v__ = v;
11919 activeStream.lineStart();
11920 activeStream.point(x, y);
11923 if (v && v_) activeStream.point(x, y);else {
11924 var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
11925 b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
11927 if (clipLine(a, b, x0, y0, x1, y1)) {
11929 activeStream.lineStart();
11930 activeStream.point(a[0], a[1]);
11933 activeStream.point(b[0], b[1]);
11934 if (!v) activeStream.lineEnd();
11937 activeStream.lineStart();
11938 activeStream.point(x, y);
11944 x_ = x, y_ = y, v_ = v;
11951 var lengthSum$1, lambda0, sinPhi0, cosPhi0;
11952 var lengthStream$1 = {
11955 lineStart: lengthLineStart,
11957 polygonStart: noop$1,
11961 function lengthLineStart() {
11962 lengthStream$1.point = lengthPointFirst$1;
11963 lengthStream$1.lineEnd = lengthLineEnd;
11966 function lengthLineEnd() {
11967 lengthStream$1.point = lengthStream$1.lineEnd = noop$1;
11970 function lengthPointFirst$1(lambda, phi) {
11971 lambda *= radians, phi *= radians;
11972 lambda0 = lambda, sinPhi0 = sin(phi), cosPhi0 = cos(phi);
11973 lengthStream$1.point = lengthPoint$1;
11976 function lengthPoint$1(lambda, phi) {
11977 lambda *= radians, phi *= radians;
11978 var sinPhi = sin(phi),
11980 delta = abs$2(lambda - lambda0),
11981 cosDelta = cos(delta),
11982 sinDelta = sin(delta),
11983 x = cosPhi * sinDelta,
11984 y = cosPhi0 * sinPhi - sinPhi0 * cosPhi * cosDelta,
11985 z = sinPhi0 * sinPhi + cosPhi0 * cosPhi * cosDelta;
11986 lengthSum$1.add(atan2(sqrt(x * x + y * y), z));
11987 lambda0 = lambda, sinPhi0 = sinPhi, cosPhi0 = cosPhi;
11990 function d3_geoLength (object) {
11991 lengthSum$1 = new Adder();
11992 d3_geoStream(object, lengthStream$1);
11993 return +lengthSum$1;
11996 var identity$4 = (function (x) {
12000 var areaSum = new Adder(),
12001 areaRingSum = new Adder(),
12010 polygonStart: function polygonStart() {
12011 areaStream.lineStart = areaRingStart;
12012 areaStream.lineEnd = areaRingEnd;
12014 polygonEnd: function polygonEnd() {
12015 areaStream.lineStart = areaStream.lineEnd = areaStream.point = noop$1;
12016 areaSum.add(abs$2(areaRingSum));
12017 areaRingSum = new Adder();
12019 result: function result() {
12020 var area = areaSum / 2;
12021 areaSum = new Adder();
12026 function areaRingStart() {
12027 areaStream.point = areaPointFirst;
12030 function areaPointFirst(x, y) {
12031 areaStream.point = areaPoint;
12032 x00$2 = x0$3 = x, y00$2 = y0$3 = y;
12035 function areaPoint(x, y) {
12036 areaRingSum.add(y0$3 * x - x0$3 * y);
12037 x0$3 = x, y0$3 = y;
12040 function areaRingEnd() {
12041 areaPoint(x00$2, y00$2);
12044 var x0$2 = Infinity,
12048 var boundsStream = {
12049 point: boundsPoint,
12052 polygonStart: noop$1,
12053 polygonEnd: noop$1,
12054 result: function result() {
12055 var bounds = [[x0$2, y0$2], [x1, y1]];
12056 x1 = y1 = -(y0$2 = x0$2 = Infinity);
12061 function boundsPoint(x, y) {
12062 if (x < x0$2) x0$2 = x;
12063 if (x > x1) x1 = x;
12064 if (y < y0$2) y0$2 = y;
12065 if (y > y1) y1 = y;
12081 var centroidStream = {
12082 point: centroidPoint,
12083 lineStart: centroidLineStart,
12084 lineEnd: centroidLineEnd,
12085 polygonStart: function polygonStart() {
12086 centroidStream.lineStart = centroidRingStart;
12087 centroidStream.lineEnd = centroidRingEnd;
12089 polygonEnd: function polygonEnd() {
12090 centroidStream.point = centroidPoint;
12091 centroidStream.lineStart = centroidLineStart;
12092 centroidStream.lineEnd = centroidLineEnd;
12094 result: function result() {
12095 var centroid = Z2 ? [X2 / Z2, Y2 / Z2] : Z1 ? [X1 / Z1, Y1 / Z1] : Z0 ? [X0 / Z0, Y0 / Z0] : [NaN, NaN];
12096 X0 = Y0 = Z0 = X1 = Y1 = Z1 = X2 = Y2 = Z2 = 0;
12101 function centroidPoint(x, y) {
12107 function centroidLineStart() {
12108 centroidStream.point = centroidPointFirstLine;
12111 function centroidPointFirstLine(x, y) {
12112 centroidStream.point = centroidPointLine;
12113 centroidPoint(x0$1 = x, y0$1 = y);
12116 function centroidPointLine(x, y) {
12119 z = sqrt(dx * dx + dy * dy);
12120 X1 += z * (x0$1 + x) / 2;
12121 Y1 += z * (y0$1 + y) / 2;
12123 centroidPoint(x0$1 = x, y0$1 = y);
12126 function centroidLineEnd() {
12127 centroidStream.point = centroidPoint;
12130 function centroidRingStart() {
12131 centroidStream.point = centroidPointFirstRing;
12134 function centroidRingEnd() {
12135 centroidPointRing(x00$1, y00$1);
12138 function centroidPointFirstRing(x, y) {
12139 centroidStream.point = centroidPointRing;
12140 centroidPoint(x00$1 = x0$1 = x, y00$1 = y0$1 = y);
12143 function centroidPointRing(x, y) {
12146 z = sqrt(dx * dx + dy * dy);
12147 X1 += z * (x0$1 + x) / 2;
12148 Y1 += z * (y0$1 + y) / 2;
12150 z = y0$1 * x - x0$1 * y;
12151 X2 += z * (x0$1 + x);
12152 Y2 += z * (y0$1 + y);
12154 centroidPoint(x0$1 = x, y0$1 = y);
12157 function PathContext(context) {
12158 this._context = context;
12160 PathContext.prototype = {
12162 pointRadius: function pointRadius(_) {
12163 return this._radius = _, this;
12165 polygonStart: function polygonStart() {
12168 polygonEnd: function polygonEnd() {
12171 lineStart: function lineStart() {
12174 lineEnd: function lineEnd() {
12175 if (this._line === 0) this._context.closePath();
12178 point: function point(x, y) {
12179 switch (this._point) {
12182 this._context.moveTo(x, y);
12190 this._context.lineTo(x, y);
12197 this._context.moveTo(x + this._radius, y);
12199 this._context.arc(x, y, this._radius, 0, tau);
12208 var lengthSum = new Adder(),
12214 var lengthStream = {
12216 lineStart: function lineStart() {
12217 lengthStream.point = lengthPointFirst;
12219 lineEnd: function lineEnd() {
12220 if (lengthRing) lengthPoint(x00, y00);
12221 lengthStream.point = noop$1;
12223 polygonStart: function polygonStart() {
12226 polygonEnd: function polygonEnd() {
12229 result: function result() {
12230 var length = +lengthSum;
12231 lengthSum = new Adder();
12236 function lengthPointFirst(x, y) {
12237 lengthStream.point = lengthPoint;
12238 x00 = x0 = x, y00 = y0 = y;
12241 function lengthPoint(x, y) {
12243 lengthSum.add(sqrt(x0 * x0 + y0 * y0));
12247 function PathString() {
12250 PathString.prototype = {
12252 _circle: circle(4.5),
12253 pointRadius: function pointRadius(_) {
12254 if ((_ = +_) !== this._radius) this._radius = _, this._circle = null;
12257 polygonStart: function polygonStart() {
12260 polygonEnd: function polygonEnd() {
12263 lineStart: function lineStart() {
12266 lineEnd: function lineEnd() {
12267 if (this._line === 0) this._string.push("Z");
12270 point: function point(x, y) {
12271 switch (this._point) {
12274 this._string.push("M", x, ",", y);
12282 this._string.push("L", x, ",", y);
12289 if (this._circle == null) this._circle = circle(this._radius);
12291 this._string.push("M", x, ",", y, this._circle);
12297 result: function result() {
12298 if (this._string.length) {
12299 var result = this._string.join("");
12309 function circle(radius) {
12310 return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z";
12313 function d3_geoPath (projection, context) {
12314 var pointRadius = 4.5,
12318 function path(object) {
12320 if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
12321 d3_geoStream(object, projectionStream(contextStream));
12324 return contextStream.result();
12327 path.area = function (object) {
12328 d3_geoStream(object, projectionStream(areaStream));
12329 return areaStream.result();
12332 path.measure = function (object) {
12333 d3_geoStream(object, projectionStream(lengthStream));
12334 return lengthStream.result();
12337 path.bounds = function (object) {
12338 d3_geoStream(object, projectionStream(boundsStream));
12339 return boundsStream.result();
12342 path.centroid = function (object) {
12343 d3_geoStream(object, projectionStream(centroidStream));
12344 return centroidStream.result();
12347 path.projection = function (_) {
12348 return arguments.length ? (projectionStream = _ == null ? (projection = null, identity$4) : (projection = _).stream, path) : projection;
12351 path.context = function (_) {
12352 if (!arguments.length) return context;
12353 contextStream = _ == null ? (context = null, new PathString()) : new PathContext(context = _);
12354 if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
12358 path.pointRadius = function (_) {
12359 if (!arguments.length) return pointRadius;
12360 pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
12364 return path.projection(projection).context(context);
12367 function d3_geoTransform (methods) {
12369 stream: transformer$1(methods)
12372 function transformer$1(methods) {
12373 return function (stream) {
12374 var s = new TransformStream();
12376 for (var key in methods) {
12377 s[key] = methods[key];
12385 function TransformStream() {}
12387 TransformStream.prototype = {
12388 constructor: TransformStream,
12389 point: function point(x, y) {
12390 this.stream.point(x, y);
12392 sphere: function sphere() {
12393 this.stream.sphere();
12395 lineStart: function lineStart() {
12396 this.stream.lineStart();
12398 lineEnd: function lineEnd() {
12399 this.stream.lineEnd();
12401 polygonStart: function polygonStart() {
12402 this.stream.polygonStart();
12404 polygonEnd: function polygonEnd() {
12405 this.stream.polygonEnd();
12409 function fit(projection, fitBounds, object) {
12410 var clip = projection.clipExtent && projection.clipExtent();
12411 projection.scale(150).translate([0, 0]);
12412 if (clip != null) projection.clipExtent(null);
12413 d3_geoStream(object, projection.stream(boundsStream));
12414 fitBounds(boundsStream.result());
12415 if (clip != null) projection.clipExtent(clip);
12419 function fitExtent(projection, extent, object) {
12420 return fit(projection, function (b) {
12421 var w = extent[1][0] - extent[0][0],
12422 h = extent[1][1] - extent[0][1],
12423 k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
12424 x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
12425 y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
12426 projection.scale(150 * k).translate([x, y]);
12429 function fitSize(projection, size, object) {
12430 return fitExtent(projection, [[0, 0], size], object);
12432 function fitWidth(projection, width, object) {
12433 return fit(projection, function (b) {
12435 k = w / (b[1][0] - b[0][0]),
12436 x = (w - k * (b[1][0] + b[0][0])) / 2,
12438 projection.scale(150 * k).translate([x, y]);
12441 function fitHeight(projection, height, object) {
12442 return fit(projection, function (b) {
12444 k = h / (b[1][1] - b[0][1]),
12446 y = (h - k * (b[1][1] + b[0][1])) / 2;
12447 projection.scale(150 * k).translate([x, y]);
12452 // maximum depth of subdivision
12453 cosMinDistance = cos(30 * radians); // cos(minimum angular distance)
12455 function resample (project, delta2) {
12456 return +delta2 ? resample$1(project, delta2) : resampleNone(project);
12459 function resampleNone(project) {
12460 return transformer$1({
12461 point: function point(x, y) {
12463 this.stream.point(x[0], x[1]);
12468 function resample$1(project, delta2) {
12469 function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
12472 d2 = dx * dx + dy * dy;
12474 if (d2 > 4 * delta2 && depth--) {
12478 m = sqrt(a * a + b * b + c * c),
12479 phi2 = asin(c /= m),
12480 lambda2 = abs$2(abs$2(c) - 1) < epsilon$1 || abs$2(lambda0 - lambda1) < epsilon$1 ? (lambda0 + lambda1) / 2 : atan2(b, a),
12481 p = project(lambda2, phi2),
12486 dz = dy * dx2 - dx * dy2;
12488 if (dz * dz / d2 > delta2 // perpendicular projected distance
12489 || abs$2((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
12490 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {
12491 // angular distance
12492 resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
12493 stream.point(x2, y2);
12494 resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
12499 return function (stream) {
12500 var lambda00, x00, y00, a00, b00, c00, // first point
12501 lambda0, x0, y0, a0, b0, c0; // previous point
12503 var resampleStream = {
12505 lineStart: lineStart,
12507 polygonStart: function polygonStart() {
12508 stream.polygonStart();
12509 resampleStream.lineStart = ringStart;
12511 polygonEnd: function polygonEnd() {
12512 stream.polygonEnd();
12513 resampleStream.lineStart = lineStart;
12517 function point(x, y) {
12519 stream.point(x[0], x[1]);
12522 function lineStart() {
12524 resampleStream.point = linePoint;
12525 stream.lineStart();
12528 function linePoint(lambda, phi) {
12529 var c = cartesian([lambda, phi]),
12530 p = project(lambda, phi);
12531 resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
12532 stream.point(x0, y0);
12535 function lineEnd() {
12536 resampleStream.point = point;
12540 function ringStart() {
12542 resampleStream.point = ringPoint;
12543 resampleStream.lineEnd = ringEnd;
12546 function ringPoint(lambda, phi) {
12547 linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
12548 resampleStream.point = linePoint;
12551 function ringEnd() {
12552 resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
12553 resampleStream.lineEnd = lineEnd;
12557 return resampleStream;
12561 var transformRadians = transformer$1({
12562 point: function point(x, y) {
12563 this.stream.point(x * radians, y * radians);
12567 function transformRotate(rotate) {
12568 return transformer$1({
12569 point: function point(x, y) {
12570 var r = rotate(x, y);
12571 return this.stream.point(r[0], r[1]);
12576 function scaleTranslate(k, dx, dy, sx, sy) {
12577 function transform(x, y) {
12580 return [dx + k * x, dy - k * y];
12583 transform.invert = function (x, y) {
12584 return [(x - dx) / k * sx, (dy - y) / k * sy];
12590 function scaleTranslateRotate(k, dx, dy, sx, sy, alpha) {
12591 if (!alpha) return scaleTranslate(k, dx, dy, sx, sy);
12592 var cosAlpha = cos(alpha),
12593 sinAlpha = sin(alpha),
12598 ci = (sinAlpha * dy - cosAlpha * dx) / k,
12599 fi = (sinAlpha * dx + cosAlpha * dy) / k;
12601 function transform(x, y) {
12604 return [a * x - b * y + dx, dy - b * x - a * y];
12607 transform.invert = function (x, y) {
12608 return [sx * (ai * x - bi * y + ci), sy * (fi - bi * x - ai * y)];
12614 function projection(project) {
12615 return projectionMutator(function () {
12619 function projectionMutator(projectAt) {
12635 // post-rotate angle
12641 preclip = clipAntimeridian,
12647 postclip = identity$4,
12648 // post-clip extent
12653 projectRotateTransform,
12657 function projection(point) {
12658 return projectRotateTransform(point[0] * radians, point[1] * radians);
12661 function invert(point) {
12662 point = projectRotateTransform.invert(point[0], point[1]);
12663 return point && [point[0] * degrees$1, point[1] * degrees$1];
12666 projection.stream = function (stream) {
12667 return cache && cacheStream === stream ? cache : cache = transformRadians(transformRotate(rotate)(preclip(projectResample(postclip(cacheStream = stream)))));
12670 projection.preclip = function (_) {
12671 return arguments.length ? (preclip = _, theta = undefined, reset()) : preclip;
12674 projection.postclip = function (_) {
12675 return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip;
12678 projection.clipAngle = function (_) {
12679 return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1;
12682 projection.clipExtent = function (_) {
12683 return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
12686 projection.scale = function (_) {
12687 return arguments.length ? (k = +_, recenter()) : k;
12690 projection.translate = function (_) {
12691 return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
12694 projection.center = function (_) {
12695 return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1];
12698 projection.rotate = function (_) {
12699 return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees$1, deltaPhi * degrees$1, deltaGamma * degrees$1];
12702 projection.angle = function (_) {
12703 return arguments.length ? (alpha = _ % 360 * radians, recenter()) : alpha * degrees$1;
12706 projection.reflectX = function (_) {
12707 return arguments.length ? (sx = _ ? -1 : 1, recenter()) : sx < 0;
12710 projection.reflectY = function (_) {
12711 return arguments.length ? (sy = _ ? -1 : 1, recenter()) : sy < 0;
12714 projection.precision = function (_) {
12715 return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2);
12718 projection.fitExtent = function (extent, object) {
12719 return fitExtent(projection, extent, object);
12722 projection.fitSize = function (size, object) {
12723 return fitSize(projection, size, object);
12726 projection.fitWidth = function (width, object) {
12727 return fitWidth(projection, width, object);
12730 projection.fitHeight = function (height, object) {
12731 return fitHeight(projection, height, object);
12734 function recenter() {
12735 var center = scaleTranslateRotate(k, 0, 0, sx, sy, alpha).apply(null, project(lambda, phi)),
12736 transform = scaleTranslateRotate(k, x - center[0], y - center[1], sx, sy, alpha);
12737 rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma);
12738 projectTransform = compose(project, transform);
12739 projectRotateTransform = compose(rotate, projectTransform);
12740 projectResample = resample(projectTransform, delta2);
12745 cache = cacheStream = null;
12749 return function () {
12750 project = projectAt.apply(this, arguments);
12751 projection.invert = project.invert && invert;
12756 function mercatorRaw(lambda, phi) {
12757 return [lambda, log$1(tan((halfPi + phi) / 2))];
12760 mercatorRaw.invert = function (x, y) {
12761 return [x, 2 * atan(exp$2(y)) - halfPi];
12764 function mercator () {
12765 return mercatorProjection(mercatorRaw).scale(961 / tau);
12767 function mercatorProjection(project) {
12768 var m = projection(project),
12771 translate = m.translate,
12772 clipExtent = m.clipExtent,
12778 m.scale = function (_) {
12779 return arguments.length ? (scale(_), reclip()) : scale();
12782 m.translate = function (_) {
12783 return arguments.length ? (translate(_), reclip()) : translate();
12786 m.center = function (_) {
12787 return arguments.length ? (center(_), reclip()) : center();
12790 m.clipExtent = function (_) {
12791 return arguments.length ? (_ == null ? x0 = y0 = x1 = y1 = null : (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reclip()) : x0 == null ? null : [[x0, y0], [x1, y1]];
12794 function reclip() {
12795 var k = pi * scale(),
12796 t = m(rotation(m.rotate()).invert([0, 0]));
12797 return clipExtent(x0 == null ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]] : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]);
12803 function d3_geoIdentity () {
12809 // scale, translate and reflect
12821 transform = transformer$1({
12822 point: function point(x, y) {
12823 var p = projection([x, y]);
12824 this.stream.point(p[0], p[1]);
12827 postclip = identity$4,
12834 cache = cacheStream = null;
12838 function projection(p) {
12843 var t = y * ca - x * sa;
12844 x = x * ca + y * sa;
12848 return [x + tx, y + ty];
12851 projection.invert = function (p) {
12856 var t = y * ca + x * sa;
12857 x = x * ca - y * sa;
12861 return [x / kx, y / ky];
12864 projection.stream = function (stream) {
12865 return cache && cacheStream === stream ? cache : cache = transform(postclip(cacheStream = stream));
12868 projection.postclip = function (_) {
12869 return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip;
12872 projection.clipExtent = function (_) {
12873 return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
12876 projection.scale = function (_) {
12877 return arguments.length ? (k = +_, reset()) : k;
12880 projection.translate = function (_) {
12881 return arguments.length ? (tx = +_[0], ty = +_[1], reset()) : [tx, ty];
12884 projection.angle = function (_) {
12885 return arguments.length ? (alpha = _ % 360 * radians, sa = sin(alpha), ca = cos(alpha), reset()) : alpha * degrees$1;
12888 projection.reflectX = function (_) {
12889 return arguments.length ? (sx = _ ? -1 : 1, reset()) : sx < 0;
12892 projection.reflectY = function (_) {
12893 return arguments.length ? (sy = _ ? -1 : 1, reset()) : sy < 0;
12896 projection.fitExtent = function (extent, object) {
12897 return fitExtent(projection, extent, object);
12900 projection.fitSize = function (size, object) {
12901 return fitSize(projection, size, object);
12904 projection.fitWidth = function (width, object) {
12905 return fitWidth(projection, width, object);
12908 projection.fitHeight = function (height, object) {
12909 return fitHeight(projection, height, object);
12916 var TAU = 2 * Math.PI;
12917 var EQUATORIAL_RADIUS = 6356752.314245179;
12918 var POLAR_RADIUS = 6378137.0;
12919 function geoLatToMeters(dLat) {
12920 return dLat * (TAU * POLAR_RADIUS / 360);
12922 function geoLonToMeters(dLon, atLat) {
12923 return Math.abs(atLat) >= 90 ? 0 : dLon * (TAU * EQUATORIAL_RADIUS / 360) * Math.abs(Math.cos(atLat * (Math.PI / 180)));
12925 function geoMetersToLat(m) {
12926 return m / (TAU * POLAR_RADIUS / 360);
12928 function geoMetersToLon(m, atLat) {
12929 return Math.abs(atLat) >= 90 ? 0 : m / (TAU * EQUATORIAL_RADIUS / 360) / Math.abs(Math.cos(atLat * (Math.PI / 180)));
12931 function geoMetersToOffset(meters, tileSize) {
12932 tileSize = tileSize || 256;
12933 return [meters[0] * tileSize / (TAU * EQUATORIAL_RADIUS), -meters[1] * tileSize / (TAU * POLAR_RADIUS)];
12935 function geoOffsetToMeters(offset, tileSize) {
12936 tileSize = tileSize || 256;
12937 return [offset[0] * TAU * EQUATORIAL_RADIUS / tileSize, -offset[1] * TAU * POLAR_RADIUS / tileSize];
12938 } // Equirectangular approximation of spherical distances on Earth
12940 function geoSphericalDistance(a, b) {
12941 var x = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2);
12942 var y = geoLatToMeters(a[1] - b[1]);
12943 return Math.sqrt(x * x + y * y);
12946 function geoScaleToZoom(k, tileSize) {
12947 tileSize = tileSize || 256;
12948 var log2ts = Math.log(tileSize) * Math.LOG2E;
12949 return Math.log(k * TAU) / Math.LN2 - log2ts;
12952 function geoZoomToScale(z, tileSize) {
12953 tileSize = tileSize || 256;
12954 return tileSize * Math.pow(2, z) / TAU;
12955 } // returns info about the node from `nodes` closest to the given `point`
12957 function geoSphericalClosestNode(nodes, point) {
12958 var minDistance = Infinity,
12962 for (var i in nodes) {
12963 distance = geoSphericalDistance(nodes[i].loc, point);
12965 if (distance < minDistance) {
12966 minDistance = distance;
12971 if (indexOfMin !== undefined) {
12974 distance: minDistance,
12975 node: nodes[indexOfMin]
12982 function geoExtent(min, max) {
12983 if (!(this instanceof geoExtent)) {
12984 return new geoExtent(min, max);
12985 } else if (min instanceof geoExtent) {
12987 } else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
12991 this[0] = min || [Infinity, Infinity];
12992 this[1] = max || min || [-Infinity, -Infinity];
12995 geoExtent.prototype = new Array(2);
12996 Object.assign(geoExtent.prototype, {
12997 equals: function equals(obj) {
12998 return this[0][0] === obj[0][0] && this[0][1] === obj[0][1] && this[1][0] === obj[1][0] && this[1][1] === obj[1][1];
13000 extend: function extend(obj) {
13001 if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
13002 return geoExtent([Math.min(obj[0][0], this[0][0]), Math.min(obj[0][1], this[0][1])], [Math.max(obj[1][0], this[1][0]), Math.max(obj[1][1], this[1][1])]);
13004 _extend: function _extend(extent) {
13005 this[0][0] = Math.min(extent[0][0], this[0][0]);
13006 this[0][1] = Math.min(extent[0][1], this[0][1]);
13007 this[1][0] = Math.max(extent[1][0], this[1][0]);
13008 this[1][1] = Math.max(extent[1][1], this[1][1]);
13010 area: function area() {
13011 return Math.abs((this[1][0] - this[0][0]) * (this[1][1] - this[0][1]));
13013 center: function center() {
13014 return [(this[0][0] + this[1][0]) / 2, (this[0][1] + this[1][1]) / 2];
13016 rectangle: function rectangle() {
13017 return [this[0][0], this[0][1], this[1][0], this[1][1]];
13019 bbox: function bbox() {
13027 polygon: function polygon() {
13028 return [[this[0][0], this[0][1]], [this[0][0], this[1][1]], [this[1][0], this[1][1]], [this[1][0], this[0][1]], [this[0][0], this[0][1]]];
13030 contains: function contains(obj) {
13031 if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
13032 return obj[0][0] >= this[0][0] && obj[0][1] >= this[0][1] && obj[1][0] <= this[1][0] && obj[1][1] <= this[1][1];
13034 intersects: function intersects(obj) {
13035 if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
13036 return obj[0][0] <= this[1][0] && obj[0][1] <= this[1][1] && obj[1][0] >= this[0][0] && obj[1][1] >= this[0][1];
13038 intersection: function intersection(obj) {
13039 if (!this.intersects(obj)) return new geoExtent();
13040 return new geoExtent([Math.max(obj[0][0], this[0][0]), Math.max(obj[0][1], this[0][1])], [Math.min(obj[1][0], this[1][0]), Math.min(obj[1][1], this[1][1])]);
13042 percentContainedIn: function percentContainedIn(obj) {
13043 if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
13044 var a1 = this.intersection(obj).area();
13045 var a2 = this.area();
13047 if (a1 === Infinity || a2 === Infinity) {
13049 } else if (a1 === 0 || a2 === 0) {
13050 if (obj.contains(this)) {
13059 padByMeters: function padByMeters(meters) {
13060 var dLat = geoMetersToLat(meters);
13061 var dLon = geoMetersToLon(meters, this.center()[1]);
13062 return geoExtent([this[0][0] - dLon, this[0][1] - dLat], [this[1][0] + dLon, this[1][1] + dLat]);
13064 toParam: function toParam() {
13065 return this.rectangle().join(',');
13070 var $every = arrayIteration.every;
13071 var arrayMethodIsStrict$2 = arrayMethodIsStrict$9;
13073 var STRICT_METHOD$2 = arrayMethodIsStrict$2('every');
13075 // `Array.prototype.every` method
13076 // https://tc39.es/ecma262/#sec-array.prototype.every
13077 $$w({ target: 'Array', proto: true, forced: !STRICT_METHOD$2 }, {
13078 every: function every(callbackfn /* , thisArg */) {
13079 return $every(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
13084 var $reduce = arrayReduce.left;
13085 var arrayMethodIsStrict$1 = arrayMethodIsStrict$9;
13086 var CHROME_VERSION$1 = engineV8Version;
13087 var IS_NODE$1 = engineIsNode;
13089 var STRICT_METHOD$1 = arrayMethodIsStrict$1('reduce');
13090 // Chrome 80-82 has a critical bug
13091 // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
13092 var CHROME_BUG$1 = !IS_NODE$1 && CHROME_VERSION$1 > 79 && CHROME_VERSION$1 < 83;
13094 // `Array.prototype.reduce` method
13095 // https://tc39.es/ecma262/#sec-array.prototype.reduce
13096 $$v({ target: 'Array', proto: true, forced: !STRICT_METHOD$1 || CHROME_BUG$1 }, {
13097 reduce: function reduce(callbackfn /* , initialValue */) {
13098 var length = arguments.length;
13099 return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : undefined);
13103 function d3_polygonArea (polygon) {
13105 n = polygon.length,
13107 b = polygon[n - 1],
13113 area += a[1] * b[0] - a[0] * b[1];
13119 function d3_polygonCentroid (polygon) {
13121 n = polygon.length,
13125 b = polygon[n - 1],
13132 k += c = a[0] * b[1] - b[0] * a[1];
13133 x += (a[0] + b[0]) * c;
13134 y += (a[1] + b[1]) * c;
13137 return k *= 3, [x / k, y / k];
13140 // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
13141 // the 3D cross product in a quadrant I Cartesian coordinate system (+x is
13142 // right, +y is up). Returns a positive value if ABC is counter-clockwise,
13143 // negative if clockwise, and zero if the points are collinear.
13144 function cross (a, b, c) {
13145 return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
13148 function lexicographicOrder(a, b) {
13149 return a[0] - b[0] || a[1] - b[1];
13150 } // Computes the upper convex hull per the monotone chain algorithm.
13151 // Assumes points.length >= 3, is sorted by x, unique in y.
13152 // Returns an array of indices into points in left-to-right order.
13155 function computeUpperHullIndexes(points) {
13156 var n = points.length,
13161 for (i = 2; i < n; ++i) {
13162 while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) {
13166 indexes[size++] = i;
13169 return indexes.slice(0, size); // remove popped points
13172 function d3_polygonHull (points) {
13173 if ((n = points.length) < 3) return null;
13176 sortedPoints = new Array(n),
13177 flippedPoints = new Array(n);
13179 for (i = 0; i < n; ++i) {
13180 sortedPoints[i] = [+points[i][0], +points[i][1], i];
13183 sortedPoints.sort(lexicographicOrder);
13185 for (i = 0; i < n; ++i) {
13186 flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]];
13189 var upperIndexes = computeUpperHullIndexes(sortedPoints),
13190 lowerIndexes = computeUpperHullIndexes(flippedPoints); // Construct the hull polygon, removing possible duplicate endpoints.
13192 var skipLeft = lowerIndexes[0] === upperIndexes[0],
13193 skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1],
13194 hull = []; // Add upper hull in right-to-l order.
13195 // Then add lower hull in left-to-right order.
13197 for (i = upperIndexes.length - 1; i >= 0; --i) {
13198 hull.push(points[sortedPoints[upperIndexes[i]][2]]);
13201 for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) {
13202 hull.push(points[sortedPoints[lowerIndexes[i]][2]]);
13209 function geoVecEqual(a, b, epsilon) {
13211 return Math.abs(a[0] - b[0]) <= epsilon && Math.abs(a[1] - b[1]) <= epsilon;
13213 return a[0] === b[0] && a[1] === b[1];
13215 } // vector addition
13217 function geoVecAdd(a, b) {
13218 return [a[0] + b[0], a[1] + b[1]];
13219 } // vector subtraction
13221 function geoVecSubtract(a, b) {
13222 return [a[0] - b[0], a[1] - b[1]];
13223 } // vector scaling
13225 function geoVecScale(a, mag) {
13226 return [a[0] * mag, a[1] * mag];
13227 } // vector rounding (was: geoRoundCoordinates)
13229 function geoVecFloor(a) {
13230 return [Math.floor(a[0]), Math.floor(a[1])];
13231 } // linear interpolation
13233 function geoVecInterp(a, b, t) {
13234 return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
13235 } // http://jsperf.com/id-dist-optimization
13237 function geoVecLength(a, b) {
13238 return Math.sqrt(geoVecLengthSquare(a, b));
13239 } // length of vector raised to the power two
13241 function geoVecLengthSquare(a, b) {
13243 var x = a[0] - b[0];
13244 var y = a[1] - b[1];
13245 return x * x + y * y;
13246 } // get a unit vector
13248 function geoVecNormalize(a) {
13249 var length = Math.sqrt(a[0] * a[0] + a[1] * a[1]);
13251 if (length !== 0) {
13252 return geoVecScale(a, 1 / length);
13256 } // Return the counterclockwise angle in the range (-pi, pi)
13257 // between the positive X axis and the line intersecting a and b.
13259 function geoVecAngle(a, b) {
13260 return Math.atan2(b[1] - a[1], b[0] - a[0]);
13263 function geoVecDot(a, b, origin) {
13264 origin = origin || [0, 0];
13265 var p = geoVecSubtract(a, origin);
13266 var q = geoVecSubtract(b, origin);
13267 return p[0] * q[0] + p[1] * q[1];
13268 } // normalized dot product
13270 function geoVecNormalizedDot(a, b, origin) {
13271 origin = origin || [0, 0];
13272 var p = geoVecNormalize(geoVecSubtract(a, origin));
13273 var q = geoVecNormalize(geoVecSubtract(b, origin));
13274 return geoVecDot(p, q);
13275 } // 2D cross product of OA and OB vectors, returns magnitude of Z vector
13276 // Returns a positive value, if OAB makes a counter-clockwise turn,
13277 // negative for clockwise turn, and zero if the points are collinear.
13279 function geoVecCross(a, b, origin) {
13280 origin = origin || [0, 0];
13281 var p = geoVecSubtract(a, origin);
13282 var q = geoVecSubtract(b, origin);
13283 return p[0] * q[1] - p[1] * q[0];
13284 } // find closest orthogonal projection of point onto points array
13286 function geoVecProject(a, points) {
13287 var min = Infinity;
13291 for (var i = 0; i < points.length - 1; i++) {
13293 var s = geoVecSubtract(points[i + 1], o);
13294 var v = geoVecSubtract(a, o);
13295 var proj = geoVecDot(v, s) / geoVecDot(s, s);
13300 } else if (proj > 1) {
13303 p = [o[0] + proj * s[0], o[1] + proj * s[1]];
13306 var dist = geoVecLength(p, a);
13315 if (idx !== undefined) {
13326 // between the positive X axis and the line intersecting a and b.
13328 function geoAngle(a, b, projection) {
13329 return geoVecAngle(projection(a.loc), projection(b.loc));
13331 function geoEdgeEqual(a, b) {
13332 return a[0] === b[0] && a[1] === b[1] || a[0] === b[1] && a[1] === b[0];
13333 } // Rotate all points counterclockwise around a pivot point by given angle
13335 function geoRotate(points, angle, around) {
13336 return points.map(function (point) {
13337 var radial = geoVecSubtract(point, around);
13338 return [radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + around[0], radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + around[1]];
13340 } // Choose the edge with the minimal distance from `point` to its orthogonal
13341 // projection onto that edge, if such a projection exists, or the distance to
13342 // the closest vertex on that edge. Returns an object with the `index` of the
13343 // chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
13345 function geoChooseEdge(nodes, point, projection, activeID) {
13346 var dist = geoVecLength;
13347 var points = nodes.map(function (n) {
13348 return projection(n.loc);
13350 var ids = nodes.map(function (n) {
13353 var min = Infinity;
13357 for (var i = 0; i < points.length - 1; i++) {
13358 if (ids[i] === activeID || ids[i + 1] === activeID) continue;
13360 var s = geoVecSubtract(points[i + 1], o);
13361 var v = geoVecSubtract(point, o);
13362 var proj = geoVecDot(v, s) / geoVecDot(s, s);
13367 } else if (proj > 1) {
13370 p = [o[0] + proj * s[0], o[1] + proj * s[1]];
13373 var d = dist(p, point);
13378 loc = projection.invert(p);
13382 if (idx !== undefined) {
13391 } // Test active (dragged or drawing) segments against inactive segments
13392 // This is used to test e.g. multipolygon rings that cross
13393 // `activeNodes` is the ring containing the activeID being dragged.
13394 // `inactiveNodes` is the other ring to test against
13396 function geoHasLineIntersections(activeNodes, inactiveNodes, activeID) {
13398 var inactives = [];
13399 var j, k, n1, n2, segment; // gather active segments (only segments in activeNodes that contain the activeID)
13401 for (j = 0; j < activeNodes.length - 1; j++) {
13402 n1 = activeNodes[j];
13403 n2 = activeNodes[j + 1];
13404 segment = [n1.loc, n2.loc];
13406 if (n1.id === activeID || n2.id === activeID) {
13407 actives.push(segment);
13409 } // gather inactive segments
13412 for (j = 0; j < inactiveNodes.length - 1; j++) {
13413 n1 = inactiveNodes[j];
13414 n2 = inactiveNodes[j + 1];
13415 segment = [n1.loc, n2.loc];
13416 inactives.push(segment);
13420 for (j = 0; j < actives.length; j++) {
13421 for (k = 0; k < inactives.length; k++) {
13422 var p = actives[j];
13423 var q = inactives[k];
13424 var hit = geoLineIntersection(p, q);
13433 } // Test active (dragged or drawing) segments against inactive segments
13434 // This is used to test whether a way intersects with itself.
13436 function geoHasSelfIntersections(nodes, activeID) {
13438 var inactives = [];
13439 var j, k; // group active and passive segments along the nodes
13441 for (j = 0; j < nodes.length - 1; j++) {
13443 var n2 = nodes[j + 1];
13444 var segment = [n1.loc, n2.loc];
13446 if (n1.id === activeID || n2.id === activeID) {
13447 actives.push(segment);
13449 inactives.push(segment);
13454 for (j = 0; j < actives.length; j++) {
13455 for (k = 0; k < inactives.length; k++) {
13456 var p = actives[j];
13457 var q = inactives[k]; // skip if segments share an endpoint
13459 if (geoVecEqual(p[1], q[0]) || geoVecEqual(p[0], q[1]) || geoVecEqual(p[0], q[0]) || geoVecEqual(p[1], q[1])) {
13463 var hit = geoLineIntersection(p, q);
13466 var epsilon = 1e-8; // skip if the hit is at the segment's endpoint
13468 if (geoVecEqual(p[1], hit, epsilon) || geoVecEqual(p[0], hit, epsilon) || geoVecEqual(q[1], hit, epsilon) || geoVecEqual(q[0], hit, epsilon)) {
13478 } // Return the intersection point of 2 line segments.
13479 // From https://github.com/pgkelley4/line-segments-intersect
13480 // This uses the vector cross product approach described below:
13481 // http://stackoverflow.com/a/565282/786339
13483 function geoLineIntersection(a, b) {
13484 var p = [a[0][0], a[0][1]];
13485 var p2 = [a[1][0], a[1][1]];
13486 var q = [b[0][0], b[0][1]];
13487 var q2 = [b[1][0], b[1][1]];
13488 var r = geoVecSubtract(p2, p);
13489 var s = geoVecSubtract(q2, q);
13490 var uNumerator = geoVecCross(geoVecSubtract(q, p), r);
13491 var denominator = geoVecCross(r, s);
13493 if (uNumerator && denominator) {
13494 var u = uNumerator / denominator;
13495 var t = geoVecCross(geoVecSubtract(q, p), s) / denominator;
13497 if (t >= 0 && t <= 1 && u >= 0 && u <= 1) {
13498 return geoVecInterp(p, p2, t);
13504 function geoPathIntersections(path1, path2) {
13505 var intersections = [];
13507 for (var i = 0; i < path1.length - 1; i++) {
13508 for (var j = 0; j < path2.length - 1; j++) {
13509 var a = [path1[i], path1[i + 1]];
13510 var b = [path2[j], path2[j + 1]];
13511 var hit = geoLineIntersection(a, b);
13514 intersections.push(hit);
13519 return intersections;
13521 function geoPathHasIntersections(path1, path2) {
13522 for (var i = 0; i < path1.length - 1; i++) {
13523 for (var j = 0; j < path2.length - 1; j++) {
13524 var a = [path1[i], path1[i + 1]];
13525 var b = [path2[j], path2[j + 1]];
13526 var hit = geoLineIntersection(a, b);
13535 } // Return whether point is contained in polygon.
13537 // `point` should be a 2-item array of coordinates.
13538 // `polygon` should be an array of 2-item arrays of coordinates.
13540 // From https://github.com/substack/point-in-polygon.
13541 // ray-casting algorithm based on
13542 // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
13545 function geoPointInPolygon(point, polygon) {
13548 var inside = false;
13550 for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
13551 var xi = polygon[i][0];
13552 var yi = polygon[i][1];
13553 var xj = polygon[j][0];
13554 var yj = polygon[j][1];
13555 var intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi;
13556 if (intersect) inside = !inside;
13561 function geoPolygonContainsPolygon(outer, inner) {
13562 return inner.every(function (point) {
13563 return geoPointInPolygon(point, outer);
13566 function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
13567 function testPoints(outer, inner) {
13568 return inner.some(function (point) {
13569 return geoPointInPolygon(point, outer);
13573 return testPoints(outer, inner) || !!checkSegments && geoPathHasIntersections(outer, inner);
13574 } // http://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points
13575 // http://gis.stackexchange.com/questions/3739/generalisation-strategies-for-building-outlines/3756#3756
13577 function geoGetSmallestSurroundingRectangle(points) {
13578 var hull = d3_polygonHull(points);
13579 var centroid = d3_polygonCentroid(hull);
13580 var minArea = Infinity;
13581 var ssrExtent = [];
13585 for (var i = 0; i <= hull.length - 1; i++) {
13586 var c2 = i === hull.length - 1 ? hull[0] : hull[i + 1];
13587 var angle = Math.atan2(c2[1] - c1[1], c2[0] - c1[0]);
13588 var poly = geoRotate(hull, -angle, centroid);
13589 var extent = poly.reduce(function (extent, point) {
13590 return extent.extend(geoExtent(point));
13592 var area = extent.area();
13594 if (area < minArea) {
13596 ssrExtent = extent;
13604 poly: geoRotate(ssrExtent.polygon(), ssrAngle, centroid),
13608 function geoPathLength(path) {
13611 for (var i = 0; i < path.length - 1; i++) {
13612 length += geoVecLength(path[i], path[i + 1]);
13616 } // If the given point is at the edge of the padded viewport,
13617 // return a vector that will nudge the viewport in that direction
13619 function geoViewportEdge(point, dimensions) {
13620 var pad = [80, 20, 50, 20]; // top, right, bottom, left
13625 if (point[0] > dimensions[0] - pad[1]) {
13629 if (point[0] < pad[3]) {
13633 if (point[1] > dimensions[1] - pad[2]) {
13637 if (point[1] < pad[0]) {
13649 value: function value() {}
13652 function dispatch$8() {
13653 for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
13654 if (!(t = arguments[i] + "") || t in _ || /[\s.]/.test(t)) throw new Error("illegal type: " + t);
13658 return new Dispatch(_);
13661 function Dispatch(_) {
13665 function parseTypenames$1(typenames, types) {
13666 return typenames.trim().split(/^|\s+/).map(function (t) {
13668 i = t.indexOf(".");
13669 if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
13670 if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
13678 Dispatch.prototype = dispatch$8.prototype = {
13679 constructor: Dispatch,
13680 on: function on(typename, callback) {
13682 T = parseTypenames$1(typename + "", _),
13685 n = T.length; // If no callback was specified, return the callback of the given type and name.
13687 if (arguments.length < 2) {
13689 if ((t = (typename = T[i]).type) && (t = get$2(_[t], typename.name))) return t;
13693 } // If a type was specified, set the callback for the given type and name.
13694 // Otherwise, if a null callback was specified, remove callbacks of the given name.
13697 if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
13700 if (t = (typename = T[i]).type) _[t] = set$1(_[t], typename.name, callback);else if (callback == null) for (t in _) {
13701 _[t] = set$1(_[t], typename.name, null);
13707 copy: function copy() {
13712 copy[t] = _[t].slice();
13715 return new Dispatch(copy);
13717 call: function call(type, that) {
13718 if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) {
13719 args[i] = arguments[i + 2];
13721 if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
13723 for (t = this._[type], i = 0, n = t.length; i < n; ++i) {
13724 t[i].value.apply(that, args);
13727 apply: function apply(type, that, args) {
13728 if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
13730 for (var t = this._[type], i = 0, n = t.length; i < n; ++i) {
13731 t[i].value.apply(that, args);
13736 function get$2(type, name) {
13737 for (var i = 0, n = type.length, c; i < n; ++i) {
13738 if ((c = type[i]).name === name) {
13744 function set$1(type, name, callback) {
13745 for (var i = 0, n = type.length; i < n; ++i) {
13746 if (type[i].name === name) {
13747 type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1));
13752 if (callback != null) type.push({
13759 var xhtml = "http://www.w3.org/1999/xhtml";
13761 svg: "http://www.w3.org/2000/svg",
13763 xlink: "http://www.w3.org/1999/xlink",
13764 xml: "http://www.w3.org/XML/1998/namespace",
13765 xmlns: "http://www.w3.org/2000/xmlns/"
13768 function namespace (name) {
13769 var prefix = name += "",
13770 i = prefix.indexOf(":");
13771 if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
13772 return namespaces.hasOwnProperty(prefix) ? {
13773 space: namespaces[prefix],
13775 } : name; // eslint-disable-line no-prototype-builtins
13778 function creatorInherit(name) {
13779 return function () {
13780 var document = this.ownerDocument,
13781 uri = this.namespaceURI;
13782 return uri === xhtml && document.documentElement.namespaceURI === xhtml ? document.createElement(name) : document.createElementNS(uri, name);
13786 function creatorFixed(fullname) {
13787 return function () {
13788 return this.ownerDocument.createElementNS(fullname.space, fullname.local);
13792 function creator (name) {
13793 var fullname = namespace(name);
13794 return (fullname.local ? creatorFixed : creatorInherit)(fullname);
13799 function selector (selector) {
13800 return selector == null ? none : function () {
13801 return this.querySelector(selector);
13805 function selection_select (select) {
13806 if (typeof select !== "function") select = selector(select);
13808 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
13809 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
13810 if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
13811 if ("__data__" in node) subnode.__data__ = node.__data__;
13812 subgroup[i] = subnode;
13817 return new Selection$1(subgroups, this._parents);
13820 function array (x) {
13821 return _typeof(x) === "object" && "length" in x ? x // Array, TypedArray, NodeList, array-like
13822 : Array.from(x); // Map, Set, iterable, string, or anything else
13829 function selectorAll (selector) {
13830 return selector == null ? empty : function () {
13831 return this.querySelectorAll(selector);
13835 function arrayAll(select) {
13836 return function () {
13837 var group = select.apply(this, arguments);
13838 return group == null ? [] : array(group);
13842 function selection_selectAll (select) {
13843 if (typeof select === "function") select = arrayAll(select);else select = selectorAll(select);
13845 for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
13846 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
13847 if (node = group[i]) {
13848 subgroups.push(select.call(node, node.__data__, i, group));
13849 parents.push(node);
13854 return new Selection$1(subgroups, parents);
13858 var $find = arrayIteration.find;
13859 var addToUnscopables$3 = addToUnscopables$6;
13862 var SKIPS_HOLES$1 = true;
13864 // Shouldn't skip holes
13865 if (FIND in []) Array(1)[FIND](function () { SKIPS_HOLES$1 = false; });
13867 // `Array.prototype.find` method
13868 // https://tc39.es/ecma262/#sec-array.prototype.find
13869 $$u({ target: 'Array', proto: true, forced: SKIPS_HOLES$1 }, {
13870 find: function find(callbackfn /* , that = undefined */) {
13871 return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
13875 // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
13876 addToUnscopables$3(FIND);
13878 function matcher (selector) {
13879 return function () {
13880 return this.matches(selector);
13883 function childMatcher(selector) {
13884 return function (node) {
13885 return node.matches(selector);
13889 var find = Array.prototype.find;
13891 function childFind(match) {
13892 return function () {
13893 return find.call(this.children, match);
13897 function childFirst() {
13898 return this.firstElementChild;
13901 function selection_selectChild (match) {
13902 return this.select(match == null ? childFirst : childFind(typeof match === "function" ? match : childMatcher(match)));
13905 var filter = Array.prototype.filter;
13907 function children() {
13908 return this.children;
13911 function childrenFilter(match) {
13912 return function () {
13913 return filter.call(this.children, match);
13917 function selection_selectChildren (match) {
13918 return this.selectAll(match == null ? children : childrenFilter(typeof match === "function" ? match : childMatcher(match)));
13921 function selection_filter (match) {
13922 if (typeof match !== "function") match = matcher(match);
13924 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
13925 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
13926 if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
13927 subgroup.push(node);
13932 return new Selection$1(subgroups, this._parents);
13935 function sparse (update) {
13936 return new Array(update.length);
13939 function selection_enter () {
13940 return new Selection$1(this._enter || this._groups.map(sparse), this._parents);
13942 function EnterNode(parent, datum) {
13943 this.ownerDocument = parent.ownerDocument;
13944 this.namespaceURI = parent.namespaceURI;
13946 this._parent = parent;
13947 this.__data__ = datum;
13949 EnterNode.prototype = {
13950 constructor: EnterNode,
13951 appendChild: function appendChild(child) {
13952 return this._parent.insertBefore(child, this._next);
13954 insertBefore: function insertBefore(child, next) {
13955 return this._parent.insertBefore(child, next);
13957 querySelector: function querySelector(selector) {
13958 return this._parent.querySelector(selector);
13960 querySelectorAll: function querySelectorAll(selector) {
13961 return this._parent.querySelectorAll(selector);
13965 function constant$3 (x) {
13966 return function () {
13971 function bindIndex(parent, group, enter, update, exit, data) {
13974 groupLength = group.length,
13975 dataLength = data.length; // Put any non-null nodes that fit into update.
13976 // Put any null nodes into enter.
13977 // Put any remaining data into enter.
13979 for (; i < dataLength; ++i) {
13980 if (node = group[i]) {
13981 node.__data__ = data[i];
13984 enter[i] = new EnterNode(parent, data[i]);
13986 } // Put any non-null nodes that don’t fit into exit.
13989 for (; i < groupLength; ++i) {
13990 if (node = group[i]) {
13996 function bindKey(parent, group, enter, update, exit, data, key) {
13999 nodeByKeyValue = new Map(),
14000 groupLength = group.length,
14001 dataLength = data.length,
14002 keyValues = new Array(groupLength),
14003 keyValue; // Compute the key for each node.
14004 // If multiple nodes have the same key, the duplicates are added to exit.
14006 for (i = 0; i < groupLength; ++i) {
14007 if (node = group[i]) {
14008 keyValues[i] = keyValue = key.call(node, node.__data__, i, group) + "";
14010 if (nodeByKeyValue.has(keyValue)) {
14013 nodeByKeyValue.set(keyValue, node);
14016 } // Compute the key for each datum.
14017 // If there a node associated with this key, join and add it to update.
14018 // If there is not (or the key is a duplicate), add it to enter.
14021 for (i = 0; i < dataLength; ++i) {
14022 keyValue = key.call(parent, data[i], i, data) + "";
14024 if (node = nodeByKeyValue.get(keyValue)) {
14026 node.__data__ = data[i];
14027 nodeByKeyValue["delete"](keyValue);
14029 enter[i] = new EnterNode(parent, data[i]);
14031 } // Add any remaining nodes that were not bound to data to exit.
14034 for (i = 0; i < groupLength; ++i) {
14035 if ((node = group[i]) && nodeByKeyValue.get(keyValues[i]) === node) {
14041 function datum(node) {
14042 return node.__data__;
14045 function selection_data (value, key) {
14046 if (!arguments.length) return Array.from(this, datum);
14047 var bind = key ? bindKey : bindIndex,
14048 parents = this._parents,
14049 groups = this._groups;
14050 if (typeof value !== "function") value = constant$3(value);
14052 for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
14053 var parent = parents[j],
14055 groupLength = group.length,
14056 data = array(value.call(parent, parent && parent.__data__, j, parents)),
14057 dataLength = data.length,
14058 enterGroup = enter[j] = new Array(dataLength),
14059 updateGroup = update[j] = new Array(dataLength),
14060 exitGroup = exit[j] = new Array(groupLength);
14061 bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); // Now connect the enter nodes to their following update node, such that
14062 // appendChild can insert the materialized enter node before this node,
14063 // rather than at the end of the parent node.
14065 for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
14066 if (previous = enterGroup[i0]) {
14067 if (i0 >= i1) i1 = i0 + 1;
14069 while (!(next = updateGroup[i1]) && ++i1 < dataLength) {
14072 previous._next = next || null;
14077 update = new Selection$1(update, parents);
14078 update._enter = enter;
14079 update._exit = exit;
14083 function selection_exit () {
14084 return new Selection$1(this._exit || this._groups.map(sparse), this._parents);
14087 function selection_join (onenter, onupdate, onexit) {
14088 var enter = this.enter(),
14090 exit = this.exit();
14091 enter = typeof onenter === "function" ? onenter(enter) : enter.append(onenter + "");
14092 if (onupdate != null) update = onupdate(update);
14093 if (onexit == null) exit.remove();else onexit(exit);
14094 return enter && update ? enter.merge(update).order() : update;
14097 function selection_merge (selection) {
14098 if (!(selection instanceof Selection$1)) throw new Error("invalid merge");
14100 for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
14101 for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
14102 if (node = group0[i] || group1[i]) {
14108 for (; j < m0; ++j) {
14109 merges[j] = groups0[j];
14112 return new Selection$1(merges, this._parents);
14115 function selection_order () {
14116 for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
14117 for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
14118 if (node = group[i]) {
14119 if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next);
14128 function selection_sort (compare) {
14129 if (!compare) compare = ascending;
14131 function compareNode(a, b) {
14132 return a && b ? compare(a.__data__, b.__data__) : !a - !b;
14135 for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
14136 for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
14137 if (node = group[i]) {
14138 sortgroup[i] = node;
14142 sortgroup.sort(compareNode);
14145 return new Selection$1(sortgroups, this._parents).order();
14148 function ascending(a, b) {
14149 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
14152 function selection_call () {
14153 var callback = arguments[0];
14154 arguments[0] = this;
14155 callback.apply(null, arguments);
14159 function selection_nodes () {
14160 return Array.from(this);
14163 function selection_node () {
14164 for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
14165 for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
14166 var node = group[i];
14167 if (node) return node;
14174 function selection_size () {
14177 var _iterator = _createForOfIteratorHelper(this),
14181 for (_iterator.s(); !(_step = _iterator.n()).done;) {
14182 var node = _step.value;
14184 } // eslint-disable-line no-unused-vars
14195 function selection_empty () {
14196 return !this.node();
14199 function selection_each (callback) {
14200 for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
14201 for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
14202 if (node = group[i]) callback.call(node, node.__data__, i, group);
14209 function attrRemove$1(name) {
14210 return function () {
14211 this.removeAttribute(name);
14215 function attrRemoveNS$1(fullname) {
14216 return function () {
14217 this.removeAttributeNS(fullname.space, fullname.local);
14221 function attrConstant$1(name, value) {
14222 return function () {
14223 this.setAttribute(name, value);
14227 function attrConstantNS$1(fullname, value) {
14228 return function () {
14229 this.setAttributeNS(fullname.space, fullname.local, value);
14233 function attrFunction$1(name, value) {
14234 return function () {
14235 var v = value.apply(this, arguments);
14236 if (v == null) this.removeAttribute(name);else this.setAttribute(name, v);
14240 function attrFunctionNS$1(fullname, value) {
14241 return function () {
14242 var v = value.apply(this, arguments);
14243 if (v == null) this.removeAttributeNS(fullname.space, fullname.local);else this.setAttributeNS(fullname.space, fullname.local, v);
14247 function selection_attr (name, value) {
14248 var fullname = namespace(name);
14250 if (arguments.length < 2) {
14251 var node = this.node();
14252 return fullname.local ? node.getAttributeNS(fullname.space, fullname.local) : node.getAttribute(fullname);
14255 return this.each((value == null ? fullname.local ? attrRemoveNS$1 : attrRemove$1 : typeof value === "function" ? fullname.local ? attrFunctionNS$1 : attrFunction$1 : fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, value));
14258 function defaultView (node) {
14259 return node.ownerDocument && node.ownerDocument.defaultView // node is a Node
14260 || node.document && node // node is a Window
14261 || node.defaultView; // node is a Document
14264 function styleRemove$1(name) {
14265 return function () {
14266 this.style.removeProperty(name);
14270 function styleConstant$1(name, value, priority) {
14271 return function () {
14272 this.style.setProperty(name, value, priority);
14276 function styleFunction$1(name, value, priority) {
14277 return function () {
14278 var v = value.apply(this, arguments);
14279 if (v == null) this.style.removeProperty(name);else this.style.setProperty(name, v, priority);
14283 function selection_style (name, value, priority) {
14284 return arguments.length > 1 ? this.each((value == null ? styleRemove$1 : typeof value === "function" ? styleFunction$1 : styleConstant$1)(name, value, priority == null ? "" : priority)) : styleValue(this.node(), name);
14286 function styleValue(node, name) {
14287 return node.style.getPropertyValue(name) || defaultView(node).getComputedStyle(node, null).getPropertyValue(name);
14290 function propertyRemove(name) {
14291 return function () {
14296 function propertyConstant(name, value) {
14297 return function () {
14298 this[name] = value;
14302 function propertyFunction(name, value) {
14303 return function () {
14304 var v = value.apply(this, arguments);
14305 if (v == null) delete this[name];else this[name] = v;
14309 function selection_property (name, value) {
14310 return arguments.length > 1 ? this.each((value == null ? propertyRemove : typeof value === "function" ? propertyFunction : propertyConstant)(name, value)) : this.node()[name];
14313 function classArray(string) {
14314 return string.trim().split(/^|\s+/);
14317 function classList(node) {
14318 return node.classList || new ClassList(node);
14321 function ClassList(node) {
14323 this._names = classArray(node.getAttribute("class") || "");
14326 ClassList.prototype = {
14327 add: function add(name) {
14328 var i = this._names.indexOf(name);
14331 this._names.push(name);
14333 this._node.setAttribute("class", this._names.join(" "));
14336 remove: function remove(name) {
14337 var i = this._names.indexOf(name);
14340 this._names.splice(i, 1);
14342 this._node.setAttribute("class", this._names.join(" "));
14345 contains: function contains(name) {
14346 return this._names.indexOf(name) >= 0;
14350 function classedAdd(node, names) {
14351 var list = classList(node),
14356 list.add(names[i]);
14360 function classedRemove(node, names) {
14361 var list = classList(node),
14366 list.remove(names[i]);
14370 function classedTrue(names) {
14371 return function () {
14372 classedAdd(this, names);
14376 function classedFalse(names) {
14377 return function () {
14378 classedRemove(this, names);
14382 function classedFunction(names, value) {
14383 return function () {
14384 (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
14388 function selection_classed (name, value) {
14389 var names = classArray(name + "");
14391 if (arguments.length < 2) {
14392 var list = classList(this.node()),
14397 if (!list.contains(names[i])) return false;
14403 return this.each((typeof value === "function" ? classedFunction : value ? classedTrue : classedFalse)(names, value));
14406 function textRemove() {
14407 this.textContent = "";
14410 function textConstant$1(value) {
14411 return function () {
14412 this.textContent = value;
14416 function textFunction$1(value) {
14417 return function () {
14418 var v = value.apply(this, arguments);
14419 this.textContent = v == null ? "" : v;
14423 function selection_text (value) {
14424 return arguments.length ? this.each(value == null ? textRemove : (typeof value === "function" ? textFunction$1 : textConstant$1)(value)) : this.node().textContent;
14427 function htmlRemove() {
14428 this.innerHTML = "";
14431 function htmlConstant(value) {
14432 return function () {
14433 this.innerHTML = value;
14437 function htmlFunction(value) {
14438 return function () {
14439 var v = value.apply(this, arguments);
14440 this.innerHTML = v == null ? "" : v;
14444 function selection_html (value) {
14445 return arguments.length ? this.each(value == null ? htmlRemove : (typeof value === "function" ? htmlFunction : htmlConstant)(value)) : this.node().innerHTML;
14449 if (this.nextSibling) this.parentNode.appendChild(this);
14452 function selection_raise () {
14453 return this.each(raise);
14457 if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
14460 function selection_lower () {
14461 return this.each(lower);
14464 function selection_append (name) {
14465 var create = typeof name === "function" ? name : creator(name);
14466 return this.select(function () {
14467 return this.appendChild(create.apply(this, arguments));
14471 function constantNull() {
14475 function selection_insert (name, before) {
14476 var create = typeof name === "function" ? name : creator(name),
14477 select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
14478 return this.select(function () {
14479 return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
14483 function remove$7() {
14484 var parent = this.parentNode;
14485 if (parent) parent.removeChild(this);
14488 function selection_remove () {
14489 return this.each(remove$7);
14492 function selection_cloneShallow() {
14493 var clone = this.cloneNode(false),
14494 parent = this.parentNode;
14495 return parent ? parent.insertBefore(clone, this.nextSibling) : clone;
14498 function selection_cloneDeep() {
14499 var clone = this.cloneNode(true),
14500 parent = this.parentNode;
14501 return parent ? parent.insertBefore(clone, this.nextSibling) : clone;
14504 function selection_clone (deep) {
14505 return this.select(deep ? selection_cloneDeep : selection_cloneShallow);
14508 function selection_datum (value) {
14509 return arguments.length ? this.property("__data__", value) : this.node().__data__;
14512 function contextListener(listener) {
14513 return function (event) {
14514 listener.call(this, event, this.__data__);
14518 function parseTypenames(typenames) {
14519 return typenames.trim().split(/^|\s+/).map(function (t) {
14521 i = t.indexOf(".");
14522 if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
14530 function onRemove(typename) {
14531 return function () {
14532 var on = this.__on;
14535 for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
14536 if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
14537 this.removeEventListener(o.type, o.listener, o.options);
14543 if (++i) on.length = i;else delete this.__on;
14547 function onAdd(typename, value, options) {
14548 return function () {
14549 var on = this.__on,
14551 listener = contextListener(value);
14552 if (on) for (var j = 0, m = on.length; j < m; ++j) {
14553 if ((o = on[j]).type === typename.type && o.name === typename.name) {
14554 this.removeEventListener(o.type, o.listener, o.options);
14555 this.addEventListener(o.type, o.listener = listener, o.options = options);
14560 this.addEventListener(typename.type, listener, options);
14562 type: typename.type,
14563 name: typename.name,
14565 listener: listener,
14568 if (!on) this.__on = [o];else on.push(o);
14572 function selection_on (typename, value, options) {
14573 var typenames = parseTypenames(typename + ""),
14575 n = typenames.length,
14578 if (arguments.length < 2) {
14579 var on = this.node().__on;
14581 if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
14582 for (i = 0, o = on[j]; i < n; ++i) {
14583 if ((t = typenames[i]).type === o.type && t.name === o.name) {
14591 on = value ? onAdd : onRemove;
14593 for (i = 0; i < n; ++i) {
14594 this.each(on(typenames[i], value, options));
14600 function dispatchEvent(node, type, params) {
14601 var window = defaultView(node),
14602 event = window.CustomEvent;
14604 if (typeof event === "function") {
14605 event = new event(type, params);
14607 event = window.document.createEvent("Event");
14608 if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;else event.initEvent(type, false, false);
14611 node.dispatchEvent(event);
14614 function dispatchConstant(type, params) {
14615 return function () {
14616 return dispatchEvent(this, type, params);
14620 function dispatchFunction(type, params) {
14621 return function () {
14622 return dispatchEvent(this, type, params.apply(this, arguments));
14626 function selection_dispatch (type, params) {
14627 return this.each((typeof params === "function" ? dispatchFunction : dispatchConstant)(type, params));
14630 var _marked$1 = /*#__PURE__*/regeneratorRuntime.mark(_callee);
14632 function _callee() {
14633 var groups, j, m, group, i, n, node;
14634 return regeneratorRuntime.wrap(function _callee$(_context) {
14636 switch (_context.prev = _context.next) {
14638 groups = this._groups, j = 0, m = groups.length;
14642 _context.next = 13;
14646 group = groups[j], i = 0, n = group.length;
14650 _context.next = 10;
14654 if (!(node = group[i])) {
14674 return _context.stop();
14677 }, _marked$1, this);
14680 var root$1 = [null];
14681 function Selection$1(groups, parents) {
14682 this._groups = groups;
14683 this._parents = parents;
14686 function selection() {
14687 return new Selection$1([[document.documentElement]], root$1);
14690 function selection_selection() {
14694 Selection$1.prototype = selection.prototype = _defineProperty({
14695 constructor: Selection$1,
14696 select: selection_select,
14697 selectAll: selection_selectAll,
14698 selectChild: selection_selectChild,
14699 selectChildren: selection_selectChildren,
14700 filter: selection_filter,
14701 data: selection_data,
14702 enter: selection_enter,
14703 exit: selection_exit,
14704 join: selection_join,
14705 merge: selection_merge,
14706 selection: selection_selection,
14707 order: selection_order,
14708 sort: selection_sort,
14709 call: selection_call,
14710 nodes: selection_nodes,
14711 node: selection_node,
14712 size: selection_size,
14713 empty: selection_empty,
14714 each: selection_each,
14715 attr: selection_attr,
14716 style: selection_style,
14717 property: selection_property,
14718 classed: selection_classed,
14719 text: selection_text,
14720 html: selection_html,
14721 raise: selection_raise,
14722 lower: selection_lower,
14723 append: selection_append,
14724 insert: selection_insert,
14725 remove: selection_remove,
14726 clone: selection_clone,
14727 datum: selection_datum,
14729 dispatch: selection_dispatch
14730 }, Symbol.iterator, _callee);
14732 function select (selector) {
14733 return typeof selector === "string" ? new Selection$1([[document.querySelector(selector)]], [document.documentElement]) : new Selection$1([[selector]], root$1);
14736 function sourceEvent (event) {
14739 while (sourceEvent = event.sourceEvent) {
14740 event = sourceEvent;
14746 function pointer (event, node) {
14747 event = sourceEvent(event);
14748 if (node === undefined) node = event.currentTarget;
14751 var svg = node.ownerSVGElement || node;
14753 if (svg.createSVGPoint) {
14754 var point = svg.createSVGPoint();
14755 point.x = event.clientX, point.y = event.clientY;
14756 point = point.matrixTransform(node.getScreenCTM().inverse());
14757 return [point.x, point.y];
14760 if (node.getBoundingClientRect) {
14761 var rect = node.getBoundingClientRect();
14762 return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
14766 return [event.pageX, event.pageY];
14769 function selectAll (selector) {
14770 return typeof selector === "string" ? new Selection$1([document.querySelectorAll(selector)], [document.documentElement]) : new Selection$1([selector == null ? [] : array(selector)], root$1);
14773 function nopropagation$1(event) {
14774 event.stopImmediatePropagation();
14776 function noevent$1 (event) {
14777 event.preventDefault();
14778 event.stopImmediatePropagation();
14781 function dragDisable (view) {
14782 var root = view.document.documentElement,
14783 selection = select(view).on("dragstart.drag", noevent$1, true);
14785 if ("onselectstart" in root) {
14786 selection.on("selectstart.drag", noevent$1, true);
14788 root.__noselect = root.style.MozUserSelect;
14789 root.style.MozUserSelect = "none";
14792 function yesdrag(view, noclick) {
14793 var root = view.document.documentElement,
14794 selection = select(view).on("dragstart.drag", null);
14797 selection.on("click.drag", noevent$1, true);
14798 setTimeout(function () {
14799 selection.on("click.drag", null);
14803 if ("onselectstart" in root) {
14804 selection.on("selectstart.drag", null);
14806 root.style.MozUserSelect = root.__noselect;
14807 delete root.__noselect;
14811 var constant$2 = (function (x) {
14812 return function () {
14817 function DragEvent(type, _ref) {
14818 var sourceEvent = _ref.sourceEvent,
14819 subject = _ref.subject,
14820 target = _ref.target,
14821 identifier = _ref.identifier,
14822 active = _ref.active,
14827 dispatch = _ref.dispatch;
14828 Object.defineProperties(this, {
14835 value: sourceEvent,
14885 DragEvent.prototype.on = function () {
14886 var value = this._.on.apply(this._, arguments);
14888 return value === this._ ? this : value;
14891 function defaultFilter$2(event) {
14892 return !event.ctrlKey && !event.button;
14895 function defaultContainer() {
14896 return this.parentNode;
14899 function defaultSubject(event, d) {
14900 return d == null ? {
14906 function defaultTouchable$1() {
14907 return navigator.maxTouchPoints || "ontouchstart" in this;
14910 function d3_drag () {
14911 var filter = defaultFilter$2,
14912 container = defaultContainer,
14913 subject = defaultSubject,
14914 touchable = defaultTouchable$1,
14916 listeners = dispatch$8("start", "drag", "end"),
14922 clickDistance2 = 0;
14924 function drag(selection) {
14925 selection.on("mousedown.drag", mousedowned).filter(touchable).on("touchstart.drag", touchstarted).on("touchmove.drag", touchmoved).on("touchend.drag touchcancel.drag", touchended).style("touch-action", "none").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
14928 function mousedowned(event, d) {
14929 if (touchending || !filter.call(this, event, d)) return;
14930 var gesture = beforestart(this, container.call(this, event, d), event, d, "mouse");
14931 if (!gesture) return;
14932 select(event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true);
14933 dragDisable(event.view);
14934 nopropagation$1(event);
14935 mousemoving = false;
14936 mousedownx = event.clientX;
14937 mousedowny = event.clientY;
14938 gesture("start", event);
14941 function mousemoved(event) {
14944 if (!mousemoving) {
14945 var dx = event.clientX - mousedownx,
14946 dy = event.clientY - mousedowny;
14947 mousemoving = dx * dx + dy * dy > clickDistance2;
14950 gestures.mouse("drag", event);
14953 function mouseupped(event) {
14954 select(event.view).on("mousemove.drag mouseup.drag", null);
14955 yesdrag(event.view, mousemoving);
14957 gestures.mouse("end", event);
14960 function touchstarted(event, d) {
14961 if (!filter.call(this, event, d)) return;
14962 var touches = event.changedTouches,
14963 c = container.call(this, event, d),
14964 n = touches.length,
14968 for (i = 0; i < n; ++i) {
14969 if (gesture = beforestart(this, c, event, d, touches[i].identifier, touches[i])) {
14970 nopropagation$1(event);
14971 gesture("start", event, touches[i]);
14976 function touchmoved(event) {
14977 var touches = event.changedTouches,
14978 n = touches.length,
14982 for (i = 0; i < n; ++i) {
14983 if (gesture = gestures[touches[i].identifier]) {
14985 gesture("drag", event, touches[i]);
14990 function touchended(event) {
14991 var touches = event.changedTouches,
14992 n = touches.length,
14995 if (touchending) clearTimeout(touchending);
14996 touchending = setTimeout(function () {
14997 touchending = null;
14998 }, 500); // Ghost clicks are delayed!
15000 for (i = 0; i < n; ++i) {
15001 if (gesture = gestures[touches[i].identifier]) {
15002 nopropagation$1(event);
15003 gesture("end", event, touches[i]);
15008 function beforestart(that, container, event, d, identifier, touch) {
15009 var dispatch = listeners.copy(),
15010 p = pointer(touch || event, container),
15014 if ((s = subject.call(that, new DragEvent("beforestart", {
15015 sourceEvent: event,
15017 identifier: identifier,
15024 }), d)) == null) return;
15025 dx = s.x - p[0] || 0;
15026 dy = s.y - p[1] || 0;
15027 return function gesture(type, event, touch) {
15033 gestures[identifier] = gesture, n = active++;
15037 delete gestures[identifier], --active;
15041 p = pointer(touch || event, container), n = active;
15045 dispatch.call(type, that, new DragEvent(type, {
15046 sourceEvent: event,
15049 identifier: identifier,
15060 drag.filter = function (_) {
15061 return arguments.length ? (filter = typeof _ === "function" ? _ : constant$2(!!_), drag) : filter;
15064 drag.container = function (_) {
15065 return arguments.length ? (container = typeof _ === "function" ? _ : constant$2(_), drag) : container;
15068 drag.subject = function (_) {
15069 return arguments.length ? (subject = typeof _ === "function" ? _ : constant$2(_), drag) : subject;
15072 drag.touchable = function (_) {
15073 return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$2(!!_), drag) : touchable;
15076 drag.on = function () {
15077 var value = listeners.on.apply(listeners, arguments);
15078 return value === listeners ? drag : value;
15081 drag.clickDistance = function (_) {
15082 return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2);
15088 var DESCRIPTORS$4 = descriptors;
15089 var global$b = global$1o;
15090 var uncurryThis$e = functionUncurryThis;
15091 var isForced$1 = isForced_1;
15092 var inheritIfRequired$1 = inheritIfRequired$4;
15093 var createNonEnumerableProperty = createNonEnumerableProperty$b;
15094 var defineProperty$1 = objectDefineProperty.f;
15095 var getOwnPropertyNames$1 = objectGetOwnPropertyNames.f;
15096 var isPrototypeOf$1 = objectIsPrototypeOf;
15097 var isRegExp$1 = isRegexp;
15098 var toString$9 = toString$k;
15099 var regExpFlags$1 = regexpFlags$1;
15100 var stickyHelpers = regexpStickyHelpers;
15101 var redefine$3 = redefine$h.exports;
15102 var fails$a = fails$V;
15103 var hasOwn$2 = hasOwnProperty_1;
15104 var enforceInternalState = internalState.enforce;
15105 var setSpecies = setSpecies$5;
15106 var wellKnownSymbol$1 = wellKnownSymbol$t;
15107 var UNSUPPORTED_DOT_ALL = regexpUnsupportedDotAll;
15108 var UNSUPPORTED_NCG = regexpUnsupportedNcg;
15110 var MATCH$1 = wellKnownSymbol$1('match');
15111 var NativeRegExp = global$b.RegExp;
15112 var RegExpPrototype$1 = NativeRegExp.prototype;
15113 var SyntaxError$1 = global$b.SyntaxError;
15114 var getFlags = uncurryThis$e(regExpFlags$1);
15115 var exec$2 = uncurryThis$e(RegExpPrototype$1.exec);
15116 var charAt$1 = uncurryThis$e(''.charAt);
15117 var replace$3 = uncurryThis$e(''.replace);
15118 var stringIndexOf$1 = uncurryThis$e(''.indexOf);
15119 var stringSlice$4 = uncurryThis$e(''.slice);
15120 // TODO: Use only propper RegExpIdentifierName
15121 var IS_NCG = /^\?<[^\s\d!#%&*+<=>@^][^\s!#%&*+<=>@^]*>/;
15125 // "new" should create a new object, old webkit bug
15126 var CORRECT_NEW = new NativeRegExp(re1) !== re1;
15128 var MISSED_STICKY = stickyHelpers.MISSED_STICKY;
15129 var UNSUPPORTED_Y = stickyHelpers.UNSUPPORTED_Y;
15131 var BASE_FORCED = DESCRIPTORS$4 &&
15132 (!CORRECT_NEW || MISSED_STICKY || UNSUPPORTED_DOT_ALL || UNSUPPORTED_NCG || fails$a(function () {
15133 re2[MATCH$1] = false;
15134 // RegExp constructor can alter flags and IsRegExp works correct with @@match
15135 return NativeRegExp(re1) != re1 || NativeRegExp(re2) == re2 || NativeRegExp(re1, 'i') != '/a/i';
15138 var handleDotAll = function (string) {
15139 var length = string.length;
15142 var brackets = false;
15144 for (; index <= length; index++) {
15145 chr = charAt$1(string, index);
15146 if (chr === '\\') {
15147 result += chr + charAt$1(string, ++index);
15150 if (!brackets && chr === '.') {
15151 result += '[\\s\\S]';
15155 } else if (chr === ']') {
15162 var handleNCG = function (string) {
15163 var length = string.length;
15168 var brackets = false;
15171 var groupname = '';
15173 for (; index <= length; index++) {
15174 chr = charAt$1(string, index);
15175 if (chr === '\\') {
15176 chr = chr + charAt$1(string, ++index);
15177 } else if (chr === ']') {
15179 } else if (!brackets) switch (true) {
15184 if (exec$2(IS_NCG, stringSlice$4(string, index + 1))) {
15191 case chr === '>' && ncg:
15192 if (groupname === '' || hasOwn$2(names, groupname)) {
15193 throw new SyntaxError$1('Invalid capture group name');
15195 names[groupname] = true;
15196 named[named.length] = [groupname, groupid];
15201 if (ncg) groupname += chr;
15202 else result += chr;
15203 } return [result, named];
15206 // `RegExp` constructor
15207 // https://tc39.es/ecma262/#sec-regexp-constructor
15208 if (isForced$1('RegExp', BASE_FORCED)) {
15209 var RegExpWrapper = function RegExp(pattern, flags) {
15210 var thisIsRegExp = isPrototypeOf$1(RegExpPrototype$1, this);
15211 var patternIsRegExp = isRegExp$1(pattern);
15212 var flagsAreUndefined = flags === undefined;
15214 var rawPattern = pattern;
15215 var rawFlags, dotAll, sticky, handled, result, state;
15217 if (!thisIsRegExp && patternIsRegExp && flagsAreUndefined && pattern.constructor === RegExpWrapper) {
15221 if (patternIsRegExp || isPrototypeOf$1(RegExpPrototype$1, pattern)) {
15222 pattern = pattern.source;
15223 if (flagsAreUndefined) flags = 'flags' in rawPattern ? rawPattern.flags : getFlags(rawPattern);
15226 pattern = pattern === undefined ? '' : toString$9(pattern);
15227 flags = flags === undefined ? '' : toString$9(flags);
15228 rawPattern = pattern;
15230 if (UNSUPPORTED_DOT_ALL && 'dotAll' in re1) {
15231 dotAll = !!flags && stringIndexOf$1(flags, 's') > -1;
15232 if (dotAll) flags = replace$3(flags, /s/g, '');
15237 if (MISSED_STICKY && 'sticky' in re1) {
15238 sticky = !!flags && stringIndexOf$1(flags, 'y') > -1;
15239 if (sticky && UNSUPPORTED_Y) flags = replace$3(flags, /y/g, '');
15242 if (UNSUPPORTED_NCG) {
15243 handled = handleNCG(pattern);
15244 pattern = handled[0];
15245 groups = handled[1];
15248 result = inheritIfRequired$1(NativeRegExp(pattern, flags), thisIsRegExp ? this : RegExpPrototype$1, RegExpWrapper);
15250 if (dotAll || sticky || groups.length) {
15251 state = enforceInternalState(result);
15253 state.dotAll = true;
15254 state.raw = RegExpWrapper(handleDotAll(pattern), rawFlags);
15256 if (sticky) state.sticky = true;
15257 if (groups.length) state.groups = groups;
15260 if (pattern !== rawPattern) try {
15261 // fails in old engines, but we have no alternatives for unsupported regex syntax
15262 createNonEnumerableProperty(result, 'source', rawPattern === '' ? '(?:)' : rawPattern);
15263 } catch (error) { /* empty */ }
15268 var proxy = function (key) {
15269 key in RegExpWrapper || defineProperty$1(RegExpWrapper, key, {
15270 configurable: true,
15271 get: function () { return NativeRegExp[key]; },
15272 set: function (it) { NativeRegExp[key] = it; }
15276 for (var keys$1 = getOwnPropertyNames$1(NativeRegExp), index$1 = 0; keys$1.length > index$1;) {
15277 proxy(keys$1[index$1++]);
15280 RegExpPrototype$1.constructor = RegExpWrapper;
15281 RegExpWrapper.prototype = RegExpPrototype$1;
15282 redefine$3(global$b, 'RegExp', RegExpWrapper);
15285 // https://tc39.es/ecma262/#sec-get-regexp-@@species
15286 setSpecies('RegExp');
15288 function define (constructor, factory, prototype) {
15289 constructor.prototype = factory.prototype = prototype;
15290 prototype.constructor = constructor;
15292 function extend$3(parent, definition) {
15293 var prototype = Object.create(parent.prototype);
15295 for (var key in definition) {
15296 prototype[key] = definition[key];
15302 function Color() {}
15305 var _brighter = 1 / _darker;
15306 var reI = "\\s*([+-]?\\d+)\\s*",
15307 reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
15308 reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
15309 reHex = /^#([0-9a-f]{3,8})$/,
15310 reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"),
15311 reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"),
15312 reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"),
15313 reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"),
15314 reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"),
15315 reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
15317 aliceblue: 0xf0f8ff,
15318 antiquewhite: 0xfaebd7,
15320 aquamarine: 0x7fffd4,
15325 blanchedalmond: 0xffebcd,
15327 blueviolet: 0x8a2be2,
15329 burlywood: 0xdeb887,
15330 cadetblue: 0x5f9ea0,
15331 chartreuse: 0x7fff00,
15332 chocolate: 0xd2691e,
15334 cornflowerblue: 0x6495ed,
15335 cornsilk: 0xfff8dc,
15338 darkblue: 0x00008b,
15339 darkcyan: 0x008b8b,
15340 darkgoldenrod: 0xb8860b,
15341 darkgray: 0xa9a9a9,
15342 darkgreen: 0x006400,
15343 darkgrey: 0xa9a9a9,
15344 darkkhaki: 0xbdb76b,
15345 darkmagenta: 0x8b008b,
15346 darkolivegreen: 0x556b2f,
15347 darkorange: 0xff8c00,
15348 darkorchid: 0x9932cc,
15350 darksalmon: 0xe9967a,
15351 darkseagreen: 0x8fbc8f,
15352 darkslateblue: 0x483d8b,
15353 darkslategray: 0x2f4f4f,
15354 darkslategrey: 0x2f4f4f,
15355 darkturquoise: 0x00ced1,
15356 darkviolet: 0x9400d3,
15357 deeppink: 0xff1493,
15358 deepskyblue: 0x00bfff,
15361 dodgerblue: 0x1e90ff,
15362 firebrick: 0xb22222,
15363 floralwhite: 0xfffaf0,
15364 forestgreen: 0x228b22,
15366 gainsboro: 0xdcdcdc,
15367 ghostwhite: 0xf8f8ff,
15369 goldenrod: 0xdaa520,
15372 greenyellow: 0xadff2f,
15374 honeydew: 0xf0fff0,
15376 indianred: 0xcd5c5c,
15380 lavender: 0xe6e6fa,
15381 lavenderblush: 0xfff0f5,
15382 lawngreen: 0x7cfc00,
15383 lemonchiffon: 0xfffacd,
15384 lightblue: 0xadd8e6,
15385 lightcoral: 0xf08080,
15386 lightcyan: 0xe0ffff,
15387 lightgoldenrodyellow: 0xfafad2,
15388 lightgray: 0xd3d3d3,
15389 lightgreen: 0x90ee90,
15390 lightgrey: 0xd3d3d3,
15391 lightpink: 0xffb6c1,
15392 lightsalmon: 0xffa07a,
15393 lightseagreen: 0x20b2aa,
15394 lightskyblue: 0x87cefa,
15395 lightslategray: 0x778899,
15396 lightslategrey: 0x778899,
15397 lightsteelblue: 0xb0c4de,
15398 lightyellow: 0xffffe0,
15400 limegreen: 0x32cd32,
15404 mediumaquamarine: 0x66cdaa,
15405 mediumblue: 0x0000cd,
15406 mediumorchid: 0xba55d3,
15407 mediumpurple: 0x9370db,
15408 mediumseagreen: 0x3cb371,
15409 mediumslateblue: 0x7b68ee,
15410 mediumspringgreen: 0x00fa9a,
15411 mediumturquoise: 0x48d1cc,
15412 mediumvioletred: 0xc71585,
15413 midnightblue: 0x191970,
15414 mintcream: 0xf5fffa,
15415 mistyrose: 0xffe4e1,
15416 moccasin: 0xffe4b5,
15417 navajowhite: 0xffdead,
15421 olivedrab: 0x6b8e23,
15423 orangered: 0xff4500,
15425 palegoldenrod: 0xeee8aa,
15426 palegreen: 0x98fb98,
15427 paleturquoise: 0xafeeee,
15428 palevioletred: 0xdb7093,
15429 papayawhip: 0xffefd5,
15430 peachpuff: 0xffdab9,
15434 powderblue: 0xb0e0e6,
15436 rebeccapurple: 0x663399,
15438 rosybrown: 0xbc8f8f,
15439 royalblue: 0x4169e1,
15440 saddlebrown: 0x8b4513,
15442 sandybrown: 0xf4a460,
15443 seagreen: 0x2e8b57,
15444 seashell: 0xfff5ee,
15448 slateblue: 0x6a5acd,
15449 slategray: 0x708090,
15450 slategrey: 0x708090,
15452 springgreen: 0x00ff7f,
15453 steelblue: 0x4682b4,
15458 turquoise: 0x40e0d0,
15462 whitesmoke: 0xf5f5f5,
15464 yellowgreen: 0x9acd32
15466 define(Color, color, {
15467 copy: function copy(channels) {
15468 return Object.assign(new this.constructor(), this, channels);
15470 displayable: function displayable() {
15471 return this.rgb().displayable();
15473 hex: color_formatHex,
15474 // Deprecated! Use color.formatHex.
15475 formatHex: color_formatHex,
15476 formatHsl: color_formatHsl,
15477 formatRgb: color_formatRgb,
15478 toString: color_formatRgb
15481 function color_formatHex() {
15482 return this.rgb().formatHex();
15485 function color_formatHsl() {
15486 return hslConvert(this).formatHsl();
15489 function color_formatRgb() {
15490 return this.rgb().formatRgb();
15493 function color(format) {
15495 format = (format + "").trim().toLowerCase();
15496 return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000
15497 : l === 3 ? new Rgb(m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, (m & 0xf) << 4 | m & 0xf, 1) // #f00
15498 : l === 8 ? rgba(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000
15499 : l === 4 ? rgba(m >> 12 & 0xf | m >> 8 & 0xf0, m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, ((m & 0xf) << 4 | m & 0xf) / 0xff) // #f000
15500 : null // invalid hex
15501 ) : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
15502 : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
15503 : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
15504 : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
15505 : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
15506 : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
15507 : named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins
15508 : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) : null;
15512 return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
15515 function rgba(r, g, b, a) {
15516 if (a <= 0) r = g = b = NaN;
15517 return new Rgb(r, g, b, a);
15520 function rgbConvert(o) {
15521 if (!(o instanceof Color)) o = color(o);
15522 if (!o) return new Rgb();
15524 return new Rgb(o.r, o.g, o.b, o.opacity);
15526 function rgb(r, g, b, opacity) {
15527 return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
15529 function Rgb(r, g, b, opacity) {
15533 this.opacity = +opacity;
15535 define(Rgb, rgb, extend$3(Color, {
15536 brighter: function brighter(k) {
15537 k = k == null ? _brighter : Math.pow(_brighter, k);
15538 return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
15540 darker: function darker(k) {
15541 k = k == null ? _darker : Math.pow(_darker, k);
15542 return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
15544 rgb: function rgb() {
15547 displayable: function displayable() {
15548 return -0.5 <= this.r && this.r < 255.5 && -0.5 <= this.g && this.g < 255.5 && -0.5 <= this.b && this.b < 255.5 && 0 <= this.opacity && this.opacity <= 1;
15550 hex: rgb_formatHex,
15551 // Deprecated! Use color.formatHex.
15552 formatHex: rgb_formatHex,
15553 formatRgb: rgb_formatRgb,
15554 toString: rgb_formatRgb
15557 function rgb_formatHex() {
15558 return "#" + hex$1(this.r) + hex$1(this.g) + hex$1(this.b);
15561 function rgb_formatRgb() {
15562 var a = this.opacity;
15563 a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
15564 return (a === 1 ? "rgb(" : "rgba(") + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + (a === 1 ? ")" : ", " + a + ")");
15567 function hex$1(value) {
15568 value = Math.max(0, Math.min(255, Math.round(value) || 0));
15569 return (value < 16 ? "0" : "") + value.toString(16);
15572 function hsla(h, s, l, a) {
15573 if (a <= 0) h = s = l = NaN;else if (l <= 0 || l >= 1) h = s = NaN;else if (s <= 0) h = NaN;
15574 return new Hsl(h, s, l, a);
15577 function hslConvert(o) {
15578 if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
15579 if (!(o instanceof Color)) o = color(o);
15580 if (!o) return new Hsl();
15581 if (o instanceof Hsl) return o;
15586 min = Math.min(r, g, b),
15587 max = Math.max(r, g, b),
15590 l = (max + min) / 2;
15593 if (r === max) h = (g - b) / s + (g < b) * 6;else if (g === max) h = (b - r) / s + 2;else h = (r - g) / s + 4;
15594 s /= l < 0.5 ? max + min : 2 - max - min;
15597 s = l > 0 && l < 1 ? 0 : h;
15600 return new Hsl(h, s, l, o.opacity);
15602 function hsl(h, s, l, opacity) {
15603 return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
15606 function Hsl(h, s, l, opacity) {
15610 this.opacity = +opacity;
15613 define(Hsl, hsl, extend$3(Color, {
15614 brighter: function brighter(k) {
15615 k = k == null ? _brighter : Math.pow(_brighter, k);
15616 return new Hsl(this.h, this.s, this.l * k, this.opacity);
15618 darker: function darker(k) {
15619 k = k == null ? _darker : Math.pow(_darker, k);
15620 return new Hsl(this.h, this.s, this.l * k, this.opacity);
15622 rgb: function rgb() {
15623 var h = this.h % 360 + (this.h < 0) * 360,
15624 s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
15626 m2 = l + (l < 0.5 ? l : 1 - l) * s,
15628 return new Rgb(hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), hsl2rgb(h, m1, m2), hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), this.opacity);
15630 displayable: function displayable() {
15631 return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && 0 <= this.l && this.l <= 1 && 0 <= this.opacity && this.opacity <= 1;
15633 formatHsl: function formatHsl() {
15634 var a = this.opacity;
15635 a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
15636 return (a === 1 ? "hsl(" : "hsla(") + (this.h || 0) + ", " + (this.s || 0) * 100 + "%, " + (this.l || 0) * 100 + "%" + (a === 1 ? ")" : ", " + a + ")");
15639 /* From FvD 13.37, CSS Color Module Level 3 */
15641 function hsl2rgb(h, m1, m2) {
15642 return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255;
15645 var constant$1 = (function (x) {
15646 return function () {
15651 function linear$2(a, d) {
15652 return function (t) {
15657 function exponential(a, b, y) {
15658 return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function (t) {
15659 return Math.pow(a + t * b, y);
15662 function gamma(y) {
15663 return (y = +y) === 1 ? nogamma : function (a, b) {
15664 return b - a ? exponential(a, b, y) : constant$1(isNaN(a) ? b : a);
15667 function nogamma(a, b) {
15669 return d ? linear$2(a, d) : constant$1(isNaN(a) ? b : a);
15672 var d3_interpolateRgb = (function rgbGamma(y) {
15673 var color = gamma(y);
15675 function rgb$1(start, end) {
15676 var r = color((start = rgb(start)).r, (end = rgb(end)).r),
15677 g = color(start.g, end.g),
15678 b = color(start.b, end.b),
15679 opacity = nogamma(start.opacity, end.opacity);
15680 return function (t) {
15684 start.opacity = opacity(t);
15689 rgb$1.gamma = rgbGamma;
15693 function numberArray (a, b) {
15695 var n = a ? Math.min(b.length, a.length) : 0,
15698 return function (t) {
15699 for (i = 0; i < n; ++i) {
15700 c[i] = a[i] * (1 - t) + b[i] * t;
15706 function isNumberArray(x) {
15707 return ArrayBuffer.isView(x) && !(x instanceof DataView);
15710 function genericArray(a, b) {
15711 var nb = b ? b.length : 0,
15712 na = a ? Math.min(nb, a.length) : 0,
15717 for (i = 0; i < na; ++i) {
15718 x[i] = interpolate$1(a[i], b[i]);
15721 for (; i < nb; ++i) {
15725 return function (t) {
15726 for (i = 0; i < na; ++i) {
15734 function date (a, b) {
15735 var d = new Date();
15736 return a = +a, b = +b, function (t) {
15737 return d.setTime(a * (1 - t) + b * t), d;
15741 function d3_interpolateNumber (a, b) {
15742 return a = +a, b = +b, function (t) {
15743 return a * (1 - t) + b * t;
15747 function object (a, b) {
15751 if (a === null || _typeof(a) !== "object") a = {};
15752 if (b === null || _typeof(b) !== "object") b = {};
15756 i[k] = interpolate$1(a[k], b[k]);
15762 return function (t) {
15771 var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,
15772 reB = new RegExp(reA.source, "g");
15775 return function () {
15781 return function (t) {
15786 function interpolateString (a, b) {
15787 var bi = reA.lastIndex = reB.lastIndex = 0,
15788 // scan index for next number in b
15790 // current match in a
15792 // current match in b
15794 // string preceding current number in b, if any
15798 // string constants and placeholders
15799 q = []; // number interpolators
15800 // Coerce inputs to strings.
15802 a = a + "", b = b + ""; // Interpolate pairs of numbers in a & b.
15804 while ((am = reA.exec(a)) && (bm = reB.exec(b))) {
15805 if ((bs = bm.index) > bi) {
15806 // a string precedes the next number in b
15807 bs = b.slice(bi, bs);
15808 if (s[i]) s[i] += bs; // coalesce with previous string
15812 if ((am = am[0]) === (bm = bm[0])) {
15813 // numbers in a & b match
15814 if (s[i]) s[i] += bm; // coalesce with previous string
15817 // interpolate non-matching numbers
15821 x: d3_interpolateNumber(am, bm)
15825 bi = reB.lastIndex;
15826 } // Add remains of b.
15829 if (bi < b.length) {
15831 if (s[i]) s[i] += bs; // coalesce with previous string
15833 } // Special optimization for only a single match.
15834 // Otherwise, interpolate each of the numbers and rejoin the string.
15837 return s.length < 2 ? q[0] ? one(q[0].x) : zero(b) : (b = q.length, function (t) {
15838 for (var i = 0, o; i < b; ++i) {
15839 s[(o = q[i]).i] = o.x(t);
15846 function interpolate$1 (a, b) {
15847 var t = _typeof(b),
15850 return b == null || t === "boolean" ? constant$1(b) : (t === "number" ? d3_interpolateNumber : t === "string" ? (c = color(b)) ? (b = c, d3_interpolateRgb) : interpolateString : b instanceof color ? d3_interpolateRgb : b instanceof Date ? date : isNumberArray(b) ? numberArray : Array.isArray(b) ? genericArray : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object : d3_interpolateNumber)(a, b);
15853 function interpolateRound (a, b) {
15854 return a = +a, b = +b, function (t) {
15855 return Math.round(a * (1 - t) + b * t);
15859 var degrees = 180 / Math.PI;
15868 function decompose (a, b, c, d, e, f) {
15869 var scaleX, scaleY, skewX;
15870 if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
15871 if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
15872 if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
15873 if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
15877 rotate: Math.atan2(b, a) * degrees,
15878 skewX: Math.atan(skewX) * degrees,
15885 /* eslint-disable no-undef */
15887 function parseCss(value) {
15888 var m = new (typeof DOMMatrix === "function" ? DOMMatrix : WebKitCSSMatrix)(value + "");
15889 return m.isIdentity ? identity$3 : decompose(m.a, m.b, m.c, m.d, m.e, m.f);
15891 function parseSvg(value) {
15892 if (value == null) return identity$3;
15893 if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g");
15894 svgNode.setAttribute("transform", value);
15895 if (!(value = svgNode.transform.baseVal.consolidate())) return identity$3;
15896 value = value.matrix;
15897 return decompose(value.a, value.b, value.c, value.d, value.e, value.f);
15900 function interpolateTransform(parse, pxComma, pxParen, degParen) {
15902 return s.length ? s.pop() + " " : "";
15905 function translate(xa, ya, xb, yb, s, q) {
15906 if (xa !== xb || ya !== yb) {
15907 var i = s.push("translate(", null, pxComma, null, pxParen);
15910 x: d3_interpolateNumber(xa, xb)
15913 x: d3_interpolateNumber(ya, yb)
15915 } else if (xb || yb) {
15916 s.push("translate(" + xb + pxComma + yb + pxParen);
15920 function rotate(a, b, s, q) {
15922 if (a - b > 180) b += 360;else if (b - a > 180) a += 360; // shortest path
15925 i: s.push(pop(s) + "rotate(", null, degParen) - 2,
15926 x: d3_interpolateNumber(a, b)
15929 s.push(pop(s) + "rotate(" + b + degParen);
15933 function skewX(a, b, s, q) {
15936 i: s.push(pop(s) + "skewX(", null, degParen) - 2,
15937 x: d3_interpolateNumber(a, b)
15940 s.push(pop(s) + "skewX(" + b + degParen);
15944 function scale(xa, ya, xb, yb, s, q) {
15945 if (xa !== xb || ya !== yb) {
15946 var i = s.push(pop(s) + "scale(", null, ",", null, ")");
15949 x: d3_interpolateNumber(xa, xb)
15952 x: d3_interpolateNumber(ya, yb)
15954 } else if (xb !== 1 || yb !== 1) {
15955 s.push(pop(s) + "scale(" + xb + "," + yb + ")");
15959 return function (a, b) {
15961 // string constants and placeholders
15962 q = []; // number interpolators
15964 a = parse(a), b = parse(b);
15965 translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
15966 rotate(a.rotate, b.rotate, s, q);
15967 skewX(a.skewX, b.skewX, s, q);
15968 scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
15969 a = b = null; // gc
15971 return function (t) {
15977 s[(o = q[i]).i] = o.x(t);
15985 var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)");
15986 var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")");
15988 var epsilon2 = 1e-12;
15991 return ((x = Math.exp(x)) + 1 / x) / 2;
15995 return ((x = Math.exp(x)) - 1 / x) / 2;
15999 return ((x = Math.exp(2 * x)) - 1) / (x + 1);
16002 var interpolateZoom = (function zoomRho(rho, rho2, rho4) {
16003 // p0 = [ux0, uy0, w0]
16004 // p1 = [ux1, uy1, w1]
16005 function zoom(p0, p1) {
16014 d2 = dx * dx + dy * dy,
16016 S; // Special case for u0 ≅ u1.
16018 if (d2 < epsilon2) {
16019 S = Math.log(w1 / w0) / rho;
16021 i = function i(t) {
16022 return [ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(rho * t * S)];
16026 var d1 = Math.sqrt(d2),
16027 b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),
16028 b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),
16029 r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
16030 r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
16031 S = (r1 - r0) / rho;
16033 i = function i(t) {
16036 u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));
16037 return [ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / cosh(rho * s + r0)];
16041 i.duration = S * 1000 * rho / Math.SQRT2;
16045 zoom.rho = function (_) {
16046 var _1 = Math.max(1e-3, +_),
16050 return zoomRho(_1, _2, _4);
16054 })(Math.SQRT2, 2, 4);
16056 function d3_quantize (interpolator, n) {
16057 var samples = new Array(n);
16059 for (var i = 0; i < n; ++i) {
16060 samples[i] = interpolator(i / (n - 1));
16067 var bind$4 = functionBind;
16069 // `Function.prototype.bind` method
16070 // https://tc39.es/ecma262/#sec-function.prototype.bind
16071 $$t({ target: 'Function', proto: true, forced: Function.bind !== bind$4 }, {
16076 // is an animation frame pending?
16078 // is a timeout pending?
16080 // are any timers active?
16082 // how frequently we check for clock skew
16088 clock = (typeof performance === "undefined" ? "undefined" : _typeof(performance)) === "object" && performance.now ? performance : Date,
16089 setFrame = (typeof window === "undefined" ? "undefined" : _typeof(window)) === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function (f) {
16093 return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
16096 function clearNow() {
16101 this._call = this._time = this._next = null;
16103 Timer.prototype = timer.prototype = {
16104 constructor: Timer,
16105 restart: function restart(callback, delay, time) {
16106 if (typeof callback !== "function") throw new TypeError("callback is not a function");
16107 time = (time == null ? now$1() : +time) + (delay == null ? 0 : +delay);
16109 if (!this._next && taskTail !== this) {
16110 if (taskTail) taskTail._next = this;else taskHead = this;
16114 this._call = callback;
16118 stop: function stop() {
16121 this._time = Infinity;
16126 function timer(callback, delay, time) {
16127 var t = new Timer();
16128 t.restart(callback, delay, time);
16131 function timerFlush() {
16132 now$1(); // Get the current time, if not already set.
16134 ++frame; // Pretend we’ve set an alarm, if we haven’t already.
16140 if ((e = clockNow - t._time) >= 0) t._call.call(null, e);
16148 clockNow = (clockLast = clock.now()) + clockSkew;
16149 frame = timeout = 0;
16161 var now = clock.now(),
16162 delay = now - clockLast;
16163 if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
16174 if (time > t1._time) time = t1._time;
16175 t0 = t1, t1 = t1._next;
16177 t2 = t1._next, t1._next = null;
16178 t1 = t0 ? t0._next = t2 : taskHead = t2;
16186 function sleep(time) {
16187 if (frame) return; // Soonest alarm already set, or will be.
16189 if (timeout) timeout = clearTimeout(timeout);
16190 var delay = time - clockNow; // Strictly less than if we recomputed clockNow.
16193 if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew);
16194 if (interval) interval = clearInterval(interval);
16196 if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay);
16197 frame = 1, setFrame(wake);
16201 function d3_timeout (callback, delay, time) {
16202 var t = new Timer();
16203 delay = delay == null ? 0 : +delay;
16204 t.restart(function (elapsed) {
16206 callback(elapsed + delay);
16211 var emptyOn = dispatch$8("start", "end", "cancel", "interrupt");
16212 var emptyTween = [];
16220 function schedule (node, name, id, index, group, timing) {
16221 var schedules = node.__transition;
16222 if (!schedules) node.__transition = {};else if (id in schedules) return;
16223 create$2(node, id, {
16226 // For context during callback.
16228 // For context during callback.
16232 delay: timing.delay,
16233 duration: timing.duration,
16239 function init(node, id) {
16240 var schedule = get$1(node, id);
16241 if (schedule.state > CREATED) throw new Error("too late; already scheduled");
16244 function set(node, id) {
16245 var schedule = get$1(node, id);
16246 if (schedule.state > STARTED) throw new Error("too late; already running");
16249 function get$1(node, id) {
16250 var schedule = node.__transition;
16251 if (!schedule || !(schedule = schedule[id])) throw new Error("transition not found");
16255 function create$2(node, id, self) {
16256 var schedules = node.__transition,
16257 tween; // Initialize the self timer when the transition is created.
16258 // Note the actual delay is not known until the first callback!
16260 schedules[id] = self;
16261 self.timer = timer(schedule, 0, self.time);
16263 function schedule(elapsed) {
16264 self.state = SCHEDULED;
16265 self.timer.restart(start, self.delay, self.time); // If the elapsed delay is less than our first sleep, start immediately.
16267 if (self.delay <= elapsed) start(elapsed - self.delay);
16270 function start(elapsed) {
16271 var i, j, n, o; // If the state is not SCHEDULED, then we previously errored on start.
16273 if (self.state !== SCHEDULED) return stop();
16275 for (i in schedules) {
16277 if (o.name !== self.name) continue; // While this element already has a starting transition during this frame,
16278 // defer starting an interrupting transition until that transition has a
16279 // chance to tick (and possibly end); see d3/d3-transition#54!
16281 if (o.state === STARTED) return d3_timeout(start); // Interrupt the active transition, if any.
16283 if (o.state === RUNNING) {
16286 o.on.call("interrupt", node, node.__data__, o.index, o.group);
16287 delete schedules[i];
16288 } // Cancel any pre-empted transitions.
16289 else if (+i < id) {
16292 o.on.call("cancel", node, node.__data__, o.index, o.group);
16293 delete schedules[i];
16295 } // Defer the first tick to end of the current frame; see d3/d3#1576.
16296 // Note the transition may be canceled after start and before the first tick!
16297 // Note this must be scheduled before the start event; see d3/d3-transition#16!
16298 // Assuming this is successful, subsequent callbacks go straight to tick.
16301 d3_timeout(function () {
16302 if (self.state === STARTED) {
16303 self.state = RUNNING;
16304 self.timer.restart(tick, self.delay, self.time);
16307 }); // Dispatch the start event.
16308 // Note this must be done before the tween are initialized.
16310 self.state = STARTING;
16311 self.on.call("start", node, node.__data__, self.index, self.group);
16312 if (self.state !== STARTING) return; // interrupted
16314 self.state = STARTED; // Initialize the tween, deleting null tween.
16316 tween = new Array(n = self.tween.length);
16318 for (i = 0, j = -1; i < n; ++i) {
16319 if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {
16324 tween.length = j + 1;
16327 function tick(elapsed) {
16328 var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1),
16333 tween[i].call(node, t);
16334 } // Dispatch the end event.
16337 if (self.state === ENDING) {
16338 self.on.call("end", node, node.__data__, self.index, self.group);
16344 self.state = ENDED;
16346 delete schedules[id];
16348 for (var i in schedules) {
16350 } // eslint-disable-line no-unused-vars
16353 delete node.__transition;
16357 function interrupt (node, name) {
16358 var schedules = node.__transition,
16363 if (!schedules) return;
16364 name = name == null ? null : name + "";
16366 for (i in schedules) {
16367 if ((schedule = schedules[i]).name !== name) {
16372 active = schedule.state > STARTING && schedule.state < ENDING;
16373 schedule.state = ENDED;
16374 schedule.timer.stop();
16375 schedule.on.call(active ? "interrupt" : "cancel", node, node.__data__, schedule.index, schedule.group);
16376 delete schedules[i];
16379 if (empty) delete node.__transition;
16382 function selection_interrupt (name) {
16383 return this.each(function () {
16384 interrupt(this, name);
16388 function tweenRemove(id, name) {
16389 var tween0, tween1;
16390 return function () {
16391 var schedule = set(this, id),
16392 tween = schedule.tween; // If this node shared tween with the previous node,
16393 // just assign the updated shared tween and we’re done!
16394 // Otherwise, copy-on-write.
16396 if (tween !== tween0) {
16397 tween1 = tween0 = tween;
16399 for (var i = 0, n = tween1.length; i < n; ++i) {
16400 if (tween1[i].name === name) {
16401 tween1 = tween1.slice();
16402 tween1.splice(i, 1);
16408 schedule.tween = tween1;
16412 function tweenFunction(id, name, value) {
16413 var tween0, tween1;
16414 if (typeof value !== "function") throw new Error();
16415 return function () {
16416 var schedule = set(this, id),
16417 tween = schedule.tween; // If this node shared tween with the previous node,
16418 // just assign the updated shared tween and we’re done!
16419 // Otherwise, copy-on-write.
16421 if (tween !== tween0) {
16422 tween1 = (tween0 = tween).slice();
16427 }, i = 0, n = tween1.length; i < n; ++i) {
16428 if (tween1[i].name === name) {
16434 if (i === n) tween1.push(t);
16437 schedule.tween = tween1;
16441 function transition_tween (name, value) {
16445 if (arguments.length < 2) {
16446 var tween = get$1(this.node(), id).tween;
16448 for (var i = 0, n = tween.length, t; i < n; ++i) {
16449 if ((t = tween[i]).name === name) {
16457 return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value));
16459 function tweenValue(transition, name, value) {
16460 var id = transition._id;
16461 transition.each(function () {
16462 var schedule = set(this, id);
16463 (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments);
16465 return function (node) {
16466 return get$1(node, id).value[name];
16470 function interpolate (a, b) {
16472 return (typeof b === "number" ? d3_interpolateNumber : b instanceof color ? d3_interpolateRgb : (c = color(b)) ? (b = c, d3_interpolateRgb) : interpolateString)(a, b);
16475 function attrRemove(name) {
16476 return function () {
16477 this.removeAttribute(name);
16481 function attrRemoveNS(fullname) {
16482 return function () {
16483 this.removeAttributeNS(fullname.space, fullname.local);
16487 function attrConstant(name, interpolate, value1) {
16489 string1 = value1 + "",
16491 return function () {
16492 var string0 = this.getAttribute(name);
16493 return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);
16497 function attrConstantNS(fullname, interpolate, value1) {
16499 string1 = value1 + "",
16501 return function () {
16502 var string0 = this.getAttributeNS(fullname.space, fullname.local);
16503 return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);
16507 function attrFunction(name, interpolate, value) {
16508 var string00, string10, interpolate0;
16509 return function () {
16511 value1 = value(this),
16513 if (value1 == null) return void this.removeAttribute(name);
16514 string0 = this.getAttribute(name);
16515 string1 = value1 + "";
16516 return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));
16520 function attrFunctionNS(fullname, interpolate, value) {
16521 var string00, string10, interpolate0;
16522 return function () {
16524 value1 = value(this),
16526 if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);
16527 string0 = this.getAttributeNS(fullname.space, fullname.local);
16528 string1 = value1 + "";
16529 return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));
16533 function transition_attr (name, value) {
16534 var fullname = namespace(name),
16535 i = fullname === "transform" ? interpolateTransformSvg : interpolate;
16536 return this.attrTween(name, typeof value === "function" ? (fullname.local ? attrFunctionNS : attrFunction)(fullname, i, tweenValue(this, "attr." + name, value)) : value == null ? (fullname.local ? attrRemoveNS : attrRemove)(fullname) : (fullname.local ? attrConstantNS : attrConstant)(fullname, i, value));
16539 function attrInterpolate(name, i) {
16540 return function (t) {
16541 this.setAttribute(name, i.call(this, t));
16545 function attrInterpolateNS(fullname, i) {
16546 return function (t) {
16547 this.setAttributeNS(fullname.space, fullname.local, i.call(this, t));
16551 function attrTweenNS(fullname, value) {
16555 var i = value.apply(this, arguments);
16556 if (i !== i0) t0 = (i0 = i) && attrInterpolateNS(fullname, i);
16560 tween._value = value;
16564 function attrTween(name, value) {
16568 var i = value.apply(this, arguments);
16569 if (i !== i0) t0 = (i0 = i) && attrInterpolate(name, i);
16573 tween._value = value;
16577 function transition_attrTween (name, value) {
16578 var key = "attr." + name;
16579 if (arguments.length < 2) return (key = this.tween(key)) && key._value;
16580 if (value == null) return this.tween(key, null);
16581 if (typeof value !== "function") throw new Error();
16582 var fullname = namespace(name);
16583 return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));
16586 function delayFunction(id, value) {
16587 return function () {
16588 init(this, id).delay = +value.apply(this, arguments);
16592 function delayConstant(id, value) {
16593 return value = +value, function () {
16594 init(this, id).delay = value;
16598 function transition_delay (value) {
16600 return arguments.length ? this.each((typeof value === "function" ? delayFunction : delayConstant)(id, value)) : get$1(this.node(), id).delay;
16603 function durationFunction(id, value) {
16604 return function () {
16605 set(this, id).duration = +value.apply(this, arguments);
16609 function durationConstant(id, value) {
16610 return value = +value, function () {
16611 set(this, id).duration = value;
16615 function transition_duration (value) {
16617 return arguments.length ? this.each((typeof value === "function" ? durationFunction : durationConstant)(id, value)) : get$1(this.node(), id).duration;
16620 function easeConstant(id, value) {
16621 if (typeof value !== "function") throw new Error();
16622 return function () {
16623 set(this, id).ease = value;
16627 function transition_ease (value) {
16629 return arguments.length ? this.each(easeConstant(id, value)) : get$1(this.node(), id).ease;
16632 function easeVarying(id, value) {
16633 return function () {
16634 var v = value.apply(this, arguments);
16635 if (typeof v !== "function") throw new Error();
16636 set(this, id).ease = v;
16640 function transition_easeVarying (value) {
16641 if (typeof value !== "function") throw new Error();
16642 return this.each(easeVarying(this._id, value));
16645 function transition_filter (match) {
16646 if (typeof match !== "function") match = matcher(match);
16648 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
16649 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
16650 if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
16651 subgroup.push(node);
16656 return new Transition(subgroups, this._parents, this._name, this._id);
16659 function transition_merge (transition) {
16660 if (transition._id !== this._id) throw new Error();
16662 for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
16663 for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
16664 if (node = group0[i] || group1[i]) {
16670 for (; j < m0; ++j) {
16671 merges[j] = groups0[j];
16674 return new Transition(merges, this._parents, this._name, this._id);
16677 function start(name) {
16678 return (name + "").trim().split(/^|\s+/).every(function (t) {
16679 var i = t.indexOf(".");
16680 if (i >= 0) t = t.slice(0, i);
16681 return !t || t === "start";
16685 function onFunction(id, name, listener) {
16688 sit = start(name) ? init : set;
16689 return function () {
16690 var schedule = sit(this, id),
16691 on = schedule.on; // If this node shared a dispatch with the previous node,
16692 // just assign the updated shared dispatch and we’re done!
16693 // Otherwise, copy-on-write.
16695 if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener);
16700 function transition_on (name, listener) {
16702 return arguments.length < 2 ? get$1(this.node(), id).on.on(name) : this.each(onFunction(id, name, listener));
16705 function removeFunction(id) {
16706 return function () {
16707 var parent = this.parentNode;
16709 for (var i in this.__transition) {
16710 if (+i !== id) return;
16713 if (parent) parent.removeChild(this);
16717 function transition_remove () {
16718 return this.on("end.remove", removeFunction(this._id));
16721 function transition_select (select) {
16722 var name = this._name,
16724 if (typeof select !== "function") select = selector(select);
16726 for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
16727 for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
16728 if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
16729 if ("__data__" in node) subnode.__data__ = node.__data__;
16730 subgroup[i] = subnode;
16731 schedule(subgroup[i], name, id, i, subgroup, get$1(node, id));
16736 return new Transition(subgroups, this._parents, name, id);
16739 function transition_selectAll (select) {
16740 var name = this._name,
16742 if (typeof select !== "function") select = selectorAll(select);
16744 for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
16745 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
16746 if (node = group[i]) {
16747 for (var children = select.call(node, node.__data__, i, group), child, inherit = get$1(node, id), k = 0, l = children.length; k < l; ++k) {
16748 if (child = children[k]) {
16749 schedule(child, name, id, k, children, inherit);
16753 subgroups.push(children);
16754 parents.push(node);
16759 return new Transition(subgroups, parents, name, id);
16762 var Selection = selection.prototype.constructor;
16763 function transition_selection () {
16764 return new Selection(this._groups, this._parents);
16767 function styleNull(name, interpolate) {
16768 var string00, string10, interpolate0;
16769 return function () {
16770 var string0 = styleValue(this, name),
16771 string1 = (this.style.removeProperty(name), styleValue(this, name));
16772 return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : interpolate0 = interpolate(string00 = string0, string10 = string1);
16776 function styleRemove(name) {
16777 return function () {
16778 this.style.removeProperty(name);
16782 function styleConstant(name, interpolate, value1) {
16784 string1 = value1 + "",
16786 return function () {
16787 var string0 = styleValue(this, name);
16788 return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);
16792 function styleFunction(name, interpolate, value) {
16793 var string00, string10, interpolate0;
16794 return function () {
16795 var string0 = styleValue(this, name),
16796 value1 = value(this),
16797 string1 = value1 + "";
16798 if (value1 == null) string1 = value1 = (this.style.removeProperty(name), styleValue(this, name));
16799 return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));
16803 function styleMaybeRemove(id, name) {
16807 key = "style." + name,
16808 event = "end." + key,
16810 return function () {
16811 var schedule = set(this, id),
16813 listener = schedule.value[key] == null ? remove || (remove = styleRemove(name)) : undefined; // If this node shared a dispatch with the previous node,
16814 // just assign the updated shared dispatch and we’re done!
16815 // Otherwise, copy-on-write.
16817 if (on !== on0 || listener0 !== listener) (on1 = (on0 = on).copy()).on(event, listener0 = listener);
16822 function transition_style (name, value, priority) {
16823 var i = (name += "") === "transform" ? interpolateTransformCss : interpolate;
16824 return value == null ? this.styleTween(name, styleNull(name, i)).on("end.style." + name, styleRemove(name)) : typeof value === "function" ? this.styleTween(name, styleFunction(name, i, tweenValue(this, "style." + name, value))).each(styleMaybeRemove(this._id, name)) : this.styleTween(name, styleConstant(name, i, value), priority).on("end.style." + name, null);
16827 function styleInterpolate(name, i, priority) {
16828 return function (t) {
16829 this.style.setProperty(name, i.call(this, t), priority);
16833 function styleTween(name, value, priority) {
16837 var i = value.apply(this, arguments);
16838 if (i !== i0) t = (i0 = i) && styleInterpolate(name, i, priority);
16842 tween._value = value;
16846 function transition_styleTween (name, value, priority) {
16847 var key = "style." + (name += "");
16848 if (arguments.length < 2) return (key = this.tween(key)) && key._value;
16849 if (value == null) return this.tween(key, null);
16850 if (typeof value !== "function") throw new Error();
16851 return this.tween(key, styleTween(name, value, priority == null ? "" : priority));
16854 function textConstant(value) {
16855 return function () {
16856 this.textContent = value;
16860 function textFunction(value) {
16861 return function () {
16862 var value1 = value(this);
16863 this.textContent = value1 == null ? "" : value1;
16867 function transition_text (value) {
16868 return this.tween("text", typeof value === "function" ? textFunction(tweenValue(this, "text", value)) : textConstant(value == null ? "" : value + ""));
16871 function textInterpolate(i) {
16872 return function (t) {
16873 this.textContent = i.call(this, t);
16877 function textTween(value) {
16881 var i = value.apply(this, arguments);
16882 if (i !== i0) t0 = (i0 = i) && textInterpolate(i);
16886 tween._value = value;
16890 function transition_textTween (value) {
16892 if (arguments.length < 1) return (key = this.tween(key)) && key._value;
16893 if (value == null) return this.tween(key, null);
16894 if (typeof value !== "function") throw new Error();
16895 return this.tween(key, textTween(value));
16898 function transition_transition () {
16899 var name = this._name,
16903 for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
16904 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
16905 if (node = group[i]) {
16906 var inherit = get$1(node, id0);
16907 schedule(node, name, id1, i, group, {
16908 time: inherit.time + inherit.delay + inherit.duration,
16910 duration: inherit.duration,
16917 return new Transition(groups, this._parents, name, id1);
16920 function transition_end () {
16925 size = that.size();
16926 return new Promise(function (resolve, reject) {
16931 value: function value() {
16932 if (--size === 0) resolve();
16935 that.each(function () {
16936 var schedule = set(this, id),
16937 on = schedule.on; // If this node shared a dispatch with the previous node,
16938 // just assign the updated shared dispatch and we’re done!
16939 // Otherwise, copy-on-write.
16942 on1 = (on0 = on).copy();
16944 on1._.cancel.push(cancel);
16946 on1._.interrupt.push(cancel);
16948 on1._.end.push(end);
16952 }); // The selection was empty, resolve end immediately
16954 if (size === 0) resolve();
16959 function Transition(groups, parents, name, id) {
16960 this._groups = groups;
16961 this._parents = parents;
16968 var selection_prototype = selection.prototype;
16969 Transition.prototype = _defineProperty({
16970 constructor: Transition,
16971 select: transition_select,
16972 selectAll: transition_selectAll,
16973 filter: transition_filter,
16974 merge: transition_merge,
16975 selection: transition_selection,
16976 transition: transition_transition,
16977 call: selection_prototype.call,
16978 nodes: selection_prototype.nodes,
16979 node: selection_prototype.node,
16980 size: selection_prototype.size,
16981 empty: selection_prototype.empty,
16982 each: selection_prototype.each,
16984 attr: transition_attr,
16985 attrTween: transition_attrTween,
16986 style: transition_style,
16987 styleTween: transition_styleTween,
16988 text: transition_text,
16989 textTween: transition_textTween,
16990 remove: transition_remove,
16991 tween: transition_tween,
16992 delay: transition_delay,
16993 duration: transition_duration,
16994 ease: transition_ease,
16995 easeVarying: transition_easeVarying,
16996 end: transition_end
16997 }, Symbol.iterator, selection_prototype[Symbol.iterator]);
16999 var linear$1 = function linear(t) {
17003 function cubicInOut(t) {
17004 return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
17007 var defaultTiming = {
17015 function inherit(node, id) {
17018 while (!(timing = node.__transition) || !(timing = timing[id])) {
17019 if (!(node = node.parentNode)) {
17020 throw new Error("transition ".concat(id, " not found"));
17027 function selection_transition (name) {
17030 if (name instanceof Transition) {
17031 id = name._id, name = name._name;
17033 id = newId(), (timing = defaultTiming).time = now$1(), name = name == null ? null : name + "";
17036 for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
17037 for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
17038 if (node = group[i]) {
17039 schedule(node, name, id, i, group, timing || inherit(node, id));
17044 return new Transition(groups, this._parents, name, id);
17047 selection.prototype.interrupt = selection_interrupt;
17048 selection.prototype.transition = selection_transition;
17050 var constant = (function (x) {
17051 return function () {
17056 function ZoomEvent(type, _ref) {
17057 var sourceEvent = _ref.sourceEvent,
17058 target = _ref.target,
17059 transform = _ref.transform,
17060 dispatch = _ref.dispatch;
17061 Object.defineProperties(this, {
17068 value: sourceEvent,
17088 function Transform(k, x, y) {
17093 Transform.prototype = {
17094 constructor: Transform,
17095 scale: function scale(k) {
17096 return k === 1 ? this : new Transform(this.k * k, this.x, this.y);
17098 translate: function translate(x, y) {
17099 return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y);
17101 apply: function apply(point) {
17102 return [point[0] * this.k + this.x, point[1] * this.k + this.y];
17104 applyX: function applyX(x) {
17105 return x * this.k + this.x;
17107 applyY: function applyY(y) {
17108 return y * this.k + this.y;
17110 invert: function invert(location) {
17111 return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];
17113 invertX: function invertX(x) {
17114 return (x - this.x) / this.k;
17116 invertY: function invertY(y) {
17117 return (y - this.y) / this.k;
17119 rescaleX: function rescaleX(x) {
17120 return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x));
17122 rescaleY: function rescaleY(y) {
17123 return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y));
17125 toString: function toString() {
17126 return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
17129 var identity$2 = new Transform(1, 0, 0);
17131 function nopropagation(event) {
17132 event.stopImmediatePropagation();
17134 function noevent (event) {
17135 event.preventDefault();
17136 event.stopImmediatePropagation();
17139 // except for pinch-to-zoom, which is sent as a wheel+ctrlKey event
17141 function defaultFilter$1(event) {
17142 return (!event.ctrlKey || event.type === 'wheel') && !event.button;
17145 function defaultExtent$1() {
17148 if (e instanceof SVGElement) {
17149 e = e.ownerSVGElement || e;
17151 if (e.hasAttribute("viewBox")) {
17152 e = e.viewBox.baseVal;
17153 return [[e.x, e.y], [e.x + e.width, e.y + e.height]];
17156 return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]];
17159 return [[0, 0], [e.clientWidth, e.clientHeight]];
17162 function defaultTransform() {
17163 return this.__zoom || identity$2;
17166 function defaultWheelDelta$1(event) {
17167 return -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 0.002) * (event.ctrlKey ? 10 : 1);
17170 function defaultTouchable() {
17171 return navigator.maxTouchPoints || "ontouchstart" in this;
17174 function defaultConstrain$1(transform, extent, translateExtent) {
17175 var dx0 = transform.invertX(extent[0][0]) - translateExtent[0][0],
17176 dx1 = transform.invertX(extent[1][0]) - translateExtent[1][0],
17177 dy0 = transform.invertY(extent[0][1]) - translateExtent[0][1],
17178 dy1 = transform.invertY(extent[1][1]) - translateExtent[1][1];
17179 return transform.translate(dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1));
17182 function d3_zoom () {
17183 var filter = defaultFilter$1,
17184 extent = defaultExtent$1,
17185 constrain = defaultConstrain$1,
17186 wheelDelta = defaultWheelDelta$1,
17187 touchable = defaultTouchable,
17188 scaleExtent = [0, Infinity],
17189 translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]],
17191 interpolate = interpolateZoom,
17192 listeners = dispatch$8("start", "zoom", "end"),
17198 clickDistance2 = 0,
17201 function zoom(selection) {
17202 selection.property("__zoom", defaultTransform).on("wheel.zoom", wheeled).on("mousedown.zoom", mousedowned).on("dblclick.zoom", dblclicked).filter(touchable).on("touchstart.zoom", touchstarted).on("touchmove.zoom", touchmoved).on("touchend.zoom touchcancel.zoom", touchended).style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
17205 zoom.transform = function (collection, transform, point, event) {
17206 var selection = collection.selection ? collection.selection() : collection;
17207 selection.property("__zoom", defaultTransform);
17209 if (collection !== selection) {
17210 schedule(collection, transform, point, event);
17212 selection.interrupt().each(function () {
17213 gesture(this, arguments).event(event).start().zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform).end();
17218 zoom.scaleBy = function (selection, k, p, event) {
17219 zoom.scaleTo(selection, function () {
17220 var k0 = this.__zoom.k,
17221 k1 = typeof k === "function" ? k.apply(this, arguments) : k;
17226 zoom.scaleTo = function (selection, k, p, event) {
17227 zoom.transform(selection, function () {
17228 var e = extent.apply(this, arguments),
17230 p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p,
17231 p1 = t0.invert(p0),
17232 k1 = typeof k === "function" ? k.apply(this, arguments) : k;
17233 return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent);
17237 zoom.translateBy = function (selection, x, y, event) {
17238 zoom.transform(selection, function () {
17239 return constrain(this.__zoom.translate(typeof x === "function" ? x.apply(this, arguments) : x, typeof y === "function" ? y.apply(this, arguments) : y), extent.apply(this, arguments), translateExtent);
17243 zoom.translateTo = function (selection, x, y, p, event) {
17244 zoom.transform(selection, function () {
17245 var e = extent.apply(this, arguments),
17247 p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p;
17248 return constrain(identity$2.translate(p0[0], p0[1]).scale(t.k).translate(typeof x === "function" ? -x.apply(this, arguments) : -x, typeof y === "function" ? -y.apply(this, arguments) : -y), e, translateExtent);
17252 function scale(transform, k) {
17253 k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k));
17254 return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
17257 function translate(transform, p0, p1) {
17258 var x = p0[0] - p1[0] * transform.k,
17259 y = p0[1] - p1[1] * transform.k;
17260 return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
17263 function centroid(extent) {
17264 return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
17267 function schedule(transition, transform, point, event) {
17268 transition.on("start.zoom", function () {
17269 gesture(this, arguments).event(event).start();
17270 }).on("interrupt.zoom end.zoom", function () {
17271 gesture(this, arguments).event(event).end();
17272 }).tween("zoom", function () {
17275 g = gesture(that, args).event(event),
17276 e = extent.apply(that, args),
17277 p = point == null ? centroid(e) : typeof point === "function" ? point.apply(that, args) : point,
17278 w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
17280 b = typeof transform === "function" ? transform.apply(that, args) : transform,
17281 i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
17282 return function (t) {
17283 if (t === 1) t = b; // Avoid rounding error on end.
17287 t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k);
17294 function gesture(that, args, clean) {
17295 return !clean && that.__zooming || new Gesture(that, args);
17298 function Gesture(that, args) {
17302 this.sourceEvent = null;
17303 this.extent = extent.apply(that, args);
17307 Gesture.prototype = {
17308 event: function event(_event) {
17309 if (_event) this.sourceEvent = _event;
17312 start: function start() {
17313 if (++this.active === 1) {
17314 this.that.__zooming = this;
17315 this.emit("start");
17320 zoom: function zoom(key, transform) {
17321 if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]);
17322 if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]);
17323 if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]);
17324 this.that.__zoom = transform;
17328 end: function end() {
17329 if (--this.active === 0) {
17330 delete this.that.__zooming;
17336 emit: function emit(type) {
17337 var d = select(this.that).datum();
17338 listeners.call(type, this.that, new ZoomEvent(type, {
17339 sourceEvent: this.sourceEvent,
17342 transform: this.that.__zoom,
17343 dispatch: listeners
17348 function wheeled(event) {
17349 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
17350 args[_key - 1] = arguments[_key];
17353 if (!filter.apply(this, arguments)) return;
17354 var g = gesture(this, args).event(event),
17356 k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))),
17357 p = pointer(event); // If the mouse is in the same location as before, reuse it.
17358 // If there were recent wheel events, reset the wheel idle timeout.
17361 if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
17362 g.mouse[1] = t.invert(g.mouse[0] = p);
17365 clearTimeout(g.wheel);
17366 } // If this wheel event won’t trigger a transform change, ignore it.
17367 else if (t.k === k) return; // Otherwise, capture the mouse point and location at the start.
17369 g.mouse = [p, t.invert(p)];
17375 g.wheel = setTimeout(wheelidled, wheelDelay);
17376 g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent));
17378 function wheelidled() {
17384 function mousedowned(event) {
17385 for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
17386 args[_key2 - 1] = arguments[_key2];
17389 if (touchending || !filter.apply(this, arguments)) return;
17390 var g = gesture(this, args, true).event(event),
17391 v = select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true),
17392 p = pointer(event, currentTarget),
17393 currentTarget = event.currentTarget,
17394 x0 = event.clientX,
17395 y0 = event.clientY;
17396 dragDisable(event.view);
17397 nopropagation(event);
17398 g.mouse = [p, this.__zoom.invert(p)];
17402 function mousemoved(event) {
17406 var dx = event.clientX - x0,
17407 dy = event.clientY - y0;
17408 g.moved = dx * dx + dy * dy > clickDistance2;
17411 g.event(event).zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = pointer(event, currentTarget), g.mouse[1]), g.extent, translateExtent));
17414 function mouseupped(event) {
17415 v.on("mousemove.zoom mouseup.zoom", null);
17416 yesdrag(event.view, g.moved);
17418 g.event(event).end();
17422 function dblclicked(event) {
17423 for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
17424 args[_key3 - 1] = arguments[_key3];
17427 if (!filter.apply(this, arguments)) return;
17428 var t0 = this.__zoom,
17429 p0 = pointer(event.changedTouches ? event.changedTouches[0] : event, this),
17430 p1 = t0.invert(p0),
17431 k1 = t0.k * (event.shiftKey ? 0.5 : 2),
17432 t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, args), translateExtent);
17434 if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0, event);else select(this).call(zoom.transform, t1, p0, event);
17437 function touchstarted(event) {
17438 for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
17439 args[_key4 - 1] = arguments[_key4];
17442 if (!filter.apply(this, arguments)) return;
17443 var touches = event.touches,
17444 n = touches.length,
17445 g = gesture(this, args, event.changedTouches.length === n).event(event),
17450 nopropagation(event);
17452 for (i = 0; i < n; ++i) {
17453 t = touches[i], p = pointer(t, this);
17454 p = [p, this.__zoom.invert(p), t.identifier];
17455 if (!g.touch0) g.touch0 = p, started = true, g.taps = 1 + !!touchstarting;else if (!g.touch1 && g.touch0[2] !== p[2]) g.touch1 = p, g.taps = 0;
17458 if (touchstarting) touchstarting = clearTimeout(touchstarting);
17461 if (g.taps < 2) touchfirst = p[0], touchstarting = setTimeout(function () {
17462 touchstarting = null;
17469 function touchmoved(event) {
17470 if (!this.__zooming) return;
17472 for (var _len5 = arguments.length, args = new Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {
17473 args[_key5 - 1] = arguments[_key5];
17476 var g = gesture(this, args).event(event),
17477 touches = event.changedTouches,
17478 n = touches.length,
17485 for (i = 0; i < n; ++i) {
17486 t = touches[i], p = pointer(t, this);
17487 if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;
17493 var p0 = g.touch0[0],
17497 dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
17498 dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
17499 t = scale(t, Math.sqrt(dp / dl));
17500 p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
17501 l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
17502 } else if (g.touch0) p = g.touch0[0], l = g.touch0[1];else return;
17504 g.zoom("touch", constrain(translate(t, p, l), g.extent, translateExtent));
17507 function touchended(event) {
17508 for (var _len6 = arguments.length, args = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) {
17509 args[_key6 - 1] = arguments[_key6];
17512 if (!this.__zooming) return;
17513 var g = gesture(this, args).event(event),
17514 touches = event.changedTouches,
17515 n = touches.length,
17518 nopropagation(event);
17519 if (touchending) clearTimeout(touchending);
17520 touchending = setTimeout(function () {
17521 touchending = null;
17524 for (i = 0; i < n; ++i) {
17526 if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;
17529 if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;
17530 if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]);else {
17531 g.end(); // If this was a dbltap, reroute to the (optional) dblclick.zoom handler.
17533 if (g.taps === 2) {
17534 t = pointer(t, this);
17536 if (Math.hypot(touchfirst[0] - t[0], touchfirst[1] - t[1]) < tapDistance) {
17537 var p = select(this).on("dblclick.zoom");
17538 if (p) p.apply(this, arguments);
17544 zoom.wheelDelta = function (_) {
17545 return arguments.length ? (wheelDelta = typeof _ === "function" ? _ : constant(+_), zoom) : wheelDelta;
17548 zoom.filter = function (_) {
17549 return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), zoom) : filter;
17552 zoom.touchable = function (_) {
17553 return arguments.length ? (touchable = typeof _ === "function" ? _ : constant(!!_), zoom) : touchable;
17556 zoom.extent = function (_) {
17557 return arguments.length ? (extent = typeof _ === "function" ? _ : constant([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
17560 zoom.scaleExtent = function (_) {
17561 return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]];
17564 zoom.translateExtent = function (_) {
17565 return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]];
17568 zoom.constrain = function (_) {
17569 return arguments.length ? (constrain = _, zoom) : constrain;
17572 zoom.duration = function (_) {
17573 return arguments.length ? (duration = +_, zoom) : duration;
17576 zoom.interpolate = function (_) {
17577 return arguments.length ? (interpolate = _, zoom) : interpolate;
17580 zoom.on = function () {
17581 var value = listeners.on.apply(listeners, arguments);
17582 return value === listeners ? zoom : value;
17585 zoom.clickDistance = function (_) {
17586 return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2);
17589 zoom.tapDistance = function (_) {
17590 return arguments.length ? (tapDistance = +_, zoom) : tapDistance;
17597 Bypasses features of D3's default projection stream pipeline that are unnecessary:
17598 * Antimeridian clipping
17599 * Spherical rotation
17603 function geoRawMercator() {
17604 var project = mercatorRaw;
17605 var k = 512 / Math.PI; // scale
17608 var y = 0; // translate
17610 var clipExtent = [[0, 0], [0, 0]];
17612 function projection(point) {
17613 point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
17614 return [point[0] * k + x, y - point[1] * k];
17617 projection.invert = function (point) {
17618 point = project.invert((point[0] - x) / k, (y - point[1]) / k);
17619 return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
17622 projection.scale = function (_) {
17623 if (!arguments.length) return k;
17628 projection.translate = function (_) {
17629 if (!arguments.length) return [x, y];
17635 projection.clipExtent = function (_) {
17636 if (!arguments.length) return clipExtent;
17641 projection.transform = function (obj) {
17642 if (!arguments.length) return identity$2.translate(x, y).scale(k);
17649 projection.stream = d3_geoTransform({
17650 point: function point(x, y) {
17651 var vec = projection([x, y]);
17652 this.stream.point(vec[0], vec[1]);
17658 function geoOrthoNormalizedDotProduct(a, b, origin) {
17659 if (geoVecEqual(origin, a) || geoVecEqual(origin, b)) {
17660 return 1; // coincident points, treat as straight and try to remove
17663 return geoVecNormalizedDot(a, b, origin);
17666 function geoOrthoFilterDotProduct(dotp, epsilon, lowerThreshold, upperThreshold, allowStraightAngles) {
17667 var val = Math.abs(dotp);
17669 if (val < epsilon) {
17670 return 0; // already orthogonal
17671 } else if (allowStraightAngles && Math.abs(val - 1) < epsilon) {
17672 return 0; // straight angle, which is okay in this case
17673 } else if (val < lowerThreshold || val > upperThreshold) {
17674 return dotp; // can be adjusted
17676 return null; // ignore vertex
17680 function geoOrthoCalcScore(points, isClosed, epsilon, threshold) {
17682 var first = isClosed ? 0 : 1;
17683 var last = isClosed ? points.length : points.length - 1;
17684 var coords = points.map(function (p) {
17687 var lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180);
17688 var upperThreshold = Math.cos(threshold * Math.PI / 180);
17690 for (var i = first; i < last; i++) {
17691 var a = coords[(i - 1 + coords.length) % coords.length];
17692 var origin = coords[i];
17693 var b = coords[(i + 1) % coords.length];
17694 var dotp = geoOrthoFilterDotProduct(geoOrthoNormalizedDotProduct(a, b, origin), epsilon, lowerThreshold, upperThreshold);
17695 if (dotp === null) continue; // ignore vertex
17697 score = score + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
17701 } // returns the maximum angle less than `lessThan` between the actual corner and a 0° or 90° corner
17703 function geoOrthoMaxOffsetAngle(coords, isClosed, lessThan) {
17704 var max = -Infinity;
17705 var first = isClosed ? 0 : 1;
17706 var last = isClosed ? coords.length : coords.length - 1;
17708 for (var i = first; i < last; i++) {
17709 var a = coords[(i - 1 + coords.length) % coords.length];
17710 var origin = coords[i];
17711 var b = coords[(i + 1) % coords.length];
17712 var normalizedDotP = geoOrthoNormalizedDotProduct(a, b, origin);
17713 var angle = Math.acos(Math.abs(normalizedDotP)) * 180 / Math.PI;
17714 if (angle > 45) angle = 90 - angle;
17715 if (angle >= lessThan) continue;
17716 if (angle > max) max = angle;
17719 if (max === -Infinity) return null;
17721 } // similar to geoOrthoCalcScore, but returns quickly if there is something to do
17723 function geoOrthoCanOrthogonalize(coords, isClosed, epsilon, threshold, allowStraightAngles) {
17725 var first = isClosed ? 0 : 1;
17726 var last = isClosed ? coords.length : coords.length - 1;
17727 var lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180);
17728 var upperThreshold = Math.cos(threshold * Math.PI / 180);
17730 for (var i = first; i < last; i++) {
17731 var a = coords[(i - 1 + coords.length) % coords.length];
17732 var origin = coords[i];
17733 var b = coords[(i + 1) % coords.length];
17734 var dotp = geoOrthoFilterDotProduct(geoOrthoNormalizedDotProduct(a, b, origin), epsilon, lowerThreshold, upperThreshold, allowStraightAngles);
17735 if (dotp === null) continue; // ignore vertex
17737 if (Math.abs(dotp) > 0) return 1; // something to do
17739 score = 0; // already square
17745 var call$2 = functionCall;
17746 var fixRegExpWellKnownSymbolLogic$1 = fixRegexpWellKnownSymbolLogic;
17747 var anObject$1 = anObject$n;
17748 var toLength$3 = toLength$c;
17749 var toString$8 = toString$k;
17750 var requireObjectCoercible$7 = requireObjectCoercible$e;
17751 var getMethod$1 = getMethod$7;
17752 var advanceStringIndex = advanceStringIndex$3;
17753 var regExpExec$1 = regexpExecAbstract;
17756 fixRegExpWellKnownSymbolLogic$1('match', function (MATCH, nativeMatch, maybeCallNative) {
17758 // `String.prototype.match` method
17759 // https://tc39.es/ecma262/#sec-string.prototype.match
17760 function match(regexp) {
17761 var O = requireObjectCoercible$7(this);
17762 var matcher = regexp == undefined ? undefined : getMethod$1(regexp, MATCH);
17763 return matcher ? call$2(matcher, regexp, O) : new RegExp(regexp)[MATCH](toString$8(O));
17765 // `RegExp.prototype[@@match]` method
17766 // https://tc39.es/ecma262/#sec-regexp.prototype-@@match
17767 function (string) {
17768 var rx = anObject$1(this);
17769 var S = toString$8(string);
17770 var res = maybeCallNative(nativeMatch, rx, S);
17772 if (res.done) return res.value;
17774 if (!rx.global) return regExpExec$1(rx, S);
17776 var fullUnicode = rx.unicode;
17781 while ((result = regExpExec$1(rx, S)) !== null) {
17782 var matchStr = toString$8(result[0]);
17784 if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength$3(rx.lastIndex), fullUnicode);
17787 return n === 0 ? null : A;
17793 var FREEZING = freezing;
17794 var fails$9 = fails$V;
17795 var isObject$4 = isObject$s;
17796 var onFreeze = internalMetadata.exports.onFreeze;
17798 // eslint-disable-next-line es/no-object-freeze -- safe
17799 var $freeze = Object.freeze;
17800 var FAILS_ON_PRIMITIVES = fails$9(function () { $freeze(1); });
17802 // `Object.freeze` method
17803 // https://tc39.es/ecma262/#sec-object.freeze
17804 $$s({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES, sham: !FREEZING }, {
17805 freeze: function freeze(it) {
17806 return $freeze && isObject$4(it) ? $freeze(onFreeze(it)) : it;
17810 // Returns true if a and b have the same elements at the same indices.
17811 function utilArrayIdentical(a, b) {
17812 // an array is always identical to itself
17813 if (a === b) return true;
17815 if (i !== b.length) return false;
17818 if (a[i] !== b[i]) return false;
17822 } // http://2ality.com/2015/01/es6-set-operations.html
17823 // Difference (a \ b): create a set that contains those elements of set a that are not in set b.
17824 // This operation is also sometimes called minus (-).
17825 // var a = [1,2,3];
17826 // var b = [4,3,2];
17827 // utilArrayDifference(a, b)
17829 // utilArrayDifference(b, a)
17832 function utilArrayDifference(a, b) {
17833 var other = new Set(b);
17834 return Array.from(new Set(a)).filter(function (v) {
17835 return !other.has(v);
17837 } // Intersection (a ∩ b): create a set that contains those elements of set a that are also in set b.
17838 // var a = [1,2,3];
17839 // var b = [4,3,2];
17840 // utilArrayIntersection(a, b)
17843 function utilArrayIntersection(a, b) {
17844 var other = new Set(b);
17845 return Array.from(new Set(a)).filter(function (v) {
17846 return other.has(v);
17848 } // Union (a ∪ b): create a set that contains the elements of both set a and set b.
17849 // var a = [1,2,3];
17850 // var b = [4,3,2];
17851 // utilArrayUnion(a, b)
17854 function utilArrayUnion(a, b) {
17855 var result = new Set(a);
17856 b.forEach(function (v) {
17859 return Array.from(result);
17860 } // Returns an Array with all the duplicates removed
17861 // var a = [1,1,2,3,3];
17862 // utilArrayUniq(a)
17865 function utilArrayUniq(a) {
17866 return Array.from(new Set(a));
17867 } // Splits array into chunks of given chunk size
17868 // var a = [1,2,3,4,5,6,7];
17869 // utilArrayChunk(a, 3);
17870 // [[1,2,3],[4,5,6],[7]];
17872 function utilArrayChunk(a, chunkSize) {
17873 if (!chunkSize || chunkSize < 0) return [a.slice()];
17874 var result = new Array(Math.ceil(a.length / chunkSize));
17875 return Array.from(result, function (item, i) {
17876 return a.slice(i * chunkSize, i * chunkSize + chunkSize);
17878 } // Flattens two level array into a single level
17879 // var a = [[1,2,3],[4,5,6],[7]];
17880 // utilArrayFlatten(a);
17881 // [1,2,3,4,5,6,7];
17883 function utilArrayFlatten(a) {
17884 return a.reduce(function (acc, val) {
17885 return acc.concat(val);
17887 } // Groups the items of the Array according to the given key
17888 // `key` can be passed as a property or as a key function
17891 // { type: 'Dog', name: 'Spot' },
17892 // { type: 'Cat', name: 'Tiger' },
17893 // { type: 'Dog', name: 'Rover' },
17894 // { type: 'Cat', name: 'Leo' }
17897 // utilArrayGroupBy(pets, 'type')
17899 // 'Dog': [{type: 'Dog', name: 'Spot'}, {type: 'Dog', name: 'Rover'}],
17900 // 'Cat': [{type: 'Cat', name: 'Tiger'}, {type: 'Cat', name: 'Leo'}]
17903 // utilArrayGroupBy(pets, function(item) { return item.name.length; })
17905 // 3: [{type: 'Cat', name: 'Leo'}],
17906 // 4: [{type: 'Dog', name: 'Spot'}],
17907 // 5: [{type: 'Cat', name: 'Tiger'}, {type: 'Dog', name: 'Rover'}]
17910 function utilArrayGroupBy(a, key) {
17911 return a.reduce(function (acc, item) {
17912 var group = typeof key === 'function' ? key(item) : item[key];
17913 (acc[group] = acc[group] || []).push(item);
17916 } // Returns an Array with all the duplicates removed
17917 // where uniqueness determined by the given key
17918 // `key` can be passed as a property or as a key function
17921 // { type: 'Dog', name: 'Spot' },
17922 // { type: 'Cat', name: 'Tiger' },
17923 // { type: 'Dog', name: 'Rover' },
17924 // { type: 'Cat', name: 'Leo' }
17927 // utilArrayUniqBy(pets, 'type')
17929 // { type: 'Dog', name: 'Spot' },
17930 // { type: 'Cat', name: 'Tiger' }
17933 // utilArrayUniqBy(pets, function(item) { return item.name.length; })
17935 // { type: 'Dog', name: 'Spot' },
17936 // { type: 'Cat', name: 'Tiger' },
17937 // { type: 'Cat', name: 'Leo' }
17940 function utilArrayUniqBy(a, key) {
17941 var seen = new Set();
17942 return a.reduce(function (acc, item) {
17943 var val = typeof key === 'function' ? key(item) : item[key];
17945 if (val && !seen.has(val)) {
17954 var uncurryThis$d = functionUncurryThis;
17956 // `thisNumberValue` abstract operation
17957 // https://tc39.es/ecma262/#sec-thisnumbervalue
17958 var thisNumberValue$3 = uncurryThis$d(1.0.valueOf);
17960 var DESCRIPTORS$3 = descriptors;
17961 var global$a = global$1o;
17962 var uncurryThis$c = functionUncurryThis;
17963 var isForced = isForced_1;
17964 var redefine$2 = redefine$h.exports;
17965 var hasOwn$1 = hasOwnProperty_1;
17966 var inheritIfRequired = inheritIfRequired$4;
17967 var isPrototypeOf = objectIsPrototypeOf;
17968 var isSymbol$1 = isSymbol$6;
17969 var toPrimitive$1 = toPrimitive$3;
17970 var fails$8 = fails$V;
17971 var getOwnPropertyNames = objectGetOwnPropertyNames.f;
17972 var getOwnPropertyDescriptor$2 = objectGetOwnPropertyDescriptor.f;
17973 var defineProperty = objectDefineProperty.f;
17974 var thisNumberValue$2 = thisNumberValue$3;
17975 var trim$2 = stringTrim.trim;
17977 var NUMBER = 'Number';
17978 var NativeNumber = global$a[NUMBER];
17979 var NumberPrototype = NativeNumber.prototype;
17980 var TypeError$4 = global$a.TypeError;
17981 var arraySlice$1 = uncurryThis$c(''.slice);
17982 var charCodeAt$1 = uncurryThis$c(''.charCodeAt);
17984 // `ToNumeric` abstract operation
17985 // https://tc39.es/ecma262/#sec-tonumeric
17986 var toNumeric = function (value) {
17987 var primValue = toPrimitive$1(value, 'number');
17988 return typeof primValue == 'bigint' ? primValue : toNumber$1(primValue);
17991 // `ToNumber` abstract operation
17992 // https://tc39.es/ecma262/#sec-tonumber
17993 var toNumber$1 = function (argument) {
17994 var it = toPrimitive$1(argument, 'number');
17995 var first, third, radix, maxCode, digits, length, index, code;
17996 if (isSymbol$1(it)) throw TypeError$4('Cannot convert a Symbol value to a number');
17997 if (typeof it == 'string' && it.length > 2) {
17999 first = charCodeAt$1(it, 0);
18000 if (first === 43 || first === 45) {
18001 third = charCodeAt$1(it, 2);
18002 if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix
18003 } else if (first === 48) {
18004 switch (charCodeAt$1(it, 1)) {
18005 case 66: case 98: radix = 2; maxCode = 49; break; // fast equal of /^0b[01]+$/i
18006 case 79: case 111: radix = 8; maxCode = 55; break; // fast equal of /^0o[0-7]+$/i
18007 default: return +it;
18009 digits = arraySlice$1(it, 2);
18010 length = digits.length;
18011 for (index = 0; index < length; index++) {
18012 code = charCodeAt$1(digits, index);
18013 // parseInt parses a string to a first unavailable symbol
18014 // but ToNumber should return NaN if a string contains unavailable symbols
18015 if (code < 48 || code > maxCode) return NaN;
18016 } return parseInt(digits, radix);
18021 // `Number` constructor
18022 // https://tc39.es/ecma262/#sec-number-constructor
18023 if (isForced(NUMBER, !NativeNumber(' 0o1') || !NativeNumber('0b1') || NativeNumber('+0x1'))) {
18024 var NumberWrapper = function Number(value) {
18025 var n = arguments.length < 1 ? 0 : NativeNumber(toNumeric(value));
18027 // check on 1..constructor(foo) case
18028 return isPrototypeOf(NumberPrototype, dummy) && fails$8(function () { thisNumberValue$2(dummy); })
18029 ? inheritIfRequired(Object(n), dummy, NumberWrapper) : n;
18031 for (var keys = DESCRIPTORS$3 ? getOwnPropertyNames(NativeNumber) : (
18033 'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' +
18034 // ES2015 (in case, if modules with ES2015 Number statics required before):
18035 'EPSILON,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,isFinite,isInteger,isNaN,isSafeInteger,parseFloat,parseInt,' +
18038 ).split(','), j$1 = 0, key; keys.length > j$1; j$1++) {
18039 if (hasOwn$1(NativeNumber, key = keys[j$1]) && !hasOwn$1(NumberWrapper, key)) {
18040 defineProperty(NumberWrapper, key, getOwnPropertyDescriptor$2(NativeNumber, key));
18043 NumberWrapper.prototype = NumberPrototype;
18044 NumberPrototype.constructor = NumberWrapper;
18045 redefine$2(global$a, NUMBER, NumberWrapper);
18048 var diacritics = {};
18050 var remove$6 = diacritics.remove = removeDiacritics;
18051 var replacementList = [{
18059 chars: "\u24B6\uFF21\xC0\xC1\xC2\u1EA6\u1EA4\u1EAA\u1EA8\xC3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\xC4\u01DE\u1EA2\xC5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F"
18065 chars: "\xC6\u01FC\u01E2"
18074 chars: "\uA738\uA73A"
18080 chars: "\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0181"
18083 chars: "\u24B8\uFF23\uA73E\u1E08\u0106C\u0108\u010A\u010C\xC7\u0187\u023B"
18086 chars: "\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018A\u0189\u1D05\uA779"
18092 chars: "\u01F1\u01C4"
18095 chars: "\u01F2\u01C5"
18098 chars: "\u025B\u24BA\uFF25\xC8\xC9\xCA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\xCB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E\u1D07"
18101 chars: "\uA77C\u24BB\uFF26\u1E1E\u0191\uA77B"
18104 chars: "\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E\u0262"
18107 chars: "\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D"
18110 chars: "\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197"
18113 chars: "\u24BF\uFF2A\u0134\u0248\u0237"
18116 chars: "\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2"
18119 chars: "\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780"
18128 chars: "\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C\u03FB"
18131 chars: "\uA7A4\u0220\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u019D\uA790\u1D0E"
18140 chars: "\u24C4\uFF2F\xD2\xD3\xD4\u1ED2\u1ED0\u1ED6\u1ED4\xD5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\xD6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\xD8\u01FE\u0186\u019F\uA74A\uA74C"
18155 chars: "\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754"
18158 chars: "\u24C6\uFF31\uA756\uA758\u024A"
18161 chars: "\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782"
18164 chars: "\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784"
18167 chars: "\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786"
18176 chars: "\u24CA\uFF35\xD9\xDA\xDB\u0168\u1E78\u016A\u1E7A\u016C\xDC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244"
18179 chars: "\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245"
18185 chars: "\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72"
18188 chars: "\u24CD\uFF38\u1E8A\u1E8C"
18191 chars: "\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE"
18194 chars: "\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762"
18197 chars: "\u24D0\uFF41\u1E9A\xE0\xE1\xE2\u1EA7\u1EA5\u1EAB\u1EA9\xE3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\xE4\u01DF\u1EA3\xE5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250\u0251"
18203 chars: "\xE6\u01FD\u01E3"
18212 chars: "\uA739\uA73B"
18218 chars: "\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0182"
18221 chars: "\uFF43\u24D2\u0107\u0109\u010B\u010D\xE7\u1E09\u0188\u023C\uA73F\u2184"
18224 chars: "\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\u018B\u13E7\u0501\uA7AA"
18230 chars: "\u01F3\u01C6"
18233 chars: "\u24D4\uFF45\xE8\xE9\xEA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\xEB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u01DD"
18236 chars: "\u24D5\uFF46\u1E1F\u0192"
18254 chars: "\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\uA77F\u1D79"
18257 chars: "\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265"
18263 chars: "\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131"
18266 chars: "\u24D9\uFF4A\u0135\u01F0\u0249"
18269 chars: "\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3"
18272 chars: "\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u026D"
18278 chars: "\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F"
18281 chars: "\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u043B\u0509"
18287 chars: "\u24DE\uFF4F\xF2\xF3\xF4\u1ED3\u1ED1\u1ED7\u1ED5\xF5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\xF6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\xF8\u01FF\uA74B\uA74D\u0275\u0254\u1D11"
18302 chars: "\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u03C1"
18305 chars: "\u24E0\uFF51\u024B\uA757\uA759"
18308 chars: "\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783"
18311 chars: "\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0282"
18317 chars: "\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787"
18326 chars: "\u24E4\uFF55\xF9\xFA\xFB\u0169\u1E79\u016B\u1E7B\u016D\xFC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289"
18329 chars: "\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C"
18335 chars: "\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73"
18338 chars: "\u24E7\uFF58\u1E8B\u1E8D"
18341 chars: "\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF"
18344 chars: "\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763"
18346 var diacriticsMap = {};
18348 for (var i$1 = 0; i$1 < replacementList.length; i$1 += 1) {
18349 var chars = replacementList[i$1].chars;
18351 for (var j = 0; j < chars.length; j += 1) {
18352 diacriticsMap[chars[j]] = replacementList[i$1].base;
18356 function removeDiacritics(str) {
18357 return str.replace(/[^\u0000-\u007e]/g, function (c) {
18358 return diacriticsMap[c] || c;
18362 diacritics.replacementList = replacementList;
18363 diacritics.diacriticsMap = diacriticsMap;
18367 var isArabic$1 = {};
18369 Object.defineProperty(isArabic$1, "__esModule", {
18372 var arabicBlocks = [[0x0600, 0x06FF], [0x0750, 0x077F], [0x08A0, 0x08FF], [0xFB50, 0xFDFF], [0xFE70, 0xFEFF], [0x10E60, 0x10E7F], [0x1EC70, 0x1ECBF], [0x1EE00, 0x1EEFF] // Mathematical Alphabetic symbols https://www.unicode.org/charts/PDF/U1EE00.pdf
18375 function isArabic(_char) {
18376 if (_char.length > 1) {
18377 // allow the newer chars?
18378 throw new Error('isArabic works on only one-character strings');
18381 var code = _char.charCodeAt(0);
18383 for (var i = 0; i < arabicBlocks.length; i++) {
18384 var block = arabicBlocks[i];
18386 if (code >= block[0] && code <= block[1]) {
18394 isArabic$1.isArabic = isArabic;
18396 function isMath(_char2) {
18397 if (_char2.length > 2) {
18398 // allow the newer chars?
18399 throw new Error('isMath works on only one-character strings');
18402 var code = _char2.charCodeAt(0);
18404 return code >= 0x660 && code <= 0x66C || code >= 0x6F0 && code <= 0x6F9;
18407 isArabic$1.isMath = isMath;
18409 var GlyphSplitter$1 = {};
18411 var reference = {};
18413 var unicodeArabic = {};
18415 Object.defineProperty(unicodeArabic, "__esModule", {
18418 var arabicReference = {
18420 "normal": ["\u0627"],
18422 "normal": ["\u0627\u0653", "\u0622"],
18423 "isolated": "\uFE81",
18427 "normal": ["\u0627\u0654", "\u0623"],
18428 "isolated": "\uFE83",
18432 "normal": ["\u0627\u0655", "\u0625"],
18433 "isolated": "\uFE87",
18437 "normal": "\u0671",
18438 "isolated": "\uFB50",
18441 "wavy_hamza_above": ["\u0672"],
18442 "wavy_hamza_below": ["\u0627\u065F", "\u0673"],
18443 "high_hamza": ["\u0675", "\u0627\u0674"],
18444 "indic_two_above": ["\u0773"],
18445 "indic_three_above": ["\u0774"],
18447 "normal": ["\u0627\u064B"],
18449 "isolated": "\uFD3D"
18451 "isolated": "\uFE8D",
18455 "normal": ["\u0628"],
18456 "dotless": ["\u066E"],
18457 "three_dots_horizontally_below": ["\u0750"],
18458 "dot_below_three_dots_above": ["\u0751"],
18459 "three_dots_pointing_upwards_below": ["\u0752"],
18460 "three_dots_pointing_upwards_below_two_dots_above": ["\u0753"],
18461 "two_dots_below_dot_above": ["\u0754"],
18462 "inverted_small_v_below": ["\u0755"],
18463 "small_v": ["\u0756"],
18464 "small_v_below": ["\u08A0"],
18465 "hamza_above": ["\u08A1"],
18466 "small_meem_above": ["\u08B6"],
18467 "isolated": "\uFE8F",
18469 "initial": "\uFE91",
18473 "normal": ["\u0629"],
18474 "isolated": "\uFE93",
18478 "normal": ["\u062A"],
18479 "ring": ["\u067C"],
18480 "three_dots_above_downwards": ["\u067D"],
18481 "small_teh_above": ["\u08B8"],
18482 "isolated": "\uFE95",
18484 "initial": "\uFE97",
18488 "normal": ["\u062B"],
18489 "isolated": "\uFE99",
18491 "initial": "\uFE9B",
18495 "normal": ["\u062C"],
18496 "two_dots_above": ["\u08A2"],
18497 "isolated": "\uFE9D",
18499 "initial": "\uFE9F",
18503 "normal": ["\u062D"],
18504 "hamza_above": ["\u0681"],
18505 "two_dots_vertical_above": ["\u0682"],
18506 "three_dots_above": ["\u0685"],
18507 "two_dots_above": ["\u0757"],
18508 "three_dots_pointing_upwards_below": ["\u0758"],
18509 "small_tah_below": ["\u076E"],
18510 "small_tah_two_dots": ["\u076F"],
18511 "small_tah_above": ["\u0772"],
18512 "indic_four_below": ["\u077C"],
18513 "isolated": "\uFEA1",
18515 "initial": "\uFEA3",
18519 "normal": ["\u062E"],
18520 "isolated": "\uFEA5",
18522 "initial": "\uFEA7",
18526 "normal": ["\u062F"],
18527 "ring": ["\u0689"],
18528 "dot_below": ["\u068A"],
18529 "dot_below_small_tah": ["\u068B"],
18530 "three_dots_above_downwards": ["\u068F"],
18531 "four_dots_above": ["\u0690"],
18532 "inverted_v": ["\u06EE"],
18533 "two_dots_vertically_below_small_tah": ["\u0759"],
18534 "inverted_small_v_below": ["\u075A"],
18535 "three_dots_below": ["\u08AE"],
18536 "isolated": "\uFEA9",
18540 "normal": ["\u0630"],
18541 "isolated": "\uFEAB",
18545 "normal": ["\u0631"],
18546 "small_v": ["\u0692"],
18547 "ring": ["\u0693"],
18548 "dot_below": ["\u0694"],
18549 "small_v_below": ["\u0695"],
18550 "dot_below_dot_above": ["\u0696"],
18551 "two_dots_above": ["\u0697"],
18552 "four_dots_above": ["\u0699"],
18553 "inverted_v": ["\u06EF"],
18554 "stroke": ["\u075B"],
18555 "two_dots_vertically_above": ["\u076B"],
18556 "hamza_above": ["\u076C"],
18557 "small_tah_two_dots": ["\u0771"],
18558 "loop": ["\u08AA"],
18559 "small_noon_above": ["\u08B9"],
18560 "isolated": "\uFEAD",
18564 "normal": ["\u0632"],
18565 "inverted_v_above": ["\u08B2"],
18566 "isolated": "\uFEAF",
18570 "normal": ["\u0633"],
18571 "dot_below_dot_above": ["\u069A"],
18572 "three_dots_below": ["\u069B"],
18573 "three_dots_below_three_dots_above": ["\u069C"],
18574 "four_dots_above": ["\u075C"],
18575 "two_dots_vertically_above": ["\u076D"],
18576 "small_tah_two_dots": ["\u0770"],
18577 "indic_four_above": ["\u077D"],
18578 "inverted_v": ["\u077E"],
18579 "isolated": "\uFEB1",
18581 "initial": "\uFEB3",
18585 "normal": ["\u0634"],
18586 "dot_below": ["\u06FA"],
18587 "isolated": "\uFEB5",
18589 "initial": "\uFEB7",
18593 "normal": ["\u0635"],
18594 "two_dots_below": ["\u069D"],
18595 "three_dots_above": ["\u069E"],
18596 "three_dots_below": ["\u08AF"],
18597 "isolated": "\uFEB9",
18599 "initial": "\uFEBB",
18603 "normal": ["\u0636"],
18604 "dot_below": ["\u06FB"],
18605 "isolated": "\uFEBD",
18607 "initial": "\uFEBF",
18611 "normal": ["\u0637"],
18612 "three_dots_above": ["\u069F"],
18613 "two_dots_above": ["\u08A3"],
18614 "isolated": "\uFEC1",
18616 "initial": "\uFEC3",
18620 "normal": ["\u0638"],
18621 "isolated": "\uFEC5",
18623 "initial": "\uFEC7",
18627 "normal": ["\u0639"],
18628 "three_dots_above": ["\u06A0"],
18629 "two_dots_above": ["\u075D"],
18630 "three_dots_pointing_downwards_above": ["\u075E"],
18631 "two_dots_vertically_above": ["\u075F"],
18632 "three_dots_below": ["\u08B3"],
18633 "isolated": "\uFEC9",
18635 "initial": "\uFECB",
18639 "normal": ["\u063A"],
18640 "dot_below": ["\u06FC"],
18641 "isolated": "\uFECD",
18643 "initial": "\uFECF",
18647 "normal": ["\u0641"],
18648 "dotless": ["\u06A1"],
18649 "dot_moved_below": ["\u06A2"],
18650 "dot_below": ["\u06A3"],
18651 "three_dots_below": ["\u06A5"],
18652 "two_dots_below": ["\u0760"],
18653 "three_dots_pointing_upwards_below": ["\u0761"],
18654 "dot_below_three_dots_above": ["\u08A4"],
18655 "isolated": "\uFED1",
18657 "initial": "\uFED3",
18661 "normal": ["\u0642"],
18662 "dotless": ["\u066F"],
18663 "dot_above": ["\u06A7"],
18664 "three_dots_above": ["\u06A8"],
18665 "dot_below": ["\u08A5"],
18666 "isolated": "\uFED5",
18668 "initial": "\uFED7",
18672 "normal": ["\u0643"],
18673 "swash": ["\u06AA"],
18674 "ring": ["\u06AB"],
18675 "dot_above": ["\u06AC"],
18676 "three_dots_below": ["\u06AE"],
18677 "two_dots_above": ["\u077F"],
18678 "dot_below": ["\u08B4"],
18679 "isolated": "\uFED9",
18681 "initial": "\uFEDB",
18685 "normal": ["\u0644"],
18686 "small_v": ["\u06B5"],
18687 "dot_above": ["\u06B6"],
18688 "three_dots_above": ["\u06B7"],
18689 "three_dots_below": ["\u06B8"],
18691 "double_bar": ["\u08A6"],
18692 "isolated": "\uFEDD",
18694 "initial": "\uFEDF",
18698 "normal": ["\u0645"],
18699 "dot_above": ["\u0765"],
18700 "dot_below": ["\u0766"],
18701 "three_dots_above": ["\u08A7"],
18702 "isolated": "\uFEE1",
18704 "initial": "\uFEE3",
18708 "normal": ["\u0646"],
18709 "dot_below": ["\u06B9"],
18710 "ring": ["\u06BC"],
18711 "three_dots_above": ["\u06BD"],
18712 "two_dots_below": ["\u0767"],
18713 "small_tah": ["\u0768"],
18714 "small_v": ["\u0769"],
18715 "isolated": "\uFEE5",
18717 "initial": "\uFEE7",
18721 "normal": ["\u0647"],
18722 "isolated": "\uFEE9",
18724 "initial": "\uFEEB",
18728 "normal": ["\u0648"],
18730 "normal": ["\u0624", "\u0648\u0654"],
18731 "isolated": "\uFE85",
18734 "high_hamza": ["\u0676", "\u0648\u0674"],
18735 "ring": ["\u06C4"],
18736 "two_dots_above": ["\u06CA"],
18737 "dot_above": ["\u06CF"],
18738 "indic_two_above": ["\u0778"],
18739 "indic_three_above": ["\u0779"],
18740 "dot_within": ["\u08AB"],
18741 "isolated": "\uFEED",
18745 "normal": ["\u0649"],
18746 "hamza_above": ["\u0626", "\u064A\u0654"],
18747 "initial": "\uFBE8",
18748 "medial": "\uFBE9",
18749 "isolated": "\uFEEF",
18753 "normal": ["\u064A"],
18755 "normal": ["\u0626", "\u0649\u0654"],
18756 "isolated": "\uFE89",
18758 "initial": "\uFE8B",
18761 "two_dots_below_hamza_above": ["\u08A8"],
18762 "high_hamza": ["\u0678", "\u064A\u0674"],
18763 "tail": ["\u06CD"],
18764 "small_v": ["\u06CE"],
18765 "three_dots_below": ["\u06D1"],
18766 "two_dots_below_dot_above": ["\u08A9"],
18767 "two_dots_below_small_noon_above": ["\u08BA"],
18768 "isolated": "\uFEF1",
18770 "initial": "\uFEF3",
18774 "normal": ["\u0679"],
18775 "isolated": "\uFB66",
18777 "initial": "\uFB68",
18781 "normal": ["\u067A"],
18782 "isolated": "\uFB5E",
18784 "initial": "\uFB60",
18788 "normal": ["\u067B"],
18789 "isolated": "\uFB52",
18791 "initial": "\uFB54",
18795 "normal": ["\u067E"],
18796 "small_meem_above": ["\u08B7"],
18797 "isolated": "\uFB56",
18799 "initial": "\uFB58",
18803 "normal": ["\u067F"],
18804 "isolated": "\uFB62",
18806 "initial": "\uFB64",
18810 "normal": ["\u0680"],
18811 "isolated": "\uFB5A",
18813 "initial": "\uFB5C",
18817 "normal": ["\u0683"],
18818 "isolated": "\uFB76",
18820 "initial": "\uFB78",
18824 "normal": ["\u0684"],
18825 "isolated": "\uFB72",
18827 "initial": "\uFB74",
18831 "normal": ["\u0686"],
18832 "dot_above": ["\u06BF"],
18833 "isolated": "\uFB7A",
18835 "initial": "\uFB7C",
18839 "normal": ["\u0687"],
18840 "isolated": "\uFB7E",
18842 "initial": "\uFB80",
18846 "normal": ["\u0688"],
18847 "isolated": "\uFB88",
18851 "normal": ["\u068C"],
18852 "isolated": "\uFB84",
18856 "normal": ["\u068D"],
18857 "isolated": "\uFB82",
18861 "normal": ["\u068F", "\u068E"],
18862 "isolated": "\uFB86",
18866 "normal": ["\u0691"],
18867 "isolated": "\uFB8C",
18871 "normal": ["\u0698"],
18872 "isolated": "\uFB8A",
18876 "normal": ["\u06A4"],
18877 "isolated": "\uFB6A",
18879 "initial": "\uFB6C",
18883 "normal": ["\u06A6"],
18884 "isolated": "\uFB6E",
18886 "initial": "\uFB70",
18890 "normal": ["\u06A9"],
18891 "dot_above": ["\u0762"],
18892 "three_dots_above": ["\u0763"],
18893 "three_dots_pointing_upwards_below": ["\u0764"],
18894 "isolated": "\uFB8E",
18896 "initial": "\uFB90",
18900 "normal": ["\u06AD"],
18901 "isolated": "\uFBD3",
18903 "initial": "\uFBD5",
18907 "normal": ["\u06AF"],
18908 "ring": ["\u06B0"],
18909 "two_dots_below": ["\u06B2"],
18910 "three_dots_above": ["\u06B4"],
18911 "inverted_stroke": ["\u08B0"],
18912 "isolated": "\uFB92",
18914 "initial": "\uFB94",
18918 "normal": ["\u06B1"],
18919 "isolated": "\uFB9A",
18921 "initial": "\uFB9C",
18925 "normal": ["\u06B3"],
18926 "isolated": "\uFB96",
18928 "initial": "\uFB98",
18932 "normal": ["\u06BA"],
18933 "isolated": "\uFB9E",
18937 "normal": ["\u06BB"],
18938 "isolated": "\uFBA0",
18940 "initial": "\uFBA2",
18943 "heh doachashmee": {
18944 "normal": ["\u06BE"],
18945 "isolated": "\uFBAA",
18947 "initial": "\uFBAC",
18951 "normal": ["\u06C1"],
18952 "hamza_above": ["\u06C1\u0654", "\u06C2"],
18953 "isolated": "\uFBA6",
18955 "initial": "\uFBA8",
18958 "teh marbuta goal": {
18959 "normal": ["\u06C3"]
18962 "normal": ["\u06C5"],
18963 "isolated": "\uFBE0",
18967 "normal": ["\u06C6"],
18968 "isolated": "\uFBD9",
18972 "normal": ["\u06C7"],
18974 "normal": ["\u0677", "\u06C7\u0674"],
18975 "isolated": "\uFBDD"
18977 "isolated": "\uFBD7",
18981 "normal": ["\u06C8"],
18982 "isolated": "\uFBDB",
18986 "normal": ["\u06C9"],
18987 "isolated": "\uFBE2",
18991 "normal": ["\u06CB"],
18992 "isolated": "\uFBDE",
18996 "normal": ["\u06CC"],
18997 "indic_two_above": ["\u0775"],
18998 "indic_three_above": ["\u0776"],
18999 "indic_four_above": ["\u0777"],
19000 "isolated": "\uFBFC",
19002 "initial": "\uFBFE",
19006 "normal": ["\u06D0"],
19007 "isolated": "\uFBE4",
19009 "initial": "\uFBE6",
19013 "normal": ["\u06D2"],
19015 "normal": ["\u06D2\u0654", "\u06D3"],
19016 "isolated": "\uFBB0",
19019 "indic_two_above": ["\u077A"],
19020 "indic_three_above": ["\u077B"],
19021 "isolated": "\uFBAE",
19025 "normal": ["\u06D5"],
19026 "isolated": "\u06D5",
19029 "normal": ["\u06C0", "\u06D5\u0654"],
19030 "isolated": "\uFBA4",
19035 "normal": ["\u08AC"]
19038 "normal": ["\u08AD"]
19041 "normal": ["\u08B1"]
19044 "normal": ["\u08BB"]
19047 "normal": ["\u08BC"]
19050 "normal": ["\u08BD"]
19054 unicodeArabic["default"] = arabicReference;
19056 var unicodeLigatures = {};
19058 Object.defineProperty(unicodeLigatures, "__esModule", {
19061 var ligatureReference = {
19063 "isolated": "\uFBEA",
19067 "isolated": "\uFBEC",
19071 "isolated": "\uFBEE",
19075 "isolated": "\uFBF0",
19079 "isolated": "\uFBF2",
19083 "isolated": "\uFBF4",
19087 "isolated": "\uFBF6",
19089 "initial": "\uFBF8"
19092 "uighur_kirghiz": {
19093 "isolated": "\uFBF9",
19095 "initial": "\uFBFB"
19097 "isolated": "\uFC03",
19101 "isolated": "\uFC00",
19102 "initial": "\uFC97"
19105 "isolated": "\uFC01",
19106 "initial": "\uFC98"
19109 "isolated": "\uFC02",
19111 "initial": "\uFC9A",
19115 "isolated": "\uFC04",
19119 "isolated": "\uFC05",
19120 "initial": "\uFC9C"
19123 "isolated": "\uFC06",
19124 "initial": "\uFC9D"
19127 "isolated": "\uFC07",
19128 "initial": "\uFC9E"
19131 "isolated": "\uFC08",
19133 "initial": "\uFC9F",
19137 "isolated": "\uFC09",
19141 "isolated": "\uFC0A",
19145 "isolated": "\uFC0B",
19146 "initial": "\uFCA1"
19149 "isolated": "\uFC0C",
19150 "initial": "\uFCA2"
19153 "isolated": "\uFC0D",
19154 "initial": "\uFCA3"
19157 "isolated": "\uFC0E",
19159 "initial": "\uFCA4",
19163 "isolated": "\uFC0F",
19167 "isolated": "\uFC10",
19171 "isolated": "\uFC11"
19174 "isolated": "\uFC12",
19176 "initial": "\uFCA6",
19180 "isolated": "\uFC13",
19184 "isolated": "\uFC14"
19187 "isolated": "\uFC15",
19188 "initial": "\uFCA7"
19191 "isolated": "\uFC16",
19192 "initial": "\uFCA8"
19195 "isolated": "\uFC17",
19196 "initial": "\uFCA9"
19199 "isolated": "\uFC18",
19200 "initial": "\uFCAA"
19203 "isolated": "\uFC19",
19204 "initial": "\uFCAB"
19207 "isolated": "\uFC1A"
19210 "isolated": "\uFC1B",
19211 "initial": "\uFCAC"
19214 "isolated": "\uFC1C",
19215 "initial": "\uFCAD",
19219 "isolated": "\uFC1D",
19220 "initial": "\uFCAE",
19224 "isolated": "\uFC1E",
19225 "initial": "\uFCAF",
19229 "isolated": "\uFC1F",
19230 "initial": "\uFCB0",
19234 "isolated": "\uFC20",
19235 "initial": "\uFCB1"
19238 "isolated": "\uFC21",
19239 "initial": "\uFCB3"
19242 "isolated": "\uFC22",
19243 "initial": "\uFCB4"
19246 "isolated": "\uFC23",
19247 "initial": "\uFCB5"
19250 "isolated": "\uFC24",
19251 "initial": "\uFCB6"
19254 "isolated": "\uFC25",
19255 "initial": "\uFCB7"
19258 "isolated": "\uFC26",
19259 "initial": "\uFCB8"
19262 "isolated": "\uFC27",
19263 "initial": "\uFD33",
19267 "isolated": "\uFC28",
19268 "initial": "\uFCB9",
19272 "isolated": "\uFC29",
19273 "initial": "\uFCBA"
19276 "isolated": "\uFC2A",
19277 "initial": "\uFCBB"
19280 "isolated": "\uFC2B",
19281 "initial": "\uFCBC"
19284 "isolated": "\uFC2C",
19285 "initial": "\uFCBD"
19288 "isolated": "\uFC2D",
19289 "initial": "\uFCBE"
19292 "isolated": "\uFC2E",
19293 "initial": "\uFCBF"
19296 "isolated": "\uFC2F",
19297 "initial": "\uFCC0"
19300 "isolated": "\uFC30",
19301 "initial": "\uFCC1"
19304 "isolated": "\uFC31",
19308 "isolated": "\uFC32",
19312 "isolated": "\uFC33",
19313 "initial": "\uFCC2"
19316 "isolated": "\uFC34",
19317 "initial": "\uFCC3"
19320 "isolated": "\uFC35",
19324 "isolated": "\uFC36",
19328 "isolated": "\uFC37",
19332 "isolated": "\uFC38",
19333 "initial": "\uFCC4"
19336 "isolated": "\uFC39",
19337 "initial": "\uFCC5"
19340 "isolated": "\uFC3A",
19341 "initial": "\uFCC6"
19344 "isolated": "\uFC3B",
19346 "initial": "\uFCC7",
19350 "isolated": "\uFC3C",
19352 "initial": "\uFCC8",
19356 "isolated": "\uFC3D",
19360 "isolated": "\uFC3E",
19364 "isolated": "\uFC3F",
19365 "initial": "\uFCC9"
19368 "isolated": "\uFC40",
19369 "initial": "\uFCCA"
19372 "isolated": "\uFC41",
19373 "initial": "\uFCCB"
19376 "isolated": "\uFC42",
19378 "initial": "\uFCCC",
19382 "isolated": "\uFC43",
19386 "isolated": "\uFC44",
19390 "isolated": "\uFC45",
19391 "initial": "\uFCCE"
19394 "isolated": "\uFC46",
19395 "initial": "\uFCCF"
19398 "isolated": "\uFC47",
19399 "initial": "\uFCD0"
19402 "isolated": "\uFC48",
19404 "initial": "\uFCD1"
19407 "isolated": "\uFC49"
19410 "isolated": "\uFC4A"
19413 "isolated": "\uFC4B",
19414 "initial": "\uFCD2"
19417 "isolated": "\uFC4C",
19418 "initial": "\uFCD3"
19421 "isolated": "\uFC4D",
19422 "initial": "\uFCD4"
19425 "isolated": "\uFC4E",
19427 "initial": "\uFCD5",
19431 "isolated": "\uFC4F",
19435 "isolated": "\uFC50",
19439 "isolated": "\uFC51",
19440 "initial": "\uFCD7"
19443 "isolated": "\uFC52",
19444 "initial": "\uFCD8"
19447 "isolated": "\uFC53"
19450 "isolated": "\uFC54"
19453 "isolated": "\uFC55",
19454 "initial": "\uFCDA"
19457 "isolated": "\uFC56",
19458 "initial": "\uFCDB"
19461 "isolated": "\uFC57",
19462 "initial": "\uFCDC"
19465 "isolated": "\uFC58",
19467 "initial": "\uFCDD",
19471 "isolated": "\uFC59",
19475 "isolated": "\uFC5A",
19479 "isolated": "\uFC5B"
19482 "isolated": "\uFC5C"
19485 "isolated": "\uFC5D",
19489 "isolated": "\uFC5E"
19492 "isolated": "\uFC5F"
19495 "isolated": "\uFC60"
19498 "isolated": "\uFC61"
19501 "isolated": "\uFC62"
19504 "isolated": "\uFC63"
19567 "initial": "\uFC99"
19570 "initial": "\uFC9B",
19574 "initial": "\uFCA0",
19578 "initial": "\uFCA5",
19582 "initial": "\uFCB2"
19585 "initial": "\uFCCD"
19588 "initial": "\uFCD6",
19592 "initial": "\uFCD9"
19595 "initial": "\uFCDE",
19602 "medial": "\uFCE8",
19603 "initial": "\uFD31"
19606 "medial": "\uFCE9",
19607 "isolated": "\uFD0C",
19609 "initial": "\uFD30"
19612 "medial": "\uFCEA",
19613 "initial": "\uFD32"
19615 "\u0640\u064E\u0651": {
19618 "\u0640\u064F\u0651": {
19621 "\u0640\u0650\u0651": {
19625 "isolated": "\uFCF5",
19629 "isolated": "\uFCF6",
19633 "isolated": "\uFCF7",
19637 "isolated": "\uFCF8",
19641 "isolated": "\uFCF9",
19645 "isolated": "\uFCFA",
19649 "isolated": "\uFCFB"
19652 "isolated": "\uFCFC",
19656 "isolated": "\uFCFD",
19660 "isolated": "\uFCFE",
19664 "isolated": "\uFCFF",
19668 "isolated": "\uFD00",
19672 "isolated": "\uFD01",
19676 "isolated": "\uFD02",
19680 "isolated": "\uFD03",
19684 "isolated": "\uFD04",
19688 "isolated": "\uFD05",
19692 "isolated": "\uFD06",
19696 "isolated": "\uFD07",
19700 "isolated": "\uFD08",
19704 "isolated": "\uFD09",
19706 "initial": "\uFD2D",
19710 "isolated": "\uFD0A",
19712 "initial": "\uFD2E",
19716 "isolated": "\uFD0B",
19718 "initial": "\uFD2F",
19722 "isolated": "\uFD0D",
19726 "isolated": "\uFD0E",
19730 "isolated": "\uFD0F",
19734 "isolated": "\uFD10",
19740 "\u062A\u062C\u0645": {
19741 "initial": "\uFD50"
19743 "\u062A\u062D\u062C": {
19745 "initial": "\uFD52"
19747 "\u062A\u062D\u0645": {
19748 "initial": "\uFD53"
19750 "\u062A\u062E\u0645": {
19751 "initial": "\uFD54"
19753 "\u062A\u0645\u062C": {
19754 "initial": "\uFD55"
19756 "\u062A\u0645\u062D": {
19757 "initial": "\uFD56"
19759 "\u062A\u0645\u062E": {
19760 "initial": "\uFD57"
19762 "\u062C\u0645\u062D": {
19764 "initial": "\uFD59"
19766 "\u062D\u0645\u064A": {
19769 "\u062D\u0645\u0649": {
19772 "\u0633\u062D\u062C": {
19773 "initial": "\uFD5C"
19775 "\u0633\u062C\u062D": {
19776 "initial": "\uFD5D"
19778 "\u0633\u062C\u0649": {
19781 "\u0633\u0645\u062D": {
19783 "initial": "\uFD60"
19785 "\u0633\u0645\u062C": {
19786 "initial": "\uFD61"
19788 "\u0633\u0645\u0645": {
19790 "initial": "\uFD63"
19792 "\u0635\u062D\u062D": {
19794 "initial": "\uFD65"
19796 "\u0635\u0645\u0645": {
19798 "initial": "\uFDC5"
19800 "\u0634\u062D\u0645": {
19802 "initial": "\uFD68"
19804 "\u0634\u062C\u064A": {
19807 "\u0634\u0645\u062E": {
19809 "initial": "\uFD6B"
19811 "\u0634\u0645\u0645": {
19813 "initial": "\uFD6D"
19815 "\u0636\u062D\u0649": {
19818 "\u0636\u062E\u0645": {
19820 "initial": "\uFD70"
19822 "\u0636\u0645\u062D": {
19825 "\u0637\u0645\u062D": {
19826 "initial": "\uFD72"
19828 "\u0637\u0645\u0645": {
19829 "initial": "\uFD73"
19831 "\u0637\u0645\u064A": {
19834 "\u0639\u062C\u0645": {
19836 "initial": "\uFDC4"
19838 "\u0639\u0645\u0645": {
19840 "initial": "\uFD77"
19842 "\u0639\u0645\u0649": {
19845 "\u063A\u0645\u0645": {
19848 "\u063A\u0645\u064A": {
19851 "\u063A\u0645\u0649": {
19854 "\u0641\u062E\u0645": {
19856 "initial": "\uFD7D"
19858 "\u0642\u0645\u062D": {
19860 "initial": "\uFDB4"
19862 "\u0642\u0645\u0645": {
19865 "\u0644\u062D\u0645": {
19867 "initial": "\uFDB5"
19869 "\u0644\u062D\u064A": {
19872 "\u0644\u062D\u0649": {
19875 "\u0644\u062C\u062C": {
19876 "initial": "\uFD83",
19879 "\u0644\u062E\u0645": {
19881 "initial": "\uFD86"
19883 "\u0644\u0645\u062D": {
19885 "initial": "\uFD88"
19887 "\u0645\u062D\u062C": {
19888 "initial": "\uFD89"
19890 "\u0645\u062D\u0645": {
19891 "initial": "\uFD8A"
19893 "\u0645\u062D\u064A": {
19896 "\u0645\u062C\u062D": {
19897 "initial": "\uFD8C"
19899 "\u0645\u062C\u0645": {
19900 "initial": "\uFD8D"
19902 "\u0645\u062E\u062C": {
19903 "initial": "\uFD8E"
19905 "\u0645\u062E\u0645": {
19906 "initial": "\uFD8F"
19908 "\u0645\u062C\u062E": {
19909 "initial": "\uFD92"
19911 "\u0647\u0645\u062C": {
19912 "initial": "\uFD93"
19914 "\u0647\u0645\u0645": {
19915 "initial": "\uFD94"
19917 "\u0646\u062D\u0645": {
19918 "initial": "\uFD95"
19920 "\u0646\u062D\u0649": {
19923 "\u0646\u062C\u0645": {
19925 "initial": "\uFD98"
19927 "\u0646\u062C\u0649": {
19930 "\u0646\u0645\u064A": {
19933 "\u0646\u0645\u0649": {
19936 "\u064A\u0645\u0645": {
19938 "initial": "\uFD9D"
19940 "\u0628\u062E\u064A": {
19943 "\u062A\u062C\u064A": {
19946 "\u062A\u062C\u0649": {
19949 "\u062A\u062E\u064A": {
19952 "\u062A\u062E\u0649": {
19955 "\u062A\u0645\u064A": {
19958 "\u062A\u0645\u0649": {
19961 "\u062C\u0645\u064A": {
19964 "\u062C\u062D\u0649": {
19967 "\u062C\u0645\u0649": {
19970 "\u0633\u062E\u0649": {
19973 "\u0635\u062D\u064A": {
19976 "\u0634\u062D\u064A": {
19979 "\u0636\u062D\u064A": {
19982 "\u0644\u062C\u064A": {
19985 "\u0644\u0645\u064A": {
19988 "\u064A\u062D\u064A": {
19991 "\u064A\u062C\u064A": {
19994 "\u064A\u0645\u064A": {
19997 "\u0645\u0645\u064A": {
20000 "\u0642\u0645\u064A": {
20003 "\u0646\u062D\u064A": {
20006 "\u0639\u0645\u064A": {
20009 "\u0643\u0645\u064A": {
20012 "\u0646\u062C\u062D": {
20013 "initial": "\uFDB8",
20016 "\u0645\u062E\u064A": {
20019 "\u0644\u062C\u0645": {
20020 "initial": "\uFDBA",
20023 "\u0643\u0645\u0645": {
20025 "initial": "\uFDC3"
20027 "\u062C\u062D\u064A": {
20030 "\u062D\u062C\u064A": {
20033 "\u0645\u062C\u064A": {
20036 "\u0641\u0645\u064A": {
20039 "\u0628\u062D\u064A": {
20042 "\u0633\u062E\u064A": {
20045 "\u0646\u062C\u064A": {
20049 "isolated": "\uFEF5",
20053 "isolated": "\uFEF7",
20057 "isolated": "\uFEF9",
20061 "isolated": "\uFEFB",
20065 "\u0635\u0644\u06D2": "\uFDF0",
20066 "\u0642\u0644\u06D2": "\uFDF1",
20067 "\u0627\u0644\u0644\u0647": "\uFDF2",
20068 "\u0627\u0643\u0628\u0631": "\uFDF3",
20069 "\u0645\u062D\u0645\u062F": "\uFDF4",
20070 "\u0635\u0644\u0639\u0645": "\uFDF5",
20071 "\u0631\u0633\u0648\u0644": "\uFDF6",
20072 "\u0639\u0644\u064A\u0647": "\uFDF7",
20073 "\u0648\u0633\u0644\u0645": "\uFDF8",
20074 "\u0635\u0644\u0649": "\uFDF9",
20075 "\u0635\u0644\u0649\u0627\u0644\u0644\u0647\u0639\u0644\u064A\u0647\u0648\u0633\u0644\u0645": "\uFDFA",
20076 "\u062C\u0644\u062C\u0644\u0627\u0644\u0647": "\uFDFB",
20077 "\u0631\u06CC\u0627\u0644": "\uFDFC"
20081 unicodeLigatures["default"] = ligatureReference;
20083 Object.defineProperty(reference, "__esModule", {
20086 var unicode_arabic_1$3 = unicodeArabic;
20087 var unicode_ligatures_1$2 = unicodeLigatures;
20088 var letterList = Object.keys(unicode_arabic_1$3["default"]);
20089 reference.letterList = letterList;
20090 var ligatureList = Object.keys(unicode_ligatures_1$2["default"]);
20091 reference.ligatureList = ligatureList;
20092 var ligatureWordList = Object.keys(unicode_ligatures_1$2["default"].words);
20093 reference.ligatureWordList = ligatureWordList;
20094 var lams = "\u0644\u06B5\u06B6\u06B7\u06B8";
20095 reference.lams = lams;
20096 var alefs = "\u0627\u0622\u0623\u0625\u0671\u0672\u0673\u0675\u0773\u0774";
20097 reference.alefs = alefs; // for (var l = 1; l < lams.length; l++) {
20098 // console.log('-');
20099 // for (var a = 0; a < alefs.length; a++) {
20100 // console.log(a + ': ' + lams[l] + alefs[a]);
20104 var tashkeel = "\u0605\u0640\u0670\u0674\u06DF\u06E7\u06E8";
20105 reference.tashkeel = tashkeel;
20107 function addToTashkeel(start, finish) {
20108 for (var i = start; i <= finish; i++) {
20109 reference.tashkeel = tashkeel += String.fromCharCode(i);
20113 addToTashkeel(0x0610, 0x061A);
20114 addToTashkeel(0x064B, 0x065F);
20115 addToTashkeel(0x06D6, 0x06DC);
20116 addToTashkeel(0x06E0, 0x06E4);
20117 addToTashkeel(0x06EA, 0x06ED);
20118 addToTashkeel(0x08D3, 0x08E1);
20119 addToTashkeel(0x08E3, 0x08FF);
20120 addToTashkeel(0xFE70, 0xFE7F);
20121 var lineBreakers = "\u0627\u0629\u0648\u06C0\u06CF\u06FD\u06FE\u076B\u076C\u0771\u0773\u0774\u0778\u0779\u08E2\u08B1\u08B2\u08B9";
20122 reference.lineBreakers = lineBreakers;
20124 function addToLineBreakers(start, finish) {
20125 for (var i = start; i <= finish; i++) {
20126 reference.lineBreakers = lineBreakers += String.fromCharCode(i);
20130 addToLineBreakers(0x0600, 0x061F); // it's OK to include tashkeel in this range as it is ignored
20132 addToLineBreakers(0x0621, 0x0625);
20133 addToLineBreakers(0x062F, 0x0632);
20134 addToLineBreakers(0x0660, 0x066D); // numerals, math
20136 addToLineBreakers(0x0671, 0x0677);
20137 addToLineBreakers(0x0688, 0x0699);
20138 addToLineBreakers(0x06C3, 0x06CB);
20139 addToLineBreakers(0x06D2, 0x06F9);
20140 addToLineBreakers(0x0759, 0x075B);
20141 addToLineBreakers(0x08AA, 0x08AE);
20142 addToLineBreakers(0xFB50, 0xFDFD); // presentation forms look like they could connect, but never do
20143 // Presentation Forms A includes diacritics but they are meant to stand alone
20145 addToLineBreakers(0xFE80, 0xFEFC); // presentation forms look like they could connect, but never do
20148 addToLineBreakers(0x10E60, 0x10E7F);
20149 addToLineBreakers(0x1EC70, 0x1ECBF);
20150 addToLineBreakers(0x1EE00, 0x1EEFF);
20152 Object.defineProperty(GlyphSplitter$1, "__esModule", {
20155 var isArabic_1$6 = isArabic$1;
20156 var reference_1$5 = reference;
20158 function GlyphSplitter(word) {
20160 var lastLetter = '';
20161 word.split('').forEach(function (letter) {
20162 if (isArabic_1$6.isArabic(letter)) {
20163 if (reference_1$5.tashkeel.indexOf(letter) > -1) {
20164 letters[letters.length - 1] += letter;
20165 } else if (lastLetter.length && (reference_1$5.lams.indexOf(lastLetter) === 0 && reference_1$5.alefs.indexOf(letter) > -1 || reference_1$5.lams.indexOf(lastLetter) > 0 && reference_1$5.alefs.indexOf(letter) === 0)) {
20167 letters[letters.length - 1] += letter;
20169 letters.push(letter);
20172 letters.push(letter);
20175 if (reference_1$5.tashkeel.indexOf(letter) === -1) {
20176 lastLetter = letter;
20182 GlyphSplitter$1.GlyphSplitter = GlyphSplitter;
20184 var BaselineSplitter$1 = {};
20186 Object.defineProperty(BaselineSplitter$1, "__esModule", {
20189 var isArabic_1$5 = isArabic$1;
20190 var reference_1$4 = reference;
20192 function BaselineSplitter(word) {
20194 var lastLetter = '';
20195 word.split('').forEach(function (letter) {
20196 if (isArabic_1$5.isArabic(letter) && isArabic_1$5.isArabic(lastLetter)) {
20197 if (lastLetter.length && reference_1$4.tashkeel.indexOf(letter) > -1) {
20198 letters[letters.length - 1] += letter;
20199 } else if (reference_1$4.lineBreakers.indexOf(lastLetter) > -1) {
20200 letters.push(letter);
20202 letters[letters.length - 1] += letter;
20205 letters.push(letter);
20208 if (reference_1$4.tashkeel.indexOf(letter) === -1) {
20209 // don't allow tashkeel to hide line break
20210 lastLetter = letter;
20216 BaselineSplitter$1.BaselineSplitter = BaselineSplitter;
20218 var Normalization = {};
20220 Object.defineProperty(Normalization, "__esModule", {
20223 var unicode_arabic_1$2 = unicodeArabic;
20224 var unicode_ligatures_1$1 = unicodeLigatures;
20225 var isArabic_1$4 = isArabic$1;
20226 var reference_1$3 = reference;
20228 function Normal(word, breakPresentationForm) {
20229 // default is to turn initial/isolated/medial/final presentation form to generic
20230 if (typeof breakPresentationForm === 'undefined') {
20231 breakPresentationForm = true;
20234 var returnable = '';
20235 word.split('').forEach(function (letter) {
20236 if (!isArabic_1$4.isArabic(letter)) {
20237 returnable += letter;
20241 for (var w = 0; w < reference_1$3.letterList.length; w++) {
20242 // ok so we are checking this potential lettertron
20243 var letterForms = unicode_arabic_1$2["default"][reference_1$3.letterList[w]];
20244 var versions = Object.keys(letterForms);
20246 for (var v = 0; v < versions.length; v++) {
20247 var localVersion = letterForms[versions[v]];
20249 if (_typeof(localVersion) === 'object' && typeof localVersion.indexOf === 'undefined') {
20250 // look at this embedded object
20251 var embeddedForms = Object.keys(localVersion);
20253 for (var ef = 0; ef < embeddedForms.length; ef++) {
20254 var form = localVersion[embeddedForms[ef]];
20256 if (form === letter || _typeof(form) === 'object' && form.indexOf && form.indexOf(letter) > -1) {
20258 // console.log('embedded match');
20259 if (form === letter) {
20261 if (breakPresentationForm && localVersion['normal'] && ['isolated', 'initial', 'medial', 'final'].indexOf(embeddedForms[ef]) > -1) {
20262 // replace presentation form
20263 // console.log('keeping normal form of the letter');
20264 if (_typeof(localVersion['normal']) === 'object') {
20265 returnable += localVersion['normal'][0];
20267 returnable += localVersion['normal'];
20271 } // console.log('keeping this letter');
20274 returnable += letter;
20276 } else if (_typeof(form) === 'object' && form.indexOf && form.indexOf(letter) > -1) {
20278 returnable += form[0]; // console.log('added the first letter from the same array');
20284 } else if (localVersion === letter) {
20286 if (breakPresentationForm && letterForms['normal'] && ['isolated', 'initial', 'medial', 'final'].indexOf(versions[v]) > -1) {
20287 // replace presentation form
20288 // console.log('keeping normal form of the letter');
20289 if (_typeof(letterForms['normal']) === 'object') {
20290 returnable += letterForms['normal'][0];
20292 returnable += letterForms['normal'];
20296 } // console.log('keeping this letter');
20299 returnable += letter;
20301 } else if (_typeof(localVersion) === 'object' && localVersion.indexOf && localVersion.indexOf(letter) > -1) {
20303 returnable += localVersion[0]; // console.log('added the first letter from the same array');
20311 for (var v2 = 0; v2 < reference_1$3.ligatureList.length; v2++) {
20312 var normalForm = reference_1$3.ligatureList[v2];
20314 if (normalForm !== 'words') {
20315 var ligForms = Object.keys(unicode_ligatures_1$1["default"][normalForm]);
20317 for (var f = 0; f < ligForms.length; f++) {
20318 if (unicode_ligatures_1$1["default"][normalForm][ligForms[f]] === letter) {
20319 returnable += normalForm;
20324 } // try words ligatures
20327 for (var v3 = 0; v3 < reference_1$3.ligatureWordList.length; v3++) {
20328 var _normalForm = reference_1$3.ligatureWordList[v3];
20330 if (unicode_ligatures_1$1["default"].words[_normalForm] === letter) {
20331 returnable += _normalForm;
20336 returnable += letter; // console.log('kept the letter')
20341 Normalization.Normal = Normal;
20343 var CharShaper$1 = {};
20345 Object.defineProperty(CharShaper$1, "__esModule", {
20348 var unicode_arabic_1$1 = unicodeArabic;
20349 var isArabic_1$3 = isArabic$1;
20350 var reference_1$2 = reference;
20352 function CharShaper(letter, form) {
20353 if (!isArabic_1$3.isArabic(letter)) {
20355 throw new Error('Not Arabic');
20358 if (letter === "\u0621") {
20363 for (var w = 0; w < reference_1$2.letterList.length; w++) {
20364 // ok so we are checking this potential lettertron
20365 var letterForms = unicode_arabic_1$1["default"][reference_1$2.letterList[w]];
20366 var versions = Object.keys(letterForms);
20368 for (var v = 0; v < versions.length; v++) {
20369 var localVersion = letterForms[versions[v]];
20371 if (localVersion === letter || _typeof(localVersion) === 'object' && localVersion.indexOf && localVersion.indexOf(letter) > -1) {
20372 if (versions.indexOf(form) > -1) {
20373 return letterForms[form];
20375 } else if (_typeof(localVersion) === 'object' && typeof localVersion.indexOf === 'undefined') {
20377 var embeddedVersions = Object.keys(localVersion);
20379 for (var ev = 0; ev < embeddedVersions.length; ev++) {
20380 if (localVersion[embeddedVersions[ev]] === letter || _typeof(localVersion[embeddedVersions[ev]]) === 'object' && localVersion[embeddedVersions[ev]].indexOf && localVersion[embeddedVersions[ev]].indexOf(letter) > -1) {
20381 if (embeddedVersions.indexOf(form) > -1) {
20382 return localVersion[form];
20391 CharShaper$1.CharShaper = CharShaper;
20393 var WordShaper$2 = {};
20395 Object.defineProperty(WordShaper$2, "__esModule", {
20398 var isArabic_1$2 = isArabic$1;
20399 var reference_1$1 = reference;
20400 var CharShaper_1$1 = CharShaper$1;
20401 var unicode_ligatures_1 = unicodeLigatures;
20403 function WordShaper$1(word) {
20404 var state = 'initial';
20407 for (var w = 0; w < word.length; w++) {
20408 var nextLetter = ' ';
20410 for (var nxw = w + 1; nxw < word.length; nxw++) {
20411 if (!isArabic_1$2.isArabic(word[nxw])) {
20415 if (reference_1$1.tashkeel.indexOf(word[nxw]) === -1) {
20416 nextLetter = word[nxw];
20421 if (!isArabic_1$2.isArabic(word[w]) || isArabic_1$2.isMath(word[w])) {
20422 // space or other non-Arabic
20425 } else if (reference_1$1.tashkeel.indexOf(word[w]) > -1) {
20426 // tashkeel - add without changing state
20428 } else if (nextLetter === ' ' // last Arabic letter in this word
20429 || reference_1$1.lineBreakers.indexOf(word[w]) > -1) {
20430 // the current letter is known to break lines
20431 output += CharShaper_1$1.CharShaper(word[w], state === 'initial' ? 'isolated' : 'final');
20433 } else if (reference_1$1.lams.indexOf(word[w]) > -1 && reference_1$1.alefs.indexOf(nextLetter) > -1) {
20434 // LA letters - advance an additional letter after this
20435 output += unicode_ligatures_1["default"][word[w] + nextLetter][state === 'initial' ? 'isolated' : 'final'];
20437 while (word[w] !== nextLetter) {
20443 output += CharShaper_1$1.CharShaper(word[w], state);
20451 WordShaper$2.WordShaper = WordShaper$1;
20453 var ParentLetter$1 = {};
20455 Object.defineProperty(ParentLetter$1, "__esModule", {
20458 var unicode_arabic_1 = unicodeArabic;
20459 var isArabic_1$1 = isArabic$1;
20460 var reference_1 = reference;
20462 function ParentLetter(letter) {
20463 if (!isArabic_1$1.isArabic(letter)) {
20464 throw new Error('Not an Arabic letter');
20467 for (var w = 0; w < reference_1.letterList.length; w++) {
20468 // ok so we are checking this potential lettertron
20469 var letterForms = unicode_arabic_1["default"][reference_1.letterList[w]];
20470 var versions = Object.keys(letterForms);
20472 for (var v = 0; v < versions.length; v++) {
20473 var localVersion = letterForms[versions[v]];
20475 if (_typeof(localVersion) === 'object' && typeof localVersion.indexOf === 'undefined') {
20476 // look at this embedded object
20477 var embeddedForms = Object.keys(localVersion);
20479 for (var ef = 0; ef < embeddedForms.length; ef++) {
20480 var form = localVersion[embeddedForms[ef]];
20482 if (form === letter || _typeof(form) === 'object' && form.indexOf && form.indexOf(letter) > -1) {
20484 return localVersion;
20487 } else if (localVersion === letter || _typeof(localVersion) === 'object' && localVersion.indexOf && localVersion.indexOf(letter) > -1) {
20489 return letterForms;
20497 ParentLetter$1.ParentLetter = ParentLetter;
20499 function GrandparentLetter(letter) {
20500 if (!isArabic_1$1.isArabic(letter)) {
20501 throw new Error('Not an Arabic letter');
20504 for (var w = 0; w < reference_1.letterList.length; w++) {
20505 // ok so we are checking this potential lettertron
20506 var letterForms = unicode_arabic_1["default"][reference_1.letterList[w]];
20507 var versions = Object.keys(letterForms);
20509 for (var v = 0; v < versions.length; v++) {
20510 var localVersion = letterForms[versions[v]];
20512 if (_typeof(localVersion) === 'object' && typeof localVersion.indexOf === 'undefined') {
20513 // look at this embedded object
20514 var embeddedForms = Object.keys(localVersion);
20516 for (var ef = 0; ef < embeddedForms.length; ef++) {
20517 var form = localVersion[embeddedForms[ef]];
20519 if (form === letter || _typeof(form) === 'object' && form.indexOf && form.indexOf(letter) > -1) {
20521 return letterForms;
20524 } else if (localVersion === letter || _typeof(localVersion) === 'object' && localVersion.indexOf && localVersion.indexOf(letter) > -1) {
20526 return letterForms;
20534 ParentLetter$1.GrandparentLetter = GrandparentLetter;
20536 Object.defineProperty(lib, "__esModule", {
20539 var isArabic_1 = isArabic$1;
20540 lib.isArabic = isArabic_1.isArabic;
20541 var GlyphSplitter_1 = GlyphSplitter$1;
20542 lib.GlyphSplitter = GlyphSplitter_1.GlyphSplitter;
20543 var BaselineSplitter_1 = BaselineSplitter$1;
20544 lib.BaselineSplitter = BaselineSplitter_1.BaselineSplitter;
20545 var Normalization_1 = Normalization;
20546 lib.Normal = Normalization_1.Normal;
20547 var CharShaper_1 = CharShaper$1;
20548 lib.CharShaper = CharShaper_1.CharShaper;
20549 var WordShaper_1 = WordShaper$2;
20550 var WordShaper = lib.WordShaper = WordShaper_1.WordShaper;
20551 var ParentLetter_1 = ParentLetter$1;
20552 lib.ParentLetter = ParentLetter_1.ParentLetter;
20553 lib.GrandparentLetter = ParentLetter_1.GrandparentLetter;
20555 var rtlRegex = /[\u0590-\u05FF\u0600-\u06FF\u0750-\u07BF\u08A0–\u08BF]/;
20556 function fixRTLTextForSvg(inputText) {
20559 var arabicRegex = /[\u0600-\u06FF]/g;
20560 var arabicDiacritics = /[\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06ED]/g;
20561 var arabicMath = /[\u0660-\u066C\u06F0-\u06F9]+/g;
20562 var thaanaVowel = /[\u07A6-\u07B0]/;
20563 var hebrewSign = /[\u0591-\u05bd\u05bf\u05c1-\u05c5\u05c7]/; // Arabic word shaping
20565 if (arabicRegex.test(inputText)) {
20566 inputText = WordShaper(inputText);
20569 for (var n = 0; n < inputText.length; n++) {
20570 var c = inputText[n];
20572 if (arabicMath.test(c)) {
20573 // Arabic numbers go LTR
20574 ret += rtlBuffer.reverse().join('');
20577 if (rtlBuffer.length && arabicMath.test(rtlBuffer[rtlBuffer.length - 1])) {
20578 ret += rtlBuffer.reverse().join('');
20582 if ((thaanaVowel.test(c) || hebrewSign.test(c) || arabicDiacritics.test(c)) && rtlBuffer.length) {
20583 rtlBuffer[rtlBuffer.length - 1] += c;
20584 } else if (rtlRegex.test(c) // include Arabic presentation forms
20585 || c.charCodeAt(0) >= 64336 && c.charCodeAt(0) <= 65023 || c.charCodeAt(0) >= 65136 && c.charCodeAt(0) <= 65279) {
20587 } else if (c === ' ' && rtlBuffer.length) {
20588 // whitespace within RTL text
20589 rtlBuffer = [rtlBuffer.reverse().join('') + ' '];
20591 // non-RTL character
20592 ret += rtlBuffer.reverse().join('') + c;
20598 ret += rtlBuffer.reverse().join('');
20602 var DESCRIPTORS$2 = descriptors;
20603 var uncurryThis$b = functionUncurryThis;
20604 var objectKeys = objectKeys$4;
20605 var toIndexedObject = toIndexedObject$d;
20606 var $propertyIsEnumerable = objectPropertyIsEnumerable.f;
20608 var propertyIsEnumerable = uncurryThis$b($propertyIsEnumerable);
20609 var push$2 = uncurryThis$b([].push);
20611 // `Object.{ entries, values }` methods implementation
20612 var createMethod$1 = function (TO_ENTRIES) {
20613 return function (it) {
20614 var O = toIndexedObject(it);
20615 var keys = objectKeys(O);
20616 var length = keys.length;
20620 while (length > i) {
20622 if (!DESCRIPTORS$2 || propertyIsEnumerable(O, key)) {
20623 push$2(result, TO_ENTRIES ? [key, O[key]] : O[key]);
20630 var objectToArray = {
20631 // `Object.entries` method
20632 // https://tc39.es/ecma262/#sec-object.entries
20633 entries: createMethod$1(true),
20634 // `Object.values` method
20635 // https://tc39.es/ecma262/#sec-object.values
20636 values: createMethod$1(false)
20640 var $values = objectToArray.values;
20642 // `Object.values` method
20643 // https://tc39.es/ecma262/#sec-object.values
20644 $$r({ target: 'Object', stat: true }, {
20645 values: function values(O) {
20650 // https://github.com/openstreetmap/iD/issues/772
20651 // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
20655 _storage = localStorage;
20656 } catch (e) {} // eslint-disable-line no-empty
20659 _storage = _storage || function () {
20662 getItem: function getItem(k) {
20665 setItem: function setItem(k, v) {
20668 removeItem: function removeItem(k) {
20669 return delete s[k];
20674 var _listeners = {}; //
20675 // corePreferences is an interface for persisting basic key-value strings
20676 // within and between iD sessions on the same site.
20680 * @param {string} k
20681 * @param {string?} v
20682 * @returns {boolean} true if the action succeeded
20685 function corePreferences(k, v) {
20687 if (v === undefined) return _storage.getItem(k);else if (v === null) _storage.removeItem(k);else _storage.setItem(k, v);
20689 if (_listeners[k]) {
20690 _listeners[k].forEach(function (handler) {
20697 /* eslint-disable no-console */
20698 if (typeof console !== 'undefined') {
20699 console.error('localStorage quota exceeded');
20701 /* eslint-enable no-console */
20706 } // adds an event listener which is triggered whenever
20709 corePreferences.onChange = function (k, handler) {
20710 _listeners[k] = _listeners[k] || [];
20712 _listeners[k].push(handler);
20715 var vparse = {exports: {}};
20717 (function (module) {
20718 (function (window) {
20720 function parseVersion(v) {
20721 var m = v.replace(/[^0-9.]/g, '').match(/[0-9]*\.|[0-9]+/g) || [];
20728 v.isEmpty = !v.major && !v.minor && !v.patch && !v.build;
20729 v.parsed = [v.major, v.minor, v.patch, v.build];
20730 v.text = v.parsed.join('.');
20731 v.compare = compare;
20735 function compare(v) {
20736 if (typeof v === 'string') {
20737 v = parseVersion(v);
20740 for (var i = 0; i < 4; i++) {
20741 if (this.parsed[i] !== v.parsed[i]) {
20742 return this.parsed[i] > v.parsed[i] ? 1 : -1;
20748 /* istanbul ignore next */
20751 if (module && 'object' === 'object') {
20752 module.exports = parseVersion;
20754 window.parseVersion = parseVersion;
20756 })(commonjsGlobal);
20759 var parseVersion = vparse.exports;
20762 var version = "2.20.4";
20763 var description = "A friendly editor for OpenStreetMap";
20764 var main = "dist/iD.min.js";
20765 var repository = "github:openstreetmap/iD";
20766 var homepage = "https://github.com/openstreetmap/iD";
20767 var bugs = "https://github.com/openstreetmap/iD/issues";
20768 var keywords = ["editor","openstreetmap"];
20769 var license = "ISC";
20770 var scripts = {all:"npm-run-all -s clean build build:legacy dist",build:"npm-run-all -s build:css build:data build:dev","build:css":"node scripts/build_css.js","build:data":"shx mkdir -p dist/data && node scripts/build_data.js","build:dev":"rollup --config config/rollup.config.dev.js","build:legacy":"rollup --config config/rollup.config.legacy.js","build:stats":"rollup --config config/rollup.config.stats.js",clean:"shx rm -f dist/*.js dist/*.map dist/*.css dist/img/*.svg",dist:"npm-run-all -p dist:**","dist:mapillary":"shx mkdir -p dist/mapillary-js && shx cp -R node_modules/mapillary-js/dist/* dist/mapillary-js/","dist:pannellum":"shx mkdir -p dist/pannellum-streetside && shx cp -R node_modules/pannellum/build/* dist/pannellum-streetside/","dist:min:iD":"uglifyjs dist/iD.legacy.js --compress --mangle --output dist/iD.min.js","dist:svg:iD":"svg-sprite --symbol --symbol-dest . --shape-id-generator \"iD-%s\" --symbol-sprite dist/img/iD-sprite.svg \"svg/iD-sprite/**/*.svg\"","dist:svg:community":"svg-sprite --symbol --symbol-dest . --shape-id-generator \"community-%s\" --symbol-sprite dist/img/community-sprite.svg node_modules/osm-community-index/dist/img/*.svg","dist:svg:fa":"svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/fa-sprite.svg svg/fontawesome/*.svg","dist:svg:maki":"svg-sprite --symbol --symbol-dest . --shape-id-generator \"maki-%s\" --symbol-sprite dist/img/maki-sprite.svg node_modules/@mapbox/maki/icons/*.svg","dist:svg:mapillary:signs":"svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/mapillary-sprite.svg node_modules/mapillary_sprite_source/package_signs/*.svg","dist:svg:mapillary:objects":"svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/mapillary-object-sprite.svg node_modules/mapillary_sprite_source/package_objects/*.svg","dist:svg:temaki":"svg-sprite --symbol --symbol-dest . --shape-id-generator \"temaki-%s\" --symbol-sprite dist/img/temaki-sprite.svg node_modules/@ideditor/temaki/icons/*.svg",imagery:"node scripts/update_imagery.js",lint:"eslint scripts test/spec modules","lint:fix":"eslint scripts test/spec modules --fix",start:"npm-run-all -s build start:server",quickstart:"npm-run-all -s build:dev start:server","start:server":"node scripts/server.js",test:"npm-run-all -s lint build test:spec","test:spec":"karma start karma.conf.js",translations:"node scripts/update_locales.js"};
20771 var dependencies = {"@ideditor/country-coder":"~5.0.3","@ideditor/location-conflation":"~1.0.2","@mapbox/geojson-area":"^0.2.2","@mapbox/sexagesimal":"1.2.0","@mapbox/vector-tile":"^1.3.1","@tmcw/togeojson":"^4.5.0","@turf/bbox-clip":"^6.0.0","abortcontroller-polyfill":"^1.4.0","aes-js":"^3.1.2","alif-toolkit":"^1.2.9","core-js":"^3.6.5",diacritics:"1.3.0","fast-deep-equal":"~3.1.1","fast-json-stable-stringify":"2.1.0","lodash-es":"~4.17.15",marked:"~2.0.0","node-diff3":"2.1.0","osm-auth":"1.1.0",pannellum:"2.5.6",pbf:"^3.2.1","polygon-clipping":"~0.15.1",rbush:"3.0.1","whatwg-fetch":"^3.4.1","which-polygon":"2.2.0"};
20772 var devDependencies = {"@babel/core":"^7.11.6","@babel/preset-env":"^7.11.5","@fortawesome/fontawesome-svg-core":"^1.2.32","@fortawesome/free-brands-svg-icons":"~5.15.1","@fortawesome/free-regular-svg-icons":"~5.15.1","@fortawesome/free-solid-svg-icons":"~5.15.1","@ideditor/temaki":"~5.0.0","@mapbox/maki":"^6.0.0","@rollup/plugin-babel":"^5.2.1","@rollup/plugin-commonjs":"^21.0.0","@rollup/plugin-json":"^4.0.1","@rollup/plugin-node-resolve":"~13.0.5",autoprefixer:"^10.0.1",btoa:"^1.2.1",chai:"^4.3.4","cldr-core":"37.0.0","cldr-localenames-full":"37.0.0",chalk:"^4.1.2","concat-files":"^0.1.1",d3:"~6.6.0","editor-layer-index":"github:osmlab/editor-layer-index#gh-pages",eslint:"^7.1.0","fetch-mock":"^9.11.0",gaze:"^1.1.3",glob:"^7.1.0",happen:"^0.3.2","js-yaml":"^4.0.0","json-stringify-pretty-compact":"^3.0.0",karma:"^6.3.5","karma-chrome-launcher":"^3.1.0","karma-coverage":"^2.0.3","karma-mocha":"^2.0.1","karma-remap-istanbul":"^0.6.0",mapillary_sprite_source:"^1.8.0","mapillary-js":"4.0.0",minimist:"^1.2.3",mocha:"^8.4.0","name-suggestion-index":"~6.0","node-fetch":"^2.6.1","npm-run-all":"^4.0.0","object-inspect":"1.10.3","osm-community-index":"~5.1.0",postcss:"^8.1.1","postcss-selector-prepend":"^0.5.0",rollup:"~2.52.8","rollup-plugin-includepaths":"~0.2.3","rollup-plugin-progress":"^1.1.1","rollup-plugin-visualizer":"~4.2.0",shelljs:"^0.8.0",shx:"^0.3.0",sinon:"^11.1.2","sinon-chai":"^3.7.0",smash:"0.0","static-server":"^2.2.1","svg-sprite":"1.5.1","uglify-js":"~3.13.0",vparse:"~1.1.0"};
20773 var engines = {node:">=10"};
20774 var browserslist = ["> 0.2%, last 6 major versions, Firefox ESR, IE 11, maintained node versions"];
20775 var packageJSON = {
20778 description: description,
20780 repository: repository,
20781 homepage: homepage,
20783 keywords: keywords,
20786 dependencies: dependencies,
20787 devDependencies: devDependencies,
20789 browserslist: browserslist
20792 var _mainFileFetcher = coreFileFetcher(); // singleton
20793 // coreFileFetcher asynchronously fetches data from JSON files
20796 function coreFileFetcher() {
20797 var ociVersion = packageJSON.devDependencies['osm-community-index'];
20798 var v = parseVersion(ociVersion);
20799 var vMinor = "".concat(v.major, ".").concat(v.minor);
20801 var _inflight = {};
20803 'address_formats': 'data/address_formats.min.json',
20804 'deprecated': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/deprecated.min.json',
20805 'discarded': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/discarded.min.json',
20806 'imagery': 'data/imagery.min.json',
20807 'intro_graph': 'data/intro_graph.min.json',
20808 'keepRight': 'data/keepRight.min.json',
20809 'languages': 'data/languages.min.json',
20810 'locales': 'locales/index.min.json',
20811 'oci_defaults': "https://cdn.jsdelivr.net/npm/osm-community-index@".concat(vMinor, "/dist/defaults.min.json"),
20812 'oci_features': "https://cdn.jsdelivr.net/npm/osm-community-index@".concat(vMinor, "/dist/featureCollection.min.json"),
20813 'oci_resources': "https://cdn.jsdelivr.net/npm/osm-community-index@".concat(vMinor, "/dist/resources.min.json"),
20814 'preset_categories': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/preset_categories.min.json',
20815 'preset_defaults': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/preset_defaults.min.json',
20816 'preset_fields': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/fields.min.json',
20817 'preset_presets': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/presets.min.json',
20818 'phone_formats': 'data/phone_formats.min.json',
20819 'qa_data': 'data/qa_data.min.json',
20820 'shortcuts': 'data/shortcuts.min.json',
20821 'territory_languages': 'data/territory_languages.min.json',
20822 'wmf_sitematrix': 'https://cdn.jsdelivr.net/npm/wmf-sitematrix@0.1/wikipedia.min.json'
20824 var _cachedData = {}; // expose the cache; useful for tests
20826 _this.cache = function () {
20827 return _cachedData;
20828 }; // Returns a Promise to fetch data
20829 // (resolved with the data if we have it already)
20832 _this.get = function (which) {
20833 if (_cachedData[which]) {
20834 return Promise.resolve(_cachedData[which]);
20837 var file = _fileMap[which];
20839 var url = file && _this.asset(file);
20842 return Promise.reject("Unknown data file for \"".concat(which, "\""));
20845 var prom = _inflight[url];
20848 _inflight[url] = prom = fetch(url).then(function (response) {
20849 // fetch in PhantomJS tests may return ok=false and status=0 even if it's okay
20850 if (!response.ok && response.status !== 0 || !response.json) {
20851 throw new Error(response.status + ' ' + response.statusText);
20854 if (response.status === 204 || response.status === 205) return; // No Content, Reset Content
20856 return response.json();
20857 }).then(function (result) {
20858 delete _inflight[url];
20861 throw new Error("No data loaded for \"".concat(which, "\""));
20864 _cachedData[which] = result;
20866 })["catch"](function (err) {
20867 delete _inflight[url];
20873 }; // Accessor for the file map
20876 _this.fileMap = function (val) {
20877 if (!arguments.length) return _fileMap;
20882 var _assetPath = '';
20884 _this.assetPath = function (val) {
20885 if (!arguments.length) return _assetPath;
20890 var _assetMap = {};
20892 _this.assetMap = function (val) {
20893 if (!arguments.length) return _assetMap;
20898 _this.asset = function (val) {
20899 if (/^http(s)?:\/\//i.test(val)) return val;
20900 var filename = _assetPath + val;
20901 return _assetMap[filename] || filename;
20907 var global$9 = global$1o;
20908 var toIntegerOrInfinity$1 = toIntegerOrInfinity$b;
20909 var toString$7 = toString$k;
20910 var requireObjectCoercible$6 = requireObjectCoercible$e;
20912 var RangeError$5 = global$9.RangeError;
20914 // `String.prototype.repeat` method implementation
20915 // https://tc39.es/ecma262/#sec-string.prototype.repeat
20916 var stringRepeat = function repeat(count) {
20917 var str = toString$7(requireObjectCoercible$6(this));
20919 var n = toIntegerOrInfinity$1(count);
20920 if (n < 0 || n == Infinity) throw RangeError$5('Wrong number of repetitions');
20921 for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) result += str;
20926 var global$8 = global$1o;
20927 var uncurryThis$a = functionUncurryThis;
20928 var toIntegerOrInfinity = toIntegerOrInfinity$b;
20929 var thisNumberValue$1 = thisNumberValue$3;
20930 var $repeat$1 = stringRepeat;
20931 var fails$7 = fails$V;
20933 var RangeError$4 = global$8.RangeError;
20934 var String$1 = global$8.String;
20935 var floor$2 = Math.floor;
20936 var repeat$2 = uncurryThis$a($repeat$1);
20937 var stringSlice$3 = uncurryThis$a(''.slice);
20938 var un$ToFixed = uncurryThis$a(1.0.toFixed);
20940 var pow$1 = function (x, n, acc) {
20941 return n === 0 ? acc : n % 2 === 1 ? pow$1(x, n - 1, acc * x) : pow$1(x * x, n / 2, acc);
20944 var log = function (x) {
20947 while (x2 >= 4096) {
20957 var multiply = function (data, n, c) {
20960 while (++index < 6) {
20961 c2 += n * data[index];
20962 data[index] = c2 % 1e7;
20963 c2 = floor$2(c2 / 1e7);
20967 var divide = function (data, n) {
20970 while (--index >= 0) {
20972 data[index] = floor$2(c / n);
20977 var dataToString = function (data) {
20980 while (--index >= 0) {
20981 if (s !== '' || index === 0 || data[index] !== 0) {
20982 var t = String$1(data[index]);
20983 s = s === '' ? t : s + repeat$2('0', 7 - t.length) + t;
20988 var FORCED$6 = fails$7(function () {
20989 return un$ToFixed(0.00008, 3) !== '0.000' ||
20990 un$ToFixed(0.9, 0) !== '1' ||
20991 un$ToFixed(1.255, 2) !== '1.25' ||
20992 un$ToFixed(1000000000000000128.0, 0) !== '1000000000000000128';
20993 }) || !fails$7(function () {
20994 // V8 ~ Android 4.3-
20998 // `Number.prototype.toFixed` method
20999 // https://tc39.es/ecma262/#sec-number.prototype.tofixed
21000 $$q({ target: 'Number', proto: true, forced: FORCED$6 }, {
21001 toFixed: function toFixed(fractionDigits) {
21002 var number = thisNumberValue$1(this);
21003 var fractDigits = toIntegerOrInfinity(fractionDigits);
21004 var data = [0, 0, 0, 0, 0, 0];
21009 // TODO: ES2018 increased the maximum number of fraction digits to 100, need to improve the implementation
21010 if (fractDigits < 0 || fractDigits > 20) throw RangeError$4('Incorrect fraction digits');
21011 // eslint-disable-next-line no-self-compare -- NaN check
21012 if (number != number) return 'NaN';
21013 if (number <= -1e21 || number >= 1e21) return String$1(number);
21018 if (number > 1e-21) {
21019 e = log(number * pow$1(2, 69, 1)) - 69;
21020 z = e < 0 ? number * pow$1(2, -e, 1) : number / pow$1(2, e, 1);
21021 z *= 0x10000000000000;
21024 multiply(data, 0, z);
21027 multiply(data, 1e7, 0);
21030 multiply(data, pow$1(10, j, 1), 0);
21033 divide(data, 1 << 23);
21036 divide(data, 1 << j);
21037 multiply(data, 1, 1);
21039 result = dataToString(data);
21041 multiply(data, 0, z);
21042 multiply(data, 1 << -e, 0);
21043 result = dataToString(data) + repeat$2('0', fractDigits);
21046 if (fractDigits > 0) {
21048 result = sign + (k <= fractDigits
21049 ? '0.' + repeat$2('0', fractDigits - k) + result
21050 : stringSlice$3(result, 0, k - fractDigits) + '.' + stringSlice$3(result, k - fractDigits));
21052 result = sign + result;
21057 var global$7 = global$1o;
21059 var globalIsFinite = global$7.isFinite;
21061 // `Number.isFinite` method
21062 // https://tc39.es/ecma262/#sec-number.isfinite
21063 // eslint-disable-next-line es/no-number-isfinite -- safe
21064 var numberIsFinite$1 = Number.isFinite || function isFinite(it) {
21065 return typeof it == 'number' && globalIsFinite(it);
21069 var numberIsFinite = numberIsFinite$1;
21071 // `Number.isFinite` method
21072 // https://tc39.es/ecma262/#sec-number.isfinite
21073 $$p({ target: 'Number', stat: true }, { isFinite: numberIsFinite });
21076 var global$6 = global$1o;
21077 var uncurryThis$9 = functionUncurryThis;
21078 var toAbsoluteIndex = toAbsoluteIndex$9;
21080 var RangeError$3 = global$6.RangeError;
21081 var fromCharCode$1 = String.fromCharCode;
21082 // eslint-disable-next-line es/no-string-fromcodepoint -- required for testing
21083 var $fromCodePoint = String.fromCodePoint;
21084 var join$2 = uncurryThis$9([].join);
21086 // length should be 1, old FF problem
21087 var INCORRECT_LENGTH = !!$fromCodePoint && $fromCodePoint.length != 1;
21089 // `String.fromCodePoint` method
21090 // https://tc39.es/ecma262/#sec-string.fromcodepoint
21091 $$o({ target: 'String', stat: true, forced: INCORRECT_LENGTH }, {
21092 // eslint-disable-next-line no-unused-vars -- required for `.length`
21093 fromCodePoint: function fromCodePoint(x) {
21095 var length = arguments.length;
21098 while (length > i) {
21099 code = +arguments[i++];
21100 if (toAbsoluteIndex(code, 0x10FFFF) !== code) throw RangeError$3(code + ' is not a valid code point');
21101 elements[i] = code < 0x10000
21102 ? fromCharCode$1(code)
21103 : fromCharCode$1(((code -= 0x10000) >> 10) + 0xD800, code % 0x400 + 0xDC00);
21104 } return join$2(elements, '');
21108 var call$1 = functionCall;
21109 var fixRegExpWellKnownSymbolLogic = fixRegexpWellKnownSymbolLogic;
21110 var anObject = anObject$n;
21111 var requireObjectCoercible$5 = requireObjectCoercible$e;
21112 var sameValue = sameValue$1;
21113 var toString$6 = toString$k;
21114 var getMethod = getMethod$7;
21115 var regExpExec = regexpExecAbstract;
21118 fixRegExpWellKnownSymbolLogic('search', function (SEARCH, nativeSearch, maybeCallNative) {
21120 // `String.prototype.search` method
21121 // https://tc39.es/ecma262/#sec-string.prototype.search
21122 function search(regexp) {
21123 var O = requireObjectCoercible$5(this);
21124 var searcher = regexp == undefined ? undefined : getMethod(regexp, SEARCH);
21125 return searcher ? call$1(searcher, regexp, O) : new RegExp(regexp)[SEARCH](toString$6(O));
21127 // `RegExp.prototype[@@search]` method
21128 // https://tc39.es/ecma262/#sec-regexp.prototype-@@search
21129 function (string) {
21130 var rx = anObject(this);
21131 var S = toString$6(string);
21132 var res = maybeCallNative(nativeSearch, rx, S);
21134 if (res.done) return res.value;
21136 var previousLastIndex = rx.lastIndex;
21137 if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0;
21138 var result = regExpExec(rx, S);
21139 if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex;
21140 return result === null ? -1 : result.index;
21145 var rbush$2 = {exports: {}};
21147 var quickselect$2 = {exports: {}};
21149 (function (module, exports) {
21150 (function (global, factory) {
21151 module.exports = factory() ;
21152 })(commonjsGlobal, function () {
21154 function quickselect(arr, k, left, right, compare) {
21155 quickselectStep(arr, k, left || 0, right || arr.length - 1, compare || defaultCompare);
21158 function quickselectStep(arr, k, left, right, compare) {
21159 while (right > left) {
21160 if (right - left > 600) {
21161 var n = right - left + 1;
21162 var m = k - left + 1;
21163 var z = Math.log(n);
21164 var s = 0.5 * Math.exp(2 * z / 3);
21165 var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
21166 var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
21167 var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
21168 quickselectStep(arr, k, newLeft, newRight, compare);
21174 swap(arr, left, k);
21175 if (compare(arr[right], t) > 0) swap(arr, left, right);
21182 while (compare(arr[i], t) < 0) {
21186 while (compare(arr[j], t) > 0) {
21191 if (compare(arr[left], t) === 0) swap(arr, left, j);else {
21193 swap(arr, j, right);
21195 if (j <= k) left = j + 1;
21196 if (k <= j) right = j - 1;
21200 function swap(arr, i, j) {
21206 function defaultCompare(a, b) {
21207 return a < b ? -1 : a > b ? 1 : 0;
21210 return quickselect;
21214 rbush$2.exports = rbush$1;
21216 rbush$2.exports["default"] = rbush$1;
21218 var quickselect$1 = quickselect$2.exports;
21220 function rbush$1(maxEntries, format) {
21221 if (!(this instanceof rbush$1)) return new rbush$1(maxEntries, format); // max entries in a node is 9 by default; min node fill is 40% for best performance
21223 this._maxEntries = Math.max(4, maxEntries || 9);
21224 this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
21227 this._initFormat(format);
21233 rbush$1.prototype = {
21234 all: function all() {
21235 return this._all(this.data, []);
21237 search: function search(bbox) {
21238 var node = this.data,
21240 toBBox = this.toBBox;
21241 if (!intersects$1(bbox, node)) return result;
21242 var nodesToSearch = [],
21249 for (i = 0, len = node.children.length; i < len; i++) {
21250 child = node.children[i];
21251 childBBox = node.leaf ? toBBox(child) : child;
21253 if (intersects$1(bbox, childBBox)) {
21254 if (node.leaf) result.push(child);else if (contains$1(bbox, childBBox)) this._all(child, result);else nodesToSearch.push(child);
21258 node = nodesToSearch.pop();
21263 collides: function collides(bbox) {
21264 var node = this.data,
21265 toBBox = this.toBBox;
21266 if (!intersects$1(bbox, node)) return false;
21267 var nodesToSearch = [],
21274 for (i = 0, len = node.children.length; i < len; i++) {
21275 child = node.children[i];
21276 childBBox = node.leaf ? toBBox(child) : child;
21278 if (intersects$1(bbox, childBBox)) {
21279 if (node.leaf || contains$1(bbox, childBBox)) return true;
21280 nodesToSearch.push(child);
21284 node = nodesToSearch.pop();
21289 load: function load(data) {
21290 if (!(data && data.length)) return this;
21292 if (data.length < this._minEntries) {
21293 for (var i = 0, len = data.length; i < len; i++) {
21294 this.insert(data[i]);
21298 } // recursively build the tree with the given data from scratch using OMT algorithm
21301 var node = this._build(data.slice(), 0, data.length - 1, 0);
21303 if (!this.data.children.length) {
21304 // save as is if tree is empty
21306 } else if (this.data.height === node.height) {
21307 // split root if trees have the same height
21308 this._splitRoot(this.data, node);
21310 if (this.data.height < node.height) {
21311 // swap trees if inserted one is bigger
21312 var tmpNode = this.data;
21315 } // insert the small tree into the large tree at appropriate level
21318 this._insert(node, this.data.height - node.height - 1, true);
21323 insert: function insert(item) {
21324 if (item) this._insert(item, this.data.height - 1);
21327 clear: function clear() {
21328 this.data = createNode$1([]);
21331 remove: function remove(item, equalsFn) {
21332 if (!item) return this;
21333 var node = this.data,
21334 bbox = this.toBBox(item),
21340 goingUp; // depth-first iterative tree traversal
21342 while (node || path.length) {
21346 parent = path[path.length - 1];
21352 // check current node
21353 index = findItem$1(item, node.children, equalsFn);
21355 if (index !== -1) {
21356 // item found, remove the item and condense tree upwards
21357 node.children.splice(index, 1);
21360 this._condense(path);
21366 if (!goingUp && !node.leaf && contains$1(node, bbox)) {
21372 node = node.children[0];
21373 } else if (parent) {
21376 node = parent.children[i];
21378 } else node = null; // nothing found
21384 toBBox: function toBBox(item) {
21387 compareMinX: compareNodeMinX$1,
21388 compareMinY: compareNodeMinY$1,
21389 toJSON: function toJSON() {
21392 fromJSON: function fromJSON(data) {
21396 _all: function _all(node, result) {
21397 var nodesToSearch = [];
21400 if (node.leaf) result.push.apply(result, node.children);else nodesToSearch.push.apply(nodesToSearch, node.children);
21401 node = nodesToSearch.pop();
21406 _build: function _build(items, left, right, height) {
21407 var N = right - left + 1,
21408 M = this._maxEntries,
21412 // reached leaf level; return leaf
21413 node = createNode$1(items.slice(left, right + 1));
21414 calcBBox$1(node, this.toBBox);
21419 // target height of the bulk-loaded tree
21420 height = Math.ceil(Math.log(N) / Math.log(M)); // target number of root entries to maximize storage utilization
21422 M = Math.ceil(N / Math.pow(M, height - 1));
21425 node = createNode$1([]);
21427 node.height = height; // split the items into M mostly square tiles
21429 var N2 = Math.ceil(N / M),
21430 N1 = N2 * Math.ceil(Math.sqrt(M)),
21435 multiSelect$1(items, left, right, N1, this.compareMinX);
21437 for (i = left; i <= right; i += N1) {
21438 right2 = Math.min(i + N1 - 1, right);
21439 multiSelect$1(items, i, right2, N2, this.compareMinY);
21441 for (j = i; j <= right2; j += N2) {
21442 right3 = Math.min(j + N2 - 1, right2); // pack each entry recursively
21444 node.children.push(this._build(items, j, right3, height - 1));
21448 calcBBox$1(node, this.toBBox);
21451 _chooseSubtree: function _chooseSubtree(bbox, node, level, path) {
21452 var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
21456 if (node.leaf || path.length - 1 === level) break;
21457 minArea = minEnlargement = Infinity;
21459 for (i = 0, len = node.children.length; i < len; i++) {
21460 child = node.children[i];
21461 area = bboxArea$1(child);
21462 enlargement = enlargedArea$1(bbox, child) - area; // choose entry with the least area enlargement
21464 if (enlargement < minEnlargement) {
21465 minEnlargement = enlargement;
21466 minArea = area < minArea ? area : minArea;
21467 targetNode = child;
21468 } else if (enlargement === minEnlargement) {
21469 // otherwise choose one with the smallest area
21470 if (area < minArea) {
21472 targetNode = child;
21477 node = targetNode || node.children[0];
21482 _insert: function _insert(item, level, isNode) {
21483 var toBBox = this.toBBox,
21484 bbox = isNode ? item : toBBox(item),
21485 insertPath = []; // find the best node for accommodating the item, saving all nodes along the path too
21487 var node = this._chooseSubtree(bbox, this.data, level, insertPath); // put the item into the node
21490 node.children.push(item);
21491 extend$2(node, bbox); // split on node overflow; propagate upwards if necessary
21493 while (level >= 0) {
21494 if (insertPath[level].children.length > this._maxEntries) {
21495 this._split(insertPath, level);
21499 } // adjust bboxes along the insertion path
21502 this._adjustParentBBoxes(bbox, insertPath, level);
21504 // split overflowed node into two
21505 _split: function _split(insertPath, level) {
21506 var node = insertPath[level],
21507 M = node.children.length,
21508 m = this._minEntries;
21510 this._chooseSplitAxis(node, m, M);
21512 var splitIndex = this._chooseSplitIndex(node, m, M);
21514 var newNode = createNode$1(node.children.splice(splitIndex, node.children.length - splitIndex));
21515 newNode.height = node.height;
21516 newNode.leaf = node.leaf;
21517 calcBBox$1(node, this.toBBox);
21518 calcBBox$1(newNode, this.toBBox);
21519 if (level) insertPath[level - 1].children.push(newNode);else this._splitRoot(node, newNode);
21521 _splitRoot: function _splitRoot(node, newNode) {
21523 this.data = createNode$1([node, newNode]);
21524 this.data.height = node.height + 1;
21525 this.data.leaf = false;
21526 calcBBox$1(this.data, this.toBBox);
21528 _chooseSplitIndex: function _chooseSplitIndex(node, m, M) {
21529 var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
21530 minOverlap = minArea = Infinity;
21532 for (i = m; i <= M - m; i++) {
21533 bbox1 = distBBox$1(node, 0, i, this.toBBox);
21534 bbox2 = distBBox$1(node, i, M, this.toBBox);
21535 overlap = intersectionArea$1(bbox1, bbox2);
21536 area = bboxArea$1(bbox1) + bboxArea$1(bbox2); // choose distribution with minimum overlap
21538 if (overlap < minOverlap) {
21539 minOverlap = overlap;
21541 minArea = area < minArea ? area : minArea;
21542 } else if (overlap === minOverlap) {
21543 // otherwise choose distribution with minimum area
21544 if (area < minArea) {
21553 // sorts node children by the best axis for split
21554 _chooseSplitAxis: function _chooseSplitAxis(node, m, M) {
21555 var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX$1,
21556 compareMinY = node.leaf ? this.compareMinY : compareNodeMinY$1,
21557 xMargin = this._allDistMargin(node, m, M, compareMinX),
21558 yMargin = this._allDistMargin(node, m, M, compareMinY); // if total distributions margin value is minimal for x, sort by minX,
21559 // otherwise it's already sorted by minY
21562 if (xMargin < yMargin) node.children.sort(compareMinX);
21564 // total margin of all possible split distributions where each node is at least m full
21565 _allDistMargin: function _allDistMargin(node, m, M, compare) {
21566 node.children.sort(compare);
21567 var toBBox = this.toBBox,
21568 leftBBox = distBBox$1(node, 0, m, toBBox),
21569 rightBBox = distBBox$1(node, M - m, M, toBBox),
21570 margin = bboxMargin$1(leftBBox) + bboxMargin$1(rightBBox),
21574 for (i = m; i < M - m; i++) {
21575 child = node.children[i];
21576 extend$2(leftBBox, node.leaf ? toBBox(child) : child);
21577 margin += bboxMargin$1(leftBBox);
21580 for (i = M - m - 1; i >= m; i--) {
21581 child = node.children[i];
21582 extend$2(rightBBox, node.leaf ? toBBox(child) : child);
21583 margin += bboxMargin$1(rightBBox);
21588 _adjustParentBBoxes: function _adjustParentBBoxes(bbox, path, level) {
21589 // adjust bboxes along the given tree path
21590 for (var i = level; i >= 0; i--) {
21591 extend$2(path[i], bbox);
21594 _condense: function _condense(path) {
21595 // go through the path, removing empty nodes and updating bboxes
21596 for (var i = path.length - 1, siblings; i >= 0; i--) {
21597 if (path[i].children.length === 0) {
21599 siblings = path[i - 1].children;
21600 siblings.splice(siblings.indexOf(path[i]), 1);
21601 } else this.clear();
21602 } else calcBBox$1(path[i], this.toBBox);
21605 _initFormat: function _initFormat(format) {
21606 // data format (minX, minY, maxX, maxY accessors)
21607 // uses eval-type function compilation instead of just accepting a toBBox function
21608 // because the algorithms are very sensitive to sorting functions performance,
21609 // so they should be dead simple and without inner calls
21610 var compareArr = ['return a', ' - b', ';'];
21611 this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
21612 this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
21613 this.toBBox = new Function('a', 'return {minX: a' + format[0] + ', minY: a' + format[1] + ', maxX: a' + format[2] + ', maxY: a' + format[3] + '};');
21617 function findItem$1(item, items, equalsFn) {
21618 if (!equalsFn) return items.indexOf(item);
21620 for (var i = 0; i < items.length; i++) {
21621 if (equalsFn(item, items[i])) return i;
21625 } // calculate node's bbox from bboxes of its children
21628 function calcBBox$1(node, toBBox) {
21629 distBBox$1(node, 0, node.children.length, toBBox, node);
21630 } // min bounding rectangle of node children from k to p-1
21633 function distBBox$1(node, k, p, toBBox, destNode) {
21634 if (!destNode) destNode = createNode$1(null);
21635 destNode.minX = Infinity;
21636 destNode.minY = Infinity;
21637 destNode.maxX = -Infinity;
21638 destNode.maxY = -Infinity;
21640 for (var i = k, child; i < p; i++) {
21641 child = node.children[i];
21642 extend$2(destNode, node.leaf ? toBBox(child) : child);
21648 function extend$2(a, b) {
21649 a.minX = Math.min(a.minX, b.minX);
21650 a.minY = Math.min(a.minY, b.minY);
21651 a.maxX = Math.max(a.maxX, b.maxX);
21652 a.maxY = Math.max(a.maxY, b.maxY);
21656 function compareNodeMinX$1(a, b) {
21657 return a.minX - b.minX;
21660 function compareNodeMinY$1(a, b) {
21661 return a.minY - b.minY;
21664 function bboxArea$1(a) {
21665 return (a.maxX - a.minX) * (a.maxY - a.minY);
21668 function bboxMargin$1(a) {
21669 return a.maxX - a.minX + (a.maxY - a.minY);
21672 function enlargedArea$1(a, b) {
21673 return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) * (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
21676 function intersectionArea$1(a, b) {
21677 var minX = Math.max(a.minX, b.minX),
21678 minY = Math.max(a.minY, b.minY),
21679 maxX = Math.min(a.maxX, b.maxX),
21680 maxY = Math.min(a.maxY, b.maxY);
21681 return Math.max(0, maxX - minX) * Math.max(0, maxY - minY);
21684 function contains$1(a, b) {
21685 return a.minX <= b.minX && a.minY <= b.minY && b.maxX <= a.maxX && b.maxY <= a.maxY;
21688 function intersects$1(a, b) {
21689 return b.minX <= a.maxX && b.minY <= a.maxY && b.maxX >= a.minX && b.maxY >= a.minY;
21692 function createNode$1(children) {
21694 children: children,
21702 } // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
21703 // combines selection algorithm with binary divide & conquer approach
21706 function multiSelect$1(arr, left, right, n, compare) {
21707 var stack = [left, right],
21710 while (stack.length) {
21711 right = stack.pop();
21712 left = stack.pop();
21713 if (right - left <= n) continue;
21714 mid = left + Math.ceil((right - left) / n / 2) * n;
21715 quickselect$1(arr, mid, left, right, compare);
21716 stack.push(left, mid, mid, right);
21720 var lineclip_1 = lineclip$2;
21721 lineclip$2.polyline = lineclip$2;
21722 lineclip$2.polygon = polygonclip$1; // Cohen-Sutherland line clippign algorithm, adapted to efficiently
21723 // handle polylines rather than just segments
21725 function lineclip$2(points, bbox, result) {
21726 var len = points.length,
21727 codeA = bitCode$1(points[0], bbox),
21734 if (!result) result = [];
21736 for (i = 1; i < len; i++) {
21739 codeB = lastCode = bitCode$1(b, bbox);
21742 if (!(codeA | codeB)) {
21746 if (codeB !== lastCode) {
21747 // segment went outside
21751 // start a new line
21755 } else if (i === len - 1) {
21760 } else if (codeA & codeB) {
21763 } else if (codeA) {
21764 // a outside, intersect with clip edge
21765 a = intersect$1(a, b, codeA, bbox);
21766 codeA = bitCode$1(a, bbox);
21769 b = intersect$1(a, b, codeB, bbox);
21770 codeB = bitCode$1(b, bbox);
21777 if (part.length) result.push(part);
21779 } // Sutherland-Hodgeman polygon clipping algorithm
21782 function polygonclip$1(points, bbox) {
21783 var result, edge, prev, prevInside, i, p, inside; // clip against each side of the clip rectangle
21785 for (edge = 1; edge <= 8; edge *= 2) {
21787 prev = points[points.length - 1];
21788 prevInside = !(bitCode$1(prev, bbox) & edge);
21790 for (i = 0; i < points.length; i++) {
21792 inside = !(bitCode$1(p, bbox) & edge); // if segment goes through the clip window, add an intersection
21794 if (inside !== prevInside) result.push(intersect$1(prev, p, edge, bbox));
21795 if (inside) result.push(p); // add a point if it's inside
21798 prevInside = inside;
21802 if (!points.length) break;
21806 } // intersect a segment against one of the 4 lines that make up the bbox
21809 function intersect$1(a, b, edge, bbox) {
21810 return edge & 8 ? [a[0] + (b[0] - a[0]) * (bbox[3] - a[1]) / (b[1] - a[1]), bbox[3]] : // top
21811 edge & 4 ? [a[0] + (b[0] - a[0]) * (bbox[1] - a[1]) / (b[1] - a[1]), bbox[1]] : // bottom
21812 edge & 2 ? [bbox[2], a[1] + (b[1] - a[1]) * (bbox[2] - a[0]) / (b[0] - a[0])] : // right
21813 edge & 1 ? [bbox[0], a[1] + (b[1] - a[1]) * (bbox[0] - a[0]) / (b[0] - a[0])] : // left
21815 } // bit code reflects the point position relative to the bbox:
21817 // top 1001 1000 1010
21818 // mid 0001 0000 0010
21819 // bottom 0101 0100 0110
21822 function bitCode$1(p, bbox) {
21824 if (p[0] < bbox[0]) code |= 1; // left
21825 else if (p[0] > bbox[2]) code |= 2; // right
21827 if (p[1] < bbox[1]) code |= 4; // bottom
21828 else if (p[1] > bbox[3]) code |= 8; // top
21833 var rbush = rbush$2.exports;
21834 var lineclip$1 = lineclip_1;
21835 var whichPolygon_1 = whichPolygon;
21837 function whichPolygon(data) {
21840 for (var i = 0; i < data.features.length; i++) {
21841 var feature = data.features[i];
21842 var coords = feature.geometry.coordinates;
21844 if (feature.geometry.type === 'Polygon') {
21845 bboxes.push(treeItem(coords, feature.properties));
21846 } else if (feature.geometry.type === 'MultiPolygon') {
21847 for (var j = 0; j < coords.length; j++) {
21848 bboxes.push(treeItem(coords[j], feature.properties));
21853 var tree = rbush().load(bboxes);
21855 function query(p, multi) {
21857 result = tree.search({
21864 for (var i = 0; i < result.length; i++) {
21865 if (insidePolygon(result[i].coords, p)) {
21866 if (multi) output.push(result[i].props);else return result[i].props;
21870 return multi && output.length ? output : null;
21875 query.bbox = function queryBBox(bbox) {
21877 var result = tree.search({
21884 for (var i = 0; i < result.length; i++) {
21885 if (polygonIntersectsBBox(result[i].coords, bbox)) {
21886 output.push(result[i].props);
21896 function polygonIntersectsBBox(polygon, bbox) {
21897 var bboxCenter = [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2];
21898 if (insidePolygon(polygon, bboxCenter)) return true;
21900 for (var i = 0; i < polygon.length; i++) {
21901 if (lineclip$1(polygon[i], bbox).length > 0) return true;
21905 } // ray casting algorithm for detecting if point is in polygon
21908 function insidePolygon(rings, p) {
21909 var inside = false;
21911 for (var i = 0, len = rings.length; i < len; i++) {
21912 var ring = rings[i];
21914 for (var j = 0, len2 = ring.length, k = len2 - 1; j < len2; k = j++) {
21915 if (rayIntersect(p, ring[j], ring[k])) inside = !inside;
21922 function rayIntersect(p, p1, p2) {
21923 return p1[1] > p[1] !== p2[1] > p[1] && p[0] < (p2[0] - p1[0]) * (p[1] - p1[1]) / (p2[1] - p1[1]) + p1[0];
21926 function treeItem(coords, props) {
21936 for (var i = 0; i < coords[0].length; i++) {
21937 var p = coords[0][i];
21938 item.minX = Math.min(item.minX, p[0]);
21939 item.minY = Math.min(item.minY, p[1]);
21940 item.maxX = Math.max(item.maxX, p[0]);
21941 item.maxY = Math.max(item.maxY, p[1]);
21947 var type = "FeatureCollection";
21953 aliases: ["GB-ENG"],
21955 groups: ["Q23666", "Q3336843", "154", "150", "UN"],
21957 roadSpeedUnit: "mph",
21958 roadHeightUnit: "ft",
21959 callingCodes: ["44"]
21962 type: "MultiPolygon",
21963 coordinates: [[[[-6.03913, 51.13217], [-7.74976, 48.64773], [1.17405, 50.74239], [2.18458, 51.52087], [2.56575, 51.85301], [0.792, 57.56437], [-2.30613, 55.62698], [-2.17058, 55.45916], [-2.6095, 55.28488], [-2.63532, 55.19452], [-3.02906, 55.04606], [-3.09361, 54.94924], [-3.38407, 54.94278], [-4.1819, 54.57861], [-3.5082, 53.54318], [-3.08228, 53.25526], [-3.03675, 53.25092], [-2.92329, 53.19383], [-2.92022, 53.17685], [-2.98598, 53.15589], [-2.90649, 53.10964], [-2.87469, 53.12337], [-2.89131, 53.09374], [-2.83133, 52.99184], [-2.7251, 52.98389], [-2.72221, 52.92969], [-2.80549, 52.89428], [-2.85897, 52.94487], [-2.92401, 52.93836], [-2.97243, 52.9651], [-3.13576, 52.895], [-3.15744, 52.84947], [-3.16105, 52.79599], [-3.08734, 52.77504], [-3.01001, 52.76636], [-2.95581, 52.71794], [-3.01724, 52.72083], [-3.04398, 52.65435], [-3.13648, 52.58208], [-3.12926, 52.5286], [-3.09746, 52.53077], [-3.08662, 52.54811], [-3.00929, 52.57774], [-2.99701, 52.551], [-3.03603, 52.49969], [-3.13359, 52.49174], [-3.22971, 52.45344], [-3.22754, 52.42526], [-3.04687, 52.34504], [-2.95364, 52.3501], [-2.99701, 52.323], [-3.00785, 52.2753], [-3.09289, 52.20546], [-3.12638, 52.08114], [-2.97111, 51.90456], [-2.8818, 51.93196], [-2.78742, 51.88833], [-2.74277, 51.84367], [-2.66234, 51.83555], [-2.66336, 51.59504], [-3.20563, 51.31615], [-6.03913, 51.13217]]]]
21969 nameEn: "Scotland",
21970 aliases: ["GB-SCT"],
21972 groups: ["Q23666", "Q3336843", "154", "150", "UN"],
21974 roadSpeedUnit: "mph",
21975 roadHeightUnit: "ft",
21976 callingCodes: ["44"]
21979 type: "MultiPolygon",
21980 coordinates: [[[[0.792, 57.56437], [-0.3751, 61.32236], [-14.78497, 57.60709], [-6.82333, 55.83103], [-4.69044, 54.3629], [-3.38407, 54.94278], [-3.09361, 54.94924], [-3.02906, 55.04606], [-2.63532, 55.19452], [-2.6095, 55.28488], [-2.17058, 55.45916], [-2.30613, 55.62698], [0.792, 57.56437]]]]
21987 aliases: ["GB-WLS"],
21989 groups: ["Q23666", "Q3336843", "154", "150", "UN"],
21991 roadSpeedUnit: "mph",
21992 roadHeightUnit: "ft",
21993 callingCodes: ["44"]
21996 type: "MultiPolygon",
21997 coordinates: [[[[-3.5082, 53.54318], [-5.37267, 53.63269], [-6.03913, 51.13217], [-3.20563, 51.31615], [-2.66336, 51.59504], [-2.66234, 51.83555], [-2.74277, 51.84367], [-2.78742, 51.88833], [-2.8818, 51.93196], [-2.97111, 51.90456], [-3.12638, 52.08114], [-3.09289, 52.20546], [-3.00785, 52.2753], [-2.99701, 52.323], [-2.95364, 52.3501], [-3.04687, 52.34504], [-3.22754, 52.42526], [-3.22971, 52.45344], [-3.13359, 52.49174], [-3.03603, 52.49969], [-2.99701, 52.551], [-3.00929, 52.57774], [-3.08662, 52.54811], [-3.09746, 52.53077], [-3.12926, 52.5286], [-3.13648, 52.58208], [-3.04398, 52.65435], [-3.01724, 52.72083], [-2.95581, 52.71794], [-3.01001, 52.76636], [-3.08734, 52.77504], [-3.16105, 52.79599], [-3.15744, 52.84947], [-3.13576, 52.895], [-2.97243, 52.9651], [-2.92401, 52.93836], [-2.85897, 52.94487], [-2.80549, 52.89428], [-2.72221, 52.92969], [-2.7251, 52.98389], [-2.83133, 52.99184], [-2.89131, 53.09374], [-2.87469, 53.12337], [-2.90649, 53.10964], [-2.98598, 53.15589], [-2.92022, 53.17685], [-2.92329, 53.19383], [-3.03675, 53.25092], [-3.08228, 53.25526], [-3.5082, 53.54318]]]]
22003 nameEn: "Northern Ireland",
22004 aliases: ["GB-NIR"],
22006 groups: ["Q22890", "Q3336843", "154", "150", "UN"],
22008 roadSpeedUnit: "mph",
22009 roadHeightUnit: "ft",
22010 callingCodes: ["44"]
22013 type: "MultiPolygon",
22014 coordinates: [[[[-6.34755, 55.49206], [-7.2471, 55.06933], [-7.34464, 55.04688], [-7.4033, 55.00391], [-7.40004, 54.94498], [-7.44404, 54.9403], [-7.4473, 54.87003], [-7.47626, 54.83084], [-7.54508, 54.79401], [-7.54671, 54.74606], [-7.64449, 54.75265], [-7.75041, 54.7103], [-7.83352, 54.73854], [-7.93293, 54.66603], [-7.70315, 54.62077], [-7.8596, 54.53671], [-7.99812, 54.54427], [-8.04538, 54.48941], [-8.179, 54.46763], [-8.04555, 54.36292], [-7.87101, 54.29299], [-7.8596, 54.21779], [-7.81397, 54.20159], [-7.69501, 54.20731], [-7.55812, 54.12239], [-7.4799, 54.12239], [-7.44567, 54.1539], [-7.32834, 54.11475], [-7.30553, 54.11869], [-7.34005, 54.14698], [-7.29157, 54.17191], [-7.28017, 54.16714], [-7.29687, 54.1354], [-7.29493, 54.12013], [-7.26316, 54.13863], [-7.25012, 54.20063], [-7.14908, 54.22732], [-7.19145, 54.31296], [-7.02034, 54.4212], [-6.87775, 54.34682], [-6.85179, 54.29176], [-6.81583, 54.22791], [-6.74575, 54.18788], [-6.70175, 54.20218], [-6.6382, 54.17071], [-6.66264, 54.0666], [-6.62842, 54.03503], [-6.47849, 54.06947], [-6.36605, 54.07234], [-6.36279, 54.11248], [-6.32694, 54.09337], [-6.29003, 54.11278], [-6.26218, 54.09785], [-5.83481, 53.87749], [-4.69044, 54.3629], [-6.34755, 55.49206]]]]
22022 groups: ["EU", "154", "150", "UN"],
22023 callingCodes: ["45"]
22026 type: "MultiPolygon",
22027 coordinates: [[[[12.16597, 56.60205], [10.40861, 58.38489], [7.28637, 57.35913], [8.02459, 55.09613], [8.45719, 55.06747], [8.55769, 54.91837], [8.63979, 54.91069], [8.76387, 54.8948], [8.81178, 54.90518], [8.92795, 54.90452], [9.04629, 54.87249], [9.14275, 54.87421], [9.20571, 54.85841], [9.24631, 54.84726], [9.23445, 54.83432], [9.2474, 54.8112], [9.32771, 54.80602], [9.33849, 54.80233], [9.36496, 54.81749], [9.38532, 54.83968], [9.41213, 54.84254], [9.43155, 54.82586], [9.4659, 54.83131], [9.58937, 54.88785], [9.62734, 54.88057], [9.61187, 54.85548], [9.73563, 54.8247], [9.89314, 54.84171], [10.16755, 54.73883], [10.31111, 54.65968], [11.00303, 54.63689], [11.90309, 54.38543], [12.85844, 54.82438], [13.93395, 54.84044], [15.36991, 54.73263], [15.79951, 55.54655], [14.89259, 55.5623], [14.28399, 55.1553], [12.84405, 55.13257], [12.60345, 55.42675], [12.88472, 55.63369], [12.6372, 55.91371], [12.65312, 56.04345], [12.07466, 56.29488], [12.16597, 56.60205]]]]
22033 nameEn: "Netherlands",
22035 groups: ["EU", "155", "150", "UN"],
22036 callingCodes: ["31"]
22039 type: "MultiPolygon",
22040 coordinates: [[[[5.45168, 54.20039], [2.56575, 51.85301], [3.36263, 51.37112], [3.38696, 51.33436], [3.35847, 51.31572], [3.38289, 51.27331], [3.41704, 51.25933], [3.43488, 51.24135], [3.52698, 51.2458], [3.51502, 51.28697], [3.58939, 51.30064], [3.78999, 51.25766], [3.78783, 51.2151], [3.90125, 51.20371], [3.97889, 51.22537], [4.01957, 51.24504], [4.05165, 51.24171], [4.16721, 51.29348], [4.24024, 51.35371], [4.21923, 51.37443], [4.33265, 51.37687], [4.34086, 51.35738], [4.39292, 51.35547], [4.43777, 51.36989], [4.38064, 51.41965], [4.39747, 51.43316], [4.38122, 51.44905], [4.47736, 51.4778], [4.5388, 51.48184], [4.54675, 51.47265], [4.52846, 51.45002], [4.53521, 51.4243], [4.57489, 51.4324], [4.65442, 51.42352], [4.72935, 51.48424], [4.74578, 51.48937], [4.77321, 51.50529], [4.78803, 51.50284], [4.84139, 51.4799], [4.82409, 51.44736], [4.82946, 51.4213], [4.78314, 51.43319], [4.76577, 51.43046], [4.77229, 51.41337], [4.78941, 51.41102], [4.84988, 51.41502], [4.90016, 51.41404], [4.92152, 51.39487], [5.00393, 51.44406], [5.0106, 51.47167], [5.03281, 51.48679], [5.04774, 51.47022], [5.07891, 51.4715], [5.10456, 51.43163], [5.07102, 51.39469], [5.13105, 51.34791], [5.13377, 51.31592], [5.16222, 51.31035], [5.2002, 51.32243], [5.24244, 51.30495], [5.22542, 51.26888], [5.23814, 51.26064], [5.26461, 51.26693], [5.29716, 51.26104], [5.33886, 51.26314], [5.347, 51.27502], [5.41672, 51.26248], [5.4407, 51.28169], [5.46519, 51.2849], [5.48476, 51.30053], [5.515, 51.29462], [5.5569, 51.26544], [5.5603, 51.22249], [5.65145, 51.19788], [5.65528, 51.18736], [5.70344, 51.1829], [5.74617, 51.18928], [5.77735, 51.17845], [5.77697, 51.1522], [5.82564, 51.16753], [5.85508, 51.14445], [5.80798, 51.11661], [5.8109, 51.10861], [5.83226, 51.10585], [5.82921, 51.09328], [5.79903, 51.09371], [5.79835, 51.05834], [5.77258, 51.06196], [5.75961, 51.03113], [5.77688, 51.02483], [5.76242, 50.99703], [5.71864, 50.96092], [5.72875, 50.95428], [5.74752, 50.96202], [5.75927, 50.95601], [5.74644, 50.94723], [5.72545, 50.92312], [5.72644, 50.91167], [5.71626, 50.90796], [5.69858, 50.91046], [5.67886, 50.88142], [5.64504, 50.87107], [5.64009, 50.84742], [5.65259, 50.82309], [5.70118, 50.80764], [5.68995, 50.79641], [5.70107, 50.7827], [5.68091, 50.75804], [5.69469, 50.75529], [5.72216, 50.76398], [5.73904, 50.75674], [5.74356, 50.7691], [5.76533, 50.78159], [5.77513, 50.78308], [5.80673, 50.7558], [5.84548, 50.76542], [5.84888, 50.75448], [5.88734, 50.77092], [5.89129, 50.75125], [5.89132, 50.75124], [5.95942, 50.7622], [5.97545, 50.75441], [6.01976, 50.75398], [6.02624, 50.77453], [5.97497, 50.79992], [5.98404, 50.80988], [6.00462, 50.80065], [6.02328, 50.81694], [6.01921, 50.84435], [6.05623, 50.8572], [6.05702, 50.85179], [6.07431, 50.84674], [6.07693, 50.86025], [6.08805, 50.87223], [6.07486, 50.89307], [6.09297, 50.92066], [6.01615, 50.93367], [6.02697, 50.98303], [5.95282, 50.98728], [5.90296, 50.97356], [5.90493, 51.00198], [5.87849, 51.01969], [5.86735, 51.05182], [5.9134, 51.06736], [5.9541, 51.03496], [5.98292, 51.07469], [6.16706, 51.15677], [6.17384, 51.19589], [6.07889, 51.17038], [6.07889, 51.24432], [6.16977, 51.33169], [6.22674, 51.36135], [6.22641, 51.39948], [6.20654, 51.40049], [6.21724, 51.48568], [6.18017, 51.54096], [6.09055, 51.60564], [6.11759, 51.65609], [6.02767, 51.6742], [6.04091, 51.71821], [5.95003, 51.7493], [5.98665, 51.76944], [5.94568, 51.82786], [5.99848, 51.83195], [6.06705, 51.86136], [6.10337, 51.84829], [6.16902, 51.84094], [6.11551, 51.89769], [6.15349, 51.90439], [6.21443, 51.86801], [6.29872, 51.86801], [6.30593, 51.84998], [6.40704, 51.82771], [6.38815, 51.87257], [6.47179, 51.85395], [6.50231, 51.86313], [6.58556, 51.89386], [6.68386, 51.91861], [6.72319, 51.89518], [6.82357, 51.96711], [6.83035, 51.9905], [6.68128, 52.05052], [6.76117, 52.11895], [6.83984, 52.11728], [6.97189, 52.20329], [6.9897, 52.2271], [7.03729, 52.22695], [7.06365, 52.23789], [7.02703, 52.27941], [7.07044, 52.37805], [7.03417, 52.40237], [6.99041, 52.47235], [6.94293, 52.43597], [6.69507, 52.488], [6.71641, 52.62905], [6.77307, 52.65375], [7.04557, 52.63318], [7.07253, 52.81083], [7.21694, 53.00742], [7.17898, 53.13817], [7.22681, 53.18165], [7.21679, 53.20058], [7.19052, 53.31866], [7.00198, 53.32672], [6.91025, 53.44221], [5.45168, 54.20039]], [[4.93295, 51.44945], [4.95244, 51.45207], [4.9524, 51.45014], [4.93909, 51.44632], [4.93295, 51.44945]], [[4.91493, 51.4353], [4.91935, 51.43634], [4.92227, 51.44252], [4.91811, 51.44621], [4.92287, 51.44741], [4.92811, 51.4437], [4.92566, 51.44273], [4.92815, 51.43856], [4.92879, 51.44161], [4.93544, 51.44634], [4.94025, 51.44193], [4.93416, 51.44185], [4.93471, 51.43861], [4.94265, 51.44003], [4.93986, 51.43064], [4.92952, 51.42984], [4.92652, 51.43329], [4.91493, 51.4353]]]]
22047 aliases: ["US-HI"],
22049 groups: ["Q35657", "061", "009", "UN"],
22050 roadSpeedUnit: "mph",
22051 roadHeightUnit: "ft",
22052 callingCodes: ["1"]
22055 type: "MultiPolygon",
22056 coordinates: [[[[-177.8563, 29.18961], [-179.49839, 27.86265], [-151.6784, 9.55515], [-154.05867, 45.51124], [-177.5224, 27.7635], [-177.8563, 29.18961]]]]
22063 aliases: ["US-AK"],
22065 groups: ["Q35657", "021", "003", "019", "UN"],
22066 roadSpeedUnit: "mph",
22067 roadHeightUnit: "ft",
22068 callingCodes: ["1"]
22071 type: "MultiPolygon",
22072 coordinates: [[[[169.34848, 52.47228], [180, 51.0171], [179.84401, 55.10087], [169.34848, 52.47228]]], [[[-168.95635, 65.98512], [-169.03888, 65.48473], [-172.76104, 63.77445], [-179.55295, 57.62081], [-179.55295, 50.81807], [-133.92876, 54.62289], [-130.61931, 54.70835], [-130.64499, 54.76912], [-130.44184, 54.85377], [-130.27203, 54.97174], [-130.18765, 55.07744], [-130.08035, 55.21556], [-129.97513, 55.28029], [-130.15373, 55.74895], [-130.00857, 55.91344], [-130.00093, 56.00325], [-130.10173, 56.12178], [-130.33965, 56.10849], [-130.77769, 56.36185], [-131.8271, 56.62247], [-133.38523, 58.42773], [-133.84645, 58.73543], [-134.27175, 58.8634], [-134.48059, 59.13231], [-134.55699, 59.1297], [-134.7047, 59.2458], [-135.00267, 59.28745], [-135.03069, 59.56208], [-135.48007, 59.79937], [-136.31566, 59.59083], [-136.22381, 59.55526], [-136.33727, 59.44466], [-136.47323, 59.46617], [-136.52365, 59.16752], [-136.82619, 59.16198], [-137.4925, 58.89415], [-137.60623, 59.24465], [-138.62145, 59.76431], [-138.71149, 59.90728], [-139.05365, 59.99655], [-139.20603, 60.08896], [-139.05831, 60.35205], [-139.68991, 60.33693], [-139.98024, 60.18027], [-140.45648, 60.30919], [-140.5227, 60.22077], [-141.00116, 60.30648], [-140.97446, 84.39275], [-168.25765, 71.99091], [-168.95635, 65.98512]]]]
22079 aliases: ["ID-SM"],
22081 groups: ["035", "142", "UN"],
22083 callingCodes: ["62"]
22086 type: "MultiPolygon",
22087 coordinates: [[[[109.82788, 2.86812], [110.90339, 7.52694], [105.01437, 3.24936], [104.56723, 1.44271], [104.34728, 1.33529], [104.12282, 1.27714], [104.03085, 1.26954], [103.74084, 1.12902], [103.66049, 1.18825], [103.56591, 1.19719], [103.03657, 1.30383], [96.11174, 6.69841], [74.28481, -3.17525], [102.92489, -8.17146], [106.32259, -5.50116], [106.38511, -5.16715], [109.17017, -4.07401], [109.3962, -2.07276], [108.50935, -2.01066], [107.94791, 1.06924], [109.82788, 2.86812]]]]
22094 aliases: ["ID-JW"],
22096 groups: ["035", "142", "UN"],
22098 callingCodes: ["62"]
22101 type: "MultiPolygon",
22102 coordinates: [[[[109.17017, -4.07401], [106.38511, -5.16715], [106.32259, -5.50116], [102.92489, -8.17146], [116.22542, -10.49172], [114.39575, -8.2889], [114.42235, -8.09762], [114.92859, -7.49253], [116.33992, -7.56171], [116.58433, -5.30385], [109.17017, -4.07401]]]]
22108 nameEn: "Kalimantan",
22109 aliases: ["ID-KA"],
22111 groups: ["Q36117", "035", "142", "UN"],
22113 callingCodes: ["62"]
22116 type: "MultiPolygon",
22117 coordinates: [[[[120.02464, 2.83703], [118.06469, 4.16638], [117.67641, 4.16535], [117.47313, 4.18857], [117.25801, 4.35108], [115.90217, 4.37708], [115.58276, 3.93499], [115.53713, 3.14776], [115.11343, 2.82879], [115.1721, 2.49671], [114.80706, 2.21665], [114.80706, 1.92351], [114.57892, 1.5], [114.03788, 1.44787], [113.64677, 1.23933], [113.01448, 1.42832], [113.021, 1.57819], [112.48648, 1.56516], [112.2127, 1.44135], [112.15679, 1.17004], [111.94553, 1.12016], [111.82846, 0.99349], [111.55434, 0.97864], [111.22979, 1.08326], [110.62374, 0.873], [110.49182, 0.88088], [110.35354, 0.98869], [109.66397, 1.60425], [109.66397, 1.79972], [109.57923, 1.80624], [109.53794, 1.91771], [109.62558, 1.99182], [109.82788, 2.86812], [107.94791, 1.06924], [108.50935, -2.01066], [109.3962, -2.07276], [109.17017, -4.07401], [116.58433, -5.30385], [120.02464, 2.83703]]]]
22123 nameEn: "Lesser Sunda Islands",
22124 aliases: ["ID-NU"],
22126 groups: ["035", "142", "UN"],
22128 callingCodes: ["62"]
22131 type: "MultiPolygon",
22132 coordinates: [[[[116.96967, -8.01483], [114.92859, -7.49253], [114.42235, -8.09762], [114.39575, -8.2889], [116.22542, -10.49172], [122.14954, -11.52517], [125.68138, -9.85176], [125.09025, -9.46406], [124.97892, -9.19281], [125.04044, -9.17093], [125.09434, -9.19669], [125.18907, -9.16434], [125.18632, -9.03142], [125.11764, -8.96359], [124.97742, -9.08128], [124.94011, -8.85617], [124.46701, -9.13002], [124.45971, -9.30263], [124.38554, -9.3582], [124.35258, -9.43002], [124.3535, -9.48493], [124.28115, -9.50453], [124.28115, -9.42189], [124.21247, -9.36904], [124.14517, -9.42324], [124.10539, -9.41206], [124.04286, -9.34243], [124.04628, -9.22671], [124.33472, -9.11416], [124.92337, -8.75859], [125.87688, -7.49892], [116.96967, -8.01483]]]]
22138 nameEn: "Sulawesi",
22139 aliases: ["ID-SL"],
22141 groups: ["035", "142", "UN"],
22143 callingCodes: ["62"]
22146 type: "MultiPolygon",
22147 coordinates: [[[[128.34321, 3.90322], [126.69413, 6.02692], [119.56457, 0.90759], [116.58433, -5.30385], [116.33992, -7.56171], [116.96967, -8.01483], [125.87688, -7.49892], [123.78965, -0.86805], [128.34321, 3.90322]]]]
22153 nameEn: "Maluku Islands",
22154 aliases: ["ID-ML"],
22156 groups: ["035", "142", "UN"],
22158 callingCodes: ["62"]
22161 type: "MultiPolygon",
22162 coordinates: [[[[129.63187, 2.21409], [128.34321, 3.90322], [123.78965, -0.86805], [125.87688, -7.49892], [125.58506, -7.95311], [125.87691, -8.31789], [127.42116, -8.22471], [127.55165, -9.05052], [135.49042, -9.2276], [135.35517, -5.01442], [132.8312, -4.70282], [130.8468, -2.61103], [128.40647, -2.30349], [129.71519, -0.24692], [129.63187, 2.21409]]]]
22168 nameEn: "Western New Guinea",
22169 aliases: ["ID-PP"],
22171 groups: ["035", "142", "UN"],
22173 callingCodes: ["62"]
22176 type: "MultiPolygon",
22177 coordinates: [[[[135.49042, -9.2276], [141.01842, -9.35091], [141.01763, -6.90181], [140.90448, -6.85033], [140.85295, -6.72996], [140.99813, -6.3233], [141.02352, 0.08993], [129.63187, 2.21409], [129.71519, -0.24692], [128.40647, -2.30349], [130.8468, -2.61103], [132.8312, -4.70282], [135.35517, -5.01442], [135.49042, -9.2276]]]]
22183 nameEn: "Balearic Islands",
22184 aliases: ["ES-IB"],
22186 groups: ["EU", "039", "150", "UN"],
22187 callingCodes: ["34 971"]
22190 type: "MultiPolygon",
22191 coordinates: [[[[-2.27707, 35.35051], [5.10072, 39.89531], [3.75438, 42.33445], [-2.27707, 35.35051]]]]
22198 aliases: ["ES-CE"],
22200 groups: ["EA", "EU", "015", "002", "UN"],
22201 level: "subterritory",
22202 callingCodes: ["34"]
22205 type: "MultiPolygon",
22206 coordinates: [[[[-5.38491, 35.92591], [-5.37338, 35.88417], [-5.35844, 35.87375], [-5.34379, 35.8711], [-5.21179, 35.90091], [-5.38491, 35.92591]]]]
22213 aliases: ["ES-ML"],
22215 groups: ["EA", "EU", "015", "002", "UN"],
22216 level: "subterritory",
22217 callingCodes: ["34"]
22220 type: "MultiPolygon",
22221 coordinates: [[[[-2.91909, 35.33927], [-2.96038, 35.31609], [-2.96648, 35.30475], [-2.96978, 35.29459], [-2.97035, 35.28852], [-2.96507, 35.28801], [-2.96826, 35.28296], [-2.96516, 35.27967], [-2.95431, 35.2728], [-2.95065, 35.26576], [-2.93893, 35.26737], [-2.92272, 35.27509], [-2.91909, 35.33927]]]]
22229 groups: ["151", "150", "UN"],
22230 level: "subterritory",
22231 callingCodes: ["7"]
22234 type: "MultiPolygon",
22235 coordinates: [[[[33.5, 44], [36.4883, 45.0488], [36.475, 45.2411], [36.5049, 45.3136], [36.6545, 45.3417], [36.6645, 45.4514], [35.0498, 45.7683], [34.9601, 45.7563], [34.7991, 45.8101], [34.8015, 45.9005], [34.7548, 45.907], [34.6668, 45.9714], [34.6086, 45.9935], [34.5589, 45.9935], [34.5201, 45.951], [34.4873, 45.9427], [34.4415, 45.9599], [34.4122, 46.0025], [34.3391, 46.0611], [34.2511, 46.0532], [34.181, 46.068], [34.1293, 46.1049], [34.0731, 46.1177], [34.0527, 46.1084], [33.9155, 46.1594], [33.8523, 46.1986], [33.7972, 46.2048], [33.7405, 46.1855], [33.646, 46.2303], [33.6152, 46.2261], [33.6385, 46.1415], [33.6147, 46.1356], [33.5732, 46.1032], [33.5909, 46.0601], [33.5597, 46.0307], [31.5, 45.5], [33.5, 44]]]]
22240 wikidata: "Q12837",
22242 level: "sharedLandform"
22248 wikidata: "Q14056",
22249 nameEn: "Jan Mayen",
22250 aliases: ["NO-22"],
22252 groups: ["SJ", "154", "150", "UN"],
22253 level: "subterritory"
22256 type: "MultiPolygon",
22257 coordinates: [[[[-9.18243, 72.23144], [-10.71459, 70.09565], [-5.93364, 70.76368], [-9.18243, 72.23144]]]]
22262 wikidata: "Q19188",
22263 nameEn: "Mainland China",
22265 groups: ["030", "142", "UN"],
22266 callingCodes: ["86"]
22269 type: "MultiPolygon",
22270 coordinates: [[[[125.6131, 53.07229], [125.17522, 53.20225], [124.46078, 53.21881], [123.86158, 53.49391], [123.26989, 53.54843], [122.85966, 53.47395], [122.35063, 53.49565], [121.39213, 53.31888], [120.85633, 53.28499], [120.0451, 52.7359], [120.04049, 52.58773], [120.46454, 52.63811], [120.71673, 52.54099], [120.61346, 52.32447], [120.77337, 52.20805], [120.65907, 51.93544], [120.10963, 51.671], [119.13553, 50.37412], [119.38598, 50.35162], [119.27996, 50.13348], [119.11003, 50.00276], [118.61623, 49.93809], [117.82343, 49.52696], [117.48208, 49.62324], [117.27597, 49.62544], [116.71193, 49.83813], [116.03781, 48.87014], [116.06565, 48.81716], [115.78876, 48.51781], [115.811, 48.25699], [115.52082, 48.15367], [115.57128, 47.91988], [115.94296, 47.67741], [116.21879, 47.88505], [116.4465, 47.83662], [116.67405, 47.89039], [116.9723, 47.87285], [117.37875, 47.63627], [117.50181, 47.77216], [117.80196, 48.01661], [118.03676, 48.00982], [118.11009, 48.04], [118.22677, 48.03853], [118.29654, 48.00246], [118.55766, 47.99277], [118.7564, 47.76947], [119.12343, 47.66458], [119.13995, 47.53997], [119.35892, 47.48104], [119.31964, 47.42617], [119.54918, 47.29505], [119.56019, 47.24874], [119.62403, 47.24575], [119.71209, 47.19192], [119.85518, 46.92196], [119.91242, 46.90091], [119.89261, 46.66423], [119.80455, 46.67631], [119.77373, 46.62947], [119.68127, 46.59015], [119.65265, 46.62342], [119.42827, 46.63783], [119.32827, 46.61433], [119.24978, 46.64761], [119.10448, 46.65516], [119.00541, 46.74273], [118.92616, 46.72765], [118.89974, 46.77139], [118.8337, 46.77742], [118.78747, 46.68689], [118.30534, 46.73519], [117.69554, 46.50991], [117.60748, 46.59771], [117.41782, 46.57862], [117.36609, 46.36335], [116.83166, 46.38637], [116.75551, 46.33083], [116.58612, 46.30211], [116.26678, 45.96479], [116.24012, 45.8778], [116.27366, 45.78637], [116.16989, 45.68603], [115.60329, 45.44717], [114.94546, 45.37377], [114.74612, 45.43585], [114.54801, 45.38337], [114.5166, 45.27189], [113.70918, 44.72891], [112.74662, 44.86297], [112.4164, 45.06858], [111.98695, 45.09074], [111.76275, 44.98032], [111.40498, 44.3461], [111.96289, 43.81596], [111.93776, 43.68709], [111.79758, 43.6637], [111.59087, 43.51207], [111.0149, 43.3289], [110.4327, 42.78293], [110.08401, 42.6411], [109.89402, 42.63111], [109.452, 42.44842], [109.00679, 42.45302], [108.84489, 42.40246], [107.57258, 42.40898], [107.49681, 42.46221], [107.29755, 42.41395], [107.24774, 42.36107], [106.76517, 42.28741], [105.0123, 41.63188], [104.51667, 41.66113], [104.52258, 41.8706], [103.92804, 41.78246], [102.72403, 42.14675], [102.07645, 42.22519], [101.80515, 42.50074], [100.84979, 42.67087], [100.33297, 42.68231], [99.50671, 42.56535], [97.1777, 42.7964], [96.37926, 42.72055], [96.35658, 42.90363], [95.89543, 43.2528], [95.52594, 43.99353], [95.32891, 44.02407], [95.39772, 44.2805], [95.01191, 44.25274], [94.71959, 44.35284], [94.10003, 44.71016], [93.51161, 44.95964], [91.64048, 45.07408], [90.89169, 45.19667], [90.65114, 45.49314], [90.70907, 45.73437], [91.03026, 46.04194], [90.99672, 46.14207], [90.89639, 46.30711], [91.07696, 46.57315], [91.0147, 46.58171], [91.03649, 46.72916], [90.84035, 46.99525], [90.76108, 46.99399], [90.48542, 47.30438], [90.48854, 47.41826], [90.33598, 47.68303], [90.10871, 47.7375], [90.06512, 47.88177], [89.76624, 47.82745], [89.55453, 48.0423], [89.0711, 47.98528], [88.93186, 48.10263], [88.8011, 48.11302], [88.58316, 48.21893], [88.58939, 48.34531], [87.96361, 48.58478], [88.0788, 48.71436], [87.73822, 48.89582], [87.88171, 48.95853], [87.81333, 49.17354], [87.48983, 49.13794], [87.478, 49.07403], [87.28386, 49.11626], [86.87238, 49.12432], [86.73568, 48.99918], [86.75343, 48.70331], [86.38069, 48.46064], [85.73581, 48.3939], [85.5169, 48.05493], [85.61067, 47.49753], [85.69696, 47.2898], [85.54294, 47.06171], [85.22443, 47.04816], [84.93995, 46.87399], [84.73077, 47.01394], [83.92184, 46.98912], [83.04622, 47.19053], [82.21792, 45.56619], [82.58474, 45.40027], [82.51374, 45.1755], [81.73278, 45.3504], [80.11169, 45.03352], [79.8987, 44.89957], [80.38384, 44.63073], [80.40229, 44.23319], [80.40031, 44.10986], [80.75156, 43.44948], [80.69718, 43.32589], [80.77771, 43.30065], [80.78817, 43.14235], [80.62913, 43.141], [80.3735, 43.01557], [80.58999, 42.9011], [80.38169, 42.83142], [80.26886, 42.8366], [80.16892, 42.61137], [80.26841, 42.23797], [80.17807, 42.21166], [80.17842, 42.03211], [79.92977, 42.04113], [78.3732, 41.39603], [78.15757, 41.38565], [78.12873, 41.23091], [77.81287, 41.14307], [77.76206, 41.01574], [77.52723, 41.00227], [77.3693, 41.0375], [77.28004, 41.0033], [76.99302, 41.0696], [76.75681, 40.95354], [76.5261, 40.46114], [76.33659, 40.3482], [75.96168, 40.38064], [75.91361, 40.2948], [75.69663, 40.28642], [75.5854, 40.66874], [75.22834, 40.45382], [75.08243, 40.43945], [74.82013, 40.52197], [74.78168, 40.44886], [74.85996, 40.32857], [74.69875, 40.34668], [74.35063, 40.09742], [74.25533, 40.13191], [73.97049, 40.04378], [73.83006, 39.76136], [73.9051, 39.75073], [73.92354, 39.69565], [73.94683, 39.60733], [73.87018, 39.47879], [73.59831, 39.46425], [73.59241, 39.40843], [73.5004, 39.38402], [73.55396, 39.3543], [73.54572, 39.27567], [73.60638, 39.24534], [73.75823, 39.023], [73.81728, 39.04007], [73.82964, 38.91517], [73.7445, 38.93867], [73.7033, 38.84782], [73.80656, 38.66449], [73.79806, 38.61106], [73.97933, 38.52945], [74.17022, 38.65504], [74.51217, 38.47034], [74.69619, 38.42947], [74.69894, 38.22155], [74.80331, 38.19889], [74.82665, 38.07359], [74.9063, 38.03033], [74.92416, 37.83428], [75.00935, 37.77486], [74.8912, 37.67576], [74.94338, 37.55501], [75.06011, 37.52779], [75.15899, 37.41443], [75.09719, 37.37297], [75.12328, 37.31839], [74.88887, 37.23275], [74.80605, 37.21565], [74.49981, 37.24518], [74.56453, 37.03023], [75.13839, 37.02622], [75.40481, 36.95382], [75.45562, 36.71971], [75.72737, 36.7529], [75.92391, 36.56986], [76.0324, 36.41198], [76.00906, 36.17511], [75.93028, 36.13136], [76.15325, 35.9264], [76.14913, 35.82848], [76.33453, 35.84296], [76.50961, 35.8908], [76.77323, 35.66062], [76.84539, 35.67356], [76.96624, 35.5932], [77.44277, 35.46132], [77.70232, 35.46244], [77.80532, 35.52058], [78.11664, 35.48022], [78.03466, 35.3785], [78.00033, 35.23954], [78.22692, 34.88771], [78.18435, 34.7998], [78.27781, 34.61484], [78.54964, 34.57283], [78.56475, 34.50835], [78.74465, 34.45174], [79.05364, 34.32482], [78.99802, 34.3027], [78.91769, 34.15452], [78.66225, 34.08858], [78.65657, 34.03195], [78.73367, 34.01121], [78.77349, 33.73871], [78.67599, 33.66445], [78.73636, 33.56521], [79.15252, 33.17156], [79.14016, 33.02545], [79.46562, 32.69668], [79.26768, 32.53277], [79.13174, 32.47766], [79.0979, 32.38051], [78.99322, 32.37948], [78.96713, 32.33655], [78.7831, 32.46873], [78.73916, 32.69438], [78.38897, 32.53938], [78.4645, 32.45367], [78.49609, 32.2762], [78.68754, 32.10256], [78.74404, 32.00384], [78.78036, 31.99478], [78.69933, 31.78723], [78.84516, 31.60631], [78.71032, 31.50197], [78.77898, 31.31209], [78.89344, 31.30481], [79.01931, 31.42817], [79.14016, 31.43403], [79.30694, 31.17357], [79.59884, 30.93943], [79.93255, 30.88288], [80.20721, 30.58541], [80.54504, 30.44936], [80.83343, 30.32023], [81.03953, 30.20059], [81.12842, 30.01395], [81.24362, 30.0126], [81.29032, 30.08806], [81.2623, 30.14596], [81.33355, 30.15303], [81.39928, 30.21862], [81.41018, 30.42153], [81.5459, 30.37688], [81.62033, 30.44703], [81.99082, 30.33423], [82.10135, 30.35439], [82.10757, 30.23745], [82.19475, 30.16884], [82.16984, 30.0692], [82.38622, 30.02608], [82.5341, 29.9735], [82.73024, 29.81695], [83.07116, 29.61957], [83.28131, 29.56813], [83.44787, 29.30513], [83.63156, 29.16249], [83.82303, 29.30513], [83.97559, 29.33091], [84.18107, 29.23451], [84.24801, 29.02783], [84.2231, 28.89571], [84.47528, 28.74023], [84.62317, 28.73887], [84.85511, 28.58041], [85.06059, 28.68562], [85.19135, 28.62825], [85.18668, 28.54076], [85.10729, 28.34092], [85.38127, 28.28336], [85.4233, 28.32996], [85.59765, 28.30529], [85.60854, 28.25045], [85.69105, 28.38475], [85.71907, 28.38064], [85.74864, 28.23126], [85.84672, 28.18187], [85.90743, 28.05144], [85.97813, 27.99023], [85.94946, 27.9401], [86.06309, 27.90021], [86.12069, 27.93047], [86.08333, 28.02121], [86.088, 28.09264], [86.18607, 28.17364], [86.22966, 27.9786], [86.42736, 27.91122], [86.51609, 27.96623], [86.56265, 28.09569], [86.74181, 28.10638], [86.75582, 28.04182], [87.03757, 27.94835], [87.11696, 27.84104], [87.56996, 27.84517], [87.72718, 27.80938], [87.82681, 27.95248], [88.13378, 27.88015], [88.1278, 27.95417], [88.25332, 27.9478], [88.54858, 28.06057], [88.63235, 28.12356], [88.83559, 28.01936], [88.88091, 27.85192], [88.77517, 27.45415], [88.82981, 27.38814], [88.91901, 27.32483], [88.93678, 27.33777], [88.96947, 27.30319], [89.00216, 27.32532], [88.95355, 27.4106], [88.97213, 27.51671], [89.0582, 27.60985], [89.12825, 27.62502], [89.59525, 28.16433], [89.79762, 28.23979], [90.13387, 28.19178], [90.58842, 28.02838], [90.69894, 28.07784], [91.20019, 27.98715], [91.25779, 28.07509], [91.46327, 28.0064], [91.48973, 27.93903], [91.5629, 27.84823], [91.6469, 27.76358], [91.84722, 27.76325], [91.87057, 27.7195], [92.27432, 27.89077], [92.32101, 27.79363], [92.42538, 27.80092], [92.7275, 27.98662], [92.73025, 28.05814], [92.65472, 28.07632], [92.67486, 28.15018], [92.93075, 28.25671], [93.14635, 28.37035], [93.18069, 28.50319], [93.44621, 28.67189], [93.72797, 28.68821], [94.35897, 29.01965], [94.2752, 29.11687], [94.69318, 29.31739], [94.81353, 29.17804], [95.0978, 29.14446], [95.11291, 29.09527], [95.2214, 29.10727], [95.26122, 29.07727], [95.3038, 29.13847], [95.41091, 29.13007], [95.50842, 29.13487], [95.72086, 29.20797], [95.75149, 29.32063], [95.84899, 29.31464], [96.05361, 29.38167], [96.31316, 29.18643], [96.18682, 29.11087], [96.20467, 29.02325], [96.3626, 29.10607], [96.61391, 28.72742], [96.40929, 28.51526], [96.48895, 28.42955], [96.6455, 28.61657], [96.85561, 28.4875], [96.88445, 28.39452], [96.98882, 28.32564], [97.1289, 28.3619], [97.34547, 28.21385], [97.41729, 28.29783], [97.47085, 28.2688], [97.50518, 28.49716], [97.56835, 28.55628], [97.70705, 28.5056], [97.79632, 28.33168], [97.90069, 28.3776], [98.15337, 28.12114], [98.13964, 27.9478], [98.32641, 27.51385], [98.42529, 27.55404], [98.43353, 27.67086], [98.69582, 27.56499], [98.7333, 26.85615], [98.77547, 26.61994], [98.72741, 26.36183], [98.67797, 26.24487], [98.7329, 26.17218], [98.66884, 26.09165], [98.63128, 26.15492], [98.57085, 26.11547], [98.60763, 26.01512], [98.70818, 25.86241], [98.63128, 25.79937], [98.54064, 25.85129], [98.40606, 25.61129], [98.31268, 25.55307], [98.25774, 25.6051], [98.16848, 25.62739], [98.18084, 25.56298], [98.12591, 25.50722], [98.14925, 25.41547], [97.92541, 25.20815], [97.83614, 25.2715], [97.77023, 25.11492], [97.72216, 25.08508], [97.72903, 24.91332], [97.79949, 24.85655], [97.76481, 24.8289], [97.73127, 24.83015], [97.70181, 24.84557], [97.64354, 24.79171], [97.56648, 24.76475], [97.56383, 24.75535], [97.5542, 24.74943], [97.54675, 24.74202], [97.56525, 24.72838], [97.56286, 24.54535], [97.52757, 24.43748], [97.60029, 24.4401], [97.66998, 24.45288], [97.7098, 24.35658], [97.65624, 24.33781], [97.66723, 24.30027], [97.71941, 24.29652], [97.76799, 24.26365], [97.72998, 24.2302], [97.72799, 24.18883], [97.75305, 24.16902], [97.72903, 24.12606], [97.62363, 24.00506], [97.5247, 23.94032], [97.64667, 23.84574], [97.72302, 23.89288], [97.79456, 23.94836], [97.79416, 23.95663], [97.84328, 23.97603], [97.86545, 23.97723], [97.88811, 23.97446], [97.8955, 23.97758], [97.89676, 23.97931], [97.89683, 23.98389], [97.88814, 23.98605], [97.88414, 23.99405], [97.88616, 24.00463], [97.90998, 24.02094], [97.93951, 24.01953], [97.98691, 24.03897], [97.99583, 24.04932], [98.04709, 24.07616], [98.05302, 24.07408], [98.05671, 24.07961], [98.0607, 24.07812], [98.06703, 24.08028], [98.07806, 24.07988], [98.20666, 24.11406], [98.54476, 24.13119], [98.59256, 24.08371], [98.85319, 24.13042], [98.87998, 24.15624], [98.89632, 24.10612], [98.67797, 23.9644], [98.68209, 23.80492], [98.79607, 23.77947], [98.82933, 23.72921], [98.81775, 23.694], [98.88396, 23.59555], [98.80294, 23.5345], [98.82877, 23.47908], [98.87683, 23.48995], [98.92104, 23.36946], [98.87573, 23.33038], [98.93958, 23.31414], [98.92515, 23.29535], [98.88597, 23.18656], [99.05975, 23.16382], [99.04601, 23.12215], [99.25741, 23.09025], [99.34127, 23.13099], [99.52214, 23.08218], [99.54218, 22.90014], [99.43537, 22.94086], [99.45654, 22.85726], [99.31243, 22.73893], [99.38247, 22.57544], [99.37972, 22.50188], [99.28771, 22.4105], [99.17318, 22.18025], [99.19176, 22.16983], [99.1552, 22.15874], [99.33166, 22.09656], [99.47585, 22.13345], [99.85351, 22.04183], [99.96612, 22.05965], [99.99084, 21.97053], [99.94003, 21.82782], [99.98654, 21.71064], [100.04956, 21.66843], [100.12679, 21.70539], [100.17486, 21.65306], [100.10757, 21.59945], [100.12542, 21.50365], [100.1625, 21.48704], [100.18447, 21.51898], [100.25863, 21.47043], [100.35201, 21.53176], [100.42892, 21.54325], [100.4811, 21.46148], [100.57861, 21.45637], [100.72143, 21.51898], [100.87265, 21.67396], [101.11744, 21.77659], [101.15156, 21.56129], [101.2124, 21.56422], [101.19349, 21.41959], [101.26912, 21.36482], [101.2229, 21.23271], [101.29326, 21.17254], [101.54563, 21.25668], [101.6068, 21.23329], [101.59491, 21.18621], [101.60886, 21.17947], [101.66977, 21.20004], [101.70548, 21.14911], [101.7622, 21.14813], [101.79266, 21.19025], [101.76745, 21.21571], [101.83887, 21.20983], [101.84412, 21.25291], [101.74014, 21.30967], [101.74224, 21.48276], [101.7727, 21.51794], [101.7475, 21.5873], [101.80001, 21.57461], [101.83257, 21.61562], [101.74555, 21.72852], [101.7791, 21.83019], [101.62566, 21.96574], [101.57525, 22.13026], [101.60675, 22.13513], [101.53638, 22.24794], [101.56789, 22.28876], [101.61306, 22.27515], [101.68973, 22.46843], [101.7685, 22.50337], [101.86828, 22.38397], [101.90714, 22.38688], [101.91344, 22.44417], [101.98487, 22.42766], [102.03633, 22.46164], [102.1245, 22.43372], [102.14099, 22.40092], [102.16621, 22.43336], [102.26428, 22.41321], [102.25339, 22.4607], [102.41061, 22.64184], [102.38415, 22.67919], [102.42618, 22.69212], [102.46665, 22.77108], [102.51802, 22.77969], [102.57095, 22.7036], [102.60675, 22.73376], [102.8636, 22.60735], [102.9321, 22.48659], [103.0722, 22.44775], [103.07843, 22.50097], [103.17961, 22.55705], [103.15782, 22.59873], [103.18895, 22.64471], [103.28079, 22.68063], [103.32282, 22.8127], [103.43179, 22.75816], [103.43646, 22.70648], [103.52675, 22.59155], [103.57812, 22.65764], [103.56255, 22.69499], [103.64506, 22.79979], [103.87904, 22.56683], [103.93286, 22.52703], [103.94513, 22.52553], [103.95191, 22.5134], [103.96352, 22.50584], [103.96783, 22.51173], [103.97384, 22.50634], [103.99247, 22.51958], [104.01088, 22.51823], [104.03734, 22.72945], [104.11384, 22.80363], [104.27084, 22.8457], [104.25683, 22.76534], [104.35593, 22.69353], [104.47225, 22.75813], [104.58122, 22.85571], [104.60457, 22.81841], [104.65283, 22.83419], [104.72755, 22.81984], [104.77114, 22.90017], [104.84942, 22.93631], [104.86765, 22.95178], [104.8334, 23.01484], [104.79478, 23.12934], [104.87382, 23.12854], [104.87992, 23.17141], [104.91435, 23.18666], [104.9486, 23.17235], [104.96532, 23.20463], [104.98712, 23.19176], [105.07002, 23.26248], [105.11672, 23.25247], [105.17276, 23.28679], [105.22569, 23.27249], [105.32376, 23.39684], [105.40782, 23.28107], [105.42805, 23.30824], [105.49966, 23.20669], [105.56037, 23.16806], [105.57594, 23.075], [105.72382, 23.06641], [105.8726, 22.92756], [105.90119, 22.94168], [105.99568, 22.94178], [106.00179, 22.99049], [106.19705, 22.98475], [106.27022, 22.87722], [106.34961, 22.86718], [106.49749, 22.91164], [106.51306, 22.94891], [106.55976, 22.92311], [106.60179, 22.92884], [106.6516, 22.86862], [106.6734, 22.89587], [106.71387, 22.88296], [106.71128, 22.85982], [106.78422, 22.81532], [106.81271, 22.8226], [106.83685, 22.8098], [106.82404, 22.7881], [106.76293, 22.73491], [106.72321, 22.63606], [106.71698, 22.58432], [106.65316, 22.5757], [106.61269, 22.60301], [106.58395, 22.474], [106.55665, 22.46498], [106.57221, 22.37], [106.55976, 22.34841], [106.6516, 22.33977], [106.69986, 22.22309], [106.67495, 22.1885], [106.6983, 22.15102], [106.70142, 22.02409], [106.68274, 21.99811], [106.69276, 21.96013], [106.72551, 21.97923], [106.74345, 22.00965], [106.81038, 21.97934], [106.9178, 21.97357], [106.92714, 21.93459], [106.97228, 21.92592], [106.99252, 21.95191], [107.05634, 21.92303], [107.06101, 21.88982], [107.00964, 21.85948], [107.02615, 21.81981], [107.10771, 21.79879], [107.20734, 21.71493], [107.24625, 21.7077], [107.29296, 21.74674], [107.35834, 21.6672], [107.35989, 21.60063], [107.38636, 21.59774], [107.41593, 21.64839], [107.47197, 21.6672], [107.49532, 21.62958], [107.49065, 21.59774], [107.54047, 21.5934], [107.56537, 21.61945], [107.66967, 21.60787], [107.80355, 21.66141], [107.86114, 21.65128], [107.90006, 21.5905], [107.92652, 21.58906], [107.95232, 21.5388], [107.96774, 21.53601], [107.97074, 21.54072], [107.97383, 21.53961], [107.97932, 21.54503], [108.02926, 21.54997], [108.0569, 21.53604], [108.10003, 21.47338], [108.00365, 17.98159], [111.60491, 13.57105], [118.41371, 24.06775], [118.11703, 24.39734], [118.28244, 24.51231], [118.35291, 24.51645], [118.42453, 24.54644], [118.56434, 24.49266], [120.49232, 25.22863], [121.03532, 26.8787], [123.5458, 31.01942], [122.29378, 31.76513], [122.80525, 33.30571], [123.85601, 37.49093], [123.90497, 38.79949], [124.17532, 39.8232], [124.23201, 39.9248], [124.35029, 39.95639], [124.37089, 40.03004], [124.3322, 40.05573], [124.38556, 40.11047], [124.40719, 40.13655], [124.86913, 40.45387], [125.71172, 40.85223], [125.76869, 40.87908], [126.00335, 40.92835], [126.242, 41.15454], [126.53189, 41.35206], [126.60631, 41.65565], [126.90729, 41.79955], [127.17841, 41.59714], [127.29712, 41.49473], [127.92943, 41.44291], [128.02633, 41.42103], [128.03311, 41.39232], [128.12967, 41.37931], [128.18546, 41.41279], [128.20061, 41.40895], [128.30716, 41.60322], [128.15119, 41.74568], [128.04487, 42.01769], [128.94007, 42.03537], [128.96068, 42.06657], [129.15178, 42.17224], [129.22285, 42.26491], [129.22423, 42.3553], [129.28541, 42.41574], [129.42882, 42.44702], [129.54701, 42.37254], [129.60482, 42.44461], [129.72541, 42.43739], [129.75294, 42.59409], [129.77183, 42.69435], [129.7835, 42.76521], [129.80719, 42.79218], [129.83277, 42.86746], [129.85261, 42.96494], [129.8865, 43.00395], [129.95082, 43.01051], [129.96409, 42.97306], [130.12957, 42.98361], [130.09764, 42.91425], [130.26095, 42.9027], [130.23068, 42.80125], [130.2385, 42.71127], [130.41826, 42.6011], [130.44361, 42.54849], [130.50123, 42.61636], [130.55143, 42.52158], [130.62107, 42.58413], [130.56576, 42.68925], [130.40213, 42.70788], [130.44361, 42.76205], [130.66524, 42.84753], [131.02438, 42.86518], [131.02668, 42.91246], [131.135, 42.94114], [131.10274, 43.04734], [131.20414, 43.13654], [131.19031, 43.21385], [131.30324, 43.39498], [131.29402, 43.46695], [131.19492, 43.53047], [131.21105, 43.82383], [131.26176, 43.94011], [131.23583, 43.96085], [131.25484, 44.03131], [131.30365, 44.04262], [131.1108, 44.70266], [130.95639, 44.85154], [131.48415, 44.99513], [131.68466, 45.12374], [131.66852, 45.2196], [131.76532, 45.22609], [131.86903, 45.33636], [131.99417, 45.2567], [132.83978, 45.05916], [132.96373, 45.0212], [133.12293, 45.1332], [133.09279, 45.25693], [133.19419, 45.51913], [133.41083, 45.57723], [133.48457, 45.86203], [133.60442, 45.90053], [133.67569, 45.9759], [133.72695, 46.05576], [133.68047, 46.14697], [133.88097, 46.25066], [133.91496, 46.4274], [133.84104, 46.46681], [134.03538, 46.75668], [134.20016, 47.33458], [134.50898, 47.4812], [134.7671, 47.72051], [134.55508, 47.98651], [134.67098, 48.1564], [134.75328, 48.36763], [134.49516, 48.42884], [132.66989, 47.96491], [132.57309, 47.71741], [131.90448, 47.68011], [131.2635, 47.73325], [131.09871, 47.6852], [130.95985, 47.6957], [130.90915, 47.90623], [130.65103, 48.10052], [130.84462, 48.30942], [130.52147, 48.61745], [130.66946, 48.88251], [130.43232, 48.90844], [130.2355, 48.86741], [129.85416, 49.11067], [129.67598, 49.29596], [129.50685, 49.42398], [129.40398, 49.44194], [129.35317, 49.3481], [129.23232, 49.40353], [129.11153, 49.36813], [128.72896, 49.58676], [127.83476, 49.5748], [127.53516, 49.84306], [127.49299, 50.01251], [127.60515, 50.23503], [127.37384, 50.28393], [127.36009, 50.43787], [127.28765, 50.46585], [127.36335, 50.58306], [127.28165, 50.72075], [127.14586, 50.91152], [126.93135, 51.0841], [126.90369, 51.3238], [126.68349, 51.70607], [126.44606, 51.98254], [126.558, 52.13738], [125.6131, 53.07229]], [[113.56865, 22.20973], [113.57123, 22.20416], [113.60504, 22.20464], [113.63011, 22.10782], [113.57191, 22.07696], [113.54839, 22.10909], [113.54942, 22.14519], [113.54093, 22.15497], [113.52659, 22.18271], [113.53552, 22.20607], [113.53301, 22.21235], [113.53591, 22.21369], [113.54093, 22.21314], [113.54333, 22.21688], [113.5508, 22.21672], [113.56865, 22.20973]], [[114.50148, 22.15017], [113.92195, 22.13873], [113.83338, 22.1826], [113.81621, 22.2163], [113.86771, 22.42972], [114.03113, 22.5065], [114.05438, 22.5026], [114.05729, 22.51104], [114.06272, 22.51617], [114.07267, 22.51855], [114.07817, 22.52997], [114.08606, 22.53276], [114.09048, 22.53716], [114.09692, 22.53435], [114.1034, 22.5352], [114.11181, 22.52878], [114.11656, 22.53415], [114.12665, 22.54003], [114.13823, 22.54319], [114.1482, 22.54091], [114.15123, 22.55163], [114.1597, 22.56041], [114.17247, 22.55944], [114.18338, 22.55444], [114.20655, 22.55706], [114.22185, 22.55343], [114.22888, 22.5436], [114.25154, 22.55977], [114.44998, 22.55977], [114.50148, 22.15017]]]]
22275 wikidata: "Q22890",
22277 level: "sharedLandform"
22283 wikidata: "Q23666",
22284 nameEn: "Great Britain",
22286 level: "sharedLandform"
22292 wikidata: "Q23681",
22293 nameEn: "Northern Cyprus",
22294 groups: ["Q644636", "145", "142"],
22296 callingCodes: ["90 392"]
22299 type: "MultiPolygon",
22300 coordinates: [[[[33.67678, 35.03866], [33.67742, 35.05963], [33.68474, 35.06602], [33.69095, 35.06237], [33.70861, 35.07644], [33.7161, 35.07279], [33.70209, 35.04882], [33.71482, 35.03722], [33.73824, 35.05321], [33.76106, 35.04253], [33.78581, 35.05104], [33.82067, 35.07826], [33.84168, 35.06823], [33.8541, 35.07201], [33.87479, 35.08881], [33.87097, 35.09389], [33.87622, 35.10457], [33.87224, 35.12293], [33.88561, 35.12449], [33.88943, 35.12007], [33.88737, 35.11408], [33.89853, 35.11377], [33.91789, 35.08688], [33.91299, 35.07579], [33.90247, 35.07686], [33.89485, 35.06873], [33.88367, 35.07877], [33.85261, 35.0574], [33.8355, 35.05777], [33.82051, 35.0667], [33.8012, 35.04786], [33.81524, 35.04192], [33.83055, 35.02865], [33.82875, 35.01685], [33.84045, 35.00616], [33.85216, 35.00579], [33.85891, 35.001], [33.85621, 34.98956], [33.83505, 34.98108], [33.84811, 34.97075], [33.86432, 34.97592], [33.90075, 34.96623], [33.98684, 34.76642], [35.48515, 34.70851], [35.51152, 36.10954], [32.82353, 35.70297], [32.46489, 35.48584], [32.60361, 35.16647], [32.64864, 35.19967], [32.70947, 35.18328], [32.70779, 35.14127], [32.85733, 35.07742], [32.86406, 35.1043], [32.94471, 35.09422], [33.01192, 35.15639], [33.08249, 35.17319], [33.11105, 35.15639], [33.15138, 35.19504], [33.27068, 35.16815], [33.3072, 35.16816], [33.31955, 35.18096], [33.35056, 35.18328], [33.34964, 35.17803], [33.35596, 35.17942], [33.35612, 35.17402], [33.36569, 35.17479], [33.3717, 35.1788], [33.37248, 35.18698], [33.38575, 35.2018], [33.4076, 35.20062], [33.41675, 35.16325], [33.46813, 35.10564], [33.48136, 35.0636], [33.47825, 35.04103], [33.45178, 35.02078], [33.45256, 35.00288], [33.47666, 35.00701], [33.48915, 35.06594], [33.53975, 35.08151], [33.57478, 35.06049], [33.567, 35.04803], [33.59658, 35.03635], [33.61215, 35.0527], [33.63765, 35.03869], [33.67678, 35.03866]]]]
22305 wikidata: "Q25231",
22306 nameEn: "Svalbard",
22307 aliases: ["NO-21"],
22309 groups: ["SJ", "154", "150", "UN"],
22310 level: "subterritory",
22311 callingCodes: ["47 79"]
22314 type: "MultiPolygon",
22315 coordinates: [[[[-7.49892, 77.24208], [32.07813, 72.01005], [36.85549, 84.09565], [-7.49892, 77.24208]]]]
22320 wikidata: "Q25263",
22322 aliases: ["PT-20"],
22324 groups: ["Q3320166", "Q2914565", "Q105472", "EU", "039", "150", "UN"],
22325 callingCodes: ["351"]
22328 type: "MultiPolygon",
22329 coordinates: [[[[-23.12984, 40.26428], [-36.43765, 41.39418], [-22.54767, 33.34416], [-23.12984, 40.26428]]]]
22334 wikidata: "Q25359",
22335 nameEn: "Navassa Island",
22336 aliases: ["UM-76"],
22338 groups: ["UM", "Q1352230", "029", "003", "419", "019", "UN"],
22339 level: "subterritory",
22340 roadSpeedUnit: "mph",
22341 roadHeightUnit: "ft"
22344 type: "MultiPolygon",
22345 coordinates: [[[[-74.7289, 18.71009], [-75.71816, 18.46438], [-74.76465, 18.06252], [-74.7289, 18.71009]]]]
22350 wikidata: "Q25396",
22352 aliases: ["BQ-BO", "NL-BQ1"],
22354 groups: ["Q1451600", "BQ", "029", "003", "419", "019", "UN"],
22355 level: "subterritory",
22356 callingCodes: ["599 7"]
22359 type: "MultiPolygon",
22360 coordinates: [[[[-67.89186, 12.4116], [-68.90012, 12.62309], [-68.33524, 11.78151], [-68.01417, 11.77722], [-67.89186, 12.4116]]]]
22365 wikidata: "Q25528",
22367 aliases: ["BQ-SA", "NL-BQ2"],
22369 groups: ["Q1451600", "BQ", "029", "003", "419", "019", "UN"],
22370 level: "subterritory",
22371 callingCodes: ["599 4"]
22374 type: "MultiPolygon",
22375 coordinates: [[[[-63.07669, 17.79659], [-63.81314, 17.95045], [-63.22932, 17.32592], [-63.07669, 17.79659]]]]
22380 wikidata: "Q26180",
22381 nameEn: "Sint Eustatius",
22382 aliases: ["BQ-SE", "NL-BQ3"],
22384 groups: ["Q1451600", "BQ", "029", "003", "419", "019", "UN"],
22385 level: "subterritory",
22386 callingCodes: ["599 3"]
22389 type: "MultiPolygon",
22390 coordinates: [[[[-63.07669, 17.79659], [-63.34999, 16.94218], [-62.76692, 17.64353], [-63.07669, 17.79659]]]]
22395 wikidata: "Q26253",
22397 aliases: ["PT-30"],
22399 groups: ["Q3320166", "Q2914565", "Q105472", "EU", "039", "150", "UN"],
22400 callingCodes: ["351"]
22403 type: "MultiPolygon",
22404 coordinates: [[[[-19.30302, 33.65304], [-16.04789, 29.65076], [-11.68307, 33.12333], [-19.30302, 33.65304]]]]
22409 wikidata: "Q26927",
22410 nameEn: "Lakshadweep",
22411 aliases: ["IN-LD"],
22413 groups: ["034", "142", "UN"],
22415 callingCodes: ["91"]
22418 type: "MultiPolygon",
22419 coordinates: [[[[67.64074, 11.57295], [76.59015, 5.591], [72.67494, 13.58102], [67.64074, 11.57295]]]]
22424 wikidata: "Q27329",
22425 nameEn: "Asian Russia",
22427 groups: ["142", "UN"],
22428 callingCodes: ["7"]
22431 type: "MultiPolygon",
22432 coordinates: [[[[-179.99933, 64.74703], [-172.76104, 63.77445], [-169.03888, 65.48473], [-168.95635, 65.98512], [-168.25765, 71.99091], [-179.9843, 71.90735], [-179.99933, 64.74703]]], [[[59.99809, 51.98263], [60.19925, 51.99173], [60.48915, 52.15175], [60.72581, 52.15538], [60.78201, 52.22067], [61.05417, 52.35096], [60.98021, 52.50068], [60.84709, 52.52228], [60.84118, 52.63912], [60.71693, 52.66245], [60.71989, 52.75923], [61.05842, 52.92217], [61.23462, 53.03227], [62.0422, 52.96105], [62.12799, 52.99133], [62.14574, 53.09626], [61.19024, 53.30536], [61.14291, 53.41481], [61.29082, 53.50992], [61.37957, 53.45887], [61.57185, 53.50112], [61.55706, 53.57144], [60.90626, 53.62937], [61.22574, 53.80268], [61.14283, 53.90063], [60.99796, 53.93699], [61.26863, 53.92797], [61.3706, 54.08464], [61.47603, 54.08048], [61.56941, 53.95703], [61.65318, 54.02445], [62.03913, 53.94768], [62.00966, 54.04134], [62.38535, 54.03961], [62.45931, 53.90737], [62.56876, 53.94047], [62.58651, 54.05871], [63.80604, 54.27079], [63.91224, 54.20013], [64.02715, 54.22679], [63.97686, 54.29763], [64.97216, 54.4212], [65.11033, 54.33028], [65.24663, 54.35721], [65.20174, 54.55216], [68.21308, 54.98645], [68.26661, 55.09226], [68.19206, 55.18823], [68.90865, 55.38148], [69.34224, 55.36344], [69.74917, 55.35545], [70.19179, 55.1476], [70.76493, 55.3027], [70.96009, 55.10558], [71.08288, 54.71253], [71.24185, 54.64965], [71.08706, 54.33376], [71.10379, 54.13326], [71.96141, 54.17736], [72.17477, 54.36303], [72.43415, 53.92685], [72.71026, 54.1161], [73.37963, 53.96132], [73.74778, 54.07194], [73.68921, 53.86522], [73.25412, 53.61532], [73.39218, 53.44623], [75.07405, 53.80831], [75.43398, 53.98652], [75.3668, 54.07439], [76.91052, 54.4677], [76.82266, 54.1798], [76.44076, 54.16017], [76.54243, 53.99329], [77.90383, 53.29807], [79.11255, 52.01171], [80.08138, 50.77658], [80.4127, 50.95581], [80.44819, 51.20855], [80.80318, 51.28262], [81.16999, 51.15662], [81.06091, 50.94833], [81.41248, 50.97524], [81.46581, 50.77658], [81.94999, 50.79307], [82.55443, 50.75412], [83.14607, 51.00796], [83.8442, 50.87375], [84.29385, 50.27257], [84.99198, 50.06793], [85.24047, 49.60239], [86.18709, 49.50259], [86.63674, 49.80136], [86.79056, 49.74787], [86.61307, 49.60239], [86.82606, 49.51796], [87.03071, 49.25142], [87.31465, 49.23603], [87.28386, 49.11626], [87.478, 49.07403], [87.48983, 49.13794], [87.81333, 49.17354], [87.98977, 49.18147], [88.15543, 49.30314], [88.17223, 49.46934], [88.42449, 49.48821], [88.82499, 49.44808], [89.70687, 49.72535], [89.59711, 49.90851], [91.86048, 50.73734], [92.07173, 50.69585], [92.44714, 50.78762], [93.01109, 50.79001], [92.99595, 50.63183], [94.30823, 50.57498], [94.39258, 50.22193], [94.49477, 50.17832], [94.6121, 50.04239], [94.97166, 50.04725], [95.02465, 49.96941], [95.74757, 49.97915], [95.80056, 50.04239], [96.97388, 49.88413], [97.24639, 49.74737], [97.56811, 49.84265], [97.56432, 49.92801], [97.76871, 49.99861], [97.85197, 49.91339], [98.29481, 50.33561], [98.31373, 50.4996], [98.06393, 50.61262], [97.9693, 50.78044], [98.01472, 50.86652], [97.83305, 51.00248], [98.05257, 51.46696], [98.22053, 51.46579], [98.33222, 51.71832], [98.74142, 51.8637], [98.87768, 52.14563], [99.27888, 51.96876], [99.75578, 51.90108], [99.89203, 51.74903], [100.61116, 51.73028], [101.39085, 51.45753], [101.5044, 51.50467], [102.14032, 51.35566], [102.32194, 50.67982], [102.71178, 50.38873], [103.70343, 50.13952], [105.32528, 50.4648], [106.05562, 50.40582], [106.07865, 50.33474], [106.47156, 50.31909], [106.49628, 50.32436], [106.51122, 50.34408], [106.58373, 50.34044], [106.80326, 50.30177], [107.00007, 50.1977], [107.1174, 50.04239], [107.36407, 49.97612], [107.96116, 49.93191], [107.95387, 49.66659], [108.27937, 49.53167], [108.53969, 49.32325], [109.18017, 49.34709], [109.51325, 49.22859], [110.24373, 49.16676], [110.39891, 49.25083], [110.64493, 49.1816], [113.02647, 49.60772], [113.20216, 49.83356], [114.325, 50.28098], [114.9703, 50.19254], [115.26068, 49.97367], [115.73602, 49.87688], [116.22402, 50.04477], [116.62502, 49.92919], [116.71193, 49.83813], [117.27597, 49.62544], [117.48208, 49.62324], [117.82343, 49.52696], [118.61623, 49.93809], [119.11003, 50.00276], [119.27996, 50.13348], [119.38598, 50.35162], [119.13553, 50.37412], [120.10963, 51.671], [120.65907, 51.93544], [120.77337, 52.20805], [120.61346, 52.32447], [120.71673, 52.54099], [120.46454, 52.63811], [120.04049, 52.58773], [120.0451, 52.7359], [120.85633, 53.28499], [121.39213, 53.31888], [122.35063, 53.49565], [122.85966, 53.47395], [123.26989, 53.54843], [123.86158, 53.49391], [124.46078, 53.21881], [125.17522, 53.20225], [125.6131, 53.07229], [126.558, 52.13738], [126.44606, 51.98254], [126.68349, 51.70607], [126.90369, 51.3238], [126.93135, 51.0841], [127.14586, 50.91152], [127.28165, 50.72075], [127.36335, 50.58306], [127.28765, 50.46585], [127.36009, 50.43787], [127.37384, 50.28393], [127.60515, 50.23503], [127.49299, 50.01251], [127.53516, 49.84306], [127.83476, 49.5748], [128.72896, 49.58676], [129.11153, 49.36813], [129.23232, 49.40353], [129.35317, 49.3481], [129.40398, 49.44194], [129.50685, 49.42398], [129.67598, 49.29596], [129.85416, 49.11067], [130.2355, 48.86741], [130.43232, 48.90844], [130.66946, 48.88251], [130.52147, 48.61745], [130.84462, 48.30942], [130.65103, 48.10052], [130.90915, 47.90623], [130.95985, 47.6957], [131.09871, 47.6852], [131.2635, 47.73325], [131.90448, 47.68011], [132.57309, 47.71741], [132.66989, 47.96491], [134.49516, 48.42884], [134.75328, 48.36763], [134.67098, 48.1564], [134.55508, 47.98651], [134.7671, 47.72051], [134.50898, 47.4812], [134.20016, 47.33458], [134.03538, 46.75668], [133.84104, 46.46681], [133.91496, 46.4274], [133.88097, 46.25066], [133.68047, 46.14697], [133.72695, 46.05576], [133.67569, 45.9759], [133.60442, 45.90053], [133.48457, 45.86203], [133.41083, 45.57723], [133.19419, 45.51913], [133.09279, 45.25693], [133.12293, 45.1332], [132.96373, 45.0212], [132.83978, 45.05916], [131.99417, 45.2567], [131.86903, 45.33636], [131.76532, 45.22609], [131.66852, 45.2196], [131.68466, 45.12374], [131.48415, 44.99513], [130.95639, 44.85154], [131.1108, 44.70266], [131.30365, 44.04262], [131.25484, 44.03131], [131.23583, 43.96085], [131.26176, 43.94011], [131.21105, 43.82383], [131.19492, 43.53047], [131.29402, 43.46695], [131.30324, 43.39498], [131.19031, 43.21385], [131.20414, 43.13654], [131.10274, 43.04734], [131.135, 42.94114], [131.02668, 42.91246], [131.02438, 42.86518], [130.66524, 42.84753], [130.44361, 42.76205], [130.40213, 42.70788], [130.56576, 42.68925], [130.62107, 42.58413], [130.55143, 42.52158], [130.56835, 42.43281], [130.60805, 42.4317], [130.64181, 42.41422], [130.66367, 42.38024], [130.65022, 42.32281], [131.95041, 41.5445], [140.9182, 45.92937], [145.82343, 44.571], [145.23667, 43.76813], [153.94307, 38.42848], [180, 62.52334], [180, 71.53642], [155.31937, 81.93282], [76.13964, 83.37843], [64.18965, 69.94255], [66.1708, 67.61252], [61.98014, 65.72191], [60.74386, 64.95767], [59.63945, 64.78384], [59.80579, 64.13948], [59.24834, 63.01859], [59.61398, 62.44915], [59.36223, 61.3882], [59.50685, 60.91162], [58.3853, 59.487], [59.15636, 59.14682], [59.40376, 58.45822], [58.71104, 58.07475], [58.81412, 57.71602], [58.13789, 57.68097], [58.07604, 57.08308], [57.28024, 56.87898], [57.51527, 56.08729], [59.28419, 56.15739], [59.49035, 55.60486], [58.81825, 55.03378], [57.25137, 55.26262], [57.14829, 54.84204], [57.95234, 54.39672], [59.95217, 54.85853], [59.70487, 54.14846], [58.94336, 53.953], [58.79644, 52.43392], [59.22409, 52.28437], [59.25033, 52.46803], [60.17516, 52.39457], [60.17253, 52.25814], [59.91279, 52.06924], [59.99809, 51.98263]]]]
22437 wikidata: "Q34366",
22438 nameEn: "Tasmania",
22439 aliases: ["AU-TAS"],
22441 groups: ["053", "009", "UN"],
22443 callingCodes: ["61"]
22446 type: "MultiPolygon",
22447 coordinates: [[[[123.64533, -39.13605], [159.69067, -56.28945], [159.74028, -39.1978], [123.64533, -39.13605]]]]
22452 wikidata: "Q34497",
22453 nameEn: "Saint Helena",
22454 aliases: ["SH-HL"],
22456 groups: ["SH", "BOTS", "011", "202", "002", "UN"],
22457 level: "subterritory",
22459 roadSpeedUnit: "mph",
22460 roadHeightUnit: "ft",
22461 callingCodes: ["290"]
22464 type: "MultiPolygon",
22465 coordinates: [[[[-8.3824, -13.9131], [-6.17428, -19.07236], [-3.29308, -15.22647], [-8.3824, -13.9131]]]]
22470 wikidata: "Q35657",
22471 nameEn: "US States",
22473 level: "subcountryGroup"
22479 wikidata: "Q36117",
22481 level: "sharedLandform"
22487 wikidata: "Q36678",
22488 nameEn: "West Bank",
22490 groups: ["145", "142"],
22491 callingCodes: ["970"]
22494 type: "MultiPolygon",
22495 coordinates: [[[[35.47672, 31.49578], [35.55941, 31.76535], [35.52758, 31.9131], [35.54375, 31.96587], [35.52012, 32.04076], [35.57111, 32.21877], [35.55807, 32.38674], [35.42078, 32.41562], [35.41048, 32.43706], [35.41598, 32.45593], [35.42034, 32.46009], [35.40224, 32.50136], [35.35212, 32.52047], [35.30685, 32.51024], [35.29306, 32.50947], [35.25049, 32.52453], [35.2244, 32.55289], [35.15937, 32.50466], [35.10882, 32.4757], [35.10024, 32.47856], [35.09236, 32.47614], [35.08564, 32.46948], [35.07059, 32.4585], [35.05423, 32.41754], [35.05311, 32.4024], [35.0421, 32.38242], [35.05142, 32.3667], [35.04243, 32.35008], [35.01772, 32.33863], [35.01119, 32.28684], [35.02939, 32.2671], [35.01841, 32.23981], [34.98885, 32.20758], [34.95703, 32.19522], [34.96009, 32.17503], [34.99039, 32.14626], [34.98507, 32.12606], [34.99437, 32.10962], [34.9863, 32.09551], [35.00261, 32.027], [34.98682, 31.96935], [35.00124, 31.93264], [35.03489, 31.92448], [35.03978, 31.89276], [35.03489, 31.85919], [34.99712, 31.85569], [34.9724, 31.83352], [35.01978, 31.82944], [35.05617, 31.85685], [35.07677, 31.85627], [35.14174, 31.81325], [35.18603, 31.80901], [35.18169, 31.82542], [35.19461, 31.82687], [35.21469, 31.81835], [35.216, 31.83894], [35.21128, 31.863], [35.20381, 31.86716], [35.20673, 31.88151], [35.20791, 31.8821], [35.20945, 31.8815], [35.21016, 31.88237], [35.21276, 31.88153], [35.2136, 31.88241], [35.22014, 31.88264], [35.22294, 31.87889], [35.22567, 31.86745], [35.22817, 31.8638], [35.2249, 31.85433], [35.2304, 31.84222], [35.24816, 31.8458], [35.25753, 31.8387], [35.251, 31.83085], [35.26404, 31.82567], [35.25573, 31.81362], [35.26058, 31.79064], [35.25225, 31.7678], [35.26319, 31.74846], [35.25182, 31.73945], [35.24981, 31.72543], [35.2438, 31.7201], [35.24315, 31.71244], [35.23972, 31.70896], [35.22392, 31.71899], [35.21937, 31.71578], [35.20538, 31.72388], [35.18023, 31.72067], [35.16478, 31.73242], [35.15474, 31.73352], [35.15119, 31.73634], [35.13931, 31.73012], [35.12933, 31.7325], [35.11895, 31.71454], [35.10782, 31.71594], [35.08226, 31.69107], [35.00879, 31.65426], [34.95249, 31.59813], [34.9415, 31.55601], [34.94356, 31.50743], [34.93258, 31.47816], [34.89756, 31.43891], [34.87833, 31.39321], [34.88932, 31.37093], [34.92571, 31.34337], [35.02459, 31.35979], [35.13033, 31.3551], [35.22921, 31.37445], [35.39675, 31.49572], [35.47672, 31.49578]]]]
22500 wikidata: "Q37362",
22501 nameEn: "Akrotiri and Dhekelia",
22509 wikidata: "Q38095",
22510 nameEn: "Gal\xE1pagos Islands",
22513 groups: ["005", "419", "019", "UN"],
22514 callingCodes: ["593"]
22517 type: "MultiPolygon",
22518 coordinates: [[[[-93.12365, 2.64343], [-92.46744, -2.52874], [-87.07749, -0.8849], [-93.12365, 2.64343]]]]
22523 wikidata: "Q39760",
22524 nameEn: "Gaza Strip",
22526 groups: ["145", "142"],
22527 callingCodes: ["970"]
22530 type: "MultiPolygon",
22531 coordinates: [[[[34.052, 31.46619], [34.21853, 31.32363], [34.23572, 31.2966], [34.24012, 31.29591], [34.26742, 31.21998], [34.29417, 31.24194], [34.36523, 31.28963], [34.37381, 31.30598], [34.36505, 31.36404], [34.40077, 31.40926], [34.48892, 31.48365], [34.56797, 31.54197], [34.48681, 31.59711], [34.29262, 31.70393], [34.052, 31.46619]]]]
22536 wikidata: "Q40888",
22537 nameEn: "Andaman and Nicobar Islands",
22538 aliases: ["IN-AN"],
22540 groups: ["034", "142", "UN"],
22542 callingCodes: ["91"]
22545 type: "MultiPolygon",
22546 coordinates: [[[[94.42132, 5.96581], [94.6371, 13.81803], [86.7822, 13.41052], [94.42132, 5.96581]]]]
22551 wikidata: "Q41684",
22552 nameEn: "Stewart Island",
22554 groups: ["053", "009", "UN"],
22556 callingCodes: ["64"]
22559 type: "MultiPolygon",
22560 coordinates: [[[[166.59185, -47.61313], [169.70504, -47.56021], [167.52103, -46.41337], [166.59185, -47.61313]]]]
22565 wikidata: "Q43296",
22566 nameEn: "Wake Island",
22567 aliases: ["WK", "WAK", "WKUM", "872", "UM-79"],
22569 groups: ["UM", "Q1352230", "057", "009", "UN"],
22570 level: "subterritory",
22571 roadSpeedUnit: "mph",
22572 roadHeightUnit: "ft",
22573 callingCodes: ["1"]
22576 type: "MultiPolygon",
22577 coordinates: [[[[167.34779, 18.97692], [166.67967, 20.14834], [165.82549, 18.97692], [167.34779, 18.97692]]]]
22582 wikidata: "Q46275",
22583 nameEn: "New Zealand Subantarctic Islands",
22585 groups: ["Q851132", "053", "009", "UN"],
22589 type: "MultiPolygon",
22590 coordinates: [[[[164.30551, -47.88072], [161.96603, -56.07661], [179.49541, -50.04657], [179.49541, -47.2902], [169.91032, -47.66283], [164.30551, -47.88072]]]]
22595 wikidata: "Q46395",
22596 nameEn: "British Overseas Territories",
22597 aliases: ["BOTS", "UKOTS"],
22599 level: "subcountryGroup"
22605 wikidata: "Q46772",
22606 nameEn: "Kerguelen Islands",
22608 groups: ["TF", "Q1451600", "014", "202", "002", "UN"],
22609 level: "subterritory"
22612 type: "MultiPolygon",
22613 coordinates: [[[[61.9216, -49.39746], [70.67507, -51.14192], [74.25129, -45.45074], [61.9216, -49.39746]]]]
22618 wikidata: "Q46879",
22619 nameEn: "Baker Island",
22620 aliases: ["UM-81"],
22622 groups: ["UM", "Q1352230", "061", "009", "UN"],
22623 level: "subterritory",
22624 roadSpeedUnit: "mph",
22625 roadHeightUnit: "ft"
22628 type: "MultiPolygon",
22629 coordinates: [[[[-175.33482, -1.40631], [-175.31323, 0.5442], [-177.91421, 0.39582], [-175.33482, -1.40631]]]]
22634 wikidata: "Q47863",
22635 nameEn: "Midway Atoll",
22636 aliases: ["MI", "MID", "MIUM", "488", "UM-71"],
22638 groups: ["UM", "Q1352230", "061", "009", "UN"],
22639 level: "subterritory",
22640 roadSpeedUnit: "mph",
22641 roadHeightUnit: "ft",
22642 callingCodes: ["1"]
22645 type: "MultiPolygon",
22646 coordinates: [[[[-176.29741, 29.09786], [-177.77531, 29.29793], [-177.5224, 27.7635], [-176.29741, 29.09786]]]]
22651 wikidata: "Q62218",
22652 nameEn: "Jarvis Island",
22653 aliases: ["UM-86"],
22655 groups: ["UM", "Q1352230", "061", "009", "UN"],
22656 level: "subterritory",
22657 roadSpeedUnit: "mph",
22658 roadHeightUnit: "ft"
22661 type: "MultiPolygon",
22662 coordinates: [[[[-160.42921, -1.4364], [-159.12443, 0.19975], [-160.38779, 0.30331], [-160.42921, -1.4364]]]]
22667 wikidata: "Q105472",
22668 nameEn: "Macaronesia",
22669 level: "sharedLandform"
22675 wikidata: "Q114935",
22676 nameEn: "Kermadec Islands",
22678 groups: ["Q851132", "053", "009", "UN"],
22680 callingCodes: ["64"]
22683 type: "MultiPolygon",
22684 coordinates: [[[[-174.40891, -29.09438], [-180, -24.21376], [-179.96512, -35.00791], [-174.40891, -29.09438]]]]
22689 wikidata: "Q115459",
22690 nameEn: "Chatham Islands",
22691 aliases: ["NZ-CIT"],
22693 groups: ["Q851132", "053", "009", "UN"],
22695 callingCodes: ["64"]
22698 type: "MultiPolygon",
22699 coordinates: [[[[-179.93224, -45.18423], [-172.47015, -45.17912], [-176.30998, -41.38382], [-179.93224, -45.18423]]]]
22704 wikidata: "Q118863",
22705 nameEn: "North Island",
22707 groups: ["053", "009", "UN"],
22709 callingCodes: ["64"]
22712 type: "MultiPolygon",
22713 coordinates: [[[[179.49541, -47.2902], [179.49541, -36.79303], [174.17679, -32.62487], [170.27492, -36.38133], [174.58663, -40.80446], [174.46634, -41.55028], [179.49541, -47.2902]]]]
22718 wikidata: "Q120755",
22719 nameEn: "South Island",
22721 groups: ["053", "009", "UN"],
22723 callingCodes: ["64"]
22726 type: "MultiPolygon",
22727 coordinates: [[[[169.70504, -47.56021], [179.49541, -47.2902], [174.46634, -41.55028], [174.58663, -40.80446], [170.27492, -36.38133], [166.56976, -39.94841], [164.8365, -46.0205], [167.52103, -46.41337], [169.70504, -47.56021]]]]
22732 wikidata: "Q123076",
22733 nameEn: "Palmyra Atoll",
22734 aliases: ["UM-95"],
22736 groups: ["UM", "Q1352230", "061", "009", "UN"],
22737 level: "subterritory",
22738 roadSpeedUnit: "mph",
22739 roadHeightUnit: "ft",
22740 callingCodes: ["1"]
22743 type: "MultiPolygon",
22744 coordinates: [[[[-161.06795, 5.2462], [-161.0731, 7.1291], [-163.24478, 5.24198], [-161.06795, 5.2462]]]]
22749 wikidata: "Q130574",
22750 nameEn: "Chafarinas Islands",
22752 groups: ["EU", "Q191011", "015", "002", "UN"],
22753 level: "subterritory"
22756 type: "MultiPolygon",
22757 coordinates: [[[[-2.40316, 35.16893], [-2.43262, 35.20652], [-2.45965, 35.16527], [-2.40316, 35.16893]]]]
22762 wikidata: "Q130895",
22763 nameEn: "Kingman Reef",
22764 aliases: ["UM-89"],
22766 groups: ["UM", "Q1352230", "061", "009", "UN"],
22767 level: "subterritory",
22768 roadSpeedUnit: "mph",
22769 roadHeightUnit: "ft"
22772 type: "MultiPolygon",
22773 coordinates: [[[[-161.0731, 7.1291], [-163.16627, 7.15036], [-163.24478, 5.24198], [-161.0731, 7.1291]]]]
22778 wikidata: "Q131008",
22779 nameEn: "Johnston Atoll",
22780 aliases: ["JT", "JTN", "JTUM", "396", "UM-67"],
22782 groups: ["UM", "Q1352230", "061", "009", "UN"],
22783 level: "subterritory",
22784 roadSpeedUnit: "mph",
22785 roadHeightUnit: "ft",
22786 callingCodes: ["1"]
22789 type: "MultiPolygon",
22790 coordinates: [[[[-170.65691, 16.57199], [-168.87689, 16.01159], [-169.2329, 17.4933], [-170.65691, 16.57199]]]]
22795 wikidata: "Q131305",
22796 nameEn: "Howland Island",
22797 aliases: ["UM-84"],
22799 groups: ["UM", "Q1352230", "061", "009", "UN"],
22800 level: "subterritory",
22801 roadSpeedUnit: "mph",
22802 roadHeightUnit: "ft"
22805 type: "MultiPolygon",
22806 coordinates: [[[[-177.91421, 0.39582], [-175.31323, 0.5442], [-176.74464, 2.28109], [-177.91421, 0.39582]]]]
22811 wikidata: "Q133888",
22812 nameEn: "Ashmore and Cartier Islands",
22814 groups: ["053", "009", "UN"],
22816 callingCodes: ["61"]
22819 type: "MultiPolygon",
22820 coordinates: [[[[123.7463, -11.1783], [120.6877, -13.59408], [125.29076, -12.33139], [123.7463, -11.1783]]]]
22825 wikidata: "Q153732",
22826 nameEn: "Mariana Islands",
22827 level: "sharedLandform"
22833 wikidata: "Q172216",
22834 nameEn: "Coral Sea Islands",
22836 groups: ["053", "009", "UN"],
22838 callingCodes: ["61"]
22841 type: "MultiPolygon",
22842 coordinates: [[[[159.77159, -28.41151], [156.73836, -14.50464], [145.2855, -9.62524], [147.69992, -17.5933], [152.93188, -20.92631], [154.02855, -24.43238], [159.77159, -28.41151]]]]
22847 wikidata: "Q179313",
22848 nameEn: "Alderney",
22850 groups: ["GG", "830", "Q185086", "154", "150", "UN"],
22851 level: "subterritory",
22853 roadSpeedUnit: "mph",
22854 roadHeightUnit: "ft",
22855 callingCodes: ["44 01481"]
22858 type: "MultiPolygon",
22859 coordinates: [[[[-2.36485, 49.48223], [-2.09454, 49.46288], [-2.02963, 49.91866], [-2.49556, 49.79012], [-2.36485, 49.48223]]]]
22864 wikidata: "Q185086",
22865 nameEn: "Crown Dependencies",
22867 level: "subcountryGroup"
22873 wikidata: "Q190571",
22874 nameEn: "Scattered Islands",
22876 groups: ["TF", "Q1451600", "014", "202", "002", "UN"],
22877 level: "subterritory"
22880 type: "MultiPolygon",
22881 coordinates: [[[[53.53458, -16.36909], [54.96649, -16.28353], [54.61476, -15.02273], [53.53458, -16.36909]]], [[[38.55969, -20.75596], [40.68027, -23.38889], [43.52893, -15.62903], [38.55969, -20.75596]]], [[[47.03092, -11.05648], [47.11593, -12.08552], [47.96702, -11.46447], [47.03092, -11.05648]]]]
22886 wikidata: "Q191011",
22887 nameEn: "Plazas de soberan\xEDa",
22894 wikidata: "Q191146",
22895 nameEn: "Pe\xF1\xF3n de V\xE9lez de la Gomera",
22897 groups: ["EU", "Q191011", "015", "002", "UN"],
22898 level: "subterritory"
22901 type: "MultiPolygon",
22902 coordinates: [[[[-4.30191, 35.17419], [-4.30112, 35.17058], [-4.29436, 35.17149], [-4.30191, 35.17419]]]]
22907 wikidata: "Q201698",
22908 nameEn: "Crozet Islands",
22910 groups: ["TF", "Q1451600", "014", "202", "002", "UN"],
22911 level: "subterritory"
22914 type: "MultiPolygon",
22915 coordinates: [[[[55.03425, -43.65017], [46.31615, -46.28749], [54.5587, -47.93013], [55.03425, -43.65017]]]]
22920 wikidata: "Q578170",
22921 nameEn: "Contiguous United States",
22922 aliases: ["CONUS"],
22924 groups: ["Q35657", "021", "003", "019", "UN"],
22925 roadSpeedUnit: "mph",
22926 roadHeightUnit: "ft",
22927 callingCodes: ["1"]
22930 type: "MultiPolygon",
22931 coordinates: [[[[-97.13927, 25.96583], [-96.92418, 25.97377], [-80.57035, 24.0565], [-78.91214, 27.76553], [-61.98255, 37.34815], [-67.16117, 44.20069], [-66.93432, 44.82597], [-66.96824, 44.83078], [-66.98249, 44.87071], [-66.96824, 44.90965], [-67.0216, 44.95333], [-67.11316, 45.11176], [-67.15965, 45.16179], [-67.19603, 45.16771], [-67.20349, 45.1722], [-67.22751, 45.16344], [-67.27039, 45.1934], [-67.29748, 45.18173], [-67.29754, 45.14865], [-67.34927, 45.122], [-67.48201, 45.27351], [-67.42394, 45.37969], [-67.50578, 45.48971], [-67.42144, 45.50584], [-67.43815, 45.59162], [-67.6049, 45.60725], [-67.80705, 45.69528], [-67.80653, 45.80022], [-67.75654, 45.82324], [-67.80961, 45.87531], [-67.75196, 45.91814], [-67.78111, 45.9392], [-67.78578, 47.06473], [-67.87993, 47.10377], [-67.94843, 47.1925], [-68.23244, 47.35712], [-68.37458, 47.35851], [-68.38332, 47.28723], [-68.57914, 47.28431], [-68.60575, 47.24659], [-68.70125, 47.24399], [-68.89222, 47.1807], [-69.05039, 47.2456], [-69.05073, 47.30076], [-69.05148, 47.42012], [-69.22119, 47.46461], [-69.99966, 46.69543], [-70.05812, 46.41768], [-70.18547, 46.35357], [-70.29078, 46.18832], [-70.23855, 46.1453], [-70.31025, 45.96424], [-70.24694, 45.95138], [-70.25976, 45.89675], [-70.41523, 45.79497], [-70.38934, 45.73215], [-70.54019, 45.67291], [-70.68516, 45.56964], [-70.72651, 45.49771], [-70.62518, 45.42286], [-70.65383, 45.37592], [-70.78372, 45.43269], [-70.82638, 45.39828], [-70.80236, 45.37444], [-70.84816, 45.22698], [-70.89864, 45.2398], [-70.91169, 45.29849], [-70.95193, 45.33895], [-71.0107, 45.34819], [-71.01866, 45.31573], [-71.08364, 45.30623], [-71.14568, 45.24128], [-71.19723, 45.25438], [-71.22338, 45.25184], [-71.29371, 45.29996], [-71.37133, 45.24624], [-71.44252, 45.2361], [-71.40364, 45.21382], [-71.42778, 45.12624], [-71.48735, 45.07784], [-71.50067, 45.01357], [-73.35025, 45.00942], [-74.32699, 44.99029], [-74.66689, 45.00646], [-74.8447, 45.00606], [-74.99101, 44.98051], [-75.01363, 44.95608], [-75.2193, 44.87821], [-75.41441, 44.76614], [-75.76813, 44.51537], [-75.8217, 44.43176], [-75.95947, 44.34463], [-76.00018, 44.34896], [-76.16285, 44.28262], [-76.1664, 44.23051], [-76.244, 44.19643], [-76.31222, 44.19894], [-76.35324, 44.13493], [-76.43859, 44.09393], [-76.79706, 43.63099], [-79.25796, 43.54052], [-79.06921, 43.26183], [-79.05512, 43.25375], [-79.05544, 43.21224], [-79.05002, 43.20133], [-79.05384, 43.17418], [-79.04652, 43.16396], [-79.0427, 43.13934], [-79.06881, 43.12029], [-79.05671, 43.10937], [-79.07486, 43.07845], [-79.01055, 43.06659], [-78.99941, 43.05612], [-79.02424, 43.01983], [-79.02074, 42.98444], [-78.98126, 42.97], [-78.96312, 42.95509], [-78.93224, 42.95229], [-78.90905, 42.93022], [-78.90712, 42.89733], [-78.93684, 42.82887], [-82.67862, 41.67615], [-83.11184, 41.95671], [-83.14962, 42.04089], [-83.12724, 42.2376], [-83.09837, 42.28877], [-83.07837, 42.30978], [-83.02253, 42.33045], [-82.82964, 42.37355], [-82.64242, 42.55594], [-82.58873, 42.54984], [-82.57583, 42.5718], [-82.51858, 42.611], [-82.51063, 42.66025], [-82.46613, 42.76615], [-82.4826, 42.8068], [-82.45331, 42.93139], [-82.4253, 42.95423], [-82.4146, 42.97626], [-82.42469, 42.992], [-82.48419, 45.30225], [-83.59589, 45.82131], [-83.43746, 45.99749], [-83.57017, 46.105], [-83.83329, 46.12169], [-83.90453, 46.05922], [-83.95399, 46.05634], [-84.1096, 46.23987], [-84.09756, 46.25512], [-84.11615, 46.2681], [-84.11254, 46.32329], [-84.13451, 46.39218], [-84.11196, 46.50248], [-84.12885, 46.53068], [-84.17723, 46.52753], [-84.1945, 46.54061], [-84.2264, 46.53337], [-84.26351, 46.49508], [-84.29893, 46.49127], [-84.34174, 46.50683], [-84.42101, 46.49853], [-84.4481, 46.48972], [-84.47607, 46.45225], [-84.55635, 46.45974], [-84.85871, 46.88881], [-88.37033, 48.30586], [-89.48837, 48.01412], [-89.57972, 48.00023], [-89.77248, 48.02607], [-89.89974, 47.98109], [-90.07418, 48.11043], [-90.56312, 48.09488], [-90.56444, 48.12184], [-90.75045, 48.09143], [-90.87588, 48.2484], [-91.08016, 48.18096], [-91.25025, 48.08522], [-91.43248, 48.04912], [-91.45829, 48.07454], [-91.58025, 48.04339], [-91.55649, 48.10611], [-91.70451, 48.11805], [-91.71231, 48.19875], [-91.86125, 48.21278], [-91.98929, 48.25409], [-92.05339, 48.35958], [-92.14732, 48.36578], [-92.202, 48.35252], [-92.26662, 48.35651], [-92.30939, 48.31251], [-92.27167, 48.25046], [-92.37185, 48.22259], [-92.48147, 48.36609], [-92.45588, 48.40624], [-92.50712, 48.44921], [-92.65606, 48.43471], [-92.71323, 48.46081], [-92.69927, 48.49573], [-92.62747, 48.50278], [-92.6342, 48.54133], [-92.7287, 48.54005], [-92.94973, 48.60866], [-93.25391, 48.64266], [-93.33946, 48.62787], [-93.3712, 48.60599], [-93.39758, 48.60364], [-93.40693, 48.60948], [-93.44472, 48.59147], [-93.47022, 48.54357], [-93.66382, 48.51845], [-93.79267, 48.51631], [-93.80939, 48.52439], [-93.80676, 48.58232], [-93.83288, 48.62745], [-93.85769, 48.63284], [-94.23215, 48.65202], [-94.25104, 48.65729], [-94.25172, 48.68404], [-94.27153, 48.70232], [-94.4174, 48.71049], [-94.44258, 48.69223], [-94.53826, 48.70216], [-94.54885, 48.71543], [-94.58903, 48.71803], [-94.69335, 48.77883], [-94.69669, 48.80918], [-94.70486, 48.82365], [-94.70087, 48.8339], [-94.687, 48.84077], [-94.75017, 49.09931], [-94.77355, 49.11998], [-94.82487, 49.29483], [-94.8159, 49.32299], [-94.85381, 49.32492], [-94.95681, 49.37035], [-94.99532, 49.36579], [-95.01419, 49.35647], [-95.05825, 49.35311], [-95.12903, 49.37056], [-95.15357, 49.384], [-95.15355, 48.9996], [-123.32163, 49.00419], [-123.0093, 48.83186], [-123.0093, 48.76586], [-123.26565, 48.6959], [-123.15614, 48.35395], [-123.50039, 48.21223], [-125.03842, 48.53282], [-133.98258, 38.06389], [-118.48109, 32.5991], [-117.1243, 32.53427], [-115.88053, 32.63624], [-114.71871, 32.71894], [-114.76736, 32.64094], [-114.80584, 32.62028], [-114.81141, 32.55543], [-114.79524, 32.55731], [-114.82011, 32.49609], [-111.07523, 31.33232], [-108.20979, 31.33316], [-108.20899, 31.78534], [-106.529, 31.784], [-106.52266, 31.77509], [-106.51251, 31.76922], [-106.50962, 31.76155], [-106.50111, 31.75714], [-106.48815, 31.74769], [-106.47298, 31.75054], [-106.46726, 31.75998], [-106.45244, 31.76523], [-106.43419, 31.75478], [-106.41773, 31.75196], [-106.38003, 31.73151], [-106.3718, 31.71165], [-106.34864, 31.69663], [-106.33419, 31.66303], [-106.30305, 31.62154], [-106.28084, 31.56173], [-106.24612, 31.54193], [-106.23711, 31.51262], [-106.20346, 31.46305], [-106.09025, 31.40569], [-106.00363, 31.39181], [-104.77674, 30.4236], [-104.5171, 29.64671], [-104.3969, 29.57105], [-104.39363, 29.55396], [-104.37752, 29.54255], [-103.15787, 28.93865], [-102.60596, 29.8192], [-101.47277, 29.7744], [-101.05686, 29.44738], [-101.01128, 29.36947], [-100.96725, 29.3477], [-100.94579, 29.34523], [-100.94056, 29.33371], [-100.87982, 29.296], [-100.79696, 29.24688], [-100.67294, 29.09744], [-100.63689, 28.90812], [-100.59809, 28.88197], [-100.52313, 28.75598], [-100.5075, 28.74066], [-100.51222, 28.70679], [-100.50029, 28.66117], [-99.55409, 27.61314], [-99.51478, 27.55836], [-99.52955, 27.49747], [-99.50208, 27.50021], [-99.48045, 27.49016], [-99.482, 27.47128], [-99.49744, 27.43746], [-99.53573, 27.30926], [-99.08477, 26.39849], [-99.03053, 26.41249], [-99.00546, 26.3925], [-98.35126, 26.15129], [-98.30491, 26.10475], [-98.27075, 26.09457], [-98.24603, 26.07191], [-97.97017, 26.05232], [-97.95155, 26.0625], [-97.66511, 26.01708], [-97.52025, 25.88518], [-97.49828, 25.89877], [-97.45669, 25.86874], [-97.42511, 25.83969], [-97.37332, 25.83854], [-97.35946, 25.92189], [-97.13927, 25.96583]]]]
22936 wikidata: "Q620634",
22937 nameEn: "Bir Tawil",
22938 groups: ["015", "002"],
22942 type: "MultiPolygon",
22943 coordinates: [[[[33.17563, 22.00405], [33.57251, 21.72406], [33.99686, 21.76784], [34.0765, 22.00501], [33.17563, 22.00405]]]]
22948 wikidata: "Q639185",
22949 nameEn: "Peros Banhos",
22951 groups: ["IO", "BOTS", "014", "202", "002", "UN"],
22952 level: "subterritory"
22955 type: "MultiPolygon",
22956 coordinates: [[[[72.12587, -4.02588], [70.1848, -6.37445], [72.09518, -5.61768], [72.12587, -4.02588]]]]
22961 wikidata: "Q644636",
22963 level: "sharedLandform"
22969 wikidata: "Q851132",
22970 nameEn: "New Zealand Outlying Islands",
22972 level: "subcountryGroup"
22978 wikidata: "Q875134",
22979 nameEn: "European Russia",
22981 groups: ["151", "150", "UN"],
22982 callingCodes: ["7"]
22985 type: "MultiPolygon",
22986 coordinates: [[[[18.57853, 55.25302], [19.64312, 54.45423], [19.8038, 54.44203], [20.63871, 54.3706], [21.41123, 54.32395], [22.79705, 54.36264], [22.7253, 54.41732], [22.70208, 54.45312], [22.67788, 54.532], [22.71293, 54.56454], [22.68021, 54.58486], [22.7522, 54.63525], [22.74225, 54.64339], [22.75467, 54.6483], [22.73397, 54.66604], [22.73631, 54.72952], [22.87317, 54.79492], [22.85083, 54.88711], [22.76422, 54.92521], [22.68723, 54.9811], [22.65451, 54.97037], [22.60075, 55.01863], [22.58907, 55.07085], [22.47688, 55.04408], [22.31562, 55.0655], [22.14267, 55.05345], [22.11697, 55.02131], [22.06087, 55.02935], [22.02582, 55.05078], [22.03984, 55.07888], [21.99543, 55.08691], [21.96505, 55.07353], [21.85521, 55.09493], [21.64954, 55.1791], [21.55605, 55.20311], [21.51095, 55.18507], [21.46766, 55.21115], [21.38446, 55.29348], [21.35465, 55.28427], [21.26425, 55.24456], [20.95181, 55.27994], [20.60454, 55.40986], [18.57853, 55.25302]]], [[[26.32936, 60.00121], [26.90044, 59.63819], [27.85643, 59.58538], [28.04187, 59.47017], [28.19061, 59.39962], [28.21137, 59.38058], [28.20537, 59.36491], [28.19284, 59.35791], [28.14215, 59.28934], [28.00689, 59.28351], [27.90911, 59.24353], [27.87978, 59.18097], [27.80482, 59.1116], [27.74429, 58.98351], [27.36366, 58.78381], [27.55489, 58.39525], [27.48541, 58.22615], [27.62393, 58.09462], [27.67282, 57.92627], [27.81841, 57.89244], [27.78526, 57.83963], [27.56689, 57.83356], [27.50171, 57.78842], [27.52615, 57.72843], [27.3746, 57.66834], [27.40393, 57.62125], [27.31919, 57.57672], [27.34698, 57.52242], [27.56832, 57.53728], [27.52453, 57.42826], [27.86101, 57.29402], [27.66511, 56.83921], [27.86101, 56.88204], [28.04768, 56.59004], [28.13526, 56.57989], [28.10069, 56.524], [28.19057, 56.44637], [28.16599, 56.37806], [28.23716, 56.27588], [28.15217, 56.16964], [28.30571, 56.06035], [28.36888, 56.05805], [28.37987, 56.11399], [28.43068, 56.09407], [28.5529, 56.11705], [28.68337, 56.10173], [28.63668, 56.07262], [28.73418, 55.97131], [29.08299, 56.03427], [29.21717, 55.98971], [29.44692, 55.95978], [29.3604, 55.75862], [29.51283, 55.70294], [29.61446, 55.77716], [29.80672, 55.79569], [29.97975, 55.87281], [30.12136, 55.8358], [30.27776, 55.86819], [30.30987, 55.83592], [30.48257, 55.81066], [30.51346, 55.78982], [30.51037, 55.76568], [30.63344, 55.73079], [30.67464, 55.64176], [30.72957, 55.66268], [30.7845, 55.58514], [30.86003, 55.63169], [30.93419, 55.6185], [30.95204, 55.50667], [30.90123, 55.46621], [30.93144, 55.3914], [30.8257, 55.3313], [30.81946, 55.27931], [30.87944, 55.28223], [30.97369, 55.17134], [31.02071, 55.06167], [31.00972, 55.02783], [30.94243, 55.03964], [30.9081, 55.02232], [30.95754, 54.98609], [30.93144, 54.9585], [30.81759, 54.94064], [30.8264, 54.90062], [30.75165, 54.80699], [30.95479, 54.74346], [30.97127, 54.71967], [31.0262, 54.70698], [30.98226, 54.68872], [30.99187, 54.67046], [31.19339, 54.66947], [31.21399, 54.63113], [31.08543, 54.50361], [31.22945, 54.46585], [31.3177, 54.34067], [31.30791, 54.25315], [31.57002, 54.14535], [31.89599, 54.0837], [31.88744, 54.03653], [31.85019, 53.91801], [31.77028, 53.80015], [31.89137, 53.78099], [32.12621, 53.81586], [32.36663, 53.7166], [32.45717, 53.74039], [32.50112, 53.68594], [32.40499, 53.6656], [32.47777, 53.5548], [32.74968, 53.45597], [32.73257, 53.33494], [32.51725, 53.28431], [32.40773, 53.18856], [32.15368, 53.07594], [31.82373, 53.10042], [31.787, 53.18033], [31.62496, 53.22886], [31.56316, 53.19432], [31.40523, 53.21406], [31.36403, 53.13504], [31.3915, 53.09712], [31.33519, 53.08805], [31.32283, 53.04101], [31.24147, 53.031], [31.35667, 52.97854], [31.592, 52.79011], [31.57277, 52.71613], [31.50406, 52.69707], [31.63869, 52.55361], [31.56316, 52.51518], [31.61397, 52.48843], [31.62084, 52.33849], [31.57971, 52.32146], [31.70735, 52.26711], [31.6895, 52.1973], [31.77877, 52.18636], [31.7822, 52.11406], [31.81722, 52.09955], [31.85018, 52.11305], [31.96141, 52.08015], [31.92159, 52.05144], [32.08813, 52.03319], [32.23331, 52.08085], [32.2777, 52.10266], [32.34044, 52.1434], [32.33083, 52.23685], [32.38988, 52.24946], [32.3528, 52.32842], [32.54781, 52.32423], [32.69475, 52.25535], [32.85405, 52.27888], [32.89937, 52.2461], [33.18913, 52.3754], [33.51323, 52.35779], [33.48027, 52.31499], [33.55718, 52.30324], [33.78789, 52.37204], [34.05239, 52.20132], [34.11199, 52.14087], [34.09413, 52.00835], [34.41136, 51.82793], [34.42922, 51.72852], [34.07765, 51.67065], [34.17599, 51.63253], [34.30562, 51.5205], [34.22048, 51.4187], [34.33446, 51.363], [34.23009, 51.26429], [34.31661, 51.23936], [34.38802, 51.2746], [34.6613, 51.25053], [34.6874, 51.18], [34.82472, 51.17483], [34.97304, 51.2342], [35.14058, 51.23162], [35.12685, 51.16191], [35.20375, 51.04723], [35.31774, 51.08434], [35.40837, 51.04119], [35.32598, 50.94524], [35.39307, 50.92145], [35.41367, 50.80227], [35.47704, 50.77274], [35.48116, 50.66405], [35.39464, 50.64751], [35.47463, 50.49247], [35.58003, 50.45117], [35.61711, 50.35707], [35.73659, 50.35489], [35.80388, 50.41356], [35.8926, 50.43829], [36.06893, 50.45205], [36.20763, 50.3943], [36.30101, 50.29088], [36.47817, 50.31457], [36.58371, 50.28563], [36.56655, 50.2413], [36.64571, 50.218], [36.69377, 50.26982], [36.91762, 50.34963], [37.08468, 50.34935], [37.48204, 50.46079], [37.47243, 50.36277], [37.62486, 50.29966], [37.62879, 50.24481], [37.61113, 50.21976], [37.75807, 50.07896], [37.79515, 50.08425], [37.90776, 50.04194], [38.02999, 49.94482], [38.02999, 49.90592], [38.21675, 49.98104], [38.18517, 50.08161], [38.32524, 50.08866], [38.35408, 50.00664], [38.65688, 49.97176], [38.68677, 50.00904], [38.73311, 49.90238], [38.90477, 49.86787], [38.9391, 49.79524], [39.1808, 49.88911], [39.27968, 49.75976], [39.44496, 49.76067], [39.59142, 49.73758], [39.65047, 49.61761], [39.84548, 49.56064], [40.13249, 49.61672], [40.16683, 49.56865], [40.03636, 49.52321], [40.03087, 49.45452], [40.1141, 49.38798], [40.14912, 49.37681], [40.18331, 49.34996], [40.22176, 49.25683], [40.01988, 49.1761], [39.93437, 49.05709], [39.6836, 49.05121], [39.6683, 48.99454], [39.71353, 48.98959], [39.72649, 48.9754], [39.74874, 48.98675], [39.78368, 48.91596], [39.98967, 48.86901], [40.03636, 48.91957], [40.08168, 48.87443], [39.97182, 48.79398], [39.79466, 48.83739], [39.73104, 48.7325], [39.71765, 48.68673], [39.67226, 48.59368], [39.79764, 48.58668], [39.84548, 48.57821], [39.86196, 48.46633], [39.88794, 48.44226], [39.94847, 48.35055], [39.84136, 48.33321], [39.84273, 48.30947], [39.90041, 48.3049], [39.91465, 48.26743], [39.95248, 48.29972], [39.9693, 48.29904], [39.97325, 48.31399], [39.99241, 48.31768], [40.00752, 48.22445], [39.94847, 48.22811], [39.83724, 48.06501], [39.88256, 48.04482], [39.77544, 48.04206], [39.82213, 47.96396], [39.73935, 47.82876], [38.87979, 47.87719], [38.79628, 47.81109], [38.76379, 47.69346], [38.35062, 47.61631], [38.28679, 47.53552], [38.28954, 47.39255], [38.22225, 47.30788], [38.33074, 47.30508], [38.32112, 47.2585], [38.23049, 47.2324], [38.22955, 47.12069], [38.3384, 46.98085], [38.12112, 46.86078], [37.62608, 46.82615], [35.23066, 45.79231], [35.04991, 45.76827], [36.6645, 45.4514], [36.6545, 45.3417], [36.5049, 45.3136], [36.475, 45.2411], [36.4883, 45.0488], [33.5943, 44.03313], [39.81147, 43.06294], [40.0078, 43.38551], [40.00853, 43.40578], [40.01552, 43.42025], [40.01007, 43.42411], [40.03312, 43.44262], [40.04445, 43.47776], [40.10657, 43.57344], [40.65957, 43.56212], [41.64935, 43.22331], [42.40563, 43.23226], [42.66667, 43.13917], [42.75889, 43.19651], [43.03322, 43.08883], [43.0419, 43.02413], [43.81453, 42.74297], [43.73119, 42.62043], [43.95517, 42.55396], [44.54202, 42.75699], [44.70002, 42.74679], [44.80941, 42.61277], [44.88754, 42.74934], [45.15318, 42.70598], [45.36501, 42.55268], [45.78692, 42.48358], [45.61676, 42.20768], [46.42738, 41.91323], [46.5332, 41.87389], [46.58924, 41.80547], [46.75269, 41.8623], [46.8134, 41.76252], [47.00955, 41.63583], [46.99554, 41.59743], [47.03757, 41.55434], [47.10762, 41.59044], [47.34579, 41.27884], [47.49004, 41.26366], [47.54504, 41.20275], [47.62288, 41.22969], [47.75831, 41.19455], [47.87973, 41.21798], [48.07587, 41.49957], [48.22064, 41.51472], [48.2878, 41.56221], [48.40277, 41.60441], [48.42301, 41.65444], [48.55078, 41.77917], [48.5867, 41.84306], [48.80971, 41.95365], [49.2134, 44.84989], [49.88945, 46.04554], [49.32259, 46.26944], [49.16518, 46.38542], [48.54988, 46.56267], [48.51142, 46.69268], [49.01136, 46.72716], [48.52326, 47.4102], [48.45173, 47.40818], [48.15348, 47.74545], [47.64973, 47.76559], [47.41689, 47.83687], [47.38731, 47.68176], [47.12107, 47.83687], [47.11516, 48.27188], [46.49011, 48.43019], [46.78392, 48.95352], [47.00857, 49.04921], [47.04658, 49.19834], [46.78398, 49.34026], [46.9078, 49.86707], [47.18319, 49.93721], [47.34589, 50.09308], [47.30448, 50.30894], [47.58551, 50.47867], [48.10044, 50.09242], [48.24519, 49.86099], [48.42564, 49.82283], [48.68352, 49.89546], [48.90782, 50.02281], [48.57946, 50.63278], [48.86936, 50.61589], [49.12673, 50.78639], [49.41959, 50.85927], [49.39001, 51.09396], [49.76866, 51.11067], [49.97277, 51.2405], [50.26859, 51.28677], [50.59695, 51.61859], [51.26254, 51.68466], [51.301, 51.48799], [51.77431, 51.49536], [51.8246, 51.67916], [52.36119, 51.74161], [52.54329, 51.48444], [53.46165, 51.49445], [53.69299, 51.23466], [54.12248, 51.11542], [54.46331, 50.85554], [54.41894, 50.61214], [54.55797, 50.52006], [54.71476, 50.61214], [54.56685, 51.01958], [54.72067, 51.03261], [55.67774, 50.54508], [56.11398, 50.7471], [56.17906, 50.93204], [57.17302, 51.11253], [57.44221, 50.88354], [57.74986, 50.93017], [57.75578, 51.13852], [58.3208, 51.15151], [58.87974, 50.70852], [59.48928, 50.64216], [59.51886, 50.49937], [59.81172, 50.54451], [60.01288, 50.8163], [60.17262, 50.83312], [60.31914, 50.67705], [60.81833, 50.6629], [61.4431, 50.80679], [61.56889, 51.23679], [61.6813, 51.25716], [61.55114, 51.32746], [61.50677, 51.40687], [60.95655, 51.48615], [60.92401, 51.61124], [60.5424, 51.61675], [60.36787, 51.66815], [60.50986, 51.7964], [60.09867, 51.87135], [59.99809, 51.98263], [59.91279, 52.06924], [60.17253, 52.25814], [60.17516, 52.39457], [59.25033, 52.46803], [59.22409, 52.28437], [58.79644, 52.43392], [58.94336, 53.953], [59.70487, 54.14846], [59.95217, 54.85853], [57.95234, 54.39672], [57.14829, 54.84204], [57.25137, 55.26262], [58.81825, 55.03378], [59.49035, 55.60486], [59.28419, 56.15739], [57.51527, 56.08729], [57.28024, 56.87898], [58.07604, 57.08308], [58.13789, 57.68097], [58.81412, 57.71602], [58.71104, 58.07475], [59.40376, 58.45822], [59.15636, 59.14682], [58.3853, 59.487], [59.50685, 60.91162], [59.36223, 61.3882], [59.61398, 62.44915], [59.24834, 63.01859], [59.80579, 64.13948], [59.63945, 64.78384], [60.74386, 64.95767], [61.98014, 65.72191], [66.1708, 67.61252], [64.18965, 69.94255], [76.13964, 83.37843], [36.85549, 84.09565], [32.07813, 72.01005], [31.59909, 70.16571], [30.84095, 69.80584], [30.95011, 69.54699], [30.52662, 69.54699], [30.16363, 69.65244], [29.97205, 69.41623], [29.27631, 69.2811], [29.26623, 69.13794], [29.0444, 69.0119], [28.91738, 69.04774], [28.45957, 68.91417], [28.78224, 68.86696], [28.43941, 68.53366], [28.62982, 68.19816], [29.34179, 68.06655], [29.66955, 67.79872], [30.02041, 67.67523], [29.91155, 67.51507], [28.9839, 66.94139], [29.91155, 66.13863], [30.16363, 65.66935], [29.97205, 65.70256], [29.74013, 65.64025], [29.84096, 65.56945], [29.68972, 65.31803], [29.61914, 65.23791], [29.8813, 65.22101], [29.84096, 65.1109], [29.61914, 65.05993], [29.68972, 64.80789], [30.05271, 64.79072], [30.12329, 64.64862], [30.01238, 64.57513], [30.06279, 64.35782], [30.4762, 64.25728], [30.55687, 64.09036], [30.25437, 63.83364], [29.98213, 63.75795], [30.49637, 63.46666], [31.23244, 63.22239], [31.29294, 63.09035], [31.58535, 62.91642], [31.38369, 62.66284], [31.10136, 62.43042], [29.01829, 61.17448], [28.82816, 61.1233], [28.47974, 60.93365], [27.77352, 60.52722], [27.71177, 60.3893], [27.44953, 60.22766], [26.32936, 60.00121]]]]
22991 wikidata: "Q1083368",
22992 nameEn: "Mainland Finland",
22994 groups: ["EU", "154", "150", "UN"],
22995 callingCodes: ["358"]
22998 type: "MultiPolygon",
22999 coordinates: [[[[29.12697, 69.69193], [28.36883, 69.81658], [28.32849, 69.88605], [27.97558, 69.99671], [27.95542, 70.0965], [27.57226, 70.06215], [27.05802, 69.92069], [26.64461, 69.96565], [26.40261, 69.91377], [25.96904, 69.68397], [25.69679, 69.27039], [25.75729, 68.99383], [25.61613, 68.89602], [25.42455, 68.90328], [25.12206, 68.78684], [25.10189, 68.63307], [24.93048, 68.61102], [24.90023, 68.55579], [24.74898, 68.65143], [24.18432, 68.73936], [24.02299, 68.81601], [23.781, 68.84514], [23.68017, 68.70276], [23.13064, 68.64684], [22.53321, 68.74393], [22.38367, 68.71561], [22.27276, 68.89514], [21.63833, 69.27485], [21.27827, 69.31281], [21.00732, 69.22755], [20.98641, 69.18809], [21.11099, 69.10291], [21.05775, 69.0356], [20.72171, 69.11874], [20.55258, 69.06069], [20.78802, 69.03087], [20.91658, 68.96764], [20.85104, 68.93142], [20.90649, 68.89696], [21.03001, 68.88969], [22.00429, 68.50692], [22.73028, 68.40881], [23.10336, 68.26551], [23.15377, 68.14759], [23.26469, 68.15134], [23.40081, 68.05545], [23.65793, 67.9497], [23.45627, 67.85297], [23.54701, 67.59306], [23.39577, 67.46974], [23.75372, 67.43688], [23.75372, 67.29914], [23.54701, 67.25435], [23.58735, 67.20752], [23.56214, 67.17038], [23.98563, 66.84149], [23.98059, 66.79585], [23.89488, 66.772], [23.85959, 66.56434], [23.63776, 66.43568], [23.67591, 66.3862], [23.64982, 66.30603], [23.71339, 66.21299], [23.90497, 66.15802], [24.15791, 65.85385], [24.14798, 65.83466], [24.15107, 65.81427], [24.14112, 65.39731], [20.15877, 63.06556], [19.23413, 60.61414], [20.96741, 60.71528], [21.15143, 60.54555], [21.08159, 60.20167], [21.02509, 60.12142], [21.35468, 59.67511], [20.5104, 59.15546], [26.32936, 60.00121], [27.44953, 60.22766], [27.71177, 60.3893], [27.77352, 60.52722], [28.47974, 60.93365], [28.82816, 61.1233], [29.01829, 61.17448], [31.10136, 62.43042], [31.38369, 62.66284], [31.58535, 62.91642], [31.29294, 63.09035], [31.23244, 63.22239], [30.49637, 63.46666], [29.98213, 63.75795], [30.25437, 63.83364], [30.55687, 64.09036], [30.4762, 64.25728], [30.06279, 64.35782], [30.01238, 64.57513], [30.12329, 64.64862], [30.05271, 64.79072], [29.68972, 64.80789], [29.61914, 65.05993], [29.84096, 65.1109], [29.8813, 65.22101], [29.61914, 65.23791], [29.68972, 65.31803], [29.84096, 65.56945], [29.74013, 65.64025], [29.97205, 65.70256], [30.16363, 65.66935], [29.91155, 66.13863], [28.9839, 66.94139], [29.91155, 67.51507], [30.02041, 67.67523], [29.66955, 67.79872], [29.34179, 68.06655], [28.62982, 68.19816], [28.43941, 68.53366], [28.78224, 68.86696], [28.45957, 68.91417], [28.91738, 69.04774], [28.81248, 69.11997], [28.8629, 69.22395], [29.31664, 69.47994], [29.12697, 69.69193]]]]
23004 wikidata: "Q1184963",
23005 nameEn: "Alhucemas Islands",
23007 groups: ["EU", "Q191011", "015", "002", "UN"],
23008 level: "subterritory"
23011 type: "MultiPolygon",
23012 coordinates: [[[[-3.90602, 35.21494], [-3.88372, 35.20767], [-3.89343, 35.22728], [-3.90602, 35.21494]]]]
23017 wikidata: "Q1298289",
23018 nameEn: "Egmont Islands",
23020 groups: ["IO", "BOTS", "014", "202", "002", "UN"],
23021 level: "subterritory"
23024 type: "MultiPolygon",
23025 coordinates: [[[[70.1848, -6.37445], [70.67958, -8.2663], [72.17991, -6.68509], [70.1848, -6.37445]]]]
23030 wikidata: "Q1352230",
23031 nameEn: "US Territories",
23033 level: "subcountryGroup"
23039 wikidata: "Q1451600",
23040 nameEn: "Overseas Countries and Territories of the EU",
23048 wikidata: "Q1544253",
23049 nameEn: "Great Chagos Bank",
23051 groups: ["IO", "BOTS", "014", "202", "002", "UN"],
23052 level: "subterritory"
23055 type: "MultiPolygon",
23056 coordinates: [[[[70.1848, -6.37445], [72.17991, -6.68509], [73.20573, -5.20727], [70.1848, -6.37445]]]]
23061 wikidata: "Q1585511",
23062 nameEn: "Salomon Atoll",
23064 groups: ["IO", "BOTS", "014", "202", "002", "UN"],
23065 level: "subterritory"
23068 type: "MultiPolygon",
23069 coordinates: [[[[72.09518, -5.61768], [73.20573, -5.20727], [72.12587, -4.02588], [72.09518, -5.61768]]]]
23074 wikidata: "Q1681727",
23075 nameEn: "Saint-Paul and Amsterdam",
23077 groups: ["TF", "Q1451600", "014", "202", "002", "UN"],
23078 level: "subterritory"
23081 type: "MultiPolygon",
23082 coordinates: [[[[76.31747, -42.16264], [80.15867, -36.04977], [71.22311, -38.75287], [76.31747, -42.16264]]]]
23087 wikidata: "Q1901211",
23088 nameEn: "East Malaysia",
23090 groups: ["Q36117", "035", "142", "UN"],
23092 callingCodes: ["60"]
23095 type: "MultiPolygon",
23096 coordinates: [[[[110.90339, 7.52694], [109.82788, 2.86812], [109.62558, 1.99182], [109.53794, 1.91771], [109.57923, 1.80624], [109.66397, 1.79972], [109.66397, 1.60425], [110.35354, 0.98869], [110.49182, 0.88088], [110.62374, 0.873], [111.22979, 1.08326], [111.55434, 0.97864], [111.82846, 0.99349], [111.94553, 1.12016], [112.15679, 1.17004], [112.2127, 1.44135], [112.48648, 1.56516], [113.021, 1.57819], [113.01448, 1.42832], [113.64677, 1.23933], [114.03788, 1.44787], [114.57892, 1.5], [114.80706, 1.92351], [114.80706, 2.21665], [115.1721, 2.49671], [115.11343, 2.82879], [115.53713, 3.14776], [115.58276, 3.93499], [115.90217, 4.37708], [117.25801, 4.35108], [117.47313, 4.18857], [117.67641, 4.16535], [118.06469, 4.16638], [118.93936, 4.09009], [119.52945, 5.35672], [117.98544, 6.27477], [117.93857, 6.89845], [117.17735, 7.52841], [116.79524, 7.43869], [115.02521, 5.35005], [115.16236, 5.01011], [115.15092, 4.87604], [115.20737, 4.8256], [115.27819, 4.63661], [115.2851, 4.42295], [115.36346, 4.33563], [115.31275, 4.30806], [115.09978, 4.39123], [115.07737, 4.53418], [115.04064, 4.63706], [115.02278, 4.74137], [115.02955, 4.82087], [115.05038, 4.90275], [114.99417, 4.88201], [114.96982, 4.81146], [114.88841, 4.81905], [114.8266, 4.75062], [114.77303, 4.72871], [114.83189, 4.42387], [114.88039, 4.4257], [114.78539, 4.12205], [114.64211, 4.00694], [114.49922, 4.13108], [114.4416, 4.27588], [114.32176, 4.2552], [114.32176, 4.34942], [114.26876, 4.49878], [114.15813, 4.57], [114.07448, 4.58441], [114.10166, 4.76112], [110.90339, 7.52694]]]]
23101 wikidata: "Q1973345",
23102 nameEn: "Peninsular Malaysia",
23104 groups: ["035", "142", "UN"],
23106 callingCodes: ["60"]
23109 type: "MultiPolygon",
23110 coordinates: [[[[102.46318, 7.22462], [102.09086, 6.23546], [102.08127, 6.22679], [102.07732, 6.193], [102.09182, 6.14161], [102.01835, 6.05407], [101.99209, 6.04075], [101.97114, 6.01992], [101.9714, 6.00575], [101.94712, 5.98421], [101.92819, 5.85511], [101.91776, 5.84269], [101.89188, 5.8386], [101.80144, 5.74505], [101.75074, 5.79091], [101.69773, 5.75881], [101.58019, 5.93534], [101.25524, 5.78633], [101.25755, 5.71065], [101.14062, 5.61613], [100.98815, 5.79464], [101.02708, 5.91013], [101.087, 5.9193], [101.12388, 6.11411], [101.06165, 6.14161], [101.12618, 6.19431], [101.10313, 6.25617], [100.85884, 6.24929], [100.81045, 6.45086], [100.74822, 6.46231], [100.74361, 6.50811], [100.66986, 6.45086], [100.43027, 6.52389], [100.42351, 6.51762], [100.41791, 6.5189], [100.41152, 6.52299], [100.35413, 6.54932], [100.31929, 6.65413], [100.32607, 6.65933], [100.32671, 6.66526], [100.31884, 6.66423], [100.31618, 6.66781], [100.30828, 6.66462], [100.29651, 6.68439], [100.19511, 6.72559], [100.12, 6.42105], [100.0756, 6.4045], [99.91873, 6.50233], [99.50117, 6.44501], [99.31854, 5.99868], [99.75778, 3.86466], [103.03657, 1.30383], [103.56591, 1.19719], [103.62738, 1.35255], [103.67468, 1.43166], [103.7219, 1.46108], [103.74161, 1.4502], [103.76395, 1.45183], [103.81181, 1.47953], [103.86383, 1.46288], [103.89565, 1.42841], [103.93384, 1.42926], [104.00131, 1.42405], [104.02277, 1.4438], [104.04622, 1.44691], [104.07348, 1.43322], [104.08871, 1.42015], [104.09162, 1.39694], [104.08072, 1.35998], [104.12282, 1.27714], [104.34728, 1.33529], [104.56723, 1.44271], [105.01437, 3.24936], [102.46318, 7.22462]]]]
23115 wikidata: "Q2093907",
23116 nameEn: "Three Kings Islands",
23118 groups: ["Q851132", "053", "009", "UN"],
23122 type: "MultiPolygon",
23123 coordinates: [[[[174.17679, -32.62487], [170.93268, -32.97889], [171.97383, -34.64644], [174.17679, -32.62487]]]]
23128 wikidata: "Q2298216",
23129 nameEn: "Solander Islands",
23131 groups: ["Q851132", "053", "009", "UN"],
23135 type: "MultiPolygon",
23136 coordinates: [[[[167.39068, -46.49187], [166.5534, -46.39484], [166.84561, -46.84889], [167.39068, -46.49187]]]]
23141 wikidata: "Q2872203",
23142 nameEn: "Mainland Australia",
23144 groups: ["053", "009", "UN"],
23145 level: "subcountryGroup",
23147 callingCodes: ["61"]
23150 type: "MultiPolygon",
23151 coordinates: [[[[88.16419, -23.49578], [123.64533, -39.13605], [159.74028, -39.1978], [159.76765, -29.76946], [154.02855, -24.43238], [152.93188, -20.92631], [147.69992, -17.5933], [145.2855, -9.62524], [143.87386, -9.02382], [143.29772, -9.33993], [142.48658, -9.36754], [142.19246, -9.15378], [141.88934, -9.36111], [141.01842, -9.35091], [135.49042, -9.2276], [127.55165, -9.05052], [125.29076, -12.33139], [88.16419, -23.49578]]]]
23156 wikidata: "Q2914565",
23157 nameEn: "Autonomous Regions of Portugal",
23159 level: "subcountryGroup"
23165 wikidata: "Q2915956",
23166 nameEn: "Mainland Portugal",
23168 groups: ["Q12837", "EU", "039", "150", "UN"],
23169 level: "subcountryGroup",
23170 callingCodes: ["351"]
23173 type: "MultiPolygon",
23174 coordinates: [[[[-10.39881, 36.12218], [-7.37282, 36.96896], [-7.39769, 37.16868], [-7.41133, 37.20314], [-7.41854, 37.23813], [-7.43227, 37.25152], [-7.43974, 37.38913], [-7.46878, 37.47127], [-7.51759, 37.56119], [-7.41981, 37.75729], [-7.33441, 37.81193], [-7.27314, 37.90145], [-7.24544, 37.98884], [-7.12648, 38.00296], [-7.10366, 38.04404], [-7.05966, 38.01966], [-7.00375, 38.01914], [-6.93418, 38.21454], [-7.09389, 38.17227], [-7.15581, 38.27597], [-7.32529, 38.44336], [-7.265, 38.61674], [-7.26174, 38.72107], [-7.03848, 38.87221], [-7.051, 38.907], [-6.95211, 39.0243], [-6.97004, 39.07619], [-7.04011, 39.11919], [-7.10692, 39.10275], [-7.14929, 39.11287], [-7.12811, 39.17101], [-7.23566, 39.20132], [-7.23403, 39.27579], [-7.3149, 39.34857], [-7.2927, 39.45847], [-7.49477, 39.58794], [-7.54121, 39.66717], [-7.33507, 39.64569], [-7.24707, 39.66576], [-7.01613, 39.66877], [-6.97492, 39.81488], [-6.91463, 39.86618], [-6.86737, 40.01986], [-6.94233, 40.10716], [-7.00589, 40.12087], [-7.02544, 40.18564], [-7.00426, 40.23169], [-6.86085, 40.26776], [-6.86085, 40.2976], [-6.80218, 40.33239], [-6.78426, 40.36468], [-6.84618, 40.42177], [-6.84944, 40.46394], [-6.7973, 40.51723], [-6.80218, 40.55067], [-6.84292, 40.56801], [-6.79567, 40.65955], [-6.82826, 40.74603], [-6.82337, 40.84472], [-6.79892, 40.84842], [-6.80707, 40.88047], [-6.84292, 40.89771], [-6.8527, 40.93958], [-6.9357, 41.02888], [-6.913, 41.03922], [-6.88843, 41.03027], [-6.84781, 41.02692], [-6.80942, 41.03629], [-6.79241, 41.05397], [-6.75655, 41.10187], [-6.77319, 41.13049], [-6.69711, 41.1858], [-6.68286, 41.21641], [-6.65046, 41.24725], [-6.55937, 41.24417], [-6.38551, 41.35274], [-6.38553, 41.38655], [-6.3306, 41.37677], [-6.26777, 41.48796], [-6.19128, 41.57638], [-6.29863, 41.66432], [-6.44204, 41.68258], [-6.49907, 41.65823], [-6.54633, 41.68623], [-6.56426, 41.74219], [-6.51374, 41.8758], [-6.56752, 41.88429], [-6.5447, 41.94371], [-6.58544, 41.96674], [-6.61967, 41.94008], [-6.75004, 41.94129], [-6.76959, 41.98734], [-6.81196, 41.99097], [-6.82174, 41.94493], [-6.94396, 41.94403], [-6.95537, 41.96553], [-6.98144, 41.9728], [-7.01078, 41.94977], [-7.07596, 41.94977], [-7.08574, 41.97401], [-7.14115, 41.98855], [-7.18549, 41.97515], [-7.18677, 41.88793], [-7.32366, 41.8406], [-7.37092, 41.85031], [-7.42864, 41.80589], [-7.42854, 41.83262], [-7.44759, 41.84451], [-7.45566, 41.86488], [-7.49803, 41.87095], [-7.52737, 41.83939], [-7.62188, 41.83089], [-7.58603, 41.87944], [-7.65774, 41.88308], [-7.69848, 41.90977], [-7.84188, 41.88065], [-7.88055, 41.84571], [-7.88751, 41.92553], [-7.90707, 41.92432], [-7.92336, 41.8758], [-7.9804, 41.87337], [-8.01136, 41.83453], [-8.0961, 41.81024], [-8.16455, 41.81753], [-8.16944, 41.87944], [-8.19551, 41.87459], [-8.2185, 41.91237], [-8.16232, 41.9828], [-8.08796, 42.01398], [-8.08847, 42.05767], [-8.11729, 42.08537], [-8.18178, 42.06436], [-8.19406, 42.12141], [-8.18947, 42.13853], [-8.1986, 42.15402], [-8.22406, 42.1328], [-8.24681, 42.13993], [-8.2732, 42.12396], [-8.29809, 42.106], [-8.32161, 42.10218], [-8.33912, 42.08358], [-8.36353, 42.09065], [-8.38323, 42.07683], [-8.40143, 42.08052], [-8.42512, 42.07199], [-8.44123, 42.08218], [-8.48185, 42.0811], [-8.52837, 42.07658], [-8.5252, 42.06264], [-8.54563, 42.0537], [-8.58086, 42.05147], [-8.59493, 42.05708], [-8.63791, 42.04691], [-8.64626, 42.03668], [-8.65832, 42.02972], [-8.6681, 41.99703], [-8.69071, 41.98862], [-8.7478, 41.96282], [-8.74606, 41.9469], [-8.75712, 41.92833], [-8.81794, 41.90375], [-8.87157, 41.86488], [-11.19304, 41.83075], [-10.39881, 36.12218]]]]
23179 wikidata: "Q3311985",
23180 nameEn: "Guernsey",
23182 groups: ["GG", "830", "Q185086", "154", "150", "UN"],
23183 level: "subterritory",
23185 roadSpeedUnit: "mph",
23186 roadHeightUnit: "ft",
23187 callingCodes: ["44 01481"]
23190 type: "MultiPolygon",
23191 coordinates: [[[[-2.49556, 49.79012], [-3.28154, 49.57329], [-2.65349, 49.15373], [-2.36485, 49.48223], [-2.49556, 49.79012]]]]
23196 wikidata: "Q3320166",
23197 nameEn: "Outermost Regions of the EU",
23205 wikidata: "Q3336843",
23206 nameEn: "Countries of the United Kingdom",
23208 level: "subcountryGroup"
23214 wikidata: "Q6736667",
23215 nameEn: "Mainland India",
23217 groups: ["034", "142", "UN"],
23219 callingCodes: ["91"]
23222 type: "MultiPolygon",
23223 coordinates: [[[[89.08044, 21.41871], [89.07114, 22.15335], [88.9367, 22.58527], [88.94614, 22.66941], [88.9151, 22.75228], [88.96713, 22.83346], [88.87063, 22.95235], [88.88327, 23.03885], [88.86377, 23.08759], [88.99148, 23.21134], [88.71133, 23.2492], [88.79254, 23.46028], [88.79351, 23.50535], [88.74841, 23.47361], [88.56507, 23.64044], [88.58087, 23.87105], [88.66189, 23.87607], [88.73743, 23.91751], [88.6976, 24.14703], [88.74841, 24.1959], [88.68801, 24.31464], [88.50934, 24.32474], [88.12296, 24.51301], [88.08786, 24.63232], [88.00683, 24.66477], [88.15515, 24.85806], [88.14004, 24.93529], [88.21832, 24.96642], [88.27325, 24.88796], [88.33917, 24.86803], [88.46277, 25.07468], [88.44766, 25.20149], [88.94067, 25.18534], [89.00463, 25.26583], [89.01105, 25.30303], [88.85278, 25.34679], [88.81296, 25.51546], [88.677, 25.46959], [88.4559, 25.59227], [88.45103, 25.66245], [88.242, 25.80811], [88.13138, 25.78773], [88.08804, 25.91334], [88.16581, 26.0238], [88.1844, 26.14417], [88.34757, 26.22216], [88.35153, 26.29123], [88.51649, 26.35923], [88.48749, 26.45855], [88.36938, 26.48683], [88.35153, 26.45241], [88.33093, 26.48929], [88.41196, 26.63837], [88.4298, 26.54489], [88.62144, 26.46783], [88.69485, 26.38353], [88.67837, 26.26291], [88.78961, 26.31093], [88.85004, 26.23211], [89.05328, 26.2469], [88.91321, 26.37984], [88.92357, 26.40711], [88.95612, 26.4564], [89.08899, 26.38845], [89.15869, 26.13708], [89.35953, 26.0077], [89.53515, 26.00382], [89.57101, 25.9682], [89.63968, 26.22595], [89.70201, 26.15138], [89.73581, 26.15818], [89.77865, 26.08387], [89.77728, 26.04254], [89.86592, 25.93115], [89.80585, 25.82489], [89.84388, 25.70042], [89.86129, 25.61714], [89.81208, 25.37244], [89.84086, 25.31854], [89.83371, 25.29548], [89.87629, 25.28337], [89.90478, 25.31038], [90.1155, 25.22686], [90.40034, 25.1534], [90.65042, 25.17788], [90.87427, 25.15799], [91.25517, 25.20677], [91.63648, 25.12846], [92.0316, 25.1834], [92.33957, 25.07593], [92.39147, 25.01471], [92.49887, 24.88796], [92.38626, 24.86055], [92.25854, 24.9191], [92.15796, 24.54435], [92.11662, 24.38997], [91.96603, 24.3799], [91.89258, 24.14674], [91.82596, 24.22345], [91.76004, 24.23848], [91.73257, 24.14703], [91.65292, 24.22095], [91.63782, 24.1132], [91.55542, 24.08687], [91.37414, 24.10693], [91.35741, 23.99072], [91.29587, 24.0041], [91.22308, 23.89616], [91.25192, 23.83463], [91.15579, 23.6599], [91.28293, 23.37538], [91.36453, 23.06612], [91.40848, 23.07117], [91.4035, 23.27522], [91.46615, 23.2328], [91.54993, 23.01051], [91.61571, 22.93929], [91.7324, 23.00043], [91.81634, 23.08001], [91.76417, 23.26619], [91.84789, 23.42235], [91.95642, 23.47361], [91.95093, 23.73284], [92.04706, 23.64229], [92.15417, 23.73409], [92.26541, 23.70392], [92.38214, 23.28705], [92.37665, 22.9435], [92.5181, 22.71441], [92.60029, 22.1522], [92.56616, 22.13554], [92.60949, 21.97638], [92.67532, 22.03547], [92.70416, 22.16017], [92.86208, 22.05456], [92.89504, 21.95143], [92.93899, 22.02656], [92.99804, 21.98964], [92.99255, 22.05965], [93.04885, 22.20595], [93.15734, 22.18687], [93.14224, 22.24535], [93.19991, 22.25425], [93.18206, 22.43716], [93.13537, 22.45873], [93.11477, 22.54374], [93.134, 22.59573], [93.09417, 22.69459], [93.134, 22.92498], [93.12988, 23.05772], [93.2878, 23.00464], [93.38478, 23.13698], [93.36862, 23.35426], [93.38781, 23.36139], [93.39981, 23.38828], [93.38805, 23.4728], [93.43475, 23.68299], [93.3908, 23.7622], [93.3908, 23.92925], [93.36059, 23.93176], [93.32351, 24.04468], [93.34735, 24.10151], [93.41415, 24.07854], [93.46633, 23.97067], [93.50616, 23.94432], [93.62871, 24.00922], [93.75952, 24.0003], [93.80279, 23.92549], [93.92089, 23.95812], [94.14081, 23.83333], [94.30215, 24.23752], [94.32362, 24.27692], [94.45279, 24.56656], [94.50729, 24.59281], [94.5526, 24.70764], [94.60204, 24.70889], [94.73937, 25.00545], [94.74212, 25.13606], [94.57458, 25.20318], [94.68032, 25.47003], [94.80117, 25.49359], [95.18556, 26.07338], [95.11428, 26.1019], [95.12801, 26.38397], [95.05798, 26.45408], [95.23513, 26.68499], [95.30339, 26.65372], [95.437, 26.7083], [95.81603, 27.01335], [95.93002, 27.04149], [96.04949, 27.19428], [96.15591, 27.24572], [96.40779, 27.29818], [96.55761, 27.29928], [96.73888, 27.36638], [96.88445, 27.25046], [96.85287, 27.2065], [96.89132, 27.17474], [97.14675, 27.09041], [97.17422, 27.14052], [96.91431, 27.45752], [96.90112, 27.62149], [97.29919, 27.92233], [97.35824, 27.87256], [97.38845, 28.01329], [97.35412, 28.06663], [97.31292, 28.06784], [97.34547, 28.21385], [97.1289, 28.3619], [96.98882, 28.32564], [96.88445, 28.39452], [96.85561, 28.4875], [96.6455, 28.61657], [96.48895, 28.42955], [96.40929, 28.51526], [96.61391, 28.72742], [96.3626, 29.10607], [96.20467, 29.02325], [96.18682, 29.11087], [96.31316, 29.18643], [96.05361, 29.38167], [95.84899, 29.31464], [95.75149, 29.32063], [95.72086, 29.20797], [95.50842, 29.13487], [95.41091, 29.13007], [95.3038, 29.13847], [95.26122, 29.07727], [95.2214, 29.10727], [95.11291, 29.09527], [95.0978, 29.14446], [94.81353, 29.17804], [94.69318, 29.31739], [94.2752, 29.11687], [94.35897, 29.01965], [93.72797, 28.68821], [93.44621, 28.67189], [93.18069, 28.50319], [93.14635, 28.37035], [92.93075, 28.25671], [92.67486, 28.15018], [92.65472, 28.07632], [92.73025, 28.05814], [92.7275, 27.98662], [92.42538, 27.80092], [92.32101, 27.79363], [92.27432, 27.89077], [91.87057, 27.7195], [91.84722, 27.76325], [91.6469, 27.76358], [91.55819, 27.6144], [91.65007, 27.48287], [92.01132, 27.47352], [92.12019, 27.27829], [92.04702, 27.26861], [92.03457, 27.07334], [92.11863, 26.893], [92.05523, 26.8692], [91.83181, 26.87318], [91.50067, 26.79223], [90.67715, 26.77215], [90.48504, 26.8594], [90.39271, 26.90704], [90.30402, 26.85098], [90.04535, 26.72422], [89.86124, 26.73307], [89.63369, 26.74402], [89.42349, 26.83727], [89.3901, 26.84225], [89.38319, 26.85963], [89.37913, 26.86224], [89.1926, 26.81329], [89.12825, 26.81661], [89.09554, 26.89089], [88.95807, 26.92668], [88.92301, 26.99286], [88.8714, 26.97488], [88.86984, 27.10937], [88.74219, 27.144], [88.91901, 27.32483], [88.82981, 27.38814], [88.77517, 27.45415], [88.88091, 27.85192], [88.83559, 28.01936], [88.63235, 28.12356], [88.54858, 28.06057], [88.25332, 27.9478], [88.1278, 27.95417], [88.13378, 27.88015], [88.1973, 27.85067], [88.19107, 27.79285], [88.04008, 27.49223], [88.07277, 27.43007], [88.01646, 27.21612], [88.01587, 27.21388], [87.9887, 27.11045], [88.11719, 26.98758], [88.13422, 26.98705], [88.12302, 26.95324], [88.19107, 26.75516], [88.1659, 26.68177], [88.16452, 26.64111], [88.09963, 26.54195], [88.09414, 26.43732], [88.00895, 26.36029], [87.90115, 26.44923], [87.89085, 26.48565], [87.84193, 26.43663], [87.7918, 26.46737], [87.76004, 26.40711], [87.67893, 26.43501], [87.66803, 26.40294], [87.59175, 26.38342], [87.55274, 26.40596], [87.51571, 26.43106], [87.46566, 26.44058], [87.37314, 26.40815], [87.34568, 26.34787], [87.26568, 26.37294], [87.26587, 26.40592], [87.24682, 26.4143], [87.18863, 26.40558], [87.14751, 26.40542], [87.09147, 26.45039], [87.0707, 26.58571], [87.04691, 26.58685], [87.01559, 26.53228], [86.95912, 26.52076], [86.94543, 26.52076], [86.82898, 26.43919], [86.76797, 26.45892], [86.74025, 26.42386], [86.69124, 26.45169], [86.62686, 26.46891], [86.61313, 26.48658], [86.57073, 26.49825], [86.54258, 26.53819], [86.49726, 26.54218], [86.31564, 26.61925], [86.26235, 26.61886], [86.22513, 26.58863], [86.13596, 26.60651], [86.02729, 26.66756], [85.8492, 26.56667], [85.85126, 26.60866], [85.83126, 26.61134], [85.76907, 26.63076], [85.72315, 26.67471], [85.73483, 26.79613], [85.66239, 26.84822], [85.61621, 26.86721], [85.59461, 26.85161], [85.5757, 26.85955], [85.56471, 26.84133], [85.47752, 26.79292], [85.34302, 26.74954], [85.21159, 26.75933], [85.18046, 26.80519], [85.19291, 26.86909], [85.15883, 26.86966], [85.02635, 26.85381], [85.05592, 26.88991], [85.00536, 26.89523], [84.97186, 26.9149], [84.96687, 26.95599], [84.85754, 26.98984], [84.82913, 27.01989], [84.793, 26.9968], [84.64496, 27.04669], [84.69166, 27.21294], [84.62161, 27.33885], [84.29315, 27.39], [84.25735, 27.44941], [84.21376, 27.45218], [84.10791, 27.52399], [84.02229, 27.43836], [83.93306, 27.44939], [83.86182, 27.4241], [83.85595, 27.35797], [83.61288, 27.47013], [83.39495, 27.4798], [83.38872, 27.39276], [83.35136, 27.33885], [83.29999, 27.32778], [83.2673, 27.36235], [83.27197, 27.38309], [83.19413, 27.45632], [82.94938, 27.46036], [82.93261, 27.50328], [82.74119, 27.49838], [82.70378, 27.72122], [82.46405, 27.6716], [82.06554, 27.92222], [81.97214, 27.93322], [81.91223, 27.84995], [81.47867, 28.08303], [81.48179, 28.12148], [81.38683, 28.17638], [81.32923, 28.13521], [81.19847, 28.36284], [81.03471, 28.40054], [80.55142, 28.69182], [80.50575, 28.6706], [80.52443, 28.54897], [80.44504, 28.63098], [80.37188, 28.63371], [80.12125, 28.82346], [80.06957, 28.82763], [80.05743, 28.91479], [80.18085, 29.13649], [80.23178, 29.11626], [80.26602, 29.13938], [80.24112, 29.21414], [80.28626, 29.20327], [80.31428, 29.30784], [80.24322, 29.44299], [80.37939, 29.57098], [80.41858, 29.63581], [80.38428, 29.68513], [80.36803, 29.73865], [80.41554, 29.79451], [80.43458, 29.80466], [80.48997, 29.79566], [80.56247, 29.86661], [80.57179, 29.91422], [80.60226, 29.95732], [80.67076, 29.95732], [80.8778, 30.13384], [80.86673, 30.17321], [80.91143, 30.22173], [80.92547, 30.17193], [81.03953, 30.20059], [80.83343, 30.32023], [80.54504, 30.44936], [80.20721, 30.58541], [79.93255, 30.88288], [79.59884, 30.93943], [79.30694, 31.17357], [79.14016, 31.43403], [79.01931, 31.42817], [78.89344, 31.30481], [78.77898, 31.31209], [78.71032, 31.50197], [78.84516, 31.60631], [78.69933, 31.78723], [78.78036, 31.99478], [78.74404, 32.00384], [78.68754, 32.10256], [78.49609, 32.2762], [78.4645, 32.45367], [78.38897, 32.53938], [78.73916, 32.69438], [78.7831, 32.46873], [78.96713, 32.33655], [78.99322, 32.37948], [79.0979, 32.38051], [79.13174, 32.47766], [79.26768, 32.53277], [79.46562, 32.69668], [79.14016, 33.02545], [79.15252, 33.17156], [78.73636, 33.56521], [78.67599, 33.66445], [78.77349, 33.73871], [78.73367, 34.01121], [78.65657, 34.03195], [78.66225, 34.08858], [78.91769, 34.15452], [78.99802, 34.3027], [79.05364, 34.32482], [78.74465, 34.45174], [78.56475, 34.50835], [78.54964, 34.57283], [78.27781, 34.61484], [78.18435, 34.7998], [78.22692, 34.88771], [78.00033, 35.23954], [78.03466, 35.3785], [78.11664, 35.48022], [77.80532, 35.52058], [77.70232, 35.46244], [77.44277, 35.46132], [76.96624, 35.5932], [76.84539, 35.67356], [76.77323, 35.66062], [76.75475, 35.52617], [76.85088, 35.39754], [76.93465, 35.39866], [77.11796, 35.05419], [76.99251, 34.93349], [76.87193, 34.96906], [76.74514, 34.92488], [76.74377, 34.84039], [76.67648, 34.76371], [76.47186, 34.78965], [76.15463, 34.6429], [76.04614, 34.67566], [75.75438, 34.51827], [75.38009, 34.55021], [75.01479, 34.64629], [74.6663, 34.703], [74.58083, 34.77386], [74.31239, 34.79626], [74.12897, 34.70073], [73.96423, 34.68244], [73.93401, 34.63386], [73.93951, 34.57169], [73.89419, 34.54568], [73.88732, 34.48911], [73.74999, 34.3781], [73.74862, 34.34183], [73.8475, 34.32935], [73.90517, 34.35317], [73.98208, 34.2522], [73.90677, 34.10504], [73.88732, 34.05105], [73.91341, 34.01235], [74.21554, 34.03853], [74.25262, 34.01577], [74.26086, 33.92237], [74.14001, 33.83002], [74.05898, 33.82089], [74.00891, 33.75437], [73.96423, 33.73071], [73.98968, 33.66155], [73.97367, 33.64061], [74.03576, 33.56718], [74.10115, 33.56392], [74.18121, 33.4745], [74.17983, 33.3679], [74.08782, 33.26232], [74.01366, 33.25199], [74.02144, 33.18908], [74.15374, 33.13477], [74.17571, 33.07495], [74.31854, 33.02891], [74.34875, 32.97823], [74.31227, 32.92795], [74.41467, 32.90563], [74.45312, 32.77755], [74.6289, 32.75561], [74.64675, 32.82604], [74.7113, 32.84219], [74.65345, 32.71225], [74.69542, 32.66792], [74.64424, 32.60985], [74.65251, 32.56416], [74.67431, 32.56676], [74.68362, 32.49298], [74.84725, 32.49075], [74.97634, 32.45367], [75.03265, 32.49538], [75.28259, 32.36556], [75.38046, 32.26836], [75.25649, 32.10187], [75.00793, 32.03786], [74.9269, 32.0658], [74.86236, 32.04485], [74.79919, 31.95983], [74.58907, 31.87824], [74.47771, 31.72227], [74.57498, 31.60382], [74.61517, 31.55698], [74.59319, 31.50197], [74.64713, 31.45605], [74.59773, 31.4136], [74.53223, 31.30321], [74.51629, 31.13829], [74.56023, 31.08303], [74.60281, 31.10419], [74.60006, 31.13711], [74.6852, 31.12771], [74.67971, 31.05479], [74.5616, 31.04153], [73.88993, 30.36305], [73.95736, 30.28466], [73.97225, 30.19829], [73.80299, 30.06969], [73.58665, 30.01848], [73.3962, 29.94707], [73.28094, 29.56646], [73.05886, 29.1878], [73.01337, 29.16422], [72.94272, 29.02487], [72.40402, 28.78283], [72.29495, 28.66367], [72.20329, 28.3869], [71.9244, 28.11555], [71.89921, 27.96035], [70.79054, 27.68423], [70.60927, 28.02178], [70.37307, 28.01208], [70.12502, 27.8057], [70.03136, 27.56627], [69.58519, 27.18109], [69.50904, 26.74892], [69.88555, 26.56836], [70.05584, 26.60398], [70.17532, 26.55362], [70.17532, 26.24118], [70.08193, 26.08094], [70.0985, 25.93238], [70.2687, 25.71156], [70.37444, 25.67443], [70.53649, 25.68928], [70.60378, 25.71898], [70.67382, 25.68186], [70.66695, 25.39314], [70.89148, 25.15064], [70.94002, 24.92843], [71.09405, 24.69017], [70.97594, 24.60904], [71.00341, 24.46038], [71.12838, 24.42662], [71.04461, 24.34657], [70.94985, 24.3791], [70.85784, 24.30903], [70.88393, 24.27398], [70.71502, 24.23517], [70.57906, 24.27774], [70.5667, 24.43787], [70.11712, 24.30915], [70.03428, 24.172], [69.73335, 24.17007], [69.59579, 24.29777], [69.29778, 24.28712], [69.19341, 24.25646], [69.07806, 24.29777], [68.97781, 24.26021], [68.90914, 24.33156], [68.7416, 24.31904], [68.74643, 23.97027], [68.39339, 23.96838], [68.20763, 23.85849], [68.11329, 23.53945], [76.59015, 5.591], [79.50447, 8.91876], [79.42124, 9.80115], [80.48418, 10.20786], [89.08044, 21.41871]]]]
23228 wikidata: "Q9143535",
23229 nameEn: "Akrotiri",
23231 groups: ["Q644636", "Q37362", "BOTS", "145", "142", "UN"],
23232 level: "subterritory",
23234 callingCodes: ["357"]
23237 type: "MultiPolygon",
23238 coordinates: [[[[32.86014, 34.70585], [32.82717, 34.70622], [32.79433, 34.67883], [32.76136, 34.68318], [32.75515, 34.64985], [32.74412, 34.43926], [33.26744, 34.49942], [33.0138, 34.64424], [32.96968, 34.64046], [32.96718, 34.63446], [32.95891, 34.62919], [32.95323, 34.64075], [32.95471, 34.64528], [32.94976, 34.65204], [32.94796, 34.6587], [32.95325, 34.66462], [32.97079, 34.66112], [32.97736, 34.65277], [32.99014, 34.65518], [32.98668, 34.67268], [32.99135, 34.68061], [32.95539, 34.68471], [32.94683, 34.67907], [32.94379, 34.67111], [32.93693, 34.67027], [32.93449, 34.66241], [32.92807, 34.66736], [32.93043, 34.67091], [32.91398, 34.67343], [32.9068, 34.66102], [32.86167, 34.68734], [32.86014, 34.70585]]]]
23243 wikidata: "Q9206745",
23244 nameEn: "Dhekelia",
23246 groups: ["Q644636", "Q37362", "BOTS", "145", "142", "UN"],
23247 level: "subterritory",
23249 callingCodes: ["357"]
23252 type: "MultiPolygon",
23253 coordinates: [[[[33.70575, 34.97947], [33.83531, 34.73974], [33.98684, 34.76642], [33.90075, 34.96623], [33.86432, 34.97592], [33.84811, 34.97075], [33.83505, 34.98108], [33.85621, 34.98956], [33.85891, 35.001], [33.85216, 35.00579], [33.84045, 35.00616], [33.82875, 35.01685], [33.83055, 35.02865], [33.81524, 35.04192], [33.8012, 35.04786], [33.82051, 35.0667], [33.8355, 35.05777], [33.85261, 35.0574], [33.88367, 35.07877], [33.89485, 35.06873], [33.90247, 35.07686], [33.91299, 35.07579], [33.91789, 35.08688], [33.89853, 35.11377], [33.88737, 35.11408], [33.88943, 35.12007], [33.88561, 35.12449], [33.87224, 35.12293], [33.87622, 35.10457], [33.87097, 35.09389], [33.87479, 35.08881], [33.8541, 35.07201], [33.84168, 35.06823], [33.82067, 35.07826], [33.78581, 35.05104], [33.76106, 35.04253], [33.73824, 35.05321], [33.71482, 35.03722], [33.70209, 35.04882], [33.7161, 35.07279], [33.70861, 35.07644], [33.69095, 35.06237], [33.68474, 35.06602], [33.67742, 35.05963], [33.67678, 35.03866], [33.69938, 35.03123], [33.69731, 35.01754], [33.71514, 35.00294], [33.70639, 34.99303], [33.70575, 34.97947]], [[33.77312, 34.9976], [33.77553, 34.99518], [33.78516, 34.99582], [33.79191, 34.98914], [33.78917, 34.98854], [33.78571, 34.98951], [33.78318, 34.98699], [33.78149, 34.98854], [33.77843, 34.988], [33.7778, 34.98981], [33.76738, 34.99188], [33.76605, 34.99543], [33.75682, 34.99916], [33.75994, 35.00113], [33.77312, 34.9976]], [[33.74144, 35.01053], [33.7343, 35.01178], [33.73781, 35.02181], [33.74265, 35.02329], [33.74983, 35.02274], [33.7492, 35.01319], [33.74144, 35.01053]]]]
23258 wikidata: "Q16390686",
23259 nameEn: "Peninsular Spain",
23261 groups: ["Q12837", "EU", "039", "150", "UN"],
23262 callingCodes: ["34"]
23265 type: "MultiPolygon",
23266 coordinates: [[[[3.75438, 42.33445], [3.17156, 42.43545], [3.11379, 42.43646], [3.10027, 42.42621], [3.08167, 42.42748], [3.03734, 42.47363], [2.96518, 42.46692], [2.94283, 42.48174], [2.92107, 42.4573], [2.88413, 42.45938], [2.86983, 42.46843], [2.85675, 42.45444], [2.84335, 42.45724], [2.77464, 42.41046], [2.75497, 42.42578], [2.72056, 42.42298], [2.65311, 42.38771], [2.6747, 42.33974], [2.57934, 42.35808], [2.55516, 42.35351], [2.54382, 42.33406], [2.48457, 42.33933], [2.43508, 42.37568], [2.43299, 42.39423], [2.38504, 42.39977], [2.25551, 42.43757], [2.20578, 42.41633], [2.16599, 42.42314], [2.12789, 42.41291], [2.11621, 42.38393], [2.06241, 42.35906], [2.00488, 42.35399], [1.96482, 42.37787], [1.9574, 42.42401], [1.94084, 42.43039], [1.94061, 42.43333], [1.94292, 42.44316], [1.93663, 42.45439], [1.88853, 42.4501], [1.83037, 42.48395], [1.76335, 42.48863], [1.72515, 42.50338], [1.70571, 42.48867], [1.66826, 42.50779], [1.65674, 42.47125], [1.58933, 42.46275], [1.57953, 42.44957], [1.55937, 42.45808], [1.55073, 42.43299], [1.5127, 42.42959], [1.44529, 42.43724], [1.43838, 42.47848], [1.41648, 42.48315], [1.46661, 42.50949], [1.44759, 42.54431], [1.41245, 42.53539], [1.4234, 42.55959], [1.44529, 42.56722], [1.42512, 42.58292], [1.44197, 42.60217], [1.35562, 42.71944], [1.15928, 42.71407], [1.0804, 42.78569], [0.98292, 42.78754], [0.96166, 42.80629], [0.93089, 42.79154], [0.711, 42.86372], [0.66121, 42.84021], [0.65421, 42.75872], [0.67873, 42.69458], [0.40214, 42.69779], [0.36251, 42.72282], [0.29407, 42.67431], [0.25336, 42.7174], [0.17569, 42.73424], [-0.02468, 42.68513], [-0.10519, 42.72761], [-0.16141, 42.79535], [-0.17939, 42.78974], [-0.3122, 42.84788], [-0.38833, 42.80132], [-0.41319, 42.80776], [-0.44334, 42.79939], [-0.50863, 42.82713], [-0.55497, 42.77846], [-0.67637, 42.88303], [-0.69837, 42.87945], [-0.72608, 42.89318], [-0.73422, 42.91228], [-0.72037, 42.92541], [-0.75478, 42.96916], [-0.81652, 42.95166], [-0.97133, 42.96239], [-1.00963, 42.99279], [-1.10333, 43.0059], [-1.22881, 43.05534], [-1.25244, 43.04164], [-1.30531, 43.06859], [-1.30052, 43.09581], [-1.27118, 43.11961], [-1.32209, 43.1127], [-1.34419, 43.09665], [-1.35272, 43.02658], [-1.44067, 43.047], [-1.47555, 43.08372], [-1.41562, 43.12815], [-1.3758, 43.24511], [-1.40942, 43.27272], [-1.45289, 43.27049], [-1.50992, 43.29481], [-1.55963, 43.28828], [-1.57674, 43.25269], [-1.61341, 43.25269], [-1.63052, 43.28591], [-1.62481, 43.30726], [-1.69407, 43.31378], [-1.73074, 43.29481], [-1.7397, 43.32979], [-1.75079, 43.3317], [-1.75334, 43.34107], [-1.77068, 43.34396], [-1.78714, 43.35476], [-1.78332, 43.36399], [-1.79319, 43.37497], [-1.77289, 43.38957], [-1.81005, 43.59738], [-10.14298, 44.17365], [-11.19304, 41.83075], [-8.87157, 41.86488], [-8.81794, 41.90375], [-8.75712, 41.92833], [-8.74606, 41.9469], [-8.7478, 41.96282], [-8.69071, 41.98862], [-8.6681, 41.99703], [-8.65832, 42.02972], [-8.64626, 42.03668], [-8.63791, 42.04691], [-8.59493, 42.05708], [-8.58086, 42.05147], [-8.54563, 42.0537], [-8.5252, 42.06264], [-8.52837, 42.07658], [-8.48185, 42.0811], [-8.44123, 42.08218], [-8.42512, 42.07199], [-8.40143, 42.08052], [-8.38323, 42.07683], [-8.36353, 42.09065], [-8.33912, 42.08358], [-8.32161, 42.10218], [-8.29809, 42.106], [-8.2732, 42.12396], [-8.24681, 42.13993], [-8.22406, 42.1328], [-8.1986, 42.15402], [-8.18947, 42.13853], [-8.19406, 42.12141], [-8.18178, 42.06436], [-8.11729, 42.08537], [-8.08847, 42.05767], [-8.08796, 42.01398], [-8.16232, 41.9828], [-8.2185, 41.91237], [-8.19551, 41.87459], [-8.16944, 41.87944], [-8.16455, 41.81753], [-8.0961, 41.81024], [-8.01136, 41.83453], [-7.9804, 41.87337], [-7.92336, 41.8758], [-7.90707, 41.92432], [-7.88751, 41.92553], [-7.88055, 41.84571], [-7.84188, 41.88065], [-7.69848, 41.90977], [-7.65774, 41.88308], [-7.58603, 41.87944], [-7.62188, 41.83089], [-7.52737, 41.83939], [-7.49803, 41.87095], [-7.45566, 41.86488], [-7.44759, 41.84451], [-7.42854, 41.83262], [-7.42864, 41.80589], [-7.37092, 41.85031], [-7.32366, 41.8406], [-7.18677, 41.88793], [-7.18549, 41.97515], [-7.14115, 41.98855], [-7.08574, 41.97401], [-7.07596, 41.94977], [-7.01078, 41.94977], [-6.98144, 41.9728], [-6.95537, 41.96553], [-6.94396, 41.94403], [-6.82174, 41.94493], [-6.81196, 41.99097], [-6.76959, 41.98734], [-6.75004, 41.94129], [-6.61967, 41.94008], [-6.58544, 41.96674], [-6.5447, 41.94371], [-6.56752, 41.88429], [-6.51374, 41.8758], [-6.56426, 41.74219], [-6.54633, 41.68623], [-6.49907, 41.65823], [-6.44204, 41.68258], [-6.29863, 41.66432], [-6.19128, 41.57638], [-6.26777, 41.48796], [-6.3306, 41.37677], [-6.38553, 41.38655], [-6.38551, 41.35274], [-6.55937, 41.24417], [-6.65046, 41.24725], [-6.68286, 41.21641], [-6.69711, 41.1858], [-6.77319, 41.13049], [-6.75655, 41.10187], [-6.79241, 41.05397], [-6.80942, 41.03629], [-6.84781, 41.02692], [-6.88843, 41.03027], [-6.913, 41.03922], [-6.9357, 41.02888], [-6.8527, 40.93958], [-6.84292, 40.89771], [-6.80707, 40.88047], [-6.79892, 40.84842], [-6.82337, 40.84472], [-6.82826, 40.74603], [-6.79567, 40.65955], [-6.84292, 40.56801], [-6.80218, 40.55067], [-6.7973, 40.51723], [-6.84944, 40.46394], [-6.84618, 40.42177], [-6.78426, 40.36468], [-6.80218, 40.33239], [-6.86085, 40.2976], [-6.86085, 40.26776], [-7.00426, 40.23169], [-7.02544, 40.18564], [-7.00589, 40.12087], [-6.94233, 40.10716], [-6.86737, 40.01986], [-6.91463, 39.86618], [-6.97492, 39.81488], [-7.01613, 39.66877], [-7.24707, 39.66576], [-7.33507, 39.64569], [-7.54121, 39.66717], [-7.49477, 39.58794], [-7.2927, 39.45847], [-7.3149, 39.34857], [-7.23403, 39.27579], [-7.23566, 39.20132], [-7.12811, 39.17101], [-7.14929, 39.11287], [-7.10692, 39.10275], [-7.04011, 39.11919], [-6.97004, 39.07619], [-6.95211, 39.0243], [-7.051, 38.907], [-7.03848, 38.87221], [-7.26174, 38.72107], [-7.265, 38.61674], [-7.32529, 38.44336], [-7.15581, 38.27597], [-7.09389, 38.17227], [-6.93418, 38.21454], [-7.00375, 38.01914], [-7.05966, 38.01966], [-7.10366, 38.04404], [-7.12648, 38.00296], [-7.24544, 37.98884], [-7.27314, 37.90145], [-7.33441, 37.81193], [-7.41981, 37.75729], [-7.51759, 37.56119], [-7.46878, 37.47127], [-7.43974, 37.38913], [-7.43227, 37.25152], [-7.41854, 37.23813], [-7.41133, 37.20314], [-7.39769, 37.16868], [-7.37282, 36.96896], [-7.2725, 35.73269], [-5.10878, 36.05227], [-2.27707, 35.35051], [3.75438, 42.33445]], [[-5.27801, 36.14942], [-5.34064, 36.03744], [-5.40526, 36.15488], [-5.34536, 36.15501], [-5.33822, 36.15272], [-5.27801, 36.14942]]], [[[1.99838, 42.44682], [2.01564, 42.45171], [1.99216, 42.46208], [1.98579, 42.47486], [1.99766, 42.4858], [1.98916, 42.49351], [1.98022, 42.49569], [1.97697, 42.48568], [1.97227, 42.48487], [1.97003, 42.48081], [1.96215, 42.47854], [1.95606, 42.45785], [1.96125, 42.45364], [1.98378, 42.44697], [1.99838, 42.44682]]]]
23271 wikidata: "Q98059339",
23272 nameEn: "Mainland Norway",
23274 groups: ["154", "150", "UN"],
23275 callingCodes: ["47"]
23278 type: "MultiPolygon",
23279 coordinates: [[[[10.40861, 58.38489], [10.64958, 58.89391], [11.08911, 58.98745], [11.15367, 59.07862], [11.34459, 59.11672], [11.4601, 58.99022], [11.45199, 58.89604], [11.65732, 58.90177], [11.8213, 59.24985], [11.69297, 59.59442], [11.92112, 59.69531], [11.87121, 59.86039], [12.15641, 59.8926], [12.36317, 59.99259], [12.52003, 60.13846], [12.59133, 60.50559], [12.2277, 61.02442], [12.69115, 61.06584], [12.86939, 61.35427], [12.57707, 61.56547], [12.40595, 61.57226], [12.14746, 61.7147], [12.29187, 62.25699], [12.07085, 62.6297], [12.19919, 63.00104], [11.98529, 63.27487], [12.19919, 63.47935], [12.14928, 63.59373], [12.74105, 64.02171], [13.23411, 64.09087], [13.98222, 64.00953], [14.16051, 64.18725], [14.11117, 64.46674], [13.64276, 64.58402], [14.50926, 65.31786], [14.53778, 66.12399], [15.05113, 66.15572], [15.49318, 66.28509], [15.37197, 66.48217], [16.35589, 67.06419], [16.39154, 67.21653], [16.09922, 67.4364], [16.12774, 67.52106], [16.38441, 67.52923], [16.7409, 67.91037], [17.30416, 68.11591], [17.90787, 67.96537], [18.13836, 68.20874], [18.1241, 68.53721], [18.39503, 68.58672], [18.63032, 68.50849], [18.97255, 68.52416], [19.93508, 68.35911], [20.22027, 68.48759], [19.95647, 68.55546], [20.22027, 68.67246], [20.33435, 68.80174], [20.28444, 68.93283], [20.0695, 69.04469], [20.55258, 69.06069], [20.72171, 69.11874], [21.05775, 69.0356], [21.11099, 69.10291], [20.98641, 69.18809], [21.00732, 69.22755], [21.27827, 69.31281], [21.63833, 69.27485], [22.27276, 68.89514], [22.38367, 68.71561], [22.53321, 68.74393], [23.13064, 68.64684], [23.68017, 68.70276], [23.781, 68.84514], [24.02299, 68.81601], [24.18432, 68.73936], [24.74898, 68.65143], [24.90023, 68.55579], [24.93048, 68.61102], [25.10189, 68.63307], [25.12206, 68.78684], [25.42455, 68.90328], [25.61613, 68.89602], [25.75729, 68.99383], [25.69679, 69.27039], [25.96904, 69.68397], [26.40261, 69.91377], [26.64461, 69.96565], [27.05802, 69.92069], [27.57226, 70.06215], [27.95542, 70.0965], [27.97558, 69.99671], [28.32849, 69.88605], [28.36883, 69.81658], [29.12697, 69.69193], [29.31664, 69.47994], [28.8629, 69.22395], [28.81248, 69.11997], [28.91738, 69.04774], [29.0444, 69.0119], [29.26623, 69.13794], [29.27631, 69.2811], [29.97205, 69.41623], [30.16363, 69.65244], [30.52662, 69.54699], [30.95011, 69.54699], [30.84095, 69.80584], [31.59909, 70.16571], [32.07813, 72.01005], [-11.60274, 67.73467], [7.28637, 57.35913], [10.40861, 58.38489]]]]
23284 wikidata: "Q98543636",
23285 nameEn: "Mainland Ecuador",
23287 groups: ["005", "419", "019", "UN"],
23288 callingCodes: ["593"]
23291 type: "MultiPolygon",
23292 coordinates: [[[[-84.52388, -3.36941], [-80.30602, -3.39149], [-80.20647, -3.431], [-80.24123, -3.46124], [-80.24586, -3.48677], [-80.23651, -3.48652], [-80.22629, -3.501], [-80.20535, -3.51667], [-80.21642, -3.5888], [-80.19848, -3.59249], [-80.18741, -3.63994], [-80.19926, -3.68894], [-80.13232, -3.90317], [-80.46386, -4.01342], [-80.4822, -4.05477], [-80.45023, -4.20938], [-80.32114, -4.21323], [-80.46386, -4.41516], [-80.39256, -4.48269], [-80.13945, -4.29786], [-79.79722, -4.47558], [-79.59402, -4.46848], [-79.26248, -4.95167], [-79.1162, -4.97774], [-79.01659, -5.01481], [-78.85149, -4.66795], [-78.68394, -4.60754], [-78.34362, -3.38633], [-78.24589, -3.39907], [-78.22642, -3.51113], [-78.14324, -3.47653], [-78.19369, -3.36431], [-77.94147, -3.05454], [-76.6324, -2.58397], [-76.05203, -2.12179], [-75.57429, -1.55961], [-75.3872, -0.9374], [-75.22862, -0.95588], [-75.22862, -0.60048], [-75.53615, -0.19213], [-75.60169, -0.18708], [-75.61997, -0.10012], [-75.40192, -0.17196], [-75.25764, -0.11943], [-75.82927, 0.09578], [-76.23441, 0.42294], [-76.41215, 0.38228], [-76.4094, 0.24015], [-76.89177, 0.24736], [-77.52001, 0.40782], [-77.49984, 0.64476], [-77.67815, 0.73863], [-77.66416, 0.81604], [-77.68613, 0.83029], [-77.7148, 0.85003], [-77.85677, 0.80197], [-78.42749, 1.15389], [-78.87137, 1.47457], [-82.12561, 4.00341], [-84.52388, -3.36941]]]]
23300 aliases: ["Earth", "Planet"],
23318 nameEn: "North America",
23327 nameEn: "South America",
23328 level: "intermediateRegion"
23345 nameEn: "Western Africa",
23346 level: "intermediateRegion"
23353 wikidata: "Q27611",
23354 nameEn: "Central America",
23355 level: "intermediateRegion"
23362 wikidata: "Q27407",
23363 nameEn: "Eastern Africa",
23364 level: "intermediateRegion"
23371 wikidata: "Q27381",
23372 nameEn: "Northern Africa",
23380 wikidata: "Q27433",
23381 nameEn: "Middle Africa",
23382 level: "intermediateRegion"
23389 wikidata: "Q27394",
23390 nameEn: "Southern Africa",
23391 level: "intermediateRegion"
23399 nameEn: "Americas",
23407 wikidata: "Q2017699",
23408 nameEn: "Northern America",
23416 wikidata: "Q664609",
23417 nameEn: "Caribbean",
23418 level: "intermediateRegion"
23425 wikidata: "Q27231",
23426 nameEn: "Eastern Asia",
23434 wikidata: "Q771405",
23435 nameEn: "Southern Asia",
23443 wikidata: "Q11708",
23444 nameEn: "South-eastern Asia",
23452 wikidata: "Q27449",
23453 nameEn: "Southern Europe",
23461 wikidata: "Q45256",
23462 nameEn: "Australia and New Zealand",
23463 aliases: ["Australasia"],
23471 wikidata: "Q37394",
23472 nameEn: "Melanesia",
23480 wikidata: "Q3359409",
23481 nameEn: "Micronesia",
23489 wikidata: "Q35942",
23490 nameEn: "Polynesia",
23507 wikidata: "Q27275",
23508 nameEn: "Central Asia",
23516 wikidata: "Q27293",
23517 nameEn: "Western Asia",
23534 wikidata: "Q27468",
23535 nameEn: "Eastern Europe",
23543 wikidata: "Q27479",
23544 nameEn: "Northern Europe",
23552 wikidata: "Q27496",
23553 nameEn: "Western Europe",
23561 wikidata: "Q132959",
23562 nameEn: "Sub-Saharan Africa",
23570 wikidata: "Q72829598",
23571 nameEn: "Latin America and the Caribbean",
23579 wikidata: "Q3405693",
23582 groups: ["GG", "830", "Q185086", "154", "150", "UN"],
23583 level: "subterritory",
23585 roadSpeedUnit: "mph",
23586 roadHeightUnit: "ft",
23587 callingCodes: ["44 01481"]
23590 type: "MultiPolygon",
23591 coordinates: [[[[-2.36485, 49.48223], [-2.65349, 49.15373], [-2.09454, 49.46288], [-2.36485, 49.48223]]]]
23597 wikidata: "Q42314",
23598 nameEn: "Channel Islands",
23599 level: "intermediateRegion"
23607 wikidata: "Q46197",
23608 nameEn: "Ascension Island",
23609 aliases: ["SH-AC"],
23611 groups: ["SH", "BOTS", "011", "202", "002", "UN"],
23612 isoStatus: "excRes",
23614 roadSpeedUnit: "mph",
23615 roadHeightUnit: "ft",
23616 callingCodes: ["247"]
23619 type: "MultiPolygon",
23620 coordinates: [[[[-14.82771, -8.70814], [-13.33271, -8.07391], [-14.91926, -6.63386], [-14.82771, -8.70814]]]]
23630 groups: ["Q12837", "039", "150", "UN"],
23631 callingCodes: ["376"]
23634 type: "MultiPolygon",
23635 coordinates: [[[[1.72515, 42.50338], [1.73683, 42.55492], [1.7858, 42.57698], [1.72588, 42.59098], [1.73452, 42.61515], [1.68267, 42.62533], [1.6625, 42.61982], [1.63485, 42.62957], [1.60085, 42.62703], [1.55418, 42.65669], [1.50867, 42.64483], [1.48043, 42.65203], [1.46718, 42.63296], [1.47986, 42.61346], [1.44197, 42.60217], [1.42512, 42.58292], [1.44529, 42.56722], [1.4234, 42.55959], [1.41245, 42.53539], [1.44759, 42.54431], [1.46661, 42.50949], [1.41648, 42.48315], [1.43838, 42.47848], [1.44529, 42.43724], [1.5127, 42.42959], [1.55073, 42.43299], [1.55937, 42.45808], [1.57953, 42.44957], [1.58933, 42.46275], [1.65674, 42.47125], [1.66826, 42.50779], [1.70571, 42.48867], [1.72515, 42.50338]]]]
23644 nameEn: "United Arab Emirates",
23645 groups: ["145", "142", "UN"],
23646 callingCodes: ["971"]
23649 type: "MultiPolygon",
23650 coordinates: [[[[56.26534, 25.62825], [56.25341, 25.61443], [56.26636, 25.60643], [56.25365, 25.60211], [56.20473, 25.61119], [56.18363, 25.65508], [56.14826, 25.66351], [56.13579, 25.73524], [56.17416, 25.77239], [56.13963, 25.82765], [56.19334, 25.9795], [56.15498, 26.06828], [56.08666, 26.05038], [55.81777, 26.18798], [55.14145, 25.62624], [53.97892, 24.64436], [52.82259, 25.51697], [52.35509, 25.00368], [52.02277, 24.75635], [51.83108, 24.71675], [51.58834, 24.66608], [51.41644, 24.39615], [51.58871, 24.27256], [51.59617, 24.12041], [52.56622, 22.94341], [55.13599, 22.63334], [55.2137, 22.71065], [55.22634, 23.10378], [55.57358, 23.669], [55.48677, 23.94946], [55.73301, 24.05994], [55.8308, 24.01633], [56.01799, 24.07426], [55.95472, 24.2172], [55.83367, 24.20193], [55.77658, 24.23476], [55.76558, 24.23227], [55.75257, 24.23466], [55.75382, 24.2466], [55.75939, 24.26114], [55.76781, 24.26209], [55.79145, 24.27914], [55.80747, 24.31069], [55.83395, 24.32776], [55.83271, 24.41521], [55.76461, 24.5287], [55.83271, 24.68567], [55.83408, 24.77858], [55.81348, 24.80102], [55.81116, 24.9116], [55.85094, 24.96858], [55.90849, 24.96771], [55.96316, 25.00857], [56.05715, 24.95727], [56.05106, 24.87461], [55.97467, 24.89639], [55.97836, 24.87673], [56.03535, 24.81161], [56.06128, 24.74457], [56.13684, 24.73699], [56.20062, 24.78565], [56.20568, 24.85063], [56.30269, 24.88334], [56.34873, 24.93205], [56.3227, 24.97284], [56.86325, 25.03856], [56.82555, 25.7713], [56.26534, 25.62825]], [[56.26062, 25.33108], [56.3005, 25.31815], [56.3111, 25.30107], [56.35172, 25.30681], [56.34438, 25.26653], [56.27628, 25.23404], [56.24341, 25.22867], [56.20872, 25.24104], [56.20838, 25.25668], [56.24465, 25.27505], [56.25008, 25.28843], [56.23362, 25.31253], [56.26062, 25.33108]]], [[[56.28423, 25.26344], [56.29379, 25.2754], [56.28102, 25.28486], [56.2716, 25.27916], [56.27086, 25.26128], [56.28423, 25.26344]]]]
23659 nameEn: "Afghanistan",
23660 groups: ["034", "142", "UN"],
23661 callingCodes: ["93"]
23664 type: "MultiPolygon",
23665 coordinates: [[[[70.61526, 38.34774], [70.60407, 38.28046], [70.54673, 38.24541], [70.4898, 38.12546], [70.17206, 37.93276], [70.1863, 37.84296], [70.27694, 37.81258], [70.28243, 37.66706], [70.15015, 37.52519], [69.95971, 37.5659], [69.93362, 37.61378], [69.84435, 37.60616], [69.80041, 37.5746], [69.51888, 37.5844], [69.44954, 37.4869], [69.36645, 37.40462], [69.45022, 37.23315], [69.39529, 37.16752], [69.25152, 37.09426], [69.03274, 37.25174], [68.96407, 37.32603], [68.88168, 37.33368], [68.91189, 37.26704], [68.80889, 37.32494], [68.81438, 37.23862], [68.6798, 37.27906], [68.61851, 37.19815], [68.41888, 37.13906], [68.41201, 37.10402], [68.29253, 37.10621], [68.27605, 37.00977], [68.18542, 37.02074], [68.02194, 36.91923], [67.87917, 37.0591], [67.7803, 37.08978], [67.78329, 37.1834], [67.51868, 37.26102], [67.2581, 37.17216], [67.2224, 37.24545], [67.13039, 37.27168], [67.08232, 37.35469], [66.95598, 37.40162], [66.64699, 37.32958], [66.55743, 37.35409], [66.30993, 37.32409], [65.72274, 37.55438], [65.64137, 37.45061], [65.64263, 37.34388], [65.51778, 37.23881], [64.97945, 37.21913], [64.61141, 36.6351], [64.62514, 36.44311], [64.57295, 36.34362], [64.43288, 36.24401], [64.05385, 36.10433], [63.98519, 36.03773], [63.56496, 35.95106], [63.53475, 35.90881], [63.29579, 35.85985], [63.12276, 35.86208], [63.10318, 35.81782], [63.23262, 35.67487], [63.10079, 35.63024], [63.12276, 35.53196], [63.0898, 35.43131], [62.90853, 35.37086], [62.74098, 35.25432], [62.62288, 35.22067], [62.48006, 35.28796], [62.29878, 35.13312], [62.29191, 35.25964], [62.15871, 35.33278], [62.05709, 35.43803], [61.97743, 35.4604], [61.77693, 35.41341], [61.58742, 35.43803], [61.27371, 35.61482], [61.18187, 35.30249], [61.0991, 35.27845], [61.12831, 35.09938], [61.06926, 34.82139], [61.00197, 34.70631], [60.99922, 34.63064], [60.72316, 34.52857], [60.91321, 34.30411], [60.66502, 34.31539], [60.50209, 34.13992], [60.5838, 33.80793], [60.5485, 33.73422], [60.57762, 33.59772], [60.69573, 33.56054], [60.91133, 33.55596], [60.88908, 33.50219], [60.56485, 33.12944], [60.86191, 32.22565], [60.84541, 31.49561], [61.70929, 31.37391], [61.80569, 31.16167], [61.80957, 31.12576], [61.83257, 31.0452], [61.8335, 30.97669], [61.78268, 30.92724], [61.80829, 30.84224], [60.87231, 29.86514], [62.47751, 29.40782], [63.5876, 29.50456], [64.12966, 29.39157], [64.19796, 29.50407], [64.62116, 29.58903], [65.04005, 29.53957], [66.24175, 29.85181], [66.36042, 29.9583], [66.23609, 30.06321], [66.34869, 30.404], [66.28413, 30.57001], [66.39194, 30.9408], [66.42645, 30.95309], [66.58175, 30.97532], [66.68166, 31.07597], [66.72561, 31.20526], [66.83273, 31.26867], [67.04147, 31.31561], [67.03323, 31.24519], [67.29964, 31.19586], [67.78854, 31.33203], [67.7748, 31.4188], [67.62374, 31.40473], [67.58323, 31.52772], [67.72056, 31.52304], [67.86887, 31.63536], [68.00071, 31.6564], [68.1655, 31.82691], [68.25614, 31.80357], [68.27605, 31.75863], [68.44222, 31.76446], [68.57475, 31.83158], [68.6956, 31.75687], [68.79997, 31.61665], [68.91078, 31.59687], [68.95995, 31.64822], [69.00939, 31.62249], [69.11514, 31.70782], [69.20577, 31.85957], [69.3225, 31.93186], [69.27032, 32.14141], [69.27932, 32.29119], [69.23599, 32.45946], [69.2868, 32.53938], [69.38155, 32.56601], [69.44747, 32.6678], [69.43649, 32.7302], [69.38018, 32.76601], [69.47082, 32.85834], [69.5436, 32.8768], [69.49854, 32.88843], [69.49004, 33.01509], [69.57656, 33.09911], [69.71526, 33.09911], [69.79766, 33.13247], [69.85259, 33.09451], [70.02563, 33.14282], [70.07369, 33.22557], [70.13686, 33.21064], [70.32775, 33.34496], [70.17062, 33.53535], [70.20141, 33.64387], [70.14785, 33.6553], [70.14236, 33.71701], [70.00503, 33.73528], [69.85671, 33.93719], [69.87307, 33.9689], [69.90203, 34.04194], [70.54336, 33.9463], [70.88119, 33.97933], [71.07345, 34.06242], [71.06933, 34.10564], [71.09307, 34.11961], [71.09453, 34.13524], [71.13078, 34.16503], [71.12815, 34.26619], [71.17662, 34.36769], [71.02401, 34.44835], [71.0089, 34.54568], [71.11602, 34.63047], [71.08718, 34.69034], [71.28356, 34.80882], [71.29472, 34.87728], [71.50329, 34.97328], [71.49917, 35.00478], [71.55273, 35.02615], [71.52938, 35.09023], [71.67495, 35.21262], [71.5541, 35.28776], [71.54294, 35.31037], [71.65435, 35.4479], [71.49917, 35.6267], [71.55273, 35.71483], [71.37969, 35.95865], [71.19505, 36.04134], [71.60491, 36.39429], [71.80267, 36.49924], [72.18135, 36.71838], [72.6323, 36.84601], [73.82685, 36.91421], [74.04856, 36.82648], [74.43389, 37.00977], [74.53739, 36.96224], [74.56453, 37.03023], [74.49981, 37.24518], [74.80605, 37.21565], [74.88887, 37.23275], [74.8294, 37.3435], [74.68383, 37.3948], [74.56161, 37.37734], [74.41055, 37.3948], [74.23339, 37.41116], [74.20308, 37.34208], [73.8564, 37.26158], [73.82552, 37.22659], [73.64974, 37.23643], [73.61129, 37.27469], [73.76647, 37.33913], [73.77197, 37.4417], [73.29633, 37.46495], [73.06884, 37.31729], [72.79693, 37.22222], [72.66381, 37.02014], [72.54095, 37.00007], [72.31676, 36.98115], [71.83229, 36.68084], [71.67083, 36.67346], [71.57195, 36.74943], [71.51502, 36.89128], [71.48481, 36.93218], [71.46923, 36.99925], [71.45578, 37.03094], [71.43097, 37.05855], [71.44127, 37.11856], [71.4494, 37.18137], [71.4555, 37.21418], [71.47386, 37.2269], [71.48339, 37.23937], [71.4824, 37.24921], [71.48536, 37.26017], [71.50674, 37.31502], [71.49821, 37.31975], [71.4862, 37.33405], [71.47685, 37.40281], [71.49612, 37.4279], [71.5256, 37.47971], [71.50616, 37.50733], [71.49693, 37.53527], [71.5065, 37.60912], [71.51972, 37.61945], [71.54186, 37.69691], [71.55234, 37.73209], [71.53053, 37.76534], [71.54324, 37.77104], [71.55752, 37.78677], [71.59255, 37.79956], [71.58843, 37.92425], [71.51565, 37.95349], [71.32871, 37.88564], [71.296, 37.93403], [71.2809, 37.91995], [71.24969, 37.93031], [71.27278, 37.96496], [71.27622, 37.99946], [71.28922, 38.01272], [71.29878, 38.04429], [71.36444, 38.15358], [71.37803, 38.25641], [71.33869, 38.27335], [71.33114, 38.30339], [71.21291, 38.32797], [71.1451, 38.40106], [71.10957, 38.40671], [71.10592, 38.42077], [71.09542, 38.42517], [71.0556, 38.40176], [71.03545, 38.44779], [70.98693, 38.48862], [70.92728, 38.43021], [70.88719, 38.46826], [70.84376, 38.44688], [70.82538, 38.45394], [70.81697, 38.44507], [70.80521, 38.44447], [70.79766, 38.44944], [70.78702, 38.45031], [70.78581, 38.45502], [70.77132, 38.45548], [70.75455, 38.4252], [70.72485, 38.4131], [70.69807, 38.41861], [70.67438, 38.40597], [70.6761, 38.39144], [70.69189, 38.37031], [70.64966, 38.34999], [70.61526, 38.34774]]]]
23674 nameEn: "Antigua and Barbuda",
23675 groups: ["029", "003", "419", "019", "UN"],
23677 roadSpeedUnit: "mph",
23678 callingCodes: ["1 268"]
23681 type: "MultiPolygon",
23682 coordinates: [[[[-61.66959, 18.6782], [-62.58307, 16.68909], [-62.1023, 16.97277], [-61.23098, 16.62484], [-61.66959, 18.6782]]]]
23690 wikidata: "Q25228",
23691 nameEn: "Anguilla",
23693 groups: ["BOTS", "029", "003", "419", "019", "UN"],
23695 roadSpeedUnit: "mph",
23696 callingCodes: ["1 264"]
23699 type: "MultiPolygon",
23700 coordinates: [[[[-63.79029, 19.11219], [-63.35989, 18.06012], [-62.62718, 18.26185], [-63.79029, 19.11219]]]]
23710 groups: ["039", "150", "UN"],
23711 callingCodes: ["355"]
23714 type: "MultiPolygon",
23715 coordinates: [[[[20.07761, 42.55582], [20.01834, 42.54622], [20.00842, 42.5109], [19.9324, 42.51699], [19.82333, 42.46581], [19.76549, 42.50237], [19.74731, 42.57422], [19.77375, 42.58517], [19.73244, 42.66299], [19.65972, 42.62774], [19.4836, 42.40831], [19.42352, 42.36546], [19.42, 42.33019], [19.28623, 42.17745], [19.40687, 42.10024], [19.37548, 42.06835], [19.36867, 42.02564], [19.37691, 41.96977], [19.34601, 41.95675], [19.33812, 41.90669], [19.37451, 41.8842], [19.37597, 41.84849], [19.26406, 41.74971], [19.0384, 40.35325], [19.95905, 39.82857], [19.97622, 39.78684], [19.92466, 39.69533], [19.98042, 39.6504], [20.00957, 39.69227], [20.05189, 39.69112], [20.12956, 39.65805], [20.15988, 39.652], [20.22376, 39.64532], [20.22707, 39.67459], [20.27412, 39.69884], [20.31961, 39.72799], [20.29152, 39.80421], [20.30804, 39.81563], [20.38572, 39.78516], [20.41475, 39.81437], [20.41546, 39.82832], [20.31135, 39.99438], [20.37911, 39.99058], [20.42373, 40.06777], [20.48487, 40.06271], [20.51297, 40.08168], [20.55593, 40.06524], [20.61081, 40.07866], [20.62566, 40.0897], [20.67162, 40.09433], [20.71789, 40.27739], [20.78234, 40.35803], [20.7906, 40.42726], [20.83688, 40.47882], [20.94925, 40.46625], [20.96908, 40.51526], [21.03932, 40.56299], [21.05833, 40.66586], [20.98134, 40.76046], [20.95752, 40.76982], [20.98396, 40.79109], [20.97887, 40.85475], [20.97693, 40.90103], [20.94305, 40.92399], [20.83671, 40.92752], [20.81567, 40.89662], [20.73504, 40.9081], [20.71634, 40.91781], [20.65558, 41.08009], [20.63454, 41.0889], [20.59832, 41.09066], [20.58546, 41.11179], [20.59715, 41.13644], [20.51068, 41.2323], [20.49432, 41.33679], [20.52119, 41.34381], [20.55976, 41.4087], [20.51301, 41.442], [20.49039, 41.49277], [20.45331, 41.51436], [20.45809, 41.5549], [20.52103, 41.56473], [20.55508, 41.58113], [20.51769, 41.65975], [20.52937, 41.69292], [20.51301, 41.72433], [20.53405, 41.78099], [20.57144, 41.7897], [20.55976, 41.87068], [20.59524, 41.8818], [20.57946, 41.91593], [20.63069, 41.94913], [20.59434, 42.03879], [20.55633, 42.08173], [20.56955, 42.12097], [20.48857, 42.25444], [20.3819, 42.3029], [20.34479, 42.32656], [20.24399, 42.32168], [20.21797, 42.41237], [20.17127, 42.50469], [20.07761, 42.55582]]]]
23725 groups: ["145", "142", "UN"],
23726 callingCodes: ["374"]
23729 type: "MultiPolygon",
23730 coordinates: [[[[45.0133, 41.29747], [44.93493, 41.25685], [44.81437, 41.30371], [44.80053, 41.25949], [44.81749, 41.23488], [44.84358, 41.23088], [44.89911, 41.21366], [44.87887, 41.20195], [44.82084, 41.21513], [44.72814, 41.20338], [44.61462, 41.24018], [44.59322, 41.1933], [44.46791, 41.18204], [44.34417, 41.2382], [44.34337, 41.20312], [44.32139, 41.2079], [44.18148, 41.24644], [44.16591, 41.19141], [43.84835, 41.16329], [43.74717, 41.1117], [43.67712, 41.13398], [43.4717, 41.12611], [43.44984, 41.0988], [43.47319, 41.02251], [43.58683, 40.98961], [43.67712, 40.93084], [43.67712, 40.84846], [43.74872, 40.7365], [43.7425, 40.66805], [43.63664, 40.54159], [43.54791, 40.47413], [43.60862, 40.43267], [43.59928, 40.34019], [43.71136, 40.16673], [43.65221, 40.14889], [43.65688, 40.11199], [43.92307, 40.01787], [44.1057, 40.03555], [44.1778, 40.02845], [44.26973, 40.04866], [44.46635, 39.97733], [44.61845, 39.8281], [44.75779, 39.7148], [44.88354, 39.74432], [44.92869, 39.72157], [45.06604, 39.79277], [45.18554, 39.67846], [45.17464, 39.58614], [45.21784, 39.58074], [45.23535, 39.61373], [45.30385, 39.61373], [45.29606, 39.57654], [45.46992, 39.49888], [45.70547, 39.60174], [45.80804, 39.56716], [45.83, 39.46487], [45.79225, 39.3695], [45.99774, 39.28931], [46.02303, 39.09978], [46.06973, 39.0744], [46.14785, 38.84206], [46.20601, 38.85262], [46.34059, 38.92076], [46.53497, 38.86548], [46.51805, 38.94982], [46.54296, 39.07078], [46.44022, 39.19636], [46.52584, 39.18912], [46.54141, 39.15895], [46.58032, 39.21204], [46.63481, 39.23013], [46.56476, 39.24942], [46.50093, 39.33736], [46.43244, 39.35181], [46.37795, 39.42039], [46.4013, 39.45405], [46.53051, 39.47809], [46.51027, 39.52373], [46.57721, 39.54414], [46.57098, 39.56694], [46.52117, 39.58734], [46.42465, 39.57534], [46.40286, 39.63651], [46.18493, 39.60533], [45.96543, 39.78859], [45.82533, 39.82925], [45.7833, 39.9475], [45.60895, 39.97733], [45.59806, 40.0131], [45.78642, 40.03218], [45.83779, 39.98925], [45.97944, 40.181], [45.95609, 40.27846], [45.65098, 40.37696], [45.42994, 40.53804], [45.45484, 40.57707], [45.35366, 40.65979], [45.4206, 40.7424], [45.55914, 40.78366], [45.60584, 40.87436], [45.40814, 40.97904], [45.44083, 41.01663], [45.39725, 41.02603], [45.35677, 40.99784], [45.28859, 41.03757], [45.26162, 41.0228], [45.25897, 41.0027], [45.1994, 41.04518], [45.16493, 41.05068], [45.1634, 41.08082], [45.1313, 41.09369], [45.12923, 41.06059], [45.06784, 41.05379], [45.08028, 41.10917], [45.19942, 41.13299], [45.1969, 41.168], [45.11811, 41.19967], [45.05201, 41.19211], [45.02932, 41.2101], [45.05497, 41.2464], [45.0133, 41.29747]], [[45.21324, 40.9817], [45.21219, 40.99001], [45.20518, 40.99348], [45.19312, 40.98998], [45.18382, 41.0066], [45.20625, 41.01484], [45.23487, 41.00226], [45.23095, 40.97828], [45.21324, 40.9817]], [[45.00864, 41.03411], [44.9903, 41.05657], [44.96031, 41.06345], [44.95383, 41.07553], [44.97169, 41.09176], [45.00864, 41.09407], [45.03406, 41.07931], [45.04517, 41.06653], [45.03792, 41.03938], [45.00864, 41.03411]]], [[[45.50279, 40.58424], [45.56071, 40.64765], [45.51825, 40.67382], [45.47927, 40.65023], [45.50279, 40.58424]]]]
23740 groups: ["017", "202", "002", "UN"],
23741 callingCodes: ["244"]
23744 type: "MultiPolygon",
23745 coordinates: [[[[16.55507, -5.85631], [13.04371, -5.87078], [12.42245, -6.07585], [11.95767, -5.94705], [12.20376, -5.76338], [12.26557, -5.74031], [12.52318, -5.74353], [12.52301, -5.17481], [12.53599, -5.1618], [12.53586, -5.14658], [12.51589, -5.1332], [12.49815, -5.14058], [12.46297, -5.09408], [12.60251, -5.01715], [12.63465, -4.94632], [12.70868, -4.95505], [12.8733, -4.74346], [13.11195, -4.67745], [13.09648, -4.63739], [12.91489, -4.47907], [12.87096, -4.40315], [12.76844, -4.38709], [12.64835, -4.55937], [12.40964, -4.60609], [12.32324, -4.78415], [12.25587, -4.79437], [12.20901, -4.75642], [12.16068, -4.90089], [12.00924, -5.02627], [11.50888, -5.33417], [10.5065, -17.25284], [11.75063, -17.25013], [12.07076, -17.15165], [12.52111, -17.24495], [12.97145, -16.98567], [13.36212, -16.98048], [13.95896, -17.43141], [14.28743, -17.38814], [18.39229, -17.38927], [18.84226, -17.80375], [21.14283, -17.94318], [21.42741, -18.02787], [23.47474, -17.62877], [23.20038, -17.47563], [22.17217, -16.50269], [22.00323, -16.18028], [21.97988, -13.00148], [24.03339, -12.99091], [23.90937, -12.844], [24.06672, -12.29058], [23.98804, -12.13149], [24.02603, -11.15368], [24.00027, -10.89356], [23.86868, -11.02856], [23.45631, -10.946], [23.16602, -11.10577], [22.54205, -11.05784], [22.25951, -11.24911], [22.17954, -10.85884], [22.32604, -10.76291], [22.19039, -9.94628], [21.84856, -9.59871], [21.79824, -7.29628], [20.56263, -7.28566], [20.61689, -6.90876], [20.31846, -6.91953], [20.30218, -6.98955], [19.5469, -7.00195], [19.33698, -7.99743], [18.33635, -8.00126], [17.5828, -8.13784], [16.96282, -7.21787], [16.55507, -5.85631]]]]
23754 nameEn: "Antarctica",
23756 callingCodes: ["672"]
23759 type: "MultiPolygon",
23760 coordinates: [[[[180, -60], [-180, -60], [-180, -90], [180, -90], [180, -60]]]]
23769 nameEn: "Argentina",
23771 groups: ["005", "419", "019", "UN"],
23772 callingCodes: ["54"]
23775 type: "MultiPolygon",
23776 coordinates: [[[[-72.31343, -50.58411], [-72.33873, -51.59954], [-71.99889, -51.98018], [-69.97824, -52.00845], [-68.41683, -52.33516], [-68.60702, -52.65781], [-68.60733, -54.9125], [-68.01394, -54.8753], [-67.46182, -54.92205], [-67.11046, -54.94199], [-66.07313, -55.19618], [-63.67376, -55.11859], [-54.78916, -36.21945], [-57.83001, -34.69099], [-58.34425, -34.15035], [-58.44442, -33.84033], [-58.40475, -33.11777], [-58.1224, -32.98842], [-58.22362, -32.52416], [-58.10036, -32.25338], [-58.20252, -31.86966], [-58.00076, -31.65016], [-58.0023, -31.53084], [-58.07569, -31.44916], [-57.98127, -31.3872], [-57.9908, -31.34924], [-57.86729, -31.06352], [-57.89476, -30.95994], [-57.8024, -30.77193], [-57.89115, -30.49572], [-57.64859, -30.35095], [-57.61478, -30.25165], [-57.65132, -30.19229], [-57.09386, -29.74211], [-56.81251, -29.48154], [-56.62789, -29.18073], [-56.57295, -29.11357], [-56.54171, -29.11447], [-56.05265, -28.62651], [-56.00458, -28.60421], [-56.01729, -28.51223], [-55.65418, -28.18304], [-55.6262, -28.17124], [-55.33303, -27.94661], [-55.16872, -27.86224], [-55.1349, -27.89759], [-54.90805, -27.73149], [-54.90159, -27.63132], [-54.67657, -27.57214], [-54.50416, -27.48232], [-54.41888, -27.40882], [-54.19268, -27.30751], [-54.19062, -27.27639], [-54.15978, -27.2889], [-53.80144, -27.09844], [-53.73372, -26.6131], [-53.68269, -26.33359], [-53.64505, -26.28089], [-53.64186, -26.25976], [-53.64632, -26.24798], [-53.63881, -26.25075], [-53.63739, -26.2496], [-53.65237, -26.23289], [-53.65018, -26.19501], [-53.73968, -26.10012], [-53.73391, -26.07006], [-53.7264, -26.0664], [-53.73086, -26.05842], [-53.73511, -26.04211], [-53.83691, -25.94849], [-53.90831, -25.55513], [-54.52926, -25.62846], [-54.5502, -25.58915], [-54.59398, -25.59224], [-54.62063, -25.91213], [-54.60664, -25.9691], [-54.67359, -25.98607], [-54.69333, -26.37705], [-54.70732, -26.45099], [-54.80868, -26.55669], [-55.00584, -26.78754], [-55.06351, -26.80195], [-55.16948, -26.96068], [-55.25243, -26.93808], [-55.39611, -26.97679], [-55.62322, -27.1941], [-55.59094, -27.32444], [-55.74475, -27.44485], [-55.89195, -27.3467], [-56.18313, -27.29851], [-56.85337, -27.5165], [-58.04205, -27.2387], [-58.59549, -27.29973], [-58.65321, -27.14028], [-58.3198, -26.83443], [-58.1188, -26.16704], [-57.87176, -25.93604], [-57.57431, -25.47269], [-57.80821, -25.13863], [-58.25492, -24.92528], [-58.33055, -24.97099], [-59.33886, -24.49935], [-59.45482, -24.34787], [-60.03367, -24.00701], [-60.28163, -24.04436], [-60.99754, -23.80934], [-61.0782, -23.62932], [-61.9756, -23.0507], [-62.22768, -22.55807], [-62.51761, -22.37684], [-62.64455, -22.25091], [-62.8078, -22.12534], [-62.81124, -21.9987], [-63.66482, -21.99918], [-63.68113, -22.0544], [-63.70963, -21.99934], [-63.93287, -21.99934], [-64.22918, -22.55807], [-64.31489, -22.88824], [-64.35108, -22.73282], [-64.4176, -22.67692], [-64.58888, -22.25035], [-64.67174, -22.18957], [-64.90014, -22.12136], [-64.99524, -22.08255], [-65.47435, -22.08908], [-65.57743, -22.07675], [-65.58694, -22.09794], [-65.61166, -22.09504], [-65.7467, -22.10105], [-65.9261, -21.93335], [-66.04832, -21.9187], [-66.03836, -21.84829], [-66.24077, -21.77837], [-66.29714, -22.08741], [-66.7298, -22.23644], [-67.18382, -22.81525], [-66.99632, -22.99839], [-67.33563, -24.04237], [-68.24825, -24.42596], [-68.56909, -24.69831], [-68.38372, -25.08636], [-68.57622, -25.32505], [-68.38372, -26.15353], [-68.56909, -26.28146], [-68.59048, -26.49861], [-68.27677, -26.90626], [-68.43363, -27.08414], [-68.77586, -27.16029], [-69.22504, -27.95042], [-69.66709, -28.44055], [-69.80969, -29.07185], [-69.99507, -29.28351], [-69.8596, -30.26131], [-70.14479, -30.36595], [-70.55832, -31.51559], [-69.88099, -33.34489], [-69.87386, -34.13344], [-70.49416, -35.24145], [-70.38008, -36.02375], [-70.95047, -36.4321], [-71.24279, -37.20264], [-70.89532, -38.6923], [-71.37826, -38.91474], [-71.92726, -40.72714], [-71.74901, -42.11711], [-72.15541, -42.15941], [-72.14828, -42.85321], [-71.64206, -43.64774], [-71.81318, -44.38097], [-71.16436, -44.46244], [-71.26418, -44.75684], [-72.06985, -44.81756], [-71.35687, -45.22075], [-71.75614, -45.61611], [-71.68577, -46.55385], [-71.94152, -47.13595], [-72.50478, -47.80586], [-72.27662, -48.28727], [-72.54042, -48.52392], [-72.56894, -48.81116], [-73.09655, -49.14342], [-73.45156, -49.79461], [-73.55259, -49.92488], [-73.15765, -50.78337], [-72.31343, -50.58411]]]]
23784 wikidata: "Q16641",
23785 nameEn: "American Samoa",
23786 aliases: ["US-AS"],
23788 groups: ["Q1352230", "061", "009", "UN"],
23789 roadSpeedUnit: "mph",
23790 roadHeightUnit: "ft",
23791 callingCodes: ["1 684"]
23794 type: "MultiPolygon",
23795 coordinates: [[[[-171.39864, -10.21587], [-170.99605, -15.1275], [-166.32598, -15.26169], [-171.39864, -10.21587]]]]
23805 groups: ["EU", "155", "150", "UN"],
23806 callingCodes: ["43"]
23809 type: "MultiPolygon",
23810 coordinates: [[[[15.34823, 48.98444], [15.28305, 48.98831], [15.26177, 48.95766], [15.16358, 48.94278], [15.15534, 48.99056], [14.99878, 49.01444], [14.97612, 48.96983], [14.98917, 48.90082], [14.95072, 48.79101], [14.98032, 48.77959], [14.9782, 48.7766], [14.98112, 48.77524], [14.9758, 48.76857], [14.95641, 48.75915], [14.94773, 48.76268], [14.81545, 48.7874], [14.80821, 48.77711], [14.80584, 48.73489], [14.72756, 48.69502], [14.71794, 48.59794], [14.66762, 48.58215], [14.60808, 48.62881], [14.56139, 48.60429], [14.4587, 48.64695], [14.43076, 48.58855], [14.33909, 48.55852], [14.20691, 48.5898], [14.09104, 48.5943], [14.01482, 48.63788], [14.06151, 48.66873], [13.84023, 48.76988], [13.82266, 48.75544], [13.81863, 48.73257], [13.79337, 48.71375], [13.81791, 48.69832], [13.81283, 48.68426], [13.81901, 48.6761], [13.82609, 48.62345], [13.80038, 48.59487], [13.80519, 48.58026], [13.76921, 48.55324], [13.7513, 48.5624], [13.74816, 48.53058], [13.72802, 48.51208], [13.66113, 48.53558], [13.65186, 48.55092], [13.62508, 48.55501], [13.59705, 48.57013], [13.57535, 48.55912], [13.51291, 48.59023], [13.50131, 48.58091], [13.50663, 48.57506], [13.46967, 48.55157], [13.45214, 48.56472], [13.43695, 48.55776], [13.45727, 48.51092], [13.42527, 48.45711], [13.43929, 48.43386], [13.40709, 48.37292], [13.30897, 48.31575], [13.26039, 48.29422], [13.18093, 48.29577], [13.126, 48.27867], [13.0851, 48.27711], [13.02083, 48.25689], [12.95306, 48.20629], [12.87126, 48.20318], [12.84475, 48.16556], [12.836, 48.1647], [12.8362, 48.15876], [12.82673, 48.15245], [12.80676, 48.14979], [12.78595, 48.12445], [12.7617, 48.12796], [12.74973, 48.10885], [12.76141, 48.07373], [12.8549, 48.01122], [12.87476, 47.96195], [12.91683, 47.95647], [12.9211, 47.95135], [12.91985, 47.94069], [12.92668, 47.93879], [12.93419, 47.94063], [12.93642, 47.94436], [12.93886, 47.94046], [12.94163, 47.92927], [13.00588, 47.84374], [12.98543, 47.82896], [12.96311, 47.79957], [12.93202, 47.77302], [12.94371, 47.76281], [12.9353, 47.74788], [12.91711, 47.74026], [12.90274, 47.72513], [12.91333, 47.7178], [12.92969, 47.71094], [12.98578, 47.7078], [13.01382, 47.72116], [13.07692, 47.68814], [13.09562, 47.63304], [13.06407, 47.60075], [13.06641, 47.58577], [13.04537, 47.58183], [13.05355, 47.56291], [13.03252, 47.53373], [13.04537, 47.49426], [12.9998, 47.46267], [12.98344, 47.48716], [12.9624, 47.47452], [12.85256, 47.52741], [12.84672, 47.54556], [12.80699, 47.54477], [12.77427, 47.58025], [12.82101, 47.61493], [12.76492, 47.64485], [12.77777, 47.66689], [12.7357, 47.6787], [12.6071, 47.6741], [12.57438, 47.63238], [12.53816, 47.63553], [12.50076, 47.62293], [12.44117, 47.6741], [12.43883, 47.6977], [12.37222, 47.68433], [12.336, 47.69534], [12.27991, 47.68827], [12.26004, 47.67725], [12.24017, 47.69534], [12.26238, 47.73544], [12.2542, 47.7433], [12.22571, 47.71776], [12.18303, 47.70065], [12.16217, 47.70105], [12.16769, 47.68167], [12.18347, 47.66663], [12.18507, 47.65984], [12.19895, 47.64085], [12.20801, 47.61082], [12.20398, 47.60667], [12.18568, 47.6049], [12.17737, 47.60121], [12.18145, 47.61019], [12.17824, 47.61506], [12.13734, 47.60639], [12.05788, 47.61742], [12.02282, 47.61033], [12.0088, 47.62451], [11.85572, 47.60166], [11.84052, 47.58354], [11.63934, 47.59202], [11.60681, 47.57881], [11.58811, 47.55515], [11.58578, 47.52281], [11.52618, 47.50939], [11.4362, 47.51413], [11.38128, 47.47465], [11.4175, 47.44621], [11.33804, 47.44937], [11.29597, 47.42566], [11.27844, 47.39956], [11.22002, 47.3964], [11.25157, 47.43277], [11.20482, 47.43198], [11.12536, 47.41222], [11.11835, 47.39719], [10.97111, 47.39561], [10.97111, 47.41617], [10.98513, 47.42882], [10.92437, 47.46991], [10.93839, 47.48018], [10.90918, 47.48571], [10.87061, 47.4786], [10.86945, 47.5015], [10.91268, 47.51334], [10.88814, 47.53701], [10.77596, 47.51729], [10.7596, 47.53228], [10.6965, 47.54253], [10.68832, 47.55752], [10.63456, 47.5591], [10.60337, 47.56755], [10.56912, 47.53584], [10.48849, 47.54057], [10.47329, 47.58552], [10.43473, 47.58394], [10.44992, 47.5524], [10.4324, 47.50111], [10.44291, 47.48453], [10.46278, 47.47901], [10.47446, 47.43318], [10.4359, 47.41183], [10.4324, 47.38494], [10.39851, 47.37623], [10.33424, 47.30813], [10.23257, 47.27088], [10.17531, 47.27167], [10.17648, 47.29149], [10.2147, 47.31014], [10.19998, 47.32832], [10.23757, 47.37609], [10.22774, 47.38904], [10.2127, 47.38019], [10.17648, 47.38889], [10.16362, 47.36674], [10.11805, 47.37228], [10.09819, 47.35724], [10.06897, 47.40709], [10.1052, 47.4316], [10.09001, 47.46005], [10.07131, 47.45531], [10.03859, 47.48927], [10.00003, 47.48216], [9.96029, 47.53899], [9.92407, 47.53111], [9.87733, 47.54688], [9.87499, 47.52953], [9.8189, 47.54688], [9.82591, 47.58158], [9.80254, 47.59419], [9.76748, 47.5934], [9.72736, 47.53457], [9.55125, 47.53629], [9.56312, 47.49495], [9.58208, 47.48344], [9.59482, 47.46305], [9.60205, 47.46165], [9.60484, 47.46358], [9.60841, 47.47178], [9.62158, 47.45858], [9.62475, 47.45685], [9.6423, 47.45599], [9.65728, 47.45383], [9.65863, 47.44847], [9.64483, 47.43842], [9.6446, 47.43233], [9.65043, 47.41937], [9.65136, 47.40504], [9.6629, 47.39591], [9.67334, 47.39191], [9.67445, 47.38429], [9.6711, 47.37824], [9.66243, 47.37136], [9.65427, 47.36824], [9.62476, 47.36639], [9.59978, 47.34671], [9.58513, 47.31334], [9.55857, 47.29919], [9.54773, 47.2809], [9.53116, 47.27029], [9.56766, 47.24281], [9.55176, 47.22585], [9.56981, 47.21926], [9.58264, 47.20673], [9.56539, 47.17124], [9.62623, 47.14685], [9.63395, 47.08443], [9.61216, 47.07732], [9.60717, 47.06091], [9.87935, 47.01337], [9.88266, 46.93343], [9.98058, 46.91434], [10.10715, 46.84296], [10.22675, 46.86942], [10.24128, 46.93147], [10.30031, 46.92093], [10.36933, 47.00212], [10.48376, 46.93891], [10.47197, 46.85698], [10.54783, 46.84505], [10.66405, 46.87614], [10.75753, 46.82258], [10.72974, 46.78972], [11.00764, 46.76896], [11.10618, 46.92966], [11.33355, 46.99862], [11.50739, 47.00644], [11.74789, 46.98484], [12.19254, 47.09331], [12.21781, 47.03996], [12.11675, 47.01241], [12.2006, 46.88854], [12.27591, 46.88651], [12.38708, 46.71529], [12.59992, 46.6595], [12.94445, 46.60401], [13.27627, 46.56059], [13.64088, 46.53438], [13.7148, 46.5222], [13.89837, 46.52331], [14.00422, 46.48474], [14.04002, 46.49117], [14.12097, 46.47724], [14.15989, 46.43327], [14.28326, 46.44315], [14.314, 46.43327], [14.42608, 46.44614], [14.45877, 46.41717], [14.52176, 46.42617], [14.56463, 46.37208], [14.5942, 46.43434], [14.66892, 46.44936], [14.72185, 46.49974], [14.81836, 46.51046], [14.83549, 46.56614], [14.86419, 46.59411], [14.87129, 46.61], [14.92283, 46.60848], [14.96002, 46.63459], [14.98024, 46.6009], [15.01451, 46.641], [15.14215, 46.66131], [15.23711, 46.63994], [15.41235, 46.65556], [15.45514, 46.63697], [15.46906, 46.61321], [15.54431, 46.6312], [15.55333, 46.64988], [15.54533, 46.66985], [15.59826, 46.68908], [15.62317, 46.67947], [15.63255, 46.68069], [15.6365, 46.6894], [15.6543, 46.69228], [15.6543, 46.70616], [15.67411, 46.70735], [15.69523, 46.69823], [15.72279, 46.69548], [15.73823, 46.70011], [15.76771, 46.69863], [15.78518, 46.70712], [15.8162, 46.71897], [15.87691, 46.7211], [15.94864, 46.68769], [15.98512, 46.68463], [15.99988, 46.67947], [16.04036, 46.6549], [16.04347, 46.68694], [16.02808, 46.71094], [15.99769, 46.7266], [15.98432, 46.74991], [15.99126, 46.78199], [15.99054, 46.82772], [16.05786, 46.83927], [16.10983, 46.867], [16.19904, 46.94134], [16.22403, 46.939], [16.27594, 46.9643], [16.28202, 47.00159], [16.51369, 47.00084], [16.43936, 47.03548], [16.52176, 47.05747], [16.46134, 47.09395], [16.52863, 47.13974], [16.44932, 47.14418], [16.46442, 47.16845], [16.4523, 47.18812], [16.42801, 47.18422], [16.41739, 47.20649], [16.43663, 47.21127], [16.44142, 47.25079], [16.47782, 47.25918], [16.45104, 47.41181], [16.49908, 47.39416], [16.52414, 47.41007], [16.57152, 47.40868], [16.6718, 47.46139], [16.64821, 47.50155], [16.71059, 47.52692], [16.64193, 47.63114], [16.58699, 47.61772], [16.4222, 47.66537], [16.55129, 47.72268], [16.53514, 47.73837], [16.54779, 47.75074], [16.61183, 47.76171], [16.65679, 47.74197], [16.72089, 47.73469], [16.7511, 47.67878], [16.82938, 47.68432], [16.86509, 47.72268], [16.87538, 47.68895], [17.08893, 47.70928], [17.05048, 47.79377], [17.07039, 47.81129], [17.00997, 47.86245], [17.08275, 47.87719], [17.11022, 47.92461], [17.09786, 47.97336], [17.16001, 48.00636], [17.07039, 48.0317], [17.09168, 48.09366], [17.05735, 48.14179], [17.02919, 48.13996], [16.97701, 48.17385], [16.89461, 48.31332], [16.90903, 48.32519], [16.84243, 48.35258], [16.83317, 48.38138], [16.83588, 48.3844], [16.8497, 48.38321], [16.85204, 48.44968], [16.94611, 48.53614], [16.93955, 48.60371], [16.90354, 48.71541], [16.79779, 48.70998], [16.71883, 48.73806], [16.68518, 48.7281], [16.67008, 48.77699], [16.46134, 48.80865], [16.40915, 48.74576], [16.37345, 48.729], [16.06034, 48.75436], [15.84404, 48.86921], [15.78087, 48.87644], [15.75341, 48.8516], [15.6921, 48.85973], [15.61622, 48.89541], [15.51357, 48.91549], [15.48027, 48.94481], [15.34823, 48.98444]]]]
23819 nameEn: "Australia"
23828 wikidata: "Q21203",
23830 aliases: ["NL-AW"],
23832 groups: ["Q1451600", "029", "003", "419", "019", "UN"],
23833 callingCodes: ["297"]
23836 type: "MultiPolygon",
23837 coordinates: [[[[-70.00823, 12.98375], [-70.35625, 12.58277], [-69.60231, 12.17], [-70.00823, 12.98375]]]]
23846 nameEn: "\xC5land Islands",
23848 groups: ["EU", "154", "150", "UN"],
23849 callingCodes: ["358 18", "358 457"]
23852 type: "MultiPolygon",
23853 coordinates: [[[[19.08191, 60.19152], [20.5104, 59.15546], [21.35468, 59.67511], [21.02509, 60.12142], [21.08159, 60.20167], [21.15143, 60.54555], [20.96741, 60.71528], [19.23413, 60.61414], [19.08191, 60.19152]]]]
23862 nameEn: "Azerbaijan",
23863 groups: ["145", "142", "UN"],
23864 callingCodes: ["994"]
23867 type: "MultiPolygon",
23868 coordinates: [[[[46.42738, 41.91323], [46.3984, 41.84399], [46.30863, 41.79133], [46.23962, 41.75811], [46.20538, 41.77205], [46.17891, 41.72094], [46.19759, 41.62327], [46.24429, 41.59883], [46.26531, 41.63339], [46.28182, 41.60089], [46.3253, 41.60912], [46.34039, 41.5947], [46.34126, 41.57454], [46.29794, 41.5724], [46.33925, 41.4963], [46.40307, 41.48464], [46.4669, 41.43331], [46.63658, 41.37727], [46.72375, 41.28609], [46.66148, 41.20533], [46.63969, 41.09515], [46.55096, 41.1104], [46.48558, 41.0576], [46.456, 41.09984], [46.37661, 41.10805], [46.27698, 41.19011], [46.13221, 41.19479], [45.95786, 41.17956], [45.80842, 41.2229], [45.69946, 41.29545], [45.75705, 41.35157], [45.71035, 41.36208], [45.68389, 41.3539], [45.45973, 41.45898], [45.4006, 41.42402], [45.31352, 41.47168], [45.26285, 41.46433], [45.1797, 41.42231], [45.09867, 41.34065], [45.0133, 41.29747], [45.05497, 41.2464], [45.02932, 41.2101], [45.05201, 41.19211], [45.11811, 41.19967], [45.1969, 41.168], [45.19942, 41.13299], [45.08028, 41.10917], [45.06784, 41.05379], [45.12923, 41.06059], [45.1313, 41.09369], [45.1634, 41.08082], [45.16493, 41.05068], [45.1994, 41.04518], [45.25897, 41.0027], [45.26162, 41.0228], [45.28859, 41.03757], [45.35677, 40.99784], [45.39725, 41.02603], [45.44083, 41.01663], [45.40814, 40.97904], [45.60584, 40.87436], [45.55914, 40.78366], [45.4206, 40.7424], [45.35366, 40.65979], [45.45484, 40.57707], [45.42994, 40.53804], [45.65098, 40.37696], [45.95609, 40.27846], [45.97944, 40.181], [45.83779, 39.98925], [45.78642, 40.03218], [45.59806, 40.0131], [45.60895, 39.97733], [45.7833, 39.9475], [45.82533, 39.82925], [45.96543, 39.78859], [46.18493, 39.60533], [46.40286, 39.63651], [46.42465, 39.57534], [46.52117, 39.58734], [46.57098, 39.56694], [46.57721, 39.54414], [46.51027, 39.52373], [46.53051, 39.47809], [46.4013, 39.45405], [46.37795, 39.42039], [46.43244, 39.35181], [46.50093, 39.33736], [46.56476, 39.24942], [46.63481, 39.23013], [46.58032, 39.21204], [46.54141, 39.15895], [46.52584, 39.18912], [46.44022, 39.19636], [46.54296, 39.07078], [46.51805, 38.94982], [46.53497, 38.86548], [46.75752, 39.03231], [46.83822, 39.13143], [46.92539, 39.16644], [46.95341, 39.13505], [47.05771, 39.20143], [47.05927, 39.24846], [47.31301, 39.37492], [47.38978, 39.45999], [47.50099, 39.49615], [47.84774, 39.66285], [47.98977, 39.70999], [48.34264, 39.42935], [48.37385, 39.37584], [48.15984, 39.30028], [48.12404, 39.25208], [48.15361, 39.19419], [48.31239, 39.09278], [48.33884, 39.03022], [48.28437, 38.97186], [48.08627, 38.94434], [48.07734, 38.91616], [48.01409, 38.90333], [48.02581, 38.82705], [48.24773, 38.71883], [48.3146, 38.59958], [48.45084, 38.61013], [48.58793, 38.45076], [48.62217, 38.40198], [48.70001, 38.40564], [48.78979, 38.45026], [48.81072, 38.44853], [48.84969, 38.45015], [48.88288, 38.43975], [52.39847, 39.43556], [48.80971, 41.95365], [48.5867, 41.84306], [48.55078, 41.77917], [48.42301, 41.65444], [48.40277, 41.60441], [48.2878, 41.56221], [48.22064, 41.51472], [48.07587, 41.49957], [47.87973, 41.21798], [47.75831, 41.19455], [47.62288, 41.22969], [47.54504, 41.20275], [47.49004, 41.26366], [47.34579, 41.27884], [47.10762, 41.59044], [47.03757, 41.55434], [46.99554, 41.59743], [47.00955, 41.63583], [46.8134, 41.76252], [46.75269, 41.8623], [46.58924, 41.80547], [46.5332, 41.87389], [46.42738, 41.91323]], [[45.50279, 40.58424], [45.47927, 40.65023], [45.51825, 40.67382], [45.56071, 40.64765], [45.50279, 40.58424]]], [[[45.00864, 41.03411], [45.03792, 41.03938], [45.04517, 41.06653], [45.03406, 41.07931], [45.00864, 41.09407], [44.97169, 41.09176], [44.95383, 41.07553], [44.96031, 41.06345], [44.9903, 41.05657], [45.00864, 41.03411]]], [[[45.21324, 40.9817], [45.23095, 40.97828], [45.23487, 41.00226], [45.20625, 41.01484], [45.18382, 41.0066], [45.19312, 40.98998], [45.20518, 40.99348], [45.21219, 40.99001], [45.21324, 40.9817]]], [[[45.46992, 39.49888], [45.29606, 39.57654], [45.30385, 39.61373], [45.23535, 39.61373], [45.21784, 39.58074], [45.17464, 39.58614], [45.18554, 39.67846], [45.06604, 39.79277], [44.92869, 39.72157], [44.88354, 39.74432], [44.75779, 39.7148], [44.80977, 39.65768], [44.81043, 39.62677], [44.88916, 39.59653], [44.96746, 39.42998], [45.05932, 39.36435], [45.08751, 39.35052], [45.16168, 39.21952], [45.30489, 39.18333], [45.40148, 39.09007], [45.40452, 39.07224], [45.44811, 39.04927], [45.44966, 38.99243], [45.6131, 38.964], [45.6155, 38.94304], [45.65172, 38.95199], [45.83883, 38.90768], [45.90266, 38.87739], [45.94624, 38.89072], [46.00228, 38.87376], [46.06766, 38.87861], [46.14785, 38.84206], [46.06973, 39.0744], [46.02303, 39.09978], [45.99774, 39.28931], [45.79225, 39.3695], [45.83, 39.46487], [45.80804, 39.56716], [45.70547, 39.60174], [45.46992, 39.49888]]]]
23877 nameEn: "Bosnia and Herzegovina",
23878 groups: ["039", "150", "UN"],
23879 callingCodes: ["387"]
23882 type: "MultiPolygon",
23883 coordinates: [[[[17.84826, 45.04489], [17.66571, 45.13408], [17.59104, 45.10816], [17.51469, 45.10791], [17.47589, 45.12656], [17.45615, 45.12523], [17.4498, 45.16119], [17.41229, 45.13335], [17.33573, 45.14521], [17.32092, 45.16246], [17.26815, 45.18444], [17.25131, 45.14957], [17.24325, 45.146], [17.18438, 45.14764], [17.0415, 45.20759], [16.9385, 45.22742], [16.92405, 45.27607], [16.83804, 45.18951], [16.81137, 45.18434], [16.78219, 45.19002], [16.74845, 45.20393], [16.64962, 45.20714], [16.60194, 45.23042], [16.56559, 45.22307], [16.5501, 45.2212], [16.52982, 45.22713], [16.49155, 45.21153], [16.4634, 45.14522], [16.40023, 45.1147], [16.38309, 45.05955], [16.38219, 45.05139], [16.3749, 45.05206], [16.35863, 45.03529], [16.35404, 45.00241], [16.29036, 44.99732], [16.12153, 45.09616], [15.98412, 45.23088], [15.83512, 45.22459], [15.76371, 45.16508], [15.78842, 45.11519], [15.74585, 45.0638], [15.78568, 44.97401], [15.74723, 44.96818], [15.76096, 44.87045], [15.79472, 44.8455], [15.72584, 44.82334], [15.8255, 44.71501], [15.89348, 44.74964], [16.05828, 44.61538], [16.00884, 44.58605], [16.03012, 44.55572], [16.10566, 44.52586], [16.16814, 44.40679], [16.12969, 44.38275], [16.21346, 44.35231], [16.18688, 44.27012], [16.36864, 44.08263], [16.43662, 44.07523], [16.43629, 44.02826], [16.50528, 44.0244], [16.55472, 43.95326], [16.70922, 43.84887], [16.75316, 43.77157], [16.80736, 43.76011], [17.00585, 43.58037], [17.15828, 43.49376], [17.24411, 43.49376], [17.29699, 43.44542], [17.25579, 43.40353], [17.286, 43.33065], [17.46986, 43.16559], [17.64268, 43.08595], [17.70879, 42.97223], [17.5392, 42.92787], [17.6444, 42.88641], [17.68151, 42.92725], [17.7948, 42.89556], [17.80854, 42.9182], [17.88201, 42.83668], [18.24318, 42.6112], [18.36197, 42.61423], [18.43735, 42.55921], [18.49778, 42.58409], [18.53751, 42.57376], [18.55504, 42.58409], [18.52232, 42.62279], [18.57373, 42.64429], [18.54841, 42.68328], [18.54603, 42.69171], [18.55221, 42.69045], [18.56789, 42.72074], [18.47324, 42.74992], [18.45921, 42.81682], [18.47633, 42.85829], [18.4935, 42.86433], [18.49661, 42.89306], [18.49076, 42.95553], [18.52232, 43.01451], [18.66254, 43.03928], [18.64735, 43.14766], [18.66605, 43.2056], [18.71747, 43.2286], [18.6976, 43.25243], [18.76538, 43.29838], [18.85342, 43.32426], [18.84794, 43.33735], [18.83912, 43.34795], [18.90911, 43.36383], [18.95819, 43.32899], [18.95001, 43.29327], [19.00844, 43.24988], [19.04233, 43.30008], [19.08206, 43.29668], [19.08673, 43.31453], [19.04071, 43.397], [19.01078, 43.43854], [18.96053, 43.45042], [18.95469, 43.49367], [18.91379, 43.50299], [19.01078, 43.55806], [19.04934, 43.50384], [19.13933, 43.5282], [19.15685, 43.53943], [19.22807, 43.5264], [19.24774, 43.53061], [19.2553, 43.5938], [19.33426, 43.58833], [19.36653, 43.60921], [19.41941, 43.54056], [19.42696, 43.57987], [19.50455, 43.58385], [19.5176, 43.71403], [19.3986, 43.79668], [19.23465, 43.98764], [19.24363, 44.01502], [19.38439, 43.96611], [19.52515, 43.95573], [19.56498, 43.99922], [19.61836, 44.01464], [19.61991, 44.05254], [19.57467, 44.04716], [19.55999, 44.06894], [19.51167, 44.08158], [19.47321, 44.1193], [19.48386, 44.14332], [19.47338, 44.15034], [19.43905, 44.13088], [19.40927, 44.16722], [19.3588, 44.18353], [19.34773, 44.23244], [19.32464, 44.27185], [19.26945, 44.26957], [19.23306, 44.26097], [19.20508, 44.2917], [19.18328, 44.28383], [19.16741, 44.28648], [19.13332, 44.31492], [19.13556, 44.338], [19.11547, 44.34218], [19.1083, 44.3558], [19.11865, 44.36712], [19.10298, 44.36924], [19.10365, 44.37795], [19.10704, 44.38249], [19.10749, 44.39421], [19.11785, 44.40313], [19.14681, 44.41463], [19.14837, 44.45253], [19.12278, 44.50132], [19.13369, 44.52521], [19.16699, 44.52197], [19.26388, 44.65412], [19.32543, 44.74058], [19.36722, 44.88164], [19.18183, 44.92055], [19.01994, 44.85493], [18.8704, 44.85097], [18.76347, 44.90669], [18.76369, 44.93707], [18.80661, 44.93561], [18.78357, 44.97741], [18.65723, 45.07544], [18.47939, 45.05871], [18.41896, 45.11083], [18.32077, 45.1021], [18.24387, 45.13699], [18.1624, 45.07654], [18.03121, 45.12632], [18.01594, 45.15163], [17.99479, 45.14958], [17.97834, 45.13831], [17.97336, 45.12245], [17.93706, 45.08016], [17.87148, 45.04645], [17.84826, 45.04489]]]]
23892 nameEn: "Barbados",
23893 groups: ["029", "003", "419", "019", "UN"],
23895 callingCodes: ["1 246"]
23898 type: "MultiPolygon",
23899 coordinates: [[[[-58.56442, 13.24471], [-59.80731, 13.87556], [-59.82929, 12.70644], [-58.56442, 13.24471]]]]
23908 nameEn: "Bangladesh",
23909 groups: ["034", "142", "UN"],
23911 callingCodes: ["880"]
23914 type: "MultiPolygon",
23915 coordinates: [[[[89.15869, 26.13708], [89.08899, 26.38845], [88.95612, 26.4564], [88.92357, 26.40711], [88.91321, 26.37984], [89.05328, 26.2469], [88.85004, 26.23211], [88.78961, 26.31093], [88.67837, 26.26291], [88.69485, 26.38353], [88.62144, 26.46783], [88.4298, 26.54489], [88.41196, 26.63837], [88.33093, 26.48929], [88.35153, 26.45241], [88.36938, 26.48683], [88.48749, 26.45855], [88.51649, 26.35923], [88.35153, 26.29123], [88.34757, 26.22216], [88.1844, 26.14417], [88.16581, 26.0238], [88.08804, 25.91334], [88.13138, 25.78773], [88.242, 25.80811], [88.45103, 25.66245], [88.4559, 25.59227], [88.677, 25.46959], [88.81296, 25.51546], [88.85278, 25.34679], [89.01105, 25.30303], [89.00463, 25.26583], [88.94067, 25.18534], [88.44766, 25.20149], [88.46277, 25.07468], [88.33917, 24.86803], [88.27325, 24.88796], [88.21832, 24.96642], [88.14004, 24.93529], [88.15515, 24.85806], [88.00683, 24.66477], [88.08786, 24.63232], [88.12296, 24.51301], [88.50934, 24.32474], [88.68801, 24.31464], [88.74841, 24.1959], [88.6976, 24.14703], [88.73743, 23.91751], [88.66189, 23.87607], [88.58087, 23.87105], [88.56507, 23.64044], [88.74841, 23.47361], [88.79351, 23.50535], [88.79254, 23.46028], [88.71133, 23.2492], [88.99148, 23.21134], [88.86377, 23.08759], [88.88327, 23.03885], [88.87063, 22.95235], [88.96713, 22.83346], [88.9151, 22.75228], [88.94614, 22.66941], [88.9367, 22.58527], [89.07114, 22.15335], [89.08044, 21.41871], [92.47409, 20.38654], [92.26071, 21.05697], [92.17752, 21.17445], [92.20087, 21.337], [92.37939, 21.47764], [92.43158, 21.37025], [92.55105, 21.3856], [92.60187, 21.24615], [92.68152, 21.28454], [92.59775, 21.6092], [92.62187, 21.87037], [92.60949, 21.97638], [92.56616, 22.13554], [92.60029, 22.1522], [92.5181, 22.71441], [92.37665, 22.9435], [92.38214, 23.28705], [92.26541, 23.70392], [92.15417, 23.73409], [92.04706, 23.64229], [91.95093, 23.73284], [91.95642, 23.47361], [91.84789, 23.42235], [91.76417, 23.26619], [91.81634, 23.08001], [91.7324, 23.00043], [91.61571, 22.93929], [91.54993, 23.01051], [91.46615, 23.2328], [91.4035, 23.27522], [91.40848, 23.07117], [91.36453, 23.06612], [91.28293, 23.37538], [91.15579, 23.6599], [91.25192, 23.83463], [91.22308, 23.89616], [91.29587, 24.0041], [91.35741, 23.99072], [91.37414, 24.10693], [91.55542, 24.08687], [91.63782, 24.1132], [91.65292, 24.22095], [91.73257, 24.14703], [91.76004, 24.23848], [91.82596, 24.22345], [91.89258, 24.14674], [91.96603, 24.3799], [92.11662, 24.38997], [92.15796, 24.54435], [92.25854, 24.9191], [92.38626, 24.86055], [92.49887, 24.88796], [92.39147, 25.01471], [92.33957, 25.07593], [92.0316, 25.1834], [91.63648, 25.12846], [91.25517, 25.20677], [90.87427, 25.15799], [90.65042, 25.17788], [90.40034, 25.1534], [90.1155, 25.22686], [89.90478, 25.31038], [89.87629, 25.28337], [89.83371, 25.29548], [89.84086, 25.31854], [89.81208, 25.37244], [89.86129, 25.61714], [89.84388, 25.70042], [89.80585, 25.82489], [89.86592, 25.93115], [89.77728, 26.04254], [89.77865, 26.08387], [89.73581, 26.15818], [89.70201, 26.15138], [89.63968, 26.22595], [89.57101, 25.9682], [89.53515, 26.00382], [89.35953, 26.0077], [89.15869, 26.13708]]]]
23925 groups: ["EU", "155", "150", "UN"],
23926 callingCodes: ["32"]
23929 type: "MultiPolygon",
23930 coordinates: [[[[4.93295, 51.44945], [4.93909, 51.44632], [4.9524, 51.45014], [4.95244, 51.45207], [4.93295, 51.44945]]], [[[4.91493, 51.4353], [4.92652, 51.43329], [4.92952, 51.42984], [4.93986, 51.43064], [4.94265, 51.44003], [4.93471, 51.43861], [4.93416, 51.44185], [4.94025, 51.44193], [4.93544, 51.44634], [4.92879, 51.44161], [4.92815, 51.43856], [4.92566, 51.44273], [4.92811, 51.4437], [4.92287, 51.44741], [4.91811, 51.44621], [4.92227, 51.44252], [4.91935, 51.43634], [4.91493, 51.4353]]], [[[4.82946, 51.4213], [4.82409, 51.44736], [4.84139, 51.4799], [4.78803, 51.50284], [4.77321, 51.50529], [4.74578, 51.48937], [4.72935, 51.48424], [4.65442, 51.42352], [4.57489, 51.4324], [4.53521, 51.4243], [4.52846, 51.45002], [4.54675, 51.47265], [4.5388, 51.48184], [4.47736, 51.4778], [4.38122, 51.44905], [4.39747, 51.43316], [4.38064, 51.41965], [4.43777, 51.36989], [4.39292, 51.35547], [4.34086, 51.35738], [4.33265, 51.37687], [4.21923, 51.37443], [4.24024, 51.35371], [4.16721, 51.29348], [4.05165, 51.24171], [4.01957, 51.24504], [3.97889, 51.22537], [3.90125, 51.20371], [3.78783, 51.2151], [3.78999, 51.25766], [3.58939, 51.30064], [3.51502, 51.28697], [3.52698, 51.2458], [3.43488, 51.24135], [3.41704, 51.25933], [3.38289, 51.27331], [3.35847, 51.31572], [3.38696, 51.33436], [3.36263, 51.37112], [2.56575, 51.85301], [2.18458, 51.52087], [2.55904, 51.07014], [2.57551, 51.00326], [2.63074, 50.94746], [2.59093, 50.91751], [2.63331, 50.81457], [2.71165, 50.81295], [2.81056, 50.71773], [2.8483, 50.72276], [2.86985, 50.7033], [2.87937, 50.70298], [2.88504, 50.70656], [2.90069, 50.69263], [2.91036, 50.6939], [2.90873, 50.702], [2.95019, 50.75138], [2.96778, 50.75242], [3.00537, 50.76588], [3.04314, 50.77674], [3.09163, 50.77717], [3.10614, 50.78303], [3.11206, 50.79416], [3.11987, 50.79188], [3.1257, 50.78603], [3.15017, 50.79031], [3.16476, 50.76843], [3.18339, 50.74981], [3.18811, 50.74025], [3.20064, 50.73547], [3.19017, 50.72569], [3.20845, 50.71662], [3.22042, 50.71019], [3.24593, 50.71389], [3.26063, 50.70086], [3.26141, 50.69151], [3.2536, 50.68977], [3.264, 50.67668], [3.23951, 50.6585], [3.2729, 50.60718], [3.28575, 50.52724], [3.37693, 50.49538], [3.44629, 50.51009], [3.47385, 50.53397], [3.51564, 50.5256], [3.49509, 50.48885], [3.5683, 50.50192], [3.58361, 50.49049], [3.61014, 50.49568], [3.64426, 50.46275], [3.66153, 50.45165], [3.67494, 50.40239], [3.67262, 50.38663], [3.65709, 50.36873], [3.66976, 50.34563], [3.71009, 50.30305], [3.70987, 50.3191], [3.73911, 50.34809], [3.84314, 50.35219], [3.90781, 50.32814], [3.96771, 50.34989], [4.0268, 50.35793], [4.0689, 50.3254], [4.10237, 50.31247], [4.10957, 50.30234], [4.11954, 50.30425], [4.13665, 50.25609], [4.16808, 50.25786], [4.15524, 50.2833], [4.17347, 50.28838], [4.17861, 50.27443], [4.20651, 50.27333], [4.21945, 50.25539], [4.15524, 50.21103], [4.16014, 50.19239], [4.13561, 50.13078], [4.20147, 50.13535], [4.23101, 50.06945], [4.16294, 50.04719], [4.13508, 50.01976], [4.14239, 49.98034], [4.20532, 49.95803], [4.31963, 49.97043], [4.35051, 49.95315], [4.43488, 49.94122], [4.51098, 49.94659], [4.5414, 49.96911], [4.68695, 49.99685], [4.70064, 50.09384], [4.75237, 50.11314], [4.82438, 50.16878], [4.83279, 50.15331], [4.88602, 50.15182], [4.8382, 50.06738], [4.78827, 49.95609], [4.88529, 49.9236], [4.85134, 49.86457], [4.86965, 49.82271], [4.85464, 49.78995], [4.96714, 49.79872], [5.09249, 49.76193], [5.14545, 49.70287], [5.26232, 49.69456], [5.31465, 49.66846], [5.33039, 49.6555], [5.30214, 49.63055], [5.3137, 49.61225], [5.33851, 49.61599], [5.34837, 49.62889], [5.3974, 49.61596], [5.43713, 49.5707], [5.46734, 49.52648], [5.46541, 49.49825], [5.55001, 49.52729], [5.60909, 49.51228], [5.64505, 49.55146], [5.75649, 49.54321], [5.7577, 49.55915], [5.77435, 49.56298], [5.79195, 49.55228], [5.81838, 49.54777], [5.84143, 49.5533], [5.84692, 49.55663], [5.8424, 49.56082], [5.87256, 49.57539], [5.86986, 49.58756], [5.84971, 49.58674], [5.84826, 49.5969], [5.8762, 49.60898], [5.87609, 49.62047], [5.88393, 49.62802], [5.88552, 49.63507], [5.90599, 49.63853], [5.90164, 49.6511], [5.9069, 49.66377], [5.86175, 49.67862], [5.86527, 49.69291], [5.88677, 49.70951], [5.86503, 49.72739], [5.84193, 49.72161], [5.82562, 49.72395], [5.83149, 49.74729], [5.82245, 49.75048], [5.78871, 49.7962], [5.75409, 49.79239], [5.74953, 49.81428], [5.74364, 49.82058], [5.74844, 49.82435], [5.7404, 49.83452], [5.74076, 49.83823], [5.74975, 49.83933], [5.74953, 49.84709], [5.75884, 49.84811], [5.74567, 49.85368], [5.75861, 49.85631], [5.75269, 49.8711], [5.78415, 49.87922], [5.73621, 49.89796], [5.77314, 49.93646], [5.77291, 49.96056], [5.80833, 49.96451], [5.81163, 49.97142], [5.83467, 49.97823], [5.83968, 49.9892], [5.82331, 49.99662], [5.81866, 50.01286], [5.8551, 50.02683], [5.86904, 50.04614], [5.85474, 50.06342], [5.8857, 50.07824], [5.89488, 50.11476], [5.95929, 50.13295], [5.96453, 50.17259], [6.02488, 50.18283], [6.03093, 50.16362], [6.06406, 50.15344], [6.08577, 50.17246], [6.12028, 50.16374], [6.1137, 50.13668], [6.1379, 50.12964], [6.15298, 50.14126], [6.14132, 50.14971], [6.14588, 50.17106], [6.18739, 50.1822], [6.18364, 50.20815], [6.16853, 50.2234], [6.208, 50.25179], [6.28797, 50.27458], [6.29949, 50.30887], [6.32488, 50.32333], [6.35701, 50.31139], [6.40641, 50.32425], [6.40785, 50.33557], [6.3688, 50.35898], [6.34406, 50.37994], [6.36852, 50.40776], [6.37219, 50.45397], [6.34005, 50.46083], [6.3465, 50.48833], [6.30809, 50.50058], [6.26637, 50.50272], [6.22335, 50.49578], [6.20599, 50.52089], [6.19193, 50.5212], [6.18716, 50.52653], [6.19579, 50.5313], [6.19735, 50.53576], [6.17802, 50.54179], [6.17739, 50.55875], [6.20281, 50.56952], [6.22581, 50.5907], [6.24005, 50.58732], [6.24888, 50.59869], [6.2476, 50.60392], [6.26957, 50.62444], [6.17852, 50.6245], [6.11707, 50.72231], [6.04428, 50.72861], [6.0406, 50.71848], [6.0326, 50.72647], [6.03889, 50.74618], [6.01976, 50.75398], [5.97545, 50.75441], [5.95942, 50.7622], [5.89132, 50.75124], [5.89129, 50.75125], [5.88734, 50.77092], [5.84888, 50.75448], [5.84548, 50.76542], [5.80673, 50.7558], [5.77513, 50.78308], [5.76533, 50.78159], [5.74356, 50.7691], [5.73904, 50.75674], [5.72216, 50.76398], [5.69469, 50.75529], [5.68091, 50.75804], [5.70107, 50.7827], [5.68995, 50.79641], [5.70118, 50.80764], [5.65259, 50.82309], [5.64009, 50.84742], [5.64504, 50.87107], [5.67886, 50.88142], [5.69858, 50.91046], [5.71626, 50.90796], [5.72644, 50.91167], [5.72545, 50.92312], [5.74644, 50.94723], [5.75927, 50.95601], [5.74752, 50.96202], [5.72875, 50.95428], [5.71864, 50.96092], [5.76242, 50.99703], [5.77688, 51.02483], [5.75961, 51.03113], [5.77258, 51.06196], [5.79835, 51.05834], [5.79903, 51.09371], [5.82921, 51.09328], [5.83226, 51.10585], [5.8109, 51.10861], [5.80798, 51.11661], [5.85508, 51.14445], [5.82564, 51.16753], [5.77697, 51.1522], [5.77735, 51.17845], [5.74617, 51.18928], [5.70344, 51.1829], [5.65528, 51.18736], [5.65145, 51.19788], [5.5603, 51.22249], [5.5569, 51.26544], [5.515, 51.29462], [5.48476, 51.30053], [5.46519, 51.2849], [5.4407, 51.28169], [5.41672, 51.26248], [5.347, 51.27502], [5.33886, 51.26314], [5.29716, 51.26104], [5.26461, 51.26693], [5.23814, 51.26064], [5.22542, 51.26888], [5.24244, 51.30495], [5.2002, 51.32243], [5.16222, 51.31035], [5.13377, 51.31592], [5.13105, 51.34791], [5.07102, 51.39469], [5.10456, 51.43163], [5.07891, 51.4715], [5.04774, 51.47022], [5.03281, 51.48679], [5.0106, 51.47167], [5.00393, 51.44406], [4.92152, 51.39487], [4.90016, 51.41404], [4.84988, 51.41502], [4.78941, 51.41102], [4.77229, 51.41337], [4.76577, 51.43046], [4.78314, 51.43319], [4.82946, 51.4213]]]]
23939 nameEn: "Burkina Faso",
23940 groups: ["011", "202", "002", "UN"],
23941 callingCodes: ["226"]
23944 type: "MultiPolygon",
23945 coordinates: [[[[0.23859, 15.00135], [0.06588, 14.96961], [-0.24673, 15.07805], [-0.72004, 15.08655], [-1.05875, 14.7921], [-1.32166, 14.72774], [-1.68083, 14.50023], [-1.97945, 14.47709], [-1.9992, 14.19011], [-2.10223, 14.14878], [-2.47587, 14.29671], [-2.66175, 14.14713], [-2.84667, 14.05532], [-2.90831, 13.81174], [-2.88189, 13.64921], [-3.26407, 13.70699], [-3.28396, 13.5422], [-3.23599, 13.29035], [-3.43507, 13.27272], [-3.4313, 13.1588], [-3.54454, 13.1781], [-3.7911, 13.36665], [-3.96282, 13.38164], [-3.90558, 13.44375], [-3.96501, 13.49778], [-4.34477, 13.12927], [-4.21819, 12.95722], [-4.238, 12.71467], [-4.47356, 12.71252], [-4.41412, 12.31922], [-4.57703, 12.19875], [-4.54841, 12.1385], [-4.62546, 12.13204], [-4.62987, 12.06531], [-4.70692, 12.06746], [-4.72893, 12.01579], [-5.07897, 11.97918], [-5.26389, 11.84778], [-5.40258, 11.8327], [-5.26389, 11.75728], [-5.29251, 11.61715], [-5.22867, 11.60421], [-5.20665, 11.43811], [-5.25509, 11.36905], [-5.25949, 11.24816], [-5.32553, 11.21578], [-5.32994, 11.13371], [-5.49284, 11.07538], [-5.41579, 10.84628], [-5.47083, 10.75329], [-5.46643, 10.56074], [-5.51058, 10.43177], [-5.39602, 10.2929], [-5.12465, 10.29788], [-4.96453, 9.99923], [-4.96621, 9.89132], [-4.6426, 9.70696], [-4.31392, 9.60062], [-4.25999, 9.76012], [-3.69703, 9.94279], [-3.31779, 9.91125], [-3.27228, 9.84981], [-3.19306, 9.93781], [-3.16609, 9.85147], [-3.00765, 9.74019], [-2.93012, 9.57403], [-2.76494, 9.40778], [-2.68802, 9.49343], [-2.76534, 9.56589], [-2.74174, 9.83172], [-2.83108, 10.40252], [-2.94232, 10.64281], [-2.83373, 11.0067], [-0.67143, 10.99811], [-0.61937, 10.91305], [-0.44298, 11.04292], [-0.42391, 11.11661], [-0.38219, 11.12596], [-0.35955, 11.07801], [-0.28566, 11.12713], [-0.27374, 11.17157], [-0.13493, 11.14075], [0.50388, 11.01011], [0.48852, 10.98561], [0.50521, 10.98035], [0.4958, 10.93269], [0.66104, 10.99964], [0.91245, 10.99597], [0.9813, 11.08876], [1.03409, 11.04719], [1.42823, 11.46822], [2.00988, 11.42227], [2.29983, 11.68254], [2.39723, 11.89473], [2.05785, 12.35539], [2.26349, 12.41915], [0.99167, 13.10727], [0.99253, 13.37515], [1.18873, 13.31771], [1.21217, 13.37853], [1.24516, 13.33968], [1.28509, 13.35488], [1.24429, 13.39373], [1.20088, 13.38951], [1.02813, 13.46635], [0.99514, 13.5668], [0.77637, 13.64442], [0.77377, 13.6866], [0.61924, 13.68491], [0.38051, 14.05575], [0.16936, 14.51654], [0.23859, 15.00135]]]]
23954 nameEn: "Bulgaria",
23955 groups: ["EU", "151", "150", "UN"],
23956 callingCodes: ["359"]
23959 type: "MultiPolygon",
23960 coordinates: [[[[23.05288, 43.79494], [22.85314, 43.84452], [22.83753, 43.88055], [22.87873, 43.9844], [23.01674, 44.01946], [23.04988, 44.07694], [22.67173, 44.21564], [22.61711, 44.16938], [22.61688, 44.06534], [22.41449, 44.00514], [22.35558, 43.81281], [22.41043, 43.69566], [22.47582, 43.6558], [22.53397, 43.47225], [22.82036, 43.33665], [22.89727, 43.22417], [23.00806, 43.19279], [22.98104, 43.11199], [22.89521, 43.03625], [22.78397, 42.98253], [22.74826, 42.88701], [22.54302, 42.87774], [22.43309, 42.82057], [22.4997, 42.74144], [22.43983, 42.56851], [22.55669, 42.50144], [22.51961, 42.3991], [22.47498, 42.3915], [22.45919, 42.33822], [22.34773, 42.31725], [22.38136, 42.30339], [22.47251, 42.20393], [22.50289, 42.19527], [22.51224, 42.15457], [22.67701, 42.06614], [22.86749, 42.02275], [22.90254, 41.87587], [22.96682, 41.77137], [23.01239, 41.76527], [23.03342, 41.71034], [22.95513, 41.63265], [22.96331, 41.35782], [22.93334, 41.34104], [23.1833, 41.31755], [23.21953, 41.33773], [23.22771, 41.37106], [23.31301, 41.40525], [23.33639, 41.36317], [23.40416, 41.39999], [23.52453, 41.40262], [23.63203, 41.37632], [23.67644, 41.41139], [23.76525, 41.40175], [23.80148, 41.43943], [23.89613, 41.45257], [23.91483, 41.47971], [23.96975, 41.44118], [24.06908, 41.46132], [24.06323, 41.53222], [24.10063, 41.54796], [24.18126, 41.51735], [24.27124, 41.57682], [24.30513, 41.51297], [24.52599, 41.56808], [24.61129, 41.42278], [24.71529, 41.41928], [24.8041, 41.34913], [24.82514, 41.4035], [24.86136, 41.39298], [24.90928, 41.40876], [24.942, 41.38685], [25.11611, 41.34212], [25.28322, 41.23411], [25.48187, 41.28506], [25.52394, 41.2798], [25.55082, 41.31667], [25.61042, 41.30614], [25.66183, 41.31316], [25.70507, 41.29209], [25.8266, 41.34563], [25.87919, 41.30526], [26.12926, 41.35878], [26.16548, 41.42278], [26.20288, 41.43943], [26.14796, 41.47533], [26.176, 41.50072], [26.17951, 41.55409], [26.14328, 41.55496], [26.15146, 41.60828], [26.07083, 41.64584], [26.06148, 41.70345], [26.16841, 41.74858], [26.21325, 41.73223], [26.22888, 41.74139], [26.2654, 41.71544], [26.30255, 41.70925], [26.35957, 41.71149], [26.32952, 41.73637], [26.33589, 41.76802], [26.36952, 41.82265], [26.53968, 41.82653], [26.57961, 41.90024], [26.56051, 41.92995], [26.62996, 41.97644], [26.79143, 41.97386], [26.95638, 42.00741], [27.03277, 42.0809], [27.08486, 42.08735], [27.19251, 42.06028], [27.22376, 42.10152], [27.27411, 42.10409], [27.45478, 41.96591], [27.52379, 41.93756], [27.55191, 41.90928], [27.69949, 41.97515], [27.81235, 41.94803], [27.83492, 41.99709], [27.91479, 41.97902], [28.02971, 41.98066], [28.32297, 41.98371], [29.24336, 43.70874], [28.23293, 43.76], [27.99558, 43.84193], [27.92008, 44.00761], [27.73468, 43.95326], [27.64542, 44.04958], [27.60834, 44.01206], [27.39757, 44.0141], [27.26845, 44.12602], [26.95141, 44.13555], [26.62712, 44.05698], [26.38764, 44.04356], [26.10115, 43.96908], [26.05584, 43.90925], [25.94911, 43.85745], [25.72792, 43.69263], [25.39528, 43.61866], [25.17144, 43.70261], [25.10718, 43.6831], [24.96682, 43.72693], [24.73542, 43.68523], [24.62281, 43.74082], [24.50264, 43.76314], [24.35364, 43.70211], [24.18149, 43.68218], [23.73978, 43.80627], [23.61687, 43.79289], [23.4507, 43.84936], [23.26772, 43.84843], [23.05288, 43.79494]]]]
23970 groups: ["145", "142", "UN"],
23971 callingCodes: ["973"]
23974 type: "MultiPolygon",
23975 coordinates: [[[[50.93865, 26.30758], [50.71771, 26.73086], [50.38162, 26.53976], [50.26923, 26.08243], [50.302, 25.87592], [50.57069, 25.57887], [50.80824, 25.54641], [50.7801, 25.595], [50.86149, 25.6965], [50.81266, 25.88946], [50.93865, 26.30758]]]]
23985 groups: ["014", "202", "002", "UN"],
23986 callingCodes: ["257"]
23989 type: "MultiPolygon",
23990 coordinates: [[[[30.54501, -2.41404], [30.42933, -2.31064], [30.14034, -2.43626], [29.95911, -2.33348], [29.88237, -2.75105], [29.36805, -2.82933], [29.32234, -2.6483], [29.0562, -2.58632], [29.04081, -2.7416], [29.00167, -2.78523], [29.00404, -2.81978], [29.0505, -2.81774], [29.09119, -2.87871], [29.09797, -2.91935], [29.16037, -2.95457], [29.17258, -2.99385], [29.25633, -3.05471], [29.21463, -3.3514], [29.23708, -3.75856], [29.43673, -4.44845], [29.63827, -4.44681], [29.75109, -4.45836], [29.77289, -4.41733], [29.82885, -4.36153], [29.88172, -4.35743], [30.03323, -4.26631], [30.22042, -4.01738], [30.45915, -3.56532], [30.84165, -3.25152], [30.83823, -2.97837], [30.6675, -2.98987], [30.57926, -2.89791], [30.4987, -2.9573], [30.40662, -2.86151], [30.52747, -2.65841], [30.41789, -2.66266], [30.54501, -2.41404]]]]
24001 groups: ["011", "202", "002", "UN"],
24002 callingCodes: ["229"]
24005 type: "MultiPolygon",
24006 coordinates: [[[[3.59375, 11.70269], [3.48187, 11.86092], [3.31613, 11.88495], [3.25352, 12.01467], [2.83978, 12.40585], [2.6593, 12.30631], [2.37783, 12.24804], [2.39657, 12.10952], [2.45824, 11.98672], [2.39723, 11.89473], [2.29983, 11.68254], [2.00988, 11.42227], [1.42823, 11.46822], [1.03409, 11.04719], [0.9813, 11.08876], [0.91245, 10.99597], [0.8804, 10.803], [0.80358, 10.71459], [0.77666, 10.37665], [1.35507, 9.99525], [1.36624, 9.5951], [1.33675, 9.54765], [1.41746, 9.3226], [1.5649, 9.16941], [1.61838, 9.0527], [1.64249, 6.99562], [1.55877, 6.99737], [1.61812, 6.74843], [1.58105, 6.68619], [1.76906, 6.43189], [1.79826, 6.28221], [1.62913, 6.24075], [1.67336, 6.02702], [2.74181, 6.13349], [2.70566, 6.38038], [2.70464, 6.50831], [2.74334, 6.57291], [2.7325, 6.64057], [2.78204, 6.70514], [2.78823, 6.76356], [2.73405, 6.78508], [2.74024, 6.92802], [2.71702, 6.95722], [2.76965, 7.13543], [2.74489, 7.42565], [2.79442, 7.43486], [2.78668, 7.5116], [2.73405, 7.5423], [2.73095, 7.7755], [2.67523, 7.87825], [2.77907, 9.06924], [3.08017, 9.10006], [3.14147, 9.28375], [3.13928, 9.47167], [3.25093, 9.61632], [3.34726, 9.70696], [3.32099, 9.78032], [3.35383, 9.83641], [3.54429, 9.87739], [3.66908, 10.18136], [3.57275, 10.27185], [3.6844, 10.46351], [3.78292, 10.40538], [3.84243, 10.59316], [3.71505, 11.13015], [3.49175, 11.29765], [3.59375, 11.70269]]]]
24014 wikidata: "Q25362",
24015 nameEn: "Saint-Barth\xE9lemy",
24017 groups: ["Q1451600", "029", "003", "419", "019", "UN"],
24018 callingCodes: ["590"]
24021 type: "MultiPolygon",
24022 coordinates: [[[[-62.62718, 18.26185], [-63.1055, 17.86651], [-62.34423, 17.49165], [-62.62718, 18.26185]]]]
24030 wikidata: "Q23635",
24033 groups: ["BOTS", "021", "003", "019", "UN"],
24035 callingCodes: ["1 441"]
24038 type: "MultiPolygon",
24039 coordinates: [[[[-63.20987, 32.6953], [-65.31453, 32.68437], [-65.63955, 31.43417], [-63.20987, 32.6953]]]]
24049 groups: ["Q36117", "035", "142", "UN"],
24051 callingCodes: ["673"]
24054 type: "MultiPolygon",
24055 coordinates: [[[[115.16236, 5.01011], [115.02521, 5.35005], [114.10166, 4.76112], [114.07448, 4.58441], [114.15813, 4.57], [114.26876, 4.49878], [114.32176, 4.34942], [114.32176, 4.2552], [114.4416, 4.27588], [114.49922, 4.13108], [114.64211, 4.00694], [114.78539, 4.12205], [114.88039, 4.4257], [114.83189, 4.42387], [114.77303, 4.72871], [114.8266, 4.75062], [114.88841, 4.81905], [114.96982, 4.81146], [114.99417, 4.88201], [115.05038, 4.90275], [115.02955, 4.82087], [115.02278, 4.74137], [115.04064, 4.63706], [115.07737, 4.53418], [115.09978, 4.39123], [115.31275, 4.30806], [115.36346, 4.33563], [115.2851, 4.42295], [115.27819, 4.63661], [115.20737, 4.8256], [115.15092, 4.87604], [115.16236, 5.01011]]]]
24065 groups: ["005", "419", "019", "UN"],
24066 callingCodes: ["591"]
24069 type: "MultiPolygon",
24070 coordinates: [[[[-63.90248, -12.52544], [-64.22539, -12.45267], [-64.30708, -12.46398], [-64.99778, -11.98604], [-65.30027, -11.48749], [-65.28141, -10.86289], [-65.35402, -10.78685], [-65.37923, -10.35141], [-65.29019, -9.86253], [-65.40615, -9.63894], [-65.56244, -9.84266], [-65.68343, -9.75323], [-67.17784, -10.34016], [-68.71533, -11.14749], [-68.7651, -11.0496], [-68.75179, -11.03688], [-68.75265, -11.02383], [-68.74802, -11.00891], [-69.42792, -10.93451], [-69.47839, -10.95254], [-69.57156, -10.94555], [-68.98115, -11.8979], [-68.65044, -12.50689], [-68.85615, -12.87769], [-68.8864, -13.40792], [-69.05265, -13.68546], [-68.88135, -14.18639], [-69.36254, -14.94634], [-69.14856, -15.23478], [-69.40336, -15.61358], [-69.20291, -16.16668], [-69.09986, -16.22693], [-68.96238, -16.194], [-68.79464, -16.33272], [-68.98358, -16.42165], [-69.04027, -16.57214], [-69.00853, -16.66769], [-69.16896, -16.72233], [-69.62883, -17.28142], [-69.46863, -17.37466], [-69.46897, -17.4988], [-69.46623, -17.60518], [-69.34126, -17.72753], [-69.28671, -17.94844], [-69.07496, -18.03715], [-69.14807, -18.16893], [-69.07432, -18.28259], [-68.94987, -18.93302], [-68.87082, -19.06003], [-68.80602, -19.08355], [-68.61989, -19.27584], [-68.41218, -19.40499], [-68.66761, -19.72118], [-68.54611, -19.84651], [-68.57132, -20.03134], [-68.74273, -20.08817], [-68.7276, -20.46178], [-68.44023, -20.62701], [-68.55383, -20.7355], [-68.53957, -20.91542], [-68.40403, -20.94562], [-68.18816, -21.28614], [-67.85114, -22.87076], [-67.54284, -22.89771], [-67.18382, -22.81525], [-66.7298, -22.23644], [-66.29714, -22.08741], [-66.24077, -21.77837], [-66.03836, -21.84829], [-66.04832, -21.9187], [-65.9261, -21.93335], [-65.7467, -22.10105], [-65.61166, -22.09504], [-65.58694, -22.09794], [-65.57743, -22.07675], [-65.47435, -22.08908], [-64.99524, -22.08255], [-64.90014, -22.12136], [-64.67174, -22.18957], [-64.58888, -22.25035], [-64.4176, -22.67692], [-64.35108, -22.73282], [-64.31489, -22.88824], [-64.22918, -22.55807], [-63.93287, -21.99934], [-63.70963, -21.99934], [-63.68113, -22.0544], [-63.66482, -21.99918], [-62.81124, -21.9987], [-62.8078, -22.12534], [-62.64455, -22.25091], [-62.2757, -21.06657], [-62.26883, -20.55311], [-61.93912, -20.10053], [-61.73723, -19.63958], [-60.00638, -19.2981], [-59.06965, -19.29148], [-58.23216, -19.80058], [-58.16225, -20.16193], [-57.8496, -19.98346], [-58.14215, -19.76276], [-57.78463, -19.03259], [-57.71113, -19.03161], [-57.69134, -19.00544], [-57.71995, -18.97546], [-57.71995, -18.89573], [-57.76764, -18.90087], [-57.56807, -18.25655], [-57.48237, -18.24219], [-57.69877, -17.8431], [-57.73949, -17.56095], [-57.90082, -17.44555], [-57.99661, -17.5273], [-58.32935, -17.28195], [-58.5058, -16.80958], [-58.30918, -16.3699], [-58.32431, -16.25861], [-58.41506, -16.32636], [-60.16069, -16.26479], [-60.23797, -15.50267], [-60.58224, -15.09887], [-60.23968, -15.09515], [-60.27887, -14.63021], [-60.46037, -14.22496], [-60.48053, -13.77981], [-61.05527, -13.50054], [-61.81151, -13.49564], [-63.76259, -12.42952], [-63.90248, -12.52544]]]]
24078 wikidata: "Q27561",
24079 nameEn: "Caribbean Netherlands",
24091 groups: ["005", "419", "019", "UN"],
24092 callingCodes: ["55"]
24095 type: "MultiPolygon",
24096 coordinates: [[[[-59.69361, 4.34069], [-59.78878, 4.45637], [-60.15953, 4.53456], [-60.04189, 4.69801], [-59.98129, 5.07097], [-60.20944, 5.28754], [-60.32352, 5.21299], [-60.73204, 5.20931], [-60.5802, 4.94312], [-60.86539, 4.70512], [-60.98303, 4.54167], [-61.15703, 4.49839], [-61.31457, 4.54167], [-61.29675, 4.44216], [-61.48569, 4.43149], [-61.54629, 4.2822], [-62.13094, 4.08309], [-62.44822, 4.18621], [-62.57656, 4.04754], [-62.74411, 4.03331], [-62.7655, 3.73099], [-62.98296, 3.59935], [-63.21111, 3.96219], [-63.4464, 3.9693], [-63.42233, 3.89995], [-63.50611, 3.83592], [-63.67099, 4.01731], [-63.70218, 3.91417], [-63.86082, 3.94796], [-63.99183, 3.90172], [-64.14512, 4.12932], [-64.57648, 4.12576], [-64.72977, 4.28931], [-64.84028, 4.24665], [-64.48379, 3.7879], [-64.02908, 2.79797], [-64.0257, 2.48156], [-63.39114, 2.4317], [-63.39827, 2.16098], [-64.06135, 1.94722], [-64.08274, 1.64792], [-64.34654, 1.35569], [-64.38932, 1.5125], [-65.11657, 1.12046], [-65.57288, 0.62856], [-65.50158, 0.92086], [-65.6727, 1.01353], [-66.28507, 0.74585], [-66.85795, 1.22998], [-67.08222, 1.17441], [-67.15784, 1.80439], [-67.299, 1.87494], [-67.40488, 2.22258], [-67.9292, 1.82455], [-68.18632, 2.00091], [-68.26699, 1.83463], [-68.18128, 1.72881], [-69.38621, 1.70865], [-69.53746, 1.76408], [-69.83491, 1.69353], [-69.82987, 1.07864], [-69.26017, 1.06856], [-69.14422, 0.84172], [-69.20976, 0.57958], [-69.47696, 0.71065], [-70.04162, 0.55437], [-70.03658, -0.19681], [-69.603, -0.51947], [-69.59796, -0.75136], [-69.4215, -1.01853], [-69.43395, -1.42219], [-69.94708, -4.2431], [-70.00888, -4.37833], [-70.11305, -4.27281], [-70.19582, -4.3607], [-70.33236, -4.15214], [-70.77601, -4.15717], [-70.96814, -4.36915], [-71.87003, -4.51661], [-72.64391, -5.0391], [-72.83973, -5.14765], [-73.24579, -6.05764], [-73.12983, -6.43852], [-73.73986, -6.87919], [-73.77011, -7.28944], [-73.96938, -7.58465], [-73.65485, -7.77897], [-73.76576, -7.89884], [-72.92886, -9.04074], [-73.21498, -9.40904], [-72.72216, -9.41397], [-72.31883, -9.5184], [-72.14742, -9.98049], [-71.23394, -9.9668], [-70.53373, -9.42628], [-70.58453, -9.58303], [-70.55429, -9.76692], [-70.62487, -9.80666], [-70.64134, -11.0108], [-70.51395, -10.92249], [-70.38791, -11.07096], [-69.90896, -10.92744], [-69.57835, -10.94051], [-69.57156, -10.94555], [-69.47839, -10.95254], [-69.42792, -10.93451], [-68.74802, -11.00891], [-68.75265, -11.02383], [-68.75179, -11.03688], [-68.7651, -11.0496], [-68.71533, -11.14749], [-67.17784, -10.34016], [-65.68343, -9.75323], [-65.56244, -9.84266], [-65.40615, -9.63894], [-65.29019, -9.86253], [-65.37923, -10.35141], [-65.35402, -10.78685], [-65.28141, -10.86289], [-65.30027, -11.48749], [-64.99778, -11.98604], [-64.30708, -12.46398], [-64.22539, -12.45267], [-63.90248, -12.52544], [-63.76259, -12.42952], [-61.81151, -13.49564], [-61.05527, -13.50054], [-60.48053, -13.77981], [-60.46037, -14.22496], [-60.27887, -14.63021], [-60.23968, -15.09515], [-60.58224, -15.09887], [-60.23797, -15.50267], [-60.16069, -16.26479], [-58.41506, -16.32636], [-58.32431, -16.25861], [-58.30918, -16.3699], [-58.5058, -16.80958], [-58.32935, -17.28195], [-57.99661, -17.5273], [-57.90082, -17.44555], [-57.73949, -17.56095], [-57.69877, -17.8431], [-57.48237, -18.24219], [-57.56807, -18.25655], [-57.76764, -18.90087], [-57.71995, -18.89573], [-57.71995, -18.97546], [-57.69134, -19.00544], [-57.71113, -19.03161], [-57.78463, -19.03259], [-58.14215, -19.76276], [-57.8496, -19.98346], [-58.16225, -20.16193], [-57.84536, -20.93155], [-57.93492, -21.65505], [-57.88239, -21.6868], [-57.94642, -21.73799], [-57.98625, -22.09157], [-56.6508, -22.28387], [-56.5212, -22.11556], [-56.45893, -22.08072], [-56.23206, -22.25347], [-55.8331, -22.29008], [-55.74941, -22.46436], [-55.741, -22.52018], [-55.72366, -22.5519], [-55.6986, -22.56268], [-55.68742, -22.58407], [-55.62493, -22.62765], [-55.63849, -22.95122], [-55.5446, -23.22811], [-55.52288, -23.2595], [-55.5555, -23.28237], [-55.43585, -23.87157], [-55.44117, -23.9185], [-55.41784, -23.9657], [-55.12292, -23.99669], [-55.0518, -23.98666], [-55.02691, -23.97317], [-54.6238, -23.83078], [-54.32807, -24.01865], [-54.28207, -24.07305], [-54.4423, -25.13381], [-54.62033, -25.46026], [-54.60196, -25.48397], [-54.59509, -25.53696], [-54.59398, -25.59224], [-54.5502, -25.58915], [-54.52926, -25.62846], [-53.90831, -25.55513], [-53.83691, -25.94849], [-53.73511, -26.04211], [-53.73086, -26.05842], [-53.7264, -26.0664], [-53.73391, -26.07006], [-53.73968, -26.10012], [-53.65018, -26.19501], [-53.65237, -26.23289], [-53.63739, -26.2496], [-53.63881, -26.25075], [-53.64632, -26.24798], [-53.64186, -26.25976], [-53.64505, -26.28089], [-53.68269, -26.33359], [-53.73372, -26.6131], [-53.80144, -27.09844], [-54.15978, -27.2889], [-54.19062, -27.27639], [-54.19268, -27.30751], [-54.41888, -27.40882], [-54.50416, -27.48232], [-54.67657, -27.57214], [-54.90159, -27.63132], [-54.90805, -27.73149], [-55.1349, -27.89759], [-55.16872, -27.86224], [-55.33303, -27.94661], [-55.6262, -28.17124], [-55.65418, -28.18304], [-56.01729, -28.51223], [-56.00458, -28.60421], [-56.05265, -28.62651], [-56.54171, -29.11447], [-56.57295, -29.11357], [-56.62789, -29.18073], [-56.81251, -29.48154], [-57.09386, -29.74211], [-57.65132, -30.19229], [-57.22502, -30.26121], [-56.90236, -30.02578], [-56.49267, -30.39471], [-56.4795, -30.3899], [-56.4619, -30.38457], [-55.87388, -31.05053], [-55.58866, -30.84117], [-55.5634, -30.8686], [-55.55373, -30.8732], [-55.55218, -30.88193], [-55.54572, -30.89051], [-55.53431, -30.89714], [-55.53276, -30.90218], [-55.52712, -30.89997], [-55.51862, -30.89828], [-55.50841, -30.9027], [-55.50821, -30.91349], [-54.17384, -31.86168], [-53.76024, -32.0751], [-53.39572, -32.58596], [-53.37671, -32.57005], [-53.1111, -32.71147], [-53.53459, -33.16843], [-53.52794, -33.68908], [-53.44031, -33.69344], [-53.39593, -33.75169], [-53.37138, -33.74313], [-52.83257, -34.01481], [-28.34015, -20.99094], [-28.99601, 1.86593], [-51.35485, 4.8383], [-51.63798, 4.51394], [-51.61983, 4.14596], [-51.79599, 3.89336], [-51.82312, 3.85825], [-51.85573, 3.83427], [-52.31787, 3.17896], [-52.6906, 2.37298], [-52.96539, 2.1881], [-53.78743, 2.34412], [-54.16286, 2.10779], [-54.6084, 2.32856], [-55.01919, 2.564], [-55.71493, 2.40342], [-55.96292, 2.53188], [-56.13054, 2.27723], [-55.92159, 2.05236], [-55.89863, 1.89861], [-55.99278, 1.83137], [-56.47045, 1.95135], [-56.7659, 1.89509], [-57.07092, 1.95304], [-57.09109, 2.01854], [-57.23981, 1.95808], [-57.35073, 1.98327], [-57.55743, 1.69605], [-57.77281, 1.73344], [-57.97336, 1.64566], [-58.01873, 1.51966], [-58.33887, 1.58014], [-58.4858, 1.48399], [-58.53571, 1.29154], [-58.84229, 1.17749], [-58.92072, 1.31293], [-59.25583, 1.40559], [-59.74066, 1.87596], [-59.7264, 2.27497], [-59.91177, 2.36759], [-59.99733, 2.92312], [-59.79769, 3.37162], [-59.86899, 3.57089], [-59.51963, 3.91951], [-59.73353, 4.20399], [-59.69361, 4.34069]]]]
24105 nameEn: "The Bahamas",
24106 groups: ["029", "003", "419", "019", "UN"],
24108 roadSpeedUnit: "mph",
24109 callingCodes: ["1 242"]
24112 type: "MultiPolygon",
24113 coordinates: [[[[-72.98446, 20.4801], [-71.70065, 25.7637], [-78.91214, 27.76553], [-80.65727, 23.71953], [-72.98446, 20.4801]]]]
24123 groups: ["034", "142", "UN"],
24125 callingCodes: ["975"]
24128 type: "MultiPolygon",
24129 coordinates: [[[[91.6469, 27.76358], [91.5629, 27.84823], [91.48973, 27.93903], [91.46327, 28.0064], [91.25779, 28.07509], [91.20019, 27.98715], [90.69894, 28.07784], [90.58842, 28.02838], [90.13387, 28.19178], [89.79762, 28.23979], [89.59525, 28.16433], [89.12825, 27.62502], [89.0582, 27.60985], [88.97213, 27.51671], [88.95355, 27.4106], [89.00216, 27.32532], [88.96947, 27.30319], [88.93678, 27.33777], [88.91901, 27.32483], [88.74219, 27.144], [88.86984, 27.10937], [88.8714, 26.97488], [88.92301, 26.99286], [88.95807, 26.92668], [89.09554, 26.89089], [89.12825, 26.81661], [89.1926, 26.81329], [89.37913, 26.86224], [89.38319, 26.85963], [89.3901, 26.84225], [89.42349, 26.83727], [89.63369, 26.74402], [89.86124, 26.73307], [90.04535, 26.72422], [90.30402, 26.85098], [90.39271, 26.90704], [90.48504, 26.8594], [90.67715, 26.77215], [91.50067, 26.79223], [91.83181, 26.87318], [92.05523, 26.8692], [92.11863, 26.893], [92.03457, 27.07334], [92.04702, 27.26861], [92.12019, 27.27829], [92.01132, 27.47352], [91.65007, 27.48287], [91.55819, 27.6144], [91.6469, 27.76358]]]]
24137 wikidata: "Q23408",
24138 nameEn: "Bouvet Island",
24140 groups: ["005", "419", "019", "UN"]
24143 type: "MultiPolygon",
24144 coordinates: [[[[4.54042, -54.0949], [2.28941, -54.13089], [3.35353, -55.17558], [4.54042, -54.0949]]]]
24153 nameEn: "Botswana",
24154 groups: ["018", "202", "002", "UN"],
24156 callingCodes: ["267"]
24159 type: "MultiPolygon",
24160 coordinates: [[[[25.26433, -17.79571], [25.16882, -17.78253], [25.05895, -17.84452], [24.95586, -17.79674], [24.73364, -17.89338], [24.71887, -17.9218], [24.6303, -17.9863], [24.57485, -18.07151], [24.40577, -17.95726], [24.19416, -18.01919], [23.61088, -18.4881], [23.29618, -17.99855], [23.0996, -18.00075], [21.45556, -18.31795], [20.99904, -18.31743], [20.99751, -22.00026], [19.99912, -21.99991], [19.99817, -24.76768], [20.02809, -24.78725], [20.03678, -24.81004], [20.29826, -24.94869], [20.64795, -25.47827], [20.86081, -26.14892], [20.61754, -26.4692], [20.63275, -26.78181], [20.68596, -26.9039], [20.87031, -26.80047], [21.13353, -26.86661], [21.37869, -26.82083], [21.69322, -26.86152], [21.7854, -26.79199], [21.77114, -26.69015], [21.83291, -26.65959], [21.90703, -26.66808], [22.06192, -26.61882], [22.21206, -26.3773], [22.41921, -26.23078], [22.56365, -26.19668], [22.70808, -25.99186], [22.86012, -25.50572], [23.03497, -25.29971], [23.47588, -25.29971], [23.9244, -25.64286], [24.18287, -25.62916], [24.36531, -25.773], [24.44703, -25.73021], [24.67319, -25.81749], [24.8946, -25.80723], [25.01718, -25.72507], [25.12266, -25.75931], [25.33076, -25.76616], [25.58543, -25.6343], [25.6643, -25.4491], [25.69661, -25.29284], [25.72702, -25.25503], [25.88571, -24.87802], [25.84295, -24.78661], [25.8515, -24.75727], [26.39409, -24.63468], [26.46346, -24.60358], [26.51667, -24.47219], [26.84165, -24.24885], [26.99749, -23.65486], [27.33768, -23.40917], [27.52393, -23.37952], [27.6066, -23.21894], [27.74154, -23.2137], [27.93539, -23.04941], [27.93729, -22.96194], [28.04752, -22.90243], [28.04562, -22.8394], [28.34874, -22.5694], [28.63287, -22.55887], [28.91889, -22.44299], [29.0151, -22.22907], [29.10881, -22.21202], [29.15268, -22.21399], [29.18974, -22.18599], [29.21955, -22.17771], [29.37703, -22.19581], [29.3533, -22.18363], [29.24648, -22.05967], [29.1974, -22.07472], [29.14501, -22.07275], [29.08495, -22.04867], [29.04108, -22.00563], [29.02191, -21.95665], [29.02191, -21.90647], [29.04023, -21.85864], [29.07763, -21.81877], [28.58114, -21.63455], [28.49942, -21.66634], [28.29416, -21.59037], [28.01669, -21.57624], [27.91407, -21.31621], [27.69171, -21.08409], [27.72972, -20.51735], [27.69361, -20.48531], [27.28865, -20.49873], [27.29831, -20.28935], [27.21278, -20.08244], [26.72246, -19.92707], [26.17227, -19.53709], [25.96226, -19.08152], [25.99837, -19.02943], [25.94326, -18.90362], [25.82353, -18.82808], [25.79217, -18.6355], [25.68859, -18.56165], [25.53465, -18.39041], [25.39972, -18.12691], [25.31799, -18.07091], [25.23909, -17.90832], [25.26433, -17.79571]]]]
24170 groups: ["151", "150", "UN"],
24171 callingCodes: ["375"]
24174 type: "MultiPolygon",
24175 coordinates: [[[[28.15217, 56.16964], [27.97865, 56.11849], [27.63065, 55.89687], [27.61683, 55.78558], [27.3541, 55.8089], [27.27804, 55.78299], [27.1559, 55.85032], [26.97153, 55.8102], [26.87448, 55.7172], [26.76872, 55.67658], [26.71802, 55.70645], [26.64888, 55.70515], [26.63231, 55.67968], [26.63167, 55.57887], [26.55094, 55.5093], [26.5522, 55.40277], [26.44937, 55.34832], [26.5709, 55.32572], [26.6714, 55.33902], [26.80929, 55.31642], [26.83266, 55.30444], [26.835, 55.28182], [26.73017, 55.24226], [26.72983, 55.21788], [26.68075, 55.19787], [26.69243, 55.16718], [26.54753, 55.14181], [26.51481, 55.16051], [26.46249, 55.12814], [26.35121, 55.1525], [26.30628, 55.12536], [26.23202, 55.10439], [26.26941, 55.08032], [26.20397, 54.99729], [26.13386, 54.98924], [26.05907, 54.94631], [25.99129, 54.95705], [25.89462, 54.93438], [25.74122, 54.80108], [25.75977, 54.57252], [25.68045, 54.5321], [25.64813, 54.48704], [25.62203, 54.4656], [25.63371, 54.42075], [25.5376, 54.33158], [25.55425, 54.31591], [25.68513, 54.31727], [25.78553, 54.23327], [25.78563, 54.15747], [25.71084, 54.16704], [25.64875, 54.1259], [25.54724, 54.14925], [25.51452, 54.17799], [25.56823, 54.25212], [25.509, 54.30267], [25.35559, 54.26544], [25.22705, 54.26271], [25.19199, 54.219], [25.0728, 54.13419], [24.991, 54.14241], [24.96894, 54.17589], [24.77131, 54.11091], [24.85311, 54.02862], [24.74279, 53.96663], [24.69185, 53.96543], [24.69652, 54.01901], [24.62275, 54.00217], [24.44411, 53.90076], [24.34128, 53.90076], [24.19638, 53.96405], [23.98837, 53.92554], [23.95098, 53.9613], [23.81309, 53.94205], [23.80543, 53.89558], [23.71726, 53.93379], [23.61677, 53.92691], [23.51284, 53.95052], [23.62004, 53.60942], [23.81995, 53.24131], [23.85657, 53.22923], [23.91393, 53.16469], [23.87548, 53.0831], [23.92184, 53.02079], [23.94689, 52.95919], [23.91805, 52.94016], [23.93763, 52.71332], [23.73615, 52.6149], [23.58296, 52.59868], [23.45112, 52.53774], [23.34141, 52.44845], [23.18196, 52.28812], [23.20071, 52.22848], [23.47859, 52.18215], [23.54314, 52.12148], [23.61, 52.11264], [23.64066, 52.07626], [23.68733, 51.9906], [23.61523, 51.92066], [23.62691, 51.78208], [23.53198, 51.74298], [23.57053, 51.55938], [23.56236, 51.53673], [23.62751, 51.50512], [23.6736, 51.50255], [23.60906, 51.62122], [23.7766, 51.66809], [23.91118, 51.63316], [23.8741, 51.59734], [23.99907, 51.58369], [24.13075, 51.66979], [24.3163, 51.75063], [24.29021, 51.80841], [24.37123, 51.88222], [24.98784, 51.91273], [25.20228, 51.97143], [25.46163, 51.92205], [25.73673, 51.91973], [25.80574, 51.94556], [25.83217, 51.92587], [26.00408, 51.92967], [26.19084, 51.86781], [26.39367, 51.87315], [26.46962, 51.80501], [26.69759, 51.82284], [26.80043, 51.75777], [26.9489, 51.73788], [26.99422, 51.76933], [27.20602, 51.77291], [27.20948, 51.66713], [27.26613, 51.65957], [27.24828, 51.60161], [27.47212, 51.61184], [27.51058, 51.5854], [27.55727, 51.63486], [27.71932, 51.60672], [27.67125, 51.50854], [27.76052, 51.47604], [27.85253, 51.62293], [27.91844, 51.61952], [27.95827, 51.56065], [28.10658, 51.57857], [28.23452, 51.66988], [28.37592, 51.54505], [28.47051, 51.59734], [28.64429, 51.5664], [28.69161, 51.44695], [28.73143, 51.46236], [28.75615, 51.41442], [28.78224, 51.45294], [28.76027, 51.48802], [28.81795, 51.55552], [28.95528, 51.59222], [28.99098, 51.56833], [29.1187, 51.65872], [29.16402, 51.64679], [29.20659, 51.56918], [29.25603, 51.57089], [29.25191, 51.49828], [29.32881, 51.37843], [29.42357, 51.4187], [29.49773, 51.39814], [29.54372, 51.48372], [29.7408, 51.53417], [29.77376, 51.4461], [30.17888, 51.51025], [30.34642, 51.42555], [30.36153, 51.33984], [30.56203, 51.25655], [30.64992, 51.35014], [30.51946, 51.59649], [30.68804, 51.82806], [30.76443, 51.89739], [30.90897, 52.00699], [30.95589, 52.07775], [31.13332, 52.1004], [31.25142, 52.04131], [31.38326, 52.12991], [31.7822, 52.11406], [31.77877, 52.18636], [31.6895, 52.1973], [31.70735, 52.26711], [31.57971, 52.32146], [31.62084, 52.33849], [31.61397, 52.48843], [31.56316, 52.51518], [31.63869, 52.55361], [31.50406, 52.69707], [31.57277, 52.71613], [31.592, 52.79011], [31.35667, 52.97854], [31.24147, 53.031], [31.32283, 53.04101], [31.33519, 53.08805], [31.3915, 53.09712], [31.36403, 53.13504], [31.40523, 53.21406], [31.56316, 53.19432], [31.62496, 53.22886], [31.787, 53.18033], [31.82373, 53.10042], [32.15368, 53.07594], [32.40773, 53.18856], [32.51725, 53.28431], [32.73257, 53.33494], [32.74968, 53.45597], [32.47777, 53.5548], [32.40499, 53.6656], [32.50112, 53.68594], [32.45717, 53.74039], [32.36663, 53.7166], [32.12621, 53.81586], [31.89137, 53.78099], [31.77028, 53.80015], [31.85019, 53.91801], [31.88744, 54.03653], [31.89599, 54.0837], [31.57002, 54.14535], [31.30791, 54.25315], [31.3177, 54.34067], [31.22945, 54.46585], [31.08543, 54.50361], [31.21399, 54.63113], [31.19339, 54.66947], [30.99187, 54.67046], [30.98226, 54.68872], [31.0262, 54.70698], [30.97127, 54.71967], [30.95479, 54.74346], [30.75165, 54.80699], [30.8264, 54.90062], [30.81759, 54.94064], [30.93144, 54.9585], [30.95754, 54.98609], [30.9081, 55.02232], [30.94243, 55.03964], [31.00972, 55.02783], [31.02071, 55.06167], [30.97369, 55.17134], [30.87944, 55.28223], [30.81946, 55.27931], [30.8257, 55.3313], [30.93144, 55.3914], [30.90123, 55.46621], [30.95204, 55.50667], [30.93419, 55.6185], [30.86003, 55.63169], [30.7845, 55.58514], [30.72957, 55.66268], [30.67464, 55.64176], [30.63344, 55.73079], [30.51037, 55.76568], [30.51346, 55.78982], [30.48257, 55.81066], [30.30987, 55.83592], [30.27776, 55.86819], [30.12136, 55.8358], [29.97975, 55.87281], [29.80672, 55.79569], [29.61446, 55.77716], [29.51283, 55.70294], [29.3604, 55.75862], [29.44692, 55.95978], [29.21717, 55.98971], [29.08299, 56.03427], [28.73418, 55.97131], [28.63668, 56.07262], [28.68337, 56.10173], [28.5529, 56.11705], [28.43068, 56.09407], [28.37987, 56.11399], [28.36888, 56.05805], [28.30571, 56.06035], [28.15217, 56.16964]]]]
24185 groups: ["013", "003", "419", "019", "UN"],
24186 roadSpeedUnit: "mph",
24187 callingCodes: ["501"]
24190 type: "MultiPolygon",
24191 coordinates: [[[[-88.3268, 18.49048], [-88.48242, 18.49164], [-88.71505, 18.0707], [-88.8716, 17.89535], [-89.03839, 18.0067], [-89.15105, 17.95104], [-89.14985, 17.81563], [-89.15025, 17.04813], [-89.22683, 15.88619], [-89.17418, 15.90898], [-89.02415, 15.9063], [-88.95358, 15.88698], [-88.40779, 16.09624], [-86.92368, 17.61462], [-87.84815, 18.18511], [-87.85693, 18.18266], [-87.86657, 18.19971], [-87.87604, 18.18313], [-87.90671, 18.15213], [-88.03165, 18.16657], [-88.03238, 18.41778], [-88.26593, 18.47617], [-88.29909, 18.47591], [-88.3268, 18.49048]]]]
24201 groups: ["021", "003", "019", "UN"],
24202 callingCodes: ["1"]
24205 type: "MultiPolygon",
24206 coordinates: [[[[-67.20349, 45.1722], [-67.19603, 45.16771], [-67.15965, 45.16179], [-67.11316, 45.11176], [-67.0216, 44.95333], [-66.96824, 44.90965], [-66.98249, 44.87071], [-66.96824, 44.83078], [-66.93432, 44.82597], [-67.16117, 44.20069], [-61.98255, 37.34815], [-56.27503, 47.39728], [-53.12387, 41.40385], [-46.37635, 57.3249], [-77.52957, 77.23408], [-68.21821, 80.48551], [-49.33696, 84.57952], [-140.97446, 84.39275], [-141.00116, 60.30648], [-140.5227, 60.22077], [-140.45648, 60.30919], [-139.98024, 60.18027], [-139.68991, 60.33693], [-139.05831, 60.35205], [-139.20603, 60.08896], [-139.05365, 59.99655], [-138.71149, 59.90728], [-138.62145, 59.76431], [-137.60623, 59.24465], [-137.4925, 58.89415], [-136.82619, 59.16198], [-136.52365, 59.16752], [-136.47323, 59.46617], [-136.33727, 59.44466], [-136.22381, 59.55526], [-136.31566, 59.59083], [-135.48007, 59.79937], [-135.03069, 59.56208], [-135.00267, 59.28745], [-134.7047, 59.2458], [-134.55699, 59.1297], [-134.48059, 59.13231], [-134.27175, 58.8634], [-133.84645, 58.73543], [-133.38523, 58.42773], [-131.8271, 56.62247], [-130.77769, 56.36185], [-130.33965, 56.10849], [-130.10173, 56.12178], [-130.00093, 56.00325], [-130.00857, 55.91344], [-130.15373, 55.74895], [-129.97513, 55.28029], [-130.08035, 55.21556], [-130.18765, 55.07744], [-130.27203, 54.97174], [-130.44184, 54.85377], [-130.64499, 54.76912], [-130.61931, 54.70835], [-133.92876, 54.62289], [-133.36909, 48.51151], [-125.03842, 48.53282], [-123.50039, 48.21223], [-123.15614, 48.35395], [-123.26565, 48.6959], [-123.0093, 48.76586], [-123.0093, 48.83186], [-123.32163, 49.00419], [-95.15355, 48.9996], [-95.15357, 49.384], [-95.12903, 49.37056], [-95.05825, 49.35311], [-95.01419, 49.35647], [-94.99532, 49.36579], [-94.95681, 49.37035], [-94.85381, 49.32492], [-94.8159, 49.32299], [-94.82487, 49.29483], [-94.77355, 49.11998], [-94.75017, 49.09931], [-94.687, 48.84077], [-94.70087, 48.8339], [-94.70486, 48.82365], [-94.69669, 48.80918], [-94.69335, 48.77883], [-94.58903, 48.71803], [-94.54885, 48.71543], [-94.53826, 48.70216], [-94.44258, 48.69223], [-94.4174, 48.71049], [-94.27153, 48.70232], [-94.25172, 48.68404], [-94.25104, 48.65729], [-94.23215, 48.65202], [-93.85769, 48.63284], [-93.83288, 48.62745], [-93.80676, 48.58232], [-93.80939, 48.52439], [-93.79267, 48.51631], [-93.66382, 48.51845], [-93.47022, 48.54357], [-93.44472, 48.59147], [-93.40693, 48.60948], [-93.39758, 48.60364], [-93.3712, 48.60599], [-93.33946, 48.62787], [-93.25391, 48.64266], [-92.94973, 48.60866], [-92.7287, 48.54005], [-92.6342, 48.54133], [-92.62747, 48.50278], [-92.69927, 48.49573], [-92.71323, 48.46081], [-92.65606, 48.43471], [-92.50712, 48.44921], [-92.45588, 48.40624], [-92.48147, 48.36609], [-92.37185, 48.22259], [-92.27167, 48.25046], [-92.30939, 48.31251], [-92.26662, 48.35651], [-92.202, 48.35252], [-92.14732, 48.36578], [-92.05339, 48.35958], [-91.98929, 48.25409], [-91.86125, 48.21278], [-91.71231, 48.19875], [-91.70451, 48.11805], [-91.55649, 48.10611], [-91.58025, 48.04339], [-91.45829, 48.07454], [-91.43248, 48.04912], [-91.25025, 48.08522], [-91.08016, 48.18096], [-90.87588, 48.2484], [-90.75045, 48.09143], [-90.56444, 48.12184], [-90.56312, 48.09488], [-90.07418, 48.11043], [-89.89974, 47.98109], [-89.77248, 48.02607], [-89.57972, 48.00023], [-89.48837, 48.01412], [-88.37033, 48.30586], [-84.85871, 46.88881], [-84.55635, 46.45974], [-84.47607, 46.45225], [-84.4481, 46.48972], [-84.42101, 46.49853], [-84.34174, 46.50683], [-84.29893, 46.49127], [-84.26351, 46.49508], [-84.2264, 46.53337], [-84.1945, 46.54061], [-84.17723, 46.52753], [-84.12885, 46.53068], [-84.11196, 46.50248], [-84.13451, 46.39218], [-84.11254, 46.32329], [-84.11615, 46.2681], [-84.09756, 46.25512], [-84.1096, 46.23987], [-83.95399, 46.05634], [-83.90453, 46.05922], [-83.83329, 46.12169], [-83.57017, 46.105], [-83.43746, 45.99749], [-83.59589, 45.82131], [-82.48419, 45.30225], [-82.42469, 42.992], [-82.4146, 42.97626], [-82.4253, 42.95423], [-82.45331, 42.93139], [-82.4826, 42.8068], [-82.46613, 42.76615], [-82.51063, 42.66025], [-82.51858, 42.611], [-82.57583, 42.5718], [-82.58873, 42.54984], [-82.64242, 42.55594], [-82.82964, 42.37355], [-83.02253, 42.33045], [-83.07837, 42.30978], [-83.09837, 42.28877], [-83.12724, 42.2376], [-83.14962, 42.04089], [-83.11184, 41.95671], [-82.67862, 41.67615], [-78.93684, 42.82887], [-78.90712, 42.89733], [-78.90905, 42.93022], [-78.93224, 42.95229], [-78.96312, 42.95509], [-78.98126, 42.97], [-79.02074, 42.98444], [-79.02424, 43.01983], [-78.99941, 43.05612], [-79.01055, 43.06659], [-79.07486, 43.07845], [-79.05671, 43.10937], [-79.06881, 43.12029], [-79.0427, 43.13934], [-79.04652, 43.16396], [-79.05384, 43.17418], [-79.05002, 43.20133], [-79.05544, 43.21224], [-79.05512, 43.25375], [-79.06921, 43.26183], [-79.25796, 43.54052], [-76.79706, 43.63099], [-76.43859, 44.09393], [-76.35324, 44.13493], [-76.31222, 44.19894], [-76.244, 44.19643], [-76.1664, 44.23051], [-76.16285, 44.28262], [-76.00018, 44.34896], [-75.95947, 44.34463], [-75.8217, 44.43176], [-75.76813, 44.51537], [-75.41441, 44.76614], [-75.2193, 44.87821], [-75.01363, 44.95608], [-74.99101, 44.98051], [-74.8447, 45.00606], [-74.66689, 45.00646], [-74.32699, 44.99029], [-73.35025, 45.00942], [-71.50067, 45.01357], [-71.48735, 45.07784], [-71.42778, 45.12624], [-71.40364, 45.21382], [-71.44252, 45.2361], [-71.37133, 45.24624], [-71.29371, 45.29996], [-71.22338, 45.25184], [-71.19723, 45.25438], [-71.14568, 45.24128], [-71.08364, 45.30623], [-71.01866, 45.31573], [-71.0107, 45.34819], [-70.95193, 45.33895], [-70.91169, 45.29849], [-70.89864, 45.2398], [-70.84816, 45.22698], [-70.80236, 45.37444], [-70.82638, 45.39828], [-70.78372, 45.43269], [-70.65383, 45.37592], [-70.62518, 45.42286], [-70.72651, 45.49771], [-70.68516, 45.56964], [-70.54019, 45.67291], [-70.38934, 45.73215], [-70.41523, 45.79497], [-70.25976, 45.89675], [-70.24694, 45.95138], [-70.31025, 45.96424], [-70.23855, 46.1453], [-70.29078, 46.18832], [-70.18547, 46.35357], [-70.05812, 46.41768], [-69.99966, 46.69543], [-69.22119, 47.46461], [-69.05148, 47.42012], [-69.05073, 47.30076], [-69.05039, 47.2456], [-68.89222, 47.1807], [-68.70125, 47.24399], [-68.60575, 47.24659], [-68.57914, 47.28431], [-68.38332, 47.28723], [-68.37458, 47.35851], [-68.23244, 47.35712], [-67.94843, 47.1925], [-67.87993, 47.10377], [-67.78578, 47.06473], [-67.78111, 45.9392], [-67.75196, 45.91814], [-67.80961, 45.87531], [-67.75654, 45.82324], [-67.80653, 45.80022], [-67.80705, 45.69528], [-67.6049, 45.60725], [-67.43815, 45.59162], [-67.42144, 45.50584], [-67.50578, 45.48971], [-67.42394, 45.37969], [-67.48201, 45.27351], [-67.34927, 45.122], [-67.29754, 45.14865], [-67.29748, 45.18173], [-67.27039, 45.1934], [-67.22751, 45.16344], [-67.20349, 45.1722]]]]
24214 wikidata: "Q36004",
24215 nameEn: "Cocos (Keeling) Islands",
24217 groups: ["053", "009", "UN"],
24219 callingCodes: ["61"]
24222 type: "MultiPolygon",
24223 coordinates: [[[[96.61846, -10.82438], [96.02343, -12.68334], [97.93979, -12.33309], [96.61846, -10.82438]]]]
24232 nameEn: "Democratic Republic of the Congo",
24234 groups: ["017", "202", "002", "UN"],
24235 callingCodes: ["243"]
24238 type: "MultiPolygon",
24239 coordinates: [[[[27.44012, 5.07349], [27.09575, 5.22305], [26.93064, 5.13535], [26.85579, 5.03887], [26.74572, 5.10685], [26.48595, 5.04984], [26.13371, 5.25594], [25.86073, 5.19455], [25.53271, 5.37431], [25.34558, 5.29101], [25.31256, 5.03668], [24.71816, 4.90509], [24.46719, 5.0915], [23.38847, 4.60013], [22.94817, 4.82392], [22.89094, 4.79321], [22.84691, 4.69887], [22.78526, 4.71423], [22.6928, 4.47285], [22.60915, 4.48821], [22.5431, 4.22041], [22.45504, 4.13039], [22.27682, 4.11347], [22.10721, 4.20723], [21.6405, 4.317], [21.55904, 4.25553], [21.25744, 4.33676], [21.21341, 4.29285], [21.11214, 4.33895], [21.08793, 4.39603], [20.90383, 4.44877], [20.60184, 4.42394], [18.62755, 3.47564], [18.63857, 3.19342], [18.10683, 2.26876], [18.08034, 1.58553], [17.85887, 1.04327], [17.86989, 0.58873], [17.95255, 0.48128], [17.93877, 0.32424], [17.81204, 0.23884], [17.66051, -0.26535], [17.72112, -0.52707], [17.32438, -0.99265], [16.97999, -1.12762], [16.70724, -1.45815], [16.50336, -1.8795], [16.16173, -2.16586], [16.22785, -2.59528], [16.1755, -3.25014], [16.21407, -3.2969], [15.89448, -3.9513], [15.53081, -4.042], [15.48121, -4.22062], [15.41785, -4.28381], [15.32693, -4.27282], [15.25411, -4.31121], [15.1978, -4.32388], [14.83101, -4.80838], [14.67948, -4.92093], [14.5059, -4.84956], [14.41499, -4.8825], [14.37366, -4.56125], [14.47284, -4.42941], [14.3957, -4.36623], [14.40672, -4.28381], [13.9108, -4.50906], [13.81162, -4.41842], [13.71794, -4.44864], [13.70417, -4.72601], [13.50305, -4.77818], [13.41764, -4.89897], [13.11182, -4.5942], [13.09648, -4.63739], [13.11195, -4.67745], [12.8733, -4.74346], [12.70868, -4.95505], [12.63465, -4.94632], [12.60251, -5.01715], [12.46297, -5.09408], [12.49815, -5.14058], [12.51589, -5.1332], [12.53586, -5.14658], [12.53599, -5.1618], [12.52301, -5.17481], [12.52318, -5.74353], [12.26557, -5.74031], [12.20376, -5.76338], [11.95767, -5.94705], [12.42245, -6.07585], [13.04371, -5.87078], [16.55507, -5.85631], [16.96282, -7.21787], [17.5828, -8.13784], [18.33635, -8.00126], [19.33698, -7.99743], [19.5469, -7.00195], [20.30218, -6.98955], [20.31846, -6.91953], [20.61689, -6.90876], [20.56263, -7.28566], [21.79824, -7.29628], [21.84856, -9.59871], [22.19039, -9.94628], [22.32604, -10.76291], [22.17954, -10.85884], [22.25951, -11.24911], [22.54205, -11.05784], [23.16602, -11.10577], [23.45631, -10.946], [23.86868, -11.02856], [24.00027, -10.89356], [24.34528, -11.06816], [24.42612, -11.44975], [25.34069, -11.19707], [25.33058, -11.65767], [26.01777, -11.91488], [26.88687, -12.01868], [27.04351, -11.61312], [27.22541, -11.60323], [27.21025, -11.76157], [27.59932, -12.22123], [28.33199, -12.41375], [29.01918, -13.41353], [29.60531, -13.21685], [29.65078, -13.41844], [29.81551, -13.44683], [29.8139, -12.14898], [29.48404, -12.23604], [29.4992, -12.43843], [29.18592, -12.37921], [28.48357, -11.87532], [28.37241, -11.57848], [28.65032, -10.65133], [28.62795, -9.92942], [28.68532, -9.78], [28.56208, -9.49122], [28.51627, -9.44726], [28.52636, -9.35379], [28.36562, -9.30091], [28.38526, -9.23393], [28.9711, -8.66935], [28.88917, -8.4831], [30.79243, -8.27382], [30.2567, -7.14121], [29.52552, -6.2731], [29.43673, -4.44845], [29.23708, -3.75856], [29.21463, -3.3514], [29.25633, -3.05471], [29.17258, -2.99385], [29.16037, -2.95457], [29.09797, -2.91935], [29.09119, -2.87871], [29.0505, -2.81774], [29.00404, -2.81978], [29.00167, -2.78523], [29.04081, -2.7416], [29.00357, -2.70596], [28.94346, -2.69124], [28.89793, -2.66111], [28.90226, -2.62385], [28.89288, -2.55848], [28.87943, -2.55165], [28.86193, -2.53185], [28.86209, -2.5231], [28.87497, -2.50887], [28.88846, -2.50493], [28.89342, -2.49017], [28.89132, -2.47557], [28.86846, -2.44866], [28.86826, -2.41888], [28.89601, -2.37321], [28.95642, -2.37321], [29.00051, -2.29001], [29.105, -2.27043], [29.17562, -2.12278], [29.11847, -1.90576], [29.24458, -1.69663], [29.24323, -1.66826], [29.36322, -1.50887], [29.45038, -1.5054], [29.53062, -1.40499], [29.59061, -1.39016], [29.58388, -0.89821], [29.63006, -0.8997], [29.62708, -0.71055], [29.67176, -0.55714], [29.67474, -0.47969], [29.65091, -0.46777], [29.72687, -0.08051], [29.7224, 0.07291], [29.77454, 0.16675], [29.81922, 0.16824], [29.87284, 0.39166], [29.97413, 0.52124], [29.95477, 0.64486], [29.98307, 0.84295], [30.1484, 0.89805], [30.22139, 0.99635], [30.24671, 1.14974], [30.48503, 1.21675], [31.30127, 2.11006], [31.28042, 2.17853], [31.20148, 2.2217], [31.1985, 2.29462], [31.12104, 2.27676], [31.07934, 2.30207], [31.06593, 2.35862], [30.96911, 2.41071], [30.91102, 2.33332], [30.83059, 2.42559], [30.74271, 2.43601], [30.75612, 2.5863], [30.8857, 2.83923], [30.8574, 2.9508], [30.77101, 3.04897], [30.84251, 3.26908], [30.93486, 3.40737], [30.94081, 3.50847], [30.85153, 3.48867], [30.85997, 3.5743], [30.80713, 3.60506], [30.78512, 3.67097], [30.56277, 3.62703], [30.57378, 3.74567], [30.55396, 3.84451], [30.47691, 3.83353], [30.27658, 3.95653], [30.22374, 3.93896], [30.1621, 4.10586], [30.06964, 4.13221], [29.79666, 4.37809], [29.82087, 4.56246], [29.49726, 4.7007], [29.43341, 4.50101], [29.22207, 4.34297], [29.03054, 4.48784], [28.8126, 4.48784], [28.6651, 4.42638], [28.20719, 4.35614], [27.79551, 4.59976], [27.76469, 4.79284], [27.65462, 4.89375], [27.56656, 4.89375], [27.44012, 5.07349]]]]
24248 nameEn: "Central African Republic",
24249 groups: ["017", "202", "002", "UN"],
24250 callingCodes: ["236"]
24253 type: "MultiPolygon",
24254 coordinates: [[[[22.87758, 10.91915], [22.45889, 11.00246], [21.72139, 10.64136], [21.71479, 10.29932], [21.63553, 10.217], [21.52766, 10.2105], [21.34934, 9.95907], [21.26348, 9.97642], [20.82979, 9.44696], [20.36748, 9.11019], [19.06421, 9.00367], [18.86388, 8.87971], [19.11044, 8.68172], [18.79783, 8.25929], [18.67455, 8.22226], [18.62612, 8.14163], [18.64153, 8.08714], [18.6085, 8.05009], [18.02731, 8.01085], [17.93926, 7.95853], [17.67288, 7.98905], [16.8143, 7.53971], [16.6668, 7.67281], [16.658, 7.75353], [16.59415, 7.76444], [16.58315, 7.88657], [16.41583, 7.77971], [16.40703, 7.68809], [15.79942, 7.44149], [15.73118, 7.52006], [15.49743, 7.52179], [15.23397, 7.25135], [15.04717, 6.77085], [14.96311, 6.75693], [14.79966, 6.39043], [14.80122, 6.34866], [14.74206, 6.26356], [14.56149, 6.18928], [14.43073, 6.08867], [14.42917, 6.00508], [14.49455, 5.91683], [14.60974, 5.91838], [14.62375, 5.70466], [14.58951, 5.59777], [14.62531, 5.51411], [14.52724, 5.28319], [14.57083, 5.23979], [14.65489, 5.21343], [14.73383, 4.6135], [15.00825, 4.41458], [15.08609, 4.30282], [15.10644, 4.1362], [15.17482, 4.05131], [15.07686, 4.01805], [15.73522, 3.24348], [15.77725, 3.26835], [16.05449, 3.02306], [16.08252, 2.45708], [16.19357, 2.21537], [16.50126, 2.84739], [16.46701, 2.92512], [16.57598, 3.47999], [16.68283, 3.54257], [17.01746, 3.55136], [17.35649, 3.63045], [17.46876, 3.70515], [17.60966, 3.63705], [17.83421, 3.61068], [17.85842, 3.53378], [18.05656, 3.56893], [18.14902, 3.54476], [18.17323, 3.47665], [18.24148, 3.50302], [18.2723, 3.57992], [18.39558, 3.58212], [18.49245, 3.63924], [18.58711, 3.49423], [18.62755, 3.47564], [20.60184, 4.42394], [20.90383, 4.44877], [21.08793, 4.39603], [21.11214, 4.33895], [21.21341, 4.29285], [21.25744, 4.33676], [21.55904, 4.25553], [21.6405, 4.317], [22.10721, 4.20723], [22.27682, 4.11347], [22.45504, 4.13039], [22.5431, 4.22041], [22.60915, 4.48821], [22.6928, 4.47285], [22.78526, 4.71423], [22.84691, 4.69887], [22.89094, 4.79321], [22.94817, 4.82392], [23.38847, 4.60013], [24.46719, 5.0915], [24.71816, 4.90509], [25.31256, 5.03668], [25.34558, 5.29101], [25.53271, 5.37431], [25.86073, 5.19455], [26.13371, 5.25594], [26.48595, 5.04984], [26.74572, 5.10685], [26.85579, 5.03887], [26.93064, 5.13535], [27.09575, 5.22305], [27.44012, 5.07349], [27.26886, 5.25876], [27.23017, 5.37167], [27.28621, 5.56382], [27.22705, 5.62889], [27.22705, 5.71254], [26.51721, 6.09655], [26.58259, 6.1987], [26.32729, 6.36272], [26.38022, 6.63493], [25.90076, 7.09549], [25.37461, 7.33024], [25.35281, 7.42595], [25.20337, 7.50312], [25.20649, 7.61115], [25.29214, 7.66675], [25.25319, 7.8487], [24.98855, 7.96588], [24.85156, 8.16933], [24.35965, 8.26177], [24.13238, 8.36959], [24.25691, 8.69288], [23.51905, 8.71749], [23.59065, 8.99743], [23.44744, 8.99128], [23.4848, 9.16959], [23.56263, 9.19418], [23.64358, 9.28637], [23.64981, 9.44303], [23.62179, 9.53823], [23.69155, 9.67566], [23.67164, 9.86923], [23.3128, 10.45214], [23.02221, 10.69235], [22.87758, 10.91915]]]]
24263 nameEn: "Republic of the Congo",
24264 groups: ["017", "202", "002", "UN"],
24265 callingCodes: ["242"]
24268 type: "MultiPolygon",
24269 coordinates: [[[[18.62755, 3.47564], [18.58711, 3.49423], [18.49245, 3.63924], [18.39558, 3.58212], [18.2723, 3.57992], [18.24148, 3.50302], [18.17323, 3.47665], [18.14902, 3.54476], [18.05656, 3.56893], [17.85842, 3.53378], [17.83421, 3.61068], [17.60966, 3.63705], [17.46876, 3.70515], [17.35649, 3.63045], [17.01746, 3.55136], [16.68283, 3.54257], [16.57598, 3.47999], [16.46701, 2.92512], [16.50126, 2.84739], [16.19357, 2.21537], [16.15568, 2.18955], [16.08563, 2.19733], [16.05294, 1.9811], [16.14634, 1.70259], [16.02647, 1.65591], [16.02959, 1.76483], [15.48942, 1.98265], [15.34776, 1.91264], [15.22634, 2.03243], [15.00996, 1.98887], [14.61145, 2.17866], [13.29457, 2.16106], [13.13461, 1.57238], [13.25447, 1.32339], [13.15519, 1.23368], [13.89582, 1.4261], [14.25186, 1.39842], [14.48179, 0.9152], [14.26066, 0.57255], [14.10909, 0.58563], [13.88648, 0.26652], [13.90632, -0.2287], [14.06862, -0.20826], [14.2165, -0.38261], [14.41887, -0.44799], [14.52569, -0.57818], [14.41838, -1.89412], [14.25932, -1.97624], [14.23518, -2.15671], [14.16202, -2.23916], [14.23829, -2.33715], [14.10442, -2.49268], [13.85846, -2.46935], [13.92073, -2.35581], [13.75884, -2.09293], [13.47977, -2.43224], [13.02759, -2.33098], [12.82172, -1.91091], [12.61312, -1.8129], [12.44656, -1.92025], [12.47925, -2.32626], [12.04895, -2.41704], [11.96866, -2.33559], [11.74605, -2.39936], [11.57637, -2.33379], [11.64487, -2.61865], [11.5359, -2.85654], [11.64798, -2.81146], [11.80365, -3.00424], [11.70558, -3.0773], [11.70227, -3.17465], [11.96554, -3.30267], [11.8318, -3.5812], [11.92719, -3.62768], [11.87083, -3.71571], [11.68608, -3.68942], [11.57949, -3.52798], [11.48764, -3.51089], [11.22301, -3.69888], [11.12647, -3.94169], [10.75913, -4.39519], [11.50888, -5.33417], [12.00924, -5.02627], [12.16068, -4.90089], [12.20901, -4.75642], [12.25587, -4.79437], [12.32324, -4.78415], [12.40964, -4.60609], [12.64835, -4.55937], [12.76844, -4.38709], [12.87096, -4.40315], [12.91489, -4.47907], [13.09648, -4.63739], [13.11182, -4.5942], [13.41764, -4.89897], [13.50305, -4.77818], [13.70417, -4.72601], [13.71794, -4.44864], [13.81162, -4.41842], [13.9108, -4.50906], [14.40672, -4.28381], [14.3957, -4.36623], [14.47284, -4.42941], [14.37366, -4.56125], [14.41499, -4.8825], [14.5059, -4.84956], [14.67948, -4.92093], [14.83101, -4.80838], [15.1978, -4.32388], [15.25411, -4.31121], [15.32693, -4.27282], [15.41785, -4.28381], [15.48121, -4.22062], [15.53081, -4.042], [15.89448, -3.9513], [16.21407, -3.2969], [16.1755, -3.25014], [16.22785, -2.59528], [16.16173, -2.16586], [16.50336, -1.8795], [16.70724, -1.45815], [16.97999, -1.12762], [17.32438, -0.99265], [17.72112, -0.52707], [17.66051, -0.26535], [17.81204, 0.23884], [17.93877, 0.32424], [17.95255, 0.48128], [17.86989, 0.58873], [17.85887, 1.04327], [18.08034, 1.58553], [18.10683, 2.26876], [18.63857, 3.19342], [18.62755, 3.47564]]]]
24278 nameEn: "Switzerland",
24279 groups: ["155", "150", "UN"],
24280 callingCodes: ["41"]
24283 type: "MultiPolygon",
24284 coordinates: [[[[8.72809, 47.69282], [8.72617, 47.69651], [8.73671, 47.7169], [8.70543, 47.73121], [8.74251, 47.75168], [8.71778, 47.76571], [8.68985, 47.75686], [8.68022, 47.78599], [8.65292, 47.80066], [8.64425, 47.76398], [8.62408, 47.7626], [8.61657, 47.79998], [8.56415, 47.80633], [8.56814, 47.78001], [8.48868, 47.77215], [8.45771, 47.7493], [8.44807, 47.72426], [8.40569, 47.69855], [8.4211, 47.68407], [8.40473, 47.67499], [8.41346, 47.66676], [8.42264, 47.66667], [8.44711, 47.65379], [8.4667, 47.65747], [8.46605, 47.64103], [8.49656, 47.64709], [8.5322, 47.64687], [8.52801, 47.66059], [8.56141, 47.67088], [8.57683, 47.66158], [8.6052, 47.67258], [8.61113, 47.66332], [8.62884, 47.65098], [8.62049, 47.63757], [8.60412, 47.63735], [8.61471, 47.64514], [8.60701, 47.65271], [8.59545, 47.64298], [8.60348, 47.61204], [8.57586, 47.59537], [8.55756, 47.62394], [8.51686, 47.63476], [8.50747, 47.61897], [8.45578, 47.60121], [8.46637, 47.58389], [8.48949, 47.588], [8.49431, 47.58107], [8.43235, 47.56617], [8.39477, 47.57826], [8.38273, 47.56608], [8.32735, 47.57133], [8.30277, 47.58607], [8.29524, 47.5919], [8.29722, 47.60603], [8.2824, 47.61225], [8.26313, 47.6103], [8.25863, 47.61571], [8.23809, 47.61204], [8.22577, 47.60385], [8.22011, 47.6181], [8.20617, 47.62141], [8.19378, 47.61636], [8.1652, 47.5945], [8.14947, 47.59558], [8.13823, 47.59147], [8.13662, 47.58432], [8.11543, 47.5841], [8.10395, 47.57918], [8.10002, 47.56504], [8.08557, 47.55768], [8.06663, 47.56374], [8.04383, 47.55443], [8.02136, 47.55096], [8.00113, 47.55616], [7.97581, 47.55493], [7.95682, 47.55789], [7.94494, 47.54511], [7.91251, 47.55031], [7.90673, 47.57674], [7.88664, 47.58854], [7.84412, 47.5841], [7.81901, 47.58798], [7.79486, 47.55691], [7.75261, 47.54599], [7.71961, 47.54219], [7.69642, 47.53297], [7.68101, 47.53232], [7.6656, 47.53752], [7.66174, 47.54554], [7.65083, 47.54662], [7.63338, 47.56256], [7.67655, 47.56435], [7.68904, 47.57133], [7.67115, 47.5871], [7.68486, 47.59601], [7.69385, 47.60099], [7.68229, 47.59905], [7.67395, 47.59212], [7.64599, 47.59695], [7.64213, 47.5944], [7.64309, 47.59151], [7.61929, 47.57683], [7.60459, 47.57869], [7.60523, 47.58519], [7.58945, 47.59017], [7.58386, 47.57536], [7.56684, 47.57785], [7.56548, 47.57617], [7.55689, 47.57232], [7.55652, 47.56779], [7.53634, 47.55553], [7.52831, 47.55347], [7.51723, 47.54578], [7.50873, 47.54546], [7.49691, 47.53821], [7.50588, 47.52856], [7.51904, 47.53515], [7.53199, 47.5284], [7.5229, 47.51644], [7.49804, 47.51798], [7.51076, 47.49651], [7.47534, 47.47932], [7.43356, 47.49712], [7.42923, 47.48628], [7.4583, 47.47216], [7.4462, 47.46264], [7.43088, 47.45846], [7.40308, 47.43638], [7.35603, 47.43432], [7.33526, 47.44186], [7.24669, 47.4205], [7.17026, 47.44312], [7.19583, 47.49455], [7.16249, 47.49025], [7.12781, 47.50371], [7.07425, 47.48863], [7.0231, 47.50522], [6.98425, 47.49432], [7.0024, 47.45264], [6.93953, 47.43388], [6.93744, 47.40714], [6.88542, 47.37262], [6.87959, 47.35335], [7.03125, 47.36996], [7.0564, 47.35134], [7.05305, 47.33304], [6.94316, 47.28747], [6.95108, 47.26428], [6.9508, 47.24338], [6.8489, 47.15933], [6.76788, 47.1208], [6.68823, 47.06616], [6.71531, 47.0494], [6.43341, 46.92703], [6.46456, 46.88865], [6.43216, 46.80336], [6.45209, 46.77502], [6.38351, 46.73171], [6.27135, 46.68251], [6.11084, 46.57649], [6.1567, 46.54402], [6.07269, 46.46244], [6.08427, 46.44305], [6.06407, 46.41676], [6.09926, 46.40768], [6.15016, 46.3778], [6.15985, 46.37721], [6.16987, 46.36759], [6.15738, 46.3491], [6.13876, 46.33844], [6.1198, 46.31157], [6.11697, 46.29547], [6.1013, 46.28512], [6.11926, 46.2634], [6.12446, 46.25059], [6.10071, 46.23772], [6.08563, 46.24651], [6.07072, 46.24085], [6.0633, 46.24583], [6.05029, 46.23518], [6.04602, 46.23127], [6.03342, 46.2383], [6.02461, 46.23313], [5.97542, 46.21525], [5.96515, 46.19638], [5.99573, 46.18587], [5.98846, 46.17046], [5.98188, 46.17392], [5.97508, 46.15863], [5.9641, 46.14412], [5.95781, 46.12925], [5.97893, 46.13303], [5.9871, 46.14499], [6.01791, 46.14228], [6.03614, 46.13712], [6.04564, 46.14031], [6.05203, 46.15191], [6.07491, 46.14879], [6.09199, 46.15191], [6.09926, 46.14373], [6.13397, 46.1406], [6.15305, 46.15194], [6.18116, 46.16187], [6.18871, 46.16644], [6.18707, 46.17999], [6.19552, 46.18401], [6.19807, 46.18369], [6.20539, 46.19163], [6.21114, 46.1927], [6.21273, 46.19409], [6.21603, 46.19507], [6.21844, 46.19837], [6.22222, 46.19888], [6.22175, 46.20045], [6.23544, 46.20714], [6.23913, 46.20511], [6.24821, 46.20531], [6.26007, 46.21165], [6.27694, 46.21566], [6.29663, 46.22688], [6.31041, 46.24417], [6.29474, 46.26221], [6.26749, 46.24745], [6.24952, 46.26255], [6.23775, 46.27822], [6.25137, 46.29014], [6.24826, 46.30175], [6.21981, 46.31304], [6.25432, 46.3632], [6.53358, 46.45431], [6.82312, 46.42661], [6.8024, 46.39171], [6.77152, 46.34784], [6.86052, 46.28512], [6.78968, 46.14058], [6.89321, 46.12548], [6.87868, 46.03855], [6.93862, 46.06502], [7.00946, 45.9944], [7.04151, 45.92435], [7.10685, 45.85653], [7.56343, 45.97421], [7.85949, 45.91485], [7.9049, 45.99945], [7.98881, 45.99867], [8.02906, 46.10331], [8.11383, 46.11577], [8.16866, 46.17817], [8.08814, 46.26692], [8.31162, 46.38044], [8.30648, 46.41587], [8.42464, 46.46367], [8.46317, 46.43712], [8.45032, 46.26869], [8.62242, 46.12112], [8.75697, 46.10395], [8.80778, 46.10085], [8.85617, 46.0748], [8.79414, 46.00913], [8.78585, 45.98973], [8.79362, 45.99207], [8.8319, 45.9879], [8.85121, 45.97239], [8.86688, 45.96135], [8.88904, 45.95465], [8.93649, 45.86775], [8.94372, 45.86587], [8.93504, 45.86245], [8.91129, 45.8388], [8.94737, 45.84285], [8.9621, 45.83707], [8.99663, 45.83466], [9.00324, 45.82055], [9.0298, 45.82127], [9.03279, 45.82865], [9.03793, 45.83548], [9.03505, 45.83976], [9.04059, 45.8464], [9.04546, 45.84968], [9.06642, 45.8761], [9.09065, 45.89906], [8.99257, 45.9698], [9.01618, 46.04928], [9.24503, 46.23616], [9.29226, 46.32717], [9.25502, 46.43743], [9.28136, 46.49685], [9.36128, 46.5081], [9.40487, 46.46621], [9.45936, 46.50873], [9.46117, 46.37481], [9.57015, 46.2958], [9.71273, 46.29266], [9.73086, 46.35071], [9.95249, 46.38045], [10.07055, 46.21668], [10.14439, 46.22992], [10.17862, 46.25626], [10.10506, 46.3372], [10.165, 46.41051], [10.03715, 46.44479], [10.10307, 46.61003], [10.23674, 46.63484], [10.25309, 46.57432], [10.46136, 46.53164], [10.49375, 46.62049], [10.44686, 46.64162], [10.40475, 46.63671], [10.38659, 46.67847], [10.47197, 46.85698], [10.48376, 46.93891], [10.36933, 47.00212], [10.30031, 46.92093], [10.24128, 46.93147], [10.22675, 46.86942], [10.10715, 46.84296], [9.98058, 46.91434], [9.88266, 46.93343], [9.87935, 47.01337], [9.60717, 47.06091], [9.55721, 47.04762], [9.54041, 47.06495], [9.47548, 47.05257], [9.47139, 47.06402], [9.51362, 47.08505], [9.52089, 47.10019], [9.51044, 47.13727], [9.48774, 47.17402], [9.4891, 47.19346], [9.50318, 47.22153], [9.52406, 47.24959], [9.53116, 47.27029], [9.54773, 47.2809], [9.55857, 47.29919], [9.58513, 47.31334], [9.59978, 47.34671], [9.62476, 47.36639], [9.65427, 47.36824], [9.66243, 47.37136], [9.6711, 47.37824], [9.67445, 47.38429], [9.67334, 47.39191], [9.6629, 47.39591], [9.65136, 47.40504], [9.65043, 47.41937], [9.6446, 47.43233], [9.64483, 47.43842], [9.65863, 47.44847], [9.65728, 47.45383], [9.6423, 47.45599], [9.62475, 47.45685], [9.62158, 47.45858], [9.60841, 47.47178], [9.60484, 47.46358], [9.60205, 47.46165], [9.59482, 47.46305], [9.58208, 47.48344], [9.56312, 47.49495], [9.55125, 47.53629], [9.25619, 47.65939], [9.18203, 47.65598], [9.17593, 47.65399], [9.1755, 47.65584], [9.1705, 47.65513], [9.15181, 47.66904], [9.13845, 47.66389], [9.09891, 47.67801], [9.02093, 47.6868], [8.94093, 47.65596], [8.89946, 47.64769], [8.87625, 47.65441], [8.87383, 47.67045], [8.85065, 47.68209], [8.86989, 47.70504], [8.82002, 47.71458], [8.80663, 47.73821], [8.77309, 47.72059], [8.76965, 47.7075], [8.79966, 47.70222], [8.79511, 47.67462], [8.75856, 47.68969], [8.72809, 47.69282]], [[8.95861, 45.96485], [8.96668, 45.98436], [8.97741, 45.98317], [8.97604, 45.96151], [8.95861, 45.96485]], [[8.70847, 47.68904], [8.68985, 47.69552], [8.66837, 47.68437], [8.65769, 47.68928], [8.67508, 47.6979], [8.66416, 47.71367], [8.70237, 47.71453], [8.71773, 47.69088], [8.70847, 47.68904]]]]
24293 nameEn: "C\xF4te d'Ivoire",
24294 groups: ["011", "202", "002", "UN"],
24295 callingCodes: ["225"]
24298 type: "MultiPolygon",
24299 coordinates: [[[[-7.52774, 3.7105], [-3.34019, 4.17519], [-3.10675, 5.08515], [-3.11073, 5.12675], [-3.063, 5.13665], [-2.96554, 5.10397], [-2.95261, 5.12477], [-2.75502, 5.10657], [-2.73074, 5.1364], [-2.77625, 5.34621], [-2.72737, 5.34789], [-2.76614, 5.60963], [-2.85378, 5.65156], [-2.93132, 5.62137], [-2.96671, 5.6415], [-2.95323, 5.71865], [-3.01896, 5.71697], [-3.25999, 6.62521], [-3.21954, 6.74407], [-3.23327, 6.81744], [-2.95438, 7.23737], [-2.97822, 7.27165], [-2.92339, 7.60847], [-2.79467, 7.86002], [-2.78395, 7.94974], [-2.74819, 7.92613], [-2.67787, 8.02055], [-2.61232, 8.02645], [-2.62901, 8.11495], [-2.49037, 8.20872], [-2.58243, 8.7789], [-2.66357, 9.01771], [-2.77799, 9.04949], [-2.69814, 9.22717], [-2.68802, 9.49343], [-2.76494, 9.40778], [-2.93012, 9.57403], [-3.00765, 9.74019], [-3.16609, 9.85147], [-3.19306, 9.93781], [-3.27228, 9.84981], [-3.31779, 9.91125], [-3.69703, 9.94279], [-4.25999, 9.76012], [-4.31392, 9.60062], [-4.6426, 9.70696], [-4.96621, 9.89132], [-4.96453, 9.99923], [-5.12465, 10.29788], [-5.39602, 10.2929], [-5.51058, 10.43177], [-5.65135, 10.46767], [-5.78124, 10.43952], [-5.99478, 10.19694], [-6.18851, 10.24244], [-6.1731, 10.46983], [-6.24795, 10.74248], [-6.325, 10.68624], [-6.40646, 10.69922], [-6.42847, 10.5694], [-6.52974, 10.59104], [-6.63541, 10.66893], [-6.68164, 10.35074], [-6.93921, 10.35291], [-7.01186, 10.25111], [-6.97444, 10.21644], [-7.00966, 10.15794], [-7.0603, 10.14711], [-7.13331, 10.24877], [-7.3707, 10.24677], [-7.44555, 10.44602], [-7.52261, 10.4655], [-7.54462, 10.40921], [-7.63048, 10.46334], [-7.92107, 10.15577], [-7.97971, 10.17117], [-8.01225, 10.1021], [-8.11921, 10.04577], [-8.15652, 9.94288], [-8.09434, 9.86936], [-8.14657, 9.55062], [-8.03463, 9.39604], [-7.85056, 9.41812], [-7.90777, 9.20456], [-7.73862, 9.08422], [-7.92518, 8.99332], [-7.95503, 8.81146], [-7.69882, 8.66148], [-7.65653, 8.36873], [-7.92518, 8.50652], [-8.22991, 8.48438], [-8.2411, 8.24196], [-8.062, 8.16071], [-7.98675, 8.20134], [-7.99919, 8.11023], [-7.94695, 8.00925], [-8.06449, 8.04989], [-8.13414, 7.87991], [-8.09931, 7.78626], [-8.21374, 7.54466], [-8.4003, 7.6285], [-8.47114, 7.55676], [-8.41935, 7.51203], [-8.37458, 7.25794], [-8.29249, 7.1691], [-8.31736, 6.82837], [-8.59456, 6.50612], [-8.48652, 6.43797], [-8.45666, 6.49977], [-8.38453, 6.35887], [-8.3298, 6.36381], [-8.17557, 6.28222], [-8.00642, 6.31684], [-7.90692, 6.27728], [-7.83478, 6.20309], [-7.8497, 6.08932], [-7.79747, 6.07696], [-7.78254, 5.99037], [-7.70294, 5.90625], [-7.67309, 5.94337], [-7.48155, 5.80974], [-7.46165, 5.84934], [-7.43677, 5.84687], [-7.43926, 5.74787], [-7.37209, 5.61173], [-7.43428, 5.42355], [-7.36463, 5.32944], [-7.46165, 5.26256], [-7.48901, 5.14118], [-7.55369, 5.08667], [-7.53876, 4.94294], [-7.59349, 4.8909], [-7.53259, 4.35145], [-7.52774, 3.7105]]]]
24307 wikidata: "Q26988",
24308 nameEn: "Cook Islands",
24310 groups: ["061", "009", "UN"],
24312 callingCodes: ["682"]
24315 type: "MultiPolygon",
24316 coordinates: [[[[-168.15106, -10.26955], [-156.45576, -31.75456], [-156.48634, -15.52824], [-156.50903, -7.4975], [-168.15106, -10.26955]]]]
24326 groups: ["005", "419", "019", "UN"],
24327 callingCodes: ["56"]
24330 type: "MultiPolygon",
24331 coordinates: [[[[-68.60702, -52.65781], [-68.41683, -52.33516], [-69.97824, -52.00845], [-71.99889, -51.98018], [-72.33873, -51.59954], [-72.31343, -50.58411], [-73.15765, -50.78337], [-73.55259, -49.92488], [-73.45156, -49.79461], [-73.09655, -49.14342], [-72.56894, -48.81116], [-72.54042, -48.52392], [-72.27662, -48.28727], [-72.50478, -47.80586], [-71.94152, -47.13595], [-71.68577, -46.55385], [-71.75614, -45.61611], [-71.35687, -45.22075], [-72.06985, -44.81756], [-71.26418, -44.75684], [-71.16436, -44.46244], [-71.81318, -44.38097], [-71.64206, -43.64774], [-72.14828, -42.85321], [-72.15541, -42.15941], [-71.74901, -42.11711], [-71.92726, -40.72714], [-71.37826, -38.91474], [-70.89532, -38.6923], [-71.24279, -37.20264], [-70.95047, -36.4321], [-70.38008, -36.02375], [-70.49416, -35.24145], [-69.87386, -34.13344], [-69.88099, -33.34489], [-70.55832, -31.51559], [-70.14479, -30.36595], [-69.8596, -30.26131], [-69.99507, -29.28351], [-69.80969, -29.07185], [-69.66709, -28.44055], [-69.22504, -27.95042], [-68.77586, -27.16029], [-68.43363, -27.08414], [-68.27677, -26.90626], [-68.59048, -26.49861], [-68.56909, -26.28146], [-68.38372, -26.15353], [-68.57622, -25.32505], [-68.38372, -25.08636], [-68.56909, -24.69831], [-68.24825, -24.42596], [-67.33563, -24.04237], [-66.99632, -22.99839], [-67.18382, -22.81525], [-67.54284, -22.89771], [-67.85114, -22.87076], [-68.18816, -21.28614], [-68.40403, -20.94562], [-68.53957, -20.91542], [-68.55383, -20.7355], [-68.44023, -20.62701], [-68.7276, -20.46178], [-68.74273, -20.08817], [-68.57132, -20.03134], [-68.54611, -19.84651], [-68.66761, -19.72118], [-68.41218, -19.40499], [-68.61989, -19.27584], [-68.80602, -19.08355], [-68.87082, -19.06003], [-68.94987, -18.93302], [-69.07432, -18.28259], [-69.14807, -18.16893], [-69.07496, -18.03715], [-69.28671, -17.94844], [-69.34126, -17.72753], [-69.46623, -17.60518], [-69.46897, -17.4988], [-69.66483, -17.65083], [-69.79087, -17.65563], [-69.82868, -17.72048], [-69.75305, -17.94605], [-69.81607, -18.12582], [-69.96732, -18.25992], [-70.16394, -18.31737], [-70.31267, -18.31258], [-70.378, -18.3495], [-70.59118, -18.35072], [-113.52687, -26.52828], [-68.11646, -58.14883], [-66.07313, -55.19618], [-67.11046, -54.94199], [-67.46182, -54.92205], [-68.01394, -54.8753], [-68.60733, -54.9125], [-68.60702, -52.65781]]]]
24340 nameEn: "Cameroon",
24341 groups: ["017", "202", "002", "UN"],
24342 callingCodes: ["237"]
24345 type: "MultiPolygon",
24346 coordinates: [[[[14.83314, 12.62963], [14.55058, 12.78256], [14.56101, 12.91036], [14.46881, 13.08259], [14.08251, 13.0797], [14.20204, 12.53405], [14.17523, 12.41916], [14.22215, 12.36533], [14.4843, 12.35223], [14.6474, 12.17466], [14.61612, 11.7798], [14.55207, 11.72001], [14.64591, 11.66166], [14.6124, 11.51283], [14.17821, 11.23831], [13.97489, 11.30258], [13.78945, 11.00154], [13.7403, 11.00593], [13.70753, 10.94451], [13.73434, 10.9255], [13.54964, 10.61236], [13.5705, 10.53183], [13.43644, 10.13326], [13.34111, 10.12299], [13.25025, 10.03647], [13.25323, 10.00127], [13.286, 9.9822], [13.27409, 9.93232], [13.24132, 9.91031], [13.25025, 9.86042], [13.29941, 9.8296], [13.25472, 9.76795], [13.22642, 9.57266], [13.02385, 9.49334], [12.85628, 9.36698], [12.91958, 9.33905], [12.90022, 9.11411], [12.81085, 8.91992], [12.79, 8.75361], [12.71701, 8.7595], [12.68722, 8.65938], [12.44146, 8.6152], [12.4489, 8.52536], [12.26123, 8.43696], [12.24782, 8.17904], [12.19271, 8.10826], [12.20909, 7.97553], [11.99908, 7.67302], [12.01844, 7.52981], [11.93205, 7.47812], [11.84864, 7.26098], [11.87396, 7.09398], [11.63117, 6.9905], [11.55818, 6.86186], [11.57755, 6.74059], [11.51499, 6.60892], [11.42264, 6.5882], [11.42041, 6.53789], [11.09495, 6.51717], [11.09644, 6.68437], [10.94302, 6.69325], [10.8179, 6.83377], [10.83727, 6.9358], [10.60789, 7.06885], [10.59746, 7.14719], [10.57214, 7.16345], [10.53639, 6.93432], [10.21466, 6.88996], [10.15135, 7.03781], [9.86314, 6.77756], [9.77824, 6.79088], [9.70674, 6.51717], [9.51757, 6.43874], [8.84209, 5.82562], [8.88156, 5.78857], [8.83687, 5.68483], [8.92029, 5.58403], [8.78027, 5.1243], [8.60302, 4.87353], [8.34397, 4.30689], [9.22018, 3.72052], [9.81162, 2.33797], [9.82123, 2.35097], [9.83754, 2.32428], [9.83238, 2.29079], [9.84716, 2.24676], [9.89012, 2.20457], [9.90749, 2.20049], [9.991, 2.16561], [11.3561, 2.17217], [11.37116, 2.29975], [13.28534, 2.25716], [13.29457, 2.16106], [14.61145, 2.17866], [15.00996, 1.98887], [15.22634, 2.03243], [15.34776, 1.91264], [15.48942, 1.98265], [16.02959, 1.76483], [16.02647, 1.65591], [16.14634, 1.70259], [16.05294, 1.9811], [16.08563, 2.19733], [16.15568, 2.18955], [16.19357, 2.21537], [16.08252, 2.45708], [16.05449, 3.02306], [15.77725, 3.26835], [15.73522, 3.24348], [15.07686, 4.01805], [15.17482, 4.05131], [15.10644, 4.1362], [15.08609, 4.30282], [15.00825, 4.41458], [14.73383, 4.6135], [14.65489, 5.21343], [14.57083, 5.23979], [14.52724, 5.28319], [14.62531, 5.51411], [14.58951, 5.59777], [14.62375, 5.70466], [14.60974, 5.91838], [14.49455, 5.91683], [14.42917, 6.00508], [14.43073, 6.08867], [14.56149, 6.18928], [14.74206, 6.26356], [14.80122, 6.34866], [14.79966, 6.39043], [14.96311, 6.75693], [15.04717, 6.77085], [15.23397, 7.25135], [15.49743, 7.52179], [15.56964, 7.58936], [15.59272, 7.7696], [15.50743, 7.79302], [15.20426, 8.50892], [15.09484, 8.65982], [14.83566, 8.80557], [14.35707, 9.19611], [14.37094, 9.2954], [13.97544, 9.6365], [14.01793, 9.73169], [14.1317, 9.82413], [14.20411, 10.00055], [14.4673, 10.00264], [14.80082, 9.93818], [14.95722, 9.97926], [15.05999, 9.94845], [15.14043, 9.99246], [15.24618, 9.99246], [15.41408, 9.92876], [15.68761, 9.99344], [15.50535, 10.1098], [15.30874, 10.31063], [15.23724, 10.47764], [15.14936, 10.53915], [15.15532, 10.62846], [15.06737, 10.80921], [15.09127, 10.87431], [15.04957, 11.02347], [15.10021, 11.04101], [15.0585, 11.40481], [15.13149, 11.5537], [15.06595, 11.71126], [15.11579, 11.79313], [15.04808, 11.8731], [15.05786, 12.0608], [15.0349, 12.10698], [15.00146, 12.1223], [14.96952, 12.0925], [14.89019, 12.16593], [14.90827, 12.3269], [14.83314, 12.62963]]]]
24355 nameEn: "People's Republic of China"
24365 nameEn: "Colombia",
24366 groups: ["005", "419", "019", "UN"],
24367 callingCodes: ["57"]
24370 type: "MultiPolygon",
24371 coordinates: [[[[-71.19849, 12.65801], [-81.58685, 18.0025], [-82.06974, 14.49418], [-82.56142, 11.91792], [-78.79327, 9.93766], [-77.58292, 9.22278], [-77.32389, 8.81247], [-77.45064, 8.49991], [-77.17257, 7.97422], [-77.57185, 7.51147], [-77.72514, 7.72348], [-77.72157, 7.47612], [-77.81426, 7.48319], [-77.89178, 7.22681], [-78.06168, 7.07793], [-82.12561, 4.00341], [-78.87137, 1.47457], [-78.42749, 1.15389], [-77.85677, 0.80197], [-77.7148, 0.85003], [-77.68613, 0.83029], [-77.66416, 0.81604], [-77.67815, 0.73863], [-77.49984, 0.64476], [-77.52001, 0.40782], [-76.89177, 0.24736], [-76.4094, 0.24015], [-76.41215, 0.38228], [-76.23441, 0.42294], [-75.82927, 0.09578], [-75.25764, -0.11943], [-75.18513, -0.0308], [-74.42701, -0.50218], [-74.26675, -0.97229], [-73.65312, -1.26222], [-72.92587, -2.44514], [-71.75223, -2.15058], [-70.94377, -2.23142], [-70.04609, -2.73906], [-70.71396, -3.7921], [-70.52393, -3.87553], [-70.3374, -3.79505], [-69.94708, -4.2431], [-69.43395, -1.42219], [-69.4215, -1.01853], [-69.59796, -0.75136], [-69.603, -0.51947], [-70.03658, -0.19681], [-70.04162, 0.55437], [-69.47696, 0.71065], [-69.20976, 0.57958], [-69.14422, 0.84172], [-69.26017, 1.06856], [-69.82987, 1.07864], [-69.83491, 1.69353], [-69.53746, 1.76408], [-69.38621, 1.70865], [-68.18128, 1.72881], [-68.26699, 1.83463], [-68.18632, 2.00091], [-67.9292, 1.82455], [-67.40488, 2.22258], [-67.299, 1.87494], [-67.15784, 1.80439], [-67.08222, 1.17441], [-66.85795, 1.22998], [-67.21967, 2.35778], [-67.65696, 2.81691], [-67.85862, 2.79173], [-67.85862, 2.86727], [-67.30945, 3.38393], [-67.50067, 3.75812], [-67.62671, 3.74303], [-67.85358, 4.53249], [-67.83341, 5.31104], [-67.59141, 5.5369], [-67.63914, 5.64963], [-67.58558, 5.84537], [-67.43513, 5.98835], [-67.4625, 6.20625], [-67.60654, 6.2891], [-69.41843, 6.1072], [-70.10716, 6.96516], [-70.7596, 7.09799], [-71.03941, 6.98163], [-71.37234, 7.01588], [-71.42212, 7.03854], [-71.44118, 7.02116], [-71.82441, 7.04314], [-72.04895, 7.03837], [-72.19437, 7.37034], [-72.43132, 7.40034], [-72.47415, 7.48928], [-72.45321, 7.57232], [-72.47827, 7.65604], [-72.46763, 7.79518], [-72.44454, 7.86031], [-72.46183, 7.90682], [-72.45806, 7.91141], [-72.47042, 7.92306], [-72.48183, 7.92909], [-72.48801, 7.94329], [-72.47213, 7.96106], [-72.39137, 8.03534], [-72.35163, 8.01163], [-72.36987, 8.19976], [-72.4042, 8.36513], [-72.65474, 8.61428], [-72.77415, 9.10165], [-72.94052, 9.10663], [-73.02119, 9.27584], [-73.36905, 9.16636], [-72.98085, 9.85253], [-72.88002, 10.44309], [-72.4767, 11.1117], [-72.24983, 11.14138], [-71.9675, 11.65536], [-71.3275, 11.85], [-70.92579, 11.96275], [-71.19849, 12.65801]]]]
24378 wikidata: "Q161258",
24379 nameEn: "Clipperton Island",
24381 groups: ["013", "003", "019", "UN"],
24382 isoStatus: "excRes"
24385 type: "MultiPolygon",
24386 coordinates: [[[[-110.36279, 9.79626], [-108.755, 9.84085], [-109.04145, 11.13245], [-110.36279, 9.79626]]]]
24395 nameEn: "Costa Rica",
24396 groups: ["013", "003", "419", "019", "UN"],
24397 callingCodes: ["506"]
24400 type: "MultiPolygon",
24401 coordinates: [[[[-83.68276, 11.01562], [-83.66597, 10.79916], [-83.90838, 10.71161], [-84.68197, 11.07568], [-84.92439, 10.9497], [-85.60529, 11.22607], [-85.71223, 11.06868], [-86.14524, 11.09059], [-87.41779, 5.02401], [-82.94503, 7.93865], [-82.89978, 8.04083], [-82.89137, 8.05755], [-82.88641, 8.10219], [-82.9388, 8.26634], [-83.05209, 8.33394], [-82.93056, 8.43465], [-82.8679, 8.44042], [-82.8382, 8.48117], [-82.83322, 8.52464], [-82.83975, 8.54755], [-82.82739, 8.60153], [-82.8794, 8.6981], [-82.92068, 8.74832], [-82.91377, 8.774], [-82.88253, 8.83331], [-82.72126, 8.97125], [-82.93516, 9.07687], [-82.93516, 9.46741], [-82.84871, 9.4973], [-82.87919, 9.62645], [-82.77206, 9.59573], [-82.66667, 9.49746], [-82.61345, 9.49881], [-82.56507, 9.57279], [-82.51044, 9.65379], [-83.54024, 10.96805], [-83.68276, 11.01562]]]]
24411 groups: ["029", "003", "419", "019", "UN"],
24412 callingCodes: ["53"]
24415 type: "MultiPolygon",
24416 coordinates: [[[[-73.62304, 20.6935], [-82.02215, 24.23074], [-85.77883, 21.92705], [-74.81171, 18.82201], [-73.62304, 20.6935]]]]
24425 nameEn: "Cape Verde",
24426 groups: ["Q105472", "011", "202", "002", "UN"],
24427 callingCodes: ["238"]
24430 type: "MultiPolygon",
24431 coordinates: [[[[-28.81604, 14.57305], [-20.39702, 14.12816], [-23.37101, 19.134], [-28.81604, 14.57305]]]]
24439 wikidata: "Q25279",
24440 nameEn: "Cura\xE7ao",
24441 aliases: ["NL-CW"],
24443 groups: ["Q1451600", "029", "003", "419", "019", "UN"],
24444 callingCodes: ["599"]
24447 type: "MultiPolygon",
24448 coordinates: [[[[-68.90012, 12.62309], [-69.59009, 12.46019], [-68.99639, 11.79035], [-68.33524, 11.78151], [-68.90012, 12.62309]]]]
24456 wikidata: "Q31063",
24457 nameEn: "Christmas Island",
24459 groups: ["053", "009", "UN"],
24461 callingCodes: ["61"]
24464 type: "MultiPolygon",
24465 coordinates: [[[[105.66835, -9.31927], [104.67494, -11.2566], [106.66176, -11.14349], [105.66835, -9.31927]]]]
24474 nameEn: "Republic of Cyprus",
24475 groups: ["Q644636", "EU", "145", "142", "UN"],
24477 callingCodes: ["357"]
24480 type: "MultiPolygon",
24481 coordinates: [[[[32.46489, 35.48584], [30.15137, 34.08517], [32.74412, 34.43926], [32.75515, 34.64985], [32.76136, 34.68318], [32.79433, 34.67883], [32.82717, 34.70622], [32.86014, 34.70585], [32.86167, 34.68734], [32.9068, 34.66102], [32.91398, 34.67343], [32.93043, 34.67091], [32.92807, 34.66736], [32.93449, 34.66241], [32.93693, 34.67027], [32.94379, 34.67111], [32.94683, 34.67907], [32.95539, 34.68471], [32.99135, 34.68061], [32.98668, 34.67268], [32.99014, 34.65518], [32.97736, 34.65277], [32.97079, 34.66112], [32.95325, 34.66462], [32.94796, 34.6587], [32.94976, 34.65204], [32.95471, 34.64528], [32.95323, 34.64075], [32.95891, 34.62919], [32.96718, 34.63446], [32.96968, 34.64046], [33.0138, 34.64424], [33.26744, 34.49942], [33.83531, 34.73974], [33.70575, 34.97947], [33.70639, 34.99303], [33.71514, 35.00294], [33.69731, 35.01754], [33.69938, 35.03123], [33.67678, 35.03866], [33.63765, 35.03869], [33.61215, 35.0527], [33.59658, 35.03635], [33.567, 35.04803], [33.57478, 35.06049], [33.53975, 35.08151], [33.48915, 35.06594], [33.47666, 35.00701], [33.45256, 35.00288], [33.45178, 35.02078], [33.47825, 35.04103], [33.48136, 35.0636], [33.46813, 35.10564], [33.41675, 35.16325], [33.4076, 35.20062], [33.38575, 35.2018], [33.37248, 35.18698], [33.3717, 35.1788], [33.36569, 35.17479], [33.35612, 35.17402], [33.35596, 35.17942], [33.34964, 35.17803], [33.35056, 35.18328], [33.31955, 35.18096], [33.3072, 35.16816], [33.27068, 35.16815], [33.15138, 35.19504], [33.11105, 35.15639], [33.08249, 35.17319], [33.01192, 35.15639], [32.94471, 35.09422], [32.86406, 35.1043], [32.85733, 35.07742], [32.70779, 35.14127], [32.70947, 35.18328], [32.64864, 35.19967], [32.60361, 35.16647], [32.46489, 35.48584]]], [[[33.74144, 35.01053], [33.7492, 35.01319], [33.74983, 35.02274], [33.74265, 35.02329], [33.73781, 35.02181], [33.7343, 35.01178], [33.74144, 35.01053]]], [[[33.77312, 34.9976], [33.75994, 35.00113], [33.75682, 34.99916], [33.76605, 34.99543], [33.76738, 34.99188], [33.7778, 34.98981], [33.77843, 34.988], [33.78149, 34.98854], [33.78318, 34.98699], [33.78571, 34.98951], [33.78917, 34.98854], [33.79191, 34.98914], [33.78516, 34.99582], [33.77553, 34.99518], [33.77312, 34.9976]]]]
24491 groups: ["EU", "151", "150", "UN"],
24492 callingCodes: ["420"]
24495 type: "MultiPolygon",
24496 coordinates: [[[[14.82803, 50.86966], [14.79139, 50.81438], [14.70661, 50.84096], [14.61993, 50.86049], [14.63434, 50.8883], [14.65259, 50.90513], [14.64802, 50.93241], [14.58024, 50.91443], [14.56374, 50.922], [14.59702, 50.96148], [14.59908, 50.98685], [14.58215, 50.99306], [14.56432, 51.01008], [14.53438, 51.00374], [14.53321, 51.01679], [14.49873, 51.02242], [14.50809, 51.0427], [14.49991, 51.04692], [14.49154, 51.04382], [14.49202, 51.02286], [14.45827, 51.03712], [14.41335, 51.02086], [14.30098, 51.05515], [14.25665, 50.98935], [14.28776, 50.97718], [14.32353, 50.98556], [14.32793, 50.97379], [14.30251, 50.96606], [14.31422, 50.95243], [14.39848, 50.93866], [14.38691, 50.89907], [14.30098, 50.88448], [14.27123, 50.89386], [14.24314, 50.88761], [14.22331, 50.86049], [14.02982, 50.80662], [13.98864, 50.8177], [13.89113, 50.78533], [13.89444, 50.74142], [13.82942, 50.7251], [13.76316, 50.73487], [13.70204, 50.71771], [13.65977, 50.73096], [13.52474, 50.70394], [13.53748, 50.67654], [13.5226, 50.64721], [13.49742, 50.63133], [13.46413, 50.60102], [13.42189, 50.61243], [13.37485, 50.64931], [13.37805, 50.627], [13.32264, 50.60317], [13.32594, 50.58009], [13.29454, 50.57904], [13.25158, 50.59268], [13.19043, 50.50237], [13.13424, 50.51709], [13.08301, 50.50132], [13.0312, 50.50944], [13.02038, 50.4734], [13.02147, 50.44763], [12.98433, 50.42016], [12.94058, 50.40944], [12.82465, 50.45738], [12.73476, 50.43237], [12.73044, 50.42268], [12.70731, 50.39948], [12.67261, 50.41949], [12.51356, 50.39694], [12.48747, 50.37278], [12.49214, 50.35228], [12.48256, 50.34784], [12.46643, 50.35527], [12.43722, 50.33774], [12.43371, 50.32506], [12.39924, 50.32302], [12.40158, 50.29521], [12.36594, 50.28289], [12.35425, 50.23993], [12.33263, 50.24367], [12.32445, 50.20442], [12.33847, 50.19432], [12.32596, 50.17146], [12.29232, 50.17524], [12.28063, 50.19544], [12.28755, 50.22429], [12.23943, 50.24594], [12.24791, 50.25525], [12.26953, 50.25189], [12.25119, 50.27079], [12.20823, 50.2729], [12.18013, 50.32146], [12.10907, 50.32041], [12.13716, 50.27396], [12.09287, 50.25032], [12.19335, 50.19997], [12.21484, 50.16399], [12.1917, 50.13434], [12.2073, 50.10315], [12.23709, 50.10213], [12.27433, 50.0771], [12.26111, 50.06331], [12.30798, 50.05719], [12.49908, 49.97305], [12.47264, 49.94222], [12.55197, 49.92094], [12.48256, 49.83575], [12.46603, 49.78882], [12.40489, 49.76321], [12.4462, 49.70233], [12.52553, 49.68415], [12.53544, 49.61888], [12.56188, 49.6146], [12.60155, 49.52887], [12.64782, 49.52565], [12.64121, 49.47628], [12.669, 49.42935], [12.71227, 49.42363], [12.75854, 49.3989], [12.78168, 49.34618], [12.88414, 49.33541], [12.88249, 49.35479], [12.94859, 49.34079], [13.03618, 49.30417], [13.02957, 49.27399], [13.05883, 49.26259], [13.17665, 49.16713], [13.17019, 49.14339], [13.20405, 49.12303], [13.23689, 49.11412], [13.28242, 49.1228], [13.39479, 49.04812], [13.40802, 48.98851], [13.50221, 48.93752], [13.50552, 48.97441], [13.58319, 48.96899], [13.61624, 48.9462], [13.67739, 48.87886], [13.73854, 48.88538], [13.76994, 48.83537], [13.78977, 48.83319], [13.8096, 48.77877], [13.84023, 48.76988], [14.06151, 48.66873], [14.01482, 48.63788], [14.09104, 48.5943], [14.20691, 48.5898], [14.33909, 48.55852], [14.43076, 48.58855], [14.4587, 48.64695], [14.56139, 48.60429], [14.60808, 48.62881], [14.66762, 48.58215], [14.71794, 48.59794], [14.72756, 48.69502], [14.80584, 48.73489], [14.80821, 48.77711], [14.81545, 48.7874], [14.94773, 48.76268], [14.95641, 48.75915], [14.9758, 48.76857], [14.98112, 48.77524], [14.9782, 48.7766], [14.98032, 48.77959], [14.95072, 48.79101], [14.98917, 48.90082], [14.97612, 48.96983], [14.99878, 49.01444], [15.15534, 48.99056], [15.16358, 48.94278], [15.26177, 48.95766], [15.28305, 48.98831], [15.34823, 48.98444], [15.48027, 48.94481], [15.51357, 48.91549], [15.61622, 48.89541], [15.6921, 48.85973], [15.75341, 48.8516], [15.78087, 48.87644], [15.84404, 48.86921], [16.06034, 48.75436], [16.37345, 48.729], [16.40915, 48.74576], [16.46134, 48.80865], [16.67008, 48.77699], [16.68518, 48.7281], [16.71883, 48.73806], [16.79779, 48.70998], [16.90354, 48.71541], [16.93955, 48.60371], [17.00215, 48.70887], [17.11202, 48.82925], [17.19355, 48.87602], [17.29054, 48.85546], [17.3853, 48.80936], [17.45671, 48.85004], [17.5295, 48.81117], [17.7094, 48.86721], [17.73126, 48.87885], [17.77944, 48.92318], [17.87831, 48.92679], [17.91814, 49.01784], [18.06885, 49.03157], [18.1104, 49.08624], [18.15022, 49.24518], [18.18456, 49.28909], [18.36446, 49.3267], [18.4139, 49.36517], [18.4084, 49.40003], [18.44686, 49.39467], [18.54848, 49.47059], [18.53063, 49.49022], [18.57183, 49.51162], [18.6144, 49.49824], [18.67757, 49.50895], [18.74761, 49.492], [18.84521, 49.51672], [18.84786, 49.5446], [18.80479, 49.6815], [18.72838, 49.68163], [18.69817, 49.70473], [18.62676, 49.71983], [18.62943, 49.74603], [18.62645, 49.75002], [18.61368, 49.75426], [18.61278, 49.7618], [18.57183, 49.83334], [18.60341, 49.86256], [18.57045, 49.87849], [18.57697, 49.91565], [18.54299, 49.92537], [18.54495, 49.9079], [18.53423, 49.89906], [18.41604, 49.93498], [18.33562, 49.94747], [18.33278, 49.92415], [18.31914, 49.91565], [18.27794, 49.93863], [18.27107, 49.96779], [18.21752, 49.97309], [18.20241, 49.99958], [18.10628, 50.00223], [18.07898, 50.04535], [18.03212, 50.06574], [18.00396, 50.04954], [18.04585, 50.03311], [18.04585, 50.01194], [18.00191, 50.01723], [17.86886, 49.97452], [17.77669, 50.02253], [17.7506, 50.07896], [17.6888, 50.12037], [17.66683, 50.10275], [17.59404, 50.16437], [17.70528, 50.18812], [17.76296, 50.23382], [17.72176, 50.25665], [17.74648, 50.29966], [17.69292, 50.32859], [17.67764, 50.28977], [17.58889, 50.27837], [17.3702, 50.28123], [17.34548, 50.2628], [17.34273, 50.32947], [17.27681, 50.32246], [17.19991, 50.3654], [17.19579, 50.38817], [17.14498, 50.38117], [17.1224, 50.39494], [16.89229, 50.45117], [16.85933, 50.41093], [16.90877, 50.38642], [16.94448, 50.31281], [16.99803, 50.30316], [17.02138, 50.27772], [16.99803, 50.25753], [17.02825, 50.23118], [17.00353, 50.21449], [16.98018, 50.24172], [16.8456, 50.20834], [16.7014, 50.09659], [16.63137, 50.1142], [16.55446, 50.16613], [16.56407, 50.21009], [16.42674, 50.32509], [16.39379, 50.3207], [16.3622, 50.34875], [16.36495, 50.37679], [16.30289, 50.38292], [16.28118, 50.36891], [16.22821, 50.41054], [16.21585, 50.40627], [16.19526, 50.43291], [16.31413, 50.50274], [16.34572, 50.49575], [16.44597, 50.58041], [16.33611, 50.66579], [16.23174, 50.67101], [16.20839, 50.63096], [16.10265, 50.66405], [16.02437, 50.60046], [15.98317, 50.61528], [16.0175, 50.63009], [15.97219, 50.69799], [15.87331, 50.67188], [15.81683, 50.75666], [15.73186, 50.73885], [15.43798, 50.80833], [15.3803, 50.77187], [15.36656, 50.83956], [15.2773, 50.8907], [15.27043, 50.97724], [15.2361, 50.99886], [15.1743, 50.9833], [15.16744, 51.01959], [15.11937, 50.99021], [15.10152, 51.01095], [15.06218, 51.02269], [15.03895, 51.0123], [15.02433, 51.0242], [14.96419, 50.99108], [15.01088, 50.97984], [14.99852, 50.86817], [14.82803, 50.86966]]]]
24506 groups: ["EU", "155", "150", "UN"],
24507 callingCodes: ["49"]
24510 type: "MultiPolygon",
24511 coordinates: [[[[8.70847, 47.68904], [8.71773, 47.69088], [8.70237, 47.71453], [8.66416, 47.71367], [8.67508, 47.6979], [8.65769, 47.68928], [8.66837, 47.68437], [8.68985, 47.69552], [8.70847, 47.68904]]], [[[8.72617, 47.69651], [8.72809, 47.69282], [8.75856, 47.68969], [8.79511, 47.67462], [8.79966, 47.70222], [8.76965, 47.7075], [8.77309, 47.72059], [8.80663, 47.73821], [8.82002, 47.71458], [8.86989, 47.70504], [8.85065, 47.68209], [8.87383, 47.67045], [8.87625, 47.65441], [8.89946, 47.64769], [8.94093, 47.65596], [9.02093, 47.6868], [9.09891, 47.67801], [9.13845, 47.66389], [9.15181, 47.66904], [9.1705, 47.65513], [9.1755, 47.65584], [9.17593, 47.65399], [9.18203, 47.65598], [9.25619, 47.65939], [9.55125, 47.53629], [9.72736, 47.53457], [9.76748, 47.5934], [9.80254, 47.59419], [9.82591, 47.58158], [9.8189, 47.54688], [9.87499, 47.52953], [9.87733, 47.54688], [9.92407, 47.53111], [9.96029, 47.53899], [10.00003, 47.48216], [10.03859, 47.48927], [10.07131, 47.45531], [10.09001, 47.46005], [10.1052, 47.4316], [10.06897, 47.40709], [10.09819, 47.35724], [10.11805, 47.37228], [10.16362, 47.36674], [10.17648, 47.38889], [10.2127, 47.38019], [10.22774, 47.38904], [10.23757, 47.37609], [10.19998, 47.32832], [10.2147, 47.31014], [10.17648, 47.29149], [10.17531, 47.27167], [10.23257, 47.27088], [10.33424, 47.30813], [10.39851, 47.37623], [10.4324, 47.38494], [10.4359, 47.41183], [10.47446, 47.43318], [10.46278, 47.47901], [10.44291, 47.48453], [10.4324, 47.50111], [10.44992, 47.5524], [10.43473, 47.58394], [10.47329, 47.58552], [10.48849, 47.54057], [10.56912, 47.53584], [10.60337, 47.56755], [10.63456, 47.5591], [10.68832, 47.55752], [10.6965, 47.54253], [10.7596, 47.53228], [10.77596, 47.51729], [10.88814, 47.53701], [10.91268, 47.51334], [10.86945, 47.5015], [10.87061, 47.4786], [10.90918, 47.48571], [10.93839, 47.48018], [10.92437, 47.46991], [10.98513, 47.42882], [10.97111, 47.41617], [10.97111, 47.39561], [11.11835, 47.39719], [11.12536, 47.41222], [11.20482, 47.43198], [11.25157, 47.43277], [11.22002, 47.3964], [11.27844, 47.39956], [11.29597, 47.42566], [11.33804, 47.44937], [11.4175, 47.44621], [11.38128, 47.47465], [11.4362, 47.51413], [11.52618, 47.50939], [11.58578, 47.52281], [11.58811, 47.55515], [11.60681, 47.57881], [11.63934, 47.59202], [11.84052, 47.58354], [11.85572, 47.60166], [12.0088, 47.62451], [12.02282, 47.61033], [12.05788, 47.61742], [12.13734, 47.60639], [12.17824, 47.61506], [12.18145, 47.61019], [12.17737, 47.60121], [12.18568, 47.6049], [12.20398, 47.60667], [12.20801, 47.61082], [12.19895, 47.64085], [12.18507, 47.65984], [12.18347, 47.66663], [12.16769, 47.68167], [12.16217, 47.70105], [12.18303, 47.70065], [12.22571, 47.71776], [12.2542, 47.7433], [12.26238, 47.73544], [12.24017, 47.69534], [12.26004, 47.67725], [12.27991, 47.68827], [12.336, 47.69534], [12.37222, 47.68433], [12.43883, 47.6977], [12.44117, 47.6741], [12.50076, 47.62293], [12.53816, 47.63553], [12.57438, 47.63238], [12.6071, 47.6741], [12.7357, 47.6787], [12.77777, 47.66689], [12.76492, 47.64485], [12.82101, 47.61493], [12.77427, 47.58025], [12.80699, 47.54477], [12.84672, 47.54556], [12.85256, 47.52741], [12.9624, 47.47452], [12.98344, 47.48716], [12.9998, 47.46267], [13.04537, 47.49426], [13.03252, 47.53373], [13.05355, 47.56291], [13.04537, 47.58183], [13.06641, 47.58577], [13.06407, 47.60075], [13.09562, 47.63304], [13.07692, 47.68814], [13.01382, 47.72116], [12.98578, 47.7078], [12.92969, 47.71094], [12.91333, 47.7178], [12.90274, 47.72513], [12.91711, 47.74026], [12.9353, 47.74788], [12.94371, 47.76281], [12.93202, 47.77302], [12.96311, 47.79957], [12.98543, 47.82896], [13.00588, 47.84374], [12.94163, 47.92927], [12.93886, 47.94046], [12.93642, 47.94436], [12.93419, 47.94063], [12.92668, 47.93879], [12.91985, 47.94069], [12.9211, 47.95135], [12.91683, 47.95647], [12.87476, 47.96195], [12.8549, 48.01122], [12.76141, 48.07373], [12.74973, 48.10885], [12.7617, 48.12796], [12.78595, 48.12445], [12.80676, 48.14979], [12.82673, 48.15245], [12.8362, 48.15876], [12.836, 48.1647], [12.84475, 48.16556], [12.87126, 48.20318], [12.95306, 48.20629], [13.02083, 48.25689], [13.0851, 48.27711], [13.126, 48.27867], [13.18093, 48.29577], [13.26039, 48.29422], [13.30897, 48.31575], [13.40709, 48.37292], [13.43929, 48.43386], [13.42527, 48.45711], [13.45727, 48.51092], [13.43695, 48.55776], [13.45214, 48.56472], [13.46967, 48.55157], [13.50663, 48.57506], [13.50131, 48.58091], [13.51291, 48.59023], [13.57535, 48.55912], [13.59705, 48.57013], [13.62508, 48.55501], [13.65186, 48.55092], [13.66113, 48.53558], [13.72802, 48.51208], [13.74816, 48.53058], [13.7513, 48.5624], [13.76921, 48.55324], [13.80519, 48.58026], [13.80038, 48.59487], [13.82609, 48.62345], [13.81901, 48.6761], [13.81283, 48.68426], [13.81791, 48.69832], [13.79337, 48.71375], [13.81863, 48.73257], [13.82266, 48.75544], [13.84023, 48.76988], [13.8096, 48.77877], [13.78977, 48.83319], [13.76994, 48.83537], [13.73854, 48.88538], [13.67739, 48.87886], [13.61624, 48.9462], [13.58319, 48.96899], [13.50552, 48.97441], [13.50221, 48.93752], [13.40802, 48.98851], [13.39479, 49.04812], [13.28242, 49.1228], [13.23689, 49.11412], [13.20405, 49.12303], [13.17019, 49.14339], [13.17665, 49.16713], [13.05883, 49.26259], [13.02957, 49.27399], [13.03618, 49.30417], [12.94859, 49.34079], [12.88249, 49.35479], [12.88414, 49.33541], [12.78168, 49.34618], [12.75854, 49.3989], [12.71227, 49.42363], [12.669, 49.42935], [12.64121, 49.47628], [12.64782, 49.52565], [12.60155, 49.52887], [12.56188, 49.6146], [12.53544, 49.61888], [12.52553, 49.68415], [12.4462, 49.70233], [12.40489, 49.76321], [12.46603, 49.78882], [12.48256, 49.83575], [12.55197, 49.92094], [12.47264, 49.94222], [12.49908, 49.97305], [12.30798, 50.05719], [12.26111, 50.06331], [12.27433, 50.0771], [12.23709, 50.10213], [12.2073, 50.10315], [12.1917, 50.13434], [12.21484, 50.16399], [12.19335, 50.19997], [12.09287, 50.25032], [12.13716, 50.27396], [12.10907, 50.32041], [12.18013, 50.32146], [12.20823, 50.2729], [12.25119, 50.27079], [12.26953, 50.25189], [12.24791, 50.25525], [12.23943, 50.24594], [12.28755, 50.22429], [12.28063, 50.19544], [12.29232, 50.17524], [12.32596, 50.17146], [12.33847, 50.19432], [12.32445, 50.20442], [12.33263, 50.24367], [12.35425, 50.23993], [12.36594, 50.28289], [12.40158, 50.29521], [12.39924, 50.32302], [12.43371, 50.32506], [12.43722, 50.33774], [12.46643, 50.35527], [12.48256, 50.34784], [12.49214, 50.35228], [12.48747, 50.37278], [12.51356, 50.39694], [12.67261, 50.41949], [12.70731, 50.39948], [12.73044, 50.42268], [12.73476, 50.43237], [12.82465, 50.45738], [12.94058, 50.40944], [12.98433, 50.42016], [13.02147, 50.44763], [13.02038, 50.4734], [13.0312, 50.50944], [13.08301, 50.50132], [13.13424, 50.51709], [13.19043, 50.50237], [13.25158, 50.59268], [13.29454, 50.57904], [13.32594, 50.58009], [13.32264, 50.60317], [13.37805, 50.627], [13.37485, 50.64931], [13.42189, 50.61243], [13.46413, 50.60102], [13.49742, 50.63133], [13.5226, 50.64721], [13.53748, 50.67654], [13.52474, 50.70394], [13.65977, 50.73096], [13.70204, 50.71771], [13.76316, 50.73487], [13.82942, 50.7251], [13.89444, 50.74142], [13.89113, 50.78533], [13.98864, 50.8177], [14.02982, 50.80662], [14.22331, 50.86049], [14.24314, 50.88761], [14.27123, 50.89386], [14.30098, 50.88448], [14.38691, 50.89907], [14.39848, 50.93866], [14.31422, 50.95243], [14.30251, 50.96606], [14.32793, 50.97379], [14.32353, 50.98556], [14.28776, 50.97718], [14.25665, 50.98935], [14.30098, 51.05515], [14.41335, 51.02086], [14.45827, 51.03712], [14.49202, 51.02286], [14.49154, 51.04382], [14.49991, 51.04692], [14.50809, 51.0427], [14.49873, 51.02242], [14.53321, 51.01679], [14.53438, 51.00374], [14.56432, 51.01008], [14.58215, 50.99306], [14.59908, 50.98685], [14.59702, 50.96148], [14.56374, 50.922], [14.58024, 50.91443], [14.64802, 50.93241], [14.65259, 50.90513], [14.63434, 50.8883], [14.61993, 50.86049], [14.70661, 50.84096], [14.79139, 50.81438], [14.82803, 50.86966], [14.81664, 50.88148], [14.89681, 50.9422], [14.89252, 50.94999], [14.92942, 50.99744], [14.95529, 51.04552], [14.97938, 51.07742], [14.98229, 51.11354], [14.99689, 51.12205], [14.99079, 51.14284], [14.99646, 51.14365], [15.00083, 51.14974], [14.99414, 51.15813], [14.99311, 51.16249], [15.0047, 51.16874], [15.01242, 51.21285], [15.04288, 51.28387], [14.98008, 51.33449], [14.96899, 51.38367], [14.9652, 51.44793], [14.94749, 51.47155], [14.73219, 51.52922], [14.72652, 51.53902], [14.73047, 51.54606], [14.71125, 51.56209], [14.7727, 51.61263], [14.75759, 51.62318], [14.75392, 51.67445], [14.69065, 51.70842], [14.66386, 51.73282], [14.64625, 51.79472], [14.60493, 51.80473], [14.59089, 51.83302], [14.6588, 51.88359], [14.6933, 51.9044], [14.70601, 51.92944], [14.7177, 51.94048], [14.72163, 51.95188], [14.71836, 51.95606], [14.7139, 51.95643], [14.70488, 51.97679], [14.71339, 52.00337], [14.76026, 52.06624], [14.72971, 52.09167], [14.6917, 52.10283], [14.67683, 52.13936], [14.70616, 52.16927], [14.68344, 52.19612], [14.71319, 52.22144], [14.70139, 52.25038], [14.58149, 52.28007], [14.56378, 52.33838], [14.55228, 52.35264], [14.54423, 52.42568], [14.63056, 52.48993], [14.60081, 52.53116], [14.6289, 52.57136], [14.61073, 52.59847], [14.22071, 52.81175], [14.13806, 52.82392], [14.12256, 52.84311], [14.15873, 52.87715], [14.14056, 52.95786], [14.25954, 53.00264], [14.35044, 53.05829], [14.38679, 53.13669], [14.36696, 53.16444], [14.37853, 53.20405], [14.40662, 53.21098], [14.45125, 53.26241], [14.44133, 53.27427], [14.4215, 53.27724], [14.35209, 53.49506], [14.3273, 53.50587], [14.30416, 53.55499], [14.31904, 53.61581], [14.2853, 53.63392], [14.28477, 53.65955], [14.27133, 53.66613], [14.2836, 53.67721], [14.26782, 53.69866], [14.27249, 53.74464], [14.21323, 53.8664], [14.20823, 53.90776], [14.18544, 53.91258], [14.20647, 53.91671], [14.22634, 53.9291], [14.20811, 54.12784], [13.93395, 54.84044], [12.85844, 54.82438], [11.90309, 54.38543], [11.00303, 54.63689], [10.31111, 54.65968], [10.16755, 54.73883], [9.89314, 54.84171], [9.73563, 54.8247], [9.61187, 54.85548], [9.62734, 54.88057], [9.58937, 54.88785], [9.4659, 54.83131], [9.43155, 54.82586], [9.41213, 54.84254], [9.38532, 54.83968], [9.36496, 54.81749], [9.33849, 54.80233], [9.32771, 54.80602], [9.2474, 54.8112], [9.23445, 54.83432], [9.24631, 54.84726], [9.20571, 54.85841], [9.14275, 54.87421], [9.04629, 54.87249], [8.92795, 54.90452], [8.81178, 54.90518], [8.76387, 54.8948], [8.63979, 54.91069], [8.55769, 54.91837], [8.45719, 55.06747], [8.02459, 55.09613], [5.45168, 54.20039], [6.91025, 53.44221], [7.00198, 53.32672], [7.19052, 53.31866], [7.21679, 53.20058], [7.22681, 53.18165], [7.17898, 53.13817], [7.21694, 53.00742], [7.07253, 52.81083], [7.04557, 52.63318], [6.77307, 52.65375], [6.71641, 52.62905], [6.69507, 52.488], [6.94293, 52.43597], [6.99041, 52.47235], [7.03417, 52.40237], [7.07044, 52.37805], [7.02703, 52.27941], [7.06365, 52.23789], [7.03729, 52.22695], [6.9897, 52.2271], [6.97189, 52.20329], [6.83984, 52.11728], [6.76117, 52.11895], [6.68128, 52.05052], [6.83035, 51.9905], [6.82357, 51.96711], [6.72319, 51.89518], [6.68386, 51.91861], [6.58556, 51.89386], [6.50231, 51.86313], [6.47179, 51.85395], [6.38815, 51.87257], [6.40704, 51.82771], [6.30593, 51.84998], [6.29872, 51.86801], [6.21443, 51.86801], [6.15349, 51.90439], [6.11551, 51.89769], [6.16902, 51.84094], [6.10337, 51.84829], [6.06705, 51.86136], [5.99848, 51.83195], [5.94568, 51.82786], [5.98665, 51.76944], [5.95003, 51.7493], [6.04091, 51.71821], [6.02767, 51.6742], [6.11759, 51.65609], [6.09055, 51.60564], [6.18017, 51.54096], [6.21724, 51.48568], [6.20654, 51.40049], [6.22641, 51.39948], [6.22674, 51.36135], [6.16977, 51.33169], [6.07889, 51.24432], [6.07889, 51.17038], [6.17384, 51.19589], [6.16706, 51.15677], [5.98292, 51.07469], [5.9541, 51.03496], [5.9134, 51.06736], [5.86735, 51.05182], [5.87849, 51.01969], [5.90493, 51.00198], [5.90296, 50.97356], [5.95282, 50.98728], [6.02697, 50.98303], [6.01615, 50.93367], [6.09297, 50.92066], [6.07486, 50.89307], [6.08805, 50.87223], [6.07693, 50.86025], [6.07431, 50.84674], [6.05702, 50.85179], [6.05623, 50.8572], [6.01921, 50.84435], [6.02328, 50.81694], [6.00462, 50.80065], [5.98404, 50.80988], [5.97497, 50.79992], [6.02624, 50.77453], [6.01976, 50.75398], [6.03889, 50.74618], [6.0326, 50.72647], [6.0406, 50.71848], [6.04428, 50.72861], [6.11707, 50.72231], [6.17852, 50.6245], [6.26957, 50.62444], [6.2476, 50.60392], [6.24888, 50.59869], [6.24005, 50.58732], [6.22581, 50.5907], [6.20281, 50.56952], [6.17739, 50.55875], [6.17802, 50.54179], [6.19735, 50.53576], [6.19579, 50.5313], [6.18716, 50.52653], [6.19193, 50.5212], [6.20599, 50.52089], [6.22335, 50.49578], [6.26637, 50.50272], [6.30809, 50.50058], [6.3465, 50.48833], [6.34005, 50.46083], [6.37219, 50.45397], [6.36852, 50.40776], [6.34406, 50.37994], [6.3688, 50.35898], [6.40785, 50.33557], [6.40641, 50.32425], [6.35701, 50.31139], [6.32488, 50.32333], [6.29949, 50.30887], [6.28797, 50.27458], [6.208, 50.25179], [6.16853, 50.2234], [6.18364, 50.20815], [6.18739, 50.1822], [6.14588, 50.17106], [6.14132, 50.14971], [6.15298, 50.14126], [6.1379, 50.12964], [6.12055, 50.09171], [6.11274, 50.05916], [6.13458, 50.04141], [6.13044, 50.02929], [6.14666, 50.02207], [6.13794, 50.01466], [6.13273, 50.02019], [6.1295, 50.01849], [6.13806, 50.01056], [6.14948, 50.00908], [6.14147, 49.99563], [6.1701, 49.98518], [6.16466, 49.97086], [6.17872, 49.9537], [6.18554, 49.95622], [6.18045, 49.96611], [6.19089, 49.96991], [6.19856, 49.95053], [6.22094, 49.94955], [6.22608, 49.929], [6.21882, 49.92403], [6.22926, 49.92096], [6.23496, 49.89972], [6.26146, 49.88203], [6.28874, 49.87592], [6.29692, 49.86685], [6.30963, 49.87021], [6.32303, 49.85133], [6.32098, 49.83728], [6.33585, 49.83785], [6.34267, 49.84974], [6.36576, 49.85032], [6.40022, 49.82029], [6.42521, 49.81591], [6.42905, 49.81091], [6.44131, 49.81443], [6.45425, 49.81164], [6.47111, 49.82263], [6.48718, 49.81267], [6.50647, 49.80916], [6.51215, 49.80124], [6.52121, 49.81338], [6.53122, 49.80666], [6.52169, 49.79787], [6.50534, 49.78952], [6.51669, 49.78336], [6.51056, 49.77515], [6.51828, 49.76855], [6.51646, 49.75961], [6.50174, 49.75292], [6.50193, 49.73291], [6.51805, 49.72425], [6.51397, 49.72058], [6.50261, 49.72718], [6.49535, 49.72645], [6.49694, 49.72205], [6.5042, 49.71808], [6.50647, 49.71353], [6.49785, 49.71118], [6.48014, 49.69767], [6.46048, 49.69092], [6.44654, 49.67799], [6.42937, 49.66857], [6.42726, 49.66078], [6.43768, 49.66021], [6.4413, 49.65722], [6.41861, 49.61723], [6.39822, 49.60081], [6.385, 49.59946], [6.37464, 49.58886], [6.38342, 49.5799], [6.38024, 49.57593], [6.36676, 49.57813], [6.35825, 49.57053], [6.38228, 49.55855], [6.38072, 49.55171], [6.35666, 49.52931], [6.36788, 49.50377], [6.36907, 49.48931], [6.36778, 49.46937], [6.38352, 49.46463], [6.39168, 49.4667], [6.40274, 49.46546], [6.42432, 49.47683], [6.55404, 49.42464], [6.533, 49.40748], [6.60091, 49.36864], [6.58807, 49.35358], [6.572, 49.35027], [6.60186, 49.31055], [6.66583, 49.28065], [6.69274, 49.21661], [6.71843, 49.2208], [6.73256, 49.20486], [6.71137, 49.18808], [6.73765, 49.16375], [6.78265, 49.16793], [6.83385, 49.15162], [6.84703, 49.15734], [6.86225, 49.18185], [6.85016, 49.19354], [6.85119, 49.20038], [6.83555, 49.21249], [6.85939, 49.22376], [6.89298, 49.20863], [6.91875, 49.22261], [6.93831, 49.2223], [6.94028, 49.21641], [6.95963, 49.203], [6.97273, 49.2099], [7.01318, 49.19018], [7.03459, 49.19096], [7.0274, 49.17042], [7.03178, 49.15734], [7.04662, 49.13724], [7.04409, 49.12123], [7.04843, 49.11422], [7.05548, 49.11185], [7.06642, 49.11415], [7.07162, 49.1255], [7.09007, 49.13094], [7.07859, 49.15031], [7.10715, 49.15631], [7.10384, 49.13787], [7.12504, 49.14253], [7.1358, 49.1282], [7.1593, 49.1204], [7.23473, 49.12971], [7.29514, 49.11426], [7.3195, 49.14231], [7.35995, 49.14399], [7.3662, 49.17308], [7.44052, 49.18354], [7.44455, 49.16765], [7.49473, 49.17], [7.49172, 49.13915], [7.53012, 49.09818], [7.56416, 49.08136], [7.62575, 49.07654], [7.63618, 49.05428], [7.75948, 49.04562], [7.79557, 49.06583], [7.86386, 49.03499], [7.93641, 49.05544], [7.97783, 49.03161], [8.14189, 48.97833], [8.22604, 48.97352], [8.20031, 48.95856], [8.19989, 48.95825], [8.12813, 48.87985], [8.10253, 48.81829], [8.06802, 48.78957], [8.0326, 48.79017], [8.01534, 48.76085], [7.96994, 48.75606], [7.96812, 48.72491], [7.89002, 48.66317], [7.84098, 48.64217], [7.80057, 48.5857], [7.80167, 48.54758], [7.80647, 48.51239], [7.76833, 48.48945], [7.73109, 48.39192], [7.74562, 48.32736], [7.69022, 48.30018], [7.6648, 48.22219], [7.57137, 48.12292], [7.56966, 48.03265], [7.62302, 47.97898], [7.55673, 47.87371], [7.52921, 47.77747], [7.54761, 47.72912], [7.53722, 47.71635], [7.51266, 47.70197], [7.51915, 47.68335], [7.52067, 47.66437], [7.53384, 47.65115], [7.5591, 47.63849], [7.57423, 47.61628], [7.58851, 47.60794], [7.59301, 47.60058], [7.58945, 47.59017], [7.60523, 47.58519], [7.60459, 47.57869], [7.61929, 47.57683], [7.64309, 47.59151], [7.64213, 47.5944], [7.64599, 47.59695], [7.67395, 47.59212], [7.68229, 47.59905], [7.69385, 47.60099], [7.68486, 47.59601], [7.67115, 47.5871], [7.68904, 47.57133], [7.67655, 47.56435], [7.63338, 47.56256], [7.65083, 47.54662], [7.66174, 47.54554], [7.6656, 47.53752], [7.68101, 47.53232], [7.69642, 47.53297], [7.71961, 47.54219], [7.75261, 47.54599], [7.79486, 47.55691], [7.81901, 47.58798], [7.84412, 47.5841], [7.88664, 47.58854], [7.90673, 47.57674], [7.91251, 47.55031], [7.94494, 47.54511], [7.95682, 47.55789], [7.97581, 47.55493], [8.00113, 47.55616], [8.02136, 47.55096], [8.04383, 47.55443], [8.06663, 47.56374], [8.08557, 47.55768], [8.10002, 47.56504], [8.10395, 47.57918], [8.11543, 47.5841], [8.13662, 47.58432], [8.13823, 47.59147], [8.14947, 47.59558], [8.1652, 47.5945], [8.19378, 47.61636], [8.20617, 47.62141], [8.22011, 47.6181], [8.22577, 47.60385], [8.23809, 47.61204], [8.25863, 47.61571], [8.26313, 47.6103], [8.2824, 47.61225], [8.29722, 47.60603], [8.29524, 47.5919], [8.30277, 47.58607], [8.32735, 47.57133], [8.35512, 47.57014], [8.38273, 47.56608], [8.39477, 47.57826], [8.43235, 47.56617], [8.49431, 47.58107], [8.48949, 47.588], [8.46637, 47.58389], [8.45578, 47.60121], [8.50747, 47.61897], [8.51686, 47.63476], [8.55756, 47.62394], [8.57586, 47.59537], [8.60348, 47.61204], [8.59545, 47.64298], [8.60701, 47.65271], [8.61471, 47.64514], [8.60412, 47.63735], [8.62049, 47.63757], [8.62884, 47.65098], [8.61113, 47.66332], [8.6052, 47.67258], [8.57683, 47.66158], [8.56141, 47.67088], [8.52801, 47.66059], [8.5322, 47.64687], [8.49656, 47.64709], [8.46605, 47.64103], [8.4667, 47.65747], [8.44711, 47.65379], [8.42264, 47.66667], [8.41346, 47.66676], [8.40473, 47.67499], [8.4211, 47.68407], [8.40569, 47.69855], [8.44807, 47.72426], [8.45771, 47.7493], [8.48868, 47.77215], [8.56814, 47.78001], [8.56415, 47.80633], [8.61657, 47.79998], [8.62408, 47.7626], [8.64425, 47.76398], [8.65292, 47.80066], [8.68022, 47.78599], [8.68985, 47.75686], [8.71778, 47.76571], [8.74251, 47.75168], [8.70543, 47.73121], [8.73671, 47.7169], [8.72617, 47.69651]]]]
24518 wikidata: "Q184851",
24519 nameEn: "Diego Garcia",
24521 groups: ["IO", "BOTS", "014", "202", "002", "UN"],
24522 isoStatus: "excRes",
24523 callingCodes: ["246"]
24526 type: "MultiPolygon",
24527 coordinates: [[[[73.14823, -7.76302], [73.09982, -6.07324], [71.43792, -7.73904], [73.14823, -7.76302]]]]
24536 nameEn: "Djibouti",
24537 groups: ["014", "202", "002", "UN"],
24538 callingCodes: ["253"]
24541 type: "MultiPolygon",
24542 coordinates: [[[[43.90659, 12.3823], [43.90659, 12.3823], [43.32909, 12.59711], [43.29075, 12.79154], [42.86195, 12.58747], [42.7996, 12.42629], [42.6957, 12.36201], [42.46941, 12.52661], [42.4037, 12.46478], [41.95461, 11.81157], [41.82878, 11.72361], [41.77727, 11.49902], [41.8096, 11.33606], [41.80056, 10.97127], [42.06302, 10.92599], [42.13691, 10.97586], [42.42669, 10.98493], [42.62989, 11.09711], [42.75111, 11.06992], [42.79037, 10.98493], [42.95776, 10.98533], [43.90659, 12.3823]]]]
24550 wikidata: "Q756617",
24551 nameEn: "Kingdom of Denmark"
24561 nameEn: "Dominica",
24562 groups: ["029", "003", "419", "019", "UN"],
24564 roadSpeedUnit: "mph",
24565 callingCodes: ["1 767"]
24568 type: "MultiPolygon",
24569 coordinates: [[[[-61.32485, 14.91445], [-60.86656, 15.82603], [-61.95646, 15.5094], [-61.32485, 14.91445]]]]
24578 nameEn: "Dominican Republic",
24579 groups: ["029", "003", "419", "019", "UN"],
24580 callingCodes: ["1 809", "1 829", "1 849"]
24583 type: "MultiPolygon",
24584 coordinates: [[[[-67.87844, 21.7938], [-72.38946, 20.27111], [-71.77419, 19.73128], [-71.75865, 19.70231], [-71.7429, 19.58445], [-71.71449, 19.55364], [-71.71268, 19.53374], [-71.6802, 19.45008], [-71.69448, 19.37866], [-71.77766, 19.33823], [-71.73229, 19.26686], [-71.62642, 19.21212], [-71.65337, 19.11759], [-71.69938, 19.10916], [-71.71088, 19.08353], [-71.74088, 19.0437], [-71.88102, 18.95007], [-71.77766, 18.95007], [-71.72624, 18.87802], [-71.71885, 18.78423], [-71.82556, 18.62551], [-71.95412, 18.64939], [-72.00201, 18.62312], [-71.88102, 18.50125], [-71.90875, 18.45821], [-71.69952, 18.34101], [-71.78271, 18.18302], [-71.75465, 18.14405], [-71.74994, 18.11115], [-71.73783, 18.07177], [-71.75671, 18.03456], [-72.29523, 17.48026], [-68.39466, 16.14167], [-67.87844, 21.7938]]]]
24594 groups: ["015", "002", "UN"],
24595 callingCodes: ["213"]
24598 type: "MultiPolygon",
24599 coordinates: [[[[8.59123, 37.14286], [5.10072, 39.89531], [-2.27707, 35.35051], [-2.21248, 35.08532], [-2.21445, 35.04378], [-2.04734, 34.93218], [-1.97833, 34.93218], [-1.97469, 34.886], [-1.73707, 34.74226], [-1.84569, 34.61907], [-1.69788, 34.48056], [-1.78042, 34.39018], [-1.64666, 34.10405], [-1.73494, 33.71721], [-1.59508, 33.59929], [-1.67067, 33.27084], [-1.46249, 33.0499], [-1.54244, 32.95499], [-1.37794, 32.73628], [-0.9912, 32.52467], [-1.24998, 32.32993], [-1.24453, 32.1917], [-1.15735, 32.12096], [-1.22829, 32.07832], [-2.46166, 32.16603], [-2.93873, 32.06557], [-2.82784, 31.79459], [-3.66314, 31.6339], [-3.66386, 31.39202], [-3.77647, 31.31912], [-3.77103, 31.14984], [-3.54944, 31.0503], [-3.65418, 30.85566], [-3.64735, 30.67539], [-4.31774, 30.53229], [-4.6058, 30.28343], [-5.21671, 29.95253], [-5.58831, 29.48103], [-5.72121, 29.52322], [-5.75616, 29.61407], [-6.69965, 29.51623], [-6.78351, 29.44634], [-6.95824, 29.50924], [-7.61585, 29.36252], [-8.6715, 28.71194], [-8.66879, 27.6666], [-8.66674, 27.31569], [-4.83423, 24.99935], [1.15698, 21.12843], [1.20992, 20.73533], [3.24648, 19.81703], [3.12501, 19.1366], [3.36082, 18.9745], [4.26651, 19.14224], [5.8153, 19.45101], [7.38361, 20.79165], [7.48273, 20.87258], [11.96886, 23.51735], [11.62498, 24.26669], [11.41061, 24.21456], [10.85323, 24.5595], [10.33159, 24.5465], [10.02432, 24.98124], [10.03146, 25.35635], [9.38834, 26.19288], [9.51696, 26.39148], [9.89569, 26.57696], [9.78136, 29.40961], [9.3876, 30.16738], [9.55544, 30.23971], [9.07483, 32.07865], [8.35999, 32.50101], [8.31895, 32.83483], [8.1179, 33.05086], [8.11433, 33.10175], [7.83028, 33.18851], [7.73687, 33.42114], [7.54088, 33.7726], [7.52851, 34.06493], [7.66174, 34.20167], [7.74207, 34.16492], [7.81242, 34.21841], [7.86264, 34.3987], [8.20482, 34.57575], [8.29655, 34.72798], [8.25189, 34.92009], [8.30727, 34.95378], [8.3555, 35.10007], [8.47318, 35.23376], [8.30329, 35.29884], [8.36086, 35.47774], [8.35371, 35.66373], [8.26472, 35.73669], [8.2626, 35.91733], [8.40731, 36.42208], [8.18936, 36.44939], [8.16167, 36.48817], [8.47609, 36.66607], [8.46537, 36.7706], [8.57613, 36.78062], [8.67706, 36.8364], [8.62972, 36.86499], [8.64044, 36.9401], [8.59123, 37.14286]]]]
24605 wikidata: "Q28868874",
24606 nameEn: "Ceuta, Melilla",
24608 level: "territory",
24609 isoStatus: "excRes"
24631 groups: ["EU", "154", "150", "UN"],
24632 callingCodes: ["372"]
24635 type: "MultiPolygon",
24636 coordinates: [[[[26.32936, 60.00121], [20.5104, 59.15546], [19.84909, 57.57876], [22.80496, 57.87798], [23.20055, 57.56697], [24.26221, 57.91787], [24.3579, 57.87471], [25.19484, 58.0831], [25.28237, 57.98539], [25.29581, 58.08288], [25.73499, 57.90193], [26.05949, 57.84744], [26.0324, 57.79037], [26.02456, 57.78342], [26.027, 57.78158], [26.0266, 57.77441], [26.02069, 57.77169], [26.02415, 57.76865], [26.03332, 57.7718], [26.0543, 57.76105], [26.08098, 57.76619], [26.2029, 57.7206], [26.1866, 57.6849], [26.29253, 57.59244], [26.46527, 57.56885], [26.54675, 57.51813], [26.90364, 57.62823], [27.34698, 57.52242], [27.31919, 57.57672], [27.40393, 57.62125], [27.3746, 57.66834], [27.52615, 57.72843], [27.50171, 57.78842], [27.56689, 57.83356], [27.78526, 57.83963], [27.81841, 57.89244], [27.67282, 57.92627], [27.62393, 58.09462], [27.48541, 58.22615], [27.55489, 58.39525], [27.36366, 58.78381], [27.74429, 58.98351], [27.80482, 59.1116], [27.87978, 59.18097], [27.90911, 59.24353], [28.00689, 59.28351], [28.14215, 59.28934], [28.19284, 59.35791], [28.20537, 59.36491], [28.21137, 59.38058], [28.19061, 59.39962], [28.04187, 59.47017], [27.85643, 59.58538], [26.90044, 59.63819], [26.32936, 60.00121]]]]
24646 groups: ["015", "002", "UN"],
24647 callingCodes: ["20"]
24650 type: "MultiPolygon",
24651 coordinates: [[[[33.62659, 31.82938], [26.92891, 33.39516], [24.8458, 31.39877], [25.01077, 30.73861], [24.71117, 30.17441], [24.99968, 29.24574], [24.99885, 21.99535], [33.17563, 22.00405], [34.0765, 22.00501], [37.8565, 22.00903], [34.4454, 27.91479], [34.8812, 29.36878], [34.92298, 29.45305], [34.26742, 31.21998], [34.24012, 31.29591], [34.23572, 31.2966], [34.21853, 31.32363], [34.052, 31.46619], [33.62659, 31.82938]]]]
24660 nameEn: "Western Sahara",
24661 groups: ["015", "002"],
24662 callingCodes: ["212"]
24665 type: "MultiPolygon",
24666 coordinates: [[[[-8.66879, 27.6666], [-8.77527, 27.66663], [-8.71787, 26.9898], [-9.08698, 26.98639], [-9.56957, 26.90042], [-9.81998, 26.71379], [-10.68417, 26.90984], [-11.35695, 26.8505], [-11.23622, 26.72023], [-11.38635, 26.611], [-11.62052, 26.05229], [-12.06001, 26.04442], [-12.12281, 25.13682], [-12.92147, 24.39502], [-13.00628, 24.01923], [-13.75627, 23.77231], [-14.10361, 22.75501], [-14.1291, 22.41636], [-14.48112, 22.00886], [-14.47329, 21.63839], [-14.78487, 21.36587], [-16.44269, 21.39745], [-16.9978, 21.36239], [-17.02707, 21.34022], [-17.21511, 21.34226], [-17.35589, 20.80492], [-17.0471, 20.76408], [-17.0695, 20.85742], [-17.06781, 20.92697], [-17.0396, 20.9961], [-17.0357, 21.05368], [-16.99806, 21.12142], [-16.95474, 21.33997], [-13.01525, 21.33343], [-13.08438, 22.53866], [-13.15313, 22.75649], [-13.10753, 22.89493], [-13.00412, 23.02297], [-12.5741, 23.28975], [-12.36213, 23.3187], [-12.14969, 23.41935], [-12.00251, 23.4538], [-12.0002, 25.9986], [-8.66721, 25.99918], [-8.66674, 27.31569], [-8.66879, 27.6666]]]]
24676 groups: ["014", "202", "002", "UN"],
24677 callingCodes: ["291"]
24680 type: "MultiPolygon",
24681 coordinates: [[[[40.99158, 15.81743], [39.63762, 18.37348], [38.57727, 17.98125], [38.45916, 17.87167], [38.37133, 17.66269], [38.13362, 17.53906], [37.50967, 17.32199], [37.42694, 17.04041], [36.99777, 17.07172], [36.92193, 16.23451], [36.76371, 15.80831], [36.69761, 15.75323], [36.54276, 15.23478], [36.44337, 15.14963], [36.54376, 14.25597], [36.56536, 14.26177], [36.55659, 14.28237], [36.63364, 14.31172], [36.85787, 14.32201], [37.01622, 14.2561], [37.09486, 14.27155], [37.13206, 14.40746], [37.3106, 14.44657], [37.47319, 14.2149], [37.528, 14.18413], [37.91287, 14.89447], [38.0364, 14.72745], [38.25562, 14.67287], [38.3533, 14.51323], [38.45748, 14.41445], [38.78306, 14.4754], [38.98058, 14.54895], [39.02834, 14.63717], [39.16074, 14.65187], [39.14772, 14.61827], [39.19547, 14.56996], [39.23888, 14.56365], [39.26927, 14.48801], [39.2302, 14.44598], [39.2519, 14.40393], [39.37685, 14.54402], [39.52756, 14.49011], [39.50585, 14.55735], [39.58182, 14.60987], [39.76632, 14.54264], [39.9443, 14.41024], [40.07236, 14.54264], [40.14649, 14.53969], [40.21128, 14.39342], [40.25686, 14.41445], [40.9167, 14.11152], [41.25097, 13.60787], [41.62864, 13.38626], [42.05841, 12.80912], [42.21469, 12.75832], [42.2798, 12.6355], [42.4037, 12.46478], [42.46941, 12.52661], [42.6957, 12.36201], [42.7996, 12.42629], [42.86195, 12.58747], [43.29075, 12.79154], [40.99158, 15.81743]]]]
24700 nameEn: "Ethiopia",
24701 groups: ["014", "202", "002", "UN"],
24702 callingCodes: ["251"]
24705 type: "MultiPolygon",
24706 coordinates: [[[[42.4037, 12.46478], [42.2798, 12.6355], [42.21469, 12.75832], [42.05841, 12.80912], [41.62864, 13.38626], [41.25097, 13.60787], [40.9167, 14.11152], [40.25686, 14.41445], [40.21128, 14.39342], [40.14649, 14.53969], [40.07236, 14.54264], [39.9443, 14.41024], [39.76632, 14.54264], [39.58182, 14.60987], [39.50585, 14.55735], [39.52756, 14.49011], [39.37685, 14.54402], [39.2519, 14.40393], [39.2302, 14.44598], [39.26927, 14.48801], [39.23888, 14.56365], [39.19547, 14.56996], [39.14772, 14.61827], [39.16074, 14.65187], [39.02834, 14.63717], [38.98058, 14.54895], [38.78306, 14.4754], [38.45748, 14.41445], [38.3533, 14.51323], [38.25562, 14.67287], [38.0364, 14.72745], [37.91287, 14.89447], [37.528, 14.18413], [37.47319, 14.2149], [37.3106, 14.44657], [37.13206, 14.40746], [37.09486, 14.27155], [37.01622, 14.2561], [36.85787, 14.32201], [36.63364, 14.31172], [36.55659, 14.28237], [36.56536, 14.26177], [36.54376, 14.25597], [36.44653, 13.95666], [36.48824, 13.83954], [36.38993, 13.56459], [36.24545, 13.36759], [36.13374, 12.92665], [36.16651, 12.88019], [36.14268, 12.70879], [36.01458, 12.72478], [35.70476, 12.67101], [35.24302, 11.91132], [35.11492, 11.85156], [35.05832, 11.71158], [35.09556, 11.56278], [34.95704, 11.24448], [35.01215, 11.19626], [34.93172, 10.95946], [34.97789, 10.91559], [34.97491, 10.86147], [34.86916, 10.78832], [34.86618, 10.74588], [34.77532, 10.69027], [34.77383, 10.74588], [34.59062, 10.89072], [34.4372, 10.781], [34.2823, 10.53508], [34.34783, 10.23914], [34.32102, 10.11599], [34.22718, 10.02506], [34.20484, 9.9033], [34.13186, 9.7492], [34.08717, 9.55243], [34.10229, 9.50238], [34.14304, 9.04654], [34.14453, 8.60204], [34.01346, 8.50041], [33.89579, 8.4842], [33.87195, 8.41938], [33.71407, 8.3678], [33.66938, 8.44442], [33.54575, 8.47094], [33.3119, 8.45474], [33.19721, 8.40317], [33.1853, 8.29264], [33.18083, 8.13047], [33.08401, 8.05822], [33.0006, 7.90333], [33.04944, 7.78989], [33.24637, 7.77939], [33.32531, 7.71297], [33.44745, 7.7543], [33.71407, 7.65983], [33.87642, 7.5491], [34.02984, 7.36449], [34.03878, 7.27437], [34.01495, 7.25664], [34.19369, 7.12807], [34.19369, 7.04382], [34.35753, 6.91963], [34.47669, 6.91076], [34.53925, 6.82794], [34.53776, 6.74808], [34.65096, 6.72589], [34.77459, 6.5957], [34.87736, 6.60161], [35.01738, 6.46991], [34.96227, 6.26415], [35.00546, 5.89387], [35.12611, 5.68937], [35.13058, 5.62118], [35.31188, 5.50106], [35.29938, 5.34042], [35.50792, 5.42431], [35.8576, 5.33413], [35.81968, 5.10757], [35.82118, 4.77382], [35.9419, 4.61933], [35.95449, 4.53244], [36.03924, 4.44406], [36.84474, 4.44518], [37.07724, 4.33503], [38.14168, 3.62487], [38.45812, 3.60445], [38.52336, 3.62551], [38.91938, 3.51198], [39.07736, 3.5267], [39.19954, 3.47834], [39.49444, 3.45521], [39.51551, 3.40895], [39.55132, 3.39634], [39.58339, 3.47434], [39.76808, 3.67058], [39.86043, 3.86974], [40.77498, 4.27683], [41.1754, 3.94079], [41.89488, 3.97375], [42.07619, 4.17667], [42.55853, 4.20518], [42.84526, 4.28357], [42.97746, 4.44032], [43.04177, 4.57923], [43.40263, 4.79289], [44.02436, 4.9451], [44.98104, 4.91821], [47.97917, 8.00124], [47.92477, 8.00111], [46.99339, 7.9989], [44.19222, 8.93028], [43.32613, 9.59205], [43.23518, 9.84605], [43.0937, 9.90579], [42.87643, 10.18441], [42.69452, 10.62672], [42.95776, 10.98533], [42.79037, 10.98493], [42.75111, 11.06992], [42.62989, 11.09711], [42.42669, 10.98493], [42.13691, 10.97586], [42.06302, 10.92599], [41.80056, 10.97127], [41.8096, 11.33606], [41.77727, 11.49902], [41.82878, 11.72361], [41.95461, 11.81157], [42.4037, 12.46478]]]]
24714 nameEn: "European Union",
24716 isoStatus: "excRes"
24738 groups: ["054", "009", "UN"],
24740 callingCodes: ["679"]
24743 type: "MultiPolygon",
24744 coordinates: [[[[174.245, -23.1974], [179.99999, -22.5], [179.99999, -11.5], [174, -11.5], [174.245, -23.1974]]], [[[-176.76826, -14.95183], [-180, -14.96041], [-180, -22.90585], [-176.74538, -22.89767], [-176.76826, -14.95183]]]]
24753 nameEn: "Falkland Islands",
24755 groups: ["BOTS", "005", "419", "019", "UN"],
24757 roadSpeedUnit: "mph",
24758 roadHeightUnit: "ft",
24759 callingCodes: ["500"]
24762 type: "MultiPolygon",
24763 coordinates: [[[[-63.67376, -55.11859], [-54.56126, -51.26248], [-61.26735, -50.63919], [-63.67376, -55.11859]]]]
24772 nameEn: "Federated States of Micronesia",
24773 groups: ["057", "009", "UN"],
24774 roadSpeedUnit: "mph",
24775 roadHeightUnit: "ft",
24776 callingCodes: ["691"]
24779 type: "MultiPolygon",
24780 coordinates: [[[[138.20583, 13.3783], [136.27107, 6.73747], [156.88247, -1.39237], [165.19726, 6.22546], [138.20583, 13.3783]]]]
24789 nameEn: "Faroe Islands",
24791 groups: ["154", "150", "UN"],
24792 callingCodes: ["298"]
24795 type: "MultiPolygon",
24796 coordinates: [[[[-8.51774, 62.35338], [-6.51083, 60.95272], [-5.70102, 62.77194], [-8.51774, 62.35338]]]]
24814 wikidata: "Q212429",
24815 nameEn: "Metropolitan France",
24817 groups: ["EU", "155", "150", "UN"],
24818 isoStatus: "excRes",
24819 callingCodes: ["33"]
24822 type: "MultiPolygon",
24823 coordinates: [[[[2.55904, 51.07014], [2.18458, 51.52087], [1.17405, 50.74239], [-2.02963, 49.91866], [-2.09454, 49.46288], [-1.83944, 49.23037], [-2.00491, 48.86706], [-2.65349, 49.15373], [-6.28985, 48.93406], [-1.81005, 43.59738], [-1.77289, 43.38957], [-1.79319, 43.37497], [-1.78332, 43.36399], [-1.78714, 43.35476], [-1.77068, 43.34396], [-1.75334, 43.34107], [-1.75079, 43.3317], [-1.7397, 43.32979], [-1.73074, 43.29481], [-1.69407, 43.31378], [-1.62481, 43.30726], [-1.63052, 43.28591], [-1.61341, 43.25269], [-1.57674, 43.25269], [-1.55963, 43.28828], [-1.50992, 43.29481], [-1.45289, 43.27049], [-1.40942, 43.27272], [-1.3758, 43.24511], [-1.41562, 43.12815], [-1.47555, 43.08372], [-1.44067, 43.047], [-1.35272, 43.02658], [-1.34419, 43.09665], [-1.32209, 43.1127], [-1.27118, 43.11961], [-1.30052, 43.09581], [-1.30531, 43.06859], [-1.25244, 43.04164], [-1.22881, 43.05534], [-1.10333, 43.0059], [-1.00963, 42.99279], [-0.97133, 42.96239], [-0.81652, 42.95166], [-0.75478, 42.96916], [-0.72037, 42.92541], [-0.73422, 42.91228], [-0.72608, 42.89318], [-0.69837, 42.87945], [-0.67637, 42.88303], [-0.55497, 42.77846], [-0.50863, 42.82713], [-0.44334, 42.79939], [-0.41319, 42.80776], [-0.38833, 42.80132], [-0.3122, 42.84788], [-0.17939, 42.78974], [-0.16141, 42.79535], [-0.10519, 42.72761], [-0.02468, 42.68513], [0.17569, 42.73424], [0.25336, 42.7174], [0.29407, 42.67431], [0.36251, 42.72282], [0.40214, 42.69779], [0.67873, 42.69458], [0.65421, 42.75872], [0.66121, 42.84021], [0.711, 42.86372], [0.93089, 42.79154], [0.96166, 42.80629], [0.98292, 42.78754], [1.0804, 42.78569], [1.15928, 42.71407], [1.35562, 42.71944], [1.44197, 42.60217], [1.47986, 42.61346], [1.46718, 42.63296], [1.48043, 42.65203], [1.50867, 42.64483], [1.55418, 42.65669], [1.60085, 42.62703], [1.63485, 42.62957], [1.6625, 42.61982], [1.68267, 42.62533], [1.73452, 42.61515], [1.72588, 42.59098], [1.7858, 42.57698], [1.73683, 42.55492], [1.72515, 42.50338], [1.76335, 42.48863], [1.83037, 42.48395], [1.88853, 42.4501], [1.93663, 42.45439], [1.94292, 42.44316], [1.94061, 42.43333], [1.94084, 42.43039], [1.9574, 42.42401], [1.96482, 42.37787], [2.00488, 42.35399], [2.06241, 42.35906], [2.11621, 42.38393], [2.12789, 42.41291], [2.16599, 42.42314], [2.20578, 42.41633], [2.25551, 42.43757], [2.38504, 42.39977], [2.43299, 42.39423], [2.43508, 42.37568], [2.48457, 42.33933], [2.54382, 42.33406], [2.55516, 42.35351], [2.57934, 42.35808], [2.6747, 42.33974], [2.65311, 42.38771], [2.72056, 42.42298], [2.75497, 42.42578], [2.77464, 42.41046], [2.84335, 42.45724], [2.85675, 42.45444], [2.86983, 42.46843], [2.88413, 42.45938], [2.92107, 42.4573], [2.94283, 42.48174], [2.96518, 42.46692], [3.03734, 42.47363], [3.08167, 42.42748], [3.10027, 42.42621], [3.11379, 42.43646], [3.17156, 42.43545], [3.75438, 42.33445], [7.60802, 41.05927], [10.09675, 41.44089], [9.56115, 43.20816], [7.50102, 43.51859], [7.42422, 43.72209], [7.40903, 43.7296], [7.41113, 43.73156], [7.41291, 43.73168], [7.41298, 43.73311], [7.41233, 43.73439], [7.42062, 43.73977], [7.42299, 43.74176], [7.42443, 43.74087], [7.42809, 43.74396], [7.43013, 43.74895], [7.43624, 43.75014], [7.43708, 43.75197], [7.4389, 43.75151], [7.4379, 43.74963], [7.47823, 43.73341], [7.53006, 43.78405], [7.50423, 43.84345], [7.49355, 43.86551], [7.51162, 43.88301], [7.56075, 43.89932], [7.56858, 43.94506], [7.60771, 43.95772], [7.65266, 43.9763], [7.66848, 43.99943], [7.6597, 44.03009], [7.72508, 44.07578], [7.66878, 44.12795], [7.68694, 44.17487], [7.63245, 44.17877], [7.62155, 44.14881], [7.36364, 44.11882], [7.34547, 44.14359], [7.27827, 44.1462], [7.16929, 44.20352], [7.00764, 44.23736], [6.98221, 44.28289], [6.89171, 44.36637], [6.88784, 44.42043], [6.94504, 44.43112], [6.86233, 44.49834], [6.85507, 44.53072], [6.96042, 44.62129], [6.95133, 44.66264], [7.00582, 44.69364], [7.07484, 44.68073], [7.00401, 44.78782], [7.02217, 44.82519], [6.93499, 44.8664], [6.90774, 44.84322], [6.75518, 44.89915], [6.74519, 44.93661], [6.74791, 45.01939], [6.66981, 45.02324], [6.62803, 45.11175], [6.7697, 45.16044], [6.85144, 45.13226], [6.96706, 45.20841], [7.07074, 45.21228], [7.13115, 45.25386], [7.10572, 45.32924], [7.18019, 45.40071], [7.00037, 45.509], [6.98948, 45.63869], [6.80785, 45.71864], [6.80785, 45.83265], [6.95315, 45.85163], [7.04151, 45.92435], [7.00946, 45.9944], [6.93862, 46.06502], [6.87868, 46.03855], [6.89321, 46.12548], [6.78968, 46.14058], [6.86052, 46.28512], [6.77152, 46.34784], [6.8024, 46.39171], [6.82312, 46.42661], [6.53358, 46.45431], [6.25432, 46.3632], [6.21981, 46.31304], [6.24826, 46.30175], [6.25137, 46.29014], [6.23775, 46.27822], [6.24952, 46.26255], [6.26749, 46.24745], [6.29474, 46.26221], [6.31041, 46.24417], [6.29663, 46.22688], [6.27694, 46.21566], [6.26007, 46.21165], [6.24821, 46.20531], [6.23913, 46.20511], [6.23544, 46.20714], [6.22175, 46.20045], [6.22222, 46.19888], [6.21844, 46.19837], [6.21603, 46.19507], [6.21273, 46.19409], [6.21114, 46.1927], [6.20539, 46.19163], [6.19807, 46.18369], [6.19552, 46.18401], [6.18707, 46.17999], [6.18871, 46.16644], [6.18116, 46.16187], [6.15305, 46.15194], [6.13397, 46.1406], [6.09926, 46.14373], [6.09199, 46.15191], [6.07491, 46.14879], [6.05203, 46.15191], [6.04564, 46.14031], [6.03614, 46.13712], [6.01791, 46.14228], [5.9871, 46.14499], [5.97893, 46.13303], [5.95781, 46.12925], [5.9641, 46.14412], [5.97508, 46.15863], [5.98188, 46.17392], [5.98846, 46.17046], [5.99573, 46.18587], [5.96515, 46.19638], [5.97542, 46.21525], [6.02461, 46.23313], [6.03342, 46.2383], [6.04602, 46.23127], [6.05029, 46.23518], [6.0633, 46.24583], [6.07072, 46.24085], [6.08563, 46.24651], [6.10071, 46.23772], [6.12446, 46.25059], [6.11926, 46.2634], [6.1013, 46.28512], [6.11697, 46.29547], [6.1198, 46.31157], [6.13876, 46.33844], [6.15738, 46.3491], [6.16987, 46.36759], [6.15985, 46.37721], [6.15016, 46.3778], [6.09926, 46.40768], [6.06407, 46.41676], [6.08427, 46.44305], [6.07269, 46.46244], [6.1567, 46.54402], [6.11084, 46.57649], [6.27135, 46.68251], [6.38351, 46.73171], [6.45209, 46.77502], [6.43216, 46.80336], [6.46456, 46.88865], [6.43341, 46.92703], [6.71531, 47.0494], [6.68823, 47.06616], [6.76788, 47.1208], [6.8489, 47.15933], [6.9508, 47.24338], [6.95108, 47.26428], [6.94316, 47.28747], [7.05305, 47.33304], [7.0564, 47.35134], [7.03125, 47.36996], [6.87959, 47.35335], [6.88542, 47.37262], [6.93744, 47.40714], [6.93953, 47.43388], [7.0024, 47.45264], [6.98425, 47.49432], [7.0231, 47.50522], [7.07425, 47.48863], [7.12781, 47.50371], [7.16249, 47.49025], [7.19583, 47.49455], [7.17026, 47.44312], [7.24669, 47.4205], [7.33526, 47.44186], [7.35603, 47.43432], [7.40308, 47.43638], [7.43088, 47.45846], [7.4462, 47.46264], [7.4583, 47.47216], [7.42923, 47.48628], [7.43356, 47.49712], [7.47534, 47.47932], [7.51076, 47.49651], [7.49804, 47.51798], [7.5229, 47.51644], [7.53199, 47.5284], [7.51904, 47.53515], [7.50588, 47.52856], [7.49691, 47.53821], [7.50873, 47.54546], [7.51723, 47.54578], [7.52831, 47.55347], [7.53634, 47.55553], [7.55652, 47.56779], [7.55689, 47.57232], [7.56548, 47.57617], [7.56684, 47.57785], [7.58386, 47.57536], [7.58945, 47.59017], [7.59301, 47.60058], [7.58851, 47.60794], [7.57423, 47.61628], [7.5591, 47.63849], [7.53384, 47.65115], [7.52067, 47.66437], [7.51915, 47.68335], [7.51266, 47.70197], [7.53722, 47.71635], [7.54761, 47.72912], [7.52921, 47.77747], [7.55673, 47.87371], [7.62302, 47.97898], [7.56966, 48.03265], [7.57137, 48.12292], [7.6648, 48.22219], [7.69022, 48.30018], [7.74562, 48.32736], [7.73109, 48.39192], [7.76833, 48.48945], [7.80647, 48.51239], [7.80167, 48.54758], [7.80057, 48.5857], [7.84098, 48.64217], [7.89002, 48.66317], [7.96812, 48.72491], [7.96994, 48.75606], [8.01534, 48.76085], [8.0326, 48.79017], [8.06802, 48.78957], [8.10253, 48.81829], [8.12813, 48.87985], [8.19989, 48.95825], [8.20031, 48.95856], [8.22604, 48.97352], [8.14189, 48.97833], [7.97783, 49.03161], [7.93641, 49.05544], [7.86386, 49.03499], [7.79557, 49.06583], [7.75948, 49.04562], [7.63618, 49.05428], [7.62575, 49.07654], [7.56416, 49.08136], [7.53012, 49.09818], [7.49172, 49.13915], [7.49473, 49.17], [7.44455, 49.16765], [7.44052, 49.18354], [7.3662, 49.17308], [7.35995, 49.14399], [7.3195, 49.14231], [7.29514, 49.11426], [7.23473, 49.12971], [7.1593, 49.1204], [7.1358, 49.1282], [7.12504, 49.14253], [7.10384, 49.13787], [7.10715, 49.15631], [7.07859, 49.15031], [7.09007, 49.13094], [7.07162, 49.1255], [7.06642, 49.11415], [7.05548, 49.11185], [7.04843, 49.11422], [7.04409, 49.12123], [7.04662, 49.13724], [7.03178, 49.15734], [7.0274, 49.17042], [7.03459, 49.19096], [7.01318, 49.19018], [6.97273, 49.2099], [6.95963, 49.203], [6.94028, 49.21641], [6.93831, 49.2223], [6.91875, 49.22261], [6.89298, 49.20863], [6.85939, 49.22376], [6.83555, 49.21249], [6.85119, 49.20038], [6.85016, 49.19354], [6.86225, 49.18185], [6.84703, 49.15734], [6.83385, 49.15162], [6.78265, 49.16793], [6.73765, 49.16375], [6.71137, 49.18808], [6.73256, 49.20486], [6.71843, 49.2208], [6.69274, 49.21661], [6.66583, 49.28065], [6.60186, 49.31055], [6.572, 49.35027], [6.58807, 49.35358], [6.60091, 49.36864], [6.533, 49.40748], [6.55404, 49.42464], [6.42432, 49.47683], [6.40274, 49.46546], [6.39168, 49.4667], [6.38352, 49.46463], [6.36778, 49.46937], [6.3687, 49.4593], [6.28818, 49.48465], [6.27875, 49.503], [6.25029, 49.50609], [6.2409, 49.51408], [6.19543, 49.50536], [6.17386, 49.50934], [6.15366, 49.50226], [6.16115, 49.49297], [6.14321, 49.48796], [6.12814, 49.49365], [6.12346, 49.4735], [6.10325, 49.4707], [6.09845, 49.46351], [6.10072, 49.45268], [6.08373, 49.45594], [6.07887, 49.46399], [6.05553, 49.46663], [6.04176, 49.44801], [6.02743, 49.44845], [6.02648, 49.45451], [5.97693, 49.45513], [5.96876, 49.49053], [5.94224, 49.49608], [5.94128, 49.50034], [5.86571, 49.50015], [5.83389, 49.52152], [5.83467, 49.52717], [5.84466, 49.53027], [5.83648, 49.5425], [5.81664, 49.53775], [5.80871, 49.5425], [5.81838, 49.54777], [5.79195, 49.55228], [5.77435, 49.56298], [5.7577, 49.55915], [5.75649, 49.54321], [5.64505, 49.55146], [5.60909, 49.51228], [5.55001, 49.52729], [5.46541, 49.49825], [5.46734, 49.52648], [5.43713, 49.5707], [5.3974, 49.61596], [5.34837, 49.62889], [5.33851, 49.61599], [5.3137, 49.61225], [5.30214, 49.63055], [5.33039, 49.6555], [5.31465, 49.66846], [5.26232, 49.69456], [5.14545, 49.70287], [5.09249, 49.76193], [4.96714, 49.79872], [4.85464, 49.78995], [4.86965, 49.82271], [4.85134, 49.86457], [4.88529, 49.9236], [4.78827, 49.95609], [4.8382, 50.06738], [4.88602, 50.15182], [4.83279, 50.15331], [4.82438, 50.16878], [4.75237, 50.11314], [4.70064, 50.09384], [4.68695, 49.99685], [4.5414, 49.96911], [4.51098, 49.94659], [4.43488, 49.94122], [4.35051, 49.95315], [4.31963, 49.97043], [4.20532, 49.95803], [4.14239, 49.98034], [4.13508, 50.01976], [4.16294, 50.04719], [4.23101, 50.06945], [4.20147, 50.13535], [4.13561, 50.13078], [4.16014, 50.19239], [4.15524, 50.21103], [4.21945, 50.25539], [4.20651, 50.27333], [4.17861, 50.27443], [4.17347, 50.28838], [4.15524, 50.2833], [4.16808, 50.25786], [4.13665, 50.25609], [4.11954, 50.30425], [4.10957, 50.30234], [4.10237, 50.31247], [4.0689, 50.3254], [4.0268, 50.35793], [3.96771, 50.34989], [3.90781, 50.32814], [3.84314, 50.35219], [3.73911, 50.34809], [3.70987, 50.3191], [3.71009, 50.30305], [3.66976, 50.34563], [3.65709, 50.36873], [3.67262, 50.38663], [3.67494, 50.40239], [3.66153, 50.45165], [3.64426, 50.46275], [3.61014, 50.49568], [3.58361, 50.49049], [3.5683, 50.50192], [3.49509, 50.48885], [3.51564, 50.5256], [3.47385, 50.53397], [3.44629, 50.51009], [3.37693, 50.49538], [3.28575, 50.52724], [3.2729, 50.60718], [3.23951, 50.6585], [3.264, 50.67668], [3.2536, 50.68977], [3.26141, 50.69151], [3.26063, 50.70086], [3.24593, 50.71389], [3.22042, 50.71019], [3.20845, 50.71662], [3.19017, 50.72569], [3.20064, 50.73547], [3.18811, 50.74025], [3.18339, 50.74981], [3.16476, 50.76843], [3.15017, 50.79031], [3.1257, 50.78603], [3.11987, 50.79188], [3.11206, 50.79416], [3.10614, 50.78303], [3.09163, 50.77717], [3.04314, 50.77674], [3.00537, 50.76588], [2.96778, 50.75242], [2.95019, 50.75138], [2.90873, 50.702], [2.91036, 50.6939], [2.90069, 50.69263], [2.88504, 50.70656], [2.87937, 50.70298], [2.86985, 50.7033], [2.8483, 50.72276], [2.81056, 50.71773], [2.71165, 50.81295], [2.63331, 50.81457], [2.59093, 50.91751], [2.63074, 50.94746], [2.57551, 51.00326], [2.55904, 51.07014]], [[1.99838, 42.44682], [1.98378, 42.44697], [1.96125, 42.45364], [1.95606, 42.45785], [1.96215, 42.47854], [1.97003, 42.48081], [1.97227, 42.48487], [1.97697, 42.48568], [1.98022, 42.49569], [1.98916, 42.49351], [1.99766, 42.4858], [1.98579, 42.47486], [1.99216, 42.46208], [2.01564, 42.45171], [1.99838, 42.44682]]]]
24833 groups: ["017", "202", "002", "UN"],
24834 callingCodes: ["241"]
24837 type: "MultiPolygon",
24838 coordinates: [[[[13.29457, 2.16106], [13.28534, 2.25716], [11.37116, 2.29975], [11.3561, 2.17217], [11.35307, 1.00251], [9.79648, 1.0019], [9.75065, 1.06753], [9.66433, 1.06723], [7.24416, -0.64092], [10.75913, -4.39519], [11.12647, -3.94169], [11.22301, -3.69888], [11.48764, -3.51089], [11.57949, -3.52798], [11.68608, -3.68942], [11.87083, -3.71571], [11.92719, -3.62768], [11.8318, -3.5812], [11.96554, -3.30267], [11.70227, -3.17465], [11.70558, -3.0773], [11.80365, -3.00424], [11.64798, -2.81146], [11.5359, -2.85654], [11.64487, -2.61865], [11.57637, -2.33379], [11.74605, -2.39936], [11.96866, -2.33559], [12.04895, -2.41704], [12.47925, -2.32626], [12.44656, -1.92025], [12.61312, -1.8129], [12.82172, -1.91091], [13.02759, -2.33098], [13.47977, -2.43224], [13.75884, -2.09293], [13.92073, -2.35581], [13.85846, -2.46935], [14.10442, -2.49268], [14.23829, -2.33715], [14.16202, -2.23916], [14.23518, -2.15671], [14.25932, -1.97624], [14.41838, -1.89412], [14.52569, -0.57818], [14.41887, -0.44799], [14.2165, -0.38261], [14.06862, -0.20826], [13.90632, -0.2287], [13.88648, 0.26652], [14.10909, 0.58563], [14.26066, 0.57255], [14.48179, 0.9152], [14.25186, 1.39842], [13.89582, 1.4261], [13.15519, 1.23368], [13.25447, 1.32339], [13.13461, 1.57238], [13.29457, 2.16106]]]]
24848 nameEn: "United Kingdom",
24861 groups: ["029", "003", "419", "019", "UN"],
24863 roadSpeedUnit: "mph",
24864 callingCodes: ["1 473"]
24867 type: "MultiPolygon",
24868 coordinates: [[[[-62.64026, 12.69984], [-61.77886, 11.36496], [-59.94058, 12.34011], [-62.64026, 12.69984]]]]
24878 groups: ["145", "142", "UN"],
24879 callingCodes: ["995"]
24882 type: "MultiPolygon",
24883 coordinates: [[[[46.42738, 41.91323], [45.61676, 42.20768], [45.78692, 42.48358], [45.36501, 42.55268], [45.15318, 42.70598], [44.88754, 42.74934], [44.80941, 42.61277], [44.70002, 42.74679], [44.54202, 42.75699], [43.95517, 42.55396], [43.73119, 42.62043], [43.81453, 42.74297], [43.0419, 43.02413], [43.03322, 43.08883], [42.75889, 43.19651], [42.66667, 43.13917], [42.40563, 43.23226], [41.64935, 43.22331], [40.65957, 43.56212], [40.10657, 43.57344], [40.04445, 43.47776], [40.03312, 43.44262], [40.01007, 43.42411], [40.01552, 43.42025], [40.00853, 43.40578], [40.0078, 43.38551], [39.81147, 43.06294], [40.89217, 41.72528], [41.54366, 41.52185], [41.7148, 41.4932], [41.7124, 41.47417], [41.81939, 41.43621], [41.95134, 41.52466], [42.26387, 41.49346], [42.51772, 41.43606], [42.59202, 41.58183], [42.72794, 41.59714], [42.84471, 41.58912], [42.78995, 41.50126], [42.84899, 41.47265], [42.8785, 41.50516], [43.02956, 41.37891], [43.21707, 41.30331], [43.13373, 41.25503], [43.1945, 41.25242], [43.23096, 41.17536], [43.36118, 41.2028], [43.44973, 41.17666], [43.4717, 41.12611], [43.67712, 41.13398], [43.74717, 41.1117], [43.84835, 41.16329], [44.16591, 41.19141], [44.18148, 41.24644], [44.32139, 41.2079], [44.34337, 41.20312], [44.34417, 41.2382], [44.46791, 41.18204], [44.59322, 41.1933], [44.61462, 41.24018], [44.72814, 41.20338], [44.82084, 41.21513], [44.87887, 41.20195], [44.89911, 41.21366], [44.84358, 41.23088], [44.81749, 41.23488], [44.80053, 41.25949], [44.81437, 41.30371], [44.93493, 41.25685], [45.0133, 41.29747], [45.09867, 41.34065], [45.1797, 41.42231], [45.26285, 41.46433], [45.31352, 41.47168], [45.4006, 41.42402], [45.45973, 41.45898], [45.68389, 41.3539], [45.71035, 41.36208], [45.75705, 41.35157], [45.69946, 41.29545], [45.80842, 41.2229], [45.95786, 41.17956], [46.13221, 41.19479], [46.27698, 41.19011], [46.37661, 41.10805], [46.456, 41.09984], [46.48558, 41.0576], [46.55096, 41.1104], [46.63969, 41.09515], [46.66148, 41.20533], [46.72375, 41.28609], [46.63658, 41.37727], [46.4669, 41.43331], [46.40307, 41.48464], [46.33925, 41.4963], [46.29794, 41.5724], [46.34126, 41.57454], [46.34039, 41.5947], [46.3253, 41.60912], [46.28182, 41.60089], [46.26531, 41.63339], [46.24429, 41.59883], [46.19759, 41.62327], [46.17891, 41.72094], [46.20538, 41.77205], [46.23962, 41.75811], [46.30863, 41.79133], [46.3984, 41.84399], [46.42738, 41.91323]]]]
24892 nameEn: "French Guiana",
24894 groups: ["Q3320166", "EU", "005", "419", "019", "UN"],
24895 callingCodes: ["594"]
24898 type: "MultiPolygon",
24899 coordinates: [[[[-51.35485, 4.8383], [-53.7094, 6.2264], [-54.01074, 5.68785], [-54.01877, 5.52789], [-54.26916, 5.26909], [-54.4717, 4.91964], [-54.38444, 4.13222], [-54.19367, 3.84387], [-54.05128, 3.63557], [-53.98914, 3.627], [-53.9849, 3.58697], [-54.28534, 2.67798], [-54.42864, 2.42442], [-54.6084, 2.32856], [-54.16286, 2.10779], [-53.78743, 2.34412], [-52.96539, 2.1881], [-52.6906, 2.37298], [-52.31787, 3.17896], [-51.85573, 3.83427], [-51.82312, 3.85825], [-51.79599, 3.89336], [-51.61983, 4.14596], [-51.63798, 4.51394], [-51.35485, 4.8383]]]]
24907 wikidata: "Q25230",
24908 nameEn: "Bailiwick of Guernsey",
24920 groups: ["011", "202", "002", "UN"],
24921 callingCodes: ["233"]
24924 type: "MultiPolygon",
24925 coordinates: [[[[-0.13493, 11.14075], [-0.27374, 11.17157], [-0.28566, 11.12713], [-0.35955, 11.07801], [-0.38219, 11.12596], [-0.42391, 11.11661], [-0.44298, 11.04292], [-0.61937, 10.91305], [-0.67143, 10.99811], [-2.83373, 11.0067], [-2.94232, 10.64281], [-2.83108, 10.40252], [-2.74174, 9.83172], [-2.76534, 9.56589], [-2.68802, 9.49343], [-2.69814, 9.22717], [-2.77799, 9.04949], [-2.66357, 9.01771], [-2.58243, 8.7789], [-2.49037, 8.20872], [-2.62901, 8.11495], [-2.61232, 8.02645], [-2.67787, 8.02055], [-2.74819, 7.92613], [-2.78395, 7.94974], [-2.79467, 7.86002], [-2.92339, 7.60847], [-2.97822, 7.27165], [-2.95438, 7.23737], [-3.23327, 6.81744], [-3.21954, 6.74407], [-3.25999, 6.62521], [-3.01896, 5.71697], [-2.95323, 5.71865], [-2.96671, 5.6415], [-2.93132, 5.62137], [-2.85378, 5.65156], [-2.76614, 5.60963], [-2.72737, 5.34789], [-2.77625, 5.34621], [-2.73074, 5.1364], [-2.75502, 5.10657], [-2.95261, 5.12477], [-2.96554, 5.10397], [-3.063, 5.13665], [-3.11073, 5.12675], [-3.10675, 5.08515], [-3.34019, 4.17519], [1.07031, 5.15655], [1.27574, 5.93551], [1.19771, 6.11522], [1.19966, 6.17069], [1.09187, 6.17074], [1.05969, 6.22998], [1.03108, 6.24064], [0.99652, 6.33779], [0.89283, 6.33779], [0.71048, 6.53083], [0.74862, 6.56517], [0.63659, 6.63857], [0.6497, 6.73682], [0.58176, 6.76049], [0.57406, 6.80348], [0.52853, 6.82921], [0.56508, 6.92971], [0.52098, 6.94391], [0.52217, 6.9723], [0.59606, 7.01252], [0.65327, 7.31643], [0.62943, 7.41099], [0.57223, 7.39326], [0.52455, 7.45354], [0.51979, 7.58706], [0.58295, 7.62368], [0.62943, 7.85751], [0.58891, 8.12779], [0.6056, 8.13959], [0.61156, 8.18324], [0.5913, 8.19622], [0.63897, 8.25873], [0.73432, 8.29529], [0.64731, 8.48866], [0.47211, 8.59945], [0.37319, 8.75262], [0.52455, 8.87746], [0.45424, 9.04581], [0.56388, 9.40697], [0.49118, 9.48339], [0.36485, 9.49749], [0.33148, 9.44812], [0.25758, 9.42696], [0.2254, 9.47869], [0.31241, 9.50337], [0.30406, 9.521], [0.2409, 9.52335], [0.23851, 9.57389], [0.38153, 9.58682], [0.36008, 9.6256], [0.29334, 9.59387], [0.26712, 9.66437], [0.28261, 9.69022], [0.32313, 9.6491], [0.34816, 9.66907], [0.34816, 9.71607], [0.32075, 9.72781], [0.36366, 10.03309], [0.41252, 10.02018], [0.41371, 10.06361], [0.35293, 10.09412], [0.39584, 10.31112], [0.33028, 10.30408], [0.29453, 10.41546], [0.18846, 10.4096], [0.12886, 10.53149], [-0.05945, 10.63458], [-0.09141, 10.7147], [-0.07327, 10.71845], [-0.07183, 10.76794], [-0.0228, 10.81916], [-0.02685, 10.8783], [-908e-5, 10.91644], [-63e-4, 10.96417], [0.03355, 10.9807], [0.02395, 11.06229], [342e-5, 11.08317], [-514e-5, 11.10763], [-0.0275, 11.11202], [-0.05733, 11.08628], [-0.14462, 11.10811], [-0.13493, 11.14075]]]]
24934 nameEn: "Gibraltar",
24936 groups: ["Q12837", "BOTS", "039", "150", "UN"],
24937 callingCodes: ["350"]
24940 type: "MultiPolygon",
24941 coordinates: [[[[-5.34064, 36.03744], [-5.27801, 36.14942], [-5.33822, 36.15272], [-5.34536, 36.15501], [-5.40526, 36.15488], [-5.34064, 36.03744]]]]
24950 nameEn: "Greenland",
24952 groups: ["Q1451600", "021", "003", "019", "UN"],
24953 callingCodes: ["299"]
24956 type: "MultiPolygon",
24957 coordinates: [[[[-49.33696, 84.57952], [-68.21821, 80.48551], [-77.52957, 77.23408], [-46.37635, 57.3249], [-9.68082, 72.73731], [-5.7106, 84.28058], [-49.33696, 84.57952]]]]
24966 nameEn: "The Gambia",
24967 groups: ["011", "202", "002", "UN"],
24968 callingCodes: ["220"]
24971 type: "MultiPolygon",
24972 coordinates: [[[[-15.14917, 13.57989], [-14.36795, 13.23033], [-13.79409, 13.34472], [-13.8955, 13.59126], [-14.34721, 13.46578], [-14.93719, 13.80173], [-15.36504, 13.79313], [-15.47902, 13.58758], [-17.43598, 13.59273], [-17.43966, 13.04579], [-16.74676, 13.06025], [-16.69343, 13.16791], [-15.80355, 13.16729], [-15.80478, 13.34832], [-15.26908, 13.37768], [-15.14917, 13.57989]]]]
24982 groups: ["011", "202", "002", "UN"],
24983 callingCodes: ["224"]
24986 type: "MultiPolygon",
24987 coordinates: [[[[-11.37536, 12.40788], [-11.46267, 12.44559], [-11.91331, 12.42008], [-12.35415, 12.32758], [-12.87336, 12.51892], [-13.06603, 12.49342], [-13.05296, 12.64003], [-13.70523, 12.68013], [-13.7039, 12.60313], [-13.65089, 12.49515], [-13.64168, 12.42764], [-13.70851, 12.24978], [-13.92745, 12.24077], [-13.94589, 12.16869], [-13.7039, 12.00869], [-13.7039, 11.70195], [-14.09799, 11.63649], [-14.26623, 11.67486], [-14.31513, 11.60713], [-14.51173, 11.49708], [-14.66677, 11.51188], [-14.77786, 11.36323], [-14.95993, 10.99244], [-15.07174, 10.89557], [-15.96748, 10.162], [-14.36218, 8.64107], [-13.29911, 9.04245], [-13.18586, 9.0925], [-13.08953, 9.0409], [-12.94095, 9.26335], [-12.76788, 9.3133], [-12.47254, 9.86834], [-12.24262, 9.92386], [-12.12634, 9.87203], [-11.91023, 9.93927], [-11.89624, 9.99763], [-11.2118, 10.00098], [-10.6534, 9.29919], [-10.74484, 9.07998], [-10.5783, 9.06386], [-10.56197, 8.81225], [-10.47707, 8.67669], [-10.61422, 8.5314], [-10.70565, 8.29235], [-10.63934, 8.35326], [-10.54891, 8.31174], [-10.37257, 8.48941], [-10.27575, 8.48711], [-10.203, 8.47991], [-10.14579, 8.52665], [-10.05375, 8.50697], [-10.05873, 8.42578], [-9.77763, 8.54633], [-9.47415, 8.35195], [-9.50898, 8.18455], [-9.41445, 8.02448], [-9.44928, 7.9284], [-9.35724, 7.74111], [-9.37465, 7.62032], [-9.48161, 7.37122], [-9.41943, 7.41809], [-9.305, 7.42056], [-9.20798, 7.38109], [-9.18311, 7.30461], [-9.09107, 7.1985], [-8.93435, 7.2824], [-8.85724, 7.26019], [-8.8448, 7.35149], [-8.72789, 7.51429], [-8.67814, 7.69428], [-8.55874, 7.70167], [-8.55874, 7.62525], [-8.47114, 7.55676], [-8.4003, 7.6285], [-8.21374, 7.54466], [-8.09931, 7.78626], [-8.13414, 7.87991], [-8.06449, 8.04989], [-7.94695, 8.00925], [-7.99919, 8.11023], [-7.98675, 8.20134], [-8.062, 8.16071], [-8.2411, 8.24196], [-8.22991, 8.48438], [-7.92518, 8.50652], [-7.65653, 8.36873], [-7.69882, 8.66148], [-7.95503, 8.81146], [-7.92518, 8.99332], [-7.73862, 9.08422], [-7.90777, 9.20456], [-7.85056, 9.41812], [-8.03463, 9.39604], [-8.14657, 9.55062], [-8.09434, 9.86936], [-8.15652, 9.94288], [-8.11921, 10.04577], [-8.01225, 10.1021], [-7.97971, 10.17117], [-7.9578, 10.2703], [-8.10207, 10.44649], [-8.22711, 10.41722], [-8.32614, 10.69273], [-8.2667, 10.91762], [-8.35083, 11.06234], [-8.66923, 10.99397], [-8.40058, 11.37466], [-8.80854, 11.66715], [-8.94784, 12.34842], [-9.13689, 12.50875], [-9.38067, 12.48446], [-9.32097, 12.29009], [-9.63938, 12.18312], [-9.714, 12.0226], [-10.30604, 12.24634], [-10.71897, 11.91552], [-10.80355, 12.1053], [-10.99758, 12.24634], [-11.24136, 12.01286], [-11.50006, 12.17826], [-11.37536, 12.40788]]]]
24995 wikidata: "Q17012",
24996 nameEn: "Guadeloupe",
24998 groups: ["Q3320166", "EU", "029", "003", "419", "019", "UN"],
24999 callingCodes: ["590"]
25002 type: "MultiPolygon",
25003 coordinates: [[[[-60.03183, 16.1129], [-61.60296, 16.73066], [-63.00549, 15.26166], [-60.03183, 16.1129]]]]
25012 nameEn: "Equatorial Guinea",
25013 groups: ["017", "202", "002", "UN"],
25014 callingCodes: ["240"]
25017 type: "MultiPolygon",
25018 coordinates: [[[[9.22018, 3.72052], [8.34397, 4.30689], [7.71762, 0.6674], [3.35016, -3.29031], [9.66433, 1.06723], [9.75065, 1.06753], [9.79648, 1.0019], [11.35307, 1.00251], [11.3561, 2.17217], [9.991, 2.16561], [9.90749, 2.20049], [9.89012, 2.20457], [9.84716, 2.24676], [9.83238, 2.29079], [9.83754, 2.32428], [9.82123, 2.35097], [9.81162, 2.33797], [9.22018, 3.72052]]]]
25029 groups: ["EU", "039", "150", "UN"],
25030 callingCodes: ["30"]
25033 type: "MultiPolygon",
25034 coordinates: [[[[26.03489, 40.73051], [26.0754, 40.72772], [26.08638, 40.73214], [26.12495, 40.74283], [26.12854, 40.77339], [26.15685, 40.80709], [26.21351, 40.83298], [26.20856, 40.86048], [26.26169, 40.9168], [26.29441, 40.89119], [26.28623, 40.93005], [26.32259, 40.94042], [26.35894, 40.94292], [26.33297, 40.98388], [26.3606, 41.02027], [26.31928, 41.07386], [26.32259, 41.24929], [26.39861, 41.25053], [26.5209, 41.33993], [26.5837, 41.32131], [26.62997, 41.34613], [26.61767, 41.42281], [26.59742, 41.48058], [26.59196, 41.60491], [26.5209, 41.62592], [26.47958, 41.67037], [26.35957, 41.71149], [26.30255, 41.70925], [26.2654, 41.71544], [26.22888, 41.74139], [26.21325, 41.73223], [26.16841, 41.74858], [26.06148, 41.70345], [26.07083, 41.64584], [26.15146, 41.60828], [26.14328, 41.55496], [26.17951, 41.55409], [26.176, 41.50072], [26.14796, 41.47533], [26.20288, 41.43943], [26.16548, 41.42278], [26.12926, 41.35878], [25.87919, 41.30526], [25.8266, 41.34563], [25.70507, 41.29209], [25.66183, 41.31316], [25.61042, 41.30614], [25.55082, 41.31667], [25.52394, 41.2798], [25.48187, 41.28506], [25.28322, 41.23411], [25.11611, 41.34212], [24.942, 41.38685], [24.90928, 41.40876], [24.86136, 41.39298], [24.82514, 41.4035], [24.8041, 41.34913], [24.71529, 41.41928], [24.61129, 41.42278], [24.52599, 41.56808], [24.30513, 41.51297], [24.27124, 41.57682], [24.18126, 41.51735], [24.10063, 41.54796], [24.06323, 41.53222], [24.06908, 41.46132], [23.96975, 41.44118], [23.91483, 41.47971], [23.89613, 41.45257], [23.80148, 41.43943], [23.76525, 41.40175], [23.67644, 41.41139], [23.63203, 41.37632], [23.52453, 41.40262], [23.40416, 41.39999], [23.33639, 41.36317], [23.31301, 41.40525], [23.22771, 41.37106], [23.21953, 41.33773], [23.1833, 41.31755], [22.93334, 41.34104], [22.81199, 41.3398], [22.76408, 41.32225], [22.74538, 41.16321], [22.71266, 41.13945], [22.65306, 41.18168], [22.62852, 41.14385], [22.58295, 41.11568], [22.5549, 41.13065], [22.42285, 41.11921], [22.26744, 41.16409], [22.17629, 41.15969], [22.1424, 41.12449], [22.06527, 41.15617], [21.90869, 41.09191], [21.91102, 41.04786], [21.7556, 40.92525], [21.69601, 40.9429], [21.57448, 40.86076], [21.53007, 40.90759], [21.41555, 40.9173], [21.35595, 40.87578], [21.25779, 40.86165], [21.21105, 40.8855], [21.15262, 40.85546], [20.97887, 40.85475], [20.98396, 40.79109], [20.95752, 40.76982], [20.98134, 40.76046], [21.05833, 40.66586], [21.03932, 40.56299], [20.96908, 40.51526], [20.94925, 40.46625], [20.83688, 40.47882], [20.7906, 40.42726], [20.78234, 40.35803], [20.71789, 40.27739], [20.67162, 40.09433], [20.62566, 40.0897], [20.61081, 40.07866], [20.55593, 40.06524], [20.51297, 40.08168], [20.48487, 40.06271], [20.42373, 40.06777], [20.37911, 39.99058], [20.31135, 39.99438], [20.41546, 39.82832], [20.41475, 39.81437], [20.38572, 39.78516], [20.30804, 39.81563], [20.29152, 39.80421], [20.31961, 39.72799], [20.27412, 39.69884], [20.22707, 39.67459], [20.22376, 39.64532], [20.15988, 39.652], [20.12956, 39.65805], [20.05189, 39.69112], [20.00957, 39.69227], [19.98042, 39.6504], [19.92466, 39.69533], [19.97622, 39.78684], [19.95905, 39.82857], [19.0384, 40.35325], [19.20409, 39.7532], [22.5213, 33.45682], [29.73302, 35.92555], [29.69611, 36.10365], [29.61805, 36.14179], [29.61002, 36.1731], [29.48192, 36.18377], [29.30783, 36.01033], [28.23708, 36.56812], [27.95037, 36.46155], [27.89482, 36.69898], [27.46117, 36.53789], [27.24613, 36.71622], [27.45627, 36.9008], [27.20312, 36.94571], [27.14757, 37.32], [26.95583, 37.64989], [26.99377, 37.69034], [27.16428, 37.72343], [27.05537, 37.9131], [26.21136, 38.17558], [26.24183, 38.44695], [26.32173, 38.48731], [26.21136, 38.65436], [26.61814, 38.81372], [26.70773, 39.0312], [26.43357, 39.43096], [25.94257, 39.39358], [25.61285, 40.17161], [26.04292, 40.3958], [25.94795, 40.72797], [26.03489, 40.73051]]]]
25042 wikidata: "Q35086",
25043 nameEn: "South Georgia and South Sandwich Islands",
25045 groups: ["BOTS", "005", "419", "019", "UN"],
25047 roadSpeedUnit: "mph",
25048 roadHeightUnit: "ft",
25049 callingCodes: ["500"]
25052 type: "MultiPolygon",
25053 coordinates: [[[[-35.26394, -43.68272], [-53.39656, -59.87088], [-22.31757, -59.85974], [-35.26394, -43.68272]]]]
25062 nameEn: "Guatemala",
25063 groups: ["013", "003", "419", "019", "UN"],
25064 callingCodes: ["502"]
25067 type: "MultiPolygon",
25068 coordinates: [[[[-89.14985, 17.81563], [-90.98678, 17.81655], [-90.99199, 17.25192], [-91.43809, 17.25373], [-91.04436, 16.92175], [-90.69064, 16.70697], [-90.61212, 16.49832], [-90.40499, 16.40524], [-90.44567, 16.07573], [-91.73182, 16.07371], [-92.20983, 15.26077], [-92.0621, 15.07406], [-92.1454, 14.98143], [-92.1423, 14.88647], [-92.18161, 14.84147], [-92.1454, 14.6804], [-92.2261, 14.53423], [-92.37213, 14.39277], [-90.55276, 12.8866], [-90.11344, 13.73679], [-90.10505, 13.85104], [-89.88937, 14.0396], [-89.81807, 14.07073], [-89.76103, 14.02923], [-89.73251, 14.04133], [-89.75569, 14.07073], [-89.70756, 14.1537], [-89.61844, 14.21937], [-89.52397, 14.22628], [-89.50614, 14.26084], [-89.58814, 14.33165], [-89.57441, 14.41637], [-89.39028, 14.44561], [-89.34776, 14.43013], [-89.35189, 14.47553], [-89.23719, 14.58046], [-89.15653, 14.57802], [-89.13132, 14.71582], [-89.23467, 14.85596], [-89.15149, 14.97775], [-89.18048, 14.99967], [-89.15149, 15.07392], [-88.97343, 15.14039], [-88.32467, 15.63665], [-88.31459, 15.66942], [-88.24022, 15.69247], [-88.22552, 15.72294], [-88.20359, 16.03858], [-88.40779, 16.09624], [-88.95358, 15.88698], [-89.02415, 15.9063], [-89.17418, 15.90898], [-89.22683, 15.88619], [-89.15025, 17.04813], [-89.14985, 17.81563]]]]
25076 wikidata: "Q16635",
25078 aliases: ["US-GU"],
25080 groups: ["Q1352230", "Q153732", "057", "009", "UN"],
25081 roadSpeedUnit: "mph",
25082 roadHeightUnit: "ft",
25083 callingCodes: ["1 671"]
25086 type: "MultiPolygon",
25087 coordinates: [[[[146.25931, 13.85876], [143.82485, 13.92273], [144.61642, 12.82462], [146.25931, 13.85876]]]]
25096 nameEn: "Guinea-Bissau",
25097 groups: ["011", "202", "002", "UN"],
25098 callingCodes: ["245"]
25101 type: "MultiPolygon",
25102 coordinates: [[[[-14.31513, 11.60713], [-14.26623, 11.67486], [-14.09799, 11.63649], [-13.7039, 11.70195], [-13.7039, 12.00869], [-13.94589, 12.16869], [-13.92745, 12.24077], [-13.70851, 12.24978], [-13.64168, 12.42764], [-13.65089, 12.49515], [-13.7039, 12.60313], [-13.70523, 12.68013], [-15.17582, 12.6847], [-15.67302, 12.42974], [-16.20591, 12.46157], [-16.38191, 12.36449], [-16.70562, 12.34803], [-17.4623, 11.92379], [-15.96748, 10.162], [-15.07174, 10.89557], [-14.95993, 10.99244], [-14.77786, 11.36323], [-14.66677, 11.51188], [-14.51173, 11.49708], [-14.31513, 11.60713]]]]
25112 groups: ["005", "419", "019", "UN"],
25114 callingCodes: ["592"]
25117 type: "MultiPolygon",
25118 coordinates: [[[[-56.84822, 6.73257], [-59.54058, 8.6862], [-59.98508, 8.53046], [-59.85562, 8.35213], [-59.80661, 8.28906], [-59.83156, 8.23261], [-59.97059, 8.20791], [-60.02407, 8.04557], [-60.38056, 7.8302], [-60.51959, 7.83373], [-60.64793, 7.56877], [-60.71923, 7.55817], [-60.59802, 7.33194], [-60.63367, 7.25061], [-60.54098, 7.14804], [-60.44116, 7.20817], [-60.28074, 7.1162], [-60.39419, 6.94847], [-60.54873, 6.8631], [-61.13632, 6.70922], [-61.20762, 6.58174], [-61.15058, 6.19558], [-61.4041, 5.95304], [-60.73204, 5.20931], [-60.32352, 5.21299], [-60.20944, 5.28754], [-59.98129, 5.07097], [-60.04189, 4.69801], [-60.15953, 4.53456], [-59.78878, 4.45637], [-59.69361, 4.34069], [-59.73353, 4.20399], [-59.51963, 3.91951], [-59.86899, 3.57089], [-59.79769, 3.37162], [-59.99733, 2.92312], [-59.91177, 2.36759], [-59.7264, 2.27497], [-59.74066, 1.87596], [-59.25583, 1.40559], [-58.92072, 1.31293], [-58.84229, 1.17749], [-58.53571, 1.29154], [-58.4858, 1.48399], [-58.33887, 1.58014], [-58.01873, 1.51966], [-57.97336, 1.64566], [-57.77281, 1.73344], [-57.55743, 1.69605], [-57.35073, 1.98327], [-57.23981, 1.95808], [-57.09109, 2.01854], [-57.07092, 1.95304], [-56.7659, 1.89509], [-56.47045, 1.95135], [-56.55439, 2.02003], [-56.70519, 2.02964], [-57.35891, 3.32121], [-58.0307, 3.95513], [-57.8699, 4.89394], [-57.37442, 5.0208], [-57.22536, 5.15605], [-57.31629, 5.33714], [-56.84822, 6.73257]]]]
25127 nameEn: "Hong Kong",
25129 groups: ["030", "142", "UN"],
25131 callingCodes: ["852"]
25134 type: "MultiPolygon",
25135 coordinates: [[[[113.92195, 22.13873], [114.50148, 22.15017], [114.44998, 22.55977], [114.25154, 22.55977], [114.22888, 22.5436], [114.22185, 22.55343], [114.20655, 22.55706], [114.18338, 22.55444], [114.17247, 22.55944], [114.1597, 22.56041], [114.15123, 22.55163], [114.1482, 22.54091], [114.13823, 22.54319], [114.12665, 22.54003], [114.11656, 22.53415], [114.11181, 22.52878], [114.1034, 22.5352], [114.09692, 22.53435], [114.09048, 22.53716], [114.08606, 22.53276], [114.07817, 22.52997], [114.07267, 22.51855], [114.06272, 22.51617], [114.05729, 22.51104], [114.05438, 22.5026], [114.03113, 22.5065], [113.86771, 22.42972], [113.81621, 22.2163], [113.83338, 22.1826], [113.92195, 22.13873]]]]
25143 wikidata: "Q131198",
25144 nameEn: "Heard Island and McDonald Islands",
25146 groups: ["053", "009", "UN"],
25150 type: "MultiPolygon",
25151 coordinates: [[[[71.08716, -53.87687], [75.44182, -53.99822], [72.87012, -51.48322], [71.08716, -53.87687]]]]
25160 nameEn: "Honduras",
25161 groups: ["013", "003", "419", "019", "UN"],
25162 callingCodes: ["504"]
25165 type: "MultiPolygon",
25166 coordinates: [[[[-83.86109, 17.73736], [-88.20359, 16.03858], [-88.22552, 15.72294], [-88.24022, 15.69247], [-88.31459, 15.66942], [-88.32467, 15.63665], [-88.97343, 15.14039], [-89.15149, 15.07392], [-89.18048, 14.99967], [-89.15149, 14.97775], [-89.23467, 14.85596], [-89.13132, 14.71582], [-89.15653, 14.57802], [-89.23719, 14.58046], [-89.35189, 14.47553], [-89.34776, 14.43013], [-89.04187, 14.33644], [-88.94608, 14.20207], [-88.85785, 14.17763], [-88.815, 14.11652], [-88.73182, 14.10919], [-88.70661, 14.04317], [-88.49738, 13.97224], [-88.48982, 13.86458], [-88.25791, 13.91108], [-88.23018, 13.99915], [-88.07641, 13.98447], [-88.00331, 13.86948], [-87.7966, 13.91353], [-87.68821, 13.80829], [-87.73106, 13.75443], [-87.78148, 13.52906], [-87.71657, 13.50577], [-87.72115, 13.46083], [-87.73841, 13.44169], [-87.77354, 13.45767], [-87.83467, 13.44655], [-87.84675, 13.41078], [-87.80177, 13.35689], [-87.73714, 13.32715], [-87.69751, 13.25228], [-87.55124, 13.12523], [-87.37107, 12.98646], [-87.06306, 13.00892], [-87.03785, 12.98682], [-86.93197, 13.05313], [-86.93383, 13.18677], [-86.87066, 13.30641], [-86.71267, 13.30348], [-86.76812, 13.79605], [-86.35219, 13.77157], [-86.14801, 14.04317], [-86.00685, 14.08474], [-86.03458, 13.99181], [-85.75477, 13.8499], [-85.73964, 13.9698], [-85.45762, 14.11304], [-85.32149, 14.2562], [-85.18602, 14.24929], [-85.1575, 14.53934], [-84.90082, 14.80489], [-84.82596, 14.82212], [-84.70119, 14.68078], [-84.48373, 14.63249], [-84.10584, 14.76353], [-83.89551, 14.76697], [-83.62101, 14.89448], [-83.49268, 15.01158], [-83.13724, 15.00002], [-83.04763, 15.03256], [-82.06974, 14.49418], [-81.58685, 18.0025], [-83.86109, 17.73736]]]]
25176 groups: ["EU", "039", "150", "UN"],
25177 callingCodes: ["385"]
25180 type: "MultiPolygon",
25181 coordinates: [[[[17.6444, 42.88641], [17.5392, 42.92787], [17.70879, 42.97223], [17.64268, 43.08595], [17.46986, 43.16559], [17.286, 43.33065], [17.25579, 43.40353], [17.29699, 43.44542], [17.24411, 43.49376], [17.15828, 43.49376], [17.00585, 43.58037], [16.80736, 43.76011], [16.75316, 43.77157], [16.70922, 43.84887], [16.55472, 43.95326], [16.50528, 44.0244], [16.43629, 44.02826], [16.43662, 44.07523], [16.36864, 44.08263], [16.18688, 44.27012], [16.21346, 44.35231], [16.12969, 44.38275], [16.16814, 44.40679], [16.10566, 44.52586], [16.03012, 44.55572], [16.00884, 44.58605], [16.05828, 44.61538], [15.89348, 44.74964], [15.8255, 44.71501], [15.72584, 44.82334], [15.79472, 44.8455], [15.76096, 44.87045], [15.74723, 44.96818], [15.78568, 44.97401], [15.74585, 45.0638], [15.78842, 45.11519], [15.76371, 45.16508], [15.83512, 45.22459], [15.98412, 45.23088], [16.12153, 45.09616], [16.29036, 44.99732], [16.35404, 45.00241], [16.35863, 45.03529], [16.3749, 45.05206], [16.38219, 45.05139], [16.38309, 45.05955], [16.40023, 45.1147], [16.4634, 45.14522], [16.49155, 45.21153], [16.52982, 45.22713], [16.5501, 45.2212], [16.56559, 45.22307], [16.60194, 45.23042], [16.64962, 45.20714], [16.74845, 45.20393], [16.78219, 45.19002], [16.81137, 45.18434], [16.83804, 45.18951], [16.92405, 45.27607], [16.9385, 45.22742], [17.0415, 45.20759], [17.18438, 45.14764], [17.24325, 45.146], [17.25131, 45.14957], [17.26815, 45.18444], [17.32092, 45.16246], [17.33573, 45.14521], [17.41229, 45.13335], [17.4498, 45.16119], [17.45615, 45.12523], [17.47589, 45.12656], [17.51469, 45.10791], [17.59104, 45.10816], [17.66571, 45.13408], [17.84826, 45.04489], [17.87148, 45.04645], [17.93706, 45.08016], [17.97336, 45.12245], [17.97834, 45.13831], [17.99479, 45.14958], [18.01594, 45.15163], [18.03121, 45.12632], [18.1624, 45.07654], [18.24387, 45.13699], [18.32077, 45.1021], [18.41896, 45.11083], [18.47939, 45.05871], [18.65723, 45.07544], [18.78357, 44.97741], [18.80661, 44.93561], [18.76369, 44.93707], [18.76347, 44.90669], [18.8704, 44.85097], [19.01994, 44.85493], [18.98957, 44.90645], [19.02871, 44.92541], [19.06853, 44.89915], [19.15573, 44.95409], [19.05205, 44.97692], [19.1011, 45.01191], [19.07952, 45.14668], [19.14063, 45.12972], [19.19144, 45.17863], [19.43589, 45.17137], [19.41941, 45.23475], [19.28208, 45.23813], [19.10774, 45.29547], [18.97446, 45.37528], [18.99918, 45.49333], [19.08364, 45.48804], [19.07471, 45.53086], [18.94562, 45.53712], [18.88776, 45.57253], [18.96691, 45.66731], [18.90305, 45.71863], [18.85783, 45.85493], [18.81394, 45.91329], [18.80211, 45.87995], [18.6792, 45.92057], [18.57483, 45.80772], [18.44368, 45.73972], [18.12439, 45.78905], [18.08869, 45.76511], [17.99805, 45.79671], [17.87377, 45.78522], [17.66545, 45.84207], [17.56821, 45.93728], [17.35672, 45.95209], [17.14592, 46.16697], [16.8903, 46.28122], [16.8541, 46.36255], [16.7154, 46.39523], [16.6639, 46.45203], [16.59527, 46.47524], [16.52604, 46.47831], [16.5007, 46.49644], [16.44036, 46.5171], [16.38771, 46.53608], [16.37193, 46.55008], [16.29793, 46.5121], [16.26733, 46.51505], [16.26759, 46.50566], [16.23961, 46.49653], [16.25124, 46.48067], [16.27398, 46.42875], [16.27329, 46.41467], [16.30162, 46.40437], [16.30233, 46.37837], [16.18824, 46.38282], [16.14859, 46.40547], [16.05281, 46.39141], [16.05065, 46.3833], [16.07314, 46.36458], [16.07616, 46.3463], [15.97965, 46.30652], [15.79284, 46.25811], [15.78817, 46.21719], [15.75479, 46.20336], [15.75436, 46.21969], [15.67395, 46.22478], [15.6434, 46.21396], [15.64904, 46.19229], [15.59909, 46.14761], [15.6083, 46.11992], [15.62317, 46.09103], [15.72977, 46.04682], [15.71246, 46.01196], [15.70327, 46.00015], [15.70636, 45.92116], [15.67967, 45.90455], [15.68383, 45.88867], [15.68232, 45.86819], [15.70411, 45.8465], [15.66662, 45.84085], [15.64185, 45.82915], [15.57952, 45.84953], [15.52234, 45.82195], [15.47325, 45.8253], [15.47531, 45.79802], [15.40836, 45.79491], [15.25423, 45.72275], [15.30872, 45.69014], [15.34919, 45.71623], [15.4057, 45.64727], [15.38952, 45.63682], [15.34214, 45.64702], [15.34695, 45.63382], [15.31027, 45.6303], [15.27747, 45.60504], [15.29837, 45.5841], [15.30249, 45.53224], [15.38188, 45.48752], [15.33051, 45.45258], [15.27758, 45.46678], [15.16862, 45.42309], [15.05187, 45.49079], [15.02385, 45.48533], [14.92266, 45.52788], [14.90554, 45.47769], [14.81992, 45.45913], [14.80124, 45.49515], [14.71718, 45.53442], [14.68605, 45.53006], [14.69694, 45.57366], [14.59576, 45.62812], [14.60977, 45.66403], [14.57397, 45.67165], [14.53816, 45.6205], [14.5008, 45.60852], [14.49769, 45.54424], [14.36693, 45.48642], [14.32487, 45.47142], [14.27681, 45.4902], [14.26611, 45.48239], [14.24239, 45.50607], [14.22371, 45.50388], [14.20348, 45.46896], [14.07116, 45.48752], [14.00578, 45.52352], [13.96063, 45.50825], [13.99488, 45.47551], [13.97309, 45.45258], [13.90771, 45.45149], [13.88124, 45.42637], [13.81742, 45.43729], [13.7785, 45.46787], [13.67398, 45.4436], [13.62902, 45.45898], [13.56979, 45.4895], [13.45644, 45.59464], [13.05142, 45.33128], [13.12821, 44.48877], [16.15283, 42.18525], [18.45131, 42.21682], [18.54128, 42.39171], [18.52152, 42.42302], [18.43588, 42.48556], [18.44307, 42.51077], [18.43735, 42.55921], [18.36197, 42.61423], [18.24318, 42.6112], [17.88201, 42.83668], [17.80854, 42.9182], [17.7948, 42.89556], [17.68151, 42.92725], [17.6444, 42.88641]]]]
25192 groups: ["029", "003", "419", "019", "UN"],
25193 callingCodes: ["509"]
25196 type: "MultiPolygon",
25197 coordinates: [[[[-71.71885, 18.78423], [-71.72624, 18.87802], [-71.77766, 18.95007], [-71.88102, 18.95007], [-71.74088, 19.0437], [-71.71088, 19.08353], [-71.69938, 19.10916], [-71.65337, 19.11759], [-71.62642, 19.21212], [-71.73229, 19.26686], [-71.77766, 19.33823], [-71.69448, 19.37866], [-71.6802, 19.45008], [-71.71268, 19.53374], [-71.71449, 19.55364], [-71.7429, 19.58445], [-71.75865, 19.70231], [-71.77419, 19.73128], [-72.38946, 20.27111], [-73.37289, 20.43199], [-74.7289, 18.71009], [-74.76465, 18.06252], [-72.29523, 17.48026], [-71.75671, 18.03456], [-71.73783, 18.07177], [-71.74994, 18.11115], [-71.75465, 18.14405], [-71.78271, 18.18302], [-71.69952, 18.34101], [-71.90875, 18.45821], [-71.88102, 18.50125], [-72.00201, 18.62312], [-71.95412, 18.64939], [-71.82556, 18.62551], [-71.71885, 18.78423]]]]
25207 groups: ["EU", "151", "150", "UN"],
25208 callingCodes: ["36"]
25211 type: "MultiPolygon",
25212 coordinates: [[[[21.72525, 48.34628], [21.67134, 48.3989], [21.6068, 48.50365], [21.44063, 48.58456], [21.11516, 48.49546], [20.83248, 48.5824], [20.5215, 48.53336], [20.29943, 48.26104], [20.24312, 48.2784], [19.92452, 48.1283], [19.63338, 48.25006], [19.52489, 48.19791], [19.47957, 48.09437], [19.28182, 48.08336], [19.23924, 48.0595], [19.01952, 48.07052], [18.82176, 48.04206], [18.76134, 47.97499], [18.76821, 47.87469], [18.8506, 47.82308], [18.74074, 47.8157], [18.66521, 47.76772], [18.56496, 47.76588], [18.29305, 47.73541], [18.02938, 47.75665], [17.71215, 47.7548], [17.23699, 48.02094], [17.16001, 48.00636], [17.09786, 47.97336], [17.11022, 47.92461], [17.08275, 47.87719], [17.00997, 47.86245], [17.07039, 47.81129], [17.05048, 47.79377], [17.08893, 47.70928], [16.87538, 47.68895], [16.86509, 47.72268], [16.82938, 47.68432], [16.7511, 47.67878], [16.72089, 47.73469], [16.65679, 47.74197], [16.61183, 47.76171], [16.54779, 47.75074], [16.53514, 47.73837], [16.55129, 47.72268], [16.4222, 47.66537], [16.58699, 47.61772], [16.64193, 47.63114], [16.71059, 47.52692], [16.64821, 47.50155], [16.6718, 47.46139], [16.57152, 47.40868], [16.52414, 47.41007], [16.49908, 47.39416], [16.45104, 47.41181], [16.47782, 47.25918], [16.44142, 47.25079], [16.43663, 47.21127], [16.41739, 47.20649], [16.42801, 47.18422], [16.4523, 47.18812], [16.46442, 47.16845], [16.44932, 47.14418], [16.52863, 47.13974], [16.46134, 47.09395], [16.52176, 47.05747], [16.43936, 47.03548], [16.51369, 47.00084], [16.28202, 47.00159], [16.27594, 46.9643], [16.22403, 46.939], [16.19904, 46.94134], [16.10983, 46.867], [16.14365, 46.8547], [16.15711, 46.85434], [16.21892, 46.86961], [16.2365, 46.87775], [16.2941, 46.87137], [16.34547, 46.83836], [16.3408, 46.80641], [16.31303, 46.79838], [16.30966, 46.7787], [16.37816, 46.69975], [16.42641, 46.69228], [16.41863, 46.66238], [16.38594, 46.6549], [16.39217, 46.63673], [16.50139, 46.56684], [16.52885, 46.53303], [16.52604, 46.5051], [16.59527, 46.47524], [16.6639, 46.45203], [16.7154, 46.39523], [16.8541, 46.36255], [16.8903, 46.28122], [17.14592, 46.16697], [17.35672, 45.95209], [17.56821, 45.93728], [17.66545, 45.84207], [17.87377, 45.78522], [17.99805, 45.79671], [18.08869, 45.76511], [18.12439, 45.78905], [18.44368, 45.73972], [18.57483, 45.80772], [18.6792, 45.92057], [18.80211, 45.87995], [18.81394, 45.91329], [18.99712, 45.93537], [19.01284, 45.96529], [19.0791, 45.96458], [19.10388, 46.04015], [19.14543, 45.9998], [19.28826, 45.99694], [19.52473, 46.1171], [19.56113, 46.16824], [19.66007, 46.19005], [19.81491, 46.1313], [19.93508, 46.17553], [20.01816, 46.17696], [20.03533, 46.14509], [20.09713, 46.17315], [20.26068, 46.12332], [20.28324, 46.1438], [20.35573, 46.16629], [20.45377, 46.14405], [20.49718, 46.18721], [20.63863, 46.12728], [20.76085, 46.21002], [20.74574, 46.25467], [20.86797, 46.28884], [21.06572, 46.24897], [21.16872, 46.30118], [21.28061, 46.44941], [21.26929, 46.4993], [21.33214, 46.63035], [21.43926, 46.65109], [21.5151, 46.72147], [21.48935, 46.7577], [21.52028, 46.84118], [21.59307, 46.86935], [21.59581, 46.91628], [21.68645, 46.99595], [21.648, 47.03902], [21.78395, 47.11104], [21.94463, 47.38046], [22.01055, 47.37767], [22.03389, 47.42508], [22.00917, 47.50492], [22.31816, 47.76126], [22.41979, 47.7391], [22.46559, 47.76583], [22.67247, 47.7871], [22.76617, 47.8417], [22.77991, 47.87211], [22.89849, 47.95851], [22.84276, 47.98602], [22.87847, 48.04665], [22.81804, 48.11363], [22.73427, 48.12005], [22.66835, 48.09162], [22.58733, 48.10813], [22.59007, 48.15121], [22.49806, 48.25189], [22.38133, 48.23726], [22.2083, 48.42534], [22.14689, 48.4005], [21.83339, 48.36242], [21.8279, 48.33321], [21.72525, 48.34628]]]]
25219 nameEn: "Canary Islands",
25221 groups: ["Q3320166", "Q105472", "EU", "039", "150", "UN"],
25222 isoStatus: "excRes",
25223 callingCodes: ["34"]
25226 type: "MultiPolygon",
25227 coordinates: [[[[-12.00985, 30.24121], [-25.3475, 27.87574], [-14.43883, 27.02969], [-12.00985, 30.24121]]]]
25236 nameEn: "Indonesia",
25247 nameEn: "Republic of Ireland",
25248 groups: ["EU", "Q22890", "154", "150", "UN"],
25250 callingCodes: ["353"]
25253 type: "MultiPolygon",
25254 coordinates: [[[[-6.26218, 54.09785], [-6.29003, 54.11278], [-6.32694, 54.09337], [-6.36279, 54.11248], [-6.36605, 54.07234], [-6.47849, 54.06947], [-6.62842, 54.03503], [-6.66264, 54.0666], [-6.6382, 54.17071], [-6.70175, 54.20218], [-6.74575, 54.18788], [-6.81583, 54.22791], [-6.85179, 54.29176], [-6.87775, 54.34682], [-7.02034, 54.4212], [-7.19145, 54.31296], [-7.14908, 54.22732], [-7.25012, 54.20063], [-7.26316, 54.13863], [-7.29493, 54.12013], [-7.29687, 54.1354], [-7.28017, 54.16714], [-7.29157, 54.17191], [-7.34005, 54.14698], [-7.30553, 54.11869], [-7.32834, 54.11475], [-7.44567, 54.1539], [-7.4799, 54.12239], [-7.55812, 54.12239], [-7.69501, 54.20731], [-7.81397, 54.20159], [-7.8596, 54.21779], [-7.87101, 54.29299], [-8.04555, 54.36292], [-8.179, 54.46763], [-8.04538, 54.48941], [-7.99812, 54.54427], [-7.8596, 54.53671], [-7.70315, 54.62077], [-7.93293, 54.66603], [-7.83352, 54.73854], [-7.75041, 54.7103], [-7.64449, 54.75265], [-7.54671, 54.74606], [-7.54508, 54.79401], [-7.47626, 54.83084], [-7.4473, 54.87003], [-7.44404, 54.9403], [-7.40004, 54.94498], [-7.4033, 55.00391], [-7.34464, 55.04688], [-7.2471, 55.06933], [-6.34755, 55.49206], [-7.75229, 55.93854], [-22.01468, 48.19557], [-6.03913, 51.13217], [-5.37267, 53.63269], [-6.26218, 54.09785]]]]
25264 groups: ["145", "142", "UN"],
25265 callingCodes: ["972"]
25268 type: "MultiPolygon",
25269 coordinates: [[[[34.052, 31.46619], [34.29262, 31.70393], [34.48681, 31.59711], [34.56797, 31.54197], [34.48892, 31.48365], [34.40077, 31.40926], [34.36505, 31.36404], [34.37381, 31.30598], [34.36523, 31.28963], [34.29417, 31.24194], [34.26742, 31.21998], [34.92298, 29.45305], [34.97718, 29.54294], [34.98207, 29.58147], [35.02147, 29.66343], [35.14108, 30.07374], [35.19183, 30.34636], [35.16218, 30.43535], [35.19595, 30.50297], [35.21379, 30.60401], [35.29311, 30.71365], [35.33456, 30.81224], [35.33984, 30.8802], [35.41371, 30.95565], [35.43658, 31.12444], [35.40316, 31.25535], [35.47672, 31.49578], [35.39675, 31.49572], [35.22921, 31.37445], [35.13033, 31.3551], [35.02459, 31.35979], [34.92571, 31.34337], [34.88932, 31.37093], [34.87833, 31.39321], [34.89756, 31.43891], [34.93258, 31.47816], [34.94356, 31.50743], [34.9415, 31.55601], [34.95249, 31.59813], [35.00879, 31.65426], [35.08226, 31.69107], [35.10782, 31.71594], [35.11895, 31.71454], [35.12933, 31.7325], [35.13931, 31.73012], [35.15119, 31.73634], [35.15474, 31.73352], [35.16478, 31.73242], [35.18023, 31.72067], [35.20538, 31.72388], [35.21937, 31.71578], [35.22392, 31.71899], [35.23972, 31.70896], [35.24315, 31.71244], [35.2438, 31.7201], [35.24981, 31.72543], [35.25182, 31.73945], [35.26319, 31.74846], [35.25225, 31.7678], [35.26058, 31.79064], [35.25573, 31.81362], [35.26404, 31.82567], [35.251, 31.83085], [35.25753, 31.8387], [35.24816, 31.8458], [35.2304, 31.84222], [35.2249, 31.85433], [35.22817, 31.8638], [35.22567, 31.86745], [35.22294, 31.87889], [35.22014, 31.88264], [35.2136, 31.88241], [35.21276, 31.88153], [35.21016, 31.88237], [35.20945, 31.8815], [35.20791, 31.8821], [35.20673, 31.88151], [35.20381, 31.86716], [35.21128, 31.863], [35.216, 31.83894], [35.21469, 31.81835], [35.19461, 31.82687], [35.18169, 31.82542], [35.18603, 31.80901], [35.14174, 31.81325], [35.07677, 31.85627], [35.05617, 31.85685], [35.01978, 31.82944], [34.9724, 31.83352], [34.99712, 31.85569], [35.03489, 31.85919], [35.03978, 31.89276], [35.03489, 31.92448], [35.00124, 31.93264], [34.98682, 31.96935], [35.00261, 32.027], [34.9863, 32.09551], [34.99437, 32.10962], [34.98507, 32.12606], [34.99039, 32.14626], [34.96009, 32.17503], [34.95703, 32.19522], [34.98885, 32.20758], [35.01841, 32.23981], [35.02939, 32.2671], [35.01119, 32.28684], [35.01772, 32.33863], [35.04243, 32.35008], [35.05142, 32.3667], [35.0421, 32.38242], [35.05311, 32.4024], [35.05423, 32.41754], [35.07059, 32.4585], [35.08564, 32.46948], [35.09236, 32.47614], [35.10024, 32.47856], [35.10882, 32.4757], [35.15937, 32.50466], [35.2244, 32.55289], [35.25049, 32.52453], [35.29306, 32.50947], [35.30685, 32.51024], [35.35212, 32.52047], [35.40224, 32.50136], [35.42034, 32.46009], [35.41598, 32.45593], [35.41048, 32.43706], [35.42078, 32.41562], [35.55807, 32.38674], [35.55494, 32.42687], [35.57485, 32.48669], [35.56614, 32.64393], [35.59813, 32.65159], [35.61669, 32.67999], [35.66527, 32.681], [35.68467, 32.70715], [35.75983, 32.74803], [35.78745, 32.77938], [35.83758, 32.82817], [35.84021, 32.8725], [35.87012, 32.91976], [35.89298, 32.9456], [35.87188, 32.98028], [35.84802, 33.1031], [35.81911, 33.11077], [35.81911, 33.1336], [35.84285, 33.16673], [35.83846, 33.19397], [35.81647, 33.2028], [35.81295, 33.24841], [35.77513, 33.27342], [35.813, 33.3172], [35.77477, 33.33609], [35.62019, 33.27278], [35.62283, 33.24226], [35.58502, 33.26653], [35.58326, 33.28381], [35.56523, 33.28969], [35.55555, 33.25844], [35.54544, 33.25513], [35.54808, 33.236], [35.5362, 33.23196], [35.54228, 33.19865], [35.52573, 33.11921], [35.50335, 33.114], [35.50272, 33.09056], [35.448, 33.09264], [35.43059, 33.06659], [35.35223, 33.05617], [35.31429, 33.10515], [35.1924, 33.08743], [35.10645, 33.09318], [34.78515, 33.20368], [33.62659, 31.82938], [34.052, 31.46619]]]]
25278 nameEn: "Isle of Man",
25280 groups: ["Q185086", "154", "150", "UN"],
25282 roadSpeedUnit: "mph",
25283 roadHeightUnit: "ft",
25284 callingCodes: ["44 01624", "44 07624", "44 07524", "44 07924"]
25287 type: "MultiPolygon",
25288 coordinates: [[[[-3.98763, 54.07351], [-4.1819, 54.57861], [-5.6384, 53.81157], [-3.98763, 54.07351]]]]
25306 wikidata: "Q43448",
25307 nameEn: "British Indian Ocean Territory",
25319 groups: ["145", "142", "UN"],
25320 callingCodes: ["964"]
25323 type: "MultiPolygon",
25324 coordinates: [[[[42.78887, 37.38615], [42.56725, 37.14878], [42.35724, 37.10998], [42.36697, 37.0627], [41.81736, 36.58782], [41.40058, 36.52502], [41.28864, 36.35368], [41.2564, 36.06012], [41.37027, 35.84095], [41.38184, 35.62502], [41.26569, 35.42708], [41.21654, 35.1508], [41.2345, 34.80049], [41.12388, 34.65742], [40.97676, 34.39788], [40.64314, 34.31604], [38.79171, 33.37328], [39.08202, 32.50304], [38.98762, 32.47694], [39.04251, 32.30203], [39.26157, 32.35555], [39.29903, 32.23259], [40.01521, 32.05667], [42.97601, 30.72204], [42.97796, 30.48295], [44.72255, 29.19736], [46.42415, 29.05947], [46.5527, 29.10283], [46.89695, 29.50584], [47.15166, 30.01044], [47.37192, 30.10421], [47.7095, 30.10453], [48.01114, 29.98906], [48.06782, 30.02906], [48.17332, 30.02448], [48.40479, 29.85763], [48.59531, 29.66815], [48.83867, 29.78572], [48.61441, 29.93675], [48.51011, 29.96238], [48.44785, 30.00148], [48.4494, 30.04456], [48.43384, 30.08233], [48.38869, 30.11062], [48.38714, 30.13485], [48.41671, 30.17254], [48.41117, 30.19846], [48.26393, 30.3408], [48.24385, 30.33846], [48.21279, 30.31644], [48.19425, 30.32796], [48.18321, 30.39703], [48.14585, 30.44133], [48.02443, 30.4789], [48.03221, 30.9967], [47.68219, 31.00004], [47.6804, 31.39086], [47.86337, 31.78422], [47.64771, 32.07666], [47.52474, 32.15972], [47.57144, 32.20583], [47.37529, 32.47808], [47.17218, 32.45393], [46.46788, 32.91992], [46.32298, 32.9731], [46.17198, 32.95612], [46.09103, 32.98354], [46.15175, 33.07229], [46.03966, 33.09577], [46.05367, 33.13097], [46.11905, 33.11924], [46.20623, 33.20395], [45.99919, 33.5082], [45.86687, 33.49263], [45.96183, 33.55751], [45.89801, 33.63661], [45.77814, 33.60938], [45.50261, 33.94968], [45.42789, 33.9458], [45.41077, 33.97421], [45.47264, 34.03099], [45.56176, 34.15088], [45.58667, 34.30147], [45.53552, 34.35148], [45.49171, 34.3439], [45.46697, 34.38221], [45.43879, 34.45949], [45.51883, 34.47692], [45.53219, 34.60441], [45.59074, 34.55558], [45.60224, 34.55057], [45.73923, 34.54416], [45.70031, 34.69277], [45.65672, 34.7222], [45.68284, 34.76624], [45.70031, 34.82322], [45.73641, 34.83975], [45.79682, 34.85133], [45.78904, 34.91135], [45.86532, 34.89858], [45.89477, 34.95805], [45.87864, 35.03441], [45.92173, 35.0465], [45.92203, 35.09538], [45.93108, 35.08148], [45.94756, 35.09188], [46.06508, 35.03699], [46.07747, 35.0838], [46.11763, 35.07551], [46.19116, 35.11097], [46.15642, 35.1268], [46.16229, 35.16984], [46.19738, 35.18536], [46.18457, 35.22561], [46.11367, 35.23729], [46.15474, 35.2883], [46.13152, 35.32548], [46.05358, 35.38568], [45.98453, 35.49848], [46.01518, 35.52012], [45.97584, 35.58132], [46.03028, 35.57416], [46.01307, 35.59756], [46.0165, 35.61501], [45.99452, 35.63574], [46.0117, 35.65059], [46.01631, 35.69139], [46.23736, 35.71414], [46.34166, 35.78363], [46.32921, 35.82655], [46.17198, 35.8013], [46.08325, 35.8581], [45.94711, 35.82218], [45.89784, 35.83708], [45.81442, 35.82107], [45.76145, 35.79898], [45.6645, 35.92872], [45.60018, 35.96069], [45.55245, 35.99943], [45.46594, 36.00042], [45.38275, 35.97156], [45.33916, 35.99424], [45.37652, 36.06222], [45.37312, 36.09917], [45.32235, 36.17383], [45.30038, 36.27769], [45.26261, 36.3001], [45.27394, 36.35846], [45.23953, 36.43257], [45.11811, 36.40751], [45.00759, 36.5402], [45.06985, 36.62645], [45.06985, 36.6814], [45.01537, 36.75128], [44.84725, 36.77622], [44.83479, 36.81362], [44.90173, 36.86096], [44.91199, 36.91468], [44.89862, 37.01897], [44.81611, 37.04383], [44.75229, 37.11958], [44.78319, 37.1431], [44.76698, 37.16162], [44.63179, 37.19229], [44.42631, 37.05825], [44.38117, 37.05825], [44.35315, 37.04955], [44.35937, 37.02843], [44.30645, 36.97373], [44.25975, 36.98119], [44.18503, 37.09551], [44.22239, 37.15756], [44.27998, 37.16501], [44.2613, 37.25055], [44.13521, 37.32486], [44.02002, 37.33229], [43.90949, 37.22453], [43.84878, 37.22205], [43.82699, 37.19477], [43.8052, 37.22825], [43.7009, 37.23692], [43.63085, 37.21957], [43.56702, 37.25675], [43.50787, 37.24436], [43.33508, 37.33105], [43.30083, 37.30629], [43.11403, 37.37436], [42.93705, 37.32015], [42.78887, 37.38615]]]]
25334 groups: ["034", "142", "UN"],
25335 callingCodes: ["98"]
25338 type: "MultiPolygon",
25339 coordinates: [[[[44.96746, 39.42998], [44.88916, 39.59653], [44.81043, 39.62677], [44.71806, 39.71124], [44.65422, 39.72163], [44.6137, 39.78393], [44.47298, 39.68788], [44.48111, 39.61579], [44.41849, 39.56659], [44.42832, 39.4131], [44.37921, 39.4131], [44.29818, 39.378], [44.22452, 39.4169], [44.03667, 39.39223], [44.1043, 39.19842], [44.20946, 39.13975], [44.18863, 38.93881], [44.30322, 38.81581], [44.26155, 38.71427], [44.28065, 38.6465], [44.32058, 38.62752], [44.3207, 38.49799], [44.3119, 38.37887], [44.38309, 38.36117], [44.44386, 38.38295], [44.50115, 38.33939], [44.42476, 38.25763], [44.22509, 37.88859], [44.3883, 37.85433], [44.45948, 37.77065], [44.55498, 37.783], [44.62096, 37.71985], [44.56887, 37.6429], [44.61401, 37.60165], [44.58449, 37.45018], [44.81021, 37.2915], [44.75986, 37.21549], [44.7868, 37.16644], [44.78319, 37.1431], [44.75229, 37.11958], [44.81611, 37.04383], [44.89862, 37.01897], [44.91199, 36.91468], [44.90173, 36.86096], [44.83479, 36.81362], [44.84725, 36.77622], [45.01537, 36.75128], [45.06985, 36.6814], [45.06985, 36.62645], [45.00759, 36.5402], [45.11811, 36.40751], [45.23953, 36.43257], [45.27394, 36.35846], [45.26261, 36.3001], [45.30038, 36.27769], [45.32235, 36.17383], [45.37312, 36.09917], [45.37652, 36.06222], [45.33916, 35.99424], [45.38275, 35.97156], [45.46594, 36.00042], [45.55245, 35.99943], [45.60018, 35.96069], [45.6645, 35.92872], [45.76145, 35.79898], [45.81442, 35.82107], [45.89784, 35.83708], [45.94711, 35.82218], [46.08325, 35.8581], [46.17198, 35.8013], [46.32921, 35.82655], [46.34166, 35.78363], [46.23736, 35.71414], [46.01631, 35.69139], [46.0117, 35.65059], [45.99452, 35.63574], [46.0165, 35.61501], [46.01307, 35.59756], [46.03028, 35.57416], [45.97584, 35.58132], [46.01518, 35.52012], [45.98453, 35.49848], [46.05358, 35.38568], [46.13152, 35.32548], [46.15474, 35.2883], [46.11367, 35.23729], [46.18457, 35.22561], [46.19738, 35.18536], [46.16229, 35.16984], [46.15642, 35.1268], [46.19116, 35.11097], [46.11763, 35.07551], [46.07747, 35.0838], [46.06508, 35.03699], [45.94756, 35.09188], [45.93108, 35.08148], [45.92203, 35.09538], [45.92173, 35.0465], [45.87864, 35.03441], [45.89477, 34.95805], [45.86532, 34.89858], [45.78904, 34.91135], [45.79682, 34.85133], [45.73641, 34.83975], [45.70031, 34.82322], [45.68284, 34.76624], [45.65672, 34.7222], [45.70031, 34.69277], [45.73923, 34.54416], [45.60224, 34.55057], [45.59074, 34.55558], [45.53219, 34.60441], [45.51883, 34.47692], [45.43879, 34.45949], [45.46697, 34.38221], [45.49171, 34.3439], [45.53552, 34.35148], [45.58667, 34.30147], [45.56176, 34.15088], [45.47264, 34.03099], [45.41077, 33.97421], [45.42789, 33.9458], [45.50261, 33.94968], [45.77814, 33.60938], [45.89801, 33.63661], [45.96183, 33.55751], [45.86687, 33.49263], [45.99919, 33.5082], [46.20623, 33.20395], [46.11905, 33.11924], [46.05367, 33.13097], [46.03966, 33.09577], [46.15175, 33.07229], [46.09103, 32.98354], [46.17198, 32.95612], [46.32298, 32.9731], [46.46788, 32.91992], [47.17218, 32.45393], [47.37529, 32.47808], [47.57144, 32.20583], [47.52474, 32.15972], [47.64771, 32.07666], [47.86337, 31.78422], [47.6804, 31.39086], [47.68219, 31.00004], [48.03221, 30.9967], [48.02443, 30.4789], [48.14585, 30.44133], [48.18321, 30.39703], [48.19425, 30.32796], [48.21279, 30.31644], [48.24385, 30.33846], [48.26393, 30.3408], [48.41117, 30.19846], [48.41671, 30.17254], [48.38714, 30.13485], [48.38869, 30.11062], [48.43384, 30.08233], [48.4494, 30.04456], [48.44785, 30.00148], [48.51011, 29.96238], [48.61441, 29.93675], [48.83867, 29.78572], [49.98877, 27.87827], [50.37726, 27.89227], [54.39838, 25.68383], [55.14145, 25.62624], [55.81777, 26.18798], [56.2644, 26.58649], [56.68954, 26.76645], [56.79239, 26.41236], [56.82555, 25.7713], [56.86325, 25.03856], [61.46682, 24.57869], [61.6433, 25.27541], [61.683, 25.66638], [61.83968, 25.7538], [61.83831, 26.07249], [61.89391, 26.26251], [62.05117, 26.31647], [62.21304, 26.26601], [62.31484, 26.528], [62.77352, 26.64099], [63.1889, 26.65072], [63.18688, 26.83844], [63.25005, 26.84212], [63.25005, 27.08692], [63.32283, 27.14437], [63.19649, 27.25674], [62.80604, 27.22412], [62.79684, 27.34381], [62.84905, 27.47627], [62.7638, 28.02992], [62.79412, 28.28108], [62.59499, 28.24842], [62.40259, 28.42703], [61.93581, 28.55284], [61.65978, 28.77937], [61.53765, 29.00507], [61.31508, 29.38903], [60.87231, 29.86514], [61.80829, 30.84224], [61.78268, 30.92724], [61.8335, 30.97669], [61.83257, 31.0452], [61.80957, 31.12576], [61.80569, 31.16167], [61.70929, 31.37391], [60.84541, 31.49561], [60.86191, 32.22565], [60.56485, 33.12944], [60.88908, 33.50219], [60.91133, 33.55596], [60.69573, 33.56054], [60.57762, 33.59772], [60.5485, 33.73422], [60.5838, 33.80793], [60.50209, 34.13992], [60.66502, 34.31539], [60.91321, 34.30411], [60.72316, 34.52857], [60.99922, 34.63064], [61.00197, 34.70631], [61.06926, 34.82139], [61.12831, 35.09938], [61.0991, 35.27845], [61.18187, 35.30249], [61.27371, 35.61482], [61.22719, 35.67038], [61.26152, 35.80749], [61.22444, 35.92879], [61.12007, 35.95992], [61.22719, 36.12759], [61.1393, 36.38782], [61.18187, 36.55348], [61.14516, 36.64644], [60.34767, 36.63214], [60.00768, 37.04102], [59.74678, 37.12499], [59.55178, 37.13594], [59.39385, 37.34257], [59.39797, 37.47892], [59.33507, 37.53146], [59.22905, 37.51161], [58.9338, 37.67374], [58.6921, 37.64548], [58.5479, 37.70526], [58.47786, 37.6433], [58.39959, 37.63134], [58.22999, 37.6856], [58.21399, 37.77281], [57.79534, 37.89299], [57.35042, 37.98546], [57.37236, 38.09321], [57.21169, 38.28965], [57.03453, 38.18717], [56.73928, 38.27887], [56.62255, 38.24005], [56.43303, 38.26054], [56.32454, 38.18502], [56.33278, 38.08132], [55.97847, 38.08024], [55.76561, 38.12238], [55.44152, 38.08564], [55.13412, 37.94705], [54.851, 37.75739], [54.77684, 37.62264], [54.81804, 37.61285], [54.77822, 37.51597], [54.67247, 37.43532], [54.58664, 37.45809], [54.36211, 37.34912], [54.24565, 37.32047], [53.89734, 37.3464], [48.88288, 38.43975], [48.84969, 38.45015], [48.81072, 38.44853], [48.78979, 38.45026], [48.70001, 38.40564], [48.62217, 38.40198], [48.58793, 38.45076], [48.45084, 38.61013], [48.3146, 38.59958], [48.24773, 38.71883], [48.02581, 38.82705], [48.01409, 38.90333], [48.07734, 38.91616], [48.08627, 38.94434], [48.28437, 38.97186], [48.33884, 39.03022], [48.31239, 39.09278], [48.15361, 39.19419], [48.12404, 39.25208], [48.15984, 39.30028], [48.37385, 39.37584], [48.34264, 39.42935], [47.98977, 39.70999], [47.84774, 39.66285], [47.50099, 39.49615], [47.38978, 39.45999], [47.31301, 39.37492], [47.05927, 39.24846], [47.05771, 39.20143], [46.95341, 39.13505], [46.92539, 39.16644], [46.83822, 39.13143], [46.75752, 39.03231], [46.53497, 38.86548], [46.34059, 38.92076], [46.20601, 38.85262], [46.14785, 38.84206], [46.06766, 38.87861], [46.00228, 38.87376], [45.94624, 38.89072], [45.90266, 38.87739], [45.83883, 38.90768], [45.65172, 38.95199], [45.6155, 38.94304], [45.6131, 38.964], [45.44966, 38.99243], [45.44811, 39.04927], [45.40452, 39.07224], [45.40148, 39.09007], [45.30489, 39.18333], [45.16168, 39.21952], [45.08751, 39.35052], [45.05932, 39.36435], [44.96746, 39.42998]]]]
25349 groups: ["154", "150", "UN"],
25350 callingCodes: ["354"]
25353 type: "MultiPolygon",
25354 coordinates: [[[[-33.15676, 62.62995], [-8.25539, 63.0423], [-15.70914, 69.67442], [-33.15676, 62.62995]]]]
25364 groups: ["EU", "039", "150", "UN"],
25365 callingCodes: ["39"]
25368 type: "MultiPolygon",
25369 coordinates: [[[[8.95861, 45.96485], [8.97604, 45.96151], [8.97741, 45.98317], [8.96668, 45.98436], [8.95861, 45.96485]]], [[[7.63035, 43.57419], [9.56115, 43.20816], [10.09675, 41.44089], [7.60802, 41.05927], [7.89009, 38.19924], [11.2718, 37.6713], [12.13667, 34.20326], [14.02721, 36.53141], [17.67657, 35.68918], [18.83516, 40.36999], [16.15283, 42.18525], [13.12821, 44.48877], [13.05142, 45.33128], [13.45644, 45.59464], [13.6076, 45.64761], [13.7198, 45.59352], [13.74587, 45.59811], [13.78445, 45.5825], [13.84106, 45.58185], [13.86771, 45.59898], [13.8695, 45.60835], [13.9191, 45.6322], [13.87933, 45.65207], [13.83422, 45.68703], [13.83332, 45.70855], [13.8235, 45.7176], [13.66986, 45.79955], [13.59784, 45.8072], [13.58858, 45.83503], [13.57563, 45.8425], [13.58644, 45.88173], [13.59565, 45.89446], [13.60857, 45.89907], [13.61931, 45.91782], [13.63815, 45.93607], [13.6329, 45.94894], [13.64307, 45.98326], [13.63458, 45.98947], [13.62074, 45.98388], [13.58903, 45.99009], [13.56759, 45.96991], [13.52963, 45.96588], [13.50104, 45.98078], [13.47474, 46.00546], [13.49702, 46.01832], [13.50998, 46.04498], [13.49568, 46.04839], [13.50104, 46.05986], [13.57072, 46.09022], [13.64053, 46.13587], [13.66472, 46.17392], [13.64451, 46.18966], [13.56682, 46.18703], [13.56114, 46.2054], [13.47587, 46.22725], [13.42218, 46.20758], [13.37671, 46.29668], [13.44808, 46.33507], [13.43418, 46.35992], [13.47019, 46.3621], [13.5763, 46.40915], [13.5763, 46.42613], [13.59777, 46.44137], [13.68684, 46.43881], [13.7148, 46.5222], [13.64088, 46.53438], [13.27627, 46.56059], [12.94445, 46.60401], [12.59992, 46.6595], [12.38708, 46.71529], [12.27591, 46.88651], [12.2006, 46.88854], [12.11675, 47.01241], [12.21781, 47.03996], [12.19254, 47.09331], [11.74789, 46.98484], [11.50739, 47.00644], [11.33355, 46.99862], [11.10618, 46.92966], [11.00764, 46.76896], [10.72974, 46.78972], [10.75753, 46.82258], [10.66405, 46.87614], [10.54783, 46.84505], [10.47197, 46.85698], [10.38659, 46.67847], [10.40475, 46.63671], [10.44686, 46.64162], [10.49375, 46.62049], [10.46136, 46.53164], [10.25309, 46.57432], [10.23674, 46.63484], [10.10307, 46.61003], [10.03715, 46.44479], [10.165, 46.41051], [10.10506, 46.3372], [10.17862, 46.25626], [10.14439, 46.22992], [10.07055, 46.21668], [9.95249, 46.38045], [9.73086, 46.35071], [9.71273, 46.29266], [9.57015, 46.2958], [9.46117, 46.37481], [9.45936, 46.50873], [9.40487, 46.46621], [9.36128, 46.5081], [9.28136, 46.49685], [9.25502, 46.43743], [9.29226, 46.32717], [9.24503, 46.23616], [9.01618, 46.04928], [8.99257, 45.9698], [9.09065, 45.89906], [9.06642, 45.8761], [9.04546, 45.84968], [9.04059, 45.8464], [9.03505, 45.83976], [9.03793, 45.83548], [9.03279, 45.82865], [9.0298, 45.82127], [9.00324, 45.82055], [8.99663, 45.83466], [8.9621, 45.83707], [8.94737, 45.84285], [8.91129, 45.8388], [8.93504, 45.86245], [8.94372, 45.86587], [8.93649, 45.86775], [8.88904, 45.95465], [8.86688, 45.96135], [8.85121, 45.97239], [8.8319, 45.9879], [8.79362, 45.99207], [8.78585, 45.98973], [8.79414, 46.00913], [8.85617, 46.0748], [8.80778, 46.10085], [8.75697, 46.10395], [8.62242, 46.12112], [8.45032, 46.26869], [8.46317, 46.43712], [8.42464, 46.46367], [8.30648, 46.41587], [8.31162, 46.38044], [8.08814, 46.26692], [8.16866, 46.17817], [8.11383, 46.11577], [8.02906, 46.10331], [7.98881, 45.99867], [7.9049, 45.99945], [7.85949, 45.91485], [7.56343, 45.97421], [7.10685, 45.85653], [7.04151, 45.92435], [6.95315, 45.85163], [6.80785, 45.83265], [6.80785, 45.71864], [6.98948, 45.63869], [7.00037, 45.509], [7.18019, 45.40071], [7.10572, 45.32924], [7.13115, 45.25386], [7.07074, 45.21228], [6.96706, 45.20841], [6.85144, 45.13226], [6.7697, 45.16044], [6.62803, 45.11175], [6.66981, 45.02324], [6.74791, 45.01939], [6.74519, 44.93661], [6.75518, 44.89915], [6.90774, 44.84322], [6.93499, 44.8664], [7.02217, 44.82519], [7.00401, 44.78782], [7.07484, 44.68073], [7.00582, 44.69364], [6.95133, 44.66264], [6.96042, 44.62129], [6.85507, 44.53072], [6.86233, 44.49834], [6.94504, 44.43112], [6.88784, 44.42043], [6.89171, 44.36637], [6.98221, 44.28289], [7.00764, 44.23736], [7.16929, 44.20352], [7.27827, 44.1462], [7.34547, 44.14359], [7.36364, 44.11882], [7.62155, 44.14881], [7.63245, 44.17877], [7.68694, 44.17487], [7.66878, 44.12795], [7.72508, 44.07578], [7.6597, 44.03009], [7.66848, 43.99943], [7.65266, 43.9763], [7.60771, 43.95772], [7.56858, 43.94506], [7.56075, 43.89932], [7.51162, 43.88301], [7.49355, 43.86551], [7.50423, 43.84345], [7.53006, 43.78405], [7.63035, 43.57419]], [[12.45181, 41.90056], [12.44834, 41.90095], [12.44582, 41.90194], [12.44815, 41.90326], [12.44984, 41.90545], [12.45091, 41.90625], [12.45543, 41.90738], [12.45561, 41.90629], [12.45762, 41.9058], [12.45755, 41.9033], [12.45826, 41.90281], [12.45834, 41.90174], [12.4577, 41.90115], [12.45691, 41.90125], [12.45626, 41.90172], [12.45435, 41.90143], [12.45446, 41.90028], [12.45181, 41.90056]], [[12.45648, 43.89369], [12.44184, 43.90498], [12.41641, 43.89991], [12.40935, 43.9024], [12.41233, 43.90956], [12.40733, 43.92379], [12.41551, 43.92984], [12.41165, 43.93769], [12.40506, 43.94325], [12.40415, 43.95485], [12.41414, 43.95273], [12.42005, 43.9578], [12.43662, 43.95698], [12.44684, 43.96597], [12.46205, 43.97463], [12.47853, 43.98052], [12.49406, 43.98492], [12.50678, 43.99113], [12.51463, 43.99122], [12.5154, 43.98508], [12.51064, 43.98165], [12.51109, 43.97201], [12.50622, 43.97131], [12.50875, 43.96198], [12.50655, 43.95796], [12.51427, 43.94897], [12.51553, 43.94096], [12.50496, 43.93017], [12.50269, 43.92363], [12.49724, 43.92248], [12.49247, 43.91774], [12.49429, 43.90973], [12.48771, 43.89706], [12.45648, 43.89369]]]]
25378 nameEn: "Bailiwick of Jersey",
25380 groups: ["830", "Q185086", "154", "150", "UN"],
25382 roadSpeedUnit: "mph",
25383 roadHeightUnit: "ft",
25384 callingCodes: ["44 01534"]
25387 type: "MultiPolygon",
25388 coordinates: [[[[-2.00491, 48.86706], [-1.83944, 49.23037], [-2.09454, 49.46288], [-2.65349, 49.15373], [-2.00491, 48.86706]]]]
25399 groups: ["029", "003", "419", "019", "UN"],
25401 callingCodes: ["1 876", "1 658"]
25404 type: "MultiPolygon",
25405 coordinates: [[[[-74.09729, 17.36817], [-78.9741, 19.59515], [-78.34606, 16.57862], [-74.09729, 17.36817]]]]
25415 groups: ["145", "142", "UN"],
25416 callingCodes: ["962"]
25419 type: "MultiPolygon",
25420 coordinates: [[[[39.04251, 32.30203], [38.98762, 32.47694], [39.08202, 32.50304], [38.79171, 33.37328], [36.83946, 32.31293], [36.40959, 32.37908], [36.23948, 32.50108], [36.20875, 32.49529], [36.20379, 32.52751], [36.08074, 32.51463], [36.02239, 32.65911], [35.96633, 32.66237], [35.93307, 32.71966], [35.88405, 32.71321], [35.75983, 32.74803], [35.68467, 32.70715], [35.66527, 32.681], [35.61669, 32.67999], [35.59813, 32.65159], [35.56614, 32.64393], [35.57485, 32.48669], [35.55494, 32.42687], [35.55807, 32.38674], [35.57111, 32.21877], [35.52012, 32.04076], [35.54375, 31.96587], [35.52758, 31.9131], [35.55941, 31.76535], [35.47672, 31.49578], [35.40316, 31.25535], [35.43658, 31.12444], [35.41371, 30.95565], [35.33984, 30.8802], [35.33456, 30.81224], [35.29311, 30.71365], [35.21379, 30.60401], [35.19595, 30.50297], [35.16218, 30.43535], [35.19183, 30.34636], [35.14108, 30.07374], [35.02147, 29.66343], [34.98207, 29.58147], [34.97718, 29.54294], [34.92298, 29.45305], [34.8812, 29.36878], [36.07081, 29.18469], [36.50005, 29.49696], [36.75083, 29.86903], [37.4971, 29.99949], [37.66395, 30.33245], [37.99354, 30.49998], [36.99791, 31.50081], [38.99233, 31.99721], [39.29903, 32.23259], [39.26157, 32.35555], [39.04251, 32.30203]]]]
25430 groups: ["030", "142", "UN"],
25432 callingCodes: ["81"]
25435 type: "MultiPolygon",
25436 coordinates: [[[[145.82361, 43.38904], [145.23667, 43.76813], [145.82343, 44.571], [140.9182, 45.92937], [133.61399, 37.41], [129.2669, 34.87122], [122.26612, 25.98197], [123.92912, 17.8782], [155.16731, 23.60141], [145.82361, 43.38904]]]]
25446 groups: ["014", "202", "002", "UN"],
25448 callingCodes: ["254"]
25451 type: "MultiPolygon",
25452 coordinates: [[[[35.9419, 4.61933], [35.51424, 4.61643], [35.42366, 4.76969], [35.47843, 4.91872], [35.30992, 4.90402], [35.34151, 5.02364], [34.47601, 4.72162], [33.9873, 4.23316], [34.06046, 4.15235], [34.15429, 3.80464], [34.45815, 3.67385], [34.44922, 3.51627], [34.39112, 3.48802], [34.41794, 3.44342], [34.40006, 3.37949], [34.45815, 3.18319], [34.56242, 3.11478], [34.60114, 2.93034], [34.65774, 2.8753], [34.73967, 2.85447], [34.78137, 2.76223], [34.77244, 2.70272], [34.95267, 2.47209], [34.90947, 2.42447], [34.98692, 1.97348], [34.9899, 1.6668], [34.92734, 1.56109], [34.87819, 1.5596], [34.7918, 1.36752], [34.82606, 1.30944], [34.82606, 1.26626], [34.80223, 1.22754], [34.67562, 1.21265], [34.58029, 1.14712], [34.57427, 1.09868], [34.52369, 1.10692], [34.43349, 0.85254], [34.40041, 0.80266], [34.31516, 0.75693], [34.27345, 0.63182], [34.20196, 0.62289], [34.13493, 0.58118], [34.11408, 0.48884], [34.08727, 0.44713], [34.10067, 0.36372], [33.90936, 0.10581], [33.98449, -0.13079], [33.9264, -0.54188], [33.93107, -0.99298], [34.02286, -1.00779], [34.03084, -1.05101], [34.0824, -1.02264], [37.67199, -3.06222], [37.71745, -3.304], [37.5903, -3.42735], [37.63099, -3.50723], [37.75036, -3.54243], [37.81321, -3.69179], [39.21631, -4.67835], [39.44306, -4.93877], [39.62121, -4.68136], [41.75542, -1.85308], [41.56362, -1.66375], [41.56, -1.59812], [41.00099, -0.83068], [40.98767, 2.82959], [41.31368, 3.14314], [41.89488, 3.97375], [41.1754, 3.94079], [40.77498, 4.27683], [39.86043, 3.86974], [39.76808, 3.67058], [39.58339, 3.47434], [39.55132, 3.39634], [39.51551, 3.40895], [39.49444, 3.45521], [39.19954, 3.47834], [39.07736, 3.5267], [38.91938, 3.51198], [38.52336, 3.62551], [38.45812, 3.60445], [38.14168, 3.62487], [37.07724, 4.33503], [36.84474, 4.44518], [36.03924, 4.44406], [35.95449, 4.53244], [35.9419, 4.61933]]]]
25461 nameEn: "Kyrgyzstan",
25462 groups: ["143", "142", "UN"],
25463 callingCodes: ["996"]
25466 type: "MultiPolygon",
25467 coordinates: [[[[74.88756, 42.98612], [74.75, 42.99029], [74.70331, 43.02519], [74.64615, 43.05881], [74.57491, 43.13702], [74.22489, 43.24657], [73.55634, 43.03071], [73.50992, 42.82356], [73.44393, 42.43098], [71.88792, 42.83578], [71.62405, 42.76613], [71.53272, 42.8014], [71.2724, 42.77853], [71.22785, 42.69248], [71.17807, 42.67381], [71.15232, 42.60486], [70.97717, 42.50147], [70.85973, 42.30188], [70.94483, 42.26238], [71.13263, 42.28356], [71.28719, 42.18033], [70.69777, 41.92554], [70.17682, 41.5455], [70.48909, 41.40335], [70.67586, 41.47953], [70.78572, 41.36419], [70.77885, 41.24813], [70.86263, 41.23833], [70.9615, 41.16393], [71.02193, 41.19494], [71.11806, 41.15359], [71.25813, 41.18796], [71.27187, 41.11015], [71.34877, 41.16807], [71.40198, 41.09436], [71.46148, 41.13958], [71.43814, 41.19644], [71.46688, 41.31883], [71.57227, 41.29175], [71.6787, 41.42111], [71.65914, 41.49599], [71.73054, 41.54713], [71.71132, 41.43012], [71.76625, 41.4466], [71.83914, 41.3546], [71.91457, 41.2982], [71.85964, 41.19081], [72.07249, 41.11739], [72.10745, 41.15483], [72.16433, 41.16483], [72.17594, 41.15522], [72.14864, 41.13363], [72.1792, 41.10621], [72.21061, 41.05607], [72.17594, 41.02377], [72.18339, 40.99571], [72.324, 41.03381], [72.34026, 41.04539], [72.34757, 41.06104], [72.36138, 41.04384], [72.38511, 41.02785], [72.45206, 41.03018], [72.48742, 40.97136], [72.55109, 40.96046], [72.59136, 40.86947], [72.68157, 40.84942], [72.84291, 40.85512], [72.94454, 40.8094], [73.01869, 40.84681], [73.13267, 40.83512], [73.13412, 40.79122], [73.0612, 40.76678], [72.99133, 40.76457], [72.93296, 40.73089], [72.8722, 40.71111], [72.85372, 40.7116], [72.84754, 40.67229], [72.80137, 40.67856], [72.74866, 40.60873], [72.74894, 40.59592], [72.75982, 40.57273], [72.74862, 40.57131], [72.74768, 40.58051], [72.73995, 40.58409], [72.69579, 40.59778], [72.66713, 40.59076], [72.66713, 40.5219], [72.47795, 40.5532], [72.40517, 40.61917], [72.34406, 40.60144], [72.41714, 40.55736], [72.38384, 40.51535], [72.41513, 40.50856], [72.44191, 40.48222], [72.40346, 40.4007], [72.24368, 40.46091], [72.18648, 40.49893], [71.96401, 40.31907], [72.05464, 40.27586], [71.85002, 40.25647], [71.82646, 40.21872], [71.73054, 40.14818], [71.71719, 40.17886], [71.69621, 40.18492], [71.70569, 40.20391], [71.68386, 40.26984], [71.61931, 40.26775], [71.61725, 40.20615], [71.51549, 40.22986], [71.51215, 40.26943], [71.4246, 40.28619], [71.36663, 40.31593], [71.13042, 40.34106], [71.05901, 40.28765], [70.95789, 40.28761], [70.9818, 40.22392], [70.80495, 40.16813], [70.7928, 40.12797], [70.65827, 40.0981], [70.65946, 39.9878], [70.58912, 39.95211], [70.55033, 39.96619], [70.47557, 39.93216], [70.57384, 39.99394], [70.58297, 40.00891], [70.01283, 40.23288], [69.67001, 40.10639], [69.64704, 40.12165], [69.57615, 40.10524], [69.55555, 40.12296], [69.53794, 40.11833], [69.53855, 40.0887], [69.5057, 40.03277], [69.53615, 39.93991], [69.43557, 39.92877], [69.43134, 39.98431], [69.35649, 40.01994], [69.26938, 39.8127], [69.3594, 39.52516], [69.68677, 39.59281], [69.87491, 39.53882], [70.11111, 39.58223], [70.2869, 39.53141], [70.44757, 39.60128], [70.64087, 39.58792], [70.7854, 39.38933], [71.06418, 39.41586], [71.08752, 39.50704], [71.49814, 39.61397], [71.55856, 39.57588], [71.5517, 39.45722], [71.62688, 39.44056], [71.76816, 39.45456], [71.80164, 39.40631], [71.7522, 39.32031], [71.79202, 39.27355], [71.90601, 39.27674], [72.04059, 39.36704], [72.09689, 39.26823], [72.17242, 39.2661], [72.23834, 39.17248], [72.33173, 39.33093], [72.62027, 39.39696], [72.85934, 39.35116], [73.18454, 39.35536], [73.31912, 39.38615], [73.45096, 39.46677], [73.59831, 39.46425], [73.87018, 39.47879], [73.94683, 39.60733], [73.92354, 39.69565], [73.9051, 39.75073], [73.83006, 39.76136], [73.97049, 40.04378], [74.25533, 40.13191], [74.35063, 40.09742], [74.69875, 40.34668], [74.85996, 40.32857], [74.78168, 40.44886], [74.82013, 40.52197], [75.08243, 40.43945], [75.22834, 40.45382], [75.5854, 40.66874], [75.69663, 40.28642], [75.91361, 40.2948], [75.96168, 40.38064], [76.33659, 40.3482], [76.5261, 40.46114], [76.75681, 40.95354], [76.99302, 41.0696], [77.28004, 41.0033], [77.3693, 41.0375], [77.52723, 41.00227], [77.76206, 41.01574], [77.81287, 41.14307], [78.12873, 41.23091], [78.15757, 41.38565], [78.3732, 41.39603], [79.92977, 42.04113], [80.17842, 42.03211], [80.17807, 42.21166], [79.97364, 42.42816], [79.52921, 42.44778], [79.19763, 42.804], [78.91502, 42.76839], [78.48469, 42.89649], [75.82823, 42.94848], [75.72174, 42.79672], [75.29966, 42.86183], [75.22619, 42.85528], [74.88756, 42.98612]], [[70.74189, 39.86319], [70.63105, 39.77923], [70.59667, 39.83542], [70.54998, 39.85137], [70.52631, 39.86989], [70.53651, 39.89155], [70.74189, 39.86319]], [[71.86463, 39.98598], [71.84316, 39.95582], [71.7504, 39.93701], [71.71511, 39.96348], [71.78838, 40.01404], [71.86463, 39.98598]], [[71.21139, 40.03369], [71.1427, 39.95026], [71.23067, 39.93581], [71.16101, 39.88423], [71.10531, 39.91354], [71.04979, 39.89808], [71.10501, 39.95568], [71.09063, 39.99], [71.11668, 39.99291], [71.11037, 40.01984], [71.01035, 40.05481], [71.00236, 40.18154], [71.06305, 40.1771], [71.12218, 40.03052], [71.21139, 40.03369]]]]
25476 nameEn: "Cambodia",
25477 groups: ["035", "142", "UN"],
25478 callingCodes: ["855"]
25481 type: "MultiPolygon",
25482 coordinates: [[[[105.87328, 11.55953], [105.81645, 11.56876], [105.80867, 11.60536], [105.8507, 11.66635], [105.88962, 11.67854], [105.95188, 11.63738], [106.00792, 11.7197], [106.02038, 11.77457], [106.06708, 11.77761], [106.13158, 11.73283], [106.18539, 11.75171], [106.26478, 11.72122], [106.30525, 11.67549], [106.37219, 11.69836], [106.44691, 11.66787], [106.45158, 11.68616], [106.41577, 11.76999], [106.44535, 11.8279], [106.44068, 11.86294], [106.4687, 11.86751], [106.4111, 11.97413], [106.70687, 11.96956], [106.79405, 12.0807], [106.92325, 12.06548], [106.99953, 12.08983], [107.15831, 12.27547], [107.34511, 12.33327], [107.42917, 12.24657], [107.4463, 12.29373], [107.55059, 12.36824], [107.5755, 12.52177], [107.55993, 12.7982], [107.49611, 12.88926], [107.49144, 13.01215], [107.62843, 13.3668], [107.61909, 13.52577], [107.53503, 13.73908], [107.45252, 13.78897], [107.46498, 13.91593], [107.44318, 13.99751], [107.38247, 13.99147], [107.35757, 14.02319], [107.37158, 14.07906], [107.33577, 14.11832], [107.40427, 14.24509], [107.39493, 14.32655], [107.44941, 14.41552], [107.48521, 14.40346], [107.52569, 14.54665], [107.52102, 14.59034], [107.55371, 14.628], [107.54361, 14.69092], [107.47238, 14.61523], [107.44435, 14.52785], [107.37897, 14.54443], [107.3276, 14.58812], [107.29803, 14.58963], [107.26534, 14.54292], [107.256, 14.48716], [107.21241, 14.48716], [107.17038, 14.41782], [107.09722, 14.3937], [107.03962, 14.45099], [107.04585, 14.41782], [106.98825, 14.36806], [106.9649, 14.3198], [106.90574, 14.33639], [106.8497, 14.29416], [106.80767, 14.31226], [106.73762, 14.42687], [106.63333, 14.44194], [106.59908, 14.50977], [106.57106, 14.50525], [106.54148, 14.59565], [106.50723, 14.58963], [106.45898, 14.55045], [106.47766, 14.50977], [106.43874, 14.52032], [106.40916, 14.45249], [106.32355, 14.44043], [106.25194, 14.48415], [106.21302, 14.36203], [106.00131, 14.36957], [105.99509, 14.32734], [106.02311, 14.30623], [106.04801, 14.20363], [106.10872, 14.18401], [106.11962, 14.11307], [106.18656, 14.06324], [106.16632, 14.01794], [106.10094, 13.98471], [106.10405, 13.9137], [105.90791, 13.92881], [105.78182, 14.02247], [105.78338, 14.08438], [105.5561, 14.15684], [105.44869, 14.10703], [105.36775, 14.09948], [105.2759, 14.17496], [105.20894, 14.34967], [105.17748, 14.34432], [105.14012, 14.23873], [105.08408, 14.20402], [105.02804, 14.23722], [104.97667, 14.38806], [104.69335, 14.42726], [104.55014, 14.36091], [104.27616, 14.39861], [103.93836, 14.3398], [103.70175, 14.38052], [103.71109, 14.4348], [103.53518, 14.42575], [103.39353, 14.35639], [103.16469, 14.33075], [102.93275, 14.19044], [102.91251, 14.01531], [102.77864, 13.93374], [102.72727, 13.77806], [102.56848, 13.69366], [102.5481, 13.6589], [102.58635, 13.6286], [102.62483, 13.60883], [102.57573, 13.60461], [102.5358, 13.56933], [102.44601, 13.5637], [102.36859, 13.57488], [102.33828, 13.55613], [102.361, 13.50551], [102.35563, 13.47307], [102.35692, 13.38274], [102.34611, 13.35618], [102.36001, 13.31142], [102.36146, 13.26006], [102.43422, 13.09061], [102.46011, 13.08057], [102.52275, 12.99813], [102.48694, 12.97537], [102.49335, 12.92711], [102.53053, 12.77506], [102.4994, 12.71736], [102.51963, 12.66117], [102.57567, 12.65358], [102.7796, 12.43781], [102.78116, 12.40284], [102.73134, 12.37091], [102.70176, 12.1686], [102.77026, 12.06815], [102.78427, 11.98746], [102.83957, 11.8519], [102.90973, 11.75613], [102.91449, 11.65512], [102.52395, 11.25257], [102.47649, 9.66162], [103.99198, 10.48391], [104.43778, 10.42386], [104.47963, 10.43046], [104.49869, 10.4057], [104.59018, 10.53073], [104.87933, 10.52833], [104.95094, 10.64003], [105.09571, 10.72722], [105.02722, 10.89236], [105.08326, 10.95656], [105.11449, 10.96332], [105.34011, 10.86179], [105.42884, 10.96878], [105.50045, 10.94586], [105.77751, 11.03671], [105.86376, 10.89839], [105.84603, 10.85873], [105.93403, 10.83853], [105.94535, 10.9168], [106.06708, 10.8098], [106.18539, 10.79451], [106.14301, 10.98176], [106.20095, 10.97795], [106.1757, 11.07301], [106.1527, 11.10476], [106.10444, 11.07879], [105.86782, 11.28343], [105.88962, 11.43605], [105.87328, 11.55953]]]]
25491 nameEn: "Kiribati",
25492 groups: ["057", "009", "UN"],
25494 callingCodes: ["686"]
25497 type: "MultiPolygon",
25498 coordinates: [[[[169, 3.9], [169, -3.5], [178, -3.5], [178, 3.9], [169, 3.9]]], [[[-161.06795, 5.2462], [-158.12991, -1.86122], [-175.33482, -1.40631], [-175.31804, -7.54825], [-156.50903, -7.4975], [-156.48634, -15.52824], [-135.59706, -4.70473], [-161.06795, 5.2462]]]]
25508 groups: ["014", "202", "002", "UN"],
25509 callingCodes: ["269"]
25512 type: "MultiPolygon",
25513 coordinates: [[[[42.63904, -10.02522], [43.28731, -13.97126], [45.4971, -11.75965], [42.63904, -10.02522]]]]
25522 nameEn: "St. Kitts and Nevis",
25523 groups: ["029", "003", "419", "019", "UN"],
25525 roadSpeedUnit: "mph",
25526 callingCodes: ["1 869"]
25529 type: "MultiPolygon",
25530 coordinates: [[[[-62.29333, 17.43155], [-62.76692, 17.64353], [-63.09677, 17.21372], [-62.63813, 16.65446], [-62.29333, 17.43155]]]]
25539 nameEn: "North Korea",
25540 groups: ["030", "142", "UN"],
25541 callingCodes: ["850"]
25544 type: "MultiPolygon",
25545 coordinates: [[[[130.26095, 42.9027], [130.09764, 42.91425], [130.12957, 42.98361], [129.96409, 42.97306], [129.95082, 43.01051], [129.8865, 43.00395], [129.85261, 42.96494], [129.83277, 42.86746], [129.80719, 42.79218], [129.7835, 42.76521], [129.77183, 42.69435], [129.75294, 42.59409], [129.72541, 42.43739], [129.60482, 42.44461], [129.54701, 42.37254], [129.42882, 42.44702], [129.28541, 42.41574], [129.22423, 42.3553], [129.22285, 42.26491], [129.15178, 42.17224], [128.96068, 42.06657], [128.94007, 42.03537], [128.04487, 42.01769], [128.15119, 41.74568], [128.30716, 41.60322], [128.20061, 41.40895], [128.18546, 41.41279], [128.12967, 41.37931], [128.03311, 41.39232], [128.02633, 41.42103], [127.92943, 41.44291], [127.29712, 41.49473], [127.17841, 41.59714], [126.90729, 41.79955], [126.60631, 41.65565], [126.53189, 41.35206], [126.242, 41.15454], [126.00335, 40.92835], [125.76869, 40.87908], [125.71172, 40.85223], [124.86913, 40.45387], [124.40719, 40.13655], [124.38556, 40.11047], [124.3322, 40.05573], [124.37089, 40.03004], [124.35029, 39.95639], [124.23201, 39.9248], [124.17532, 39.8232], [123.90497, 38.79949], [123.85601, 37.49093], [124.67666, 38.05679], [124.84224, 37.977], [124.87921, 37.80827], [125.06408, 37.66334], [125.37112, 37.62643], [125.81159, 37.72949], [126.13074, 37.70512], [126.18776, 37.74728], [126.19097, 37.81462], [126.24402, 37.83113], [126.43239, 37.84095], [126.46818, 37.80873], [126.56709, 37.76857], [126.59918, 37.76364], [126.66067, 37.7897], [126.68793, 37.83728], [126.68793, 37.9175], [126.67023, 37.95852], [126.84961, 38.0344], [126.88106, 38.10246], [126.95887, 38.1347], [126.95338, 38.17735], [127.04479, 38.25518], [127.15749, 38.30722], [127.38727, 38.33227], [127.49672, 38.30647], [127.55013, 38.32257], [128.02917, 38.31861], [128.27652, 38.41657], [128.31105, 38.58462], [128.37487, 38.62345], [128.65655, 38.61914], [131.95041, 41.5445], [130.65022, 42.32281], [130.66367, 42.38024], [130.64181, 42.41422], [130.60805, 42.4317], [130.56835, 42.43281], [130.55143, 42.52158], [130.50123, 42.61636], [130.44361, 42.54849], [130.41826, 42.6011], [130.2385, 42.71127], [130.23068, 42.80125], [130.26095, 42.9027]]]]
25554 nameEn: "South Korea",
25555 groups: ["030", "142", "UN"],
25556 callingCodes: ["82"]
25559 type: "MultiPolygon",
25560 coordinates: [[[[133.11729, 37.53115], [128.65655, 38.61914], [128.37487, 38.62345], [128.31105, 38.58462], [128.27652, 38.41657], [128.02917, 38.31861], [127.55013, 38.32257], [127.49672, 38.30647], [127.38727, 38.33227], [127.15749, 38.30722], [127.04479, 38.25518], [126.95338, 38.17735], [126.95887, 38.1347], [126.88106, 38.10246], [126.84961, 38.0344], [126.67023, 37.95852], [126.68793, 37.9175], [126.68793, 37.83728], [126.66067, 37.7897], [126.59918, 37.76364], [126.56709, 37.76857], [126.46818, 37.80873], [126.43239, 37.84095], [126.24402, 37.83113], [126.19097, 37.81462], [126.18776, 37.74728], [126.13074, 37.70512], [125.81159, 37.72949], [125.37112, 37.62643], [125.06408, 37.66334], [124.87921, 37.80827], [124.84224, 37.977], [124.67666, 38.05679], [123.85601, 37.49093], [122.80525, 33.30571], [125.99728, 32.63328], [129.2669, 34.87122], [133.11729, 37.53115]]]]
25570 groups: ["145", "142", "UN"],
25571 callingCodes: ["965"]
25574 type: "MultiPolygon",
25575 coordinates: [[[[49.00421, 28.81495], [48.59531, 29.66815], [48.40479, 29.85763], [48.17332, 30.02448], [48.06782, 30.02906], [48.01114, 29.98906], [47.7095, 30.10453], [47.37192, 30.10421], [47.15166, 30.01044], [46.89695, 29.50584], [46.5527, 29.10283], [47.46202, 29.0014], [47.58376, 28.83382], [47.59863, 28.66798], [47.70561, 28.5221], [48.42991, 28.53628], [49.00421, 28.81495]]]]
25584 nameEn: "Cayman Islands",
25586 groups: ["BOTS", "029", "003", "419", "019", "UN"],
25588 roadSpeedUnit: "mph",
25589 roadHeightUnit: "ft",
25590 callingCodes: ["1 345"]
25593 type: "MultiPolygon",
25594 coordinates: [[[[-82.11509, 19.60401], [-80.36068, 18.11751], [-79.32727, 20.06742], [-82.11509, 19.60401]]]]
25603 nameEn: "Kazakhstan",
25604 groups: ["143", "142", "UN"],
25605 callingCodes: ["7"]
25608 type: "MultiPolygon",
25609 coordinates: [[[[68.90865, 55.38148], [68.19206, 55.18823], [68.26661, 55.09226], [68.21308, 54.98645], [65.20174, 54.55216], [65.24663, 54.35721], [65.11033, 54.33028], [64.97216, 54.4212], [63.97686, 54.29763], [64.02715, 54.22679], [63.91224, 54.20013], [63.80604, 54.27079], [62.58651, 54.05871], [62.56876, 53.94047], [62.45931, 53.90737], [62.38535, 54.03961], [62.00966, 54.04134], [62.03913, 53.94768], [61.65318, 54.02445], [61.56941, 53.95703], [61.47603, 54.08048], [61.3706, 54.08464], [61.26863, 53.92797], [60.99796, 53.93699], [61.14283, 53.90063], [61.22574, 53.80268], [60.90626, 53.62937], [61.55706, 53.57144], [61.57185, 53.50112], [61.37957, 53.45887], [61.29082, 53.50992], [61.14291, 53.41481], [61.19024, 53.30536], [62.14574, 53.09626], [62.12799, 52.99133], [62.0422, 52.96105], [61.23462, 53.03227], [61.05842, 52.92217], [60.71989, 52.75923], [60.71693, 52.66245], [60.84118, 52.63912], [60.84709, 52.52228], [60.98021, 52.50068], [61.05417, 52.35096], [60.78201, 52.22067], [60.72581, 52.15538], [60.48915, 52.15175], [60.19925, 51.99173], [59.99809, 51.98263], [60.09867, 51.87135], [60.50986, 51.7964], [60.36787, 51.66815], [60.5424, 51.61675], [60.92401, 51.61124], [60.95655, 51.48615], [61.50677, 51.40687], [61.55114, 51.32746], [61.6813, 51.25716], [61.56889, 51.23679], [61.4431, 50.80679], [60.81833, 50.6629], [60.31914, 50.67705], [60.17262, 50.83312], [60.01288, 50.8163], [59.81172, 50.54451], [59.51886, 50.49937], [59.48928, 50.64216], [58.87974, 50.70852], [58.3208, 51.15151], [57.75578, 51.13852], [57.74986, 50.93017], [57.44221, 50.88354], [57.17302, 51.11253], [56.17906, 50.93204], [56.11398, 50.7471], [55.67774, 50.54508], [54.72067, 51.03261], [54.56685, 51.01958], [54.71476, 50.61214], [54.55797, 50.52006], [54.41894, 50.61214], [54.46331, 50.85554], [54.12248, 51.11542], [53.69299, 51.23466], [53.46165, 51.49445], [52.54329, 51.48444], [52.36119, 51.74161], [51.8246, 51.67916], [51.77431, 51.49536], [51.301, 51.48799], [51.26254, 51.68466], [50.59695, 51.61859], [50.26859, 51.28677], [49.97277, 51.2405], [49.76866, 51.11067], [49.39001, 51.09396], [49.41959, 50.85927], [49.12673, 50.78639], [48.86936, 50.61589], [48.57946, 50.63278], [48.90782, 50.02281], [48.68352, 49.89546], [48.42564, 49.82283], [48.24519, 49.86099], [48.10044, 50.09242], [47.58551, 50.47867], [47.30448, 50.30894], [47.34589, 50.09308], [47.18319, 49.93721], [46.9078, 49.86707], [46.78398, 49.34026], [47.04658, 49.19834], [47.00857, 49.04921], [46.78392, 48.95352], [46.49011, 48.43019], [47.11516, 48.27188], [47.12107, 47.83687], [47.38731, 47.68176], [47.41689, 47.83687], [47.64973, 47.76559], [48.15348, 47.74545], [48.45173, 47.40818], [48.52326, 47.4102], [49.01136, 46.72716], [48.51142, 46.69268], [48.54988, 46.56267], [49.16518, 46.38542], [49.32259, 46.26944], [49.88945, 46.04554], [49.2134, 44.84989], [52.26048, 41.69249], [52.47884, 41.78034], [52.97575, 42.1308], [54.20635, 42.38477], [54.95182, 41.92424], [55.45471, 41.25609], [56.00314, 41.32584], [55.97584, 44.99322], [55.97584, 44.99328], [55.97584, 44.99338], [55.97584, 44.99343], [55.97584, 44.99348], [55.97584, 44.99353], [55.97584, 44.99359], [55.97584, 44.99369], [55.97584, 44.99374], [55.97584, 44.99384], [55.97584, 44.9939], [55.97584, 44.994], [55.97584, 44.99405], [55.97584, 44.99415], [55.97584, 44.99421], [55.97584, 44.99426], [55.97584, 44.99431], [55.97584, 44.99436], [55.97584, 44.99441], [55.97594, 44.99446], [55.97605, 44.99452], [55.97605, 44.99457], [55.97605, 44.99462], [55.97605, 44.99467], [55.97605, 44.99477], [55.97615, 44.99477], [55.97615, 44.99483], [55.97615, 44.99493], [55.97615, 44.99498], [55.97615, 44.99503], [55.97615, 44.99508], [55.97625, 44.99514], [55.97636, 44.99519], [55.97636, 44.99524], [55.97646, 44.99529], [55.97646, 44.99534], [55.97656, 44.99539], [55.97667, 44.99545], [55.97677, 44.9955], [55.97677, 44.99555], [55.97677, 44.9956], [55.97687, 44.9956], [55.97698, 44.99565], [55.97698, 44.9957], [55.97708, 44.99576], [55.97718, 44.99581], [55.97729, 44.99586], [55.97739, 44.99586], [55.97739, 44.99591], [55.97749, 44.99591], [55.9776, 44.99591], [55.9777, 44.99596], [55.9777, 44.99601], [55.9778, 44.99607], [55.97791, 44.99607], [55.97801, 44.99607], [55.97801, 44.99612], [55.97811, 44.99617], [55.97822, 44.99617], [55.97832, 44.99622], [55.97842, 44.99622], [58.59711, 45.58671], [61.01475, 44.41383], [62.01711, 43.51008], [63.34656, 43.64003], [64.53885, 43.56941], [64.96464, 43.74748], [65.18666, 43.48835], [65.53277, 43.31856], [65.85194, 42.85481], [66.09482, 42.93426], [66.00546, 41.94455], [66.53302, 41.87388], [66.69129, 41.1311], [67.9644, 41.14611], [67.98511, 41.02794], [68.08273, 41.08148], [68.1271, 41.0324], [67.96736, 40.83798], [68.49983, 40.56437], [68.63, 40.59358], [68.58444, 40.91447], [68.49983, 40.99669], [68.62221, 41.03019], [68.65662, 40.93861], [68.73945, 40.96989], [68.7217, 41.05025], [69.01308, 41.22804], [69.05006, 41.36183], [69.15137, 41.43078], [69.17701, 41.43769], [69.18528, 41.45175], [69.20439, 41.45391], [69.22671, 41.46298], [69.23332, 41.45847], [69.25059, 41.46693], [69.29778, 41.43673], [69.35554, 41.47211], [69.37468, 41.46555], [69.45081, 41.46246], [69.39485, 41.51518], [69.45751, 41.56863], [69.49545, 41.545], [70.94483, 42.26238], [70.85973, 42.30188], [70.97717, 42.50147], [71.15232, 42.60486], [71.17807, 42.67381], [71.22785, 42.69248], [71.2724, 42.77853], [71.53272, 42.8014], [71.62405, 42.76613], [71.88792, 42.83578], [73.44393, 42.43098], [73.50992, 42.82356], [73.55634, 43.03071], [74.22489, 43.24657], [74.57491, 43.13702], [74.64615, 43.05881], [74.70331, 43.02519], [74.75, 42.99029], [74.88756, 42.98612], [75.22619, 42.85528], [75.29966, 42.86183], [75.72174, 42.79672], [75.82823, 42.94848], [78.48469, 42.89649], [78.91502, 42.76839], [79.19763, 42.804], [79.52921, 42.44778], [79.97364, 42.42816], [80.17807, 42.21166], [80.26841, 42.23797], [80.16892, 42.61137], [80.26886, 42.8366], [80.38169, 42.83142], [80.58999, 42.9011], [80.3735, 43.01557], [80.62913, 43.141], [80.78817, 43.14235], [80.77771, 43.30065], [80.69718, 43.32589], [80.75156, 43.44948], [80.40031, 44.10986], [80.40229, 44.23319], [80.38384, 44.63073], [79.8987, 44.89957], [80.11169, 45.03352], [81.73278, 45.3504], [82.51374, 45.1755], [82.58474, 45.40027], [82.21792, 45.56619], [83.04622, 47.19053], [83.92184, 46.98912], [84.73077, 47.01394], [84.93995, 46.87399], [85.22443, 47.04816], [85.54294, 47.06171], [85.69696, 47.2898], [85.61067, 47.49753], [85.5169, 48.05493], [85.73581, 48.3939], [86.38069, 48.46064], [86.75343, 48.70331], [86.73568, 48.99918], [86.87238, 49.12432], [87.28386, 49.11626], [87.31465, 49.23603], [87.03071, 49.25142], [86.82606, 49.51796], [86.61307, 49.60239], [86.79056, 49.74787], [86.63674, 49.80136], [86.18709, 49.50259], [85.24047, 49.60239], [84.99198, 50.06793], [84.29385, 50.27257], [83.8442, 50.87375], [83.14607, 51.00796], [82.55443, 50.75412], [81.94999, 50.79307], [81.46581, 50.77658], [81.41248, 50.97524], [81.06091, 50.94833], [81.16999, 51.15662], [80.80318, 51.28262], [80.44819, 51.20855], [80.4127, 50.95581], [80.08138, 50.77658], [79.11255, 52.01171], [77.90383, 53.29807], [76.54243, 53.99329], [76.44076, 54.16017], [76.82266, 54.1798], [76.91052, 54.4677], [75.3668, 54.07439], [75.43398, 53.98652], [75.07405, 53.80831], [73.39218, 53.44623], [73.25412, 53.61532], [73.68921, 53.86522], [73.74778, 54.07194], [73.37963, 53.96132], [72.71026, 54.1161], [72.43415, 53.92685], [72.17477, 54.36303], [71.96141, 54.17736], [71.10379, 54.13326], [71.08706, 54.33376], [71.24185, 54.64965], [71.08288, 54.71253], [70.96009, 55.10558], [70.76493, 55.3027], [70.19179, 55.1476], [69.74917, 55.35545], [69.34224, 55.36344], [68.90865, 55.38148]]]]
25619 groups: ["035", "142", "UN"],
25620 callingCodes: ["856"]
25623 type: "MultiPolygon",
25624 coordinates: [[[[102.1245, 22.43372], [102.03633, 22.46164], [101.98487, 22.42766], [101.91344, 22.44417], [101.90714, 22.38688], [101.86828, 22.38397], [101.7685, 22.50337], [101.68973, 22.46843], [101.61306, 22.27515], [101.56789, 22.28876], [101.53638, 22.24794], [101.60675, 22.13513], [101.57525, 22.13026], [101.62566, 21.96574], [101.7791, 21.83019], [101.74555, 21.72852], [101.83257, 21.61562], [101.80001, 21.57461], [101.7475, 21.5873], [101.7727, 21.51794], [101.74224, 21.48276], [101.74014, 21.30967], [101.84412, 21.25291], [101.83887, 21.20983], [101.76745, 21.21571], [101.79266, 21.19025], [101.7622, 21.14813], [101.70548, 21.14911], [101.66977, 21.20004], [101.60886, 21.17947], [101.59491, 21.18621], [101.6068, 21.23329], [101.54563, 21.25668], [101.29326, 21.17254], [101.2229, 21.23271], [101.26912, 21.36482], [101.19349, 21.41959], [101.2124, 21.56422], [101.15156, 21.56129], [101.16198, 21.52808], [101.00234, 21.39612], [100.80173, 21.2934], [100.72716, 21.31786], [100.63578, 21.05639], [100.55281, 21.02796], [100.50974, 20.88574], [100.64628, 20.88279], [100.60112, 20.8347], [100.51079, 20.82194], [100.36375, 20.82783], [100.1957, 20.68247], [100.08404, 20.36626], [100.09999, 20.31614], [100.09337, 20.26293], [100.11785, 20.24787], [100.1712, 20.24324], [100.16668, 20.2986], [100.22076, 20.31598], [100.25769, 20.3992], [100.33383, 20.4028], [100.37439, 20.35156], [100.41473, 20.25625], [100.44992, 20.23644], [100.4537, 20.19971], [100.47567, 20.19133], [100.51052, 20.14928], [100.55218, 20.17741], [100.58808, 20.15791], [100.5094, 19.87904], [100.398, 19.75047], [100.49604, 19.53504], [100.58219, 19.49164], [100.64606, 19.55884], [100.77231, 19.48324], [100.90302, 19.61901], [101.08928, 19.59748], [101.26545, 19.59242], [101.26991, 19.48324], [101.21347, 19.46223], [101.20604, 19.35296], [101.24911, 19.33334], [101.261, 19.12717], [101.35606, 19.04716], [101.25803, 18.89545], [101.22832, 18.73377], [101.27585, 18.68875], [101.06047, 18.43247], [101.18227, 18.34367], [101.15108, 18.25624], [101.19118, 18.2125], [101.1793, 18.0544], [101.02185, 17.87637], [100.96541, 17.57926], [101.15108, 17.47586], [101.44667, 17.7392], [101.72294, 17.92867], [101.78087, 18.07559], [101.88485, 18.02474], [102.11359, 18.21532], [102.45523, 17.97106], [102.59234, 17.96127], [102.60971, 17.95411], [102.61432, 17.92273], [102.5896, 17.84889], [102.59485, 17.83537], [102.68194, 17.80151], [102.69946, 17.81686], [102.67543, 17.84529], [102.68538, 17.86653], [102.75954, 17.89561], [102.79044, 17.93612], [102.81988, 17.94233], [102.86323, 17.97531], [102.95812, 18.0054], [102.9912, 17.9949], [103.01998, 17.97095], [103.0566, 18.00144], [103.07823, 18.03833], [103.07343, 18.12351], [103.1493, 18.17799], [103.14994, 18.23172], [103.17093, 18.2618], [103.29757, 18.30475], [103.23818, 18.34875], [103.24779, 18.37807], [103.30977, 18.4341], [103.41044, 18.4486], [103.47773, 18.42841], [103.60957, 18.40528], [103.699, 18.34125], [103.82449, 18.33979], [103.85642, 18.28666], [103.93916, 18.33914], [103.97725, 18.33631], [104.06533, 18.21656], [104.10927, 18.10826], [104.21776, 17.99335], [104.2757, 17.86139], [104.35432, 17.82871], [104.45404, 17.66788], [104.69867, 17.53038], [104.80061, 17.39367], [104.80716, 17.19025], [104.73712, 17.01404], [104.7373, 16.91125], [104.76442, 16.84752], [104.7397, 16.81005], [104.76099, 16.69302], [104.73349, 16.565], [104.88057, 16.37311], [105.00262, 16.25627], [105.06204, 16.09792], [105.42001, 16.00657], [105.38508, 15.987], [105.34115, 15.92737], [105.37959, 15.84074], [105.42285, 15.76971], [105.46573, 15.74742], [105.61756, 15.68792], [105.60446, 15.53301], [105.58191, 15.41031], [105.47635, 15.3796], [105.4692, 15.33709], [105.50662, 15.32054], [105.58043, 15.32724], [105.46661, 15.13132], [105.61162, 15.00037], [105.5121, 14.80802], [105.53864, 14.55731], [105.43783, 14.43865], [105.20894, 14.34967], [105.2759, 14.17496], [105.36775, 14.09948], [105.44869, 14.10703], [105.5561, 14.15684], [105.78338, 14.08438], [105.78182, 14.02247], [105.90791, 13.92881], [106.10405, 13.9137], [106.10094, 13.98471], [106.16632, 14.01794], [106.18656, 14.06324], [106.11962, 14.11307], [106.10872, 14.18401], [106.04801, 14.20363], [106.02311, 14.30623], [105.99509, 14.32734], [106.00131, 14.36957], [106.21302, 14.36203], [106.25194, 14.48415], [106.32355, 14.44043], [106.40916, 14.45249], [106.43874, 14.52032], [106.47766, 14.50977], [106.45898, 14.55045], [106.50723, 14.58963], [106.54148, 14.59565], [106.57106, 14.50525], [106.59908, 14.50977], [106.63333, 14.44194], [106.73762, 14.42687], [106.80767, 14.31226], [106.8497, 14.29416], [106.90574, 14.33639], [106.9649, 14.3198], [106.98825, 14.36806], [107.04585, 14.41782], [107.03962, 14.45099], [107.09722, 14.3937], [107.17038, 14.41782], [107.21241, 14.48716], [107.256, 14.48716], [107.26534, 14.54292], [107.29803, 14.58963], [107.3276, 14.58812], [107.37897, 14.54443], [107.44435, 14.52785], [107.47238, 14.61523], [107.54361, 14.69092], [107.51579, 14.79282], [107.59285, 14.87795], [107.48277, 14.93751], [107.46516, 15.00982], [107.61486, 15.0566], [107.61926, 15.13949], [107.58844, 15.20111], [107.62587, 15.2266], [107.60605, 15.37524], [107.62367, 15.42193], [107.53341, 15.40496], [107.50699, 15.48771], [107.3815, 15.49832], [107.34408, 15.62345], [107.27583, 15.62769], [107.27143, 15.71459], [107.21859, 15.74638], [107.21419, 15.83747], [107.34188, 15.89464], [107.39471, 15.88829], [107.46296, 16.01106], [107.44975, 16.08511], [107.33968, 16.05549], [107.25822, 16.13587], [107.14595, 16.17816], [107.15035, 16.26271], [107.09091, 16.3092], [107.02597, 16.31132], [106.97385, 16.30204], [106.96638, 16.34938], [106.88067, 16.43594], [106.88727, 16.52671], [106.84104, 16.55415], [106.74418, 16.41904], [106.65832, 16.47816], [106.66052, 16.56892], [106.61477, 16.60713], [106.58267, 16.6012], [106.59013, 16.62259], [106.55485, 16.68704], [106.55265, 16.86831], [106.52183, 16.87884], [106.51963, 16.92097], [106.54824, 16.92729], [106.55045, 17.0031], [106.50862, 16.9673], [106.43597, 17.01362], [106.31929, 17.20509], [106.29287, 17.3018], [106.24444, 17.24714], [106.18991, 17.28227], [106.09019, 17.36399], [105.85744, 17.63221], [105.76612, 17.67147], [105.60381, 17.89356], [105.64784, 17.96687], [105.46292, 18.22008], [105.38366, 18.15315], [105.15942, 18.38691], [105.10408, 18.43533], [105.1327, 18.58355], [105.19654, 18.64196], [105.12829, 18.70453], [104.64617, 18.85668], [104.5361, 18.97747], [103.87125, 19.31854], [104.06058, 19.43484], [104.10832, 19.51575], [104.05617, 19.61743], [104.06498, 19.66926], [104.23229, 19.70242], [104.41281, 19.70035], [104.53169, 19.61743], [104.64837, 19.62365], [104.68359, 19.72729], [104.8355, 19.80395], [104.8465, 19.91783], [104.9874, 20.09573], [104.91695, 20.15567], [104.86852, 20.14121], [104.61315, 20.24452], [104.62195, 20.36633], [104.72102, 20.40554], [104.66158, 20.47774], [104.47886, 20.37459], [104.40621, 20.3849], [104.38199, 20.47155], [104.63957, 20.6653], [104.27412, 20.91433], [104.11121, 20.96779], [103.98024, 20.91531], [103.82282, 20.8732], [103.73478, 20.6669], [103.68633, 20.66324], [103.45737, 20.82382], [103.38032, 20.79501], [103.21497, 20.89832], [103.12055, 20.89994], [103.03469, 21.05821], [102.97745, 21.05821], [102.89825, 21.24707], [102.80794, 21.25736], [102.88939, 21.3107], [102.94223, 21.46034], [102.86297, 21.4255], [102.98846, 21.58936], [102.97965, 21.74076], [102.86077, 21.71213], [102.85637, 21.84501], [102.81894, 21.83888], [102.82115, 21.73667], [102.74189, 21.66713], [102.67145, 21.65894], [102.62301, 21.91447], [102.49092, 21.99002], [102.51734, 22.02676], [102.18712, 22.30403], [102.14099, 22.40092], [102.1245, 22.43372]]]]
25635 groups: ["145", "142", "UN"],
25636 callingCodes: ["961"]
25639 type: "MultiPolygon",
25640 coordinates: [[[[35.94816, 33.47886], [35.94465, 33.52774], [36.05723, 33.57904], [35.9341, 33.6596], [36.06778, 33.82927], [36.14517, 33.85118], [36.3967, 33.83365], [36.38263, 33.86579], [36.28589, 33.91981], [36.41078, 34.05253], [36.50576, 34.05982], [36.5128, 34.09916], [36.62537, 34.20251], [36.59195, 34.2316], [36.58667, 34.27667], [36.60778, 34.31009], [36.56556, 34.31881], [36.53039, 34.3798], [36.55853, 34.41609], [36.46179, 34.46541], [36.4442, 34.50165], [36.34745, 34.5002], [36.3369, 34.52629], [36.39846, 34.55672], [36.41429, 34.61175], [36.45299, 34.59438], [36.46003, 34.6378], [36.42941, 34.62505], [36.35384, 34.65447], [36.35135, 34.68516], [36.32399, 34.69334], [36.29165, 34.62991], [35.98718, 34.64977], [35.97386, 34.63322], [35.48515, 34.70851], [34.78515, 33.20368], [35.10645, 33.09318], [35.1924, 33.08743], [35.31429, 33.10515], [35.35223, 33.05617], [35.43059, 33.06659], [35.448, 33.09264], [35.50272, 33.09056], [35.50335, 33.114], [35.52573, 33.11921], [35.54228, 33.19865], [35.5362, 33.23196], [35.54808, 33.236], [35.54544, 33.25513], [35.55555, 33.25844], [35.56523, 33.28969], [35.58326, 33.28381], [35.58502, 33.26653], [35.62283, 33.24226], [35.62019, 33.27278], [35.77477, 33.33609], [35.81324, 33.36354], [35.82577, 33.40479], [35.88668, 33.43183], [35.94816, 33.47886]]]]
25649 nameEn: "St. Lucia",
25651 groups: ["029", "003", "419", "019", "UN"],
25653 roadSpeedUnit: "mph",
25654 callingCodes: ["1 758"]
25657 type: "MultiPolygon",
25658 coordinates: [[[[-59.95997, 14.20285], [-61.69315, 14.26451], [-59.94058, 12.34011], [-59.95997, 14.20285]]]]
25667 nameEn: "Liechtenstein",
25669 groups: ["155", "150", "UN"],
25670 callingCodes: ["423"]
25673 type: "MultiPolygon",
25674 coordinates: [[[[9.60717, 47.06091], [9.61216, 47.07732], [9.63395, 47.08443], [9.62623, 47.14685], [9.56539, 47.17124], [9.58264, 47.20673], [9.56981, 47.21926], [9.55176, 47.22585], [9.56766, 47.24281], [9.53116, 47.27029], [9.52406, 47.24959], [9.50318, 47.22153], [9.4891, 47.19346], [9.48774, 47.17402], [9.51044, 47.13727], [9.52089, 47.10019], [9.51362, 47.08505], [9.47139, 47.06402], [9.47548, 47.05257], [9.54041, 47.06495], [9.55721, 47.04762], [9.60717, 47.06091]]]]
25683 nameEn: "Sri Lanka",
25684 groups: ["034", "142", "UN"],
25686 callingCodes: ["94"]
25689 type: "MultiPolygon",
25690 coordinates: [[[[76.59015, 5.591], [85.15017, 5.21497], [80.48418, 10.20786], [79.42124, 9.80115], [79.50447, 8.91876], [76.59015, 5.591]]]]
25700 groups: ["011", "202", "002", "UN"],
25701 callingCodes: ["231"]
25704 type: "MultiPolygon",
25705 coordinates: [[[[-8.47114, 7.55676], [-8.55874, 7.62525], [-8.55874, 7.70167], [-8.67814, 7.69428], [-8.72789, 7.51429], [-8.8448, 7.35149], [-8.85724, 7.26019], [-8.93435, 7.2824], [-9.09107, 7.1985], [-9.18311, 7.30461], [-9.20798, 7.38109], [-9.305, 7.42056], [-9.41943, 7.41809], [-9.48161, 7.37122], [-9.37465, 7.62032], [-9.35724, 7.74111], [-9.44928, 7.9284], [-9.41445, 8.02448], [-9.50898, 8.18455], [-9.47415, 8.35195], [-9.77763, 8.54633], [-10.05873, 8.42578], [-10.05375, 8.50697], [-10.14579, 8.52665], [-10.203, 8.47991], [-10.27575, 8.48711], [-10.30084, 8.30008], [-10.31635, 8.28554], [-10.29839, 8.21283], [-10.35227, 8.15223], [-10.45023, 8.15627], [-10.51554, 8.1393], [-10.57523, 8.04829], [-10.60492, 8.04072], [-10.60422, 7.7739], [-11.29417, 7.21576], [-11.4027, 6.97746], [-11.50429, 6.92704], [-12.15048, 6.15992], [-7.52774, 3.7105], [-7.53259, 4.35145], [-7.59349, 4.8909], [-7.53876, 4.94294], [-7.55369, 5.08667], [-7.48901, 5.14118], [-7.46165, 5.26256], [-7.36463, 5.32944], [-7.43428, 5.42355], [-7.37209, 5.61173], [-7.43926, 5.74787], [-7.43677, 5.84687], [-7.46165, 5.84934], [-7.48155, 5.80974], [-7.67309, 5.94337], [-7.70294, 5.90625], [-7.78254, 5.99037], [-7.79747, 6.07696], [-7.8497, 6.08932], [-7.83478, 6.20309], [-7.90692, 6.27728], [-8.00642, 6.31684], [-8.17557, 6.28222], [-8.3298, 6.36381], [-8.38453, 6.35887], [-8.45666, 6.49977], [-8.48652, 6.43797], [-8.59456, 6.50612], [-8.31736, 6.82837], [-8.29249, 7.1691], [-8.37458, 7.25794], [-8.41935, 7.51203], [-8.47114, 7.55676]]]]
25715 groups: ["018", "202", "002", "UN"],
25717 callingCodes: ["266"]
25720 type: "MultiPolygon",
25721 coordinates: [[[[29.33204, -29.45598], [29.44883, -29.3772], [29.40524, -29.21246], [28.68043, -28.58744], [28.65091, -28.57025], [28.40612, -28.6215], [28.30518, -28.69531], [28.2348, -28.69471], [28.1317, -28.7293], [28.02503, -28.85991], [27.98675, -28.8787], [27.9392, -28.84864], [27.88933, -28.88156], [27.8907, -28.91612], [27.75458, -28.89839], [27.55974, -29.18954], [27.5158, -29.2261], [27.54258, -29.25575], [27.48679, -29.29349], [27.45125, -29.29708], [27.47254, -29.31968], [27.4358, -29.33465], [27.33464, -29.48161], [27.01016, -29.65439], [27.09489, -29.72796], [27.22719, -30.00718], [27.29603, -30.05473], [27.32555, -30.14785], [27.40778, -30.14577], [27.37293, -30.19401], [27.36649, -30.27246], [27.38108, -30.33456], [27.45452, -30.32239], [27.56901, -30.42504], [27.56781, -30.44562], [27.62137, -30.50509], [27.6521, -30.51707], [27.67819, -30.53437], [27.69467, -30.55862], [27.74814, -30.60635], [28.12073, -30.68072], [28.2319, -30.28476], [28.399, -30.1592], [28.68627, -30.12885], [28.80222, -30.10579], [28.9338, -30.05072], [29.16548, -29.91706], [29.12553, -29.76266], [29.28545, -29.58456], [29.33204, -29.45598]]]]
25730 nameEn: "Lithuania",
25731 groups: ["EU", "154", "150", "UN"],
25732 callingCodes: ["370"]
25735 type: "MultiPolygon",
25736 coordinates: [[[[24.89005, 56.46666], [24.83686, 56.41565], [24.70022, 56.40483], [24.57353, 56.31525], [24.58143, 56.29125], [24.42746, 56.26522], [24.32334, 56.30226], [24.13139, 56.24881], [24.02657, 56.3231], [23.75726, 56.37282], [23.49803, 56.34307], [23.40486, 56.37689], [23.31606, 56.3827], [23.17312, 56.36795], [23.09531, 56.30511], [22.96988, 56.41213], [22.83048, 56.367], [22.69354, 56.36284], [22.56441, 56.39305], [22.3361, 56.4016], [22.09728, 56.42851], [22.00548, 56.41508], [21.74558, 56.33181], [21.57888, 56.31406], [21.49736, 56.29106], [21.24644, 56.16917], [21.15016, 56.07818], [20.68447, 56.04073], [20.60454, 55.40986], [20.95181, 55.27994], [21.26425, 55.24456], [21.35465, 55.28427], [21.38446, 55.29348], [21.46766, 55.21115], [21.51095, 55.18507], [21.55605, 55.20311], [21.64954, 55.1791], [21.85521, 55.09493], [21.96505, 55.07353], [21.99543, 55.08691], [22.03984, 55.07888], [22.02582, 55.05078], [22.06087, 55.02935], [22.11697, 55.02131], [22.14267, 55.05345], [22.31562, 55.0655], [22.47688, 55.04408], [22.58907, 55.07085], [22.60075, 55.01863], [22.65451, 54.97037], [22.68723, 54.9811], [22.76422, 54.92521], [22.85083, 54.88711], [22.87317, 54.79492], [22.73631, 54.72952], [22.73397, 54.66604], [22.75467, 54.6483], [22.74225, 54.64339], [22.7522, 54.63525], [22.68021, 54.58486], [22.71293, 54.56454], [22.67788, 54.532], [22.70208, 54.45312], [22.7253, 54.41732], [22.79705, 54.36264], [22.83756, 54.40827], [23.00584, 54.38514], [22.99649, 54.35927], [23.05726, 54.34565], [23.04323, 54.31567], [23.104, 54.29794], [23.13905, 54.31567], [23.15526, 54.31076], [23.15938, 54.29894], [23.24656, 54.25701], [23.3494, 54.25155], [23.39525, 54.21672], [23.42418, 54.17911], [23.45223, 54.17775], [23.49196, 54.14764], [23.52702, 54.04622], [23.48261, 53.98855], [23.51284, 53.95052], [23.61677, 53.92691], [23.71726, 53.93379], [23.80543, 53.89558], [23.81309, 53.94205], [23.95098, 53.9613], [23.98837, 53.92554], [24.19638, 53.96405], [24.34128, 53.90076], [24.44411, 53.90076], [24.62275, 54.00217], [24.69652, 54.01901], [24.69185, 53.96543], [24.74279, 53.96663], [24.85311, 54.02862], [24.77131, 54.11091], [24.96894, 54.17589], [24.991, 54.14241], [25.0728, 54.13419], [25.19199, 54.219], [25.22705, 54.26271], [25.35559, 54.26544], [25.509, 54.30267], [25.56823, 54.25212], [25.51452, 54.17799], [25.54724, 54.14925], [25.64875, 54.1259], [25.71084, 54.16704], [25.78563, 54.15747], [25.78553, 54.23327], [25.68513, 54.31727], [25.55425, 54.31591], [25.5376, 54.33158], [25.63371, 54.42075], [25.62203, 54.4656], [25.64813, 54.48704], [25.68045, 54.5321], [25.75977, 54.57252], [25.74122, 54.80108], [25.89462, 54.93438], [25.99129, 54.95705], [26.05907, 54.94631], [26.13386, 54.98924], [26.20397, 54.99729], [26.26941, 55.08032], [26.23202, 55.10439], [26.30628, 55.12536], [26.35121, 55.1525], [26.46249, 55.12814], [26.51481, 55.16051], [26.54753, 55.14181], [26.69243, 55.16718], [26.68075, 55.19787], [26.72983, 55.21788], [26.73017, 55.24226], [26.835, 55.28182], [26.83266, 55.30444], [26.80929, 55.31642], [26.6714, 55.33902], [26.5709, 55.32572], [26.44937, 55.34832], [26.5522, 55.40277], [26.55094, 55.5093], [26.63167, 55.57887], [26.63231, 55.67968], [26.58248, 55.6754], [26.46661, 55.70375], [26.39561, 55.71156], [26.18509, 55.86813], [26.03815, 55.95884], [25.90047, 56.0013], [25.85893, 56.00188], [25.81773, 56.05444], [25.69246, 56.08892], [25.68588, 56.14725], [25.53621, 56.16663], [25.39751, 56.15707], [25.23099, 56.19147], [25.09325, 56.1878], [25.05762, 56.26742], [24.89005, 56.46666]]]]
25745 nameEn: "Luxembourg",
25746 groups: ["EU", "155", "150", "UN"],
25747 callingCodes: ["352"]
25750 type: "MultiPolygon",
25751 coordinates: [[[[6.1379, 50.12964], [6.1137, 50.13668], [6.12028, 50.16374], [6.08577, 50.17246], [6.06406, 50.15344], [6.03093, 50.16362], [6.02488, 50.18283], [5.96453, 50.17259], [5.95929, 50.13295], [5.89488, 50.11476], [5.8857, 50.07824], [5.85474, 50.06342], [5.86904, 50.04614], [5.8551, 50.02683], [5.81866, 50.01286], [5.82331, 49.99662], [5.83968, 49.9892], [5.83467, 49.97823], [5.81163, 49.97142], [5.80833, 49.96451], [5.77291, 49.96056], [5.77314, 49.93646], [5.73621, 49.89796], [5.78415, 49.87922], [5.75269, 49.8711], [5.75861, 49.85631], [5.74567, 49.85368], [5.75884, 49.84811], [5.74953, 49.84709], [5.74975, 49.83933], [5.74076, 49.83823], [5.7404, 49.83452], [5.74844, 49.82435], [5.74364, 49.82058], [5.74953, 49.81428], [5.75409, 49.79239], [5.78871, 49.7962], [5.82245, 49.75048], [5.83149, 49.74729], [5.82562, 49.72395], [5.84193, 49.72161], [5.86503, 49.72739], [5.88677, 49.70951], [5.86527, 49.69291], [5.86175, 49.67862], [5.9069, 49.66377], [5.90164, 49.6511], [5.90599, 49.63853], [5.88552, 49.63507], [5.88393, 49.62802], [5.87609, 49.62047], [5.8762, 49.60898], [5.84826, 49.5969], [5.84971, 49.58674], [5.86986, 49.58756], [5.87256, 49.57539], [5.8424, 49.56082], [5.84692, 49.55663], [5.84143, 49.5533], [5.81838, 49.54777], [5.80871, 49.5425], [5.81664, 49.53775], [5.83648, 49.5425], [5.84466, 49.53027], [5.83467, 49.52717], [5.83389, 49.52152], [5.86571, 49.50015], [5.94128, 49.50034], [5.94224, 49.49608], [5.96876, 49.49053], [5.97693, 49.45513], [6.02648, 49.45451], [6.02743, 49.44845], [6.04176, 49.44801], [6.05553, 49.46663], [6.07887, 49.46399], [6.08373, 49.45594], [6.10072, 49.45268], [6.09845, 49.46351], [6.10325, 49.4707], [6.12346, 49.4735], [6.12814, 49.49365], [6.14321, 49.48796], [6.16115, 49.49297], [6.15366, 49.50226], [6.17386, 49.50934], [6.19543, 49.50536], [6.2409, 49.51408], [6.25029, 49.50609], [6.27875, 49.503], [6.28818, 49.48465], [6.3687, 49.4593], [6.36778, 49.46937], [6.36907, 49.48931], [6.36788, 49.50377], [6.35666, 49.52931], [6.38072, 49.55171], [6.38228, 49.55855], [6.35825, 49.57053], [6.36676, 49.57813], [6.38024, 49.57593], [6.38342, 49.5799], [6.37464, 49.58886], [6.385, 49.59946], [6.39822, 49.60081], [6.41861, 49.61723], [6.4413, 49.65722], [6.43768, 49.66021], [6.42726, 49.66078], [6.42937, 49.66857], [6.44654, 49.67799], [6.46048, 49.69092], [6.48014, 49.69767], [6.49785, 49.71118], [6.50647, 49.71353], [6.5042, 49.71808], [6.49694, 49.72205], [6.49535, 49.72645], [6.50261, 49.72718], [6.51397, 49.72058], [6.51805, 49.72425], [6.50193, 49.73291], [6.50174, 49.75292], [6.51646, 49.75961], [6.51828, 49.76855], [6.51056, 49.77515], [6.51669, 49.78336], [6.50534, 49.78952], [6.52169, 49.79787], [6.53122, 49.80666], [6.52121, 49.81338], [6.51215, 49.80124], [6.50647, 49.80916], [6.48718, 49.81267], [6.47111, 49.82263], [6.45425, 49.81164], [6.44131, 49.81443], [6.42905, 49.81091], [6.42521, 49.81591], [6.40022, 49.82029], [6.36576, 49.85032], [6.34267, 49.84974], [6.33585, 49.83785], [6.32098, 49.83728], [6.32303, 49.85133], [6.30963, 49.87021], [6.29692, 49.86685], [6.28874, 49.87592], [6.26146, 49.88203], [6.23496, 49.89972], [6.22926, 49.92096], [6.21882, 49.92403], [6.22608, 49.929], [6.22094, 49.94955], [6.19856, 49.95053], [6.19089, 49.96991], [6.18045, 49.96611], [6.18554, 49.95622], [6.17872, 49.9537], [6.16466, 49.97086], [6.1701, 49.98518], [6.14147, 49.99563], [6.14948, 50.00908], [6.13806, 50.01056], [6.1295, 50.01849], [6.13273, 50.02019], [6.13794, 50.01466], [6.14666, 50.02207], [6.13044, 50.02929], [6.13458, 50.04141], [6.11274, 50.05916], [6.12055, 50.09171], [6.1379, 50.12964]]]]
25761 groups: ["EU", "154", "150", "UN"],
25762 callingCodes: ["371"]
25765 type: "MultiPolygon",
25766 coordinates: [[[[27.34698, 57.52242], [26.90364, 57.62823], [26.54675, 57.51813], [26.46527, 57.56885], [26.29253, 57.59244], [26.1866, 57.6849], [26.2029, 57.7206], [26.08098, 57.76619], [26.0543, 57.76105], [26.03332, 57.7718], [26.02415, 57.76865], [26.02069, 57.77169], [26.0266, 57.77441], [26.027, 57.78158], [26.02456, 57.78342], [26.0324, 57.79037], [26.05949, 57.84744], [25.73499, 57.90193], [25.29581, 58.08288], [25.28237, 57.98539], [25.19484, 58.0831], [24.3579, 57.87471], [24.26221, 57.91787], [23.20055, 57.56697], [22.80496, 57.87798], [19.84909, 57.57876], [19.64795, 57.06466], [20.68447, 56.04073], [21.15016, 56.07818], [21.24644, 56.16917], [21.49736, 56.29106], [21.57888, 56.31406], [21.74558, 56.33181], [22.00548, 56.41508], [22.09728, 56.42851], [22.3361, 56.4016], [22.56441, 56.39305], [22.69354, 56.36284], [22.83048, 56.367], [22.96988, 56.41213], [23.09531, 56.30511], [23.17312, 56.36795], [23.31606, 56.3827], [23.40486, 56.37689], [23.49803, 56.34307], [23.75726, 56.37282], [24.02657, 56.3231], [24.13139, 56.24881], [24.32334, 56.30226], [24.42746, 56.26522], [24.58143, 56.29125], [24.57353, 56.31525], [24.70022, 56.40483], [24.83686, 56.41565], [24.89005, 56.46666], [25.05762, 56.26742], [25.09325, 56.1878], [25.23099, 56.19147], [25.39751, 56.15707], [25.53621, 56.16663], [25.68588, 56.14725], [25.69246, 56.08892], [25.81773, 56.05444], [25.85893, 56.00188], [25.90047, 56.0013], [26.03815, 55.95884], [26.18509, 55.86813], [26.39561, 55.71156], [26.46661, 55.70375], [26.58248, 55.6754], [26.63231, 55.67968], [26.64888, 55.70515], [26.71802, 55.70645], [26.76872, 55.67658], [26.87448, 55.7172], [26.97153, 55.8102], [27.1559, 55.85032], [27.27804, 55.78299], [27.3541, 55.8089], [27.61683, 55.78558], [27.63065, 55.89687], [27.97865, 56.11849], [28.15217, 56.16964], [28.23716, 56.27588], [28.16599, 56.37806], [28.19057, 56.44637], [28.10069, 56.524], [28.13526, 56.57989], [28.04768, 56.59004], [27.86101, 56.88204], [27.66511, 56.83921], [27.86101, 57.29402], [27.52453, 57.42826], [27.56832, 57.53728], [27.34698, 57.52242]]]]
25776 groups: ["015", "002", "UN"],
25777 callingCodes: ["218"]
25780 type: "MultiPolygon",
25781 coordinates: [[[[26.92891, 33.39516], [11.58941, 33.36891], [11.55852, 33.1409], [11.51549, 33.09826], [11.46037, 32.6307], [11.57828, 32.48013], [11.53898, 32.4138], [11.04234, 32.2145], [10.7315, 31.97235], [10.62788, 31.96629], [10.48497, 31.72956], [10.31364, 31.72648], [10.12239, 31.42098], [10.29516, 30.90337], [9.88152, 30.34074], [9.76848, 30.34366], [9.55544, 30.23971], [9.3876, 30.16738], [9.78136, 29.40961], [9.89569, 26.57696], [9.51696, 26.39148], [9.38834, 26.19288], [10.03146, 25.35635], [10.02432, 24.98124], [10.33159, 24.5465], [10.85323, 24.5595], [11.41061, 24.21456], [11.62498, 24.26669], [11.96886, 23.51735], [13.5631, 23.16574], [14.22918, 22.61719], [14.99751, 23.00539], [15.99566, 23.49639], [23.99539, 19.49944], [23.99715, 20.00038], [24.99794, 19.99661], [24.99885, 21.99535], [24.99968, 29.24574], [24.71117, 30.17441], [25.01077, 30.73861], [24.8458, 31.39877], [26.92891, 33.39516]]]]
25791 groups: ["015", "002", "UN"],
25792 callingCodes: ["212"]
25795 type: "MultiPolygon",
25796 coordinates: [[[[-2.27707, 35.35051], [-5.10878, 36.05227], [-7.2725, 35.73269], [-14.43883, 27.02969], [-17.27295, 21.93519], [-17.21511, 21.34226], [-17.02707, 21.34022], [-16.9978, 21.36239], [-16.44269, 21.39745], [-14.78487, 21.36587], [-14.47329, 21.63839], [-14.48112, 22.00886], [-14.1291, 22.41636], [-14.10361, 22.75501], [-13.75627, 23.77231], [-13.00628, 24.01923], [-12.92147, 24.39502], [-12.12281, 25.13682], [-12.06001, 26.04442], [-11.62052, 26.05229], [-11.38635, 26.611], [-11.23622, 26.72023], [-11.35695, 26.8505], [-10.68417, 26.90984], [-9.81998, 26.71379], [-9.56957, 26.90042], [-9.08698, 26.98639], [-8.71787, 26.9898], [-8.77527, 27.66663], [-8.66879, 27.6666], [-8.6715, 28.71194], [-7.61585, 29.36252], [-6.95824, 29.50924], [-6.78351, 29.44634], [-6.69965, 29.51623], [-5.75616, 29.61407], [-5.72121, 29.52322], [-5.58831, 29.48103], [-5.21671, 29.95253], [-4.6058, 30.28343], [-4.31774, 30.53229], [-3.64735, 30.67539], [-3.65418, 30.85566], [-3.54944, 31.0503], [-3.77103, 31.14984], [-3.77647, 31.31912], [-3.66386, 31.39202], [-3.66314, 31.6339], [-2.82784, 31.79459], [-2.93873, 32.06557], [-2.46166, 32.16603], [-1.22829, 32.07832], [-1.15735, 32.12096], [-1.24453, 32.1917], [-1.24998, 32.32993], [-0.9912, 32.52467], [-1.37794, 32.73628], [-1.54244, 32.95499], [-1.46249, 33.0499], [-1.67067, 33.27084], [-1.59508, 33.59929], [-1.73494, 33.71721], [-1.64666, 34.10405], [-1.78042, 34.39018], [-1.69788, 34.48056], [-1.84569, 34.61907], [-1.73707, 34.74226], [-1.97469, 34.886], [-1.97833, 34.93218], [-2.04734, 34.93218], [-2.21445, 35.04378], [-2.21248, 35.08532], [-2.27707, 35.35051]], [[-2.91909, 35.33927], [-2.92272, 35.27509], [-2.93893, 35.26737], [-2.95065, 35.26576], [-2.95431, 35.2728], [-2.96516, 35.27967], [-2.96826, 35.28296], [-2.96507, 35.28801], [-2.97035, 35.28852], [-2.96978, 35.29459], [-2.96648, 35.30475], [-2.96038, 35.31609], [-2.91909, 35.33927]], [[-3.90602, 35.21494], [-3.89343, 35.22728], [-3.88372, 35.20767], [-3.90602, 35.21494]], [[-4.30191, 35.17419], [-4.29436, 35.17149], [-4.30112, 35.17058], [-4.30191, 35.17419]], [[-2.40316, 35.16893], [-2.45965, 35.16527], [-2.43262, 35.20652], [-2.40316, 35.16893]], [[-5.38491, 35.92591], [-5.21179, 35.90091], [-5.34379, 35.8711], [-5.35844, 35.87375], [-5.37338, 35.88417], [-5.38491, 35.92591]]]]
25806 groups: ["155", "150", "UN"],
25807 callingCodes: ["377"]
25810 type: "MultiPolygon",
25811 coordinates: [[[[7.47823, 43.73341], [7.4379, 43.74963], [7.4389, 43.75151], [7.43708, 43.75197], [7.43624, 43.75014], [7.43013, 43.74895], [7.42809, 43.74396], [7.42443, 43.74087], [7.42299, 43.74176], [7.42062, 43.73977], [7.41233, 43.73439], [7.41298, 43.73311], [7.41291, 43.73168], [7.41113, 43.73156], [7.40903, 43.7296], [7.42422, 43.72209], [7.47823, 43.73341]]]]
25821 groups: ["151", "150", "UN"],
25822 callingCodes: ["373"]
25825 type: "MultiPolygon",
25826 coordinates: [[[[27.74422, 48.45926], [27.6658, 48.44034], [27.59027, 48.46311], [27.5889, 48.49224], [27.46942, 48.454], [27.44333, 48.41209], [27.37741, 48.41026], [27.37604, 48.44398], [27.32159, 48.4434], [27.27855, 48.37534], [27.13434, 48.37288], [27.08078, 48.43214], [27.0231, 48.42485], [27.03821, 48.37653], [26.93384, 48.36558], [26.85556, 48.41095], [26.71274, 48.40388], [26.82809, 48.31629], [26.79239, 48.29071], [26.6839, 48.35828], [26.62823, 48.25804], [26.81161, 48.25049], [26.87708, 48.19919], [26.94265, 48.1969], [26.98042, 48.15752], [26.96119, 48.13003], [27.04118, 48.12522], [27.02985, 48.09083], [27.15622, 47.98538], [27.1618, 47.92391], [27.29069, 47.73722], [27.25519, 47.71366], [27.32202, 47.64009], [27.3979, 47.59473], [27.47942, 47.48113], [27.55731, 47.46637], [27.60263, 47.32507], [27.68706, 47.28962], [27.73172, 47.29248], [27.81892, 47.1381], [28.09095, 46.97621], [28.12173, 46.82283], [28.24808, 46.64305], [28.22281, 46.50481], [28.25769, 46.43334], [28.18902, 46.35283], [28.19864, 46.31869], [28.10937, 46.22852], [28.13684, 46.18099], [28.08612, 46.01105], [28.13111, 45.92819], [28.16568, 45.6421], [28.08927, 45.6051], [28.18741, 45.47358], [28.21139, 45.46895], [28.30201, 45.54744], [28.41836, 45.51715], [28.43072, 45.48538], [28.51449, 45.49982], [28.49252, 45.56716], [28.54196, 45.58062], [28.51587, 45.6613], [28.47879, 45.66994], [28.52823, 45.73803], [28.70401, 45.78019], [28.69852, 45.81753], [28.78503, 45.83475], [28.74383, 45.96664], [28.98004, 46.00385], [29.00613, 46.04962], [28.94643, 46.09176], [29.06656, 46.19716], [28.94953, 46.25852], [28.98478, 46.31803], [29.004, 46.31495], [28.9306, 46.45699], [29.01241, 46.46177], [29.02409, 46.49582], [29.23547, 46.55435], [29.24886, 46.37912], [29.35357, 46.49505], [29.49914, 46.45889], [29.5939, 46.35472], [29.6763, 46.36041], [29.66359, 46.4215], [29.74496, 46.45605], [29.88329, 46.35851], [29.94114, 46.40114], [30.09103, 46.38694], [30.16794, 46.40967], [30.02511, 46.45132], [29.88916, 46.54302], [29.94409, 46.56002], [29.9743, 46.75325], [29.94522, 46.80055], [29.98814, 46.82358], [29.87405, 46.88199], [29.75458, 46.8604], [29.72986, 46.92234], [29.57056, 46.94766], [29.62137, 47.05069], [29.61038, 47.09932], [29.53044, 47.07851], [29.49732, 47.12878], [29.57696, 47.13581], [29.54996, 47.24962], [29.59665, 47.25521], [29.5733, 47.36508], [29.48678, 47.36043], [29.47854, 47.30366], [29.39889, 47.30179], [29.3261, 47.44664], [29.18603, 47.43387], [29.11743, 47.55001], [29.22414, 47.60012], [29.22242, 47.73607], [29.27255, 47.79953], [29.20663, 47.80367], [29.27804, 47.88893], [29.19839, 47.89261], [29.1723, 47.99013], [28.9306, 47.96255], [28.8414, 48.03392], [28.85232, 48.12506], [28.69896, 48.13106], [28.53921, 48.17453], [28.48428, 48.0737], [28.42454, 48.12047], [28.43701, 48.15832], [28.38712, 48.17567], [28.34009, 48.13147], [28.30609, 48.14018], [28.30586, 48.1597], [28.34912, 48.1787], [28.36996, 48.20543], [28.35519, 48.24957], [28.32508, 48.23384], [28.2856, 48.23202], [28.19314, 48.20749], [28.17666, 48.25963], [28.07504, 48.23494], [28.09873, 48.3124], [28.04527, 48.32661], [27.95883, 48.32368], [27.88391, 48.36699], [27.87533, 48.4037], [27.81902, 48.41874], [27.79225, 48.44244], [27.74422, 48.45926]]]]
25835 nameEn: "Montenegro",
25836 groups: ["039", "150", "UN"],
25837 callingCodes: ["382"]
25840 type: "MultiPolygon",
25841 coordinates: [[[[19.22807, 43.5264], [19.15685, 43.53943], [19.13933, 43.5282], [19.04934, 43.50384], [19.01078, 43.55806], [18.91379, 43.50299], [18.95469, 43.49367], [18.96053, 43.45042], [19.01078, 43.43854], [19.04071, 43.397], [19.08673, 43.31453], [19.08206, 43.29668], [19.04233, 43.30008], [19.00844, 43.24988], [18.95001, 43.29327], [18.95819, 43.32899], [18.90911, 43.36383], [18.83912, 43.34795], [18.84794, 43.33735], [18.85342, 43.32426], [18.76538, 43.29838], [18.6976, 43.25243], [18.71747, 43.2286], [18.66605, 43.2056], [18.64735, 43.14766], [18.66254, 43.03928], [18.52232, 43.01451], [18.49076, 42.95553], [18.49661, 42.89306], [18.4935, 42.86433], [18.47633, 42.85829], [18.45921, 42.81682], [18.47324, 42.74992], [18.56789, 42.72074], [18.55221, 42.69045], [18.54603, 42.69171], [18.54841, 42.68328], [18.57373, 42.64429], [18.52232, 42.62279], [18.55504, 42.58409], [18.53751, 42.57376], [18.49778, 42.58409], [18.43735, 42.55921], [18.44307, 42.51077], [18.43588, 42.48556], [18.52152, 42.42302], [18.54128, 42.39171], [18.45131, 42.21682], [19.26406, 41.74971], [19.37597, 41.84849], [19.37451, 41.8842], [19.33812, 41.90669], [19.34601, 41.95675], [19.37691, 41.96977], [19.36867, 42.02564], [19.37548, 42.06835], [19.40687, 42.10024], [19.28623, 42.17745], [19.42, 42.33019], [19.42352, 42.36546], [19.4836, 42.40831], [19.65972, 42.62774], [19.73244, 42.66299], [19.77375, 42.58517], [19.74731, 42.57422], [19.76549, 42.50237], [19.82333, 42.46581], [19.9324, 42.51699], [20.00842, 42.5109], [20.01834, 42.54622], [20.07761, 42.55582], [20.0969, 42.65559], [20.02915, 42.71147], [20.02088, 42.74789], [20.04898, 42.77701], [20.2539, 42.76245], [20.27869, 42.81945], [20.35692, 42.8335], [20.34528, 42.90676], [20.16415, 42.97177], [20.14896, 42.99058], [20.12325, 42.96237], [20.05431, 42.99571], [20.04729, 43.02732], [19.98887, 43.0538], [19.96549, 43.11098], [19.92576, 43.08539], [19.79255, 43.11951], [19.76918, 43.16044], [19.64063, 43.19027], [19.62661, 43.2286], [19.54598, 43.25158], [19.52962, 43.31623], [19.48171, 43.32644], [19.44315, 43.38846], [19.22229, 43.47926], [19.22807, 43.5264]]]]
25849 wikidata: "Q126125",
25850 nameEn: "Saint-Martin",
25852 groups: ["Q3320166", "EU", "029", "003", "419", "019", "UN"],
25853 callingCodes: ["590"]
25856 type: "MultiPolygon",
25857 coordinates: [[[[-62.93924, 18.02904], [-62.62718, 18.26185], [-63.35989, 18.06012], [-63.33064, 17.9615], [-63.13502, 18.05445], [-63.11042, 18.05339], [-63.09686, 18.04608], [-63.07759, 18.04943], [-63.0579, 18.06614], [-63.04039, 18.05619], [-63.02323, 18.05757], [-62.93924, 18.02904]]]]
25866 nameEn: "Madagascar",
25868 groups: ["014", "202", "002", "UN"],
25869 callingCodes: ["261"]
25872 type: "MultiPolygon",
25873 coordinates: [[[[51.93891, -10.85085], [45.84651, -12.77177], [42.14681, -19.63341], [45.80092, -33.00974], [51.93891, -10.85085]]]]
25882 nameEn: "Marshall Islands",
25883 groups: ["057", "009", "UN"],
25884 roadSpeedUnit: "mph",
25885 callingCodes: ["692"]
25888 type: "MultiPolygon",
25889 coordinates: [[[[169, 3.9], [173.53711, 5.70687], [169.29099, 15.77133], [159.04653, 10.59067], [169, 3.9]]]]
25898 nameEn: "North Macedonia",
25899 groups: ["039", "150", "UN"],
25900 callingCodes: ["389"]
25903 type: "MultiPolygon",
25904 coordinates: [[[[22.34773, 42.31725], [22.29275, 42.34913], [22.29605, 42.37477], [22.16384, 42.32103], [22.02908, 42.29848], [21.94405, 42.34669], [21.91595, 42.30392], [21.84654, 42.3247], [21.77176, 42.2648], [21.70111, 42.23789], [21.58992, 42.25915], [21.52145, 42.24465], [21.50823, 42.27156], [21.43882, 42.2789], [21.43882, 42.23609], [21.38428, 42.24465], [21.30496, 42.1418], [21.29913, 42.13954], [21.31983, 42.10993], [21.22728, 42.08909], [21.16614, 42.19815], [21.11491, 42.20794], [20.75464, 42.05229], [20.76786, 41.91839], [20.68523, 41.85318], [20.59524, 41.8818], [20.55976, 41.87068], [20.57144, 41.7897], [20.53405, 41.78099], [20.51301, 41.72433], [20.52937, 41.69292], [20.51769, 41.65975], [20.55508, 41.58113], [20.52103, 41.56473], [20.45809, 41.5549], [20.45331, 41.51436], [20.49039, 41.49277], [20.51301, 41.442], [20.55976, 41.4087], [20.52119, 41.34381], [20.49432, 41.33679], [20.51068, 41.2323], [20.59715, 41.13644], [20.58546, 41.11179], [20.59832, 41.09066], [20.63454, 41.0889], [20.65558, 41.08009], [20.71634, 40.91781], [20.73504, 40.9081], [20.81567, 40.89662], [20.83671, 40.92752], [20.94305, 40.92399], [20.97693, 40.90103], [20.97887, 40.85475], [21.15262, 40.85546], [21.21105, 40.8855], [21.25779, 40.86165], [21.35595, 40.87578], [21.41555, 40.9173], [21.53007, 40.90759], [21.57448, 40.86076], [21.69601, 40.9429], [21.7556, 40.92525], [21.91102, 41.04786], [21.90869, 41.09191], [22.06527, 41.15617], [22.1424, 41.12449], [22.17629, 41.15969], [22.26744, 41.16409], [22.42285, 41.11921], [22.5549, 41.13065], [22.58295, 41.11568], [22.62852, 41.14385], [22.65306, 41.18168], [22.71266, 41.13945], [22.74538, 41.16321], [22.76408, 41.32225], [22.81199, 41.3398], [22.93334, 41.34104], [22.96331, 41.35782], [22.95513, 41.63265], [23.03342, 41.71034], [23.01239, 41.76527], [22.96682, 41.77137], [22.90254, 41.87587], [22.86749, 42.02275], [22.67701, 42.06614], [22.51224, 42.15457], [22.50289, 42.19527], [22.47251, 42.20393], [22.38136, 42.30339], [22.34773, 42.31725]]]]
25914 groups: ["011", "202", "002", "UN"],
25915 callingCodes: ["223"]
25918 type: "MultiPolygon",
25919 coordinates: [[[[-4.83423, 24.99935], [-6.57191, 25.0002], [-5.60725, 16.49919], [-5.33435, 16.33354], [-5.50165, 15.50061], [-9.32979, 15.50032], [-9.31106, 15.69412], [-9.33314, 15.7044], [-9.44673, 15.60553], [-9.40447, 15.4396], [-10.71721, 15.4223], [-10.90932, 15.11001], [-11.43483, 15.62339], [-11.70705, 15.51558], [-11.94903, 14.76143], [-12.23936, 14.76324], [-11.93043, 13.84505], [-12.06897, 13.71049], [-11.83345, 13.33333], [-11.63025, 13.39174], [-11.39935, 12.97808], [-11.37536, 12.40788], [-11.50006, 12.17826], [-11.24136, 12.01286], [-10.99758, 12.24634], [-10.80355, 12.1053], [-10.71897, 11.91552], [-10.30604, 12.24634], [-9.714, 12.0226], [-9.63938, 12.18312], [-9.32097, 12.29009], [-9.38067, 12.48446], [-9.13689, 12.50875], [-8.94784, 12.34842], [-8.80854, 11.66715], [-8.40058, 11.37466], [-8.66923, 10.99397], [-8.35083, 11.06234], [-8.2667, 10.91762], [-8.32614, 10.69273], [-8.22711, 10.41722], [-8.10207, 10.44649], [-7.9578, 10.2703], [-7.97971, 10.17117], [-7.92107, 10.15577], [-7.63048, 10.46334], [-7.54462, 10.40921], [-7.52261, 10.4655], [-7.44555, 10.44602], [-7.3707, 10.24677], [-7.13331, 10.24877], [-7.0603, 10.14711], [-7.00966, 10.15794], [-6.97444, 10.21644], [-7.01186, 10.25111], [-6.93921, 10.35291], [-6.68164, 10.35074], [-6.63541, 10.66893], [-6.52974, 10.59104], [-6.42847, 10.5694], [-6.40646, 10.69922], [-6.325, 10.68624], [-6.24795, 10.74248], [-6.1731, 10.46983], [-6.18851, 10.24244], [-5.99478, 10.19694], [-5.78124, 10.43952], [-5.65135, 10.46767], [-5.51058, 10.43177], [-5.46643, 10.56074], [-5.47083, 10.75329], [-5.41579, 10.84628], [-5.49284, 11.07538], [-5.32994, 11.13371], [-5.32553, 11.21578], [-5.25949, 11.24816], [-5.25509, 11.36905], [-5.20665, 11.43811], [-5.22867, 11.60421], [-5.29251, 11.61715], [-5.26389, 11.75728], [-5.40258, 11.8327], [-5.26389, 11.84778], [-5.07897, 11.97918], [-4.72893, 12.01579], [-4.70692, 12.06746], [-4.62987, 12.06531], [-4.62546, 12.13204], [-4.54841, 12.1385], [-4.57703, 12.19875], [-4.41412, 12.31922], [-4.47356, 12.71252], [-4.238, 12.71467], [-4.21819, 12.95722], [-4.34477, 13.12927], [-3.96501, 13.49778], [-3.90558, 13.44375], [-3.96282, 13.38164], [-3.7911, 13.36665], [-3.54454, 13.1781], [-3.4313, 13.1588], [-3.43507, 13.27272], [-3.23599, 13.29035], [-3.28396, 13.5422], [-3.26407, 13.70699], [-2.88189, 13.64921], [-2.90831, 13.81174], [-2.84667, 14.05532], [-2.66175, 14.14713], [-2.47587, 14.29671], [-2.10223, 14.14878], [-1.9992, 14.19011], [-1.97945, 14.47709], [-1.68083, 14.50023], [-1.32166, 14.72774], [-1.05875, 14.7921], [-0.72004, 15.08655], [-0.24673, 15.07805], [0.06588, 14.96961], [0.23859, 15.00135], [0.72632, 14.95898], [0.96711, 14.98275], [1.31275, 15.27978], [3.01806, 15.34571], [3.03134, 15.42221], [3.50368, 15.35934], [4.19893, 16.39923], [4.21787, 17.00118], [4.26762, 17.00432], [4.26651, 19.14224], [3.36082, 18.9745], [3.12501, 19.1366], [3.24648, 19.81703], [1.20992, 20.73533], [1.15698, 21.12843], [-4.83423, 24.99935]]]]
25929 aliases: ["Burma", "BU"],
25930 groups: ["035", "142", "UN"],
25931 callingCodes: ["95"]
25934 type: "MultiPolygon",
25935 coordinates: [[[[92.62187, 21.87037], [92.59775, 21.6092], [92.68152, 21.28454], [92.60187, 21.24615], [92.55105, 21.3856], [92.43158, 21.37025], [92.37939, 21.47764], [92.20087, 21.337], [92.17752, 21.17445], [92.26071, 21.05697], [92.47409, 20.38654], [92.61042, 13.76986], [94.6371, 13.81803], [97.63455, 9.60854], [98.12555, 9.44056], [98.33094, 9.91973], [98.47298, 9.95782], [98.52291, 9.92389], [98.55174, 9.92804], [98.7391, 10.31488], [98.81944, 10.52761], [98.77275, 10.62548], [98.78511, 10.68351], [98.86819, 10.78336], [99.0069, 10.85485], [98.99701, 10.92962], [99.02337, 10.97217], [99.06938, 10.94857], [99.32756, 11.28545], [99.31573, 11.32081], [99.39485, 11.3925], [99.47598, 11.62434], [99.5672, 11.62732], [99.64108, 11.78948], [99.64891, 11.82699], [99.53424, 12.02317], [99.56445, 12.14805], [99.47519, 12.1353], [99.409, 12.60603], [99.29254, 12.68921], [99.18905, 12.84799], [99.18748, 12.9898], [99.10646, 13.05804], [99.12225, 13.19847], [99.20617, 13.20575], [99.16695, 13.72621], [98.97356, 14.04868], [98.56762, 14.37701], [98.24874, 14.83013], [98.18821, 15.13125], [98.22, 15.21327], [98.30446, 15.30667], [98.40522, 15.25268], [98.41906, 15.27103], [98.39351, 15.34177], [98.4866, 15.39154], [98.56027, 15.33471], [98.58598, 15.46821], [98.541, 15.65406], [98.59853, 15.87197], [98.57019, 16.04578], [98.69585, 16.13353], [98.8376, 16.11706], [98.92656, 16.36425], [98.84485, 16.42354], [98.68074, 16.27068], [98.63817, 16.47424], [98.57912, 16.55983], [98.5695, 16.62826], [98.51113, 16.64503], [98.51833, 16.676], [98.51472, 16.68521], [98.51579, 16.69433], [98.51043, 16.70107], [98.49713, 16.69022], [98.50253, 16.7139], [98.46994, 16.73613], [98.53833, 16.81934], [98.49603, 16.8446], [98.52624, 16.89979], [98.39441, 17.06266], [98.34566, 17.04822], [98.10439, 17.33847], [98.11185, 17.36829], [97.91829, 17.54504], [97.76407, 17.71595], [97.66794, 17.88005], [97.73723, 17.97912], [97.60841, 18.23846], [97.64116, 18.29778], [97.56219, 18.33885], [97.50383, 18.26844], [97.34522, 18.54596], [97.36444, 18.57138], [97.5258, 18.4939], [97.76752, 18.58097], [97.73836, 18.88478], [97.66487, 18.9371], [97.73654, 18.9812], [97.73797, 19.04261], [97.83479, 19.09972], [97.84024, 19.22217], [97.78606, 19.26769], [97.84186, 19.29526], [97.78769, 19.39429], [97.88423, 19.5041], [97.84715, 19.55782], [98.04364, 19.65755], [98.03314, 19.80941], [98.13829, 19.78541], [98.24884, 19.67876], [98.51182, 19.71303], [98.56065, 19.67807], [98.83661, 19.80931], [98.98679, 19.7419], [99.0735, 20.10298], [99.20328, 20.12877], [99.416, 20.08614], [99.52943, 20.14811], [99.5569, 20.20676], [99.46077, 20.36198], [99.46008, 20.39673], [99.68255, 20.32077], [99.81096, 20.33687], [99.86383, 20.44371], [99.88211, 20.44488], [99.88451, 20.44596], [99.89168, 20.44548], [99.89301, 20.44311], [99.89692, 20.44789], [99.90499, 20.4487], [99.91616, 20.44986], [99.95721, 20.46301], [100.08404, 20.36626], [100.1957, 20.68247], [100.36375, 20.82783], [100.51079, 20.82194], [100.60112, 20.8347], [100.64628, 20.88279], [100.50974, 20.88574], [100.55281, 21.02796], [100.63578, 21.05639], [100.72716, 21.31786], [100.80173, 21.2934], [101.00234, 21.39612], [101.16198, 21.52808], [101.15156, 21.56129], [101.11744, 21.77659], [100.87265, 21.67396], [100.72143, 21.51898], [100.57861, 21.45637], [100.4811, 21.46148], [100.42892, 21.54325], [100.35201, 21.53176], [100.25863, 21.47043], [100.18447, 21.51898], [100.1625, 21.48704], [100.12542, 21.50365], [100.10757, 21.59945], [100.17486, 21.65306], [100.12679, 21.70539], [100.04956, 21.66843], [99.98654, 21.71064], [99.94003, 21.82782], [99.99084, 21.97053], [99.96612, 22.05965], [99.85351, 22.04183], [99.47585, 22.13345], [99.33166, 22.09656], [99.1552, 22.15874], [99.19176, 22.16983], [99.17318, 22.18025], [99.28771, 22.4105], [99.37972, 22.50188], [99.38247, 22.57544], [99.31243, 22.73893], [99.45654, 22.85726], [99.43537, 22.94086], [99.54218, 22.90014], [99.52214, 23.08218], [99.34127, 23.13099], [99.25741, 23.09025], [99.04601, 23.12215], [99.05975, 23.16382], [98.88597, 23.18656], [98.92515, 23.29535], [98.93958, 23.31414], [98.87573, 23.33038], [98.92104, 23.36946], [98.87683, 23.48995], [98.82877, 23.47908], [98.80294, 23.5345], [98.88396, 23.59555], [98.81775, 23.694], [98.82933, 23.72921], [98.79607, 23.77947], [98.68209, 23.80492], [98.67797, 23.9644], [98.89632, 24.10612], [98.87998, 24.15624], [98.85319, 24.13042], [98.59256, 24.08371], [98.54476, 24.13119], [98.20666, 24.11406], [98.07806, 24.07988], [98.06703, 24.08028], [98.0607, 24.07812], [98.05671, 24.07961], [98.05302, 24.07408], [98.04709, 24.07616], [97.99583, 24.04932], [97.98691, 24.03897], [97.93951, 24.01953], [97.90998, 24.02094], [97.88616, 24.00463], [97.88414, 23.99405], [97.88814, 23.98605], [97.89683, 23.98389], [97.89676, 23.97931], [97.8955, 23.97758], [97.88811, 23.97446], [97.86545, 23.97723], [97.84328, 23.97603], [97.79416, 23.95663], [97.79456, 23.94836], [97.72302, 23.89288], [97.64667, 23.84574], [97.5247, 23.94032], [97.62363, 24.00506], [97.72903, 24.12606], [97.75305, 24.16902], [97.72799, 24.18883], [97.72998, 24.2302], [97.76799, 24.26365], [97.71941, 24.29652], [97.66723, 24.30027], [97.65624, 24.33781], [97.7098, 24.35658], [97.66998, 24.45288], [97.60029, 24.4401], [97.52757, 24.43748], [97.56286, 24.54535], [97.56525, 24.72838], [97.54675, 24.74202], [97.5542, 24.74943], [97.56383, 24.75535], [97.56648, 24.76475], [97.64354, 24.79171], [97.70181, 24.84557], [97.73127, 24.83015], [97.76481, 24.8289], [97.79949, 24.85655], [97.72903, 24.91332], [97.72216, 25.08508], [97.77023, 25.11492], [97.83614, 25.2715], [97.92541, 25.20815], [98.14925, 25.41547], [98.12591, 25.50722], [98.18084, 25.56298], [98.16848, 25.62739], [98.25774, 25.6051], [98.31268, 25.55307], [98.40606, 25.61129], [98.54064, 25.85129], [98.63128, 25.79937], [98.70818, 25.86241], [98.60763, 26.01512], [98.57085, 26.11547], [98.63128, 26.15492], [98.66884, 26.09165], [98.7329, 26.17218], [98.67797, 26.24487], [98.72741, 26.36183], [98.77547, 26.61994], [98.7333, 26.85615], [98.69582, 27.56499], [98.43353, 27.67086], [98.42529, 27.55404], [98.32641, 27.51385], [98.13964, 27.9478], [98.15337, 28.12114], [97.90069, 28.3776], [97.79632, 28.33168], [97.70705, 28.5056], [97.56835, 28.55628], [97.50518, 28.49716], [97.47085, 28.2688], [97.41729, 28.29783], [97.34547, 28.21385], [97.31292, 28.06784], [97.35412, 28.06663], [97.38845, 28.01329], [97.35824, 27.87256], [97.29919, 27.92233], [96.90112, 27.62149], [96.91431, 27.45752], [97.17422, 27.14052], [97.14675, 27.09041], [96.89132, 27.17474], [96.85287, 27.2065], [96.88445, 27.25046], [96.73888, 27.36638], [96.55761, 27.29928], [96.40779, 27.29818], [96.15591, 27.24572], [96.04949, 27.19428], [95.93002, 27.04149], [95.81603, 27.01335], [95.437, 26.7083], [95.30339, 26.65372], [95.23513, 26.68499], [95.05798, 26.45408], [95.12801, 26.38397], [95.11428, 26.1019], [95.18556, 26.07338], [94.80117, 25.49359], [94.68032, 25.47003], [94.57458, 25.20318], [94.74212, 25.13606], [94.73937, 25.00545], [94.60204, 24.70889], [94.5526, 24.70764], [94.50729, 24.59281], [94.45279, 24.56656], [94.32362, 24.27692], [94.30215, 24.23752], [94.14081, 23.83333], [93.92089, 23.95812], [93.80279, 23.92549], [93.75952, 24.0003], [93.62871, 24.00922], [93.50616, 23.94432], [93.46633, 23.97067], [93.41415, 24.07854], [93.34735, 24.10151], [93.32351, 24.04468], [93.36059, 23.93176], [93.3908, 23.92925], [93.3908, 23.7622], [93.43475, 23.68299], [93.38805, 23.4728], [93.39981, 23.38828], [93.38781, 23.36139], [93.36862, 23.35426], [93.38478, 23.13698], [93.2878, 23.00464], [93.12988, 23.05772], [93.134, 22.92498], [93.09417, 22.69459], [93.134, 22.59573], [93.11477, 22.54374], [93.13537, 22.45873], [93.18206, 22.43716], [93.19991, 22.25425], [93.14224, 22.24535], [93.15734, 22.18687], [93.04885, 22.20595], [92.99255, 22.05965], [92.99804, 21.98964], [92.93899, 22.02656], [92.89504, 21.95143], [92.86208, 22.05456], [92.70416, 22.16017], [92.67532, 22.03547], [92.60949, 21.97638], [92.62187, 21.87037]]]]
25944 nameEn: "Mongolia",
25945 groups: ["030", "142", "UN"],
25946 callingCodes: ["976"]
25949 type: "MultiPolygon",
25950 coordinates: [[[[102.14032, 51.35566], [101.5044, 51.50467], [101.39085, 51.45753], [100.61116, 51.73028], [99.89203, 51.74903], [99.75578, 51.90108], [99.27888, 51.96876], [98.87768, 52.14563], [98.74142, 51.8637], [98.33222, 51.71832], [98.22053, 51.46579], [98.05257, 51.46696], [97.83305, 51.00248], [98.01472, 50.86652], [97.9693, 50.78044], [98.06393, 50.61262], [98.31373, 50.4996], [98.29481, 50.33561], [97.85197, 49.91339], [97.76871, 49.99861], [97.56432, 49.92801], [97.56811, 49.84265], [97.24639, 49.74737], [96.97388, 49.88413], [95.80056, 50.04239], [95.74757, 49.97915], [95.02465, 49.96941], [94.97166, 50.04725], [94.6121, 50.04239], [94.49477, 50.17832], [94.39258, 50.22193], [94.30823, 50.57498], [92.99595, 50.63183], [93.01109, 50.79001], [92.44714, 50.78762], [92.07173, 50.69585], [91.86048, 50.73734], [89.59711, 49.90851], [89.70687, 49.72535], [88.82499, 49.44808], [88.42449, 49.48821], [88.17223, 49.46934], [88.15543, 49.30314], [87.98977, 49.18147], [87.81333, 49.17354], [87.88171, 48.95853], [87.73822, 48.89582], [88.0788, 48.71436], [87.96361, 48.58478], [88.58939, 48.34531], [88.58316, 48.21893], [88.8011, 48.11302], [88.93186, 48.10263], [89.0711, 47.98528], [89.55453, 48.0423], [89.76624, 47.82745], [90.06512, 47.88177], [90.10871, 47.7375], [90.33598, 47.68303], [90.48854, 47.41826], [90.48542, 47.30438], [90.76108, 46.99399], [90.84035, 46.99525], [91.03649, 46.72916], [91.0147, 46.58171], [91.07696, 46.57315], [90.89639, 46.30711], [90.99672, 46.14207], [91.03026, 46.04194], [90.70907, 45.73437], [90.65114, 45.49314], [90.89169, 45.19667], [91.64048, 45.07408], [93.51161, 44.95964], [94.10003, 44.71016], [94.71959, 44.35284], [95.01191, 44.25274], [95.39772, 44.2805], [95.32891, 44.02407], [95.52594, 43.99353], [95.89543, 43.2528], [96.35658, 42.90363], [96.37926, 42.72055], [97.1777, 42.7964], [99.50671, 42.56535], [100.33297, 42.68231], [100.84979, 42.67087], [101.80515, 42.50074], [102.07645, 42.22519], [102.72403, 42.14675], [103.92804, 41.78246], [104.52258, 41.8706], [104.51667, 41.66113], [105.0123, 41.63188], [106.76517, 42.28741], [107.24774, 42.36107], [107.29755, 42.41395], [107.49681, 42.46221], [107.57258, 42.40898], [108.84489, 42.40246], [109.00679, 42.45302], [109.452, 42.44842], [109.89402, 42.63111], [110.08401, 42.6411], [110.4327, 42.78293], [111.0149, 43.3289], [111.59087, 43.51207], [111.79758, 43.6637], [111.93776, 43.68709], [111.96289, 43.81596], [111.40498, 44.3461], [111.76275, 44.98032], [111.98695, 45.09074], [112.4164, 45.06858], [112.74662, 44.86297], [113.70918, 44.72891], [114.5166, 45.27189], [114.54801, 45.38337], [114.74612, 45.43585], [114.94546, 45.37377], [115.60329, 45.44717], [116.16989, 45.68603], [116.27366, 45.78637], [116.24012, 45.8778], [116.26678, 45.96479], [116.58612, 46.30211], [116.75551, 46.33083], [116.83166, 46.38637], [117.36609, 46.36335], [117.41782, 46.57862], [117.60748, 46.59771], [117.69554, 46.50991], [118.30534, 46.73519], [118.78747, 46.68689], [118.8337, 46.77742], [118.89974, 46.77139], [118.92616, 46.72765], [119.00541, 46.74273], [119.10448, 46.65516], [119.24978, 46.64761], [119.32827, 46.61433], [119.42827, 46.63783], [119.65265, 46.62342], [119.68127, 46.59015], [119.77373, 46.62947], [119.80455, 46.67631], [119.89261, 46.66423], [119.91242, 46.90091], [119.85518, 46.92196], [119.71209, 47.19192], [119.62403, 47.24575], [119.56019, 47.24874], [119.54918, 47.29505], [119.31964, 47.42617], [119.35892, 47.48104], [119.13995, 47.53997], [119.12343, 47.66458], [118.7564, 47.76947], [118.55766, 47.99277], [118.29654, 48.00246], [118.22677, 48.03853], [118.11009, 48.04], [118.03676, 48.00982], [117.80196, 48.01661], [117.50181, 47.77216], [117.37875, 47.63627], [116.9723, 47.87285], [116.67405, 47.89039], [116.4465, 47.83662], [116.21879, 47.88505], [115.94296, 47.67741], [115.57128, 47.91988], [115.52082, 48.15367], [115.811, 48.25699], [115.78876, 48.51781], [116.06565, 48.81716], [116.03781, 48.87014], [116.71193, 49.83813], [116.62502, 49.92919], [116.22402, 50.04477], [115.73602, 49.87688], [115.26068, 49.97367], [114.9703, 50.19254], [114.325, 50.28098], [113.20216, 49.83356], [113.02647, 49.60772], [110.64493, 49.1816], [110.39891, 49.25083], [110.24373, 49.16676], [109.51325, 49.22859], [109.18017, 49.34709], [108.53969, 49.32325], [108.27937, 49.53167], [107.95387, 49.66659], [107.96116, 49.93191], [107.36407, 49.97612], [107.1174, 50.04239], [107.00007, 50.1977], [106.80326, 50.30177], [106.58373, 50.34044], [106.51122, 50.34408], [106.49628, 50.32436], [106.47156, 50.31909], [106.07865, 50.33474], [106.05562, 50.40582], [105.32528, 50.4648], [103.70343, 50.13952], [102.71178, 50.38873], [102.32194, 50.67982], [102.14032, 51.35566]]]]
25958 wikidata: "Q14773",
25960 aliases: ["Macao"],
25962 groups: ["030", "142", "UN"],
25964 callingCodes: ["853"]
25967 type: "MultiPolygon",
25968 coordinates: [[[[113.54942, 22.14519], [113.54839, 22.10909], [113.57191, 22.07696], [113.63011, 22.10782], [113.60504, 22.20464], [113.57123, 22.20416], [113.56865, 22.20973], [113.5508, 22.21672], [113.54333, 22.21688], [113.54093, 22.21314], [113.53593, 22.2137], [113.53301, 22.21235], [113.53552, 22.20607], [113.52659, 22.18271], [113.54093, 22.15497], [113.54942, 22.14519]]]]
25976 wikidata: "Q16644",
25977 nameEn: "Northern Mariana Islands",
25978 aliases: ["US-MP"],
25980 groups: ["Q1352230", "Q153732", "057", "009", "UN"],
25981 roadSpeedUnit: "mph",
25982 callingCodes: ["1 670"]
25985 type: "MultiPolygon",
25986 coordinates: [[[[135.52896, 14.32623], [152.19114, 13.63487], [145.05972, 21.28731], [135.52896, 14.32623]]]]
25994 wikidata: "Q17054",
25995 nameEn: "Martinique",
25997 groups: ["Q3320166", "EU", "029", "003", "419", "019", "UN"],
25998 callingCodes: ["596"]
26001 type: "MultiPolygon",
26002 coordinates: [[[[-59.95997, 14.20285], [-61.07821, 15.25109], [-61.69315, 14.26451], [-59.95997, 14.20285]]]]
26011 nameEn: "Mauritania",
26012 groups: ["011", "202", "002", "UN"],
26013 callingCodes: ["222"]
26016 type: "MultiPolygon",
26017 coordinates: [[[[-5.60725, 16.49919], [-6.57191, 25.0002], [-4.83423, 24.99935], [-8.66674, 27.31569], [-8.66721, 25.99918], [-12.0002, 25.9986], [-12.00251, 23.4538], [-12.14969, 23.41935], [-12.36213, 23.3187], [-12.5741, 23.28975], [-13.00412, 23.02297], [-13.10753, 22.89493], [-13.15313, 22.75649], [-13.08438, 22.53866], [-13.01525, 21.33343], [-16.95474, 21.33997], [-16.99806, 21.12142], [-17.0357, 21.05368], [-17.0396, 20.9961], [-17.06781, 20.92697], [-17.0695, 20.85742], [-17.0471, 20.76408], [-17.15288, 16.07139], [-16.50854, 16.09032], [-16.48967, 16.0496], [-16.44814, 16.09753], [-16.4429, 16.20605], [-16.27016, 16.51565], [-15.6509, 16.50315], [-15.00557, 16.64997], [-14.32144, 16.61495], [-13.80075, 16.13961], [-13.43135, 16.09022], [-13.11029, 15.52116], [-12.23936, 14.76324], [-11.94903, 14.76143], [-11.70705, 15.51558], [-11.43483, 15.62339], [-10.90932, 15.11001], [-10.71721, 15.4223], [-9.40447, 15.4396], [-9.44673, 15.60553], [-9.33314, 15.7044], [-9.31106, 15.69412], [-9.32979, 15.50032], [-5.50165, 15.50061], [-5.33435, 16.33354], [-5.60725, 16.49919]]]]
26025 wikidata: "Q13353",
26026 nameEn: "Montserrat",
26028 groups: ["BOTS", "029", "003", "419", "019", "UN"],
26030 roadSpeedUnit: "mph",
26031 roadHeightUnit: "ft",
26032 callingCodes: ["1 664"]
26035 type: "MultiPolygon",
26036 coordinates: [[[[-61.91508, 16.51165], [-62.1023, 16.97277], [-62.58307, 16.68909], [-61.91508, 16.51165]]]]
26046 groups: ["EU", "039", "150", "UN"],
26048 callingCodes: ["356"]
26051 type: "MultiPolygon",
26052 coordinates: [[[[15.70991, 35.79901], [14.07544, 36.41525], [13.27636, 35.20764], [15.70991, 35.79901]]]]
26061 nameEn: "Mauritius",
26062 groups: ["014", "202", "002", "UN"],
26064 callingCodes: ["230"]
26067 type: "MultiPolygon",
26068 coordinates: [[[[56.09755, -9.55401], [57.50644, -31.92637], [68.4673, -19.15185], [56.09755, -9.55401]]]]
26077 nameEn: "Maldives",
26078 groups: ["034", "142", "UN"],
26080 callingCodes: ["960"]
26083 type: "MultiPolygon",
26084 coordinates: [[[[71.9161, 8.55531], [72.57428, -3.7623], [76.59015, 5.591], [71.9161, 8.55531]]]]
26094 groups: ["014", "202", "002", "UN"],
26096 callingCodes: ["265"]
26099 type: "MultiPolygon",
26100 coordinates: [[[[33.48052, -9.62442], [33.31581, -9.48554], [33.14925, -9.49322], [32.99397, -9.36712], [32.95389, -9.40138], [33.00476, -9.5133], [33.00256, -9.63053], [33.05485, -9.61316], [33.10163, -9.66525], [33.12144, -9.58929], [33.2095, -9.61099], [33.31517, -9.82364], [33.36581, -9.81063], [33.37902, -9.9104], [33.31297, -10.05133], [33.53863, -10.20148], [33.54797, -10.36077], [33.70675, -10.56896], [33.47636, -10.78465], [33.28022, -10.84428], [33.25998, -10.88862], [33.39697, -11.15296], [33.29267, -11.3789], [33.29267, -11.43536], [33.23663, -11.40637], [33.24252, -11.59302], [33.32692, -11.59248], [33.33937, -11.91252], [33.25998, -12.14242], [33.3705, -12.34931], [33.47636, -12.32498], [33.54485, -12.35996], [33.37517, -12.54085], [33.28177, -12.54692], [33.18837, -12.61377], [33.05917, -12.59554], [32.94397, -12.76868], [32.96733, -12.88251], [33.02181, -12.88707], [32.98289, -13.12671], [33.0078, -13.19492], [32.86113, -13.47292], [32.84176, -13.52794], [32.73683, -13.57682], [32.68436, -13.55769], [32.66468, -13.60019], [32.68654, -13.64268], [32.7828, -13.64805], [32.84528, -13.71576], [32.76962, -13.77224], [32.79015, -13.80755], [32.88985, -13.82956], [32.99042, -13.95689], [33.02977, -14.05022], [33.07568, -13.98447], [33.16749, -13.93992], [33.24249, -14.00019], [33.66677, -14.61306], [33.7247, -14.4989], [33.88503, -14.51652], [33.92898, -14.47929], [34.08588, -14.48893], [34.18733, -14.43823], [34.22355, -14.43607], [34.34453, -14.3985], [34.35843, -14.38652], [34.39277, -14.39467], [34.4192, -14.43191], [34.44641, -14.47746], [34.45053, -14.49873], [34.47628, -14.53363], [34.48932, -14.53646], [34.49636, -14.55091], [34.52366, -14.5667], [34.53962, -14.59776], [34.55112, -14.64494], [34.53516, -14.67782], [34.52057, -14.68263], [34.54503, -14.74672], [34.567, -14.77345], [34.61522, -14.99583], [34.57503, -15.30619], [34.43126, -15.44778], [34.44981, -15.60864], [34.25195, -15.90321], [34.43126, -16.04737], [34.40344, -16.20923], [35.04805, -16.83167], [35.13771, -16.81687], [35.17017, -16.93521], [35.04805, -17.00027], [35.0923, -17.13235], [35.3062, -17.1244], [35.27065, -16.93817], [35.30929, -16.82871], [35.27219, -16.69402], [35.14235, -16.56812], [35.25828, -16.4792], [35.30157, -16.2211], [35.43355, -16.11371], [35.52365, -16.15414], [35.70107, -16.10147], [35.80487, -16.03907], [35.85303, -15.41913], [35.78799, -15.17428], [35.91812, -14.89514], [35.87212, -14.89478], [35.86945, -14.67481], [35.5299, -14.27714], [35.47989, -14.15594], [34.86229, -13.48958], [34.60253, -13.48487], [34.37831, -12.17408], [34.46088, -12.0174], [34.70739, -12.15652], [34.82903, -12.04837], [34.57917, -11.87849], [34.64241, -11.57499], [34.96296, -11.57354], [34.91153, -11.39799], [34.79375, -11.32245], [34.63305, -11.11731], [34.61161, -11.01611], [34.67047, -10.93796], [34.65946, -10.6828], [34.57581, -10.56271], [34.51911, -10.12279], [34.54499, -10.0678], [34.03865, -9.49398], [33.95829, -9.54066], [33.9638, -9.62206], [33.93298, -9.71647], [33.76677, -9.58516], [33.48052, -9.62442]]]]
26110 groups: ["013", "003", "419", "019", "UN"],
26111 callingCodes: ["52"]
26114 type: "MultiPolygon",
26115 coordinates: [[[[-117.1243, 32.53427], [-118.48109, 32.5991], [-120.12904, 18.41089], [-92.37213, 14.39277], [-92.2261, 14.53423], [-92.1454, 14.6804], [-92.18161, 14.84147], [-92.1423, 14.88647], [-92.1454, 14.98143], [-92.0621, 15.07406], [-92.20983, 15.26077], [-91.73182, 16.07371], [-90.44567, 16.07573], [-90.40499, 16.40524], [-90.61212, 16.49832], [-90.69064, 16.70697], [-91.04436, 16.92175], [-91.43809, 17.25373], [-90.99199, 17.25192], [-90.98678, 17.81655], [-89.14985, 17.81563], [-89.15105, 17.95104], [-89.03839, 18.0067], [-88.8716, 17.89535], [-88.71505, 18.0707], [-88.48242, 18.49164], [-88.3268, 18.49048], [-88.29909, 18.47591], [-88.26593, 18.47617], [-88.03238, 18.41778], [-88.03165, 18.16657], [-87.90671, 18.15213], [-87.87604, 18.18313], [-87.86657, 18.19971], [-87.85693, 18.18266], [-87.84815, 18.18511], [-86.92368, 17.61462], [-85.9092, 21.8218], [-96.92418, 25.97377], [-97.13927, 25.96583], [-97.35946, 25.92189], [-97.37332, 25.83854], [-97.42511, 25.83969], [-97.45669, 25.86874], [-97.49828, 25.89877], [-97.52025, 25.88518], [-97.66511, 26.01708], [-97.95155, 26.0625], [-97.97017, 26.05232], [-98.24603, 26.07191], [-98.27075, 26.09457], [-98.30491, 26.10475], [-98.35126, 26.15129], [-99.00546, 26.3925], [-99.03053, 26.41249], [-99.08477, 26.39849], [-99.53573, 27.30926], [-99.49744, 27.43746], [-99.482, 27.47128], [-99.48045, 27.49016], [-99.50208, 27.50021], [-99.52955, 27.49747], [-99.51478, 27.55836], [-99.55409, 27.61314], [-100.50029, 28.66117], [-100.51222, 28.70679], [-100.5075, 28.74066], [-100.52313, 28.75598], [-100.59809, 28.88197], [-100.63689, 28.90812], [-100.67294, 29.09744], [-100.79696, 29.24688], [-100.87982, 29.296], [-100.94056, 29.33371], [-100.94579, 29.34523], [-100.96725, 29.3477], [-101.01128, 29.36947], [-101.05686, 29.44738], [-101.47277, 29.7744], [-102.60596, 29.8192], [-103.15787, 28.93865], [-104.37752, 29.54255], [-104.39363, 29.55396], [-104.3969, 29.57105], [-104.5171, 29.64671], [-104.77674, 30.4236], [-106.00363, 31.39181], [-106.09025, 31.40569], [-106.20346, 31.46305], [-106.23711, 31.51262], [-106.24612, 31.54193], [-106.28084, 31.56173], [-106.30305, 31.62154], [-106.33419, 31.66303], [-106.34864, 31.69663], [-106.3718, 31.71165], [-106.38003, 31.73151], [-106.41773, 31.75196], [-106.43419, 31.75478], [-106.45244, 31.76523], [-106.46726, 31.75998], [-106.47298, 31.75054], [-106.48815, 31.74769], [-106.50111, 31.75714], [-106.50962, 31.76155], [-106.51251, 31.76922], [-106.52266, 31.77509], [-106.529, 31.784], [-108.20899, 31.78534], [-108.20979, 31.33316], [-111.07523, 31.33232], [-114.82011, 32.49609], [-114.79524, 32.55731], [-114.81141, 32.55543], [-114.80584, 32.62028], [-114.76736, 32.64094], [-114.71871, 32.71894], [-115.88053, 32.63624], [-117.1243, 32.53427]]]]
26134 nameEn: "Mozambique",
26135 groups: ["014", "202", "002", "UN"],
26137 callingCodes: ["258"]
26140 type: "MultiPolygon",
26141 coordinates: [[[[40.74206, -10.25691], [40.44265, -10.4618], [40.00295, -10.80255], [39.58249, -10.96043], [39.24395, -11.17433], [38.88996, -11.16978], [38.47258, -11.4199], [38.21598, -11.27289], [37.93618, -11.26228], [37.8388, -11.3123], [37.76614, -11.53352], [37.3936, -11.68949], [36.80309, -11.56836], [36.62068, -11.72884], [36.19094, -11.70008], [36.19094, -11.57593], [35.82767, -11.41081], [35.63599, -11.55927], [34.96296, -11.57354], [34.64241, -11.57499], [34.57917, -11.87849], [34.82903, -12.04837], [34.70739, -12.15652], [34.46088, -12.0174], [34.37831, -12.17408], [34.60253, -13.48487], [34.86229, -13.48958], [35.47989, -14.15594], [35.5299, -14.27714], [35.86945, -14.67481], [35.87212, -14.89478], [35.91812, -14.89514], [35.78799, -15.17428], [35.85303, -15.41913], [35.80487, -16.03907], [35.70107, -16.10147], [35.52365, -16.15414], [35.43355, -16.11371], [35.30157, -16.2211], [35.25828, -16.4792], [35.14235, -16.56812], [35.27219, -16.69402], [35.30929, -16.82871], [35.27065, -16.93817], [35.3062, -17.1244], [35.0923, -17.13235], [35.04805, -17.00027], [35.17017, -16.93521], [35.13771, -16.81687], [35.04805, -16.83167], [34.40344, -16.20923], [34.43126, -16.04737], [34.25195, -15.90321], [34.44981, -15.60864], [34.43126, -15.44778], [34.57503, -15.30619], [34.61522, -14.99583], [34.567, -14.77345], [34.54503, -14.74672], [34.52057, -14.68263], [34.53516, -14.67782], [34.55112, -14.64494], [34.53962, -14.59776], [34.52366, -14.5667], [34.49636, -14.55091], [34.48932, -14.53646], [34.47628, -14.53363], [34.45053, -14.49873], [34.44641, -14.47746], [34.4192, -14.43191], [34.39277, -14.39467], [34.35843, -14.38652], [34.34453, -14.3985], [34.22355, -14.43607], [34.18733, -14.43823], [34.08588, -14.48893], [33.92898, -14.47929], [33.88503, -14.51652], [33.7247, -14.4989], [33.66677, -14.61306], [33.24249, -14.00019], [30.22098, -14.99447], [30.41902, -15.62269], [30.42568, -15.9962], [30.91597, -15.99924], [30.97761, -16.05848], [31.13171, -15.98019], [31.30563, -16.01193], [31.42451, -16.15154], [31.67988, -16.19595], [31.90223, -16.34388], [31.91324, -16.41569], [32.02772, -16.43892], [32.28529, -16.43892], [32.42838, -16.4727], [32.71017, -16.59932], [32.69917, -16.66893], [32.78943, -16.70267], [32.97655, -16.70689], [32.91051, -16.89446], [32.84113, -16.92259], [32.96554, -17.11971], [33.00517, -17.30477], [33.0426, -17.3468], [32.96554, -17.48964], [32.98536, -17.55891], [33.0492, -17.60298], [32.94133, -17.99705], [33.03159, -18.35054], [33.02278, -18.4696], [32.88629, -18.51344], [32.88629, -18.58023], [32.95013, -18.69079], [32.9017, -18.7992], [32.82465, -18.77419], [32.70137, -18.84712], [32.73439, -18.92628], [32.69917, -18.94293], [32.72118, -19.02204], [32.84006, -19.0262], [32.87088, -19.09279], [32.85107, -19.29238], [32.77966, -19.36098], [32.78282, -19.47513], [32.84446, -19.48343], [32.84666, -19.68462], [32.95013, -19.67219], [33.06461, -19.77787], [33.01178, -20.02007], [32.93032, -20.03868], [32.85987, -20.16686], [32.85987, -20.27841], [32.66174, -20.56106], [32.55167, -20.56312], [32.48122, -20.63319], [32.51644, -20.91929], [32.37115, -21.133], [32.48236, -21.32873], [32.41234, -21.31246], [31.38336, -22.36919], [31.30611, -22.422], [31.55779, -23.176], [31.56539, -23.47268], [31.67942, -23.60858], [31.70223, -23.72695], [31.77445, -23.90082], [31.87707, -23.95293], [31.90368, -24.18892], [31.9835, -24.29983], [32.03196, -25.10785], [32.01676, -25.38117], [31.97875, -25.46356], [32.00631, -25.65044], [31.92649, -25.84216], [31.974, -25.95387], [32.00916, -25.999], [32.08599, -26.00978], [32.10435, -26.15656], [32.07352, -26.40185], [32.13409, -26.5317], [32.13315, -26.84345], [32.19409, -26.84032], [32.22302, -26.84136], [32.29584, -26.852], [32.35222, -26.86027], [34.51034, -26.91792], [42.99868, -12.65261], [40.74206, -10.25691]]]]
26151 groups: ["018", "202", "002", "UN"],
26153 callingCodes: ["264"]
26156 type: "MultiPolygon",
26157 coordinates: [[[[14.28743, -17.38814], [13.95896, -17.43141], [13.36212, -16.98048], [12.97145, -16.98567], [12.52111, -17.24495], [12.07076, -17.15165], [11.75063, -17.25013], [10.5065, -17.25284], [12.51595, -32.27486], [16.45332, -28.63117], [16.46592, -28.57126], [16.59922, -28.53246], [16.90446, -28.057], [17.15405, -28.08573], [17.4579, -28.68718], [18.99885, -28.89165], [19.99882, -28.42622], [19.99817, -24.76768], [19.99912, -21.99991], [20.99751, -22.00026], [20.99904, -18.31743], [21.45556, -18.31795], [23.0996, -18.00075], [23.29618, -17.99855], [23.61088, -18.4881], [24.19416, -18.01919], [24.40577, -17.95726], [24.57485, -18.07151], [24.6303, -17.9863], [24.71887, -17.9218], [24.73364, -17.89338], [24.95586, -17.79674], [25.05895, -17.84452], [25.16882, -17.78253], [25.26433, -17.79571], [25.00198, -17.58221], [24.70864, -17.49501], [24.5621, -17.52963], [24.38712, -17.46818], [24.32811, -17.49082], [24.23619, -17.47489], [23.47474, -17.62877], [21.42741, -18.02787], [21.14283, -17.94318], [18.84226, -17.80375], [18.39229, -17.38927], [14.28743, -17.38814]]]]
26165 wikidata: "Q33788",
26166 nameEn: "New Caledonia",
26168 groups: ["Q1451600", "054", "009", "UN"],
26169 callingCodes: ["687"]
26172 type: "MultiPolygon",
26173 coordinates: [[[[159.77159, -28.41151], [174.245, -23.1974], [156.73836, -14.50464], [159.77159, -28.41151]]]]
26184 groups: ["011", "202", "002", "UN"],
26185 callingCodes: ["227"]
26188 type: "MultiPolygon",
26189 coordinates: [[[[14.22918, 22.61719], [13.5631, 23.16574], [11.96886, 23.51735], [7.48273, 20.87258], [7.38361, 20.79165], [5.8153, 19.45101], [4.26651, 19.14224], [4.26762, 17.00432], [4.21787, 17.00118], [4.19893, 16.39923], [3.50368, 15.35934], [3.03134, 15.42221], [3.01806, 15.34571], [1.31275, 15.27978], [0.96711, 14.98275], [0.72632, 14.95898], [0.23859, 15.00135], [0.16936, 14.51654], [0.38051, 14.05575], [0.61924, 13.68491], [0.77377, 13.6866], [0.77637, 13.64442], [0.99514, 13.5668], [1.02813, 13.46635], [1.20088, 13.38951], [1.24429, 13.39373], [1.28509, 13.35488], [1.24516, 13.33968], [1.21217, 13.37853], [1.18873, 13.31771], [0.99253, 13.37515], [0.99167, 13.10727], [2.26349, 12.41915], [2.05785, 12.35539], [2.39723, 11.89473], [2.45824, 11.98672], [2.39657, 12.10952], [2.37783, 12.24804], [2.6593, 12.30631], [2.83978, 12.40585], [3.25352, 12.01467], [3.31613, 11.88495], [3.48187, 11.86092], [3.59375, 11.70269], [3.61075, 11.69181], [3.67988, 11.75429], [3.67122, 11.80865], [3.63063, 11.83042], [3.61955, 11.91847], [3.67775, 11.97599], [3.63136, 12.11826], [3.66364, 12.25884], [3.65111, 12.52223], [3.94339, 12.74979], [4.10006, 12.98862], [4.14367, 13.17189], [4.14186, 13.47586], [4.23456, 13.47725], [4.4668, 13.68286], [4.87425, 13.78], [4.9368, 13.7345], [5.07396, 13.75052], [5.21026, 13.73627], [5.27797, 13.75474], [5.35437, 13.83567], [5.52957, 13.8845], [6.15771, 13.64564], [6.27411, 13.67835], [6.43053, 13.6006], [6.69617, 13.34057], [6.94445, 12.99825], [7.0521, 13.00076], [7.12676, 13.02445], [7.22399, 13.1293], [7.39241, 13.09717], [7.81085, 13.34902], [8.07997, 13.30847], [8.25185, 13.20369], [8.41853, 13.06166], [8.49493, 13.07519], [8.60431, 13.01768], [8.64251, 12.93985], [8.97413, 12.83661], [9.65995, 12.80614], [10.00373, 13.18171], [10.19993, 13.27129], [10.46731, 13.28819], [10.66004, 13.36422], [11.4535, 13.37773], [11.88236, 13.2527], [12.04209, 13.14452], [12.16189, 13.10056], [12.19315, 13.12423], [12.47095, 13.06673], [12.58033, 13.27805], [12.6793, 13.29157], [12.87376, 13.48919], [13.05085, 13.53984], [13.19844, 13.52802], [13.33213, 13.71195], [13.6302, 13.71094], [13.47559, 14.40881], [13.48259, 14.46704], [13.68573, 14.55276], [13.67878, 14.64013], [13.809, 14.72915], [13.78991, 14.87519], [13.86301, 15.04043], [14.37425, 15.72591], [15.50373, 16.89649], [15.6032, 18.77402], [15.75098, 19.93002], [15.99632, 20.35364], [15.6721, 20.70069], [15.59841, 20.74039], [15.56004, 20.79488], [15.55382, 20.86507], [15.57248, 20.92138], [15.62515, 20.95395], [15.28332, 21.44557], [15.20213, 21.49365], [15.19692, 21.99339], [14.99751, 23.00539], [14.22918, 22.61719]]]]
26197 wikidata: "Q31057",
26198 nameEn: "Norfolk Island",
26200 groups: ["053", "009", "UN"],
26202 callingCodes: ["672 3"]
26205 type: "MultiPolygon",
26206 coordinates: [[[[169.82316, -28.16667], [166.29505, -28.29175], [167.94076, -30.60745], [169.82316, -28.16667]]]]
26216 groups: ["011", "202", "002", "UN"],
26217 callingCodes: ["234"]
26220 type: "MultiPolygon",
26221 coordinates: [[[[6.15771, 13.64564], [5.52957, 13.8845], [5.35437, 13.83567], [5.27797, 13.75474], [5.21026, 13.73627], [5.07396, 13.75052], [4.9368, 13.7345], [4.87425, 13.78], [4.4668, 13.68286], [4.23456, 13.47725], [4.14186, 13.47586], [4.14367, 13.17189], [4.10006, 12.98862], [3.94339, 12.74979], [3.65111, 12.52223], [3.66364, 12.25884], [3.63136, 12.11826], [3.67775, 11.97599], [3.61955, 11.91847], [3.63063, 11.83042], [3.67122, 11.80865], [3.67988, 11.75429], [3.61075, 11.69181], [3.59375, 11.70269], [3.49175, 11.29765], [3.71505, 11.13015], [3.84243, 10.59316], [3.78292, 10.40538], [3.6844, 10.46351], [3.57275, 10.27185], [3.66908, 10.18136], [3.54429, 9.87739], [3.35383, 9.83641], [3.32099, 9.78032], [3.34726, 9.70696], [3.25093, 9.61632], [3.13928, 9.47167], [3.14147, 9.28375], [3.08017, 9.10006], [2.77907, 9.06924], [2.67523, 7.87825], [2.73095, 7.7755], [2.73405, 7.5423], [2.78668, 7.5116], [2.79442, 7.43486], [2.74489, 7.42565], [2.76965, 7.13543], [2.71702, 6.95722], [2.74024, 6.92802], [2.73405, 6.78508], [2.78823, 6.76356], [2.78204, 6.70514], [2.7325, 6.64057], [2.74334, 6.57291], [2.70464, 6.50831], [2.70566, 6.38038], [2.74181, 6.13349], [5.87055, 3.78489], [8.34397, 4.30689], [8.60302, 4.87353], [8.78027, 5.1243], [8.92029, 5.58403], [8.83687, 5.68483], [8.88156, 5.78857], [8.84209, 5.82562], [9.51757, 6.43874], [9.70674, 6.51717], [9.77824, 6.79088], [9.86314, 6.77756], [10.15135, 7.03781], [10.21466, 6.88996], [10.53639, 6.93432], [10.57214, 7.16345], [10.59746, 7.14719], [10.60789, 7.06885], [10.83727, 6.9358], [10.8179, 6.83377], [10.94302, 6.69325], [11.09644, 6.68437], [11.09495, 6.51717], [11.42041, 6.53789], [11.42264, 6.5882], [11.51499, 6.60892], [11.57755, 6.74059], [11.55818, 6.86186], [11.63117, 6.9905], [11.87396, 7.09398], [11.84864, 7.26098], [11.93205, 7.47812], [12.01844, 7.52981], [11.99908, 7.67302], [12.20909, 7.97553], [12.19271, 8.10826], [12.24782, 8.17904], [12.26123, 8.43696], [12.4489, 8.52536], [12.44146, 8.6152], [12.68722, 8.65938], [12.71701, 8.7595], [12.79, 8.75361], [12.81085, 8.91992], [12.90022, 9.11411], [12.91958, 9.33905], [12.85628, 9.36698], [13.02385, 9.49334], [13.22642, 9.57266], [13.25472, 9.76795], [13.29941, 9.8296], [13.25025, 9.86042], [13.24132, 9.91031], [13.27409, 9.93232], [13.286, 9.9822], [13.25323, 10.00127], [13.25025, 10.03647], [13.34111, 10.12299], [13.43644, 10.13326], [13.5705, 10.53183], [13.54964, 10.61236], [13.73434, 10.9255], [13.70753, 10.94451], [13.7403, 11.00593], [13.78945, 11.00154], [13.97489, 11.30258], [14.17821, 11.23831], [14.6124, 11.51283], [14.64591, 11.66166], [14.55207, 11.72001], [14.61612, 11.7798], [14.6474, 12.17466], [14.4843, 12.35223], [14.22215, 12.36533], [14.17523, 12.41916], [14.20204, 12.53405], [14.08251, 13.0797], [13.6302, 13.71094], [13.33213, 13.71195], [13.19844, 13.52802], [13.05085, 13.53984], [12.87376, 13.48919], [12.6793, 13.29157], [12.58033, 13.27805], [12.47095, 13.06673], [12.19315, 13.12423], [12.16189, 13.10056], [12.04209, 13.14452], [11.88236, 13.2527], [11.4535, 13.37773], [10.66004, 13.36422], [10.46731, 13.28819], [10.19993, 13.27129], [10.00373, 13.18171], [9.65995, 12.80614], [8.97413, 12.83661], [8.64251, 12.93985], [8.60431, 13.01768], [8.49493, 13.07519], [8.41853, 13.06166], [8.25185, 13.20369], [8.07997, 13.30847], [7.81085, 13.34902], [7.39241, 13.09717], [7.22399, 13.1293], [7.12676, 13.02445], [7.0521, 13.00076], [6.94445, 12.99825], [6.69617, 13.34057], [6.43053, 13.6006], [6.27411, 13.67835], [6.15771, 13.64564]]]]
26230 nameEn: "Nicaragua",
26231 groups: ["013", "003", "419", "019", "UN"],
26232 callingCodes: ["505"]
26235 type: "MultiPolygon",
26236 coordinates: [[[[-83.13724, 15.00002], [-83.49268, 15.01158], [-83.62101, 14.89448], [-83.89551, 14.76697], [-84.10584, 14.76353], [-84.48373, 14.63249], [-84.70119, 14.68078], [-84.82596, 14.82212], [-84.90082, 14.80489], [-85.1575, 14.53934], [-85.18602, 14.24929], [-85.32149, 14.2562], [-85.45762, 14.11304], [-85.73964, 13.9698], [-85.75477, 13.8499], [-86.03458, 13.99181], [-86.00685, 14.08474], [-86.14801, 14.04317], [-86.35219, 13.77157], [-86.76812, 13.79605], [-86.71267, 13.30348], [-86.87066, 13.30641], [-86.93383, 13.18677], [-86.93197, 13.05313], [-87.03785, 12.98682], [-87.06306, 13.00892], [-87.37107, 12.98646], [-87.55124, 13.12523], [-87.7346, 13.13228], [-88.11443, 12.63306], [-86.14524, 11.09059], [-85.71223, 11.06868], [-85.60529, 11.22607], [-84.92439, 10.9497], [-84.68197, 11.07568], [-83.90838, 10.71161], [-83.66597, 10.79916], [-83.68276, 11.01562], [-82.56142, 11.91792], [-82.06974, 14.49418], [-83.04763, 15.03256], [-83.13724, 15.00002]]]]
26244 wikidata: "Q29999",
26245 nameEn: "Kingdom of the Netherlands"
26266 groups: ["034", "142", "UN"],
26268 callingCodes: ["977"]
26271 type: "MultiPolygon",
26272 coordinates: [[[[88.13378, 27.88015], [87.82681, 27.95248], [87.72718, 27.80938], [87.56996, 27.84517], [87.11696, 27.84104], [87.03757, 27.94835], [86.75582, 28.04182], [86.74181, 28.10638], [86.56265, 28.09569], [86.51609, 27.96623], [86.42736, 27.91122], [86.22966, 27.9786], [86.18607, 28.17364], [86.088, 28.09264], [86.08333, 28.02121], [86.12069, 27.93047], [86.06309, 27.90021], [85.94946, 27.9401], [85.97813, 27.99023], [85.90743, 28.05144], [85.84672, 28.18187], [85.74864, 28.23126], [85.71907, 28.38064], [85.69105, 28.38475], [85.60854, 28.25045], [85.59765, 28.30529], [85.4233, 28.32996], [85.38127, 28.28336], [85.10729, 28.34092], [85.18668, 28.54076], [85.19135, 28.62825], [85.06059, 28.68562], [84.85511, 28.58041], [84.62317, 28.73887], [84.47528, 28.74023], [84.2231, 28.89571], [84.24801, 29.02783], [84.18107, 29.23451], [83.97559, 29.33091], [83.82303, 29.30513], [83.63156, 29.16249], [83.44787, 29.30513], [83.28131, 29.56813], [83.07116, 29.61957], [82.73024, 29.81695], [82.5341, 29.9735], [82.38622, 30.02608], [82.16984, 30.0692], [82.19475, 30.16884], [82.10757, 30.23745], [82.10135, 30.35439], [81.99082, 30.33423], [81.62033, 30.44703], [81.5459, 30.37688], [81.41018, 30.42153], [81.39928, 30.21862], [81.33355, 30.15303], [81.2623, 30.14596], [81.29032, 30.08806], [81.24362, 30.0126], [81.12842, 30.01395], [81.03953, 30.20059], [80.92547, 30.17193], [80.91143, 30.22173], [80.86673, 30.17321], [80.8778, 30.13384], [80.67076, 29.95732], [80.60226, 29.95732], [80.57179, 29.91422], [80.56247, 29.86661], [80.48997, 29.79566], [80.43458, 29.80466], [80.41554, 29.79451], [80.36803, 29.73865], [80.38428, 29.68513], [80.41858, 29.63581], [80.37939, 29.57098], [80.24322, 29.44299], [80.31428, 29.30784], [80.28626, 29.20327], [80.24112, 29.21414], [80.26602, 29.13938], [80.23178, 29.11626], [80.18085, 29.13649], [80.05743, 28.91479], [80.06957, 28.82763], [80.12125, 28.82346], [80.37188, 28.63371], [80.44504, 28.63098], [80.52443, 28.54897], [80.50575, 28.6706], [80.55142, 28.69182], [81.03471, 28.40054], [81.19847, 28.36284], [81.32923, 28.13521], [81.38683, 28.17638], [81.48179, 28.12148], [81.47867, 28.08303], [81.91223, 27.84995], [81.97214, 27.93322], [82.06554, 27.92222], [82.46405, 27.6716], [82.70378, 27.72122], [82.74119, 27.49838], [82.93261, 27.50328], [82.94938, 27.46036], [83.19413, 27.45632], [83.27197, 27.38309], [83.2673, 27.36235], [83.29999, 27.32778], [83.35136, 27.33885], [83.38872, 27.39276], [83.39495, 27.4798], [83.61288, 27.47013], [83.85595, 27.35797], [83.86182, 27.4241], [83.93306, 27.44939], [84.02229, 27.43836], [84.10791, 27.52399], [84.21376, 27.45218], [84.25735, 27.44941], [84.29315, 27.39], [84.62161, 27.33885], [84.69166, 27.21294], [84.64496, 27.04669], [84.793, 26.9968], [84.82913, 27.01989], [84.85754, 26.98984], [84.96687, 26.95599], [84.97186, 26.9149], [85.00536, 26.89523], [85.05592, 26.88991], [85.02635, 26.85381], [85.15883, 26.86966], [85.19291, 26.86909], [85.18046, 26.80519], [85.21159, 26.75933], [85.34302, 26.74954], [85.47752, 26.79292], [85.56471, 26.84133], [85.5757, 26.85955], [85.59461, 26.85161], [85.61621, 26.86721], [85.66239, 26.84822], [85.73483, 26.79613], [85.72315, 26.67471], [85.76907, 26.63076], [85.83126, 26.61134], [85.85126, 26.60866], [85.8492, 26.56667], [86.02729, 26.66756], [86.13596, 26.60651], [86.22513, 26.58863], [86.26235, 26.61886], [86.31564, 26.61925], [86.49726, 26.54218], [86.54258, 26.53819], [86.57073, 26.49825], [86.61313, 26.48658], [86.62686, 26.46891], [86.69124, 26.45169], [86.74025, 26.42386], [86.76797, 26.45892], [86.82898, 26.43919], [86.94543, 26.52076], [86.95912, 26.52076], [87.01559, 26.53228], [87.04691, 26.58685], [87.0707, 26.58571], [87.09147, 26.45039], [87.14751, 26.40542], [87.18863, 26.40558], [87.24682, 26.4143], [87.26587, 26.40592], [87.26568, 26.37294], [87.34568, 26.34787], [87.37314, 26.40815], [87.46566, 26.44058], [87.51571, 26.43106], [87.55274, 26.40596], [87.59175, 26.38342], [87.66803, 26.40294], [87.67893, 26.43501], [87.76004, 26.40711], [87.7918, 26.46737], [87.84193, 26.43663], [87.89085, 26.48565], [87.90115, 26.44923], [88.00895, 26.36029], [88.09414, 26.43732], [88.09963, 26.54195], [88.16452, 26.64111], [88.1659, 26.68177], [88.19107, 26.75516], [88.12302, 26.95324], [88.13422, 26.98705], [88.11719, 26.98758], [87.9887, 27.11045], [88.01587, 27.21388], [88.01646, 27.21612], [88.07277, 27.43007], [88.04008, 27.49223], [88.19107, 27.79285], [88.1973, 27.85067], [88.13378, 27.88015]]]]
26282 groups: ["057", "009", "UN"],
26284 callingCodes: ["674"]
26287 type: "MultiPolygon",
26288 coordinates: [[[[166.95155, 0.14829], [166.21778, -0.7977], [167.60042, -0.88259], [166.95155, 0.14829]]]]
26296 wikidata: "Q34020",
26299 groups: ["061", "009", "UN"],
26301 callingCodes: ["683"]
26304 type: "MultiPolygon",
26305 coordinates: [[[[-170.83899, -18.53439], [-170.82274, -20.44429], [-168.63096, -18.60489], [-170.83899, -18.53439]]]]
26314 nameEn: "New Zealand"
26325 groups: ["145", "142", "UN"],
26326 callingCodes: ["968"]
26329 type: "MultiPolygon",
26330 coordinates: [[[[56.82555, 25.7713], [56.79239, 26.41236], [56.68954, 26.76645], [56.2644, 26.58649], [55.81777, 26.18798], [56.08666, 26.05038], [56.15498, 26.06828], [56.19334, 25.9795], [56.13963, 25.82765], [56.17416, 25.77239], [56.13579, 25.73524], [56.14826, 25.66351], [56.18363, 25.65508], [56.20473, 25.61119], [56.25365, 25.60211], [56.26636, 25.60643], [56.25341, 25.61443], [56.26534, 25.62825], [56.82555, 25.7713]]], [[[56.26062, 25.33108], [56.23362, 25.31253], [56.25008, 25.28843], [56.24465, 25.27505], [56.20838, 25.25668], [56.20872, 25.24104], [56.24341, 25.22867], [56.27628, 25.23404], [56.34438, 25.26653], [56.35172, 25.30681], [56.3111, 25.30107], [56.3005, 25.31815], [56.26062, 25.33108]], [[56.28423, 25.26344], [56.27086, 25.26128], [56.2716, 25.27916], [56.28102, 25.28486], [56.29379, 25.2754], [56.28423, 25.26344]]], [[[61.45114, 22.55394], [56.86325, 25.03856], [56.3227, 24.97284], [56.34873, 24.93205], [56.30269, 24.88334], [56.20568, 24.85063], [56.20062, 24.78565], [56.13684, 24.73699], [56.06128, 24.74457], [56.03535, 24.81161], [55.97836, 24.87673], [55.97467, 24.89639], [56.05106, 24.87461], [56.05715, 24.95727], [55.96316, 25.00857], [55.90849, 24.96771], [55.85094, 24.96858], [55.81116, 24.9116], [55.81348, 24.80102], [55.83408, 24.77858], [55.83271, 24.68567], [55.76461, 24.5287], [55.83271, 24.41521], [55.83395, 24.32776], [55.80747, 24.31069], [55.79145, 24.27914], [55.76781, 24.26209], [55.75939, 24.26114], [55.75382, 24.2466], [55.75257, 24.23466], [55.76558, 24.23227], [55.77658, 24.23476], [55.83367, 24.20193], [55.95472, 24.2172], [56.01799, 24.07426], [55.8308, 24.01633], [55.73301, 24.05994], [55.48677, 23.94946], [55.57358, 23.669], [55.22634, 23.10378], [55.2137, 22.71065], [55.66469, 21.99658], [54.99756, 20.00083], [52.00311, 19.00083], [52.78009, 17.35124], [52.74267, 17.29519], [52.81185, 17.28568], [57.49095, 8.14549], [61.45114, 22.55394]]]]
26340 groups: ["013", "003", "419", "019", "UN"],
26341 callingCodes: ["507"]
26344 type: "MultiPolygon",
26345 coordinates: [[[[-77.32389, 8.81247], [-77.58292, 9.22278], [-78.79327, 9.93766], [-82.51044, 9.65379], [-82.56507, 9.57279], [-82.61345, 9.49881], [-82.66667, 9.49746], [-82.77206, 9.59573], [-82.87919, 9.62645], [-82.84871, 9.4973], [-82.93516, 9.46741], [-82.93516, 9.07687], [-82.72126, 8.97125], [-82.88253, 8.83331], [-82.91377, 8.774], [-82.92068, 8.74832], [-82.8794, 8.6981], [-82.82739, 8.60153], [-82.83975, 8.54755], [-82.83322, 8.52464], [-82.8382, 8.48117], [-82.8679, 8.44042], [-82.93056, 8.43465], [-83.05209, 8.33394], [-82.9388, 8.26634], [-82.88641, 8.10219], [-82.89137, 8.05755], [-82.89978, 8.04083], [-82.94503, 7.93865], [-82.13751, 6.97312], [-78.06168, 7.07793], [-77.89178, 7.22681], [-77.81426, 7.48319], [-77.72157, 7.47612], [-77.72514, 7.72348], [-77.57185, 7.51147], [-77.17257, 7.97422], [-77.45064, 8.49991], [-77.32389, 8.81247]]]]
26355 groups: ["005", "419", "019", "UN"],
26356 callingCodes: ["51"]
26359 type: "MultiPolygon",
26360 coordinates: [[[[-74.26675, -0.97229], [-74.42701, -0.50218], [-75.18513, -0.0308], [-75.25764, -0.11943], [-75.40192, -0.17196], [-75.61997, -0.10012], [-75.60169, -0.18708], [-75.53615, -0.19213], [-75.22862, -0.60048], [-75.22862, -0.95588], [-75.3872, -0.9374], [-75.57429, -1.55961], [-76.05203, -2.12179], [-76.6324, -2.58397], [-77.94147, -3.05454], [-78.19369, -3.36431], [-78.14324, -3.47653], [-78.22642, -3.51113], [-78.24589, -3.39907], [-78.34362, -3.38633], [-78.68394, -4.60754], [-78.85149, -4.66795], [-79.01659, -5.01481], [-79.1162, -4.97774], [-79.26248, -4.95167], [-79.59402, -4.46848], [-79.79722, -4.47558], [-80.13945, -4.29786], [-80.39256, -4.48269], [-80.46386, -4.41516], [-80.32114, -4.21323], [-80.45023, -4.20938], [-80.4822, -4.05477], [-80.46386, -4.01342], [-80.13232, -3.90317], [-80.19926, -3.68894], [-80.18741, -3.63994], [-80.19848, -3.59249], [-80.21642, -3.5888], [-80.20535, -3.51667], [-80.22629, -3.501], [-80.23651, -3.48652], [-80.24586, -3.48677], [-80.24123, -3.46124], [-80.20647, -3.431], [-80.30602, -3.39149], [-84.52388, -3.36941], [-85.71054, -21.15413], [-70.59118, -18.35072], [-70.378, -18.3495], [-70.31267, -18.31258], [-70.16394, -18.31737], [-69.96732, -18.25992], [-69.81607, -18.12582], [-69.75305, -17.94605], [-69.82868, -17.72048], [-69.79087, -17.65563], [-69.66483, -17.65083], [-69.46897, -17.4988], [-69.46863, -17.37466], [-69.62883, -17.28142], [-69.16896, -16.72233], [-69.00853, -16.66769], [-69.04027, -16.57214], [-68.98358, -16.42165], [-68.79464, -16.33272], [-68.96238, -16.194], [-69.09986, -16.22693], [-69.20291, -16.16668], [-69.40336, -15.61358], [-69.14856, -15.23478], [-69.36254, -14.94634], [-68.88135, -14.18639], [-69.05265, -13.68546], [-68.8864, -13.40792], [-68.85615, -12.87769], [-68.65044, -12.50689], [-68.98115, -11.8979], [-69.57156, -10.94555], [-69.57835, -10.94051], [-69.90896, -10.92744], [-70.38791, -11.07096], [-70.51395, -10.92249], [-70.64134, -11.0108], [-70.62487, -9.80666], [-70.55429, -9.76692], [-70.58453, -9.58303], [-70.53373, -9.42628], [-71.23394, -9.9668], [-72.14742, -9.98049], [-72.31883, -9.5184], [-72.72216, -9.41397], [-73.21498, -9.40904], [-72.92886, -9.04074], [-73.76576, -7.89884], [-73.65485, -7.77897], [-73.96938, -7.58465], [-73.77011, -7.28944], [-73.73986, -6.87919], [-73.12983, -6.43852], [-73.24579, -6.05764], [-72.83973, -5.14765], [-72.64391, -5.0391], [-71.87003, -4.51661], [-70.96814, -4.36915], [-70.77601, -4.15717], [-70.33236, -4.15214], [-70.19582, -4.3607], [-70.11305, -4.27281], [-70.00888, -4.37833], [-69.94708, -4.2431], [-70.3374, -3.79505], [-70.52393, -3.87553], [-70.71396, -3.7921], [-70.04609, -2.73906], [-70.94377, -2.23142], [-71.75223, -2.15058], [-72.92587, -2.44514], [-73.65312, -1.26222], [-74.26675, -0.97229]]]]
26368 wikidata: "Q30971",
26369 nameEn: "French Polynesia",
26371 groups: ["Q1451600", "061", "009", "UN"],
26372 callingCodes: ["689"]
26375 type: "MultiPolygon",
26376 coordinates: [[[[-135.59706, -4.70473], [-156.48634, -15.52824], [-156.45576, -31.75456], [-133.59543, -28.4709], [-135.59706, -4.70473]]]]
26385 nameEn: "Papua New Guinea",
26386 groups: ["054", "009", "UN"],
26388 callingCodes: ["675"]
26391 type: "MultiPolygon",
26392 coordinates: [[[[141.03157, 2.12829], [140.99813, -6.3233], [140.85295, -6.72996], [140.90448, -6.85033], [141.01763, -6.90181], [141.01842, -9.35091], [141.88934, -9.36111], [142.19246, -9.15378], [142.48658, -9.36754], [143.29772, -9.33993], [143.87386, -9.02382], [145.2855, -9.62524], [156.73836, -14.50464], [154.74815, -7.33315], [155.60735, -6.92266], [155.69784, -6.92661], [155.92557, -6.84664], [156.03993, -6.65703], [156.03296, -6.55528], [160.43769, -4.17974], [141.03157, 2.12829]]]]
26401 nameEn: "Philippines",
26402 aliases: ["PI", "RP"],
26403 groups: ["035", "142", "UN"],
26404 callingCodes: ["63"]
26407 type: "MultiPolygon",
26408 coordinates: [[[[129.19694, 7.84182], [121.8109, 21.77688], [120.69238, 21.52331], [118.82252, 14.67191], [115.39742, 10.92666], [116.79524, 7.43869], [117.17735, 7.52841], [117.93857, 6.89845], [117.98544, 6.27477], [119.52945, 5.35672], [118.93936, 4.09009], [118.06469, 4.16638], [121.14448, 2.12444], [129.19694, 7.84182]]]]
26417 nameEn: "Pakistan",
26418 groups: ["034", "142", "UN"],
26420 callingCodes: ["92"]
26423 type: "MultiPolygon",
26424 coordinates: [[[[75.72737, 36.7529], [75.45562, 36.71971], [75.40481, 36.95382], [75.13839, 37.02622], [74.56453, 37.03023], [74.53739, 36.96224], [74.43389, 37.00977], [74.04856, 36.82648], [73.82685, 36.91421], [72.6323, 36.84601], [72.18135, 36.71838], [71.80267, 36.49924], [71.60491, 36.39429], [71.19505, 36.04134], [71.37969, 35.95865], [71.55273, 35.71483], [71.49917, 35.6267], [71.65435, 35.4479], [71.54294, 35.31037], [71.5541, 35.28776], [71.67495, 35.21262], [71.52938, 35.09023], [71.55273, 35.02615], [71.49917, 35.00478], [71.50329, 34.97328], [71.29472, 34.87728], [71.28356, 34.80882], [71.08718, 34.69034], [71.11602, 34.63047], [71.0089, 34.54568], [71.02401, 34.44835], [71.17662, 34.36769], [71.12815, 34.26619], [71.13078, 34.16503], [71.09453, 34.13524], [71.09307, 34.11961], [71.06933, 34.10564], [71.07345, 34.06242], [70.88119, 33.97933], [70.54336, 33.9463], [69.90203, 34.04194], [69.87307, 33.9689], [69.85671, 33.93719], [70.00503, 33.73528], [70.14236, 33.71701], [70.14785, 33.6553], [70.20141, 33.64387], [70.17062, 33.53535], [70.32775, 33.34496], [70.13686, 33.21064], [70.07369, 33.22557], [70.02563, 33.14282], [69.85259, 33.09451], [69.79766, 33.13247], [69.71526, 33.09911], [69.57656, 33.09911], [69.49004, 33.01509], [69.49854, 32.88843], [69.5436, 32.8768], [69.47082, 32.85834], [69.38018, 32.76601], [69.43649, 32.7302], [69.44747, 32.6678], [69.38155, 32.56601], [69.2868, 32.53938], [69.23599, 32.45946], [69.27932, 32.29119], [69.27032, 32.14141], [69.3225, 31.93186], [69.20577, 31.85957], [69.11514, 31.70782], [69.00939, 31.62249], [68.95995, 31.64822], [68.91078, 31.59687], [68.79997, 31.61665], [68.6956, 31.75687], [68.57475, 31.83158], [68.44222, 31.76446], [68.27605, 31.75863], [68.25614, 31.80357], [68.1655, 31.82691], [68.00071, 31.6564], [67.86887, 31.63536], [67.72056, 31.52304], [67.58323, 31.52772], [67.62374, 31.40473], [67.7748, 31.4188], [67.78854, 31.33203], [67.29964, 31.19586], [67.03323, 31.24519], [67.04147, 31.31561], [66.83273, 31.26867], [66.72561, 31.20526], [66.68166, 31.07597], [66.58175, 30.97532], [66.42645, 30.95309], [66.39194, 30.9408], [66.28413, 30.57001], [66.34869, 30.404], [66.23609, 30.06321], [66.36042, 29.9583], [66.24175, 29.85181], [65.04005, 29.53957], [64.62116, 29.58903], [64.19796, 29.50407], [64.12966, 29.39157], [63.5876, 29.50456], [62.47751, 29.40782], [60.87231, 29.86514], [61.31508, 29.38903], [61.53765, 29.00507], [61.65978, 28.77937], [61.93581, 28.55284], [62.40259, 28.42703], [62.59499, 28.24842], [62.79412, 28.28108], [62.7638, 28.02992], [62.84905, 27.47627], [62.79684, 27.34381], [62.80604, 27.22412], [63.19649, 27.25674], [63.32283, 27.14437], [63.25005, 27.08692], [63.25005, 26.84212], [63.18688, 26.83844], [63.1889, 26.65072], [62.77352, 26.64099], [62.31484, 26.528], [62.21304, 26.26601], [62.05117, 26.31647], [61.89391, 26.26251], [61.83831, 26.07249], [61.83968, 25.7538], [61.683, 25.66638], [61.6433, 25.27541], [61.46682, 24.57869], [68.11329, 23.53945], [68.20763, 23.85849], [68.39339, 23.96838], [68.74643, 23.97027], [68.7416, 24.31904], [68.90914, 24.33156], [68.97781, 24.26021], [69.07806, 24.29777], [69.19341, 24.25646], [69.29778, 24.28712], [69.59579, 24.29777], [69.73335, 24.17007], [70.03428, 24.172], [70.11712, 24.30915], [70.5667, 24.43787], [70.57906, 24.27774], [70.71502, 24.23517], [70.88393, 24.27398], [70.85784, 24.30903], [70.94985, 24.3791], [71.04461, 24.34657], [71.12838, 24.42662], [71.00341, 24.46038], [70.97594, 24.60904], [71.09405, 24.69017], [70.94002, 24.92843], [70.89148, 25.15064], [70.66695, 25.39314], [70.67382, 25.68186], [70.60378, 25.71898], [70.53649, 25.68928], [70.37444, 25.67443], [70.2687, 25.71156], [70.0985, 25.93238], [70.08193, 26.08094], [70.17532, 26.24118], [70.17532, 26.55362], [70.05584, 26.60398], [69.88555, 26.56836], [69.50904, 26.74892], [69.58519, 27.18109], [70.03136, 27.56627], [70.12502, 27.8057], [70.37307, 28.01208], [70.60927, 28.02178], [70.79054, 27.68423], [71.89921, 27.96035], [71.9244, 28.11555], [72.20329, 28.3869], [72.29495, 28.66367], [72.40402, 28.78283], [72.94272, 29.02487], [73.01337, 29.16422], [73.05886, 29.1878], [73.28094, 29.56646], [73.3962, 29.94707], [73.58665, 30.01848], [73.80299, 30.06969], [73.97225, 30.19829], [73.95736, 30.28466], [73.88993, 30.36305], [74.5616, 31.04153], [74.67971, 31.05479], [74.6852, 31.12771], [74.60006, 31.13711], [74.60281, 31.10419], [74.56023, 31.08303], [74.51629, 31.13829], [74.53223, 31.30321], [74.59773, 31.4136], [74.64713, 31.45605], [74.59319, 31.50197], [74.61517, 31.55698], [74.57498, 31.60382], [74.47771, 31.72227], [74.58907, 31.87824], [74.79919, 31.95983], [74.86236, 32.04485], [74.9269, 32.0658], [75.00793, 32.03786], [75.25649, 32.10187], [75.38046, 32.26836], [75.28259, 32.36556], [75.03265, 32.49538], [74.97634, 32.45367], [74.84725, 32.49075], [74.68362, 32.49298], [74.67431, 32.56676], [74.65251, 32.56416], [74.64424, 32.60985], [74.69542, 32.66792], [74.65345, 32.71225], [74.7113, 32.84219], [74.64675, 32.82604], [74.6289, 32.75561], [74.45312, 32.77755], [74.41467, 32.90563], [74.31227, 32.92795], [74.34875, 32.97823], [74.31854, 33.02891], [74.17571, 33.07495], [74.15374, 33.13477], [74.02144, 33.18908], [74.01366, 33.25199], [74.08782, 33.26232], [74.17983, 33.3679], [74.18121, 33.4745], [74.10115, 33.56392], [74.03576, 33.56718], [73.97367, 33.64061], [73.98968, 33.66155], [73.96423, 33.73071], [74.00891, 33.75437], [74.05898, 33.82089], [74.14001, 33.83002], [74.26086, 33.92237], [74.25262, 34.01577], [74.21554, 34.03853], [73.91341, 34.01235], [73.88732, 34.05105], [73.90677, 34.10504], [73.98208, 34.2522], [73.90517, 34.35317], [73.8475, 34.32935], [73.74862, 34.34183], [73.74999, 34.3781], [73.88732, 34.48911], [73.89419, 34.54568], [73.93951, 34.57169], [73.93401, 34.63386], [73.96423, 34.68244], [74.12897, 34.70073], [74.31239, 34.79626], [74.58083, 34.77386], [74.6663, 34.703], [75.01479, 34.64629], [75.38009, 34.55021], [75.75438, 34.51827], [76.04614, 34.67566], [76.15463, 34.6429], [76.47186, 34.78965], [76.67648, 34.76371], [76.74377, 34.84039], [76.74514, 34.92488], [76.87193, 34.96906], [76.99251, 34.93349], [77.11796, 35.05419], [76.93465, 35.39866], [76.85088, 35.39754], [76.75475, 35.52617], [76.77323, 35.66062], [76.50961, 35.8908], [76.33453, 35.84296], [76.14913, 35.82848], [76.15325, 35.9264], [75.93028, 36.13136], [76.00906, 36.17511], [76.0324, 36.41198], [75.92391, 36.56986], [75.72737, 36.7529]]]]
26434 groups: ["EU", "151", "150", "UN"],
26435 callingCodes: ["48"]
26438 type: "MultiPolygon",
26439 coordinates: [[[[18.57853, 55.25302], [14.20811, 54.12784], [14.22634, 53.9291], [14.20647, 53.91671], [14.18544, 53.91258], [14.20823, 53.90776], [14.21323, 53.8664], [14.27249, 53.74464], [14.26782, 53.69866], [14.2836, 53.67721], [14.27133, 53.66613], [14.28477, 53.65955], [14.2853, 53.63392], [14.31904, 53.61581], [14.30416, 53.55499], [14.3273, 53.50587], [14.35209, 53.49506], [14.4215, 53.27724], [14.44133, 53.27427], [14.45125, 53.26241], [14.40662, 53.21098], [14.37853, 53.20405], [14.36696, 53.16444], [14.38679, 53.13669], [14.35044, 53.05829], [14.25954, 53.00264], [14.14056, 52.95786], [14.15873, 52.87715], [14.12256, 52.84311], [14.13806, 52.82392], [14.22071, 52.81175], [14.61073, 52.59847], [14.6289, 52.57136], [14.60081, 52.53116], [14.63056, 52.48993], [14.54423, 52.42568], [14.55228, 52.35264], [14.56378, 52.33838], [14.58149, 52.28007], [14.70139, 52.25038], [14.71319, 52.22144], [14.68344, 52.19612], [14.70616, 52.16927], [14.67683, 52.13936], [14.6917, 52.10283], [14.72971, 52.09167], [14.76026, 52.06624], [14.71339, 52.00337], [14.70488, 51.97679], [14.7139, 51.95643], [14.71836, 51.95606], [14.72163, 51.95188], [14.7177, 51.94048], [14.70601, 51.92944], [14.6933, 51.9044], [14.6588, 51.88359], [14.59089, 51.83302], [14.60493, 51.80473], [14.64625, 51.79472], [14.66386, 51.73282], [14.69065, 51.70842], [14.75392, 51.67445], [14.75759, 51.62318], [14.7727, 51.61263], [14.71125, 51.56209], [14.73047, 51.54606], [14.72652, 51.53902], [14.73219, 51.52922], [14.94749, 51.47155], [14.9652, 51.44793], [14.96899, 51.38367], [14.98008, 51.33449], [15.04288, 51.28387], [15.01242, 51.21285], [15.0047, 51.16874], [14.99311, 51.16249], [14.99414, 51.15813], [15.00083, 51.14974], [14.99646, 51.14365], [14.99079, 51.14284], [14.99689, 51.12205], [14.98229, 51.11354], [14.97938, 51.07742], [14.95529, 51.04552], [14.92942, 50.99744], [14.89252, 50.94999], [14.89681, 50.9422], [14.81664, 50.88148], [14.82803, 50.86966], [14.99852, 50.86817], [15.01088, 50.97984], [14.96419, 50.99108], [15.02433, 51.0242], [15.03895, 51.0123], [15.06218, 51.02269], [15.10152, 51.01095], [15.11937, 50.99021], [15.16744, 51.01959], [15.1743, 50.9833], [15.2361, 50.99886], [15.27043, 50.97724], [15.2773, 50.8907], [15.36656, 50.83956], [15.3803, 50.77187], [15.43798, 50.80833], [15.73186, 50.73885], [15.81683, 50.75666], [15.87331, 50.67188], [15.97219, 50.69799], [16.0175, 50.63009], [15.98317, 50.61528], [16.02437, 50.60046], [16.10265, 50.66405], [16.20839, 50.63096], [16.23174, 50.67101], [16.33611, 50.66579], [16.44597, 50.58041], [16.34572, 50.49575], [16.31413, 50.50274], [16.19526, 50.43291], [16.21585, 50.40627], [16.22821, 50.41054], [16.28118, 50.36891], [16.30289, 50.38292], [16.36495, 50.37679], [16.3622, 50.34875], [16.39379, 50.3207], [16.42674, 50.32509], [16.56407, 50.21009], [16.55446, 50.16613], [16.63137, 50.1142], [16.7014, 50.09659], [16.8456, 50.20834], [16.98018, 50.24172], [17.00353, 50.21449], [17.02825, 50.23118], [16.99803, 50.25753], [17.02138, 50.27772], [16.99803, 50.30316], [16.94448, 50.31281], [16.90877, 50.38642], [16.85933, 50.41093], [16.89229, 50.45117], [17.1224, 50.39494], [17.14498, 50.38117], [17.19579, 50.38817], [17.19991, 50.3654], [17.27681, 50.32246], [17.34273, 50.32947], [17.34548, 50.2628], [17.3702, 50.28123], [17.58889, 50.27837], [17.67764, 50.28977], [17.69292, 50.32859], [17.74648, 50.29966], [17.72176, 50.25665], [17.76296, 50.23382], [17.70528, 50.18812], [17.59404, 50.16437], [17.66683, 50.10275], [17.6888, 50.12037], [17.7506, 50.07896], [17.77669, 50.02253], [17.86886, 49.97452], [18.00191, 50.01723], [18.04585, 50.01194], [18.04585, 50.03311], [18.00396, 50.04954], [18.03212, 50.06574], [18.07898, 50.04535], [18.10628, 50.00223], [18.20241, 49.99958], [18.21752, 49.97309], [18.27107, 49.96779], [18.27794, 49.93863], [18.31914, 49.91565], [18.33278, 49.92415], [18.33562, 49.94747], [18.41604, 49.93498], [18.53423, 49.89906], [18.54495, 49.9079], [18.54299, 49.92537], [18.57697, 49.91565], [18.57045, 49.87849], [18.60341, 49.86256], [18.57183, 49.83334], [18.61278, 49.7618], [18.61368, 49.75426], [18.62645, 49.75002], [18.62943, 49.74603], [18.62676, 49.71983], [18.69817, 49.70473], [18.72838, 49.68163], [18.80479, 49.6815], [18.84786, 49.5446], [18.84521, 49.51672], [18.94536, 49.52143], [18.97283, 49.49914], [18.9742, 49.39557], [19.18019, 49.41165], [19.25435, 49.53391], [19.36009, 49.53747], [19.37795, 49.574], [19.45348, 49.61583], [19.52626, 49.57311], [19.53313, 49.52856], [19.57845, 49.46077], [19.64162, 49.45184], [19.6375, 49.40897], [19.72127, 49.39288], [19.78581, 49.41701], [19.82237, 49.27806], [19.75286, 49.20751], [19.86409, 49.19316], [19.90529, 49.23532], [19.98494, 49.22904], [20.08238, 49.1813], [20.13738, 49.31685], [20.21977, 49.35265], [20.31453, 49.34817], [20.31728, 49.39914], [20.39939, 49.3896], [20.46422, 49.41612], [20.5631, 49.375], [20.61666, 49.41791], [20.72274, 49.41813], [20.77971, 49.35383], [20.9229, 49.29626], [20.98733, 49.30774], [21.09799, 49.37176], [21.041, 49.41791], [21.12477, 49.43666], [21.19756, 49.4054], [21.27858, 49.45988], [21.43376, 49.41433], [21.62328, 49.4447], [21.77983, 49.35443], [21.82927, 49.39467], [21.96385, 49.3437], [22.04427, 49.22136], [22.56155, 49.08865], [22.89122, 49.00725], [22.86336, 49.10513], [22.72009, 49.20288], [22.748, 49.32759], [22.69444, 49.49378], [22.64534, 49.53094], [22.78304, 49.65543], [22.80261, 49.69098], [22.83179, 49.69875], [22.99329, 49.84249], [23.28221, 50.0957], [23.67635, 50.33385], [23.71382, 50.38248], [23.79445, 50.40481], [23.99563, 50.41289], [24.03668, 50.44507], [24.07048, 50.5071], [24.0996, 50.60752], [24.0595, 50.71625], [23.95925, 50.79271], [23.99254, 50.83847], [24.0952, 50.83262], [24.14524, 50.86128], [24.04576, 50.90196], [23.92217, 51.00836], [23.90376, 51.07697], [23.80678, 51.18405], [23.63858, 51.32182], [23.69905, 51.40871], [23.62751, 51.50512], [23.56236, 51.53673], [23.57053, 51.55938], [23.53198, 51.74298], [23.62691, 51.78208], [23.61523, 51.92066], [23.68733, 51.9906], [23.64066, 52.07626], [23.61, 52.11264], [23.54314, 52.12148], [23.47859, 52.18215], [23.20071, 52.22848], [23.18196, 52.28812], [23.34141, 52.44845], [23.45112, 52.53774], [23.58296, 52.59868], [23.73615, 52.6149], [23.93763, 52.71332], [23.91805, 52.94016], [23.94689, 52.95919], [23.92184, 53.02079], [23.87548, 53.0831], [23.91393, 53.16469], [23.85657, 53.22923], [23.81995, 53.24131], [23.62004, 53.60942], [23.51284, 53.95052], [23.48261, 53.98855], [23.52702, 54.04622], [23.49196, 54.14764], [23.45223, 54.17775], [23.42418, 54.17911], [23.39525, 54.21672], [23.3494, 54.25155], [23.24656, 54.25701], [23.15938, 54.29894], [23.15526, 54.31076], [23.13905, 54.31567], [23.104, 54.29794], [23.04323, 54.31567], [23.05726, 54.34565], [22.99649, 54.35927], [23.00584, 54.38514], [22.83756, 54.40827], [22.79705, 54.36264], [21.41123, 54.32395], [20.63871, 54.3706], [19.8038, 54.44203], [19.64312, 54.45423], [18.57853, 55.25302]]]]
26447 wikidata: "Q34617",
26448 nameEn: "Saint Pierre and Miquelon",
26450 groups: ["Q1451600", "021", "003", "019", "UN"],
26451 callingCodes: ["508"]
26454 type: "MultiPolygon",
26455 coordinates: [[[[-56.72993, 46.65575], [-55.90758, 46.6223], [-56.27503, 47.39728], [-56.72993, 46.65575]]]]
26463 wikidata: "Q35672",
26464 nameEn: "Pitcairn Islands",
26466 groups: ["BOTS", "061", "009", "UN"],
26468 callingCodes: ["64"]
26471 type: "MultiPolygon",
26472 coordinates: [[[[-133.59543, -28.4709], [-122.0366, -24.55017], [-133.61511, -21.93325], [-133.59543, -28.4709]]]]
26481 nameEn: "Puerto Rico",
26482 aliases: ["US-PR"],
26484 groups: ["Q1352230", "029", "003", "419", "019", "UN"],
26485 roadSpeedUnit: "mph",
26486 callingCodes: ["1 787", "1 939"]
26489 type: "MultiPolygon",
26490 coordinates: [[[[-65.27974, 17.56928], [-65.02435, 18.73231], [-67.99519, 18.97186], [-68.23894, 17.84663], [-65.27974, 17.56928]]]]
26498 wikidata: "Q219060",
26499 nameEn: "Palestine"
26520 groups: ["057", "009", "UN"],
26521 roadSpeedUnit: "mph",
26522 callingCodes: ["680"]
26525 type: "MultiPolygon",
26526 coordinates: [[[[128.97621, 3.08804], [136.39296, 1.54187], [136.04605, 12.45908], [128.97621, 3.08804]]]]
26535 nameEn: "Paraguay",
26536 groups: ["005", "419", "019", "UN"],
26537 callingCodes: ["595"]
26540 type: "MultiPolygon",
26541 coordinates: [[[[-58.16225, -20.16193], [-58.23216, -19.80058], [-59.06965, -19.29148], [-60.00638, -19.2981], [-61.73723, -19.63958], [-61.93912, -20.10053], [-62.26883, -20.55311], [-62.2757, -21.06657], [-62.64455, -22.25091], [-62.51761, -22.37684], [-62.22768, -22.55807], [-61.9756, -23.0507], [-61.0782, -23.62932], [-60.99754, -23.80934], [-60.28163, -24.04436], [-60.03367, -24.00701], [-59.45482, -24.34787], [-59.33886, -24.49935], [-58.33055, -24.97099], [-58.25492, -24.92528], [-57.80821, -25.13863], [-57.57431, -25.47269], [-57.87176, -25.93604], [-58.1188, -26.16704], [-58.3198, -26.83443], [-58.65321, -27.14028], [-58.59549, -27.29973], [-58.04205, -27.2387], [-56.85337, -27.5165], [-56.18313, -27.29851], [-55.89195, -27.3467], [-55.74475, -27.44485], [-55.59094, -27.32444], [-55.62322, -27.1941], [-55.39611, -26.97679], [-55.25243, -26.93808], [-55.16948, -26.96068], [-55.06351, -26.80195], [-55.00584, -26.78754], [-54.80868, -26.55669], [-54.70732, -26.45099], [-54.69333, -26.37705], [-54.67359, -25.98607], [-54.60664, -25.9691], [-54.62063, -25.91213], [-54.59398, -25.59224], [-54.59509, -25.53696], [-54.60196, -25.48397], [-54.62033, -25.46026], [-54.4423, -25.13381], [-54.28207, -24.07305], [-54.32807, -24.01865], [-54.6238, -23.83078], [-55.02691, -23.97317], [-55.0518, -23.98666], [-55.12292, -23.99669], [-55.41784, -23.9657], [-55.44117, -23.9185], [-55.43585, -23.87157], [-55.5555, -23.28237], [-55.52288, -23.2595], [-55.5446, -23.22811], [-55.63849, -22.95122], [-55.62493, -22.62765], [-55.68742, -22.58407], [-55.6986, -22.56268], [-55.72366, -22.5519], [-55.741, -22.52018], [-55.74941, -22.46436], [-55.8331, -22.29008], [-56.23206, -22.25347], [-56.45893, -22.08072], [-56.5212, -22.11556], [-56.6508, -22.28387], [-57.98625, -22.09157], [-57.94642, -21.73799], [-57.88239, -21.6868], [-57.93492, -21.65505], [-57.84536, -20.93155], [-58.16225, -20.16193]]]]
26551 groups: ["145", "142", "UN"],
26552 callingCodes: ["974"]
26555 type: "MultiPolygon",
26556 coordinates: [[[[50.92992, 24.54396], [51.09638, 24.46907], [51.29972, 24.50747], [51.39468, 24.62785], [51.58834, 24.66608], [51.83108, 24.71675], [51.83682, 26.70231], [50.93865, 26.30758], [50.81266, 25.88946], [50.86149, 25.6965], [50.7801, 25.595], [50.80824, 25.54641], [50.57069, 25.57887], [50.8133, 24.74049], [50.92992, 24.54396]]]]
26564 wikidata: "Q17070",
26565 nameEn: "R\xE9union",
26567 groups: ["Q3320166", "EU", "014", "202", "002", "UN"],
26568 callingCodes: ["262"]
26571 type: "MultiPolygon",
26572 coordinates: [[[[53.37984, -21.23941], [56.73473, -21.9174], [56.62373, -20.2711], [53.37984, -21.23941]]]]
26582 groups: ["EU", "151", "150", "UN"],
26583 callingCodes: ["40"]
26586 type: "MultiPolygon",
26587 coordinates: [[[[27.15622, 47.98538], [27.02985, 48.09083], [27.04118, 48.12522], [26.96119, 48.13003], [26.98042, 48.15752], [26.94265, 48.1969], [26.87708, 48.19919], [26.81161, 48.25049], [26.62823, 48.25804], [26.55202, 48.22445], [26.33504, 48.18418], [26.17711, 47.99246], [26.05901, 47.9897], [25.77723, 47.93919], [25.63878, 47.94924], [25.23778, 47.89403], [25.11144, 47.75203], [24.88896, 47.7234], [24.81893, 47.82031], [24.70632, 47.84428], [24.61994, 47.95062], [24.43578, 47.97131], [24.34926, 47.9244], [24.22566, 47.90231], [24.11281, 47.91487], [24.06466, 47.95317], [24.02999, 47.95087], [24.00801, 47.968], [23.98553, 47.96076], [23.96337, 47.96672], [23.94192, 47.94868], [23.89352, 47.94512], [23.8602, 47.9329], [23.80904, 47.98142], [23.75188, 47.99705], [23.66262, 47.98786], [23.63894, 48.00293], [23.5653, 48.00499], [23.52803, 48.01818], [23.4979, 47.96858], [23.33577, 48.0237], [23.27397, 48.08245], [23.15999, 48.12188], [23.1133, 48.08061], [23.08858, 48.00716], [23.0158, 47.99338], [22.92241, 48.02002], [22.94301, 47.96672], [22.89849, 47.95851], [22.77991, 47.87211], [22.76617, 47.8417], [22.67247, 47.7871], [22.46559, 47.76583], [22.41979, 47.7391], [22.31816, 47.76126], [22.00917, 47.50492], [22.03389, 47.42508], [22.01055, 47.37767], [21.94463, 47.38046], [21.78395, 47.11104], [21.648, 47.03902], [21.68645, 46.99595], [21.59581, 46.91628], [21.59307, 46.86935], [21.52028, 46.84118], [21.48935, 46.7577], [21.5151, 46.72147], [21.43926, 46.65109], [21.33214, 46.63035], [21.26929, 46.4993], [21.28061, 46.44941], [21.16872, 46.30118], [21.06572, 46.24897], [20.86797, 46.28884], [20.74574, 46.25467], [20.76085, 46.21002], [20.63863, 46.12728], [20.49718, 46.18721], [20.45377, 46.14405], [20.35573, 46.16629], [20.28324, 46.1438], [20.26068, 46.12332], [20.35862, 45.99356], [20.54818, 45.89939], [20.65645, 45.82801], [20.70069, 45.7493], [20.77416, 45.75601], [20.78446, 45.78522], [20.82364, 45.77738], [20.80361, 45.65875], [20.76798, 45.60969], [20.83321, 45.53567], [20.77217, 45.49788], [20.86026, 45.47295], [20.87948, 45.42743], [21.09894, 45.30144], [21.17612, 45.32566], [21.20392, 45.2677], [21.29398, 45.24148], [21.48278, 45.19557], [21.51299, 45.15345], [21.4505, 45.04294], [21.35855, 45.01941], [21.54938, 44.9327], [21.56328, 44.89502], [21.48202, 44.87199], [21.44013, 44.87613], [21.35643, 44.86364], [21.38802, 44.78133], [21.55007, 44.77304], [21.60019, 44.75208], [21.61942, 44.67059], [21.67504, 44.67107], [21.71692, 44.65349], [21.7795, 44.66165], [21.99364, 44.63395], [22.08016, 44.49844], [22.13234, 44.47444], [22.18315, 44.48179], [22.30844, 44.6619], [22.45301, 44.7194], [22.61917, 44.61489], [22.69196, 44.61587], [22.76749, 44.54446], [22.70981, 44.51852], [22.61368, 44.55719], [22.56493, 44.53419], [22.54021, 44.47836], [22.45436, 44.47258], [22.56012, 44.30712], [22.68166, 44.28206], [22.67173, 44.21564], [23.04988, 44.07694], [23.01674, 44.01946], [22.87873, 43.9844], [22.83753, 43.88055], [22.85314, 43.84452], [23.05288, 43.79494], [23.26772, 43.84843], [23.4507, 43.84936], [23.61687, 43.79289], [23.73978, 43.80627], [24.18149, 43.68218], [24.35364, 43.70211], [24.50264, 43.76314], [24.62281, 43.74082], [24.73542, 43.68523], [24.96682, 43.72693], [25.10718, 43.6831], [25.17144, 43.70261], [25.39528, 43.61866], [25.72792, 43.69263], [25.94911, 43.85745], [26.05584, 43.90925], [26.10115, 43.96908], [26.38764, 44.04356], [26.62712, 44.05698], [26.95141, 44.13555], [27.26845, 44.12602], [27.39757, 44.0141], [27.60834, 44.01206], [27.64542, 44.04958], [27.73468, 43.95326], [27.92008, 44.00761], [27.99558, 43.84193], [28.23293, 43.76], [29.24336, 43.70874], [30.04414, 45.08461], [29.69272, 45.19227], [29.65428, 45.25629], [29.68175, 45.26885], [29.59798, 45.38857], [29.42632, 45.44545], [29.24779, 45.43388], [28.96077, 45.33164], [28.94292, 45.28045], [28.81383, 45.3384], [28.78911, 45.24179], [28.71358, 45.22631], [28.5735, 45.24759], [28.34554, 45.32102], [28.28504, 45.43907], [28.21139, 45.46895], [28.18741, 45.47358], [28.08927, 45.6051], [28.16568, 45.6421], [28.13111, 45.92819], [28.08612, 46.01105], [28.13684, 46.18099], [28.10937, 46.22852], [28.19864, 46.31869], [28.18902, 46.35283], [28.25769, 46.43334], [28.22281, 46.50481], [28.24808, 46.64305], [28.12173, 46.82283], [28.09095, 46.97621], [27.81892, 47.1381], [27.73172, 47.29248], [27.68706, 47.28962], [27.60263, 47.32507], [27.55731, 47.46637], [27.47942, 47.48113], [27.3979, 47.59473], [27.32202, 47.64009], [27.25519, 47.71366], [27.29069, 47.73722], [27.1618, 47.92391], [27.15622, 47.98538]]]]
26597 groups: ["039", "150", "UN"],
26598 callingCodes: ["381"]
26601 type: "MultiPolygon",
26602 coordinates: [[[[19.66007, 46.19005], [19.56113, 46.16824], [19.52473, 46.1171], [19.28826, 45.99694], [19.14543, 45.9998], [19.10388, 46.04015], [19.0791, 45.96458], [19.01284, 45.96529], [18.99712, 45.93537], [18.81394, 45.91329], [18.85783, 45.85493], [18.90305, 45.71863], [18.96691, 45.66731], [18.88776, 45.57253], [18.94562, 45.53712], [19.07471, 45.53086], [19.08364, 45.48804], [18.99918, 45.49333], [18.97446, 45.37528], [19.10774, 45.29547], [19.28208, 45.23813], [19.41941, 45.23475], [19.43589, 45.17137], [19.19144, 45.17863], [19.14063, 45.12972], [19.07952, 45.14668], [19.1011, 45.01191], [19.05205, 44.97692], [19.15573, 44.95409], [19.06853, 44.89915], [19.02871, 44.92541], [18.98957, 44.90645], [19.01994, 44.85493], [19.18183, 44.92055], [19.36722, 44.88164], [19.32543, 44.74058], [19.26388, 44.65412], [19.16699, 44.52197], [19.13369, 44.52521], [19.12278, 44.50132], [19.14837, 44.45253], [19.14681, 44.41463], [19.11785, 44.40313], [19.10749, 44.39421], [19.10704, 44.38249], [19.10365, 44.37795], [19.10298, 44.36924], [19.11865, 44.36712], [19.1083, 44.3558], [19.11547, 44.34218], [19.13556, 44.338], [19.13332, 44.31492], [19.16741, 44.28648], [19.18328, 44.28383], [19.20508, 44.2917], [19.23306, 44.26097], [19.26945, 44.26957], [19.32464, 44.27185], [19.34773, 44.23244], [19.3588, 44.18353], [19.40927, 44.16722], [19.43905, 44.13088], [19.47338, 44.15034], [19.48386, 44.14332], [19.47321, 44.1193], [19.51167, 44.08158], [19.55999, 44.06894], [19.57467, 44.04716], [19.61991, 44.05254], [19.61836, 44.01464], [19.56498, 43.99922], [19.52515, 43.95573], [19.38439, 43.96611], [19.24363, 44.01502], [19.23465, 43.98764], [19.3986, 43.79668], [19.5176, 43.71403], [19.50455, 43.58385], [19.42696, 43.57987], [19.41941, 43.54056], [19.36653, 43.60921], [19.33426, 43.58833], [19.2553, 43.5938], [19.24774, 43.53061], [19.22807, 43.5264], [19.22229, 43.47926], [19.44315, 43.38846], [19.48171, 43.32644], [19.52962, 43.31623], [19.54598, 43.25158], [19.62661, 43.2286], [19.64063, 43.19027], [19.76918, 43.16044], [19.79255, 43.11951], [19.92576, 43.08539], [19.96549, 43.11098], [19.98887, 43.0538], [20.04729, 43.02732], [20.05431, 42.99571], [20.12325, 42.96237], [20.14896, 42.99058], [20.16415, 42.97177], [20.34528, 42.90676], [20.35692, 42.8335], [20.40594, 42.84853], [20.43734, 42.83157], [20.53484, 42.8885], [20.48692, 42.93208], [20.59929, 43.01067], [20.64557, 43.00826], [20.69515, 43.09641], [20.59929, 43.20492], [20.68688, 43.21335], [20.73811, 43.25068], [20.82145, 43.26769], [20.88685, 43.21697], [20.83727, 43.17842], [20.96287, 43.12416], [21.00749, 43.13984], [21.05378, 43.10707], [21.08952, 43.13471], [21.14465, 43.11089], [21.16734, 42.99694], [21.2041, 43.02277], [21.23877, 43.00848], [21.23534, 42.95523], [21.2719, 42.8994], [21.32974, 42.90424], [21.36941, 42.87397], [21.44047, 42.87276], [21.39045, 42.74888], [21.47498, 42.74695], [21.59154, 42.72643], [21.58755, 42.70418], [21.6626, 42.67813], [21.75025, 42.70125], [21.79413, 42.65923], [21.75672, 42.62695], [21.7327, 42.55041], [21.70522, 42.54176], [21.7035, 42.51899], [21.62556, 42.45106], [21.64209, 42.41081], [21.62887, 42.37664], [21.59029, 42.38042], [21.57021, 42.3647], [21.53467, 42.36809], [21.5264, 42.33634], [21.56772, 42.30946], [21.58992, 42.25915], [21.70111, 42.23789], [21.77176, 42.2648], [21.84654, 42.3247], [21.91595, 42.30392], [21.94405, 42.34669], [22.02908, 42.29848], [22.16384, 42.32103], [22.29605, 42.37477], [22.29275, 42.34913], [22.34773, 42.31725], [22.45919, 42.33822], [22.47498, 42.3915], [22.51961, 42.3991], [22.55669, 42.50144], [22.43983, 42.56851], [22.4997, 42.74144], [22.43309, 42.82057], [22.54302, 42.87774], [22.74826, 42.88701], [22.78397, 42.98253], [22.89521, 43.03625], [22.98104, 43.11199], [23.00806, 43.19279], [22.89727, 43.22417], [22.82036, 43.33665], [22.53397, 43.47225], [22.47582, 43.6558], [22.41043, 43.69566], [22.35558, 43.81281], [22.41449, 44.00514], [22.61688, 44.06534], [22.61711, 44.16938], [22.67173, 44.21564], [22.68166, 44.28206], [22.56012, 44.30712], [22.45436, 44.47258], [22.54021, 44.47836], [22.56493, 44.53419], [22.61368, 44.55719], [22.70981, 44.51852], [22.76749, 44.54446], [22.69196, 44.61587], [22.61917, 44.61489], [22.45301, 44.7194], [22.30844, 44.6619], [22.18315, 44.48179], [22.13234, 44.47444], [22.08016, 44.49844], [21.99364, 44.63395], [21.7795, 44.66165], [21.71692, 44.65349], [21.67504, 44.67107], [21.61942, 44.67059], [21.60019, 44.75208], [21.55007, 44.77304], [21.38802, 44.78133], [21.35643, 44.86364], [21.44013, 44.87613], [21.48202, 44.87199], [21.56328, 44.89502], [21.54938, 44.9327], [21.35855, 45.01941], [21.4505, 45.04294], [21.51299, 45.15345], [21.48278, 45.19557], [21.29398, 45.24148], [21.20392, 45.2677], [21.17612, 45.32566], [21.09894, 45.30144], [20.87948, 45.42743], [20.86026, 45.47295], [20.77217, 45.49788], [20.83321, 45.53567], [20.76798, 45.60969], [20.80361, 45.65875], [20.82364, 45.77738], [20.78446, 45.78522], [20.77416, 45.75601], [20.70069, 45.7493], [20.65645, 45.82801], [20.54818, 45.89939], [20.35862, 45.99356], [20.26068, 46.12332], [20.09713, 46.17315], [20.03533, 46.14509], [20.01816, 46.17696], [19.93508, 46.17553], [19.81491, 46.1313], [19.66007, 46.19005]]]]
26622 groups: ["014", "202", "002", "UN"],
26623 callingCodes: ["250"]
26626 type: "MultiPolygon",
26627 coordinates: [[[[30.47194, -1.0555], [30.35212, -1.06896], [30.16369, -1.34303], [29.912, -1.48269], [29.82657, -1.31187], [29.59061, -1.39016], [29.53062, -1.40499], [29.45038, -1.5054], [29.36322, -1.50887], [29.24323, -1.66826], [29.24458, -1.69663], [29.11847, -1.90576], [29.17562, -2.12278], [29.105, -2.27043], [29.00051, -2.29001], [28.95642, -2.37321], [28.89601, -2.37321], [28.86826, -2.41888], [28.86846, -2.44866], [28.89132, -2.47557], [28.89342, -2.49017], [28.88846, -2.50493], [28.87497, -2.50887], [28.86209, -2.5231], [28.86193, -2.53185], [28.87943, -2.55165], [28.89288, -2.55848], [28.90226, -2.62385], [28.89793, -2.66111], [28.94346, -2.69124], [29.00357, -2.70596], [29.04081, -2.7416], [29.0562, -2.58632], [29.32234, -2.6483], [29.36805, -2.82933], [29.88237, -2.75105], [29.95911, -2.33348], [30.14034, -2.43626], [30.42933, -2.31064], [30.54501, -2.41404], [30.83915, -2.35795], [30.89303, -2.08223], [30.80802, -1.91477], [30.84079, -1.64652], [30.71974, -1.43244], [30.57123, -1.33264], [30.50889, -1.16412], [30.45116, -1.10641], [30.47194, -1.0555]]]]
26636 nameEn: "Saudi Arabia",
26637 groups: ["145", "142", "UN"],
26638 callingCodes: ["966"]
26641 type: "MultiPolygon",
26642 coordinates: [[[[40.01521, 32.05667], [39.29903, 32.23259], [38.99233, 31.99721], [36.99791, 31.50081], [37.99354, 30.49998], [37.66395, 30.33245], [37.4971, 29.99949], [36.75083, 29.86903], [36.50005, 29.49696], [36.07081, 29.18469], [34.8812, 29.36878], [34.4454, 27.91479], [37.8565, 22.00903], [39.63762, 18.37348], [40.99158, 15.81743], [42.15205, 16.40211], [42.76801, 16.40371], [42.94625, 16.39721], [42.94351, 16.49467], [42.97215, 16.51093], [43.11601, 16.53166], [43.15274, 16.67248], [43.22066, 16.65179], [43.21325, 16.74416], [43.25857, 16.75304], [43.26303, 16.79479], [43.24801, 16.80613], [43.22956, 16.80613], [43.22012, 16.83932], [43.18338, 16.84852], [43.1398, 16.90696], [43.19328, 16.94703], [43.1813, 16.98438], [43.18233, 17.02673], [43.23967, 17.03428], [43.17787, 17.14717], [43.20156, 17.25901], [43.32653, 17.31179], [43.22533, 17.38343], [43.29185, 17.53224], [43.43005, 17.56148], [43.70631, 17.35762], [44.50126, 17.47475], [46.31018, 17.20464], [46.76494, 17.29151], [47.00571, 16.94765], [47.48245, 17.10808], [47.58351, 17.50366], [48.19996, 18.20584], [49.04884, 18.59899], [52.00311, 19.00083], [54.99756, 20.00083], [55.66469, 21.99658], [55.2137, 22.71065], [55.13599, 22.63334], [52.56622, 22.94341], [51.59617, 24.12041], [51.58871, 24.27256], [51.41644, 24.39615], [51.58834, 24.66608], [51.39468, 24.62785], [51.29972, 24.50747], [51.09638, 24.46907], [50.92992, 24.54396], [50.8133, 24.74049], [50.57069, 25.57887], [50.302, 25.87592], [50.26923, 26.08243], [50.38162, 26.53976], [50.71771, 26.73086], [50.37726, 27.89227], [49.98877, 27.87827], [49.00421, 28.81495], [48.42991, 28.53628], [47.70561, 28.5221], [47.59863, 28.66798], [47.58376, 28.83382], [47.46202, 29.0014], [46.5527, 29.10283], [46.42415, 29.05947], [44.72255, 29.19736], [42.97796, 30.48295], [42.97601, 30.72204], [40.01521, 32.05667]]]]
26651 nameEn: "Solomon Islands",
26652 groups: ["054", "009", "UN"],
26654 callingCodes: ["677"]
26657 type: "MultiPolygon",
26658 coordinates: [[[[172.71443, -12.01327], [160.43769, -4.17974], [156.03296, -6.55528], [156.03993, -6.65703], [155.92557, -6.84664], [155.69784, -6.92661], [155.60735, -6.92266], [154.74815, -7.33315], [156.73836, -14.50464], [172.71443, -12.01327]]]]
26667 nameEn: "Seychelles",
26668 groups: ["014", "202", "002", "UN"],
26670 callingCodes: ["248"]
26673 type: "MultiPolygon",
26674 coordinates: [[[[43.75112, -10.38913], [54.83239, -10.93575], [66.3222, 5.65313], [43.75112, -10.38913]]]]
26684 groups: ["015", "002", "UN"],
26685 callingCodes: ["249"]
26688 type: "MultiPolygon",
26689 coordinates: [[[[37.8565, 22.00903], [34.0765, 22.00501], [33.99686, 21.76784], [33.57251, 21.72406], [33.17563, 22.00405], [24.99885, 21.99535], [24.99794, 19.99661], [23.99715, 20.00038], [23.99539, 19.49944], [23.99997, 15.69575], [23.62785, 15.7804], [23.38812, 15.69649], [23.10792, 15.71297], [22.93201, 15.55107], [22.92579, 15.47007], [22.99584, 15.40105], [22.99584, 15.22989], [22.66115, 14.86308], [22.70474, 14.69149], [22.38562, 14.58907], [22.44944, 14.24986], [22.55997, 14.23024], [22.5553, 14.11704], [22.22995, 13.96754], [22.08674, 13.77863], [22.29689, 13.3731], [22.1599, 13.19281], [22.02914, 13.13976], [21.94819, 13.05637], [21.81432, 12.81362], [21.89371, 12.68001], [21.98711, 12.63292], [22.15679, 12.66634], [22.22684, 12.74682], [22.46345, 12.61925], [22.38873, 12.45514], [22.50548, 12.16769], [22.48369, 12.02766], [22.64092, 12.07485], [22.54907, 11.64372], [22.7997, 11.40424], [22.93124, 11.41645], [22.97249, 11.21955], [22.87758, 10.91915], [23.02221, 10.69235], [23.3128, 10.45214], [23.67164, 9.86923], [23.69155, 9.67566], [24.09319, 9.66572], [24.12744, 9.73784], [24.49389, 9.79962], [24.84653, 9.80643], [24.97739, 9.9081], [25.05688, 10.06776], [25.0918, 10.33718], [25.78141, 10.42599], [25.93163, 10.38159], [25.93241, 10.17941], [26.21338, 9.91545], [26.35815, 9.57946], [26.70685, 9.48735], [27.14427, 9.62858], [27.90704, 9.61323], [28.99983, 9.67155], [29.06988, 9.74826], [29.53844, 9.75133], [29.54, 10.07949], [29.94629, 10.29245], [30.00389, 10.28633], [30.53005, 9.95992], [30.82893, 9.71451], [30.84605, 9.7498], [31.28504, 9.75287], [31.77539, 10.28939], [31.99177, 10.65065], [32.46967, 11.04662], [32.39358, 11.18207], [32.39578, 11.70208], [32.10079, 11.95203], [32.73921, 11.95203], [32.73921, 12.22757], [33.25876, 12.22111], [33.13988, 11.43248], [33.26977, 10.83632], [33.24645, 10.77913], [33.52294, 10.64382], [33.66604, 10.44254], [33.80913, 10.32994], [33.90159, 10.17179], [33.96984, 10.15446], [33.99185, 9.99623], [33.96323, 9.80972], [33.9082, 9.762], [33.87958, 9.49937], [34.10229, 9.50238], [34.08717, 9.55243], [34.13186, 9.7492], [34.20484, 9.9033], [34.22718, 10.02506], [34.32102, 10.11599], [34.34783, 10.23914], [34.2823, 10.53508], [34.4372, 10.781], [34.59062, 10.89072], [34.77383, 10.74588], [34.77532, 10.69027], [34.86618, 10.74588], [34.86916, 10.78832], [34.97491, 10.86147], [34.97789, 10.91559], [34.93172, 10.95946], [35.01215, 11.19626], [34.95704, 11.24448], [35.09556, 11.56278], [35.05832, 11.71158], [35.11492, 11.85156], [35.24302, 11.91132], [35.70476, 12.67101], [36.01458, 12.72478], [36.14268, 12.70879], [36.16651, 12.88019], [36.13374, 12.92665], [36.24545, 13.36759], [36.38993, 13.56459], [36.48824, 13.83954], [36.44653, 13.95666], [36.54376, 14.25597], [36.44337, 15.14963], [36.54276, 15.23478], [36.69761, 15.75323], [36.76371, 15.80831], [36.92193, 16.23451], [36.99777, 17.07172], [37.42694, 17.04041], [37.50967, 17.32199], [38.13362, 17.53906], [38.37133, 17.66269], [38.45916, 17.87167], [38.57727, 17.98125], [39.63762, 18.37348], [37.8565, 22.00903]]]]
26699 groups: ["EU", "154", "150", "UN"],
26700 callingCodes: ["46"]
26703 type: "MultiPolygon",
26704 coordinates: [[[[24.15791, 65.85385], [23.90497, 66.15802], [23.71339, 66.21299], [23.64982, 66.30603], [23.67591, 66.3862], [23.63776, 66.43568], [23.85959, 66.56434], [23.89488, 66.772], [23.98059, 66.79585], [23.98563, 66.84149], [23.56214, 67.17038], [23.58735, 67.20752], [23.54701, 67.25435], [23.75372, 67.29914], [23.75372, 67.43688], [23.39577, 67.46974], [23.54701, 67.59306], [23.45627, 67.85297], [23.65793, 67.9497], [23.40081, 68.05545], [23.26469, 68.15134], [23.15377, 68.14759], [23.10336, 68.26551], [22.73028, 68.40881], [22.00429, 68.50692], [21.03001, 68.88969], [20.90649, 68.89696], [20.85104, 68.93142], [20.91658, 68.96764], [20.78802, 69.03087], [20.55258, 69.06069], [20.0695, 69.04469], [20.28444, 68.93283], [20.33435, 68.80174], [20.22027, 68.67246], [19.95647, 68.55546], [20.22027, 68.48759], [19.93508, 68.35911], [18.97255, 68.52416], [18.63032, 68.50849], [18.39503, 68.58672], [18.1241, 68.53721], [18.13836, 68.20874], [17.90787, 67.96537], [17.30416, 68.11591], [16.7409, 67.91037], [16.38441, 67.52923], [16.12774, 67.52106], [16.09922, 67.4364], [16.39154, 67.21653], [16.35589, 67.06419], [15.37197, 66.48217], [15.49318, 66.28509], [15.05113, 66.15572], [14.53778, 66.12399], [14.50926, 65.31786], [13.64276, 64.58402], [14.11117, 64.46674], [14.16051, 64.18725], [13.98222, 64.00953], [13.23411, 64.09087], [12.74105, 64.02171], [12.14928, 63.59373], [12.19919, 63.47935], [11.98529, 63.27487], [12.19919, 63.00104], [12.07085, 62.6297], [12.29187, 62.25699], [12.14746, 61.7147], [12.40595, 61.57226], [12.57707, 61.56547], [12.86939, 61.35427], [12.69115, 61.06584], [12.2277, 61.02442], [12.59133, 60.50559], [12.52003, 60.13846], [12.36317, 59.99259], [12.15641, 59.8926], [11.87121, 59.86039], [11.92112, 59.69531], [11.69297, 59.59442], [11.8213, 59.24985], [11.65732, 58.90177], [11.45199, 58.89604], [11.4601, 58.99022], [11.34459, 59.11672], [11.15367, 59.07862], [11.08911, 58.98745], [10.64958, 58.89391], [10.40861, 58.38489], [12.16597, 56.60205], [12.07466, 56.29488], [12.65312, 56.04345], [12.6372, 55.91371], [12.88472, 55.63369], [12.60345, 55.42675], [12.84405, 55.13257], [14.28399, 55.1553], [14.89259, 55.5623], [15.79951, 55.54655], [19.64795, 57.06466], [19.84909, 57.57876], [20.5104, 59.15546], [19.08191, 60.19152], [19.23413, 60.61414], [20.15877, 63.06556], [24.14112, 65.39731], [24.15107, 65.81427], [24.14798, 65.83466], [24.15791, 65.85385]]]]
26713 nameEn: "Singapore",
26714 groups: ["035", "142", "UN"],
26716 callingCodes: ["65"]
26719 type: "MultiPolygon",
26720 coordinates: [[[[104.00131, 1.42405], [103.93384, 1.42926], [103.89565, 1.42841], [103.86383, 1.46288], [103.81181, 1.47953], [103.76395, 1.45183], [103.74161, 1.4502], [103.7219, 1.46108], [103.67468, 1.43166], [103.62738, 1.35255], [103.56591, 1.19719], [103.66049, 1.18825], [103.74084, 1.12902], [104.03085, 1.26954], [104.12282, 1.27714], [104.08072, 1.35998], [104.09162, 1.39694], [104.08871, 1.42015], [104.07348, 1.43322], [104.04622, 1.44691], [104.02277, 1.4438], [104.00131, 1.42405]]]]
26728 wikidata: "Q192184",
26729 nameEn: "Saint Helena, Ascension and Tristan da Cunha",
26740 nameEn: "Slovenia",
26741 groups: ["EU", "039", "150", "UN"],
26742 callingCodes: ["386"]
26745 type: "MultiPolygon",
26746 coordinates: [[[[16.50139, 46.56684], [16.39217, 46.63673], [16.38594, 46.6549], [16.41863, 46.66238], [16.42641, 46.69228], [16.37816, 46.69975], [16.30966, 46.7787], [16.31303, 46.79838], [16.3408, 46.80641], [16.34547, 46.83836], [16.2941, 46.87137], [16.2365, 46.87775], [16.21892, 46.86961], [16.15711, 46.85434], [16.14365, 46.8547], [16.10983, 46.867], [16.05786, 46.83927], [15.99054, 46.82772], [15.99126, 46.78199], [15.98432, 46.74991], [15.99769, 46.7266], [16.02808, 46.71094], [16.04347, 46.68694], [16.04036, 46.6549], [15.99988, 46.67947], [15.98512, 46.68463], [15.94864, 46.68769], [15.87691, 46.7211], [15.8162, 46.71897], [15.78518, 46.70712], [15.76771, 46.69863], [15.73823, 46.70011], [15.72279, 46.69548], [15.69523, 46.69823], [15.67411, 46.70735], [15.6543, 46.70616], [15.6543, 46.69228], [15.6365, 46.6894], [15.63255, 46.68069], [15.62317, 46.67947], [15.59826, 46.68908], [15.54533, 46.66985], [15.55333, 46.64988], [15.54431, 46.6312], [15.46906, 46.61321], [15.45514, 46.63697], [15.41235, 46.65556], [15.23711, 46.63994], [15.14215, 46.66131], [15.01451, 46.641], [14.98024, 46.6009], [14.96002, 46.63459], [14.92283, 46.60848], [14.87129, 46.61], [14.86419, 46.59411], [14.83549, 46.56614], [14.81836, 46.51046], [14.72185, 46.49974], [14.66892, 46.44936], [14.5942, 46.43434], [14.56463, 46.37208], [14.52176, 46.42617], [14.45877, 46.41717], [14.42608, 46.44614], [14.314, 46.43327], [14.28326, 46.44315], [14.15989, 46.43327], [14.12097, 46.47724], [14.04002, 46.49117], [14.00422, 46.48474], [13.89837, 46.52331], [13.7148, 46.5222], [13.68684, 46.43881], [13.59777, 46.44137], [13.5763, 46.42613], [13.5763, 46.40915], [13.47019, 46.3621], [13.43418, 46.35992], [13.44808, 46.33507], [13.37671, 46.29668], [13.42218, 46.20758], [13.47587, 46.22725], [13.56114, 46.2054], [13.56682, 46.18703], [13.64451, 46.18966], [13.66472, 46.17392], [13.64053, 46.13587], [13.57072, 46.09022], [13.50104, 46.05986], [13.49568, 46.04839], [13.50998, 46.04498], [13.49702, 46.01832], [13.47474, 46.00546], [13.50104, 45.98078], [13.52963, 45.96588], [13.56759, 45.96991], [13.58903, 45.99009], [13.62074, 45.98388], [13.63458, 45.98947], [13.64307, 45.98326], [13.6329, 45.94894], [13.63815, 45.93607], [13.61931, 45.91782], [13.60857, 45.89907], [13.59565, 45.89446], [13.58644, 45.88173], [13.57563, 45.8425], [13.58858, 45.83503], [13.59784, 45.8072], [13.66986, 45.79955], [13.8235, 45.7176], [13.83332, 45.70855], [13.83422, 45.68703], [13.87933, 45.65207], [13.9191, 45.6322], [13.8695, 45.60835], [13.86771, 45.59898], [13.84106, 45.58185], [13.78445, 45.5825], [13.74587, 45.59811], [13.7198, 45.59352], [13.6076, 45.64761], [13.45644, 45.59464], [13.56979, 45.4895], [13.62902, 45.45898], [13.67398, 45.4436], [13.7785, 45.46787], [13.81742, 45.43729], [13.88124, 45.42637], [13.90771, 45.45149], [13.97309, 45.45258], [13.99488, 45.47551], [13.96063, 45.50825], [14.00578, 45.52352], [14.07116, 45.48752], [14.20348, 45.46896], [14.22371, 45.50388], [14.24239, 45.50607], [14.26611, 45.48239], [14.27681, 45.4902], [14.32487, 45.47142], [14.36693, 45.48642], [14.49769, 45.54424], [14.5008, 45.60852], [14.53816, 45.6205], [14.57397, 45.67165], [14.60977, 45.66403], [14.59576, 45.62812], [14.69694, 45.57366], [14.68605, 45.53006], [14.71718, 45.53442], [14.80124, 45.49515], [14.81992, 45.45913], [14.90554, 45.47769], [14.92266, 45.52788], [15.02385, 45.48533], [15.05187, 45.49079], [15.16862, 45.42309], [15.27758, 45.46678], [15.33051, 45.45258], [15.38188, 45.48752], [15.30249, 45.53224], [15.29837, 45.5841], [15.27747, 45.60504], [15.31027, 45.6303], [15.34695, 45.63382], [15.34214, 45.64702], [15.38952, 45.63682], [15.4057, 45.64727], [15.34919, 45.71623], [15.30872, 45.69014], [15.25423, 45.72275], [15.40836, 45.79491], [15.47531, 45.79802], [15.47325, 45.8253], [15.52234, 45.82195], [15.57952, 45.84953], [15.64185, 45.82915], [15.66662, 45.84085], [15.70411, 45.8465], [15.68232, 45.86819], [15.68383, 45.88867], [15.67967, 45.90455], [15.70636, 45.92116], [15.70327, 46.00015], [15.71246, 46.01196], [15.72977, 46.04682], [15.62317, 46.09103], [15.6083, 46.11992], [15.59909, 46.14761], [15.64904, 46.19229], [15.6434, 46.21396], [15.67395, 46.22478], [15.75436, 46.21969], [15.75479, 46.20336], [15.78817, 46.21719], [15.79284, 46.25811], [15.97965, 46.30652], [16.07616, 46.3463], [16.07314, 46.36458], [16.05065, 46.3833], [16.05281, 46.39141], [16.14859, 46.40547], [16.18824, 46.38282], [16.30233, 46.37837], [16.30162, 46.40437], [16.27329, 46.41467], [16.27398, 46.42875], [16.25124, 46.48067], [16.23961, 46.49653], [16.26759, 46.50566], [16.26733, 46.51505], [16.29793, 46.5121], [16.37193, 46.55008], [16.38771, 46.53608], [16.44036, 46.5171], [16.5007, 46.49644], [16.52604, 46.47831], [16.59527, 46.47524], [16.52604, 46.5051], [16.52885, 46.53303], [16.50139, 46.56684]]]]
26754 wikidata: "Q842829",
26755 nameEn: "Svalbard and Jan Mayen",
26766 nameEn: "Slovakia",
26767 groups: ["EU", "151", "150", "UN"],
26768 callingCodes: ["421"]
26771 type: "MultiPolygon",
26772 coordinates: [[[[19.82237, 49.27806], [19.78581, 49.41701], [19.72127, 49.39288], [19.6375, 49.40897], [19.64162, 49.45184], [19.57845, 49.46077], [19.53313, 49.52856], [19.52626, 49.57311], [19.45348, 49.61583], [19.37795, 49.574], [19.36009, 49.53747], [19.25435, 49.53391], [19.18019, 49.41165], [18.9742, 49.39557], [18.97283, 49.49914], [18.94536, 49.52143], [18.84521, 49.51672], [18.74761, 49.492], [18.67757, 49.50895], [18.6144, 49.49824], [18.57183, 49.51162], [18.53063, 49.49022], [18.54848, 49.47059], [18.44686, 49.39467], [18.4084, 49.40003], [18.4139, 49.36517], [18.36446, 49.3267], [18.18456, 49.28909], [18.15022, 49.24518], [18.1104, 49.08624], [18.06885, 49.03157], [17.91814, 49.01784], [17.87831, 48.92679], [17.77944, 48.92318], [17.73126, 48.87885], [17.7094, 48.86721], [17.5295, 48.81117], [17.45671, 48.85004], [17.3853, 48.80936], [17.29054, 48.85546], [17.19355, 48.87602], [17.11202, 48.82925], [17.00215, 48.70887], [16.93955, 48.60371], [16.94611, 48.53614], [16.85204, 48.44968], [16.8497, 48.38321], [16.83588, 48.3844], [16.83317, 48.38138], [16.84243, 48.35258], [16.90903, 48.32519], [16.89461, 48.31332], [16.97701, 48.17385], [17.02919, 48.13996], [17.05735, 48.14179], [17.09168, 48.09366], [17.07039, 48.0317], [17.16001, 48.00636], [17.23699, 48.02094], [17.71215, 47.7548], [18.02938, 47.75665], [18.29305, 47.73541], [18.56496, 47.76588], [18.66521, 47.76772], [18.74074, 47.8157], [18.8506, 47.82308], [18.76821, 47.87469], [18.76134, 47.97499], [18.82176, 48.04206], [19.01952, 48.07052], [19.23924, 48.0595], [19.28182, 48.08336], [19.47957, 48.09437], [19.52489, 48.19791], [19.63338, 48.25006], [19.92452, 48.1283], [20.24312, 48.2784], [20.29943, 48.26104], [20.5215, 48.53336], [20.83248, 48.5824], [21.11516, 48.49546], [21.44063, 48.58456], [21.6068, 48.50365], [21.67134, 48.3989], [21.72525, 48.34628], [21.8279, 48.33321], [21.83339, 48.36242], [22.14689, 48.4005], [22.16023, 48.56548], [22.21379, 48.6218], [22.34151, 48.68893], [22.42934, 48.92857], [22.48296, 48.99172], [22.54338, 49.01424], [22.56155, 49.08865], [22.04427, 49.22136], [21.96385, 49.3437], [21.82927, 49.39467], [21.77983, 49.35443], [21.62328, 49.4447], [21.43376, 49.41433], [21.27858, 49.45988], [21.19756, 49.4054], [21.12477, 49.43666], [21.041, 49.41791], [21.09799, 49.37176], [20.98733, 49.30774], [20.9229, 49.29626], [20.77971, 49.35383], [20.72274, 49.41813], [20.61666, 49.41791], [20.5631, 49.375], [20.46422, 49.41612], [20.39939, 49.3896], [20.31728, 49.39914], [20.31453, 49.34817], [20.21977, 49.35265], [20.13738, 49.31685], [20.08238, 49.1813], [19.98494, 49.22904], [19.90529, 49.23532], [19.86409, 49.19316], [19.75286, 49.20751], [19.82237, 49.27806]]]]
26781 nameEn: "Sierra Leone",
26782 groups: ["011", "202", "002", "UN"],
26783 callingCodes: ["232"]
26786 type: "MultiPolygon",
26787 coordinates: [[[[-10.27575, 8.48711], [-10.37257, 8.48941], [-10.54891, 8.31174], [-10.63934, 8.35326], [-10.70565, 8.29235], [-10.61422, 8.5314], [-10.47707, 8.67669], [-10.56197, 8.81225], [-10.5783, 9.06386], [-10.74484, 9.07998], [-10.6534, 9.29919], [-11.2118, 10.00098], [-11.89624, 9.99763], [-11.91023, 9.93927], [-12.12634, 9.87203], [-12.24262, 9.92386], [-12.47254, 9.86834], [-12.76788, 9.3133], [-12.94095, 9.26335], [-13.08953, 9.0409], [-13.18586, 9.0925], [-13.29911, 9.04245], [-14.36218, 8.64107], [-12.15048, 6.15992], [-11.50429, 6.92704], [-11.4027, 6.97746], [-11.29417, 7.21576], [-10.60422, 7.7739], [-10.60492, 8.04072], [-10.57523, 8.04829], [-10.51554, 8.1393], [-10.45023, 8.15627], [-10.35227, 8.15223], [-10.29839, 8.21283], [-10.31635, 8.28554], [-10.30084, 8.30008], [-10.27575, 8.48711]]]]
26796 nameEn: "San Marino",
26797 groups: ["039", "150", "UN"],
26798 callingCodes: ["378"]
26801 type: "MultiPolygon",
26802 coordinates: [[[[12.45648, 43.89369], [12.48771, 43.89706], [12.49429, 43.90973], [12.49247, 43.91774], [12.49724, 43.92248], [12.50269, 43.92363], [12.50496, 43.93017], [12.51553, 43.94096], [12.51427, 43.94897], [12.50655, 43.95796], [12.50875, 43.96198], [12.50622, 43.97131], [12.51109, 43.97201], [12.51064, 43.98165], [12.5154, 43.98508], [12.51463, 43.99122], [12.50678, 43.99113], [12.49406, 43.98492], [12.47853, 43.98052], [12.46205, 43.97463], [12.44684, 43.96597], [12.43662, 43.95698], [12.42005, 43.9578], [12.41414, 43.95273], [12.40415, 43.95485], [12.40506, 43.94325], [12.41165, 43.93769], [12.41551, 43.92984], [12.40733, 43.92379], [12.41233, 43.90956], [12.40935, 43.9024], [12.41641, 43.89991], [12.44184, 43.90498], [12.45648, 43.89369]]]]
26812 groups: ["011", "202", "002", "UN"],
26813 callingCodes: ["221"]
26816 type: "MultiPolygon",
26817 coordinates: [[[[-14.32144, 16.61495], [-15.00557, 16.64997], [-15.6509, 16.50315], [-16.27016, 16.51565], [-16.4429, 16.20605], [-16.44814, 16.09753], [-16.48967, 16.0496], [-16.50854, 16.09032], [-17.15288, 16.07139], [-18.35085, 14.63444], [-17.43598, 13.59273], [-15.47902, 13.58758], [-15.36504, 13.79313], [-14.93719, 13.80173], [-14.34721, 13.46578], [-13.8955, 13.59126], [-13.79409, 13.34472], [-14.36795, 13.23033], [-15.14917, 13.57989], [-15.26908, 13.37768], [-15.80478, 13.34832], [-15.80355, 13.16729], [-16.69343, 13.16791], [-16.74676, 13.06025], [-17.43966, 13.04579], [-17.4623, 11.92379], [-16.70562, 12.34803], [-16.38191, 12.36449], [-16.20591, 12.46157], [-15.67302, 12.42974], [-15.17582, 12.6847], [-13.70523, 12.68013], [-13.05296, 12.64003], [-13.06603, 12.49342], [-12.87336, 12.51892], [-12.35415, 12.32758], [-11.91331, 12.42008], [-11.46267, 12.44559], [-11.37536, 12.40788], [-11.39935, 12.97808], [-11.63025, 13.39174], [-11.83345, 13.33333], [-12.06897, 13.71049], [-11.93043, 13.84505], [-12.23936, 14.76324], [-13.11029, 15.52116], [-13.43135, 16.09022], [-13.80075, 16.13961], [-14.32144, 16.61495]]]]
26827 groups: ["014", "202", "002", "UN"],
26828 callingCodes: ["252"]
26831 type: "MultiPolygon",
26832 coordinates: [[[[51.12877, 12.56479], [43.90659, 12.3823], [42.95776, 10.98533], [42.69452, 10.62672], [42.87643, 10.18441], [43.0937, 9.90579], [43.23518, 9.84605], [43.32613, 9.59205], [44.19222, 8.93028], [46.99339, 7.9989], [47.92477, 8.00111], [47.97917, 8.00124], [44.98104, 4.91821], [44.02436, 4.9451], [43.40263, 4.79289], [43.04177, 4.57923], [42.97746, 4.44032], [42.84526, 4.28357], [42.55853, 4.20518], [42.07619, 4.17667], [41.89488, 3.97375], [41.31368, 3.14314], [40.98767, 2.82959], [41.00099, -0.83068], [41.56, -1.59812], [41.56362, -1.66375], [41.75542, -1.85308], [57.49095, 8.14549], [51.12877, 12.56479]]]]
26841 nameEn: "Suriname",
26842 groups: ["005", "419", "019", "UN"],
26844 callingCodes: ["597"]
26847 type: "MultiPolygon",
26848 coordinates: [[[[-54.26916, 5.26909], [-54.01877, 5.52789], [-54.01074, 5.68785], [-53.7094, 6.2264], [-56.84822, 6.73257], [-57.31629, 5.33714], [-57.22536, 5.15605], [-57.37442, 5.0208], [-57.8699, 4.89394], [-58.0307, 3.95513], [-57.35891, 3.32121], [-56.70519, 2.02964], [-56.55439, 2.02003], [-56.47045, 1.95135], [-55.99278, 1.83137], [-55.89863, 1.89861], [-55.92159, 2.05236], [-56.13054, 2.27723], [-55.96292, 2.53188], [-55.71493, 2.40342], [-55.01919, 2.564], [-54.6084, 2.32856], [-54.42864, 2.42442], [-54.28534, 2.67798], [-53.9849, 3.58697], [-53.98914, 3.627], [-54.05128, 3.63557], [-54.19367, 3.84387], [-54.38444, 4.13222], [-54.4717, 4.91964], [-54.26916, 5.26909]]]]
26857 nameEn: "South Sudan",
26858 groups: ["014", "202", "002", "UN"],
26859 callingCodes: ["211"]
26862 type: "MultiPolygon",
26863 coordinates: [[[[34.10229, 9.50238], [33.87958, 9.49937], [33.9082, 9.762], [33.96323, 9.80972], [33.99185, 9.99623], [33.96984, 10.15446], [33.90159, 10.17179], [33.80913, 10.32994], [33.66604, 10.44254], [33.52294, 10.64382], [33.24645, 10.77913], [33.26977, 10.83632], [33.13988, 11.43248], [33.25876, 12.22111], [32.73921, 12.22757], [32.73921, 11.95203], [32.10079, 11.95203], [32.39578, 11.70208], [32.39358, 11.18207], [32.46967, 11.04662], [31.99177, 10.65065], [31.77539, 10.28939], [31.28504, 9.75287], [30.84605, 9.7498], [30.82893, 9.71451], [30.53005, 9.95992], [30.00389, 10.28633], [29.94629, 10.29245], [29.54, 10.07949], [29.53844, 9.75133], [29.06988, 9.74826], [28.99983, 9.67155], [27.90704, 9.61323], [27.14427, 9.62858], [26.70685, 9.48735], [26.35815, 9.57946], [26.21338, 9.91545], [25.93241, 10.17941], [25.93163, 10.38159], [25.78141, 10.42599], [25.0918, 10.33718], [25.05688, 10.06776], [24.97739, 9.9081], [24.84653, 9.80643], [24.49389, 9.79962], [24.12744, 9.73784], [24.09319, 9.66572], [23.69155, 9.67566], [23.62179, 9.53823], [23.64981, 9.44303], [23.64358, 9.28637], [23.56263, 9.19418], [23.4848, 9.16959], [23.44744, 8.99128], [23.59065, 8.99743], [23.51905, 8.71749], [24.25691, 8.69288], [24.13238, 8.36959], [24.35965, 8.26177], [24.85156, 8.16933], [24.98855, 7.96588], [25.25319, 7.8487], [25.29214, 7.66675], [25.20649, 7.61115], [25.20337, 7.50312], [25.35281, 7.42595], [25.37461, 7.33024], [25.90076, 7.09549], [26.38022, 6.63493], [26.32729, 6.36272], [26.58259, 6.1987], [26.51721, 6.09655], [27.22705, 5.71254], [27.22705, 5.62889], [27.28621, 5.56382], [27.23017, 5.37167], [27.26886, 5.25876], [27.44012, 5.07349], [27.56656, 4.89375], [27.65462, 4.89375], [27.76469, 4.79284], [27.79551, 4.59976], [28.20719, 4.35614], [28.6651, 4.42638], [28.8126, 4.48784], [29.03054, 4.48784], [29.22207, 4.34297], [29.43341, 4.50101], [29.49726, 4.7007], [29.82087, 4.56246], [29.79666, 4.37809], [30.06964, 4.13221], [30.1621, 4.10586], [30.22374, 3.93896], [30.27658, 3.95653], [30.47691, 3.83353], [30.55396, 3.84451], [30.57378, 3.74567], [30.56277, 3.62703], [30.78512, 3.67097], [30.80713, 3.60506], [30.85997, 3.5743], [30.85153, 3.48867], [30.97601, 3.693], [31.16666, 3.79853], [31.29476, 3.8015], [31.50478, 3.67814], [31.50776, 3.63652], [31.72075, 3.74354], [31.81459, 3.82083], [31.86821, 3.78664], [31.96205, 3.6499], [31.95907, 3.57408], [32.05187, 3.589], [32.08491, 3.56287], [32.08866, 3.53543], [32.19888, 3.50867], [32.20782, 3.6053], [32.41337, 3.748], [32.72021, 3.77327], [32.89746, 3.81339], [33.02852, 3.89296], [33.18356, 3.77812], [33.51264, 3.75068], [33.9873, 4.23316], [34.47601, 4.72162], [35.34151, 5.02364], [35.30992, 4.90402], [35.47843, 4.91872], [35.42366, 4.76969], [35.51424, 4.61643], [35.9419, 4.61933], [35.82118, 4.77382], [35.81968, 5.10757], [35.8576, 5.33413], [35.50792, 5.42431], [35.29938, 5.34042], [35.31188, 5.50106], [35.13058, 5.62118], [35.12611, 5.68937], [35.00546, 5.89387], [34.96227, 6.26415], [35.01738, 6.46991], [34.87736, 6.60161], [34.77459, 6.5957], [34.65096, 6.72589], [34.53776, 6.74808], [34.53925, 6.82794], [34.47669, 6.91076], [34.35753, 6.91963], [34.19369, 7.04382], [34.19369, 7.12807], [34.01495, 7.25664], [34.03878, 7.27437], [34.02984, 7.36449], [33.87642, 7.5491], [33.71407, 7.65983], [33.44745, 7.7543], [33.32531, 7.71297], [33.24637, 7.77939], [33.04944, 7.78989], [33.0006, 7.90333], [33.08401, 8.05822], [33.18083, 8.13047], [33.1853, 8.29264], [33.19721, 8.40317], [33.3119, 8.45474], [33.54575, 8.47094], [33.66938, 8.44442], [33.71407, 8.3678], [33.87195, 8.41938], [33.89579, 8.4842], [34.01346, 8.50041], [34.14453, 8.60204], [34.14304, 9.04654], [34.10229, 9.50238]]]]
26872 nameEn: "S\xE3o Tom\xE9 and Principe",
26873 groups: ["017", "202", "002", "UN"],
26874 callingCodes: ["239"]
26877 type: "MultiPolygon",
26878 coordinates: [[[[4.34149, 1.91417], [6.6507, -0.28606], [7.9035, 1.92304], [4.34149, 1.91417]]]]
26887 nameEn: "El Salvador",
26888 groups: ["013", "003", "419", "019", "UN"],
26889 callingCodes: ["503"]
26892 type: "MultiPolygon",
26893 coordinates: [[[[-89.34776, 14.43013], [-89.39028, 14.44561], [-89.57441, 14.41637], [-89.58814, 14.33165], [-89.50614, 14.26084], [-89.52397, 14.22628], [-89.61844, 14.21937], [-89.70756, 14.1537], [-89.75569, 14.07073], [-89.73251, 14.04133], [-89.76103, 14.02923], [-89.81807, 14.07073], [-89.88937, 14.0396], [-90.10505, 13.85104], [-90.11344, 13.73679], [-90.55276, 12.8866], [-88.11443, 12.63306], [-87.7346, 13.13228], [-87.55124, 13.12523], [-87.69751, 13.25228], [-87.73714, 13.32715], [-87.80177, 13.35689], [-87.84675, 13.41078], [-87.83467, 13.44655], [-87.77354, 13.45767], [-87.73841, 13.44169], [-87.72115, 13.46083], [-87.71657, 13.50577], [-87.78148, 13.52906], [-87.73106, 13.75443], [-87.68821, 13.80829], [-87.7966, 13.91353], [-88.00331, 13.86948], [-88.07641, 13.98447], [-88.23018, 13.99915], [-88.25791, 13.91108], [-88.48982, 13.86458], [-88.49738, 13.97224], [-88.70661, 14.04317], [-88.73182, 14.10919], [-88.815, 14.11652], [-88.85785, 14.17763], [-88.94608, 14.20207], [-89.04187, 14.33644], [-89.34776, 14.43013]]]]
26901 wikidata: "Q26273",
26902 nameEn: "Sint Maarten",
26903 aliases: ["NL-SX"],
26905 groups: ["Q1451600", "029", "003", "419", "019", "UN"],
26906 callingCodes: ["1 721"]
26909 type: "MultiPolygon",
26910 coordinates: [[[[-63.33064, 17.9615], [-63.1055, 17.86651], [-62.93924, 18.02904], [-63.02323, 18.05757], [-63.04039, 18.05619], [-63.0579, 18.06614], [-63.07759, 18.04943], [-63.09686, 18.04608], [-63.11042, 18.05339], [-63.13502, 18.05445], [-63.33064, 17.9615]]]]
26920 groups: ["145", "142", "UN"],
26921 callingCodes: ["963"]
26924 type: "MultiPolygon",
26925 coordinates: [[[[42.23683, 37.2863], [42.21548, 37.28026], [42.20454, 37.28715], [42.22381, 37.30238], [42.22257, 37.31395], [42.2112, 37.32491], [42.19301, 37.31323], [42.18225, 37.28569], [42.00894, 37.17209], [41.515, 37.08084], [41.21937, 37.07665], [40.90856, 37.13147], [40.69136, 37.0996], [39.81589, 36.75538], [39.21538, 36.66834], [39.03217, 36.70911], [38.74042, 36.70629], [38.55908, 36.84429], [38.38859, 36.90064], [38.21064, 36.91842], [37.81974, 36.76055], [37.68048, 36.75065], [37.49103, 36.66904], [37.47253, 36.63243], [37.21988, 36.6736], [37.16177, 36.66069], [37.10894, 36.6704], [37.08279, 36.63495], [37.02088, 36.66422], [37.01647, 36.69512], [37.04619, 36.71101], [37.04399, 36.73483], [36.99886, 36.74012], [36.99557, 36.75997], [36.66727, 36.82901], [36.61581, 36.74629], [36.62681, 36.71189], [36.57398, 36.65186], [36.58829, 36.58295], [36.54206, 36.49539], [36.6081, 36.33772], [36.65653, 36.33861], [36.68672, 36.23677], [36.6125, 36.22592], [36.50463, 36.2419], [36.4617, 36.20461], [36.39206, 36.22088], [36.37474, 36.01163], [36.33956, 35.98687], [36.30099, 36.00985], [36.28338, 36.00273], [36.29769, 35.96086], [36.27678, 35.94839], [36.25366, 35.96264], [36.19973, 35.95195], [36.17441, 35.92076], [36.1623, 35.80925], [36.14029, 35.81015], [36.13919, 35.83692], [36.11827, 35.85923], [35.99829, 35.88242], [36.01844, 35.92403], [36.00514, 35.94113], [35.98499, 35.94107], [35.931, 35.92109], [35.51152, 36.10954], [35.48515, 34.70851], [35.97386, 34.63322], [35.98718, 34.64977], [36.29165, 34.62991], [36.32399, 34.69334], [36.35135, 34.68516], [36.35384, 34.65447], [36.42941, 34.62505], [36.46003, 34.6378], [36.45299, 34.59438], [36.41429, 34.61175], [36.39846, 34.55672], [36.3369, 34.52629], [36.34745, 34.5002], [36.4442, 34.50165], [36.46179, 34.46541], [36.55853, 34.41609], [36.53039, 34.3798], [36.56556, 34.31881], [36.60778, 34.31009], [36.58667, 34.27667], [36.59195, 34.2316], [36.62537, 34.20251], [36.5128, 34.09916], [36.50576, 34.05982], [36.41078, 34.05253], [36.28589, 33.91981], [36.38263, 33.86579], [36.3967, 33.83365], [36.14517, 33.85118], [36.06778, 33.82927], [35.9341, 33.6596], [36.05723, 33.57904], [35.94465, 33.52774], [35.94816, 33.47886], [35.88668, 33.43183], [35.82577, 33.40479], [35.81324, 33.36354], [35.77477, 33.33609], [35.813, 33.3172], [35.77513, 33.27342], [35.81295, 33.24841], [35.81647, 33.2028], [35.83846, 33.19397], [35.84285, 33.16673], [35.81911, 33.1336], [35.81911, 33.11077], [35.84802, 33.1031], [35.87188, 32.98028], [35.89298, 32.9456], [35.87012, 32.91976], [35.84021, 32.8725], [35.83758, 32.82817], [35.78745, 32.77938], [35.75983, 32.74803], [35.88405, 32.71321], [35.93307, 32.71966], [35.96633, 32.66237], [36.02239, 32.65911], [36.08074, 32.51463], [36.20379, 32.52751], [36.20875, 32.49529], [36.23948, 32.50108], [36.40959, 32.37908], [36.83946, 32.31293], [38.79171, 33.37328], [40.64314, 34.31604], [40.97676, 34.39788], [41.12388, 34.65742], [41.2345, 34.80049], [41.21654, 35.1508], [41.26569, 35.42708], [41.38184, 35.62502], [41.37027, 35.84095], [41.2564, 36.06012], [41.28864, 36.35368], [41.40058, 36.52502], [41.81736, 36.58782], [42.36697, 37.0627], [42.35724, 37.10998], [42.32313, 37.17814], [42.34735, 37.22548], [42.2824, 37.2798], [42.26039, 37.27017], [42.23683, 37.2863]]]]
26934 nameEn: "Eswatini",
26935 aliases: ["Swaziland"],
26936 groups: ["018", "202", "002", "UN"],
26938 callingCodes: ["268"]
26941 type: "MultiPolygon",
26942 coordinates: [[[[31.86881, -25.99973], [31.4175, -25.71886], [31.31237, -25.7431], [31.13073, -25.91558], [30.95819, -26.26303], [30.78927, -26.48271], [30.81101, -26.84722], [30.88826, -26.79622], [30.97757, -26.92706], [30.96088, -27.0245], [31.15027, -27.20151], [31.49834, -27.31549], [31.97592, -27.31675], [31.97463, -27.11057], [32.00893, -26.8096], [32.09664, -26.80721], [32.13315, -26.84345], [32.13409, -26.5317], [32.07352, -26.40185], [32.10435, -26.15656], [32.08599, -26.00978], [32.00916, -25.999], [31.974, -25.95387], [31.86881, -25.99973]]]]
26949 wikidata: "Q220982",
26950 nameEn: "Tristan da Cunha",
26951 aliases: ["SH-TA"],
26953 groups: ["SH", "BOTS", "011", "202", "002", "UN"],
26954 isoStatus: "excRes",
26956 roadSpeedUnit: "mph",
26957 roadHeightUnit: "ft",
26958 callingCodes: ["290 8", "44 20"]
26961 type: "MultiPolygon",
26962 coordinates: [[[[-13.38232, -34.07258], [-16.67337, -41.9188], [-5.88482, -41.4829], [-13.38232, -34.07258]]]]
26970 wikidata: "Q18221",
26971 nameEn: "Turks and Caicos Islands",
26973 groups: ["BOTS", "029", "003", "419", "019", "UN"],
26975 roadSpeedUnit: "mph",
26976 roadHeightUnit: "ft",
26977 callingCodes: ["1 649"]
26980 type: "MultiPolygon",
26981 coordinates: [[[[-71.70065, 25.7637], [-72.98446, 20.4801], [-69.80718, 21.35956], [-71.70065, 25.7637]]]]
26991 groups: ["017", "202", "002", "UN"],
26992 callingCodes: ["235"]
26995 type: "MultiPolygon",
26996 coordinates: [[[[23.99539, 19.49944], [15.99566, 23.49639], [14.99751, 23.00539], [15.19692, 21.99339], [15.20213, 21.49365], [15.28332, 21.44557], [15.62515, 20.95395], [15.57248, 20.92138], [15.55382, 20.86507], [15.56004, 20.79488], [15.59841, 20.74039], [15.6721, 20.70069], [15.99632, 20.35364], [15.75098, 19.93002], [15.6032, 18.77402], [15.50373, 16.89649], [14.37425, 15.72591], [13.86301, 15.04043], [13.78991, 14.87519], [13.809, 14.72915], [13.67878, 14.64013], [13.68573, 14.55276], [13.48259, 14.46704], [13.47559, 14.40881], [13.6302, 13.71094], [14.08251, 13.0797], [14.46881, 13.08259], [14.56101, 12.91036], [14.55058, 12.78256], [14.83314, 12.62963], [14.90827, 12.3269], [14.89019, 12.16593], [14.96952, 12.0925], [15.00146, 12.1223], [15.0349, 12.10698], [15.05786, 12.0608], [15.04808, 11.8731], [15.11579, 11.79313], [15.06595, 11.71126], [15.13149, 11.5537], [15.0585, 11.40481], [15.10021, 11.04101], [15.04957, 11.02347], [15.09127, 10.87431], [15.06737, 10.80921], [15.15532, 10.62846], [15.14936, 10.53915], [15.23724, 10.47764], [15.30874, 10.31063], [15.50535, 10.1098], [15.68761, 9.99344], [15.41408, 9.92876], [15.24618, 9.99246], [15.14043, 9.99246], [15.05999, 9.94845], [14.95722, 9.97926], [14.80082, 9.93818], [14.4673, 10.00264], [14.20411, 10.00055], [14.1317, 9.82413], [14.01793, 9.73169], [13.97544, 9.6365], [14.37094, 9.2954], [14.35707, 9.19611], [14.83566, 8.80557], [15.09484, 8.65982], [15.20426, 8.50892], [15.50743, 7.79302], [15.59272, 7.7696], [15.56964, 7.58936], [15.49743, 7.52179], [15.73118, 7.52006], [15.79942, 7.44149], [16.40703, 7.68809], [16.41583, 7.77971], [16.58315, 7.88657], [16.59415, 7.76444], [16.658, 7.75353], [16.6668, 7.67281], [16.8143, 7.53971], [17.67288, 7.98905], [17.93926, 7.95853], [18.02731, 8.01085], [18.6085, 8.05009], [18.64153, 8.08714], [18.62612, 8.14163], [18.67455, 8.22226], [18.79783, 8.25929], [19.11044, 8.68172], [18.86388, 8.87971], [19.06421, 9.00367], [20.36748, 9.11019], [20.82979, 9.44696], [21.26348, 9.97642], [21.34934, 9.95907], [21.52766, 10.2105], [21.63553, 10.217], [21.71479, 10.29932], [21.72139, 10.64136], [22.45889, 11.00246], [22.87758, 10.91915], [22.97249, 11.21955], [22.93124, 11.41645], [22.7997, 11.40424], [22.54907, 11.64372], [22.64092, 12.07485], [22.48369, 12.02766], [22.50548, 12.16769], [22.38873, 12.45514], [22.46345, 12.61925], [22.22684, 12.74682], [22.15679, 12.66634], [21.98711, 12.63292], [21.89371, 12.68001], [21.81432, 12.81362], [21.94819, 13.05637], [22.02914, 13.13976], [22.1599, 13.19281], [22.29689, 13.3731], [22.08674, 13.77863], [22.22995, 13.96754], [22.5553, 14.11704], [22.55997, 14.23024], [22.44944, 14.24986], [22.38562, 14.58907], [22.70474, 14.69149], [22.66115, 14.86308], [22.99584, 15.22989], [22.99584, 15.40105], [22.92579, 15.47007], [22.93201, 15.55107], [23.10792, 15.71297], [23.38812, 15.69649], [23.62785, 15.7804], [23.99997, 15.69575], [23.99539, 19.49944]]]]
27004 wikidata: "Q129003",
27005 nameEn: "French Southern Territories",
27017 groups: ["011", "202", "002", "UN"],
27018 callingCodes: ["228"]
27021 type: "MultiPolygon",
27022 coordinates: [[[[0.50388, 11.01011], [-0.13493, 11.14075], [-0.14462, 11.10811], [-0.05733, 11.08628], [-0.0275, 11.11202], [-514e-5, 11.10763], [342e-5, 11.08317], [0.02395, 11.06229], [0.03355, 10.9807], [-63e-4, 10.96417], [-908e-5, 10.91644], [-0.02685, 10.8783], [-0.0228, 10.81916], [-0.07183, 10.76794], [-0.07327, 10.71845], [-0.09141, 10.7147], [-0.05945, 10.63458], [0.12886, 10.53149], [0.18846, 10.4096], [0.29453, 10.41546], [0.33028, 10.30408], [0.39584, 10.31112], [0.35293, 10.09412], [0.41371, 10.06361], [0.41252, 10.02018], [0.36366, 10.03309], [0.32075, 9.72781], [0.34816, 9.71607], [0.34816, 9.66907], [0.32313, 9.6491], [0.28261, 9.69022], [0.26712, 9.66437], [0.29334, 9.59387], [0.36008, 9.6256], [0.38153, 9.58682], [0.23851, 9.57389], [0.2409, 9.52335], [0.30406, 9.521], [0.31241, 9.50337], [0.2254, 9.47869], [0.25758, 9.42696], [0.33148, 9.44812], [0.36485, 9.49749], [0.49118, 9.48339], [0.56388, 9.40697], [0.45424, 9.04581], [0.52455, 8.87746], [0.37319, 8.75262], [0.47211, 8.59945], [0.64731, 8.48866], [0.73432, 8.29529], [0.63897, 8.25873], [0.5913, 8.19622], [0.61156, 8.18324], [0.6056, 8.13959], [0.58891, 8.12779], [0.62943, 7.85751], [0.58295, 7.62368], [0.51979, 7.58706], [0.52455, 7.45354], [0.57223, 7.39326], [0.62943, 7.41099], [0.65327, 7.31643], [0.59606, 7.01252], [0.52217, 6.9723], [0.52098, 6.94391], [0.56508, 6.92971], [0.52853, 6.82921], [0.57406, 6.80348], [0.58176, 6.76049], [0.6497, 6.73682], [0.63659, 6.63857], [0.74862, 6.56517], [0.71048, 6.53083], [0.89283, 6.33779], [0.99652, 6.33779], [1.03108, 6.24064], [1.05969, 6.22998], [1.09187, 6.17074], [1.19966, 6.17069], [1.19771, 6.11522], [1.27574, 5.93551], [1.67336, 6.02702], [1.62913, 6.24075], [1.79826, 6.28221], [1.76906, 6.43189], [1.58105, 6.68619], [1.61812, 6.74843], [1.55877, 6.99737], [1.64249, 6.99562], [1.61838, 9.0527], [1.5649, 9.16941], [1.41746, 9.3226], [1.33675, 9.54765], [1.36624, 9.5951], [1.35507, 9.99525], [0.77666, 10.37665], [0.80358, 10.71459], [0.8804, 10.803], [0.91245, 10.99597], [0.66104, 10.99964], [0.4958, 10.93269], [0.50521, 10.98035], [0.48852, 10.98561], [0.50388, 11.01011]]]]
27031 nameEn: "Thailand",
27032 groups: ["035", "142", "UN"],
27034 callingCodes: ["66"]
27037 type: "MultiPolygon",
27038 coordinates: [[[[100.08404, 20.36626], [99.95721, 20.46301], [99.91616, 20.44986], [99.90499, 20.4487], [99.89692, 20.44789], [99.89301, 20.44311], [99.89168, 20.44548], [99.88451, 20.44596], [99.88211, 20.44488], [99.86383, 20.44371], [99.81096, 20.33687], [99.68255, 20.32077], [99.46008, 20.39673], [99.46077, 20.36198], [99.5569, 20.20676], [99.52943, 20.14811], [99.416, 20.08614], [99.20328, 20.12877], [99.0735, 20.10298], [98.98679, 19.7419], [98.83661, 19.80931], [98.56065, 19.67807], [98.51182, 19.71303], [98.24884, 19.67876], [98.13829, 19.78541], [98.03314, 19.80941], [98.04364, 19.65755], [97.84715, 19.55782], [97.88423, 19.5041], [97.78769, 19.39429], [97.84186, 19.29526], [97.78606, 19.26769], [97.84024, 19.22217], [97.83479, 19.09972], [97.73797, 19.04261], [97.73654, 18.9812], [97.66487, 18.9371], [97.73836, 18.88478], [97.76752, 18.58097], [97.5258, 18.4939], [97.36444, 18.57138], [97.34522, 18.54596], [97.50383, 18.26844], [97.56219, 18.33885], [97.64116, 18.29778], [97.60841, 18.23846], [97.73723, 17.97912], [97.66794, 17.88005], [97.76407, 17.71595], [97.91829, 17.54504], [98.11185, 17.36829], [98.10439, 17.33847], [98.34566, 17.04822], [98.39441, 17.06266], [98.52624, 16.89979], [98.49603, 16.8446], [98.53833, 16.81934], [98.46994, 16.73613], [98.50253, 16.7139], [98.49713, 16.69022], [98.51043, 16.70107], [98.51579, 16.69433], [98.51472, 16.68521], [98.51833, 16.676], [98.51113, 16.64503], [98.5695, 16.62826], [98.57912, 16.55983], [98.63817, 16.47424], [98.68074, 16.27068], [98.84485, 16.42354], [98.92656, 16.36425], [98.8376, 16.11706], [98.69585, 16.13353], [98.57019, 16.04578], [98.59853, 15.87197], [98.541, 15.65406], [98.58598, 15.46821], [98.56027, 15.33471], [98.4866, 15.39154], [98.39351, 15.34177], [98.41906, 15.27103], [98.40522, 15.25268], [98.30446, 15.30667], [98.22, 15.21327], [98.18821, 15.13125], [98.24874, 14.83013], [98.56762, 14.37701], [98.97356, 14.04868], [99.16695, 13.72621], [99.20617, 13.20575], [99.12225, 13.19847], [99.10646, 13.05804], [99.18748, 12.9898], [99.18905, 12.84799], [99.29254, 12.68921], [99.409, 12.60603], [99.47519, 12.1353], [99.56445, 12.14805], [99.53424, 12.02317], [99.64891, 11.82699], [99.64108, 11.78948], [99.5672, 11.62732], [99.47598, 11.62434], [99.39485, 11.3925], [99.31573, 11.32081], [99.32756, 11.28545], [99.06938, 10.94857], [99.02337, 10.97217], [98.99701, 10.92962], [99.0069, 10.85485], [98.86819, 10.78336], [98.78511, 10.68351], [98.77275, 10.62548], [98.81944, 10.52761], [98.7391, 10.31488], [98.55174, 9.92804], [98.52291, 9.92389], [98.47298, 9.95782], [98.33094, 9.91973], [98.12555, 9.44056], [97.63455, 9.60854], [97.19814, 8.18901], [99.31854, 5.99868], [99.50117, 6.44501], [99.91873, 6.50233], [100.0756, 6.4045], [100.12, 6.42105], [100.19511, 6.72559], [100.29651, 6.68439], [100.30828, 6.66462], [100.31618, 6.66781], [100.31884, 6.66423], [100.32671, 6.66526], [100.32607, 6.65933], [100.31929, 6.65413], [100.35413, 6.54932], [100.41152, 6.52299], [100.41791, 6.5189], [100.42351, 6.51762], [100.43027, 6.52389], [100.66986, 6.45086], [100.74361, 6.50811], [100.74822, 6.46231], [100.81045, 6.45086], [100.85884, 6.24929], [101.10313, 6.25617], [101.12618, 6.19431], [101.06165, 6.14161], [101.12388, 6.11411], [101.087, 5.9193], [101.02708, 5.91013], [100.98815, 5.79464], [101.14062, 5.61613], [101.25755, 5.71065], [101.25524, 5.78633], [101.58019, 5.93534], [101.69773, 5.75881], [101.75074, 5.79091], [101.80144, 5.74505], [101.89188, 5.8386], [101.91776, 5.84269], [101.92819, 5.85511], [101.94712, 5.98421], [101.9714, 6.00575], [101.97114, 6.01992], [101.99209, 6.04075], [102.01835, 6.05407], [102.09182, 6.14161], [102.07732, 6.193], [102.08127, 6.22679], [102.09086, 6.23546], [102.46318, 7.22462], [102.47649, 9.66162], [102.52395, 11.25257], [102.91449, 11.65512], [102.90973, 11.75613], [102.83957, 11.8519], [102.78427, 11.98746], [102.77026, 12.06815], [102.70176, 12.1686], [102.73134, 12.37091], [102.78116, 12.40284], [102.7796, 12.43781], [102.57567, 12.65358], [102.51963, 12.66117], [102.4994, 12.71736], [102.53053, 12.77506], [102.49335, 12.92711], [102.48694, 12.97537], [102.52275, 12.99813], [102.46011, 13.08057], [102.43422, 13.09061], [102.36146, 13.26006], [102.36001, 13.31142], [102.34611, 13.35618], [102.35692, 13.38274], [102.35563, 13.47307], [102.361, 13.50551], [102.33828, 13.55613], [102.36859, 13.57488], [102.44601, 13.5637], [102.5358, 13.56933], [102.57573, 13.60461], [102.62483, 13.60883], [102.58635, 13.6286], [102.5481, 13.6589], [102.56848, 13.69366], [102.72727, 13.77806], [102.77864, 13.93374], [102.91251, 14.01531], [102.93275, 14.19044], [103.16469, 14.33075], [103.39353, 14.35639], [103.53518, 14.42575], [103.71109, 14.4348], [103.70175, 14.38052], [103.93836, 14.3398], [104.27616, 14.39861], [104.55014, 14.36091], [104.69335, 14.42726], [104.97667, 14.38806], [105.02804, 14.23722], [105.08408, 14.20402], [105.14012, 14.23873], [105.17748, 14.34432], [105.20894, 14.34967], [105.43783, 14.43865], [105.53864, 14.55731], [105.5121, 14.80802], [105.61162, 15.00037], [105.46661, 15.13132], [105.58043, 15.32724], [105.50662, 15.32054], [105.4692, 15.33709], [105.47635, 15.3796], [105.58191, 15.41031], [105.60446, 15.53301], [105.61756, 15.68792], [105.46573, 15.74742], [105.42285, 15.76971], [105.37959, 15.84074], [105.34115, 15.92737], [105.38508, 15.987], [105.42001, 16.00657], [105.06204, 16.09792], [105.00262, 16.25627], [104.88057, 16.37311], [104.73349, 16.565], [104.76099, 16.69302], [104.7397, 16.81005], [104.76442, 16.84752], [104.7373, 16.91125], [104.73712, 17.01404], [104.80716, 17.19025], [104.80061, 17.39367], [104.69867, 17.53038], [104.45404, 17.66788], [104.35432, 17.82871], [104.2757, 17.86139], [104.21776, 17.99335], [104.10927, 18.10826], [104.06533, 18.21656], [103.97725, 18.33631], [103.93916, 18.33914], [103.85642, 18.28666], [103.82449, 18.33979], [103.699, 18.34125], [103.60957, 18.40528], [103.47773, 18.42841], [103.41044, 18.4486], [103.30977, 18.4341], [103.24779, 18.37807], [103.23818, 18.34875], [103.29757, 18.30475], [103.17093, 18.2618], [103.14994, 18.23172], [103.1493, 18.17799], [103.07343, 18.12351], [103.07823, 18.03833], [103.0566, 18.00144], [103.01998, 17.97095], [102.9912, 17.9949], [102.95812, 18.0054], [102.86323, 17.97531], [102.81988, 17.94233], [102.79044, 17.93612], [102.75954, 17.89561], [102.68538, 17.86653], [102.67543, 17.84529], [102.69946, 17.81686], [102.68194, 17.80151], [102.59485, 17.83537], [102.5896, 17.84889], [102.61432, 17.92273], [102.60971, 17.95411], [102.59234, 17.96127], [102.45523, 17.97106], [102.11359, 18.21532], [101.88485, 18.02474], [101.78087, 18.07559], [101.72294, 17.92867], [101.44667, 17.7392], [101.15108, 17.47586], [100.96541, 17.57926], [101.02185, 17.87637], [101.1793, 18.0544], [101.19118, 18.2125], [101.15108, 18.25624], [101.18227, 18.34367], [101.06047, 18.43247], [101.27585, 18.68875], [101.22832, 18.73377], [101.25803, 18.89545], [101.35606, 19.04716], [101.261, 19.12717], [101.24911, 19.33334], [101.20604, 19.35296], [101.21347, 19.46223], [101.26991, 19.48324], [101.26545, 19.59242], [101.08928, 19.59748], [100.90302, 19.61901], [100.77231, 19.48324], [100.64606, 19.55884], [100.58219, 19.49164], [100.49604, 19.53504], [100.398, 19.75047], [100.5094, 19.87904], [100.58808, 20.15791], [100.55218, 20.17741], [100.51052, 20.14928], [100.47567, 20.19133], [100.4537, 20.19971], [100.44992, 20.23644], [100.41473, 20.25625], [100.37439, 20.35156], [100.33383, 20.4028], [100.25769, 20.3992], [100.22076, 20.31598], [100.16668, 20.2986], [100.1712, 20.24324], [100.11785, 20.24787], [100.09337, 20.26293], [100.09999, 20.31614], [100.08404, 20.36626]]]]
27047 nameEn: "Tajikistan",
27048 groups: ["143", "142", "UN"],
27049 callingCodes: ["992"]
27052 type: "MultiPolygon",
27053 coordinates: [[[[70.45251, 41.04438], [70.38028, 41.02014], [70.36655, 40.90296], [69.69434, 40.62615], [69.59441, 40.70181], [69.53021, 40.77621], [69.38327, 40.7918], [69.32834, 40.70233], [69.3455, 40.57988], [69.2643, 40.57506], [69.21063, 40.54469], [69.27066, 40.49274], [69.28525, 40.41894], [69.30774, 40.36102], [69.33794, 40.34819], [69.32833, 40.29794], [69.30808, 40.2821], [69.24817, 40.30357], [69.25229, 40.26362], [69.30104, 40.24502], [69.30448, 40.18774], [69.2074, 40.21488], [69.15659, 40.2162], [69.04544, 40.22904], [68.85832, 40.20885], [68.84357, 40.18604], [68.79276, 40.17555], [68.77902, 40.20492], [68.5332, 40.14826], [68.52771, 40.11676], [68.62796, 40.07789], [69.01523, 40.15771], [69.01935, 40.11466], [68.96579, 40.06949], [68.84906, 40.04952], [68.93695, 39.91167], [68.88889, 39.87163], [68.63071, 39.85265], [68.61972, 39.68905], [68.54166, 39.53929], [68.12053, 39.56317], [67.70992, 39.66156], [67.62889, 39.60234], [67.44899, 39.57799], [67.46547, 39.53564], [67.39681, 39.52505], [67.46822, 39.46146], [67.45998, 39.315], [67.36522, 39.31287], [67.33226, 39.23739], [67.67833, 39.14479], [67.68915, 39.00775], [68.09704, 39.02589], [68.19743, 38.85985], [68.06948, 38.82115], [68.12877, 38.73677], [68.05598, 38.71641], [68.0807, 38.64136], [68.05873, 38.56087], [68.11366, 38.47169], [68.06274, 38.39435], [68.13289, 38.40822], [68.40343, 38.19484], [68.27159, 37.91477], [68.12635, 37.93], [67.81566, 37.43107], [67.8474, 37.31594], [67.78329, 37.1834], [67.7803, 37.08978], [67.87917, 37.0591], [68.02194, 36.91923], [68.18542, 37.02074], [68.27605, 37.00977], [68.29253, 37.10621], [68.41201, 37.10402], [68.41888, 37.13906], [68.61851, 37.19815], [68.6798, 37.27906], [68.81438, 37.23862], [68.80889, 37.32494], [68.91189, 37.26704], [68.88168, 37.33368], [68.96407, 37.32603], [69.03274, 37.25174], [69.25152, 37.09426], [69.39529, 37.16752], [69.45022, 37.23315], [69.36645, 37.40462], [69.44954, 37.4869], [69.51888, 37.5844], [69.80041, 37.5746], [69.84435, 37.60616], [69.93362, 37.61378], [69.95971, 37.5659], [70.15015, 37.52519], [70.28243, 37.66706], [70.27694, 37.81258], [70.1863, 37.84296], [70.17206, 37.93276], [70.4898, 38.12546], [70.54673, 38.24541], [70.60407, 38.28046], [70.61526, 38.34774], [70.64966, 38.34999], [70.69189, 38.37031], [70.6761, 38.39144], [70.67438, 38.40597], [70.69807, 38.41861], [70.72485, 38.4131], [70.75455, 38.4252], [70.77132, 38.45548], [70.78581, 38.45502], [70.78702, 38.45031], [70.79766, 38.44944], [70.80521, 38.44447], [70.81697, 38.44507], [70.82538, 38.45394], [70.84376, 38.44688], [70.88719, 38.46826], [70.92728, 38.43021], [70.98693, 38.48862], [71.03545, 38.44779], [71.0556, 38.40176], [71.09542, 38.42517], [71.10592, 38.42077], [71.10957, 38.40671], [71.1451, 38.40106], [71.21291, 38.32797], [71.33114, 38.30339], [71.33869, 38.27335], [71.37803, 38.25641], [71.36444, 38.15358], [71.29878, 38.04429], [71.28922, 38.01272], [71.27622, 37.99946], [71.27278, 37.96496], [71.24969, 37.93031], [71.2809, 37.91995], [71.296, 37.93403], [71.32871, 37.88564], [71.51565, 37.95349], [71.58843, 37.92425], [71.59255, 37.79956], [71.55752, 37.78677], [71.54324, 37.77104], [71.53053, 37.76534], [71.55234, 37.73209], [71.54186, 37.69691], [71.51972, 37.61945], [71.5065, 37.60912], [71.49693, 37.53527], [71.50616, 37.50733], [71.5256, 37.47971], [71.49612, 37.4279], [71.47685, 37.40281], [71.4862, 37.33405], [71.49821, 37.31975], [71.50674, 37.31502], [71.48536, 37.26017], [71.4824, 37.24921], [71.48339, 37.23937], [71.47386, 37.2269], [71.4555, 37.21418], [71.4494, 37.18137], [71.44127, 37.11856], [71.43097, 37.05855], [71.45578, 37.03094], [71.46923, 36.99925], [71.48481, 36.93218], [71.51502, 36.89128], [71.57195, 36.74943], [71.67083, 36.67346], [71.83229, 36.68084], [72.31676, 36.98115], [72.54095, 37.00007], [72.66381, 37.02014], [72.79693, 37.22222], [73.06884, 37.31729], [73.29633, 37.46495], [73.77197, 37.4417], [73.76647, 37.33913], [73.61129, 37.27469], [73.64974, 37.23643], [73.82552, 37.22659], [73.8564, 37.26158], [74.20308, 37.34208], [74.23339, 37.41116], [74.41055, 37.3948], [74.56161, 37.37734], [74.68383, 37.3948], [74.8294, 37.3435], [74.88887, 37.23275], [75.12328, 37.31839], [75.09719, 37.37297], [75.15899, 37.41443], [75.06011, 37.52779], [74.94338, 37.55501], [74.8912, 37.67576], [75.00935, 37.77486], [74.92416, 37.83428], [74.9063, 38.03033], [74.82665, 38.07359], [74.80331, 38.19889], [74.69894, 38.22155], [74.69619, 38.42947], [74.51217, 38.47034], [74.17022, 38.65504], [73.97933, 38.52945], [73.79806, 38.61106], [73.80656, 38.66449], [73.7033, 38.84782], [73.7445, 38.93867], [73.82964, 38.91517], [73.81728, 39.04007], [73.75823, 39.023], [73.60638, 39.24534], [73.54572, 39.27567], [73.55396, 39.3543], [73.5004, 39.38402], [73.59241, 39.40843], [73.59831, 39.46425], [73.45096, 39.46677], [73.31912, 39.38615], [73.18454, 39.35536], [72.85934, 39.35116], [72.62027, 39.39696], [72.33173, 39.33093], [72.23834, 39.17248], [72.17242, 39.2661], [72.09689, 39.26823], [72.04059, 39.36704], [71.90601, 39.27674], [71.79202, 39.27355], [71.7522, 39.32031], [71.80164, 39.40631], [71.76816, 39.45456], [71.62688, 39.44056], [71.5517, 39.45722], [71.55856, 39.57588], [71.49814, 39.61397], [71.08752, 39.50704], [71.06418, 39.41586], [70.7854, 39.38933], [70.64087, 39.58792], [70.44757, 39.60128], [70.2869, 39.53141], [70.11111, 39.58223], [69.87491, 39.53882], [69.68677, 39.59281], [69.3594, 39.52516], [69.26938, 39.8127], [69.35649, 40.01994], [69.43134, 39.98431], [69.43557, 39.92877], [69.53615, 39.93991], [69.5057, 40.03277], [69.53855, 40.0887], [69.53794, 40.11833], [69.55555, 40.12296], [69.57615, 40.10524], [69.64704, 40.12165], [69.67001, 40.10639], [70.01283, 40.23288], [70.58297, 40.00891], [70.57384, 39.99394], [70.47557, 39.93216], [70.55033, 39.96619], [70.58912, 39.95211], [70.65946, 39.9878], [70.65827, 40.0981], [70.7928, 40.12797], [70.80495, 40.16813], [70.9818, 40.22392], [70.8607, 40.217], [70.62342, 40.17396], [70.56394, 40.26421], [70.57149, 40.3442], [70.37511, 40.38605], [70.32626, 40.45174], [70.49871, 40.52503], [70.80009, 40.72825], [70.45251, 41.04438]]], [[[70.68112, 40.90612], [70.6158, 40.97661], [70.56077, 41.00642], [70.54223, 40.98787], [70.57501, 40.98941], [70.6721, 40.90555], [70.68112, 40.90612]]], [[[70.74189, 39.86319], [70.53651, 39.89155], [70.52631, 39.86989], [70.54998, 39.85137], [70.59667, 39.83542], [70.63105, 39.77923], [70.74189, 39.86319]]]]
27061 wikidata: "Q36823",
27064 groups: ["061", "009", "UN"],
27066 callingCodes: ["690"]
27069 type: "MultiPolygon",
27070 coordinates: [[[[-168.251, -9.44289], [-174.18635, -7.80441], [-174.17993, -10.13616], [-168.251, -9.44289]]]]
27079 nameEn: "East Timor",
27080 aliases: ["Timor-Leste", "TP"],
27081 groups: ["035", "142", "UN"],
27083 callingCodes: ["670"]
27086 type: "MultiPolygon",
27087 coordinates: [[[[124.46701, -9.13002], [124.94011, -8.85617], [124.97742, -9.08128], [125.11764, -8.96359], [125.18632, -9.03142], [125.18907, -9.16434], [125.09434, -9.19669], [125.04044, -9.17093], [124.97892, -9.19281], [125.09025, -9.46406], [125.68138, -9.85176], [127.55165, -9.05052], [127.42116, -8.22471], [125.87691, -8.31789], [125.58506, -7.95311], [124.92337, -8.75859], [124.33472, -9.11416], [124.04628, -9.22671], [124.04286, -9.34243], [124.10539, -9.41206], [124.14517, -9.42324], [124.21247, -9.36904], [124.28115, -9.42189], [124.28115, -9.50453], [124.3535, -9.48493], [124.35258, -9.43002], [124.38554, -9.3582], [124.45971, -9.30263], [124.46701, -9.13002]]]]
27096 nameEn: "Turkmenistan",
27097 groups: ["143", "142", "UN"],
27098 callingCodes: ["993"]
27101 type: "MultiPolygon",
27102 coordinates: [[[[60.5078, 41.21694], [60.06581, 41.4363], [60.18117, 41.60082], [60.06032, 41.76287], [60.08504, 41.80997], [60.33223, 41.75058], [59.95046, 41.97966], [60.0356, 42.01028], [60.04659, 42.08982], [59.96419, 42.1428], [60.00539, 42.212], [59.94633, 42.27655], [59.4341, 42.29738], [59.2955, 42.37064], [59.17317, 42.52248], [58.93422, 42.5407], [58.6266, 42.79314], [58.57991, 42.64988], [58.27504, 42.69632], [58.14321, 42.62159], [58.29427, 42.56497], [58.51674, 42.30348], [58.40688, 42.29535], [58.3492, 42.43335], [57.99214, 42.50021], [57.90975, 42.4374], [57.92897, 42.24047], [57.84932, 42.18555], [57.6296, 42.16519], [57.30275, 42.14076], [57.03633, 41.92043], [56.96218, 41.80383], [57.03359, 41.41777], [57.13796, 41.36625], [57.03423, 41.25435], [56.00314, 41.32584], [55.45471, 41.25609], [54.95182, 41.92424], [54.20635, 42.38477], [52.97575, 42.1308], [52.47884, 41.78034], [52.26048, 41.69249], [51.7708, 40.29239], [53.89734, 37.3464], [54.24565, 37.32047], [54.36211, 37.34912], [54.58664, 37.45809], [54.67247, 37.43532], [54.77822, 37.51597], [54.81804, 37.61285], [54.77684, 37.62264], [54.851, 37.75739], [55.13412, 37.94705], [55.44152, 38.08564], [55.76561, 38.12238], [55.97847, 38.08024], [56.33278, 38.08132], [56.32454, 38.18502], [56.43303, 38.26054], [56.62255, 38.24005], [56.73928, 38.27887], [57.03453, 38.18717], [57.21169, 38.28965], [57.37236, 38.09321], [57.35042, 37.98546], [57.79534, 37.89299], [58.21399, 37.77281], [58.22999, 37.6856], [58.39959, 37.63134], [58.47786, 37.6433], [58.5479, 37.70526], [58.6921, 37.64548], [58.9338, 37.67374], [59.22905, 37.51161], [59.33507, 37.53146], [59.39797, 37.47892], [59.39385, 37.34257], [59.55178, 37.13594], [59.74678, 37.12499], [60.00768, 37.04102], [60.34767, 36.63214], [61.14516, 36.64644], [61.18187, 36.55348], [61.1393, 36.38782], [61.22719, 36.12759], [61.12007, 35.95992], [61.22444, 35.92879], [61.26152, 35.80749], [61.22719, 35.67038], [61.27371, 35.61482], [61.58742, 35.43803], [61.77693, 35.41341], [61.97743, 35.4604], [62.05709, 35.43803], [62.15871, 35.33278], [62.29191, 35.25964], [62.29878, 35.13312], [62.48006, 35.28796], [62.62288, 35.22067], [62.74098, 35.25432], [62.90853, 35.37086], [63.0898, 35.43131], [63.12276, 35.53196], [63.10079, 35.63024], [63.23262, 35.67487], [63.10318, 35.81782], [63.12276, 35.86208], [63.29579, 35.85985], [63.53475, 35.90881], [63.56496, 35.95106], [63.98519, 36.03773], [64.05385, 36.10433], [64.43288, 36.24401], [64.57295, 36.34362], [64.62514, 36.44311], [64.61141, 36.6351], [64.97945, 37.21913], [65.51778, 37.23881], [65.64263, 37.34388], [65.64137, 37.45061], [65.72274, 37.55438], [66.30993, 37.32409], [66.55743, 37.35409], [66.52303, 37.39827], [66.65761, 37.45497], [66.52852, 37.58568], [66.53676, 37.80084], [66.67684, 37.96776], [66.56697, 38.0435], [66.41042, 38.02403], [66.24013, 38.16238], [65.83913, 38.25733], [65.55873, 38.29052], [64.32576, 38.98691], [64.19086, 38.95561], [63.70778, 39.22349], [63.6913, 39.27666], [62.43337, 39.98528], [62.34273, 40.43206], [62.11751, 40.58242], [61.87856, 41.12257], [61.4446, 41.29407], [61.39732, 41.19873], [61.33199, 41.14946], [61.22212, 41.14946], [61.03261, 41.25691], [60.5078, 41.21694]]]]
27112 groups: ["015", "002", "UN"],
27113 callingCodes: ["216"]
27116 type: "MultiPolygon",
27117 coordinates: [[[[11.2718, 37.6713], [7.89009, 38.19924], [8.59123, 37.14286], [8.64044, 36.9401], [8.62972, 36.86499], [8.67706, 36.8364], [8.57613, 36.78062], [8.46537, 36.7706], [8.47609, 36.66607], [8.16167, 36.48817], [8.18936, 36.44939], [8.40731, 36.42208], [8.2626, 35.91733], [8.26472, 35.73669], [8.35371, 35.66373], [8.36086, 35.47774], [8.30329, 35.29884], [8.47318, 35.23376], [8.3555, 35.10007], [8.30727, 34.95378], [8.25189, 34.92009], [8.29655, 34.72798], [8.20482, 34.57575], [7.86264, 34.3987], [7.81242, 34.21841], [7.74207, 34.16492], [7.66174, 34.20167], [7.52851, 34.06493], [7.54088, 33.7726], [7.73687, 33.42114], [7.83028, 33.18851], [8.11433, 33.10175], [8.1179, 33.05086], [8.31895, 32.83483], [8.35999, 32.50101], [9.07483, 32.07865], [9.55544, 30.23971], [9.76848, 30.34366], [9.88152, 30.34074], [10.29516, 30.90337], [10.12239, 31.42098], [10.31364, 31.72648], [10.48497, 31.72956], [10.62788, 31.96629], [10.7315, 31.97235], [11.04234, 32.2145], [11.53898, 32.4138], [11.57828, 32.48013], [11.46037, 32.6307], [11.51549, 33.09826], [11.55852, 33.1409], [11.58941, 33.36891], [11.2718, 37.6713]]]]
27127 groups: ["061", "009", "UN"],
27129 callingCodes: ["676"]
27132 type: "MultiPolygon",
27133 coordinates: [[[[-176.74538, -22.89767], [-180, -22.90585], [-180, -24.21376], [-173.10761, -24.19665], [-173.13438, -14.94228], [-176.76826, -14.95183], [-176.74538, -22.89767]]]]
27143 groups: ["145", "142", "UN"],
27144 callingCodes: ["90"]
27147 type: "MultiPolygon",
27148 coordinates: [[[[41.54366, 41.52185], [40.89217, 41.72528], [34.8305, 42.4581], [28.32297, 41.98371], [28.02971, 41.98066], [27.91479, 41.97902], [27.83492, 41.99709], [27.81235, 41.94803], [27.69949, 41.97515], [27.55191, 41.90928], [27.52379, 41.93756], [27.45478, 41.96591], [27.27411, 42.10409], [27.22376, 42.10152], [27.19251, 42.06028], [27.08486, 42.08735], [27.03277, 42.0809], [26.95638, 42.00741], [26.79143, 41.97386], [26.62996, 41.97644], [26.56051, 41.92995], [26.57961, 41.90024], [26.53968, 41.82653], [26.36952, 41.82265], [26.33589, 41.76802], [26.32952, 41.73637], [26.35957, 41.71149], [26.47958, 41.67037], [26.5209, 41.62592], [26.59196, 41.60491], [26.59742, 41.48058], [26.61767, 41.42281], [26.62997, 41.34613], [26.5837, 41.32131], [26.5209, 41.33993], [26.39861, 41.25053], [26.32259, 41.24929], [26.31928, 41.07386], [26.3606, 41.02027], [26.33297, 40.98388], [26.35894, 40.94292], [26.32259, 40.94042], [26.28623, 40.93005], [26.29441, 40.89119], [26.26169, 40.9168], [26.20856, 40.86048], [26.21351, 40.83298], [26.15685, 40.80709], [26.12854, 40.77339], [26.12495, 40.74283], [26.08638, 40.73214], [26.0754, 40.72772], [26.03489, 40.73051], [25.94795, 40.72797], [26.04292, 40.3958], [25.61285, 40.17161], [25.94257, 39.39358], [26.43357, 39.43096], [26.70773, 39.0312], [26.61814, 38.81372], [26.21136, 38.65436], [26.32173, 38.48731], [26.24183, 38.44695], [26.21136, 38.17558], [27.05537, 37.9131], [27.16428, 37.72343], [26.99377, 37.69034], [26.95583, 37.64989], [27.14757, 37.32], [27.20312, 36.94571], [27.45627, 36.9008], [27.24613, 36.71622], [27.46117, 36.53789], [27.89482, 36.69898], [27.95037, 36.46155], [28.23708, 36.56812], [29.30783, 36.01033], [29.48192, 36.18377], [29.61002, 36.1731], [29.61805, 36.14179], [29.69611, 36.10365], [29.73302, 35.92555], [32.82353, 35.70297], [35.51152, 36.10954], [35.931, 35.92109], [35.98499, 35.94107], [36.00514, 35.94113], [36.01844, 35.92403], [35.99829, 35.88242], [36.11827, 35.85923], [36.13919, 35.83692], [36.14029, 35.81015], [36.1623, 35.80925], [36.17441, 35.92076], [36.19973, 35.95195], [36.25366, 35.96264], [36.27678, 35.94839], [36.29769, 35.96086], [36.28338, 36.00273], [36.30099, 36.00985], [36.33956, 35.98687], [36.37474, 36.01163], [36.39206, 36.22088], [36.4617, 36.20461], [36.50463, 36.2419], [36.6125, 36.22592], [36.68672, 36.23677], [36.65653, 36.33861], [36.6081, 36.33772], [36.54206, 36.49539], [36.58829, 36.58295], [36.57398, 36.65186], [36.62681, 36.71189], [36.61581, 36.74629], [36.66727, 36.82901], [36.99557, 36.75997], [36.99886, 36.74012], [37.04399, 36.73483], [37.04619, 36.71101], [37.01647, 36.69512], [37.02088, 36.66422], [37.08279, 36.63495], [37.10894, 36.6704], [37.16177, 36.66069], [37.21988, 36.6736], [37.47253, 36.63243], [37.49103, 36.66904], [37.68048, 36.75065], [37.81974, 36.76055], [38.21064, 36.91842], [38.38859, 36.90064], [38.55908, 36.84429], [38.74042, 36.70629], [39.03217, 36.70911], [39.21538, 36.66834], [39.81589, 36.75538], [40.69136, 37.0996], [40.90856, 37.13147], [41.21937, 37.07665], [41.515, 37.08084], [42.00894, 37.17209], [42.18225, 37.28569], [42.19301, 37.31323], [42.2112, 37.32491], [42.22257, 37.31395], [42.22381, 37.30238], [42.20454, 37.28715], [42.21548, 37.28026], [42.23683, 37.2863], [42.26039, 37.27017], [42.2824, 37.2798], [42.34735, 37.22548], [42.32313, 37.17814], [42.35724, 37.10998], [42.56725, 37.14878], [42.78887, 37.38615], [42.93705, 37.32015], [43.11403, 37.37436], [43.30083, 37.30629], [43.33508, 37.33105], [43.50787, 37.24436], [43.56702, 37.25675], [43.63085, 37.21957], [43.7009, 37.23692], [43.8052, 37.22825], [43.82699, 37.19477], [43.84878, 37.22205], [43.90949, 37.22453], [44.02002, 37.33229], [44.13521, 37.32486], [44.2613, 37.25055], [44.27998, 37.16501], [44.22239, 37.15756], [44.18503, 37.09551], [44.25975, 36.98119], [44.30645, 36.97373], [44.35937, 37.02843], [44.35315, 37.04955], [44.38117, 37.05825], [44.42631, 37.05825], [44.63179, 37.19229], [44.76698, 37.16162], [44.78319, 37.1431], [44.7868, 37.16644], [44.75986, 37.21549], [44.81021, 37.2915], [44.58449, 37.45018], [44.61401, 37.60165], [44.56887, 37.6429], [44.62096, 37.71985], [44.55498, 37.783], [44.45948, 37.77065], [44.3883, 37.85433], [44.22509, 37.88859], [44.42476, 38.25763], [44.50115, 38.33939], [44.44386, 38.38295], [44.38309, 38.36117], [44.3119, 38.37887], [44.3207, 38.49799], [44.32058, 38.62752], [44.28065, 38.6465], [44.26155, 38.71427], [44.30322, 38.81581], [44.18863, 38.93881], [44.20946, 39.13975], [44.1043, 39.19842], [44.03667, 39.39223], [44.22452, 39.4169], [44.29818, 39.378], [44.37921, 39.4131], [44.42832, 39.4131], [44.41849, 39.56659], [44.48111, 39.61579], [44.47298, 39.68788], [44.6137, 39.78393], [44.65422, 39.72163], [44.71806, 39.71124], [44.81043, 39.62677], [44.80977, 39.65768], [44.75779, 39.7148], [44.61845, 39.8281], [44.46635, 39.97733], [44.26973, 40.04866], [44.1778, 40.02845], [44.1057, 40.03555], [43.92307, 40.01787], [43.65688, 40.11199], [43.65221, 40.14889], [43.71136, 40.16673], [43.59928, 40.34019], [43.60862, 40.43267], [43.54791, 40.47413], [43.63664, 40.54159], [43.7425, 40.66805], [43.74872, 40.7365], [43.67712, 40.84846], [43.67712, 40.93084], [43.58683, 40.98961], [43.47319, 41.02251], [43.44984, 41.0988], [43.4717, 41.12611], [43.44973, 41.17666], [43.36118, 41.2028], [43.23096, 41.17536], [43.1945, 41.25242], [43.13373, 41.25503], [43.21707, 41.30331], [43.02956, 41.37891], [42.8785, 41.50516], [42.84899, 41.47265], [42.78995, 41.50126], [42.84471, 41.58912], [42.72794, 41.59714], [42.59202, 41.58183], [42.51772, 41.43606], [42.26387, 41.49346], [41.95134, 41.52466], [41.81939, 41.43621], [41.7124, 41.47417], [41.7148, 41.4932], [41.54366, 41.52185]]]]
27157 nameEn: "Trinidad and Tobago",
27158 groups: ["029", "003", "419", "019", "UN"],
27160 callingCodes: ["1 868"]
27163 type: "MultiPolygon",
27164 coordinates: [[[[-61.62505, 11.18974], [-62.08693, 10.04435], [-60.89962, 9.81445], [-60.07172, 11.77667], [-61.62505, 11.18974]]]]
27174 groups: ["061", "009", "UN"],
27176 callingCodes: ["688"]
27179 type: "MultiPolygon",
27180 coordinates: [[[[174, -5], [174, -11.5], [179.99999, -11.5], [179.99999, -5], [174, -5]]]]
27191 groups: ["030", "142"],
27192 callingCodes: ["886"]
27195 type: "MultiPolygon",
27196 coordinates: [[[[121.8109, 21.77688], [122.26612, 25.98197], [120.49232, 25.22863], [118.56434, 24.49266], [118.42453, 24.54644], [118.35291, 24.51645], [118.28244, 24.51231], [118.11703, 24.39734], [120.69238, 21.52331], [121.8109, 21.77688]]]]
27205 nameEn: "Tanzania",
27206 groups: ["014", "202", "002", "UN"],
27208 callingCodes: ["255"]
27211 type: "MultiPolygon",
27212 coordinates: [[[[30.80408, -0.99911], [30.76635, -0.9852], [30.70631, -1.01175], [30.64166, -1.06601], [30.47194, -1.0555], [30.45116, -1.10641], [30.50889, -1.16412], [30.57123, -1.33264], [30.71974, -1.43244], [30.84079, -1.64652], [30.80802, -1.91477], [30.89303, -2.08223], [30.83915, -2.35795], [30.54501, -2.41404], [30.41789, -2.66266], [30.52747, -2.65841], [30.40662, -2.86151], [30.4987, -2.9573], [30.57926, -2.89791], [30.6675, -2.98987], [30.83823, -2.97837], [30.84165, -3.25152], [30.45915, -3.56532], [30.22042, -4.01738], [30.03323, -4.26631], [29.88172, -4.35743], [29.82885, -4.36153], [29.77289, -4.41733], [29.75109, -4.45836], [29.63827, -4.44681], [29.43673, -4.44845], [29.52552, -6.2731], [30.2567, -7.14121], [30.79243, -8.27382], [31.00796, -8.58615], [31.37533, -8.60769], [31.57147, -8.70619], [31.57147, -8.81388], [31.71158, -8.91386], [31.81587, -8.88618], [31.94663, -8.93846], [31.94196, -9.02303], [31.98866, -9.07069], [32.08206, -9.04609], [32.16146, -9.05993], [32.25486, -9.13371], [32.43543, -9.11988], [32.49147, -9.14754], [32.53661, -9.24281], [32.75611, -9.28583], [32.76233, -9.31963], [32.95389, -9.40138], [32.99397, -9.36712], [33.14925, -9.49322], [33.31581, -9.48554], [33.48052, -9.62442], [33.76677, -9.58516], [33.93298, -9.71647], [33.9638, -9.62206], [33.95829, -9.54066], [34.03865, -9.49398], [34.54499, -10.0678], [34.51911, -10.12279], [34.57581, -10.56271], [34.65946, -10.6828], [34.67047, -10.93796], [34.61161, -11.01611], [34.63305, -11.11731], [34.79375, -11.32245], [34.91153, -11.39799], [34.96296, -11.57354], [35.63599, -11.55927], [35.82767, -11.41081], [36.19094, -11.57593], [36.19094, -11.70008], [36.62068, -11.72884], [36.80309, -11.56836], [37.3936, -11.68949], [37.76614, -11.53352], [37.8388, -11.3123], [37.93618, -11.26228], [38.21598, -11.27289], [38.47258, -11.4199], [38.88996, -11.16978], [39.24395, -11.17433], [39.58249, -10.96043], [40.00295, -10.80255], [40.44265, -10.4618], [40.74206, -10.25691], [40.14328, -4.64201], [39.62121, -4.68136], [39.44306, -4.93877], [39.21631, -4.67835], [37.81321, -3.69179], [37.75036, -3.54243], [37.63099, -3.50723], [37.5903, -3.42735], [37.71745, -3.304], [37.67199, -3.06222], [34.0824, -1.02264], [34.03084, -1.05101], [34.02286, -1.00779], [33.93107, -0.99298], [30.80408, -0.99911]]]]
27222 groups: ["151", "150", "UN"],
27223 callingCodes: ["380"]
27226 type: "MultiPolygon",
27227 coordinates: [[[[33.57318, 46.10317], [33.61467, 46.13561], [33.63854, 46.14147], [33.61517, 46.22615], [33.646, 46.23028], [33.74047, 46.18555], [33.79715, 46.20482], [33.85234, 46.19863], [33.91549, 46.15938], [34.05272, 46.10838], [34.07311, 46.11769], [34.12929, 46.10494], [34.181, 46.06804], [34.25111, 46.0532], [34.33912, 46.06114], [34.41221, 46.00245], [34.44155, 45.95995], [34.48729, 45.94267], [34.52011, 45.95097], [34.55889, 45.99347], [34.60861, 45.99347], [34.66679, 45.97136], [34.75479, 45.90705], [34.80153, 45.90047], [34.79905, 45.81009], [34.96015, 45.75634], [35.23066, 45.79231], [37.62608, 46.82615], [38.12112, 46.86078], [38.3384, 46.98085], [38.22955, 47.12069], [38.23049, 47.2324], [38.32112, 47.2585], [38.33074, 47.30508], [38.22225, 47.30788], [38.28954, 47.39255], [38.28679, 47.53552], [38.35062, 47.61631], [38.76379, 47.69346], [38.79628, 47.81109], [38.87979, 47.87719], [39.73935, 47.82876], [39.82213, 47.96396], [39.77544, 48.04206], [39.88256, 48.04482], [39.83724, 48.06501], [39.94847, 48.22811], [40.00752, 48.22445], [39.99241, 48.31768], [39.97325, 48.31399], [39.9693, 48.29904], [39.95248, 48.29972], [39.91465, 48.26743], [39.90041, 48.3049], [39.84273, 48.30947], [39.84136, 48.33321], [39.94847, 48.35055], [39.88794, 48.44226], [39.86196, 48.46633], [39.84548, 48.57821], [39.79764, 48.58668], [39.67226, 48.59368], [39.71765, 48.68673], [39.73104, 48.7325], [39.79466, 48.83739], [39.97182, 48.79398], [40.08168, 48.87443], [40.03636, 48.91957], [39.98967, 48.86901], [39.78368, 48.91596], [39.74874, 48.98675], [39.72649, 48.9754], [39.71353, 48.98959], [39.6683, 48.99454], [39.6836, 49.05121], [39.93437, 49.05709], [40.01988, 49.1761], [40.22176, 49.25683], [40.18331, 49.34996], [40.14912, 49.37681], [40.1141, 49.38798], [40.03087, 49.45452], [40.03636, 49.52321], [40.16683, 49.56865], [40.13249, 49.61672], [39.84548, 49.56064], [39.65047, 49.61761], [39.59142, 49.73758], [39.44496, 49.76067], [39.27968, 49.75976], [39.1808, 49.88911], [38.9391, 49.79524], [38.90477, 49.86787], [38.73311, 49.90238], [38.68677, 50.00904], [38.65688, 49.97176], [38.35408, 50.00664], [38.32524, 50.08866], [38.18517, 50.08161], [38.21675, 49.98104], [38.02999, 49.90592], [38.02999, 49.94482], [37.90776, 50.04194], [37.79515, 50.08425], [37.75807, 50.07896], [37.61113, 50.21976], [37.62879, 50.24481], [37.62486, 50.29966], [37.47243, 50.36277], [37.48204, 50.46079], [37.08468, 50.34935], [36.91762, 50.34963], [36.69377, 50.26982], [36.64571, 50.218], [36.56655, 50.2413], [36.58371, 50.28563], [36.47817, 50.31457], [36.30101, 50.29088], [36.20763, 50.3943], [36.06893, 50.45205], [35.8926, 50.43829], [35.80388, 50.41356], [35.73659, 50.35489], [35.61711, 50.35707], [35.58003, 50.45117], [35.47463, 50.49247], [35.39464, 50.64751], [35.48116, 50.66405], [35.47704, 50.77274], [35.41367, 50.80227], [35.39307, 50.92145], [35.32598, 50.94524], [35.40837, 51.04119], [35.31774, 51.08434], [35.20375, 51.04723], [35.12685, 51.16191], [35.14058, 51.23162], [34.97304, 51.2342], [34.82472, 51.17483], [34.6874, 51.18], [34.6613, 51.25053], [34.38802, 51.2746], [34.31661, 51.23936], [34.23009, 51.26429], [34.33446, 51.363], [34.22048, 51.4187], [34.30562, 51.5205], [34.17599, 51.63253], [34.07765, 51.67065], [34.42922, 51.72852], [34.41136, 51.82793], [34.09413, 52.00835], [34.11199, 52.14087], [34.05239, 52.20132], [33.78789, 52.37204], [33.55718, 52.30324], [33.48027, 52.31499], [33.51323, 52.35779], [33.18913, 52.3754], [32.89937, 52.2461], [32.85405, 52.27888], [32.69475, 52.25535], [32.54781, 52.32423], [32.3528, 52.32842], [32.38988, 52.24946], [32.33083, 52.23685], [32.34044, 52.1434], [32.2777, 52.10266], [32.23331, 52.08085], [32.08813, 52.03319], [31.92159, 52.05144], [31.96141, 52.08015], [31.85018, 52.11305], [31.81722, 52.09955], [31.7822, 52.11406], [31.38326, 52.12991], [31.25142, 52.04131], [31.13332, 52.1004], [30.95589, 52.07775], [30.90897, 52.00699], [30.76443, 51.89739], [30.68804, 51.82806], [30.51946, 51.59649], [30.64992, 51.35014], [30.56203, 51.25655], [30.36153, 51.33984], [30.34642, 51.42555], [30.17888, 51.51025], [29.77376, 51.4461], [29.7408, 51.53417], [29.54372, 51.48372], [29.49773, 51.39814], [29.42357, 51.4187], [29.32881, 51.37843], [29.25191, 51.49828], [29.25603, 51.57089], [29.20659, 51.56918], [29.16402, 51.64679], [29.1187, 51.65872], [28.99098, 51.56833], [28.95528, 51.59222], [28.81795, 51.55552], [28.76027, 51.48802], [28.78224, 51.45294], [28.75615, 51.41442], [28.73143, 51.46236], [28.69161, 51.44695], [28.64429, 51.5664], [28.47051, 51.59734], [28.37592, 51.54505], [28.23452, 51.66988], [28.10658, 51.57857], [27.95827, 51.56065], [27.91844, 51.61952], [27.85253, 51.62293], [27.76052, 51.47604], [27.67125, 51.50854], [27.71932, 51.60672], [27.55727, 51.63486], [27.51058, 51.5854], [27.47212, 51.61184], [27.24828, 51.60161], [27.26613, 51.65957], [27.20948, 51.66713], [27.20602, 51.77291], [26.99422, 51.76933], [26.9489, 51.73788], [26.80043, 51.75777], [26.69759, 51.82284], [26.46962, 51.80501], [26.39367, 51.87315], [26.19084, 51.86781], [26.00408, 51.92967], [25.83217, 51.92587], [25.80574, 51.94556], [25.73673, 51.91973], [25.46163, 51.92205], [25.20228, 51.97143], [24.98784, 51.91273], [24.37123, 51.88222], [24.29021, 51.80841], [24.3163, 51.75063], [24.13075, 51.66979], [23.99907, 51.58369], [23.8741, 51.59734], [23.91118, 51.63316], [23.7766, 51.66809], [23.60906, 51.62122], [23.6736, 51.50255], [23.62751, 51.50512], [23.69905, 51.40871], [23.63858, 51.32182], [23.80678, 51.18405], [23.90376, 51.07697], [23.92217, 51.00836], [24.04576, 50.90196], [24.14524, 50.86128], [24.0952, 50.83262], [23.99254, 50.83847], [23.95925, 50.79271], [24.0595, 50.71625], [24.0996, 50.60752], [24.07048, 50.5071], [24.03668, 50.44507], [23.99563, 50.41289], [23.79445, 50.40481], [23.71382, 50.38248], [23.67635, 50.33385], [23.28221, 50.0957], [22.99329, 49.84249], [22.83179, 49.69875], [22.80261, 49.69098], [22.78304, 49.65543], [22.64534, 49.53094], [22.69444, 49.49378], [22.748, 49.32759], [22.72009, 49.20288], [22.86336, 49.10513], [22.89122, 49.00725], [22.56155, 49.08865], [22.54338, 49.01424], [22.48296, 48.99172], [22.42934, 48.92857], [22.34151, 48.68893], [22.21379, 48.6218], [22.16023, 48.56548], [22.14689, 48.4005], [22.2083, 48.42534], [22.38133, 48.23726], [22.49806, 48.25189], [22.59007, 48.15121], [22.58733, 48.10813], [22.66835, 48.09162], [22.73427, 48.12005], [22.81804, 48.11363], [22.87847, 48.04665], [22.84276, 47.98602], [22.89849, 47.95851], [22.94301, 47.96672], [22.92241, 48.02002], [23.0158, 47.99338], [23.08858, 48.00716], [23.1133, 48.08061], [23.15999, 48.12188], [23.27397, 48.08245], [23.33577, 48.0237], [23.4979, 47.96858], [23.52803, 48.01818], [23.5653, 48.00499], [23.63894, 48.00293], [23.66262, 47.98786], [23.75188, 47.99705], [23.80904, 47.98142], [23.8602, 47.9329], [23.89352, 47.94512], [23.94192, 47.94868], [23.96337, 47.96672], [23.98553, 47.96076], [24.00801, 47.968], [24.02999, 47.95087], [24.06466, 47.95317], [24.11281, 47.91487], [24.22566, 47.90231], [24.34926, 47.9244], [24.43578, 47.97131], [24.61994, 47.95062], [24.70632, 47.84428], [24.81893, 47.82031], [24.88896, 47.7234], [25.11144, 47.75203], [25.23778, 47.89403], [25.63878, 47.94924], [25.77723, 47.93919], [26.05901, 47.9897], [26.17711, 47.99246], [26.33504, 48.18418], [26.55202, 48.22445], [26.62823, 48.25804], [26.6839, 48.35828], [26.79239, 48.29071], [26.82809, 48.31629], [26.71274, 48.40388], [26.85556, 48.41095], [26.93384, 48.36558], [27.03821, 48.37653], [27.0231, 48.42485], [27.08078, 48.43214], [27.13434, 48.37288], [27.27855, 48.37534], [27.32159, 48.4434], [27.37604, 48.44398], [27.37741, 48.41026], [27.44333, 48.41209], [27.46942, 48.454], [27.5889, 48.49224], [27.59027, 48.46311], [27.6658, 48.44034], [27.74422, 48.45926], [27.79225, 48.44244], [27.81902, 48.41874], [27.87533, 48.4037], [27.88391, 48.36699], [27.95883, 48.32368], [28.04527, 48.32661], [28.09873, 48.3124], [28.07504, 48.23494], [28.17666, 48.25963], [28.19314, 48.20749], [28.2856, 48.23202], [28.32508, 48.23384], [28.35519, 48.24957], [28.36996, 48.20543], [28.34912, 48.1787], [28.30586, 48.1597], [28.30609, 48.14018], [28.34009, 48.13147], [28.38712, 48.17567], [28.43701, 48.15832], [28.42454, 48.12047], [28.48428, 48.0737], [28.53921, 48.17453], [28.69896, 48.13106], [28.85232, 48.12506], [28.8414, 48.03392], [28.9306, 47.96255], [29.1723, 47.99013], [29.19839, 47.89261], [29.27804, 47.88893], [29.20663, 47.80367], [29.27255, 47.79953], [29.22242, 47.73607], [29.22414, 47.60012], [29.11743, 47.55001], [29.18603, 47.43387], [29.3261, 47.44664], [29.39889, 47.30179], [29.47854, 47.30366], [29.48678, 47.36043], [29.5733, 47.36508], [29.59665, 47.25521], [29.54996, 47.24962], [29.57696, 47.13581], [29.49732, 47.12878], [29.53044, 47.07851], [29.61038, 47.09932], [29.62137, 47.05069], [29.57056, 46.94766], [29.72986, 46.92234], [29.75458, 46.8604], [29.87405, 46.88199], [29.98814, 46.82358], [29.94522, 46.80055], [29.9743, 46.75325], [29.94409, 46.56002], [29.88916, 46.54302], [30.02511, 46.45132], [30.16794, 46.40967], [30.09103, 46.38694], [29.94114, 46.40114], [29.88329, 46.35851], [29.74496, 46.45605], [29.66359, 46.4215], [29.6763, 46.36041], [29.5939, 46.35472], [29.49914, 46.45889], [29.35357, 46.49505], [29.24886, 46.37912], [29.23547, 46.55435], [29.02409, 46.49582], [29.01241, 46.46177], [28.9306, 46.45699], [29.004, 46.31495], [28.98478, 46.31803], [28.94953, 46.25852], [29.06656, 46.19716], [28.94643, 46.09176], [29.00613, 46.04962], [28.98004, 46.00385], [28.74383, 45.96664], [28.78503, 45.83475], [28.69852, 45.81753], [28.70401, 45.78019], [28.52823, 45.73803], [28.47879, 45.66994], [28.51587, 45.6613], [28.54196, 45.58062], [28.49252, 45.56716], [28.51449, 45.49982], [28.43072, 45.48538], [28.41836, 45.51715], [28.30201, 45.54744], [28.21139, 45.46895], [28.28504, 45.43907], [28.34554, 45.32102], [28.5735, 45.24759], [28.71358, 45.22631], [28.78911, 45.24179], [28.81383, 45.3384], [28.94292, 45.28045], [28.96077, 45.33164], [29.24779, 45.43388], [29.42632, 45.44545], [29.59798, 45.38857], [29.68175, 45.26885], [29.65428, 45.25629], [29.69272, 45.19227], [30.04414, 45.08461], [31.62627, 45.50633], [33.54017, 46.0123], [33.59087, 46.06013], [33.57318, 46.10317]]]]
27237 groups: ["014", "202", "002", "UN"],
27239 callingCodes: ["256"]
27242 type: "MultiPolygon",
27243 coordinates: [[[[33.93107, -0.99298], [33.9264, -0.54188], [33.98449, -0.13079], [33.90936, 0.10581], [34.10067, 0.36372], [34.08727, 0.44713], [34.11408, 0.48884], [34.13493, 0.58118], [34.20196, 0.62289], [34.27345, 0.63182], [34.31516, 0.75693], [34.40041, 0.80266], [34.43349, 0.85254], [34.52369, 1.10692], [34.57427, 1.09868], [34.58029, 1.14712], [34.67562, 1.21265], [34.80223, 1.22754], [34.82606, 1.26626], [34.82606, 1.30944], [34.7918, 1.36752], [34.87819, 1.5596], [34.92734, 1.56109], [34.9899, 1.6668], [34.98692, 1.97348], [34.90947, 2.42447], [34.95267, 2.47209], [34.77244, 2.70272], [34.78137, 2.76223], [34.73967, 2.85447], [34.65774, 2.8753], [34.60114, 2.93034], [34.56242, 3.11478], [34.45815, 3.18319], [34.40006, 3.37949], [34.41794, 3.44342], [34.39112, 3.48802], [34.44922, 3.51627], [34.45815, 3.67385], [34.15429, 3.80464], [34.06046, 4.15235], [33.9873, 4.23316], [33.51264, 3.75068], [33.18356, 3.77812], [33.02852, 3.89296], [32.89746, 3.81339], [32.72021, 3.77327], [32.41337, 3.748], [32.20782, 3.6053], [32.19888, 3.50867], [32.08866, 3.53543], [32.08491, 3.56287], [32.05187, 3.589], [31.95907, 3.57408], [31.96205, 3.6499], [31.86821, 3.78664], [31.81459, 3.82083], [31.72075, 3.74354], [31.50776, 3.63652], [31.50478, 3.67814], [31.29476, 3.8015], [31.16666, 3.79853], [30.97601, 3.693], [30.85153, 3.48867], [30.94081, 3.50847], [30.93486, 3.40737], [30.84251, 3.26908], [30.77101, 3.04897], [30.8574, 2.9508], [30.8857, 2.83923], [30.75612, 2.5863], [30.74271, 2.43601], [30.83059, 2.42559], [30.91102, 2.33332], [30.96911, 2.41071], [31.06593, 2.35862], [31.07934, 2.30207], [31.12104, 2.27676], [31.1985, 2.29462], [31.20148, 2.2217], [31.28042, 2.17853], [31.30127, 2.11006], [30.48503, 1.21675], [30.24671, 1.14974], [30.22139, 0.99635], [30.1484, 0.89805], [29.98307, 0.84295], [29.95477, 0.64486], [29.97413, 0.52124], [29.87284, 0.39166], [29.81922, 0.16824], [29.77454, 0.16675], [29.7224, 0.07291], [29.72687, -0.08051], [29.65091, -0.46777], [29.67474, -0.47969], [29.67176, -0.55714], [29.62708, -0.71055], [29.63006, -0.8997], [29.58388, -0.89821], [29.59061, -1.39016], [29.82657, -1.31187], [29.912, -1.48269], [30.16369, -1.34303], [30.35212, -1.06896], [30.47194, -1.0555], [30.64166, -1.06601], [30.70631, -1.01175], [30.76635, -0.9852], [30.80408, -0.99911], [33.93107, -0.99298]]]]
27251 wikidata: "Q16645",
27252 nameEn: "United States Minor Outlying Islands",
27261 nameEn: "United Nations",
27262 level: "unitedNations",
27263 isoStatus: "excRes"
27273 nameEn: "United States of America"
27284 groups: ["005", "419", "019", "UN"],
27285 callingCodes: ["598"]
27288 type: "MultiPolygon",
27289 coordinates: [[[[-57.65132, -30.19229], [-57.61478, -30.25165], [-57.64859, -30.35095], [-57.89115, -30.49572], [-57.8024, -30.77193], [-57.89476, -30.95994], [-57.86729, -31.06352], [-57.9908, -31.34924], [-57.98127, -31.3872], [-58.07569, -31.44916], [-58.0023, -31.53084], [-58.00076, -31.65016], [-58.20252, -31.86966], [-58.10036, -32.25338], [-58.22362, -32.52416], [-58.1224, -32.98842], [-58.40475, -33.11777], [-58.44442, -33.84033], [-58.34425, -34.15035], [-57.83001, -34.69099], [-54.78916, -36.21945], [-52.83257, -34.01481], [-53.37138, -33.74313], [-53.39593, -33.75169], [-53.44031, -33.69344], [-53.52794, -33.68908], [-53.53459, -33.16843], [-53.1111, -32.71147], [-53.37671, -32.57005], [-53.39572, -32.58596], [-53.76024, -32.0751], [-54.17384, -31.86168], [-55.50821, -30.91349], [-55.50841, -30.9027], [-55.51862, -30.89828], [-55.52712, -30.89997], [-55.53276, -30.90218], [-55.53431, -30.89714], [-55.54572, -30.89051], [-55.55218, -30.88193], [-55.55373, -30.8732], [-55.5634, -30.8686], [-55.58866, -30.84117], [-55.87388, -31.05053], [-56.4619, -30.38457], [-56.4795, -30.3899], [-56.49267, -30.39471], [-56.90236, -30.02578], [-57.22502, -30.26121], [-57.65132, -30.19229]]]]
27298 nameEn: "Uzbekistan",
27299 groups: ["143", "142", "UN"],
27300 callingCodes: ["998"]
27303 type: "MultiPolygon",
27304 coordinates: [[[[65.85194, 42.85481], [65.53277, 43.31856], [65.18666, 43.48835], [64.96464, 43.74748], [64.53885, 43.56941], [63.34656, 43.64003], [62.01711, 43.51008], [61.01475, 44.41383], [58.59711, 45.58671], [55.97842, 44.99622], [55.97832, 44.99622], [55.97822, 44.99617], [55.97811, 44.99617], [55.97801, 44.99612], [55.97801, 44.99607], [55.97791, 44.99607], [55.9778, 44.99607], [55.9777, 44.99601], [55.9777, 44.99596], [55.9776, 44.99591], [55.97749, 44.99591], [55.97739, 44.99591], [55.97739, 44.99586], [55.97729, 44.99586], [55.97718, 44.99581], [55.97708, 44.99576], [55.97698, 44.9957], [55.97698, 44.99565], [55.97687, 44.9956], [55.97677, 44.9956], [55.97677, 44.99555], [55.97677, 44.9955], [55.97667, 44.99545], [55.97656, 44.99539], [55.97646, 44.99534], [55.97646, 44.99529], [55.97636, 44.99524], [55.97636, 44.99519], [55.97625, 44.99514], [55.97615, 44.99508], [55.97615, 44.99503], [55.97615, 44.99498], [55.97615, 44.99493], [55.97615, 44.99483], [55.97615, 44.99477], [55.97605, 44.99477], [55.97605, 44.99467], [55.97605, 44.99462], [55.97605, 44.99457], [55.97605, 44.99452], [55.97594, 44.99446], [55.97584, 44.99441], [55.97584, 44.99436], [55.97584, 44.99431], [55.97584, 44.99426], [55.97584, 44.99421], [55.97584, 44.99415], [55.97584, 44.99405], [55.97584, 44.994], [55.97584, 44.9939], [55.97584, 44.99384], [55.97584, 44.99374], [55.97584, 44.99369], [55.97584, 44.99359], [55.97584, 44.99353], [55.97584, 44.99348], [55.97584, 44.99343], [55.97584, 44.99338], [55.97584, 44.99328], [55.97584, 44.99322], [56.00314, 41.32584], [57.03423, 41.25435], [57.13796, 41.36625], [57.03359, 41.41777], [56.96218, 41.80383], [57.03633, 41.92043], [57.30275, 42.14076], [57.6296, 42.16519], [57.84932, 42.18555], [57.92897, 42.24047], [57.90975, 42.4374], [57.99214, 42.50021], [58.3492, 42.43335], [58.40688, 42.29535], [58.51674, 42.30348], [58.29427, 42.56497], [58.14321, 42.62159], [58.27504, 42.69632], [58.57991, 42.64988], [58.6266, 42.79314], [58.93422, 42.5407], [59.17317, 42.52248], [59.2955, 42.37064], [59.4341, 42.29738], [59.94633, 42.27655], [60.00539, 42.212], [59.96419, 42.1428], [60.04659, 42.08982], [60.0356, 42.01028], [59.95046, 41.97966], [60.33223, 41.75058], [60.08504, 41.80997], [60.06032, 41.76287], [60.18117, 41.60082], [60.06581, 41.4363], [60.5078, 41.21694], [61.03261, 41.25691], [61.22212, 41.14946], [61.33199, 41.14946], [61.39732, 41.19873], [61.4446, 41.29407], [61.87856, 41.12257], [62.11751, 40.58242], [62.34273, 40.43206], [62.43337, 39.98528], [63.6913, 39.27666], [63.70778, 39.22349], [64.19086, 38.95561], [64.32576, 38.98691], [65.55873, 38.29052], [65.83913, 38.25733], [66.24013, 38.16238], [66.41042, 38.02403], [66.56697, 38.0435], [66.67684, 37.96776], [66.53676, 37.80084], [66.52852, 37.58568], [66.65761, 37.45497], [66.52303, 37.39827], [66.55743, 37.35409], [66.64699, 37.32958], [66.95598, 37.40162], [67.08232, 37.35469], [67.13039, 37.27168], [67.2224, 37.24545], [67.2581, 37.17216], [67.51868, 37.26102], [67.78329, 37.1834], [67.8474, 37.31594], [67.81566, 37.43107], [68.12635, 37.93], [68.27159, 37.91477], [68.40343, 38.19484], [68.13289, 38.40822], [68.06274, 38.39435], [68.11366, 38.47169], [68.05873, 38.56087], [68.0807, 38.64136], [68.05598, 38.71641], [68.12877, 38.73677], [68.06948, 38.82115], [68.19743, 38.85985], [68.09704, 39.02589], [67.68915, 39.00775], [67.67833, 39.14479], [67.33226, 39.23739], [67.36522, 39.31287], [67.45998, 39.315], [67.46822, 39.46146], [67.39681, 39.52505], [67.46547, 39.53564], [67.44899, 39.57799], [67.62889, 39.60234], [67.70992, 39.66156], [68.12053, 39.56317], [68.54166, 39.53929], [68.61972, 39.68905], [68.63071, 39.85265], [68.88889, 39.87163], [68.93695, 39.91167], [68.84906, 40.04952], [68.96579, 40.06949], [69.01935, 40.11466], [69.01523, 40.15771], [68.62796, 40.07789], [68.52771, 40.11676], [68.5332, 40.14826], [68.77902, 40.20492], [68.79276, 40.17555], [68.84357, 40.18604], [68.85832, 40.20885], [69.04544, 40.22904], [69.15659, 40.2162], [69.2074, 40.21488], [69.30448, 40.18774], [69.30104, 40.24502], [69.25229, 40.26362], [69.24817, 40.30357], [69.30808, 40.2821], [69.32833, 40.29794], [69.33794, 40.34819], [69.30774, 40.36102], [69.28525, 40.41894], [69.27066, 40.49274], [69.21063, 40.54469], [69.2643, 40.57506], [69.3455, 40.57988], [69.32834, 40.70233], [69.38327, 40.7918], [69.53021, 40.77621], [69.59441, 40.70181], [69.69434, 40.62615], [70.36655, 40.90296], [70.38028, 41.02014], [70.45251, 41.04438], [70.80009, 40.72825], [70.49871, 40.52503], [70.32626, 40.45174], [70.37511, 40.38605], [70.57149, 40.3442], [70.56394, 40.26421], [70.62342, 40.17396], [70.8607, 40.217], [70.9818, 40.22392], [70.95789, 40.28761], [71.05901, 40.28765], [71.13042, 40.34106], [71.36663, 40.31593], [71.4246, 40.28619], [71.51215, 40.26943], [71.51549, 40.22986], [71.61725, 40.20615], [71.61931, 40.26775], [71.68386, 40.26984], [71.70569, 40.20391], [71.69621, 40.18492], [71.71719, 40.17886], [71.73054, 40.14818], [71.82646, 40.21872], [71.85002, 40.25647], [72.05464, 40.27586], [71.96401, 40.31907], [72.18648, 40.49893], [72.24368, 40.46091], [72.40346, 40.4007], [72.44191, 40.48222], [72.41513, 40.50856], [72.38384, 40.51535], [72.41714, 40.55736], [72.34406, 40.60144], [72.40517, 40.61917], [72.47795, 40.5532], [72.66713, 40.5219], [72.66713, 40.59076], [72.69579, 40.59778], [72.73995, 40.58409], [72.74768, 40.58051], [72.74862, 40.57131], [72.75982, 40.57273], [72.74894, 40.59592], [72.74866, 40.60873], [72.80137, 40.67856], [72.84754, 40.67229], [72.85372, 40.7116], [72.8722, 40.71111], [72.93296, 40.73089], [72.99133, 40.76457], [73.0612, 40.76678], [73.13412, 40.79122], [73.13267, 40.83512], [73.01869, 40.84681], [72.94454, 40.8094], [72.84291, 40.85512], [72.68157, 40.84942], [72.59136, 40.86947], [72.55109, 40.96046], [72.48742, 40.97136], [72.45206, 41.03018], [72.38511, 41.02785], [72.36138, 41.04384], [72.34757, 41.06104], [72.34026, 41.04539], [72.324, 41.03381], [72.18339, 40.99571], [72.17594, 41.02377], [72.21061, 41.05607], [72.1792, 41.10621], [72.14864, 41.13363], [72.17594, 41.15522], [72.16433, 41.16483], [72.10745, 41.15483], [72.07249, 41.11739], [71.85964, 41.19081], [71.91457, 41.2982], [71.83914, 41.3546], [71.76625, 41.4466], [71.71132, 41.43012], [71.73054, 41.54713], [71.65914, 41.49599], [71.6787, 41.42111], [71.57227, 41.29175], [71.46688, 41.31883], [71.43814, 41.19644], [71.46148, 41.13958], [71.40198, 41.09436], [71.34877, 41.16807], [71.27187, 41.11015], [71.25813, 41.18796], [71.11806, 41.15359], [71.02193, 41.19494], [70.9615, 41.16393], [70.86263, 41.23833], [70.77885, 41.24813], [70.78572, 41.36419], [70.67586, 41.47953], [70.48909, 41.40335], [70.17682, 41.5455], [70.69777, 41.92554], [71.28719, 42.18033], [71.13263, 42.28356], [70.94483, 42.26238], [69.49545, 41.545], [69.45751, 41.56863], [69.39485, 41.51518], [69.45081, 41.46246], [69.37468, 41.46555], [69.35554, 41.47211], [69.29778, 41.43673], [69.25059, 41.46693], [69.23332, 41.45847], [69.22671, 41.46298], [69.20439, 41.45391], [69.18528, 41.45175], [69.17701, 41.43769], [69.15137, 41.43078], [69.05006, 41.36183], [69.01308, 41.22804], [68.7217, 41.05025], [68.73945, 40.96989], [68.65662, 40.93861], [68.62221, 41.03019], [68.49983, 40.99669], [68.58444, 40.91447], [68.63, 40.59358], [68.49983, 40.56437], [67.96736, 40.83798], [68.1271, 41.0324], [68.08273, 41.08148], [67.98511, 41.02794], [67.9644, 41.14611], [66.69129, 41.1311], [66.53302, 41.87388], [66.00546, 41.94455], [66.09482, 42.93426], [65.85194, 42.85481]], [[70.68112, 40.90612], [70.6721, 40.90555], [70.57501, 40.98941], [70.54223, 40.98787], [70.56077, 41.00642], [70.6158, 40.97661], [70.68112, 40.90612]]], [[[71.21139, 40.03369], [71.12218, 40.03052], [71.06305, 40.1771], [71.00236, 40.18154], [71.01035, 40.05481], [71.11037, 40.01984], [71.11668, 39.99291], [71.09063, 39.99], [71.10501, 39.95568], [71.04979, 39.89808], [71.10531, 39.91354], [71.16101, 39.88423], [71.23067, 39.93581], [71.1427, 39.95026], [71.21139, 40.03369]]], [[[71.86463, 39.98598], [71.78838, 40.01404], [71.71511, 39.96348], [71.7504, 39.93701], [71.84316, 39.95582], [71.86463, 39.98598]]]]
27313 nameEn: "Vatican City",
27314 aliases: ["Holy See"],
27315 groups: ["039", "150"],
27316 callingCodes: ["379", "39 06"]
27319 type: "MultiPolygon",
27320 coordinates: [[[[12.45181, 41.90056], [12.45446, 41.90028], [12.45435, 41.90143], [12.45626, 41.90172], [12.45691, 41.90125], [12.4577, 41.90115], [12.45834, 41.90174], [12.45826, 41.90281], [12.45755, 41.9033], [12.45762, 41.9058], [12.45561, 41.90629], [12.45543, 41.90738], [12.45091, 41.90625], [12.44984, 41.90545], [12.44815, 41.90326], [12.44582, 41.90194], [12.44834, 41.90095], [12.45181, 41.90056]]]]
27329 nameEn: "St. Vincent and the Grenadines",
27331 groups: ["029", "003", "419", "019", "UN"],
27333 roadSpeedUnit: "mph",
27334 callingCodes: ["1 784"]
27337 type: "MultiPolygon",
27338 coordinates: [[[[-62.64026, 12.69984], [-59.94058, 12.34011], [-61.69315, 14.26451], [-62.64026, 12.69984]]]]
27347 nameEn: "Venezuela",
27349 groups: ["005", "419", "019", "UN"],
27350 callingCodes: ["58"]
27353 type: "MultiPolygon",
27354 coordinates: [[[[-71.22331, 13.01387], [-70.92579, 11.96275], [-71.3275, 11.85], [-71.9675, 11.65536], [-72.24983, 11.14138], [-72.4767, 11.1117], [-72.88002, 10.44309], [-72.98085, 9.85253], [-73.36905, 9.16636], [-73.02119, 9.27584], [-72.94052, 9.10663], [-72.77415, 9.10165], [-72.65474, 8.61428], [-72.4042, 8.36513], [-72.36987, 8.19976], [-72.35163, 8.01163], [-72.39137, 8.03534], [-72.47213, 7.96106], [-72.48801, 7.94329], [-72.48183, 7.92909], [-72.47042, 7.92306], [-72.45806, 7.91141], [-72.46183, 7.90682], [-72.44454, 7.86031], [-72.46763, 7.79518], [-72.47827, 7.65604], [-72.45321, 7.57232], [-72.47415, 7.48928], [-72.43132, 7.40034], [-72.19437, 7.37034], [-72.04895, 7.03837], [-71.82441, 7.04314], [-71.44118, 7.02116], [-71.42212, 7.03854], [-71.37234, 7.01588], [-71.03941, 6.98163], [-70.7596, 7.09799], [-70.10716, 6.96516], [-69.41843, 6.1072], [-67.60654, 6.2891], [-67.4625, 6.20625], [-67.43513, 5.98835], [-67.58558, 5.84537], [-67.63914, 5.64963], [-67.59141, 5.5369], [-67.83341, 5.31104], [-67.85358, 4.53249], [-67.62671, 3.74303], [-67.50067, 3.75812], [-67.30945, 3.38393], [-67.85862, 2.86727], [-67.85862, 2.79173], [-67.65696, 2.81691], [-67.21967, 2.35778], [-66.85795, 1.22998], [-66.28507, 0.74585], [-65.6727, 1.01353], [-65.50158, 0.92086], [-65.57288, 0.62856], [-65.11657, 1.12046], [-64.38932, 1.5125], [-64.34654, 1.35569], [-64.08274, 1.64792], [-64.06135, 1.94722], [-63.39827, 2.16098], [-63.39114, 2.4317], [-64.0257, 2.48156], [-64.02908, 2.79797], [-64.48379, 3.7879], [-64.84028, 4.24665], [-64.72977, 4.28931], [-64.57648, 4.12576], [-64.14512, 4.12932], [-63.99183, 3.90172], [-63.86082, 3.94796], [-63.70218, 3.91417], [-63.67099, 4.01731], [-63.50611, 3.83592], [-63.42233, 3.89995], [-63.4464, 3.9693], [-63.21111, 3.96219], [-62.98296, 3.59935], [-62.7655, 3.73099], [-62.74411, 4.03331], [-62.57656, 4.04754], [-62.44822, 4.18621], [-62.13094, 4.08309], [-61.54629, 4.2822], [-61.48569, 4.43149], [-61.29675, 4.44216], [-61.31457, 4.54167], [-61.15703, 4.49839], [-60.98303, 4.54167], [-60.86539, 4.70512], [-60.5802, 4.94312], [-60.73204, 5.20931], [-61.4041, 5.95304], [-61.15058, 6.19558], [-61.20762, 6.58174], [-61.13632, 6.70922], [-60.54873, 6.8631], [-60.39419, 6.94847], [-60.28074, 7.1162], [-60.44116, 7.20817], [-60.54098, 7.14804], [-60.63367, 7.25061], [-60.59802, 7.33194], [-60.71923, 7.55817], [-60.64793, 7.56877], [-60.51959, 7.83373], [-60.38056, 7.8302], [-60.02407, 8.04557], [-59.97059, 8.20791], [-59.83156, 8.23261], [-59.80661, 8.28906], [-59.85562, 8.35213], [-59.98508, 8.53046], [-59.54058, 8.6862], [-60.89962, 9.81445], [-62.08693, 10.04435], [-61.62505, 11.18974], [-63.73917, 11.92623], [-63.19938, 16.44103], [-67.89186, 12.4116], [-68.01417, 11.77722], [-68.33524, 11.78151], [-68.99639, 11.79035], [-71.22331, 13.01387]]]]
27362 wikidata: "Q25305",
27363 nameEn: "British Virgin Islands",
27365 groups: ["BOTS", "029", "003", "419", "019", "UN"],
27367 roadSpeedUnit: "mph",
27368 roadHeightUnit: "ft",
27369 callingCodes: ["1 284"]
27372 type: "MultiPolygon",
27373 coordinates: [[[[-64.47127, 17.55688], [-63.88746, 19.15706], [-65.02435, 18.73231], [-64.86027, 18.39056], [-64.64673, 18.36549], [-64.47127, 17.55688]]]]
27381 wikidata: "Q11703",
27382 nameEn: "United States Virgin Islands",
27383 aliases: ["US-VI"],
27385 groups: ["Q1352230", "029", "003", "419", "019", "UN"],
27387 roadSpeedUnit: "mph",
27388 roadHeightUnit: "ft",
27389 callingCodes: ["1 340"]
27392 type: "MultiPolygon",
27393 coordinates: [[[[-65.02435, 18.73231], [-65.27974, 17.56928], [-64.47127, 17.55688], [-64.64673, 18.36549], [-64.86027, 18.39056], [-65.02435, 18.73231]]]]
27403 groups: ["035", "142", "UN"],
27404 callingCodes: ["84"]
27407 type: "MultiPolygon",
27408 coordinates: [[[[108.10003, 21.47338], [108.0569, 21.53604], [108.02926, 21.54997], [107.97932, 21.54503], [107.97383, 21.53961], [107.97074, 21.54072], [107.96774, 21.53601], [107.95232, 21.5388], [107.92652, 21.58906], [107.90006, 21.5905], [107.86114, 21.65128], [107.80355, 21.66141], [107.66967, 21.60787], [107.56537, 21.61945], [107.54047, 21.5934], [107.49065, 21.59774], [107.49532, 21.62958], [107.47197, 21.6672], [107.41593, 21.64839], [107.38636, 21.59774], [107.35989, 21.60063], [107.35834, 21.6672], [107.29296, 21.74674], [107.24625, 21.7077], [107.20734, 21.71493], [107.10771, 21.79879], [107.02615, 21.81981], [107.00964, 21.85948], [107.06101, 21.88982], [107.05634, 21.92303], [106.99252, 21.95191], [106.97228, 21.92592], [106.92714, 21.93459], [106.9178, 21.97357], [106.81038, 21.97934], [106.74345, 22.00965], [106.72551, 21.97923], [106.69276, 21.96013], [106.68274, 21.99811], [106.70142, 22.02409], [106.6983, 22.15102], [106.67495, 22.1885], [106.69986, 22.22309], [106.6516, 22.33977], [106.55976, 22.34841], [106.57221, 22.37], [106.55665, 22.46498], [106.58395, 22.474], [106.61269, 22.60301], [106.65316, 22.5757], [106.71698, 22.58432], [106.72321, 22.63606], [106.76293, 22.73491], [106.82404, 22.7881], [106.83685, 22.8098], [106.81271, 22.8226], [106.78422, 22.81532], [106.71128, 22.85982], [106.71387, 22.88296], [106.6734, 22.89587], [106.6516, 22.86862], [106.60179, 22.92884], [106.55976, 22.92311], [106.51306, 22.94891], [106.49749, 22.91164], [106.34961, 22.86718], [106.27022, 22.87722], [106.19705, 22.98475], [106.00179, 22.99049], [105.99568, 22.94178], [105.90119, 22.94168], [105.8726, 22.92756], [105.72382, 23.06641], [105.57594, 23.075], [105.56037, 23.16806], [105.49966, 23.20669], [105.42805, 23.30824], [105.40782, 23.28107], [105.32376, 23.39684], [105.22569, 23.27249], [105.17276, 23.28679], [105.11672, 23.25247], [105.07002, 23.26248], [104.98712, 23.19176], [104.96532, 23.20463], [104.9486, 23.17235], [104.91435, 23.18666], [104.87992, 23.17141], [104.87382, 23.12854], [104.79478, 23.12934], [104.8334, 23.01484], [104.86765, 22.95178], [104.84942, 22.93631], [104.77114, 22.90017], [104.72755, 22.81984], [104.65283, 22.83419], [104.60457, 22.81841], [104.58122, 22.85571], [104.47225, 22.75813], [104.35593, 22.69353], [104.25683, 22.76534], [104.27084, 22.8457], [104.11384, 22.80363], [104.03734, 22.72945], [104.01088, 22.51823], [103.99247, 22.51958], [103.97384, 22.50634], [103.96783, 22.51173], [103.96352, 22.50584], [103.95191, 22.5134], [103.94513, 22.52553], [103.93286, 22.52703], [103.87904, 22.56683], [103.64506, 22.79979], [103.56255, 22.69499], [103.57812, 22.65764], [103.52675, 22.59155], [103.43646, 22.70648], [103.43179, 22.75816], [103.32282, 22.8127], [103.28079, 22.68063], [103.18895, 22.64471], [103.15782, 22.59873], [103.17961, 22.55705], [103.07843, 22.50097], [103.0722, 22.44775], [102.9321, 22.48659], [102.8636, 22.60735], [102.60675, 22.73376], [102.57095, 22.7036], [102.51802, 22.77969], [102.46665, 22.77108], [102.42618, 22.69212], [102.38415, 22.67919], [102.41061, 22.64184], [102.25339, 22.4607], [102.26428, 22.41321], [102.16621, 22.43336], [102.14099, 22.40092], [102.18712, 22.30403], [102.51734, 22.02676], [102.49092, 21.99002], [102.62301, 21.91447], [102.67145, 21.65894], [102.74189, 21.66713], [102.82115, 21.73667], [102.81894, 21.83888], [102.85637, 21.84501], [102.86077, 21.71213], [102.97965, 21.74076], [102.98846, 21.58936], [102.86297, 21.4255], [102.94223, 21.46034], [102.88939, 21.3107], [102.80794, 21.25736], [102.89825, 21.24707], [102.97745, 21.05821], [103.03469, 21.05821], [103.12055, 20.89994], [103.21497, 20.89832], [103.38032, 20.79501], [103.45737, 20.82382], [103.68633, 20.66324], [103.73478, 20.6669], [103.82282, 20.8732], [103.98024, 20.91531], [104.11121, 20.96779], [104.27412, 20.91433], [104.63957, 20.6653], [104.38199, 20.47155], [104.40621, 20.3849], [104.47886, 20.37459], [104.66158, 20.47774], [104.72102, 20.40554], [104.62195, 20.36633], [104.61315, 20.24452], [104.86852, 20.14121], [104.91695, 20.15567], [104.9874, 20.09573], [104.8465, 19.91783], [104.8355, 19.80395], [104.68359, 19.72729], [104.64837, 19.62365], [104.53169, 19.61743], [104.41281, 19.70035], [104.23229, 19.70242], [104.06498, 19.66926], [104.05617, 19.61743], [104.10832, 19.51575], [104.06058, 19.43484], [103.87125, 19.31854], [104.5361, 18.97747], [104.64617, 18.85668], [105.12829, 18.70453], [105.19654, 18.64196], [105.1327, 18.58355], [105.10408, 18.43533], [105.15942, 18.38691], [105.38366, 18.15315], [105.46292, 18.22008], [105.64784, 17.96687], [105.60381, 17.89356], [105.76612, 17.67147], [105.85744, 17.63221], [106.09019, 17.36399], [106.18991, 17.28227], [106.24444, 17.24714], [106.29287, 17.3018], [106.31929, 17.20509], [106.43597, 17.01362], [106.50862, 16.9673], [106.55045, 17.0031], [106.54824, 16.92729], [106.51963, 16.92097], [106.52183, 16.87884], [106.55265, 16.86831], [106.55485, 16.68704], [106.59013, 16.62259], [106.58267, 16.6012], [106.61477, 16.60713], [106.66052, 16.56892], [106.65832, 16.47816], [106.74418, 16.41904], [106.84104, 16.55415], [106.88727, 16.52671], [106.88067, 16.43594], [106.96638, 16.34938], [106.97385, 16.30204], [107.02597, 16.31132], [107.09091, 16.3092], [107.15035, 16.26271], [107.14595, 16.17816], [107.25822, 16.13587], [107.33968, 16.05549], [107.44975, 16.08511], [107.46296, 16.01106], [107.39471, 15.88829], [107.34188, 15.89464], [107.21419, 15.83747], [107.21859, 15.74638], [107.27143, 15.71459], [107.27583, 15.62769], [107.34408, 15.62345], [107.3815, 15.49832], [107.50699, 15.48771], [107.53341, 15.40496], [107.62367, 15.42193], [107.60605, 15.37524], [107.62587, 15.2266], [107.58844, 15.20111], [107.61926, 15.13949], [107.61486, 15.0566], [107.46516, 15.00982], [107.48277, 14.93751], [107.59285, 14.87795], [107.51579, 14.79282], [107.54361, 14.69092], [107.55371, 14.628], [107.52102, 14.59034], [107.52569, 14.54665], [107.48521, 14.40346], [107.44941, 14.41552], [107.39493, 14.32655], [107.40427, 14.24509], [107.33577, 14.11832], [107.37158, 14.07906], [107.35757, 14.02319], [107.38247, 13.99147], [107.44318, 13.99751], [107.46498, 13.91593], [107.45252, 13.78897], [107.53503, 13.73908], [107.61909, 13.52577], [107.62843, 13.3668], [107.49144, 13.01215], [107.49611, 12.88926], [107.55993, 12.7982], [107.5755, 12.52177], [107.55059, 12.36824], [107.4463, 12.29373], [107.42917, 12.24657], [107.34511, 12.33327], [107.15831, 12.27547], [106.99953, 12.08983], [106.92325, 12.06548], [106.79405, 12.0807], [106.70687, 11.96956], [106.4111, 11.97413], [106.4687, 11.86751], [106.44068, 11.86294], [106.44535, 11.8279], [106.41577, 11.76999], [106.45158, 11.68616], [106.44691, 11.66787], [106.37219, 11.69836], [106.30525, 11.67549], [106.26478, 11.72122], [106.18539, 11.75171], [106.13158, 11.73283], [106.06708, 11.77761], [106.02038, 11.77457], [106.00792, 11.7197], [105.95188, 11.63738], [105.88962, 11.67854], [105.8507, 11.66635], [105.80867, 11.60536], [105.81645, 11.56876], [105.87328, 11.55953], [105.88962, 11.43605], [105.86782, 11.28343], [106.10444, 11.07879], [106.1527, 11.10476], [106.1757, 11.07301], [106.20095, 10.97795], [106.14301, 10.98176], [106.18539, 10.79451], [106.06708, 10.8098], [105.94535, 10.9168], [105.93403, 10.83853], [105.84603, 10.85873], [105.86376, 10.89839], [105.77751, 11.03671], [105.50045, 10.94586], [105.42884, 10.96878], [105.34011, 10.86179], [105.11449, 10.96332], [105.08326, 10.95656], [105.02722, 10.89236], [105.09571, 10.72722], [104.95094, 10.64003], [104.87933, 10.52833], [104.59018, 10.53073], [104.49869, 10.4057], [104.47963, 10.43046], [104.43778, 10.42386], [103.99198, 10.48391], [102.47649, 9.66162], [104.81582, 8.03101], [109.55486, 8.10026], [111.60491, 13.57105], [108.00365, 17.98159], [108.10003, 21.47338]]]]
27418 groups: ["054", "009", "UN"],
27419 callingCodes: ["678"]
27422 type: "MultiPolygon",
27423 coordinates: [[[[156.73836, -14.50464], [174.245, -23.1974], [172.71443, -12.01327], [156.73836, -14.50464]]]]
27431 wikidata: "Q35555",
27432 nameEn: "Wallis and Futuna",
27434 groups: ["Q1451600", "061", "009", "UN"],
27435 callingCodes: ["681"]
27438 type: "MultiPolygon",
27439 coordinates: [[[[-178.66551, -14.32452], [-176.76826, -14.95183], [-175.59809, -12.61507], [-178.66551, -14.32452]]]]
27449 groups: ["061", "009", "UN"],
27451 callingCodes: ["685"]
27454 type: "MultiPolygon",
27455 coordinates: [[[[-173.74402, -14.26669], [-170.99605, -15.1275], [-171.39864, -10.21587], [-173.74402, -14.26669]]]]
27465 groups: ["039", "150"],
27466 isoStatus: "usrAssn",
27467 callingCodes: ["383"]
27470 type: "MultiPolygon",
27471 coordinates: [[[[21.39045, 42.74888], [21.44047, 42.87276], [21.36941, 42.87397], [21.32974, 42.90424], [21.2719, 42.8994], [21.23534, 42.95523], [21.23877, 43.00848], [21.2041, 43.02277], [21.16734, 42.99694], [21.14465, 43.11089], [21.08952, 43.13471], [21.05378, 43.10707], [21.00749, 43.13984], [20.96287, 43.12416], [20.83727, 43.17842], [20.88685, 43.21697], [20.82145, 43.26769], [20.73811, 43.25068], [20.68688, 43.21335], [20.59929, 43.20492], [20.69515, 43.09641], [20.64557, 43.00826], [20.59929, 43.01067], [20.48692, 42.93208], [20.53484, 42.8885], [20.43734, 42.83157], [20.40594, 42.84853], [20.35692, 42.8335], [20.27869, 42.81945], [20.2539, 42.76245], [20.04898, 42.77701], [20.02088, 42.74789], [20.02915, 42.71147], [20.0969, 42.65559], [20.07761, 42.55582], [20.17127, 42.50469], [20.21797, 42.41237], [20.24399, 42.32168], [20.34479, 42.32656], [20.3819, 42.3029], [20.48857, 42.25444], [20.56955, 42.12097], [20.55633, 42.08173], [20.59434, 42.03879], [20.63069, 41.94913], [20.57946, 41.91593], [20.59524, 41.8818], [20.68523, 41.85318], [20.76786, 41.91839], [20.75464, 42.05229], [21.11491, 42.20794], [21.16614, 42.19815], [21.22728, 42.08909], [21.31983, 42.10993], [21.29913, 42.13954], [21.30496, 42.1418], [21.38428, 42.24465], [21.43882, 42.23609], [21.43882, 42.2789], [21.50823, 42.27156], [21.52145, 42.24465], [21.58992, 42.25915], [21.56772, 42.30946], [21.5264, 42.33634], [21.53467, 42.36809], [21.57021, 42.3647], [21.59029, 42.38042], [21.62887, 42.37664], [21.64209, 42.41081], [21.62556, 42.45106], [21.7035, 42.51899], [21.70522, 42.54176], [21.7327, 42.55041], [21.75672, 42.62695], [21.79413, 42.65923], [21.75025, 42.70125], [21.6626, 42.67813], [21.58755, 42.70418], [21.59154, 42.72643], [21.47498, 42.74695], [21.39045, 42.74888]]]]
27481 groups: ["145", "142", "UN"],
27482 callingCodes: ["967"]
27485 type: "MultiPolygon",
27486 coordinates: [[[[57.49095, 8.14549], [52.81185, 17.28568], [52.74267, 17.29519], [52.78009, 17.35124], [52.00311, 19.00083], [49.04884, 18.59899], [48.19996, 18.20584], [47.58351, 17.50366], [47.48245, 17.10808], [47.00571, 16.94765], [46.76494, 17.29151], [46.31018, 17.20464], [44.50126, 17.47475], [43.70631, 17.35762], [43.43005, 17.56148], [43.29185, 17.53224], [43.22533, 17.38343], [43.32653, 17.31179], [43.20156, 17.25901], [43.17787, 17.14717], [43.23967, 17.03428], [43.18233, 17.02673], [43.1813, 16.98438], [43.19328, 16.94703], [43.1398, 16.90696], [43.18338, 16.84852], [43.22012, 16.83932], [43.22956, 16.80613], [43.24801, 16.80613], [43.26303, 16.79479], [43.25857, 16.75304], [43.21325, 16.74416], [43.22066, 16.65179], [43.15274, 16.67248], [43.11601, 16.53166], [42.97215, 16.51093], [42.94351, 16.49467], [42.94625, 16.39721], [42.76801, 16.40371], [42.15205, 16.40211], [40.99158, 15.81743], [43.29075, 12.79154], [43.32909, 12.59711], [43.90659, 12.3823], [51.12877, 12.56479], [57.49095, 8.14549]]]]
27494 wikidata: "Q17063",
27497 groups: ["Q3320166", "EU", "014", "202", "002", "UN"],
27498 callingCodes: ["262"]
27501 type: "MultiPolygon",
27502 coordinates: [[[[43.28731, -13.97126], [45.54824, -13.22353], [45.4971, -11.75965], [43.28731, -13.97126]]]]
27511 nameEn: "South Africa",
27512 groups: ["018", "202", "002", "UN"],
27514 callingCodes: ["27"]
27517 type: "MultiPolygon",
27518 coordinates: [[[[31.30611, -22.422], [31.16344, -22.32599], [31.08932, -22.34884], [30.86696, -22.28907], [30.6294, -22.32599], [30.48686, -22.31368], [30.38614, -22.34533], [30.28351, -22.35587], [30.2265, -22.2961], [30.13147, -22.30841], [29.92242, -22.19408], [29.76848, -22.14128], [29.64609, -22.12917], [29.37703, -22.19581], [29.21955, -22.17771], [29.18974, -22.18599], [29.15268, -22.21399], [29.10881, -22.21202], [29.0151, -22.22907], [28.91889, -22.44299], [28.63287, -22.55887], [28.34874, -22.5694], [28.04562, -22.8394], [28.04752, -22.90243], [27.93729, -22.96194], [27.93539, -23.04941], [27.74154, -23.2137], [27.6066, -23.21894], [27.52393, -23.37952], [27.33768, -23.40917], [26.99749, -23.65486], [26.84165, -24.24885], [26.51667, -24.47219], [26.46346, -24.60358], [26.39409, -24.63468], [25.8515, -24.75727], [25.84295, -24.78661], [25.88571, -24.87802], [25.72702, -25.25503], [25.69661, -25.29284], [25.6643, -25.4491], [25.58543, -25.6343], [25.33076, -25.76616], [25.12266, -25.75931], [25.01718, -25.72507], [24.8946, -25.80723], [24.67319, -25.81749], [24.44703, -25.73021], [24.36531, -25.773], [24.18287, -25.62916], [23.9244, -25.64286], [23.47588, -25.29971], [23.03497, -25.29971], [22.86012, -25.50572], [22.70808, -25.99186], [22.56365, -26.19668], [22.41921, -26.23078], [22.21206, -26.3773], [22.06192, -26.61882], [21.90703, -26.66808], [21.83291, -26.65959], [21.77114, -26.69015], [21.7854, -26.79199], [21.69322, -26.86152], [21.37869, -26.82083], [21.13353, -26.86661], [20.87031, -26.80047], [20.68596, -26.9039], [20.63275, -26.78181], [20.61754, -26.4692], [20.86081, -26.14892], [20.64795, -25.47827], [20.29826, -24.94869], [20.03678, -24.81004], [20.02809, -24.78725], [19.99817, -24.76768], [19.99882, -28.42622], [18.99885, -28.89165], [17.4579, -28.68718], [17.15405, -28.08573], [16.90446, -28.057], [16.59922, -28.53246], [16.46592, -28.57126], [16.45332, -28.63117], [12.51595, -32.27486], [38.88176, -48.03306], [34.51034, -26.91792], [32.35222, -26.86027], [32.29584, -26.852], [32.22302, -26.84136], [32.19409, -26.84032], [32.13315, -26.84345], [32.09664, -26.80721], [32.00893, -26.8096], [31.97463, -27.11057], [31.97592, -27.31675], [31.49834, -27.31549], [31.15027, -27.20151], [30.96088, -27.0245], [30.97757, -26.92706], [30.88826, -26.79622], [30.81101, -26.84722], [30.78927, -26.48271], [30.95819, -26.26303], [31.13073, -25.91558], [31.31237, -25.7431], [31.4175, -25.71886], [31.86881, -25.99973], [31.974, -25.95387], [31.92649, -25.84216], [32.00631, -25.65044], [31.97875, -25.46356], [32.01676, -25.38117], [32.03196, -25.10785], [31.9835, -24.29983], [31.90368, -24.18892], [31.87707, -23.95293], [31.77445, -23.90082], [31.70223, -23.72695], [31.67942, -23.60858], [31.56539, -23.47268], [31.55779, -23.176], [31.30611, -22.422]], [[29.33204, -29.45598], [29.28545, -29.58456], [29.12553, -29.76266], [29.16548, -29.91706], [28.9338, -30.05072], [28.80222, -30.10579], [28.68627, -30.12885], [28.399, -30.1592], [28.2319, -30.28476], [28.12073, -30.68072], [27.74814, -30.60635], [27.69467, -30.55862], [27.67819, -30.53437], [27.6521, -30.51707], [27.62137, -30.50509], [27.56781, -30.44562], [27.56901, -30.42504], [27.45452, -30.32239], [27.38108, -30.33456], [27.36649, -30.27246], [27.37293, -30.19401], [27.40778, -30.14577], [27.32555, -30.14785], [27.29603, -30.05473], [27.22719, -30.00718], [27.09489, -29.72796], [27.01016, -29.65439], [27.33464, -29.48161], [27.4358, -29.33465], [27.47254, -29.31968], [27.45125, -29.29708], [27.48679, -29.29349], [27.54258, -29.25575], [27.5158, -29.2261], [27.55974, -29.18954], [27.75458, -28.89839], [27.8907, -28.91612], [27.88933, -28.88156], [27.9392, -28.84864], [27.98675, -28.8787], [28.02503, -28.85991], [28.1317, -28.7293], [28.2348, -28.69471], [28.30518, -28.69531], [28.40612, -28.6215], [28.65091, -28.57025], [28.68043, -28.58744], [29.40524, -29.21246], [29.44883, -29.3772], [29.33204, -29.45598]]]]
27528 groups: ["014", "202", "002", "UN"],
27530 callingCodes: ["260"]
27533 type: "MultiPolygon",
27534 coordinates: [[[[32.95389, -9.40138], [32.76233, -9.31963], [32.75611, -9.28583], [32.53661, -9.24281], [32.49147, -9.14754], [32.43543, -9.11988], [32.25486, -9.13371], [32.16146, -9.05993], [32.08206, -9.04609], [31.98866, -9.07069], [31.94196, -9.02303], [31.94663, -8.93846], [31.81587, -8.88618], [31.71158, -8.91386], [31.57147, -8.81388], [31.57147, -8.70619], [31.37533, -8.60769], [31.00796, -8.58615], [30.79243, -8.27382], [28.88917, -8.4831], [28.9711, -8.66935], [28.38526, -9.23393], [28.36562, -9.30091], [28.52636, -9.35379], [28.51627, -9.44726], [28.56208, -9.49122], [28.68532, -9.78], [28.62795, -9.92942], [28.65032, -10.65133], [28.37241, -11.57848], [28.48357, -11.87532], [29.18592, -12.37921], [29.4992, -12.43843], [29.48404, -12.23604], [29.8139, -12.14898], [29.81551, -13.44683], [29.65078, -13.41844], [29.60531, -13.21685], [29.01918, -13.41353], [28.33199, -12.41375], [27.59932, -12.22123], [27.21025, -11.76157], [27.22541, -11.60323], [27.04351, -11.61312], [26.88687, -12.01868], [26.01777, -11.91488], [25.33058, -11.65767], [25.34069, -11.19707], [24.42612, -11.44975], [24.34528, -11.06816], [24.00027, -10.89356], [24.02603, -11.15368], [23.98804, -12.13149], [24.06672, -12.29058], [23.90937, -12.844], [24.03339, -12.99091], [21.97988, -13.00148], [22.00323, -16.18028], [22.17217, -16.50269], [23.20038, -17.47563], [23.47474, -17.62877], [24.23619, -17.47489], [24.32811, -17.49082], [24.38712, -17.46818], [24.5621, -17.52963], [24.70864, -17.49501], [25.00198, -17.58221], [25.26433, -17.79571], [25.51646, -17.86232], [25.6827, -17.81987], [25.85738, -17.91403], [25.85892, -17.97726], [26.08925, -17.98168], [26.0908, -17.93021], [26.21601, -17.88608], [26.55918, -17.99638], [26.68403, -18.07411], [26.74314, -18.0199], [26.89926, -17.98756], [27.14196, -17.81398], [27.30736, -17.60487], [27.61377, -17.34378], [27.62795, -17.24365], [27.83141, -16.96274], [28.73725, -16.5528], [28.76199, -16.51575], [28.81454, -16.48611], [28.8501, -16.04537], [28.9243, -15.93987], [29.01298, -15.93805], [29.21955, -15.76589], [29.4437, -15.68702], [29.8317, -15.6126], [30.35574, -15.6513], [30.41902, -15.62269], [30.22098, -14.99447], [33.24249, -14.00019], [33.16749, -13.93992], [33.07568, -13.98447], [33.02977, -14.05022], [32.99042, -13.95689], [32.88985, -13.82956], [32.79015, -13.80755], [32.76962, -13.77224], [32.84528, -13.71576], [32.7828, -13.64805], [32.68654, -13.64268], [32.66468, -13.60019], [32.68436, -13.55769], [32.73683, -13.57682], [32.84176, -13.52794], [32.86113, -13.47292], [33.0078, -13.19492], [32.98289, -13.12671], [33.02181, -12.88707], [32.96733, -12.88251], [32.94397, -12.76868], [33.05917, -12.59554], [33.18837, -12.61377], [33.28177, -12.54692], [33.37517, -12.54085], [33.54485, -12.35996], [33.47636, -12.32498], [33.3705, -12.34931], [33.25998, -12.14242], [33.33937, -11.91252], [33.32692, -11.59248], [33.24252, -11.59302], [33.23663, -11.40637], [33.29267, -11.43536], [33.29267, -11.3789], [33.39697, -11.15296], [33.25998, -10.88862], [33.28022, -10.84428], [33.47636, -10.78465], [33.70675, -10.56896], [33.54797, -10.36077], [33.53863, -10.20148], [33.31297, -10.05133], [33.37902, -9.9104], [33.36581, -9.81063], [33.31517, -9.82364], [33.2095, -9.61099], [33.12144, -9.58929], [33.10163, -9.66525], [33.05485, -9.61316], [33.00256, -9.63053], [33.00476, -9.5133], [32.95389, -9.40138]]]]
27543 nameEn: "Zimbabwe",
27544 groups: ["014", "202", "002", "UN"],
27546 callingCodes: ["263"]
27549 type: "MultiPolygon",
27550 coordinates: [[[[30.41902, -15.62269], [30.35574, -15.6513], [29.8317, -15.6126], [29.4437, -15.68702], [29.21955, -15.76589], [29.01298, -15.93805], [28.9243, -15.93987], [28.8501, -16.04537], [28.81454, -16.48611], [28.76199, -16.51575], [28.73725, -16.5528], [27.83141, -16.96274], [27.62795, -17.24365], [27.61377, -17.34378], [27.30736, -17.60487], [27.14196, -17.81398], [26.89926, -17.98756], [26.74314, -18.0199], [26.68403, -18.07411], [26.55918, -17.99638], [26.21601, -17.88608], [26.0908, -17.93021], [26.08925, -17.98168], [25.85892, -17.97726], [25.85738, -17.91403], [25.6827, -17.81987], [25.51646, -17.86232], [25.26433, -17.79571], [25.23909, -17.90832], [25.31799, -18.07091], [25.39972, -18.12691], [25.53465, -18.39041], [25.68859, -18.56165], [25.79217, -18.6355], [25.82353, -18.82808], [25.94326, -18.90362], [25.99837, -19.02943], [25.96226, -19.08152], [26.17227, -19.53709], [26.72246, -19.92707], [27.21278, -20.08244], [27.29831, -20.28935], [27.28865, -20.49873], [27.69361, -20.48531], [27.72972, -20.51735], [27.69171, -21.08409], [27.91407, -21.31621], [28.01669, -21.57624], [28.29416, -21.59037], [28.49942, -21.66634], [28.58114, -21.63455], [29.07763, -21.81877], [29.04023, -21.85864], [29.02191, -21.90647], [29.02191, -21.95665], [29.04108, -22.00563], [29.08495, -22.04867], [29.14501, -22.07275], [29.1974, -22.07472], [29.24648, -22.05967], [29.3533, -22.18363], [29.37703, -22.19581], [29.64609, -22.12917], [29.76848, -22.14128], [29.92242, -22.19408], [30.13147, -22.30841], [30.2265, -22.2961], [30.28351, -22.35587], [30.38614, -22.34533], [30.48686, -22.31368], [30.6294, -22.32599], [30.86696, -22.28907], [31.08932, -22.34884], [31.16344, -22.32599], [31.30611, -22.422], [31.38336, -22.36919], [32.41234, -21.31246], [32.48236, -21.32873], [32.37115, -21.133], [32.51644, -20.91929], [32.48122, -20.63319], [32.55167, -20.56312], [32.66174, -20.56106], [32.85987, -20.27841], [32.85987, -20.16686], [32.93032, -20.03868], [33.01178, -20.02007], [33.06461, -19.77787], [32.95013, -19.67219], [32.84666, -19.68462], [32.84446, -19.48343], [32.78282, -19.47513], [32.77966, -19.36098], [32.85107, -19.29238], [32.87088, -19.09279], [32.84006, -19.0262], [32.72118, -19.02204], [32.69917, -18.94293], [32.73439, -18.92628], [32.70137, -18.84712], [32.82465, -18.77419], [32.9017, -18.7992], [32.95013, -18.69079], [32.88629, -18.58023], [32.88629, -18.51344], [33.02278, -18.4696], [33.03159, -18.35054], [32.94133, -17.99705], [33.0492, -17.60298], [32.98536, -17.55891], [32.96554, -17.48964], [33.0426, -17.3468], [33.00517, -17.30477], [32.96554, -17.11971], [32.84113, -16.92259], [32.91051, -16.89446], [32.97655, -16.70689], [32.78943, -16.70267], [32.69917, -16.66893], [32.71017, -16.59932], [32.42838, -16.4727], [32.28529, -16.43892], [32.02772, -16.43892], [31.91324, -16.41569], [31.90223, -16.34388], [31.67988, -16.19595], [31.42451, -16.15154], [31.30563, -16.01193], [31.13171, -15.98019], [30.97761, -16.05848], [30.91597, -15.99924], [30.42568, -15.9962], [30.41902, -15.62269]]]]
27553 var borders_default = {
27556 }; // src/country-coder.ts
27558 var borders = borders_default;
27559 var whichPolygonGetter = {};
27560 var featuresByCode = {};
27561 var idFilterRegex = /(?=(?!^(and|the|of|el|la|de)$))(\b(and|the|of|el|la|de)\b)|[-_ .,'()&[\]/]/gi;
27563 function canonicalID(id) {
27566 if (s.charAt(0) === ".") {
27567 return s.toUpperCase();
27569 return s.replace(idFilterRegex, "").toUpperCase();
27573 var levels = ["subterritory", "territory", "subcountryGroup", "country", "sharedLandform", "intermediateRegion", "subregion", "region", "subunion", "union", "unitedNations", "world"];
27574 loadDerivedDataAndCaches(borders);
27576 function loadDerivedDataAndCaches(borders2) {
27577 var identifierProps = ["iso1A2", "iso1A3", "m49", "wikidata", "emojiFlag", "ccTLD", "nameEn"];
27578 var geometryFeatures = [];
27580 for (var i in borders2.features) {
27581 var feature2 = borders2.features[i];
27582 feature2.properties.id = feature2.properties.iso1A2 || feature2.properties.m49 || feature2.properties.wikidata;
27585 loadIsoStatus(feature2);
27586 loadLevel(feature2);
27587 loadGroups(feature2);
27588 loadFlag(feature2);
27589 cacheFeatureByIDs(feature2);
27590 if (feature2.geometry) geometryFeatures.push(feature2);
27593 for (var _i in borders2.features) {
27594 var _feature = borders2.features[_i];
27595 _feature.properties.groups = _feature.properties.groups.map(function (groupID) {
27596 return featuresByCode[groupID].properties.id;
27598 loadMembersForGroupsOf(_feature);
27601 for (var _i2 in borders2.features) {
27602 var _feature2 = borders2.features[_i2];
27603 loadRoadSpeedUnit(_feature2);
27604 loadRoadHeightUnit(_feature2);
27605 loadDriveSide(_feature2);
27606 loadCallingCodes(_feature2);
27607 loadGroupGroups(_feature2);
27610 for (var _i3 in borders2.features) {
27611 var _feature3 = borders2.features[_i3];
27613 _feature3.properties.groups.sort(function (groupID1, groupID2) {
27614 return levels.indexOf(featuresByCode[groupID1].properties.level) - levels.indexOf(featuresByCode[groupID2].properties.level);
27617 if (_feature3.properties.members) _feature3.properties.members.sort(function (id1, id2) {
27618 var diff = levels.indexOf(featuresByCode[id1].properties.level) - levels.indexOf(featuresByCode[id2].properties.level);
27621 return borders2.features.indexOf(featuresByCode[id1]) - borders2.features.indexOf(featuresByCode[id2]);
27628 var geometryOnlyCollection = {
27629 type: "FeatureCollection",
27630 features: geometryFeatures
27632 whichPolygonGetter = whichPolygon_1(geometryOnlyCollection);
27634 function loadGroups(feature2) {
27635 var props = feature2.properties;
27637 if (!props.groups) {
27641 if (feature2.geometry && props.country) {
27642 props.groups.push(props.country);
27645 if (props.m49 !== "001") {
27646 props.groups.push("001");
27650 function loadM49(feature2) {
27651 var props = feature2.properties;
27653 if (!props.m49 && props.iso1N3) {
27654 props.m49 = props.iso1N3;
27658 function loadTLD(feature2) {
27659 var props = feature2.properties;
27660 if (props.level === "unitedNations") return;
27662 if (!props.ccTLD && props.iso1A2) {
27663 props.ccTLD = "." + props.iso1A2.toLowerCase();
27667 function loadIsoStatus(feature2) {
27668 var props = feature2.properties;
27670 if (!props.isoStatus && props.iso1A2) {
27671 props.isoStatus = "official";
27675 function loadLevel(feature2) {
27676 var props = feature2.properties;
27677 if (props.level) return;
27679 if (!props.country) {
27680 props.level = "country";
27681 } else if (!props.iso1A2 || props.isoStatus === "official") {
27682 props.level = "territory";
27684 props.level = "subterritory";
27688 function loadGroupGroups(feature2) {
27689 var props = feature2.properties;
27690 if (feature2.geometry || !props.members) return;
27691 var featureLevelIndex = levels.indexOf(props.level);
27692 var sharedGroups = [];
27694 var _loop = function _loop(_i4) {
27695 var memberID = props.members[_i4];
27696 var member = featuresByCode[memberID];
27697 var memberGroups = member.properties.groups.filter(function (groupID) {
27698 return groupID !== feature2.properties.id && featureLevelIndex < levels.indexOf(featuresByCode[groupID].properties.level);
27702 sharedGroups = memberGroups;
27704 sharedGroups = sharedGroups.filter(function (groupID) {
27705 return memberGroups.indexOf(groupID) !== -1;
27710 for (var _i4 in props.members) {
27714 props.groups = props.groups.concat(sharedGroups.filter(function (groupID) {
27715 return props.groups.indexOf(groupID) === -1;
27718 for (var j in sharedGroups) {
27719 var groupFeature = featuresByCode[sharedGroups[j]];
27721 if (groupFeature.properties.members.indexOf(props.id) === -1) {
27722 groupFeature.properties.members.push(props.id);
27727 function loadRoadSpeedUnit(feature2) {
27728 var props = feature2.properties;
27730 if (feature2.geometry) {
27731 if (!props.roadSpeedUnit) props.roadSpeedUnit = "km/h";
27732 } else if (props.members) {
27733 var vals = Array.from(new Set(props.members.map(function (id) {
27734 var member = featuresByCode[id];
27735 if (member.geometry) return member.properties.roadSpeedUnit || "km/h";
27736 }).filter(Boolean)));
27737 if (vals.length === 1) props.roadSpeedUnit = vals[0];
27741 function loadRoadHeightUnit(feature2) {
27742 var props = feature2.properties;
27744 if (feature2.geometry) {
27745 if (!props.roadHeightUnit) props.roadHeightUnit = "m";
27746 } else if (props.members) {
27747 var vals = Array.from(new Set(props.members.map(function (id) {
27748 var member = featuresByCode[id];
27749 if (member.geometry) return member.properties.roadHeightUnit || "m";
27750 }).filter(Boolean)));
27751 if (vals.length === 1) props.roadHeightUnit = vals[0];
27755 function loadDriveSide(feature2) {
27756 var props = feature2.properties;
27758 if (feature2.geometry) {
27759 if (!props.driveSide) props.driveSide = "right";
27760 } else if (props.members) {
27761 var vals = Array.from(new Set(props.members.map(function (id) {
27762 var member = featuresByCode[id];
27763 if (member.geometry) return member.properties.driveSide || "right";
27764 }).filter(Boolean)));
27765 if (vals.length === 1) props.driveSide = vals[0];
27769 function loadCallingCodes(feature2) {
27770 var props = feature2.properties;
27772 if (!feature2.geometry && props.members) {
27773 props.callingCodes = Array.from(new Set(props.members.reduce(function (array, id) {
27774 var member = featuresByCode[id];
27775 if (member.geometry && member.properties.callingCodes) return array.concat(member.properties.callingCodes);
27781 function loadFlag(feature2) {
27782 if (!feature2.properties.iso1A2) return;
27783 var flag = feature2.properties.iso1A2.replace(/./g, function (_char) {
27784 return String.fromCodePoint(_char.charCodeAt(0) + 127397);
27786 feature2.properties.emojiFlag = flag;
27789 function loadMembersForGroupsOf(feature2) {
27790 for (var j in feature2.properties.groups) {
27791 var groupID = feature2.properties.groups[j];
27792 var groupFeature = featuresByCode[groupID];
27793 if (!groupFeature.properties.members) groupFeature.properties.members = [];
27794 groupFeature.properties.members.push(feature2.properties.id);
27798 function cacheFeatureByIDs(feature2) {
27801 for (var k in identifierProps) {
27802 var prop = identifierProps[k];
27803 var id = feature2.properties[prop];
27804 if (id) ids.push(id);
27807 if (feature2.properties.aliases) {
27808 for (var j in feature2.properties.aliases) {
27809 ids.push(feature2.properties.aliases[j]);
27813 for (var _i5 in ids) {
27814 var _id = canonicalID(ids[_i5]);
27816 featuresByCode[_id] = feature2;
27821 function locArray(loc) {
27822 if (Array.isArray(loc)) {
27824 } else if (loc.coordinates) {
27825 return loc.coordinates;
27828 return loc.geometry.coordinates;
27831 function smallestFeature(loc) {
27832 var query = locArray(loc);
27833 var featureProperties = whichPolygonGetter(query);
27834 if (!featureProperties) return null;
27835 return featuresByCode[featureProperties.id];
27838 function countryFeature(loc) {
27839 var feature2 = smallestFeature(loc);
27840 if (!feature2) return null;
27841 var countryCode = feature2.properties.country || feature2.properties.iso1A2;
27842 return featuresByCode[countryCode] || null;
27845 var defaultOpts = {
27851 function featureForLoc(loc, opts) {
27852 var targetLevel = opts.level || "country";
27853 var maxLevel = opts.maxLevel || "world";
27854 var withProp = opts.withProp;
27855 var targetLevelIndex = levels.indexOf(targetLevel);
27856 if (targetLevelIndex === -1) return null;
27857 var maxLevelIndex = levels.indexOf(maxLevel);
27858 if (maxLevelIndex === -1) return null;
27859 if (maxLevelIndex < targetLevelIndex) return null;
27861 if (targetLevel === "country") {
27862 var fastFeature = countryFeature(loc);
27865 if (!withProp || fastFeature.properties[withProp]) {
27866 return fastFeature;
27871 var features2 = featuresContaining(loc);
27873 for (var i in features2) {
27874 var feature2 = features2[i];
27875 var levelIndex = levels.indexOf(feature2.properties.level);
27877 if (feature2.properties.level === targetLevel || levelIndex > targetLevelIndex && levelIndex <= maxLevelIndex) {
27878 if (!withProp || feature2.properties[withProp]) {
27887 function featureForID(id) {
27890 if (typeof id === "number") {
27891 stringID = id.toString();
27893 if (stringID.length === 1) {
27894 stringID = "00" + stringID;
27895 } else if (stringID.length === 2) {
27896 stringID = "0" + stringID;
27899 stringID = canonicalID(id);
27902 return featuresByCode[stringID] || null;
27905 function smallestFeaturesForBbox(bbox) {
27906 return whichPolygonGetter.bbox(bbox).map(function (props) {
27907 return featuresByCode[props.id];
27911 function smallestOrMatchingFeature(query) {
27912 if (_typeof(query) === "object") {
27913 return smallestFeature(query);
27916 return featureForID(query);
27919 function feature$1(query) {
27920 var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultOpts;
27922 if (_typeof(query) === "object") {
27923 return featureForLoc(query, opts);
27926 return featureForID(query);
27929 function iso1A2Code(query) {
27930 var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultOpts;
27931 opts.withProp = "iso1A2";
27932 var match = feature$1(query, opts);
27933 if (!match) return null;
27934 return match.properties.iso1A2 || null;
27937 function featuresContaining(query, strict) {
27938 var matchingFeatures;
27940 if (Array.isArray(query) && query.length === 4) {
27941 matchingFeatures = smallestFeaturesForBbox(query);
27943 var smallestOrMatching = smallestOrMatchingFeature(query);
27944 matchingFeatures = smallestOrMatching ? [smallestOrMatching] : [];
27947 if (!matchingFeatures.length) return [];
27948 var returnFeatures;
27950 if (!strict || _typeof(query) === "object") {
27951 returnFeatures = matchingFeatures.slice();
27953 returnFeatures = [];
27956 for (var j in matchingFeatures) {
27957 var properties = matchingFeatures[j].properties;
27959 for (var i in properties.groups) {
27960 var groupID = properties.groups[i];
27961 var groupFeature = featuresByCode[groupID];
27963 if (returnFeatures.indexOf(groupFeature) === -1) {
27964 returnFeatures.push(groupFeature);
27969 return returnFeatures;
27972 function featuresIn(id, strict) {
27973 var feature2 = featureForID(id);
27974 if (!feature2) return [];
27975 var features2 = [];
27978 features2.push(feature2);
27981 var properties = feature2.properties;
27983 if (properties.members) {
27984 for (var i in properties.members) {
27985 var memberID = properties.members[i];
27986 features2.push(featuresByCode[memberID]);
27993 function aggregateFeature(id) {
27994 var features2 = featuresIn(id, false);
27995 if (features2.length === 0) return null;
27996 var aggregateCoordinates = [];
27998 for (var i in features2) {
27999 var feature2 = features2[i];
28001 if (feature2.geometry && feature2.geometry.type === "MultiPolygon" && feature2.geometry.coordinates) {
28002 aggregateCoordinates = aggregateCoordinates.concat(feature2.geometry.coordinates);
28008 properties: features2[0].properties,
28010 type: "MultiPolygon",
28011 coordinates: aggregateCoordinates
28016 function roadSpeedUnit(query) {
28017 var feature2 = smallestOrMatchingFeature(query);
28018 return feature2 && feature2.properties.roadSpeedUnit || null;
28021 function roadHeightUnit(query) {
28022 var feature2 = smallestOrMatchingFeature(query);
28023 return feature2 && feature2.properties.roadHeightUnit || null;
28026 var geojsonArea = {};
28030 wgs84$1.RADIUS = 6378137;
28031 wgs84$1.FLATTENING = 1 / 298.257223563;
28032 wgs84$1.POLAR_RADIUS = 6356752.3142;
28034 var wgs84 = wgs84$1;
28035 geojsonArea.geometry = geometry;
28036 geojsonArea.ring = ringArea;
28038 function geometry(_) {
28044 return polygonArea(_.coordinates);
28046 case 'MultiPolygon':
28047 for (i = 0; i < _.coordinates.length; i++) {
28048 area += polygonArea(_.coordinates[i]);
28056 case 'MultiLineString':
28059 case 'GeometryCollection':
28060 for (i = 0; i < _.geometries.length; i++) {
28061 area += geometry(_.geometries[i]);
28068 function polygonArea(coords) {
28071 if (coords && coords.length > 0) {
28072 area += Math.abs(ringArea(coords[0]));
28074 for (var i = 1; i < coords.length; i++) {
28075 area -= Math.abs(ringArea(coords[i]));
28082 * Calculate the approximate area of the polygon were it projected onto
28083 * the earth. Note that this area will be positive if ring is oriented
28084 * clockwise, otherwise it will be negative.
28087 * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
28088 * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
28089 * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
28092 * {float} The approximate signed geodesic area of the polygon in square
28097 function ringArea(coords) {
28106 coordsLength = coords.length;
28108 if (coordsLength > 2) {
28109 for (i = 0; i < coordsLength; i++) {
28110 if (i === coordsLength - 2) {
28112 lowerIndex = coordsLength - 2;
28113 middleIndex = coordsLength - 1;
28115 } else if (i === coordsLength - 1) {
28117 lowerIndex = coordsLength - 1;
28123 middleIndex = i + 1;
28124 upperIndex = i + 2;
28127 p1 = coords[lowerIndex];
28128 p2 = coords[middleIndex];
28129 p3 = coords[upperIndex];
28130 area += (rad(p3[0]) - rad(p1[0])) * Math.sin(rad(p2[1]));
28133 area = area * wgs84.RADIUS * wgs84.RADIUS / 2;
28140 return _ * Math.PI / 180;
28143 var inputValidation = {};
28146 var $includes = arrayIncludes.includes;
28147 var addToUnscopables$2 = addToUnscopables$6;
28149 // `Array.prototype.includes` method
28150 // https://tc39.es/ecma262/#sec-array.prototype.includes
28151 $$n({ target: 'Array', proto: true }, {
28152 includes: function includes(el /* , fromIndex = 0 */) {
28153 return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
28157 // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
28158 addToUnscopables$2('includes');
28160 var validateCenter$1 = {};
28162 validateCenter$1.validateCenter = function validateCenter(center) {
28163 var validCenterLengths = [2, 3];
28165 if (!Array.isArray(center) || !validCenterLengths.includes(center.length)) {
28166 throw new Error("ERROR! Center has to be an array of length two or three");
28169 var _center = _slicedToArray(center, 2),
28173 if (typeof lng !== "number" || typeof lat !== "number") {
28174 throw new Error("ERROR! Longitude and Latitude has to be numbers but where ".concat(_typeof(lng), " and ").concat(_typeof(lat)));
28177 if (lng > 180 || lng < -180) {
28178 throw new Error("ERROR! Longitude has to be between -180 and 180 but was ".concat(lng));
28181 if (lat > 90 || lat < -90) {
28182 throw new Error("ERROR! Latitude has to be between -90 and 90 but was ".concat(lat));
28186 var validateRadius$1 = {};
28188 validateRadius$1.validateRadius = function validateRadius(radius) {
28189 if (typeof radius !== "number") {
28190 throw new Error("ERROR! Radius has to be a positive number but was: ".concat(_typeof(radius)));
28194 throw new Error("ERROR! Radius has to be a positive number but was: ".concat(radius));
28198 var validateNumberOfEdges$1 = {};
28200 validateNumberOfEdges$1.validateNumberOfEdges = function validateNumberOfEdges(numberOfEdges) {
28201 if (typeof numberOfEdges !== "number") {
28202 var ARGUMENT_TYPE = Array.isArray(numberOfEdges) ? "array" : _typeof(numberOfEdges);
28203 throw new Error("ERROR! Number of edges has to be a number but was: ".concat(ARGUMENT_TYPE));
28206 if (numberOfEdges < 3) {
28207 throw new Error("ERROR! Number of edges has to be at least 3 but was: ".concat(numberOfEdges));
28211 var validateEarthRadius$1 = {};
28213 validateEarthRadius$1.validateEarthRadius = function validateEarthRadius(earthRadius) {
28214 if (typeof earthRadius !== "number") {
28215 var ARGUMENT_TYPE = Array.isArray(earthRadius) ? "array" : _typeof(earthRadius);
28216 throw new Error("ERROR! Earth radius has to be a number but was: ".concat(ARGUMENT_TYPE));
28219 if (earthRadius <= 0) {
28220 throw new Error("ERROR! Earth radius has to be a positive number but was: ".concat(earthRadius));
28224 var validateBearing$1 = {};
28226 validateBearing$1.validateBearing = function validateBearing(bearing) {
28227 if (typeof bearing !== "number") {
28228 var ARGUMENT_TYPE = Array.isArray(bearing) ? "array" : _typeof(bearing);
28229 throw new Error("ERROR! Bearing has to be a number but was: ".concat(ARGUMENT_TYPE));
28233 var validateCenter = validateCenter$1.validateCenter;
28234 var validateRadius = validateRadius$1.validateRadius;
28235 var validateNumberOfEdges = validateNumberOfEdges$1.validateNumberOfEdges;
28236 var validateEarthRadius = validateEarthRadius$1.validateEarthRadius;
28237 var validateBearing = validateBearing$1.validateBearing;
28239 function validateInput$1(_ref) {
28240 var center = _ref.center,
28241 radius = _ref.radius,
28242 numberOfEdges = _ref.numberOfEdges,
28243 earthRadius = _ref.earthRadius,
28244 bearing = _ref.bearing;
28245 validateCenter(center);
28246 validateRadius(radius);
28247 validateNumberOfEdges(numberOfEdges);
28248 validateEarthRadius(earthRadius);
28249 validateBearing(bearing);
28252 inputValidation.validateCenter = validateCenter;
28253 inputValidation.validateRadius = validateRadius;
28254 inputValidation.validateNumberOfEdges = validateNumberOfEdges;
28255 inputValidation.validateEarthRadius = validateEarthRadius;
28256 inputValidation.validateBearing = validateBearing;
28257 inputValidation.validateInput = validateInput$1;
28259 var validateInput = inputValidation.validateInput;
28260 var defaultEarthRadius = 6378137; // equatorial Earth radius
28262 function toRadians(angleInDegrees) {
28263 return angleInDegrees * Math.PI / 180;
28266 function toDegrees(angleInRadians) {
28267 return angleInRadians * 180 / Math.PI;
28270 function offset(c1, distance, earthRadius, bearing) {
28271 var lat1 = toRadians(c1[1]);
28272 var lon1 = toRadians(c1[0]);
28273 var dByR = distance / earthRadius;
28274 var lat = Math.asin(Math.sin(lat1) * Math.cos(dByR) + Math.cos(lat1) * Math.sin(dByR) * Math.cos(bearing));
28275 var lon = lon1 + Math.atan2(Math.sin(bearing) * Math.sin(dByR) * Math.cos(lat1), Math.cos(dByR) - Math.sin(lat1) * Math.sin(lat));
28276 return [toDegrees(lon), toDegrees(lat)];
28279 var circleToPolygon = function circleToPolygon(center, radius, options) {
28280 var n = getNumberOfEdges(options);
28281 var earthRadius = getEarthRadius(options);
28282 var bearing = getBearing(options);
28283 var direction = getDirection(options); // validateInput() throws error on invalid input and do nothing on valid input
28289 earthRadius: earthRadius,
28292 var start = toRadians(bearing);
28293 var coordinates = [];
28295 for (var i = 0; i < n; ++i) {
28296 coordinates.push(offset(center, radius, earthRadius, start + direction * 2 * Math.PI * -i / n));
28299 coordinates.push(coordinates[0]);
28302 coordinates: [coordinates]
28306 function getNumberOfEdges(options) {
28307 if (isUndefinedOrNull(options)) {
28309 } else if (isObjectNotArray(options)) {
28310 var numberOfEdges = options.numberOfEdges;
28311 return numberOfEdges === undefined ? 32 : numberOfEdges;
28317 function getEarthRadius(options) {
28318 if (isUndefinedOrNull(options)) {
28319 return defaultEarthRadius;
28320 } else if (isObjectNotArray(options)) {
28321 var earthRadius = options.earthRadius;
28322 return earthRadius === undefined ? defaultEarthRadius : earthRadius;
28325 return defaultEarthRadius;
28328 function getDirection(options) {
28329 if (isObjectNotArray(options) && options.rightHandRule) {
28336 function getBearing(options) {
28337 if (isUndefinedOrNull(options)) {
28339 } else if (isObjectNotArray(options)) {
28340 var bearing = options.bearing;
28341 return bearing === undefined ? 0 : bearing;
28347 function isObjectNotArray(argument) {
28348 return argument !== null && _typeof(argument) === "object" && !Array.isArray(argument);
28351 function isUndefinedOrNull(argument) {
28352 return argument === null || argument === undefined;
28357 // `Number.EPSILON` constant
28358 // https://tc39.es/ecma262/#sec-number.epsilon
28359 $$m({ target: 'Number', stat: true }, {
28360 EPSILON: Math.pow(2, -52)
28363 var uncurryThis$8 = functionUncurryThis;
28364 var requireObjectCoercible$4 = requireObjectCoercible$e;
28365 var toString$5 = toString$k;
28368 var replace$2 = uncurryThis$8(''.replace);
28370 // `CreateHTML` abstract operation
28371 // https://tc39.es/ecma262/#sec-createhtml
28372 var createHtml = function (string, tag, attribute, value) {
28373 var S = toString$5(requireObjectCoercible$4(string));
28374 var p1 = '<' + tag;
28375 if (attribute !== '') p1 += ' ' + attribute + '="' + replace$2(toString$5(value), quot, '"') + '"';
28376 return p1 + '>' + S + '</' + tag + '>';
28379 var fails$6 = fails$V;
28381 // check the existence of a method, lowercase
28382 // of a tag and escaping quotes in arguments
28383 var stringHtmlForced = function (METHOD_NAME) {
28384 return fails$6(function () {
28385 var test = ''[METHOD_NAME]('"');
28386 return test !== test.toLowerCase() || test.split('"').length > 3;
28391 var createHTML = createHtml;
28392 var forcedStringHTMLMethod = stringHtmlForced;
28394 // `String.prototype.link` method
28395 // https://tc39.es/ecma262/#sec-string.prototype.link
28396 $$l({ target: 'String', proto: true, forced: forcedStringHTMLMethod('link') }, {
28397 link: function link(url) {
28398 return createHTML(this, 'a', 'href', url);
28404 * Fast Splay tree for Node and browser
28406 * @author Alexander Milevski <info@w8r.name>
28413 function Node(key, data) {
28423 /* follows "An implementation of top-down splaying"
28424 * by D. Sleator <sleator@cs.cmu.edu> March 1992
28428 function DEFAULT_COMPARE(a, b) {
28429 return a > b ? 1 : a < b ? -1 : 0;
28432 * Simple top down splay, not requiring i to be in the tree t.
28436 function splay(i, t, comparator) {
28437 var N = new Node(null, null);
28442 var cmp = comparator(i, t.key); //if (i < t.key) {
28445 if (t.left === null) break; //if (i < t.left.key) {
28447 if (comparator(i, t.left.key) < 0) {
28454 if (t.left === null) break;
28461 t = t.left; //} else if (i > t.key) {
28462 } else if (cmp > 0) {
28463 if (t.right === null) break; //if (i > t.right.key) {
28465 if (comparator(i, t.right.key) > 0) {
28472 if (t.right === null) break;
28492 function insert(i, data, t, comparator) {
28493 var node = new Node(i, data);
28496 node.left = node.right = null;
28500 t = splay(i, t, comparator);
28501 var cmp = comparator(i, t.key);
28504 node.left = t.left;
28507 } else if (cmp >= 0) {
28508 node.right = t.right;
28516 function split$2(key, v, comparator) {
28521 v = splay(key, v, comparator);
28522 var cmp = comparator(v.key, key);
28527 } else if (cmp < 0) {
28544 function merge$3(left, right, comparator) {
28545 if (right === null) return left;
28546 if (left === null) return right;
28547 right = splay(left.key, right, comparator);
28552 * Prints level of the tree
28556 function printRow(root, prefix, isTail, out, printNode) {
28558 out("" + prefix + (isTail ? '└── ' : '├── ') + printNode(root) + "\n");
28559 var indent = prefix + (isTail ? ' ' : '│ ');
28560 if (root.left) printRow(root.left, indent, false, out, printNode);
28561 if (root.right) printRow(root.right, indent, true, out, printNode);
28568 function Tree(comparator) {
28569 if (comparator === void 0) {
28570 comparator = DEFAULT_COMPARE;
28575 this._comparator = comparator;
28578 * Inserts a key, allows duplicates
28582 Tree.prototype.insert = function (key, data) {
28584 return this._root = insert(key, data, this._root, this._comparator);
28587 * Adds a key, if it is not present in the tree
28591 Tree.prototype.add = function (key, data) {
28592 var node = new Node(key, data);
28594 if (this._root === null) {
28595 node.left = node.right = null;
28600 var comparator = this._comparator;
28601 var t = splay(key, this._root, comparator);
28602 var cmp = comparator(key, t.key);
28603 if (cmp === 0) this._root = t;else {
28605 node.left = t.left;
28608 } else if (cmp > 0) {
28609 node.right = t.right;
28621 * @return {Node|null}
28625 Tree.prototype.remove = function (key) {
28626 this._root = this._remove(key, this._root, this._comparator);
28629 * Deletes i from the tree if it's there
28633 Tree.prototype._remove = function (i, t, comparator) {
28635 if (t === null) return null;
28636 t = splay(i, t, comparator);
28637 var cmp = comparator(i, t.key);
28641 if (t.left === null) {
28644 x = splay(i, t.left, comparator);
28653 /* It wasn't there */
28656 * Removes and returns the node with smallest key
28660 Tree.prototype.pop = function () {
28661 var node = this._root;
28664 while (node.left) {
28668 this._root = splay(node.key, this._root, this._comparator);
28669 this._root = this._remove(node.key, this._root, this._comparator);
28679 * Find without splaying
28683 Tree.prototype.findStatic = function (key) {
28684 var current = this._root;
28685 var compare = this._comparator;
28688 var cmp = compare(key, current.key);
28689 if (cmp === 0) return current;else if (cmp < 0) current = current.left;else current = current.right;
28695 Tree.prototype.find = function (key) {
28697 this._root = splay(key, this._root, this._comparator);
28698 if (this._comparator(key, this._root.key) !== 0) return null;
28704 Tree.prototype.contains = function (key) {
28705 var current = this._root;
28706 var compare = this._comparator;
28709 var cmp = compare(key, current.key);
28710 if (cmp === 0) return true;else if (cmp < 0) current = current.left;else current = current.right;
28716 Tree.prototype.forEach = function (visitor, ctx) {
28717 var current = this._root;
28719 /* Initialize stack s */
28724 if (current !== null) {
28726 current = current.left;
28728 if (Q.length !== 0) {
28730 visitor.call(ctx, current);
28731 current = current.right;
28732 } else done = true;
28739 * Walk key range from `low` to `high`. Stops if `fn` returns a value.
28743 Tree.prototype.range = function (low, high, fn, ctx) {
28745 var compare = this._comparator;
28746 var node = this._root;
28749 while (Q.length !== 0 || node) {
28755 cmp = compare(node.key, high);
28759 } else if (compare(node.key, low) >= 0) {
28760 if (fn.call(ctx, node)) return this; // stop if smth is returned
28770 * Returns array of keys
28774 Tree.prototype.keys = function () {
28776 this.forEach(function (_a) {
28778 return keys.push(key);
28783 * Returns array of all the data in the nodes
28787 Tree.prototype.values = function () {
28789 this.forEach(function (_a) {
28790 var data = _a.data;
28791 return values.push(data);
28796 Tree.prototype.min = function () {
28797 if (this._root) return this.minNode(this._root).key;
28801 Tree.prototype.max = function () {
28802 if (this._root) return this.maxNode(this._root).key;
28806 Tree.prototype.minNode = function (t) {
28807 if (t === void 0) {
28811 if (t) while (t.left) {
28817 Tree.prototype.maxNode = function (t) {
28818 if (t === void 0) {
28822 if (t) while (t.right) {
28828 * Returns node at given index
28832 Tree.prototype.at = function (index) {
28833 var current = this._root;
28841 current = current.left;
28843 if (Q.length > 0) {
28845 if (i === index) return current;
28847 current = current.right;
28848 } else done = true;
28855 Tree.prototype.next = function (d) {
28856 var root = this._root;
28857 var successor = null;
28860 successor = d.right;
28862 while (successor.left) {
28863 successor = successor.left;
28869 var comparator = this._comparator;
28872 var cmp = comparator(d.key, root.key);
28873 if (cmp === 0) break;else if (cmp < 0) {
28876 } else root = root.right;
28882 Tree.prototype.prev = function (d) {
28883 var root = this._root;
28884 var predecessor = null;
28886 if (d.left !== null) {
28887 predecessor = d.left;
28889 while (predecessor.right) {
28890 predecessor = predecessor.right;
28893 return predecessor;
28896 var comparator = this._comparator;
28899 var cmp = comparator(d.key, root.key);
28900 if (cmp === 0) break;else if (cmp < 0) root = root.left;else {
28901 predecessor = root;
28906 return predecessor;
28909 Tree.prototype.clear = function () {
28915 Tree.prototype.toList = function () {
28916 return toList(this._root);
28919 * Bulk-load items. Both array have to be same size
28923 Tree.prototype.load = function (keys, values, presort) {
28924 if (values === void 0) {
28928 if (presort === void 0) {
28932 var size = keys.length;
28933 var comparator = this._comparator; // sort if needed
28935 if (presort) sort(keys, values, 0, size - 1, comparator);
28937 if (this._root === null) {
28939 this._root = loadRecursive(keys, values, 0, size);
28942 // that re-builds the whole tree from two in-order traversals
28943 var mergedList = mergeLists(this.toList(), createList(keys, values), comparator);
28944 size = this._size + size;
28945 this._root = sortedListToBST({
28953 Tree.prototype.isEmpty = function () {
28954 return this._root === null;
28957 Object.defineProperty(Tree.prototype, "size", {
28958 get: function get() {
28964 Object.defineProperty(Tree.prototype, "root", {
28965 get: function get() {
28972 Tree.prototype.toString = function (printNode) {
28973 if (printNode === void 0) {
28974 printNode = function printNode(n) {
28975 return String(n.key);
28980 printRow(this._root, '', true, function (v) {
28981 return out.push(v);
28983 return out.join('');
28986 Tree.prototype.update = function (key, newKey, newData) {
28987 var comparator = this._comparator;
28989 var _a = split$2(key, this._root, comparator),
28993 if (comparator(key, newKey) < 0) {
28994 right = insert(newKey, newData, right, comparator);
28996 left = insert(newKey, newData, left, comparator);
28999 this._root = merge$3(left, right, comparator);
29002 Tree.prototype.split = function (key) {
29003 return split$2(key, this._root, this._comparator);
29009 function loadRecursive(keys, values, start, end) {
29010 var size = end - start;
29013 var middle = start + Math.floor(size / 2);
29014 var key = keys[middle];
29015 var data = values[middle];
29016 var node = new Node(key, data);
29017 node.left = loadRecursive(keys, values, start, middle);
29018 node.right = loadRecursive(keys, values, middle + 1, end);
29025 function createList(keys, values) {
29026 var head = new Node(null, null);
29029 for (var i = 0; i < keys.length; i++) {
29030 p = p.next = new Node(keys[i], values[i]);
29037 function toList(root) {
29038 var current = root;
29041 var head = new Node(null, null);
29047 current = current.left;
29049 if (Q.length > 0) {
29050 current = p = p.next = Q.pop();
29051 current = current.right;
29052 } else done = true;
29056 p.next = null; // that'll work even if the tree was empty
29061 function sortedListToBST(list, start, end) {
29062 var size = end - start;
29065 var middle = start + Math.floor(size / 2);
29066 var left = sortedListToBST(list, start, middle);
29067 var root = list.head;
29069 list.head = list.head.next;
29070 root.right = sortedListToBST(list, middle + 1, end);
29077 function mergeLists(l1, l2, compare) {
29078 var head = new Node(null, null); // dummy
29084 while (p1 !== null && p2 !== null) {
29085 if (compare(p1.key, p2.key) < 0) {
29098 } else if (p2 !== null) {
29105 function sort(keys, values, left, right, compare) {
29106 if (left >= right) return;
29107 var pivot = keys[left + right >> 1];
29114 } while (compare(keys[i], pivot) < 0);
29118 } while (compare(keys[j], pivot) > 0);
29125 values[i] = values[j];
29129 sort(keys, values, left, j, compare);
29130 sort(keys, values, j + 1, right, compare);
29133 function _classCallCheck(instance, Constructor) {
29134 if (!(instance instanceof Constructor)) {
29135 throw new TypeError("Cannot call a class as a function");
29139 function _defineProperties(target, props) {
29140 for (var i = 0; i < props.length; i++) {
29141 var descriptor = props[i];
29142 descriptor.enumerable = descriptor.enumerable || false;
29143 descriptor.configurable = true;
29144 if ("value" in descriptor) descriptor.writable = true;
29145 Object.defineProperty(target, descriptor.key, descriptor);
29149 function _createClass(Constructor, protoProps, staticProps) {
29150 if (protoProps) _defineProperties(Constructor.prototype, protoProps);
29151 if (staticProps) _defineProperties(Constructor, staticProps);
29152 return Constructor;
29155 * A bounding box has the format:
29157 * { ll: { x: xmin, y: ymin }, ur: { x: xmax, y: ymax } }
29162 var isInBbox = function isInBbox(bbox, point) {
29163 return bbox.ll.x <= point.x && point.x <= bbox.ur.x && bbox.ll.y <= point.y && point.y <= bbox.ur.y;
29165 /* Returns either null, or a bbox (aka an ordered pair of points)
29166 * If there is only one point of overlap, a bbox with identical points
29167 * will be returned */
29170 var getBboxOverlap = function getBboxOverlap(b1, b2) {
29171 // check if the bboxes overlap at all
29172 if (b2.ur.x < b1.ll.x || b1.ur.x < b2.ll.x || b2.ur.y < b1.ll.y || b1.ur.y < b2.ll.y) return null; // find the middle two X values
29174 var lowerX = b1.ll.x < b2.ll.x ? b2.ll.x : b1.ll.x;
29175 var upperX = b1.ur.x < b2.ur.x ? b1.ur.x : b2.ur.x; // find the middle two Y values
29177 var lowerY = b1.ll.y < b2.ll.y ? b2.ll.y : b1.ll.y;
29178 var upperY = b1.ur.y < b2.ur.y ? b1.ur.y : b2.ur.y; // put those middle values together to get the overlap
29191 /* Javascript doesn't do integer math. Everything is
29192 * floating point with percision Number.EPSILON.
29194 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON
29198 var epsilon = Number.EPSILON; // IE Polyfill
29200 if (epsilon === undefined) epsilon = Math.pow(2, -52);
29201 var EPSILON_SQ = epsilon * epsilon;
29202 /* FLP comparator */
29204 var cmp = function cmp(a, b) {
29205 // check if they're both 0
29206 if (-epsilon < a && a < epsilon) {
29207 if (-epsilon < b && b < epsilon) {
29210 } // check if they're flp equal
29215 if (ab * ab < EPSILON_SQ * a * b) {
29217 } // normal comparison
29220 return a < b ? -1 : 1;
29223 * This class rounds incoming values sufficiently so that
29224 * floating points problems are, for the most part, avoided.
29226 * Incoming points are have their x & y values tested against
29227 * all previously seen x & y values. If either is 'too close'
29228 * to a previously seen value, it's value is 'snapped' to the
29229 * previously seen value.
29231 * All points should be rounded by this class before being
29232 * stored in any data structures in the rest of this algorithm.
29236 var PtRounder = /*#__PURE__*/function () {
29237 function PtRounder() {
29238 _classCallCheck(this, PtRounder);
29243 _createClass(PtRounder, [{
29245 value: function reset() {
29246 this.xRounder = new CoordRounder();
29247 this.yRounder = new CoordRounder();
29251 value: function round(x, y) {
29253 x: this.xRounder.round(x),
29254 y: this.yRounder.round(y)
29262 var CoordRounder = /*#__PURE__*/function () {
29263 function CoordRounder() {
29264 _classCallCheck(this, CoordRounder);
29266 this.tree = new Tree(); // preseed with 0 so we don't end up with values < Number.EPSILON
29269 } // Note: this can rounds input values backwards or forwards.
29270 // You might ask, why not restrict this to just rounding
29271 // forwards? Wouldn't that allow left endpoints to always
29272 // remain left endpoints during splitting (never change to
29273 // right). No - it wouldn't, because we snap intersections
29274 // to endpoints (to establish independence from the segment
29275 // angle for t-intersections).
29278 _createClass(CoordRounder, [{
29280 value: function round(coord) {
29281 var node = this.tree.add(coord);
29282 var prevNode = this.tree.prev(node);
29284 if (prevNode !== null && cmp(node.key, prevNode.key) === 0) {
29285 this.tree.remove(coord);
29286 return prevNode.key;
29289 var nextNode = this.tree.next(node);
29291 if (nextNode !== null && cmp(node.key, nextNode.key) === 0) {
29292 this.tree.remove(coord);
29293 return nextNode.key;
29300 return CoordRounder;
29301 }(); // singleton available by import
29304 var rounder = new PtRounder();
29305 /* Cross Product of two vectors with first point at origin */
29307 var crossProduct = function crossProduct(a, b) {
29308 return a.x * b.y - a.y * b.x;
29310 /* Dot Product of two vectors with first point at origin */
29313 var dotProduct = function dotProduct(a, b) {
29314 return a.x * b.x + a.y * b.y;
29316 /* Comparator for two vectors with same starting point */
29319 var compareVectorAngles = function compareVectorAngles(basePt, endPt1, endPt2) {
29321 x: endPt1.x - basePt.x,
29322 y: endPt1.y - basePt.y
29325 x: endPt2.x - basePt.x,
29326 y: endPt2.y - basePt.y
29328 var kross = crossProduct(v1, v2);
29329 return cmp(kross, 0);
29332 var length = function length(v) {
29333 return Math.sqrt(dotProduct(v, v));
29335 /* Get the sine of the angle from pShared -> pAngle to pShaed -> pBase */
29338 var sineOfAngle = function sineOfAngle(pShared, pBase, pAngle) {
29340 x: pBase.x - pShared.x,
29341 y: pBase.y - pShared.y
29344 x: pAngle.x - pShared.x,
29345 y: pAngle.y - pShared.y
29347 return crossProduct(vAngle, vBase) / length(vAngle) / length(vBase);
29349 /* Get the cosine of the angle from pShared -> pAngle to pShaed -> pBase */
29352 var cosineOfAngle = function cosineOfAngle(pShared, pBase, pAngle) {
29354 x: pBase.x - pShared.x,
29355 y: pBase.y - pShared.y
29358 x: pAngle.x - pShared.x,
29359 y: pAngle.y - pShared.y
29361 return dotProduct(vAngle, vBase) / length(vAngle) / length(vBase);
29363 /* Get the x coordinate where the given line (defined by a point and vector)
29364 * crosses the horizontal line with the given y coordiante.
29365 * In the case of parrallel lines (including overlapping ones) returns null. */
29368 var horizontalIntersection = function horizontalIntersection(pt, v, y) {
29369 if (v.y === 0) return null;
29371 x: pt.x + v.x / v.y * (y - pt.y),
29375 /* Get the y coordinate where the given line (defined by a point and vector)
29376 * crosses the vertical line with the given x coordiante.
29377 * In the case of parrallel lines (including overlapping ones) returns null. */
29380 var verticalIntersection = function verticalIntersection(pt, v, x) {
29381 if (v.x === 0) return null;
29384 y: pt.y + v.y / v.x * (x - pt.x)
29387 /* Get the intersection of two lines, each defined by a base point and a vector.
29388 * In the case of parrallel lines (including overlapping ones) returns null. */
29391 var intersection = function intersection(pt1, v1, pt2, v2) {
29392 // take some shortcuts for vertical and horizontal lines
29393 // this also ensures we don't calculate an intersection and then discover
29394 // it's actually outside the bounding box of the line
29395 if (v1.x === 0) return verticalIntersection(pt2, v2, pt1.x);
29396 if (v2.x === 0) return verticalIntersection(pt1, v1, pt2.x);
29397 if (v1.y === 0) return horizontalIntersection(pt2, v2, pt1.y);
29398 if (v2.y === 0) return horizontalIntersection(pt1, v1, pt2.y); // General case for non-overlapping segments.
29399 // This algorithm is based on Schneider and Eberly.
29400 // http://www.cimec.org.ar/~ncalvo/Schneider_Eberly.pdf - pg 244
29402 var kross = crossProduct(v1, v2);
29403 if (kross == 0) return null;
29408 var d1 = crossProduct(ve, v1) / kross;
29409 var d2 = crossProduct(ve, v2) / kross; // take the average of the two calculations to minimize rounding error
29411 var x1 = pt1.x + d2 * v1.x,
29412 x2 = pt2.x + d1 * v2.x;
29413 var y1 = pt1.y + d2 * v1.y,
29414 y2 = pt2.y + d1 * v2.y;
29415 var x = (x1 + x2) / 2;
29416 var y = (y1 + y2) / 2;
29423 var SweepEvent = /*#__PURE__*/function () {
29424 _createClass(SweepEvent, null, [{
29426 // for ordering sweep events in the sweep event queue
29427 value: function compare(a, b) {
29428 // favor event with a point that the sweep line hits first
29429 var ptCmp = SweepEvent.comparePoints(a.point, b.point);
29430 if (ptCmp !== 0) return ptCmp; // the points are the same, so link them if needed
29432 if (a.point !== b.point) a.link(b); // favor right events over left
29434 if (a.isLeft !== b.isLeft) return a.isLeft ? 1 : -1; // we have two matching left or right endpoints
29435 // ordering of this case is the same as for their segments
29437 return Segment.compare(a.segment, b.segment);
29438 } // for ordering points in sweep line order
29441 key: "comparePoints",
29442 value: function comparePoints(aPt, bPt) {
29443 if (aPt.x < bPt.x) return -1;
29444 if (aPt.x > bPt.x) return 1;
29445 if (aPt.y < bPt.y) return -1;
29446 if (aPt.y > bPt.y) return 1;
29448 } // Warning: 'point' input will be modified and re-used (for performance)
29452 function SweepEvent(point, isLeft) {
29453 _classCallCheck(this, SweepEvent);
29455 if (point.events === undefined) point.events = [this];else point.events.push(this);
29456 this.point = point;
29457 this.isLeft = isLeft; // this.segment, this.otherSE set by factory
29460 _createClass(SweepEvent, [{
29462 value: function link(other) {
29463 if (other.point === this.point) {
29464 throw new Error('Tried to link already linked events');
29467 var otherEvents = other.point.events;
29469 for (var i = 0, iMax = otherEvents.length; i < iMax; i++) {
29470 var evt = otherEvents[i];
29471 this.point.events.push(evt);
29472 evt.point = this.point;
29475 this.checkForConsuming();
29477 /* Do a pass over our linked events and check to see if any pair
29478 * of segments match, and should be consumed. */
29481 key: "checkForConsuming",
29482 value: function checkForConsuming() {
29483 // FIXME: The loops in this method run O(n^2) => no good.
29484 // Maintain little ordered sweep event trees?
29485 // Can we maintaining an ordering that avoids the need
29486 // for the re-sorting with getLeftmostComparator in geom-out?
29487 // Compare each pair of events to see if other events also match
29488 var numEvents = this.point.events.length;
29490 for (var i = 0; i < numEvents; i++) {
29491 var evt1 = this.point.events[i];
29492 if (evt1.segment.consumedBy !== undefined) continue;
29494 for (var j = i + 1; j < numEvents; j++) {
29495 var evt2 = this.point.events[j];
29496 if (evt2.consumedBy !== undefined) continue;
29497 if (evt1.otherSE.point.events !== evt2.otherSE.point.events) continue;
29498 evt1.segment.consume(evt2.segment);
29503 key: "getAvailableLinkedEvents",
29504 value: function getAvailableLinkedEvents() {
29505 // point.events is always of length 2 or greater
29508 for (var i = 0, iMax = this.point.events.length; i < iMax; i++) {
29509 var evt = this.point.events[i];
29511 if (evt !== this && !evt.segment.ringOut && evt.segment.isInResult()) {
29519 * Returns a comparator function for sorting linked events that will
29520 * favor the event that will give us the smallest left-side angle.
29521 * All ring construction starts as low as possible heading to the right,
29522 * so by always turning left as sharp as possible we'll get polygons
29523 * without uncessary loops & holes.
29525 * The comparator function has a compute cache such that it avoids
29526 * re-computing already-computed values.
29530 key: "getLeftmostComparator",
29531 value: function getLeftmostComparator(baseEvent) {
29534 var cache = new Map();
29536 var fillCache = function fillCache(linkedEvent) {
29537 var nextEvent = linkedEvent.otherSE;
29538 cache.set(linkedEvent, {
29539 sine: sineOfAngle(_this.point, baseEvent.point, nextEvent.point),
29540 cosine: cosineOfAngle(_this.point, baseEvent.point, nextEvent.point)
29544 return function (a, b) {
29545 if (!cache.has(a)) fillCache(a);
29546 if (!cache.has(b)) fillCache(b);
29548 var _cache$get = cache.get(a),
29549 asine = _cache$get.sine,
29550 acosine = _cache$get.cosine;
29552 var _cache$get2 = cache.get(b),
29553 bsine = _cache$get2.sine,
29554 bcosine = _cache$get2.cosine; // both on or above x-axis
29557 if (asine >= 0 && bsine >= 0) {
29558 if (acosine < bcosine) return 1;
29559 if (acosine > bcosine) return -1;
29561 } // both below x-axis
29564 if (asine < 0 && bsine < 0) {
29565 if (acosine < bcosine) return -1;
29566 if (acosine > bcosine) return 1;
29568 } // one above x-axis, one below
29571 if (bsine < asine) return -1;
29572 if (bsine > asine) return 1;
29579 }(); // segments and sweep events when all else is identical
29584 var Segment = /*#__PURE__*/function () {
29585 _createClass(Segment, null, [{
29588 /* This compare() function is for ordering segments in the sweep
29589 * line tree, and does so according to the following criteria:
29591 * Consider the vertical line that lies an infinestimal step to the
29592 * right of the right-more of the two left endpoints of the input
29593 * segments. Imagine slowly moving a point up from negative infinity
29594 * in the increasing y direction. Which of the two segments will that
29595 * point intersect first? That segment comes 'before' the other one.
29597 * If neither segment would be intersected by such a line, (if one
29598 * or more of the segments are vertical) then the line to be considered
29599 * is directly on the right-more of the two left inputs.
29601 value: function compare(a, b) {
29602 var alx = a.leftSE.point.x;
29603 var blx = b.leftSE.point.x;
29604 var arx = a.rightSE.point.x;
29605 var brx = b.rightSE.point.x; // check if they're even in the same vertical plane
29607 if (brx < alx) return 1;
29608 if (arx < blx) return -1;
29609 var aly = a.leftSE.point.y;
29610 var bly = b.leftSE.point.y;
29611 var ary = a.rightSE.point.y;
29612 var bry = b.rightSE.point.y; // is left endpoint of segment B the right-more?
29615 // are the two segments in the same horizontal plane?
29616 if (bly < aly && bly < ary) return 1;
29617 if (bly > aly && bly > ary) return -1; // is the B left endpoint colinear to segment A?
29619 var aCmpBLeft = a.comparePoint(b.leftSE.point);
29620 if (aCmpBLeft < 0) return 1;
29621 if (aCmpBLeft > 0) return -1; // is the A right endpoint colinear to segment B ?
29623 var bCmpARight = b.comparePoint(a.rightSE.point);
29624 if (bCmpARight !== 0) return bCmpARight; // colinear segments, consider the one with left-more
29625 // left endpoint to be first (arbitrary?)
29628 } // is left endpoint of segment A the right-more?
29632 if (aly < bly && aly < bry) return -1;
29633 if (aly > bly && aly > bry) return 1; // is the A left endpoint colinear to segment B?
29635 var bCmpALeft = b.comparePoint(a.leftSE.point);
29636 if (bCmpALeft !== 0) return bCmpALeft; // is the B right endpoint colinear to segment A?
29638 var aCmpBRight = a.comparePoint(b.rightSE.point);
29639 if (aCmpBRight < 0) return 1;
29640 if (aCmpBRight > 0) return -1; // colinear segments, consider the one with left-more
29641 // left endpoint to be first (arbitrary?)
29644 } // if we get here, the two left endpoints are in the same
29645 // vertical plane, ie alx === blx
29646 // consider the lower left-endpoint to come first
29649 if (aly < bly) return -1;
29650 if (aly > bly) return 1; // left endpoints are identical
29651 // check for colinearity by using the left-more right endpoint
29652 // is the A right endpoint more left-more?
29655 var _bCmpARight = b.comparePoint(a.rightSE.point);
29657 if (_bCmpARight !== 0) return _bCmpARight;
29658 } // is the B right endpoint more left-more?
29662 var _aCmpBRight = a.comparePoint(b.rightSE.point);
29664 if (_aCmpBRight < 0) return 1;
29665 if (_aCmpBRight > 0) return -1;
29669 // are these two [almost] vertical segments with opposite orientation?
29670 // if so, the one with the lower right endpoint comes first
29671 var ay = ary - aly;
29672 var ax = arx - alx;
29673 var by = bry - bly;
29674 var bx = brx - blx;
29675 if (ay > ax && by < bx) return 1;
29676 if (ay < ax && by > bx) return -1;
29677 } // we have colinear segments with matching orientation
29678 // consider the one with more left-more right endpoint to be first
29681 if (arx > brx) return 1;
29682 if (arx < brx) return -1; // if we get here, two two right endpoints are in the same
29683 // vertical plane, ie arx === brx
29684 // consider the lower right-endpoint to come first
29686 if (ary < bry) return -1;
29687 if (ary > bry) return 1; // right endpoints identical as well, so the segments are idential
29688 // fall back on creation order as consistent tie-breaker
29690 if (a.id < b.id) return -1;
29691 if (a.id > b.id) return 1; // identical segment, ie a === b
29695 /* Warning: a reference to ringWindings input will be stored,
29696 * and possibly will be later modified */
29700 function Segment(leftSE, rightSE, rings, windings) {
29701 _classCallCheck(this, Segment);
29703 this.id = ++segmentId;
29704 this.leftSE = leftSE;
29705 leftSE.segment = this;
29706 leftSE.otherSE = rightSE;
29707 this.rightSE = rightSE;
29708 rightSE.segment = this;
29709 rightSE.otherSE = leftSE;
29710 this.rings = rings;
29711 this.windings = windings; // left unset for performance, set later in algorithm
29712 // this.ringOut, this.consumedBy, this.prev
29715 _createClass(Segment, [{
29716 key: "replaceRightSE",
29718 /* When a segment is split, the rightSE is replaced with a new sweep event */
29719 value: function replaceRightSE(newRightSE) {
29720 this.rightSE = newRightSE;
29721 this.rightSE.segment = this;
29722 this.rightSE.otherSE = this.leftSE;
29723 this.leftSE.otherSE = this.rightSE;
29727 value: function bbox() {
29728 var y1 = this.leftSE.point.y;
29729 var y2 = this.rightSE.point.y;
29732 x: this.leftSE.point.x,
29733 y: y1 < y2 ? y1 : y2
29736 x: this.rightSE.point.x,
29737 y: y1 > y2 ? y1 : y2
29741 /* A vector from the left point to the right */
29745 value: function vector() {
29747 x: this.rightSE.point.x - this.leftSE.point.x,
29748 y: this.rightSE.point.y - this.leftSE.point.y
29752 key: "isAnEndpoint",
29753 value: function isAnEndpoint(pt) {
29754 return pt.x === this.leftSE.point.x && pt.y === this.leftSE.point.y || pt.x === this.rightSE.point.x && pt.y === this.rightSE.point.y;
29756 /* Compare this segment with a point.
29758 * A point P is considered to be colinear to a segment if there
29759 * exists a distance D such that if we travel along the segment
29760 * from one * endpoint towards the other a distance D, we find
29761 * ourselves at point P.
29763 * Return value indicates:
29765 * 1: point lies above the segment (to the left of vertical)
29766 * 0: point is colinear to segment
29767 * -1: point lies below the segment (to the right of vertical)
29771 key: "comparePoint",
29772 value: function comparePoint(point) {
29773 if (this.isAnEndpoint(point)) return 0;
29774 var lPt = this.leftSE.point;
29775 var rPt = this.rightSE.point;
29776 var v = this.vector(); // Exactly vertical segments.
29778 if (lPt.x === rPt.x) {
29779 if (point.x === lPt.x) return 0;
29780 return point.x < lPt.x ? 1 : -1;
29781 } // Nearly vertical segments with an intersection.
29782 // Check to see where a point on the line with matching Y coordinate is.
29785 var yDist = (point.y - lPt.y) / v.y;
29786 var xFromYDist = lPt.x + yDist * v.x;
29787 if (point.x === xFromYDist) return 0; // General case.
29788 // Check to see where a point on the line with matching X coordinate is.
29790 var xDist = (point.x - lPt.x) / v.x;
29791 var yFromXDist = lPt.y + xDist * v.y;
29792 if (point.y === yFromXDist) return 0;
29793 return point.y < yFromXDist ? -1 : 1;
29796 * Given another segment, returns the first non-trivial intersection
29797 * between the two segments (in terms of sweep line ordering), if it exists.
29799 * A 'non-trivial' intersection is one that will cause one or both of the
29800 * segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:
29802 * * endpoint of segA with endpoint of segB --> trivial
29803 * * endpoint of segA with point along segB --> non-trivial
29804 * * endpoint of segB with point along segA --> non-trivial
29805 * * point along segA with point along segB --> non-trivial
29807 * If no non-trivial intersection exists, return null
29808 * Else, return null.
29812 key: "getIntersection",
29813 value: function getIntersection(other) {
29814 // If bboxes don't overlap, there can't be any intersections
29815 var tBbox = this.bbox();
29816 var oBbox = other.bbox();
29817 var bboxOverlap = getBboxOverlap(tBbox, oBbox);
29818 if (bboxOverlap === null) return null; // We first check to see if the endpoints can be considered intersections.
29819 // This will 'snap' intersections to endpoints if possible, and will
29820 // handle cases of colinearity.
29822 var tlp = this.leftSE.point;
29823 var trp = this.rightSE.point;
29824 var olp = other.leftSE.point;
29825 var orp = other.rightSE.point; // does each endpoint touch the other segment?
29826 // note that we restrict the 'touching' definition to only allow segments
29827 // to touch endpoints that lie forward from where we are in the sweep line pass
29829 var touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0;
29830 var touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0;
29831 var touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0;
29832 var touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0; // do left endpoints match?
29834 if (touchesThisLSE && touchesOtherLSE) {
29835 // these two cases are for colinear segments with matching left
29836 // endpoints, and one segment being longer than the other
29837 if (touchesThisRSE && !touchesOtherRSE) return trp;
29838 if (!touchesThisRSE && touchesOtherRSE) return orp; // either the two segments match exactly (two trival intersections)
29839 // or just on their left endpoint (one trivial intersection
29842 } // does this left endpoint matches (other doesn't)
29845 if (touchesThisLSE) {
29846 // check for segments that just intersect on opposing endpoints
29847 if (touchesOtherRSE) {
29848 if (tlp.x === orp.x && tlp.y === orp.y) return null;
29849 } // t-intersection on left endpoint
29853 } // does other left endpoint matches (this doesn't)
29856 if (touchesOtherLSE) {
29857 // check for segments that just intersect on opposing endpoints
29858 if (touchesThisRSE) {
29859 if (trp.x === olp.x && trp.y === olp.y) return null;
29860 } // t-intersection on left endpoint
29864 } // trivial intersection on right endpoints
29867 if (touchesThisRSE && touchesOtherRSE) return null; // t-intersections on just one right endpoint
29869 if (touchesThisRSE) return trp;
29870 if (touchesOtherRSE) return orp; // None of our endpoints intersect. Look for a general intersection between
29871 // infinite lines laid over the segments
29873 var pt = intersection(tlp, this.vector(), olp, other.vector()); // are the segments parrallel? Note that if they were colinear with overlap,
29874 // they would have an endpoint intersection and that case was already handled above
29876 if (pt === null) return null; // is the intersection found between the lines not on the segments?
29878 if (!isInBbox(bboxOverlap, pt)) return null; // round the the computed point if needed
29880 return rounder.round(pt.x, pt.y);
29883 * Split the given segment into multiple segments on the given points.
29884 * * Each existing segment will retain its leftSE and a new rightSE will be
29885 * generated for it.
29886 * * A new segment will be generated which will adopt the original segment's
29887 * rightSE, and a new leftSE will be generated for it.
29888 * * If there are more than two points given to split on, new segments
29889 * in the middle will be generated with new leftSE and rightSE's.
29890 * * An array of the newly generated SweepEvents will be returned.
29892 * Warning: input array of points is modified
29897 value: function split(point) {
29898 var newEvents = [];
29899 var alreadyLinked = point.events !== undefined;
29900 var newLeftSE = new SweepEvent(point, true);
29901 var newRightSE = new SweepEvent(point, false);
29902 var oldRightSE = this.rightSE;
29903 this.replaceRightSE(newRightSE);
29904 newEvents.push(newRightSE);
29905 newEvents.push(newLeftSE);
29906 var newSeg = new Segment(newLeftSE, oldRightSE, this.rings.slice(), this.windings.slice()); // when splitting a nearly vertical downward-facing segment,
29907 // sometimes one of the resulting new segments is vertical, in which
29908 // case its left and right events may need to be swapped
29910 if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) {
29911 newSeg.swapEvents();
29914 if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) {
29916 } // in the point we just used to create new sweep events with was already
29917 // linked to other events, we need to check if either of the affected
29918 // segments should be consumed
29921 if (alreadyLinked) {
29922 newLeftSE.checkForConsuming();
29923 newRightSE.checkForConsuming();
29928 /* Swap which event is left and right */
29932 value: function swapEvents() {
29933 var tmpEvt = this.rightSE;
29934 this.rightSE = this.leftSE;
29935 this.leftSE = tmpEvt;
29936 this.leftSE.isLeft = true;
29937 this.rightSE.isLeft = false;
29939 for (var i = 0, iMax = this.windings.length; i < iMax; i++) {
29940 this.windings[i] *= -1;
29943 /* Consume another segment. We take their rings under our wing
29944 * and mark them as consumed. Use for perfectly overlapping segments */
29948 value: function consume(other) {
29949 var consumer = this;
29950 var consumee = other;
29952 while (consumer.consumedBy) {
29953 consumer = consumer.consumedBy;
29956 while (consumee.consumedBy) {
29957 consumee = consumee.consumedBy;
29960 var cmp = Segment.compare(consumer, consumee);
29961 if (cmp === 0) return; // already consumed
29962 // the winner of the consumption is the earlier segment
29963 // according to sweep line ordering
29966 var tmp = consumer;
29967 consumer = consumee;
29969 } // make sure a segment doesn't consume it's prev
29972 if (consumer.prev === consumee) {
29973 var _tmp = consumer;
29974 consumer = consumee;
29978 for (var i = 0, iMax = consumee.rings.length; i < iMax; i++) {
29979 var ring = consumee.rings[i];
29980 var winding = consumee.windings[i];
29981 var index = consumer.rings.indexOf(ring);
29983 if (index === -1) {
29984 consumer.rings.push(ring);
29985 consumer.windings.push(winding);
29986 } else consumer.windings[index] += winding;
29989 consumee.rings = null;
29990 consumee.windings = null;
29991 consumee.consumedBy = consumer; // mark sweep events consumed as to maintain ordering in sweep event queue
29993 consumee.leftSE.consumedBy = consumer.leftSE;
29994 consumee.rightSE.consumedBy = consumer.rightSE;
29996 /* The first segment previous segment chain that is in the result */
29999 key: "prevInResult",
30000 value: function prevInResult() {
30001 if (this._prevInResult !== undefined) return this._prevInResult;
30002 if (!this.prev) this._prevInResult = null;else if (this.prev.isInResult()) this._prevInResult = this.prev;else this._prevInResult = this.prev.prevInResult();
30003 return this._prevInResult;
30006 key: "beforeState",
30007 value: function beforeState() {
30008 if (this._beforeState !== undefined) return this._beforeState;
30009 if (!this.prev) this._beforeState = {
30014 var seg = this.prev.consumedBy || this.prev;
30015 this._beforeState = seg.afterState();
30017 return this._beforeState;
30021 value: function afterState() {
30022 if (this._afterState !== undefined) return this._afterState;
30023 var beforeState = this.beforeState();
30024 this._afterState = {
30025 rings: beforeState.rings.slice(0),
30026 windings: beforeState.windings.slice(0),
30029 var ringsAfter = this._afterState.rings;
30030 var windingsAfter = this._afterState.windings;
30031 var mpsAfter = this._afterState.multiPolys; // calculate ringsAfter, windingsAfter
30033 for (var i = 0, iMax = this.rings.length; i < iMax; i++) {
30034 var ring = this.rings[i];
30035 var winding = this.windings[i];
30036 var index = ringsAfter.indexOf(ring);
30038 if (index === -1) {
30039 ringsAfter.push(ring);
30040 windingsAfter.push(winding);
30041 } else windingsAfter[index] += winding;
30042 } // calcualte polysAfter
30045 var polysAfter = [];
30046 var polysExclude = [];
30048 for (var _i = 0, _iMax = ringsAfter.length; _i < _iMax; _i++) {
30049 if (windingsAfter[_i] === 0) continue; // non-zero rule
30051 var _ring = ringsAfter[_i];
30052 var poly = _ring.poly;
30053 if (polysExclude.indexOf(poly) !== -1) continue;
30054 if (_ring.isExterior) polysAfter.push(poly);else {
30055 if (polysExclude.indexOf(poly) === -1) polysExclude.push(poly);
30057 var _index = polysAfter.indexOf(_ring.poly);
30059 if (_index !== -1) polysAfter.splice(_index, 1);
30061 } // calculate multiPolysAfter
30064 for (var _i2 = 0, _iMax2 = polysAfter.length; _i2 < _iMax2; _i2++) {
30065 var mp = polysAfter[_i2].multiPoly;
30066 if (mpsAfter.indexOf(mp) === -1) mpsAfter.push(mp);
30069 return this._afterState;
30071 /* Is this segment part of the final result? */
30075 value: function isInResult() {
30076 // if we've been consumed, we're not in the result
30077 if (this.consumedBy) return false;
30078 if (this._isInResult !== undefined) return this._isInResult;
30079 var mpsBefore = this.beforeState().multiPolys;
30080 var mpsAfter = this.afterState().multiPolys;
30082 switch (operation.type) {
30085 // UNION - included iff:
30086 // * On one side of us there is 0 poly interiors AND
30087 // * On the other side there is 1 or more.
30088 var noBefores = mpsBefore.length === 0;
30089 var noAfters = mpsAfter.length === 0;
30090 this._isInResult = noBefores !== noAfters;
30094 case 'intersection':
30096 // INTERSECTION - included iff:
30097 // * on one side of us all multipolys are rep. with poly interiors AND
30098 // * on the other side of us, not all multipolys are repsented
30099 // with poly interiors
30103 if (mpsBefore.length < mpsAfter.length) {
30104 least = mpsBefore.length;
30105 most = mpsAfter.length;
30107 least = mpsAfter.length;
30108 most = mpsBefore.length;
30111 this._isInResult = most === operation.numMultiPolys && least < most;
30117 // XOR - included iff:
30118 // * the difference between the number of multipolys represented
30119 // with poly interiors on our two sides is an odd number
30120 var diff = Math.abs(mpsBefore.length - mpsAfter.length);
30121 this._isInResult = diff % 2 === 1;
30127 // DIFFERENCE included iff:
30128 // * on exactly one side, we have just the subject
30129 var isJustSubject = function isJustSubject(mps) {
30130 return mps.length === 1 && mps[0].isSubject;
30133 this._isInResult = isJustSubject(mpsBefore) !== isJustSubject(mpsAfter);
30138 throw new Error("Unrecognized operation type found ".concat(operation.type));
30141 return this._isInResult;
30145 value: function fromRing(pt1, pt2, ring) {
30146 var leftPt, rightPt, winding; // ordering the two points according to sweep line ordering
30148 var cmpPts = SweepEvent.comparePoints(pt1, pt2);
30154 } else if (cmpPts > 0) {
30158 } else throw new Error("Tried to create degenerate segment at [".concat(pt1.x, ", ").concat(pt1.y, "]"));
30160 var leftSE = new SweepEvent(leftPt, true);
30161 var rightSE = new SweepEvent(rightPt, false);
30162 return new Segment(leftSE, rightSE, [ring], [winding]);
30169 var RingIn = /*#__PURE__*/function () {
30170 function RingIn(geomRing, poly, isExterior) {
30171 _classCallCheck(this, RingIn);
30173 if (!Array.isArray(geomRing) || geomRing.length === 0) {
30174 throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30178 this.isExterior = isExterior;
30179 this.segments = [];
30181 if (typeof geomRing[0][0] !== 'number' || typeof geomRing[0][1] !== 'number') {
30182 throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30185 var firstPoint = rounder.round(geomRing[0][0], geomRing[0][1]);
30196 var prevPoint = firstPoint;
30198 for (var i = 1, iMax = geomRing.length; i < iMax; i++) {
30199 if (typeof geomRing[i][0] !== 'number' || typeof geomRing[i][1] !== 'number') {
30200 throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30203 var point = rounder.round(geomRing[i][0], geomRing[i][1]); // skip repeated points
30205 if (point.x === prevPoint.x && point.y === prevPoint.y) continue;
30206 this.segments.push(Segment.fromRing(prevPoint, point, this));
30207 if (point.x < this.bbox.ll.x) this.bbox.ll.x = point.x;
30208 if (point.y < this.bbox.ll.y) this.bbox.ll.y = point.y;
30209 if (point.x > this.bbox.ur.x) this.bbox.ur.x = point.x;
30210 if (point.y > this.bbox.ur.y) this.bbox.ur.y = point.y;
30212 } // add segment from last to first if last is not the same as first
30215 if (firstPoint.x !== prevPoint.x || firstPoint.y !== prevPoint.y) {
30216 this.segments.push(Segment.fromRing(prevPoint, firstPoint, this));
30220 _createClass(RingIn, [{
30221 key: "getSweepEvents",
30222 value: function getSweepEvents() {
30223 var sweepEvents = [];
30225 for (var i = 0, iMax = this.segments.length; i < iMax; i++) {
30226 var segment = this.segments[i];
30227 sweepEvents.push(segment.leftSE);
30228 sweepEvents.push(segment.rightSE);
30231 return sweepEvents;
30238 var PolyIn = /*#__PURE__*/function () {
30239 function PolyIn(geomPoly, multiPoly) {
30240 _classCallCheck(this, PolyIn);
30242 if (!Array.isArray(geomPoly)) {
30243 throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30246 this.exteriorRing = new RingIn(geomPoly[0], this, true); // copy by value
30250 x: this.exteriorRing.bbox.ll.x,
30251 y: this.exteriorRing.bbox.ll.y
30254 x: this.exteriorRing.bbox.ur.x,
30255 y: this.exteriorRing.bbox.ur.y
30258 this.interiorRings = [];
30260 for (var i = 1, iMax = geomPoly.length; i < iMax; i++) {
30261 var ring = new RingIn(geomPoly[i], this, false);
30262 if (ring.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = ring.bbox.ll.x;
30263 if (ring.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = ring.bbox.ll.y;
30264 if (ring.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = ring.bbox.ur.x;
30265 if (ring.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = ring.bbox.ur.y;
30266 this.interiorRings.push(ring);
30269 this.multiPoly = multiPoly;
30272 _createClass(PolyIn, [{
30273 key: "getSweepEvents",
30274 value: function getSweepEvents() {
30275 var sweepEvents = this.exteriorRing.getSweepEvents();
30277 for (var i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
30278 var ringSweepEvents = this.interiorRings[i].getSweepEvents();
30280 for (var j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {
30281 sweepEvents.push(ringSweepEvents[j]);
30285 return sweepEvents;
30292 var MultiPolyIn = /*#__PURE__*/function () {
30293 function MultiPolyIn(geom, isSubject) {
30294 _classCallCheck(this, MultiPolyIn);
30296 if (!Array.isArray(geom)) {
30297 throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30301 // if the input looks like a polygon, convert it to a multipolygon
30302 if (typeof geom[0][0][0] === 'number') geom = [geom];
30303 } catch (ex) {// The input is either malformed or has empty arrays.
30304 // In either case, it will be handled later on.
30310 x: Number.POSITIVE_INFINITY,
30311 y: Number.POSITIVE_INFINITY
30314 x: Number.NEGATIVE_INFINITY,
30315 y: Number.NEGATIVE_INFINITY
30319 for (var i = 0, iMax = geom.length; i < iMax; i++) {
30320 var poly = new PolyIn(geom[i], this);
30321 if (poly.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = poly.bbox.ll.x;
30322 if (poly.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = poly.bbox.ll.y;
30323 if (poly.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = poly.bbox.ur.x;
30324 if (poly.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = poly.bbox.ur.y;
30325 this.polys.push(poly);
30328 this.isSubject = isSubject;
30331 _createClass(MultiPolyIn, [{
30332 key: "getSweepEvents",
30333 value: function getSweepEvents() {
30334 var sweepEvents = [];
30336 for (var i = 0, iMax = this.polys.length; i < iMax; i++) {
30337 var polySweepEvents = this.polys[i].getSweepEvents();
30339 for (var j = 0, jMax = polySweepEvents.length; j < jMax; j++) {
30340 sweepEvents.push(polySweepEvents[j]);
30344 return sweepEvents;
30348 return MultiPolyIn;
30351 var RingOut = /*#__PURE__*/function () {
30352 _createClass(RingOut, null, [{
30355 /* Given the segments from the sweep line pass, compute & return a series
30356 * of closed rings from all the segments marked to be part of the result */
30357 value: function factory(allSegments) {
30360 for (var i = 0, iMax = allSegments.length; i < iMax; i++) {
30361 var segment = allSegments[i];
30362 if (!segment.isInResult() || segment.ringOut) continue;
30363 var prevEvent = null;
30364 var event = segment.leftSE;
30365 var nextEvent = segment.rightSE;
30366 var events = [event];
30367 var startingPoint = event.point;
30368 var intersectionLEs = [];
30369 /* Walk the chain of linked events to form a closed ring */
30374 events.push(event);
30375 /* Is the ring complete? */
30377 if (event.point === startingPoint) break;
30380 var availableLEs = event.getAvailableLinkedEvents();
30381 /* Did we hit a dead end? This shouldn't happen. Indicates some earlier
30382 * part of the algorithm malfunctioned... please file a bug report. */
30384 if (availableLEs.length === 0) {
30385 var firstPt = events[0].point;
30386 var lastPt = events[events.length - 1].point;
30387 throw new Error("Unable to complete output ring starting at [".concat(firstPt.x, ",") + " ".concat(firstPt.y, "]. Last matching segment found ends at") + " [".concat(lastPt.x, ", ").concat(lastPt.y, "]."));
30389 /* Only one way to go, so cotinue on the path */
30392 if (availableLEs.length === 1) {
30393 nextEvent = availableLEs[0].otherSE;
30396 /* We must have an intersection. Check for a completed loop */
30399 var indexLE = null;
30401 for (var j = 0, jMax = intersectionLEs.length; j < jMax; j++) {
30402 if (intersectionLEs[j].point === event.point) {
30407 /* Found a completed loop. Cut that off and make a ring */
30410 if (indexLE !== null) {
30411 var intersectionLE = intersectionLEs.splice(indexLE)[0];
30412 var ringEvents = events.splice(intersectionLE.index);
30413 ringEvents.unshift(ringEvents[0].otherSE);
30414 ringsOut.push(new RingOut(ringEvents.reverse()));
30417 /* register the intersection */
30420 intersectionLEs.push({
30421 index: events.length,
30424 /* Choose the left-most option to continue the walk */
30426 var comparator = event.getLeftmostComparator(prevEvent);
30427 nextEvent = availableLEs.sort(comparator)[0].otherSE;
30432 ringsOut.push(new RingOut(events));
30439 function RingOut(events) {
30440 _classCallCheck(this, RingOut);
30442 this.events = events;
30444 for (var i = 0, iMax = events.length; i < iMax; i++) {
30445 events[i].segment.ringOut = this;
30451 _createClass(RingOut, [{
30453 value: function getGeom() {
30454 // Remove superfluous points (ie extra points along a straight line),
30455 var prevPt = this.events[0].point;
30456 var points = [prevPt];
30458 for (var i = 1, iMax = this.events.length - 1; i < iMax; i++) {
30459 var _pt = this.events[i].point;
30460 var _nextPt = this.events[i + 1].point;
30461 if (compareVectorAngles(_pt, prevPt, _nextPt) === 0) continue;
30464 } // ring was all (within rounding error of angle calc) colinear points
30467 if (points.length === 1) return null; // check if the starting point is necessary
30469 var pt = points[0];
30470 var nextPt = points[1];
30471 if (compareVectorAngles(pt, prevPt, nextPt) === 0) points.shift();
30472 points.push(points[0]);
30473 var step = this.isExteriorRing() ? 1 : -1;
30474 var iStart = this.isExteriorRing() ? 0 : points.length - 1;
30475 var iEnd = this.isExteriorRing() ? points.length : -1;
30476 var orderedPoints = [];
30478 for (var _i = iStart; _i != iEnd; _i += step) {
30479 orderedPoints.push([points[_i].x, points[_i].y]);
30482 return orderedPoints;
30485 key: "isExteriorRing",
30486 value: function isExteriorRing() {
30487 if (this._isExteriorRing === undefined) {
30488 var enclosing = this.enclosingRing();
30489 this._isExteriorRing = enclosing ? !enclosing.isExteriorRing() : true;
30492 return this._isExteriorRing;
30495 key: "enclosingRing",
30496 value: function enclosingRing() {
30497 if (this._enclosingRing === undefined) {
30498 this._enclosingRing = this._calcEnclosingRing();
30501 return this._enclosingRing;
30503 /* Returns the ring that encloses this one, if any */
30506 key: "_calcEnclosingRing",
30507 value: function _calcEnclosingRing() {
30508 // start with the ealier sweep line event so that the prevSeg
30509 // chain doesn't lead us inside of a loop of ours
30510 var leftMostEvt = this.events[0];
30512 for (var i = 1, iMax = this.events.length; i < iMax; i++) {
30513 var evt = this.events[i];
30514 if (SweepEvent.compare(leftMostEvt, evt) > 0) leftMostEvt = evt;
30517 var prevSeg = leftMostEvt.segment.prevInResult();
30518 var prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
30521 // no segment found, thus no ring can enclose us
30522 if (!prevSeg) return null; // no segments below prev segment found, thus the ring of the prev
30523 // segment must loop back around and enclose us
30525 if (!prevPrevSeg) return prevSeg.ringOut; // if the two segments are of different rings, the ring of the prev
30526 // segment must either loop around us or the ring of the prev prev
30527 // seg, which would make us and the ring of the prev peers
30529 if (prevPrevSeg.ringOut !== prevSeg.ringOut) {
30530 if (prevPrevSeg.ringOut.enclosingRing() !== prevSeg.ringOut) {
30531 return prevSeg.ringOut;
30532 } else return prevSeg.ringOut.enclosingRing();
30533 } // two segments are from the same ring, so this was a penisula
30534 // of that ring. iterate downward, keep searching
30537 prevSeg = prevPrevSeg.prevInResult();
30538 prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
30546 var PolyOut = /*#__PURE__*/function () {
30547 function PolyOut(exteriorRing) {
30548 _classCallCheck(this, PolyOut);
30550 this.exteriorRing = exteriorRing;
30551 exteriorRing.poly = this;
30552 this.interiorRings = [];
30555 _createClass(PolyOut, [{
30556 key: "addInterior",
30557 value: function addInterior(ring) {
30558 this.interiorRings.push(ring);
30563 value: function getGeom() {
30564 var geom = [this.exteriorRing.getGeom()]; // exterior ring was all (within rounding error of angle calc) colinear points
30566 if (geom[0] === null) return null;
30568 for (var i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
30569 var ringGeom = this.interiorRings[i].getGeom(); // interior ring was all (within rounding error of angle calc) colinear points
30571 if (ringGeom === null) continue;
30572 geom.push(ringGeom);
30582 var MultiPolyOut = /*#__PURE__*/function () {
30583 function MultiPolyOut(rings) {
30584 _classCallCheck(this, MultiPolyOut);
30586 this.rings = rings;
30587 this.polys = this._composePolys(rings);
30590 _createClass(MultiPolyOut, [{
30592 value: function getGeom() {
30595 for (var i = 0, iMax = this.polys.length; i < iMax; i++) {
30596 var polyGeom = this.polys[i].getGeom(); // exterior ring was all (within rounding error of angle calc) colinear points
30598 if (polyGeom === null) continue;
30599 geom.push(polyGeom);
30605 key: "_composePolys",
30606 value: function _composePolys(rings) {
30609 for (var i = 0, iMax = rings.length; i < iMax; i++) {
30610 var ring = rings[i];
30611 if (ring.poly) continue;
30612 if (ring.isExteriorRing()) polys.push(new PolyOut(ring));else {
30613 var enclosingRing = ring.enclosingRing();
30614 if (!enclosingRing.poly) polys.push(new PolyOut(enclosingRing));
30615 enclosingRing.poly.addInterior(ring);
30623 return MultiPolyOut;
30626 * NOTE: We must be careful not to change any segments while
30627 * they are in the SplayTree. AFAIK, there's no way to tell
30628 * the tree to rebalance itself - thus before splitting
30629 * a segment that's in the tree, we remove it from the tree,
30630 * do the split, then re-insert it. (Even though splitting a
30631 * segment *shouldn't* change its correct position in the
30632 * sweep line tree, the reality is because of rounding errors,
30633 * it sometimes does.)
30637 var SweepLine = /*#__PURE__*/function () {
30638 function SweepLine(queue) {
30639 var comparator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Segment.compare;
30641 _classCallCheck(this, SweepLine);
30643 this.queue = queue;
30644 this.tree = new Tree(comparator);
30645 this.segments = [];
30648 _createClass(SweepLine, [{
30650 value: function process(event) {
30651 var segment = event.segment;
30652 var newEvents = []; // if we've already been consumed by another segment,
30653 // clean up our body parts and get out
30655 if (event.consumedBy) {
30656 if (event.isLeft) this.queue.remove(event.otherSE);else this.tree.remove(segment);
30660 var node = event.isLeft ? this.tree.insert(segment) : this.tree.find(segment);
30661 if (!node) throw new Error("Unable to find segment #".concat(segment.id, " ") + "[".concat(segment.leftSE.point.x, ", ").concat(segment.leftSE.point.y, "] -> ") + "[".concat(segment.rightSE.point.x, ", ").concat(segment.rightSE.point.y, "] ") + 'in SweepLine tree. Please submit a bug report.');
30662 var prevNode = node;
30663 var nextNode = node;
30664 var prevSeg = undefined;
30665 var nextSeg = undefined; // skip consumed segments still in tree
30667 while (prevSeg === undefined) {
30668 prevNode = this.tree.prev(prevNode);
30669 if (prevNode === null) prevSeg = null;else if (prevNode.key.consumedBy === undefined) prevSeg = prevNode.key;
30670 } // skip consumed segments still in tree
30673 while (nextSeg === undefined) {
30674 nextNode = this.tree.next(nextNode);
30675 if (nextNode === null) nextSeg = null;else if (nextNode.key.consumedBy === undefined) nextSeg = nextNode.key;
30678 if (event.isLeft) {
30679 // Check for intersections against the previous segment in the sweep line
30680 var prevMySplitter = null;
30683 var prevInter = prevSeg.getIntersection(segment);
30685 if (prevInter !== null) {
30686 if (!segment.isAnEndpoint(prevInter)) prevMySplitter = prevInter;
30688 if (!prevSeg.isAnEndpoint(prevInter)) {
30689 var newEventsFromSplit = this._splitSafely(prevSeg, prevInter);
30691 for (var i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
30692 newEvents.push(newEventsFromSplit[i]);
30696 } // Check for intersections against the next segment in the sweep line
30699 var nextMySplitter = null;
30702 var nextInter = nextSeg.getIntersection(segment);
30704 if (nextInter !== null) {
30705 if (!segment.isAnEndpoint(nextInter)) nextMySplitter = nextInter;
30707 if (!nextSeg.isAnEndpoint(nextInter)) {
30708 var _newEventsFromSplit = this._splitSafely(nextSeg, nextInter);
30710 for (var _i = 0, _iMax = _newEventsFromSplit.length; _i < _iMax; _i++) {
30711 newEvents.push(_newEventsFromSplit[_i]);
30715 } // For simplicity, even if we find more than one intersection we only
30716 // spilt on the 'earliest' (sweep-line style) of the intersections.
30717 // The other intersection will be handled in a future process().
30720 if (prevMySplitter !== null || nextMySplitter !== null) {
30721 var mySplitter = null;
30722 if (prevMySplitter === null) mySplitter = nextMySplitter;else if (nextMySplitter === null) mySplitter = prevMySplitter;else {
30723 var cmpSplitters = SweepEvent.comparePoints(prevMySplitter, nextMySplitter);
30724 mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter;
30725 } // Rounding errors can cause changes in ordering,
30726 // so remove afected segments and right sweep events before splitting
30728 this.queue.remove(segment.rightSE);
30729 newEvents.push(segment.rightSE);
30731 var _newEventsFromSplit2 = segment.split(mySplitter);
30733 for (var _i2 = 0, _iMax2 = _newEventsFromSplit2.length; _i2 < _iMax2; _i2++) {
30734 newEvents.push(_newEventsFromSplit2[_i2]);
30738 if (newEvents.length > 0) {
30739 // We found some intersections, so re-do the current event to
30740 // make sure sweep line ordering is totally consistent for later
30741 // use with the segment 'prev' pointers
30742 this.tree.remove(segment);
30743 newEvents.push(event);
30745 // done with left event
30746 this.segments.push(segment);
30747 segment.prev = prevSeg;
30751 // since we're about to be removed from the sweep line, check for
30752 // intersections between our previous and next segments
30753 if (prevSeg && nextSeg) {
30754 var inter = prevSeg.getIntersection(nextSeg);
30756 if (inter !== null) {
30757 if (!prevSeg.isAnEndpoint(inter)) {
30758 var _newEventsFromSplit3 = this._splitSafely(prevSeg, inter);
30760 for (var _i3 = 0, _iMax3 = _newEventsFromSplit3.length; _i3 < _iMax3; _i3++) {
30761 newEvents.push(_newEventsFromSplit3[_i3]);
30765 if (!nextSeg.isAnEndpoint(inter)) {
30766 var _newEventsFromSplit4 = this._splitSafely(nextSeg, inter);
30768 for (var _i4 = 0, _iMax4 = _newEventsFromSplit4.length; _i4 < _iMax4; _i4++) {
30769 newEvents.push(_newEventsFromSplit4[_i4]);
30775 this.tree.remove(segment);
30780 /* Safely split a segment that is currently in the datastructures
30781 * IE - a segment other than the one that is currently being processed. */
30784 key: "_splitSafely",
30785 value: function _splitSafely(seg, pt) {
30786 // Rounding errors can cause changes in ordering,
30787 // so remove afected segments and right sweep events before splitting
30788 // removeNode() doesn't work, so have re-find the seg
30789 // https://github.com/w8r/splay-tree/pull/5
30790 this.tree.remove(seg);
30791 var rightSE = seg.rightSE;
30792 this.queue.remove(rightSE);
30793 var newEvents = seg.split(pt);
30794 newEvents.push(rightSE); // splitting can trigger consumption
30796 if (seg.consumedBy === undefined) this.tree.insert(seg);
30804 var POLYGON_CLIPPING_MAX_QUEUE_SIZE = typeof process !== 'undefined' && process.env.POLYGON_CLIPPING_MAX_QUEUE_SIZE || 1000000;
30805 var POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS = typeof process !== 'undefined' && process.env.POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS || 1000000;
30807 var Operation = /*#__PURE__*/function () {
30808 function Operation() {
30809 _classCallCheck(this, Operation);
30812 _createClass(Operation, [{
30814 value: function run(type, geom, moreGeoms) {
30815 operation.type = type;
30817 /* Convert inputs to MultiPoly objects */
30819 var multipolys = [new MultiPolyIn(geom, true)];
30821 for (var i = 0, iMax = moreGeoms.length; i < iMax; i++) {
30822 multipolys.push(new MultiPolyIn(moreGeoms[i], false));
30825 operation.numMultiPolys = multipolys.length;
30826 /* BBox optimization for difference operation
30827 * If the bbox of a multipolygon that's part of the clipping doesn't
30828 * intersect the bbox of the subject at all, we can just drop that
30831 if (operation.type === 'difference') {
30832 // in place removal
30833 var subject = multipolys[0];
30836 while (_i < multipolys.length) {
30837 if (getBboxOverlap(multipolys[_i].bbox, subject.bbox) !== null) _i++;else multipolys.splice(_i, 1);
30840 /* BBox optimization for intersection operation
30841 * If we can find any pair of multipolygons whose bbox does not overlap,
30842 * then the result will be empty. */
30845 if (operation.type === 'intersection') {
30846 // TODO: this is O(n^2) in number of polygons. By sorting the bboxes,
30847 // it could be optimized to O(n * ln(n))
30848 for (var _i2 = 0, _iMax = multipolys.length; _i2 < _iMax; _i2++) {
30849 var mpA = multipolys[_i2];
30851 for (var j = _i2 + 1, jMax = multipolys.length; j < jMax; j++) {
30852 if (getBboxOverlap(mpA.bbox, multipolys[j].bbox) === null) return [];
30856 /* Put segment endpoints in a priority queue */
30859 var queue = new Tree(SweepEvent.compare);
30861 for (var _i3 = 0, _iMax2 = multipolys.length; _i3 < _iMax2; _i3++) {
30862 var sweepEvents = multipolys[_i3].getSweepEvents();
30864 for (var _j = 0, _jMax = sweepEvents.length; _j < _jMax; _j++) {
30865 queue.insert(sweepEvents[_j]);
30867 if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {
30868 // prevents an infinite loop, an otherwise common manifestation of bugs
30869 throw new Error('Infinite loop when putting segment endpoints in a priority queue ' + '(queue size too big). Please file a bug report.');
30873 /* Pass the sweep line over those endpoints */
30876 var sweepLine = new SweepLine(queue);
30877 var prevQueueSize = queue.size;
30878 var node = queue.pop();
30881 var evt = node.key;
30883 if (queue.size === prevQueueSize) {
30884 // prevents an infinite loop, an otherwise common manifestation of bugs
30885 var seg = evt.segment;
30886 throw new Error("Unable to pop() ".concat(evt.isLeft ? 'left' : 'right', " SweepEvent ") + "[".concat(evt.point.x, ", ").concat(evt.point.y, "] from segment #").concat(seg.id, " ") + "[".concat(seg.leftSE.point.x, ", ").concat(seg.leftSE.point.y, "] -> ") + "[".concat(seg.rightSE.point.x, ", ").concat(seg.rightSE.point.y, "] from queue. ") + 'Please file a bug report.');
30889 if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {
30890 // prevents an infinite loop, an otherwise common manifestation of bugs
30891 throw new Error('Infinite loop when passing sweep line over endpoints ' + '(queue size too big). Please file a bug report.');
30894 if (sweepLine.segments.length > POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS) {
30895 // prevents an infinite loop, an otherwise common manifestation of bugs
30896 throw new Error('Infinite loop when passing sweep line over endpoints ' + '(too many sweep line segments). Please file a bug report.');
30899 var newEvents = sweepLine.process(evt);
30901 for (var _i4 = 0, _iMax3 = newEvents.length; _i4 < _iMax3; _i4++) {
30902 var _evt = newEvents[_i4];
30903 if (_evt.consumedBy === undefined) queue.insert(_evt);
30906 prevQueueSize = queue.size;
30907 node = queue.pop();
30908 } // free some memory we don't need anymore
30912 /* Collect and compile segments we're keeping into a multipolygon */
30914 var ringsOut = RingOut.factory(sweepLine.segments);
30915 var result = new MultiPolyOut(ringsOut);
30916 return result.getGeom();
30921 }(); // singleton available by import
30924 var operation = new Operation();
30926 var union = function union(geom) {
30927 for (var _len = arguments.length, moreGeoms = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
30928 moreGeoms[_key - 1] = arguments[_key];
30931 return operation.run('union', geom, moreGeoms);
30934 var intersection$1 = function intersection(geom) {
30935 for (var _len2 = arguments.length, moreGeoms = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
30936 moreGeoms[_key2 - 1] = arguments[_key2];
30939 return operation.run('intersection', geom, moreGeoms);
30942 var xor = function xor(geom) {
30943 for (var _len3 = arguments.length, moreGeoms = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
30944 moreGeoms[_key3 - 1] = arguments[_key3];
30947 return operation.run('xor', geom, moreGeoms);
30950 var difference = function difference(subjectGeom) {
30951 for (var _len4 = arguments.length, clippingGeoms = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
30952 clippingGeoms[_key4 - 1] = arguments[_key4];
30955 return operation.run('difference', subjectGeom, clippingGeoms);
30960 intersection: intersection$1,
30962 difference: difference
30965 var geojsonPrecision = {exports: {}};
30968 function parse(t, coordinatePrecision, extrasPrecision) {
30969 function point(p) {
30970 return p.map(function (e, index) {
30972 return 1 * e.toFixed(coordinatePrecision);
30974 return 1 * e.toFixed(extrasPrecision);
30979 function multi(l) {
30980 return l.map(point);
30984 return p.map(multi);
30987 function multiPoly(m) {
30988 return m.map(poly);
30991 function geometry(obj) {
30996 switch (obj.type) {
30998 obj.coordinates = point(obj.coordinates);
31003 obj.coordinates = multi(obj.coordinates);
31007 case "MultiLineString":
31008 obj.coordinates = poly(obj.coordinates);
31011 case "MultiPolygon":
31012 obj.coordinates = multiPoly(obj.coordinates);
31015 case "GeometryCollection":
31016 obj.geometries = obj.geometries.map(geometry);
31024 function feature(obj) {
31025 obj.geometry = geometry(obj.geometry);
31029 function featureCollection(f) {
31030 f.features = f.features.map(feature);
31034 function geometryCollection(g) {
31035 g.geometries = g.geometries.map(geometry);
31047 case "GeometryCollection":
31048 return geometryCollection(t);
31050 case "FeatureCollection":
31051 return featureCollection(t);
31057 case "MultiPolygon":
31058 case "MultiLineString":
31059 return geometry(t);
31066 geojsonPrecision.exports = parse;
31067 geojsonPrecision.exports.parse = parse;
31070 var precision = geojsonPrecision.exports;
31073 var fails$5 = fails$V;
31074 var toObject$1 = toObject$i;
31075 var toPrimitive = toPrimitive$3;
31077 var FORCED$5 = fails$5(function () {
31078 return new Date(NaN).toJSON() !== null
31079 || Date.prototype.toJSON.call({ toISOString: function () { return 1; } }) !== 1;
31082 // `Date.prototype.toJSON` method
31083 // https://tc39.es/ecma262/#sec-date.prototype.tojson
31084 $$k({ target: 'Date', proto: true, forced: FORCED$5 }, {
31085 // eslint-disable-next-line no-unused-vars -- required for `.length`
31086 toJSON: function toJSON(key) {
31087 var O = toObject$1(this);
31088 var pv = toPrimitive(O, 'number');
31089 return typeof pv == 'number' && !isFinite(pv) ? null : O.toISOString();
31094 var call = functionCall;
31096 // `URL.prototype.toJSON` method
31097 // https://url.spec.whatwg.org/#dom-url-tojson
31098 $$j({ target: 'URL', proto: true, enumerable: true }, {
31099 toJSON: function toJSON() {
31100 return call(URL.prototype.toString, this);
31104 function isObject$3(obj) {
31105 return _typeof(obj) === 'object' && obj !== null;
31108 function forEach(obj, cb) {
31109 if (Array.isArray(obj)) {
31111 } else if (isObject$3(obj)) {
31112 Object.keys(obj).forEach(function (key) {
31113 var val = obj[key];
31119 function getTreeDepth(obj) {
31122 if (Array.isArray(obj) || isObject$3(obj)) {
31123 forEach(obj, function (val) {
31124 if (Array.isArray(val) || isObject$3(val)) {
31125 var tmpDepth = getTreeDepth(val);
31127 if (tmpDepth > depth) {
31138 function stringify(obj, options) {
31139 options = options || {};
31140 var indent = JSON.stringify([1], null, get(options, 'indent', 2)).slice(2, -3);
31141 var addMargin = get(options, 'margins', false);
31142 var addArrayMargin = get(options, 'arrayMargins', false);
31143 var addObjectMargin = get(options, 'objectMargins', false);
31144 var maxLength = indent === '' ? Infinity : get(options, 'maxLength', 80);
31145 var maxNesting = get(options, 'maxNesting', Infinity);
31146 return function _stringify(obj, currentIndent, reserved) {
31147 if (obj && typeof obj.toJSON === 'function') {
31148 obj = obj.toJSON();
31151 var string = JSON.stringify(obj);
31153 if (string === undefined) {
31157 var length = maxLength - currentIndent.length - reserved;
31158 var treeDepth = getTreeDepth(obj);
31160 if (treeDepth <= maxNesting && string.length <= length) {
31161 var prettified = prettify(string, {
31162 addMargin: addMargin,
31163 addArrayMargin: addArrayMargin,
31164 addObjectMargin: addObjectMargin
31167 if (prettified.length <= length) {
31172 if (isObject$3(obj)) {
31173 var nextIndent = currentIndent + indent;
31177 var comma = function comma(array, index) {
31178 return index === array.length - 1 ? 0 : 1;
31181 if (Array.isArray(obj)) {
31182 for (var index = 0; index < obj.length; index++) {
31183 items.push(_stringify(obj[index], nextIndent, comma(obj, index)) || 'null');
31188 Object.keys(obj).forEach(function (key, index, array) {
31189 var keyPart = JSON.stringify(key) + ': ';
31191 var value = _stringify(obj[key], nextIndent, keyPart.length + comma(array, index));
31193 if (value !== undefined) {
31194 items.push(keyPart + value);
31200 if (items.length > 0) {
31201 return [delimiters[0], indent + items.join(',\n' + nextIndent), delimiters[1]].join('\n' + currentIndent);
31207 } // Note: This regex matches even invalid JSON strings, but since we’re
31208 // working on the output of `JSON.stringify` we know that only valid strings
31209 // are present (unless the user supplied a weird `options.indent` but in
31210 // that case we don’t care since the output would be invalid anyway).
31213 var stringOrChar = /("(?:[^\\"]|\\.)*")|[:,\][}{]/g;
31215 function prettify(string, options) {
31216 options = options || {};
31226 if (options.addMargin || options.addObjectMargin) {
31227 tokens['{'] = '{ ';
31228 tokens['}'] = ' }';
31231 if (options.addMargin || options.addArrayMargin) {
31232 tokens['['] = '[ ';
31233 tokens[']'] = ' ]';
31236 return string.replace(stringOrChar, function (match, string) {
31237 return string ? match : tokens[match];
31241 function get(options, name, defaultValue) {
31242 return name in options ? options[name] : defaultValue;
31245 var jsonStringifyPrettyCompact = stringify;
31247 var _default = /*#__PURE__*/function () {
31250 // `fc` Optional FeatureCollection of known features
31252 // Optionally pass a GeoJSON FeatureCollection of known features which we can refer to later.
31253 // Each feature must have a filename-like `id`, for example: `something.geojson`
31256 // "type": "FeatureCollection"
31259 // "type": "Feature",
31260 // "id": "philly_metro.geojson",
31261 // "properties": { … },
31262 // "geometry": { … }
31266 function _default(fc) {
31269 _classCallCheck$1(this, _default);
31271 // The _cache retains resolved features, so if you ask for the same thing multiple times
31272 // we don't repeat the expensive resolving/clipping operations.
31274 // Each feature has a stable identifier that is used as the cache key.
31275 // The identifiers look like:
31276 // - for point locations, the stringified point: e.g. '[8.67039,49.41882]'
31277 // - for geojson locations, the geojson id: e.g. 'de-hamburg.geojson'
31278 // - for countrycoder locations, feature.id property: e.g. 'Q2' (countrycoder uses Wikidata identifiers)
31279 // - for aggregated locationSets, +[include]-[exclude]: e.g '+[Q2]-[Q18,Q27611]'
31280 this._cache = {}; // When strict mode = true, throw on invalid locations or locationSets.
31281 // When strict mode = false, return `null` for invalid locations or locationSets.
31283 this._strict = true; // process input FeatureCollection
31285 if (fc && fc.type === 'FeatureCollection' && Array.isArray(fc.features)) {
31286 fc.features.forEach(function (feature) {
31287 feature.properties = feature.properties || {};
31288 var props = feature.properties; // Get `id` from either `id` or `properties`
31290 var id = feature.id || props.id;
31291 if (!id || !/^\S+\.geojson$/i.test(id)) return; // Ensure `id` exists and is lowercase
31293 id = id.toLowerCase();
31295 props.id = id; // Ensure `area` property exists
31298 var area = geojsonArea.geometry(feature.geometry) / 1e6; // m² to km²
31300 props.area = Number(area.toFixed(2));
31303 _this._cache[id] = feature;
31305 } // Replace CountryCoder world geometry to be a polygon covering the world.
31308 var world = _cloneDeep(feature$1('Q2'));
31312 coordinates: [[[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]]]
31315 world.properties.id = 'Q2';
31316 world.properties.area = geojsonArea.geometry(world.geometry) / 1e6; // m² to km²
31318 this._cache.Q2 = world;
31319 } // validateLocation
31320 // `location` The location to validate
31322 // Pass a `location` value to validate
31324 // Returns a result like:
31326 // type: 'point', 'geojson', or 'countrycoder'
31327 // location: the queried location
31328 // id: the stable identifier for the feature
31330 // or `null` if the location is invalid
31334 _createClass$1(_default, [{
31335 key: "validateLocation",
31336 value: function validateLocation(location) {
31337 if (Array.isArray(location) && (location.length === 2 || location.length === 3)) {
31338 // [lon, lat] or [lon, lat, radius] point?
31339 var lon = location[0];
31340 var lat = location[1];
31341 var radius = location[2];
31343 if (Number.isFinite(lon) && lon >= -180 && lon <= 180 && Number.isFinite(lat) && lat >= -90 && lat <= 90 && (location.length === 2 || Number.isFinite(radius) && radius > 0)) {
31344 var id = '[' + location.toString() + ']';
31347 location: location,
31351 } else if (typeof location === 'string' && /^\S+\.geojson$/i.test(location)) {
31352 // a .geojson filename?
31353 var _id = location.toLowerCase();
31355 if (this._cache[_id]) {
31358 location: location,
31362 } else if (typeof location === 'string' || typeof location === 'number') {
31363 // a country-coder value?
31364 var feature = feature$1(location);
31367 // Use wikidata QID as the identifier, since that seems to be the one
31368 // property that everything in CountryCoder is guaranteed to have.
31369 var _id2 = feature.properties.wikidata;
31371 type: 'countrycoder',
31372 location: location,
31378 if (this._strict) {
31379 throw new Error("validateLocation: Invalid location: \"".concat(location, "\"."));
31383 } // resolveLocation
31384 // `location` The location to resolve
31386 // Pass a `location` value to resolve
31388 // Returns a result like:
31390 // type: 'point', 'geojson', or 'countrycoder'
31391 // location: the queried location
31392 // id: a stable identifier for the feature
31393 // feature: the resolved GeoJSON feature
31395 // or `null` if the location is invalid
31399 key: "resolveLocation",
31400 value: function resolveLocation(location) {
31401 var valid = this.validateLocation(location);
31402 if (!valid) return null;
31403 var id = valid.id; // Return a result from cache if we can
31405 if (this._cache[id]) {
31406 return Object.assign(valid, {
31407 feature: this._cache[id]
31409 } // A [lon,lat] coordinate pair?
31412 if (valid.type === 'point') {
31413 var lon = location[0];
31414 var lat = location[1];
31415 var radius = location[2] || 25; // km
31419 var area = Math.PI * radius * radius;
31420 var feature = this._cache[id] = precision({
31425 area: Number(area.toFixed(2))
31427 geometry: circleToPolygon([lon, lat], radius * 1000, EDGES) // km to m
31430 return Object.assign(valid, {
31432 }); // A .geojson filename?
31433 } else if (valid.type === 'geojson') ; else if (valid.type === 'countrycoder') {
31434 var _feature = _cloneDeep(feature$1(id));
31436 var props = _feature.properties; // -> This block of code is weird and requires some explanation. <-
31437 // CountryCoder includes higher level features which are made up of members.
31438 // These features don't have their own geometry, but CountryCoder provides an
31439 // `aggregateFeature` method to combine these members into a MultiPolygon.
31440 // In the past, Turf/JSTS/martinez could not handle the aggregated features,
31441 // so we'd iteratively union them all together. (this was slow)
31442 // But now mfogel/polygon-clipping handles these MultiPolygons like a boss.
31443 // This approach also has the benefit of removing all the internal boaders and
31444 // simplifying the regional polygons a lot.
31446 if (Array.isArray(props.members)) {
31447 var aggregate = aggregateFeature(id);
31448 aggregate.geometry.coordinates = _clip([aggregate], 'UNION').geometry.coordinates;
31449 _feature.geometry = aggregate.geometry;
31450 } // Ensure `area` property exists
31454 var _area = geojsonArea.geometry(_feature.geometry) / 1e6; // m² to km²
31457 props.area = Number(_area.toFixed(2));
31458 } // Ensure `id` property exists
31463 this._cache[id] = _feature;
31464 return Object.assign(valid, {
31469 if (this._strict) {
31470 throw new Error("resolveLocation: Couldn't resolve location \"".concat(location, "\"."));
31474 } // validateLocationSet
31475 // `locationSet` the locationSet to validate
31477 // Pass a locationSet Object to validate like:
31479 // include: [ Array of locations ],
31480 // exclude: [ Array of locations ]
31483 // Returns a result like:
31485 // type: 'locationset'
31486 // locationSet: the queried locationSet
31487 // id: the stable identifier for the feature
31489 // or `null` if the locationSet is invalid
31493 key: "validateLocationSet",
31494 value: function validateLocationSet(locationSet) {
31495 locationSet = locationSet || {};
31496 var validator = this.validateLocation.bind(this);
31497 var include = (locationSet.include || []).map(validator).filter(Boolean);
31498 var exclude = (locationSet.exclude || []).map(validator).filter(Boolean);
31500 if (!include.length) {
31501 if (this._strict) {
31502 throw new Error("validateLocationSet: LocationSet includes nothing.");
31504 // non-strict mode, replace an empty locationSet with one that includes "the world"
31505 locationSet.include = ['Q2'];
31507 type: 'countrycoder',
31512 } // Generate stable identifier
31515 include.sort(_sortLocations);
31516 var id = '+[' + include.map(function (d) {
31518 }).join(',') + ']';
31520 if (exclude.length) {
31521 exclude.sort(_sortLocations);
31522 id += '-[' + exclude.map(function (d) {
31524 }).join(',') + ']';
31528 type: 'locationset',
31529 locationSet: locationSet,
31532 } // resolveLocationSet
31533 // `locationSet` the locationSet to resolve
31535 // Pass a locationSet Object to validate like:
31537 // include: [ Array of locations ],
31538 // exclude: [ Array of locations ]
31541 // Returns a result like:
31543 // type: 'locationset'
31544 // locationSet: the queried locationSet
31545 // id: the stable identifier for the feature
31546 // feature: the resolved GeoJSON feature
31548 // or `null` if the locationSet is invalid
31552 key: "resolveLocationSet",
31553 value: function resolveLocationSet(locationSet) {
31554 locationSet = locationSet || {};
31555 var valid = this.validateLocationSet(locationSet);
31556 if (!valid) return null;
31557 var id = valid.id; // Return a result from cache if we can
31559 if (this._cache[id]) {
31560 return Object.assign(valid, {
31561 feature: this._cache[id]
31565 var resolver = this.resolveLocation.bind(this);
31566 var includes = (locationSet.include || []).map(resolver).filter(Boolean);
31567 var excludes = (locationSet.exclude || []).map(resolver).filter(Boolean); // Return quickly if it's a single included location..
31569 if (includes.length === 1 && excludes.length === 0) {
31570 return Object.assign(valid, {
31571 feature: includes[0].feature
31573 } // Calculate unions
31576 var includeGeoJSON = _clip(includes.map(function (d) {
31580 var excludeGeoJSON = _clip(excludes.map(function (d) {
31582 }), 'UNION'); // Calculate difference, update `area` and return result
31585 var resultGeoJSON = excludeGeoJSON ? _clip([includeGeoJSON, excludeGeoJSON], 'DIFFERENCE') : includeGeoJSON;
31586 var area = geojsonArea.geometry(resultGeoJSON.geometry) / 1e6; // m² to km²
31588 resultGeoJSON.id = id;
31589 resultGeoJSON.properties = {
31591 area: Number(area.toFixed(2))
31593 this._cache[id] = resultGeoJSON;
31594 return Object.assign(valid, {
31595 feature: resultGeoJSON
31602 value: function strict(val) {
31603 if (val === undefined) {
31605 return this._strict;
31608 this._strict = val;
31612 // convenience method to access the internal cache
31616 value: function cache() {
31617 return this._cache;
31619 // convenience method to prettyStringify the given object
31623 value: function stringify(obj, options) {
31624 return jsonStringifyPrettyCompact(obj, options);
31629 }(); // Wrap the mfogel/polygon-clipping library and return a GeoJSON feature.
31631 function _clip(features, which) {
31632 if (!Array.isArray(features) || !features.length) return null;
31634 UNION: index.union,
31635 DIFFERENCE: index.difference
31637 var args = features.map(function (feature) {
31638 return feature.geometry.coordinates;
31640 var coords = fn.apply(null, args);
31645 type: whichType(coords),
31646 coordinates: coords
31648 }; // is this a Polygon or a MultiPolygon?
31650 function whichType(coords) {
31651 var a = Array.isArray(coords);
31652 var b = a && Array.isArray(coords[0]);
31653 var c = b && Array.isArray(coords[0][0]);
31654 var d = c && Array.isArray(coords[0][0][0]);
31655 return d ? 'MultiPolygon' : 'Polygon';
31659 function _cloneDeep(obj) {
31660 return JSON.parse(JSON.stringify(obj));
31661 } // Sorting the location lists is ok because they end up unioned together.
31662 // This sorting makes it possible to generate a deterministic id.
31665 function _sortLocations(a, b) {
31671 var aRank = rank[a.type];
31672 var bRank = rank[b.type];
31673 return aRank > bRank ? 1 : aRank < bRank ? -1 : a.id.localeCompare(b.id);
31678 // `Number.MAX_SAFE_INTEGER` constant
31679 // https://tc39.es/ecma262/#sec-number.max_safe_integer
31680 $$i({ target: 'Number', stat: true }, {
31681 MAX_SAFE_INTEGER: 0x1FFFFFFFFFFFFF
31684 var aesJs = {exports: {}};
31686 (function (module, exports) {
31689 function checkInt(value) {
31690 return parseInt(value) === value;
31693 function checkInts(arrayish) {
31694 if (!checkInt(arrayish.length)) {
31698 for (var i = 0; i < arrayish.length; i++) {
31699 if (!checkInt(arrayish[i]) || arrayish[i] < 0 || arrayish[i] > 255) {
31707 function coerceArray(arg, copy) {
31708 // ArrayBuffer view
31709 if (arg.buffer && arg.name === 'Uint8Array') {
31714 arg = Array.prototype.slice.call(arg);
31719 } // It's an array; check it is a valid representation of a byte
31722 if (Array.isArray(arg)) {
31723 if (!checkInts(arg)) {
31724 throw new Error('Array contains invalid value: ' + arg);
31727 return new Uint8Array(arg);
31728 } // Something else, but behaves like an array (maybe a Buffer? Arguments?)
31731 if (checkInt(arg.length) && checkInts(arg)) {
31732 return new Uint8Array(arg);
31735 throw new Error('unsupported array-like object');
31738 function createArray(length) {
31739 return new Uint8Array(length);
31742 function copyArray(sourceArray, targetArray, targetStart, sourceStart, sourceEnd) {
31743 if (sourceStart != null || sourceEnd != null) {
31744 if (sourceArray.slice) {
31745 sourceArray = sourceArray.slice(sourceStart, sourceEnd);
31747 sourceArray = Array.prototype.slice.call(sourceArray, sourceStart, sourceEnd);
31751 targetArray.set(sourceArray, targetStart);
31754 var convertUtf8 = function () {
31755 function toBytes(text) {
31758 text = encodeURI(text);
31760 while (i < text.length) {
31761 var c = text.charCodeAt(i++); // if it is a % sign, encode the following 2 bytes as a hex value
31764 result.push(parseInt(text.substr(i, 2), 16));
31765 i += 2; // otherwise, just the actual byte
31771 return coerceArray(result);
31774 function fromBytes(bytes) {
31778 while (i < bytes.length) {
31782 result.push(String.fromCharCode(c));
31784 } else if (c > 191 && c < 224) {
31785 result.push(String.fromCharCode((c & 0x1f) << 6 | bytes[i + 1] & 0x3f));
31788 result.push(String.fromCharCode((c & 0x0f) << 12 | (bytes[i + 1] & 0x3f) << 6 | bytes[i + 2] & 0x3f));
31793 return result.join('');
31798 fromBytes: fromBytes
31802 var convertHex = function () {
31803 function toBytes(text) {
31806 for (var i = 0; i < text.length; i += 2) {
31807 result.push(parseInt(text.substr(i, 2), 16));
31811 } // http://ixti.net/development/javascript/2011/11/11/base64-encodedecode-of-utf8-in-browser-with-js.html
31814 var Hex = '0123456789abcdef';
31816 function fromBytes(bytes) {
31819 for (var i = 0; i < bytes.length; i++) {
31821 result.push(Hex[(v & 0xf0) >> 4] + Hex[v & 0x0f]);
31824 return result.join('');
31829 fromBytes: fromBytes
31831 }(); // Number of rounds by keysize
31834 var numberOfRounds = {
31838 }; // Round constant words
31840 var rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91]; // S-box and Inverse S-box (S is for Substitution)
31842 var S = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16];
31843 var Si = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]; // Transformations for encryption
31845 var T1 = [0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a];
31846 var T2 = [0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616];
31847 var T3 = [0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16];
31848 var T4 = [0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c]; // Transformations for decryption
31850 var T5 = [0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742];
31851 var T6 = [0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857];
31852 var T7 = [0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8];
31853 var T8 = [0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0]; // Transformations for decryption key expansion
31855 var U1 = [0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3];
31856 var U2 = [0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697];
31857 var U3 = [0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46];
31858 var U4 = [0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d];
31860 function convertToInt32(bytes) {
31863 for (var i = 0; i < bytes.length; i += 4) {
31864 result.push(bytes[i] << 24 | bytes[i + 1] << 16 | bytes[i + 2] << 8 | bytes[i + 3]);
31870 var AES = function AES(key) {
31871 if (!(this instanceof AES)) {
31872 throw Error('AES must be instanitated with `new`');
31875 Object.defineProperty(this, 'key', {
31876 value: coerceArray(key, true)
31882 AES.prototype._prepare = function () {
31883 var rounds = numberOfRounds[this.key.length];
31885 if (rounds == null) {
31886 throw new Error('invalid key size (must be 16, 24 or 32 bytes)');
31887 } // encryption round keys
31890 this._Ke = []; // decryption round keys
31894 for (var i = 0; i <= rounds; i++) {
31895 this._Ke.push([0, 0, 0, 0]);
31897 this._Kd.push([0, 0, 0, 0]);
31900 var roundKeyCount = (rounds + 1) * 4;
31901 var KC = this.key.length / 4; // convert the key into ints
31903 var tk = convertToInt32(this.key); // copy values into round key arrays
31907 for (var i = 0; i < KC; i++) {
31909 this._Ke[index][i % 4] = tk[i];
31910 this._Kd[rounds - index][i % 4] = tk[i];
31911 } // key expansion (fips-197 section 5.2)
31914 var rconpointer = 0;
31918 while (t < roundKeyCount) {
31920 tk[0] ^= S[tt >> 16 & 0xFF] << 24 ^ S[tt >> 8 & 0xFF] << 16 ^ S[tt & 0xFF] << 8 ^ S[tt >> 24 & 0xFF] ^ rcon[rconpointer] << 24;
31921 rconpointer += 1; // key expansion (for non-256 bit)
31924 for (var i = 1; i < KC; i++) {
31925 tk[i] ^= tk[i - 1];
31926 } // key expansion for 256-bit keys is "slightly different" (fips-197)
31929 for (var i = 1; i < KC / 2; i++) {
31930 tk[i] ^= tk[i - 1];
31933 tt = tk[KC / 2 - 1];
31934 tk[KC / 2] ^= S[tt & 0xFF] ^ S[tt >> 8 & 0xFF] << 8 ^ S[tt >> 16 & 0xFF] << 16 ^ S[tt >> 24 & 0xFF] << 24;
31936 for (var i = KC / 2 + 1; i < KC; i++) {
31937 tk[i] ^= tk[i - 1];
31939 } // copy values into round key arrays
31946 while (i < KC && t < roundKeyCount) {
31949 this._Ke[r][c] = tk[i];
31950 this._Kd[rounds - r][c] = tk[i++];
31953 } // inverse-cipher-ify the decryption round key (fips-197 section 5.3)
31956 for (var r = 1; r < rounds; r++) {
31957 for (var c = 0; c < 4; c++) {
31958 tt = this._Kd[r][c];
31959 this._Kd[r][c] = U1[tt >> 24 & 0xFF] ^ U2[tt >> 16 & 0xFF] ^ U3[tt >> 8 & 0xFF] ^ U4[tt & 0xFF];
31964 AES.prototype.encrypt = function (plaintext) {
31965 if (plaintext.length != 16) {
31966 throw new Error('invalid plaintext size (must be 16 bytes)');
31969 var rounds = this._Ke.length - 1;
31970 var a = [0, 0, 0, 0]; // convert plaintext to (ints ^ key)
31972 var t = convertToInt32(plaintext);
31974 for (var i = 0; i < 4; i++) {
31975 t[i] ^= this._Ke[0][i];
31976 } // apply round transforms
31979 for (var r = 1; r < rounds; r++) {
31980 for (var i = 0; i < 4; i++) {
31981 a[i] = T1[t[i] >> 24 & 0xff] ^ T2[t[(i + 1) % 4] >> 16 & 0xff] ^ T3[t[(i + 2) % 4] >> 8 & 0xff] ^ T4[t[(i + 3) % 4] & 0xff] ^ this._Ke[r][i];
31985 } // the last round is special
31988 var result = createArray(16),
31991 for (var i = 0; i < 4; i++) {
31992 tt = this._Ke[rounds][i];
31993 result[4 * i] = (S[t[i] >> 24 & 0xff] ^ tt >> 24) & 0xff;
31994 result[4 * i + 1] = (S[t[(i + 1) % 4] >> 16 & 0xff] ^ tt >> 16) & 0xff;
31995 result[4 * i + 2] = (S[t[(i + 2) % 4] >> 8 & 0xff] ^ tt >> 8) & 0xff;
31996 result[4 * i + 3] = (S[t[(i + 3) % 4] & 0xff] ^ tt) & 0xff;
32002 AES.prototype.decrypt = function (ciphertext) {
32003 if (ciphertext.length != 16) {
32004 throw new Error('invalid ciphertext size (must be 16 bytes)');
32007 var rounds = this._Kd.length - 1;
32008 var a = [0, 0, 0, 0]; // convert plaintext to (ints ^ key)
32010 var t = convertToInt32(ciphertext);
32012 for (var i = 0; i < 4; i++) {
32013 t[i] ^= this._Kd[0][i];
32014 } // apply round transforms
32017 for (var r = 1; r < rounds; r++) {
32018 for (var i = 0; i < 4; i++) {
32019 a[i] = T5[t[i] >> 24 & 0xff] ^ T6[t[(i + 3) % 4] >> 16 & 0xff] ^ T7[t[(i + 2) % 4] >> 8 & 0xff] ^ T8[t[(i + 1) % 4] & 0xff] ^ this._Kd[r][i];
32023 } // the last round is special
32026 var result = createArray(16),
32029 for (var i = 0; i < 4; i++) {
32030 tt = this._Kd[rounds][i];
32031 result[4 * i] = (Si[t[i] >> 24 & 0xff] ^ tt >> 24) & 0xff;
32032 result[4 * i + 1] = (Si[t[(i + 3) % 4] >> 16 & 0xff] ^ tt >> 16) & 0xff;
32033 result[4 * i + 2] = (Si[t[(i + 2) % 4] >> 8 & 0xff] ^ tt >> 8) & 0xff;
32034 result[4 * i + 3] = (Si[t[(i + 1) % 4] & 0xff] ^ tt) & 0xff;
32040 * Mode Of Operation - Electonic Codebook (ECB)
32044 var ModeOfOperationECB = function ModeOfOperationECB(key) {
32045 if (!(this instanceof ModeOfOperationECB)) {
32046 throw Error('AES must be instanitated with `new`');
32049 this.description = "Electronic Code Block";
32051 this._aes = new AES(key);
32054 ModeOfOperationECB.prototype.encrypt = function (plaintext) {
32055 plaintext = coerceArray(plaintext);
32057 if (plaintext.length % 16 !== 0) {
32058 throw new Error('invalid plaintext size (must be multiple of 16 bytes)');
32061 var ciphertext = createArray(plaintext.length);
32062 var block = createArray(16);
32064 for (var i = 0; i < plaintext.length; i += 16) {
32065 copyArray(plaintext, block, 0, i, i + 16);
32066 block = this._aes.encrypt(block);
32067 copyArray(block, ciphertext, i);
32073 ModeOfOperationECB.prototype.decrypt = function (ciphertext) {
32074 ciphertext = coerceArray(ciphertext);
32076 if (ciphertext.length % 16 !== 0) {
32077 throw new Error('invalid ciphertext size (must be multiple of 16 bytes)');
32080 var plaintext = createArray(ciphertext.length);
32081 var block = createArray(16);
32083 for (var i = 0; i < ciphertext.length; i += 16) {
32084 copyArray(ciphertext, block, 0, i, i + 16);
32085 block = this._aes.decrypt(block);
32086 copyArray(block, plaintext, i);
32092 * Mode Of Operation - Cipher Block Chaining (CBC)
32096 var ModeOfOperationCBC = function ModeOfOperationCBC(key, iv) {
32097 if (!(this instanceof ModeOfOperationCBC)) {
32098 throw Error('AES must be instanitated with `new`');
32101 this.description = "Cipher Block Chaining";
32105 iv = createArray(16);
32106 } else if (iv.length != 16) {
32107 throw new Error('invalid initialation vector size (must be 16 bytes)');
32110 this._lastCipherblock = coerceArray(iv, true);
32111 this._aes = new AES(key);
32114 ModeOfOperationCBC.prototype.encrypt = function (plaintext) {
32115 plaintext = coerceArray(plaintext);
32117 if (plaintext.length % 16 !== 0) {
32118 throw new Error('invalid plaintext size (must be multiple of 16 bytes)');
32121 var ciphertext = createArray(plaintext.length);
32122 var block = createArray(16);
32124 for (var i = 0; i < plaintext.length; i += 16) {
32125 copyArray(plaintext, block, 0, i, i + 16);
32127 for (var j = 0; j < 16; j++) {
32128 block[j] ^= this._lastCipherblock[j];
32131 this._lastCipherblock = this._aes.encrypt(block);
32132 copyArray(this._lastCipherblock, ciphertext, i);
32138 ModeOfOperationCBC.prototype.decrypt = function (ciphertext) {
32139 ciphertext = coerceArray(ciphertext);
32141 if (ciphertext.length % 16 !== 0) {
32142 throw new Error('invalid ciphertext size (must be multiple of 16 bytes)');
32145 var plaintext = createArray(ciphertext.length);
32146 var block = createArray(16);
32148 for (var i = 0; i < ciphertext.length; i += 16) {
32149 copyArray(ciphertext, block, 0, i, i + 16);
32150 block = this._aes.decrypt(block);
32152 for (var j = 0; j < 16; j++) {
32153 plaintext[i + j] = block[j] ^ this._lastCipherblock[j];
32156 copyArray(ciphertext, this._lastCipherblock, 0, i, i + 16);
32162 * Mode Of Operation - Cipher Feedback (CFB)
32166 var ModeOfOperationCFB = function ModeOfOperationCFB(key, iv, segmentSize) {
32167 if (!(this instanceof ModeOfOperationCFB)) {
32168 throw Error('AES must be instanitated with `new`');
32171 this.description = "Cipher Feedback";
32175 iv = createArray(16);
32176 } else if (iv.length != 16) {
32177 throw new Error('invalid initialation vector size (must be 16 size)');
32180 if (!segmentSize) {
32184 this.segmentSize = segmentSize;
32185 this._shiftRegister = coerceArray(iv, true);
32186 this._aes = new AES(key);
32189 ModeOfOperationCFB.prototype.encrypt = function (plaintext) {
32190 if (plaintext.length % this.segmentSize != 0) {
32191 throw new Error('invalid plaintext size (must be segmentSize bytes)');
32194 var encrypted = coerceArray(plaintext, true);
32197 for (var i = 0; i < encrypted.length; i += this.segmentSize) {
32198 xorSegment = this._aes.encrypt(this._shiftRegister);
32200 for (var j = 0; j < this.segmentSize; j++) {
32201 encrypted[i + j] ^= xorSegment[j];
32202 } // Shift the register
32205 copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize);
32206 copyArray(encrypted, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize);
32212 ModeOfOperationCFB.prototype.decrypt = function (ciphertext) {
32213 if (ciphertext.length % this.segmentSize != 0) {
32214 throw new Error('invalid ciphertext size (must be segmentSize bytes)');
32217 var plaintext = coerceArray(ciphertext, true);
32220 for (var i = 0; i < plaintext.length; i += this.segmentSize) {
32221 xorSegment = this._aes.encrypt(this._shiftRegister);
32223 for (var j = 0; j < this.segmentSize; j++) {
32224 plaintext[i + j] ^= xorSegment[j];
32225 } // Shift the register
32228 copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize);
32229 copyArray(ciphertext, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize);
32235 * Mode Of Operation - Output Feedback (OFB)
32239 var ModeOfOperationOFB = function ModeOfOperationOFB(key, iv) {
32240 if (!(this instanceof ModeOfOperationOFB)) {
32241 throw Error('AES must be instanitated with `new`');
32244 this.description = "Output Feedback";
32248 iv = createArray(16);
32249 } else if (iv.length != 16) {
32250 throw new Error('invalid initialation vector size (must be 16 bytes)');
32253 this._lastPrecipher = coerceArray(iv, true);
32254 this._lastPrecipherIndex = 16;
32255 this._aes = new AES(key);
32258 ModeOfOperationOFB.prototype.encrypt = function (plaintext) {
32259 var encrypted = coerceArray(plaintext, true);
32261 for (var i = 0; i < encrypted.length; i++) {
32262 if (this._lastPrecipherIndex === 16) {
32263 this._lastPrecipher = this._aes.encrypt(this._lastPrecipher);
32264 this._lastPrecipherIndex = 0;
32267 encrypted[i] ^= this._lastPrecipher[this._lastPrecipherIndex++];
32271 }; // Decryption is symetric
32274 ModeOfOperationOFB.prototype.decrypt = ModeOfOperationOFB.prototype.encrypt;
32276 * Counter object for CTR common mode of operation
32279 var Counter = function Counter(initialValue) {
32280 if (!(this instanceof Counter)) {
32281 throw Error('Counter must be instanitated with `new`');
32282 } // We allow 0, but anything false-ish uses the default 1
32285 if (initialValue !== 0 && !initialValue) {
32289 if (typeof initialValue === 'number') {
32290 this._counter = createArray(16);
32291 this.setValue(initialValue);
32293 this.setBytes(initialValue);
32297 Counter.prototype.setValue = function (value) {
32298 if (typeof value !== 'number' || parseInt(value) != value) {
32299 throw new Error('invalid counter value (must be an integer)');
32300 } // We cannot safely handle numbers beyond the safe range for integers
32303 if (value > Number.MAX_SAFE_INTEGER) {
32304 throw new Error('integer value out of safe range');
32307 for (var index = 15; index >= 0; --index) {
32308 this._counter[index] = value % 256;
32309 value = parseInt(value / 256);
32313 Counter.prototype.setBytes = function (bytes) {
32314 bytes = coerceArray(bytes, true);
32316 if (bytes.length != 16) {
32317 throw new Error('invalid counter bytes size (must be 16 bytes)');
32320 this._counter = bytes;
32323 Counter.prototype.increment = function () {
32324 for (var i = 15; i >= 0; i--) {
32325 if (this._counter[i] === 255) {
32326 this._counter[i] = 0;
32328 this._counter[i]++;
32334 * Mode Of Operation - Counter (CTR)
32338 var ModeOfOperationCTR = function ModeOfOperationCTR(key, counter) {
32339 if (!(this instanceof ModeOfOperationCTR)) {
32340 throw Error('AES must be instanitated with `new`');
32343 this.description = "Counter";
32346 if (!(counter instanceof Counter)) {
32347 counter = new Counter(counter);
32350 this._counter = counter;
32351 this._remainingCounter = null;
32352 this._remainingCounterIndex = 16;
32353 this._aes = new AES(key);
32356 ModeOfOperationCTR.prototype.encrypt = function (plaintext) {
32357 var encrypted = coerceArray(plaintext, true);
32359 for (var i = 0; i < encrypted.length; i++) {
32360 if (this._remainingCounterIndex === 16) {
32361 this._remainingCounter = this._aes.encrypt(this._counter._counter);
32362 this._remainingCounterIndex = 0;
32364 this._counter.increment();
32367 encrypted[i] ^= this._remainingCounter[this._remainingCounterIndex++];
32371 }; // Decryption is symetric
32374 ModeOfOperationCTR.prototype.decrypt = ModeOfOperationCTR.prototype.encrypt; ///////////////////////
32376 // See:https://tools.ietf.org/html/rfc2315
32378 function pkcs7pad(data) {
32379 data = coerceArray(data, true);
32380 var padder = 16 - data.length % 16;
32381 var result = createArray(data.length + padder);
32382 copyArray(data, result);
32384 for (var i = data.length; i < result.length; i++) {
32385 result[i] = padder;
32391 function pkcs7strip(data) {
32392 data = coerceArray(data, true);
32394 if (data.length < 16) {
32395 throw new Error('PKCS#7 invalid length');
32398 var padder = data[data.length - 1];
32401 throw new Error('PKCS#7 padding byte out of range');
32404 var length = data.length - padder;
32406 for (var i = 0; i < padder; i++) {
32407 if (data[length + i] !== padder) {
32408 throw new Error('PKCS#7 invalid padding byte');
32412 var result = createArray(length);
32413 copyArray(data, result, 0, 0, length);
32415 } ///////////////////////
32417 // The block cipher
32424 ecb: ModeOfOperationECB,
32425 cbc: ModeOfOperationCBC,
32426 cfb: ModeOfOperationCFB,
32427 ofb: ModeOfOperationOFB,
32428 ctr: ModeOfOperationCTR
32441 coerceArray: coerceArray,
32442 createArray: createArray,
32443 copyArray: copyArray
32448 module.exports = aesjs; // RequireJS/AMD
32449 // http://www.requirejs.org/docs/api.html
32450 // https://github.com/amdjs/amdjs-api/wiki/AMD
32455 var aesjs = aesJs.exports;
32457 // We can use keys that are 128 bits (16 bytes), 192 bits (24 bytes) or 256 bits (32 bytes).
32458 // To generate a random key: window.crypto.getRandomValues(new Uint8Array(16));
32459 // This default signing key is built into iD and can be used to mask/unmask sensitive values.
32461 var DEFAULT_128 = [250, 157, 60, 79, 142, 134, 229, 129, 138, 126, 210, 129, 29, 71, 160, 208];
32462 function utilAesEncrypt(text, key) {
32463 key = key || DEFAULT_128;
32464 var textBytes = aesjs.utils.utf8.toBytes(text);
32465 var aesCtr = new aesjs.ModeOfOperation.ctr(key);
32466 var encryptedBytes = aesCtr.encrypt(textBytes);
32467 var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
32468 return encryptedHex;
32470 function utilAesDecrypt(encryptedHex, key) {
32471 key = key || DEFAULT_128;
32472 var encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex);
32473 var aesCtr = new aesjs.ModeOfOperation.ctr(key);
32474 var decryptedBytes = aesCtr.decrypt(encryptedBytes);
32475 var text = aesjs.utils.utf8.fromBytes(decryptedBytes);
32479 function utilCleanTags(tags) {
32482 for (var k in tags) {
32486 if (v !== undefined) {
32487 out[k] = cleanValue(k, v);
32493 function cleanValue(k, v) {
32494 function keepSpaces(k) {
32495 return /_hours|_times|:conditional$/.test(k);
32499 return /^(description|note|fixme)$/.test(k);
32502 if (skip(k)) return v;
32503 var cleaned = v.split(';').map(function (s) {
32505 }).join(keepSpaces(k) ? '; ' : ';'); // The code below is not intended to validate websites and emails.
32506 // It is only intended to prevent obvious copy-paste errors. (#2323)
32507 // clean website- and email-like tags
32509 if (k.indexOf('website') !== -1 || k.indexOf('email') !== -1 || cleaned.indexOf('http') === 0) {
32510 cleaned = cleaned.replace(/[\u200B-\u200F\uFEFF]/g, ''); // strip LRM and other zero width chars
32519 function utilDetect(refresh) {
32520 if (_detected && !refresh) return _detected;
32522 var ua = navigator.userAgent;
32526 m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i); // Edge
32529 _detected.browser = m[1];
32530 _detected.version = m[2];
32533 if (!_detected.browser) {
32534 m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i); // IE11
32537 _detected.browser = 'msie';
32538 _detected.version = m[1];
32542 if (!_detected.browser) {
32543 m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i); // Opera 15+
32546 _detected.browser = 'Opera';
32547 _detected.version = m[2];
32551 if (!_detected.browser) {
32552 m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
32555 _detected.browser = m[1];
32556 _detected.version = m[2];
32557 m = ua.match(/version\/([\.\d]+)/i);
32558 if (m !== null) _detected.version = m[1];
32562 if (!_detected.browser) {
32563 _detected.browser = navigator.appName;
32564 _detected.version = navigator.appVersion;
32565 } // keep major.minor version only..
32568 _detected.version = _detected.version.split(/\W/).slice(0, 2).join('.'); // detect other browser capabilities
32569 // Legacy Opera has incomplete svg style support. See #715
32571 _detected.opera = _detected.browser.toLowerCase() === 'opera' && parseFloat(_detected.version) < 15;
32573 if (_detected.browser.toLowerCase() === 'msie') {
32574 _detected.ie = true;
32575 _detected.browser = 'Internet Explorer';
32576 _detected.support = parseFloat(_detected.version) >= 11;
32578 _detected.ie = false;
32579 _detected.support = true;
32582 _detected.filedrop = window.FileReader && 'ondrop' in window;
32583 _detected.download = !(_detected.ie || _detected.browser.toLowerCase() === 'edge');
32584 _detected.cssfilters = !(_detected.ie || _detected.browser.toLowerCase() === 'edge');
32587 if (/Win/.test(ua)) {
32588 _detected.os = 'win';
32589 _detected.platform = 'Windows';
32590 } else if (/Mac/.test(ua)) {
32591 _detected.os = 'mac';
32592 _detected.platform = 'Macintosh';
32593 } else if (/X11/.test(ua) || /Linux/.test(ua)) {
32594 _detected.os = 'linux';
32595 _detected.platform = 'Linux';
32597 _detected.os = 'win';
32598 _detected.platform = 'Unknown';
32601 _detected.isMobileWebKit = (/\b(iPad|iPhone|iPod)\b/.test(ua) || // HACK: iPadOS 13+ requests desktop sites by default by using a Mac user agent,
32602 // so assume any "mac" with multitouch is actually iOS
32603 navigator.platform === 'MacIntel' && 'maxTouchPoints' in navigator && navigator.maxTouchPoints > 1) && /WebKit/.test(ua) && !/Edge/.test(ua) && !window.MSStream;
32605 // An array of locales requested by the browser in priority order.
32607 _detected.browserLocales = Array.from(new Set( // remove duplicates
32608 [navigator.language].concat(navigator.languages || []).concat([// old property for backwards compatibility
32609 navigator.userLanguage]) // remove any undefined values
32610 .filter(Boolean)));
32613 var loc = window.top.location;
32614 var origin = loc.origin;
32617 // for unpatched IE11
32618 origin = loc.protocol + '//' + loc.hostname + (loc.port ? ':' + loc.port : '');
32621 _detected.host = origin + loc.pathname;
32625 // Like selection.property('value', ...), but avoids no-op value sets,
32626 // which can result in layout/repaint thrashing in some situations.
32628 /** @returns {string} */
32629 function utilGetSetValue(selection, value) {
32630 function d3_selection_value(value) {
32631 function valueNull() {
32635 function valueConstant() {
32636 if (this.value !== value) {
32637 this.value = value;
32641 function valueFunction() {
32642 var x = value.apply(this, arguments);
32644 if (x === null || x === undefined) {
32646 } else if (this.value !== x) {
32651 return value === null || value === undefined ? valueNull : typeof value === 'function' ? valueFunction : valueConstant;
32654 if (arguments.length === 1) {
32655 return selection.property('value');
32658 return selection.each(d3_selection_value(value));
32661 function utilKeybinding(namespace) {
32662 var _keybindings = {};
32664 function testBindings(d3_event, isCapturing) {
32665 var didMatch = false;
32666 var bindings = Object.keys(_keybindings).map(function (id) {
32667 return _keybindings[id];
32669 var i, binding; // Most key shortcuts will accept either lower or uppercase ('h' or 'H'),
32670 // so we don't strictly match on the shift key, but we prioritize
32671 // shifted keybindings first, and fallback to unshifted only if no match.
32672 // (This lets us differentiate between '←'/'⇧←' or '⌘Z'/'⌘⇧Z')
32673 // priority match shifted keybindings first
32675 for (i = 0; i < bindings.length; i++) {
32676 binding = bindings[i];
32677 if (!binding.event.modifiers.shiftKey) continue; // no shift
32679 if (!!binding.capture !== isCapturing) continue;
32681 if (matches(d3_event, binding, true)) {
32682 binding.callback(d3_event);
32683 didMatch = true; // match a max of one binding per event
32689 if (didMatch) return; // then unshifted keybindings
32691 for (i = 0; i < bindings.length; i++) {
32692 binding = bindings[i];
32693 if (binding.event.modifiers.shiftKey) continue; // shift
32695 if (!!binding.capture !== isCapturing) continue;
32697 if (matches(d3_event, binding, false)) {
32698 binding.callback(d3_event);
32703 function matches(d3_event, binding, testShift) {
32704 var event = d3_event;
32705 var isMatch = false;
32706 var tryKeyCode = true; // Prefer a match on `KeyboardEvent.key`
32708 if (event.key !== undefined) {
32709 tryKeyCode = event.key.charCodeAt(0) > 255; // outside ISO-Latin-1
32713 if (binding.event.key === undefined) {
32715 } else if (Array.isArray(binding.event.key)) {
32716 if (binding.event.key.map(function (s) {
32717 return s.toLowerCase();
32718 }).indexOf(event.key.toLowerCase()) === -1) {
32722 if (event.key.toLowerCase() !== binding.event.key.toLowerCase()) {
32726 } // Fallback match on `KeyboardEvent.keyCode`, can happen if:
32727 // - browser doesn't support `KeyboardEvent.key`
32728 // - `KeyboardEvent.key` is outside ISO-Latin-1 range (cyrillic?)
32731 if (!isMatch && tryKeyCode) {
32732 isMatch = event.keyCode === binding.event.keyCode;
32735 if (!isMatch) return false; // test modifier keys
32737 if (!(event.ctrlKey && event.altKey)) {
32738 // if both are set, assume AltGr and skip it - #4096
32739 if (event.ctrlKey !== binding.event.modifiers.ctrlKey) return false;
32740 if (event.altKey !== binding.event.modifiers.altKey) return false;
32743 if (event.metaKey !== binding.event.modifiers.metaKey) return false;
32744 if (testShift && event.shiftKey !== binding.event.modifiers.shiftKey) return false;
32749 function capture(d3_event) {
32750 testBindings(d3_event, true);
32753 function bubble(d3_event) {
32754 var tagName = select(d3_event.target).node().tagName;
32756 if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA') {
32760 testBindings(d3_event, false);
32763 function keybinding(selection) {
32764 selection = selection || select(document);
32765 selection.on('keydown.capture.' + namespace, capture, true);
32766 selection.on('keydown.bubble.' + namespace, bubble, false);
32768 } // was: keybinding.off()
32771 keybinding.unbind = function (selection) {
32773 selection = selection || select(document);
32774 selection.on('keydown.capture.' + namespace, null);
32775 selection.on('keydown.bubble.' + namespace, null);
32779 keybinding.clear = function () {
32782 }; // Remove one or more keycode bindings.
32785 keybinding.off = function (codes, capture) {
32786 var arr = utilArrayUniq([].concat(codes));
32788 for (var i = 0; i < arr.length; i++) {
32789 var id = arr[i] + (capture ? '-capture' : '-bubble');
32790 delete _keybindings[id];
32794 }; // Add one or more keycode bindings.
32797 keybinding.on = function (codes, callback, capture) {
32798 if (typeof callback !== 'function') {
32799 return keybinding.off(codes, capture);
32802 var arr = utilArrayUniq([].concat(codes));
32804 for (var i = 0; i < arr.length; i++) {
32805 var id = arr[i] + (capture ? '-capture' : '-bubble');
32809 callback: callback,
32824 if (_keybindings[id]) {
32825 console.warn('warning: duplicate keybinding for "' + id + '"'); // eslint-disable-line no-console
32828 _keybindings[id] = binding;
32829 var matches = arr[i].toLowerCase().match(/(?:(?:[^+⇧⌃⌥⌘])+|[⇧⌃⌥⌘]|\+\+|^\+$)/g);
32831 for (var j = 0; j < matches.length; j++) {
32832 // Normalise matching errors
32833 if (matches[j] === '++') matches[j] = '+';
32835 if (matches[j] in utilKeybinding.modifierCodes) {
32836 var prop = utilKeybinding.modifierProperties[utilKeybinding.modifierCodes[matches[j]]];
32837 binding.event.modifiers[prop] = true;
32839 binding.event.key = utilKeybinding.keys[matches[j]] || matches[j];
32841 if (matches[j] in utilKeybinding.keyCodes) {
32842 binding.event.keyCode = utilKeybinding.keyCodes[matches[j]];
32854 * See https://github.com/keithamus/jwerty
32857 utilKeybinding.modifierCodes = {
32861 // CTRL key, on Mac: ⌃
32864 // ALT key, on Mac: ⌥ (Alt)
32868 // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
32875 utilKeybinding.modifierProperties = {
32881 utilKeybinding.plusKeys = ['plus', 'ffplus', '=', 'ffequals', '≠', '±'];
32882 utilKeybinding.minusKeys = ['_', '-', 'ffminus', 'dash', '–', '—'];
32883 utilKeybinding.keys = {
32884 // Backspace key, on Mac: ⌫ (Backspace)
32886 backspace: 'Backspace',
32887 // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
32900 'pause-break': 'Pause',
32901 // Caps Lock key, ⇪
32904 'caps-lock': 'CapsLock',
32905 // Escape key, on Mac: ⎋, on Windows: Esc
32906 '⎋': ['Escape', 'Esc'],
32907 escape: ['Escape', 'Esc'],
32908 esc: ['Escape', 'Esc'],
32910 space: [' ', 'Spacebar'],
32911 // Page-Up key, or pgup, on Mac: ↖
32914 'page-up': 'PageUp',
32915 // Page-Down key, or pgdown, on Mac: ↘
32917 pgdown: 'PageDown',
32918 'page-down': 'PageDown',
32919 // END key, on Mac: ⇟
32922 // HOME key, on Mac: ⇞
32925 // Insert key, or ins
32928 // Delete key, on Mac: ⌦ (Delete)
32929 '⌦': ['Delete', 'Del'],
32930 del: ['Delete', 'Del'],
32931 'delete': ['Delete', 'Del'],
32932 // Left Arrow Key, or ←
32933 '←': ['ArrowLeft', 'Left'],
32934 left: ['ArrowLeft', 'Left'],
32935 'arrow-left': ['ArrowLeft', 'Left'],
32936 // Up Arrow Key, or ↑
32937 '↑': ['ArrowUp', 'Up'],
32938 up: ['ArrowUp', 'Up'],
32939 'arrow-up': ['ArrowUp', 'Up'],
32940 // Right Arrow Key, or →
32941 '→': ['ArrowRight', 'Right'],
32942 right: ['ArrowRight', 'Right'],
32943 'arrow-right': ['ArrowRight', 'Right'],
32944 // Up Arrow Key, or ↓
32945 '↓': ['ArrowDown', 'Down'],
32946 down: ['ArrowDown', 'Down'],
32947 'arrow-down': ['ArrowDown', 'Down'],
32948 // odities, stuff for backward compatibility (browsers and code):
32949 // Num-Multiply, or *
32950 '*': ['*', 'Multiply'],
32951 star: ['*', 'Multiply'],
32952 asterisk: ['*', 'Multiply'],
32953 multiply: ['*', 'Multiply'],
32956 'plus': ['+', 'Add'],
32957 // Num-Subtract, or -
32958 '-': ['-', 'Subtract'],
32959 subtract: ['-', 'Subtract'],
32960 'dash': ['-', 'Subtract'],
32967 // Period, or ., or full-stop
32970 // Slash, or /, or forward-slash
32972 'forward-slash': '/',
32973 // Tick, or `, or back-quote
32976 // Open bracket, or [
32977 'open-bracket': '[',
32978 // Back slash, or \
32979 'back-slash': '\\',
32980 // Close backet, or ]
32981 'close-bracket': ']',
32982 // Apostrophe, or Quote, or '
33023 utilKeybinding.keyCodes = {
33024 // Backspace key, on Mac: ⌫ (Backspace)
33027 // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
33041 // Caps Lock key, ⇪
33045 // Escape key, on Mac: ⎋, on Windows: Esc
33051 // Page-Up key, or pgup, on Mac: ↖
33055 // Page-Down key, or pgdown, on Mac: ↘
33059 // END key, on Mac: ⇟
33062 // HOME key, on Mac: ⇞
33065 // Insert key, or ins
33068 // Delete key, on Mac: ⌦ (Delete)
33072 // Left Arrow Key, or ←
33076 // Up Arrow Key, or ↑
33080 // Right Arrow Key, or →
33084 // Up Arrow Key, or ↓
33088 // odities, printing characters that come out wrong:
33091 // Num-Multiply, or *
33099 // Num-Subtract, or -
33102 // Vertical Bar / Pipe
33117 // Dash / Underscore key
33119 // Period, or ., or full-stop
33123 // Slash, or /, or forward-slash
33126 'forward-slash': 191,
33127 // Tick, or `, or back-quote
33131 // Open bracket, or [
33133 'open-bracket': 219,
33134 // Back slash, or \
33137 // Close backet, or ]
33139 'close-bracket': 221,
33140 // Apostrophe, or Quote, or '
33149 while (++i < 106) {
33150 utilKeybinding.keyCodes['num-' + n] = i;
33159 utilKeybinding.keyCodes[n] = i;
33167 while (++i < 136) {
33168 utilKeybinding.keyCodes['f' + n] = i;
33176 utilKeybinding.keyCodes[String.fromCharCode(i).toLowerCase()] = i;
33179 function utilObjectOmit(obj, omitKeys) {
33180 return Object.keys(obj).reduce(function (result, key) {
33181 if (omitKeys.indexOf(key) === -1) {
33182 result[key] = obj[key]; // keep
33189 // Copies a variable number of methods from source to target.
33190 function utilRebind(target, source) {
33192 n = arguments.length,
33196 target[method = arguments[i]] = d3_rebind(target, source, source[method]);
33200 } // Method is assumed to be a standard D3 getter-setter:
33201 // If passed with no arguments, gets the value.
33202 // If passed with arguments, sets the value and returns the target.
33204 function d3_rebind(target, source, method) {
33205 return function () {
33206 var value = method.apply(source, arguments);
33207 return value === source ? target : value;
33211 // A per-domain session mutex backed by a cookie and dead man's
33212 // switch. If the session crashes, the mutex will auto-release
33213 // after 5 seconds.
33214 // This accepts a string and returns an object that complies with utilSessionMutexType
33215 function utilSessionMutex(name) {
33220 var expires = new Date();
33221 expires.setSeconds(expires.getSeconds() + 5);
33222 document.cookie = name + '=1; expires=' + expires.toUTCString() + '; sameSite=strict';
33225 mutex.lock = function () {
33226 if (intervalID) return true;
33227 var cookie = document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
33228 if (cookie) return false;
33230 intervalID = window.setInterval(renew, 4000);
33234 mutex.unlock = function () {
33235 if (!intervalID) return;
33236 document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; sameSite=strict';
33237 clearInterval(intervalID);
33241 mutex.locked = function () {
33242 return !!intervalID;
33248 function utilTiler() {
33249 var _size = [256, 256];
33251 var _tileSize = 256;
33252 var _zoomExtent = [0, 20];
33253 var _translate = [_size[0] / 2, _size[1] / 2];
33255 var _skipNullIsland = false;
33257 function clamp(num, min, max) {
33258 return Math.max(min, Math.min(num, max));
33261 function nearNullIsland(tile) {
33267 var center = Math.pow(2, z - 1);
33268 var width = Math.pow(2, z - 6);
33269 var min = center - width / 2;
33270 var max = center + width / 2 - 1;
33271 return x >= min && x <= max && y >= min && y <= max;
33278 var z = geoScaleToZoom(_scale / (2 * Math.PI), _tileSize);
33279 var z0 = clamp(Math.round(z), _zoomExtent[0], _zoomExtent[1]);
33281 var tileMax = Math.pow(2, z0) - 1;
33282 var log2ts = Math.log(_tileSize) * Math.LOG2E;
33283 var k = Math.pow(2, z - z0 + log2ts);
33284 var origin = [(_translate[0] - _scale / 2) / k, (_translate[1] - _scale / 2) / k];
33285 var cols = range$1(clamp(Math.floor(-origin[0]) - _margin, tileMin, tileMax + 1), clamp(Math.ceil(_size[0] / k - origin[0]) + _margin, tileMin, tileMax + 1));
33286 var rows = range$1(clamp(Math.floor(-origin[1]) - _margin, tileMin, tileMax + 1), clamp(Math.ceil(_size[1] / k - origin[1]) + _margin, tileMin, tileMax + 1));
33289 for (var i = 0; i < rows.length; i++) {
33292 for (var j = 0; j < cols.length; j++) {
33295 if (i >= _margin && i <= rows.length - _margin && j >= _margin && j <= cols.length - _margin) {
33296 tiles.unshift([x, y, z0]); // tiles in view at beginning
33298 tiles.push([x, y, z0]); // tiles in margin at the end
33303 tiles.translate = origin;
33308 * getTiles() returns an array of tiles that cover the map view
33312 tiler.getTiles = function (projection) {
33313 var origin = [projection.scale() * Math.PI - projection.translate()[0], projection.scale() * Math.PI - projection.translate()[1]];
33314 this.size(projection.clipExtent()[1]).scale(projection.scale() * 2 * Math.PI).translate(projection.translate());
33315 var tiles = tiler();
33316 var ts = tiles.scale;
33317 return tiles.map(function (tile) {
33318 if (_skipNullIsland && nearNullIsland(tile)) {
33322 var x = tile[0] * ts - origin[0];
33323 var y = tile[1] * ts - origin[1];
33325 id: tile.toString(),
33327 extent: geoExtent(projection.invert([x, y + ts]), projection.invert([x + ts, y]))
33329 }).filter(Boolean);
33332 * getGeoJSON() returns a FeatureCollection for debugging tiles
33336 tiler.getGeoJSON = function (projection) {
33337 var features = tiler.getTiles(projection).map(function (tile) {
33346 coordinates: [tile.extent.polygon()]
33351 type: 'FeatureCollection',
33356 tiler.tileSize = function (val) {
33357 if (!arguments.length) return _tileSize;
33362 tiler.zoomExtent = function (val) {
33363 if (!arguments.length) return _zoomExtent;
33368 tiler.size = function (val) {
33369 if (!arguments.length) return _size;
33374 tiler.scale = function (val) {
33375 if (!arguments.length) return _scale;
33380 tiler.translate = function (val) {
33381 if (!arguments.length) return _translate;
33384 }; // number to extend the rows/columns beyond those covering the viewport
33387 tiler.margin = function (val) {
33388 if (!arguments.length) return _margin;
33393 tiler.skipNullIsland = function (val) {
33394 if (!arguments.length) return _skipNullIsland;
33395 _skipNullIsland = val;
33402 function utilTriggerEvent(target, type) {
33403 target.each(function () {
33404 var evt = document.createEvent('HTMLEvents');
33405 evt.initEvent(type, true, true);
33406 this.dispatchEvent(evt);
33410 var _mainLocations = coreLocations(); // singleton
33411 // `coreLocations` maintains an internal index of all the boundaries/geofences used by iD.
33412 // It's used by presets, community index, background imagery, to know where in the world these things are valid.
33413 // These geofences should be defined by `locationSet` objects:
33415 // let locationSet = {
33416 // include: [ Array of locations ],
33417 // exclude: [ Array of locations ]
33420 // For more info see the location-conflation and country-coder projects, see:
33421 // https://github.com/ideditor/location-conflation
33422 // https://github.com/ideditor/country-coder
33425 function coreLocations() {
33427 var _resolvedFeatures = {}; // cache of *resolved* locationSet features
33429 var _loco = new _default(); // instance of a location-conflation resolver
33432 var _wp; // instance of a which-polygon index
33433 // pre-resolve the worldwide locationSet
33441 resolveLocationSet(world);
33445 var _deferred = new Set();
33447 var _inProcess; // Returns a Promise to process the queue
33450 function processQueue() {
33451 if (!_queue.length) return Promise.resolve(); // console.log(`queue length ${_queue.length}`);
33453 var chunk = _queue.pop();
33455 return new Promise(function (resolvePromise) {
33456 var handle = window.requestIdleCallback(function () {
33457 _deferred["delete"](handle); // const t0 = performance.now();
33460 chunk.forEach(resolveLocationSet); // const t1 = performance.now();
33461 // console.log('chunk processed in ' + (t1 - t0) + ' ms');
33466 _deferred.add(handle);
33467 }).then(function () {
33468 return processQueue();
33470 } // Pass an Object with a `locationSet` property,
33471 // Performs the locationSet resolution, caches the result, and sets a `locationSetID` property on the object.
33474 function resolveLocationSet(obj) {
33475 if (obj.locationSetID) return; // work was done already
33478 var locationSet = obj.locationSet;
33480 if (!locationSet) {
33481 throw new Error('object missing locationSet property');
33484 if (!locationSet.include) {
33485 // missing `include`, default to worldwide include
33486 locationSet.include = ['Q2']; // https://github.com/openstreetmap/iD/pull/8305#discussion_r662344647
33489 var resolved = _loco.resolveLocationSet(locationSet);
33491 var locationSetID = resolved.id;
33492 obj.locationSetID = locationSetID;
33494 if (!resolved.feature.geometry.coordinates.length || !resolved.feature.properties.area) {
33495 throw new Error("locationSet ".concat(locationSetID, " resolves to an empty feature."));
33498 if (!_resolvedFeatures[locationSetID]) {
33499 // First time seeing this locationSet feature
33500 var feature = JSON.parse(JSON.stringify(resolved.feature)); // deep clone
33502 feature.id = locationSetID; // Important: always use the locationSet `id` (`+[Q30]`), not the feature `id` (`Q30`)
33504 feature.properties.id = locationSetID;
33505 _resolvedFeatures[locationSetID] = feature; // insert into cache
33508 obj.locationSet = {
33510 }; // default worldwide
33512 obj.locationSetID = '+[Q2]';
33514 } // Rebuilds the whichPolygon index with whatever features have been resolved.
33517 function rebuildIndex() {
33518 _wp = whichPolygon_1({
33519 features: Object.values(_resolvedFeatures)
33522 // `mergeCustomGeoJSON`
33523 // Accepts an FeatureCollection-like object containing custom locations
33524 // Each feature must have a filename-like `id`, for example: `something.geojson`
33527 // "type": "FeatureCollection"
33530 // "type": "Feature",
33531 // "id": "philly_metro.geojson",
33532 // "properties": { … },
33533 // "geometry": { … }
33540 _this.mergeCustomGeoJSON = function (fc) {
33541 if (fc && fc.type === 'FeatureCollection' && Array.isArray(fc.features)) {
33542 fc.features.forEach(function (feature) {
33543 feature.properties = feature.properties || {};
33544 var props = feature.properties; // Get `id` from either `id` or `properties`
33546 var id = feature.id || props.id;
33547 if (!id || !/^\S+\.geojson$/i.test(id)) return; // Ensure `id` exists and is lowercase
33549 id = id.toLowerCase();
33551 props.id = id; // Ensure `area` property exists
33554 var area = geojsonArea.geometry(feature.geometry) / 1e6; // m² to km²
33556 props.area = Number(area.toFixed(2));
33559 _loco._cache[id] = feature;
33563 // `mergeLocationSets`
33564 // Accepts an Array of Objects containing `locationSet` properties.
33565 // The locationSets will be resolved and indexed in the background.
33567 // { id: 'preset1', locationSet: {…} },
33568 // { id: 'preset2', locationSet: {…} },
33569 // { id: 'preset3', locationSet: {…} },
33572 // After resolving and indexing, the Objects will be decorated with a
33573 // `locationSetID` property.
33575 // { id: 'preset1', locationSet: {…}, locationSetID: '+[Q2]' },
33576 // { id: 'preset2', locationSet: {…}, locationSetID: '+[Q30]' },
33577 // { id: 'preset3', locationSet: {…}, locationSetID: '+[Q2]' },
33581 // Returns a Promise fulfilled when the resolving/indexing has been completed
33582 // This will take some seconds but happen in the background during browser idle time.
33586 _this.mergeLocationSets = function (objects) {
33587 if (!Array.isArray(objects)) return Promise.reject('nothing to do'); // Resolve all locationSets -> geojson, processing data in chunks
33589 // Because this will happen during idle callbacks, we want to choose a chunk size
33590 // that won't make the browser stutter too badly. LocationSets that are a simple
33591 // country coder include will resolve instantly, but ones that involve complex
33592 // include/exclude operations will take some milliseconds longer.
33594 // Some discussion and performance results on these tickets:
33595 // https://github.com/ideditor/location-conflation/issues/26
33596 // https://github.com/osmlab/name-suggestion-index/issues/4784#issuecomment-742003434
33598 _queue = _queue.concat(utilArrayChunk(objects, 200));
33601 _inProcess = processQueue().then(function () {
33611 // Returns a locationSetID for a given locationSet (fallback to `+[Q2]`, world)
33612 // (The locationset doesn't necessarily need to be resolved to compute its `id`)
33615 // `locationSet`: A locationSet, e.g. `{ include: ['us'] }`
33617 // The locationSetID, e.g. `+[Q30]`
33621 _this.locationSetID = function (locationSet) {
33625 locationSetID = _loco.validateLocationSet(locationSet).id;
33627 locationSetID = '+[Q2]'; // the world
33630 return locationSetID;
33633 // Returns the resolved GeoJSON feature for a given locationSetID (fallback to 'world')
33636 // `locationSetID`: id of the form like `+[Q30]` (United States)
33638 // A GeoJSON feature:
33640 // type: 'Feature',
33642 // properties: { id: '+[Q30]', area: 21817019.17, … },
33647 _this.feature = function (locationSetID) {
33648 return _resolvedFeatures[locationSetID] || _resolvedFeatures['+[Q2]'];
33651 // Find all the resolved locationSets valid at the given location.
33652 // Results include the area (in km²) to facilitate sorting.
33655 // `loc`: the [lon,lat] location to query, e.g. `[-74.4813, 40.7967]`
33657 // Object of locationSetIDs to areas (in km²)
33659 // "+[Q2]": 511207893.3958111,
33660 // "+[Q30]": 21817019.17,
33661 // "+[new_jersey.geojson]": 22390.77,
33667 _this.locationsAt = function (loc) {
33669 (_wp(loc, true) || []).forEach(function (prop) {
33670 return result[prop.id] = prop.area;
33675 // Execute a query directly against which-polygon
33676 // https://github.com/mapbox/which-polygon
33679 // `loc`: the [lon,lat] location to query,
33680 // `multi`: `true` to return all results, `false` to return first result
33682 // Array of GeoJSON *properties* for the locationSet features that exist at `loc`
33686 _this.query = function (loc, multi) {
33687 return _wp(loc, multi);
33688 }; // Direct access to the location-conflation resolver
33691 _this.loco = function () {
33693 }; // Direct access to the which-polygon index
33696 _this.wp = function () {
33704 var $findIndex = arrayIteration.findIndex;
33705 var addToUnscopables$1 = addToUnscopables$6;
33707 var FIND_INDEX = 'findIndex';
33708 var SKIPS_HOLES = true;
33710 // Shouldn't skip holes
33711 if (FIND_INDEX in []) Array(1)[FIND_INDEX](function () { SKIPS_HOLES = false; });
33713 // `Array.prototype.findIndex` method
33714 // https://tc39.es/ecma262/#sec-array.prototype.findindex
33715 $$h({ target: 'Array', proto: true, forced: SKIPS_HOLES }, {
33716 findIndex: function findIndex(callbackfn /* , that = undefined */) {
33717 return $findIndex(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
33721 // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
33722 addToUnscopables$1(FIND_INDEX);
33724 var global$5 = global$1o;
33725 var isRegExp = isRegexp;
33727 var TypeError$3 = global$5.TypeError;
33729 var notARegexp = function (it) {
33730 if (isRegExp(it)) {
33731 throw TypeError$3("The method doesn't accept regular expressions");
33735 var wellKnownSymbol = wellKnownSymbol$t;
33737 var MATCH = wellKnownSymbol('match');
33739 var correctIsRegexpLogic = function (METHOD_NAME) {
33742 '/./'[METHOD_NAME](regexp);
33745 regexp[MATCH] = false;
33746 return '/./'[METHOD_NAME](regexp);
33747 } catch (error2) { /* empty */ }
33752 var uncurryThis$7 = functionUncurryThis;
33753 var notARegExp$2 = notARegexp;
33754 var requireObjectCoercible$3 = requireObjectCoercible$e;
33755 var toString$4 = toString$k;
33756 var correctIsRegExpLogic$2 = correctIsRegexpLogic;
33758 var stringIndexOf = uncurryThis$7(''.indexOf);
33760 // `String.prototype.includes` method
33761 // https://tc39.es/ecma262/#sec-string.prototype.includes
33762 $$g({ target: 'String', proto: true, forced: !correctIsRegExpLogic$2('includes') }, {
33763 includes: function includes(searchString /* , position = 0 */) {
33764 return !!~stringIndexOf(
33765 toString$4(requireObjectCoercible$3(this)),
33766 toString$4(notARegExp$2(searchString)),
33767 arguments.length > 1 ? arguments[1] : undefined
33772 /** Detect free variable `global` from Node.js. */
33773 var freeGlobal = (typeof global === "undefined" ? "undefined" : _typeof(global)) == 'object' && global && global.Object === Object && global;
33775 /** Detect free variable `self`. */
33777 var freeSelf = (typeof self === "undefined" ? "undefined" : _typeof(self)) == 'object' && self && self.Object === Object && self;
33778 /** Used as a reference to the global object. */
33780 var root = freeGlobal || freeSelf || Function('return this')();
33782 /** Built-in value references. */
33784 var _Symbol = root.Symbol;
33786 /** Used for built-in method references. */
33788 var objectProto$1 = Object.prototype;
33789 /** Used to check objects for own properties. */
33791 var hasOwnProperty$2 = objectProto$1.hasOwnProperty;
33793 * Used to resolve the
33794 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
33798 var nativeObjectToString$1 = objectProto$1.toString;
33799 /** Built-in value references. */
33801 var symToStringTag$1 = _Symbol ? _Symbol.toStringTag : undefined;
33803 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
33806 * @param {*} value The value to query.
33807 * @returns {string} Returns the raw `toStringTag`.
33810 function getRawTag(value) {
33811 var isOwn = hasOwnProperty$2.call(value, symToStringTag$1),
33812 tag = value[symToStringTag$1];
33815 value[symToStringTag$1] = undefined;
33816 var unmasked = true;
33819 var result = nativeObjectToString$1.call(value);
33823 value[symToStringTag$1] = tag;
33825 delete value[symToStringTag$1];
33832 /** Used for built-in method references. */
33833 var objectProto = Object.prototype;
33835 * Used to resolve the
33836 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
33840 var nativeObjectToString = objectProto.toString;
33842 * Converts `value` to a string using `Object.prototype.toString`.
33845 * @param {*} value The value to convert.
33846 * @returns {string} Returns the converted string.
33849 function objectToString(value) {
33850 return nativeObjectToString.call(value);
33853 /** `Object#toString` result references. */
33855 var nullTag = '[object Null]',
33856 undefinedTag = '[object Undefined]';
33857 /** Built-in value references. */
33859 var symToStringTag = _Symbol ? _Symbol.toStringTag : undefined;
33861 * The base implementation of `getTag` without fallbacks for buggy environments.
33864 * @param {*} value The value to query.
33865 * @returns {string} Returns the `toStringTag`.
33868 function baseGetTag(value) {
33869 if (value == null) {
33870 return value === undefined ? undefinedTag : nullTag;
33873 return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
33877 * Checks if `value` is object-like. A value is object-like if it's not `null`
33878 * and has a `typeof` result of "object".
33884 * @param {*} value The value to check.
33885 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
33888 * _.isObjectLike({});
33891 * _.isObjectLike([1, 2, 3]);
33894 * _.isObjectLike(_.noop);
33897 * _.isObjectLike(null);
33900 function isObjectLike(value) {
33901 return value != null && _typeof(value) == 'object';
33904 /** `Object#toString` result references. */
33906 var symbolTag = '[object Symbol]';
33908 * Checks if `value` is classified as a `Symbol` primitive or object.
33914 * @param {*} value The value to check.
33915 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
33918 * _.isSymbol(Symbol.iterator);
33921 * _.isSymbol('abc');
33925 function isSymbol(value) {
33926 return _typeof(value) == 'symbol' || isObjectLike(value) && baseGetTag(value) == symbolTag;
33930 * A specialized version of `_.map` for arrays without support for iteratee
33934 * @param {Array} [array] The array to iterate over.
33935 * @param {Function} iteratee The function invoked per iteration.
33936 * @returns {Array} Returns the new mapped array.
33938 function arrayMap(array, iteratee) {
33940 length = array == null ? 0 : array.length,
33941 result = Array(length);
33943 while (++index < length) {
33944 result[index] = iteratee(array[index], index, array);
33951 * Checks if `value` is classified as an `Array` object.
33957 * @param {*} value The value to check.
33958 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
33961 * _.isArray([1, 2, 3]);
33964 * _.isArray(document.body.children);
33967 * _.isArray('abc');
33970 * _.isArray(_.noop);
33973 var isArray$1 = Array.isArray;
33975 /** Used as references for various `Number` constants. */
33977 var INFINITY = 1 / 0;
33978 /** Used to convert symbols to primitives and strings. */
33980 var symbolProto = _Symbol ? _Symbol.prototype : undefined,
33981 symbolToString = symbolProto ? symbolProto.toString : undefined;
33983 * The base implementation of `_.toString` which doesn't convert nullish
33984 * values to empty strings.
33987 * @param {*} value The value to process.
33988 * @returns {string} Returns the string.
33991 function baseToString(value) {
33992 // Exit early for strings to avoid a performance hit in some environments.
33993 if (typeof value == 'string') {
33997 if (isArray$1(value)) {
33998 // Recursively convert values (susceptible to call stack limits).
33999 return arrayMap(value, baseToString) + '';
34002 if (isSymbol(value)) {
34003 return symbolToString ? symbolToString.call(value) : '';
34006 var result = value + '';
34007 return result == '0' && 1 / value == -INFINITY ? '-0' : result;
34010 /** Used to match a single whitespace character. */
34011 var reWhitespace = /\s/;
34013 * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
34014 * character of `string`.
34017 * @param {string} string The string to inspect.
34018 * @returns {number} Returns the index of the last non-whitespace character.
34021 function trimmedEndIndex(string) {
34022 var index = string.length;
34024 while (index-- && reWhitespace.test(string.charAt(index))) {}
34029 /** Used to match leading whitespace. */
34031 var reTrimStart = /^\s+/;
34033 * The base implementation of `_.trim`.
34036 * @param {string} string The string to trim.
34037 * @returns {string} Returns the trimmed string.
34040 function baseTrim(string) {
34041 return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') : string;
34045 * Checks if `value` is the
34046 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
34047 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
34053 * @param {*} value The value to check.
34054 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
34060 * _.isObject([1, 2, 3]);
34063 * _.isObject(_.noop);
34066 * _.isObject(null);
34069 function isObject$2(value) {
34070 var type = _typeof(value);
34072 return value != null && (type == 'object' || type == 'function');
34075 /** Used as references for various `Number` constants. */
34078 /** Used to detect bad signed hexadecimal string values. */
34080 var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
34081 /** Used to detect binary string values. */
34083 var reIsBinary = /^0b[01]+$/i;
34084 /** Used to detect octal string values. */
34086 var reIsOctal = /^0o[0-7]+$/i;
34087 /** Built-in method references without a dependency on `root`. */
34089 var freeParseInt = parseInt;
34091 * Converts `value` to a number.
34097 * @param {*} value The value to process.
34098 * @returns {number} Returns the number.
34104 * _.toNumber(Number.MIN_VALUE);
34107 * _.toNumber(Infinity);
34110 * _.toNumber('3.2');
34114 function toNumber(value) {
34115 if (typeof value == 'number') {
34119 if (isSymbol(value)) {
34123 if (isObject$2(value)) {
34124 var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
34125 value = isObject$2(other) ? other + '' : other;
34128 if (typeof value != 'string') {
34129 return value === 0 ? value : +value;
34132 value = baseTrim(value);
34133 var isBinary = reIsBinary.test(value);
34134 return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
34138 * Converts `value` to a string. An empty string is returned for `null`
34139 * and `undefined` values. The sign of `-0` is preserved.
34145 * @param {*} value The value to convert.
34146 * @returns {string} Returns the converted string.
34149 * _.toString(null);
34155 * _.toString([1, 2, 3]);
34159 function toString$3(value) {
34160 return value == null ? '' : baseToString(value);
34164 * The base implementation of `_.propertyOf` without support for deep paths.
34167 * @param {Object} object The object to query.
34168 * @returns {Function} Returns the new accessor function.
34170 function basePropertyOf(object) {
34171 return function (key) {
34172 return object == null ? undefined : object[key];
34177 * Gets the timestamp of the number of milliseconds that have elapsed since
34178 * the Unix epoch (1 January 1970 00:00:00 UTC).
34184 * @returns {number} Returns the timestamp.
34187 * _.defer(function(stamp) {
34188 * console.log(_.now() - stamp);
34190 * // => Logs the number of milliseconds it took for the deferred invocation.
34193 var now = function now() {
34194 return root.Date.now();
34197 /** Error message constants. */
34199 var FUNC_ERROR_TEXT$1 = 'Expected a function';
34200 /* Built-in method references for those with the same name as other `lodash` methods. */
34202 var nativeMax = Math.max,
34203 nativeMin = Math.min;
34205 * Creates a debounced function that delays invoking `func` until after `wait`
34206 * milliseconds have elapsed since the last time the debounced function was
34207 * invoked. The debounced function comes with a `cancel` method to cancel
34208 * delayed `func` invocations and a `flush` method to immediately invoke them.
34209 * Provide `options` to indicate whether `func` should be invoked on the
34210 * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
34211 * with the last arguments provided to the debounced function. Subsequent
34212 * calls to the debounced function return the result of the last `func`
34215 * **Note:** If `leading` and `trailing` options are `true`, `func` is
34216 * invoked on the trailing edge of the timeout only if the debounced function
34217 * is invoked more than once during the `wait` timeout.
34219 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
34220 * until to the next tick, similar to `setTimeout` with a timeout of `0`.
34222 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
34223 * for details over the differences between `_.debounce` and `_.throttle`.
34228 * @category Function
34229 * @param {Function} func The function to debounce.
34230 * @param {number} [wait=0] The number of milliseconds to delay.
34231 * @param {Object} [options={}] The options object.
34232 * @param {boolean} [options.leading=false]
34233 * Specify invoking on the leading edge of the timeout.
34234 * @param {number} [options.maxWait]
34235 * The maximum time `func` is allowed to be delayed before it's invoked.
34236 * @param {boolean} [options.trailing=true]
34237 * Specify invoking on the trailing edge of the timeout.
34238 * @returns {Function} Returns the new debounced function.
34241 * // Avoid costly calculations while the window size is in flux.
34242 * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
34244 * // Invoke `sendMail` when clicked, debouncing subsequent calls.
34245 * jQuery(element).on('click', _.debounce(sendMail, 300, {
34247 * 'trailing': false
34250 * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
34251 * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
34252 * var source = new EventSource('/stream');
34253 * jQuery(source).on('message', debounced);
34255 * // Cancel the trailing debounced invocation.
34256 * jQuery(window).on('popstate', debounced.cancel);
34259 function debounce(func, wait, options) {
34266 lastInvokeTime = 0,
34271 if (typeof func != 'function') {
34272 throw new TypeError(FUNC_ERROR_TEXT$1);
34275 wait = toNumber(wait) || 0;
34277 if (isObject$2(options)) {
34278 leading = !!options.leading;
34279 maxing = 'maxWait' in options;
34280 maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
34281 trailing = 'trailing' in options ? !!options.trailing : trailing;
34284 function invokeFunc(time) {
34285 var args = lastArgs,
34286 thisArg = lastThis;
34287 lastArgs = lastThis = undefined;
34288 lastInvokeTime = time;
34289 result = func.apply(thisArg, args);
34293 function leadingEdge(time) {
34294 // Reset any `maxWait` timer.
34295 lastInvokeTime = time; // Start the timer for the trailing edge.
34297 timerId = setTimeout(timerExpired, wait); // Invoke the leading edge.
34299 return leading ? invokeFunc(time) : result;
34302 function remainingWait(time) {
34303 var timeSinceLastCall = time - lastCallTime,
34304 timeSinceLastInvoke = time - lastInvokeTime,
34305 timeWaiting = wait - timeSinceLastCall;
34306 return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
34309 function shouldInvoke(time) {
34310 var timeSinceLastCall = time - lastCallTime,
34311 timeSinceLastInvoke = time - lastInvokeTime; // Either this is the first call, activity has stopped and we're at the
34312 // trailing edge, the system time has gone backwards and we're treating
34313 // it as the trailing edge, or we've hit the `maxWait` limit.
34315 return lastCallTime === undefined || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
34318 function timerExpired() {
34321 if (shouldInvoke(time)) {
34322 return trailingEdge(time);
34323 } // Restart the timer.
34326 timerId = setTimeout(timerExpired, remainingWait(time));
34329 function trailingEdge(time) {
34330 timerId = undefined; // Only invoke if we have `lastArgs` which means `func` has been
34331 // debounced at least once.
34333 if (trailing && lastArgs) {
34334 return invokeFunc(time);
34337 lastArgs = lastThis = undefined;
34341 function cancel() {
34342 if (timerId !== undefined) {
34343 clearTimeout(timerId);
34346 lastInvokeTime = 0;
34347 lastArgs = lastCallTime = lastThis = timerId = undefined;
34351 return timerId === undefined ? result : trailingEdge(now());
34354 function debounced() {
34356 isInvoking = shouldInvoke(time);
34357 lastArgs = arguments;
34359 lastCallTime = time;
34362 if (timerId === undefined) {
34363 return leadingEdge(lastCallTime);
34367 // Handle invocations in a tight loop.
34368 clearTimeout(timerId);
34369 timerId = setTimeout(timerExpired, wait);
34370 return invokeFunc(lastCallTime);
34374 if (timerId === undefined) {
34375 timerId = setTimeout(timerExpired, wait);
34381 debounced.cancel = cancel;
34382 debounced.flush = flush;
34386 /** Used to map characters to HTML entities. */
34388 var htmlEscapes = {
34396 * Used by `_.escape` to convert characters to HTML entities.
34399 * @param {string} chr The matched character to escape.
34400 * @returns {string} Returns the escaped character.
34403 var escapeHtmlChar = basePropertyOf(htmlEscapes);
34405 /** Used to match HTML entities and HTML characters. */
34407 var reUnescapedHtml = /[&<>"']/g,
34408 reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
34410 * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
34411 * corresponding HTML entities.
34413 * **Note:** No other characters are escaped. To escape additional
34414 * characters use a third-party library like [_he_](https://mths.be/he).
34416 * Though the ">" character is escaped for symmetry, characters like
34417 * ">" and "/" don't need escaping in HTML and have no special meaning
34418 * unless they're part of a tag or unquoted attribute value. See
34419 * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
34420 * (under "semi-related fun fact") for more details.
34422 * When working with HTML you should always
34423 * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
34430 * @param {string} [string=''] The string to escape.
34431 * @returns {string} Returns the escaped string.
34434 * _.escape('fred, barney, & pebbles');
34435 * // => 'fred, barney, & pebbles'
34438 function escape$4(string) {
34439 string = toString$3(string);
34440 return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string;
34443 /** Error message constants. */
34445 var FUNC_ERROR_TEXT = 'Expected a function';
34447 * Creates a throttled function that only invokes `func` at most once per
34448 * every `wait` milliseconds. The throttled function comes with a `cancel`
34449 * method to cancel delayed `func` invocations and a `flush` method to
34450 * immediately invoke them. Provide `options` to indicate whether `func`
34451 * should be invoked on the leading and/or trailing edge of the `wait`
34452 * timeout. The `func` is invoked with the last arguments provided to the
34453 * throttled function. Subsequent calls to the throttled function return the
34454 * result of the last `func` invocation.
34456 * **Note:** If `leading` and `trailing` options are `true`, `func` is
34457 * invoked on the trailing edge of the timeout only if the throttled function
34458 * is invoked more than once during the `wait` timeout.
34460 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
34461 * until to the next tick, similar to `setTimeout` with a timeout of `0`.
34463 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
34464 * for details over the differences between `_.throttle` and `_.debounce`.
34469 * @category Function
34470 * @param {Function} func The function to throttle.
34471 * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
34472 * @param {Object} [options={}] The options object.
34473 * @param {boolean} [options.leading=true]
34474 * Specify invoking on the leading edge of the timeout.
34475 * @param {boolean} [options.trailing=true]
34476 * Specify invoking on the trailing edge of the timeout.
34477 * @returns {Function} Returns the new throttled function.
34480 * // Avoid excessively updating the position while scrolling.
34481 * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
34483 * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
34484 * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
34485 * jQuery(element).on('click', throttled);
34487 * // Cancel the trailing throttled invocation.
34488 * jQuery(window).on('popstate', throttled.cancel);
34491 function throttle(func, wait, options) {
34492 var leading = true,
34495 if (typeof func != 'function') {
34496 throw new TypeError(FUNC_ERROR_TEXT);
34499 if (isObject$2(options)) {
34500 leading = 'leading' in options ? !!options.leading : leading;
34501 trailing = 'trailing' in options ? !!options.trailing : trailing;
34504 return debounce(func, wait, {
34505 'leading': leading,
34507 'trailing': trailing
34512 var lastIndexOf = arrayLastIndexOf;
34514 // `Array.prototype.lastIndexOf` method
34515 // https://tc39.es/ecma262/#sec-array.prototype.lastindexof
34516 // eslint-disable-next-line es/no-array-prototype-lastindexof -- required for testing
34517 $$f({ target: 'Array', proto: true, forced: lastIndexOf !== [].lastIndexOf }, {
34518 lastIndexOf: lastIndexOf
34521 /** Used to map HTML entities to characters. */
34523 var htmlUnescapes = {
34531 * Used by `_.unescape` to convert HTML entities to characters.
34534 * @param {string} chr The matched character to unescape.
34535 * @returns {string} Returns the unescaped character.
34538 var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
34540 /** Used to match HTML entities and HTML characters. */
34542 var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
34543 reHasEscapedHtml = RegExp(reEscapedHtml.source);
34545 * The inverse of `_.escape`; this method converts the HTML entities
34546 * `&`, `<`, `>`, `"`, and `'` in `string` to
34547 * their corresponding characters.
34549 * **Note:** No other HTML entities are unescaped. To unescape additional
34550 * HTML entities use a third-party library like [_he_](https://mths.be/he).
34556 * @param {string} [string=''] The string to unescape.
34557 * @returns {string} Returns the unescaped string.
34560 * _.unescape('fred, barney, & pebbles');
34561 * // => 'fred, barney, & pebbles'
34564 function unescape$3(string) {
34565 string = toString$3(string);
34566 return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string;
34569 var global$4 = global$1o;
34570 var isArray = isArray$8;
34571 var lengthOfArrayLike$1 = lengthOfArrayLike$i;
34572 var bind$3 = functionBindContext;
34574 var TypeError$2 = global$4.TypeError;
34576 // `FlattenIntoArray` abstract operation
34577 // https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
34578 var flattenIntoArray$1 = function (target, original, source, sourceLen, start, depth, mapper, thisArg) {
34579 var targetIndex = start;
34580 var sourceIndex = 0;
34581 var mapFn = mapper ? bind$3(mapper, thisArg) : false;
34582 var element, elementLen;
34584 while (sourceIndex < sourceLen) {
34585 if (sourceIndex in source) {
34586 element = mapFn ? mapFn(source[sourceIndex], sourceIndex, original) : source[sourceIndex];
34588 if (depth > 0 && isArray(element)) {
34589 elementLen = lengthOfArrayLike$1(element);
34590 targetIndex = flattenIntoArray$1(target, original, element, elementLen, targetIndex, depth - 1) - 1;
34592 if (targetIndex >= 0x1FFFFFFFFFFFFF) throw TypeError$2('Exceed the acceptable array length');
34593 target[targetIndex] = element;
34600 return targetIndex;
34603 var flattenIntoArray_1 = flattenIntoArray$1;
34606 var flattenIntoArray = flattenIntoArray_1;
34607 var aCallable = aCallable$a;
34608 var toObject = toObject$i;
34609 var lengthOfArrayLike = lengthOfArrayLike$i;
34610 var arraySpeciesCreate = arraySpeciesCreate$4;
34612 // `Array.prototype.flatMap` method
34613 // https://tc39.es/ecma262/#sec-array.prototype.flatmap
34614 $$e({ target: 'Array', proto: true }, {
34615 flatMap: function flatMap(callbackfn /* , thisArg */) {
34616 var O = toObject(this);
34617 var sourceLen = lengthOfArrayLike(O);
34619 aCallable(callbackfn);
34620 A = arraySpeciesCreate(O, 0);
34621 A.length = flattenIntoArray(A, O, O, sourceLen, 0, 1, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
34626 // this method was added to unscopables after implementation
34627 // in popular engines, so it's moved to a separate module
34628 var addToUnscopables = addToUnscopables$6;
34630 // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
34631 addToUnscopables('flatMap');
34634 var uncurryThis$6 = functionUncurryThis;
34635 var getOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f;
34636 var toLength$2 = toLength$c;
34637 var toString$2 = toString$k;
34638 var notARegExp$1 = notARegexp;
34639 var requireObjectCoercible$2 = requireObjectCoercible$e;
34640 var correctIsRegExpLogic$1 = correctIsRegexpLogic;
34642 // eslint-disable-next-line es/no-string-prototype-endswith -- safe
34643 var un$EndsWith = uncurryThis$6(''.endsWith);
34644 var slice$2 = uncurryThis$6(''.slice);
34645 var min$1 = Math.min;
34647 var CORRECT_IS_REGEXP_LOGIC$1 = correctIsRegExpLogic$1('endsWith');
34648 // https://github.com/zloirock/core-js/pull/702
34649 var MDN_POLYFILL_BUG$1 = !CORRECT_IS_REGEXP_LOGIC$1 && !!function () {
34650 var descriptor = getOwnPropertyDescriptor$1(String.prototype, 'endsWith');
34651 return descriptor && !descriptor.writable;
34654 // `String.prototype.endsWith` method
34655 // https://tc39.es/ecma262/#sec-string.prototype.endswith
34656 $$d({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG$1 && !CORRECT_IS_REGEXP_LOGIC$1 }, {
34657 endsWith: function endsWith(searchString /* , endPosition = @length */) {
34658 var that = toString$2(requireObjectCoercible$2(this));
34659 notARegExp$1(searchString);
34660 var endPosition = arguments.length > 1 ? arguments[1] : undefined;
34661 var len = that.length;
34662 var end = endPosition === undefined ? len : min$1(toLength$2(endPosition), len);
34663 var search = toString$2(searchString);
34665 ? un$EndsWith(that, search, end)
34666 : slice$2(that, end - search.length, end) === search;
34670 // https://github.com/tc39/proposal-string-pad-start-end
34671 var uncurryThis$5 = functionUncurryThis;
34672 var toLength$1 = toLength$c;
34673 var toString$1 = toString$k;
34674 var $repeat = stringRepeat;
34675 var requireObjectCoercible$1 = requireObjectCoercible$e;
34677 var repeat$1 = uncurryThis$5($repeat);
34678 var stringSlice$2 = uncurryThis$5(''.slice);
34679 var ceil = Math.ceil;
34681 // `String.prototype.{ padStart, padEnd }` methods implementation
34682 var createMethod = function (IS_END) {
34683 return function ($this, maxLength, fillString) {
34684 var S = toString$1(requireObjectCoercible$1($this));
34685 var intMaxLength = toLength$1(maxLength);
34686 var stringLength = S.length;
34687 var fillStr = fillString === undefined ? ' ' : toString$1(fillString);
34688 var fillLen, stringFiller;
34689 if (intMaxLength <= stringLength || fillStr == '') return S;
34690 fillLen = intMaxLength - stringLength;
34691 stringFiller = repeat$1(fillStr, ceil(fillLen / fillStr.length));
34692 if (stringFiller.length > fillLen) stringFiller = stringSlice$2(stringFiller, 0, fillLen);
34693 return IS_END ? S + stringFiller : stringFiller + S;
34698 // `String.prototype.padStart` method
34699 // https://tc39.es/ecma262/#sec-string.prototype.padstart
34700 start: createMethod(false),
34701 // `String.prototype.padEnd` method
34702 // https://tc39.es/ecma262/#sec-string.prototype.padend
34703 end: createMethod(true)
34706 // https://github.com/zloirock/core-js/issues/280
34707 var userAgent = engineUserAgent;
34709 var stringPadWebkitBug = /Version\/10(?:\.\d+){1,2}(?: [\w./]+)?(?: Mobile\/\w+)? Safari\//.test(userAgent);
34712 var $padEnd = stringPad.end;
34713 var WEBKIT_BUG$1 = stringPadWebkitBug;
34715 // `String.prototype.padEnd` method
34716 // https://tc39.es/ecma262/#sec-string.prototype.padend
34717 $$c({ target: 'String', proto: true, forced: WEBKIT_BUG$1 }, {
34718 padEnd: function padEnd(maxLength /* , fillString = ' ' */) {
34719 return $padEnd(this, maxLength, arguments.length > 1 ? arguments[1] : undefined);
34724 var $padStart = stringPad.start;
34725 var WEBKIT_BUG = stringPadWebkitBug;
34727 // `String.prototype.padStart` method
34728 // https://tc39.es/ecma262/#sec-string.prototype.padstart
34729 $$b({ target: 'String', proto: true, forced: WEBKIT_BUG }, {
34730 padStart: function padStart(maxLength /* , fillString = ' ' */) {
34731 return $padStart(this, maxLength, arguments.length > 1 ? arguments[1] : undefined);
34736 var $reduceRight = arrayReduce.right;
34737 var arrayMethodIsStrict = arrayMethodIsStrict$9;
34738 var CHROME_VERSION = engineV8Version;
34739 var IS_NODE = engineIsNode;
34741 var STRICT_METHOD = arrayMethodIsStrict('reduceRight');
34742 // Chrome 80-82 has a critical bug
34743 // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
34744 var CHROME_BUG = !IS_NODE && CHROME_VERSION > 79 && CHROME_VERSION < 83;
34746 // `Array.prototype.reduceRight` method
34747 // https://tc39.es/ecma262/#sec-array.prototype.reduceright
34748 $$a({ target: 'Array', proto: true, forced: !STRICT_METHOD || CHROME_BUG }, {
34749 reduceRight: function reduceRight(callbackfn /* , initialValue */) {
34750 return $reduceRight(this, callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined);
34755 var repeat = stringRepeat;
34757 // `String.prototype.repeat` method
34758 // https://tc39.es/ecma262/#sec-string.prototype.repeat
34759 $$9({ target: 'String', proto: true }, {
34764 var uncurryThis$4 = functionUncurryThis;
34765 var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
34766 var toLength = toLength$c;
34767 var toString = toString$k;
34768 var notARegExp = notARegexp;
34769 var requireObjectCoercible = requireObjectCoercible$e;
34770 var correctIsRegExpLogic = correctIsRegexpLogic;
34772 // eslint-disable-next-line es/no-string-prototype-startswith -- safe
34773 var un$StartsWith = uncurryThis$4(''.startsWith);
34774 var stringSlice$1 = uncurryThis$4(''.slice);
34775 var min = Math.min;
34777 var CORRECT_IS_REGEXP_LOGIC = correctIsRegExpLogic('startsWith');
34778 // https://github.com/zloirock/core-js/pull/702
34779 var MDN_POLYFILL_BUG = !CORRECT_IS_REGEXP_LOGIC && !!function () {
34780 var descriptor = getOwnPropertyDescriptor(String.prototype, 'startsWith');
34781 return descriptor && !descriptor.writable;
34784 // `String.prototype.startsWith` method
34785 // https://tc39.es/ecma262/#sec-string.prototype.startswith
34786 $$8({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG && !CORRECT_IS_REGEXP_LOGIC }, {
34787 startsWith: function startsWith(searchString /* , position = 0 */) {
34788 var that = toString(requireObjectCoercible(this));
34789 notARegExp(searchString);
34790 var index = toLength(min(arguments.length > 1 ? arguments[1] : undefined, that.length));
34791 var search = toString(searchString);
34792 return un$StartsWith
34793 ? un$StartsWith(that, search, index)
34794 : stringSlice$1(that, index, index + search.length) === search;
34799 var $trimEnd = stringTrim.end;
34800 var forcedStringTrimMethod$1 = stringTrimForced;
34802 var FORCED$4 = forcedStringTrimMethod$1('trimEnd');
34804 var trimEnd = FORCED$4 ? function trimEnd() {
34805 return $trimEnd(this);
34806 // eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe
34809 // `String.prototype.{ trimEnd, trimRight }` methods
34810 // https://tc39.es/ecma262/#sec-string.prototype.trimend
34811 // https://tc39.es/ecma262/#String.prototype.trimright
34812 $$7({ target: 'String', proto: true, name: 'trimEnd', forced: FORCED$4 }, {
34818 var $trimStart = stringTrim.start;
34819 var forcedStringTrimMethod = stringTrimForced;
34821 var FORCED$3 = forcedStringTrimMethod('trimStart');
34823 var trimStart = FORCED$3 ? function trimStart() {
34824 return $trimStart(this);
34825 // eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe
34828 // `String.prototype.{ trimStart, trimLeft }` methods
34829 // https://tc39.es/ecma262/#sec-string.prototype.trimstart
34830 // https://tc39.es/ecma262/#String.prototype.trimleft
34831 $$6({ target: 'String', proto: true, name: 'trimStart', forced: FORCED$3 }, {
34832 trimStart: trimStart,
34833 trimLeft: trimStart
34836 var _mainLocalizer = coreLocalizer(); // singleton
34839 var _t = _mainLocalizer.t;
34840 // coreLocalizer manages language and locale parameters including translated strings
34843 function coreLocalizer() {
34844 var localizer = {};
34845 var _dataLanguages = {}; // `_dataLocales` is an object containing all _supported_ locale codes -> language info.
34846 // * `rtl` - right-to-left or left-to-right text direction
34847 // * `pct` - the percent of strings translated; 1 = 100%, full coverage
34850 // en: { rtl: false, pct: {…} },
34851 // de: { rtl: false, pct: {…} },
34855 var _dataLocales = {}; // `localeStrings` is an object containing all _loaded_ locale codes -> string data.
34857 // en: { icons: {…}, toolbar: {…}, modes: {…}, operations: {…}, … },
34858 // de: { icons: {…}, toolbar: {…}, modes: {…}, operations: {…}, … },
34862 var _localeStrings = {}; // the current locale
34864 var _localeCode = 'en-US'; // `_localeCodes` must contain `_localeCode` first, optionally followed by fallbacks
34866 var _localeCodes = ['en-US', 'en'];
34867 var _languageCode = 'en';
34868 var _textDirection = 'ltr';
34869 var _usesMetric = false;
34870 var _languageNames = {};
34871 var _scriptNames = {}; // getters for the current locale parameters
34873 localizer.localeCode = function () {
34874 return _localeCode;
34877 localizer.localeCodes = function () {
34878 return _localeCodes;
34881 localizer.languageCode = function () {
34882 return _languageCode;
34885 localizer.textDirection = function () {
34886 return _textDirection;
34889 localizer.usesMetric = function () {
34890 return _usesMetric;
34893 localizer.languageNames = function () {
34894 return _languageNames;
34897 localizer.scriptNames = function () {
34898 return _scriptNames;
34899 }; // The client app may want to manually set the locale, regardless of the
34900 // settings provided by the browser
34903 var _preferredLocaleCodes = [];
34905 localizer.preferredLocaleCodes = function (codes) {
34906 if (!arguments.length) return _preferredLocaleCodes;
34908 if (typeof codes === 'string') {
34909 // be generous and accept delimited strings as input
34910 _preferredLocaleCodes = codes.split(/,|;| /gi).filter(Boolean);
34912 _preferredLocaleCodes = codes;
34920 localizer.ensureLoaded = function () {
34921 if (_loadPromise) return _loadPromise;
34922 var filesToFetch = ['languages', // load the list of languages
34923 'locales' // load the list of supported locales
34926 general: 'locales',
34927 tagging: 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/translations'
34929 var fileMap = _mainFileFetcher.fileMap();
34931 for (var scopeId in localeDirs) {
34932 var key = "locales_index_".concat(scopeId);
34934 if (!fileMap[key]) {
34935 fileMap[key] = localeDirs[scopeId] + '/index.min.json';
34938 filesToFetch.push(key);
34941 return _loadPromise = Promise.all(filesToFetch.map(function (key) {
34942 return _mainFileFetcher.get(key);
34943 })).then(function (results) {
34944 _dataLanguages = results[0];
34945 _dataLocales = results[1];
34946 var indexes = results.slice(2);
34948 var requestedLocales = (_preferredLocaleCodes || []).concat(utilDetect().browserLocales) // List of locales preferred by the browser in priority order.
34949 .concat(['en']); // fallback to English since it's the only guaranteed complete language
34952 _localeCodes = localesToUseFrom(requestedLocales);
34953 _localeCode = _localeCodes[0]; // Run iD in the highest-priority locale; the rest are fallbacks
34955 var loadStringsPromises = [];
34956 indexes.forEach(function (index, i) {
34957 // Will always return the index for `en` if nothing else
34958 var fullCoverageIndex = _localeCodes.findIndex(function (locale) {
34959 return index[locale] && index[locale].pct === 1;
34960 }); // We only need to load locales up until we find one with full coverage
34963 _localeCodes.slice(0, fullCoverageIndex + 1).forEach(function (code) {
34964 var scopeId = Object.keys(localeDirs)[i];
34965 var directory = Object.values(localeDirs)[i];
34966 if (index[code]) loadStringsPromises.push(localizer.loadLocale(code, scopeId, directory));
34969 return Promise.all(loadStringsPromises);
34970 }).then(function () {
34971 updateForCurrentLocale();
34972 })["catch"](function (err) {
34973 return console.error(err);
34974 }); // eslint-disable-line
34975 }; // Returns the locales from `requestedLocales` supported by iD that we should use
34978 function localesToUseFrom(requestedLocales) {
34979 var supportedLocales = _dataLocales;
34982 for (var i in requestedLocales) {
34983 var locale = requestedLocales[i];
34984 if (supportedLocales[locale]) toUse.push(locale);
34986 if (locale.includes('-')) {
34987 // Full locale ('es-ES'), add fallback to the base ('es')
34988 var langPart = locale.split('-')[0];
34989 if (supportedLocales[langPart]) toUse.push(langPart);
34991 } // remove duplicates
34994 return utilArrayUniq(toUse);
34997 function updateForCurrentLocale() {
34998 if (!_localeCode) return;
34999 _languageCode = _localeCode.split('-')[0];
35000 var currentData = _dataLocales[_localeCode] || _dataLocales[_languageCode];
35001 var hash = utilStringQs(window.location.hash);
35003 if (hash.rtl === 'true') {
35004 _textDirection = 'rtl';
35005 } else if (hash.rtl === 'false') {
35006 _textDirection = 'ltr';
35008 _textDirection = currentData && currentData.rtl ? 'rtl' : 'ltr';
35011 var locale = _localeCode;
35012 if (locale.toLowerCase() === 'en-us') locale = 'en';
35013 _languageNames = _localeStrings.general[locale].languageNames;
35014 _scriptNames = _localeStrings.general[locale].scriptNames;
35015 _usesMetric = _localeCode.slice(-3).toLowerCase() !== '-us';
35018 // Returns a Promise to load the strings for the requested locale
35021 localizer.loadLocale = function (locale, scopeId, directory) {
35022 // US English is the default
35023 if (locale.toLowerCase() === 'en-us') locale = 'en';
35025 if (_localeStrings[scopeId] && _localeStrings[scopeId][locale]) {
35027 return Promise.resolve(locale);
35030 var fileMap = _mainFileFetcher.fileMap();
35031 var key = "locale_".concat(scopeId, "_").concat(locale);
35033 if (!fileMap[key]) {
35034 fileMap[key] = "".concat(directory, "/").concat(locale, ".min.json");
35037 return _mainFileFetcher.get(key).then(function (d) {
35038 if (!_localeStrings[scopeId]) _localeStrings[scopeId] = {};
35039 _localeStrings[scopeId][locale] = d[locale];
35044 localizer.pluralRule = function (number) {
35045 return pluralRule(number, _localeCode);
35046 }; // Returns the plural rule for the given `number` with the given `localeCode`.
35047 // One of: `zero`, `one`, `two`, `few`, `many`, `other`
35050 function pluralRule(number, localeCode) {
35051 // modern browsers have this functionality built-in
35052 var rules = 'Intl' in window && Intl.PluralRules && new Intl.PluralRules(localeCode);
35055 return rules.select(number);
35056 } // fallback to basic one/other, as in English
35059 if (number === 1) return 'one';
35063 * Try to find that string in `locale` or the current `_localeCode` matching
35064 * the given `stringId`. If no string can be found in the requested locale,
35065 * we'll recurse down all the `_localeCodes` until one is found.
35067 * @param {string} stringId string identifier
35068 * @param {object?} replacements token replacements and default string
35069 * @param {string?} locale locale to use (defaults to currentLocale)
35070 * @return {string?} localized string
35074 localizer.tInfo = function (origStringId, replacements, locale) {
35075 var stringId = origStringId.trim();
35076 var scopeId = 'general';
35078 if (stringId[0] === '_') {
35079 var split = stringId.split('.');
35080 scopeId = split[0].slice(1);
35081 stringId = split.slice(1).join('.');
35084 locale = locale || _localeCode;
35085 var path = stringId.split('.').map(function (s) {
35086 return s.replace(/<TX_DOT>/g, '.');
35088 var stringsKey = locale; // US English is the default
35090 if (stringsKey.toLowerCase() === 'en-us') stringsKey = 'en';
35091 var result = _localeStrings && _localeStrings[scopeId] && _localeStrings[scopeId][stringsKey];
35093 while (result !== undefined && path.length) {
35094 result = result[path.pop()];
35097 if (result !== undefined) {
35098 if (replacements) {
35099 if (_typeof(result) === 'object' && Object.keys(result).length) {
35100 // If plural forms are provided, dig one level deeper based on the
35101 // first numeric token replacement provided.
35102 var number = Object.values(replacements).find(function (value) {
35103 return typeof value === 'number';
35106 if (number !== undefined) {
35107 var rule = pluralRule(number, locale);
35109 if (result[rule]) {
35110 result = result[rule];
35112 // We're pretty sure this should be a plural but no string
35113 // could be found for the given rule. Just pick the first
35114 // string and hope it makes sense.
35115 result = Object.values(result)[0];
35120 if (typeof result === 'string') {
35121 for (var key in replacements) {
35122 var value = replacements[key];
35124 if (typeof value === 'number') {
35125 if (value.toLocaleString) {
35126 // format numbers for the locale
35127 value = value.toLocaleString(locale, {
35130 minimumFractionDigits: 0
35133 value = value.toString();
35137 var token = "{".concat(key, "}");
35138 var regex = new RegExp(token, 'g');
35139 result = result.replace(regex, value);
35144 if (typeof result === 'string') {
35145 // found a localized string!
35151 } // no localized string found...
35152 // attempt to fallback to a lower-priority language
35155 var index = _localeCodes.indexOf(locale);
35157 if (index >= 0 && index < _localeCodes.length - 1) {
35158 // eventually this will be 'en' or another locale with 100% coverage
35159 var fallback = _localeCodes[index + 1];
35160 return localizer.tInfo(origStringId, replacements, fallback);
35163 if (replacements && 'default' in replacements) {
35164 // Fallback to a default value if one is specified in `replacements`
35166 text: replacements["default"],
35171 var missing = "Missing ".concat(locale, " translation: ").concat(origStringId);
35172 if (typeof console !== 'undefined') console.error(missing); // eslint-disable-line
35180 localizer.hasTextForStringId = function (stringId) {
35181 return !!localizer.tInfo(stringId, {
35182 "default": 'nothing found'
35184 }; // Returns only the localized text, discarding the locale info
35187 localizer.t = function (stringId, replacements, locale) {
35188 return localizer.tInfo(stringId, replacements, locale).text;
35189 }; // Returns the localized text wrapped in an HTML element encoding the locale info
35192 * @deprecated This method is considered deprecated. Instead, use the direct DOM manipulating
35193 * method `t.append`.
35197 localizer.t.html = function (stringId, replacements, locale) {
35198 // replacement string might be html unsafe, so we need to escape it except if it is explicitly marked as html code
35199 replacements = Object.assign({}, replacements);
35201 for (var k in replacements) {
35202 if (typeof replacements[k] === 'string') {
35203 replacements[k] = escape$4(replacements[k]);
35206 if (_typeof(replacements[k]) === 'object' && typeof replacements[k].html === 'string') {
35207 replacements[k] = replacements[k].html;
35211 var info = localizer.tInfo(stringId, replacements, locale); // text may be empty or undefined if `replacements.default` is
35214 return "<span class=\"localized-text\" lang=\"".concat(info.locale || 'und', "\">").concat(info.text, "</span>");
35218 }; // Adds localized text wrapped as an HTML span element with locale info to the DOM
35221 localizer.t.append = function (stringId, replacements, locale) {
35222 return function (selection) {
35223 var info = localizer.tInfo(stringId, replacements, locale);
35224 return selection.append('span').attr('class', 'localized-text').attr('lang', info.locale || 'und').text((replacements && replacements.prefix || '') + info.text + (replacements && replacements.suffix || ''));
35228 localizer.languageName = function (code, options) {
35229 if (_languageNames[code]) {
35230 // name in locale language
35232 return _languageNames[code];
35233 } // sometimes we only want the local name
35236 if (options && options.localOnly) return null;
35237 var langInfo = _dataLanguages[code];
35240 if (langInfo.nativeName) {
35241 // name in native language
35242 // e.g. "Deutsch (de)"
35243 return localizer.t('translate.language_and_code', {
35244 language: langInfo.nativeName,
35247 } else if (langInfo.base && langInfo.script) {
35248 var base = langInfo.base; // the code of the language this is based on
35250 if (_languageNames[base]) {
35251 // base language name in locale language
35252 var scriptCode = langInfo.script;
35253 var script = _scriptNames[scriptCode] || scriptCode; // e.g. "Serbian (Cyrillic)"
35255 return localizer.t('translate.language_and_code', {
35256 language: _languageNames[base],
35259 } else if (_dataLanguages[base] && _dataLanguages[base].nativeName) {
35260 // e.g. "српски (sr-Cyrl)"
35261 return localizer.t('translate.language_and_code', {
35262 language: _dataLanguages[base].nativeName,
35269 return code; // if not found, use the code
35275 // `presetCollection` is a wrapper around an `Array` of presets `collection`,
35276 // and decorated with some extra methods for searching and matching geometry
35279 function presetCollection(collection) {
35280 var MAXRESULTS = 50;
35283 _this.collection = collection;
35285 _this.item = function (id) {
35286 if (_memo[id]) return _memo[id];
35288 var found = _this.collection.find(function (d) {
35289 return d.id === id;
35292 if (found) _memo[id] = found;
35296 _this.index = function (id) {
35297 return _this.collection.findIndex(function (d) {
35298 return d.id === id;
35302 _this.matchGeometry = function (geometry) {
35303 return presetCollection(_this.collection.filter(function (d) {
35304 return d.matchGeometry(geometry);
35308 _this.matchAllGeometry = function (geometries) {
35309 return presetCollection(_this.collection.filter(function (d) {
35310 return d && d.matchAllGeometry(geometries);
35314 _this.matchAnyGeometry = function (geometries) {
35315 return presetCollection(_this.collection.filter(function (d) {
35316 return geometries.some(function (geom) {
35317 return d.matchGeometry(geom);
35322 _this.fallback = function (geometry) {
35324 if (id === 'vertex') id = 'point';
35325 return _this.item(id);
35328 _this.search = function (value, geometry, loc) {
35329 if (!value) return _this; // don't remove diacritical characters since we're assuming the user is being intentional
35331 value = value.toLowerCase().trim(); // match at name beginning or just after a space (e.g. "office" -> match "Law Office")
35333 function leading(a) {
35334 var index = a.indexOf(value);
35335 return index === 0 || a[index - 1] === ' ';
35336 } // match at name beginning only
35339 function leadingStrict(a) {
35340 var index = a.indexOf(value);
35341 return index === 0;
35344 function sortPresets(nameProp) {
35345 return function sortNames(a, b) {
35346 var aCompare = a[nameProp]();
35347 var bCompare = b[nameProp](); // priority if search string matches preset name exactly - #4325
35349 if (value === aCompare) return -1;
35350 if (value === bCompare) return 1; // priority for higher matchScore
35352 var i = b.originalScore - a.originalScore;
35353 if (i !== 0) return i; // priority if search string appears earlier in preset name
35355 i = aCompare.indexOf(value) - bCompare.indexOf(value);
35356 if (i !== 0) return i; // priority for shorter preset names
35358 return aCompare.length - bCompare.length;
35362 var pool = _this.collection;
35364 if (Array.isArray(loc)) {
35365 var validLocations = _mainLocations.locationsAt(loc);
35366 pool = pool.filter(function (a) {
35367 return !a.locationSetID || validLocations[a.locationSetID];
35371 var searchable = pool.filter(function (a) {
35372 return a.searchable !== false && a.suggestion !== true;
35374 var suggestions = pool.filter(function (a) {
35375 return a.suggestion === true;
35376 }); // matches value to preset.name
35378 var leadingNames = searchable.filter(function (a) {
35379 return leading(a.searchName());
35380 }).sort(sortPresets('searchName')); // matches value to preset suggestion name
35382 var leadingSuggestions = suggestions.filter(function (a) {
35383 return leadingStrict(a.searchName());
35384 }).sort(sortPresets('searchName'));
35385 var leadingNamesStripped = searchable.filter(function (a) {
35386 return leading(a.searchNameStripped());
35387 }).sort(sortPresets('searchNameStripped'));
35388 var leadingSuggestionsStripped = suggestions.filter(function (a) {
35389 return leadingStrict(a.searchNameStripped());
35390 }).sort(sortPresets('searchNameStripped')); // matches value to preset.terms values
35392 var leadingTerms = searchable.filter(function (a) {
35393 return (a.terms() || []).some(leading);
35395 var leadingSuggestionTerms = suggestions.filter(function (a) {
35396 return (a.terms() || []).some(leading);
35397 }); // matches value to preset.tags values
35399 var leadingTagValues = searchable.filter(function (a) {
35400 return Object.values(a.tags || {}).filter(function (val) {
35401 return val !== '*';
35403 }); // finds close matches to value in preset.name
35405 var similarName = searchable.map(function (a) {
35408 dist: utilEditDistance(value, a.searchName())
35410 }).filter(function (a) {
35411 return a.dist + Math.min(value.length - a.preset.searchName().length, 0) < 3;
35412 }).sort(function (a, b) {
35413 return a.dist - b.dist;
35414 }).map(function (a) {
35416 }); // finds close matches to value to preset suggestion name
35418 var similarSuggestions = suggestions.map(function (a) {
35421 dist: utilEditDistance(value, a.searchName())
35423 }).filter(function (a) {
35424 return a.dist + Math.min(value.length - a.preset.searchName().length, 0) < 1;
35425 }).sort(function (a, b) {
35426 return a.dist - b.dist;
35427 }).map(function (a) {
35429 }); // finds close matches to value in preset.terms
35431 var similarTerms = searchable.filter(function (a) {
35432 return (a.terms() || []).some(function (b) {
35433 return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
35436 var results = leadingNames.concat(leadingSuggestions, leadingNamesStripped, leadingSuggestionsStripped, leadingTerms, leadingSuggestionTerms, leadingTagValues, similarName, similarSuggestions, similarTerms).slice(0, MAXRESULTS - 1);
35439 if (typeof geometry === 'string') {
35440 results.push(_this.fallback(geometry));
35442 geometry.forEach(function (geom) {
35443 return results.push(_this.fallback(geom));
35448 return presetCollection(utilArrayUniq(results));
35454 // `presetCategory` builds a `presetCollection` of member presets,
35455 // decorated with some extra methods for searching and matching geometry
35458 function presetCategory(categoryID, category, allPresets) {
35459 var _this = Object.assign({}, category); // shallow copy
35462 var _searchName; // cache
35465 var _searchNameStripped; // cache
35468 _this.id = categoryID;
35469 _this.members = presetCollection((category.members || []).map(function (presetID) {
35470 return allPresets[presetID];
35471 }).filter(Boolean));
35472 _this.geometry = _this.members.collection.reduce(function (acc, preset) {
35473 for (var i in preset.geometry) {
35474 var geometry = preset.geometry[i];
35476 if (acc.indexOf(geometry) === -1) {
35477 acc.push(geometry);
35484 _this.matchGeometry = function (geom) {
35485 return _this.geometry.indexOf(geom) >= 0;
35488 _this.matchAllGeometry = function (geometries) {
35489 return _this.members.collection.some(function (preset) {
35490 return preset.matchAllGeometry(geometries);
35494 _this.matchScore = function () {
35498 _this.name = function () {
35499 return _t("_tagging.presets.categories.".concat(categoryID, ".name"), {
35500 'default': categoryID
35504 _this.nameLabel = function () {
35505 return _t.html("_tagging.presets.categories.".concat(categoryID, ".name"), {
35506 'default': categoryID
35510 _this.terms = function () {
35514 _this.searchName = function () {
35515 if (!_searchName) {
35516 _searchName = (_this.suggestion ? _this.originalName : _this.name()).toLowerCase();
35519 return _searchName;
35522 _this.searchNameStripped = function () {
35523 if (!_searchNameStripped) {
35524 _searchNameStripped = _this.searchName(); // split combined diacritical characters into their parts
35526 if (_searchNameStripped.normalize) _searchNameStripped = _searchNameStripped.normalize('NFD'); // remove diacritics
35528 _searchNameStripped = _searchNameStripped.replace(/[\u0300-\u036f]/g, '');
35531 return _searchNameStripped;
35537 // `presetField` decorates a given `field` Object
35538 // with some extra methods for searching and matching geometry
35541 function presetField(fieldID, field) {
35542 var _this = Object.assign({}, field); // shallow copy
35545 _this.id = fieldID; // for use in classes, element ids, css selectors
35547 _this.safeid = utilSafeClassName(fieldID);
35549 _this.matchGeometry = function (geom) {
35550 return !_this.geometry || _this.geometry.indexOf(geom) !== -1;
35553 _this.matchAllGeometry = function (geometries) {
35554 return !_this.geometry || geometries.every(function (geom) {
35555 return _this.geometry.indexOf(geom) !== -1;
35559 _this.t = function (scope, options) {
35560 return _t("_tagging.presets.fields.".concat(fieldID, ".").concat(scope), options);
35563 _this.t.html = function (scope, options) {
35564 return _t.html("_tagging.presets.fields.".concat(fieldID, ".").concat(scope), options);
35567 _this.hasTextForStringId = function (scope) {
35568 return _mainLocalizer.hasTextForStringId("_tagging.presets.fields.".concat(fieldID, ".").concat(scope));
35571 _this.title = function () {
35572 return _this.overrideLabel || _this.t('label', {
35577 _this.label = function () {
35578 return _this.overrideLabel || _this.t.html('label', {
35583 var _placeholder = _this.placeholder;
35585 _this.placeholder = function () {
35586 return _this.t('placeholder', {
35587 'default': _placeholder
35591 _this.originalTerms = (_this.terms || []).join();
35593 _this.terms = function () {
35594 return _this.t('terms', {
35595 'default': _this.originalTerms
35596 }).toLowerCase().trim().split(/\s*,+\s*/);
35599 _this.increment = _this.type === 'number' ? _this.increment || 1 : undefined;
35603 // `presetPreset` decorates a given `preset` Object
35604 // with some extra methods for searching and matching geometry
35607 function presetPreset(presetID, preset, addable, allFields, allPresets) {
35608 allFields = allFields || {};
35609 allPresets = allPresets || {};
35611 var _this = Object.assign({}, preset); // shallow copy
35614 var _addable = addable || false;
35616 var _resolvedFields; // cache
35619 var _resolvedMoreFields; // cache
35622 var _searchName; // cache
35625 var _searchNameStripped; // cache
35628 _this.id = presetID;
35629 _this.safeid = utilSafeClassName(presetID); // for use in css classes, selectors, element ids
35631 _this.originalTerms = (_this.terms || []).join();
35632 _this.originalName = _this.name || '';
35633 _this.originalScore = _this.matchScore || 1;
35634 _this.originalReference = _this.reference || {};
35635 _this.originalFields = _this.fields || [];
35636 _this.originalMoreFields = _this.moreFields || [];
35638 _this.fields = function () {
35639 return _resolvedFields || (_resolvedFields = resolve('fields'));
35642 _this.moreFields = function () {
35643 return _resolvedMoreFields || (_resolvedMoreFields = resolve('moreFields'));
35646 _this.resetFields = function () {
35647 return _resolvedFields = _resolvedMoreFields = null;
35650 _this.tags = _this.tags || {};
35651 _this.addTags = _this.addTags || _this.tags;
35652 _this.removeTags = _this.removeTags || _this.addTags;
35653 _this.geometry = _this.geometry || [];
35655 _this.matchGeometry = function (geom) {
35656 return _this.geometry.indexOf(geom) >= 0;
35659 _this.matchAllGeometry = function (geoms) {
35660 return geoms.every(_this.matchGeometry);
35663 _this.matchScore = function (entityTags) {
35664 var tags = _this.tags;
35666 var score = 0; // match on tags
35668 for (var k in tags) {
35671 if (entityTags[k] === tags[k]) {
35672 score += _this.originalScore;
35673 } else if (tags[k] === '*' && k in entityTags) {
35674 score += _this.originalScore / 2;
35678 } // boost score for additional matches in addTags - #6802
35681 var addTags = _this.addTags;
35683 for (var _k in addTags) {
35684 if (!seen[_k] && entityTags[_k] === addTags[_k]) {
35685 score += _this.originalScore;
35692 _this.t = function (scope, options) {
35693 var textID = "_tagging.presets.presets.".concat(presetID, ".").concat(scope);
35694 return _t(textID, options);
35697 _this.t.html = function (scope, options) {
35698 var textID = "_tagging.presets.presets.".concat(presetID, ".").concat(scope);
35699 return _t.html(textID, options);
35702 _this.name = function () {
35703 return _this.t('name', {
35704 'default': _this.originalName
35708 _this.nameLabel = function () {
35709 return _this.t.html('name', {
35710 'default': _this.originalName
35714 _this.subtitle = function () {
35715 if (_this.suggestion) {
35716 var path = presetID.split('/');
35717 path.pop(); // remove brand name
35719 return _t('_tagging.presets.presets.' + path.join('/') + '.name');
35725 _this.subtitleLabel = function () {
35726 if (_this.suggestion) {
35727 var path = presetID.split('/');
35728 path.pop(); // remove brand name
35730 return _t.html('_tagging.presets.presets.' + path.join('/') + '.name');
35736 _this.terms = function () {
35737 return _this.t('terms', {
35738 'default': _this.originalTerms
35739 }).toLowerCase().trim().split(/\s*,+\s*/);
35742 _this.searchName = function () {
35743 if (!_searchName) {
35744 _searchName = (_this.suggestion ? _this.originalName : _this.name()).toLowerCase();
35747 return _searchName;
35750 _this.searchNameStripped = function () {
35751 if (!_searchNameStripped) {
35752 _searchNameStripped = _this.searchName(); // split combined diacritical characters into their parts
35754 if (_searchNameStripped.normalize) _searchNameStripped = _searchNameStripped.normalize('NFD'); // remove diacritics
35756 _searchNameStripped = _searchNameStripped.replace(/[\u0300-\u036f]/g, '');
35759 return _searchNameStripped;
35762 _this.isFallback = function () {
35763 var tagCount = Object.keys(_this.tags).length;
35764 return tagCount === 0 || tagCount === 1 && _this.tags.hasOwnProperty('area');
35767 _this.addable = function (val) {
35768 if (!arguments.length) return _addable;
35773 _this.reference = function () {
35774 // Lookup documentation on Wikidata...
35775 var qid = _this.tags.wikidata || _this.tags['flag:wikidata'] || _this.tags['brand:wikidata'] || _this.tags['network:wikidata'] || _this.tags['operator:wikidata'];
35781 } // Lookup documentation on OSM Wikibase...
35784 var key = _this.originalReference.key || Object.keys(utilObjectOmit(_this.tags, 'name'))[0];
35785 var value = _this.originalReference.value || _this.tags[key];
35787 if (value === '*') {
35799 _this.unsetTags = function (tags, geometry, ignoringKeys, skipFieldDefaults) {
35800 // allow manually keeping some tags
35801 var removeTags = ignoringKeys ? utilObjectOmit(_this.removeTags, ignoringKeys) : _this.removeTags;
35802 tags = utilObjectOmit(tags, Object.keys(removeTags));
35804 if (geometry && !skipFieldDefaults) {
35805 _this.fields().forEach(function (field) {
35806 if (field.matchGeometry(geometry) && field.key && field["default"] === tags[field.key]) {
35807 delete tags[field.key];
35816 _this.setTags = function (tags, geometry, skipFieldDefaults) {
35817 var addTags = _this.addTags;
35818 tags = Object.assign({}, tags); // shallow copy
35820 for (var k in addTags) {
35821 if (addTags[k] === '*') {
35822 // if this tag is ancillary, don't override an existing value since any value is okay
35823 if (_this.tags[k] || !tags[k] || tags[k] === 'no') {
35827 tags[k] = addTags[k];
35829 } // Add area=yes if necessary.
35830 // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
35831 // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
35832 // 2. chosen preset doesn't have a key in osmAreaKeys (`railway=station`)
35835 if (!addTags.hasOwnProperty('area')) {
35838 if (geometry === 'area') {
35839 var needsAreaTag = true;
35841 if (_this.geometry.indexOf('line') === -1) {
35842 for (var _k2 in addTags) {
35843 if (_k2 in osmAreaKeys) {
35844 needsAreaTag = false;
35850 if (needsAreaTag) {
35856 if (geometry && !skipFieldDefaults) {
35857 _this.fields().forEach(function (field) {
35858 if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field["default"]) {
35859 tags[field.key] = field["default"];
35865 }; // For a preset without fields, use the fields of the parent preset.
35866 // Replace {preset} placeholders with the fields of the specified presets.
35869 function resolve(which) {
35870 var fieldIDs = which === 'fields' ? _this.originalFields : _this.originalMoreFields;
35872 fieldIDs.forEach(function (fieldID) {
35873 var match = fieldID.match(/\{(.*)\}/);
35875 if (match !== null) {
35876 // a presetID wrapped in braces {}
35877 resolved = resolved.concat(inheritFields(match[1], which));
35878 } else if (allFields[fieldID]) {
35879 // a normal fieldID
35880 resolved.push(allFields[fieldID]);
35882 console.log("Cannot resolve \"".concat(fieldID, "\" found in ").concat(_this.id, ".").concat(which)); // eslint-disable-line no-console
35884 }); // no fields resolved, so use the parent's if possible
35886 if (!resolved.length) {
35887 var endIndex = _this.id.lastIndexOf('/');
35889 var parentID = endIndex && _this.id.substring(0, endIndex);
35892 resolved = inheritFields(parentID, which);
35896 return utilArrayUniq(resolved); // returns an array of fields to inherit from the given presetID, if found
35898 function inheritFields(presetID, which) {
35899 var parent = allPresets[presetID];
35900 if (!parent) return [];
35902 if (which === 'fields') {
35903 return parent.fields().filter(shouldInherit);
35904 } else if (which === 'moreFields') {
35905 return parent.moreFields();
35909 } // Skip `fields` for the keys which define the preset.
35910 // These are usually `typeCombo` fields like `shop=*`
35913 function shouldInherit(f) {
35914 if (f.key && _this.tags[f.key] !== undefined && // inherit anyway if multiple values are allowed or just a checkbox
35915 f.type !== 'multiCombo' && f.type !== 'semiCombo' && f.type !== 'manyCombo' && f.type !== 'check') return false;
35923 var _mainPresetIndex = presetIndex(); // singleton
35924 // `presetIndex` wraps a `presetCollection`
35925 // with methods for loading new data and returning defaults
35928 function presetIndex() {
35929 var dispatch = dispatch$8('favoritePreset', 'recentsChange');
35930 var MAXRECENTS = 30; // seed the preset lists with geometry fallbacks
35932 var POINT = presetPreset('point', {
35935 geometry: ['point', 'vertex'],
35938 var LINE = presetPreset('line', {
35941 geometry: ['line'],
35944 var AREA = presetPreset('area', {
35949 geometry: ['area'],
35952 var RELATION = presetPreset('relation', {
35955 geometry: ['relation'],
35959 var _this = presetCollection([POINT, LINE, AREA, RELATION]);
35968 point: presetCollection([POINT]),
35969 vertex: presetCollection([POINT]),
35970 line: presetCollection([LINE]),
35971 area: presetCollection([AREA]),
35972 relation: presetCollection([RELATION])
35975 var _categories = {};
35976 var _universal = [];
35977 var _addablePresetIDs = null; // Set of preset IDs that the user can add
35981 var _favorites; // Index of presets by (geometry, tag key).
35984 var _geometryIndex = {
35994 _this.ensureLoaded = function () {
35995 if (_loadPromise) return _loadPromise;
35996 return _loadPromise = Promise.all([_mainFileFetcher.get('preset_categories'), _mainFileFetcher.get('preset_defaults'), _mainFileFetcher.get('preset_presets'), _mainFileFetcher.get('preset_fields')]).then(function (vals) {
35998 categories: vals[0],
36004 osmSetAreaKeys(_this.areaKeys());
36005 osmSetPointTags(_this.pointTags());
36006 osmSetVertexTags(_this.vertexTags());
36008 }; // `merge` accepts an object containing new preset data (all properties optional):
36014 // featureCollection: {}
36018 _this.merge = function (d) {
36019 var newLocationSets = []; // Merge Fields
36022 Object.keys(d.fields).forEach(function (fieldID) {
36023 var f = d.fields[fieldID];
36027 f = presetField(fieldID, f);
36028 if (f.locationSet) newLocationSets.push(f);
36029 _fields[fieldID] = f;
36032 delete _fields[fieldID];
36039 Object.keys(d.presets).forEach(function (presetID) {
36040 var p = d.presets[presetID];
36044 var isAddable = !_addablePresetIDs || _addablePresetIDs.has(presetID);
36046 p = presetPreset(presetID, p, isAddable, _fields, _presets);
36047 if (p.locationSet) newLocationSets.push(p);
36048 _presets[presetID] = p;
36050 // remove (but not if it's a fallback)
36051 var existing = _presets[presetID];
36053 if (existing && !existing.isFallback()) {
36054 delete _presets[presetID];
36058 } // Merge Categories
36061 if (d.categories) {
36062 Object.keys(d.categories).forEach(function (categoryID) {
36063 var c = d.categories[categoryID];
36067 c = presetCategory(categoryID, c, _presets);
36068 if (c.locationSet) newLocationSets.push(c);
36069 _categories[categoryID] = c;
36072 delete _categories[categoryID];
36075 } // Rebuild _this.collection after changing presets and categories
36078 _this.collection = Object.values(_presets).concat(Object.values(_categories)); // Merge Defaults
36081 Object.keys(d.defaults).forEach(function (geometry) {
36082 var def = d.defaults[geometry];
36084 if (Array.isArray(def)) {
36086 _defaults[geometry] = presetCollection(def.map(function (id) {
36087 return _presets[id] || _categories[id];
36088 }).filter(Boolean));
36091 delete _defaults[geometry];
36094 } // Rebuild universal fields array
36097 _universal = Object.values(_fields).filter(function (field) {
36098 return field.universal;
36099 }); // Reset all the preset fields - they'll need to be resolved again
36101 Object.values(_presets).forEach(function (preset) {
36102 return preset.resetFields();
36103 }); // Rebuild geometry index
36113 _this.collection.forEach(function (preset) {
36114 (preset.geometry || []).forEach(function (geometry) {
36115 var g = _geometryIndex[geometry];
36117 for (var key in preset.tags) {
36118 g[key] = g[key] || {};
36119 var value = preset.tags[key];
36120 (g[key][value] = g[key][value] || []).push(preset);
36123 }); // Merge Custom Features
36126 if (d.featureCollection && Array.isArray(d.featureCollection.features)) {
36127 _mainLocations.mergeCustomGeoJSON(d.featureCollection);
36128 } // Resolve all locationSet features.
36131 if (newLocationSets.length) {
36132 _mainLocations.mergeLocationSets(newLocationSets);
36138 _this.match = function (entity, resolver) {
36139 return resolver["transient"](entity, 'presetMatch', function () {
36140 var geometry = entity.geometry(resolver); // Treat entities on addr:interpolation lines as points, not vertices - #3241
36142 if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
36143 geometry = 'point';
36146 var entityExtent = entity.extent(resolver);
36147 return _this.matchTags(entity.tags, geometry, entityExtent.center());
36151 _this.matchTags = function (tags, geometry, loc) {
36152 var keyIndex = _geometryIndex[geometry];
36153 var bestScore = -1;
36155 var matchCandidates = [];
36157 for (var k in tags) {
36158 var indexMatches = [];
36159 var valueIndex = keyIndex[k];
36160 if (!valueIndex) continue;
36161 var keyValueMatches = valueIndex[tags[k]];
36162 if (keyValueMatches) indexMatches.push.apply(indexMatches, _toConsumableArray(keyValueMatches));
36163 var keyStarMatches = valueIndex['*'];
36164 if (keyStarMatches) indexMatches.push.apply(indexMatches, _toConsumableArray(keyStarMatches));
36165 if (indexMatches.length === 0) continue;
36167 for (var i = 0; i < indexMatches.length; i++) {
36168 var candidate = indexMatches[i];
36169 var score = candidate.matchScore(tags);
36171 if (score === -1) {
36175 matchCandidates.push({
36177 candidate: candidate
36180 if (score > bestScore) {
36182 bestMatch = candidate;
36187 if (bestMatch && bestMatch.locationSetID && bestMatch.locationSetID !== '+[Q2]' && Array.isArray(loc)) {
36188 var validLocations = _mainLocations.locationsAt(loc);
36190 if (!validLocations[bestMatch.locationSetID]) {
36191 matchCandidates.sort(function (a, b) {
36192 return a.score < b.score ? 1 : -1;
36195 for (var _i = 0; _i < matchCandidates.length; _i++) {
36196 var candidateScore = matchCandidates[_i];
36198 if (!candidateScore.candidate.locationSetID || validLocations[candidateScore.candidate.locationSetID]) {
36199 bestMatch = candidateScore.candidate;
36200 bestScore = candidateScore.score;
36205 } // If any part of an address is present, allow fallback to "Address" preset - #4353
36208 if (!bestMatch || bestMatch.isFallback()) {
36209 for (var _k in tags) {
36210 if (/^addr:/.test(_k) && keyIndex['addr:*'] && keyIndex['addr:*']['*']) {
36211 bestMatch = keyIndex['addr:*']['*'][0];
36217 return bestMatch || _this.fallback(geometry);
36220 _this.allowsVertex = function (entity, resolver) {
36221 if (entity.type !== 'node') return false;
36222 if (Object.keys(entity.tags).length === 0) return true;
36223 return resolver["transient"](entity, 'vertexMatch', function () {
36224 // address lines allow vertices to act as standalone points
36225 if (entity.isOnAddressLine(resolver)) return true;
36226 var geometries = osmNodeGeometriesForTags(entity.tags);
36227 if (geometries.vertex) return true;
36228 if (geometries.point) return false; // allow vertices for unspecified points
36232 }; // Because of the open nature of tagging, iD will never have a complete
36233 // list of tags used in OSM, so we want it to have logic like "assume
36234 // that a closed way with an amenity tag is an area, unless the amenity
36235 // is one of these specific types". This function computes a structure
36236 // that allows testing of such conditions, based on the presets designated
36237 // as as supporting (or not supporting) the area geometry.
36239 // The returned object L is a keeplist/discardlist of tags. A closed way
36240 // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
36241 // (see `Way#isArea()`). In other words, the keys of L form the keeplist,
36242 // and the subkeys form the discardlist.
36245 _this.areaKeys = function () {
36246 // The ignore list is for keys that imply lines. (We always add `area=yes` for exceptions)
36247 var ignore = ['barrier', 'highway', 'footway', 'railway', 'junction', 'type'];
36248 var areaKeys = {}; // ignore name-suggestion-index and deprecated presets
36250 var presets = _this.collection.filter(function (p) {
36251 return !p.suggestion && !p.replacement;
36255 presets.forEach(function (p) {
36256 var keys = p.tags && Object.keys(p.tags);
36257 var key = keys && keys.length && keys[0]; // pick the first tag
36260 if (ignore.indexOf(key) !== -1) return;
36262 if (p.geometry.indexOf('area') !== -1) {
36263 // probably an area..
36264 areaKeys[key] = areaKeys[key] || {};
36268 presets.forEach(function (p) {
36271 for (key in p.addTags) {
36272 // examine all addTags to get a better sense of what can be tagged on lines - #6800
36273 var value = p.addTags[key];
36275 if (key in areaKeys && // probably an area...
36276 p.geometry.indexOf('line') !== -1 && // but sometimes a line
36278 areaKeys[key][value] = true;
36285 _this.pointTags = function () {
36286 return _this.collection.reduce(function (pointTags, d) {
36287 // ignore name-suggestion-index, deprecated, and generic presets
36288 if (d.suggestion || d.replacement || d.searchable === false) return pointTags; // only care about the primary tag
36290 var keys = d.tags && Object.keys(d.tags);
36291 var key = keys && keys.length && keys[0]; // pick the first tag
36293 if (!key) return pointTags; // if this can be a point
36295 if (d.geometry.indexOf('point') !== -1) {
36296 pointTags[key] = pointTags[key] || {};
36297 pointTags[key][d.tags[key]] = true;
36304 _this.vertexTags = function () {
36305 return _this.collection.reduce(function (vertexTags, d) {
36306 // ignore name-suggestion-index, deprecated, and generic presets
36307 if (d.suggestion || d.replacement || d.searchable === false) return vertexTags; // only care about the primary tag
36309 var keys = d.tags && Object.keys(d.tags);
36310 var key = keys && keys.length && keys[0]; // pick the first tag
36312 if (!key) return vertexTags; // if this can be a vertex
36314 if (d.geometry.indexOf('vertex') !== -1) {
36315 vertexTags[key] = vertexTags[key] || {};
36316 vertexTags[key][d.tags[key]] = true;
36323 _this.field = function (id) {
36324 return _fields[id];
36327 _this.universal = function () {
36331 _this.defaults = function (geometry, n, startWithRecents, loc) {
36334 if (startWithRecents) {
36335 recents = _this.recent().matchGeometry(geometry).collection.slice(0, 4);
36340 if (_addablePresetIDs) {
36341 defaults = Array.from(_addablePresetIDs).map(function (id) {
36342 var preset = _this.item(id);
36344 if (preset && preset.matchGeometry(geometry)) return preset;
36346 }).filter(Boolean);
36348 defaults = _defaults[geometry].collection.concat(_this.fallback(geometry));
36351 var result = presetCollection(utilArrayUniq(recents.concat(defaults)).slice(0, n - 1));
36353 if (Array.isArray(loc)) {
36354 var validLocations = _mainLocations.locationsAt(loc);
36355 result.collection = result.collection.filter(function (a) {
36356 return !a.locationSetID || validLocations[a.locationSetID];
36361 }; // pass a Set of addable preset ids
36364 _this.addablePresetIDs = function (val) {
36365 if (!arguments.length) return _addablePresetIDs; // accept and convert arrays
36367 if (Array.isArray(val)) val = new Set(val);
36368 _addablePresetIDs = val;
36370 if (_addablePresetIDs) {
36371 // reset all presets
36372 _this.collection.forEach(function (p) {
36373 // categories aren't addable
36374 if (p.addable) p.addable(_addablePresetIDs.has(p.id));
36377 _this.collection.forEach(function (p) {
36378 if (p.addable) p.addable(true);
36385 _this.recent = function () {
36386 return presetCollection(utilArrayUniq(_this.getRecents().map(function (d) {
36391 function RibbonItem(preset, source) {
36393 item.preset = preset;
36394 item.source = source;
36396 item.isFavorite = function () {
36397 return item.source === 'favorite';
36400 item.isRecent = function () {
36401 return item.source === 'recent';
36404 item.matches = function (preset) {
36405 return item.preset.id === preset.id;
36408 item.minified = function () {
36410 pID: item.preset.id
36417 function ribbonItemForMinified(d, source) {
36419 var preset = _this.item(d.pID);
36421 if (!preset) return null;
36422 return RibbonItem(preset, source);
36428 _this.getGenericRibbonItems = function () {
36429 return ['point', 'line', 'area'].map(function (id) {
36430 return RibbonItem(_this.item(id), 'generic');
36434 _this.getAddable = function () {
36435 if (!_addablePresetIDs) return [];
36436 return _addablePresetIDs.map(function (id) {
36437 var preset = _this.item(id);
36439 if (preset) return RibbonItem(preset, 'addable');
36441 }).filter(Boolean);
36444 function setRecents(items) {
36446 var minifiedItems = items.map(function (d) {
36447 return d.minified();
36449 corePreferences('preset_recents', JSON.stringify(minifiedItems));
36450 dispatch.call('recentsChange');
36453 _this.getRecents = function () {
36455 // fetch from local storage
36456 _recents = (JSON.parse(corePreferences('preset_recents')) || []).reduce(function (acc, d) {
36457 var item = ribbonItemForMinified(d, 'recent');
36458 if (item && item.preset.addable()) acc.push(item);
36466 _this.addRecent = function (preset, besidePreset, after) {
36467 var recents = _this.getRecents();
36469 var beforeItem = _this.recentMatching(besidePreset);
36471 var toIndex = recents.indexOf(beforeItem);
36472 if (after) toIndex += 1;
36473 var newItem = RibbonItem(preset, 'recent');
36474 recents.splice(toIndex, 0, newItem);
36475 setRecents(recents);
36478 _this.removeRecent = function (preset) {
36479 var item = _this.recentMatching(preset);
36482 var items = _this.getRecents();
36484 items.splice(items.indexOf(item), 1);
36489 _this.recentMatching = function (preset) {
36490 var items = _this.getRecents();
36492 for (var i in items) {
36493 if (items[i].matches(preset)) {
36501 _this.moveItem = function (items, fromIndex, toIndex) {
36502 if (fromIndex === toIndex || fromIndex < 0 || toIndex < 0 || fromIndex >= items.length || toIndex >= items.length) return null;
36503 items.splice(toIndex, 0, items.splice(fromIndex, 1)[0]);
36507 _this.moveRecent = function (item, beforeItem) {
36508 var recents = _this.getRecents();
36510 var fromIndex = recents.indexOf(item);
36511 var toIndex = recents.indexOf(beforeItem);
36513 var items = _this.moveItem(recents, fromIndex, toIndex);
36515 if (items) setRecents(items);
36518 _this.setMostRecent = function (preset) {
36519 if (preset.searchable === false) return;
36521 var items = _this.getRecents();
36523 var item = _this.recentMatching(preset);
36526 items.splice(items.indexOf(item), 1);
36528 item = RibbonItem(preset, 'recent');
36529 } // remove the last recent (first in, first out)
36532 while (items.length >= MAXRECENTS) {
36537 items.unshift(item);
36541 function setFavorites(items) {
36542 _favorites = items;
36543 var minifiedItems = items.map(function (d) {
36544 return d.minified();
36546 corePreferences('preset_favorites', JSON.stringify(minifiedItems)); // call update
36548 dispatch.call('favoritePreset');
36551 _this.addFavorite = function (preset, besidePreset, after) {
36552 var favorites = _this.getFavorites();
36554 var beforeItem = _this.favoriteMatching(besidePreset);
36556 var toIndex = favorites.indexOf(beforeItem);
36557 if (after) toIndex += 1;
36558 var newItem = RibbonItem(preset, 'favorite');
36559 favorites.splice(toIndex, 0, newItem);
36560 setFavorites(favorites);
36563 _this.toggleFavorite = function (preset) {
36564 var favs = _this.getFavorites();
36566 var favorite = _this.favoriteMatching(preset);
36569 favs.splice(favs.indexOf(favorite), 1);
36571 // only allow 10 favorites
36572 if (favs.length === 10) {
36573 // remove the last favorite (last in, first out)
36578 favs.push(RibbonItem(preset, 'favorite'));
36581 setFavorites(favs);
36584 _this.removeFavorite = function (preset) {
36585 var item = _this.favoriteMatching(preset);
36588 var items = _this.getFavorites();
36590 items.splice(items.indexOf(item), 1);
36591 setFavorites(items);
36595 _this.getFavorites = function () {
36597 // fetch from local storage
36598 var rawFavorites = JSON.parse(corePreferences('preset_favorites'));
36600 if (!rawFavorites) {
36602 corePreferences('preset_favorites', JSON.stringify(rawFavorites));
36605 _favorites = rawFavorites.reduce(function (output, d) {
36606 var item = ribbonItemForMinified(d, 'favorite');
36607 if (item && item.preset.addable()) output.push(item);
36615 _this.favoriteMatching = function (preset) {
36616 var favs = _this.getFavorites();
36618 for (var index in favs) {
36619 if (favs[index].matches(preset)) {
36620 return favs[index];
36627 return utilRebind(_this, dispatch, 'on');
36630 function utilTagText(entity) {
36631 var obj = entity && entity.tags || {};
36632 return Object.keys(obj).map(function (k) {
36633 return k + '=' + obj[k];
36636 function utilTotalExtent(array, graph) {
36637 var extent = geoExtent();
36640 for (var i = 0; i < array.length; i++) {
36642 entity = typeof val === 'string' ? graph.hasEntity(val) : val;
36645 extent._extend(entity.extent(graph));
36651 function utilTagDiff(oldTags, newTags) {
36653 var keys = utilArrayUnion(Object.keys(oldTags), Object.keys(newTags)).sort();
36654 keys.forEach(function (k) {
36655 var oldVal = oldTags[k];
36656 var newVal = newTags[k];
36658 if ((oldVal || oldVal === '') && (newVal === undefined || newVal !== oldVal)) {
36664 display: '- ' + k + '=' + oldVal
36668 if ((newVal || newVal === '') && (oldVal === undefined || newVal !== oldVal)) {
36674 display: '+ ' + k + '=' + newVal
36680 function utilEntitySelector(ids) {
36681 return ids.length ? '.' + ids.join(',.') : 'nothing';
36682 } // returns an selector to select entity ids for:
36683 // - entityIDs passed in
36684 // - shallow descendant entityIDs for any of those entities that are relations
36686 function utilEntityOrMemberSelector(ids, graph) {
36687 var seen = new Set(ids);
36688 ids.forEach(collectShallowDescendants);
36689 return utilEntitySelector(Array.from(seen));
36691 function collectShallowDescendants(id) {
36692 var entity = graph.hasEntity(id);
36693 if (!entity || entity.type !== 'relation') return;
36694 entity.members.map(function (member) {
36696 }).forEach(function (id) {
36700 } // returns an selector to select entity ids for:
36701 // - entityIDs passed in
36702 // - deep descendant entityIDs for any of those entities that are relations
36704 function utilEntityOrDeepMemberSelector(ids, graph) {
36705 return utilEntitySelector(utilEntityAndDeepMemberIDs(ids, graph));
36706 } // returns an selector to select entity ids for:
36707 // - entityIDs passed in
36708 // - deep descendant entityIDs for any of those entities that are relations
36710 function utilEntityAndDeepMemberIDs(ids, graph) {
36711 var seen = new Set();
36712 ids.forEach(collectDeepDescendants);
36713 return Array.from(seen);
36715 function collectDeepDescendants(id) {
36716 if (seen.has(id)) return;
36718 var entity = graph.hasEntity(id);
36719 if (!entity || entity.type !== 'relation') return;
36720 entity.members.map(function (member) {
36722 }).forEach(collectDeepDescendants); // recurse
36724 } // returns an selector to select entity ids for:
36725 // - deep descendant entityIDs for any of those entities that are relations
36727 function utilDeepMemberSelector(ids, graph, skipMultipolgonMembers) {
36728 var idsSet = new Set(ids);
36729 var seen = new Set();
36730 var returners = new Set();
36731 ids.forEach(collectDeepDescendants);
36732 return utilEntitySelector(Array.from(returners));
36734 function collectDeepDescendants(id) {
36735 if (seen.has(id)) return;
36738 if (!idsSet.has(id)) {
36742 var entity = graph.hasEntity(id);
36743 if (!entity || entity.type !== 'relation') return;
36744 if (skipMultipolgonMembers && entity.isMultipolygon()) return;
36745 entity.members.map(function (member) {
36747 }).forEach(collectDeepDescendants); // recurse
36749 } // Adds or removes highlight styling for the specified entities
36751 function utilHighlightEntities(ids, highlighted, context) {
36752 context.surface().selectAll(utilEntityOrDeepMemberSelector(ids, context.graph())).classed('highlighted', highlighted);
36753 } // returns an Array that is the union of:
36754 // - nodes for any nodeIDs passed in
36755 // - child nodes of any wayIDs passed in
36756 // - descendant member and child nodes of relationIDs passed in
36758 function utilGetAllNodes(ids, graph) {
36759 var seen = new Set();
36760 var nodes = new Set();
36761 ids.forEach(collectNodes);
36762 return Array.from(nodes);
36764 function collectNodes(id) {
36765 if (seen.has(id)) return;
36767 var entity = graph.hasEntity(id);
36768 if (!entity) return;
36770 if (entity.type === 'node') {
36772 } else if (entity.type === 'way') {
36773 entity.nodes.forEach(collectNodes);
36775 entity.members.map(function (member) {
36777 }).forEach(collectNodes); // recurse
36781 function utilDisplayName(entity) {
36782 var localizedNameKey = 'name:' + _mainLocalizer.languageCode().toLowerCase();
36783 var name = entity.tags[localizedNameKey] || entity.tags.name || '';
36784 if (name) return name;
36786 direction: entity.tags.direction,
36787 from: entity.tags.from,
36788 network: entity.tags.cycle_network || entity.tags.network,
36789 ref: entity.tags.ref,
36790 to: entity.tags.to,
36791 via: entity.tags.via
36793 var keyComponents = [];
36795 if (tags.network) {
36796 keyComponents.push('network');
36800 keyComponents.push('ref');
36801 } // Routes may need more disambiguation based on direction or destination
36804 if (entity.tags.route) {
36805 if (tags.direction) {
36806 keyComponents.push('direction');
36807 } else if (tags.from && tags.to) {
36808 keyComponents.push('from');
36809 keyComponents.push('to');
36812 keyComponents.push('via');
36817 if (keyComponents.length) {
36818 name = _t('inspector.display_name.' + keyComponents.join('_'), tags);
36823 function utilDisplayNameForPath(entity) {
36824 var name = utilDisplayName(entity);
36825 var isFirefox = utilDetect().browser.toLowerCase().indexOf('firefox') > -1;
36826 var isNewChromium = Number(utilDetect().version.split('.')[0]) >= 96.0;
36828 if (!isFirefox && !isNewChromium && name && rtlRegex.test(name)) {
36829 name = fixRTLTextForSvg(name);
36834 function utilDisplayType(id) {
36836 n: _t('inspector.node'),
36837 w: _t('inspector.way'),
36838 r: _t('inspector.relation')
36840 } // `utilDisplayLabel`
36841 // Returns a string suitable for display
36842 // By default returns something like name/ref, fallback to preset type, fallback to OSM type
36843 // "Main Street" or "Tertiary Road"
36844 // If `verbose=true`, include both preset name and feature name.
36845 // "Tertiary Road Main Street"
36848 function utilDisplayLabel(entity, graphOrGeometry, verbose) {
36850 var displayName = utilDisplayName(entity);
36851 var preset = typeof graphOrGeometry === 'string' ? _mainPresetIndex.matchTags(entity.tags, graphOrGeometry) : _mainPresetIndex.match(entity, graphOrGeometry);
36852 var presetName = preset && (preset.suggestion ? preset.subtitle() : preset.name());
36855 result = [presetName, displayName].filter(Boolean).join(' ');
36857 result = displayName || presetName;
36858 } // Fallback to the OSM type (node/way/relation)
36861 return result || utilDisplayType(entity.id);
36863 function utilEntityRoot(entityType) {
36869 } // Returns a single object containing the tags of all the given entities.
36872 // highway: 'service',
36873 // service: 'parking_aisle'
36877 // highway: 'service',
36878 // service: 'driveway',
36883 // highway: 'service',
36884 // service: [ 'driveway', 'parking_aisle' ],
36885 // width: [ '3', undefined ]
36888 function utilCombinedTags(entityIDs, graph) {
36890 var tagCounts = {};
36891 var allKeys = new Set();
36892 var entities = entityIDs.map(function (entityID) {
36893 return graph.hasEntity(entityID);
36894 }).filter(Boolean); // gather the aggregate keys
36896 entities.forEach(function (entity) {
36897 var keys = Object.keys(entity.tags).filter(Boolean);
36898 keys.forEach(function (key) {
36902 entities.forEach(function (entity) {
36903 allKeys.forEach(function (key) {
36904 var value = entity.tags[key]; // purposely allow `undefined`
36906 if (!tags.hasOwnProperty(key)) {
36907 // first value, set as raw
36910 if (!Array.isArray(tags[key])) {
36911 if (tags[key] !== value) {
36912 // first alternate value, replace single value with array
36913 tags[key] = [tags[key], value];
36917 if (tags[key].indexOf(value) === -1) {
36918 // subsequent alternate value, add to array
36919 tags[key].push(value);
36924 var tagHash = key + '=' + value;
36925 if (!tagCounts[tagHash]) tagCounts[tagHash] = 0;
36926 tagCounts[tagHash] += 1;
36930 for (var key in tags) {
36931 if (!Array.isArray(tags[key])) continue; // sort values by frequency then alphabetically
36933 tags[key] = tags[key].sort(function (val1, val2) {
36934 var key = key; // capture
36936 var count2 = tagCounts[key + '=' + val2];
36937 var count1 = tagCounts[key + '=' + val1];
36939 if (count2 !== count1) {
36940 return count2 - count1;
36943 if (val2 && val1) {
36944 return val1.localeCompare(val2);
36947 return val1 ? 1 : -1;
36953 function utilStringQs(str) {
36954 var i = 0; // advance past any leading '?' or '#' characters
36956 while (i < str.length && (str[i] === '?' || str[i] === '#')) {
36960 str = str.slice(i);
36961 return str.split('&').reduce(function (obj, pair) {
36962 var parts = pair.split('=');
36964 if (parts.length === 2) {
36965 obj[parts[0]] = null === parts[1] ? '' : decodeURIComponent(parts[1]);
36971 function utilQsString(obj, noencode) {
36972 // encode everything except special characters used in certain hash parameters:
36973 // "/" in map states, ":", ",", {" and "}" in background
36974 function softEncode(s) {
36975 return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
36978 return Object.keys(obj).sort().map(function (key) {
36979 return encodeURIComponent(key) + '=' + (noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
36982 function utilPrefixDOMProperty(property) {
36983 var prefixes = ['webkit', 'ms', 'moz', 'o'];
36985 var n = prefixes.length;
36986 var s = document.body;
36987 if (property in s) return property;
36988 property = property.substr(0, 1).toUpperCase() + property.substr(1);
36991 if (prefixes[i] + property in s) {
36992 return prefixes[i] + property;
36998 function utilPrefixCSSProperty(property) {
36999 var prefixes = ['webkit', 'ms', 'Moz', 'O'];
37001 var n = prefixes.length;
37002 var s = document.body.style;
37004 if (property.toLowerCase() in s) {
37005 return property.toLowerCase();
37009 if (prefixes[i] + property in s) {
37010 return '-' + prefixes[i].toLowerCase() + property.replace(/([A-Z])/g, '-$1').toLowerCase();
37016 var transformProperty;
37017 function utilSetTransform(el, x, y, scale) {
37018 var prop = transformProperty = transformProperty || utilPrefixCSSProperty('Transform');
37019 var translate = utilDetect().opera ? 'translate(' + x + 'px,' + y + 'px)' : 'translate3d(' + x + 'px,' + y + 'px,0)';
37020 return el.style(prop, translate + (scale ? ' scale(' + scale + ')' : ''));
37021 } // Calculates Levenshtein distance between two strings
37022 // see: https://en.wikipedia.org/wiki/Levenshtein_distance
37023 // first converts the strings to lowercase and replaces diacritic marks with ascii equivalents.
37025 function utilEditDistance(a, b) {
37026 a = remove$6(a.toLowerCase());
37027 b = remove$6(b.toLowerCase());
37028 if (a.length === 0) return b.length;
37029 if (b.length === 0) return a.length;
37033 for (i = 0; i <= b.length; i++) {
37037 for (j = 0; j <= a.length; j++) {
37041 for (i = 1; i <= b.length; i++) {
37042 for (j = 1; j <= a.length; j++) {
37043 if (b.charAt(i - 1) === a.charAt(j - 1)) {
37044 matrix[i][j] = matrix[i - 1][j - 1];
37046 matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
37047 Math.min(matrix[i][j - 1] + 1, // insertion
37048 matrix[i - 1][j] + 1)); // deletion
37053 return matrix[b.length][a.length];
37054 } // a d3.mouse-alike which
37055 // 1. Only works on HTML elements, not SVG
37056 // 2. Does not cause style recalculation
37058 function utilFastMouse(container) {
37059 var rect = container.getBoundingClientRect();
37060 var rectLeft = rect.left;
37061 var rectTop = rect.top;
37062 var clientLeft = +container.clientLeft;
37063 var clientTop = +container.clientTop;
37064 return function (e) {
37065 return [e.clientX - rectLeft - clientLeft, e.clientY - rectTop - clientTop];
37068 function utilAsyncMap(inputs, func, callback) {
37069 var remaining = inputs.length;
37072 inputs.forEach(function (d, i) {
37073 func(d, function done(err, data) {
37077 if (!remaining) callback(errors, results);
37080 } // wraps an index to an interval [0..length-1]
37082 function utilWrap(index, length) {
37084 index += Math.ceil(-index / length) * length;
37087 return index % length;
37090 * a replacement for functor
37092 * @param {*} value any value
37093 * @returns {Function} a function that returns that value or the value if it's a function
37096 function utilFunctor(value) {
37097 if (typeof value === 'function') return value;
37098 return function () {
37102 function utilNoAuto(selection) {
37103 var isText = selection.size() && selection.node().tagName.toLowerCase() === 'textarea';
37104 return selection // assign 'new-password' even for non-password fields to prevent browsers (Chrome) ignoring 'off'
37105 .attr('autocomplete', 'new-password').attr('autocorrect', 'off').attr('autocapitalize', 'off').attr('spellcheck', isText ? 'true' : 'false');
37106 } // https://stackoverflow.com/questions/194846/is-there-any-kind-of-hash-code-function-in-javascript
37107 // https://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
37109 function utilHashcode(str) {
37112 if (str.length === 0) {
37116 for (var i = 0; i < str.length; i++) {
37117 var _char = str.charCodeAt(i);
37119 hash = (hash << 5) - hash + _char;
37120 hash = hash & hash; // Convert to 32bit integer
37124 } // Returns version of `str` with all runs of special characters replaced by `_`;
37125 // suitable for HTML ids, classes, selectors, etc.
37127 function utilSafeClassName(str) {
37128 return str.toLowerCase().replace(/[^a-z0-9]+/g, '_');
37129 } // Returns string based on `val` that is highly unlikely to collide with an id
37130 // used previously or that's present elsewhere in the document. Useful for preventing
37131 // browser-provided autofills or when embedding iD on pages with unknown elements.
37133 function utilUniqueDomId(val) {
37134 return 'ideditor-' + utilSafeClassName(val.toString()) + '-' + new Date().getTime().toString();
37135 } // Returns the length of `str` in unicode characters. This can be less than
37136 // `String.length()` since a single unicode character can be composed of multiple
37137 // JavaScript UTF-16 code units.
37139 function utilUnicodeCharsCount(str) {
37140 // Native ES2015 implementations of `Array.from` split strings into unicode characters
37141 return Array.from(str).length;
37142 } // Returns a new string representing `str` cut from its start to `limit` length
37143 // in unicode characters. Note that this runs the risk of splitting graphemes.
37145 function utilUnicodeCharsTruncated(str, limit) {
37146 return Array.from(str).slice(0, limit).join('');
37149 function toNumericID(id) {
37150 var match = id.match(/^[cnwr](-?\d+)$/);
37153 return parseInt(match[1], 10);
37159 function compareNumericIDs(left, right) {
37160 if (isNaN(left) && isNaN(right)) return -1;
37161 if (isNaN(left)) return 1;
37162 if (isNaN(right)) return -1;
37163 if (Math.sign(left) !== Math.sign(right)) return -Math.sign(left);
37164 if (Math.sign(left) < 0) return Math.sign(right - left);
37165 return Math.sign(left - right);
37166 } // Returns -1 if the first parameter ID is older than the second,
37167 // 1 if the second parameter is older, 0 if they are the same.
37168 // If both IDs are test IDs, the function returns -1.
37171 function utilCompareIDs(left, right) {
37172 return compareNumericIDs(toNumericID(left), toNumericID(right));
37173 } // Returns the chronologically oldest ID in the list.
37174 // Database IDs (with positive numbers) before editor ones (with negative numbers).
37175 // Among each category, the closest number to 0 is the oldest.
37176 // Test IDs (any string that does not conform to OSM's ID scheme) are taken last.
37178 function utilOldestID(ids) {
37179 if (ids.length === 0) {
37183 var oldestIDIndex = 0;
37184 var oldestID = toNumericID(ids[0]);
37186 for (var i = 1; i < ids.length; i++) {
37187 var num = toNumericID(ids[i]);
37189 if (compareNumericIDs(oldestID, num) === 1) {
37195 return ids[oldestIDIndex];
37198 function osmEntity(attrs) {
37199 // For prototypal inheritance.
37200 if (this instanceof osmEntity) return; // Create the appropriate subtype.
37202 if (attrs && attrs.type) {
37203 return osmEntity[attrs.type].apply(this, arguments);
37204 } else if (attrs && attrs.id) {
37205 return osmEntity[osmEntity.id.type(attrs.id)].apply(this, arguments);
37206 } // Initialize a generic Entity (used only in tests).
37209 return new osmEntity().initialize(arguments);
37212 osmEntity.id = function (type) {
37213 return osmEntity.id.fromOSM(type, osmEntity.id.next[type]--);
37216 osmEntity.id.next = {
37223 osmEntity.id.fromOSM = function (type, id) {
37224 return type[0] + id;
37227 osmEntity.id.toOSM = function (id) {
37228 var match = id.match(/^[cnwr](-?\d+)$/);
37237 osmEntity.id.type = function (id) {
37244 }; // A function suitable for use as the second argument to d3.selection#data().
37247 osmEntity.key = function (entity) {
37248 return entity.id + 'v' + (entity.v || 0);
37251 var _deprecatedTagValuesByKey;
37253 osmEntity.deprecatedTagValuesByKey = function (dataDeprecated) {
37254 if (!_deprecatedTagValuesByKey) {
37255 _deprecatedTagValuesByKey = {};
37256 dataDeprecated.forEach(function (d) {
37257 var oldKeys = Object.keys(d.old);
37259 if (oldKeys.length === 1) {
37260 var oldKey = oldKeys[0];
37261 var oldValue = d.old[oldKey];
37263 if (oldValue !== '*') {
37264 if (!_deprecatedTagValuesByKey[oldKey]) {
37265 _deprecatedTagValuesByKey[oldKey] = [oldValue];
37267 _deprecatedTagValuesByKey[oldKey].push(oldValue);
37274 return _deprecatedTagValuesByKey;
37277 osmEntity.prototype = {
37279 initialize: function initialize(sources) {
37280 for (var i = 0; i < sources.length; ++i) {
37281 var source = sources[i];
37283 for (var prop in source) {
37284 if (Object.prototype.hasOwnProperty.call(source, prop)) {
37285 if (source[prop] === undefined) {
37288 this[prop] = source[prop];
37294 if (!this.id && this.type) {
37295 this.id = osmEntity.id(this.type);
37298 if (!this.hasOwnProperty('visible')) {
37299 this.visible = true;
37303 Object.freeze(this);
37304 Object.freeze(this.tags);
37305 if (this.loc) Object.freeze(this.loc);
37306 if (this.nodes) Object.freeze(this.nodes);
37307 if (this.members) Object.freeze(this.members);
37312 copy: function copy(resolver, copies) {
37313 if (copies[this.id]) return copies[this.id];
37314 var copy = osmEntity(this, {
37319 copies[this.id] = copy;
37322 osmId: function osmId() {
37323 return osmEntity.id.toOSM(this.id);
37325 isNew: function isNew() {
37326 var osmId = osmEntity.id.toOSM(this.id);
37327 return osmId.length === 0 || osmId[0] === '-';
37329 update: function update(attrs) {
37330 return osmEntity(this, attrs, {
37331 v: 1 + (this.v || 0)
37334 mergeTags: function mergeTags(tags) {
37335 var merged = Object.assign({}, this.tags); // shallow copy
37337 var changed = false;
37339 for (var k in tags) {
37340 var t1 = merged[k];
37346 } else if (t1 !== t2) {
37348 merged[k] = utilUnicodeCharsTruncated(utilArrayUnion(t1.split(/;\s*/), t2.split(/;\s*/)).join(';'), 255 // avoid exceeding character limit; see also services/osm.js -> maxCharsForTagValue()
37353 return changed ? this.update({
37357 intersects: function intersects(extent, resolver) {
37358 return this.extent(resolver).intersects(extent);
37360 hasNonGeometryTags: function hasNonGeometryTags() {
37361 return Object.keys(this.tags).some(function (k) {
37362 return k !== 'area';
37365 hasParentRelations: function hasParentRelations(resolver) {
37366 return resolver.parentRelations(this).length > 0;
37368 hasInterestingTags: function hasInterestingTags() {
37369 return Object.keys(this.tags).some(osmIsInterestingTag);
37371 isHighwayIntersection: function isHighwayIntersection() {
37374 isDegenerate: function isDegenerate() {
37377 deprecatedTags: function deprecatedTags(dataDeprecated) {
37378 var tags = this.tags; // if there are no tags, none can be deprecated
37380 if (Object.keys(tags).length === 0) return [];
37381 var deprecated = [];
37382 dataDeprecated.forEach(function (d) {
37383 var oldKeys = Object.keys(d.old);
37386 var hasExistingValues = Object.keys(d.replace).some(function (replaceKey) {
37387 if (!tags[replaceKey] || d.old[replaceKey]) return false;
37388 var replaceValue = d.replace[replaceKey];
37389 if (replaceValue === '*') return false;
37390 if (replaceValue === tags[replaceKey]) return false;
37392 }); // don't flag deprecated tags if the upgrade path would overwrite existing data - #7843
37394 if (hasExistingValues) return;
37397 var matchesDeprecatedTags = oldKeys.every(function (oldKey) {
37398 if (!tags[oldKey]) return false;
37399 if (d.old[oldKey] === '*') return true;
37400 if (d.old[oldKey] === tags[oldKey]) return true;
37401 var vals = tags[oldKey].split(';').filter(Boolean);
37403 if (vals.length === 0) {
37405 } else if (vals.length > 1) {
37406 return vals.indexOf(d.old[oldKey]) !== -1;
37408 if (tags[oldKey] === d.old[oldKey]) {
37409 if (d.replace && d.old[oldKey] === d.replace[oldKey]) {
37410 var replaceKeys = Object.keys(d.replace);
37411 return !replaceKeys.every(function (replaceKey) {
37412 return tags[replaceKey] === d.replace[replaceKey];
37423 if (matchesDeprecatedTags) {
37424 deprecated.push(d);
37431 function osmLanes(entity) {
37432 if (entity.type !== 'way') return null;
37433 if (!entity.tags.highway) return null;
37434 var tags = entity.tags;
37435 var isOneWay = entity.isOneWay();
37436 var laneCount = getLaneCount(tags, isOneWay);
37437 var maxspeed = parseMaxspeed(tags);
37438 var laneDirections = parseLaneDirections(tags, isOneWay, laneCount);
37439 var forward = laneDirections.forward;
37440 var backward = laneDirections.backward;
37441 var bothways = laneDirections.bothways; // parse the piped string 'x|y|z' format
37443 var turnLanes = {};
37444 turnLanes.unspecified = parseTurnLanes(tags['turn:lanes']);
37445 turnLanes.forward = parseTurnLanes(tags['turn:lanes:forward']);
37446 turnLanes.backward = parseTurnLanes(tags['turn:lanes:backward']);
37447 var maxspeedLanes = {};
37448 maxspeedLanes.unspecified = parseMaxspeedLanes(tags['maxspeed:lanes'], maxspeed);
37449 maxspeedLanes.forward = parseMaxspeedLanes(tags['maxspeed:lanes:forward'], maxspeed);
37450 maxspeedLanes.backward = parseMaxspeedLanes(tags['maxspeed:lanes:backward'], maxspeed);
37452 psvLanes.unspecified = parseMiscLanes(tags['psv:lanes']);
37453 psvLanes.forward = parseMiscLanes(tags['psv:lanes:forward']);
37454 psvLanes.backward = parseMiscLanes(tags['psv:lanes:backward']);
37456 busLanes.unspecified = parseMiscLanes(tags['bus:lanes']);
37457 busLanes.forward = parseMiscLanes(tags['bus:lanes:forward']);
37458 busLanes.backward = parseMiscLanes(tags['bus:lanes:backward']);
37459 var taxiLanes = {};
37460 taxiLanes.unspecified = parseMiscLanes(tags['taxi:lanes']);
37461 taxiLanes.forward = parseMiscLanes(tags['taxi:lanes:forward']);
37462 taxiLanes.backward = parseMiscLanes(tags['taxi:lanes:backward']);
37464 hovLanes.unspecified = parseMiscLanes(tags['hov:lanes']);
37465 hovLanes.forward = parseMiscLanes(tags['hov:lanes:forward']);
37466 hovLanes.backward = parseMiscLanes(tags['hov:lanes:backward']);
37468 hgvLanes.unspecified = parseMiscLanes(tags['hgv:lanes']);
37469 hgvLanes.forward = parseMiscLanes(tags['hgv:lanes:forward']);
37470 hgvLanes.backward = parseMiscLanes(tags['hgv:lanes:backward']);
37471 var bicyclewayLanes = {};
37472 bicyclewayLanes.unspecified = parseBicycleWay(tags['bicycleway:lanes']);
37473 bicyclewayLanes.forward = parseBicycleWay(tags['bicycleway:lanes:forward']);
37474 bicyclewayLanes.backward = parseBicycleWay(tags['bicycleway:lanes:backward']);
37479 }; // map forward/backward/unspecified of each lane type to lanesObj
37481 mapToLanesObj(lanesObj, turnLanes, 'turnLane');
37482 mapToLanesObj(lanesObj, maxspeedLanes, 'maxspeed');
37483 mapToLanesObj(lanesObj, psvLanes, 'psv');
37484 mapToLanesObj(lanesObj, busLanes, 'bus');
37485 mapToLanesObj(lanesObj, taxiLanes, 'taxi');
37486 mapToLanesObj(lanesObj, hovLanes, 'hov');
37487 mapToLanesObj(lanesObj, hgvLanes, 'hgv');
37488 mapToLanesObj(lanesObj, bicyclewayLanes, 'bicycleway');
37494 backward: backward,
37495 bothways: bothways,
37496 turnLanes: turnLanes,
37497 maxspeed: maxspeed,
37498 maxspeedLanes: maxspeedLanes,
37499 psvLanes: psvLanes,
37500 busLanes: busLanes,
37501 taxiLanes: taxiLanes,
37502 hovLanes: hovLanes,
37503 hgvLanes: hgvLanes,
37504 bicyclewayLanes: bicyclewayLanes
37510 function getLaneCount(tags, isOneWay) {
37514 count = parseInt(tags.lanes, 10);
37521 switch (tags.highway) {
37524 count = isOneWay ? 2 : 4;
37528 count = isOneWay ? 1 : 2;
37535 function parseMaxspeed(tags) {
37536 var maxspeed = tags.maxspeed;
37537 if (!maxspeed) return;
37538 var maxspeedRegex = /^([0-9][\.0-9]+?)(?:[ ]?(?:km\/h|kmh|kph|mph|knots))?$/;
37539 if (!maxspeedRegex.test(maxspeed)) return;
37540 return parseInt(maxspeed, 10);
37543 function parseLaneDirections(tags, isOneWay, laneCount) {
37544 var forward = parseInt(tags['lanes:forward'], 10);
37545 var backward = parseInt(tags['lanes:backward'], 10);
37546 var bothways = parseInt(tags['lanes:both_ways'], 10) > 0 ? 1 : 0;
37548 if (parseInt(tags.oneway, 10) === -1) {
37551 backward = laneCount;
37552 } else if (isOneWay) {
37553 forward = laneCount;
37556 } else if (isNaN(forward) && isNaN(backward)) {
37557 backward = Math.floor((laneCount - bothways) / 2);
37558 forward = laneCount - bothways - backward;
37559 } else if (isNaN(forward)) {
37560 if (backward > laneCount - bothways) {
37561 backward = laneCount - bothways;
37564 forward = laneCount - bothways - backward;
37565 } else if (isNaN(backward)) {
37566 if (forward > laneCount - bothways) {
37567 forward = laneCount - bothways;
37570 backward = laneCount - bothways - forward;
37575 backward: backward,
37580 function parseTurnLanes(tag) {
37582 var validValues = ['left', 'slight_left', 'sharp_left', 'through', 'right', 'slight_right', 'sharp_right', 'reverse', 'merge_to_left', 'merge_to_right', 'none'];
37583 return tag.split('|').map(function (s) {
37584 if (s === '') s = 'none';
37585 return s.split(';').map(function (d) {
37586 return validValues.indexOf(d) === -1 ? 'unknown' : d;
37591 function parseMaxspeedLanes(tag, maxspeed) {
37593 return tag.split('|').map(function (s) {
37594 if (s === 'none') return s;
37595 var m = parseInt(s, 10);
37596 if (s === '' || m === maxspeed) return null;
37597 return isNaN(m) ? 'unknown' : m;
37601 function parseMiscLanes(tag) {
37603 var validValues = ['yes', 'no', 'designated'];
37604 return tag.split('|').map(function (s) {
37605 if (s === '') s = 'no';
37606 return validValues.indexOf(s) === -1 ? 'unknown' : s;
37610 function parseBicycleWay(tag) {
37612 var validValues = ['yes', 'no', 'designated', 'lane'];
37613 return tag.split('|').map(function (s) {
37614 if (s === '') s = 'no';
37615 return validValues.indexOf(s) === -1 ? 'unknown' : s;
37619 function mapToLanesObj(lanesObj, data, key) {
37620 if (data.forward) {
37621 data.forward.forEach(function (l, i) {
37622 if (!lanesObj.forward[i]) lanesObj.forward[i] = {};
37623 lanesObj.forward[i][key] = l;
37627 if (data.backward) {
37628 data.backward.forEach(function (l, i) {
37629 if (!lanesObj.backward[i]) lanesObj.backward[i] = {};
37630 lanesObj.backward[i][key] = l;
37634 if (data.unspecified) {
37635 data.unspecified.forEach(function (l, i) {
37636 if (!lanesObj.unspecified[i]) lanesObj.unspecified[i] = {};
37637 lanesObj.unspecified[i][key] = l;
37642 function osmWay() {
37643 if (!(this instanceof osmWay)) {
37644 return new osmWay().initialize(arguments);
37645 } else if (arguments.length) {
37646 this.initialize(arguments);
37649 osmEntity.way = osmWay;
37650 osmWay.prototype = Object.create(osmEntity.prototype);
37651 Object.assign(osmWay.prototype, {
37654 copy: function copy(resolver, copies) {
37655 if (copies[this.id]) return copies[this.id];
37656 var copy = osmEntity.prototype.copy.call(this, resolver, copies);
37657 var nodes = this.nodes.map(function (id) {
37658 return resolver.entity(id).copy(resolver, copies).id;
37660 copy = copy.update({
37663 copies[this.id] = copy;
37666 extent: function extent(resolver) {
37667 return resolver["transient"](this, 'extent', function () {
37668 var extent = geoExtent();
37670 for (var i = 0; i < this.nodes.length; i++) {
37671 var node = resolver.hasEntity(this.nodes[i]);
37674 extent._extend(node.extent());
37681 first: function first() {
37682 return this.nodes[0];
37684 last: function last() {
37685 return this.nodes[this.nodes.length - 1];
37687 contains: function contains(node) {
37688 return this.nodes.indexOf(node) >= 0;
37690 affix: function affix(node) {
37691 if (this.nodes[0] === node) return 'prefix';
37692 if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
37694 layer: function layer() {
37695 // explicit layer tag, clamp between -10, 10..
37696 if (isFinite(this.tags.layer)) {
37697 return Math.max(-10, Math.min(+this.tags.layer, 10));
37698 } // implied layer tag..
37701 if (this.tags.covered === 'yes') return -1;
37702 if (this.tags.location === 'overground') return 1;
37703 if (this.tags.location === 'underground') return -1;
37704 if (this.tags.location === 'underwater') return -10;
37705 if (this.tags.power === 'line') return 10;
37706 if (this.tags.power === 'minor_line') return 10;
37707 if (this.tags.aerialway) return 10;
37708 if (this.tags.bridge) return 1;
37709 if (this.tags.cutting) return -1;
37710 if (this.tags.tunnel) return -1;
37711 if (this.tags.waterway) return -1;
37712 if (this.tags.man_made === 'pipeline') return -10;
37713 if (this.tags.boundary) return -10;
37716 // the approximate width of the line based on its tags except its `width` tag
37717 impliedLineWidthMeters: function impliedLineWidthMeters() {
37718 var averageWidths = {
37720 // width is for single lane
37747 // width includes ties and rail bed, not just track gauge
37770 for (var key in averageWidths) {
37771 if (this.tags[key] && averageWidths[key][this.tags[key]]) {
37772 var width = averageWidths[key][this.tags[key]];
37774 if (key === 'highway') {
37775 var laneCount = this.tags.lanes && parseInt(this.tags.lanes, 10);
37776 if (!laneCount) laneCount = this.isOneWay() ? 1 : 2;
37777 return width * laneCount;
37786 isOneWay: function isOneWay() {
37787 // explicit oneway tag..
37792 'reversible': true,
37793 'alternating': true,
37798 if (values[this.tags.oneway] !== undefined) {
37799 return values[this.tags.oneway];
37800 } // implied oneway tag..
37803 for (var key in this.tags) {
37804 if (key in osmOneWayTags && this.tags[key] in osmOneWayTags[key]) {
37811 // Some identifier for tag that implies that this way is "sided",
37812 // i.e. the right side is the 'inside' (e.g. the right side of a
37813 // natural=cliff is lower).
37814 sidednessIdentifier: function sidednessIdentifier() {
37815 for (var key in this.tags) {
37816 var value = this.tags[key];
37818 if (key in osmRightSideIsInsideTags && value in osmRightSideIsInsideTags[key]) {
37819 if (osmRightSideIsInsideTags[key][value] === true) {
37822 // if the map's value is something other than a
37823 // literal true, we should use it so we can
37824 // special case some keys (e.g. natural=coastline
37825 // is handled differently to other naturals).
37826 return osmRightSideIsInsideTags[key][value];
37833 isSided: function isSided() {
37834 if (this.tags.two_sided === 'yes') {
37838 return this.sidednessIdentifier() !== null;
37840 lanes: function lanes() {
37841 return osmLanes(this);
37843 isClosed: function isClosed() {
37844 return this.nodes.length > 1 && this.first() === this.last();
37846 isConvex: function isConvex(resolver) {
37847 if (!this.isClosed() || this.isDegenerate()) return null;
37848 var nodes = utilArrayUniq(resolver.childNodes(this));
37849 var coords = nodes.map(function (n) {
37855 for (var i = 0; i < coords.length; i++) {
37856 var o = coords[(i + 1) % coords.length];
37858 var b = coords[(i + 2) % coords.length];
37859 var res = geoVecCross(a, b, o);
37860 curr = res > 0 ? 1 : res < 0 ? -1 : 0;
37864 } else if (prev && curr !== prev) {
37873 // returns an object with the tag that implies this is an area, if any
37874 tagSuggestingArea: function tagSuggestingArea() {
37875 return osmTagSuggestingArea(this.tags);
37877 isArea: function isArea() {
37878 if (this.tags.area === 'yes') return true;
37879 if (!this.isClosed() || this.tags.area === 'no') return false;
37880 return this.tagSuggestingArea() !== null;
37882 isDegenerate: function isDegenerate() {
37883 return new Set(this.nodes).size < (this.isArea() ? 3 : 2);
37885 areAdjacent: function areAdjacent(n1, n2) {
37886 for (var i = 0; i < this.nodes.length; i++) {
37887 if (this.nodes[i] === n1) {
37888 if (this.nodes[i - 1] === n2) return true;
37889 if (this.nodes[i + 1] === n2) return true;
37895 geometry: function geometry(graph) {
37896 return graph["transient"](this, 'geometry', function () {
37897 return this.isArea() ? 'area' : 'line';
37900 // returns an array of objects representing the segments between the nodes in this way
37901 segments: function segments(graph) {
37902 function segmentExtent(graph) {
37903 var n1 = graph.hasEntity(this.nodes[0]);
37904 var n2 = graph.hasEntity(this.nodes[1]);
37905 return n1 && n2 && geoExtent([[Math.min(n1.loc[0], n2.loc[0]), Math.min(n1.loc[1], n2.loc[1])], [Math.max(n1.loc[0], n2.loc[0]), Math.max(n1.loc[1], n2.loc[1])]]);
37908 return graph["transient"](this, 'segments', function () {
37911 for (var i = 0; i < this.nodes.length - 1; i++) {
37913 id: this.id + '-' + i,
37916 nodes: [this.nodes[i], this.nodes[i + 1]],
37917 extent: segmentExtent
37924 // If this way is not closed, append the beginning node to the end of the nodelist to close it.
37925 close: function close() {
37926 if (this.isClosed() || !this.nodes.length) return this;
37927 var nodes = this.nodes.slice();
37928 nodes = nodes.filter(noRepeatNodes);
37929 nodes.push(nodes[0]);
37930 return this.update({
37934 // If this way is closed, remove any connector nodes from the end of the nodelist to unclose it.
37935 unclose: function unclose() {
37936 if (!this.isClosed()) return this;
37937 var nodes = this.nodes.slice();
37938 var connector = this.first();
37939 var i = nodes.length - 1; // remove trailing connectors..
37941 while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
37942 nodes.splice(i, 1);
37943 i = nodes.length - 1;
37946 nodes = nodes.filter(noRepeatNodes);
37947 return this.update({
37951 // Adds a node (id) in front of the node which is currently at position index.
37952 // If index is undefined, the node will be added to the end of the way for linear ways,
37953 // or just before the final connecting node for circular ways.
37954 // Consecutive duplicates are eliminated including existing ones.
37955 // Circularity is always preserved when adding a node.
37956 addNode: function addNode(id, index) {
37957 var nodes = this.nodes.slice();
37958 var isClosed = this.isClosed();
37959 var max = isClosed ? nodes.length - 1 : nodes.length;
37961 if (index === undefined) {
37965 if (index < 0 || index > max) {
37966 throw new RangeError('index ' + index + ' out of range 0..' + max);
37967 } // If this is a closed way, remove all connector nodes except the first one
37968 // (there may be duplicates) and adjust index if necessary..
37972 var connector = this.first(); // leading connectors..
37976 while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
37977 nodes.splice(i, 1);
37978 if (index > i) index--;
37979 } // trailing connectors..
37982 i = nodes.length - 1;
37984 while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
37985 nodes.splice(i, 1);
37986 if (index > i) index--;
37987 i = nodes.length - 1;
37991 nodes.splice(index, 0, id);
37992 nodes = nodes.filter(noRepeatNodes); // If the way was closed before, append a connector node to keep it closed..
37994 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
37995 nodes.push(nodes[0]);
37998 return this.update({
38002 // Replaces the node which is currently at position index with the given node (id).
38003 // Consecutive duplicates are eliminated including existing ones.
38004 // Circularity is preserved when updating a node.
38005 updateNode: function updateNode(id, index) {
38006 var nodes = this.nodes.slice();
38007 var isClosed = this.isClosed();
38008 var max = nodes.length - 1;
38010 if (index === undefined || index < 0 || index > max) {
38011 throw new RangeError('index ' + index + ' out of range 0..' + max);
38012 } // If this is a closed way, remove all connector nodes except the first one
38013 // (there may be duplicates) and adjust index if necessary..
38017 var connector = this.first(); // leading connectors..
38021 while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
38022 nodes.splice(i, 1);
38023 if (index > i) index--;
38024 } // trailing connectors..
38027 i = nodes.length - 1;
38029 while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
38030 nodes.splice(i, 1);
38031 if (index === i) index = 0; // update leading connector instead
38033 i = nodes.length - 1;
38037 nodes.splice(index, 1, id);
38038 nodes = nodes.filter(noRepeatNodes); // If the way was closed before, append a connector node to keep it closed..
38040 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
38041 nodes.push(nodes[0]);
38044 return this.update({
38048 // Replaces each occurrence of node id needle with replacement.
38049 // Consecutive duplicates are eliminated including existing ones.
38050 // Circularity is preserved.
38051 replaceNode: function replaceNode(needleID, replacementID) {
38052 var nodes = this.nodes.slice();
38053 var isClosed = this.isClosed();
38055 for (var i = 0; i < nodes.length; i++) {
38056 if (nodes[i] === needleID) {
38057 nodes[i] = replacementID;
38061 nodes = nodes.filter(noRepeatNodes); // If the way was closed before, append a connector node to keep it closed..
38063 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
38064 nodes.push(nodes[0]);
38067 return this.update({
38071 // Removes each occurrence of node id.
38072 // Consecutive duplicates are eliminated including existing ones.
38073 // Circularity is preserved.
38074 removeNode: function removeNode(id) {
38075 var nodes = this.nodes.slice();
38076 var isClosed = this.isClosed();
38077 nodes = nodes.filter(function (node) {
38078 return node !== id;
38079 }).filter(noRepeatNodes); // If the way was closed before, append a connector node to keep it closed..
38081 if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
38082 nodes.push(nodes[0]);
38085 return this.update({
38089 asJXON: function asJXON(changeset_id) {
38092 '@id': this.osmId(),
38093 '@version': this.version || 0,
38094 nd: this.nodes.map(function (id) {
38097 ref: osmEntity.id.toOSM(id)
38101 tag: Object.keys(this.tags).map(function (k) {
38112 if (changeset_id) {
38113 r.way['@changeset'] = changeset_id;
38118 asGeoJSON: function asGeoJSON(resolver) {
38119 return resolver["transient"](this, 'GeoJSON', function () {
38120 var coordinates = resolver.childNodes(this).map(function (n) {
38124 if (this.isArea() && this.isClosed()) {
38127 coordinates: [coordinates]
38131 type: 'LineString',
38132 coordinates: coordinates
38137 area: function area(resolver) {
38138 return resolver["transient"](this, 'area', function () {
38139 var nodes = resolver.childNodes(this);
38142 coordinates: [nodes.map(function (n) {
38147 if (!this.isClosed() && nodes.length) {
38148 json.coordinates[0].push(nodes[0].loc);
38151 var area = d3_geoArea(json); // Heuristic for detecting counterclockwise winding order. Assumes
38152 // that OpenStreetMap polygons are not hemisphere-spanning.
38154 if (area > 2 * Math.PI) {
38155 json.coordinates[0] = json.coordinates[0].reverse();
38156 area = d3_geoArea(json);
38159 return isNaN(area) ? 0 : area;
38162 }); // Filter function to eliminate consecutive duplicates.
38164 function noRepeatNodes(node, i, arr) {
38165 return i === 0 || node !== arr[i - 1];
38169 // 1. Relation tagged with `type=multipolygon` and no interesting tags.
38170 // 2. One and only one member with the `outer` role. Must be a way with interesting tags.
38171 // 3. No members without a role.
38173 // Old multipolygons are no longer recommended but are still rendered as areas by iD.
38175 function osmOldMultipolygonOuterMemberOfRelation(entity, graph) {
38176 if (entity.type !== 'relation' || !entity.isMultipolygon() || Object.keys(entity.tags).filter(osmIsInterestingTag).length > 1) {
38182 for (var memberIndex in entity.members) {
38183 var member = entity.members[memberIndex];
38185 if (!member.role || member.role === 'outer') {
38186 if (outerMember) return false;
38187 if (member.type !== 'way') return false;
38188 if (!graph.hasEntity(member.id)) return false;
38189 outerMember = graph.entity(member.id);
38191 if (Object.keys(outerMember.tags).filter(osmIsInterestingTag).length === 0) {
38197 return outerMember;
38198 } // For fixing up rendering of multipolygons with tags on the outer member.
38199 // https://github.com/openstreetmap/iD/issues/613
38201 function osmIsOldMultipolygonOuterMember(entity, graph) {
38202 if (entity.type !== 'way' || Object.keys(entity.tags).filter(osmIsInterestingTag).length === 0) {
38206 var parents = graph.parentRelations(entity);
38207 if (parents.length !== 1) return false;
38208 var parent = parents[0];
38210 if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) {
38214 var members = parent.members,
38217 for (var i = 0; i < members.length; i++) {
38218 member = members[i];
38220 if (member.id === entity.id && member.role && member.role !== 'outer') {
38221 // Not outer member
38225 if (member.id !== entity.id && (!member.role || member.role === 'outer')) {
38226 // Not a simple multipolygon
38233 function osmOldMultipolygonOuterMember(entity, graph) {
38234 if (entity.type !== 'way') return false;
38235 var parents = graph.parentRelations(entity);
38236 if (parents.length !== 1) return false;
38237 var parent = parents[0];
38239 if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) {
38243 var members = parent.members,
38247 for (var i = 0; i < members.length; i++) {
38248 member = members[i];
38250 if (!member.role || member.role === 'outer') {
38251 if (outerMember) return false; // Not a simple multipolygon
38253 outerMember = member;
38257 if (!outerMember) return false;
38258 var outerEntity = graph.hasEntity(outerMember.id);
38260 if (!outerEntity || !Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length) {
38264 return outerEntity;
38265 } // Join `toJoin` array into sequences of connecting ways.
38266 // Segments which share identical start/end nodes will, as much as possible,
38267 // be connected with each other.
38269 // The return value is a nested array. Each constituent array contains elements
38270 // of `toJoin` which have been determined to connect.
38272 // Each consitituent array also has a `nodes` property whose value is an
38273 // ordered array of member nodes, with appropriate order reversal and
38274 // start/end coordinate de-duplication.
38276 // Members of `toJoin` must have, at minimum, `type` and `id` properties.
38277 // Thus either an array of `osmWay`s or a relation member array may be used.
38279 // If an member is an `osmWay`, its tags and childnodes may be reversed via
38280 // `actionReverse` in the output.
38282 // The returned sequences array also has an `actions` array property, containing
38283 // any reversal actions that should be applied to the graph, should the calling
38284 // code attempt to actually join the given ways.
38286 // Incomplete members (those for which `graph.hasEntity(element.id)` returns
38287 // false) and non-way members are ignored.
38290 function osmJoinWays(toJoin, graph) {
38291 function resolve(member) {
38292 return graph.childNodes(graph.entity(member.id));
38295 function reverse(item) {
38296 var action = actionReverse(item.id, {
38297 reverseOneway: true
38299 sequences.actions.push(action);
38300 return item instanceof osmWay ? action(graph).entity(item.id) : item;
38301 } // make a copy containing only the items to join
38304 toJoin = toJoin.filter(function (member) {
38305 return member.type === 'way' && graph.hasEntity(member.id);
38306 }); // Are the things we are joining relation members or `osmWays`?
38307 // If `osmWays`, skip the "prefer a forward path" code below (see #4872)
38310 var joinAsMembers = true;
38312 for (i = 0; i < toJoin.length; i++) {
38313 if (toJoin[i] instanceof osmWay) {
38314 joinAsMembers = false;
38319 var sequences = [];
38320 sequences.actions = [];
38322 while (toJoin.length) {
38323 // start a new sequence
38324 var item = toJoin.shift();
38325 var currWays = [item];
38326 var currNodes = resolve(item).slice(); // add to it
38328 while (toJoin.length) {
38329 var start = currNodes[0];
38330 var end = currNodes[currNodes.length - 1];
38332 var nodes = null; // Find the next way/member to join.
38334 for (i = 0; i < toJoin.length; i++) {
38336 nodes = resolve(item); // (for member ordering only, not way ordering - see #4872)
38337 // Strongly prefer to generate a forward path that preserves the order
38338 // of the members array. For multipolygons and most relations, member
38339 // order does not matter - but for routes, it does. (see #4589)
38340 // If we started this sequence backwards (i.e. next member way attaches to
38341 // the start node and not the end node), reverse the initial way before continuing.
38343 if (joinAsMembers && currWays.length === 1 && nodes[0] !== end && nodes[nodes.length - 1] !== end && (nodes[nodes.length - 1] === start || nodes[0] === start)) {
38344 currWays[0] = reverse(currWays[0]);
38345 currNodes.reverse();
38346 start = currNodes[0];
38347 end = currNodes[currNodes.length - 1];
38350 if (nodes[0] === end) {
38351 fn = currNodes.push; // join to end
38353 nodes = nodes.slice(1);
38355 } else if (nodes[nodes.length - 1] === end) {
38356 fn = currNodes.push; // join to end
38358 nodes = nodes.slice(0, -1).reverse();
38359 item = reverse(item);
38361 } else if (nodes[nodes.length - 1] === start) {
38362 fn = currNodes.unshift; // join to beginning
38364 nodes = nodes.slice(0, -1);
38366 } else if (nodes[0] === start) {
38367 fn = currNodes.unshift; // join to beginning
38369 nodes = nodes.slice(1).reverse();
38370 item = reverse(item);
38378 // couldn't find a joinable way/member
38382 fn.apply(currWays, [item]);
38383 fn.apply(currNodes, nodes);
38384 toJoin.splice(i, 1);
38387 currWays.nodes = currNodes;
38388 sequences.push(currWays);
38394 function actionAddMember(relationId, member, memberIndex, insertPair) {
38395 return function action(graph) {
38396 var relation = graph.entity(relationId); // There are some special rules for Public Transport v2 routes.
38398 var isPTv2 = /stop|platform/.test(member.role);
38400 if ((isNaN(memberIndex) || insertPair) && member.type === 'way' && !isPTv2) {
38401 // Try to perform sensible inserts based on how the ways join together
38402 graph = addWayMember(relation, graph);
38404 // see https://wiki.openstreetmap.org/wiki/Public_transport#Service_routes
38405 // Stops and Platforms for PTv2 should be ordered first.
38406 // hack: We do not currently have the ability to place them in the exactly correct order.
38407 if (isPTv2 && isNaN(memberIndex)) {
38411 graph = graph.replace(relation.addMember(member, memberIndex));
38415 }; // Add a way member into the relation "wherever it makes sense".
38416 // In this situation we were not supplied a memberIndex.
38418 function addWayMember(relation, graph) {
38419 var groups, tempWay, insertPairIsReversed, item, i, j, k; // remove PTv2 stops and platforms before doing anything.
38421 var PTv2members = [];
38424 for (i = 0; i < relation.members.length; i++) {
38425 var m = relation.members[i];
38427 if (/stop|platform/.test(m.role)) {
38428 PTv2members.push(m);
38434 relation = relation.update({
38439 // We're adding a member that must stay paired with an existing member.
38440 // (This feature is used by `actionSplit`)
38442 // This is tricky because the members may exist multiple times in the
38443 // member list, and with different A-B/B-A ordering and different roles.
38444 // (e.g. a bus route that loops out and back - #4589).
38446 // Replace the existing member with a temporary way,
38447 // so that `osmJoinWays` can treat the pair like a single way.
38450 nodes: insertPair.nodes
38452 graph = graph.replace(tempWay);
38458 var tempRelation = relation.replaceMember({
38459 id: insertPair.originalID
38460 }, tempMember, true);
38461 groups = utilArrayGroupBy(tempRelation.members, 'type');
38462 groups.way = groups.way || []; // Insert pair is reversed if the inserted way comes before the original one.
38463 // (Except when they form a loop.)
38465 var originalWay = graph.entity(insertPair.originalID);
38466 var insertedWay = graph.entity(insertPair.insertedID);
38467 insertPairIsReversed = originalWay.nodes.length > 0 && insertedWay.nodes.length > 0 && insertedWay.nodes[insertedWay.nodes.length - 1] === originalWay.nodes[0] && originalWay.nodes[originalWay.nodes.length - 1] !== insertedWay.nodes[0];
38469 // Add the member anywhere, one time. Just push and let `osmJoinWays` decide where to put it.
38470 groups = utilArrayGroupBy(relation.members, 'type');
38471 groups.way = groups.way || [];
38472 groups.way.push(member);
38475 members = withIndex(groups.way);
38476 var joined = osmJoinWays(members, graph); // `joined` might not contain all of the way members,
38477 // But will contain only the completed (downloaded) members
38479 for (i = 0; i < joined.length; i++) {
38480 var segment = joined[i];
38481 var nodes = segment.nodes.slice();
38482 var startIndex = segment[0].index; // j = array index in `members` where this segment starts
38484 for (j = 0; j < members.length; j++) {
38485 if (members[j].index === startIndex) {
38488 } // k = each member in segment
38491 for (k = 0; k < segment.length; k++) {
38493 var way = graph.entity(item.id); // If this is a paired item, generate members in correct order and role
38495 if (tempWay && item.id === tempWay.id) {
38496 var reverse = nodes[0].id !== insertPair.nodes[0] ^ insertPairIsReversed;
38500 id: insertPair.insertedID,
38504 id: insertPair.originalID,
38510 id: insertPair.originalID,
38514 id: insertPair.insertedID,
38519 } // reorder `members` if necessary
38523 if (j + k >= members.length || item.index !== members[j + k].index) {
38524 moveMember(members, item.index, j + k);
38528 nodes.splice(0, way.nodes.length - 1);
38533 graph = graph.remove(tempWay);
38534 } // Final pass: skip dead items, split pairs, remove index properties
38537 var wayMembers = [];
38539 for (i = 0; i < members.length; i++) {
38541 if (item.index === -1) continue;
38544 wayMembers.push(item.pair[0]);
38545 wayMembers.push(item.pair[1]);
38547 wayMembers.push(utilObjectOmit(item, ['index']));
38549 } // Put stops and platforms first, then nodes, ways, relations
38550 // This is recommended for Public Transport v2 routes:
38551 // see https://wiki.openstreetmap.org/wiki/Public_transport#Service_routes
38554 var newMembers = PTv2members.concat(groups.node || [], wayMembers, groups.relation || []);
38555 return graph.replace(relation.update({
38556 members: newMembers
38557 })); // `moveMember()` changes the `members` array in place by splicing
38558 // the item with `.index = findIndex` to where it belongs,
38559 // and marking the old position as "dead" with `.index = -1`
38563 // members 0 1 2 3 4 5 6 7 8 9 keep 5 in j+k
38567 // members 0 1 2 3 4 5 6 7 8 9 move 4 to j+k
38568 // members 0 1 2 3 x 5 4 6 7 8 9 moved
38572 // members 0 1 2 3 x 5 4 6 7 8 9 move 7 to j+k
38573 // members 0 1 2 3 x 5 4 7 6 x 8 9 moved
38577 // members 0 1 2 3 x 5 4 7 6 x 8 9 keep 6 in j+k
38580 function moveMember(arr, findIndex, toIndex) {
38583 for (i = 0; i < arr.length; i++) {
38584 if (arr[i].index === findIndex) {
38589 var item = Object.assign({}, arr[i]); // shallow copy
38591 arr[i].index = -1; // mark as dead
38593 item.index = toIndex;
38594 arr.splice(toIndex, 0, item);
38595 } // This is the same as `Relation.indexedMembers`,
38596 // Except we don't want to index all the members, only the ways
38599 function withIndex(arr) {
38600 var result = new Array(arr.length);
38602 for (var i = 0; i < arr.length; i++) {
38603 result[i] = Object.assign({}, arr[i]); // shallow copy
38605 result[i].index = i;
38613 function actionAddMidpoint(midpoint, node) {
38614 return function (graph) {
38615 graph = graph.replace(node.move(midpoint.loc));
38616 var parents = utilArrayIntersection(graph.parentWays(graph.entity(midpoint.edge[0])), graph.parentWays(graph.entity(midpoint.edge[1])));
38617 parents.forEach(function (way) {
38618 for (var i = 0; i < way.nodes.length - 1; i++) {
38619 if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
38620 graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1)); // Add only one midpoint on doubled-back segments,
38621 // turning them into self-intersections.
38631 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
38632 function actionAddVertex(wayId, nodeId, index) {
38633 return function (graph) {
38634 return graph.replace(graph.entity(wayId).addNode(nodeId, index));
38638 function actionChangeMember(relationId, member, memberIndex) {
38639 return function (graph) {
38640 return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
38644 function actionChangePreset(entityID, oldPreset, newPreset, skipFieldDefaults) {
38645 return function action(graph) {
38646 var entity = graph.entity(entityID);
38647 var geometry = entity.geometry(graph);
38648 var tags = entity.tags; // preserve tags that the new preset might care about, if any
38650 if (oldPreset) tags = oldPreset.unsetTags(tags, geometry, newPreset && newPreset.addTags ? Object.keys(newPreset.addTags) : null);
38651 if (newPreset) tags = newPreset.setTags(tags, geometry, skipFieldDefaults);
38652 return graph.replace(entity.update({
38658 function actionChangeTags(entityId, tags) {
38659 return function (graph) {
38660 var entity = graph.entity(entityId);
38661 return graph.replace(entity.update({
38667 function osmNode() {
38668 if (!(this instanceof osmNode)) {
38669 return new osmNode().initialize(arguments);
38670 } else if (arguments.length) {
38671 this.initialize(arguments);
38674 osmEntity.node = osmNode;
38675 osmNode.prototype = Object.create(osmEntity.prototype);
38676 Object.assign(osmNode.prototype, {
38679 extent: function extent() {
38680 return new geoExtent(this.loc);
38682 geometry: function geometry(graph) {
38683 return graph["transient"](this, 'geometry', function () {
38684 return graph.isPoi(this) ? 'point' : 'vertex';
38687 move: function move(loc) {
38688 return this.update({
38692 isDegenerate: function isDegenerate() {
38693 return !(Array.isArray(this.loc) && this.loc.length === 2 && this.loc[0] >= -180 && this.loc[0] <= 180 && this.loc[1] >= -90 && this.loc[1] <= 90);
38695 // Inspect tags and geometry to determine which direction(s) this node/vertex points
38696 directions: function directions(resolver, projection) {
38698 var i; // which tag to use?
38700 if (this.isHighwayIntersection(resolver) && (this.tags.stop || '').toLowerCase() === 'all') {
38701 // all-way stop tag on a highway intersection
38704 // generic direction tag
38705 val = (this.tags.direction || '').toLowerCase(); // better suffix-style direction tag
38707 var re = /:direction$/i;
38708 var keys = Object.keys(this.tags);
38710 for (i = 0; i < keys.length; i++) {
38711 if (re.test(keys[i])) {
38712 val = this.tags[keys[i]].toLowerCase();
38718 if (val === '') return [];
38722 northnortheast: 22,
38730 eastsoutheast: 112,
38734 southsoutheast: 157,
38738 southsouthwest: 202,
38742 westsouthwest: 247,
38746 westnorthwest: 292,
38750 northnorthwest: 337,
38753 var values = val.split(';');
38755 values.forEach(function (v) {
38756 // swap cardinal for numeric directions
38757 if (cardinal[v] !== undefined) {
38759 } // numeric direction - just add to results
38762 if (v !== '' && !isNaN(+v)) {
38765 } // string direction - inspect parent ways
38768 var lookBackward = this.tags['traffic_sign:backward'] || v === 'backward' || v === 'both' || v === 'all';
38769 var lookForward = this.tags['traffic_sign:forward'] || v === 'forward' || v === 'both' || v === 'all';
38770 if (!lookForward && !lookBackward) return;
38772 resolver.parentWays(this).forEach(function (parent) {
38773 var nodes = parent.nodes;
38775 for (i = 0; i < nodes.length; i++) {
38776 if (nodes[i] === this.id) {
38777 // match current entity
38778 if (lookForward && i > 0) {
38779 nodeIds[nodes[i - 1]] = true; // look back to prev node
38782 if (lookBackward && i < nodes.length - 1) {
38783 nodeIds[nodes[i + 1]] = true; // look ahead to next node
38788 Object.keys(nodeIds).forEach(function (nodeId) {
38789 // +90 because geoAngle returns angle from X axis, not Y (north)
38790 results.push(geoAngle(this, resolver.entity(nodeId), projection) * (180 / Math.PI) + 90);
38793 return utilArrayUniq(results);
38795 isCrossing: function isCrossing() {
38796 return this.tags.highway === 'crossing' || this.tags.railway && this.tags.railway.indexOf('crossing') !== -1;
38798 isEndpoint: function isEndpoint(resolver) {
38799 return resolver["transient"](this, 'isEndpoint', function () {
38801 return resolver.parentWays(this).filter(function (parent) {
38802 return !parent.isClosed() && !!parent.affix(id);
38806 isConnected: function isConnected(resolver) {
38807 return resolver["transient"](this, 'isConnected', function () {
38808 var parents = resolver.parentWays(this);
38810 if (parents.length > 1) {
38811 // vertex is connected to multiple parent ways
38812 for (var i in parents) {
38813 if (parents[i].geometry(resolver) === 'line' && parents[i].hasInterestingTags()) return true;
38815 } else if (parents.length === 1) {
38816 var way = parents[0];
38817 var nodes = way.nodes.slice();
38819 if (way.isClosed()) {
38821 } // ignore connecting node if closed
38822 // return true if vertex appears multiple times (way is self intersecting)
38825 return nodes.indexOf(this.id) !== nodes.lastIndexOf(this.id);
38831 parentIntersectionWays: function parentIntersectionWays(resolver) {
38832 return resolver["transient"](this, 'parentIntersectionWays', function () {
38833 return resolver.parentWays(this).filter(function (parent) {
38834 return (parent.tags.highway || parent.tags.waterway || parent.tags.railway || parent.tags.aeroway) && parent.geometry(resolver) === 'line';
38838 isIntersection: function isIntersection(resolver) {
38839 return this.parentIntersectionWays(resolver).length > 1;
38841 isHighwayIntersection: function isHighwayIntersection(resolver) {
38842 return resolver["transient"](this, 'isHighwayIntersection', function () {
38843 return resolver.parentWays(this).filter(function (parent) {
38844 return parent.tags.highway && parent.geometry(resolver) === 'line';
38848 isOnAddressLine: function isOnAddressLine(resolver) {
38849 return resolver["transient"](this, 'isOnAddressLine', function () {
38850 return resolver.parentWays(this).filter(function (parent) {
38851 return parent.tags.hasOwnProperty('addr:interpolation') && parent.geometry(resolver) === 'line';
38855 asJXON: function asJXON(changeset_id) {
38858 '@id': this.osmId(),
38859 '@lon': this.loc[0],
38860 '@lat': this.loc[1],
38861 '@version': this.version || 0,
38862 tag: Object.keys(this.tags).map(function (k) {
38872 if (changeset_id) r.node['@changeset'] = changeset_id;
38875 asGeoJSON: function asGeoJSON() {
38878 coordinates: this.loc
38883 function actionCircularize(wayId, projection, maxAngle) {
38884 maxAngle = (maxAngle || 20) * Math.PI / 180;
38886 var action = function action(graph, t) {
38887 if (t === null || !isFinite(t)) t = 1;
38888 t = Math.min(Math.max(+t, 0), 1);
38889 var way = graph.entity(wayId);
38890 var origNodes = {};
38891 graph.childNodes(way).forEach(function (node) {
38892 if (!origNodes[node.id]) origNodes[node.id] = node;
38895 if (!way.isConvex(graph)) {
38896 graph = action.makeConvex(graph);
38899 var nodes = utilArrayUniq(graph.childNodes(way));
38900 var keyNodes = nodes.filter(function (n) {
38901 return graph.parentWays(n).length !== 1;
38903 var points = nodes.map(function (n) {
38904 return projection(n.loc);
38906 var keyPoints = keyNodes.map(function (n) {
38907 return projection(n.loc);
38909 var centroid = points.length === 2 ? geoVecInterp(points[0], points[1], 0.5) : d3_polygonCentroid(points);
38910 var radius = d3_median(points, function (p) {
38911 return geoVecLength(centroid, p);
38913 var sign = d3_polygonArea(points) > 0 ? 1 : -1;
38914 var ids, i, j, k; // we need at least two key nodes for the algorithm to work
38916 if (!keyNodes.length) {
38917 keyNodes = [nodes[0]];
38918 keyPoints = [points[0]];
38921 if (keyNodes.length === 1) {
38922 var index = nodes.indexOf(keyNodes[0]);
38923 var oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
38924 keyNodes.push(nodes[oppositeIndex]);
38925 keyPoints.push(points[oppositeIndex]);
38926 } // key points and nodes are those connected to the ways,
38927 // they are projected onto the circle, in between nodes are moved
38928 // to constant intervals between key nodes, extra in between nodes are
38929 // added if necessary.
38932 for (i = 0; i < keyPoints.length; i++) {
38933 var nextKeyNodeIndex = (i + 1) % keyNodes.length;
38934 var startNode = keyNodes[i];
38935 var endNode = keyNodes[nextKeyNodeIndex];
38936 var startNodeIndex = nodes.indexOf(startNode);
38937 var endNodeIndex = nodes.indexOf(endNode);
38938 var numberNewPoints = -1;
38939 var indexRange = endNodeIndex - startNodeIndex;
38940 var nearNodes = {};
38941 var inBetweenNodes = [];
38942 var startAngle, endAngle, totalAngle, eachAngle;
38943 var angle, loc, node, origNode;
38945 if (indexRange < 0) {
38946 indexRange += nodes.length;
38947 } // position this key node
38950 var distance = geoVecLength(centroid, keyPoints[i]) || 1e-4;
38951 keyPoints[i] = [centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius, centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius];
38952 loc = projection.invert(keyPoints[i]);
38953 node = keyNodes[i];
38954 origNode = origNodes[node.id];
38955 node = node.move(geoVecInterp(origNode.loc, loc, t));
38956 graph = graph.replace(node); // figure out the between delta angle we want to match to
38958 startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
38959 endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
38960 totalAngle = endAngle - startAngle; // detects looping around -pi/pi
38962 if (totalAngle * sign > 0) {
38963 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
38968 eachAngle = totalAngle / (indexRange + numberNewPoints);
38969 } while (Math.abs(eachAngle) > maxAngle); // move existing nodes
38972 for (j = 1; j < indexRange; j++) {
38973 angle = startAngle + j * eachAngle;
38974 loc = projection.invert([centroid[0] + Math.cos(angle) * radius, centroid[1] + Math.sin(angle) * radius]);
38975 node = nodes[(j + startNodeIndex) % nodes.length];
38976 origNode = origNodes[node.id];
38977 nearNodes[node.id] = angle;
38978 node = node.move(geoVecInterp(origNode.loc, loc, t));
38979 graph = graph.replace(node);
38980 } // add new in between nodes if necessary
38983 for (j = 0; j < numberNewPoints; j++) {
38984 angle = startAngle + (indexRange + j) * eachAngle;
38985 loc = projection.invert([centroid[0] + Math.cos(angle) * radius, centroid[1] + Math.sin(angle) * radius]); // choose a nearnode to use as the original
38987 var min = Infinity;
38989 for (var nodeId in nearNodes) {
38990 var nearAngle = nearNodes[nodeId];
38991 var dist = Math.abs(nearAngle - angle);
38995 origNode = origNodes[nodeId];
39000 loc: geoVecInterp(origNode.loc, loc, t)
39002 graph = graph.replace(node);
39003 nodes.splice(endNodeIndex + j, 0, node);
39004 inBetweenNodes.push(node.id);
39005 } // Check for other ways that share these keyNodes..
39006 // If keyNodes are adjacent in both ways,
39007 // we can add inBetweenNodes to that shared way too..
39010 if (indexRange === 1 && inBetweenNodes.length) {
39011 var startIndex1 = way.nodes.lastIndexOf(startNode.id);
39012 var endIndex1 = way.nodes.lastIndexOf(endNode.id);
39013 var wayDirection1 = endIndex1 - startIndex1;
39015 if (wayDirection1 < -1) {
39019 var parentWays = graph.parentWays(keyNodes[i]);
39021 for (j = 0; j < parentWays.length; j++) {
39022 var sharedWay = parentWays[j];
39023 if (sharedWay === way) continue;
39025 if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
39026 var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id);
39027 var endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id);
39028 var wayDirection2 = endIndex2 - startIndex2;
39029 var insertAt = endIndex2;
39031 if (wayDirection2 < -1) {
39035 if (wayDirection1 !== wayDirection2) {
39036 inBetweenNodes.reverse();
39037 insertAt = startIndex2;
39040 for (k = 0; k < inBetweenNodes.length; k++) {
39041 sharedWay = sharedWay.addNode(inBetweenNodes[k], insertAt + k);
39044 graph = graph.replace(sharedWay);
39048 } // update the way to have all the new nodes
39051 ids = nodes.map(function (n) {
39058 graph = graph.replace(way);
39062 action.makeConvex = function (graph) {
39063 var way = graph.entity(wayId);
39064 var nodes = utilArrayUniq(graph.childNodes(way));
39065 var points = nodes.map(function (n) {
39066 return projection(n.loc);
39068 var sign = d3_polygonArea(points) > 0 ? 1 : -1;
39069 var hull = d3_polygonHull(points);
39070 var i, j; // D3 convex hulls go counterclockwise..
39077 for (i = 0; i < hull.length - 1; i++) {
39078 var startIndex = points.indexOf(hull[i]);
39079 var endIndex = points.indexOf(hull[i + 1]);
39080 var indexRange = endIndex - startIndex;
39082 if (indexRange < 0) {
39083 indexRange += nodes.length;
39084 } // move interior nodes to the surface of the convex hull..
39087 for (j = 1; j < indexRange; j++) {
39088 var point = geoVecInterp(hull[i], hull[i + 1], j / indexRange);
39089 var node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
39090 graph = graph.replace(node);
39097 action.disabled = function (graph) {
39098 if (!graph.entity(wayId).isClosed()) {
39099 return 'not_closed';
39100 } //disable when already circular
39103 var way = graph.entity(wayId);
39104 var nodes = utilArrayUniq(graph.childNodes(way));
39105 var points = nodes.map(function (n) {
39106 return projection(n.loc);
39108 var hull = d3_polygonHull(points);
39109 var epsilonAngle = Math.PI / 180;
39111 if (hull.length !== points.length || hull.length < 3) {
39115 var centroid = d3_polygonCentroid(points);
39116 var radius = geoVecLengthSquare(centroid, points[0]);
39117 var i, actualPoint; // compare distances between centroid and points
39119 for (i = 0; i < hull.length; i++) {
39120 actualPoint = hull[i];
39121 var actualDist = geoVecLengthSquare(actualPoint, centroid);
39122 var diff = Math.abs(actualDist - radius); //compare distances with epsilon-error (5%)
39124 if (diff > 0.05 * radius) {
39127 } //check if central angles are smaller than maxAngle
39130 for (i = 0; i < hull.length; i++) {
39131 actualPoint = hull[i];
39132 var nextPoint = hull[(i + 1) % hull.length];
39133 var startAngle = Math.atan2(actualPoint[1] - centroid[1], actualPoint[0] - centroid[0]);
39134 var endAngle = Math.atan2(nextPoint[1] - centroid[1], nextPoint[0] - centroid[0]);
39135 var angle = endAngle - startAngle;
39141 if (angle > Math.PI) {
39142 angle = 2 * Math.PI - angle;
39145 if (angle > maxAngle + epsilonAngle) {
39150 return 'already_circular';
39153 action.transitionable = true;
39157 function actionDeleteWay(wayID) {
39158 function canDeleteNode(node, graph) {
39159 // don't delete nodes still attached to ways or relations
39160 if (graph.parentWays(node).length || graph.parentRelations(node).length) return false;
39161 var geometries = osmNodeGeometriesForTags(node.tags); // don't delete if this node can be a standalone point
39163 if (geometries.point) return false; // delete if this node only be a vertex
39165 if (geometries.vertex) return true; // iD doesn't know if this should be a point or vertex,
39166 // so only delete if there are no interesting tags
39168 return !node.hasInterestingTags();
39171 var action = function action(graph) {
39172 var way = graph.entity(wayID);
39173 graph.parentRelations(way).forEach(function (parent) {
39174 parent = parent.removeMembersWithID(wayID);
39175 graph = graph.replace(parent);
39177 if (parent.isDegenerate()) {
39178 graph = actionDeleteRelation(parent.id)(graph);
39181 new Set(way.nodes).forEach(function (nodeID) {
39182 graph = graph.replace(way.removeNode(nodeID));
39183 var node = graph.entity(nodeID);
39185 if (canDeleteNode(node, graph)) {
39186 graph = graph.remove(node);
39189 return graph.remove(way);
39195 function actionDeleteMultiple(ids) {
39197 way: actionDeleteWay,
39198 node: actionDeleteNode,
39199 relation: actionDeleteRelation
39202 var action = function action(graph) {
39203 ids.forEach(function (id) {
39204 if (graph.hasEntity(id)) {
39205 // It may have been deleted already.
39206 graph = actions[graph.entity(id).type](id)(graph);
39215 function actionDeleteRelation(relationID, allowUntaggedMembers) {
39216 function canDeleteEntity(entity, graph) {
39217 return !graph.parentWays(entity).length && !graph.parentRelations(entity).length && !entity.hasInterestingTags() && !allowUntaggedMembers;
39220 var action = function action(graph) {
39221 var relation = graph.entity(relationID);
39222 graph.parentRelations(relation).forEach(function (parent) {
39223 parent = parent.removeMembersWithID(relationID);
39224 graph = graph.replace(parent);
39226 if (parent.isDegenerate()) {
39227 graph = actionDeleteRelation(parent.id)(graph);
39230 var memberIDs = utilArrayUniq(relation.members.map(function (m) {
39233 memberIDs.forEach(function (memberID) {
39234 graph = graph.replace(relation.removeMembersWithID(memberID));
39235 var entity = graph.entity(memberID);
39237 if (canDeleteEntity(entity, graph)) {
39238 graph = actionDeleteMultiple([memberID])(graph);
39241 return graph.remove(relation);
39247 function actionDeleteNode(nodeId) {
39248 var action = function action(graph) {
39249 var node = graph.entity(nodeId);
39250 graph.parentWays(node).forEach(function (parent) {
39251 parent = parent.removeNode(nodeId);
39252 graph = graph.replace(parent);
39254 if (parent.isDegenerate()) {
39255 graph = actionDeleteWay(parent.id)(graph);
39258 graph.parentRelations(node).forEach(function (parent) {
39259 parent = parent.removeMembersWithID(nodeId);
39260 graph = graph.replace(parent);
39262 if (parent.isDegenerate()) {
39263 graph = actionDeleteRelation(parent.id)(graph);
39266 return graph.remove(node);
39273 // First choose a node to be the survivor, with preference given
39274 // to the oldest existing (not new) and "interesting" node.
39276 // Tags and relation memberships of of non-surviving nodes are merged
39277 // to the survivor.
39279 // This is the inverse of `iD.actionDisconnect`.
39282 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
39283 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
39286 function actionConnect(nodeIDs) {
39287 var action = function action(graph) {
39291 var i, j; // Select the node with the ID passed as parameter if it is in the list,
39292 // otherwise select the node with the oldest ID as the survivor, or the
39293 // last one if there are only new nodes.
39296 var interestingIDs = [];
39298 for (i = 0; i < nodeIDs.length; i++) {
39299 node = graph.entity(nodeIDs[i]);
39301 if (node.hasInterestingTags()) {
39302 if (!node.isNew()) {
39303 interestingIDs.push(node.id);
39308 survivor = graph.entity(utilOldestID(interestingIDs.length > 0 ? interestingIDs : nodeIDs)); // Replace all non-surviving nodes with the survivor and merge tags.
39310 for (i = 0; i < nodeIDs.length; i++) {
39311 node = graph.entity(nodeIDs[i]);
39312 if (node.id === survivor.id) continue;
39313 parents = graph.parentWays(node);
39315 for (j = 0; j < parents.length; j++) {
39316 graph = graph.replace(parents[j].replaceNode(node.id, survivor.id));
39319 parents = graph.parentRelations(node);
39321 for (j = 0; j < parents.length; j++) {
39322 graph = graph.replace(parents[j].replaceMember(node, survivor));
39325 survivor = survivor.mergeTags(node.tags);
39326 graph = actionDeleteNode(node.id)(graph);
39329 graph = graph.replace(survivor); // find and delete any degenerate ways created by connecting adjacent vertices
39331 parents = graph.parentWays(survivor);
39333 for (i = 0; i < parents.length; i++) {
39334 if (parents[i].isDegenerate()) {
39335 graph = actionDeleteWay(parents[i].id)(graph);
39342 action.disabled = function (graph) {
39344 var restrictionIDs = [];
39347 var relations, relation, role;
39348 var i, j, k; // Select the node with the oldest ID as the survivor.
39350 survivor = graph.entity(utilOldestID(nodeIDs)); // 1. disable if the nodes being connected have conflicting relation roles
39352 for (i = 0; i < nodeIDs.length; i++) {
39353 node = graph.entity(nodeIDs[i]);
39354 relations = graph.parentRelations(node);
39356 for (j = 0; j < relations.length; j++) {
39357 relation = relations[j];
39358 role = relation.memberById(node.id).role || ''; // if this node is a via node in a restriction, remember for later
39360 if (relation.hasFromViaTo()) {
39361 restrictionIDs.push(relation.id);
39364 if (seen[relation.id] !== undefined && seen[relation.id] !== role) {
39367 seen[relation.id] = role;
39370 } // gather restrictions for parent ways
39373 for (i = 0; i < nodeIDs.length; i++) {
39374 node = graph.entity(nodeIDs[i]);
39375 var parents = graph.parentWays(node);
39377 for (j = 0; j < parents.length; j++) {
39378 var parent = parents[j];
39379 relations = graph.parentRelations(parent);
39381 for (k = 0; k < relations.length; k++) {
39382 relation = relations[k];
39384 if (relation.hasFromViaTo()) {
39385 restrictionIDs.push(relation.id);
39389 } // test restrictions
39392 restrictionIDs = utilArrayUniq(restrictionIDs);
39394 for (i = 0; i < restrictionIDs.length; i++) {
39395 relation = graph.entity(restrictionIDs[i]);
39396 if (!relation.isComplete(graph)) continue;
39397 var memberWays = relation.members.filter(function (m) {
39398 return m.type === 'way';
39399 }).map(function (m) {
39400 return graph.entity(m.id);
39402 memberWays = utilArrayUniq(memberWays);
39403 var f = relation.memberByRole('from');
39404 var t = relation.memberByRole('to');
39405 var isUturn = f.id === t.id; // 2a. disable if connection would damage a restriction
39406 // (a key node is a node at the junction of ways)
39416 for (j = 0; j < relation.members.length; j++) {
39417 collectNodes(relation.members[j], nodes);
39420 nodes.keyfrom = utilArrayUniq(nodes.keyfrom.filter(hasDuplicates));
39421 nodes.keyto = utilArrayUniq(nodes.keyto.filter(hasDuplicates));
39422 var filter = keyNodeFilter(nodes.keyfrom, nodes.keyto);
39423 nodes.from = nodes.from.filter(filter);
39424 nodes.via = nodes.via.filter(filter);
39425 nodes.to = nodes.to.filter(filter);
39426 var connectFrom = false;
39427 var connectVia = false;
39428 var connectTo = false;
39429 var connectKeyFrom = false;
39430 var connectKeyTo = false;
39432 for (j = 0; j < nodeIDs.length; j++) {
39433 var n = nodeIDs[j];
39435 if (nodes.from.indexOf(n) !== -1) {
39436 connectFrom = true;
39439 if (nodes.via.indexOf(n) !== -1) {
39443 if (nodes.to.indexOf(n) !== -1) {
39447 if (nodes.keyfrom.indexOf(n) !== -1) {
39448 connectKeyFrom = true;
39451 if (nodes.keyto.indexOf(n) !== -1) {
39452 connectKeyTo = true;
39456 if (connectFrom && connectTo && !isUturn) {
39457 return 'restriction';
39460 if (connectFrom && connectVia) {
39461 return 'restriction';
39464 if (connectTo && connectVia) {
39465 return 'restriction';
39466 } // connecting to a key node -
39467 // if both nodes are on a member way (i.e. part of the turn restriction),
39468 // the connecting node must be adjacent to the key node.
39471 if (connectKeyFrom || connectKeyTo) {
39472 if (nodeIDs.length !== 2) {
39473 return 'restriction';
39479 for (j = 0; j < memberWays.length; j++) {
39480 way = memberWays[j];
39482 if (way.contains(nodeIDs[0])) {
39486 if (way.contains(nodeIDs[1])) {
39492 // both nodes are part of the restriction
39495 for (j = 0; j < memberWays.length; j++) {
39496 way = memberWays[j];
39498 if (way.areAdjacent(n0, n1)) {
39505 return 'restriction';
39508 } // 2b. disable if nodes being connected will destroy a member way in a restriction
39509 // (to test, make a copy and try actually connecting the nodes)
39512 for (j = 0; j < memberWays.length; j++) {
39513 way = memberWays[j].update({}); // make copy
39515 for (k = 0; k < nodeIDs.length; k++) {
39516 if (nodeIDs[k] === survivor.id) continue;
39518 if (way.areAdjacent(nodeIDs[k], survivor.id)) {
39519 way = way.removeNode(nodeIDs[k]);
39521 way = way.replaceNode(nodeIDs[k], survivor.id);
39525 if (way.isDegenerate()) {
39526 return 'restriction';
39531 return false; // if a key node appears multiple times (indexOf !== lastIndexOf) it's a FROM-VIA or TO-VIA junction
39533 function hasDuplicates(n, i, arr) {
39534 return arr.indexOf(n) !== arr.lastIndexOf(n);
39537 function keyNodeFilter(froms, tos) {
39538 return function (n) {
39539 return froms.indexOf(n) === -1 && tos.indexOf(n) === -1;
39543 function collectNodes(member, collection) {
39544 var entity = graph.hasEntity(member.id);
39545 if (!entity) return;
39546 var role = member.role || '';
39548 if (!collection[role]) {
39549 collection[role] = [];
39552 if (member.type === 'node') {
39553 collection[role].push(member.id);
39555 if (role === 'via') {
39556 collection.keyfrom.push(member.id);
39557 collection.keyto.push(member.id);
39559 } else if (member.type === 'way') {
39560 collection[role].push.apply(collection[role], entity.nodes);
39562 if (role === 'from' || role === 'via') {
39563 collection.keyfrom.push(entity.first());
39564 collection.keyfrom.push(entity.last());
39567 if (role === 'to' || role === 'via') {
39568 collection.keyto.push(entity.first());
39569 collection.keyto.push(entity.last());
39578 function actionCopyEntities(ids, fromGraph) {
39581 var action = function action(graph) {
39582 ids.forEach(function (id) {
39583 fromGraph.entity(id).copy(fromGraph, _copies);
39586 for (var id in _copies) {
39587 graph = graph.replace(_copies[id]);
39593 action.copies = function () {
39600 function actionDeleteMember(relationId, memberIndex) {
39601 return function (graph) {
39602 var relation = graph.entity(relationId).removeMember(memberIndex);
39603 graph = graph.replace(relation);
39605 if (relation.isDegenerate()) {
39606 graph = actionDeleteRelation(relation.id)(graph);
39613 function actionDiscardTags(difference, discardTags) {
39614 discardTags = discardTags || {};
39615 return function (graph) {
39616 difference.modified().forEach(checkTags);
39617 difference.created().forEach(checkTags);
39620 function checkTags(entity) {
39621 var keys = Object.keys(entity.tags);
39622 var didDiscard = false;
39625 for (var i = 0; i < keys.length; i++) {
39628 if (discardTags[k] || !entity.tags[k]) {
39631 tags[k] = entity.tags[k];
39636 graph = graph.replace(entity.update({
39645 // Optionally, disconnect only the given ways.
39647 // For testing convenience, accepts an ID to assign to the (first) new node.
39648 // Normally, this will be undefined and the way will automatically
39649 // be assigned a new ID.
39651 // This is the inverse of `iD.actionConnect`.
39654 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
39655 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
39658 function actionDisconnect(nodeId, newNodeId) {
39660 var disconnectableRelationTypes = {
39661 'associatedStreet': true,
39662 'enforcement': true,
39666 var action = function action(graph) {
39667 var node = graph.entity(nodeId);
39668 var connections = action.connections(graph);
39669 connections.forEach(function (connection) {
39670 var way = graph.entity(connection.wayID);
39671 var newNode = osmNode({
39676 graph = graph.replace(newNode);
39678 if (connection.index === 0 && way.isArea()) {
39679 // replace shared node with shared node..
39680 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
39681 } else if (way.isClosed() && connection.index === way.nodes.length - 1) {
39682 // replace closing node with new new node..
39683 graph = graph.replace(way.unclose().addNode(newNode.id));
39685 // replace shared node with multiple new nodes..
39686 graph = graph.replace(way.updateNode(newNode.id, connection.index));
39692 action.connections = function (graph) {
39693 var candidates = [];
39694 var keeping = false;
39695 var parentWays = graph.parentWays(graph.entity(nodeId));
39698 for (var i = 0; i < parentWays.length; i++) {
39699 way = parentWays[i];
39701 if (wayIds && wayIds.indexOf(way.id) === -1) {
39706 if (way.isArea() && way.nodes[0] === nodeId) {
39712 for (var j = 0; j < way.nodes.length; j++) {
39713 waynode = way.nodes[j];
39715 if (waynode === nodeId) {
39716 if (way.isClosed() && parentWays.length > 1 && wayIds && wayIds.indexOf(way.id) !== -1 && j === way.nodes.length - 1) {
39729 return keeping ? candidates : candidates.slice(1);
39732 action.disabled = function (graph) {
39733 var connections = action.connections(graph);
39734 if (connections.length === 0) return 'not_connected';
39735 var parentWays = graph.parentWays(graph.entity(nodeId));
39736 var seenRelationIds = {};
39737 var sharedRelation;
39738 parentWays.forEach(function (way) {
39739 var relations = graph.parentRelations(way);
39740 relations.filter(function (relation) {
39741 return !disconnectableRelationTypes[relation.tags.type];
39742 }).forEach(function (relation) {
39743 if (relation.id in seenRelationIds) {
39745 if (wayIds.indexOf(way.id) !== -1 || wayIds.indexOf(seenRelationIds[relation.id]) !== -1) {
39746 sharedRelation = relation;
39749 sharedRelation = relation;
39752 seenRelationIds[relation.id] = way.id;
39756 if (sharedRelation) return 'relation';
39759 action.limitWays = function (val) {
39760 if (!arguments.length) return wayIds;
39768 function actionExtract(entityID, projection) {
39769 var extractedNodeID;
39771 var action = function action(graph) {
39772 var entity = graph.entity(entityID);
39774 if (entity.type === 'node') {
39775 return extractFromNode(entity, graph);
39778 return extractFromWayOrRelation(entity, graph);
39781 function extractFromNode(node, graph) {
39782 extractedNodeID = node.id; // Create a new node to replace the one we will detach
39784 var replacement = osmNode({
39787 graph = graph.replace(replacement); // Process each way in turn, updating the graph as we go
39789 graph = graph.parentWays(node).reduce(function (accGraph, parentWay) {
39790 return accGraph.replace(parentWay.replaceNode(entityID, replacement.id));
39791 }, graph); // Process any relations too
39793 return graph.parentRelations(node).reduce(function (accGraph, parentRel) {
39794 return accGraph.replace(parentRel.replaceMember(node, replacement));
39798 function extractFromWayOrRelation(entity, graph) {
39799 var fromGeometry = entity.geometry(graph);
39800 var keysToCopyAndRetain = ['source', 'wheelchair'];
39801 var keysToRetain = ['area'];
39802 var buildingKeysToRetain = ['architect', 'building', 'height', 'layer'];
39803 var extractedLoc = d3_geoPath(projection).centroid(entity.asGeoJSON(graph));
39804 extractedLoc = extractedLoc && projection.invert(extractedLoc);
39806 if (!extractedLoc || !isFinite(extractedLoc[0]) || !isFinite(extractedLoc[1])) {
39807 extractedLoc = entity.extent(graph).center();
39810 var indoorAreaValues = {
39817 var isBuilding = entity.tags.building && entity.tags.building !== 'no' || entity.tags['building:part'] && entity.tags['building:part'] !== 'no';
39818 var isIndoorArea = fromGeometry === 'area' && entity.tags.indoor && indoorAreaValues[entity.tags.indoor];
39819 var entityTags = Object.assign({}, entity.tags); // shallow copy
39821 var pointTags = {};
39823 for (var key in entityTags) {
39824 if (entity.type === 'relation' && key === 'type') {
39828 if (keysToRetain.indexOf(key) !== -1) {
39833 // don't transfer building-related tags
39834 if (buildingKeysToRetain.indexOf(key) !== -1 || key.match(/^building:.{1,}/) || key.match(/^roof:.{1,}/)) continue;
39835 } // leave `indoor` tag on the area
39838 if (isIndoorArea && key === 'indoor') {
39840 } // copy the tag from the entity to the point
39843 pointTags[key] = entityTags[key]; // leave addresses and some other tags so they're on both features
39845 if (keysToCopyAndRetain.indexOf(key) !== -1 || key.match(/^addr:.{1,}/)) {
39847 } else if (isIndoorArea && key === 'level') {
39848 // leave `level` on both features
39850 } // remove the tag from the entity
39853 delete entityTags[key];
39856 if (!isBuilding && !isIndoorArea && fromGeometry === 'area') {
39857 // ensure that areas keep area geometry
39858 entityTags.area = 'yes';
39861 var replacement = osmNode({
39865 graph = graph.replace(replacement);
39866 extractedNodeID = replacement.id;
39867 return graph.replace(entity.update({
39872 action.getExtractedNodeID = function () {
39873 return extractedNodeID;
39880 // This is the inverse of `iD.actionSplit`.
39883 // https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
39884 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
39887 function actionJoin(ids) {
39888 function groupEntitiesByGeometry(graph) {
39889 var entities = ids.map(function (id) {
39890 return graph.entity(id);
39892 return Object.assign({
39894 }, utilArrayGroupBy(entities, function (entity) {
39895 return entity.geometry(graph);
39899 var action = function action(graph) {
39900 var ways = ids.map(graph.entity, graph); // Prefer to keep an existing way.
39901 // if there are multiple existing ways, keep the oldest one
39902 // the oldest way is determined by the ID of the way.
39904 var survivorID = utilOldestID(ways.map(function (way) {
39906 })); // if any of the ways are sided (e.g. coastline, cliff, kerb)
39907 // sort them first so they establish the overall order - #6033
39909 ways.sort(function (a, b) {
39910 var aSided = a.isSided();
39911 var bSided = b.isSided();
39912 return aSided && !bSided ? -1 : bSided && !aSided ? 1 : 0;
39914 var sequences = osmJoinWays(ways, graph);
39915 var joined = sequences[0]; // We might need to reverse some of these ways before joining them. #4688
39916 // `joined.actions` property will contain any actions we need to apply.
39918 graph = sequences.actions.reduce(function (g, action) {
39921 var survivor = graph.entity(survivorID);
39922 survivor = survivor.update({
39923 nodes: joined.nodes.map(function (n) {
39927 graph = graph.replace(survivor);
39928 joined.forEach(function (way) {
39929 if (way.id === survivorID) return;
39930 graph.parentRelations(way).forEach(function (parent) {
39931 graph = graph.replace(parent.replaceMember(way, survivor));
39933 survivor = survivor.mergeTags(way.tags);
39934 graph = graph.replace(survivor);
39935 graph = actionDeleteWay(way.id)(graph);
39936 }); // Finds if the join created a single-member multipolygon,
39937 // and if so turns it into a basic area instead
39939 function checkForSimpleMultipolygon() {
39940 if (!survivor.isClosed()) return;
39941 var multipolygons = graph.parentMultipolygons(survivor).filter(function (multipolygon) {
39942 // find multipolygons where the survivor is the only member
39943 return multipolygon.members.length === 1;
39944 }); // skip if this is the single member of multiple multipolygons
39946 if (multipolygons.length !== 1) return;
39947 var multipolygon = multipolygons[0];
39949 for (var key in survivor.tags) {
39950 if (multipolygon.tags[key] && // don't collapse if tags cannot be cleanly merged
39951 multipolygon.tags[key] !== survivor.tags[key]) return;
39954 survivor = survivor.mergeTags(multipolygon.tags);
39955 graph = graph.replace(survivor);
39956 graph = actionDeleteRelation(multipolygon.id, true
39957 /* allow untagged members */
39959 var tags = Object.assign({}, survivor.tags);
39961 if (survivor.geometry(graph) !== 'area') {
39962 // ensure the feature persists as an area
39966 delete tags.type; // remove type=multipolygon
39968 survivor = survivor.update({
39971 graph = graph.replace(survivor);
39974 checkForSimpleMultipolygon();
39976 }; // Returns the number of nodes the resultant way is expected to have
39979 action.resultingWayNodesLength = function (graph) {
39980 return ids.reduce(function (count, id) {
39981 return count + graph.entity(id).nodes.length;
39982 }, 0) - ids.length - 1;
39985 action.disabled = function (graph) {
39986 var geometries = groupEntitiesByGeometry(graph);
39988 if (ids.length < 2 || ids.length !== geometries.line.length) {
39989 return 'not_eligible';
39992 var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
39994 if (joined.length > 1) {
39995 return 'not_adjacent';
39998 var i; // All joined ways must belong to the same set of (non-restriction) relations.
39999 // Restriction relations have different logic, below, which allows some cases
40000 // this prohibits, and prohibits some cases this allows.
40002 var sortedParentRelations = function sortedParentRelations(id) {
40003 return graph.parentRelations(graph.entity(id)).filter(function (rel) {
40004 return !rel.isRestriction() && !rel.isConnectivity();
40005 }).sort(function (a, b) {
40006 return a.id - b.id;
40010 var relsA = sortedParentRelations(ids[0]);
40012 for (i = 1; i < ids.length; i++) {
40013 var relsB = sortedParentRelations(ids[i]);
40015 if (!utilArrayIdentical(relsA, relsB)) {
40016 return 'conflicting_relations';
40018 } // Loop through all combinations of path-pairs
40019 // to check potential intersections between all pairs
40022 for (i = 0; i < ids.length - 1; i++) {
40023 for (var j = i + 1; j < ids.length; j++) {
40024 var path1 = graph.childNodes(graph.entity(ids[i])).map(function (e) {
40027 var path2 = graph.childNodes(graph.entity(ids[j])).map(function (e) {
40030 var intersections = geoPathIntersections(path1, path2); // Check if intersections are just nodes lying on top of
40031 // each other/the line, as opposed to crossing it
40033 var common = utilArrayIntersection(joined[0].nodes.map(function (n) {
40034 return n.loc.toString();
40035 }), intersections.map(function (n) {
40036 return n.toString();
40039 if (common.length !== intersections.length) {
40040 return 'paths_intersect';
40045 var nodeIds = joined[0].nodes.map(function (n) {
40050 var conflicting = false;
40051 joined[0].forEach(function (way) {
40052 var parents = graph.parentRelations(way);
40053 parents.forEach(function (parent) {
40054 if ((parent.isRestriction() || parent.isConnectivity()) && parent.members.some(function (m) {
40055 return nodeIds.indexOf(m.id) >= 0;
40061 for (var k in way.tags) {
40062 if (!(k in tags)) {
40063 tags[k] = way.tags[k];
40064 } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
40065 conflicting = true;
40071 return relation.isRestriction() ? 'restriction' : 'connectivity';
40075 return 'conflicting_tags';
40082 function actionMerge(ids) {
40083 function groupEntitiesByGeometry(graph) {
40084 var entities = ids.map(function (id) {
40085 return graph.entity(id);
40087 return Object.assign({
40092 }, utilArrayGroupBy(entities, function (entity) {
40093 return entity.geometry(graph);
40097 var action = function action(graph) {
40098 var geometries = groupEntitiesByGeometry(graph);
40099 var target = geometries.area[0] || geometries.line[0];
40100 var points = geometries.point;
40101 points.forEach(function (point) {
40102 target = target.mergeTags(point.tags);
40103 graph = graph.replace(target);
40104 graph.parentRelations(point).forEach(function (parent) {
40105 graph = graph.replace(parent.replaceMember(point, target));
40107 var nodes = utilArrayUniq(graph.childNodes(target));
40108 var removeNode = point;
40110 if (!point.isNew()) {
40111 // Try to preserve the original point if it already has
40112 // an ID in the database.
40113 var inserted = false;
40115 var canBeReplaced = function canBeReplaced(node) {
40116 return !(graph.parentWays(node).length > 1 || graph.parentRelations(node).length);
40119 var replaceNode = function replaceNode(node) {
40120 graph = graph.replace(point.update({
40124 target = target.replaceNode(node.id, point.id);
40125 graph = graph.replace(target);
40131 var node; // First, try to replace a new child node on the target way.
40133 for (i = 0; i < nodes.length; i++) {
40136 if (canBeReplaced(node) && node.isNew()) {
40142 if (!inserted && point.hasInterestingTags()) {
40143 // No new child node found, try to find an existing, but
40144 // uninteresting child node instead.
40145 for (i = 0; i < nodes.length; i++) {
40148 if (canBeReplaced(node) && !node.hasInterestingTags()) {
40155 // Still not inserted, try to find an existing, interesting,
40156 // but more recent child node.
40157 for (i = 0; i < nodes.length; i++) {
40160 if (canBeReplaced(node) && utilCompareIDs(point.id, node.id) < 0) {
40165 } // If the point still hasn't been inserted, we give up.
40166 // There are more interesting or older nodes on the way.
40171 graph = graph.remove(removeNode);
40174 if (target.tags.area === 'yes') {
40175 var tags = Object.assign({}, target.tags); // shallow copy
40179 if (osmTagSuggestingArea(tags)) {
40180 // remove the `area` tag if area geometry is now implied - #3851
40181 target = target.update({
40184 graph = graph.replace(target);
40191 action.disabled = function (graph) {
40192 var geometries = groupEntitiesByGeometry(graph);
40194 if (geometries.point.length === 0 || geometries.area.length + geometries.line.length !== 1 || geometries.relation.length !== 0) {
40195 return 'not_eligible';
40203 // 1. move all the nodes to a common location
40204 // 2. `actionConnect` them
40206 function actionMergeNodes(nodeIDs, loc) {
40207 // If there is a single "interesting" node, use that as the location.
40208 // Otherwise return the average location of all the nodes.
40209 function chooseLoc(graph) {
40210 if (!nodeIDs.length) return null;
40212 var interestingCount = 0;
40213 var interestingLoc;
40215 for (var i = 0; i < nodeIDs.length; i++) {
40216 var node = graph.entity(nodeIDs[i]);
40218 if (node.hasInterestingTags()) {
40219 interestingLoc = ++interestingCount === 1 ? node.loc : null;
40222 sum = geoVecAdd(sum, node.loc);
40225 return interestingLoc || geoVecScale(sum, 1 / nodeIDs.length);
40228 var action = function action(graph) {
40229 if (nodeIDs.length < 2) return graph;
40233 toLoc = chooseLoc(graph);
40236 for (var i = 0; i < nodeIDs.length; i++) {
40237 var node = graph.entity(nodeIDs[i]);
40239 if (node.loc !== toLoc) {
40240 graph = graph.replace(node.move(toLoc));
40244 return actionConnect(nodeIDs)(graph);
40247 action.disabled = function (graph) {
40248 if (nodeIDs.length < 2) return 'not_eligible';
40250 for (var i = 0; i < nodeIDs.length; i++) {
40251 var entity = graph.entity(nodeIDs[i]);
40252 if (entity.type !== 'node') return 'not_eligible';
40255 return actionConnect(nodeIDs).disabled(graph);
40261 function osmChangeset() {
40262 if (!(this instanceof osmChangeset)) {
40263 return new osmChangeset().initialize(arguments);
40264 } else if (arguments.length) {
40265 this.initialize(arguments);
40268 osmEntity.changeset = osmChangeset;
40269 osmChangeset.prototype = Object.create(osmEntity.prototype);
40270 Object.assign(osmChangeset.prototype, {
40272 extent: function extent() {
40273 return new geoExtent();
40275 geometry: function geometry() {
40276 return 'changeset';
40278 asJXON: function asJXON() {
40282 tag: Object.keys(this.tags).map(function (k) {
40294 // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
40295 // XML. Returns a string.
40296 osmChangeJXON: function osmChangeJXON(changes) {
40297 var changeset_id = this.id;
40299 function nest(x, order) {
40302 for (var i = 0; i < x.length; i++) {
40303 var tagName = Object.keys(x[i])[0];
40304 if (!groups[tagName]) groups[tagName] = [];
40305 groups[tagName].push(x[i][tagName]);
40309 order.forEach(function (o) {
40310 if (groups[o]) ordered[o] = groups[o];
40313 } // sort relations in a changeset by dependencies
40316 function sort(changes) {
40317 // find a referenced relation in the current changeset
40318 function resolve(item) {
40319 return relations.find(function (relation) {
40320 return item.keyAttributes.type === 'relation' && item.keyAttributes.ref === relation['@id'];
40322 } // a new item is an item that has not been already processed
40325 function isNew(item) {
40326 return !sorted[item['@id']] && !processing.find(function (proc) {
40327 return proc['@id'] === item['@id'];
40331 var processing = [];
40333 var relations = changes.relation;
40334 if (!relations) return changes;
40336 for (var i = 0; i < relations.length; i++) {
40337 var relation = relations[i]; // skip relation if already sorted
40339 if (!sorted[relation['@id']]) {
40340 processing.push(relation);
40343 while (processing.length > 0) {
40344 var next = processing[0],
40345 deps = next.member.map(resolve).filter(Boolean).filter(isNew);
40347 if (deps.length === 0) {
40348 sorted[next['@id']] = next;
40349 processing.shift();
40351 processing = deps.concat(processing);
40356 changes.relation = Object.values(sorted);
40360 function rep(entity) {
40361 return entity.asJXON(changeset_id);
40367 '@generator': 'iD',
40368 'create': sort(nest(changes.created.map(rep), ['node', 'way', 'relation'])),
40369 'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']),
40370 'delete': Object.assign(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), {
40376 asGeoJSON: function asGeoJSON() {
40381 function osmNote() {
40382 if (!(this instanceof osmNote)) {
40383 return new osmNote().initialize(arguments);
40384 } else if (arguments.length) {
40385 this.initialize(arguments);
40389 osmNote.id = function () {
40390 return osmNote.id.next--;
40393 osmNote.id.next = -1;
40394 Object.assign(osmNote.prototype, {
40396 initialize: function initialize(sources) {
40397 for (var i = 0; i < sources.length; ++i) {
40398 var source = sources[i];
40400 for (var prop in source) {
40401 if (Object.prototype.hasOwnProperty.call(source, prop)) {
40402 if (source[prop] === undefined) {
40405 this[prop] = source[prop];
40412 this.id = osmNote.id().toString();
40417 extent: function extent() {
40418 return new geoExtent(this.loc);
40420 update: function update(attrs) {
40421 return osmNote(this, attrs); // {v: 1 + (this.v || 0)}
40423 isNew: function isNew() {
40424 return this.id < 0;
40426 move: function move(loc) {
40427 return this.update({
40433 function osmRelation() {
40434 if (!(this instanceof osmRelation)) {
40435 return new osmRelation().initialize(arguments);
40436 } else if (arguments.length) {
40437 this.initialize(arguments);
40440 osmEntity.relation = osmRelation;
40441 osmRelation.prototype = Object.create(osmEntity.prototype);
40443 osmRelation.creationOrder = function (a, b) {
40444 var aId = parseInt(osmEntity.id.toOSM(a.id), 10);
40445 var bId = parseInt(osmEntity.id.toOSM(b.id), 10);
40446 if (aId < 0 || bId < 0) return aId - bId;
40450 Object.assign(osmRelation.prototype, {
40453 copy: function copy(resolver, copies) {
40454 if (copies[this.id]) return copies[this.id];
40455 var copy = osmEntity.prototype.copy.call(this, resolver, copies);
40456 var members = this.members.map(function (member) {
40457 return Object.assign({}, member, {
40458 id: resolver.entity(member.id).copy(resolver, copies).id
40461 copy = copy.update({
40464 copies[this.id] = copy;
40467 extent: function extent(resolver, memo) {
40468 return resolver["transient"](this, 'extent', function () {
40469 if (memo && memo[this.id]) return geoExtent();
40471 memo[this.id] = true;
40472 var extent = geoExtent();
40474 for (var i = 0; i < this.members.length; i++) {
40475 var member = resolver.hasEntity(this.members[i].id);
40478 extent._extend(member.extent(resolver, memo));
40485 geometry: function geometry(graph) {
40486 return graph["transient"](this, 'geometry', function () {
40487 return this.isMultipolygon() ? 'area' : 'relation';
40490 isDegenerate: function isDegenerate() {
40491 return this.members.length === 0;
40493 // Return an array of members, each extended with an 'index' property whose value
40494 // is the member index.
40495 indexedMembers: function indexedMembers() {
40496 var result = new Array(this.members.length);
40498 for (var i = 0; i < this.members.length; i++) {
40499 result[i] = Object.assign({}, this.members[i], {
40506 // Return the first member with the given role. A copy of the member object
40507 // is returned, extended with an 'index' property whose value is the member index.
40508 memberByRole: function memberByRole(role) {
40509 for (var i = 0; i < this.members.length; i++) {
40510 if (this.members[i].role === role) {
40511 return Object.assign({}, this.members[i], {
40517 // Same as memberByRole, but returns all members with the given role
40518 membersByRole: function membersByRole(role) {
40521 for (var i = 0; i < this.members.length; i++) {
40522 if (this.members[i].role === role) {
40523 result.push(Object.assign({}, this.members[i], {
40531 // Return the first member with the given id. A copy of the member object
40532 // is returned, extended with an 'index' property whose value is the member index.
40533 memberById: function memberById(id) {
40534 for (var i = 0; i < this.members.length; i++) {
40535 if (this.members[i].id === id) {
40536 return Object.assign({}, this.members[i], {
40542 // Return the first member with the given id and role. A copy of the member object
40543 // is returned, extended with an 'index' property whose value is the member index.
40544 memberByIdAndRole: function memberByIdAndRole(id, role) {
40545 for (var i = 0; i < this.members.length; i++) {
40546 if (this.members[i].id === id && this.members[i].role === role) {
40547 return Object.assign({}, this.members[i], {
40553 addMember: function addMember(member, index) {
40554 var members = this.members.slice();
40555 members.splice(index === undefined ? members.length : index, 0, member);
40556 return this.update({
40560 updateMember: function updateMember(member, index) {
40561 var members = this.members.slice();
40562 members.splice(index, 1, Object.assign({}, members[index], member));
40563 return this.update({
40567 removeMember: function removeMember(index) {
40568 var members = this.members.slice();
40569 members.splice(index, 1);
40570 return this.update({
40574 removeMembersWithID: function removeMembersWithID(id) {
40575 var members = this.members.filter(function (m) {
40576 return m.id !== id;
40578 return this.update({
40582 moveMember: function moveMember(fromIndex, toIndex) {
40583 var members = this.members.slice();
40584 members.splice(toIndex, 0, members.splice(fromIndex, 1)[0]);
40585 return this.update({
40589 // Wherever a member appears with id `needle.id`, replace it with a member
40590 // with id `replacement.id`, type `replacement.type`, and the original role,
40591 // By default, adding a duplicate member (by id and role) is prevented.
40592 // Return an updated relation.
40593 replaceMember: function replaceMember(needle, replacement, keepDuplicates) {
40594 if (!this.memberById(needle.id)) return this;
40597 for (var i = 0; i < this.members.length; i++) {
40598 var member = this.members[i];
40600 if (member.id !== needle.id) {
40601 members.push(member);
40602 } else if (keepDuplicates || !this.memberByIdAndRole(replacement.id, member.role)) {
40604 id: replacement.id,
40605 type: replacement.type,
40611 return this.update({
40615 asJXON: function asJXON(changeset_id) {
40618 '@id': this.osmId(),
40619 '@version': this.version || 0,
40620 member: this.members.map(function (member) {
40625 ref: osmEntity.id.toOSM(member.id)
40629 tag: Object.keys(this.tags).map(function (k) {
40640 if (changeset_id) {
40641 r.relation['@changeset'] = changeset_id;
40646 asGeoJSON: function asGeoJSON(resolver) {
40647 return resolver["transient"](this, 'GeoJSON', function () {
40648 if (this.isMultipolygon()) {
40650 type: 'MultiPolygon',
40651 coordinates: this.multipolygon(resolver)
40655 type: 'FeatureCollection',
40656 properties: this.tags,
40657 features: this.members.map(function (member) {
40658 return Object.assign({
40660 }, resolver.entity(member.id).asGeoJSON(resolver));
40666 area: function area(resolver) {
40667 return resolver["transient"](this, 'area', function () {
40668 return d3_geoArea(this.asGeoJSON(resolver));
40671 isMultipolygon: function isMultipolygon() {
40672 return this.tags.type === 'multipolygon';
40674 isComplete: function isComplete(resolver) {
40675 for (var i = 0; i < this.members.length; i++) {
40676 if (!resolver.hasEntity(this.members[i].id)) {
40683 hasFromViaTo: function hasFromViaTo() {
40684 return this.members.some(function (m) {
40685 return m.role === 'from';
40686 }) && this.members.some(function (m) {
40687 return m.role === 'via';
40688 }) && this.members.some(function (m) {
40689 return m.role === 'to';
40692 isRestriction: function isRestriction() {
40693 return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
40695 isValidRestriction: function isValidRestriction() {
40696 if (!this.isRestriction()) return false;
40697 var froms = this.members.filter(function (m) {
40698 return m.role === 'from';
40700 var vias = this.members.filter(function (m) {
40701 return m.role === 'via';
40703 var tos = this.members.filter(function (m) {
40704 return m.role === 'to';
40706 if (froms.length !== 1 && this.tags.restriction !== 'no_entry') return false;
40707 if (froms.some(function (m) {
40708 return m.type !== 'way';
40710 if (tos.length !== 1 && this.tags.restriction !== 'no_exit') return false;
40711 if (tos.some(function (m) {
40712 return m.type !== 'way';
40714 if (vias.length === 0) return false;
40715 if (vias.length > 1 && vias.some(function (m) {
40716 return m.type !== 'way';
40720 isConnectivity: function isConnectivity() {
40721 return !!(this.tags.type && this.tags.type.match(/^connectivity:?/));
40723 // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
40724 // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
40726 // This corresponds to the structure needed for rendering a multipolygon path using a
40727 // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
40729 // In the case of invalid geometries, this function will still return a result which
40730 // includes the nodes of all way members, but some Nds may be unclosed and some inner
40731 // rings not matched with the intended outer ring.
40733 multipolygon: function multipolygon(resolver) {
40734 var outers = this.members.filter(function (m) {
40735 return 'outer' === (m.role || 'outer');
40737 var inners = this.members.filter(function (m) {
40738 return 'inner' === m.role;
40740 outers = osmJoinWays(outers, resolver);
40741 inners = osmJoinWays(inners, resolver);
40743 var sequenceToLineString = function sequenceToLineString(sequence) {
40744 if (sequence.nodes.length > 2 && sequence.nodes[0] !== sequence.nodes[sequence.nodes.length - 1]) {
40745 // close unclosed parts to ensure correct area rendering - #2945
40746 sequence.nodes.push(sequence.nodes[0]);
40749 return sequence.nodes.map(function (node) {
40754 outers = outers.map(sequenceToLineString);
40755 inners = inners.map(sequenceToLineString);
40756 var result = outers.map(function (o) {
40757 // Heuristic for detecting counterclockwise winding order. Assumes
40758 // that OpenStreetMap polygons are not hemisphere-spanning.
40759 return [d3_geoArea({
40762 }) > 2 * Math.PI ? o.reverse() : o];
40765 function findOuter(inner) {
40768 for (o = 0; o < outers.length; o++) {
40771 if (geoPolygonContainsPolygon(outer, inner)) {
40776 for (o = 0; o < outers.length; o++) {
40779 if (geoPolygonIntersectsPolygon(outer, inner, false)) {
40785 for (var i = 0; i < inners.length; i++) {
40786 var inner = inners[i];
40790 coordinates: [inner]
40791 }) < 2 * Math.PI) {
40792 inner = inner.reverse();
40795 var o = findOuter(inners[i]);
40797 if (o !== undefined) {
40798 result[o].push(inners[i]);
40800 result.push([inners[i]]); // Invalid geometry
40808 var QAItem = /*#__PURE__*/function () {
40809 function QAItem(loc, service, itemType, id, props) {
40810 _classCallCheck$1(this, QAItem);
40812 // Store required properties
40814 this.service = service.title;
40815 this.itemType = itemType; // All issues must have an ID for selection, use generic if none specified
40817 this.id = id ? id : "".concat(QAItem.id());
40818 this.update(props); // Some QA services have marker icons to differentiate issues
40820 if (service && typeof service.getIcon === 'function') {
40821 this.icon = service.getIcon(itemType);
40825 _createClass$1(QAItem, [{
40827 value: function update(props) {
40830 // You can't override this initial information
40831 var loc = this.loc,
40832 service = this.service,
40833 itemType = this.itemType,
40835 Object.keys(props).forEach(function (prop) {
40836 return _this[prop] = props[prop];
40839 this.service = service;
40840 this.itemType = itemType;
40843 } // Generic handling for newly created QAItems
40847 value: function id() {
40848 return this.nextId--;
40854 QAItem.nextId = -1;
40857 // Optionally, split only the given ways, if multiple ways share
40860 // This is the inverse of `iD.actionJoin`.
40862 // For testing convenience, accepts an ID to assign to the new way.
40863 // Normally, this will be undefined and the way will automatically
40864 // be assigned a new ID.
40867 // https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
40870 function actionSplit(nodeIds, newWayIds) {
40871 // accept single ID for backwards-compatiblity
40872 if (typeof nodeIds === 'string') nodeIds = [nodeIds];
40874 var _wayIDs; // the strategy for picking which way will have a new version and which way is newly created
40877 var _keepHistoryOn = 'longest'; // 'longest', 'first'
40878 // The IDs of the ways actually created by running this action
40880 var _createdWayIDs = [];
40882 function dist(graph, nA, nB) {
40883 var locA = graph.entity(nA).loc;
40884 var locB = graph.entity(nB).loc;
40885 var epsilon = 1e-6;
40886 return locA && locB ? geoSphericalDistance(locA, locB) : epsilon;
40887 } // If the way is closed, we need to search for a partner node
40888 // to split the way at.
40890 // The following looks for a node that is both far away from
40891 // the initial node in terms of way segment length and nearby
40892 // in terms of beeline-distance. This assures that areas get
40893 // split on the most "natural" points (independent of the number
40895 // For example: bone-shaped areas get split across their waist
40896 // line, circles across the diameter.
40899 function splitArea(nodes, idxA, graph) {
40900 var lengths = new Array(nodes.length);
40906 function wrap(index) {
40907 return utilWrap(index, nodes.length);
40908 } // calculate lengths
40913 for (i = wrap(idxA + 1); i !== idxA; i = wrap(i + 1)) {
40914 length += dist(graph, nodes[i], nodes[wrap(i - 1)]);
40915 lengths[i] = length;
40920 for (i = wrap(idxA - 1); i !== idxA; i = wrap(i - 1)) {
40921 length += dist(graph, nodes[i], nodes[wrap(i + 1)]);
40923 if (length < lengths[i]) {
40924 lengths[i] = length;
40926 } // determine best opposite node to split
40929 for (i = 0; i < nodes.length; i++) {
40930 var cost = lengths[i] / dist(graph, nodes[idxA], nodes[i]);
40941 function totalLengthBetweenNodes(graph, nodes) {
40942 var totalLength = 0;
40944 for (var i = 0; i < nodes.length - 1; i++) {
40945 totalLength += dist(graph, nodes[i], nodes[i + 1]);
40948 return totalLength;
40951 function split(graph, nodeId, wayA, newWayId) {
40952 var wayB = osmWay({
40955 }); // `wayB` is the NEW way
40957 var origNodes = wayA.nodes.slice();
40960 var isArea = wayA.isArea();
40961 var isOuter = osmIsOldMultipolygonOuterMember(wayA, graph);
40963 if (wayA.isClosed()) {
40964 var nodes = wayA.nodes.slice(0, -1);
40965 var idxA = nodes.indexOf(nodeId);
40966 var idxB = splitArea(nodes, idxA, graph);
40969 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
40970 nodesB = nodes.slice(idxB, idxA + 1);
40972 nodesA = nodes.slice(idxA, idxB + 1);
40973 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
40976 var idx = wayA.nodes.indexOf(nodeId, 1);
40977 nodesA = wayA.nodes.slice(0, idx + 1);
40978 nodesB = wayA.nodes.slice(idx);
40981 var lengthA = totalLengthBetweenNodes(graph, nodesA);
40982 var lengthB = totalLengthBetweenNodes(graph, nodesB);
40984 if (_keepHistoryOn === 'longest' && lengthB > lengthA) {
40985 // keep the history on the longer way, regardless of the node count
40986 wayA = wayA.update({
40989 wayB = wayB.update({
40992 var temp = lengthA;
40996 wayA = wayA.update({
40999 wayB = wayB.update({
41004 if (wayA.tags.step_count) {
41005 // divide up the the step count proportionally between the two ways
41006 var stepCount = parseFloat(wayA.tags.step_count);
41008 if (stepCount && // ensure a number
41009 isFinite(stepCount) && // ensure positive
41010 stepCount > 0 && // ensure integer
41011 Math.round(stepCount) === stepCount) {
41012 var tagsA = Object.assign({}, wayA.tags);
41013 var tagsB = Object.assign({}, wayB.tags);
41014 var ratioA = lengthA / (lengthA + lengthB);
41015 var countA = Math.round(stepCount * ratioA);
41016 tagsA.step_count = countA.toString();
41017 tagsB.step_count = (stepCount - countA).toString();
41018 wayA = wayA.update({
41021 wayB = wayB.update({
41027 graph = graph.replace(wayA);
41028 graph = graph.replace(wayB);
41029 graph.parentRelations(wayA).forEach(function (relation) {
41030 var member; // Turn restrictions - make sure:
41031 // 1. Splitting a FROM/TO way - only `wayA` OR `wayB` remains in relation
41032 // (whichever one is connected to the VIA node/ways)
41033 // 2. Splitting a VIA way - `wayB` remains in relation as a VIA way
41035 if (relation.hasFromViaTo()) {
41036 var f = relation.memberByRole('from');
41037 var v = relation.membersByRole('via');
41038 var t = relation.memberByRole('to');
41039 var i; // 1. split a FROM/TO
41041 if (f.id === wayA.id || t.id === wayA.id) {
41044 if (v.length === 1 && v[0].type === 'node') {
41046 keepB = wayB.contains(v[0].id);
41048 // check via way(s)
41049 for (i = 0; i < v.length; i++) {
41050 if (v[i].type === 'way') {
41051 var wayVia = graph.hasEntity(v[i].id);
41053 if (wayVia && utilArrayIntersection(wayB.nodes, wayVia.nodes).length) {
41062 relation = relation.replaceMember(wayA, wayB);
41063 graph = graph.replace(relation);
41064 } // 2. split a VIA
41067 for (i = 0; i < v.length; i++) {
41068 if (v[i].type === 'way' && v[i].id === wayA.id) {
41074 graph = actionAddMember(relation.id, member, v[i].index + 1)(graph);
41078 } // All other relations (Routes, Multipolygons, etc):
41079 // 1. Both `wayA` and `wayB` remain in the relation
41080 // 2. But must be inserted as a pair (see `actionAddMember` for details)
41083 if (relation === isOuter) {
41084 graph = graph.replace(relation.mergeTags(wayA.tags));
41085 graph = graph.replace(wayA.update({
41088 graph = graph.replace(wayB.update({
41096 role: relation.memberById(wayA.id).role
41099 originalID: wayA.id,
41100 insertedID: wayB.id,
41103 graph = actionAddMember(relation.id, member, undefined, insertPair)(graph);
41107 if (!isOuter && isArea) {
41108 var multipolygon = osmRelation({
41109 tags: Object.assign({}, wayA.tags, {
41110 type: 'multipolygon'
41122 graph = graph.replace(multipolygon);
41123 graph = graph.replace(wayA.update({
41126 graph = graph.replace(wayB.update({
41131 _createdWayIDs.push(wayB.id);
41136 var action = function action(graph) {
41137 _createdWayIDs = [];
41138 var newWayIndex = 0;
41140 for (var i = 0; i < nodeIds.length; i++) {
41141 var nodeId = nodeIds[i];
41142 var candidates = action.waysForNode(nodeId, graph);
41144 for (var j = 0; j < candidates.length; j++) {
41145 graph = split(graph, nodeId, candidates[j], newWayIds && newWayIds[newWayIndex]);
41153 action.getCreatedWayIDs = function () {
41154 return _createdWayIDs;
41157 action.waysForNode = function (nodeId, graph) {
41158 var node = graph.entity(nodeId);
41159 var splittableParents = graph.parentWays(node).filter(isSplittable);
41162 // If the ways to split aren't specified, only split the lines.
41163 // If there are no lines to split, split the areas.
41164 var hasLine = splittableParents.some(function (parent) {
41165 return parent.geometry(graph) === 'line';
41169 return splittableParents.filter(function (parent) {
41170 return parent.geometry(graph) === 'line';
41175 return splittableParents;
41177 function isSplittable(parent) {
41178 // If the ways to split are specified, ignore everything else.
41179 if (_wayIDs && _wayIDs.indexOf(parent.id) === -1) return false; // We can fake splitting closed ways at their endpoints...
41181 if (parent.isClosed()) return true; // otherwise, we can't split nodes at their endpoints.
41183 for (var i = 1; i < parent.nodes.length - 1; i++) {
41184 if (parent.nodes[i] === nodeId) return true;
41191 action.ways = function (graph) {
41192 return utilArrayUniq([].concat.apply([], nodeIds.map(function (nodeId) {
41193 return action.waysForNode(nodeId, graph);
41197 action.disabled = function (graph) {
41198 for (var i = 0; i < nodeIds.length; i++) {
41199 var nodeId = nodeIds[i];
41200 var candidates = action.waysForNode(nodeId, graph);
41202 if (candidates.length === 0 || _wayIDs && _wayIDs.length !== candidates.length) {
41203 return 'not_eligible';
41208 action.limitWays = function (val) {
41209 if (!arguments.length) return _wayIDs;
41214 action.keepHistoryOn = function (val) {
41215 if (!arguments.length) return _keepHistoryOn;
41216 _keepHistoryOn = val;
41223 function coreGraph(other, mutable) {
41224 if (!(this instanceof coreGraph)) return new coreGraph(other, mutable);
41226 if (other instanceof coreGraph) {
41227 var base = other.base();
41228 this.entities = Object.assign(Object.create(base.entities), other.entities);
41229 this._parentWays = Object.assign(Object.create(base.parentWays), other._parentWays);
41230 this._parentRels = Object.assign(Object.create(base.parentRels), other._parentRels);
41232 this.entities = Object.create({});
41233 this._parentWays = Object.create({});
41234 this._parentRels = Object.create({});
41235 this.rebase(other || [], [this]);
41238 this.transients = {};
41239 this._childNodes = {};
41240 this.frozen = !mutable;
41242 coreGraph.prototype = {
41243 hasEntity: function hasEntity(id) {
41244 return this.entities[id];
41246 entity: function entity(id) {
41247 var entity = this.entities[id]; //https://github.com/openstreetmap/iD/issues/3973#issuecomment-307052376
41250 entity = this.entities.__proto__[id]; // eslint-disable-line no-proto
41254 throw new Error('entity ' + id + ' not found');
41259 geometry: function geometry(id) {
41260 return this.entity(id).geometry(this);
41262 "transient": function transient(entity, key, fn) {
41263 var id = entity.id;
41264 var transients = this.transients[id] || (this.transients[id] = {});
41266 if (transients[key] !== undefined) {
41267 return transients[key];
41270 transients[key] = fn.call(entity);
41271 return transients[key];
41273 parentWays: function parentWays(entity) {
41274 var parents = this._parentWays[entity.id];
41278 parents.forEach(function (id) {
41279 result.push(this.entity(id));
41285 isPoi: function isPoi(entity) {
41286 var parents = this._parentWays[entity.id];
41287 return !parents || parents.size === 0;
41289 isShared: function isShared(entity) {
41290 var parents = this._parentWays[entity.id];
41291 return parents && parents.size > 1;
41293 parentRelations: function parentRelations(entity) {
41294 var parents = this._parentRels[entity.id];
41298 parents.forEach(function (id) {
41299 result.push(this.entity(id));
41305 parentMultipolygons: function parentMultipolygons(entity) {
41306 return this.parentRelations(entity).filter(function (relation) {
41307 return relation.isMultipolygon();
41310 childNodes: function childNodes(entity) {
41311 if (this._childNodes[entity.id]) return this._childNodes[entity.id];
41312 if (!entity.nodes) return [];
41315 for (var i = 0; i < entity.nodes.length; i++) {
41316 nodes[i] = this.entity(entity.nodes[i]);
41318 this._childNodes[entity.id] = nodes;
41319 return this._childNodes[entity.id];
41321 base: function base() {
41323 'entities': Object.getPrototypeOf(this.entities),
41324 'parentWays': Object.getPrototypeOf(this._parentWays),
41325 'parentRels': Object.getPrototypeOf(this._parentRels)
41328 // Unlike other graph methods, rebase mutates in place. This is because it
41329 // is used only during the history operation that merges newly downloaded
41330 // data into each state. To external consumers, it should appear as if the
41331 // graph always contained the newly downloaded data.
41332 rebase: function rebase(entities, stack, force) {
41333 var base = this.base();
41336 for (i = 0; i < entities.length; i++) {
41337 var entity = entities[i];
41338 if (!entity.visible || !force && base.entities[entity.id]) continue; // Merging data into the base graph
41340 base.entities[entity.id] = entity;
41342 this._updateCalculated(undefined, entity, base.parentWays, base.parentRels); // Restore provisionally-deleted nodes that are discovered to have an extant parent
41345 if (entity.type === 'way') {
41346 for (j = 0; j < entity.nodes.length; j++) {
41347 id = entity.nodes[j];
41349 for (k = 1; k < stack.length; k++) {
41350 var ents = stack[k].entities;
41352 if (ents.hasOwnProperty(id) && ents[id] === undefined) {
41360 for (i = 0; i < stack.length; i++) {
41361 stack[i]._updateRebased();
41364 _updateRebased: function _updateRebased() {
41365 var base = this.base();
41366 Object.keys(this._parentWays).forEach(function (child) {
41367 if (base.parentWays[child]) {
41368 base.parentWays[child].forEach(function (id) {
41369 if (!this.entities.hasOwnProperty(id)) {
41370 this._parentWays[child].add(id);
41375 Object.keys(this._parentRels).forEach(function (child) {
41376 if (base.parentRels[child]) {
41377 base.parentRels[child].forEach(function (id) {
41378 if (!this.entities.hasOwnProperty(id)) {
41379 this._parentRels[child].add(id);
41384 this.transients = {}; // this._childNodes is not updated, under the assumption that
41385 // ways are always downloaded with their child nodes.
41387 // Updates calculated properties (parentWays, parentRels) for the specified change
41388 _updateCalculated: function _updateCalculated(oldentity, entity, parentWays, parentRels) {
41389 parentWays = parentWays || this._parentWays;
41390 parentRels = parentRels || this._parentRels;
41391 var type = entity && entity.type || oldentity && oldentity.type;
41392 var removed, added, i;
41394 if (type === 'way') {
41395 // Update parentWays
41396 if (oldentity && entity) {
41397 removed = utilArrayDifference(oldentity.nodes, entity.nodes);
41398 added = utilArrayDifference(entity.nodes, oldentity.nodes);
41399 } else if (oldentity) {
41400 removed = oldentity.nodes;
41402 } else if (entity) {
41404 added = entity.nodes;
41407 for (i = 0; i < removed.length; i++) {
41408 // make a copy of prototype property, store as own property, and update..
41409 parentWays[removed[i]] = new Set(parentWays[removed[i]]);
41410 parentWays[removed[i]]["delete"](oldentity.id);
41413 for (i = 0; i < added.length; i++) {
41414 // make a copy of prototype property, store as own property, and update..
41415 parentWays[added[i]] = new Set(parentWays[added[i]]);
41416 parentWays[added[i]].add(entity.id);
41418 } else if (type === 'relation') {
41419 // Update parentRels
41420 // diff only on the IDs since the same entity can be a member multiple times with different roles
41421 var oldentityMemberIDs = oldentity ? oldentity.members.map(function (m) {
41424 var entityMemberIDs = entity ? entity.members.map(function (m) {
41428 if (oldentity && entity) {
41429 removed = utilArrayDifference(oldentityMemberIDs, entityMemberIDs);
41430 added = utilArrayDifference(entityMemberIDs, oldentityMemberIDs);
41431 } else if (oldentity) {
41432 removed = oldentityMemberIDs;
41434 } else if (entity) {
41436 added = entityMemberIDs;
41439 for (i = 0; i < removed.length; i++) {
41440 // make a copy of prototype property, store as own property, and update..
41441 parentRels[removed[i]] = new Set(parentRels[removed[i]]);
41442 parentRels[removed[i]]["delete"](oldentity.id);
41445 for (i = 0; i < added.length; i++) {
41446 // make a copy of prototype property, store as own property, and update..
41447 parentRels[added[i]] = new Set(parentRels[added[i]]);
41448 parentRels[added[i]].add(entity.id);
41452 replace: function replace(entity) {
41453 if (this.entities[entity.id] === entity) return this;
41454 return this.update(function () {
41455 this._updateCalculated(this.entities[entity.id], entity);
41457 this.entities[entity.id] = entity;
41460 remove: function remove(entity) {
41461 return this.update(function () {
41462 this._updateCalculated(entity, undefined);
41464 this.entities[entity.id] = undefined;
41467 revert: function revert(id) {
41468 var baseEntity = this.base().entities[id];
41469 var headEntity = this.entities[id];
41470 if (headEntity === baseEntity) return this;
41471 return this.update(function () {
41472 this._updateCalculated(headEntity, baseEntity);
41474 delete this.entities[id];
41477 update: function update() {
41478 var graph = this.frozen ? coreGraph(this, true) : this;
41480 for (var i = 0; i < arguments.length; i++) {
41481 arguments[i].call(graph, graph);
41484 if (this.frozen) graph.frozen = true;
41487 // Obliterates any existing entities
41488 load: function load(entities) {
41489 var base = this.base();
41490 this.entities = Object.create(base.entities);
41492 for (var i in entities) {
41493 this.entities[i] = entities[i];
41495 this._updateCalculated(base.entities[i], this.entities[i]);
41502 function osmTurn(turn) {
41503 if (!(this instanceof osmTurn)) {
41504 return new osmTurn(turn);
41507 Object.assign(this, turn);
41509 function osmIntersection(graph, startVertexId, maxDistance) {
41510 maxDistance = maxDistance || 30; // in meters
41512 var vgraph = coreGraph(); // virtual graph
41516 function memberOfRestriction(entity) {
41517 return graph.parentRelations(entity).some(function (r) {
41518 return r.isRestriction();
41522 function isRoad(way) {
41523 if (way.isArea() || way.isDegenerate()) return false;
41526 'motorway_link': true,
41528 'trunk_link': true,
41530 'primary_link': true,
41532 'secondary_link': true,
41534 'tertiary_link': true,
41535 'residential': true,
41536 'unclassified': true,
41537 'living_street': true,
41542 return roads[way.tags.highway];
41545 var startNode = graph.entity(startVertexId);
41546 var checkVertices = [startNode];
41549 var vertexIds = [];
41557 var parent; // `actions` will store whatever actions must be performed to satisfy
41558 // preconditions for adding a turn restriction to this intersection.
41559 // - Remove any existing degenerate turn restrictions (missing from/to, etc)
41560 // - Reverse oneways so that they are drawn in the forward direction
41561 // - Split ways on key vertices
41563 var actions = []; // STEP 1: walk the graph outwards from starting vertex to search
41564 // for more key vertices and ways to include in the intersection..
41566 while (checkVertices.length) {
41567 vertex = checkVertices.pop(); // check this vertex for parent ways that are roads
41569 checkWays = graph.parentWays(vertex);
41570 var hasWays = false;
41572 for (i = 0; i < checkWays.length; i++) {
41573 way = checkWays[i];
41574 if (!isRoad(way) && !memberOfRestriction(way)) continue;
41575 ways.push(way); // it's a road, or it's already in a turn restriction
41577 hasWays = true; // check the way's children for more key vertices
41579 nodes = utilArrayUniq(graph.childNodes(way));
41581 for (j = 0; j < nodes.length; j++) {
41583 if (node === vertex) continue; // same thing
41585 if (vertices.indexOf(node) !== -1) continue; // seen it already
41587 if (geoSphericalDistance(node.loc, startNode.loc) > maxDistance) continue; // too far from start
41588 // a key vertex will have parents that are also roads
41590 var hasParents = false;
41591 parents = graph.parentWays(node);
41593 for (k = 0; k < parents.length; k++) {
41594 parent = parents[k];
41595 if (parent === way) continue; // same thing
41597 if (ways.indexOf(parent) !== -1) continue; // seen it already
41599 if (!isRoad(parent)) continue; // not a road
41606 checkVertices.push(node);
41612 vertices.push(vertex);
41616 vertices = utilArrayUniq(vertices);
41617 ways = utilArrayUniq(ways); // STEP 2: Build a virtual graph containing only the entities in the intersection..
41618 // Everything done after this step should act on the virtual graph
41619 // Any actions that must be performed later to the main graph go in `actions` array
41621 ways.forEach(function (way) {
41622 graph.childNodes(way).forEach(function (node) {
41623 vgraph = vgraph.replace(node);
41625 vgraph = vgraph.replace(way);
41626 graph.parentRelations(way).forEach(function (relation) {
41627 if (relation.isRestriction()) {
41628 if (relation.isValidRestriction(graph)) {
41629 vgraph = vgraph.replace(relation);
41630 } else if (relation.isComplete(graph)) {
41631 actions.push(actionDeleteRelation(relation.id));
41635 }); // STEP 3: Force all oneways to be drawn in the forward direction
41637 ways.forEach(function (w) {
41638 var way = vgraph.entity(w.id);
41640 if (way.tags.oneway === '-1') {
41641 var action = actionReverse(way.id, {
41642 reverseOneway: true
41644 actions.push(action);
41645 vgraph = action(vgraph);
41647 }); // STEP 4: Split ways on key vertices
41649 var origCount = osmEntity.id.next.way;
41650 vertices.forEach(function (v) {
41651 // This is an odd way to do it, but we need to find all the ways that
41652 // will be split here, then split them one at a time to ensure that these
41653 // actions can be replayed on the main graph exactly in the same order.
41654 // (It is unintuitive, but the order of ways returned from graph.parentWays()
41655 // is arbitrary, depending on how the main graph and vgraph were built)
41656 var splitAll = actionSplit([v.id]).keepHistoryOn('first');
41658 if (!splitAll.disabled(vgraph)) {
41659 splitAll.ways(vgraph).forEach(function (way) {
41660 var splitOne = actionSplit([v.id]).limitWays([way.id]).keepHistoryOn('first');
41661 actions.push(splitOne);
41662 vgraph = splitOne(vgraph);
41665 }); // In here is where we should also split the intersection at nearby junction.
41666 // for https://github.com/mapbox/iD-internal/issues/31
41667 // nearbyVertices.forEach(function(v) {
41669 // Reasons why we reset the way id count here:
41670 // 1. Continuity with way ids created by the splits so that we can replay
41671 // these actions later if the user decides to create a turn restriction
41672 // 2. Avoids churning way ids just by hovering over a vertex
41673 // and displaying the turn restriction editor
41675 osmEntity.id.next.way = origCount; // STEP 5: Update arrays to point to vgraph entities
41677 vertexIds = vertices.map(function (v) {
41682 vertexIds.forEach(function (id) {
41683 var vertex = vgraph.entity(id);
41684 var parents = vgraph.parentWays(vertex);
41685 vertices.push(vertex);
41686 ways = ways.concat(parents);
41688 vertices = utilArrayUniq(vertices);
41689 ways = utilArrayUniq(ways);
41690 vertexIds = vertices.map(function (v) {
41693 wayIds = ways.map(function (w) {
41695 }); // STEP 6: Update the ways with some metadata that will be useful for
41696 // walking the intersection graph later and rendering turn arrows.
41698 function withMetadata(way, vertexIds) {
41699 var __oneWay = way.isOneWay(); // which affixes are key vertices?
41702 var __first = vertexIds.indexOf(way.first()) !== -1;
41704 var __last = vertexIds.indexOf(way.last()) !== -1; // what roles is this way eligible for?
41707 var __via = __first && __last;
41709 var __from = __first && !__oneWay || __last;
41711 var __to = __first || __last && !__oneWay;
41713 return way.update({
41724 wayIds.forEach(function (id) {
41725 var way = withMetadata(vgraph.entity(id), vertexIds);
41726 vgraph = vgraph.replace(way);
41728 }); // STEP 7: Simplify - This is an iterative process where we:
41729 // 1. Find trivial vertices with only 2 parents
41730 // 2. trim off the leaf way from those vertices and remove from vgraph
41733 var removeWayIds = [];
41734 var removeVertexIds = [];
41738 checkVertices = vertexIds.slice();
41740 for (i = 0; i < checkVertices.length; i++) {
41741 var vertexId = checkVertices[i];
41742 vertex = vgraph.hasEntity(vertexId);
41745 if (vertexIds.indexOf(vertexId) !== -1) {
41746 vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one
41749 removeVertexIds.push(vertexId);
41753 parents = vgraph.parentWays(vertex);
41755 if (parents.length < 3) {
41756 if (vertexIds.indexOf(vertexId) !== -1) {
41757 vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one
41761 if (parents.length === 2) {
41762 // vertex with 2 parents is trivial
41763 var a = parents[0];
41764 var b = parents[1];
41765 var aIsLeaf = a && !a.__via;
41766 var bIsLeaf = b && !b.__via;
41767 var leaf, survivor;
41769 if (aIsLeaf && !bIsLeaf) {
41772 } else if (!aIsLeaf && bIsLeaf) {
41777 if (leaf && survivor) {
41778 survivor = withMetadata(survivor, vertexIds); // update survivor way
41780 vgraph = vgraph.replace(survivor).remove(leaf); // update graph
41782 removeWayIds.push(leaf.id);
41787 parents = vgraph.parentWays(vertex);
41789 if (parents.length < 2) {
41790 // vertex is no longer a key vertex
41791 if (vertexIds.indexOf(vertexId) !== -1) {
41792 vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one
41795 removeVertexIds.push(vertexId);
41799 if (parents.length < 1) {
41800 // vertex is no longer attached to anything
41801 vgraph = vgraph.remove(vertex);
41804 } while (keepGoing);
41806 vertices = vertices.filter(function (vertex) {
41807 return removeVertexIds.indexOf(vertex.id) === -1;
41808 }).map(function (vertex) {
41809 return vgraph.entity(vertex.id);
41811 ways = ways.filter(function (way) {
41812 return removeWayIds.indexOf(way.id) === -1;
41813 }).map(function (way) {
41814 return vgraph.entity(way.id);
41815 }); // OK! Here is our intersection..
41817 var intersection = {
41820 vertices: vertices,
41822 }; // Get all the valid turns through this intersection given a starting way id.
41823 // This operates on the virtual graph for everything.
41825 // Basically, walk through all possible paths from starting way,
41826 // honoring the existing turn restrictions as we go (watch out for loops!)
41828 // For each path found, generate and return a `osmTurn` datastructure.
41831 intersection.turns = function (fromWayId, maxViaWay) {
41832 if (!fromWayId) return [];
41833 if (!maxViaWay) maxViaWay = 0;
41834 var vgraph = intersection.graph;
41835 var keyVertexIds = intersection.vertices.map(function (v) {
41838 var start = vgraph.entity(fromWayId);
41839 if (!start || !(start.__from || start.__via)) return []; // maxViaWay=0 from-*-to (0 vias)
41840 // maxViaWay=1 from-*-via-*-to (1 via max)
41841 // maxViaWay=2 from-*-via-*-via-*-to (2 vias max)
41843 var maxPathLength = maxViaWay * 2 + 3;
41846 return turns; // traverse the intersection graph and find all the valid paths
41848 function step(entity, currPath, currRestrictions, matchedRestriction) {
41849 currPath = (currPath || []).slice(); // shallow copy
41851 if (currPath.length >= maxPathLength) return;
41852 currPath.push(entity.id);
41853 currRestrictions = (currRestrictions || []).slice(); // shallow copy
41857 if (entity.type === 'node') {
41858 var parents = vgraph.parentWays(entity);
41859 var nextWays = []; // which ways can we step into?
41861 for (i = 0; i < parents.length; i++) {
41862 var way = parents[i]; // if next way is a oneway incoming to this vertex, skip
41864 if (way.__oneWay && way.nodes[0] !== entity.id) continue; // if we have seen it before (allowing for an initial u-turn), skip
41866 if (currPath.indexOf(way.id) !== -1 && currPath.length >= 3) continue; // Check all "current" restrictions (where we've already walked the `FROM`)
41868 var restrict = null;
41870 for (j = 0; j < currRestrictions.length; j++) {
41871 var restriction = currRestrictions[j];
41872 var f = restriction.memberByRole('from');
41873 var v = restriction.membersByRole('via');
41874 var t = restriction.memberByRole('to');
41875 var isOnly = /^only_/.test(restriction.tags.restriction); // Does the current path match this turn restriction?
41877 var matchesFrom = f.id === fromWayId;
41878 var matchesViaTo = false;
41879 var isAlongOnlyPath = false;
41881 if (t.id === way.id) {
41883 if (v.length === 1 && v[0].type === 'node') {
41885 matchesViaTo = v[0].id === entity.id && (matchesFrom && currPath.length === 2 || !matchesFrom && currPath.length > 2);
41887 // match all VIA ways
41890 for (k = 2; k < currPath.length; k += 2) {
41891 // k = 2 skips FROM
41892 pathVias.push(currPath[k]); // (path goes way-node-way...)
41895 var restrictionVias = [];
41897 for (k = 0; k < v.length; k++) {
41898 if (v[k].type === 'way') {
41899 restrictionVias.push(v[k].id);
41903 var diff = utilArrayDifference(pathVias, restrictionVias);
41904 matchesViaTo = !diff.length;
41906 } else if (isOnly) {
41907 for (k = 0; k < v.length; k++) {
41908 // way doesn't match TO, but is one of the via ways along the path of an "only"
41909 if (v[k].type === 'way' && v[k].id === way.id) {
41910 isAlongOnlyPath = true;
41916 if (matchesViaTo) {
41919 id: restriction.id,
41920 direct: matchesFrom,
41927 id: restriction.id,
41928 direct: matchesFrom,
41935 // indirect - caused by a different nearby restriction
41936 if (isAlongOnlyPath) {
41938 id: restriction.id,
41944 } else if (isOnly) {
41946 id: restriction.id,
41953 } // stop looking if we find a "direct" restriction (matching FROM, VIA, TO)
41956 if (restrict && restrict.direct) break;
41965 nextWays.forEach(function (nextWay) {
41966 step(nextWay.way, currPath, currRestrictions, nextWay.restrict);
41969 // entity.type === 'way'
41970 if (currPath.length >= 3) {
41971 // this is a "complete" path..
41972 var turnPath = currPath.slice(); // shallow copy
41973 // an indirect restriction - only include the partial path (starting at FROM)
41975 if (matchedRestriction && matchedRestriction.direct === false) {
41976 for (i = 0; i < turnPath.length; i++) {
41977 if (turnPath[i] === matchedRestriction.from) {
41978 turnPath = turnPath.slice(i);
41984 var turn = pathToTurn(turnPath);
41987 if (matchedRestriction) {
41988 turn.restrictionID = matchedRestriction.id;
41989 turn.no = matchedRestriction.no;
41990 turn.only = matchedRestriction.only;
41991 turn.direct = matchedRestriction.direct;
41994 turns.push(osmTurn(turn));
41997 if (currPath[0] === currPath[2]) return; // if we made a u-turn - stop here
42000 if (matchedRestriction && matchedRestriction.end) return; // don't advance any further
42001 // which nodes can we step into?
42003 var n1 = vgraph.entity(entity.first());
42004 var n2 = vgraph.entity(entity.last());
42005 var dist = geoSphericalDistance(n1.loc, n2.loc);
42006 var nextNodes = [];
42008 if (currPath.length > 1) {
42009 if (dist > maxDistance) return; // the next node is too far
42011 if (!entity.__via) return; // this way is a leaf / can't be a via
42014 if (!entity.__oneWay && // bidirectional..
42015 keyVertexIds.indexOf(n1.id) !== -1 && // key vertex..
42016 currPath.indexOf(n1.id) === -1) {
42017 // haven't seen it yet..
42018 nextNodes.push(n1); // can advance to first node
42021 if (keyVertexIds.indexOf(n2.id) !== -1 && // key vertex..
42022 currPath.indexOf(n2.id) === -1) {
42023 // haven't seen it yet..
42024 nextNodes.push(n2); // can advance to last node
42027 nextNodes.forEach(function (nextNode) {
42028 // gather restrictions FROM this way
42029 var fromRestrictions = vgraph.parentRelations(entity).filter(function (r) {
42030 if (!r.isRestriction()) return false;
42031 var f = r.memberByRole('from');
42032 if (!f || f.id !== entity.id) return false;
42033 var isOnly = /^only_/.test(r.tags.restriction);
42034 if (!isOnly) return true; // `only_` restrictions only matter along the direction of the VIA - #4849
42036 var isOnlyVia = false;
42037 var v = r.membersByRole('via');
42039 if (v.length === 1 && v[0].type === 'node') {
42041 isOnlyVia = v[0].id === nextNode.id;
42044 for (var i = 0; i < v.length; i++) {
42045 if (v[i].type !== 'way') continue;
42046 var viaWay = vgraph.entity(v[i].id);
42048 if (viaWay.first() === nextNode.id || viaWay.last() === nextNode.id) {
42057 step(nextNode, currPath, currRestrictions.concat(fromRestrictions), false);
42060 } // assumes path is alternating way-node-way of odd length
42063 function pathToTurn(path) {
42064 if (path.length < 3) return;
42065 var fromWayId, fromNodeId, fromVertexId;
42066 var toWayId, toNodeId, toVertexId;
42067 var viaWayIds, viaNodeId, isUturn;
42068 fromWayId = path[0];
42069 toWayId = path[path.length - 1];
42071 if (path.length === 3 && fromWayId === toWayId) {
42073 var way = vgraph.entity(fromWayId);
42074 if (way.__oneWay) return null;
42076 viaNodeId = fromVertexId = toVertexId = path[1];
42077 fromNodeId = toNodeId = adjacentNode(fromWayId, viaNodeId);
42080 fromVertexId = path[1];
42081 fromNodeId = adjacentNode(fromWayId, fromVertexId);
42082 toVertexId = path[path.length - 2];
42083 toNodeId = adjacentNode(toWayId, toVertexId);
42085 if (path.length === 3) {
42086 viaNodeId = path[1];
42088 viaWayIds = path.filter(function (entityId) {
42089 return entityId[0] === 'w';
42091 viaWayIds = viaWayIds.slice(1, viaWayIds.length - 1); // remove first, last
42096 key: path.join('_'),
42101 vertex: fromVertexId
42115 function adjacentNode(wayId, affixId) {
42116 var nodes = vgraph.entity(wayId).nodes;
42117 return affixId === nodes[0] ? nodes[1] : nodes[nodes.length - 2];
42122 return intersection;
42124 function osmInferRestriction(graph, turn, projection) {
42125 var fromWay = graph.entity(turn.from.way);
42126 var fromNode = graph.entity(turn.from.node);
42127 var fromVertex = graph.entity(turn.from.vertex);
42128 var toWay = graph.entity(turn.to.way);
42129 var toNode = graph.entity(turn.to.node);
42130 var toVertex = graph.entity(turn.to.vertex);
42131 var fromOneWay = fromWay.tags.oneway === 'yes';
42132 var toOneWay = toWay.tags.oneway === 'yes';
42133 var angle = (geoAngle(fromVertex, fromNode, projection) - geoAngle(toVertex, toNode, projection)) * 180 / Math.PI;
42135 while (angle < 0) {
42139 if (fromNode === toNode) {
42140 return 'no_u_turn';
42143 if ((angle < 23 || angle > 336) && fromOneWay && toOneWay) {
42144 return 'no_u_turn'; // wider tolerance for u-turn if both ways are oneway
42147 if ((angle < 40 || angle > 319) && fromOneWay && toOneWay && turn.from.vertex !== turn.to.vertex) {
42148 return 'no_u_turn'; // even wider tolerance for u-turn if there is a via way (from !== to)
42152 return 'no_right_turn';
42156 return 'no_left_turn';
42159 return 'no_straight_on';
42162 function actionMergePolygon(ids, newRelationId) {
42163 function groupEntities(graph) {
42164 var entities = ids.map(function (id) {
42165 return graph.entity(id);
42167 var geometryGroups = utilArrayGroupBy(entities, function (entity) {
42168 if (entity.type === 'way' && entity.isClosed()) {
42169 return 'closedWay';
42170 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
42171 return 'multipolygon';
42176 return Object.assign({
42180 }, geometryGroups);
42183 var action = function action(graph) {
42184 var entities = groupEntities(graph); // An array representing all the polygons that are part of the multipolygon.
42186 // Each element is itself an array of objects with an id property, and has a
42187 // locs property which is an array of the locations forming the polygon.
42189 var polygons = entities.multipolygon.reduce(function (polygons, m) {
42190 return polygons.concat(osmJoinWays(m.members, graph));
42191 }, []).concat(entities.closedWay.map(function (d) {
42195 member.nodes = graph.childNodes(d);
42197 })); // contained is an array of arrays of boolean values,
42198 // where contained[j][k] is true iff the jth way is
42199 // contained by the kth way.
42201 var contained = polygons.map(function (w, i) {
42202 return polygons.map(function (d, n) {
42203 if (i === n) return null;
42204 return geoPolygonContainsPolygon(d.nodes.map(function (n) {
42206 }), w.nodes.map(function (n) {
42210 }); // Sort all polygons as either outer or inner ways
42215 while (polygons.length) {
42216 extractUncontained(polygons);
42217 polygons = polygons.filter(isContained);
42218 contained = contained.filter(isContained).map(filterContained);
42221 function isContained(d, i) {
42222 return contained[i].some(function (val) {
42227 function filterContained(d) {
42228 return d.filter(isContained);
42231 function extractUncontained(polygons) {
42232 polygons.forEach(function (d, i) {
42233 if (!isContained(d, i)) {
42234 d.forEach(function (member) {
42238 role: outer ? 'outer' : 'inner'
42244 } // Move all tags to one relation.
42245 // Keep the oldest multipolygon alive if it exists.
42250 if (entities.multipolygon.length > 0) {
42251 var oldestID = utilOldestID(entities.multipolygon.map(function (entity) {
42254 relation = entities.multipolygon.find(function (entity) {
42255 return entity.id === oldestID;
42258 relation = osmRelation({
42261 type: 'multipolygon'
42266 entities.multipolygon.forEach(function (m) {
42267 if (m.id !== relation.id) {
42268 relation = relation.mergeTags(m.tags);
42269 graph = graph.remove(m);
42272 entities.closedWay.forEach(function (way) {
42273 function isThisOuter(m) {
42274 return m.id === way.id && m.role !== 'inner';
42277 if (members.some(isThisOuter)) {
42278 relation = relation.mergeTags(way.tags);
42279 graph = graph.replace(way.update({
42284 return graph.replace(relation.update({
42286 tags: utilObjectOmit(relation.tags, ['area'])
42290 action.disabled = function (graph) {
42291 var entities = groupEntities(graph);
42293 if (entities.other.length > 0 || entities.closedWay.length + entities.multipolygon.length < 2) {
42294 return 'not_eligible';
42297 if (!entities.multipolygon.every(function (r) {
42298 return r.isComplete(graph);
42300 return 'incomplete_relation';
42303 if (!entities.multipolygon.length) {
42304 var sharedMultipolygons = [];
42305 entities.closedWay.forEach(function (way, i) {
42307 sharedMultipolygons = graph.parentMultipolygons(way);
42309 sharedMultipolygons = utilArrayIntersection(sharedMultipolygons, graph.parentMultipolygons(way));
42312 sharedMultipolygons = sharedMultipolygons.filter(function (relation) {
42313 return relation.members.length === entities.closedWay.length;
42316 if (sharedMultipolygons.length) {
42317 // don't create a new multipolygon if it'd be redundant
42318 return 'not_eligible';
42320 } else if (entities.closedWay.some(function (way) {
42321 return utilArrayIntersection(graph.parentMultipolygons(way), entities.multipolygon).length;
42323 // don't add a way to a multipolygon again if it's already a member
42324 return 'not_eligible';
42331 var DESCRIPTORS$1 = descriptors;
42332 var objectDefinePropertyModule = objectDefineProperty;
42333 var regExpFlags = regexpFlags$1;
42334 var fails$4 = fails$V;
42336 var RegExpPrototype = RegExp.prototype;
42338 var FORCED$2 = DESCRIPTORS$1 && fails$4(function () {
42339 // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
42340 return Object.getOwnPropertyDescriptor(RegExpPrototype, 'flags').get.call({ dotAll: true, sticky: true }) !== 'sy';
42343 // `RegExp.prototype.flags` getter
42344 // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
42345 if (FORCED$2) objectDefinePropertyModule.f(RegExpPrototype, 'flags', {
42346 configurable: true,
42350 var fastDeepEqual = function equal(a, b) {
42351 if (a === b) return true;
42353 if (a && b && _typeof(a) == 'object' && _typeof(b) == 'object') {
42354 if (a.constructor !== b.constructor) return false;
42355 var length, i, keys;
42357 if (Array.isArray(a)) {
42359 if (length != b.length) return false;
42361 for (i = length; i-- !== 0;) {
42362 if (!equal(a[i], b[i])) return false;
42368 if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
42369 if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
42370 if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
42371 keys = Object.keys(a);
42372 length = keys.length;
42373 if (length !== Object.keys(b).length) return false;
42375 for (i = length; i-- !== 0;) {
42376 if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
42379 for (i = length; i-- !== 0;) {
42381 if (!equal(a[key], b[key])) return false;
42385 } // true if both NaN, false otherwise
42388 return a !== a && b !== b;
42391 // J. W. Hunt and M. D. McIlroy, An algorithm for differential buffer
42392 // comparison, Bell Telephone Laboratories CSTR #41 (1976)
42393 // http://www.cs.dartmouth.edu/~doug/
42394 // https://en.wikipedia.org/wiki/Longest_common_subsequence_problem
42396 // Expects two arrays, finds longest common sequence
42398 function LCS(buffer1, buffer2) {
42399 var equivalenceClasses = {};
42401 for (var j = 0; j < buffer2.length; j++) {
42402 var item = buffer2[j];
42404 if (equivalenceClasses[item]) {
42405 equivalenceClasses[item].push(j);
42407 equivalenceClasses[item] = [j];
42416 var candidates = [NULLRESULT];
42418 for (var i = 0; i < buffer1.length; i++) {
42419 var _item = buffer1[i];
42420 var buffer2indices = equivalenceClasses[_item] || [];
42422 var c = candidates[0];
42424 for (var jx = 0; jx < buffer2indices.length; jx++) {
42425 var _j = buffer2indices[jx];
42428 for (s = r; s < candidates.length; s++) {
42429 if (candidates[s].buffer2index < _j && (s === candidates.length - 1 || candidates[s + 1].buffer2index > _j)) {
42434 if (s < candidates.length) {
42435 var newCandidate = {
42438 chain: candidates[s]
42441 if (r === candidates.length) {
42442 candidates.push(c);
42450 if (r === candidates.length) {
42451 break; // no point in examining further (j)s
42457 } // At this point, we know the LCS: it's in the reverse of the
42458 // linked-list through .chain of candidates[candidates.length - 1].
42461 return candidates[candidates.length - 1];
42462 } // We apply the LCS to build a 'comm'-style picture of the
42463 // offsets and lengths of mismatched chunks in the input
42464 // buffers. This is used by diff3MergeRegions.
42467 function diffIndices(buffer1, buffer2) {
42468 var lcs = LCS(buffer1, buffer2);
42470 var tail1 = buffer1.length;
42471 var tail2 = buffer2.length;
42473 for (var candidate = lcs; candidate !== null; candidate = candidate.chain) {
42474 var mismatchLength1 = tail1 - candidate.buffer1index - 1;
42475 var mismatchLength2 = tail2 - candidate.buffer2index - 1;
42476 tail1 = candidate.buffer1index;
42477 tail2 = candidate.buffer2index;
42479 if (mismatchLength1 || mismatchLength2) {
42481 buffer1: [tail1 + 1, mismatchLength1],
42482 buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1),
42483 buffer2: [tail2 + 1, mismatchLength2],
42484 buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2)
42491 } // We apply the LCS to build a JSON representation of a
42492 // independently derived from O, returns a fairly complicated
42493 // internal representation of merge decisions it's taken. The
42494 // interested reader may wish to consult
42496 // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce.
42497 // 'A Formal Investigation of ' In Arvind and Prasad,
42498 // editors, Foundations of Software Technology and Theoretical
42499 // Computer Science (FSTTCS), December 2007.
42501 // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
42505 function diff3MergeRegions(a, o, b) {
42506 // "hunks" are array subsets where `a` or `b` are different from `o`
42507 // https://www.gnu.org/software/diffutils/manual/html_node/diff3-Hunks.html
42510 function addHunk(h, ab) {
42513 oStart: h.buffer1[0],
42514 oLength: h.buffer1[1],
42515 // length of o to remove
42516 abStart: h.buffer2[0],
42517 abLength: h.buffer2[1] // length of a/b to insert
42518 // abContent: (ab === 'a' ? a : b).slice(h.buffer2[0], h.buffer2[0] + h.buffer2[1])
42523 diffIndices(o, a).forEach(function (item) {
42524 return addHunk(item, 'a');
42526 diffIndices(o, b).forEach(function (item) {
42527 return addHunk(item, 'b');
42529 hunks.sort(function (x, y) {
42530 return x.oStart - y.oStart;
42533 var currOffset = 0;
42535 function advanceTo(endOffset) {
42536 if (endOffset > currOffset) {
42540 bufferStart: currOffset,
42541 bufferLength: endOffset - currOffset,
42542 bufferContent: o.slice(currOffset, endOffset)
42544 currOffset = endOffset;
42548 while (hunks.length) {
42549 var hunk = hunks.shift();
42550 var regionStart = hunk.oStart;
42551 var regionEnd = hunk.oStart + hunk.oLength;
42552 var regionHunks = [hunk];
42553 advanceTo(regionStart); // Try to pull next overlapping hunk into this region
42555 while (hunks.length) {
42556 var nextHunk = hunks[0];
42557 var nextHunkStart = nextHunk.oStart;
42558 if (nextHunkStart > regionEnd) break; // no overlap
42560 regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength);
42561 regionHunks.push(hunks.shift());
42564 if (regionHunks.length === 1) {
42565 // Only one hunk touches this region, meaning that there is no conflict here.
42566 // Either `a` or `b` is inserting into a region of `o` unchanged by the other.
42567 if (hunk.abLength > 0) {
42568 var buffer = hunk.ab === 'a' ? a : b;
42572 bufferStart: hunk.abStart,
42573 bufferLength: hunk.abLength,
42574 bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength)
42578 // A true a/b conflict. Determine the bounds involved from `a`, `o`, and `b`.
42579 // Effectively merge all the `a` hunks into one giant hunk, then do the
42580 // same for the `b` hunks; then, correct for skew in the regions of `o`
42581 // that each side changed, and report appropriate spans for the three sides.
42583 a: [a.length, -1, o.length, -1],
42584 b: [b.length, -1, o.length, -1]
42587 while (regionHunks.length) {
42588 hunk = regionHunks.shift();
42589 var oStart = hunk.oStart;
42590 var oEnd = oStart + hunk.oLength;
42591 var abStart = hunk.abStart;
42592 var abEnd = abStart + hunk.abLength;
42593 var _b = bounds[hunk.ab];
42594 _b[0] = Math.min(abStart, _b[0]);
42595 _b[1] = Math.max(abEnd, _b[1]);
42596 _b[2] = Math.min(oStart, _b[2]);
42597 _b[3] = Math.max(oEnd, _b[3]);
42600 var aStart = bounds.a[0] + (regionStart - bounds.a[2]);
42601 var aEnd = bounds.a[1] + (regionEnd - bounds.a[3]);
42602 var bStart = bounds.b[0] + (regionStart - bounds.b[2]);
42603 var bEnd = bounds.b[1] + (regionEnd - bounds.b[3]);
42607 aLength: aEnd - aStart,
42608 aContent: a.slice(aStart, aEnd),
42609 oStart: regionStart,
42610 oLength: regionEnd - regionStart,
42611 oContent: o.slice(regionStart, regionEnd),
42613 bLength: bEnd - bStart,
42614 bContent: b.slice(bStart, bEnd)
42616 results.push(result);
42619 currOffset = regionEnd;
42622 advanceTo(o.length);
42624 } // Applies the output of diff3MergeRegions to actually
42625 // construct the merged buffer; the returned result alternates
42626 // between 'ok' and 'conflict' blocks.
42627 // A "false conflict" is where `a` and `b` both change the same from `o`
42630 function diff3Merge(a, o, b, options) {
42632 excludeFalseConflicts: true,
42633 stringSeparator: /\s+/
42635 options = Object.assign(defaults, options);
42636 var aString = typeof a === 'string';
42637 var oString = typeof o === 'string';
42638 var bString = typeof b === 'string';
42639 if (aString) a = a.split(options.stringSeparator);
42640 if (oString) o = o.split(options.stringSeparator);
42641 if (bString) b = b.split(options.stringSeparator);
42643 var regions = diff3MergeRegions(a, o, b);
42646 function flushOk() {
42647 if (okBuffer.length) {
42656 function isFalseConflict(a, b) {
42657 if (a.length !== b.length) return false;
42659 for (var i = 0; i < a.length; i++) {
42660 if (a[i] !== b[i]) return false;
42666 regions.forEach(function (region) {
42667 if (region.stable) {
42670 (_okBuffer = okBuffer).push.apply(_okBuffer, _toConsumableArray(region.bufferContent));
42672 if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) {
42675 (_okBuffer2 = okBuffer).push.apply(_okBuffer2, _toConsumableArray(region.aContent));
42680 a: region.aContent,
42681 aIndex: region.aStart,
42682 o: region.oContent,
42683 oIndex: region.oStart,
42684 b: region.bContent,
42685 bIndex: region.bStart
42695 var lodash = {exports: {}};
42697 (function (module, exports) {
42699 /** Used as a safe reference for `undefined` in pre-ES5 environments. */
42701 /** Used as the semantic version number. */
42703 var VERSION = '4.17.21';
42704 /** Used as the size to enable large array optimizations. */
42706 var LARGE_ARRAY_SIZE = 200;
42707 /** Error message constants. */
42709 var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
42710 FUNC_ERROR_TEXT = 'Expected a function',
42711 INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';
42712 /** Used to stand-in for `undefined` hash values. */
42714 var HASH_UNDEFINED = '__lodash_hash_undefined__';
42715 /** Used as the maximum memoize cache size. */
42717 var MAX_MEMOIZE_SIZE = 500;
42718 /** Used as the internal argument placeholder. */
42720 var PLACEHOLDER = '__lodash_placeholder__';
42721 /** Used to compose bitmasks for cloning. */
42723 var CLONE_DEEP_FLAG = 1,
42724 CLONE_FLAT_FLAG = 2,
42725 CLONE_SYMBOLS_FLAG = 4;
42726 /** Used to compose bitmasks for value comparisons. */
42728 var COMPARE_PARTIAL_FLAG = 1,
42729 COMPARE_UNORDERED_FLAG = 2;
42730 /** Used to compose bitmasks for function metadata. */
42732 var WRAP_BIND_FLAG = 1,
42733 WRAP_BIND_KEY_FLAG = 2,
42734 WRAP_CURRY_BOUND_FLAG = 4,
42735 WRAP_CURRY_FLAG = 8,
42736 WRAP_CURRY_RIGHT_FLAG = 16,
42737 WRAP_PARTIAL_FLAG = 32,
42738 WRAP_PARTIAL_RIGHT_FLAG = 64,
42739 WRAP_ARY_FLAG = 128,
42740 WRAP_REARG_FLAG = 256,
42741 WRAP_FLIP_FLAG = 512;
42742 /** Used as default options for `_.truncate`. */
42744 var DEFAULT_TRUNC_LENGTH = 30,
42745 DEFAULT_TRUNC_OMISSION = '...';
42746 /** Used to detect hot functions by number of calls within a span of milliseconds. */
42748 var HOT_COUNT = 800,
42750 /** Used to indicate the type of lazy iteratees. */
42752 var LAZY_FILTER_FLAG = 1,
42754 LAZY_WHILE_FLAG = 3;
42755 /** Used as references for various `Number` constants. */
42757 var INFINITY = 1 / 0,
42758 MAX_SAFE_INTEGER = 9007199254740991,
42759 MAX_INTEGER = 1.7976931348623157e+308,
42761 /** Used as references for the maximum length and index of an array. */
42763 var MAX_ARRAY_LENGTH = 4294967295,
42764 MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
42765 HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
42766 /** Used to associate wrap methods with their bit flags. */
42768 var wrapFlags = [['ary', WRAP_ARY_FLAG], ['bind', WRAP_BIND_FLAG], ['bindKey', WRAP_BIND_KEY_FLAG], ['curry', WRAP_CURRY_FLAG], ['curryRight', WRAP_CURRY_RIGHT_FLAG], ['flip', WRAP_FLIP_FLAG], ['partial', WRAP_PARTIAL_FLAG], ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], ['rearg', WRAP_REARG_FLAG]];
42769 /** `Object#toString` result references. */
42771 var argsTag = '[object Arguments]',
42772 arrayTag = '[object Array]',
42773 asyncTag = '[object AsyncFunction]',
42774 boolTag = '[object Boolean]',
42775 dateTag = '[object Date]',
42776 domExcTag = '[object DOMException]',
42777 errorTag = '[object Error]',
42778 funcTag = '[object Function]',
42779 genTag = '[object GeneratorFunction]',
42780 mapTag = '[object Map]',
42781 numberTag = '[object Number]',
42782 nullTag = '[object Null]',
42783 objectTag = '[object Object]',
42784 promiseTag = '[object Promise]',
42785 proxyTag = '[object Proxy]',
42786 regexpTag = '[object RegExp]',
42787 setTag = '[object Set]',
42788 stringTag = '[object String]',
42789 symbolTag = '[object Symbol]',
42790 undefinedTag = '[object Undefined]',
42791 weakMapTag = '[object WeakMap]',
42792 weakSetTag = '[object WeakSet]';
42793 var arrayBufferTag = '[object ArrayBuffer]',
42794 dataViewTag = '[object DataView]',
42795 float32Tag = '[object Float32Array]',
42796 float64Tag = '[object Float64Array]',
42797 int8Tag = '[object Int8Array]',
42798 int16Tag = '[object Int16Array]',
42799 int32Tag = '[object Int32Array]',
42800 uint8Tag = '[object Uint8Array]',
42801 uint8ClampedTag = '[object Uint8ClampedArray]',
42802 uint16Tag = '[object Uint16Array]',
42803 uint32Tag = '[object Uint32Array]';
42804 /** Used to match empty string literals in compiled template source. */
42806 var reEmptyStringLeading = /\b__p \+= '';/g,
42807 reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
42808 reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
42809 /** Used to match HTML entities and HTML characters. */
42811 var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
42812 reUnescapedHtml = /[&<>"']/g,
42813 reHasEscapedHtml = RegExp(reEscapedHtml.source),
42814 reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
42815 /** Used to match template delimiters. */
42817 var reEscape = /<%-([\s\S]+?)%>/g,
42818 reEvaluate = /<%([\s\S]+?)%>/g,
42819 reInterpolate = /<%=([\s\S]+?)%>/g;
42820 /** Used to match property names within property paths. */
42822 var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
42823 reIsPlainProp = /^\w*$/,
42824 rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
42826 * Used to match `RegExp`
42827 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
42830 var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
42831 reHasRegExpChar = RegExp(reRegExpChar.source);
42832 /** Used to match leading whitespace. */
42834 var reTrimStart = /^\s+/;
42835 /** Used to match a single whitespace character. */
42837 var reWhitespace = /\s/;
42838 /** Used to match wrap detail comments. */
42840 var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
42841 reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
42842 reSplitDetails = /,? & /;
42843 /** Used to match words composed of alphanumeric characters. */
42845 var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
42847 * Used to validate the `validate` option in `_.template` variable.
42849 * Forbids characters which could potentially change the meaning of the function argument definition:
42850 * - "()," (modification of function parameters)
42851 * - "=" (default value)
42852 * - "[]{}" (destructuring of function parameters)
42853 * - "/" (beginning of a comment)
42857 var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
42858 /** Used to match backslashes in property paths. */
42860 var reEscapeChar = /\\(\\)?/g;
42863 * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
42866 var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
42867 /** Used to match `RegExp` flags from their coerced string values. */
42869 var reFlags = /\w*$/;
42870 /** Used to detect bad signed hexadecimal string values. */
42872 var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
42873 /** Used to detect binary string values. */
42875 var reIsBinary = /^0b[01]+$/i;
42876 /** Used to detect host constructors (Safari). */
42878 var reIsHostCtor = /^\[object .+?Constructor\]$/;
42879 /** Used to detect octal string values. */
42881 var reIsOctal = /^0o[0-7]+$/i;
42882 /** Used to detect unsigned integer values. */
42884 var reIsUint = /^(?:0|[1-9]\d*)$/;
42885 /** Used to match Latin Unicode letters (excluding mathematical operators). */
42887 var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
42888 /** Used to ensure capturing order of template delimiters. */
42890 var reNoMatch = /($^)/;
42891 /** Used to match unescaped characters in compiled string literals. */
42893 var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
42894 /** Used to compose unicode character classes. */
42896 var rsAstralRange = "\\ud800-\\udfff",
42897 rsComboMarksRange = "\\u0300-\\u036f",
42898 reComboHalfMarksRange = "\\ufe20-\\ufe2f",
42899 rsComboSymbolsRange = "\\u20d0-\\u20ff",
42900 rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
42901 rsDingbatRange = "\\u2700-\\u27bf",
42902 rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
42903 rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
42904 rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
42905 rsPunctuationRange = "\\u2000-\\u206f",
42906 rsSpaceRange = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",
42907 rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
42908 rsVarRange = "\\ufe0e\\ufe0f",
42909 rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
42910 /** Used to compose unicode capture groups. */
42912 var rsApos = "['\u2019]",
42913 rsAstral = '[' + rsAstralRange + ']',
42914 rsBreak = '[' + rsBreakRange + ']',
42915 rsCombo = '[' + rsComboRange + ']',
42917 rsDingbat = '[' + rsDingbatRange + ']',
42918 rsLower = '[' + rsLowerRange + ']',
42919 rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
42920 rsFitz = "\\ud83c[\\udffb-\\udfff]",
42921 rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
42922 rsNonAstral = '[^' + rsAstralRange + ']',
42923 rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}",
42924 rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]",
42925 rsUpper = '[' + rsUpperRange + ']',
42927 /** Used to compose unicode regexes. */
42929 var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
42930 rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
42931 rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
42932 rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
42933 reOptMod = rsModifier + '?',
42934 rsOptVar = '[' + rsVarRange + ']?',
42935 rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
42936 rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])',
42937 rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])',
42938 rsSeq = rsOptVar + reOptMod + rsOptJoin,
42939 rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
42940 rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
42941 /** Used to match apostrophes. */
42943 var reApos = RegExp(rsApos, 'g');
42945 * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
42946 * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
42949 var reComboMark = RegExp(rsCombo, 'g');
42950 /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
42952 var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
42953 /** Used to match complex or compound words. */
42955 var reUnicodeWord = RegExp([rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')', rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower, rsUpper + '+' + rsOptContrUpper, rsOrdUpper, rsOrdLower, rsDigits, rsEmoji].join('|'), 'g');
42956 /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
42958 var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
42959 /** Used to detect strings that need a more robust regexp to match words. */
42961 var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
42962 /** Used to assign default `context` object properties. */
42964 var contextProps = ['Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'];
42965 /** Used to make template sourceURLs easier to identify. */
42967 var templateCounter = -1;
42968 /** Used to identify `toStringTag` values of typed arrays. */
42970 var typedArrayTags = {};
42971 typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true;
42972 typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
42973 /** Used to identify `toStringTag` values supported by `_.clone`. */
42975 var cloneableTags = {};
42976 cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
42977 cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false;
42978 /** Used to map Latin Unicode letters to basic Latin letters. */
42980 var deburredLetters = {
42981 // Latin-1 Supplement block.
43044 // Latin Extended-A block.
43174 /** Used to map characters to HTML entities. */
43176 var htmlEscapes = {
43183 /** Used to map HTML entities to characters. */
43185 var htmlUnescapes = {
43192 /** Used to escape characters for inclusion in compiled string literals. */
43194 var stringEscapes = {
43202 /** Built-in method references without a dependency on `root`. */
43204 var freeParseFloat = parseFloat,
43205 freeParseInt = parseInt;
43206 /** Detect free variable `global` from Node.js. */
43208 var freeGlobal = _typeof(commonjsGlobal) == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
43209 /** Detect free variable `self`. */
43211 var freeSelf = (typeof self === "undefined" ? "undefined" : _typeof(self)) == 'object' && self && self.Object === Object && self;
43212 /** Used as a reference to the global object. */
43214 var root = freeGlobal || freeSelf || Function('return this')();
43215 /** Detect free variable `exports`. */
43217 var freeExports = exports && !exports.nodeType && exports;
43218 /** Detect free variable `module`. */
43220 var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
43221 /** Detect the popular CommonJS extension `module.exports`. */
43223 var moduleExports = freeModule && freeModule.exports === freeExports;
43224 /** Detect free variable `process` from Node.js. */
43226 var freeProcess = moduleExports && freeGlobal.process;
43227 /** Used to access faster Node.js helpers. */
43229 var nodeUtil = function () {
43231 // Use `util.types` for Node.js 10+.
43232 var types = freeModule && freeModule.require && freeModule.require('util').types;
43236 } // Legacy `process.binding('util')` for Node.js < 10.
43239 return freeProcess && freeProcess.binding && freeProcess.binding('util');
43242 /* Node.js helper references. */
43245 var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
43246 nodeIsDate = nodeUtil && nodeUtil.isDate,
43247 nodeIsMap = nodeUtil && nodeUtil.isMap,
43248 nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
43249 nodeIsSet = nodeUtil && nodeUtil.isSet,
43250 nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
43251 /*--------------------------------------------------------------------------*/
43254 * A faster alternative to `Function#apply`, this function invokes `func`
43255 * with the `this` binding of `thisArg` and the arguments of `args`.
43258 * @param {Function} func The function to invoke.
43259 * @param {*} thisArg The `this` binding of `func`.
43260 * @param {Array} args The arguments to invoke `func` with.
43261 * @returns {*} Returns the result of `func`.
43264 function apply(func, thisArg, args) {
43265 switch (args.length) {
43267 return func.call(thisArg);
43270 return func.call(thisArg, args[0]);
43273 return func.call(thisArg, args[0], args[1]);
43276 return func.call(thisArg, args[0], args[1], args[2]);
43279 return func.apply(thisArg, args);
43282 * A specialized version of `baseAggregator` for arrays.
43285 * @param {Array} [array] The array to iterate over.
43286 * @param {Function} setter The function to set `accumulator` values.
43287 * @param {Function} iteratee The iteratee to transform keys.
43288 * @param {Object} accumulator The initial aggregated object.
43289 * @returns {Function} Returns `accumulator`.
43293 function arrayAggregator(array, setter, iteratee, accumulator) {
43295 length = array == null ? 0 : array.length;
43297 while (++index < length) {
43298 var value = array[index];
43299 setter(accumulator, value, iteratee(value), array);
43302 return accumulator;
43305 * A specialized version of `_.forEach` for arrays without support for
43306 * iteratee shorthands.
43309 * @param {Array} [array] The array to iterate over.
43310 * @param {Function} iteratee The function invoked per iteration.
43311 * @returns {Array} Returns `array`.
43315 function arrayEach(array, iteratee) {
43317 length = array == null ? 0 : array.length;
43319 while (++index < length) {
43320 if (iteratee(array[index], index, array) === false) {
43328 * A specialized version of `_.forEachRight` for arrays without support for
43329 * iteratee shorthands.
43332 * @param {Array} [array] The array to iterate over.
43333 * @param {Function} iteratee The function invoked per iteration.
43334 * @returns {Array} Returns `array`.
43338 function arrayEachRight(array, iteratee) {
43339 var length = array == null ? 0 : array.length;
43342 if (iteratee(array[length], length, array) === false) {
43350 * A specialized version of `_.every` for arrays without support for
43351 * iteratee shorthands.
43354 * @param {Array} [array] The array to iterate over.
43355 * @param {Function} predicate The function invoked per iteration.
43356 * @returns {boolean} Returns `true` if all elements pass the predicate check,
43361 function arrayEvery(array, predicate) {
43363 length = array == null ? 0 : array.length;
43365 while (++index < length) {
43366 if (!predicate(array[index], index, array)) {
43374 * A specialized version of `_.filter` for arrays without support for
43375 * iteratee shorthands.
43378 * @param {Array} [array] The array to iterate over.
43379 * @param {Function} predicate The function invoked per iteration.
43380 * @returns {Array} Returns the new filtered array.
43384 function arrayFilter(array, predicate) {
43386 length = array == null ? 0 : array.length,
43390 while (++index < length) {
43391 var value = array[index];
43393 if (predicate(value, index, array)) {
43394 result[resIndex++] = value;
43401 * A specialized version of `_.includes` for arrays without support for
43402 * specifying an index to search from.
43405 * @param {Array} [array] The array to inspect.
43406 * @param {*} target The value to search for.
43407 * @returns {boolean} Returns `true` if `target` is found, else `false`.
43411 function arrayIncludes(array, value) {
43412 var length = array == null ? 0 : array.length;
43413 return !!length && baseIndexOf(array, value, 0) > -1;
43416 * This function is like `arrayIncludes` except that it accepts a comparator.
43419 * @param {Array} [array] The array to inspect.
43420 * @param {*} target The value to search for.
43421 * @param {Function} comparator The comparator invoked per element.
43422 * @returns {boolean} Returns `true` if `target` is found, else `false`.
43426 function arrayIncludesWith(array, value, comparator) {
43428 length = array == null ? 0 : array.length;
43430 while (++index < length) {
43431 if (comparator(value, array[index])) {
43439 * A specialized version of `_.map` for arrays without support for iteratee
43443 * @param {Array} [array] The array to iterate over.
43444 * @param {Function} iteratee The function invoked per iteration.
43445 * @returns {Array} Returns the new mapped array.
43449 function arrayMap(array, iteratee) {
43451 length = array == null ? 0 : array.length,
43452 result = Array(length);
43454 while (++index < length) {
43455 result[index] = iteratee(array[index], index, array);
43461 * Appends the elements of `values` to `array`.
43464 * @param {Array} array The array to modify.
43465 * @param {Array} values The values to append.
43466 * @returns {Array} Returns `array`.
43470 function arrayPush(array, values) {
43472 length = values.length,
43473 offset = array.length;
43475 while (++index < length) {
43476 array[offset + index] = values[index];
43482 * A specialized version of `_.reduce` for arrays without support for
43483 * iteratee shorthands.
43486 * @param {Array} [array] The array to iterate over.
43487 * @param {Function} iteratee The function invoked per iteration.
43488 * @param {*} [accumulator] The initial value.
43489 * @param {boolean} [initAccum] Specify using the first element of `array` as
43490 * the initial value.
43491 * @returns {*} Returns the accumulated value.
43495 function arrayReduce(array, iteratee, accumulator, initAccum) {
43497 length = array == null ? 0 : array.length;
43499 if (initAccum && length) {
43500 accumulator = array[++index];
43503 while (++index < length) {
43504 accumulator = iteratee(accumulator, array[index], index, array);
43507 return accumulator;
43510 * A specialized version of `_.reduceRight` for arrays without support for
43511 * iteratee shorthands.
43514 * @param {Array} [array] The array to iterate over.
43515 * @param {Function} iteratee The function invoked per iteration.
43516 * @param {*} [accumulator] The initial value.
43517 * @param {boolean} [initAccum] Specify using the last element of `array` as
43518 * the initial value.
43519 * @returns {*} Returns the accumulated value.
43523 function arrayReduceRight(array, iteratee, accumulator, initAccum) {
43524 var length = array == null ? 0 : array.length;
43526 if (initAccum && length) {
43527 accumulator = array[--length];
43531 accumulator = iteratee(accumulator, array[length], length, array);
43534 return accumulator;
43537 * A specialized version of `_.some` for arrays without support for iteratee
43541 * @param {Array} [array] The array to iterate over.
43542 * @param {Function} predicate The function invoked per iteration.
43543 * @returns {boolean} Returns `true` if any element passes the predicate check,
43548 function arraySome(array, predicate) {
43550 length = array == null ? 0 : array.length;
43552 while (++index < length) {
43553 if (predicate(array[index], index, array)) {
43561 * Gets the size of an ASCII `string`.
43564 * @param {string} string The string inspect.
43565 * @returns {number} Returns the string size.
43569 var asciiSize = baseProperty('length');
43571 * Converts an ASCII `string` to an array.
43574 * @param {string} string The string to convert.
43575 * @returns {Array} Returns the converted array.
43578 function asciiToArray(string) {
43579 return string.split('');
43582 * Splits an ASCII `string` into an array of its words.
43585 * @param {string} The string to inspect.
43586 * @returns {Array} Returns the words of `string`.
43590 function asciiWords(string) {
43591 return string.match(reAsciiWord) || [];
43594 * The base implementation of methods like `_.findKey` and `_.findLastKey`,
43595 * without support for iteratee shorthands, which iterates over `collection`
43596 * using `eachFunc`.
43599 * @param {Array|Object} collection The collection to inspect.
43600 * @param {Function} predicate The function invoked per iteration.
43601 * @param {Function} eachFunc The function to iterate over `collection`.
43602 * @returns {*} Returns the found element or its key, else `undefined`.
43606 function baseFindKey(collection, predicate, eachFunc) {
43608 eachFunc(collection, function (value, key, collection) {
43609 if (predicate(value, key, collection)) {
43617 * The base implementation of `_.findIndex` and `_.findLastIndex` without
43618 * support for iteratee shorthands.
43621 * @param {Array} array The array to inspect.
43622 * @param {Function} predicate The function invoked per iteration.
43623 * @param {number} fromIndex The index to search from.
43624 * @param {boolean} [fromRight] Specify iterating from right to left.
43625 * @returns {number} Returns the index of the matched value, else `-1`.
43629 function baseFindIndex(array, predicate, fromIndex, fromRight) {
43630 var length = array.length,
43631 index = fromIndex + (fromRight ? 1 : -1);
43633 while (fromRight ? index-- : ++index < length) {
43634 if (predicate(array[index], index, array)) {
43642 * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
43645 * @param {Array} array The array to inspect.
43646 * @param {*} value The value to search for.
43647 * @param {number} fromIndex The index to search from.
43648 * @returns {number} Returns the index of the matched value, else `-1`.
43652 function baseIndexOf(array, value, fromIndex) {
43653 return value === value ? strictIndexOf(array, value, fromIndex) : baseFindIndex(array, baseIsNaN, fromIndex);
43656 * This function is like `baseIndexOf` except that it accepts a comparator.
43659 * @param {Array} array The array to inspect.
43660 * @param {*} value The value to search for.
43661 * @param {number} fromIndex The index to search from.
43662 * @param {Function} comparator The comparator invoked per element.
43663 * @returns {number} Returns the index of the matched value, else `-1`.
43667 function baseIndexOfWith(array, value, fromIndex, comparator) {
43668 var index = fromIndex - 1,
43669 length = array.length;
43671 while (++index < length) {
43672 if (comparator(array[index], value)) {
43680 * The base implementation of `_.isNaN` without support for number objects.
43683 * @param {*} value The value to check.
43684 * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
43688 function baseIsNaN(value) {
43689 return value !== value;
43692 * The base implementation of `_.mean` and `_.meanBy` without support for
43693 * iteratee shorthands.
43696 * @param {Array} array The array to iterate over.
43697 * @param {Function} iteratee The function invoked per iteration.
43698 * @returns {number} Returns the mean.
43702 function baseMean(array, iteratee) {
43703 var length = array == null ? 0 : array.length;
43704 return length ? baseSum(array, iteratee) / length : NAN;
43707 * The base implementation of `_.property` without support for deep paths.
43710 * @param {string} key The key of the property to get.
43711 * @returns {Function} Returns the new accessor function.
43715 function baseProperty(key) {
43716 return function (object) {
43717 return object == null ? undefined$1 : object[key];
43721 * The base implementation of `_.propertyOf` without support for deep paths.
43724 * @param {Object} object The object to query.
43725 * @returns {Function} Returns the new accessor function.
43729 function basePropertyOf(object) {
43730 return function (key) {
43731 return object == null ? undefined$1 : object[key];
43735 * The base implementation of `_.reduce` and `_.reduceRight`, without support
43736 * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
43739 * @param {Array|Object} collection The collection to iterate over.
43740 * @param {Function} iteratee The function invoked per iteration.
43741 * @param {*} accumulator The initial value.
43742 * @param {boolean} initAccum Specify using the first or last element of
43743 * `collection` as the initial value.
43744 * @param {Function} eachFunc The function to iterate over `collection`.
43745 * @returns {*} Returns the accumulated value.
43749 function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
43750 eachFunc(collection, function (value, index, collection) {
43751 accumulator = initAccum ? (initAccum = false, value) : iteratee(accumulator, value, index, collection);
43753 return accumulator;
43756 * The base implementation of `_.sortBy` which uses `comparer` to define the
43757 * sort order of `array` and replaces criteria objects with their corresponding
43761 * @param {Array} array The array to sort.
43762 * @param {Function} comparer The function to define sort order.
43763 * @returns {Array} Returns `array`.
43767 function baseSortBy(array, comparer) {
43768 var length = array.length;
43769 array.sort(comparer);
43772 array[length] = array[length].value;
43778 * The base implementation of `_.sum` and `_.sumBy` without support for
43779 * iteratee shorthands.
43782 * @param {Array} array The array to iterate over.
43783 * @param {Function} iteratee The function invoked per iteration.
43784 * @returns {number} Returns the sum.
43788 function baseSum(array, iteratee) {
43791 length = array.length;
43793 while (++index < length) {
43794 var current = iteratee(array[index]);
43796 if (current !== undefined$1) {
43797 result = result === undefined$1 ? current : result + current;
43804 * The base implementation of `_.times` without support for iteratee shorthands
43805 * or max array length checks.
43808 * @param {number} n The number of times to invoke `iteratee`.
43809 * @param {Function} iteratee The function invoked per iteration.
43810 * @returns {Array} Returns the array of results.
43814 function baseTimes(n, iteratee) {
43818 while (++index < n) {
43819 result[index] = iteratee(index);
43825 * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
43826 * of key-value pairs for `object` corresponding to the property names of `props`.
43829 * @param {Object} object The object to query.
43830 * @param {Array} props The property names to get values for.
43831 * @returns {Object} Returns the key-value pairs.
43835 function baseToPairs(object, props) {
43836 return arrayMap(props, function (key) {
43837 return [key, object[key]];
43841 * The base implementation of `_.trim`.
43844 * @param {string} string The string to trim.
43845 * @returns {string} Returns the trimmed string.
43849 function baseTrim(string) {
43850 return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') : string;
43853 * The base implementation of `_.unary` without support for storing metadata.
43856 * @param {Function} func The function to cap arguments for.
43857 * @returns {Function} Returns the new capped function.
43861 function baseUnary(func) {
43862 return function (value) {
43863 return func(value);
43867 * The base implementation of `_.values` and `_.valuesIn` which creates an
43868 * array of `object` property values corresponding to the property names
43872 * @param {Object} object The object to query.
43873 * @param {Array} props The property names to get values for.
43874 * @returns {Object} Returns the array of property values.
43878 function baseValues(object, props) {
43879 return arrayMap(props, function (key) {
43880 return object[key];
43884 * Checks if a `cache` value for `key` exists.
43887 * @param {Object} cache The cache to query.
43888 * @param {string} key The key of the entry to check.
43889 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
43893 function cacheHas(cache, key) {
43894 return cache.has(key);
43897 * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
43898 * that is not found in the character symbols.
43901 * @param {Array} strSymbols The string symbols to inspect.
43902 * @param {Array} chrSymbols The character symbols to find.
43903 * @returns {number} Returns the index of the first unmatched string symbol.
43907 function charsStartIndex(strSymbols, chrSymbols) {
43909 length = strSymbols.length;
43911 while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
43916 * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
43917 * that is not found in the character symbols.
43920 * @param {Array} strSymbols The string symbols to inspect.
43921 * @param {Array} chrSymbols The character symbols to find.
43922 * @returns {number} Returns the index of the last unmatched string symbol.
43926 function charsEndIndex(strSymbols, chrSymbols) {
43927 var index = strSymbols.length;
43929 while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
43934 * Gets the number of `placeholder` occurrences in `array`.
43937 * @param {Array} array The array to inspect.
43938 * @param {*} placeholder The placeholder to search for.
43939 * @returns {number} Returns the placeholder count.
43943 function countHolders(array, placeholder) {
43944 var length = array.length,
43948 if (array[length] === placeholder) {
43956 * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
43957 * letters to basic Latin letters.
43960 * @param {string} letter The matched letter to deburr.
43961 * @returns {string} Returns the deburred letter.
43965 var deburrLetter = basePropertyOf(deburredLetters);
43967 * Used by `_.escape` to convert characters to HTML entities.
43970 * @param {string} chr The matched character to escape.
43971 * @returns {string} Returns the escaped character.
43974 var escapeHtmlChar = basePropertyOf(htmlEscapes);
43976 * Used by `_.template` to escape characters for inclusion in compiled string literals.
43979 * @param {string} chr The matched character to escape.
43980 * @returns {string} Returns the escaped character.
43983 function escapeStringChar(chr) {
43984 return '\\' + stringEscapes[chr];
43987 * Gets the value at `key` of `object`.
43990 * @param {Object} [object] The object to query.
43991 * @param {string} key The key of the property to get.
43992 * @returns {*} Returns the property value.
43996 function getValue(object, key) {
43997 return object == null ? undefined$1 : object[key];
44000 * Checks if `string` contains Unicode symbols.
44003 * @param {string} string The string to inspect.
44004 * @returns {boolean} Returns `true` if a symbol is found, else `false`.
44008 function hasUnicode(string) {
44009 return reHasUnicode.test(string);
44012 * Checks if `string` contains a word composed of Unicode symbols.
44015 * @param {string} string The string to inspect.
44016 * @returns {boolean} Returns `true` if a word is found, else `false`.
44020 function hasUnicodeWord(string) {
44021 return reHasUnicodeWord.test(string);
44024 * Converts `iterator` to an array.
44027 * @param {Object} iterator The iterator to convert.
44028 * @returns {Array} Returns the converted array.
44032 function iteratorToArray(iterator) {
44036 while (!(data = iterator.next()).done) {
44037 result.push(data.value);
44043 * Converts `map` to its key-value pairs.
44046 * @param {Object} map The map to convert.
44047 * @returns {Array} Returns the key-value pairs.
44051 function mapToArray(map) {
44053 result = Array(map.size);
44054 map.forEach(function (value, key) {
44055 result[++index] = [key, value];
44060 * Creates a unary function that invokes `func` with its argument transformed.
44063 * @param {Function} func The function to wrap.
44064 * @param {Function} transform The argument transform.
44065 * @returns {Function} Returns the new function.
44069 function overArg(func, transform) {
44070 return function (arg) {
44071 return func(transform(arg));
44075 * Replaces all `placeholder` elements in `array` with an internal placeholder
44076 * and returns an array of their indexes.
44079 * @param {Array} array The array to modify.
44080 * @param {*} placeholder The placeholder to replace.
44081 * @returns {Array} Returns the new array of placeholder indexes.
44085 function replaceHolders(array, placeholder) {
44087 length = array.length,
44091 while (++index < length) {
44092 var value = array[index];
44094 if (value === placeholder || value === PLACEHOLDER) {
44095 array[index] = PLACEHOLDER;
44096 result[resIndex++] = index;
44103 * Converts `set` to an array of its values.
44106 * @param {Object} set The set to convert.
44107 * @returns {Array} Returns the values.
44111 function setToArray(set) {
44113 result = Array(set.size);
44114 set.forEach(function (value) {
44115 result[++index] = value;
44120 * Converts `set` to its value-value pairs.
44123 * @param {Object} set The set to convert.
44124 * @returns {Array} Returns the value-value pairs.
44128 function setToPairs(set) {
44130 result = Array(set.size);
44131 set.forEach(function (value) {
44132 result[++index] = [value, value];
44137 * A specialized version of `_.indexOf` which performs strict equality
44138 * comparisons of values, i.e. `===`.
44141 * @param {Array} array The array to inspect.
44142 * @param {*} value The value to search for.
44143 * @param {number} fromIndex The index to search from.
44144 * @returns {number} Returns the index of the matched value, else `-1`.
44148 function strictIndexOf(array, value, fromIndex) {
44149 var index = fromIndex - 1,
44150 length = array.length;
44152 while (++index < length) {
44153 if (array[index] === value) {
44161 * A specialized version of `_.lastIndexOf` which performs strict equality
44162 * comparisons of values, i.e. `===`.
44165 * @param {Array} array The array to inspect.
44166 * @param {*} value The value to search for.
44167 * @param {number} fromIndex The index to search from.
44168 * @returns {number} Returns the index of the matched value, else `-1`.
44172 function strictLastIndexOf(array, value, fromIndex) {
44173 var index = fromIndex + 1;
44176 if (array[index] === value) {
44184 * Gets the number of symbols in `string`.
44187 * @param {string} string The string to inspect.
44188 * @returns {number} Returns the string size.
44192 function stringSize(string) {
44193 return hasUnicode(string) ? unicodeSize(string) : asciiSize(string);
44196 * Converts `string` to an array.
44199 * @param {string} string The string to convert.
44200 * @returns {Array} Returns the converted array.
44204 function stringToArray(string) {
44205 return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string);
44208 * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
44209 * character of `string`.
44212 * @param {string} string The string to inspect.
44213 * @returns {number} Returns the index of the last non-whitespace character.
44217 function trimmedEndIndex(string) {
44218 var index = string.length;
44220 while (index-- && reWhitespace.test(string.charAt(index))) {}
44225 * Used by `_.unescape` to convert HTML entities to characters.
44228 * @param {string} chr The matched character to unescape.
44229 * @returns {string} Returns the unescaped character.
44233 var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
44235 * Gets the size of a Unicode `string`.
44238 * @param {string} string The string inspect.
44239 * @returns {number} Returns the string size.
44242 function unicodeSize(string) {
44243 var result = reUnicode.lastIndex = 0;
44245 while (reUnicode.test(string)) {
44252 * Converts a Unicode `string` to an array.
44255 * @param {string} string The string to convert.
44256 * @returns {Array} Returns the converted array.
44260 function unicodeToArray(string) {
44261 return string.match(reUnicode) || [];
44264 * Splits a Unicode `string` into an array of its words.
44267 * @param {string} The string to inspect.
44268 * @returns {Array} Returns the words of `string`.
44272 function unicodeWords(string) {
44273 return string.match(reUnicodeWord) || [];
44275 /*--------------------------------------------------------------------------*/
44278 * Create a new pristine `lodash` function using the `context` object.
44284 * @param {Object} [context=root] The context object.
44285 * @returns {Function} Returns a new `lodash` function.
44288 * _.mixin({ 'foo': _.constant('foo') });
44290 * var lodash = _.runInContext();
44291 * lodash.mixin({ 'bar': lodash.constant('bar') });
44293 * _.isFunction(_.foo);
44295 * _.isFunction(_.bar);
44298 * lodash.isFunction(lodash.foo);
44300 * lodash.isFunction(lodash.bar);
44303 * // Create a suped-up `defer` in Node.js.
44304 * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
44308 var runInContext = function runInContext(context) {
44309 context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
44310 /** Built-in constructor references. */
44312 var Array = context.Array,
44313 Date = context.Date,
44314 Error = context.Error,
44315 Function = context.Function,
44316 Math = context.Math,
44317 Object = context.Object,
44318 RegExp = context.RegExp,
44319 String = context.String,
44320 TypeError = context.TypeError;
44321 /** Used for built-in method references. */
44323 var arrayProto = Array.prototype,
44324 funcProto = Function.prototype,
44325 objectProto = Object.prototype;
44326 /** Used to detect overreaching core-js shims. */
44328 var coreJsData = context['__core-js_shared__'];
44329 /** Used to resolve the decompiled source of functions. */
44331 var funcToString = funcProto.toString;
44332 /** Used to check objects for own properties. */
44334 var hasOwnProperty = objectProto.hasOwnProperty;
44335 /** Used to generate unique IDs. */
44338 /** Used to detect methods masquerading as native. */
44340 var maskSrcKey = function () {
44341 var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
44342 return uid ? 'Symbol(src)_1.' + uid : '';
44345 * Used to resolve the
44346 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
44351 var nativeObjectToString = objectProto.toString;
44352 /** Used to infer the `Object` constructor. */
44354 var objectCtorString = funcToString.call(Object);
44355 /** Used to restore the original `_` reference in `_.noConflict`. */
44357 var oldDash = root._;
44358 /** Used to detect if a method is native. */
44360 var reIsNative = RegExp('^' + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&').replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$');
44361 /** Built-in value references. */
44363 var Buffer = moduleExports ? context.Buffer : undefined$1,
44364 _Symbol = context.Symbol,
44365 Uint8Array = context.Uint8Array,
44366 allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined$1,
44367 getPrototype = overArg(Object.getPrototypeOf, Object),
44368 objectCreate = Object.create,
44369 propertyIsEnumerable = objectProto.propertyIsEnumerable,
44370 splice = arrayProto.splice,
44371 spreadableSymbol = _Symbol ? _Symbol.isConcatSpreadable : undefined$1,
44372 symIterator = _Symbol ? _Symbol.iterator : undefined$1,
44373 symToStringTag = _Symbol ? _Symbol.toStringTag : undefined$1;
44375 var defineProperty = function () {
44377 var func = getNative(Object, 'defineProperty');
44382 /** Mocked built-ins. */
44385 var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
44386 ctxNow = Date && Date.now !== root.Date.now && Date.now,
44387 ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
44388 /* Built-in method references for those with the same name as other `lodash` methods. */
44390 var nativeCeil = Math.ceil,
44391 nativeFloor = Math.floor,
44392 nativeGetSymbols = Object.getOwnPropertySymbols,
44393 nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined$1,
44394 nativeIsFinite = context.isFinite,
44395 nativeJoin = arrayProto.join,
44396 nativeKeys = overArg(Object.keys, Object),
44397 nativeMax = Math.max,
44398 nativeMin = Math.min,
44399 nativeNow = Date.now,
44400 nativeParseInt = context.parseInt,
44401 nativeRandom = Math.random,
44402 nativeReverse = arrayProto.reverse;
44403 /* Built-in method references that are verified to be native. */
44405 var DataView = getNative(context, 'DataView'),
44406 Map = getNative(context, 'Map'),
44407 Promise = getNative(context, 'Promise'),
44408 Set = getNative(context, 'Set'),
44409 WeakMap = getNative(context, 'WeakMap'),
44410 nativeCreate = getNative(Object, 'create');
44411 /** Used to store function metadata. */
44413 var metaMap = WeakMap && new WeakMap();
44414 /** Used to lookup unminified function names. */
44416 var realNames = {};
44417 /** Used to detect maps, sets, and weakmaps. */
44419 var dataViewCtorString = toSource(DataView),
44420 mapCtorString = toSource(Map),
44421 promiseCtorString = toSource(Promise),
44422 setCtorString = toSource(Set),
44423 weakMapCtorString = toSource(WeakMap);
44424 /** Used to convert symbols to primitives and strings. */
44426 var symbolProto = _Symbol ? _Symbol.prototype : undefined$1,
44427 symbolValueOf = symbolProto ? symbolProto.valueOf : undefined$1,
44428 symbolToString = symbolProto ? symbolProto.toString : undefined$1;
44429 /*------------------------------------------------------------------------*/
44432 * Creates a `lodash` object which wraps `value` to enable implicit method
44433 * chain sequences. Methods that operate on and return arrays, collections,
44434 * and functions can be chained together. Methods that retrieve a single value
44435 * or may return a primitive value will automatically end the chain sequence
44436 * and return the unwrapped value. Otherwise, the value must be unwrapped
44439 * Explicit chain sequences, which must be unwrapped with `_#value`, may be
44440 * enabled using `_.chain`.
44442 * The execution of chained methods is lazy, that is, it's deferred until
44443 * `_#value` is implicitly or explicitly called.
44445 * Lazy evaluation allows several methods to support shortcut fusion.
44446 * Shortcut fusion is an optimization to merge iteratee calls; this avoids
44447 * the creation of intermediate arrays and can greatly reduce the number of
44448 * iteratee executions. Sections of a chain sequence qualify for shortcut
44449 * fusion if the section is applied to an array and iteratees accept only
44450 * one argument. The heuristic for whether a section qualifies for shortcut
44451 * fusion is subject to change.
44453 * Chaining is supported in custom builds as long as the `_#value` method is
44454 * directly or indirectly included in the build.
44456 * In addition to lodash methods, wrappers have `Array` and `String` methods.
44458 * The wrapper `Array` methods are:
44459 * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
44461 * The wrapper `String` methods are:
44462 * `replace` and `split`
44464 * The wrapper methods that support shortcut fusion are:
44465 * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
44466 * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
44467 * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
44469 * The chainable wrapper methods are:
44470 * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
44471 * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
44472 * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
44473 * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
44474 * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
44475 * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
44476 * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
44477 * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
44478 * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
44479 * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
44480 * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
44481 * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
44482 * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
44483 * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
44484 * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
44485 * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
44486 * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
44487 * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
44488 * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
44489 * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
44490 * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
44491 * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
44492 * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
44493 * `zipObject`, `zipObjectDeep`, and `zipWith`
44495 * The wrapper methods that are **not** chainable by default are:
44496 * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
44497 * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
44498 * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
44499 * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
44500 * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
44501 * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
44502 * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
44503 * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
44504 * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
44505 * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
44506 * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
44507 * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
44508 * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
44509 * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
44510 * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
44511 * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
44512 * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
44513 * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
44514 * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
44515 * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
44516 * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
44517 * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
44518 * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
44519 * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
44520 * `upperFirst`, `value`, and `words`
44525 * @param {*} value The value to wrap in a `lodash` instance.
44526 * @returns {Object} Returns the new `lodash` wrapper instance.
44529 * function square(n) {
44533 * var wrapped = _([1, 2, 3]);
44535 * // Returns an unwrapped value.
44536 * wrapped.reduce(_.add);
44539 * // Returns a wrapped value.
44540 * var squares = wrapped.map(square);
44542 * _.isArray(squares);
44545 * _.isArray(squares.value());
44549 function lodash(value) {
44550 if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
44551 if (value instanceof LodashWrapper) {
44555 if (hasOwnProperty.call(value, '__wrapped__')) {
44556 return wrapperClone(value);
44560 return new LodashWrapper(value);
44563 * The base implementation of `_.create` without support for assigning
44564 * properties to the created object.
44567 * @param {Object} proto The object to inherit from.
44568 * @returns {Object} Returns the new object.
44572 var baseCreate = function () {
44573 function object() {}
44575 return function (proto) {
44576 if (!isObject(proto)) {
44580 if (objectCreate) {
44581 return objectCreate(proto);
44584 object.prototype = proto;
44585 var result = new object();
44586 object.prototype = undefined$1;
44591 * The function whose prototype chain sequence wrappers inherit from.
44597 function baseLodash() {// No operation performed.
44600 * The base constructor for creating `lodash` wrapper objects.
44603 * @param {*} value The value to wrap.
44604 * @param {boolean} [chainAll] Enable explicit method chain sequences.
44608 function LodashWrapper(value, chainAll) {
44609 this.__wrapped__ = value;
44610 this.__actions__ = [];
44611 this.__chain__ = !!chainAll;
44612 this.__index__ = 0;
44613 this.__values__ = undefined$1;
44616 * By default, the template delimiters used by lodash are like those in
44617 * embedded Ruby (ERB) as well as ES2015 template strings. Change the
44618 * following template settings to use alternative delimiters.
44626 lodash.templateSettings = {
44628 * Used to detect `data` property values to be HTML-escaped.
44630 * @memberOf _.templateSettings
44633 'escape': reEscape,
44636 * Used to detect code to be evaluated.
44638 * @memberOf _.templateSettings
44641 'evaluate': reEvaluate,
44644 * Used to detect `data` property values to inject.
44646 * @memberOf _.templateSettings
44649 'interpolate': reInterpolate,
44652 * Used to reference the data object in the template text.
44654 * @memberOf _.templateSettings
44660 * Used to import variables into the compiled template.
44662 * @memberOf _.templateSettings
44667 * A reference to the `lodash` function.
44669 * @memberOf _.templateSettings.imports
44674 }; // Ensure wrappers are instances of `baseLodash`.
44676 lodash.prototype = baseLodash.prototype;
44677 lodash.prototype.constructor = lodash;
44678 LodashWrapper.prototype = baseCreate(baseLodash.prototype);
44679 LodashWrapper.prototype.constructor = LodashWrapper;
44680 /*------------------------------------------------------------------------*/
44683 * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
44687 * @param {*} value The value to wrap.
44690 function LazyWrapper(value) {
44691 this.__wrapped__ = value;
44692 this.__actions__ = [];
44694 this.__filtered__ = false;
44695 this.__iteratees__ = [];
44696 this.__takeCount__ = MAX_ARRAY_LENGTH;
44697 this.__views__ = [];
44700 * Creates a clone of the lazy wrapper object.
44704 * @memberOf LazyWrapper
44705 * @returns {Object} Returns the cloned `LazyWrapper` object.
44709 function lazyClone() {
44710 var result = new LazyWrapper(this.__wrapped__);
44711 result.__actions__ = copyArray(this.__actions__);
44712 result.__dir__ = this.__dir__;
44713 result.__filtered__ = this.__filtered__;
44714 result.__iteratees__ = copyArray(this.__iteratees__);
44715 result.__takeCount__ = this.__takeCount__;
44716 result.__views__ = copyArray(this.__views__);
44720 * Reverses the direction of lazy iteration.
44724 * @memberOf LazyWrapper
44725 * @returns {Object} Returns the new reversed `LazyWrapper` object.
44729 function lazyReverse() {
44730 if (this.__filtered__) {
44731 var result = new LazyWrapper(this);
44732 result.__dir__ = -1;
44733 result.__filtered__ = true;
44735 result = this.clone();
44736 result.__dir__ *= -1;
44742 * Extracts the unwrapped value from its lazy wrapper.
44746 * @memberOf LazyWrapper
44747 * @returns {*} Returns the unwrapped value.
44751 function lazyValue() {
44752 var array = this.__wrapped__.value(),
44753 dir = this.__dir__,
44754 isArr = isArray(array),
44756 arrLength = isArr ? array.length : 0,
44757 view = getView(0, arrLength, this.__views__),
44758 start = view.start,
44760 length = end - start,
44761 index = isRight ? end : start - 1,
44762 iteratees = this.__iteratees__,
44763 iterLength = iteratees.length,
44765 takeCount = nativeMin(length, this.__takeCount__);
44767 if (!isArr || !isRight && arrLength == length && takeCount == length) {
44768 return baseWrapperValue(array, this.__actions__);
44773 outer: while (length-- && resIndex < takeCount) {
44775 var iterIndex = -1,
44776 value = array[index];
44778 while (++iterIndex < iterLength) {
44779 var data = iteratees[iterIndex],
44780 iteratee = data.iteratee,
44782 computed = iteratee(value);
44784 if (type == LAZY_MAP_FLAG) {
44786 } else if (!computed) {
44787 if (type == LAZY_FILTER_FLAG) {
44795 result[resIndex++] = value;
44799 } // Ensure `LazyWrapper` is an instance of `baseLodash`.
44802 LazyWrapper.prototype = baseCreate(baseLodash.prototype);
44803 LazyWrapper.prototype.constructor = LazyWrapper;
44804 /*------------------------------------------------------------------------*/
44807 * Creates a hash object.
44811 * @param {Array} [entries] The key-value pairs to cache.
44814 function Hash(entries) {
44816 length = entries == null ? 0 : entries.length;
44819 while (++index < length) {
44820 var entry = entries[index];
44821 this.set(entry[0], entry[1]);
44825 * Removes all key-value entries from the hash.
44833 function hashClear() {
44834 this.__data__ = nativeCreate ? nativeCreate(null) : {};
44838 * Removes `key` and its value from the hash.
44843 * @param {Object} hash The hash to modify.
44844 * @param {string} key The key of the value to remove.
44845 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
44849 function hashDelete(key) {
44850 var result = this.has(key) && delete this.__data__[key];
44851 this.size -= result ? 1 : 0;
44855 * Gets the hash value for `key`.
44860 * @param {string} key The key of the value to get.
44861 * @returns {*} Returns the entry value.
44865 function hashGet(key) {
44866 var data = this.__data__;
44868 if (nativeCreate) {
44869 var result = data[key];
44870 return result === HASH_UNDEFINED ? undefined$1 : result;
44873 return hasOwnProperty.call(data, key) ? data[key] : undefined$1;
44876 * Checks if a hash value for `key` exists.
44881 * @param {string} key The key of the entry to check.
44882 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
44886 function hashHas(key) {
44887 var data = this.__data__;
44888 return nativeCreate ? data[key] !== undefined$1 : hasOwnProperty.call(data, key);
44891 * Sets the hash `key` to `value`.
44896 * @param {string} key The key of the value to set.
44897 * @param {*} value The value to set.
44898 * @returns {Object} Returns the hash instance.
44902 function hashSet(key, value) {
44903 var data = this.__data__;
44904 this.size += this.has(key) ? 0 : 1;
44905 data[key] = nativeCreate && value === undefined$1 ? HASH_UNDEFINED : value;
44907 } // Add methods to `Hash`.
44910 Hash.prototype.clear = hashClear;
44911 Hash.prototype['delete'] = hashDelete;
44912 Hash.prototype.get = hashGet;
44913 Hash.prototype.has = hashHas;
44914 Hash.prototype.set = hashSet;
44915 /*------------------------------------------------------------------------*/
44918 * Creates an list cache object.
44922 * @param {Array} [entries] The key-value pairs to cache.
44925 function ListCache(entries) {
44927 length = entries == null ? 0 : entries.length;
44930 while (++index < length) {
44931 var entry = entries[index];
44932 this.set(entry[0], entry[1]);
44936 * Removes all key-value entries from the list cache.
44940 * @memberOf ListCache
44944 function listCacheClear() {
44945 this.__data__ = [];
44949 * Removes `key` and its value from the list cache.
44953 * @memberOf ListCache
44954 * @param {string} key The key of the value to remove.
44955 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
44959 function listCacheDelete(key) {
44960 var data = this.__data__,
44961 index = assocIndexOf(data, key);
44967 var lastIndex = data.length - 1;
44969 if (index == lastIndex) {
44972 splice.call(data, index, 1);
44979 * Gets the list cache value for `key`.
44983 * @memberOf ListCache
44984 * @param {string} key The key of the value to get.
44985 * @returns {*} Returns the entry value.
44989 function listCacheGet(key) {
44990 var data = this.__data__,
44991 index = assocIndexOf(data, key);
44992 return index < 0 ? undefined$1 : data[index][1];
44995 * Checks if a list cache value for `key` exists.
44999 * @memberOf ListCache
45000 * @param {string} key The key of the entry to check.
45001 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
45005 function listCacheHas(key) {
45006 return assocIndexOf(this.__data__, key) > -1;
45009 * Sets the list cache `key` to `value`.
45013 * @memberOf ListCache
45014 * @param {string} key The key of the value to set.
45015 * @param {*} value The value to set.
45016 * @returns {Object} Returns the list cache instance.
45020 function listCacheSet(key, value) {
45021 var data = this.__data__,
45022 index = assocIndexOf(data, key);
45026 data.push([key, value]);
45028 data[index][1] = value;
45032 } // Add methods to `ListCache`.
45035 ListCache.prototype.clear = listCacheClear;
45036 ListCache.prototype['delete'] = listCacheDelete;
45037 ListCache.prototype.get = listCacheGet;
45038 ListCache.prototype.has = listCacheHas;
45039 ListCache.prototype.set = listCacheSet;
45040 /*------------------------------------------------------------------------*/
45043 * Creates a map cache object to store key-value pairs.
45047 * @param {Array} [entries] The key-value pairs to cache.
45050 function MapCache(entries) {
45052 length = entries == null ? 0 : entries.length;
45055 while (++index < length) {
45056 var entry = entries[index];
45057 this.set(entry[0], entry[1]);
45061 * Removes all key-value entries from the map.
45065 * @memberOf MapCache
45069 function mapCacheClear() {
45072 'hash': new Hash(),
45073 'map': new (Map || ListCache)(),
45074 'string': new Hash()
45078 * Removes `key` and its value from the map.
45082 * @memberOf MapCache
45083 * @param {string} key The key of the value to remove.
45084 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
45088 function mapCacheDelete(key) {
45089 var result = getMapData(this, key)['delete'](key);
45090 this.size -= result ? 1 : 0;
45094 * Gets the map value for `key`.
45098 * @memberOf MapCache
45099 * @param {string} key The key of the value to get.
45100 * @returns {*} Returns the entry value.
45104 function mapCacheGet(key) {
45105 return getMapData(this, key).get(key);
45108 * Checks if a map value for `key` exists.
45112 * @memberOf MapCache
45113 * @param {string} key The key of the entry to check.
45114 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
45118 function mapCacheHas(key) {
45119 return getMapData(this, key).has(key);
45122 * Sets the map `key` to `value`.
45126 * @memberOf MapCache
45127 * @param {string} key The key of the value to set.
45128 * @param {*} value The value to set.
45129 * @returns {Object} Returns the map cache instance.
45133 function mapCacheSet(key, value) {
45134 var data = getMapData(this, key),
45136 data.set(key, value);
45137 this.size += data.size == size ? 0 : 1;
45139 } // Add methods to `MapCache`.
45142 MapCache.prototype.clear = mapCacheClear;
45143 MapCache.prototype['delete'] = mapCacheDelete;
45144 MapCache.prototype.get = mapCacheGet;
45145 MapCache.prototype.has = mapCacheHas;
45146 MapCache.prototype.set = mapCacheSet;
45147 /*------------------------------------------------------------------------*/
45151 * Creates an array cache object to store unique values.
45155 * @param {Array} [values] The values to cache.
45158 function SetCache(values) {
45160 length = values == null ? 0 : values.length;
45161 this.__data__ = new MapCache();
45163 while (++index < length) {
45164 this.add(values[index]);
45168 * Adds `value` to the array cache.
45172 * @memberOf SetCache
45174 * @param {*} value The value to cache.
45175 * @returns {Object} Returns the cache instance.
45179 function setCacheAdd(value) {
45180 this.__data__.set(value, HASH_UNDEFINED);
45185 * Checks if `value` is in the array cache.
45189 * @memberOf SetCache
45190 * @param {*} value The value to search for.
45191 * @returns {number} Returns `true` if `value` is found, else `false`.
45195 function setCacheHas(value) {
45196 return this.__data__.has(value);
45197 } // Add methods to `SetCache`.
45200 SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
45201 SetCache.prototype.has = setCacheHas;
45202 /*------------------------------------------------------------------------*/
45205 * Creates a stack cache object to store key-value pairs.
45209 * @param {Array} [entries] The key-value pairs to cache.
45212 function Stack(entries) {
45213 var data = this.__data__ = new ListCache(entries);
45214 this.size = data.size;
45217 * Removes all key-value entries from the stack.
45225 function stackClear() {
45226 this.__data__ = new ListCache();
45230 * Removes `key` and its value from the stack.
45235 * @param {string} key The key of the value to remove.
45236 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
45240 function stackDelete(key) {
45241 var data = this.__data__,
45242 result = data['delete'](key);
45243 this.size = data.size;
45247 * Gets the stack value for `key`.
45252 * @param {string} key The key of the value to get.
45253 * @returns {*} Returns the entry value.
45257 function stackGet(key) {
45258 return this.__data__.get(key);
45261 * Checks if a stack value for `key` exists.
45266 * @param {string} key The key of the entry to check.
45267 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
45271 function stackHas(key) {
45272 return this.__data__.has(key);
45275 * Sets the stack `key` to `value`.
45280 * @param {string} key The key of the value to set.
45281 * @param {*} value The value to set.
45282 * @returns {Object} Returns the stack cache instance.
45286 function stackSet(key, value) {
45287 var data = this.__data__;
45289 if (data instanceof ListCache) {
45290 var pairs = data.__data__;
45292 if (!Map || pairs.length < LARGE_ARRAY_SIZE - 1) {
45293 pairs.push([key, value]);
45294 this.size = ++data.size;
45298 data = this.__data__ = new MapCache(pairs);
45301 data.set(key, value);
45302 this.size = data.size;
45304 } // Add methods to `Stack`.
45307 Stack.prototype.clear = stackClear;
45308 Stack.prototype['delete'] = stackDelete;
45309 Stack.prototype.get = stackGet;
45310 Stack.prototype.has = stackHas;
45311 Stack.prototype.set = stackSet;
45312 /*------------------------------------------------------------------------*/
45315 * Creates an array of the enumerable property names of the array-like `value`.
45318 * @param {*} value The value to query.
45319 * @param {boolean} inherited Specify returning inherited property names.
45320 * @returns {Array} Returns the array of property names.
45323 function arrayLikeKeys(value, inherited) {
45324 var isArr = isArray(value),
45325 isArg = !isArr && isArguments(value),
45326 isBuff = !isArr && !isArg && isBuffer(value),
45327 isType = !isArr && !isArg && !isBuff && isTypedArray(value),
45328 skipIndexes = isArr || isArg || isBuff || isType,
45329 result = skipIndexes ? baseTimes(value.length, String) : [],
45330 length = result.length;
45332 for (var key in value) {
45333 if ((inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && ( // Safari 9 has enumerable `arguments.length` in strict mode.
45334 key == 'length' || // Node.js 0.10 has enumerable non-index properties on buffers.
45335 isBuff && (key == 'offset' || key == 'parent') || // PhantomJS 2 has enumerable non-index properties on typed arrays.
45336 isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset') || // Skip index properties.
45337 isIndex(key, length)))) {
45345 * A specialized version of `_.sample` for arrays.
45348 * @param {Array} array The array to sample.
45349 * @returns {*} Returns the random element.
45353 function arraySample(array) {
45354 var length = array.length;
45355 return length ? array[baseRandom(0, length - 1)] : undefined$1;
45358 * A specialized version of `_.sampleSize` for arrays.
45361 * @param {Array} array The array to sample.
45362 * @param {number} n The number of elements to sample.
45363 * @returns {Array} Returns the random elements.
45367 function arraySampleSize(array, n) {
45368 return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
45371 * A specialized version of `_.shuffle` for arrays.
45374 * @param {Array} array The array to shuffle.
45375 * @returns {Array} Returns the new shuffled array.
45379 function arrayShuffle(array) {
45380 return shuffleSelf(copyArray(array));
45383 * This function is like `assignValue` except that it doesn't assign
45384 * `undefined` values.
45387 * @param {Object} object The object to modify.
45388 * @param {string} key The key of the property to assign.
45389 * @param {*} value The value to assign.
45393 function assignMergeValue(object, key, value) {
45394 if (value !== undefined$1 && !eq(object[key], value) || value === undefined$1 && !(key in object)) {
45395 baseAssignValue(object, key, value);
45399 * Assigns `value` to `key` of `object` if the existing value is not equivalent
45400 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
45401 * for equality comparisons.
45404 * @param {Object} object The object to modify.
45405 * @param {string} key The key of the property to assign.
45406 * @param {*} value The value to assign.
45410 function assignValue(object, key, value) {
45411 var objValue = object[key];
45413 if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || value === undefined$1 && !(key in object)) {
45414 baseAssignValue(object, key, value);
45418 * Gets the index at which the `key` is found in `array` of key-value pairs.
45421 * @param {Array} array The array to inspect.
45422 * @param {*} key The key to search for.
45423 * @returns {number} Returns the index of the matched value, else `-1`.
45427 function assocIndexOf(array, key) {
45428 var length = array.length;
45431 if (eq(array[length][0], key)) {
45439 * Aggregates elements of `collection` on `accumulator` with keys transformed
45440 * by `iteratee` and values set by `setter`.
45443 * @param {Array|Object} collection The collection to iterate over.
45444 * @param {Function} setter The function to set `accumulator` values.
45445 * @param {Function} iteratee The iteratee to transform keys.
45446 * @param {Object} accumulator The initial aggregated object.
45447 * @returns {Function} Returns `accumulator`.
45451 function baseAggregator(collection, setter, iteratee, accumulator) {
45452 baseEach(collection, function (value, key, collection) {
45453 setter(accumulator, value, iteratee(value), collection);
45455 return accumulator;
45458 * The base implementation of `_.assign` without support for multiple sources
45459 * or `customizer` functions.
45462 * @param {Object} object The destination object.
45463 * @param {Object} source The source object.
45464 * @returns {Object} Returns `object`.
45468 function baseAssign(object, source) {
45469 return object && copyObject(source, keys(source), object);
45472 * The base implementation of `_.assignIn` without support for multiple sources
45473 * or `customizer` functions.
45476 * @param {Object} object The destination object.
45477 * @param {Object} source The source object.
45478 * @returns {Object} Returns `object`.
45482 function baseAssignIn(object, source) {
45483 return object && copyObject(source, keysIn(source), object);
45486 * The base implementation of `assignValue` and `assignMergeValue` without
45490 * @param {Object} object The object to modify.
45491 * @param {string} key The key of the property to assign.
45492 * @param {*} value The value to assign.
45496 function baseAssignValue(object, key, value) {
45497 if (key == '__proto__' && defineProperty) {
45498 defineProperty(object, key, {
45499 'configurable': true,
45500 'enumerable': true,
45505 object[key] = value;
45509 * The base implementation of `_.at` without support for individual paths.
45512 * @param {Object} object The object to iterate over.
45513 * @param {string[]} paths The property paths to pick.
45514 * @returns {Array} Returns the picked elements.
45518 function baseAt(object, paths) {
45520 length = paths.length,
45521 result = Array(length),
45522 skip = object == null;
45524 while (++index < length) {
45525 result[index] = skip ? undefined$1 : get(object, paths[index]);
45531 * The base implementation of `_.clamp` which doesn't coerce arguments.
45534 * @param {number} number The number to clamp.
45535 * @param {number} [lower] The lower bound.
45536 * @param {number} upper The upper bound.
45537 * @returns {number} Returns the clamped number.
45541 function baseClamp(number, lower, upper) {
45542 if (number === number) {
45543 if (upper !== undefined$1) {
45544 number = number <= upper ? number : upper;
45547 if (lower !== undefined$1) {
45548 number = number >= lower ? number : lower;
45555 * The base implementation of `_.clone` and `_.cloneDeep` which tracks
45556 * traversed objects.
45559 * @param {*} value The value to clone.
45560 * @param {boolean} bitmask The bitmask flags.
45562 * 2 - Flatten inherited properties
45563 * 4 - Clone symbols
45564 * @param {Function} [customizer] The function to customize cloning.
45565 * @param {string} [key] The key of `value`.
45566 * @param {Object} [object] The parent object of `value`.
45567 * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
45568 * @returns {*} Returns the cloned value.
45572 function baseClone(value, bitmask, customizer, key, object, stack) {
45574 isDeep = bitmask & CLONE_DEEP_FLAG,
45575 isFlat = bitmask & CLONE_FLAT_FLAG,
45576 isFull = bitmask & CLONE_SYMBOLS_FLAG;
45579 result = object ? customizer(value, key, object, stack) : customizer(value);
45582 if (result !== undefined$1) {
45586 if (!isObject(value)) {
45590 var isArr = isArray(value);
45593 result = initCloneArray(value);
45596 return copyArray(value, result);
45599 var tag = getTag(value),
45600 isFunc = tag == funcTag || tag == genTag;
45602 if (isBuffer(value)) {
45603 return cloneBuffer(value, isDeep);
45606 if (tag == objectTag || tag == argsTag || isFunc && !object) {
45607 result = isFlat || isFunc ? {} : initCloneObject(value);
45610 return isFlat ? copySymbolsIn(value, baseAssignIn(result, value)) : copySymbols(value, baseAssign(result, value));
45613 if (!cloneableTags[tag]) {
45614 return object ? value : {};
45617 result = initCloneByTag(value, tag, isDeep);
45619 } // Check for circular references and return its corresponding clone.
45622 stack || (stack = new Stack());
45623 var stacked = stack.get(value);
45629 stack.set(value, result);
45631 if (isSet(value)) {
45632 value.forEach(function (subValue) {
45633 result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
45635 } else if (isMap(value)) {
45636 value.forEach(function (subValue, key) {
45637 result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
45641 var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys;
45642 var props = isArr ? undefined$1 : keysFunc(value);
45643 arrayEach(props || value, function (subValue, key) {
45646 subValue = value[key];
45647 } // Recursively populate clone (susceptible to call stack limits).
45650 assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
45655 * The base implementation of `_.conforms` which doesn't clone `source`.
45658 * @param {Object} source The object of property predicates to conform to.
45659 * @returns {Function} Returns the new spec function.
45663 function baseConforms(source) {
45664 var props = keys(source);
45665 return function (object) {
45666 return baseConformsTo(object, source, props);
45670 * The base implementation of `_.conformsTo` which accepts `props` to check.
45673 * @param {Object} object The object to inspect.
45674 * @param {Object} source The object of property predicates to conform to.
45675 * @returns {boolean} Returns `true` if `object` conforms, else `false`.
45679 function baseConformsTo(object, source, props) {
45680 var length = props.length;
45682 if (object == null) {
45686 object = Object(object);
45689 var key = props[length],
45690 predicate = source[key],
45691 value = object[key];
45693 if (value === undefined$1 && !(key in object) || !predicate(value)) {
45701 * The base implementation of `_.delay` and `_.defer` which accepts `args`
45702 * to provide to `func`.
45705 * @param {Function} func The function to delay.
45706 * @param {number} wait The number of milliseconds to delay invocation.
45707 * @param {Array} args The arguments to provide to `func`.
45708 * @returns {number|Object} Returns the timer id or timeout object.
45712 function baseDelay(func, wait, args) {
45713 if (typeof func != 'function') {
45714 throw new TypeError(FUNC_ERROR_TEXT);
45717 return setTimeout(function () {
45718 func.apply(undefined$1, args);
45722 * The base implementation of methods like `_.difference` without support
45723 * for excluding multiple arrays or iteratee shorthands.
45726 * @param {Array} array The array to inspect.
45727 * @param {Array} values The values to exclude.
45728 * @param {Function} [iteratee] The iteratee invoked per element.
45729 * @param {Function} [comparator] The comparator invoked per element.
45730 * @returns {Array} Returns the new array of filtered values.
45734 function baseDifference(array, values, iteratee, comparator) {
45736 includes = arrayIncludes,
45738 length = array.length,
45740 valuesLength = values.length;
45747 values = arrayMap(values, baseUnary(iteratee));
45751 includes = arrayIncludesWith;
45753 } else if (values.length >= LARGE_ARRAY_SIZE) {
45754 includes = cacheHas;
45756 values = new SetCache(values);
45759 outer: while (++index < length) {
45760 var value = array[index],
45761 computed = iteratee == null ? value : iteratee(value);
45762 value = comparator || value !== 0 ? value : 0;
45764 if (isCommon && computed === computed) {
45765 var valuesIndex = valuesLength;
45767 while (valuesIndex--) {
45768 if (values[valuesIndex] === computed) {
45773 result.push(value);
45774 } else if (!includes(values, computed, comparator)) {
45775 result.push(value);
45782 * The base implementation of `_.forEach` without support for iteratee shorthands.
45785 * @param {Array|Object} collection The collection to iterate over.
45786 * @param {Function} iteratee The function invoked per iteration.
45787 * @returns {Array|Object} Returns `collection`.
45791 var baseEach = createBaseEach(baseForOwn);
45793 * The base implementation of `_.forEachRight` without support for iteratee shorthands.
45796 * @param {Array|Object} collection The collection to iterate over.
45797 * @param {Function} iteratee The function invoked per iteration.
45798 * @returns {Array|Object} Returns `collection`.
45801 var baseEachRight = createBaseEach(baseForOwnRight, true);
45803 * The base implementation of `_.every` without support for iteratee shorthands.
45806 * @param {Array|Object} collection The collection to iterate over.
45807 * @param {Function} predicate The function invoked per iteration.
45808 * @returns {boolean} Returns `true` if all elements pass the predicate check,
45812 function baseEvery(collection, predicate) {
45814 baseEach(collection, function (value, index, collection) {
45815 result = !!predicate(value, index, collection);
45821 * The base implementation of methods like `_.max` and `_.min` which accepts a
45822 * `comparator` to determine the extremum value.
45825 * @param {Array} array The array to iterate over.
45826 * @param {Function} iteratee The iteratee invoked per iteration.
45827 * @param {Function} comparator The comparator used to compare values.
45828 * @returns {*} Returns the extremum value.
45832 function baseExtremum(array, iteratee, comparator) {
45834 length = array.length;
45836 while (++index < length) {
45837 var value = array[index],
45838 current = iteratee(value);
45840 if (current != null && (computed === undefined$1 ? current === current && !isSymbol(current) : comparator(current, computed))) {
45841 var computed = current,
45849 * The base implementation of `_.fill` without an iteratee call guard.
45852 * @param {Array} array The array to fill.
45853 * @param {*} value The value to fill `array` with.
45854 * @param {number} [start=0] The start position.
45855 * @param {number} [end=array.length] The end position.
45856 * @returns {Array} Returns `array`.
45860 function baseFill(array, value, start, end) {
45861 var length = array.length;
45862 start = toInteger(start);
45865 start = -start > length ? 0 : length + start;
45868 end = end === undefined$1 || end > length ? length : toInteger(end);
45874 end = start > end ? 0 : toLength(end);
45876 while (start < end) {
45877 array[start++] = value;
45883 * The base implementation of `_.filter` without support for iteratee shorthands.
45886 * @param {Array|Object} collection The collection to iterate over.
45887 * @param {Function} predicate The function invoked per iteration.
45888 * @returns {Array} Returns the new filtered array.
45892 function baseFilter(collection, predicate) {
45894 baseEach(collection, function (value, index, collection) {
45895 if (predicate(value, index, collection)) {
45896 result.push(value);
45902 * The base implementation of `_.flatten` with support for restricting flattening.
45905 * @param {Array} array The array to flatten.
45906 * @param {number} depth The maximum recursion depth.
45907 * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
45908 * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
45909 * @param {Array} [result=[]] The initial result value.
45910 * @returns {Array} Returns the new flattened array.
45914 function baseFlatten(array, depth, predicate, isStrict, result) {
45916 length = array.length;
45917 predicate || (predicate = isFlattenable);
45918 result || (result = []);
45920 while (++index < length) {
45921 var value = array[index];
45923 if (depth > 0 && predicate(value)) {
45925 // Recursively flatten arrays (susceptible to call stack limits).
45926 baseFlatten(value, depth - 1, predicate, isStrict, result);
45928 arrayPush(result, value);
45930 } else if (!isStrict) {
45931 result[result.length] = value;
45938 * The base implementation of `baseForOwn` which iterates over `object`
45939 * properties returned by `keysFunc` and invokes `iteratee` for each property.
45940 * Iteratee functions may exit iteration early by explicitly returning `false`.
45943 * @param {Object} object The object to iterate over.
45944 * @param {Function} iteratee The function invoked per iteration.
45945 * @param {Function} keysFunc The function to get the keys of `object`.
45946 * @returns {Object} Returns `object`.
45950 var baseFor = createBaseFor();
45952 * This function is like `baseFor` except that it iterates over properties
45953 * in the opposite order.
45956 * @param {Object} object The object to iterate over.
45957 * @param {Function} iteratee The function invoked per iteration.
45958 * @param {Function} keysFunc The function to get the keys of `object`.
45959 * @returns {Object} Returns `object`.
45962 var baseForRight = createBaseFor(true);
45964 * The base implementation of `_.forOwn` without support for iteratee shorthands.
45967 * @param {Object} object The object to iterate over.
45968 * @param {Function} iteratee The function invoked per iteration.
45969 * @returns {Object} Returns `object`.
45972 function baseForOwn(object, iteratee) {
45973 return object && baseFor(object, iteratee, keys);
45976 * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
45979 * @param {Object} object The object to iterate over.
45980 * @param {Function} iteratee The function invoked per iteration.
45981 * @returns {Object} Returns `object`.
45985 function baseForOwnRight(object, iteratee) {
45986 return object && baseForRight(object, iteratee, keys);
45989 * The base implementation of `_.functions` which creates an array of
45990 * `object` function property names filtered from `props`.
45993 * @param {Object} object The object to inspect.
45994 * @param {Array} props The property names to filter.
45995 * @returns {Array} Returns the function names.
45999 function baseFunctions(object, props) {
46000 return arrayFilter(props, function (key) {
46001 return isFunction(object[key]);
46005 * The base implementation of `_.get` without support for default values.
46008 * @param {Object} object The object to query.
46009 * @param {Array|string} path The path of the property to get.
46010 * @returns {*} Returns the resolved value.
46014 function baseGet(object, path) {
46015 path = castPath(path, object);
46017 length = path.length;
46019 while (object != null && index < length) {
46020 object = object[toKey(path[index++])];
46023 return index && index == length ? object : undefined$1;
46026 * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
46027 * `keysFunc` and `symbolsFunc` to get the enumerable property names and
46028 * symbols of `object`.
46031 * @param {Object} object The object to query.
46032 * @param {Function} keysFunc The function to get the keys of `object`.
46033 * @param {Function} symbolsFunc The function to get the symbols of `object`.
46034 * @returns {Array} Returns the array of property names and symbols.
46038 function baseGetAllKeys(object, keysFunc, symbolsFunc) {
46039 var result = keysFunc(object);
46040 return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
46043 * The base implementation of `getTag` without fallbacks for buggy environments.
46046 * @param {*} value The value to query.
46047 * @returns {string} Returns the `toStringTag`.
46051 function baseGetTag(value) {
46052 if (value == null) {
46053 return value === undefined$1 ? undefinedTag : nullTag;
46056 return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
46059 * The base implementation of `_.gt` which doesn't coerce arguments.
46062 * @param {*} value The value to compare.
46063 * @param {*} other The other value to compare.
46064 * @returns {boolean} Returns `true` if `value` is greater than `other`,
46069 function baseGt(value, other) {
46070 return value > other;
46073 * The base implementation of `_.has` without support for deep paths.
46076 * @param {Object} [object] The object to query.
46077 * @param {Array|string} key The key to check.
46078 * @returns {boolean} Returns `true` if `key` exists, else `false`.
46082 function baseHas(object, key) {
46083 return object != null && hasOwnProperty.call(object, key);
46086 * The base implementation of `_.hasIn` without support for deep paths.
46089 * @param {Object} [object] The object to query.
46090 * @param {Array|string} key The key to check.
46091 * @returns {boolean} Returns `true` if `key` exists, else `false`.
46095 function baseHasIn(object, key) {
46096 return object != null && key in Object(object);
46099 * The base implementation of `_.inRange` which doesn't coerce arguments.
46102 * @param {number} number The number to check.
46103 * @param {number} start The start of the range.
46104 * @param {number} end The end of the range.
46105 * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
46109 function baseInRange(number, start, end) {
46110 return number >= nativeMin(start, end) && number < nativeMax(start, end);
46113 * The base implementation of methods like `_.intersection`, without support
46114 * for iteratee shorthands, that accepts an array of arrays to inspect.
46117 * @param {Array} arrays The arrays to inspect.
46118 * @param {Function} [iteratee] The iteratee invoked per element.
46119 * @param {Function} [comparator] The comparator invoked per element.
46120 * @returns {Array} Returns the new array of shared values.
46124 function baseIntersection(arrays, iteratee, comparator) {
46125 var includes = comparator ? arrayIncludesWith : arrayIncludes,
46126 length = arrays[0].length,
46127 othLength = arrays.length,
46128 othIndex = othLength,
46129 caches = Array(othLength),
46130 maxLength = Infinity,
46133 while (othIndex--) {
46134 var array = arrays[othIndex];
46136 if (othIndex && iteratee) {
46137 array = arrayMap(array, baseUnary(iteratee));
46140 maxLength = nativeMin(array.length, maxLength);
46141 caches[othIndex] = !comparator && (iteratee || length >= 120 && array.length >= 120) ? new SetCache(othIndex && array) : undefined$1;
46148 outer: while (++index < length && result.length < maxLength) {
46149 var value = array[index],
46150 computed = iteratee ? iteratee(value) : value;
46151 value = comparator || value !== 0 ? value : 0;
46153 if (!(seen ? cacheHas(seen, computed) : includes(result, computed, comparator))) {
46154 othIndex = othLength;
46156 while (--othIndex) {
46157 var cache = caches[othIndex];
46159 if (!(cache ? cacheHas(cache, computed) : includes(arrays[othIndex], computed, comparator))) {
46165 seen.push(computed);
46168 result.push(value);
46175 * The base implementation of `_.invert` and `_.invertBy` which inverts
46176 * `object` with values transformed by `iteratee` and set by `setter`.
46179 * @param {Object} object The object to iterate over.
46180 * @param {Function} setter The function to set `accumulator` values.
46181 * @param {Function} iteratee The iteratee to transform values.
46182 * @param {Object} accumulator The initial inverted object.
46183 * @returns {Function} Returns `accumulator`.
46187 function baseInverter(object, setter, iteratee, accumulator) {
46188 baseForOwn(object, function (value, key, object) {
46189 setter(accumulator, iteratee(value), key, object);
46191 return accumulator;
46194 * The base implementation of `_.invoke` without support for individual
46195 * method arguments.
46198 * @param {Object} object The object to query.
46199 * @param {Array|string} path The path of the method to invoke.
46200 * @param {Array} args The arguments to invoke the method with.
46201 * @returns {*} Returns the result of the invoked method.
46205 function baseInvoke(object, path, args) {
46206 path = castPath(path, object);
46207 object = parent(object, path);
46208 var func = object == null ? object : object[toKey(last(path))];
46209 return func == null ? undefined$1 : apply(func, object, args);
46212 * The base implementation of `_.isArguments`.
46215 * @param {*} value The value to check.
46216 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
46220 function baseIsArguments(value) {
46221 return isObjectLike(value) && baseGetTag(value) == argsTag;
46224 * The base implementation of `_.isArrayBuffer` without Node.js optimizations.
46227 * @param {*} value The value to check.
46228 * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
46232 function baseIsArrayBuffer(value) {
46233 return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
46236 * The base implementation of `_.isDate` without Node.js optimizations.
46239 * @param {*} value The value to check.
46240 * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
46244 function baseIsDate(value) {
46245 return isObjectLike(value) && baseGetTag(value) == dateTag;
46248 * The base implementation of `_.isEqual` which supports partial comparisons
46249 * and tracks traversed objects.
46252 * @param {*} value The value to compare.
46253 * @param {*} other The other value to compare.
46254 * @param {boolean} bitmask The bitmask flags.
46255 * 1 - Unordered comparison
46256 * 2 - Partial comparison
46257 * @param {Function} [customizer] The function to customize comparisons.
46258 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
46259 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
46263 function baseIsEqual(value, other, bitmask, customizer, stack) {
46264 if (value === other) {
46268 if (value == null || other == null || !isObjectLike(value) && !isObjectLike(other)) {
46269 return value !== value && other !== other;
46272 return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
46275 * A specialized version of `baseIsEqual` for arrays and objects which performs
46276 * deep comparisons and tracks traversed objects enabling objects with circular
46277 * references to be compared.
46280 * @param {Object} object The object to compare.
46281 * @param {Object} other The other object to compare.
46282 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
46283 * @param {Function} customizer The function to customize comparisons.
46284 * @param {Function} equalFunc The function to determine equivalents of values.
46285 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
46286 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
46290 function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
46291 var objIsArr = isArray(object),
46292 othIsArr = isArray(other),
46293 objTag = objIsArr ? arrayTag : getTag(object),
46294 othTag = othIsArr ? arrayTag : getTag(other);
46295 objTag = objTag == argsTag ? objectTag : objTag;
46296 othTag = othTag == argsTag ? objectTag : othTag;
46297 var objIsObj = objTag == objectTag,
46298 othIsObj = othTag == objectTag,
46299 isSameTag = objTag == othTag;
46301 if (isSameTag && isBuffer(object)) {
46302 if (!isBuffer(other)) {
46310 if (isSameTag && !objIsObj) {
46311 stack || (stack = new Stack());
46312 return objIsArr || isTypedArray(object) ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
46315 if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
46316 var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
46317 othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
46319 if (objIsWrapped || othIsWrapped) {
46320 var objUnwrapped = objIsWrapped ? object.value() : object,
46321 othUnwrapped = othIsWrapped ? other.value() : other;
46322 stack || (stack = new Stack());
46323 return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
46331 stack || (stack = new Stack());
46332 return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
46335 * The base implementation of `_.isMap` without Node.js optimizations.
46338 * @param {*} value The value to check.
46339 * @returns {boolean} Returns `true` if `value` is a map, else `false`.
46343 function baseIsMap(value) {
46344 return isObjectLike(value) && getTag(value) == mapTag;
46347 * The base implementation of `_.isMatch` without support for iteratee shorthands.
46350 * @param {Object} object The object to inspect.
46351 * @param {Object} source The object of property values to match.
46352 * @param {Array} matchData The property names, values, and compare flags to match.
46353 * @param {Function} [customizer] The function to customize comparisons.
46354 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
46358 function baseIsMatch(object, source, matchData, customizer) {
46359 var index = matchData.length,
46361 noCustomizer = !customizer;
46363 if (object == null) {
46367 object = Object(object);
46370 var data = matchData[index];
46372 if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) {
46377 while (++index < length) {
46378 data = matchData[index];
46380 objValue = object[key],
46381 srcValue = data[1];
46383 if (noCustomizer && data[2]) {
46384 if (objValue === undefined$1 && !(key in object)) {
46388 var stack = new Stack();
46391 var result = customizer(objValue, srcValue, key, object, source, stack);
46394 if (!(result === undefined$1 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) : result)) {
46403 * The base implementation of `_.isNative` without bad shim checks.
46406 * @param {*} value The value to check.
46407 * @returns {boolean} Returns `true` if `value` is a native function,
46412 function baseIsNative(value) {
46413 if (!isObject(value) || isMasked(value)) {
46417 var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
46418 return pattern.test(toSource(value));
46421 * The base implementation of `_.isRegExp` without Node.js optimizations.
46424 * @param {*} value The value to check.
46425 * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
46429 function baseIsRegExp(value) {
46430 return isObjectLike(value) && baseGetTag(value) == regexpTag;
46433 * The base implementation of `_.isSet` without Node.js optimizations.
46436 * @param {*} value The value to check.
46437 * @returns {boolean} Returns `true` if `value` is a set, else `false`.
46441 function baseIsSet(value) {
46442 return isObjectLike(value) && getTag(value) == setTag;
46445 * The base implementation of `_.isTypedArray` without Node.js optimizations.
46448 * @param {*} value The value to check.
46449 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
46453 function baseIsTypedArray(value) {
46454 return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
46457 * The base implementation of `_.iteratee`.
46460 * @param {*} [value=_.identity] The value to convert to an iteratee.
46461 * @returns {Function} Returns the iteratee.
46465 function baseIteratee(value) {
46466 // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
46467 // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
46468 if (typeof value == 'function') {
46472 if (value == null) {
46476 if (_typeof(value) == 'object') {
46477 return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value);
46480 return property(value);
46483 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
46486 * @param {Object} object The object to query.
46487 * @returns {Array} Returns the array of property names.
46491 function baseKeys(object) {
46492 if (!isPrototype(object)) {
46493 return nativeKeys(object);
46498 for (var key in Object(object)) {
46499 if (hasOwnProperty.call(object, key) && key != 'constructor') {
46507 * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
46510 * @param {Object} object The object to query.
46511 * @returns {Array} Returns the array of property names.
46515 function baseKeysIn(object) {
46516 if (!isObject(object)) {
46517 return nativeKeysIn(object);
46520 var isProto = isPrototype(object),
46523 for (var key in object) {
46524 if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
46532 * The base implementation of `_.lt` which doesn't coerce arguments.
46535 * @param {*} value The value to compare.
46536 * @param {*} other The other value to compare.
46537 * @returns {boolean} Returns `true` if `value` is less than `other`,
46542 function baseLt(value, other) {
46543 return value < other;
46546 * The base implementation of `_.map` without support for iteratee shorthands.
46549 * @param {Array|Object} collection The collection to iterate over.
46550 * @param {Function} iteratee The function invoked per iteration.
46551 * @returns {Array} Returns the new mapped array.
46555 function baseMap(collection, iteratee) {
46557 result = isArrayLike(collection) ? Array(collection.length) : [];
46558 baseEach(collection, function (value, key, collection) {
46559 result[++index] = iteratee(value, key, collection);
46564 * The base implementation of `_.matches` which doesn't clone `source`.
46567 * @param {Object} source The object of property values to match.
46568 * @returns {Function} Returns the new spec function.
46572 function baseMatches(source) {
46573 var matchData = getMatchData(source);
46575 if (matchData.length == 1 && matchData[0][2]) {
46576 return matchesStrictComparable(matchData[0][0], matchData[0][1]);
46579 return function (object) {
46580 return object === source || baseIsMatch(object, source, matchData);
46584 * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
46587 * @param {string} path The path of the property to get.
46588 * @param {*} srcValue The value to match.
46589 * @returns {Function} Returns the new spec function.
46593 function baseMatchesProperty(path, srcValue) {
46594 if (isKey(path) && isStrictComparable(srcValue)) {
46595 return matchesStrictComparable(toKey(path), srcValue);
46598 return function (object) {
46599 var objValue = get(object, path);
46600 return objValue === undefined$1 && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
46604 * The base implementation of `_.merge` without support for multiple sources.
46607 * @param {Object} object The destination object.
46608 * @param {Object} source The source object.
46609 * @param {number} srcIndex The index of `source`.
46610 * @param {Function} [customizer] The function to customize merged values.
46611 * @param {Object} [stack] Tracks traversed source values and their merged
46616 function baseMerge(object, source, srcIndex, customizer, stack) {
46617 if (object === source) {
46621 baseFor(source, function (srcValue, key) {
46622 stack || (stack = new Stack());
46624 if (isObject(srcValue)) {
46625 baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
46627 var newValue = customizer ? customizer(safeGet(object, key), srcValue, key + '', object, source, stack) : undefined$1;
46629 if (newValue === undefined$1) {
46630 newValue = srcValue;
46633 assignMergeValue(object, key, newValue);
46638 * A specialized version of `baseMerge` for arrays and objects which performs
46639 * deep merges and tracks traversed objects enabling objects with circular
46640 * references to be merged.
46643 * @param {Object} object The destination object.
46644 * @param {Object} source The source object.
46645 * @param {string} key The key of the value to merge.
46646 * @param {number} srcIndex The index of `source`.
46647 * @param {Function} mergeFunc The function to merge values.
46648 * @param {Function} [customizer] The function to customize assigned values.
46649 * @param {Object} [stack] Tracks traversed source values and their merged
46654 function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
46655 var objValue = safeGet(object, key),
46656 srcValue = safeGet(source, key),
46657 stacked = stack.get(srcValue);
46660 assignMergeValue(object, key, stacked);
46664 var newValue = customizer ? customizer(objValue, srcValue, key + '', object, source, stack) : undefined$1;
46665 var isCommon = newValue === undefined$1;
46668 var isArr = isArray(srcValue),
46669 isBuff = !isArr && isBuffer(srcValue),
46670 isTyped = !isArr && !isBuff && isTypedArray(srcValue);
46671 newValue = srcValue;
46673 if (isArr || isBuff || isTyped) {
46674 if (isArray(objValue)) {
46675 newValue = objValue;
46676 } else if (isArrayLikeObject(objValue)) {
46677 newValue = copyArray(objValue);
46678 } else if (isBuff) {
46680 newValue = cloneBuffer(srcValue, true);
46681 } else if (isTyped) {
46683 newValue = cloneTypedArray(srcValue, true);
46687 } else if (isPlainObject(srcValue) || isArguments(srcValue)) {
46688 newValue = objValue;
46690 if (isArguments(objValue)) {
46691 newValue = toPlainObject(objValue);
46692 } else if (!isObject(objValue) || isFunction(objValue)) {
46693 newValue = initCloneObject(srcValue);
46701 // Recursively merge objects and arrays (susceptible to call stack limits).
46702 stack.set(srcValue, newValue);
46703 mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
46704 stack['delete'](srcValue);
46707 assignMergeValue(object, key, newValue);
46710 * The base implementation of `_.nth` which doesn't coerce arguments.
46713 * @param {Array} array The array to query.
46714 * @param {number} n The index of the element to return.
46715 * @returns {*} Returns the nth element of `array`.
46719 function baseNth(array, n) {
46720 var length = array.length;
46726 n += n < 0 ? length : 0;
46727 return isIndex(n, length) ? array[n] : undefined$1;
46730 * The base implementation of `_.orderBy` without param guards.
46733 * @param {Array|Object} collection The collection to iterate over.
46734 * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
46735 * @param {string[]} orders The sort orders of `iteratees`.
46736 * @returns {Array} Returns the new sorted array.
46740 function baseOrderBy(collection, iteratees, orders) {
46741 if (iteratees.length) {
46742 iteratees = arrayMap(iteratees, function (iteratee) {
46743 if (isArray(iteratee)) {
46744 return function (value) {
46745 return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);
46752 iteratees = [identity];
46756 iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
46757 var result = baseMap(collection, function (value, key, collection) {
46758 var criteria = arrayMap(iteratees, function (iteratee) {
46759 return iteratee(value);
46762 'criteria': criteria,
46767 return baseSortBy(result, function (object, other) {
46768 return compareMultiple(object, other, orders);
46772 * The base implementation of `_.pick` without support for individual
46773 * property identifiers.
46776 * @param {Object} object The source object.
46777 * @param {string[]} paths The property paths to pick.
46778 * @returns {Object} Returns the new object.
46782 function basePick(object, paths) {
46783 return basePickBy(object, paths, function (value, path) {
46784 return hasIn(object, path);
46788 * The base implementation of `_.pickBy` without support for iteratee shorthands.
46791 * @param {Object} object The source object.
46792 * @param {string[]} paths The property paths to pick.
46793 * @param {Function} predicate The function invoked per property.
46794 * @returns {Object} Returns the new object.
46798 function basePickBy(object, paths, predicate) {
46800 length = paths.length,
46803 while (++index < length) {
46804 var path = paths[index],
46805 value = baseGet(object, path);
46807 if (predicate(value, path)) {
46808 baseSet(result, castPath(path, object), value);
46815 * A specialized version of `baseProperty` which supports deep paths.
46818 * @param {Array|string} path The path of the property to get.
46819 * @returns {Function} Returns the new accessor function.
46823 function basePropertyDeep(path) {
46824 return function (object) {
46825 return baseGet(object, path);
46829 * The base implementation of `_.pullAllBy` without support for iteratee
46833 * @param {Array} array The array to modify.
46834 * @param {Array} values The values to remove.
46835 * @param {Function} [iteratee] The iteratee invoked per element.
46836 * @param {Function} [comparator] The comparator invoked per element.
46837 * @returns {Array} Returns `array`.
46841 function basePullAll(array, values, iteratee, comparator) {
46842 var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
46844 length = values.length,
46847 if (array === values) {
46848 values = copyArray(values);
46852 seen = arrayMap(array, baseUnary(iteratee));
46855 while (++index < length) {
46857 value = values[index],
46858 computed = iteratee ? iteratee(value) : value;
46860 while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
46861 if (seen !== array) {
46862 splice.call(seen, fromIndex, 1);
46865 splice.call(array, fromIndex, 1);
46872 * The base implementation of `_.pullAt` without support for individual
46873 * indexes or capturing the removed elements.
46876 * @param {Array} array The array to modify.
46877 * @param {number[]} indexes The indexes of elements to remove.
46878 * @returns {Array} Returns `array`.
46882 function basePullAt(array, indexes) {
46883 var length = array ? indexes.length : 0,
46884 lastIndex = length - 1;
46887 var index = indexes[length];
46889 if (length == lastIndex || index !== previous) {
46890 var previous = index;
46892 if (isIndex(index)) {
46893 splice.call(array, index, 1);
46895 baseUnset(array, index);
46903 * The base implementation of `_.random` without support for returning
46904 * floating-point numbers.
46907 * @param {number} lower The lower bound.
46908 * @param {number} upper The upper bound.
46909 * @returns {number} Returns the random number.
46913 function baseRandom(lower, upper) {
46914 return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
46917 * The base implementation of `_.range` and `_.rangeRight` which doesn't
46918 * coerce arguments.
46921 * @param {number} start The start of the range.
46922 * @param {number} end The end of the range.
46923 * @param {number} step The value to increment or decrement by.
46924 * @param {boolean} [fromRight] Specify iterating from right to left.
46925 * @returns {Array} Returns the range of numbers.
46929 function baseRange(start, end, step, fromRight) {
46931 length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
46932 result = Array(length);
46935 result[fromRight ? length : ++index] = start;
46942 * The base implementation of `_.repeat` which doesn't coerce arguments.
46945 * @param {string} string The string to repeat.
46946 * @param {number} n The number of times to repeat the string.
46947 * @returns {string} Returns the repeated string.
46951 function baseRepeat(string, n) {
46954 if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
46956 } // Leverage the exponentiation by squaring algorithm for a faster repeat.
46957 // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
46965 n = nativeFloor(n / 2);
46975 * The base implementation of `_.rest` which doesn't validate or coerce arguments.
46978 * @param {Function} func The function to apply a rest parameter to.
46979 * @param {number} [start=func.length-1] The start position of the rest parameter.
46980 * @returns {Function} Returns the new function.
46984 function baseRest(func, start) {
46985 return setToString(overRest(func, start, identity), func + '');
46988 * The base implementation of `_.sample`.
46991 * @param {Array|Object} collection The collection to sample.
46992 * @returns {*} Returns the random element.
46996 function baseSample(collection) {
46997 return arraySample(values(collection));
47000 * The base implementation of `_.sampleSize` without param guards.
47003 * @param {Array|Object} collection The collection to sample.
47004 * @param {number} n The number of elements to sample.
47005 * @returns {Array} Returns the random elements.
47009 function baseSampleSize(collection, n) {
47010 var array = values(collection);
47011 return shuffleSelf(array, baseClamp(n, 0, array.length));
47014 * The base implementation of `_.set`.
47017 * @param {Object} object The object to modify.
47018 * @param {Array|string} path The path of the property to set.
47019 * @param {*} value The value to set.
47020 * @param {Function} [customizer] The function to customize path creation.
47021 * @returns {Object} Returns `object`.
47025 function baseSet(object, path, value, customizer) {
47026 if (!isObject(object)) {
47030 path = castPath(path, object);
47032 length = path.length,
47033 lastIndex = length - 1,
47036 while (nested != null && ++index < length) {
47037 var key = toKey(path[index]),
47040 if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
47044 if (index != lastIndex) {
47045 var objValue = nested[key];
47046 newValue = customizer ? customizer(objValue, key, nested) : undefined$1;
47048 if (newValue === undefined$1) {
47049 newValue = isObject(objValue) ? objValue : isIndex(path[index + 1]) ? [] : {};
47053 assignValue(nested, key, newValue);
47054 nested = nested[key];
47060 * The base implementation of `setData` without support for hot loop shorting.
47063 * @param {Function} func The function to associate metadata with.
47064 * @param {*} data The metadata.
47065 * @returns {Function} Returns `func`.
47069 var baseSetData = !metaMap ? identity : function (func, data) {
47070 metaMap.set(func, data);
47074 * The base implementation of `setToString` without support for hot loop shorting.
47077 * @param {Function} func The function to modify.
47078 * @param {Function} string The `toString` result.
47079 * @returns {Function} Returns `func`.
47082 var baseSetToString = !defineProperty ? identity : function (func, string) {
47083 return defineProperty(func, 'toString', {
47084 'configurable': true,
47085 'enumerable': false,
47086 'value': constant(string),
47091 * The base implementation of `_.shuffle`.
47094 * @param {Array|Object} collection The collection to shuffle.
47095 * @returns {Array} Returns the new shuffled array.
47098 function baseShuffle(collection) {
47099 return shuffleSelf(values(collection));
47102 * The base implementation of `_.slice` without an iteratee call guard.
47105 * @param {Array} array The array to slice.
47106 * @param {number} [start=0] The start position.
47107 * @param {number} [end=array.length] The end position.
47108 * @returns {Array} Returns the slice of `array`.
47112 function baseSlice(array, start, end) {
47114 length = array.length;
47117 start = -start > length ? 0 : length + start;
47120 end = end > length ? length : end;
47126 length = start > end ? 0 : end - start >>> 0;
47128 var result = Array(length);
47130 while (++index < length) {
47131 result[index] = array[index + start];
47137 * The base implementation of `_.some` without support for iteratee shorthands.
47140 * @param {Array|Object} collection The collection to iterate over.
47141 * @param {Function} predicate The function invoked per iteration.
47142 * @returns {boolean} Returns `true` if any element passes the predicate check,
47147 function baseSome(collection, predicate) {
47149 baseEach(collection, function (value, index, collection) {
47150 result = predicate(value, index, collection);
47156 * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
47157 * performs a binary search of `array` to determine the index at which `value`
47158 * should be inserted into `array` in order to maintain its sort order.
47161 * @param {Array} array The sorted array to inspect.
47162 * @param {*} value The value to evaluate.
47163 * @param {boolean} [retHighest] Specify returning the highest qualified index.
47164 * @returns {number} Returns the index at which `value` should be inserted
47169 function baseSortedIndex(array, value, retHighest) {
47171 high = array == null ? low : array.length;
47173 if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
47174 while (low < high) {
47175 var mid = low + high >>> 1,
47176 computed = array[mid];
47178 if (computed !== null && !isSymbol(computed) && (retHighest ? computed <= value : computed < value)) {
47188 return baseSortedIndexBy(array, value, identity, retHighest);
47191 * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
47192 * which invokes `iteratee` for `value` and each element of `array` to compute
47193 * their sort ranking. The iteratee is invoked with one argument; (value).
47196 * @param {Array} array The sorted array to inspect.
47197 * @param {*} value The value to evaluate.
47198 * @param {Function} iteratee The iteratee invoked per element.
47199 * @param {boolean} [retHighest] Specify returning the highest qualified index.
47200 * @returns {number} Returns the index at which `value` should be inserted
47205 function baseSortedIndexBy(array, value, iteratee, retHighest) {
47207 high = array == null ? 0 : array.length;
47213 value = iteratee(value);
47214 var valIsNaN = value !== value,
47215 valIsNull = value === null,
47216 valIsSymbol = isSymbol(value),
47217 valIsUndefined = value === undefined$1;
47219 while (low < high) {
47220 var mid = nativeFloor((low + high) / 2),
47221 computed = iteratee(array[mid]),
47222 othIsDefined = computed !== undefined$1,
47223 othIsNull = computed === null,
47224 othIsReflexive = computed === computed,
47225 othIsSymbol = isSymbol(computed);
47228 var setLow = retHighest || othIsReflexive;
47229 } else if (valIsUndefined) {
47230 setLow = othIsReflexive && (retHighest || othIsDefined);
47231 } else if (valIsNull) {
47232 setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
47233 } else if (valIsSymbol) {
47234 setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
47235 } else if (othIsNull || othIsSymbol) {
47238 setLow = retHighest ? computed <= value : computed < value;
47248 return nativeMin(high, MAX_ARRAY_INDEX);
47251 * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
47252 * support for iteratee shorthands.
47255 * @param {Array} array The array to inspect.
47256 * @param {Function} [iteratee] The iteratee invoked per element.
47257 * @returns {Array} Returns the new duplicate free array.
47261 function baseSortedUniq(array, iteratee) {
47263 length = array.length,
47267 while (++index < length) {
47268 var value = array[index],
47269 computed = iteratee ? iteratee(value) : value;
47271 if (!index || !eq(computed, seen)) {
47272 var seen = computed;
47273 result[resIndex++] = value === 0 ? 0 : value;
47280 * The base implementation of `_.toNumber` which doesn't ensure correct
47281 * conversions of binary, hexadecimal, or octal string values.
47284 * @param {*} value The value to process.
47285 * @returns {number} Returns the number.
47289 function baseToNumber(value) {
47290 if (typeof value == 'number') {
47294 if (isSymbol(value)) {
47301 * The base implementation of `_.toString` which doesn't convert nullish
47302 * values to empty strings.
47305 * @param {*} value The value to process.
47306 * @returns {string} Returns the string.
47310 function baseToString(value) {
47311 // Exit early for strings to avoid a performance hit in some environments.
47312 if (typeof value == 'string') {
47316 if (isArray(value)) {
47317 // Recursively convert values (susceptible to call stack limits).
47318 return arrayMap(value, baseToString) + '';
47321 if (isSymbol(value)) {
47322 return symbolToString ? symbolToString.call(value) : '';
47325 var result = value + '';
47326 return result == '0' && 1 / value == -INFINITY ? '-0' : result;
47329 * The base implementation of `_.uniqBy` without support for iteratee shorthands.
47332 * @param {Array} array The array to inspect.
47333 * @param {Function} [iteratee] The iteratee invoked per element.
47334 * @param {Function} [comparator] The comparator invoked per element.
47335 * @returns {Array} Returns the new duplicate free array.
47339 function baseUniq(array, iteratee, comparator) {
47341 includes = arrayIncludes,
47342 length = array.length,
47349 includes = arrayIncludesWith;
47350 } else if (length >= LARGE_ARRAY_SIZE) {
47351 var set = iteratee ? null : createSet(array);
47354 return setToArray(set);
47358 includes = cacheHas;
47359 seen = new SetCache();
47361 seen = iteratee ? [] : result;
47364 outer: while (++index < length) {
47365 var value = array[index],
47366 computed = iteratee ? iteratee(value) : value;
47367 value = comparator || value !== 0 ? value : 0;
47369 if (isCommon && computed === computed) {
47370 var seenIndex = seen.length;
47372 while (seenIndex--) {
47373 if (seen[seenIndex] === computed) {
47379 seen.push(computed);
47382 result.push(value);
47383 } else if (!includes(seen, computed, comparator)) {
47384 if (seen !== result) {
47385 seen.push(computed);
47388 result.push(value);
47395 * The base implementation of `_.unset`.
47398 * @param {Object} object The object to modify.
47399 * @param {Array|string} path The property path to unset.
47400 * @returns {boolean} Returns `true` if the property is deleted, else `false`.
47404 function baseUnset(object, path) {
47405 path = castPath(path, object);
47406 object = parent(object, path);
47407 return object == null || delete object[toKey(last(path))];
47410 * The base implementation of `_.update`.
47413 * @param {Object} object The object to modify.
47414 * @param {Array|string} path The path of the property to update.
47415 * @param {Function} updater The function to produce the updated value.
47416 * @param {Function} [customizer] The function to customize path creation.
47417 * @returns {Object} Returns `object`.
47421 function baseUpdate(object, path, updater, customizer) {
47422 return baseSet(object, path, updater(baseGet(object, path)), customizer);
47425 * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
47426 * without support for iteratee shorthands.
47429 * @param {Array} array The array to query.
47430 * @param {Function} predicate The function invoked per iteration.
47431 * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
47432 * @param {boolean} [fromRight] Specify iterating from right to left.
47433 * @returns {Array} Returns the slice of `array`.
47437 function baseWhile(array, predicate, isDrop, fromRight) {
47438 var length = array.length,
47439 index = fromRight ? length : -1;
47441 while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {}
47443 return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index);
47446 * The base implementation of `wrapperValue` which returns the result of
47447 * performing a sequence of actions on the unwrapped `value`, where each
47448 * successive action is supplied the return value of the previous.
47451 * @param {*} value The unwrapped value.
47452 * @param {Array} actions Actions to perform to resolve the unwrapped value.
47453 * @returns {*} Returns the resolved value.
47457 function baseWrapperValue(value, actions) {
47458 var result = value;
47460 if (result instanceof LazyWrapper) {
47461 result = result.value();
47464 return arrayReduce(actions, function (result, action) {
47465 return action.func.apply(action.thisArg, arrayPush([result], action.args));
47469 * The base implementation of methods like `_.xor`, without support for
47470 * iteratee shorthands, that accepts an array of arrays to inspect.
47473 * @param {Array} arrays The arrays to inspect.
47474 * @param {Function} [iteratee] The iteratee invoked per element.
47475 * @param {Function} [comparator] The comparator invoked per element.
47476 * @returns {Array} Returns the new array of values.
47480 function baseXor(arrays, iteratee, comparator) {
47481 var length = arrays.length;
47484 return length ? baseUniq(arrays[0]) : [];
47488 result = Array(length);
47490 while (++index < length) {
47491 var array = arrays[index],
47494 while (++othIndex < length) {
47495 if (othIndex != index) {
47496 result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
47501 return baseUniq(baseFlatten(result, 1), iteratee, comparator);
47504 * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
47507 * @param {Array} props The property identifiers.
47508 * @param {Array} values The property values.
47509 * @param {Function} assignFunc The function to assign values.
47510 * @returns {Object} Returns the new object.
47514 function baseZipObject(props, values, assignFunc) {
47516 length = props.length,
47517 valsLength = values.length,
47520 while (++index < length) {
47521 var value = index < valsLength ? values[index] : undefined$1;
47522 assignFunc(result, props[index], value);
47528 * Casts `value` to an empty array if it's not an array like object.
47531 * @param {*} value The value to inspect.
47532 * @returns {Array|Object} Returns the cast array-like object.
47536 function castArrayLikeObject(value) {
47537 return isArrayLikeObject(value) ? value : [];
47540 * Casts `value` to `identity` if it's not a function.
47543 * @param {*} value The value to inspect.
47544 * @returns {Function} Returns cast function.
47548 function castFunction(value) {
47549 return typeof value == 'function' ? value : identity;
47552 * Casts `value` to a path array if it's not one.
47555 * @param {*} value The value to inspect.
47556 * @param {Object} [object] The object to query keys on.
47557 * @returns {Array} Returns the cast property path array.
47561 function castPath(value, object) {
47562 if (isArray(value)) {
47566 return isKey(value, object) ? [value] : stringToPath(toString(value));
47569 * A `baseRest` alias which can be replaced with `identity` by module
47570 * replacement plugins.
47574 * @param {Function} func The function to apply a rest parameter to.
47575 * @returns {Function} Returns the new function.
47579 var castRest = baseRest;
47581 * Casts `array` to a slice if it's needed.
47584 * @param {Array} array The array to inspect.
47585 * @param {number} start The start position.
47586 * @param {number} [end=array.length] The end position.
47587 * @returns {Array} Returns the cast slice.
47590 function castSlice(array, start, end) {
47591 var length = array.length;
47592 end = end === undefined$1 ? length : end;
47593 return !start && end >= length ? array : baseSlice(array, start, end);
47596 * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
47599 * @param {number|Object} id The timer id or timeout object of the timer to clear.
47603 var clearTimeout = ctxClearTimeout || function (id) {
47604 return root.clearTimeout(id);
47607 * Creates a clone of `buffer`.
47610 * @param {Buffer} buffer The buffer to clone.
47611 * @param {boolean} [isDeep] Specify a deep clone.
47612 * @returns {Buffer} Returns the cloned buffer.
47616 function cloneBuffer(buffer, isDeep) {
47618 return buffer.slice();
47621 var length = buffer.length,
47622 result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
47623 buffer.copy(result);
47627 * Creates a clone of `arrayBuffer`.
47630 * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
47631 * @returns {ArrayBuffer} Returns the cloned array buffer.
47635 function cloneArrayBuffer(arrayBuffer) {
47636 var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
47637 new Uint8Array(result).set(new Uint8Array(arrayBuffer));
47641 * Creates a clone of `dataView`.
47644 * @param {Object} dataView The data view to clone.
47645 * @param {boolean} [isDeep] Specify a deep clone.
47646 * @returns {Object} Returns the cloned data view.
47650 function cloneDataView(dataView, isDeep) {
47651 var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
47652 return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
47655 * Creates a clone of `regexp`.
47658 * @param {Object} regexp The regexp to clone.
47659 * @returns {Object} Returns the cloned regexp.
47663 function cloneRegExp(regexp) {
47664 var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
47665 result.lastIndex = regexp.lastIndex;
47669 * Creates a clone of the `symbol` object.
47672 * @param {Object} symbol The symbol object to clone.
47673 * @returns {Object} Returns the cloned symbol object.
47677 function cloneSymbol(symbol) {
47678 return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
47681 * Creates a clone of `typedArray`.
47684 * @param {Object} typedArray The typed array to clone.
47685 * @param {boolean} [isDeep] Specify a deep clone.
47686 * @returns {Object} Returns the cloned typed array.
47690 function cloneTypedArray(typedArray, isDeep) {
47691 var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
47692 return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
47695 * Compares values to sort them in ascending order.
47698 * @param {*} value The value to compare.
47699 * @param {*} other The other value to compare.
47700 * @returns {number} Returns the sort order indicator for `value`.
47704 function compareAscending(value, other) {
47705 if (value !== other) {
47706 var valIsDefined = value !== undefined$1,
47707 valIsNull = value === null,
47708 valIsReflexive = value === value,
47709 valIsSymbol = isSymbol(value);
47710 var othIsDefined = other !== undefined$1,
47711 othIsNull = other === null,
47712 othIsReflexive = other === other,
47713 othIsSymbol = isSymbol(other);
47715 if (!othIsNull && !othIsSymbol && !valIsSymbol && value > other || valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol || valIsNull && othIsDefined && othIsReflexive || !valIsDefined && othIsReflexive || !valIsReflexive) {
47719 if (!valIsNull && !valIsSymbol && !othIsSymbol && value < other || othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol || othIsNull && valIsDefined && valIsReflexive || !othIsDefined && valIsReflexive || !othIsReflexive) {
47727 * Used by `_.orderBy` to compare multiple properties of a value to another
47728 * and stable sort them.
47730 * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
47731 * specify an order of "desc" for descending or "asc" for ascending sort order
47732 * of corresponding values.
47735 * @param {Object} object The object to compare.
47736 * @param {Object} other The other object to compare.
47737 * @param {boolean[]|string[]} orders The order to sort by for each property.
47738 * @returns {number} Returns the sort order indicator for `object`.
47742 function compareMultiple(object, other, orders) {
47744 objCriteria = object.criteria,
47745 othCriteria = other.criteria,
47746 length = objCriteria.length,
47747 ordersLength = orders.length;
47749 while (++index < length) {
47750 var result = compareAscending(objCriteria[index], othCriteria[index]);
47753 if (index >= ordersLength) {
47757 var order = orders[index];
47758 return result * (order == 'desc' ? -1 : 1);
47760 } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
47761 // that causes it, under certain circumstances, to provide the same value for
47762 // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
47763 // for more details.
47765 // This also ensures a stable sort in V8 and other engines.
47766 // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
47769 return object.index - other.index;
47772 * Creates an array that is the composition of partially applied arguments,
47773 * placeholders, and provided arguments into a single array of arguments.
47776 * @param {Array} args The provided arguments.
47777 * @param {Array} partials The arguments to prepend to those provided.
47778 * @param {Array} holders The `partials` placeholder indexes.
47779 * @params {boolean} [isCurried] Specify composing for a curried function.
47780 * @returns {Array} Returns the new array of composed arguments.
47784 function composeArgs(args, partials, holders, isCurried) {
47785 var argsIndex = -1,
47786 argsLength = args.length,
47787 holdersLength = holders.length,
47789 leftLength = partials.length,
47790 rangeLength = nativeMax(argsLength - holdersLength, 0),
47791 result = Array(leftLength + rangeLength),
47792 isUncurried = !isCurried;
47794 while (++leftIndex < leftLength) {
47795 result[leftIndex] = partials[leftIndex];
47798 while (++argsIndex < holdersLength) {
47799 if (isUncurried || argsIndex < argsLength) {
47800 result[holders[argsIndex]] = args[argsIndex];
47804 while (rangeLength--) {
47805 result[leftIndex++] = args[argsIndex++];
47811 * This function is like `composeArgs` except that the arguments composition
47812 * is tailored for `_.partialRight`.
47815 * @param {Array} args The provided arguments.
47816 * @param {Array} partials The arguments to append to those provided.
47817 * @param {Array} holders The `partials` placeholder indexes.
47818 * @params {boolean} [isCurried] Specify composing for a curried function.
47819 * @returns {Array} Returns the new array of composed arguments.
47823 function composeArgsRight(args, partials, holders, isCurried) {
47824 var argsIndex = -1,
47825 argsLength = args.length,
47827 holdersLength = holders.length,
47829 rightLength = partials.length,
47830 rangeLength = nativeMax(argsLength - holdersLength, 0),
47831 result = Array(rangeLength + rightLength),
47832 isUncurried = !isCurried;
47834 while (++argsIndex < rangeLength) {
47835 result[argsIndex] = args[argsIndex];
47838 var offset = argsIndex;
47840 while (++rightIndex < rightLength) {
47841 result[offset + rightIndex] = partials[rightIndex];
47844 while (++holdersIndex < holdersLength) {
47845 if (isUncurried || argsIndex < argsLength) {
47846 result[offset + holders[holdersIndex]] = args[argsIndex++];
47853 * Copies the values of `source` to `array`.
47856 * @param {Array} source The array to copy values from.
47857 * @param {Array} [array=[]] The array to copy values to.
47858 * @returns {Array} Returns `array`.
47862 function copyArray(source, array) {
47864 length = source.length;
47865 array || (array = Array(length));
47867 while (++index < length) {
47868 array[index] = source[index];
47874 * Copies properties of `source` to `object`.
47877 * @param {Object} source The object to copy properties from.
47878 * @param {Array} props The property identifiers to copy.
47879 * @param {Object} [object={}] The object to copy properties to.
47880 * @param {Function} [customizer] The function to customize copied values.
47881 * @returns {Object} Returns `object`.
47885 function copyObject(source, props, object, customizer) {
47886 var isNew = !object;
47887 object || (object = {});
47889 length = props.length;
47891 while (++index < length) {
47892 var key = props[index];
47893 var newValue = customizer ? customizer(object[key], source[key], key, object, source) : undefined$1;
47895 if (newValue === undefined$1) {
47896 newValue = source[key];
47900 baseAssignValue(object, key, newValue);
47902 assignValue(object, key, newValue);
47909 * Copies own symbols of `source` to `object`.
47912 * @param {Object} source The object to copy symbols from.
47913 * @param {Object} [object={}] The object to copy symbols to.
47914 * @returns {Object} Returns `object`.
47918 function copySymbols(source, object) {
47919 return copyObject(source, getSymbols(source), object);
47922 * Copies own and inherited symbols of `source` to `object`.
47925 * @param {Object} source The object to copy symbols from.
47926 * @param {Object} [object={}] The object to copy symbols to.
47927 * @returns {Object} Returns `object`.
47931 function copySymbolsIn(source, object) {
47932 return copyObject(source, getSymbolsIn(source), object);
47935 * Creates a function like `_.groupBy`.
47938 * @param {Function} setter The function to set accumulator values.
47939 * @param {Function} [initializer] The accumulator object initializer.
47940 * @returns {Function} Returns the new aggregator function.
47944 function createAggregator(setter, initializer) {
47945 return function (collection, iteratee) {
47946 var func = isArray(collection) ? arrayAggregator : baseAggregator,
47947 accumulator = initializer ? initializer() : {};
47948 return func(collection, setter, getIteratee(iteratee, 2), accumulator);
47952 * Creates a function like `_.assign`.
47955 * @param {Function} assigner The function to assign values.
47956 * @returns {Function} Returns the new assigner function.
47960 function createAssigner(assigner) {
47961 return baseRest(function (object, sources) {
47963 length = sources.length,
47964 customizer = length > 1 ? sources[length - 1] : undefined$1,
47965 guard = length > 2 ? sources[2] : undefined$1;
47966 customizer = assigner.length > 3 && typeof customizer == 'function' ? (length--, customizer) : undefined$1;
47968 if (guard && isIterateeCall(sources[0], sources[1], guard)) {
47969 customizer = length < 3 ? undefined$1 : customizer;
47973 object = Object(object);
47975 while (++index < length) {
47976 var source = sources[index];
47979 assigner(object, source, index, customizer);
47987 * Creates a `baseEach` or `baseEachRight` function.
47990 * @param {Function} eachFunc The function to iterate over a collection.
47991 * @param {boolean} [fromRight] Specify iterating from right to left.
47992 * @returns {Function} Returns the new base function.
47996 function createBaseEach(eachFunc, fromRight) {
47997 return function (collection, iteratee) {
47998 if (collection == null) {
48002 if (!isArrayLike(collection)) {
48003 return eachFunc(collection, iteratee);
48006 var length = collection.length,
48007 index = fromRight ? length : -1,
48008 iterable = Object(collection);
48010 while (fromRight ? index-- : ++index < length) {
48011 if (iteratee(iterable[index], index, iterable) === false) {
48020 * Creates a base function for methods like `_.forIn` and `_.forOwn`.
48023 * @param {boolean} [fromRight] Specify iterating from right to left.
48024 * @returns {Function} Returns the new base function.
48028 function createBaseFor(fromRight) {
48029 return function (object, iteratee, keysFunc) {
48031 iterable = Object(object),
48032 props = keysFunc(object),
48033 length = props.length;
48036 var key = props[fromRight ? length : ++index];
48038 if (iteratee(iterable[key], key, iterable) === false) {
48047 * Creates a function that wraps `func` to invoke it with the optional `this`
48048 * binding of `thisArg`.
48051 * @param {Function} func The function to wrap.
48052 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48053 * @param {*} [thisArg] The `this` binding of `func`.
48054 * @returns {Function} Returns the new wrapped function.
48058 function createBind(func, bitmask, thisArg) {
48059 var isBind = bitmask & WRAP_BIND_FLAG,
48060 Ctor = createCtor(func);
48062 function wrapper() {
48063 var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
48064 return fn.apply(isBind ? thisArg : this, arguments);
48070 * Creates a function like `_.lowerFirst`.
48073 * @param {string} methodName The name of the `String` case method to use.
48074 * @returns {Function} Returns the new case function.
48078 function createCaseFirst(methodName) {
48079 return function (string) {
48080 string = toString(string);
48081 var strSymbols = hasUnicode(string) ? stringToArray(string) : undefined$1;
48082 var chr = strSymbols ? strSymbols[0] : string.charAt(0);
48083 var trailing = strSymbols ? castSlice(strSymbols, 1).join('') : string.slice(1);
48084 return chr[methodName]() + trailing;
48088 * Creates a function like `_.camelCase`.
48091 * @param {Function} callback The function to combine each word.
48092 * @returns {Function} Returns the new compounder function.
48096 function createCompounder(callback) {
48097 return function (string) {
48098 return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
48102 * Creates a function that produces an instance of `Ctor` regardless of
48103 * whether it was invoked as part of a `new` expression or by `call` or `apply`.
48106 * @param {Function} Ctor The constructor to wrap.
48107 * @returns {Function} Returns the new wrapped function.
48111 function createCtor(Ctor) {
48112 return function () {
48113 // Use a `switch` statement to work with class constructors. See
48114 // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
48115 // for more details.
48116 var args = arguments;
48118 switch (args.length) {
48123 return new Ctor(args[0]);
48126 return new Ctor(args[0], args[1]);
48129 return new Ctor(args[0], args[1], args[2]);
48132 return new Ctor(args[0], args[1], args[2], args[3]);
48135 return new Ctor(args[0], args[1], args[2], args[3], args[4]);
48138 return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
48141 return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
48144 var thisBinding = baseCreate(Ctor.prototype),
48145 result = Ctor.apply(thisBinding, args); // Mimic the constructor's `return` behavior.
48146 // See https://es5.github.io/#x13.2.2 for more details.
48148 return isObject(result) ? result : thisBinding;
48152 * Creates a function that wraps `func` to enable currying.
48155 * @param {Function} func The function to wrap.
48156 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48157 * @param {number} arity The arity of `func`.
48158 * @returns {Function} Returns the new wrapped function.
48162 function createCurry(func, bitmask, arity) {
48163 var Ctor = createCtor(func);
48165 function wrapper() {
48166 var length = arguments.length,
48167 args = Array(length),
48169 placeholder = getHolder(wrapper);
48172 args[index] = arguments[index];
48175 var holders = length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder ? [] : replaceHolders(args, placeholder);
48176 length -= holders.length;
48178 if (length < arity) {
48179 return createRecurry(func, bitmask, createHybrid, wrapper.placeholder, undefined$1, args, holders, undefined$1, undefined$1, arity - length);
48182 var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
48183 return apply(fn, this, args);
48189 * Creates a `_.find` or `_.findLast` function.
48192 * @param {Function} findIndexFunc The function to find the collection index.
48193 * @returns {Function} Returns the new find function.
48197 function createFind(findIndexFunc) {
48198 return function (collection, predicate, fromIndex) {
48199 var iterable = Object(collection);
48201 if (!isArrayLike(collection)) {
48202 var iteratee = getIteratee(predicate, 3);
48203 collection = keys(collection);
48205 predicate = function predicate(key) {
48206 return iteratee(iterable[key], key, iterable);
48210 var index = findIndexFunc(collection, predicate, fromIndex);
48211 return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined$1;
48215 * Creates a `_.flow` or `_.flowRight` function.
48218 * @param {boolean} [fromRight] Specify iterating from right to left.
48219 * @returns {Function} Returns the new flow function.
48223 function createFlow(fromRight) {
48224 return flatRest(function (funcs) {
48225 var length = funcs.length,
48227 prereq = LodashWrapper.prototype.thru;
48234 var func = funcs[index];
48236 if (typeof func != 'function') {
48237 throw new TypeError(FUNC_ERROR_TEXT);
48240 if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
48241 var wrapper = new LodashWrapper([], true);
48245 index = wrapper ? index : length;
48247 while (++index < length) {
48248 func = funcs[index];
48249 var funcName = getFuncName(func),
48250 data = funcName == 'wrapper' ? getData(func) : undefined$1;
48252 if (data && isLaziable(data[0]) && data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && !data[4].length && data[9] == 1) {
48253 wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
48255 wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func);
48259 return function () {
48260 var args = arguments,
48263 if (wrapper && args.length == 1 && isArray(value)) {
48264 return wrapper.plant(value).value();
48268 result = length ? funcs[index].apply(this, args) : value;
48270 while (++index < length) {
48271 result = funcs[index].call(this, result);
48279 * Creates a function that wraps `func` to invoke it with optional `this`
48280 * binding of `thisArg`, partial application, and currying.
48283 * @param {Function|string} func The function or method name to wrap.
48284 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48285 * @param {*} [thisArg] The `this` binding of `func`.
48286 * @param {Array} [partials] The arguments to prepend to those provided to
48287 * the new function.
48288 * @param {Array} [holders] The `partials` placeholder indexes.
48289 * @param {Array} [partialsRight] The arguments to append to those provided
48290 * to the new function.
48291 * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
48292 * @param {Array} [argPos] The argument positions of the new function.
48293 * @param {number} [ary] The arity cap of `func`.
48294 * @param {number} [arity] The arity of `func`.
48295 * @returns {Function} Returns the new wrapped function.
48299 function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
48300 var isAry = bitmask & WRAP_ARY_FLAG,
48301 isBind = bitmask & WRAP_BIND_FLAG,
48302 isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
48303 isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
48304 isFlip = bitmask & WRAP_FLIP_FLAG,
48305 Ctor = isBindKey ? undefined$1 : createCtor(func);
48307 function wrapper() {
48308 var length = arguments.length,
48309 args = Array(length),
48313 args[index] = arguments[index];
48317 var placeholder = getHolder(wrapper),
48318 holdersCount = countHolders(args, placeholder);
48322 args = composeArgs(args, partials, holders, isCurried);
48325 if (partialsRight) {
48326 args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
48329 length -= holdersCount;
48331 if (isCurried && length < arity) {
48332 var newHolders = replaceHolders(args, placeholder);
48333 return createRecurry(func, bitmask, createHybrid, wrapper.placeholder, thisArg, args, newHolders, argPos, ary, arity - length);
48336 var thisBinding = isBind ? thisArg : this,
48337 fn = isBindKey ? thisBinding[func] : func;
48338 length = args.length;
48341 args = reorder(args, argPos);
48342 } else if (isFlip && length > 1) {
48346 if (isAry && ary < length) {
48350 if (this && this !== root && this instanceof wrapper) {
48351 fn = Ctor || createCtor(fn);
48354 return fn.apply(thisBinding, args);
48360 * Creates a function like `_.invertBy`.
48363 * @param {Function} setter The function to set accumulator values.
48364 * @param {Function} toIteratee The function to resolve iteratees.
48365 * @returns {Function} Returns the new inverter function.
48369 function createInverter(setter, toIteratee) {
48370 return function (object, iteratee) {
48371 return baseInverter(object, setter, toIteratee(iteratee), {});
48375 * Creates a function that performs a mathematical operation on two values.
48378 * @param {Function} operator The function to perform the operation.
48379 * @param {number} [defaultValue] The value used for `undefined` arguments.
48380 * @returns {Function} Returns the new mathematical operation function.
48384 function createMathOperation(operator, defaultValue) {
48385 return function (value, other) {
48388 if (value === undefined$1 && other === undefined$1) {
48389 return defaultValue;
48392 if (value !== undefined$1) {
48396 if (other !== undefined$1) {
48397 if (result === undefined$1) {
48401 if (typeof value == 'string' || typeof other == 'string') {
48402 value = baseToString(value);
48403 other = baseToString(other);
48405 value = baseToNumber(value);
48406 other = baseToNumber(other);
48409 result = operator(value, other);
48416 * Creates a function like `_.over`.
48419 * @param {Function} arrayFunc The function to iterate over iteratees.
48420 * @returns {Function} Returns the new over function.
48424 function createOver(arrayFunc) {
48425 return flatRest(function (iteratees) {
48426 iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
48427 return baseRest(function (args) {
48428 var thisArg = this;
48429 return arrayFunc(iteratees, function (iteratee) {
48430 return apply(iteratee, thisArg, args);
48436 * Creates the padding for `string` based on `length`. The `chars` string
48437 * is truncated if the number of characters exceeds `length`.
48440 * @param {number} length The padding length.
48441 * @param {string} [chars=' '] The string used as padding.
48442 * @returns {string} Returns the padding for `string`.
48446 function createPadding(length, chars) {
48447 chars = chars === undefined$1 ? ' ' : baseToString(chars);
48448 var charsLength = chars.length;
48450 if (charsLength < 2) {
48451 return charsLength ? baseRepeat(chars, length) : chars;
48454 var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
48455 return hasUnicode(chars) ? castSlice(stringToArray(result), 0, length).join('') : result.slice(0, length);
48458 * Creates a function that wraps `func` to invoke it with the `this` binding
48459 * of `thisArg` and `partials` prepended to the arguments it receives.
48462 * @param {Function} func The function to wrap.
48463 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48464 * @param {*} thisArg The `this` binding of `func`.
48465 * @param {Array} partials The arguments to prepend to those provided to
48466 * the new function.
48467 * @returns {Function} Returns the new wrapped function.
48471 function createPartial(func, bitmask, thisArg, partials) {
48472 var isBind = bitmask & WRAP_BIND_FLAG,
48473 Ctor = createCtor(func);
48475 function wrapper() {
48476 var argsIndex = -1,
48477 argsLength = arguments.length,
48479 leftLength = partials.length,
48480 args = Array(leftLength + argsLength),
48481 fn = this && this !== root && this instanceof wrapper ? Ctor : func;
48483 while (++leftIndex < leftLength) {
48484 args[leftIndex] = partials[leftIndex];
48487 while (argsLength--) {
48488 args[leftIndex++] = arguments[++argsIndex];
48491 return apply(fn, isBind ? thisArg : this, args);
48497 * Creates a `_.range` or `_.rangeRight` function.
48500 * @param {boolean} [fromRight] Specify iterating from right to left.
48501 * @returns {Function} Returns the new range function.
48505 function createRange(fromRight) {
48506 return function (start, end, step) {
48507 if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
48508 end = step = undefined$1;
48509 } // Ensure the sign of `-0` is preserved.
48512 start = toFinite(start);
48514 if (end === undefined$1) {
48518 end = toFinite(end);
48521 step = step === undefined$1 ? start < end ? 1 : -1 : toFinite(step);
48522 return baseRange(start, end, step, fromRight);
48526 * Creates a function that performs a relational operation on two values.
48529 * @param {Function} operator The function to perform the operation.
48530 * @returns {Function} Returns the new relational operation function.
48534 function createRelationalOperation(operator) {
48535 return function (value, other) {
48536 if (!(typeof value == 'string' && typeof other == 'string')) {
48537 value = toNumber(value);
48538 other = toNumber(other);
48541 return operator(value, other);
48545 * Creates a function that wraps `func` to continue currying.
48548 * @param {Function} func The function to wrap.
48549 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48550 * @param {Function} wrapFunc The function to create the `func` wrapper.
48551 * @param {*} placeholder The placeholder value.
48552 * @param {*} [thisArg] The `this` binding of `func`.
48553 * @param {Array} [partials] The arguments to prepend to those provided to
48554 * the new function.
48555 * @param {Array} [holders] The `partials` placeholder indexes.
48556 * @param {Array} [argPos] The argument positions of the new function.
48557 * @param {number} [ary] The arity cap of `func`.
48558 * @param {number} [arity] The arity of `func`.
48559 * @returns {Function} Returns the new wrapped function.
48563 function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
48564 var isCurry = bitmask & WRAP_CURRY_FLAG,
48565 newHolders = isCurry ? holders : undefined$1,
48566 newHoldersRight = isCurry ? undefined$1 : holders,
48567 newPartials = isCurry ? partials : undefined$1,
48568 newPartialsRight = isCurry ? undefined$1 : partials;
48569 bitmask |= isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG;
48570 bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
48572 if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
48573 bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
48576 var newData = [func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, newHoldersRight, argPos, ary, arity];
48577 var result = wrapFunc.apply(undefined$1, newData);
48579 if (isLaziable(func)) {
48580 setData(result, newData);
48583 result.placeholder = placeholder;
48584 return setWrapToString(result, func, bitmask);
48587 * Creates a function like `_.round`.
48590 * @param {string} methodName The name of the `Math` method to use when rounding.
48591 * @returns {Function} Returns the new round function.
48595 function createRound(methodName) {
48596 var func = Math[methodName];
48597 return function (number, precision) {
48598 number = toNumber(number);
48599 precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
48601 if (precision && nativeIsFinite(number)) {
48602 // Shift with exponential notation to avoid floating-point issues.
48603 // See [MDN](https://mdn.io/round#Examples) for more details.
48604 var pair = (toString(number) + 'e').split('e'),
48605 value = func(pair[0] + 'e' + (+pair[1] + precision));
48606 pair = (toString(value) + 'e').split('e');
48607 return +(pair[0] + 'e' + (+pair[1] - precision));
48610 return func(number);
48614 * Creates a set object of `values`.
48617 * @param {Array} values The values to add to the set.
48618 * @returns {Object} Returns the new set.
48622 var createSet = !(Set && 1 / setToArray(new Set([, -0]))[1] == INFINITY) ? noop : function (values) {
48623 return new Set(values);
48626 * Creates a `_.toPairs` or `_.toPairsIn` function.
48629 * @param {Function} keysFunc The function to get the keys of a given object.
48630 * @returns {Function} Returns the new pairs function.
48633 function createToPairs(keysFunc) {
48634 return function (object) {
48635 var tag = getTag(object);
48637 if (tag == mapTag) {
48638 return mapToArray(object);
48641 if (tag == setTag) {
48642 return setToPairs(object);
48645 return baseToPairs(object, keysFunc(object));
48649 * Creates a function that either curries or invokes `func` with optional
48650 * `this` binding and partially applied arguments.
48653 * @param {Function|string} func The function or method name to wrap.
48654 * @param {number} bitmask The bitmask flags.
48657 * 4 - `_.curry` or `_.curryRight` of a bound function
48659 * 16 - `_.curryRight`
48661 * 64 - `_.partialRight`
48665 * @param {*} [thisArg] The `this` binding of `func`.
48666 * @param {Array} [partials] The arguments to be partially applied.
48667 * @param {Array} [holders] The `partials` placeholder indexes.
48668 * @param {Array} [argPos] The argument positions of the new function.
48669 * @param {number} [ary] The arity cap of `func`.
48670 * @param {number} [arity] The arity of `func`.
48671 * @returns {Function} Returns the new wrapped function.
48675 function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
48676 var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
48678 if (!isBindKey && typeof func != 'function') {
48679 throw new TypeError(FUNC_ERROR_TEXT);
48682 var length = partials ? partials.length : 0;
48685 bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
48686 partials = holders = undefined$1;
48689 ary = ary === undefined$1 ? ary : nativeMax(toInteger(ary), 0);
48690 arity = arity === undefined$1 ? arity : toInteger(arity);
48691 length -= holders ? holders.length : 0;
48693 if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
48694 var partialsRight = partials,
48695 holdersRight = holders;
48696 partials = holders = undefined$1;
48699 var data = isBindKey ? undefined$1 : getData(func);
48700 var newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
48703 mergeData(newData, data);
48707 bitmask = newData[1];
48708 thisArg = newData[2];
48709 partials = newData[3];
48710 holders = newData[4];
48711 arity = newData[9] = newData[9] === undefined$1 ? isBindKey ? 0 : func.length : nativeMax(newData[9] - length, 0);
48713 if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
48714 bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
48717 if (!bitmask || bitmask == WRAP_BIND_FLAG) {
48718 var result = createBind(func, bitmask, thisArg);
48719 } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
48720 result = createCurry(func, bitmask, arity);
48721 } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
48722 result = createPartial(func, bitmask, thisArg, partials);
48724 result = createHybrid.apply(undefined$1, newData);
48727 var setter = data ? baseSetData : setData;
48728 return setWrapToString(setter(result, newData), func, bitmask);
48731 * Used by `_.defaults` to customize its `_.assignIn` use to assign properties
48732 * of source objects to the destination object for all destination properties
48733 * that resolve to `undefined`.
48736 * @param {*} objValue The destination value.
48737 * @param {*} srcValue The source value.
48738 * @param {string} key The key of the property to assign.
48739 * @param {Object} object The parent object of `objValue`.
48740 * @returns {*} Returns the value to assign.
48744 function customDefaultsAssignIn(objValue, srcValue, key, object) {
48745 if (objValue === undefined$1 || eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key)) {
48752 * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
48753 * objects into destination objects that are passed thru.
48756 * @param {*} objValue The destination value.
48757 * @param {*} srcValue The source value.
48758 * @param {string} key The key of the property to merge.
48759 * @param {Object} object The parent object of `objValue`.
48760 * @param {Object} source The parent object of `srcValue`.
48761 * @param {Object} [stack] Tracks traversed source values and their merged
48763 * @returns {*} Returns the value to assign.
48767 function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
48768 if (isObject(objValue) && isObject(srcValue)) {
48769 // Recursively merge objects and arrays (susceptible to call stack limits).
48770 stack.set(srcValue, objValue);
48771 baseMerge(objValue, srcValue, undefined$1, customDefaultsMerge, stack);
48772 stack['delete'](srcValue);
48778 * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
48782 * @param {*} value The value to inspect.
48783 * @param {string} key The key of the property to inspect.
48784 * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
48788 function customOmitClone(value) {
48789 return isPlainObject(value) ? undefined$1 : value;
48792 * A specialized version of `baseIsEqualDeep` for arrays with support for
48793 * partial deep comparisons.
48796 * @param {Array} array The array to compare.
48797 * @param {Array} other The other array to compare.
48798 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
48799 * @param {Function} customizer The function to customize comparisons.
48800 * @param {Function} equalFunc The function to determine equivalents of values.
48801 * @param {Object} stack Tracks traversed `array` and `other` objects.
48802 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
48806 function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
48807 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
48808 arrLength = array.length,
48809 othLength = other.length;
48811 if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
48813 } // Check that cyclic values are equal.
48816 var arrStacked = stack.get(array);
48817 var othStacked = stack.get(other);
48819 if (arrStacked && othStacked) {
48820 return arrStacked == other && othStacked == array;
48825 seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache() : undefined$1;
48826 stack.set(array, other);
48827 stack.set(other, array); // Ignore non-index properties.
48829 while (++index < arrLength) {
48830 var arrValue = array[index],
48831 othValue = other[index];
48834 var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack);
48837 if (compared !== undefined$1) {
48844 } // Recursively compare arrays (susceptible to call stack limits).
48848 if (!arraySome(other, function (othValue, othIndex) {
48849 if (!cacheHas(seen, othIndex) && (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
48850 return seen.push(othIndex);
48856 } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
48862 stack['delete'](array);
48863 stack['delete'](other);
48867 * A specialized version of `baseIsEqualDeep` for comparing objects of
48868 * the same `toStringTag`.
48870 * **Note:** This function only supports comparing values with tags of
48871 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
48874 * @param {Object} object The object to compare.
48875 * @param {Object} other The other object to compare.
48876 * @param {string} tag The `toStringTag` of the objects to compare.
48877 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
48878 * @param {Function} customizer The function to customize comparisons.
48879 * @param {Function} equalFunc The function to determine equivalents of values.
48880 * @param {Object} stack Tracks traversed `object` and `other` objects.
48881 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
48885 function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
48888 if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) {
48892 object = object.buffer;
48893 other = other.buffer;
48895 case arrayBufferTag:
48896 if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
48905 // Coerce booleans to `1` or `0` and dates to milliseconds.
48906 // Invalid dates are coerced to `NaN`.
48907 return eq(+object, +other);
48910 return object.name == other.name && object.message == other.message;
48914 // Coerce regexes to strings and treat strings, primitives and objects,
48915 // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
48916 // for more details.
48917 return object == other + '';
48920 var convert = mapToArray;
48923 var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
48924 convert || (convert = setToArray);
48926 if (object.size != other.size && !isPartial) {
48928 } // Assume cyclic values are equal.
48931 var stacked = stack.get(object);
48934 return stacked == other;
48937 bitmask |= COMPARE_UNORDERED_FLAG; // Recursively compare objects (susceptible to call stack limits).
48939 stack.set(object, other);
48940 var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
48941 stack['delete'](object);
48945 if (symbolValueOf) {
48946 return symbolValueOf.call(object) == symbolValueOf.call(other);
48954 * A specialized version of `baseIsEqualDeep` for objects with support for
48955 * partial deep comparisons.
48958 * @param {Object} object The object to compare.
48959 * @param {Object} other The other object to compare.
48960 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
48961 * @param {Function} customizer The function to customize comparisons.
48962 * @param {Function} equalFunc The function to determine equivalents of values.
48963 * @param {Object} stack Tracks traversed `object` and `other` objects.
48964 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
48968 function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
48969 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
48970 objProps = getAllKeys(object),
48971 objLength = objProps.length,
48972 othProps = getAllKeys(other),
48973 othLength = othProps.length;
48975 if (objLength != othLength && !isPartial) {
48979 var index = objLength;
48982 var key = objProps[index];
48984 if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
48987 } // Check that cyclic values are equal.
48990 var objStacked = stack.get(object);
48991 var othStacked = stack.get(other);
48993 if (objStacked && othStacked) {
48994 return objStacked == other && othStacked == object;
48998 stack.set(object, other);
48999 stack.set(other, object);
49000 var skipCtor = isPartial;
49002 while (++index < objLength) {
49003 key = objProps[index];
49004 var objValue = object[key],
49005 othValue = other[key];
49008 var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack);
49009 } // Recursively compare objects (susceptible to call stack limits).
49012 if (!(compared === undefined$1 ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) {
49017 skipCtor || (skipCtor = key == 'constructor');
49020 if (result && !skipCtor) {
49021 var objCtor = object.constructor,
49022 othCtor = other.constructor; // Non `Object` object instances with different constructors are not equal.
49024 if (objCtor != othCtor && 'constructor' in object && 'constructor' in other && !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) {
49029 stack['delete'](object);
49030 stack['delete'](other);
49034 * A specialized version of `baseRest` which flattens the rest array.
49037 * @param {Function} func The function to apply a rest parameter to.
49038 * @returns {Function} Returns the new function.
49042 function flatRest(func) {
49043 return setToString(overRest(func, undefined$1, flatten), func + '');
49046 * Creates an array of own enumerable property names and symbols of `object`.
49049 * @param {Object} object The object to query.
49050 * @returns {Array} Returns the array of property names and symbols.
49054 function getAllKeys(object) {
49055 return baseGetAllKeys(object, keys, getSymbols);
49058 * Creates an array of own and inherited enumerable property names and
49059 * symbols of `object`.
49062 * @param {Object} object The object to query.
49063 * @returns {Array} Returns the array of property names and symbols.
49067 function getAllKeysIn(object) {
49068 return baseGetAllKeys(object, keysIn, getSymbolsIn);
49071 * Gets metadata for `func`.
49074 * @param {Function} func The function to query.
49075 * @returns {*} Returns the metadata for `func`.
49079 var getData = !metaMap ? noop : function (func) {
49080 return metaMap.get(func);
49083 * Gets the name of `func`.
49086 * @param {Function} func The function to query.
49087 * @returns {string} Returns the function name.
49090 function getFuncName(func) {
49091 var result = func.name + '',
49092 array = realNames[result],
49093 length = hasOwnProperty.call(realNames, result) ? array.length : 0;
49096 var data = array[length],
49097 otherFunc = data.func;
49099 if (otherFunc == null || otherFunc == func) {
49107 * Gets the argument placeholder value for `func`.
49110 * @param {Function} func The function to inspect.
49111 * @returns {*} Returns the placeholder value.
49115 function getHolder(func) {
49116 var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
49117 return object.placeholder;
49120 * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
49121 * this function returns the custom method, otherwise it returns `baseIteratee`.
49122 * If arguments are provided, the chosen function is invoked with them and
49123 * its result is returned.
49126 * @param {*} [value] The value to convert to an iteratee.
49127 * @param {number} [arity] The arity of the created iteratee.
49128 * @returns {Function} Returns the chosen function or its result.
49132 function getIteratee() {
49133 var result = lodash.iteratee || iteratee;
49134 result = result === iteratee ? baseIteratee : result;
49135 return arguments.length ? result(arguments[0], arguments[1]) : result;
49138 * Gets the data for `map`.
49141 * @param {Object} map The map to query.
49142 * @param {string} key The reference key.
49143 * @returns {*} Returns the map data.
49147 function getMapData(map, key) {
49148 var data = map.__data__;
49149 return isKeyable(key) ? data[typeof key == 'string' ? 'string' : 'hash'] : data.map;
49152 * Gets the property names, values, and compare flags of `object`.
49155 * @param {Object} object The object to query.
49156 * @returns {Array} Returns the match data of `object`.
49160 function getMatchData(object) {
49161 var result = keys(object),
49162 length = result.length;
49165 var key = result[length],
49166 value = object[key];
49167 result[length] = [key, value, isStrictComparable(value)];
49173 * Gets the native function at `key` of `object`.
49176 * @param {Object} object The object to query.
49177 * @param {string} key The key of the method to get.
49178 * @returns {*} Returns the function if it's native, else `undefined`.
49182 function getNative(object, key) {
49183 var value = getValue(object, key);
49184 return baseIsNative(value) ? value : undefined$1;
49187 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
49190 * @param {*} value The value to query.
49191 * @returns {string} Returns the raw `toStringTag`.
49195 function getRawTag(value) {
49196 var isOwn = hasOwnProperty.call(value, symToStringTag),
49197 tag = value[symToStringTag];
49200 value[symToStringTag] = undefined$1;
49201 var unmasked = true;
49204 var result = nativeObjectToString.call(value);
49208 value[symToStringTag] = tag;
49210 delete value[symToStringTag];
49217 * Creates an array of the own enumerable symbols of `object`.
49220 * @param {Object} object The object to query.
49221 * @returns {Array} Returns the array of symbols.
49225 var getSymbols = !nativeGetSymbols ? stubArray : function (object) {
49226 if (object == null) {
49230 object = Object(object);
49231 return arrayFilter(nativeGetSymbols(object), function (symbol) {
49232 return propertyIsEnumerable.call(object, symbol);
49236 * Creates an array of the own and inherited enumerable symbols of `object`.
49239 * @param {Object} object The object to query.
49240 * @returns {Array} Returns the array of symbols.
49243 var getSymbolsIn = !nativeGetSymbols ? stubArray : function (object) {
49247 arrayPush(result, getSymbols(object));
49248 object = getPrototype(object);
49254 * Gets the `toStringTag` of `value`.
49257 * @param {*} value The value to query.
49258 * @returns {string} Returns the `toStringTag`.
49261 var getTag = baseGetTag; // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
49263 if (DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag || Map && getTag(new Map()) != mapTag || Promise && getTag(Promise.resolve()) != promiseTag || Set && getTag(new Set()) != setTag || WeakMap && getTag(new WeakMap()) != weakMapTag) {
49264 getTag = function getTag(value) {
49265 var result = baseGetTag(value),
49266 Ctor = result == objectTag ? value.constructor : undefined$1,
49267 ctorString = Ctor ? toSource(Ctor) : '';
49270 switch (ctorString) {
49271 case dataViewCtorString:
49272 return dataViewTag;
49274 case mapCtorString:
49277 case promiseCtorString:
49280 case setCtorString:
49283 case weakMapCtorString:
49292 * Gets the view, applying any `transforms` to the `start` and `end` positions.
49295 * @param {number} start The start of the view.
49296 * @param {number} end The end of the view.
49297 * @param {Array} transforms The transformations to apply to the view.
49298 * @returns {Object} Returns an object containing the `start` and `end`
49299 * positions of the view.
49303 function getView(start, end, transforms) {
49305 length = transforms.length;
49307 while (++index < length) {
49308 var data = transforms[index],
49311 switch (data.type) {
49321 end = nativeMin(end, start + size);
49325 start = nativeMax(start, end - size);
49336 * Extracts wrapper details from the `source` body comment.
49339 * @param {string} source The source to inspect.
49340 * @returns {Array} Returns the wrapper details.
49344 function getWrapDetails(source) {
49345 var match = source.match(reWrapDetails);
49346 return match ? match[1].split(reSplitDetails) : [];
49349 * Checks if `path` exists on `object`.
49352 * @param {Object} object The object to query.
49353 * @param {Array|string} path The path to check.
49354 * @param {Function} hasFunc The function to check properties.
49355 * @returns {boolean} Returns `true` if `path` exists, else `false`.
49359 function hasPath(object, path, hasFunc) {
49360 path = castPath(path, object);
49362 length = path.length,
49365 while (++index < length) {
49366 var key = toKey(path[index]);
49368 if (!(result = object != null && hasFunc(object, key))) {
49372 object = object[key];
49375 if (result || ++index != length) {
49379 length = object == null ? 0 : object.length;
49380 return !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object));
49383 * Initializes an array clone.
49386 * @param {Array} array The array to clone.
49387 * @returns {Array} Returns the initialized clone.
49391 function initCloneArray(array) {
49392 var length = array.length,
49393 result = new array.constructor(length); // Add properties assigned by `RegExp#exec`.
49395 if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
49396 result.index = array.index;
49397 result.input = array.input;
49403 * Initializes an object clone.
49406 * @param {Object} object The object to clone.
49407 * @returns {Object} Returns the initialized clone.
49411 function initCloneObject(object) {
49412 return typeof object.constructor == 'function' && !isPrototype(object) ? baseCreate(getPrototype(object)) : {};
49415 * Initializes an object clone based on its `toStringTag`.
49417 * **Note:** This function only supports cloning values with tags of
49418 * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.
49421 * @param {Object} object The object to clone.
49422 * @param {string} tag The `toStringTag` of the object to clone.
49423 * @param {boolean} [isDeep] Specify a deep clone.
49424 * @returns {Object} Returns the initialized clone.
49428 function initCloneByTag(object, tag, isDeep) {
49429 var Ctor = object.constructor;
49432 case arrayBufferTag:
49433 return cloneArrayBuffer(object);
49437 return new Ctor(+object);
49440 return cloneDataView(object, isDeep);
49448 case uint8ClampedTag:
49451 return cloneTypedArray(object, isDeep);
49458 return new Ctor(object);
49461 return cloneRegExp(object);
49467 return cloneSymbol(object);
49471 * Inserts wrapper `details` in a comment at the top of the `source` body.
49474 * @param {string} source The source to modify.
49475 * @returns {Array} details The details to insert.
49476 * @returns {string} Returns the modified source.
49480 function insertWrapDetails(source, details) {
49481 var length = details.length;
49487 var lastIndex = length - 1;
49488 details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
49489 details = details.join(length > 2 ? ', ' : ' ');
49490 return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
49493 * Checks if `value` is a flattenable `arguments` object or array.
49496 * @param {*} value The value to check.
49497 * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
49501 function isFlattenable(value) {
49502 return isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]);
49505 * Checks if `value` is a valid array-like index.
49508 * @param {*} value The value to check.
49509 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
49510 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
49514 function isIndex(value, length) {
49515 var type = _typeof(value);
49517 length = length == null ? MAX_SAFE_INTEGER : length;
49518 return !!length && (type == 'number' || type != 'symbol' && reIsUint.test(value)) && value > -1 && value % 1 == 0 && value < length;
49521 * Checks if the given arguments are from an iteratee call.
49524 * @param {*} value The potential iteratee value argument.
49525 * @param {*} index The potential iteratee index or key argument.
49526 * @param {*} object The potential iteratee object argument.
49527 * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
49532 function isIterateeCall(value, index, object) {
49533 if (!isObject(object)) {
49537 var type = _typeof(index);
49539 if (type == 'number' ? isArrayLike(object) && isIndex(index, object.length) : type == 'string' && index in object) {
49540 return eq(object[index], value);
49546 * Checks if `value` is a property name and not a property path.
49549 * @param {*} value The value to check.
49550 * @param {Object} [object] The object to query keys on.
49551 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
49555 function isKey(value, object) {
49556 if (isArray(value)) {
49560 var type = _typeof(value);
49562 if (type == 'number' || type == 'symbol' || type == 'boolean' || value == null || isSymbol(value)) {
49566 return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object(object);
49569 * Checks if `value` is suitable for use as unique object key.
49572 * @param {*} value The value to check.
49573 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
49577 function isKeyable(value) {
49578 var type = _typeof(value);
49580 return type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean' ? value !== '__proto__' : value === null;
49583 * Checks if `func` has a lazy counterpart.
49586 * @param {Function} func The function to check.
49587 * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
49592 function isLaziable(func) {
49593 var funcName = getFuncName(func),
49594 other = lodash[funcName];
49596 if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
49600 if (func === other) {
49604 var data = getData(other);
49605 return !!data && func === data[0];
49608 * Checks if `func` has its source masked.
49611 * @param {Function} func The function to check.
49612 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
49616 function isMasked(func) {
49617 return !!maskSrcKey && maskSrcKey in func;
49620 * Checks if `func` is capable of being masked.
49623 * @param {*} value The value to check.
49624 * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
49628 var isMaskable = coreJsData ? isFunction : stubFalse;
49630 * Checks if `value` is likely a prototype object.
49633 * @param {*} value The value to check.
49634 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
49637 function isPrototype(value) {
49638 var Ctor = value && value.constructor,
49639 proto = typeof Ctor == 'function' && Ctor.prototype || objectProto;
49640 return value === proto;
49643 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
49646 * @param {*} value The value to check.
49647 * @returns {boolean} Returns `true` if `value` if suitable for strict
49648 * equality comparisons, else `false`.
49652 function isStrictComparable(value) {
49653 return value === value && !isObject(value);
49656 * A specialized version of `matchesProperty` for source values suitable
49657 * for strict equality comparisons, i.e. `===`.
49660 * @param {string} key The key of the property to get.
49661 * @param {*} srcValue The value to match.
49662 * @returns {Function} Returns the new spec function.
49666 function matchesStrictComparable(key, srcValue) {
49667 return function (object) {
49668 if (object == null) {
49672 return object[key] === srcValue && (srcValue !== undefined$1 || key in Object(object));
49676 * A specialized version of `_.memoize` which clears the memoized function's
49677 * cache when it exceeds `MAX_MEMOIZE_SIZE`.
49680 * @param {Function} func The function to have its output memoized.
49681 * @returns {Function} Returns the new memoized function.
49685 function memoizeCapped(func) {
49686 var result = memoize(func, function (key) {
49687 if (cache.size === MAX_MEMOIZE_SIZE) {
49693 var cache = result.cache;
49697 * Merges the function metadata of `source` into `data`.
49699 * Merging metadata reduces the number of wrappers used to invoke a function.
49700 * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
49701 * may be applied regardless of execution order. Methods like `_.ary` and
49702 * `_.rearg` modify function arguments, making the order in which they are
49703 * executed important, preventing the merging of metadata. However, we make
49704 * an exception for a safe combined case where curried functions have `_.ary`
49705 * and or `_.rearg` applied.
49708 * @param {Array} data The destination metadata.
49709 * @param {Array} source The source metadata.
49710 * @returns {Array} Returns `data`.
49714 function mergeData(data, source) {
49715 var bitmask = data[1],
49716 srcBitmask = source[1],
49717 newBitmask = bitmask | srcBitmask,
49718 isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
49719 var isCombo = srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_CURRY_FLAG || srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_REARG_FLAG && data[7].length <= source[8] || srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG) && source[7].length <= source[8] && bitmask == WRAP_CURRY_FLAG; // Exit early if metadata can't be merged.
49721 if (!(isCommon || isCombo)) {
49723 } // Use source `thisArg` if available.
49726 if (srcBitmask & WRAP_BIND_FLAG) {
49727 data[2] = source[2]; // Set when currying a bound function.
49729 newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
49730 } // Compose partial arguments.
49733 var value = source[3];
49736 var partials = data[3];
49737 data[3] = partials ? composeArgs(partials, value, source[4]) : value;
49738 data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
49739 } // Compose partial right arguments.
49745 partials = data[5];
49746 data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
49747 data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
49748 } // Use source `argPos` if available.
49755 } // Use source `ary` if it's smaller.
49758 if (srcBitmask & WRAP_ARY_FLAG) {
49759 data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
49760 } // Use source `arity` if one is not provided.
49763 if (data[9] == null) {
49764 data[9] = source[9];
49765 } // Use source `func` and merge bitmasks.
49768 data[0] = source[0];
49769 data[1] = newBitmask;
49773 * This function is like
49774 * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
49775 * except that it includes inherited enumerable properties.
49778 * @param {Object} object The object to query.
49779 * @returns {Array} Returns the array of property names.
49783 function nativeKeysIn(object) {
49786 if (object != null) {
49787 for (var key in Object(object)) {
49795 * Converts `value` to a string using `Object.prototype.toString`.
49798 * @param {*} value The value to convert.
49799 * @returns {string} Returns the converted string.
49803 function objectToString(value) {
49804 return nativeObjectToString.call(value);
49807 * A specialized version of `baseRest` which transforms the rest array.
49810 * @param {Function} func The function to apply a rest parameter to.
49811 * @param {number} [start=func.length-1] The start position of the rest parameter.
49812 * @param {Function} transform The rest array transform.
49813 * @returns {Function} Returns the new function.
49817 function overRest(func, start, transform) {
49818 start = nativeMax(start === undefined$1 ? func.length - 1 : start, 0);
49819 return function () {
49820 var args = arguments,
49822 length = nativeMax(args.length - start, 0),
49823 array = Array(length);
49825 while (++index < length) {
49826 array[index] = args[start + index];
49830 var otherArgs = Array(start + 1);
49832 while (++index < start) {
49833 otherArgs[index] = args[index];
49836 otherArgs[start] = transform(array);
49837 return apply(func, this, otherArgs);
49841 * Gets the parent value at `path` of `object`.
49844 * @param {Object} object The object to query.
49845 * @param {Array} path The path to get the parent value of.
49846 * @returns {*} Returns the parent value.
49850 function parent(object, path) {
49851 return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
49854 * Reorder `array` according to the specified indexes where the element at
49855 * the first index is assigned as the first element, the element at
49856 * the second index is assigned as the second element, and so on.
49859 * @param {Array} array The array to reorder.
49860 * @param {Array} indexes The arranged array indexes.
49861 * @returns {Array} Returns `array`.
49865 function reorder(array, indexes) {
49866 var arrLength = array.length,
49867 length = nativeMin(indexes.length, arrLength),
49868 oldArray = copyArray(array);
49871 var index = indexes[length];
49872 array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined$1;
49878 * Gets the value at `key`, unless `key` is "__proto__" or "constructor".
49881 * @param {Object} object The object to query.
49882 * @param {string} key The key of the property to get.
49883 * @returns {*} Returns the property value.
49887 function safeGet(object, key) {
49888 if (key === 'constructor' && typeof object[key] === 'function') {
49892 if (key == '__proto__') {
49896 return object[key];
49899 * Sets metadata for `func`.
49901 * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
49902 * period of time, it will trip its breaker and transition to an identity
49903 * function to avoid garbage collection pauses in V8. See
49904 * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
49905 * for more details.
49908 * @param {Function} func The function to associate metadata with.
49909 * @param {*} data The metadata.
49910 * @returns {Function} Returns `func`.
49914 var setData = shortOut(baseSetData);
49916 * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
49919 * @param {Function} func The function to delay.
49920 * @param {number} wait The number of milliseconds to delay invocation.
49921 * @returns {number|Object} Returns the timer id or timeout object.
49924 var setTimeout = ctxSetTimeout || function (func, wait) {
49925 return root.setTimeout(func, wait);
49928 * Sets the `toString` method of `func` to return `string`.
49931 * @param {Function} func The function to modify.
49932 * @param {Function} string The `toString` result.
49933 * @returns {Function} Returns `func`.
49937 var setToString = shortOut(baseSetToString);
49939 * Sets the `toString` method of `wrapper` to mimic the source of `reference`
49940 * with wrapper details in a comment at the top of the source body.
49943 * @param {Function} wrapper The function to modify.
49944 * @param {Function} reference The reference function.
49945 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
49946 * @returns {Function} Returns `wrapper`.
49949 function setWrapToString(wrapper, reference, bitmask) {
49950 var source = reference + '';
49951 return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
49954 * Creates a function that'll short out and invoke `identity` instead
49955 * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
49959 * @param {Function} func The function to restrict.
49960 * @returns {Function} Returns the new shortable function.
49964 function shortOut(func) {
49967 return function () {
49968 var stamp = nativeNow(),
49969 remaining = HOT_SPAN - (stamp - lastCalled);
49970 lastCalled = stamp;
49972 if (remaining > 0) {
49973 if (++count >= HOT_COUNT) {
49974 return arguments[0];
49980 return func.apply(undefined$1, arguments);
49984 * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
49987 * @param {Array} array The array to shuffle.
49988 * @param {number} [size=array.length] The size of `array`.
49989 * @returns {Array} Returns `array`.
49993 function shuffleSelf(array, size) {
49995 length = array.length,
49996 lastIndex = length - 1;
49997 size = size === undefined$1 ? length : size;
49999 while (++index < size) {
50000 var rand = baseRandom(index, lastIndex),
50001 value = array[rand];
50002 array[rand] = array[index];
50003 array[index] = value;
50006 array.length = size;
50010 * Converts `string` to a property path array.
50013 * @param {string} string The string to convert.
50014 * @returns {Array} Returns the property path array.
50018 var stringToPath = memoizeCapped(function (string) {
50021 if (string.charCodeAt(0) === 46
50027 string.replace(rePropName, function (match, number, quote, subString) {
50028 result.push(quote ? subString.replace(reEscapeChar, '$1') : number || match);
50033 * Converts `value` to a string key if it's not a string or symbol.
50036 * @param {*} value The value to inspect.
50037 * @returns {string|symbol} Returns the key.
50040 function toKey(value) {
50041 if (typeof value == 'string' || isSymbol(value)) {
50045 var result = value + '';
50046 return result == '0' && 1 / value == -INFINITY ? '-0' : result;
50049 * Converts `func` to its source code.
50052 * @param {Function} func The function to convert.
50053 * @returns {string} Returns the source code.
50057 function toSource(func) {
50058 if (func != null) {
50060 return funcToString.call(func);
50071 * Updates wrapper `details` based on `bitmask` flags.
50074 * @returns {Array} details The details to modify.
50075 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
50076 * @returns {Array} Returns `details`.
50080 function updateWrapDetails(details, bitmask) {
50081 arrayEach(wrapFlags, function (pair) {
50082 var value = '_.' + pair[0];
50084 if (bitmask & pair[1] && !arrayIncludes(details, value)) {
50085 details.push(value);
50088 return details.sort();
50091 * Creates a clone of `wrapper`.
50094 * @param {Object} wrapper The wrapper to clone.
50095 * @returns {Object} Returns the cloned wrapper.
50099 function wrapperClone(wrapper) {
50100 if (wrapper instanceof LazyWrapper) {
50101 return wrapper.clone();
50104 var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
50105 result.__actions__ = copyArray(wrapper.__actions__);
50106 result.__index__ = wrapper.__index__;
50107 result.__values__ = wrapper.__values__;
50110 /*------------------------------------------------------------------------*/
50113 * Creates an array of elements split into groups the length of `size`.
50114 * If `array` can't be split evenly, the final chunk will be the remaining
50121 * @param {Array} array The array to process.
50122 * @param {number} [size=1] The length of each chunk
50123 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
50124 * @returns {Array} Returns the new array of chunks.
50127 * _.chunk(['a', 'b', 'c', 'd'], 2);
50128 * // => [['a', 'b'], ['c', 'd']]
50130 * _.chunk(['a', 'b', 'c', 'd'], 3);
50131 * // => [['a', 'b', 'c'], ['d']]
50135 function chunk(array, size, guard) {
50136 if (guard ? isIterateeCall(array, size, guard) : size === undefined$1) {
50139 size = nativeMax(toInteger(size), 0);
50142 var length = array == null ? 0 : array.length;
50144 if (!length || size < 1) {
50150 result = Array(nativeCeil(length / size));
50152 while (index < length) {
50153 result[resIndex++] = baseSlice(array, index, index += size);
50159 * Creates an array with all falsey values removed. The values `false`, `null`,
50160 * `0`, `""`, `undefined`, and `NaN` are falsey.
50166 * @param {Array} array The array to compact.
50167 * @returns {Array} Returns the new array of filtered values.
50170 * _.compact([0, 1, false, 2, '', 3]);
50175 function compact(array) {
50177 length = array == null ? 0 : array.length,
50181 while (++index < length) {
50182 var value = array[index];
50185 result[resIndex++] = value;
50192 * Creates a new array concatenating `array` with any additional arrays
50199 * @param {Array} array The array to concatenate.
50200 * @param {...*} [values] The values to concatenate.
50201 * @returns {Array} Returns the new concatenated array.
50205 * var other = _.concat(array, 2, [3], [[4]]);
50207 * console.log(other);
50208 * // => [1, 2, 3, [4]]
50210 * console.log(array);
50215 function concat() {
50216 var length = arguments.length;
50222 var args = Array(length - 1),
50223 array = arguments[0],
50227 args[index - 1] = arguments[index];
50230 return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
50233 * Creates an array of `array` values not included in the other given arrays
50234 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
50235 * for equality comparisons. The order and references of result values are
50236 * determined by the first array.
50238 * **Note:** Unlike `_.pullAll`, this method returns a new array.
50244 * @param {Array} array The array to inspect.
50245 * @param {...Array} [values] The values to exclude.
50246 * @returns {Array} Returns the new array of filtered values.
50247 * @see _.without, _.xor
50250 * _.difference([2, 1], [2, 3]);
50255 var difference = baseRest(function (array, values) {
50256 return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) : [];
50259 * This method is like `_.difference` except that it accepts `iteratee` which
50260 * is invoked for each element of `array` and `values` to generate the criterion
50261 * by which they're compared. The order and references of result values are
50262 * determined by the first array. The iteratee is invoked with one argument:
50265 * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
50271 * @param {Array} array The array to inspect.
50272 * @param {...Array} [values] The values to exclude.
50273 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
50274 * @returns {Array} Returns the new array of filtered values.
50277 * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
50280 * // The `_.property` iteratee shorthand.
50281 * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
50282 * // => [{ 'x': 2 }]
50285 var differenceBy = baseRest(function (array, values) {
50286 var iteratee = last(values);
50288 if (isArrayLikeObject(iteratee)) {
50289 iteratee = undefined$1;
50292 return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) : [];
50295 * This method is like `_.difference` except that it accepts `comparator`
50296 * which is invoked to compare elements of `array` to `values`. The order and
50297 * references of result values are determined by the first array. The comparator
50298 * is invoked with two arguments: (arrVal, othVal).
50300 * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
50306 * @param {Array} array The array to inspect.
50307 * @param {...Array} [values] The values to exclude.
50308 * @param {Function} [comparator] The comparator invoked per element.
50309 * @returns {Array} Returns the new array of filtered values.
50312 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
50314 * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
50315 * // => [{ 'x': 2, 'y': 1 }]
50318 var differenceWith = baseRest(function (array, values) {
50319 var comparator = last(values);
50321 if (isArrayLikeObject(comparator)) {
50322 comparator = undefined$1;
50325 return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined$1, comparator) : [];
50328 * Creates a slice of `array` with `n` elements dropped from the beginning.
50334 * @param {Array} array The array to query.
50335 * @param {number} [n=1] The number of elements to drop.
50336 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
50337 * @returns {Array} Returns the slice of `array`.
50340 * _.drop([1, 2, 3]);
50343 * _.drop([1, 2, 3], 2);
50346 * _.drop([1, 2, 3], 5);
50349 * _.drop([1, 2, 3], 0);
50353 function drop(array, n, guard) {
50354 var length = array == null ? 0 : array.length;
50360 n = guard || n === undefined$1 ? 1 : toInteger(n);
50361 return baseSlice(array, n < 0 ? 0 : n, length);
50364 * Creates a slice of `array` with `n` elements dropped from the end.
50370 * @param {Array} array The array to query.
50371 * @param {number} [n=1] The number of elements to drop.
50372 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
50373 * @returns {Array} Returns the slice of `array`.
50376 * _.dropRight([1, 2, 3]);
50379 * _.dropRight([1, 2, 3], 2);
50382 * _.dropRight([1, 2, 3], 5);
50385 * _.dropRight([1, 2, 3], 0);
50390 function dropRight(array, n, guard) {
50391 var length = array == null ? 0 : array.length;
50397 n = guard || n === undefined$1 ? 1 : toInteger(n);
50399 return baseSlice(array, 0, n < 0 ? 0 : n);
50402 * Creates a slice of `array` excluding elements dropped from the end.
50403 * Elements are dropped until `predicate` returns falsey. The predicate is
50404 * invoked with three arguments: (value, index, array).
50410 * @param {Array} array The array to query.
50411 * @param {Function} [predicate=_.identity] The function invoked per iteration.
50412 * @returns {Array} Returns the slice of `array`.
50416 * { 'user': 'barney', 'active': true },
50417 * { 'user': 'fred', 'active': false },
50418 * { 'user': 'pebbles', 'active': false }
50421 * _.dropRightWhile(users, function(o) { return !o.active; });
50422 * // => objects for ['barney']
50424 * // The `_.matches` iteratee shorthand.
50425 * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
50426 * // => objects for ['barney', 'fred']
50428 * // The `_.matchesProperty` iteratee shorthand.
50429 * _.dropRightWhile(users, ['active', false]);
50430 * // => objects for ['barney']
50432 * // The `_.property` iteratee shorthand.
50433 * _.dropRightWhile(users, 'active');
50434 * // => objects for ['barney', 'fred', 'pebbles']
50438 function dropRightWhile(array, predicate) {
50439 return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true, true) : [];
50442 * Creates a slice of `array` excluding elements dropped from the beginning.
50443 * Elements are dropped until `predicate` returns falsey. The predicate is
50444 * invoked with three arguments: (value, index, array).
50450 * @param {Array} array The array to query.
50451 * @param {Function} [predicate=_.identity] The function invoked per iteration.
50452 * @returns {Array} Returns the slice of `array`.
50456 * { 'user': 'barney', 'active': false },
50457 * { 'user': 'fred', 'active': false },
50458 * { 'user': 'pebbles', 'active': true }
50461 * _.dropWhile(users, function(o) { return !o.active; });
50462 * // => objects for ['pebbles']
50464 * // The `_.matches` iteratee shorthand.
50465 * _.dropWhile(users, { 'user': 'barney', 'active': false });
50466 * // => objects for ['fred', 'pebbles']
50468 * // The `_.matchesProperty` iteratee shorthand.
50469 * _.dropWhile(users, ['active', false]);
50470 * // => objects for ['pebbles']
50472 * // The `_.property` iteratee shorthand.
50473 * _.dropWhile(users, 'active');
50474 * // => objects for ['barney', 'fred', 'pebbles']
50478 function dropWhile(array, predicate) {
50479 return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true) : [];
50482 * Fills elements of `array` with `value` from `start` up to, but not
50483 * including, `end`.
50485 * **Note:** This method mutates `array`.
50491 * @param {Array} array The array to fill.
50492 * @param {*} value The value to fill `array` with.
50493 * @param {number} [start=0] The start position.
50494 * @param {number} [end=array.length] The end position.
50495 * @returns {Array} Returns `array`.
50498 * var array = [1, 2, 3];
50500 * _.fill(array, 'a');
50501 * console.log(array);
50502 * // => ['a', 'a', 'a']
50504 * _.fill(Array(3), 2);
50507 * _.fill([4, 6, 8, 10], '*', 1, 3);
50508 * // => [4, '*', '*', 10]
50512 function fill(array, value, start, end) {
50513 var length = array == null ? 0 : array.length;
50519 if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
50524 return baseFill(array, value, start, end);
50527 * This method is like `_.find` except that it returns the index of the first
50528 * element `predicate` returns truthy for instead of the element itself.
50534 * @param {Array} array The array to inspect.
50535 * @param {Function} [predicate=_.identity] The function invoked per iteration.
50536 * @param {number} [fromIndex=0] The index to search from.
50537 * @returns {number} Returns the index of the found element, else `-1`.
50541 * { 'user': 'barney', 'active': false },
50542 * { 'user': 'fred', 'active': false },
50543 * { 'user': 'pebbles', 'active': true }
50546 * _.findIndex(users, function(o) { return o.user == 'barney'; });
50549 * // The `_.matches` iteratee shorthand.
50550 * _.findIndex(users, { 'user': 'fred', 'active': false });
50553 * // The `_.matchesProperty` iteratee shorthand.
50554 * _.findIndex(users, ['active', false]);
50557 * // The `_.property` iteratee shorthand.
50558 * _.findIndex(users, 'active');
50563 function findIndex(array, predicate, fromIndex) {
50564 var length = array == null ? 0 : array.length;
50570 var index = fromIndex == null ? 0 : toInteger(fromIndex);
50573 index = nativeMax(length + index, 0);
50576 return baseFindIndex(array, getIteratee(predicate, 3), index);
50579 * This method is like `_.findIndex` except that it iterates over elements
50580 * of `collection` from right to left.
50586 * @param {Array} array The array to inspect.
50587 * @param {Function} [predicate=_.identity] The function invoked per iteration.
50588 * @param {number} [fromIndex=array.length-1] The index to search from.
50589 * @returns {number} Returns the index of the found element, else `-1`.
50593 * { 'user': 'barney', 'active': true },
50594 * { 'user': 'fred', 'active': false },
50595 * { 'user': 'pebbles', 'active': false }
50598 * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
50601 * // The `_.matches` iteratee shorthand.
50602 * _.findLastIndex(users, { 'user': 'barney', 'active': true });
50605 * // The `_.matchesProperty` iteratee shorthand.
50606 * _.findLastIndex(users, ['active', false]);
50609 * // The `_.property` iteratee shorthand.
50610 * _.findLastIndex(users, 'active');
50615 function findLastIndex(array, predicate, fromIndex) {
50616 var length = array == null ? 0 : array.length;
50622 var index = length - 1;
50624 if (fromIndex !== undefined$1) {
50625 index = toInteger(fromIndex);
50626 index = fromIndex < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
50629 return baseFindIndex(array, getIteratee(predicate, 3), index, true);
50632 * Flattens `array` a single level deep.
50638 * @param {Array} array The array to flatten.
50639 * @returns {Array} Returns the new flattened array.
50642 * _.flatten([1, [2, [3, [4]], 5]]);
50643 * // => [1, 2, [3, [4]], 5]
50647 function flatten(array) {
50648 var length = array == null ? 0 : array.length;
50649 return length ? baseFlatten(array, 1) : [];
50652 * Recursively flattens `array`.
50658 * @param {Array} array The array to flatten.
50659 * @returns {Array} Returns the new flattened array.
50662 * _.flattenDeep([1, [2, [3, [4]], 5]]);
50663 * // => [1, 2, 3, 4, 5]
50667 function flattenDeep(array) {
50668 var length = array == null ? 0 : array.length;
50669 return length ? baseFlatten(array, INFINITY) : [];
50672 * Recursively flatten `array` up to `depth` times.
50678 * @param {Array} array The array to flatten.
50679 * @param {number} [depth=1] The maximum recursion depth.
50680 * @returns {Array} Returns the new flattened array.
50683 * var array = [1, [2, [3, [4]], 5]];
50685 * _.flattenDepth(array, 1);
50686 * // => [1, 2, [3, [4]], 5]
50688 * _.flattenDepth(array, 2);
50689 * // => [1, 2, 3, [4], 5]
50693 function flattenDepth(array, depth) {
50694 var length = array == null ? 0 : array.length;
50700 depth = depth === undefined$1 ? 1 : toInteger(depth);
50701 return baseFlatten(array, depth);
50704 * The inverse of `_.toPairs`; this method returns an object composed
50705 * from key-value `pairs`.
50711 * @param {Array} pairs The key-value pairs.
50712 * @returns {Object} Returns the new object.
50715 * _.fromPairs([['a', 1], ['b', 2]]);
50716 * // => { 'a': 1, 'b': 2 }
50720 function fromPairs(pairs) {
50722 length = pairs == null ? 0 : pairs.length,
50725 while (++index < length) {
50726 var pair = pairs[index];
50727 result[pair[0]] = pair[1];
50733 * Gets the first element of `array`.
50740 * @param {Array} array The array to query.
50741 * @returns {*} Returns the first element of `array`.
50744 * _.head([1, 2, 3]);
50752 function head(array) {
50753 return array && array.length ? array[0] : undefined$1;
50756 * Gets the index at which the first occurrence of `value` is found in `array`
50757 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
50758 * for equality comparisons. If `fromIndex` is negative, it's used as the
50759 * offset from the end of `array`.
50765 * @param {Array} array The array to inspect.
50766 * @param {*} value The value to search for.
50767 * @param {number} [fromIndex=0] The index to search from.
50768 * @returns {number} Returns the index of the matched value, else `-1`.
50771 * _.indexOf([1, 2, 1, 2], 2);
50774 * // Search from the `fromIndex`.
50775 * _.indexOf([1, 2, 1, 2], 2, 2);
50780 function indexOf(array, value, fromIndex) {
50781 var length = array == null ? 0 : array.length;
50787 var index = fromIndex == null ? 0 : toInteger(fromIndex);
50790 index = nativeMax(length + index, 0);
50793 return baseIndexOf(array, value, index);
50796 * Gets all but the last element of `array`.
50802 * @param {Array} array The array to query.
50803 * @returns {Array} Returns the slice of `array`.
50806 * _.initial([1, 2, 3]);
50811 function initial(array) {
50812 var length = array == null ? 0 : array.length;
50813 return length ? baseSlice(array, 0, -1) : [];
50816 * Creates an array of unique values that are included in all given arrays
50817 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
50818 * for equality comparisons. The order and references of result values are
50819 * determined by the first array.
50825 * @param {...Array} [arrays] The arrays to inspect.
50826 * @returns {Array} Returns the new array of intersecting values.
50829 * _.intersection([2, 1], [2, 3]);
50834 var intersection = baseRest(function (arrays) {
50835 var mapped = arrayMap(arrays, castArrayLikeObject);
50836 return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped) : [];
50839 * This method is like `_.intersection` except that it accepts `iteratee`
50840 * which is invoked for each element of each `arrays` to generate the criterion
50841 * by which they're compared. The order and references of result values are
50842 * determined by the first array. The iteratee is invoked with one argument:
50849 * @param {...Array} [arrays] The arrays to inspect.
50850 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
50851 * @returns {Array} Returns the new array of intersecting values.
50854 * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
50857 * // The `_.property` iteratee shorthand.
50858 * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
50859 * // => [{ 'x': 1 }]
50862 var intersectionBy = baseRest(function (arrays) {
50863 var iteratee = last(arrays),
50864 mapped = arrayMap(arrays, castArrayLikeObject);
50866 if (iteratee === last(mapped)) {
50867 iteratee = undefined$1;
50872 return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, getIteratee(iteratee, 2)) : [];
50875 * This method is like `_.intersection` except that it accepts `comparator`
50876 * which is invoked to compare elements of `arrays`. The order and references
50877 * of result values are determined by the first array. The comparator is
50878 * invoked with two arguments: (arrVal, othVal).
50884 * @param {...Array} [arrays] The arrays to inspect.
50885 * @param {Function} [comparator] The comparator invoked per element.
50886 * @returns {Array} Returns the new array of intersecting values.
50889 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
50890 * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
50892 * _.intersectionWith(objects, others, _.isEqual);
50893 * // => [{ 'x': 1, 'y': 2 }]
50896 var intersectionWith = baseRest(function (arrays) {
50897 var comparator = last(arrays),
50898 mapped = arrayMap(arrays, castArrayLikeObject);
50899 comparator = typeof comparator == 'function' ? comparator : undefined$1;
50905 return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined$1, comparator) : [];
50908 * Converts all elements in `array` into a string separated by `separator`.
50914 * @param {Array} array The array to convert.
50915 * @param {string} [separator=','] The element separator.
50916 * @returns {string} Returns the joined string.
50919 * _.join(['a', 'b', 'c'], '~');
50923 function join(array, separator) {
50924 return array == null ? '' : nativeJoin.call(array, separator);
50927 * Gets the last element of `array`.
50933 * @param {Array} array The array to query.
50934 * @returns {*} Returns the last element of `array`.
50937 * _.last([1, 2, 3]);
50942 function last(array) {
50943 var length = array == null ? 0 : array.length;
50944 return length ? array[length - 1] : undefined$1;
50947 * This method is like `_.indexOf` except that it iterates over elements of
50948 * `array` from right to left.
50954 * @param {Array} array The array to inspect.
50955 * @param {*} value The value to search for.
50956 * @param {number} [fromIndex=array.length-1] The index to search from.
50957 * @returns {number} Returns the index of the matched value, else `-1`.
50960 * _.lastIndexOf([1, 2, 1, 2], 2);
50963 * // Search from the `fromIndex`.
50964 * _.lastIndexOf([1, 2, 1, 2], 2, 2);
50969 function lastIndexOf(array, value, fromIndex) {
50970 var length = array == null ? 0 : array.length;
50976 var index = length;
50978 if (fromIndex !== undefined$1) {
50979 index = toInteger(fromIndex);
50980 index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
50983 return value === value ? strictLastIndexOf(array, value, index) : baseFindIndex(array, baseIsNaN, index, true);
50986 * Gets the element at index `n` of `array`. If `n` is negative, the nth
50987 * element from the end is returned.
50993 * @param {Array} array The array to query.
50994 * @param {number} [n=0] The index of the element to return.
50995 * @returns {*} Returns the nth element of `array`.
50998 * var array = ['a', 'b', 'c', 'd'];
51003 * _.nth(array, -2);
51008 function nth(array, n) {
51009 return array && array.length ? baseNth(array, toInteger(n)) : undefined$1;
51012 * Removes all given values from `array` using
51013 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
51014 * for equality comparisons.
51016 * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
51017 * to remove elements from an array by predicate.
51023 * @param {Array} array The array to modify.
51024 * @param {...*} [values] The values to remove.
51025 * @returns {Array} Returns `array`.
51028 * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
51030 * _.pull(array, 'a', 'c');
51031 * console.log(array);
51036 var pull = baseRest(pullAll);
51038 * This method is like `_.pull` except that it accepts an array of values to remove.
51040 * **Note:** Unlike `_.difference`, this method mutates `array`.
51046 * @param {Array} array The array to modify.
51047 * @param {Array} values The values to remove.
51048 * @returns {Array} Returns `array`.
51051 * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
51053 * _.pullAll(array, ['a', 'c']);
51054 * console.log(array);
51058 function pullAll(array, values) {
51059 return array && array.length && values && values.length ? basePullAll(array, values) : array;
51062 * This method is like `_.pullAll` except that it accepts `iteratee` which is
51063 * invoked for each element of `array` and `values` to generate the criterion
51064 * by which they're compared. The iteratee is invoked with one argument: (value).
51066 * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
51072 * @param {Array} array The array to modify.
51073 * @param {Array} values The values to remove.
51074 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51075 * @returns {Array} Returns `array`.
51078 * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
51080 * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
51081 * console.log(array);
51082 * // => [{ 'x': 2 }]
51086 function pullAllBy(array, values, iteratee) {
51087 return array && array.length && values && values.length ? basePullAll(array, values, getIteratee(iteratee, 2)) : array;
51090 * This method is like `_.pullAll` except that it accepts `comparator` which
51091 * is invoked to compare elements of `array` to `values`. The comparator is
51092 * invoked with two arguments: (arrVal, othVal).
51094 * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
51100 * @param {Array} array The array to modify.
51101 * @param {Array} values The values to remove.
51102 * @param {Function} [comparator] The comparator invoked per element.
51103 * @returns {Array} Returns `array`.
51106 * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
51108 * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
51109 * console.log(array);
51110 * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
51114 function pullAllWith(array, values, comparator) {
51115 return array && array.length && values && values.length ? basePullAll(array, values, undefined$1, comparator) : array;
51118 * Removes elements from `array` corresponding to `indexes` and returns an
51119 * array of removed elements.
51121 * **Note:** Unlike `_.at`, this method mutates `array`.
51127 * @param {Array} array The array to modify.
51128 * @param {...(number|number[])} [indexes] The indexes of elements to remove.
51129 * @returns {Array} Returns the new array of removed elements.
51132 * var array = ['a', 'b', 'c', 'd'];
51133 * var pulled = _.pullAt(array, [1, 3]);
51135 * console.log(array);
51138 * console.log(pulled);
51143 var pullAt = flatRest(function (array, indexes) {
51144 var length = array == null ? 0 : array.length,
51145 result = baseAt(array, indexes);
51146 basePullAt(array, arrayMap(indexes, function (index) {
51147 return isIndex(index, length) ? +index : index;
51148 }).sort(compareAscending));
51152 * Removes all elements from `array` that `predicate` returns truthy for
51153 * and returns an array of the removed elements. The predicate is invoked
51154 * with three arguments: (value, index, array).
51156 * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
51157 * to pull elements from an array by value.
51163 * @param {Array} array The array to modify.
51164 * @param {Function} [predicate=_.identity] The function invoked per iteration.
51165 * @returns {Array} Returns the new array of removed elements.
51168 * var array = [1, 2, 3, 4];
51169 * var evens = _.remove(array, function(n) {
51170 * return n % 2 == 0;
51173 * console.log(array);
51176 * console.log(evens);
51180 function remove(array, predicate) {
51183 if (!(array && array.length)) {
51189 length = array.length;
51190 predicate = getIteratee(predicate, 3);
51192 while (++index < length) {
51193 var value = array[index];
51195 if (predicate(value, index, array)) {
51196 result.push(value);
51197 indexes.push(index);
51201 basePullAt(array, indexes);
51205 * Reverses `array` so that the first element becomes the last, the second
51206 * element becomes the second to last, and so on.
51208 * **Note:** This method mutates `array` and is based on
51209 * [`Array#reverse`](https://mdn.io/Array/reverse).
51215 * @param {Array} array The array to modify.
51216 * @returns {Array} Returns `array`.
51219 * var array = [1, 2, 3];
51221 * _.reverse(array);
51224 * console.log(array);
51229 function reverse(array) {
51230 return array == null ? array : nativeReverse.call(array);
51233 * Creates a slice of `array` from `start` up to, but not including, `end`.
51235 * **Note:** This method is used instead of
51236 * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
51243 * @param {Array} array The array to slice.
51244 * @param {number} [start=0] The start position.
51245 * @param {number} [end=array.length] The end position.
51246 * @returns {Array} Returns the slice of `array`.
51250 function slice(array, start, end) {
51251 var length = array == null ? 0 : array.length;
51257 if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
51261 start = start == null ? 0 : toInteger(start);
51262 end = end === undefined$1 ? length : toInteger(end);
51265 return baseSlice(array, start, end);
51268 * Uses a binary search to determine the lowest index at which `value`
51269 * should be inserted into `array` in order to maintain its sort order.
51275 * @param {Array} array The sorted array to inspect.
51276 * @param {*} value The value to evaluate.
51277 * @returns {number} Returns the index at which `value` should be inserted
51281 * _.sortedIndex([30, 50], 40);
51286 function sortedIndex(array, value) {
51287 return baseSortedIndex(array, value);
51290 * This method is like `_.sortedIndex` except that it accepts `iteratee`
51291 * which is invoked for `value` and each element of `array` to compute their
51292 * sort ranking. The iteratee is invoked with one argument: (value).
51298 * @param {Array} array The sorted array to inspect.
51299 * @param {*} value The value to evaluate.
51300 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51301 * @returns {number} Returns the index at which `value` should be inserted
51305 * var objects = [{ 'x': 4 }, { 'x': 5 }];
51307 * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
51310 * // The `_.property` iteratee shorthand.
51311 * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
51316 function sortedIndexBy(array, value, iteratee) {
51317 return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
51320 * This method is like `_.indexOf` except that it performs a binary
51321 * search on a sorted `array`.
51327 * @param {Array} array The array to inspect.
51328 * @param {*} value The value to search for.
51329 * @returns {number} Returns the index of the matched value, else `-1`.
51332 * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
51337 function sortedIndexOf(array, value) {
51338 var length = array == null ? 0 : array.length;
51341 var index = baseSortedIndex(array, value);
51343 if (index < length && eq(array[index], value)) {
51351 * This method is like `_.sortedIndex` except that it returns the highest
51352 * index at which `value` should be inserted into `array` in order to
51353 * maintain its sort order.
51359 * @param {Array} array The sorted array to inspect.
51360 * @param {*} value The value to evaluate.
51361 * @returns {number} Returns the index at which `value` should be inserted
51365 * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
51370 function sortedLastIndex(array, value) {
51371 return baseSortedIndex(array, value, true);
51374 * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
51375 * which is invoked for `value` and each element of `array` to compute their
51376 * sort ranking. The iteratee is invoked with one argument: (value).
51382 * @param {Array} array The sorted array to inspect.
51383 * @param {*} value The value to evaluate.
51384 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51385 * @returns {number} Returns the index at which `value` should be inserted
51389 * var objects = [{ 'x': 4 }, { 'x': 5 }];
51391 * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
51394 * // The `_.property` iteratee shorthand.
51395 * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
51400 function sortedLastIndexBy(array, value, iteratee) {
51401 return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
51404 * This method is like `_.lastIndexOf` except that it performs a binary
51405 * search on a sorted `array`.
51411 * @param {Array} array The array to inspect.
51412 * @param {*} value The value to search for.
51413 * @returns {number} Returns the index of the matched value, else `-1`.
51416 * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
51421 function sortedLastIndexOf(array, value) {
51422 var length = array == null ? 0 : array.length;
51425 var index = baseSortedIndex(array, value, true) - 1;
51427 if (eq(array[index], value)) {
51435 * This method is like `_.uniq` except that it's designed and optimized
51436 * for sorted arrays.
51442 * @param {Array} array The array to inspect.
51443 * @returns {Array} Returns the new duplicate free array.
51446 * _.sortedUniq([1, 1, 2]);
51451 function sortedUniq(array) {
51452 return array && array.length ? baseSortedUniq(array) : [];
51455 * This method is like `_.uniqBy` except that it's designed and optimized
51456 * for sorted arrays.
51462 * @param {Array} array The array to inspect.
51463 * @param {Function} [iteratee] The iteratee invoked per element.
51464 * @returns {Array} Returns the new duplicate free array.
51467 * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
51472 function sortedUniqBy(array, iteratee) {
51473 return array && array.length ? baseSortedUniq(array, getIteratee(iteratee, 2)) : [];
51476 * Gets all but the first element of `array`.
51482 * @param {Array} array The array to query.
51483 * @returns {Array} Returns the slice of `array`.
51486 * _.tail([1, 2, 3]);
51491 function tail(array) {
51492 var length = array == null ? 0 : array.length;
51493 return length ? baseSlice(array, 1, length) : [];
51496 * Creates a slice of `array` with `n` elements taken from the beginning.
51502 * @param {Array} array The array to query.
51503 * @param {number} [n=1] The number of elements to take.
51504 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
51505 * @returns {Array} Returns the slice of `array`.
51508 * _.take([1, 2, 3]);
51511 * _.take([1, 2, 3], 2);
51514 * _.take([1, 2, 3], 5);
51517 * _.take([1, 2, 3], 0);
51522 function take(array, n, guard) {
51523 if (!(array && array.length)) {
51527 n = guard || n === undefined$1 ? 1 : toInteger(n);
51528 return baseSlice(array, 0, n < 0 ? 0 : n);
51531 * Creates a slice of `array` with `n` elements taken from the end.
51537 * @param {Array} array The array to query.
51538 * @param {number} [n=1] The number of elements to take.
51539 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
51540 * @returns {Array} Returns the slice of `array`.
51543 * _.takeRight([1, 2, 3]);
51546 * _.takeRight([1, 2, 3], 2);
51549 * _.takeRight([1, 2, 3], 5);
51552 * _.takeRight([1, 2, 3], 0);
51557 function takeRight(array, n, guard) {
51558 var length = array == null ? 0 : array.length;
51564 n = guard || n === undefined$1 ? 1 : toInteger(n);
51566 return baseSlice(array, n < 0 ? 0 : n, length);
51569 * Creates a slice of `array` with elements taken from the end. Elements are
51570 * taken until `predicate` returns falsey. The predicate is invoked with
51571 * three arguments: (value, index, array).
51577 * @param {Array} array The array to query.
51578 * @param {Function} [predicate=_.identity] The function invoked per iteration.
51579 * @returns {Array} Returns the slice of `array`.
51583 * { 'user': 'barney', 'active': true },
51584 * { 'user': 'fred', 'active': false },
51585 * { 'user': 'pebbles', 'active': false }
51588 * _.takeRightWhile(users, function(o) { return !o.active; });
51589 * // => objects for ['fred', 'pebbles']
51591 * // The `_.matches` iteratee shorthand.
51592 * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
51593 * // => objects for ['pebbles']
51595 * // The `_.matchesProperty` iteratee shorthand.
51596 * _.takeRightWhile(users, ['active', false]);
51597 * // => objects for ['fred', 'pebbles']
51599 * // The `_.property` iteratee shorthand.
51600 * _.takeRightWhile(users, 'active');
51605 function takeRightWhile(array, predicate) {
51606 return array && array.length ? baseWhile(array, getIteratee(predicate, 3), false, true) : [];
51609 * Creates a slice of `array` with elements taken from the beginning. Elements
51610 * are taken until `predicate` returns falsey. The predicate is invoked with
51611 * three arguments: (value, index, array).
51617 * @param {Array} array The array to query.
51618 * @param {Function} [predicate=_.identity] The function invoked per iteration.
51619 * @returns {Array} Returns the slice of `array`.
51623 * { 'user': 'barney', 'active': false },
51624 * { 'user': 'fred', 'active': false },
51625 * { 'user': 'pebbles', 'active': true }
51628 * _.takeWhile(users, function(o) { return !o.active; });
51629 * // => objects for ['barney', 'fred']
51631 * // The `_.matches` iteratee shorthand.
51632 * _.takeWhile(users, { 'user': 'barney', 'active': false });
51633 * // => objects for ['barney']
51635 * // The `_.matchesProperty` iteratee shorthand.
51636 * _.takeWhile(users, ['active', false]);
51637 * // => objects for ['barney', 'fred']
51639 * // The `_.property` iteratee shorthand.
51640 * _.takeWhile(users, 'active');
51645 function takeWhile(array, predicate) {
51646 return array && array.length ? baseWhile(array, getIteratee(predicate, 3)) : [];
51649 * Creates an array of unique values, in order, from all given arrays using
51650 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
51651 * for equality comparisons.
51657 * @param {...Array} [arrays] The arrays to inspect.
51658 * @returns {Array} Returns the new array of combined values.
51661 * _.union([2], [1, 2]);
51666 var union = baseRest(function (arrays) {
51667 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
51670 * This method is like `_.union` except that it accepts `iteratee` which is
51671 * invoked for each element of each `arrays` to generate the criterion by
51672 * which uniqueness is computed. Result values are chosen from the first
51673 * array in which the value occurs. The iteratee is invoked with one argument:
51680 * @param {...Array} [arrays] The arrays to inspect.
51681 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51682 * @returns {Array} Returns the new array of combined values.
51685 * _.unionBy([2.1], [1.2, 2.3], Math.floor);
51688 * // The `_.property` iteratee shorthand.
51689 * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
51690 * // => [{ 'x': 1 }, { 'x': 2 }]
51693 var unionBy = baseRest(function (arrays) {
51694 var iteratee = last(arrays);
51696 if (isArrayLikeObject(iteratee)) {
51697 iteratee = undefined$1;
51700 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
51703 * This method is like `_.union` except that it accepts `comparator` which
51704 * is invoked to compare elements of `arrays`. Result values are chosen from
51705 * the first array in which the value occurs. The comparator is invoked
51706 * with two arguments: (arrVal, othVal).
51712 * @param {...Array} [arrays] The arrays to inspect.
51713 * @param {Function} [comparator] The comparator invoked per element.
51714 * @returns {Array} Returns the new array of combined values.
51717 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
51718 * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
51720 * _.unionWith(objects, others, _.isEqual);
51721 * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
51724 var unionWith = baseRest(function (arrays) {
51725 var comparator = last(arrays);
51726 comparator = typeof comparator == 'function' ? comparator : undefined$1;
51727 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined$1, comparator);
51730 * Creates a duplicate-free version of an array, using
51731 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
51732 * for equality comparisons, in which only the first occurrence of each element
51733 * is kept. The order of result values is determined by the order they occur
51740 * @param {Array} array The array to inspect.
51741 * @returns {Array} Returns the new duplicate free array.
51744 * _.uniq([2, 1, 2]);
51748 function uniq(array) {
51749 return array && array.length ? baseUniq(array) : [];
51752 * This method is like `_.uniq` except that it accepts `iteratee` which is
51753 * invoked for each element in `array` to generate the criterion by which
51754 * uniqueness is computed. The order of result values is determined by the
51755 * order they occur in the array. The iteratee is invoked with one argument:
51762 * @param {Array} array The array to inspect.
51763 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51764 * @returns {Array} Returns the new duplicate free array.
51767 * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
51770 * // The `_.property` iteratee shorthand.
51771 * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
51772 * // => [{ 'x': 1 }, { 'x': 2 }]
51776 function uniqBy(array, iteratee) {
51777 return array && array.length ? baseUniq(array, getIteratee(iteratee, 2)) : [];
51780 * This method is like `_.uniq` except that it accepts `comparator` which
51781 * is invoked to compare elements of `array`. The order of result values is
51782 * determined by the order they occur in the array.The comparator is invoked
51783 * with two arguments: (arrVal, othVal).
51789 * @param {Array} array The array to inspect.
51790 * @param {Function} [comparator] The comparator invoked per element.
51791 * @returns {Array} Returns the new duplicate free array.
51794 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
51796 * _.uniqWith(objects, _.isEqual);
51797 * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
51801 function uniqWith(array, comparator) {
51802 comparator = typeof comparator == 'function' ? comparator : undefined$1;
51803 return array && array.length ? baseUniq(array, undefined$1, comparator) : [];
51806 * This method is like `_.zip` except that it accepts an array of grouped
51807 * elements and creates an array regrouping the elements to their pre-zip
51814 * @param {Array} array The array of grouped elements to process.
51815 * @returns {Array} Returns the new array of regrouped elements.
51818 * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
51819 * // => [['a', 1, true], ['b', 2, false]]
51822 * // => [['a', 'b'], [1, 2], [true, false]]
51826 function unzip(array) {
51827 if (!(array && array.length)) {
51832 array = arrayFilter(array, function (group) {
51833 if (isArrayLikeObject(group)) {
51834 length = nativeMax(group.length, length);
51838 return baseTimes(length, function (index) {
51839 return arrayMap(array, baseProperty(index));
51843 * This method is like `_.unzip` except that it accepts `iteratee` to specify
51844 * how regrouped values should be combined. The iteratee is invoked with the
51845 * elements of each group: (...group).
51851 * @param {Array} array The array of grouped elements to process.
51852 * @param {Function} [iteratee=_.identity] The function to combine
51853 * regrouped values.
51854 * @returns {Array} Returns the new array of regrouped elements.
51857 * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
51858 * // => [[1, 10, 100], [2, 20, 200]]
51860 * _.unzipWith(zipped, _.add);
51861 * // => [3, 30, 300]
51865 function unzipWith(array, iteratee) {
51866 if (!(array && array.length)) {
51870 var result = unzip(array);
51872 if (iteratee == null) {
51876 return arrayMap(result, function (group) {
51877 return apply(iteratee, undefined$1, group);
51881 * Creates an array excluding all given values using
51882 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
51883 * for equality comparisons.
51885 * **Note:** Unlike `_.pull`, this method returns a new array.
51891 * @param {Array} array The array to inspect.
51892 * @param {...*} [values] The values to exclude.
51893 * @returns {Array} Returns the new array of filtered values.
51894 * @see _.difference, _.xor
51897 * _.without([2, 1, 2, 3], 1, 2);
51902 var without = baseRest(function (array, values) {
51903 return isArrayLikeObject(array) ? baseDifference(array, values) : [];
51906 * Creates an array of unique values that is the
51907 * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
51908 * of the given arrays. The order of result values is determined by the order
51909 * they occur in the arrays.
51915 * @param {...Array} [arrays] The arrays to inspect.
51916 * @returns {Array} Returns the new array of filtered values.
51917 * @see _.difference, _.without
51920 * _.xor([2, 1], [2, 3]);
51924 var xor = baseRest(function (arrays) {
51925 return baseXor(arrayFilter(arrays, isArrayLikeObject));
51928 * This method is like `_.xor` except that it accepts `iteratee` which is
51929 * invoked for each element of each `arrays` to generate the criterion by
51930 * which by which they're compared. The order of result values is determined
51931 * by the order they occur in the arrays. The iteratee is invoked with one
51932 * argument: (value).
51938 * @param {...Array} [arrays] The arrays to inspect.
51939 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51940 * @returns {Array} Returns the new array of filtered values.
51943 * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
51946 * // The `_.property` iteratee shorthand.
51947 * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
51948 * // => [{ 'x': 2 }]
51951 var xorBy = baseRest(function (arrays) {
51952 var iteratee = last(arrays);
51954 if (isArrayLikeObject(iteratee)) {
51955 iteratee = undefined$1;
51958 return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
51961 * This method is like `_.xor` except that it accepts `comparator` which is
51962 * invoked to compare elements of `arrays`. The order of result values is
51963 * determined by the order they occur in the arrays. The comparator is invoked
51964 * with two arguments: (arrVal, othVal).
51970 * @param {...Array} [arrays] The arrays to inspect.
51971 * @param {Function} [comparator] The comparator invoked per element.
51972 * @returns {Array} Returns the new array of filtered values.
51975 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
51976 * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
51978 * _.xorWith(objects, others, _.isEqual);
51979 * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
51982 var xorWith = baseRest(function (arrays) {
51983 var comparator = last(arrays);
51984 comparator = typeof comparator == 'function' ? comparator : undefined$1;
51985 return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined$1, comparator);
51988 * Creates an array of grouped elements, the first of which contains the
51989 * first elements of the given arrays, the second of which contains the
51990 * second elements of the given arrays, and so on.
51996 * @param {...Array} [arrays] The arrays to process.
51997 * @returns {Array} Returns the new array of grouped elements.
52000 * _.zip(['a', 'b'], [1, 2], [true, false]);
52001 * // => [['a', 1, true], ['b', 2, false]]
52004 var zip = baseRest(unzip);
52006 * This method is like `_.fromPairs` except that it accepts two arrays,
52007 * one of property identifiers and one of corresponding values.
52013 * @param {Array} [props=[]] The property identifiers.
52014 * @param {Array} [values=[]] The property values.
52015 * @returns {Object} Returns the new object.
52018 * _.zipObject(['a', 'b'], [1, 2]);
52019 * // => { 'a': 1, 'b': 2 }
52022 function zipObject(props, values) {
52023 return baseZipObject(props || [], values || [], assignValue);
52026 * This method is like `_.zipObject` except that it supports property paths.
52032 * @param {Array} [props=[]] The property identifiers.
52033 * @param {Array} [values=[]] The property values.
52034 * @returns {Object} Returns the new object.
52037 * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
52038 * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
52042 function zipObjectDeep(props, values) {
52043 return baseZipObject(props || [], values || [], baseSet);
52046 * This method is like `_.zip` except that it accepts `iteratee` to specify
52047 * how grouped values should be combined. The iteratee is invoked with the
52048 * elements of each group: (...group).
52054 * @param {...Array} [arrays] The arrays to process.
52055 * @param {Function} [iteratee=_.identity] The function to combine
52057 * @returns {Array} Returns the new array of grouped elements.
52060 * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
52061 * return a + b + c;
52067 var zipWith = baseRest(function (arrays) {
52068 var length = arrays.length,
52069 iteratee = length > 1 ? arrays[length - 1] : undefined$1;
52070 iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined$1;
52071 return unzipWith(arrays, iteratee);
52073 /*------------------------------------------------------------------------*/
52076 * Creates a `lodash` wrapper instance that wraps `value` with explicit method
52077 * chain sequences enabled. The result of such sequences must be unwrapped
52084 * @param {*} value The value to wrap.
52085 * @returns {Object} Returns the new `lodash` wrapper instance.
52089 * { 'user': 'barney', 'age': 36 },
52090 * { 'user': 'fred', 'age': 40 },
52091 * { 'user': 'pebbles', 'age': 1 }
52097 * .map(function(o) {
52098 * return o.user + ' is ' + o.age;
52102 * // => 'pebbles is 1'
52105 function chain(value) {
52106 var result = lodash(value);
52107 result.__chain__ = true;
52111 * This method invokes `interceptor` and returns `value`. The interceptor
52112 * is invoked with one argument; (value). The purpose of this method is to
52113 * "tap into" a method chain sequence in order to modify intermediate results.
52119 * @param {*} value The value to provide to `interceptor`.
52120 * @param {Function} interceptor The function to invoke.
52121 * @returns {*} Returns `value`.
52125 * .tap(function(array) {
52126 * // Mutate input array.
52135 function tap(value, interceptor) {
52136 interceptor(value);
52140 * This method is like `_.tap` except that it returns the result of `interceptor`.
52141 * The purpose of this method is to "pass thru" values replacing intermediate
52142 * results in a method chain sequence.
52148 * @param {*} value The value to provide to `interceptor`.
52149 * @param {Function} interceptor The function to invoke.
52150 * @returns {*} Returns the result of `interceptor`.
52156 * .thru(function(value) {
52164 function thru(value, interceptor) {
52165 return interceptor(value);
52168 * This method is the wrapper version of `_.at`.
52174 * @param {...(string|string[])} [paths] The property paths to pick.
52175 * @returns {Object} Returns the new `lodash` wrapper instance.
52178 * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
52180 * _(object).at(['a[0].b.c', 'a[1]']).value();
52185 var wrapperAt = flatRest(function (paths) {
52186 var length = paths.length,
52187 start = length ? paths[0] : 0,
52188 value = this.__wrapped__,
52189 interceptor = function interceptor(object) {
52190 return baseAt(object, paths);
52193 if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start)) {
52194 return this.thru(interceptor);
52197 value = value.slice(start, +start + (length ? 1 : 0));
52199 value.__actions__.push({
52201 'args': [interceptor],
52202 'thisArg': undefined$1
52205 return new LodashWrapper(value, this.__chain__).thru(function (array) {
52206 if (length && !array.length) {
52207 array.push(undefined$1);
52214 * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
52220 * @returns {Object} Returns the new `lodash` wrapper instance.
52224 * { 'user': 'barney', 'age': 36 },
52225 * { 'user': 'fred', 'age': 40 }
52228 * // A sequence without explicit chaining.
52230 * // => { 'user': 'barney', 'age': 36 }
52232 * // A sequence with explicit chaining.
52238 * // => { 'user': 'barney' }
52241 function wrapperChain() {
52242 return chain(this);
52245 * Executes the chain sequence and returns the wrapped result.
52251 * @returns {Object} Returns the new `lodash` wrapper instance.
52254 * var array = [1, 2];
52255 * var wrapped = _(array).push(3);
52257 * console.log(array);
52260 * wrapped = wrapped.commit();
52261 * console.log(array);
52267 * console.log(array);
52272 function wrapperCommit() {
52273 return new LodashWrapper(this.value(), this.__chain__);
52276 * Gets the next value on a wrapped object following the
52277 * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
52283 * @returns {Object} Returns the next iterator value.
52286 * var wrapped = _([1, 2]);
52289 * // => { 'done': false, 'value': 1 }
52292 * // => { 'done': false, 'value': 2 }
52295 * // => { 'done': true, 'value': undefined }
52299 function wrapperNext() {
52300 if (this.__values__ === undefined$1) {
52301 this.__values__ = toArray(this.value());
52304 var done = this.__index__ >= this.__values__.length,
52305 value = done ? undefined$1 : this.__values__[this.__index__++];
52312 * Enables the wrapper to be iterable.
52314 * @name Symbol.iterator
52318 * @returns {Object} Returns the wrapper object.
52321 * var wrapped = _([1, 2]);
52323 * wrapped[Symbol.iterator]() === wrapped;
52326 * Array.from(wrapped);
52331 function wrapperToIterator() {
52335 * Creates a clone of the chain sequence planting `value` as the wrapped value.
52341 * @param {*} value The value to plant.
52342 * @returns {Object} Returns the new `lodash` wrapper instance.
52345 * function square(n) {
52349 * var wrapped = _([1, 2]).map(square);
52350 * var other = wrapped.plant([3, 4]);
52360 function wrapperPlant(value) {
52364 while (parent instanceof baseLodash) {
52365 var clone = wrapperClone(parent);
52366 clone.__index__ = 0;
52367 clone.__values__ = undefined$1;
52370 previous.__wrapped__ = clone;
52375 var previous = clone;
52376 parent = parent.__wrapped__;
52379 previous.__wrapped__ = value;
52383 * This method is the wrapper version of `_.reverse`.
52385 * **Note:** This method mutates the wrapped array.
52391 * @returns {Object} Returns the new `lodash` wrapper instance.
52394 * var array = [1, 2, 3];
52396 * _(array).reverse().value()
52399 * console.log(array);
52404 function wrapperReverse() {
52405 var value = this.__wrapped__;
52407 if (value instanceof LazyWrapper) {
52408 var wrapped = value;
52410 if (this.__actions__.length) {
52411 wrapped = new LazyWrapper(this);
52414 wrapped = wrapped.reverse();
52416 wrapped.__actions__.push({
52419 'thisArg': undefined$1
52422 return new LodashWrapper(wrapped, this.__chain__);
52425 return this.thru(reverse);
52428 * Executes the chain sequence to resolve the unwrapped value.
52433 * @alias toJSON, valueOf
52435 * @returns {*} Returns the resolved unwrapped value.
52438 * _([1, 2, 3]).value();
52443 function wrapperValue() {
52444 return baseWrapperValue(this.__wrapped__, this.__actions__);
52446 /*------------------------------------------------------------------------*/
52449 * Creates an object composed of keys generated from the results of running
52450 * each element of `collection` thru `iteratee`. The corresponding value of
52451 * each key is the number of times the key was returned by `iteratee`. The
52452 * iteratee is invoked with one argument: (value).
52457 * @category Collection
52458 * @param {Array|Object} collection The collection to iterate over.
52459 * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
52460 * @returns {Object} Returns the composed aggregate object.
52463 * _.countBy([6.1, 4.2, 6.3], Math.floor);
52464 * // => { '4': 1, '6': 2 }
52466 * // The `_.property` iteratee shorthand.
52467 * _.countBy(['one', 'two', 'three'], 'length');
52468 * // => { '3': 2, '5': 1 }
52472 var countBy = createAggregator(function (result, value, key) {
52473 if (hasOwnProperty.call(result, key)) {
52476 baseAssignValue(result, key, 1);
52480 * Checks if `predicate` returns truthy for **all** elements of `collection`.
52481 * Iteration is stopped once `predicate` returns falsey. The predicate is
52482 * invoked with three arguments: (value, index|key, collection).
52484 * **Note:** This method returns `true` for
52485 * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
52486 * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
52487 * elements of empty collections.
52492 * @category Collection
52493 * @param {Array|Object} collection The collection to iterate over.
52494 * @param {Function} [predicate=_.identity] The function invoked per iteration.
52495 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
52496 * @returns {boolean} Returns `true` if all elements pass the predicate check,
52500 * _.every([true, 1, null, 'yes'], Boolean);
52504 * { 'user': 'barney', 'age': 36, 'active': false },
52505 * { 'user': 'fred', 'age': 40, 'active': false }
52508 * // The `_.matches` iteratee shorthand.
52509 * _.every(users, { 'user': 'barney', 'active': false });
52512 * // The `_.matchesProperty` iteratee shorthand.
52513 * _.every(users, ['active', false]);
52516 * // The `_.property` iteratee shorthand.
52517 * _.every(users, 'active');
52521 function every(collection, predicate, guard) {
52522 var func = isArray(collection) ? arrayEvery : baseEvery;
52524 if (guard && isIterateeCall(collection, predicate, guard)) {
52525 predicate = undefined$1;
52528 return func(collection, getIteratee(predicate, 3));
52531 * Iterates over elements of `collection`, returning an array of all elements
52532 * `predicate` returns truthy for. The predicate is invoked with three
52533 * arguments: (value, index|key, collection).
52535 * **Note:** Unlike `_.remove`, this method returns a new array.
52540 * @category Collection
52541 * @param {Array|Object} collection The collection to iterate over.
52542 * @param {Function} [predicate=_.identity] The function invoked per iteration.
52543 * @returns {Array} Returns the new filtered array.
52548 * { 'user': 'barney', 'age': 36, 'active': true },
52549 * { 'user': 'fred', 'age': 40, 'active': false }
52552 * _.filter(users, function(o) { return !o.active; });
52553 * // => objects for ['fred']
52555 * // The `_.matches` iteratee shorthand.
52556 * _.filter(users, { 'age': 36, 'active': true });
52557 * // => objects for ['barney']
52559 * // The `_.matchesProperty` iteratee shorthand.
52560 * _.filter(users, ['active', false]);
52561 * // => objects for ['fred']
52563 * // The `_.property` iteratee shorthand.
52564 * _.filter(users, 'active');
52565 * // => objects for ['barney']
52567 * // Combining several predicates using `_.overEvery` or `_.overSome`.
52568 * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]]));
52569 * // => objects for ['fred', 'barney']
52573 function filter(collection, predicate) {
52574 var func = isArray(collection) ? arrayFilter : baseFilter;
52575 return func(collection, getIteratee(predicate, 3));
52578 * Iterates over elements of `collection`, returning the first element
52579 * `predicate` returns truthy for. The predicate is invoked with three
52580 * arguments: (value, index|key, collection).
52585 * @category Collection
52586 * @param {Array|Object} collection The collection to inspect.
52587 * @param {Function} [predicate=_.identity] The function invoked per iteration.
52588 * @param {number} [fromIndex=0] The index to search from.
52589 * @returns {*} Returns the matched element, else `undefined`.
52593 * { 'user': 'barney', 'age': 36, 'active': true },
52594 * { 'user': 'fred', 'age': 40, 'active': false },
52595 * { 'user': 'pebbles', 'age': 1, 'active': true }
52598 * _.find(users, function(o) { return o.age < 40; });
52599 * // => object for 'barney'
52601 * // The `_.matches` iteratee shorthand.
52602 * _.find(users, { 'age': 1, 'active': true });
52603 * // => object for 'pebbles'
52605 * // The `_.matchesProperty` iteratee shorthand.
52606 * _.find(users, ['active', false]);
52607 * // => object for 'fred'
52609 * // The `_.property` iteratee shorthand.
52610 * _.find(users, 'active');
52611 * // => object for 'barney'
52615 var find = createFind(findIndex);
52617 * This method is like `_.find` except that it iterates over elements of
52618 * `collection` from right to left.
52623 * @category Collection
52624 * @param {Array|Object} collection The collection to inspect.
52625 * @param {Function} [predicate=_.identity] The function invoked per iteration.
52626 * @param {number} [fromIndex=collection.length-1] The index to search from.
52627 * @returns {*} Returns the matched element, else `undefined`.
52630 * _.findLast([1, 2, 3, 4], function(n) {
52631 * return n % 2 == 1;
52636 var findLast = createFind(findLastIndex);
52638 * Creates a flattened array of values by running each element in `collection`
52639 * thru `iteratee` and flattening the mapped results. The iteratee is invoked
52640 * with three arguments: (value, index|key, collection).
52645 * @category Collection
52646 * @param {Array|Object} collection The collection to iterate over.
52647 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52648 * @returns {Array} Returns the new flattened array.
52651 * function duplicate(n) {
52655 * _.flatMap([1, 2], duplicate);
52656 * // => [1, 1, 2, 2]
52659 function flatMap(collection, iteratee) {
52660 return baseFlatten(map(collection, iteratee), 1);
52663 * This method is like `_.flatMap` except that it recursively flattens the
52669 * @category Collection
52670 * @param {Array|Object} collection The collection to iterate over.
52671 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52672 * @returns {Array} Returns the new flattened array.
52675 * function duplicate(n) {
52676 * return [[[n, n]]];
52679 * _.flatMapDeep([1, 2], duplicate);
52680 * // => [1, 1, 2, 2]
52684 function flatMapDeep(collection, iteratee) {
52685 return baseFlatten(map(collection, iteratee), INFINITY);
52688 * This method is like `_.flatMap` except that it recursively flattens the
52689 * mapped results up to `depth` times.
52694 * @category Collection
52695 * @param {Array|Object} collection The collection to iterate over.
52696 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52697 * @param {number} [depth=1] The maximum recursion depth.
52698 * @returns {Array} Returns the new flattened array.
52701 * function duplicate(n) {
52702 * return [[[n, n]]];
52705 * _.flatMapDepth([1, 2], duplicate, 2);
52706 * // => [[1, 1], [2, 2]]
52710 function flatMapDepth(collection, iteratee, depth) {
52711 depth = depth === undefined$1 ? 1 : toInteger(depth);
52712 return baseFlatten(map(collection, iteratee), depth);
52715 * Iterates over elements of `collection` and invokes `iteratee` for each element.
52716 * The iteratee is invoked with three arguments: (value, index|key, collection).
52717 * Iteratee functions may exit iteration early by explicitly returning `false`.
52719 * **Note:** As with other "Collections" methods, objects with a "length"
52720 * property are iterated like arrays. To avoid this behavior use `_.forIn`
52721 * or `_.forOwn` for object iteration.
52727 * @category Collection
52728 * @param {Array|Object} collection The collection to iterate over.
52729 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52730 * @returns {Array|Object} Returns `collection`.
52731 * @see _.forEachRight
52734 * _.forEach([1, 2], function(value) {
52735 * console.log(value);
52737 * // => Logs `1` then `2`.
52739 * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
52740 * console.log(key);
52742 * // => Logs 'a' then 'b' (iteration order is not guaranteed).
52746 function forEach(collection, iteratee) {
52747 var func = isArray(collection) ? arrayEach : baseEach;
52748 return func(collection, getIteratee(iteratee, 3));
52751 * This method is like `_.forEach` except that it iterates over elements of
52752 * `collection` from right to left.
52758 * @category Collection
52759 * @param {Array|Object} collection The collection to iterate over.
52760 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52761 * @returns {Array|Object} Returns `collection`.
52765 * _.forEachRight([1, 2], function(value) {
52766 * console.log(value);
52768 * // => Logs `2` then `1`.
52772 function forEachRight(collection, iteratee) {
52773 var func = isArray(collection) ? arrayEachRight : baseEachRight;
52774 return func(collection, getIteratee(iteratee, 3));
52777 * Creates an object composed of keys generated from the results of running
52778 * each element of `collection` thru `iteratee`. The order of grouped values
52779 * is determined by the order they occur in `collection`. The corresponding
52780 * value of each key is an array of elements responsible for generating the
52781 * key. The iteratee is invoked with one argument: (value).
52786 * @category Collection
52787 * @param {Array|Object} collection The collection to iterate over.
52788 * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
52789 * @returns {Object} Returns the composed aggregate object.
52792 * _.groupBy([6.1, 4.2, 6.3], Math.floor);
52793 * // => { '4': [4.2], '6': [6.1, 6.3] }
52795 * // The `_.property` iteratee shorthand.
52796 * _.groupBy(['one', 'two', 'three'], 'length');
52797 * // => { '3': ['one', 'two'], '5': ['three'] }
52801 var groupBy = createAggregator(function (result, value, key) {
52802 if (hasOwnProperty.call(result, key)) {
52803 result[key].push(value);
52805 baseAssignValue(result, key, [value]);
52809 * Checks if `value` is in `collection`. If `collection` is a string, it's
52810 * checked for a substring of `value`, otherwise
52811 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
52812 * is used for equality comparisons. If `fromIndex` is negative, it's used as
52813 * the offset from the end of `collection`.
52818 * @category Collection
52819 * @param {Array|Object|string} collection The collection to inspect.
52820 * @param {*} value The value to search for.
52821 * @param {number} [fromIndex=0] The index to search from.
52822 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
52823 * @returns {boolean} Returns `true` if `value` is found, else `false`.
52826 * _.includes([1, 2, 3], 1);
52829 * _.includes([1, 2, 3], 1, 2);
52832 * _.includes({ 'a': 1, 'b': 2 }, 1);
52835 * _.includes('abcd', 'bc');
52839 function includes(collection, value, fromIndex, guard) {
52840 collection = isArrayLike(collection) ? collection : values(collection);
52841 fromIndex = fromIndex && !guard ? toInteger(fromIndex) : 0;
52842 var length = collection.length;
52844 if (fromIndex < 0) {
52845 fromIndex = nativeMax(length + fromIndex, 0);
52848 return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1;
52851 * Invokes the method at `path` of each element in `collection`, returning
52852 * an array of the results of each invoked method. Any additional arguments
52853 * are provided to each invoked method. If `path` is a function, it's invoked
52854 * for, and `this` bound to, each element in `collection`.
52859 * @category Collection
52860 * @param {Array|Object} collection The collection to iterate over.
52861 * @param {Array|Function|string} path The path of the method to invoke or
52862 * the function invoked per iteration.
52863 * @param {...*} [args] The arguments to invoke each method with.
52864 * @returns {Array} Returns the array of results.
52867 * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
52868 * // => [[1, 5, 7], [1, 2, 3]]
52870 * _.invokeMap([123, 456], String.prototype.split, '');
52871 * // => [['1', '2', '3'], ['4', '5', '6']]
52875 var invokeMap = baseRest(function (collection, path, args) {
52877 isFunc = typeof path == 'function',
52878 result = isArrayLike(collection) ? Array(collection.length) : [];
52879 baseEach(collection, function (value) {
52880 result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
52885 * Creates an object composed of keys generated from the results of running
52886 * each element of `collection` thru `iteratee`. The corresponding value of
52887 * each key is the last element responsible for generating the key. The
52888 * iteratee is invoked with one argument: (value).
52893 * @category Collection
52894 * @param {Array|Object} collection The collection to iterate over.
52895 * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
52896 * @returns {Object} Returns the composed aggregate object.
52900 * { 'dir': 'left', 'code': 97 },
52901 * { 'dir': 'right', 'code': 100 }
52904 * _.keyBy(array, function(o) {
52905 * return String.fromCharCode(o.code);
52907 * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
52909 * _.keyBy(array, 'dir');
52910 * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
52913 var keyBy = createAggregator(function (result, value, key) {
52914 baseAssignValue(result, key, value);
52917 * Creates an array of values by running each element in `collection` thru
52918 * `iteratee`. The iteratee is invoked with three arguments:
52919 * (value, index|key, collection).
52921 * Many lodash methods are guarded to work as iteratees for methods like
52922 * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
52924 * The guarded methods are:
52925 * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
52926 * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
52927 * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
52928 * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
52933 * @category Collection
52934 * @param {Array|Object} collection The collection to iterate over.
52935 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52936 * @returns {Array} Returns the new mapped array.
52939 * function square(n) {
52943 * _.map([4, 8], square);
52946 * _.map({ 'a': 4, 'b': 8 }, square);
52947 * // => [16, 64] (iteration order is not guaranteed)
52950 * { 'user': 'barney' },
52951 * { 'user': 'fred' }
52954 * // The `_.property` iteratee shorthand.
52955 * _.map(users, 'user');
52956 * // => ['barney', 'fred']
52959 function map(collection, iteratee) {
52960 var func = isArray(collection) ? arrayMap : baseMap;
52961 return func(collection, getIteratee(iteratee, 3));
52964 * This method is like `_.sortBy` except that it allows specifying the sort
52965 * orders of the iteratees to sort by. If `orders` is unspecified, all values
52966 * are sorted in ascending order. Otherwise, specify an order of "desc" for
52967 * descending or "asc" for ascending sort order of corresponding values.
52972 * @category Collection
52973 * @param {Array|Object} collection The collection to iterate over.
52974 * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
52975 * The iteratees to sort by.
52976 * @param {string[]} [orders] The sort orders of `iteratees`.
52977 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
52978 * @returns {Array} Returns the new sorted array.
52982 * { 'user': 'fred', 'age': 48 },
52983 * { 'user': 'barney', 'age': 34 },
52984 * { 'user': 'fred', 'age': 40 },
52985 * { 'user': 'barney', 'age': 36 }
52988 * // Sort by `user` in ascending order and by `age` in descending order.
52989 * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
52990 * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
52994 function orderBy(collection, iteratees, orders, guard) {
52995 if (collection == null) {
52999 if (!isArray(iteratees)) {
53000 iteratees = iteratees == null ? [] : [iteratees];
53003 orders = guard ? undefined$1 : orders;
53005 if (!isArray(orders)) {
53006 orders = orders == null ? [] : [orders];
53009 return baseOrderBy(collection, iteratees, orders);
53012 * Creates an array of elements split into two groups, the first of which
53013 * contains elements `predicate` returns truthy for, the second of which
53014 * contains elements `predicate` returns falsey for. The predicate is
53015 * invoked with one argument: (value).
53020 * @category Collection
53021 * @param {Array|Object} collection The collection to iterate over.
53022 * @param {Function} [predicate=_.identity] The function invoked per iteration.
53023 * @returns {Array} Returns the array of grouped elements.
53027 * { 'user': 'barney', 'age': 36, 'active': false },
53028 * { 'user': 'fred', 'age': 40, 'active': true },
53029 * { 'user': 'pebbles', 'age': 1, 'active': false }
53032 * _.partition(users, function(o) { return o.active; });
53033 * // => objects for [['fred'], ['barney', 'pebbles']]
53035 * // The `_.matches` iteratee shorthand.
53036 * _.partition(users, { 'age': 1, 'active': false });
53037 * // => objects for [['pebbles'], ['barney', 'fred']]
53039 * // The `_.matchesProperty` iteratee shorthand.
53040 * _.partition(users, ['active', false]);
53041 * // => objects for [['barney', 'pebbles'], ['fred']]
53043 * // The `_.property` iteratee shorthand.
53044 * _.partition(users, 'active');
53045 * // => objects for [['fred'], ['barney', 'pebbles']]
53049 var partition = createAggregator(function (result, value, key) {
53050 result[key ? 0 : 1].push(value);
53055 * Reduces `collection` to a value which is the accumulated result of running
53056 * each element in `collection` thru `iteratee`, where each successive
53057 * invocation is supplied the return value of the previous. If `accumulator`
53058 * is not given, the first element of `collection` is used as the initial
53059 * value. The iteratee is invoked with four arguments:
53060 * (accumulator, value, index|key, collection).
53062 * Many lodash methods are guarded to work as iteratees for methods like
53063 * `_.reduce`, `_.reduceRight`, and `_.transform`.
53065 * The guarded methods are:
53066 * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
53072 * @category Collection
53073 * @param {Array|Object} collection The collection to iterate over.
53074 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
53075 * @param {*} [accumulator] The initial value.
53076 * @returns {*} Returns the accumulated value.
53077 * @see _.reduceRight
53080 * _.reduce([1, 2], function(sum, n) {
53085 * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
53086 * (result[value] || (result[value] = [])).push(key);
53089 * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
53092 function reduce(collection, iteratee, accumulator) {
53093 var func = isArray(collection) ? arrayReduce : baseReduce,
53094 initAccum = arguments.length < 3;
53095 return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
53098 * This method is like `_.reduce` except that it iterates over elements of
53099 * `collection` from right to left.
53104 * @category Collection
53105 * @param {Array|Object} collection The collection to iterate over.
53106 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
53107 * @param {*} [accumulator] The initial value.
53108 * @returns {*} Returns the accumulated value.
53112 * var array = [[0, 1], [2, 3], [4, 5]];
53114 * _.reduceRight(array, function(flattened, other) {
53115 * return flattened.concat(other);
53117 * // => [4, 5, 2, 3, 0, 1]
53121 function reduceRight(collection, iteratee, accumulator) {
53122 var func = isArray(collection) ? arrayReduceRight : baseReduce,
53123 initAccum = arguments.length < 3;
53124 return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
53127 * The opposite of `_.filter`; this method returns the elements of `collection`
53128 * that `predicate` does **not** return truthy for.
53133 * @category Collection
53134 * @param {Array|Object} collection The collection to iterate over.
53135 * @param {Function} [predicate=_.identity] The function invoked per iteration.
53136 * @returns {Array} Returns the new filtered array.
53141 * { 'user': 'barney', 'age': 36, 'active': false },
53142 * { 'user': 'fred', 'age': 40, 'active': true }
53145 * _.reject(users, function(o) { return !o.active; });
53146 * // => objects for ['fred']
53148 * // The `_.matches` iteratee shorthand.
53149 * _.reject(users, { 'age': 40, 'active': true });
53150 * // => objects for ['barney']
53152 * // The `_.matchesProperty` iteratee shorthand.
53153 * _.reject(users, ['active', false]);
53154 * // => objects for ['fred']
53156 * // The `_.property` iteratee shorthand.
53157 * _.reject(users, 'active');
53158 * // => objects for ['barney']
53162 function reject(collection, predicate) {
53163 var func = isArray(collection) ? arrayFilter : baseFilter;
53164 return func(collection, negate(getIteratee(predicate, 3)));
53167 * Gets a random element from `collection`.
53172 * @category Collection
53173 * @param {Array|Object} collection The collection to sample.
53174 * @returns {*} Returns the random element.
53177 * _.sample([1, 2, 3, 4]);
53182 function sample(collection) {
53183 var func = isArray(collection) ? arraySample : baseSample;
53184 return func(collection);
53187 * Gets `n` random elements at unique keys from `collection` up to the
53188 * size of `collection`.
53193 * @category Collection
53194 * @param {Array|Object} collection The collection to sample.
53195 * @param {number} [n=1] The number of elements to sample.
53196 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53197 * @returns {Array} Returns the random elements.
53200 * _.sampleSize([1, 2, 3], 2);
53203 * _.sampleSize([1, 2, 3], 4);
53208 function sampleSize(collection, n, guard) {
53209 if (guard ? isIterateeCall(collection, n, guard) : n === undefined$1) {
53215 var func = isArray(collection) ? arraySampleSize : baseSampleSize;
53216 return func(collection, n);
53219 * Creates an array of shuffled values, using a version of the
53220 * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
53225 * @category Collection
53226 * @param {Array|Object} collection The collection to shuffle.
53227 * @returns {Array} Returns the new shuffled array.
53230 * _.shuffle([1, 2, 3, 4]);
53231 * // => [4, 1, 3, 2]
53235 function shuffle(collection) {
53236 var func = isArray(collection) ? arrayShuffle : baseShuffle;
53237 return func(collection);
53240 * Gets the size of `collection` by returning its length for array-like
53241 * values or the number of own enumerable string keyed properties for objects.
53246 * @category Collection
53247 * @param {Array|Object|string} collection The collection to inspect.
53248 * @returns {number} Returns the collection size.
53251 * _.size([1, 2, 3]);
53254 * _.size({ 'a': 1, 'b': 2 });
53257 * _.size('pebbles');
53262 function size(collection) {
53263 if (collection == null) {
53267 if (isArrayLike(collection)) {
53268 return isString(collection) ? stringSize(collection) : collection.length;
53271 var tag = getTag(collection);
53273 if (tag == mapTag || tag == setTag) {
53274 return collection.size;
53277 return baseKeys(collection).length;
53280 * Checks if `predicate` returns truthy for **any** element of `collection`.
53281 * Iteration is stopped once `predicate` returns truthy. The predicate is
53282 * invoked with three arguments: (value, index|key, collection).
53287 * @category Collection
53288 * @param {Array|Object} collection The collection to iterate over.
53289 * @param {Function} [predicate=_.identity] The function invoked per iteration.
53290 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53291 * @returns {boolean} Returns `true` if any element passes the predicate check,
53295 * _.some([null, 0, 'yes', false], Boolean);
53299 * { 'user': 'barney', 'active': true },
53300 * { 'user': 'fred', 'active': false }
53303 * // The `_.matches` iteratee shorthand.
53304 * _.some(users, { 'user': 'barney', 'active': false });
53307 * // The `_.matchesProperty` iteratee shorthand.
53308 * _.some(users, ['active', false]);
53311 * // The `_.property` iteratee shorthand.
53312 * _.some(users, 'active');
53317 function some(collection, predicate, guard) {
53318 var func = isArray(collection) ? arraySome : baseSome;
53320 if (guard && isIterateeCall(collection, predicate, guard)) {
53321 predicate = undefined$1;
53324 return func(collection, getIteratee(predicate, 3));
53327 * Creates an array of elements, sorted in ascending order by the results of
53328 * running each element in a collection thru each iteratee. This method
53329 * performs a stable sort, that is, it preserves the original sort order of
53330 * equal elements. The iteratees are invoked with one argument: (value).
53335 * @category Collection
53336 * @param {Array|Object} collection The collection to iterate over.
53337 * @param {...(Function|Function[])} [iteratees=[_.identity]]
53338 * The iteratees to sort by.
53339 * @returns {Array} Returns the new sorted array.
53343 * { 'user': 'fred', 'age': 48 },
53344 * { 'user': 'barney', 'age': 36 },
53345 * { 'user': 'fred', 'age': 30 },
53346 * { 'user': 'barney', 'age': 34 }
53349 * _.sortBy(users, [function(o) { return o.user; }]);
53350 * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]
53352 * _.sortBy(users, ['user', 'age']);
53353 * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]
53357 var sortBy = baseRest(function (collection, iteratees) {
53358 if (collection == null) {
53362 var length = iteratees.length;
53364 if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
53366 } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
53367 iteratees = [iteratees[0]];
53370 return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
53372 /*------------------------------------------------------------------------*/
53375 * Gets the timestamp of the number of milliseconds that have elapsed since
53376 * the Unix epoch (1 January 1970 00:00:00 UTC).
53382 * @returns {number} Returns the timestamp.
53385 * _.defer(function(stamp) {
53386 * console.log(_.now() - stamp);
53388 * // => Logs the number of milliseconds it took for the deferred invocation.
53391 var now = ctxNow || function () {
53392 return root.Date.now();
53394 /*------------------------------------------------------------------------*/
53397 * The opposite of `_.before`; this method creates a function that invokes
53398 * `func` once it's called `n` or more times.
53403 * @category Function
53404 * @param {number} n The number of calls before `func` is invoked.
53405 * @param {Function} func The function to restrict.
53406 * @returns {Function} Returns the new restricted function.
53409 * var saves = ['profile', 'settings'];
53411 * var done = _.after(saves.length, function() {
53412 * console.log('done saving!');
53415 * _.forEach(saves, function(type) {
53416 * asyncSave({ 'type': type, 'complete': done });
53418 * // => Logs 'done saving!' after the two async saves have completed.
53422 function after(n, func) {
53423 if (typeof func != 'function') {
53424 throw new TypeError(FUNC_ERROR_TEXT);
53428 return function () {
53430 return func.apply(this, arguments);
53435 * Creates a function that invokes `func`, with up to `n` arguments,
53436 * ignoring any additional arguments.
53441 * @category Function
53442 * @param {Function} func The function to cap arguments for.
53443 * @param {number} [n=func.length] The arity cap.
53444 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53445 * @returns {Function} Returns the new capped function.
53448 * _.map(['6', '8', '10'], _.ary(parseInt, 1));
53453 function ary(func, n, guard) {
53454 n = guard ? undefined$1 : n;
53455 n = func && n == null ? func.length : n;
53456 return createWrap(func, WRAP_ARY_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, n);
53459 * Creates a function that invokes `func`, with the `this` binding and arguments
53460 * of the created function, while it's called less than `n` times. Subsequent
53461 * calls to the created function return the result of the last `func` invocation.
53466 * @category Function
53467 * @param {number} n The number of calls at which `func` is no longer invoked.
53468 * @param {Function} func The function to restrict.
53469 * @returns {Function} Returns the new restricted function.
53472 * jQuery(element).on('click', _.before(5, addContactToList));
53473 * // => Allows adding up to 4 contacts to the list.
53477 function before(n, func) {
53480 if (typeof func != 'function') {
53481 throw new TypeError(FUNC_ERROR_TEXT);
53485 return function () {
53487 result = func.apply(this, arguments);
53491 func = undefined$1;
53498 * Creates a function that invokes `func` with the `this` binding of `thisArg`
53499 * and `partials` prepended to the arguments it receives.
53501 * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
53502 * may be used as a placeholder for partially applied arguments.
53504 * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
53505 * property of bound functions.
53510 * @category Function
53511 * @param {Function} func The function to bind.
53512 * @param {*} thisArg The `this` binding of `func`.
53513 * @param {...*} [partials] The arguments to be partially applied.
53514 * @returns {Function} Returns the new bound function.
53517 * function greet(greeting, punctuation) {
53518 * return greeting + ' ' + this.user + punctuation;
53521 * var object = { 'user': 'fred' };
53523 * var bound = _.bind(greet, object, 'hi');
53527 * // Bound with placeholders.
53528 * var bound = _.bind(greet, object, _, '!');
53534 var bind = baseRest(function (func, thisArg, partials) {
53535 var bitmask = WRAP_BIND_FLAG;
53537 if (partials.length) {
53538 var holders = replaceHolders(partials, getHolder(bind));
53539 bitmask |= WRAP_PARTIAL_FLAG;
53542 return createWrap(func, bitmask, thisArg, partials, holders);
53545 * Creates a function that invokes the method at `object[key]` with `partials`
53546 * prepended to the arguments it receives.
53548 * This method differs from `_.bind` by allowing bound functions to reference
53549 * methods that may be redefined or don't yet exist. See
53550 * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
53551 * for more details.
53553 * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
53554 * builds, may be used as a placeholder for partially applied arguments.
53559 * @category Function
53560 * @param {Object} object The object to invoke the method on.
53561 * @param {string} key The key of the method.
53562 * @param {...*} [partials] The arguments to be partially applied.
53563 * @returns {Function} Returns the new bound function.
53568 * 'greet': function(greeting, punctuation) {
53569 * return greeting + ' ' + this.user + punctuation;
53573 * var bound = _.bindKey(object, 'greet', 'hi');
53577 * object.greet = function(greeting, punctuation) {
53578 * return greeting + 'ya ' + this.user + punctuation;
53582 * // => 'hiya fred!'
53584 * // Bound with placeholders.
53585 * var bound = _.bindKey(object, 'greet', _, '!');
53587 * // => 'hiya fred!'
53590 var bindKey = baseRest(function (object, key, partials) {
53591 var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
53593 if (partials.length) {
53594 var holders = replaceHolders(partials, getHolder(bindKey));
53595 bitmask |= WRAP_PARTIAL_FLAG;
53598 return createWrap(key, bitmask, object, partials, holders);
53601 * Creates a function that accepts arguments of `func` and either invokes
53602 * `func` returning its result, if at least `arity` number of arguments have
53603 * been provided, or returns a function that accepts the remaining `func`
53604 * arguments, and so on. The arity of `func` may be specified if `func.length`
53605 * is not sufficient.
53607 * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
53608 * may be used as a placeholder for provided arguments.
53610 * **Note:** This method doesn't set the "length" property of curried functions.
53615 * @category Function
53616 * @param {Function} func The function to curry.
53617 * @param {number} [arity=func.length] The arity of `func`.
53618 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53619 * @returns {Function} Returns the new curried function.
53622 * var abc = function(a, b, c) {
53623 * return [a, b, c];
53626 * var curried = _.curry(abc);
53628 * curried(1)(2)(3);
53631 * curried(1, 2)(3);
53634 * curried(1, 2, 3);
53637 * // Curried with placeholders.
53638 * curried(1)(_, 3)(2);
53642 function curry(func, arity, guard) {
53643 arity = guard ? undefined$1 : arity;
53644 var result = createWrap(func, WRAP_CURRY_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, undefined$1, arity);
53645 result.placeholder = curry.placeholder;
53649 * This method is like `_.curry` except that arguments are applied to `func`
53650 * in the manner of `_.partialRight` instead of `_.partial`.
53652 * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
53653 * builds, may be used as a placeholder for provided arguments.
53655 * **Note:** This method doesn't set the "length" property of curried functions.
53660 * @category Function
53661 * @param {Function} func The function to curry.
53662 * @param {number} [arity=func.length] The arity of `func`.
53663 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53664 * @returns {Function} Returns the new curried function.
53667 * var abc = function(a, b, c) {
53668 * return [a, b, c];
53671 * var curried = _.curryRight(abc);
53673 * curried(3)(2)(1);
53676 * curried(2, 3)(1);
53679 * curried(1, 2, 3);
53682 * // Curried with placeholders.
53683 * curried(3)(1, _)(2);
53688 function curryRight(func, arity, guard) {
53689 arity = guard ? undefined$1 : arity;
53690 var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, undefined$1, arity);
53691 result.placeholder = curryRight.placeholder;
53695 * Creates a debounced function that delays invoking `func` until after `wait`
53696 * milliseconds have elapsed since the last time the debounced function was
53697 * invoked. The debounced function comes with a `cancel` method to cancel
53698 * delayed `func` invocations and a `flush` method to immediately invoke them.
53699 * Provide `options` to indicate whether `func` should be invoked on the
53700 * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
53701 * with the last arguments provided to the debounced function. Subsequent
53702 * calls to the debounced function return the result of the last `func`
53705 * **Note:** If `leading` and `trailing` options are `true`, `func` is
53706 * invoked on the trailing edge of the timeout only if the debounced function
53707 * is invoked more than once during the `wait` timeout.
53709 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
53710 * until to the next tick, similar to `setTimeout` with a timeout of `0`.
53712 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
53713 * for details over the differences between `_.debounce` and `_.throttle`.
53718 * @category Function
53719 * @param {Function} func The function to debounce.
53720 * @param {number} [wait=0] The number of milliseconds to delay.
53721 * @param {Object} [options={}] The options object.
53722 * @param {boolean} [options.leading=false]
53723 * Specify invoking on the leading edge of the timeout.
53724 * @param {number} [options.maxWait]
53725 * The maximum time `func` is allowed to be delayed before it's invoked.
53726 * @param {boolean} [options.trailing=true]
53727 * Specify invoking on the trailing edge of the timeout.
53728 * @returns {Function} Returns the new debounced function.
53731 * // Avoid costly calculations while the window size is in flux.
53732 * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
53734 * // Invoke `sendMail` when clicked, debouncing subsequent calls.
53735 * jQuery(element).on('click', _.debounce(sendMail, 300, {
53737 * 'trailing': false
53740 * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
53741 * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
53742 * var source = new EventSource('/stream');
53743 * jQuery(source).on('message', debounced);
53745 * // Cancel the trailing debounced invocation.
53746 * jQuery(window).on('popstate', debounced.cancel);
53750 function debounce(func, wait, options) {
53757 lastInvokeTime = 0,
53762 if (typeof func != 'function') {
53763 throw new TypeError(FUNC_ERROR_TEXT);
53766 wait = toNumber(wait) || 0;
53768 if (isObject(options)) {
53769 leading = !!options.leading;
53770 maxing = 'maxWait' in options;
53771 maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
53772 trailing = 'trailing' in options ? !!options.trailing : trailing;
53775 function invokeFunc(time) {
53776 var args = lastArgs,
53777 thisArg = lastThis;
53778 lastArgs = lastThis = undefined$1;
53779 lastInvokeTime = time;
53780 result = func.apply(thisArg, args);
53784 function leadingEdge(time) {
53785 // Reset any `maxWait` timer.
53786 lastInvokeTime = time; // Start the timer for the trailing edge.
53788 timerId = setTimeout(timerExpired, wait); // Invoke the leading edge.
53790 return leading ? invokeFunc(time) : result;
53793 function remainingWait(time) {
53794 var timeSinceLastCall = time - lastCallTime,
53795 timeSinceLastInvoke = time - lastInvokeTime,
53796 timeWaiting = wait - timeSinceLastCall;
53797 return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
53800 function shouldInvoke(time) {
53801 var timeSinceLastCall = time - lastCallTime,
53802 timeSinceLastInvoke = time - lastInvokeTime; // Either this is the first call, activity has stopped and we're at the
53803 // trailing edge, the system time has gone backwards and we're treating
53804 // it as the trailing edge, or we've hit the `maxWait` limit.
53806 return lastCallTime === undefined$1 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
53809 function timerExpired() {
53812 if (shouldInvoke(time)) {
53813 return trailingEdge(time);
53814 } // Restart the timer.
53817 timerId = setTimeout(timerExpired, remainingWait(time));
53820 function trailingEdge(time) {
53821 timerId = undefined$1; // Only invoke if we have `lastArgs` which means `func` has been
53822 // debounced at least once.
53824 if (trailing && lastArgs) {
53825 return invokeFunc(time);
53828 lastArgs = lastThis = undefined$1;
53832 function cancel() {
53833 if (timerId !== undefined$1) {
53834 clearTimeout(timerId);
53837 lastInvokeTime = 0;
53838 lastArgs = lastCallTime = lastThis = timerId = undefined$1;
53842 return timerId === undefined$1 ? result : trailingEdge(now());
53845 function debounced() {
53847 isInvoking = shouldInvoke(time);
53848 lastArgs = arguments;
53850 lastCallTime = time;
53853 if (timerId === undefined$1) {
53854 return leadingEdge(lastCallTime);
53858 // Handle invocations in a tight loop.
53859 clearTimeout(timerId);
53860 timerId = setTimeout(timerExpired, wait);
53861 return invokeFunc(lastCallTime);
53865 if (timerId === undefined$1) {
53866 timerId = setTimeout(timerExpired, wait);
53872 debounced.cancel = cancel;
53873 debounced.flush = flush;
53877 * Defers invoking the `func` until the current call stack has cleared. Any
53878 * additional arguments are provided to `func` when it's invoked.
53883 * @category Function
53884 * @param {Function} func The function to defer.
53885 * @param {...*} [args] The arguments to invoke `func` with.
53886 * @returns {number} Returns the timer id.
53889 * _.defer(function(text) {
53890 * console.log(text);
53892 * // => Logs 'deferred' after one millisecond.
53896 var defer = baseRest(function (func, args) {
53897 return baseDelay(func, 1, args);
53900 * Invokes `func` after `wait` milliseconds. Any additional arguments are
53901 * provided to `func` when it's invoked.
53906 * @category Function
53907 * @param {Function} func The function to delay.
53908 * @param {number} wait The number of milliseconds to delay invocation.
53909 * @param {...*} [args] The arguments to invoke `func` with.
53910 * @returns {number} Returns the timer id.
53913 * _.delay(function(text) {
53914 * console.log(text);
53915 * }, 1000, 'later');
53916 * // => Logs 'later' after one second.
53919 var delay = baseRest(function (func, wait, args) {
53920 return baseDelay(func, toNumber(wait) || 0, args);
53923 * Creates a function that invokes `func` with arguments reversed.
53928 * @category Function
53929 * @param {Function} func The function to flip arguments for.
53930 * @returns {Function} Returns the new flipped function.
53933 * var flipped = _.flip(function() {
53934 * return _.toArray(arguments);
53937 * flipped('a', 'b', 'c', 'd');
53938 * // => ['d', 'c', 'b', 'a']
53941 function flip(func) {
53942 return createWrap(func, WRAP_FLIP_FLAG);
53945 * Creates a function that memoizes the result of `func`. If `resolver` is
53946 * provided, it determines the cache key for storing the result based on the
53947 * arguments provided to the memoized function. By default, the first argument
53948 * provided to the memoized function is used as the map cache key. The `func`
53949 * is invoked with the `this` binding of the memoized function.
53951 * **Note:** The cache is exposed as the `cache` property on the memoized
53952 * function. Its creation may be customized by replacing the `_.memoize.Cache`
53953 * constructor with one whose instances implement the
53954 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
53955 * method interface of `clear`, `delete`, `get`, `has`, and `set`.
53960 * @category Function
53961 * @param {Function} func The function to have its output memoized.
53962 * @param {Function} [resolver] The function to resolve the cache key.
53963 * @returns {Function} Returns the new memoized function.
53966 * var object = { 'a': 1, 'b': 2 };
53967 * var other = { 'c': 3, 'd': 4 };
53969 * var values = _.memoize(_.values);
53980 * // Modify the result cache.
53981 * values.cache.set(object, ['a', 'b']);
53985 * // Replace `_.memoize.Cache`.
53986 * _.memoize.Cache = WeakMap;
53990 function memoize(func, resolver) {
53991 if (typeof func != 'function' || resolver != null && typeof resolver != 'function') {
53992 throw new TypeError(FUNC_ERROR_TEXT);
53995 var memoized = function memoized() {
53996 var args = arguments,
53997 key = resolver ? resolver.apply(this, args) : args[0],
53998 cache = memoized.cache;
54000 if (cache.has(key)) {
54001 return cache.get(key);
54004 var result = func.apply(this, args);
54005 memoized.cache = cache.set(key, result) || cache;
54009 memoized.cache = new (memoize.Cache || MapCache)();
54011 } // Expose `MapCache`.
54014 memoize.Cache = MapCache;
54016 * Creates a function that negates the result of the predicate `func`. The
54017 * `func` predicate is invoked with the `this` binding and arguments of the
54018 * created function.
54023 * @category Function
54024 * @param {Function} predicate The predicate to negate.
54025 * @returns {Function} Returns the new negated function.
54028 * function isEven(n) {
54029 * return n % 2 == 0;
54032 * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
54036 function negate(predicate) {
54037 if (typeof predicate != 'function') {
54038 throw new TypeError(FUNC_ERROR_TEXT);
54041 return function () {
54042 var args = arguments;
54044 switch (args.length) {
54046 return !predicate.call(this);
54049 return !predicate.call(this, args[0]);
54052 return !predicate.call(this, args[0], args[1]);
54055 return !predicate.call(this, args[0], args[1], args[2]);
54058 return !predicate.apply(this, args);
54062 * Creates a function that is restricted to invoking `func` once. Repeat calls
54063 * to the function return the value of the first invocation. The `func` is
54064 * invoked with the `this` binding and arguments of the created function.
54069 * @category Function
54070 * @param {Function} func The function to restrict.
54071 * @returns {Function} Returns the new restricted function.
54074 * var initialize = _.once(createApplication);
54077 * // => `createApplication` is invoked once
54081 function once(func) {
54082 return before(2, func);
54085 * Creates a function that invokes `func` with its arguments transformed.
54090 * @category Function
54091 * @param {Function} func The function to wrap.
54092 * @param {...(Function|Function[])} [transforms=[_.identity]]
54093 * The argument transforms.
54094 * @returns {Function} Returns the new function.
54097 * function doubled(n) {
54101 * function square(n) {
54105 * var func = _.overArgs(function(x, y) {
54107 * }, [square, doubled]);
54117 var overArgs = castRest(function (func, transforms) {
54118 transforms = transforms.length == 1 && isArray(transforms[0]) ? arrayMap(transforms[0], baseUnary(getIteratee())) : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
54119 var funcsLength = transforms.length;
54120 return baseRest(function (args) {
54122 length = nativeMin(args.length, funcsLength);
54124 while (++index < length) {
54125 args[index] = transforms[index].call(this, args[index]);
54128 return apply(func, this, args);
54132 * Creates a function that invokes `func` with `partials` prepended to the
54133 * arguments it receives. This method is like `_.bind` except it does **not**
54134 * alter the `this` binding.
54136 * The `_.partial.placeholder` value, which defaults to `_` in monolithic
54137 * builds, may be used as a placeholder for partially applied arguments.
54139 * **Note:** This method doesn't set the "length" property of partially
54140 * applied functions.
54145 * @category Function
54146 * @param {Function} func The function to partially apply arguments to.
54147 * @param {...*} [partials] The arguments to be partially applied.
54148 * @returns {Function} Returns the new partially applied function.
54151 * function greet(greeting, name) {
54152 * return greeting + ' ' + name;
54155 * var sayHelloTo = _.partial(greet, 'hello');
54156 * sayHelloTo('fred');
54157 * // => 'hello fred'
54159 * // Partially applied with placeholders.
54160 * var greetFred = _.partial(greet, _, 'fred');
54165 var partial = baseRest(function (func, partials) {
54166 var holders = replaceHolders(partials, getHolder(partial));
54167 return createWrap(func, WRAP_PARTIAL_FLAG, undefined$1, partials, holders);
54170 * This method is like `_.partial` except that partially applied arguments
54171 * are appended to the arguments it receives.
54173 * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
54174 * builds, may be used as a placeholder for partially applied arguments.
54176 * **Note:** This method doesn't set the "length" property of partially
54177 * applied functions.
54182 * @category Function
54183 * @param {Function} func The function to partially apply arguments to.
54184 * @param {...*} [partials] The arguments to be partially applied.
54185 * @returns {Function} Returns the new partially applied function.
54188 * function greet(greeting, name) {
54189 * return greeting + ' ' + name;
54192 * var greetFred = _.partialRight(greet, 'fred');
54196 * // Partially applied with placeholders.
54197 * var sayHelloTo = _.partialRight(greet, 'hello', _);
54198 * sayHelloTo('fred');
54199 * // => 'hello fred'
54202 var partialRight = baseRest(function (func, partials) {
54203 var holders = replaceHolders(partials, getHolder(partialRight));
54204 return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined$1, partials, holders);
54207 * Creates a function that invokes `func` with arguments arranged according
54208 * to the specified `indexes` where the argument value at the first index is
54209 * provided as the first argument, the argument value at the second index is
54210 * provided as the second argument, and so on.
54215 * @category Function
54216 * @param {Function} func The function to rearrange arguments for.
54217 * @param {...(number|number[])} indexes The arranged argument indexes.
54218 * @returns {Function} Returns the new function.
54221 * var rearged = _.rearg(function(a, b, c) {
54222 * return [a, b, c];
54225 * rearged('b', 'c', 'a')
54226 * // => ['a', 'b', 'c']
54229 var rearg = flatRest(function (func, indexes) {
54230 return createWrap(func, WRAP_REARG_FLAG, undefined$1, undefined$1, undefined$1, indexes);
54233 * Creates a function that invokes `func` with the `this` binding of the
54234 * created function and arguments from `start` and beyond provided as
54237 * **Note:** This method is based on the
54238 * [rest parameter](https://mdn.io/rest_parameters).
54243 * @category Function
54244 * @param {Function} func The function to apply a rest parameter to.
54245 * @param {number} [start=func.length-1] The start position of the rest parameter.
54246 * @returns {Function} Returns the new function.
54249 * var say = _.rest(function(what, names) {
54250 * return what + ' ' + _.initial(names).join(', ') +
54251 * (_.size(names) > 1 ? ', & ' : '') + _.last(names);
54254 * say('hello', 'fred', 'barney', 'pebbles');
54255 * // => 'hello fred, barney, & pebbles'
54258 function rest(func, start) {
54259 if (typeof func != 'function') {
54260 throw new TypeError(FUNC_ERROR_TEXT);
54263 start = start === undefined$1 ? start : toInteger(start);
54264 return baseRest(func, start);
54267 * Creates a function that invokes `func` with the `this` binding of the
54268 * create function and an array of arguments much like
54269 * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
54271 * **Note:** This method is based on the
54272 * [spread operator](https://mdn.io/spread_operator).
54277 * @category Function
54278 * @param {Function} func The function to spread arguments over.
54279 * @param {number} [start=0] The start position of the spread.
54280 * @returns {Function} Returns the new function.
54283 * var say = _.spread(function(who, what) {
54284 * return who + ' says ' + what;
54287 * say(['fred', 'hello']);
54288 * // => 'fred says hello'
54290 * var numbers = Promise.all([
54291 * Promise.resolve(40),
54292 * Promise.resolve(36)
54295 * numbers.then(_.spread(function(x, y) {
54298 * // => a Promise of 76
54302 function spread(func, start) {
54303 if (typeof func != 'function') {
54304 throw new TypeError(FUNC_ERROR_TEXT);
54307 start = start == null ? 0 : nativeMax(toInteger(start), 0);
54308 return baseRest(function (args) {
54309 var array = args[start],
54310 otherArgs = castSlice(args, 0, start);
54313 arrayPush(otherArgs, array);
54316 return apply(func, this, otherArgs);
54320 * Creates a throttled function that only invokes `func` at most once per
54321 * every `wait` milliseconds. The throttled function comes with a `cancel`
54322 * method to cancel delayed `func` invocations and a `flush` method to
54323 * immediately invoke them. Provide `options` to indicate whether `func`
54324 * should be invoked on the leading and/or trailing edge of the `wait`
54325 * timeout. The `func` is invoked with the last arguments provided to the
54326 * throttled function. Subsequent calls to the throttled function return the
54327 * result of the last `func` invocation.
54329 * **Note:** If `leading` and `trailing` options are `true`, `func` is
54330 * invoked on the trailing edge of the timeout only if the throttled function
54331 * is invoked more than once during the `wait` timeout.
54333 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
54334 * until to the next tick, similar to `setTimeout` with a timeout of `0`.
54336 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
54337 * for details over the differences between `_.throttle` and `_.debounce`.
54342 * @category Function
54343 * @param {Function} func The function to throttle.
54344 * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
54345 * @param {Object} [options={}] The options object.
54346 * @param {boolean} [options.leading=true]
54347 * Specify invoking on the leading edge of the timeout.
54348 * @param {boolean} [options.trailing=true]
54349 * Specify invoking on the trailing edge of the timeout.
54350 * @returns {Function} Returns the new throttled function.
54353 * // Avoid excessively updating the position while scrolling.
54354 * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
54356 * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
54357 * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
54358 * jQuery(element).on('click', throttled);
54360 * // Cancel the trailing throttled invocation.
54361 * jQuery(window).on('popstate', throttled.cancel);
54365 function throttle(func, wait, options) {
54366 var leading = true,
54369 if (typeof func != 'function') {
54370 throw new TypeError(FUNC_ERROR_TEXT);
54373 if (isObject(options)) {
54374 leading = 'leading' in options ? !!options.leading : leading;
54375 trailing = 'trailing' in options ? !!options.trailing : trailing;
54378 return debounce(func, wait, {
54379 'leading': leading,
54381 'trailing': trailing
54385 * Creates a function that accepts up to one argument, ignoring any
54386 * additional arguments.
54391 * @category Function
54392 * @param {Function} func The function to cap arguments for.
54393 * @returns {Function} Returns the new capped function.
54396 * _.map(['6', '8', '10'], _.unary(parseInt));
54401 function unary(func) {
54402 return ary(func, 1);
54405 * Creates a function that provides `value` to `wrapper` as its first
54406 * argument. Any additional arguments provided to the function are appended
54407 * to those provided to the `wrapper`. The wrapper is invoked with the `this`
54408 * binding of the created function.
54413 * @category Function
54414 * @param {*} value The value to wrap.
54415 * @param {Function} [wrapper=identity] The wrapper function.
54416 * @returns {Function} Returns the new function.
54419 * var p = _.wrap(_.escape, function(func, text) {
54420 * return '<p>' + func(text) + '</p>';
54423 * p('fred, barney, & pebbles');
54424 * // => '<p>fred, barney, & pebbles</p>'
54428 function wrap(value, wrapper) {
54429 return partial(castFunction(wrapper), value);
54431 /*------------------------------------------------------------------------*/
54434 * Casts `value` as an array if it's not one.
54440 * @param {*} value The value to inspect.
54441 * @returns {Array} Returns the cast array.
54447 * _.castArray({ 'a': 1 });
54448 * // => [{ 'a': 1 }]
54450 * _.castArray('abc');
54453 * _.castArray(null);
54456 * _.castArray(undefined);
54457 * // => [undefined]
54462 * var array = [1, 2, 3];
54463 * console.log(_.castArray(array) === array);
54468 function castArray() {
54469 if (!arguments.length) {
54473 var value = arguments[0];
54474 return isArray(value) ? value : [value];
54477 * Creates a shallow clone of `value`.
54479 * **Note:** This method is loosely based on the
54480 * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
54481 * and supports cloning arrays, array buffers, booleans, date objects, maps,
54482 * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
54483 * arrays. The own enumerable properties of `arguments` objects are cloned
54484 * as plain objects. An empty object is returned for uncloneable values such
54485 * as error objects, functions, DOM nodes, and WeakMaps.
54491 * @param {*} value The value to clone.
54492 * @returns {*} Returns the cloned value.
54496 * var objects = [{ 'a': 1 }, { 'b': 2 }];
54498 * var shallow = _.clone(objects);
54499 * console.log(shallow[0] === objects[0]);
54504 function clone(value) {
54505 return baseClone(value, CLONE_SYMBOLS_FLAG);
54508 * This method is like `_.clone` except that it accepts `customizer` which
54509 * is invoked to produce the cloned value. If `customizer` returns `undefined`,
54510 * cloning is handled by the method instead. The `customizer` is invoked with
54511 * up to four arguments; (value [, index|key, object, stack]).
54517 * @param {*} value The value to clone.
54518 * @param {Function} [customizer] The function to customize cloning.
54519 * @returns {*} Returns the cloned value.
54520 * @see _.cloneDeepWith
54523 * function customizer(value) {
54524 * if (_.isElement(value)) {
54525 * return value.cloneNode(false);
54529 * var el = _.cloneWith(document.body, customizer);
54531 * console.log(el === document.body);
54533 * console.log(el.nodeName);
54535 * console.log(el.childNodes.length);
54540 function cloneWith(value, customizer) {
54541 customizer = typeof customizer == 'function' ? customizer : undefined$1;
54542 return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
54545 * This method is like `_.clone` except that it recursively clones `value`.
54551 * @param {*} value The value to recursively clone.
54552 * @returns {*} Returns the deep cloned value.
54556 * var objects = [{ 'a': 1 }, { 'b': 2 }];
54558 * var deep = _.cloneDeep(objects);
54559 * console.log(deep[0] === objects[0]);
54564 function cloneDeep(value) {
54565 return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
54568 * This method is like `_.cloneWith` except that it recursively clones `value`.
54574 * @param {*} value The value to recursively clone.
54575 * @param {Function} [customizer] The function to customize cloning.
54576 * @returns {*} Returns the deep cloned value.
54580 * function customizer(value) {
54581 * if (_.isElement(value)) {
54582 * return value.cloneNode(true);
54586 * var el = _.cloneDeepWith(document.body, customizer);
54588 * console.log(el === document.body);
54590 * console.log(el.nodeName);
54592 * console.log(el.childNodes.length);
54597 function cloneDeepWith(value, customizer) {
54598 customizer = typeof customizer == 'function' ? customizer : undefined$1;
54599 return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
54602 * Checks if `object` conforms to `source` by invoking the predicate
54603 * properties of `source` with the corresponding property values of `object`.
54605 * **Note:** This method is equivalent to `_.conforms` when `source` is
54606 * partially applied.
54612 * @param {Object} object The object to inspect.
54613 * @param {Object} source The object of property predicates to conform to.
54614 * @returns {boolean} Returns `true` if `object` conforms, else `false`.
54617 * var object = { 'a': 1, 'b': 2 };
54619 * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
54622 * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
54627 function conformsTo(object, source) {
54628 return source == null || baseConformsTo(object, source, keys(source));
54632 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
54633 * comparison between two values to determine if they are equivalent.
54639 * @param {*} value The value to compare.
54640 * @param {*} other The other value to compare.
54641 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
54644 * var object = { 'a': 1 };
54645 * var other = { 'a': 1 };
54647 * _.eq(object, object);
54650 * _.eq(object, other);
54656 * _.eq('a', Object('a'));
54664 function eq(value, other) {
54665 return value === other || value !== value && other !== other;
54668 * Checks if `value` is greater than `other`.
54674 * @param {*} value The value to compare.
54675 * @param {*} other The other value to compare.
54676 * @returns {boolean} Returns `true` if `value` is greater than `other`,
54692 var gt = createRelationalOperation(baseGt);
54694 * Checks if `value` is greater than or equal to `other`.
54700 * @param {*} value The value to compare.
54701 * @param {*} other The other value to compare.
54702 * @returns {boolean} Returns `true` if `value` is greater than or equal to
54703 * `other`, else `false`.
54717 var gte = createRelationalOperation(function (value, other) {
54718 return value >= other;
54721 * Checks if `value` is likely an `arguments` object.
54727 * @param {*} value The value to check.
54728 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
54732 * _.isArguments(function() { return arguments; }());
54735 * _.isArguments([1, 2, 3]);
54739 var isArguments = baseIsArguments(function () {
54741 }()) ? baseIsArguments : function (value) {
54742 return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
54745 * Checks if `value` is classified as an `Array` object.
54751 * @param {*} value The value to check.
54752 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
54755 * _.isArray([1, 2, 3]);
54758 * _.isArray(document.body.children);
54761 * _.isArray('abc');
54764 * _.isArray(_.noop);
54768 var isArray = Array.isArray;
54770 * Checks if `value` is classified as an `ArrayBuffer` object.
54776 * @param {*} value The value to check.
54777 * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
54780 * _.isArrayBuffer(new ArrayBuffer(2));
54783 * _.isArrayBuffer(new Array(2));
54787 var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
54789 * Checks if `value` is array-like. A value is considered array-like if it's
54790 * not a function and has a `value.length` that's an integer greater than or
54791 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
54797 * @param {*} value The value to check.
54798 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
54801 * _.isArrayLike([1, 2, 3]);
54804 * _.isArrayLike(document.body.children);
54807 * _.isArrayLike('abc');
54810 * _.isArrayLike(_.noop);
54814 function isArrayLike(value) {
54815 return value != null && isLength(value.length) && !isFunction(value);
54818 * This method is like `_.isArrayLike` except that it also checks if `value`
54825 * @param {*} value The value to check.
54826 * @returns {boolean} Returns `true` if `value` is an array-like object,
54830 * _.isArrayLikeObject([1, 2, 3]);
54833 * _.isArrayLikeObject(document.body.children);
54836 * _.isArrayLikeObject('abc');
54839 * _.isArrayLikeObject(_.noop);
54844 function isArrayLikeObject(value) {
54845 return isObjectLike(value) && isArrayLike(value);
54848 * Checks if `value` is classified as a boolean primitive or object.
54854 * @param {*} value The value to check.
54855 * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
54858 * _.isBoolean(false);
54861 * _.isBoolean(null);
54866 function isBoolean(value) {
54867 return value === true || value === false || isObjectLike(value) && baseGetTag(value) == boolTag;
54870 * Checks if `value` is a buffer.
54876 * @param {*} value The value to check.
54877 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
54880 * _.isBuffer(new Buffer(2));
54883 * _.isBuffer(new Uint8Array(2));
54888 var isBuffer = nativeIsBuffer || stubFalse;
54890 * Checks if `value` is classified as a `Date` object.
54896 * @param {*} value The value to check.
54897 * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
54900 * _.isDate(new Date);
54903 * _.isDate('Mon April 23 2012');
54907 var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
54909 * Checks if `value` is likely a DOM element.
54915 * @param {*} value The value to check.
54916 * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
54919 * _.isElement(document.body);
54922 * _.isElement('<body>');
54926 function isElement(value) {
54927 return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
54930 * Checks if `value` is an empty object, collection, map, or set.
54932 * Objects are considered empty if they have no own enumerable string keyed
54935 * Array-like values such as `arguments` objects, arrays, buffers, strings, or
54936 * jQuery-like collections are considered empty if they have a `length` of `0`.
54937 * Similarly, maps and sets are considered empty if they have a `size` of `0`.
54943 * @param {*} value The value to check.
54944 * @returns {boolean} Returns `true` if `value` is empty, else `false`.
54956 * _.isEmpty([1, 2, 3]);
54959 * _.isEmpty({ 'a': 1 });
54964 function isEmpty(value) {
54965 if (value == null) {
54969 if (isArrayLike(value) && (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || isBuffer(value) || isTypedArray(value) || isArguments(value))) {
54970 return !value.length;
54973 var tag = getTag(value);
54975 if (tag == mapTag || tag == setTag) {
54976 return !value.size;
54979 if (isPrototype(value)) {
54980 return !baseKeys(value).length;
54983 for (var key in value) {
54984 if (hasOwnProperty.call(value, key)) {
54992 * Performs a deep comparison between two values to determine if they are
54995 * **Note:** This method supports comparing arrays, array buffers, booleans,
54996 * date objects, error objects, maps, numbers, `Object` objects, regexes,
54997 * sets, strings, symbols, and typed arrays. `Object` objects are compared
54998 * by their own, not inherited, enumerable properties. Functions and DOM
54999 * nodes are compared by strict equality, i.e. `===`.
55005 * @param {*} value The value to compare.
55006 * @param {*} other The other value to compare.
55007 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
55010 * var object = { 'a': 1 };
55011 * var other = { 'a': 1 };
55013 * _.isEqual(object, other);
55016 * object === other;
55021 function isEqual(value, other) {
55022 return baseIsEqual(value, other);
55025 * This method is like `_.isEqual` except that it accepts `customizer` which
55026 * is invoked to compare values. If `customizer` returns `undefined`, comparisons
55027 * are handled by the method instead. The `customizer` is invoked with up to
55028 * six arguments: (objValue, othValue [, index|key, object, other, stack]).
55034 * @param {*} value The value to compare.
55035 * @param {*} other The other value to compare.
55036 * @param {Function} [customizer] The function to customize comparisons.
55037 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
55040 * function isGreeting(value) {
55041 * return /^h(?:i|ello)$/.test(value);
55044 * function customizer(objValue, othValue) {
55045 * if (isGreeting(objValue) && isGreeting(othValue)) {
55050 * var array = ['hello', 'goodbye'];
55051 * var other = ['hi', 'goodbye'];
55053 * _.isEqualWith(array, other, customizer);
55058 function isEqualWith(value, other, customizer) {
55059 customizer = typeof customizer == 'function' ? customizer : undefined$1;
55060 var result = customizer ? customizer(value, other) : undefined$1;
55061 return result === undefined$1 ? baseIsEqual(value, other, undefined$1, customizer) : !!result;
55064 * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
55065 * `SyntaxError`, `TypeError`, or `URIError` object.
55071 * @param {*} value The value to check.
55072 * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
55075 * _.isError(new Error);
55078 * _.isError(Error);
55083 function isError(value) {
55084 if (!isObjectLike(value)) {
55088 var tag = baseGetTag(value);
55089 return tag == errorTag || tag == domExcTag || typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value);
55092 * Checks if `value` is a finite primitive number.
55094 * **Note:** This method is based on
55095 * [`Number.isFinite`](https://mdn.io/Number/isFinite).
55101 * @param {*} value The value to check.
55102 * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
55108 * _.isFinite(Number.MIN_VALUE);
55111 * _.isFinite(Infinity);
55119 function isFinite(value) {
55120 return typeof value == 'number' && nativeIsFinite(value);
55123 * Checks if `value` is classified as a `Function` object.
55129 * @param {*} value The value to check.
55130 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
55136 * _.isFunction(/abc/);
55141 function isFunction(value) {
55142 if (!isObject(value)) {
55144 } // The use of `Object#toString` avoids issues with the `typeof` operator
55145 // in Safari 9 which returns 'object' for typed arrays and other constructors.
55148 var tag = baseGetTag(value);
55149 return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
55152 * Checks if `value` is an integer.
55154 * **Note:** This method is based on
55155 * [`Number.isInteger`](https://mdn.io/Number/isInteger).
55161 * @param {*} value The value to check.
55162 * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
55168 * _.isInteger(Number.MIN_VALUE);
55171 * _.isInteger(Infinity);
55174 * _.isInteger('3');
55179 function isInteger(value) {
55180 return typeof value == 'number' && value == toInteger(value);
55183 * Checks if `value` is a valid array-like length.
55185 * **Note:** This method is loosely based on
55186 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
55192 * @param {*} value The value to check.
55193 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
55199 * _.isLength(Number.MIN_VALUE);
55202 * _.isLength(Infinity);
55210 function isLength(value) {
55211 return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
55214 * Checks if `value` is the
55215 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
55216 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
55222 * @param {*} value The value to check.
55223 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
55229 * _.isObject([1, 2, 3]);
55232 * _.isObject(_.noop);
55235 * _.isObject(null);
55240 function isObject(value) {
55241 var type = _typeof(value);
55243 return value != null && (type == 'object' || type == 'function');
55246 * Checks if `value` is object-like. A value is object-like if it's not `null`
55247 * and has a `typeof` result of "object".
55253 * @param {*} value The value to check.
55254 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
55257 * _.isObjectLike({});
55260 * _.isObjectLike([1, 2, 3]);
55263 * _.isObjectLike(_.noop);
55266 * _.isObjectLike(null);
55271 function isObjectLike(value) {
55272 return value != null && _typeof(value) == 'object';
55275 * Checks if `value` is classified as a `Map` object.
55281 * @param {*} value The value to check.
55282 * @returns {boolean} Returns `true` if `value` is a map, else `false`.
55285 * _.isMap(new Map);
55288 * _.isMap(new WeakMap);
55293 var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
55295 * Performs a partial deep comparison between `object` and `source` to
55296 * determine if `object` contains equivalent property values.
55298 * **Note:** This method is equivalent to `_.matches` when `source` is
55299 * partially applied.
55301 * Partial comparisons will match empty array and empty object `source`
55302 * values against any array or object value, respectively. See `_.isEqual`
55303 * for a list of supported value comparisons.
55309 * @param {Object} object The object to inspect.
55310 * @param {Object} source The object of property values to match.
55311 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
55314 * var object = { 'a': 1, 'b': 2 };
55316 * _.isMatch(object, { 'b': 2 });
55319 * _.isMatch(object, { 'b': 1 });
55323 function isMatch(object, source) {
55324 return object === source || baseIsMatch(object, source, getMatchData(source));
55327 * This method is like `_.isMatch` except that it accepts `customizer` which
55328 * is invoked to compare values. If `customizer` returns `undefined`, comparisons
55329 * are handled by the method instead. The `customizer` is invoked with five
55330 * arguments: (objValue, srcValue, index|key, object, source).
55336 * @param {Object} object The object to inspect.
55337 * @param {Object} source The object of property values to match.
55338 * @param {Function} [customizer] The function to customize comparisons.
55339 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
55342 * function isGreeting(value) {
55343 * return /^h(?:i|ello)$/.test(value);
55346 * function customizer(objValue, srcValue) {
55347 * if (isGreeting(objValue) && isGreeting(srcValue)) {
55352 * var object = { 'greeting': 'hello' };
55353 * var source = { 'greeting': 'hi' };
55355 * _.isMatchWith(object, source, customizer);
55360 function isMatchWith(object, source, customizer) {
55361 customizer = typeof customizer == 'function' ? customizer : undefined$1;
55362 return baseIsMatch(object, source, getMatchData(source), customizer);
55365 * Checks if `value` is `NaN`.
55367 * **Note:** This method is based on
55368 * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
55369 * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
55370 * `undefined` and other non-number values.
55376 * @param {*} value The value to check.
55377 * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
55383 * _.isNaN(new Number(NaN));
55386 * isNaN(undefined);
55389 * _.isNaN(undefined);
55394 function isNaN(value) {
55395 // An `NaN` primitive is the only value that is not equal to itself.
55396 // Perform the `toStringTag` check first to avoid errors with some
55397 // ActiveX objects in IE.
55398 return isNumber(value) && value != +value;
55401 * Checks if `value` is a pristine native function.
55403 * **Note:** This method can't reliably detect native functions in the presence
55404 * of the core-js package because core-js circumvents this kind of detection.
55405 * Despite multiple requests, the core-js maintainer has made it clear: any
55406 * attempt to fix the detection will be obstructed. As a result, we're left
55407 * with little choice but to throw an error. Unfortunately, this also affects
55408 * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
55409 * which rely on core-js.
55415 * @param {*} value The value to check.
55416 * @returns {boolean} Returns `true` if `value` is a native function,
55420 * _.isNative(Array.prototype.push);
55428 function isNative(value) {
55429 if (isMaskable(value)) {
55430 throw new Error(CORE_ERROR_TEXT);
55433 return baseIsNative(value);
55436 * Checks if `value` is `null`.
55442 * @param {*} value The value to check.
55443 * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
55449 * _.isNull(void 0);
55454 function isNull(value) {
55455 return value === null;
55458 * Checks if `value` is `null` or `undefined`.
55464 * @param {*} value The value to check.
55465 * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
55479 function isNil(value) {
55480 return value == null;
55483 * Checks if `value` is classified as a `Number` primitive or object.
55485 * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
55486 * classified as numbers, use the `_.isFinite` method.
55492 * @param {*} value The value to check.
55493 * @returns {boolean} Returns `true` if `value` is a number, else `false`.
55499 * _.isNumber(Number.MIN_VALUE);
55502 * _.isNumber(Infinity);
55510 function isNumber(value) {
55511 return typeof value == 'number' || isObjectLike(value) && baseGetTag(value) == numberTag;
55514 * Checks if `value` is a plain object, that is, an object created by the
55515 * `Object` constructor or one with a `[[Prototype]]` of `null`.
55521 * @param {*} value The value to check.
55522 * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
55529 * _.isPlainObject(new Foo);
55532 * _.isPlainObject([1, 2, 3]);
55535 * _.isPlainObject({ 'x': 0, 'y': 0 });
55538 * _.isPlainObject(Object.create(null));
55543 function isPlainObject(value) {
55544 if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
55548 var proto = getPrototype(value);
55550 if (proto === null) {
55554 var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
55555 return typeof Ctor == 'function' && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
55558 * Checks if `value` is classified as a `RegExp` object.
55564 * @param {*} value The value to check.
55565 * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
55568 * _.isRegExp(/abc/);
55571 * _.isRegExp('/abc/');
55576 var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
55578 * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
55579 * double precision number which isn't the result of a rounded unsafe integer.
55581 * **Note:** This method is based on
55582 * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
55588 * @param {*} value The value to check.
55589 * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
55592 * _.isSafeInteger(3);
55595 * _.isSafeInteger(Number.MIN_VALUE);
55598 * _.isSafeInteger(Infinity);
55601 * _.isSafeInteger('3');
55605 function isSafeInteger(value) {
55606 return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
55609 * Checks if `value` is classified as a `Set` object.
55615 * @param {*} value The value to check.
55616 * @returns {boolean} Returns `true` if `value` is a set, else `false`.
55619 * _.isSet(new Set);
55622 * _.isSet(new WeakSet);
55627 var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
55629 * Checks if `value` is classified as a `String` primitive or object.
55635 * @param {*} value The value to check.
55636 * @returns {boolean} Returns `true` if `value` is a string, else `false`.
55639 * _.isString('abc');
55646 function isString(value) {
55647 return typeof value == 'string' || !isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag;
55650 * Checks if `value` is classified as a `Symbol` primitive or object.
55656 * @param {*} value The value to check.
55657 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
55660 * _.isSymbol(Symbol.iterator);
55663 * _.isSymbol('abc');
55668 function isSymbol(value) {
55669 return _typeof(value) == 'symbol' || isObjectLike(value) && baseGetTag(value) == symbolTag;
55672 * Checks if `value` is classified as a typed array.
55678 * @param {*} value The value to check.
55679 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
55682 * _.isTypedArray(new Uint8Array);
55685 * _.isTypedArray([]);
55690 var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
55692 * Checks if `value` is `undefined`.
55698 * @param {*} value The value to check.
55699 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
55702 * _.isUndefined(void 0);
55705 * _.isUndefined(null);
55709 function isUndefined(value) {
55710 return value === undefined$1;
55713 * Checks if `value` is classified as a `WeakMap` object.
55719 * @param {*} value The value to check.
55720 * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
55723 * _.isWeakMap(new WeakMap);
55726 * _.isWeakMap(new Map);
55731 function isWeakMap(value) {
55732 return isObjectLike(value) && getTag(value) == weakMapTag;
55735 * Checks if `value` is classified as a `WeakSet` object.
55741 * @param {*} value The value to check.
55742 * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
55745 * _.isWeakSet(new WeakSet);
55748 * _.isWeakSet(new Set);
55753 function isWeakSet(value) {
55754 return isObjectLike(value) && baseGetTag(value) == weakSetTag;
55757 * Checks if `value` is less than `other`.
55763 * @param {*} value The value to compare.
55764 * @param {*} other The other value to compare.
55765 * @returns {boolean} Returns `true` if `value` is less than `other`,
55781 var lt = createRelationalOperation(baseLt);
55783 * Checks if `value` is less than or equal to `other`.
55789 * @param {*} value The value to compare.
55790 * @param {*} other The other value to compare.
55791 * @returns {boolean} Returns `true` if `value` is less than or equal to
55792 * `other`, else `false`.
55806 var lte = createRelationalOperation(function (value, other) {
55807 return value <= other;
55810 * Converts `value` to an array.
55816 * @param {*} value The value to convert.
55817 * @returns {Array} Returns the converted array.
55820 * _.toArray({ 'a': 1, 'b': 2 });
55823 * _.toArray('abc');
55824 * // => ['a', 'b', 'c']
55833 function toArray(value) {
55838 if (isArrayLike(value)) {
55839 return isString(value) ? stringToArray(value) : copyArray(value);
55842 if (symIterator && value[symIterator]) {
55843 return iteratorToArray(value[symIterator]());
55846 var tag = getTag(value),
55847 func = tag == mapTag ? mapToArray : tag == setTag ? setToArray : values;
55848 return func(value);
55851 * Converts `value` to a finite number.
55857 * @param {*} value The value to convert.
55858 * @returns {number} Returns the converted number.
55864 * _.toFinite(Number.MIN_VALUE);
55867 * _.toFinite(Infinity);
55868 * // => 1.7976931348623157e+308
55870 * _.toFinite('3.2');
55875 function toFinite(value) {
55877 return value === 0 ? value : 0;
55880 value = toNumber(value);
55882 if (value === INFINITY || value === -INFINITY) {
55883 var sign = value < 0 ? -1 : 1;
55884 return sign * MAX_INTEGER;
55887 return value === value ? value : 0;
55890 * Converts `value` to an integer.
55892 * **Note:** This method is loosely based on
55893 * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
55899 * @param {*} value The value to convert.
55900 * @returns {number} Returns the converted integer.
55903 * _.toInteger(3.2);
55906 * _.toInteger(Number.MIN_VALUE);
55909 * _.toInteger(Infinity);
55910 * // => 1.7976931348623157e+308
55912 * _.toInteger('3.2');
55917 function toInteger(value) {
55918 var result = toFinite(value),
55919 remainder = result % 1;
55920 return result === result ? remainder ? result - remainder : result : 0;
55923 * Converts `value` to an integer suitable for use as the length of an
55924 * array-like object.
55926 * **Note:** This method is based on
55927 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
55933 * @param {*} value The value to convert.
55934 * @returns {number} Returns the converted integer.
55940 * _.toLength(Number.MIN_VALUE);
55943 * _.toLength(Infinity);
55946 * _.toLength('3.2');
55951 function toLength(value) {
55952 return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
55955 * Converts `value` to a number.
55961 * @param {*} value The value to process.
55962 * @returns {number} Returns the number.
55968 * _.toNumber(Number.MIN_VALUE);
55971 * _.toNumber(Infinity);
55974 * _.toNumber('3.2');
55979 function toNumber(value) {
55980 if (typeof value == 'number') {
55984 if (isSymbol(value)) {
55988 if (isObject(value)) {
55989 var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
55990 value = isObject(other) ? other + '' : other;
55993 if (typeof value != 'string') {
55994 return value === 0 ? value : +value;
55997 value = baseTrim(value);
55998 var isBinary = reIsBinary.test(value);
55999 return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
56002 * Converts `value` to a plain object flattening inherited enumerable string
56003 * keyed properties of `value` to own properties of the plain object.
56009 * @param {*} value The value to convert.
56010 * @returns {Object} Returns the converted plain object.
56017 * Foo.prototype.c = 3;
56019 * _.assign({ 'a': 1 }, new Foo);
56020 * // => { 'a': 1, 'b': 2 }
56022 * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
56023 * // => { 'a': 1, 'b': 2, 'c': 3 }
56027 function toPlainObject(value) {
56028 return copyObject(value, keysIn(value));
56031 * Converts `value` to a safe integer. A safe integer can be compared and
56032 * represented correctly.
56038 * @param {*} value The value to convert.
56039 * @returns {number} Returns the converted integer.
56042 * _.toSafeInteger(3.2);
56045 * _.toSafeInteger(Number.MIN_VALUE);
56048 * _.toSafeInteger(Infinity);
56049 * // => 9007199254740991
56051 * _.toSafeInteger('3.2');
56056 function toSafeInteger(value) {
56057 return value ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) : value === 0 ? value : 0;
56060 * Converts `value` to a string. An empty string is returned for `null`
56061 * and `undefined` values. The sign of `-0` is preserved.
56067 * @param {*} value The value to convert.
56068 * @returns {string} Returns the converted string.
56071 * _.toString(null);
56077 * _.toString([1, 2, 3]);
56082 function toString(value) {
56083 return value == null ? '' : baseToString(value);
56085 /*------------------------------------------------------------------------*/
56088 * Assigns own enumerable string keyed properties of source objects to the
56089 * destination object. Source objects are applied from left to right.
56090 * Subsequent sources overwrite property assignments of previous sources.
56092 * **Note:** This method mutates `object` and is loosely based on
56093 * [`Object.assign`](https://mdn.io/Object/assign).
56099 * @param {Object} object The destination object.
56100 * @param {...Object} [sources] The source objects.
56101 * @returns {Object} Returns `object`.
56113 * Foo.prototype.b = 2;
56114 * Bar.prototype.d = 4;
56116 * _.assign({ 'a': 0 }, new Foo, new Bar);
56117 * // => { 'a': 1, 'c': 3 }
56121 var assign = createAssigner(function (object, source) {
56122 if (isPrototype(source) || isArrayLike(source)) {
56123 copyObject(source, keys(source), object);
56127 for (var key in source) {
56128 if (hasOwnProperty.call(source, key)) {
56129 assignValue(object, key, source[key]);
56134 * This method is like `_.assign` except that it iterates over own and
56135 * inherited source properties.
56137 * **Note:** This method mutates `object`.
56144 * @param {Object} object The destination object.
56145 * @param {...Object} [sources] The source objects.
56146 * @returns {Object} Returns `object`.
56158 * Foo.prototype.b = 2;
56159 * Bar.prototype.d = 4;
56161 * _.assignIn({ 'a': 0 }, new Foo, new Bar);
56162 * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
56165 var assignIn = createAssigner(function (object, source) {
56166 copyObject(source, keysIn(source), object);
56169 * This method is like `_.assignIn` except that it accepts `customizer`
56170 * which is invoked to produce the assigned values. If `customizer` returns
56171 * `undefined`, assignment is handled by the method instead. The `customizer`
56172 * is invoked with five arguments: (objValue, srcValue, key, object, source).
56174 * **Note:** This method mutates `object`.
56179 * @alias extendWith
56181 * @param {Object} object The destination object.
56182 * @param {...Object} sources The source objects.
56183 * @param {Function} [customizer] The function to customize assigned values.
56184 * @returns {Object} Returns `object`.
56185 * @see _.assignWith
56188 * function customizer(objValue, srcValue) {
56189 * return _.isUndefined(objValue) ? srcValue : objValue;
56192 * var defaults = _.partialRight(_.assignInWith, customizer);
56194 * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
56195 * // => { 'a': 1, 'b': 2 }
56198 var assignInWith = createAssigner(function (object, source, srcIndex, customizer) {
56199 copyObject(source, keysIn(source), object, customizer);
56202 * This method is like `_.assign` except that it accepts `customizer`
56203 * which is invoked to produce the assigned values. If `customizer` returns
56204 * `undefined`, assignment is handled by the method instead. The `customizer`
56205 * is invoked with five arguments: (objValue, srcValue, key, object, source).
56207 * **Note:** This method mutates `object`.
56213 * @param {Object} object The destination object.
56214 * @param {...Object} sources The source objects.
56215 * @param {Function} [customizer] The function to customize assigned values.
56216 * @returns {Object} Returns `object`.
56217 * @see _.assignInWith
56220 * function customizer(objValue, srcValue) {
56221 * return _.isUndefined(objValue) ? srcValue : objValue;
56224 * var defaults = _.partialRight(_.assignWith, customizer);
56226 * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
56227 * // => { 'a': 1, 'b': 2 }
56230 var assignWith = createAssigner(function (object, source, srcIndex, customizer) {
56231 copyObject(source, keys(source), object, customizer);
56234 * Creates an array of values corresponding to `paths` of `object`.
56240 * @param {Object} object The object to iterate over.
56241 * @param {...(string|string[])} [paths] The property paths to pick.
56242 * @returns {Array} Returns the picked values.
56245 * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
56247 * _.at(object, ['a[0].b.c', 'a[1]']);
56251 var at = flatRest(baseAt);
56253 * Creates an object that inherits from the `prototype` object. If a
56254 * `properties` object is given, its own enumerable string keyed properties
56255 * are assigned to the created object.
56261 * @param {Object} prototype The object to inherit from.
56262 * @param {Object} [properties] The properties to assign to the object.
56263 * @returns {Object} Returns the new object.
56266 * function Shape() {
56271 * function Circle() {
56272 * Shape.call(this);
56275 * Circle.prototype = _.create(Shape.prototype, {
56276 * 'constructor': Circle
56279 * var circle = new Circle;
56280 * circle instanceof Circle;
56283 * circle instanceof Shape;
56287 function create(prototype, properties) {
56288 var result = baseCreate(prototype);
56289 return properties == null ? result : baseAssign(result, properties);
56292 * Assigns own and inherited enumerable string keyed properties of source
56293 * objects to the destination object for all destination properties that
56294 * resolve to `undefined`. Source objects are applied from left to right.
56295 * Once a property is set, additional values of the same property are ignored.
56297 * **Note:** This method mutates `object`.
56303 * @param {Object} object The destination object.
56304 * @param {...Object} [sources] The source objects.
56305 * @returns {Object} Returns `object`.
56306 * @see _.defaultsDeep
56309 * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
56310 * // => { 'a': 1, 'b': 2 }
56314 var defaults = baseRest(function (object, sources) {
56315 object = Object(object);
56317 var length = sources.length;
56318 var guard = length > 2 ? sources[2] : undefined$1;
56320 if (guard && isIterateeCall(sources[0], sources[1], guard)) {
56324 while (++index < length) {
56325 var source = sources[index];
56326 var props = keysIn(source);
56327 var propsIndex = -1;
56328 var propsLength = props.length;
56330 while (++propsIndex < propsLength) {
56331 var key = props[propsIndex];
56332 var value = object[key];
56334 if (value === undefined$1 || eq(value, objectProto[key]) && !hasOwnProperty.call(object, key)) {
56335 object[key] = source[key];
56343 * This method is like `_.defaults` except that it recursively assigns
56344 * default properties.
56346 * **Note:** This method mutates `object`.
56352 * @param {Object} object The destination object.
56353 * @param {...Object} [sources] The source objects.
56354 * @returns {Object} Returns `object`.
56358 * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
56359 * // => { 'a': { 'b': 2, 'c': 3 } }
56362 var defaultsDeep = baseRest(function (args) {
56363 args.push(undefined$1, customDefaultsMerge);
56364 return apply(mergeWith, undefined$1, args);
56367 * This method is like `_.find` except that it returns the key of the first
56368 * element `predicate` returns truthy for instead of the element itself.
56374 * @param {Object} object The object to inspect.
56375 * @param {Function} [predicate=_.identity] The function invoked per iteration.
56376 * @returns {string|undefined} Returns the key of the matched element,
56377 * else `undefined`.
56381 * 'barney': { 'age': 36, 'active': true },
56382 * 'fred': { 'age': 40, 'active': false },
56383 * 'pebbles': { 'age': 1, 'active': true }
56386 * _.findKey(users, function(o) { return o.age < 40; });
56387 * // => 'barney' (iteration order is not guaranteed)
56389 * // The `_.matches` iteratee shorthand.
56390 * _.findKey(users, { 'age': 1, 'active': true });
56393 * // The `_.matchesProperty` iteratee shorthand.
56394 * _.findKey(users, ['active', false]);
56397 * // The `_.property` iteratee shorthand.
56398 * _.findKey(users, 'active');
56402 function findKey(object, predicate) {
56403 return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
56406 * This method is like `_.findKey` except that it iterates over elements of
56407 * a collection in the opposite order.
56413 * @param {Object} object The object to inspect.
56414 * @param {Function} [predicate=_.identity] The function invoked per iteration.
56415 * @returns {string|undefined} Returns the key of the matched element,
56416 * else `undefined`.
56420 * 'barney': { 'age': 36, 'active': true },
56421 * 'fred': { 'age': 40, 'active': false },
56422 * 'pebbles': { 'age': 1, 'active': true }
56425 * _.findLastKey(users, function(o) { return o.age < 40; });
56426 * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
56428 * // The `_.matches` iteratee shorthand.
56429 * _.findLastKey(users, { 'age': 36, 'active': true });
56432 * // The `_.matchesProperty` iteratee shorthand.
56433 * _.findLastKey(users, ['active', false]);
56436 * // The `_.property` iteratee shorthand.
56437 * _.findLastKey(users, 'active');
56442 function findLastKey(object, predicate) {
56443 return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
56446 * Iterates over own and inherited enumerable string keyed properties of an
56447 * object and invokes `iteratee` for each property. The iteratee is invoked
56448 * with three arguments: (value, key, object). Iteratee functions may exit
56449 * iteration early by explicitly returning `false`.
56455 * @param {Object} object The object to iterate over.
56456 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56457 * @returns {Object} Returns `object`.
56458 * @see _.forInRight
56466 * Foo.prototype.c = 3;
56468 * _.forIn(new Foo, function(value, key) {
56469 * console.log(key);
56471 * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
56475 function forIn(object, iteratee) {
56476 return object == null ? object : baseFor(object, getIteratee(iteratee, 3), keysIn);
56479 * This method is like `_.forIn` except that it iterates over properties of
56480 * `object` in the opposite order.
56486 * @param {Object} object The object to iterate over.
56487 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56488 * @returns {Object} Returns `object`.
56497 * Foo.prototype.c = 3;
56499 * _.forInRight(new Foo, function(value, key) {
56500 * console.log(key);
56502 * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
56506 function forInRight(object, iteratee) {
56507 return object == null ? object : baseForRight(object, getIteratee(iteratee, 3), keysIn);
56510 * Iterates over own enumerable string keyed properties of an object and
56511 * invokes `iteratee` for each property. The iteratee is invoked with three
56512 * arguments: (value, key, object). Iteratee functions may exit iteration
56513 * early by explicitly returning `false`.
56519 * @param {Object} object The object to iterate over.
56520 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56521 * @returns {Object} Returns `object`.
56522 * @see _.forOwnRight
56530 * Foo.prototype.c = 3;
56532 * _.forOwn(new Foo, function(value, key) {
56533 * console.log(key);
56535 * // => Logs 'a' then 'b' (iteration order is not guaranteed).
56539 function forOwn(object, iteratee) {
56540 return object && baseForOwn(object, getIteratee(iteratee, 3));
56543 * This method is like `_.forOwn` except that it iterates over properties of
56544 * `object` in the opposite order.
56550 * @param {Object} object The object to iterate over.
56551 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56552 * @returns {Object} Returns `object`.
56561 * Foo.prototype.c = 3;
56563 * _.forOwnRight(new Foo, function(value, key) {
56564 * console.log(key);
56566 * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
56570 function forOwnRight(object, iteratee) {
56571 return object && baseForOwnRight(object, getIteratee(iteratee, 3));
56574 * Creates an array of function property names from own enumerable properties
56581 * @param {Object} object The object to inspect.
56582 * @returns {Array} Returns the function names.
56583 * @see _.functionsIn
56587 * this.a = _.constant('a');
56588 * this.b = _.constant('b');
56591 * Foo.prototype.c = _.constant('c');
56593 * _.functions(new Foo);
56598 function functions(object) {
56599 return object == null ? [] : baseFunctions(object, keys(object));
56602 * Creates an array of function property names from own and inherited
56603 * enumerable properties of `object`.
56609 * @param {Object} object The object to inspect.
56610 * @returns {Array} Returns the function names.
56615 * this.a = _.constant('a');
56616 * this.b = _.constant('b');
56619 * Foo.prototype.c = _.constant('c');
56621 * _.functionsIn(new Foo);
56622 * // => ['a', 'b', 'c']
56626 function functionsIn(object) {
56627 return object == null ? [] : baseFunctions(object, keysIn(object));
56630 * Gets the value at `path` of `object`. If the resolved value is
56631 * `undefined`, the `defaultValue` is returned in its place.
56637 * @param {Object} object The object to query.
56638 * @param {Array|string} path The path of the property to get.
56639 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
56640 * @returns {*} Returns the resolved value.
56643 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
56645 * _.get(object, 'a[0].b.c');
56648 * _.get(object, ['a', '0', 'b', 'c']);
56651 * _.get(object, 'a.b.c', 'default');
56656 function get(object, path, defaultValue) {
56657 var result = object == null ? undefined$1 : baseGet(object, path);
56658 return result === undefined$1 ? defaultValue : result;
56661 * Checks if `path` is a direct property of `object`.
56667 * @param {Object} object The object to query.
56668 * @param {Array|string} path The path to check.
56669 * @returns {boolean} Returns `true` if `path` exists, else `false`.
56672 * var object = { 'a': { 'b': 2 } };
56673 * var other = _.create({ 'a': _.create({ 'b': 2 }) });
56675 * _.has(object, 'a');
56678 * _.has(object, 'a.b');
56681 * _.has(object, ['a', 'b']);
56684 * _.has(other, 'a');
56689 function has(object, path) {
56690 return object != null && hasPath(object, path, baseHas);
56693 * Checks if `path` is a direct or inherited property of `object`.
56699 * @param {Object} object The object to query.
56700 * @param {Array|string} path The path to check.
56701 * @returns {boolean} Returns `true` if `path` exists, else `false`.
56704 * var object = _.create({ 'a': _.create({ 'b': 2 }) });
56706 * _.hasIn(object, 'a');
56709 * _.hasIn(object, 'a.b');
56712 * _.hasIn(object, ['a', 'b']);
56715 * _.hasIn(object, 'b');
56720 function hasIn(object, path) {
56721 return object != null && hasPath(object, path, baseHasIn);
56724 * Creates an object composed of the inverted keys and values of `object`.
56725 * If `object` contains duplicate values, subsequent values overwrite
56726 * property assignments of previous values.
56732 * @param {Object} object The object to invert.
56733 * @returns {Object} Returns the new inverted object.
56736 * var object = { 'a': 1, 'b': 2, 'c': 1 };
56738 * _.invert(object);
56739 * // => { '1': 'c', '2': 'b' }
56743 var invert = createInverter(function (result, value, key) {
56744 if (value != null && typeof value.toString != 'function') {
56745 value = nativeObjectToString.call(value);
56748 result[value] = key;
56749 }, constant(identity));
56751 * This method is like `_.invert` except that the inverted object is generated
56752 * from the results of running each element of `object` thru `iteratee`. The
56753 * corresponding inverted value of each inverted key is an array of keys
56754 * responsible for generating the inverted value. The iteratee is invoked
56755 * with one argument: (value).
56761 * @param {Object} object The object to invert.
56762 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
56763 * @returns {Object} Returns the new inverted object.
56766 * var object = { 'a': 1, 'b': 2, 'c': 1 };
56768 * _.invertBy(object);
56769 * // => { '1': ['a', 'c'], '2': ['b'] }
56771 * _.invertBy(object, function(value) {
56772 * return 'group' + value;
56774 * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
56777 var invertBy = createInverter(function (result, value, key) {
56778 if (value != null && typeof value.toString != 'function') {
56779 value = nativeObjectToString.call(value);
56782 if (hasOwnProperty.call(result, value)) {
56783 result[value].push(key);
56785 result[value] = [key];
56789 * Invokes the method at `path` of `object`.
56795 * @param {Object} object The object to query.
56796 * @param {Array|string} path The path of the method to invoke.
56797 * @param {...*} [args] The arguments to invoke the method with.
56798 * @returns {*} Returns the result of the invoked method.
56801 * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
56803 * _.invoke(object, 'a[0].b.c.slice', 1, 3);
56807 var invoke = baseRest(baseInvoke);
56809 * Creates an array of the own enumerable property names of `object`.
56811 * **Note:** Non-object values are coerced to objects. See the
56812 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
56813 * for more details.
56819 * @param {Object} object The object to query.
56820 * @returns {Array} Returns the array of property names.
56828 * Foo.prototype.c = 3;
56831 * // => ['a', 'b'] (iteration order is not guaranteed)
56837 function keys(object) {
56838 return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
56841 * Creates an array of the own and inherited enumerable property names of `object`.
56843 * **Note:** Non-object values are coerced to objects.
56849 * @param {Object} object The object to query.
56850 * @returns {Array} Returns the array of property names.
56858 * Foo.prototype.c = 3;
56860 * _.keysIn(new Foo);
56861 * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
56865 function keysIn(object) {
56866 return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
56869 * The opposite of `_.mapValues`; this method creates an object with the
56870 * same values as `object` and keys generated by running each own enumerable
56871 * string keyed property of `object` thru `iteratee`. The iteratee is invoked
56872 * with three arguments: (value, key, object).
56878 * @param {Object} object The object to iterate over.
56879 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56880 * @returns {Object} Returns the new mapped object.
56884 * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
56885 * return key + value;
56887 * // => { 'a1': 1, 'b2': 2 }
56891 function mapKeys(object, iteratee) {
56893 iteratee = getIteratee(iteratee, 3);
56894 baseForOwn(object, function (value, key, object) {
56895 baseAssignValue(result, iteratee(value, key, object), value);
56900 * Creates an object with the same keys as `object` and values generated
56901 * by running each own enumerable string keyed property of `object` thru
56902 * `iteratee`. The iteratee is invoked with three arguments:
56903 * (value, key, object).
56909 * @param {Object} object The object to iterate over.
56910 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56911 * @returns {Object} Returns the new mapped object.
56916 * 'fred': { 'user': 'fred', 'age': 40 },
56917 * 'pebbles': { 'user': 'pebbles', 'age': 1 }
56920 * _.mapValues(users, function(o) { return o.age; });
56921 * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
56923 * // The `_.property` iteratee shorthand.
56924 * _.mapValues(users, 'age');
56925 * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
56929 function mapValues(object, iteratee) {
56931 iteratee = getIteratee(iteratee, 3);
56932 baseForOwn(object, function (value, key, object) {
56933 baseAssignValue(result, key, iteratee(value, key, object));
56938 * This method is like `_.assign` except that it recursively merges own and
56939 * inherited enumerable string keyed properties of source objects into the
56940 * destination object. Source properties that resolve to `undefined` are
56941 * skipped if a destination value exists. Array and plain object properties
56942 * are merged recursively. Other objects and value types are overridden by
56943 * assignment. Source objects are applied from left to right. Subsequent
56944 * sources overwrite property assignments of previous sources.
56946 * **Note:** This method mutates `object`.
56952 * @param {Object} object The destination object.
56953 * @param {...Object} [sources] The source objects.
56954 * @returns {Object} Returns `object`.
56958 * 'a': [{ 'b': 2 }, { 'd': 4 }]
56962 * 'a': [{ 'c': 3 }, { 'e': 5 }]
56965 * _.merge(object, other);
56966 * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
56970 var merge = createAssigner(function (object, source, srcIndex) {
56971 baseMerge(object, source, srcIndex);
56974 * This method is like `_.merge` except that it accepts `customizer` which
56975 * is invoked to produce the merged values of the destination and source
56976 * properties. If `customizer` returns `undefined`, merging is handled by the
56977 * method instead. The `customizer` is invoked with six arguments:
56978 * (objValue, srcValue, key, object, source, stack).
56980 * **Note:** This method mutates `object`.
56986 * @param {Object} object The destination object.
56987 * @param {...Object} sources The source objects.
56988 * @param {Function} customizer The function to customize assigned values.
56989 * @returns {Object} Returns `object`.
56992 * function customizer(objValue, srcValue) {
56993 * if (_.isArray(objValue)) {
56994 * return objValue.concat(srcValue);
56998 * var object = { 'a': [1], 'b': [2] };
56999 * var other = { 'a': [3], 'b': [4] };
57001 * _.mergeWith(object, other, customizer);
57002 * // => { 'a': [1, 3], 'b': [2, 4] }
57005 var mergeWith = createAssigner(function (object, source, srcIndex, customizer) {
57006 baseMerge(object, source, srcIndex, customizer);
57009 * The opposite of `_.pick`; this method creates an object composed of the
57010 * own and inherited enumerable property paths of `object` that are not omitted.
57012 * **Note:** This method is considerably slower than `_.pick`.
57018 * @param {Object} object The source object.
57019 * @param {...(string|string[])} [paths] The property paths to omit.
57020 * @returns {Object} Returns the new object.
57023 * var object = { 'a': 1, 'b': '2', 'c': 3 };
57025 * _.omit(object, ['a', 'c']);
57026 * // => { 'b': '2' }
57029 var omit = flatRest(function (object, paths) {
57032 if (object == null) {
57036 var isDeep = false;
57037 paths = arrayMap(paths, function (path) {
57038 path = castPath(path, object);
57039 isDeep || (isDeep = path.length > 1);
57042 copyObject(object, getAllKeysIn(object), result);
57045 result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
57048 var length = paths.length;
57051 baseUnset(result, paths[length]);
57057 * The opposite of `_.pickBy`; this method creates an object composed of
57058 * the own and inherited enumerable string keyed properties of `object` that
57059 * `predicate` doesn't return truthy for. The predicate is invoked with two
57060 * arguments: (value, key).
57066 * @param {Object} object The source object.
57067 * @param {Function} [predicate=_.identity] The function invoked per property.
57068 * @returns {Object} Returns the new object.
57071 * var object = { 'a': 1, 'b': '2', 'c': 3 };
57073 * _.omitBy(object, _.isNumber);
57074 * // => { 'b': '2' }
57077 function omitBy(object, predicate) {
57078 return pickBy(object, negate(getIteratee(predicate)));
57081 * Creates an object composed of the picked `object` properties.
57087 * @param {Object} object The source object.
57088 * @param {...(string|string[])} [paths] The property paths to pick.
57089 * @returns {Object} Returns the new object.
57092 * var object = { 'a': 1, 'b': '2', 'c': 3 };
57094 * _.pick(object, ['a', 'c']);
57095 * // => { 'a': 1, 'c': 3 }
57099 var pick = flatRest(function (object, paths) {
57100 return object == null ? {} : basePick(object, paths);
57103 * Creates an object composed of the `object` properties `predicate` returns
57104 * truthy for. The predicate is invoked with two arguments: (value, key).
57110 * @param {Object} object The source object.
57111 * @param {Function} [predicate=_.identity] The function invoked per property.
57112 * @returns {Object} Returns the new object.
57115 * var object = { 'a': 1, 'b': '2', 'c': 3 };
57117 * _.pickBy(object, _.isNumber);
57118 * // => { 'a': 1, 'c': 3 }
57121 function pickBy(object, predicate) {
57122 if (object == null) {
57126 var props = arrayMap(getAllKeysIn(object), function (prop) {
57129 predicate = getIteratee(predicate);
57130 return basePickBy(object, props, function (value, path) {
57131 return predicate(value, path[0]);
57135 * This method is like `_.get` except that if the resolved value is a
57136 * function it's invoked with the `this` binding of its parent object and
57137 * its result is returned.
57143 * @param {Object} object The object to query.
57144 * @param {Array|string} path The path of the property to resolve.
57145 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
57146 * @returns {*} Returns the resolved value.
57149 * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
57151 * _.result(object, 'a[0].b.c1');
57154 * _.result(object, 'a[0].b.c2');
57157 * _.result(object, 'a[0].b.c3', 'default');
57160 * _.result(object, 'a[0].b.c3', _.constant('default'));
57165 function result(object, path, defaultValue) {
57166 path = castPath(path, object);
57168 length = path.length; // Ensure the loop is entered when path is empty.
57172 object = undefined$1;
57175 while (++index < length) {
57176 var value = object == null ? undefined$1 : object[toKey(path[index])];
57178 if (value === undefined$1) {
57180 value = defaultValue;
57183 object = isFunction(value) ? value.call(object) : value;
57189 * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
57190 * it's created. Arrays are created for missing index properties while objects
57191 * are created for all other missing properties. Use `_.setWith` to customize
57194 * **Note:** This method mutates `object`.
57200 * @param {Object} object The object to modify.
57201 * @param {Array|string} path The path of the property to set.
57202 * @param {*} value The value to set.
57203 * @returns {Object} Returns `object`.
57206 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
57208 * _.set(object, 'a[0].b.c', 4);
57209 * console.log(object.a[0].b.c);
57212 * _.set(object, ['x', '0', 'y', 'z'], 5);
57213 * console.log(object.x[0].y.z);
57218 function set(object, path, value) {
57219 return object == null ? object : baseSet(object, path, value);
57222 * This method is like `_.set` except that it accepts `customizer` which is
57223 * invoked to produce the objects of `path`. If `customizer` returns `undefined`
57224 * path creation is handled by the method instead. The `customizer` is invoked
57225 * with three arguments: (nsValue, key, nsObject).
57227 * **Note:** This method mutates `object`.
57233 * @param {Object} object The object to modify.
57234 * @param {Array|string} path The path of the property to set.
57235 * @param {*} value The value to set.
57236 * @param {Function} [customizer] The function to customize assigned values.
57237 * @returns {Object} Returns `object`.
57242 * _.setWith(object, '[0][1]', 'a', Object);
57243 * // => { '0': { '1': 'a' } }
57247 function setWith(object, path, value, customizer) {
57248 customizer = typeof customizer == 'function' ? customizer : undefined$1;
57249 return object == null ? object : baseSet(object, path, value, customizer);
57252 * Creates an array of own enumerable string keyed-value pairs for `object`
57253 * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
57254 * entries are returned.
57261 * @param {Object} object The object to query.
57262 * @returns {Array} Returns the key-value pairs.
57270 * Foo.prototype.c = 3;
57272 * _.toPairs(new Foo);
57273 * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
57277 var toPairs = createToPairs(keys);
57279 * Creates an array of own and inherited enumerable string keyed-value pairs
57280 * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
57281 * or set, its entries are returned.
57288 * @param {Object} object The object to query.
57289 * @returns {Array} Returns the key-value pairs.
57297 * Foo.prototype.c = 3;
57299 * _.toPairsIn(new Foo);
57300 * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
57303 var toPairsIn = createToPairs(keysIn);
57305 * An alternative to `_.reduce`; this method transforms `object` to a new
57306 * `accumulator` object which is the result of running each of its own
57307 * enumerable string keyed properties thru `iteratee`, with each invocation
57308 * potentially mutating the `accumulator` object. If `accumulator` is not
57309 * provided, a new object with the same `[[Prototype]]` will be used. The
57310 * iteratee is invoked with four arguments: (accumulator, value, key, object).
57311 * Iteratee functions may exit iteration early by explicitly returning `false`.
57317 * @param {Object} object The object to iterate over.
57318 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
57319 * @param {*} [accumulator] The custom accumulator value.
57320 * @returns {*} Returns the accumulated value.
57323 * _.transform([2, 3, 4], function(result, n) {
57324 * result.push(n *= n);
57325 * return n % 2 == 0;
57329 * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
57330 * (result[value] || (result[value] = [])).push(key);
57332 * // => { '1': ['a', 'c'], '2': ['b'] }
57335 function transform(object, iteratee, accumulator) {
57336 var isArr = isArray(object),
57337 isArrLike = isArr || isBuffer(object) || isTypedArray(object);
57338 iteratee = getIteratee(iteratee, 4);
57340 if (accumulator == null) {
57341 var Ctor = object && object.constructor;
57344 accumulator = isArr ? new Ctor() : [];
57345 } else if (isObject(object)) {
57346 accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
57352 (isArrLike ? arrayEach : baseForOwn)(object, function (value, index, object) {
57353 return iteratee(accumulator, value, index, object);
57355 return accumulator;
57358 * Removes the property at `path` of `object`.
57360 * **Note:** This method mutates `object`.
57366 * @param {Object} object The object to modify.
57367 * @param {Array|string} path The path of the property to unset.
57368 * @returns {boolean} Returns `true` if the property is deleted, else `false`.
57371 * var object = { 'a': [{ 'b': { 'c': 7 } }] };
57372 * _.unset(object, 'a[0].b.c');
57375 * console.log(object);
57376 * // => { 'a': [{ 'b': {} }] };
57378 * _.unset(object, ['a', '0', 'b', 'c']);
57381 * console.log(object);
57382 * // => { 'a': [{ 'b': {} }] };
57386 function unset(object, path) {
57387 return object == null ? true : baseUnset(object, path);
57390 * This method is like `_.set` except that accepts `updater` to produce the
57391 * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
57392 * is invoked with one argument: (value).
57394 * **Note:** This method mutates `object`.
57400 * @param {Object} object The object to modify.
57401 * @param {Array|string} path The path of the property to set.
57402 * @param {Function} updater The function to produce the updated value.
57403 * @returns {Object} Returns `object`.
57406 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
57408 * _.update(object, 'a[0].b.c', function(n) { return n * n; });
57409 * console.log(object.a[0].b.c);
57412 * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
57413 * console.log(object.x[0].y.z);
57418 function update(object, path, updater) {
57419 return object == null ? object : baseUpdate(object, path, castFunction(updater));
57422 * This method is like `_.update` except that it accepts `customizer` which is
57423 * invoked to produce the objects of `path`. If `customizer` returns `undefined`
57424 * path creation is handled by the method instead. The `customizer` is invoked
57425 * with three arguments: (nsValue, key, nsObject).
57427 * **Note:** This method mutates `object`.
57433 * @param {Object} object The object to modify.
57434 * @param {Array|string} path The path of the property to set.
57435 * @param {Function} updater The function to produce the updated value.
57436 * @param {Function} [customizer] The function to customize assigned values.
57437 * @returns {Object} Returns `object`.
57442 * _.updateWith(object, '[0][1]', _.constant('a'), Object);
57443 * // => { '0': { '1': 'a' } }
57447 function updateWith(object, path, updater, customizer) {
57448 customizer = typeof customizer == 'function' ? customizer : undefined$1;
57449 return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
57452 * Creates an array of the own enumerable string keyed property values of `object`.
57454 * **Note:** Non-object values are coerced to objects.
57460 * @param {Object} object The object to query.
57461 * @returns {Array} Returns the array of property values.
57469 * Foo.prototype.c = 3;
57471 * _.values(new Foo);
57472 * // => [1, 2] (iteration order is not guaranteed)
57479 function values(object) {
57480 return object == null ? [] : baseValues(object, keys(object));
57483 * Creates an array of the own and inherited enumerable string keyed property
57484 * values of `object`.
57486 * **Note:** Non-object values are coerced to objects.
57492 * @param {Object} object The object to query.
57493 * @returns {Array} Returns the array of property values.
57501 * Foo.prototype.c = 3;
57503 * _.valuesIn(new Foo);
57504 * // => [1, 2, 3] (iteration order is not guaranteed)
57508 function valuesIn(object) {
57509 return object == null ? [] : baseValues(object, keysIn(object));
57511 /*------------------------------------------------------------------------*/
57514 * Clamps `number` within the inclusive `lower` and `upper` bounds.
57520 * @param {number} number The number to clamp.
57521 * @param {number} [lower] The lower bound.
57522 * @param {number} upper The upper bound.
57523 * @returns {number} Returns the clamped number.
57526 * _.clamp(-10, -5, 5);
57529 * _.clamp(10, -5, 5);
57534 function clamp(number, lower, upper) {
57535 if (upper === undefined$1) {
57537 lower = undefined$1;
57540 if (upper !== undefined$1) {
57541 upper = toNumber(upper);
57542 upper = upper === upper ? upper : 0;
57545 if (lower !== undefined$1) {
57546 lower = toNumber(lower);
57547 lower = lower === lower ? lower : 0;
57550 return baseClamp(toNumber(number), lower, upper);
57553 * Checks if `n` is between `start` and up to, but not including, `end`. If
57554 * `end` is not specified, it's set to `start` with `start` then set to `0`.
57555 * If `start` is greater than `end` the params are swapped to support
57562 * @param {number} number The number to check.
57563 * @param {number} [start=0] The start of the range.
57564 * @param {number} end The end of the range.
57565 * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
57566 * @see _.range, _.rangeRight
57569 * _.inRange(3, 2, 4);
57581 * _.inRange(1.2, 2);
57584 * _.inRange(5.2, 4);
57587 * _.inRange(-3, -2, -6);
57592 function inRange(number, start, end) {
57593 start = toFinite(start);
57595 if (end === undefined$1) {
57599 end = toFinite(end);
57602 number = toNumber(number);
57603 return baseInRange(number, start, end);
57606 * Produces a random number between the inclusive `lower` and `upper` bounds.
57607 * If only one argument is provided a number between `0` and the given number
57608 * is returned. If `floating` is `true`, or either `lower` or `upper` are
57609 * floats, a floating-point number is returned instead of an integer.
57611 * **Note:** JavaScript follows the IEEE-754 standard for resolving
57612 * floating-point values which can produce unexpected results.
57618 * @param {number} [lower=0] The lower bound.
57619 * @param {number} [upper=1] The upper bound.
57620 * @param {boolean} [floating] Specify returning a floating-point number.
57621 * @returns {number} Returns the random number.
57625 * // => an integer between 0 and 5
57628 * // => also an integer between 0 and 5
57630 * _.random(5, true);
57631 * // => a floating-point number between 0 and 5
57633 * _.random(1.2, 5.2);
57634 * // => a floating-point number between 1.2 and 5.2
57638 function random(lower, upper, floating) {
57639 if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
57640 upper = floating = undefined$1;
57643 if (floating === undefined$1) {
57644 if (typeof upper == 'boolean') {
57646 upper = undefined$1;
57647 } else if (typeof lower == 'boolean') {
57649 lower = undefined$1;
57653 if (lower === undefined$1 && upper === undefined$1) {
57657 lower = toFinite(lower);
57659 if (upper === undefined$1) {
57663 upper = toFinite(upper);
57667 if (lower > upper) {
57673 if (floating || lower % 1 || upper % 1) {
57674 var rand = nativeRandom();
57675 return nativeMin(lower + rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1))), upper);
57678 return baseRandom(lower, upper);
57680 /*------------------------------------------------------------------------*/
57683 * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
57689 * @param {string} [string=''] The string to convert.
57690 * @returns {string} Returns the camel cased string.
57693 * _.camelCase('Foo Bar');
57696 * _.camelCase('--foo-bar--');
57699 * _.camelCase('__FOO_BAR__');
57704 var camelCase = createCompounder(function (result, word, index) {
57705 word = word.toLowerCase();
57706 return result + (index ? capitalize(word) : word);
57709 * Converts the first character of `string` to upper case and the remaining
57716 * @param {string} [string=''] The string to capitalize.
57717 * @returns {string} Returns the capitalized string.
57720 * _.capitalize('FRED');
57724 function capitalize(string) {
57725 return upperFirst(toString(string).toLowerCase());
57728 * Deburrs `string` by converting
57729 * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
57730 * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
57731 * letters to basic Latin letters and removing
57732 * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
57738 * @param {string} [string=''] The string to deburr.
57739 * @returns {string} Returns the deburred string.
57742 * _.deburr('déjà vu');
57747 function deburr(string) {
57748 string = toString(string);
57749 return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
57752 * Checks if `string` ends with the given target string.
57758 * @param {string} [string=''] The string to inspect.
57759 * @param {string} [target] The string to search for.
57760 * @param {number} [position=string.length] The position to search up to.
57761 * @returns {boolean} Returns `true` if `string` ends with `target`,
57765 * _.endsWith('abc', 'c');
57768 * _.endsWith('abc', 'b');
57771 * _.endsWith('abc', 'b', 2);
57776 function endsWith(string, target, position) {
57777 string = toString(string);
57778 target = baseToString(target);
57779 var length = string.length;
57780 position = position === undefined$1 ? length : baseClamp(toInteger(position), 0, length);
57781 var end = position;
57782 position -= target.length;
57783 return position >= 0 && string.slice(position, end) == target;
57786 * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
57787 * corresponding HTML entities.
57789 * **Note:** No other characters are escaped. To escape additional
57790 * characters use a third-party library like [_he_](https://mths.be/he).
57792 * Though the ">" character is escaped for symmetry, characters like
57793 * ">" and "/" don't need escaping in HTML and have no special meaning
57794 * unless they're part of a tag or unquoted attribute value. See
57795 * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
57796 * (under "semi-related fun fact") for more details.
57798 * When working with HTML you should always
57799 * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
57806 * @param {string} [string=''] The string to escape.
57807 * @returns {string} Returns the escaped string.
57810 * _.escape('fred, barney, & pebbles');
57811 * // => 'fred, barney, & pebbles'
57815 function escape(string) {
57816 string = toString(string);
57817 return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string;
57820 * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
57821 * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
57827 * @param {string} [string=''] The string to escape.
57828 * @returns {string} Returns the escaped string.
57831 * _.escapeRegExp('[lodash](https://lodash.com/)');
57832 * // => '\[lodash\]\(https://lodash\.com/\)'
57836 function escapeRegExp(string) {
57837 string = toString(string);
57838 return string && reHasRegExpChar.test(string) ? string.replace(reRegExpChar, '\\$&') : string;
57841 * Converts `string` to
57842 * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
57848 * @param {string} [string=''] The string to convert.
57849 * @returns {string} Returns the kebab cased string.
57852 * _.kebabCase('Foo Bar');
57855 * _.kebabCase('fooBar');
57858 * _.kebabCase('__FOO_BAR__');
57863 var kebabCase = createCompounder(function (result, word, index) {
57864 return result + (index ? '-' : '') + word.toLowerCase();
57867 * Converts `string`, as space separated words, to lower case.
57873 * @param {string} [string=''] The string to convert.
57874 * @returns {string} Returns the lower cased string.
57877 * _.lowerCase('--Foo-Bar--');
57880 * _.lowerCase('fooBar');
57883 * _.lowerCase('__FOO_BAR__');
57887 var lowerCase = createCompounder(function (result, word, index) {
57888 return result + (index ? ' ' : '') + word.toLowerCase();
57891 * Converts the first character of `string` to lower case.
57897 * @param {string} [string=''] The string to convert.
57898 * @returns {string} Returns the converted string.
57901 * _.lowerFirst('Fred');
57904 * _.lowerFirst('FRED');
57908 var lowerFirst = createCaseFirst('toLowerCase');
57910 * Pads `string` on the left and right sides if it's shorter than `length`.
57911 * Padding characters are truncated if they can't be evenly divided by `length`.
57917 * @param {string} [string=''] The string to pad.
57918 * @param {number} [length=0] The padding length.
57919 * @param {string} [chars=' '] The string used as padding.
57920 * @returns {string} Returns the padded string.
57926 * _.pad('abc', 8, '_-');
57933 function pad(string, length, chars) {
57934 string = toString(string);
57935 length = toInteger(length);
57936 var strLength = length ? stringSize(string) : 0;
57938 if (!length || strLength >= length) {
57942 var mid = (length - strLength) / 2;
57943 return createPadding(nativeFloor(mid), chars) + string + createPadding(nativeCeil(mid), chars);
57946 * Pads `string` on the right side if it's shorter than `length`. Padding
57947 * characters are truncated if they exceed `length`.
57953 * @param {string} [string=''] The string to pad.
57954 * @param {number} [length=0] The padding length.
57955 * @param {string} [chars=' '] The string used as padding.
57956 * @returns {string} Returns the padded string.
57959 * _.padEnd('abc', 6);
57962 * _.padEnd('abc', 6, '_-');
57965 * _.padEnd('abc', 3);
57970 function padEnd(string, length, chars) {
57971 string = toString(string);
57972 length = toInteger(length);
57973 var strLength = length ? stringSize(string) : 0;
57974 return length && strLength < length ? string + createPadding(length - strLength, chars) : string;
57977 * Pads `string` on the left side if it's shorter than `length`. Padding
57978 * characters are truncated if they exceed `length`.
57984 * @param {string} [string=''] The string to pad.
57985 * @param {number} [length=0] The padding length.
57986 * @param {string} [chars=' '] The string used as padding.
57987 * @returns {string} Returns the padded string.
57990 * _.padStart('abc', 6);
57993 * _.padStart('abc', 6, '_-');
57996 * _.padStart('abc', 3);
58001 function padStart(string, length, chars) {
58002 string = toString(string);
58003 length = toInteger(length);
58004 var strLength = length ? stringSize(string) : 0;
58005 return length && strLength < length ? createPadding(length - strLength, chars) + string : string;
58008 * Converts `string` to an integer of the specified radix. If `radix` is
58009 * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
58010 * hexadecimal, in which case a `radix` of `16` is used.
58012 * **Note:** This method aligns with the
58013 * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
58019 * @param {string} string The string to convert.
58020 * @param {number} [radix=10] The radix to interpret `value` by.
58021 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58022 * @returns {number} Returns the converted integer.
58025 * _.parseInt('08');
58028 * _.map(['6', '08', '10'], _.parseInt);
58033 function parseInt(string, radix, guard) {
58034 if (guard || radix == null) {
58036 } else if (radix) {
58040 return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
58043 * Repeats the given string `n` times.
58049 * @param {string} [string=''] The string to repeat.
58050 * @param {number} [n=1] The number of times to repeat the string.
58051 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58052 * @returns {string} Returns the repeated string.
58055 * _.repeat('*', 3);
58058 * _.repeat('abc', 2);
58061 * _.repeat('abc', 0);
58066 function repeat(string, n, guard) {
58067 if (guard ? isIterateeCall(string, n, guard) : n === undefined$1) {
58073 return baseRepeat(toString(string), n);
58076 * Replaces matches for `pattern` in `string` with `replacement`.
58078 * **Note:** This method is based on
58079 * [`String#replace`](https://mdn.io/String/replace).
58085 * @param {string} [string=''] The string to modify.
58086 * @param {RegExp|string} pattern The pattern to replace.
58087 * @param {Function|string} replacement The match replacement.
58088 * @returns {string} Returns the modified string.
58091 * _.replace('Hi Fred', 'Fred', 'Barney');
58092 * // => 'Hi Barney'
58096 function replace() {
58097 var args = arguments,
58098 string = toString(args[0]);
58099 return args.length < 3 ? string : string.replace(args[1], args[2]);
58102 * Converts `string` to
58103 * [snake case](https://en.wikipedia.org/wiki/Snake_case).
58109 * @param {string} [string=''] The string to convert.
58110 * @returns {string} Returns the snake cased string.
58113 * _.snakeCase('Foo Bar');
58116 * _.snakeCase('fooBar');
58119 * _.snakeCase('--FOO-BAR--');
58124 var snakeCase = createCompounder(function (result, word, index) {
58125 return result + (index ? '_' : '') + word.toLowerCase();
58128 * Splits `string` by `separator`.
58130 * **Note:** This method is based on
58131 * [`String#split`](https://mdn.io/String/split).
58137 * @param {string} [string=''] The string to split.
58138 * @param {RegExp|string} separator The separator pattern to split by.
58139 * @param {number} [limit] The length to truncate results to.
58140 * @returns {Array} Returns the string segments.
58143 * _.split('a-b-c', '-', 2);
58147 function split(string, separator, limit) {
58148 if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
58149 separator = limit = undefined$1;
58152 limit = limit === undefined$1 ? MAX_ARRAY_LENGTH : limit >>> 0;
58158 string = toString(string);
58160 if (string && (typeof separator == 'string' || separator != null && !isRegExp(separator))) {
58161 separator = baseToString(separator);
58163 if (!separator && hasUnicode(string)) {
58164 return castSlice(stringToArray(string), 0, limit);
58168 return string.split(separator, limit);
58171 * Converts `string` to
58172 * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
58178 * @param {string} [string=''] The string to convert.
58179 * @returns {string} Returns the start cased string.
58182 * _.startCase('--foo-bar--');
58185 * _.startCase('fooBar');
58188 * _.startCase('__FOO_BAR__');
58193 var startCase = createCompounder(function (result, word, index) {
58194 return result + (index ? ' ' : '') + upperFirst(word);
58197 * Checks if `string` starts with the given target string.
58203 * @param {string} [string=''] The string to inspect.
58204 * @param {string} [target] The string to search for.
58205 * @param {number} [position=0] The position to search from.
58206 * @returns {boolean} Returns `true` if `string` starts with `target`,
58210 * _.startsWith('abc', 'a');
58213 * _.startsWith('abc', 'b');
58216 * _.startsWith('abc', 'b', 1);
58220 function startsWith(string, target, position) {
58221 string = toString(string);
58222 position = position == null ? 0 : baseClamp(toInteger(position), 0, string.length);
58223 target = baseToString(target);
58224 return string.slice(position, position + target.length) == target;
58227 * Creates a compiled template function that can interpolate data properties
58228 * in "interpolate" delimiters, HTML-escape interpolated data properties in
58229 * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
58230 * properties may be accessed as free variables in the template. If a setting
58231 * object is given, it takes precedence over `_.templateSettings` values.
58233 * **Note:** In the development build `_.template` utilizes
58234 * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
58235 * for easier debugging.
58237 * For more information on precompiling templates see
58238 * [lodash's custom builds documentation](https://lodash.com/custom-builds).
58240 * For more information on Chrome extension sandboxes see
58241 * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
58247 * @param {string} [string=''] The template string.
58248 * @param {Object} [options={}] The options object.
58249 * @param {RegExp} [options.escape=_.templateSettings.escape]
58250 * The HTML "escape" delimiter.
58251 * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
58252 * The "evaluate" delimiter.
58253 * @param {Object} [options.imports=_.templateSettings.imports]
58254 * An object to import into the template as free variables.
58255 * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
58256 * The "interpolate" delimiter.
58257 * @param {string} [options.sourceURL='lodash.templateSources[n]']
58258 * The sourceURL of the compiled template.
58259 * @param {string} [options.variable='obj']
58260 * The data object variable name.
58261 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58262 * @returns {Function} Returns the compiled template function.
58265 * // Use the "interpolate" delimiter to create a compiled template.
58266 * var compiled = _.template('hello <%= user %>!');
58267 * compiled({ 'user': 'fred' });
58268 * // => 'hello fred!'
58270 * // Use the HTML "escape" delimiter to escape data property values.
58271 * var compiled = _.template('<b><%- value %></b>');
58272 * compiled({ 'value': '<script>' });
58273 * // => '<b><script></b>'
58275 * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
58276 * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
58277 * compiled({ 'users': ['fred', 'barney'] });
58278 * // => '<li>fred</li><li>barney</li>'
58280 * // Use the internal `print` function in "evaluate" delimiters.
58281 * var compiled = _.template('<% print("hello " + user); %>!');
58282 * compiled({ 'user': 'barney' });
58283 * // => 'hello barney!'
58285 * // Use the ES template literal delimiter as an "interpolate" delimiter.
58286 * // Disable support by replacing the "interpolate" delimiter.
58287 * var compiled = _.template('hello ${ user }!');
58288 * compiled({ 'user': 'pebbles' });
58289 * // => 'hello pebbles!'
58291 * // Use backslashes to treat delimiters as plain text.
58292 * var compiled = _.template('<%= "\\<%- value %\\>" %>');
58293 * compiled({ 'value': 'ignored' });
58294 * // => '<%- value %>'
58296 * // Use the `imports` option to import `jQuery` as `jq`.
58297 * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
58298 * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
58299 * compiled({ 'users': ['fred', 'barney'] });
58300 * // => '<li>fred</li><li>barney</li>'
58302 * // Use the `sourceURL` option to specify a custom sourceURL for the template.
58303 * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
58305 * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
58307 * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
58308 * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
58310 * // => function(data) {
58311 * // var __t, __p = '';
58312 * // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
58316 * // Use custom template delimiters.
58317 * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
58318 * var compiled = _.template('hello {{ user }}!');
58319 * compiled({ 'user': 'mustache' });
58320 * // => 'hello mustache!'
58322 * // Use the `source` property to inline compiled templates for meaningful
58323 * // line numbers in error messages and stack traces.
58324 * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
58326 * "main": ' + _.template(mainText).source + '\
58332 function template(string, options, guard) {
58333 // Based on John Resig's `tmpl` implementation
58334 // (http://ejohn.org/blog/javascript-micro-templating/)
58335 // and Laura Doktorova's doT.js (https://github.com/olado/doT).
58336 var settings = lodash.templateSettings;
58338 if (guard && isIterateeCall(string, options, guard)) {
58339 options = undefined$1;
58342 string = toString(string);
58343 options = assignInWith({}, options, settings, customDefaultsAssignIn);
58344 var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
58345 importsKeys = keys(imports),
58346 importsValues = baseValues(imports, importsKeys);
58350 interpolate = options.interpolate || reNoMatch,
58351 source = "__p += '"; // Compile the regexp to match each delimiter.
58353 var reDelimiters = RegExp((options.escape || reNoMatch).source + '|' + interpolate.source + '|' + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' + (options.evaluate || reNoMatch).source + '|$', 'g'); // Use a sourceURL for easier debugging.
58354 // The sourceURL gets injected into the source that's eval-ed, so be careful
58355 // to normalize all kinds of whitespace, so e.g. newlines (and unicode versions of it) can't sneak in
58356 // and escape the comment, thus injecting code that gets evaled.
58358 var sourceURL = '//# sourceURL=' + (hasOwnProperty.call(options, 'sourceURL') ? (options.sourceURL + '').replace(/\s/g, ' ') : 'lodash.templateSources[' + ++templateCounter + ']') + '\n';
58359 string.replace(reDelimiters, function (match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
58360 interpolateValue || (interpolateValue = esTemplateValue); // Escape characters that can't be included in string literals.
58362 source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); // Replace delimiters with snippets.
58366 source += "' +\n__e(" + escapeValue + ") +\n'";
58369 if (evaluateValue) {
58370 isEvaluating = true;
58371 source += "';\n" + evaluateValue + ";\n__p += '";
58374 if (interpolateValue) {
58375 source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
58378 index = offset + match.length; // The JS engine embedded in Adobe products needs `match` returned in
58379 // order to produce the correct `offset` value.
58383 source += "';\n"; // If `variable` is not specified wrap a with-statement around the generated
58384 // code to add the data object to the top of the scope chain.
58386 var variable = hasOwnProperty.call(options, 'variable') && options.variable;
58389 source = 'with (obj) {\n' + source + '\n}\n';
58390 } // Throw an error if a forbidden character was found in `variable`, to prevent
58391 // potential command injection attacks.
58392 else if (reForbiddenIdentifierChars.test(variable)) {
58393 throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
58394 } // Cleanup code by stripping empty strings.
58397 source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source).replace(reEmptyStringMiddle, '$1').replace(reEmptyStringTrailing, '$1;'); // Frame code as the function body.
58399 source = 'function(' + (variable || 'obj') + ') {\n' + (variable ? '' : 'obj || (obj = {});\n') + "var __t, __p = ''" + (isEscaping ? ', __e = _.escape' : '') + (isEvaluating ? ', __j = Array.prototype.join;\n' + "function print() { __p += __j.call(arguments, '') }\n" : ';\n') + source + 'return __p\n}';
58400 var result = attempt(function () {
58401 return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined$1, importsValues);
58402 }); // Provide the compiled function's source by its `toString` method or
58403 // the `source` property as a convenience for inlining compiled templates.
58405 result.source = source;
58407 if (isError(result)) {
58414 * Converts `string`, as a whole, to lower case just like
58415 * [String#toLowerCase](https://mdn.io/toLowerCase).
58421 * @param {string} [string=''] The string to convert.
58422 * @returns {string} Returns the lower cased string.
58425 * _.toLower('--Foo-Bar--');
58426 * // => '--foo-bar--'
58428 * _.toLower('fooBar');
58431 * _.toLower('__FOO_BAR__');
58432 * // => '__foo_bar__'
58436 function toLower(value) {
58437 return toString(value).toLowerCase();
58440 * Converts `string`, as a whole, to upper case just like
58441 * [String#toUpperCase](https://mdn.io/toUpperCase).
58447 * @param {string} [string=''] The string to convert.
58448 * @returns {string} Returns the upper cased string.
58451 * _.toUpper('--foo-bar--');
58452 * // => '--FOO-BAR--'
58454 * _.toUpper('fooBar');
58457 * _.toUpper('__foo_bar__');
58458 * // => '__FOO_BAR__'
58462 function toUpper(value) {
58463 return toString(value).toUpperCase();
58466 * Removes leading and trailing whitespace or specified characters from `string`.
58472 * @param {string} [string=''] The string to trim.
58473 * @param {string} [chars=whitespace] The characters to trim.
58474 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58475 * @returns {string} Returns the trimmed string.
58481 * _.trim('-_-abc-_-', '_-');
58484 * _.map([' foo ', ' bar '], _.trim);
58485 * // => ['foo', 'bar']
58489 function trim(string, chars, guard) {
58490 string = toString(string);
58492 if (string && (guard || chars === undefined$1)) {
58493 return baseTrim(string);
58496 if (!string || !(chars = baseToString(chars))) {
58500 var strSymbols = stringToArray(string),
58501 chrSymbols = stringToArray(chars),
58502 start = charsStartIndex(strSymbols, chrSymbols),
58503 end = charsEndIndex(strSymbols, chrSymbols) + 1;
58504 return castSlice(strSymbols, start, end).join('');
58507 * Removes trailing whitespace or specified characters from `string`.
58513 * @param {string} [string=''] The string to trim.
58514 * @param {string} [chars=whitespace] The characters to trim.
58515 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58516 * @returns {string} Returns the trimmed string.
58519 * _.trimEnd(' abc ');
58522 * _.trimEnd('-_-abc-_-', '_-');
58527 function trimEnd(string, chars, guard) {
58528 string = toString(string);
58530 if (string && (guard || chars === undefined$1)) {
58531 return string.slice(0, trimmedEndIndex(string) + 1);
58534 if (!string || !(chars = baseToString(chars))) {
58538 var strSymbols = stringToArray(string),
58539 end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
58540 return castSlice(strSymbols, 0, end).join('');
58543 * Removes leading whitespace or specified characters from `string`.
58549 * @param {string} [string=''] The string to trim.
58550 * @param {string} [chars=whitespace] The characters to trim.
58551 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58552 * @returns {string} Returns the trimmed string.
58555 * _.trimStart(' abc ');
58558 * _.trimStart('-_-abc-_-', '_-');
58563 function trimStart(string, chars, guard) {
58564 string = toString(string);
58566 if (string && (guard || chars === undefined$1)) {
58567 return string.replace(reTrimStart, '');
58570 if (!string || !(chars = baseToString(chars))) {
58574 var strSymbols = stringToArray(string),
58575 start = charsStartIndex(strSymbols, stringToArray(chars));
58576 return castSlice(strSymbols, start).join('');
58579 * Truncates `string` if it's longer than the given maximum string length.
58580 * The last characters of the truncated string are replaced with the omission
58581 * string which defaults to "...".
58587 * @param {string} [string=''] The string to truncate.
58588 * @param {Object} [options={}] The options object.
58589 * @param {number} [options.length=30] The maximum string length.
58590 * @param {string} [options.omission='...'] The string to indicate text is omitted.
58591 * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
58592 * @returns {string} Returns the truncated string.
58595 * _.truncate('hi-diddly-ho there, neighborino');
58596 * // => 'hi-diddly-ho there, neighbo...'
58598 * _.truncate('hi-diddly-ho there, neighborino', {
58602 * // => 'hi-diddly-ho there,...'
58604 * _.truncate('hi-diddly-ho there, neighborino', {
58606 * 'separator': /,? +/
58608 * // => 'hi-diddly-ho there...'
58610 * _.truncate('hi-diddly-ho there, neighborino', {
58611 * 'omission': ' [...]'
58613 * // => 'hi-diddly-ho there, neig [...]'
58617 function truncate(string, options) {
58618 var length = DEFAULT_TRUNC_LENGTH,
58619 omission = DEFAULT_TRUNC_OMISSION;
58621 if (isObject(options)) {
58622 var separator = 'separator' in options ? options.separator : separator;
58623 length = 'length' in options ? toInteger(options.length) : length;
58624 omission = 'omission' in options ? baseToString(options.omission) : omission;
58627 string = toString(string);
58628 var strLength = string.length;
58630 if (hasUnicode(string)) {
58631 var strSymbols = stringToArray(string);
58632 strLength = strSymbols.length;
58635 if (length >= strLength) {
58639 var end = length - stringSize(omission);
58645 var result = strSymbols ? castSlice(strSymbols, 0, end).join('') : string.slice(0, end);
58647 if (separator === undefined$1) {
58648 return result + omission;
58652 end += result.length - end;
58655 if (isRegExp(separator)) {
58656 if (string.slice(end).search(separator)) {
58658 substring = result;
58660 if (!separator.global) {
58661 separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
58664 separator.lastIndex = 0;
58666 while (match = separator.exec(substring)) {
58667 var newEnd = match.index;
58670 result = result.slice(0, newEnd === undefined$1 ? end : newEnd);
58672 } else if (string.indexOf(baseToString(separator), end) != end) {
58673 var index = result.lastIndexOf(separator);
58676 result = result.slice(0, index);
58680 return result + omission;
58683 * The inverse of `_.escape`; this method converts the HTML entities
58684 * `&`, `<`, `>`, `"`, and `'` in `string` to
58685 * their corresponding characters.
58687 * **Note:** No other HTML entities are unescaped. To unescape additional
58688 * HTML entities use a third-party library like [_he_](https://mths.be/he).
58694 * @param {string} [string=''] The string to unescape.
58695 * @returns {string} Returns the unescaped string.
58698 * _.unescape('fred, barney, & pebbles');
58699 * // => 'fred, barney, & pebbles'
58703 function unescape(string) {
58704 string = toString(string);
58705 return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string;
58708 * Converts `string`, as space separated words, to upper case.
58714 * @param {string} [string=''] The string to convert.
58715 * @returns {string} Returns the upper cased string.
58718 * _.upperCase('--foo-bar');
58721 * _.upperCase('fooBar');
58724 * _.upperCase('__foo_bar__');
58729 var upperCase = createCompounder(function (result, word, index) {
58730 return result + (index ? ' ' : '') + word.toUpperCase();
58733 * Converts the first character of `string` to upper case.
58739 * @param {string} [string=''] The string to convert.
58740 * @returns {string} Returns the converted string.
58743 * _.upperFirst('fred');
58746 * _.upperFirst('FRED');
58750 var upperFirst = createCaseFirst('toUpperCase');
58752 * Splits `string` into an array of its words.
58758 * @param {string} [string=''] The string to inspect.
58759 * @param {RegExp|string} [pattern] The pattern to match words.
58760 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58761 * @returns {Array} Returns the words of `string`.
58764 * _.words('fred, barney, & pebbles');
58765 * // => ['fred', 'barney', 'pebbles']
58767 * _.words('fred, barney, & pebbles', /[^, ]+/g);
58768 * // => ['fred', 'barney', '&', 'pebbles']
58771 function words(string, pattern, guard) {
58772 string = toString(string);
58773 pattern = guard ? undefined$1 : pattern;
58775 if (pattern === undefined$1) {
58776 return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
58779 return string.match(pattern) || [];
58781 /*------------------------------------------------------------------------*/
58784 * Attempts to invoke `func`, returning either the result or the caught error
58785 * object. Any additional arguments are provided to `func` when it's invoked.
58791 * @param {Function} func The function to attempt.
58792 * @param {...*} [args] The arguments to invoke `func` with.
58793 * @returns {*} Returns the `func` result or error object.
58796 * // Avoid throwing errors for invalid selectors.
58797 * var elements = _.attempt(function(selector) {
58798 * return document.querySelectorAll(selector);
58801 * if (_.isError(elements)) {
58807 var attempt = baseRest(function (func, args) {
58809 return apply(func, undefined$1, args);
58811 return isError(e) ? e : new Error(e);
58815 * Binds methods of an object to the object itself, overwriting the existing
58818 * **Note:** This method doesn't set the "length" property of bound functions.
58824 * @param {Object} object The object to bind and assign the bound methods to.
58825 * @param {...(string|string[])} methodNames The object method names to bind.
58826 * @returns {Object} Returns `object`.
58831 * 'click': function() {
58832 * console.log('clicked ' + this.label);
58836 * _.bindAll(view, ['click']);
58837 * jQuery(element).on('click', view.click);
58838 * // => Logs 'clicked docs' when clicked.
58841 var bindAll = flatRest(function (object, methodNames) {
58842 arrayEach(methodNames, function (key) {
58844 baseAssignValue(object, key, bind(object[key], object));
58849 * Creates a function that iterates over `pairs` and invokes the corresponding
58850 * function of the first predicate to return truthy. The predicate-function
58851 * pairs are invoked with the `this` binding and arguments of the created
58858 * @param {Array} pairs The predicate-function pairs.
58859 * @returns {Function} Returns the new composite function.
58862 * var func = _.cond([
58863 * [_.matches({ 'a': 1 }), _.constant('matches A')],
58864 * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
58865 * [_.stubTrue, _.constant('no match')]
58868 * func({ 'a': 1, 'b': 2 });
58869 * // => 'matches A'
58871 * func({ 'a': 0, 'b': 1 });
58872 * // => 'matches B'
58874 * func({ 'a': '1', 'b': '2' });
58878 function cond(pairs) {
58879 var length = pairs == null ? 0 : pairs.length,
58880 toIteratee = getIteratee();
58881 pairs = !length ? [] : arrayMap(pairs, function (pair) {
58882 if (typeof pair[1] != 'function') {
58883 throw new TypeError(FUNC_ERROR_TEXT);
58886 return [toIteratee(pair[0]), pair[1]];
58888 return baseRest(function (args) {
58891 while (++index < length) {
58892 var pair = pairs[index];
58894 if (apply(pair[0], this, args)) {
58895 return apply(pair[1], this, args);
58901 * Creates a function that invokes the predicate properties of `source` with
58902 * the corresponding property values of a given object, returning `true` if
58903 * all predicates return truthy, else `false`.
58905 * **Note:** The created function is equivalent to `_.conformsTo` with
58906 * `source` partially applied.
58912 * @param {Object} source The object of property predicates to conform to.
58913 * @returns {Function} Returns the new spec function.
58917 * { 'a': 2, 'b': 1 },
58918 * { 'a': 1, 'b': 2 }
58921 * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
58922 * // => [{ 'a': 1, 'b': 2 }]
58926 function conforms(source) {
58927 return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
58930 * Creates a function that returns `value`.
58936 * @param {*} value The value to return from the new function.
58937 * @returns {Function} Returns the new constant function.
58940 * var objects = _.times(2, _.constant({ 'a': 1 }));
58942 * console.log(objects);
58943 * // => [{ 'a': 1 }, { 'a': 1 }]
58945 * console.log(objects[0] === objects[1]);
58950 function constant(value) {
58951 return function () {
58956 * Checks `value` to determine whether a default value should be returned in
58957 * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
58964 * @param {*} value The value to check.
58965 * @param {*} defaultValue The default value.
58966 * @returns {*} Returns the resolved value.
58969 * _.defaultTo(1, 10);
58972 * _.defaultTo(undefined, 10);
58977 function defaultTo(value, defaultValue) {
58978 return value == null || value !== value ? defaultValue : value;
58981 * Creates a function that returns the result of invoking the given functions
58982 * with the `this` binding of the created function, where each successive
58983 * invocation is supplied the return value of the previous.
58989 * @param {...(Function|Function[])} [funcs] The functions to invoke.
58990 * @returns {Function} Returns the new composite function.
58994 * function square(n) {
58998 * var addSquare = _.flow([_.add, square]);
59004 var flow = createFlow();
59006 * This method is like `_.flow` except that it creates a function that
59007 * invokes the given functions from right to left.
59013 * @param {...(Function|Function[])} [funcs] The functions to invoke.
59014 * @returns {Function} Returns the new composite function.
59018 * function square(n) {
59022 * var addSquare = _.flowRight([square, _.add]);
59027 var flowRight = createFlow(true);
59029 * This method returns the first argument it receives.
59035 * @param {*} value Any value.
59036 * @returns {*} Returns `value`.
59039 * var object = { 'a': 1 };
59041 * console.log(_.identity(object) === object);
59045 function identity(value) {
59049 * Creates a function that invokes `func` with the arguments of the created
59050 * function. If `func` is a property name, the created function returns the
59051 * property value for a given element. If `func` is an array or object, the
59052 * created function returns `true` for elements that contain the equivalent
59053 * source properties, otherwise it returns `false`.
59059 * @param {*} [func=_.identity] The value to convert to a callback.
59060 * @returns {Function} Returns the callback.
59064 * { 'user': 'barney', 'age': 36, 'active': true },
59065 * { 'user': 'fred', 'age': 40, 'active': false }
59068 * // The `_.matches` iteratee shorthand.
59069 * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
59070 * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
59072 * // The `_.matchesProperty` iteratee shorthand.
59073 * _.filter(users, _.iteratee(['user', 'fred']));
59074 * // => [{ 'user': 'fred', 'age': 40 }]
59076 * // The `_.property` iteratee shorthand.
59077 * _.map(users, _.iteratee('user'));
59078 * // => ['barney', 'fred']
59080 * // Create custom iteratee shorthands.
59081 * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
59082 * return !_.isRegExp(func) ? iteratee(func) : function(string) {
59083 * return func.test(string);
59087 * _.filter(['abc', 'def'], /ef/);
59092 function iteratee(func) {
59093 return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
59096 * Creates a function that performs a partial deep comparison between a given
59097 * object and `source`, returning `true` if the given object has equivalent
59098 * property values, else `false`.
59100 * **Note:** The created function is equivalent to `_.isMatch` with `source`
59101 * partially applied.
59103 * Partial comparisons will match empty array and empty object `source`
59104 * values against any array or object value, respectively. See `_.isEqual`
59105 * for a list of supported value comparisons.
59107 * **Note:** Multiple values can be checked by combining several matchers
59108 * using `_.overSome`
59114 * @param {Object} source The object of property values to match.
59115 * @returns {Function} Returns the new spec function.
59119 * { 'a': 1, 'b': 2, 'c': 3 },
59120 * { 'a': 4, 'b': 5, 'c': 6 }
59123 * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
59124 * // => [{ 'a': 4, 'b': 5, 'c': 6 }]
59126 * // Checking for several possible values
59127 * _.filter(objects, _.overSome([_.matches({ 'a': 1 }), _.matches({ 'a': 4 })]));
59128 * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]
59132 function matches(source) {
59133 return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
59136 * Creates a function that performs a partial deep comparison between the
59137 * value at `path` of a given object to `srcValue`, returning `true` if the
59138 * object value is equivalent, else `false`.
59140 * **Note:** Partial comparisons will match empty array and empty object
59141 * `srcValue` values against any array or object value, respectively. See
59142 * `_.isEqual` for a list of supported value comparisons.
59144 * **Note:** Multiple values can be checked by combining several matchers
59145 * using `_.overSome`
59151 * @param {Array|string} path The path of the property to get.
59152 * @param {*} srcValue The value to match.
59153 * @returns {Function} Returns the new spec function.
59157 * { 'a': 1, 'b': 2, 'c': 3 },
59158 * { 'a': 4, 'b': 5, 'c': 6 }
59161 * _.find(objects, _.matchesProperty('a', 4));
59162 * // => { 'a': 4, 'b': 5, 'c': 6 }
59164 * // Checking for several possible values
59165 * _.filter(objects, _.overSome([_.matchesProperty('a', 1), _.matchesProperty('a', 4)]));
59166 * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]
59170 function matchesProperty(path, srcValue) {
59171 return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
59174 * Creates a function that invokes the method at `path` of a given object.
59175 * Any additional arguments are provided to the invoked method.
59181 * @param {Array|string} path The path of the method to invoke.
59182 * @param {...*} [args] The arguments to invoke the method with.
59183 * @returns {Function} Returns the new invoker function.
59187 * { 'a': { 'b': _.constant(2) } },
59188 * { 'a': { 'b': _.constant(1) } }
59191 * _.map(objects, _.method('a.b'));
59194 * _.map(objects, _.method(['a', 'b']));
59199 var method = baseRest(function (path, args) {
59200 return function (object) {
59201 return baseInvoke(object, path, args);
59205 * The opposite of `_.method`; this method creates a function that invokes
59206 * the method at a given path of `object`. Any additional arguments are
59207 * provided to the invoked method.
59213 * @param {Object} object The object to query.
59214 * @param {...*} [args] The arguments to invoke the method with.
59215 * @returns {Function} Returns the new invoker function.
59218 * var array = _.times(3, _.constant),
59219 * object = { 'a': array, 'b': array, 'c': array };
59221 * _.map(['a[2]', 'c[0]'], _.methodOf(object));
59224 * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
59228 var methodOf = baseRest(function (object, args) {
59229 return function (path) {
59230 return baseInvoke(object, path, args);
59234 * Adds all own enumerable string keyed function properties of a source
59235 * object to the destination object. If `object` is a function, then methods
59236 * are added to its prototype as well.
59238 * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
59239 * avoid conflicts caused by modifying the original.
59245 * @param {Function|Object} [object=lodash] The destination object.
59246 * @param {Object} source The object of functions to add.
59247 * @param {Object} [options={}] The options object.
59248 * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
59249 * @returns {Function|Object} Returns `object`.
59252 * function vowels(string) {
59253 * return _.filter(string, function(v) {
59254 * return /[aeiou]/i.test(v);
59258 * _.mixin({ 'vowels': vowels });
59259 * _.vowels('fred');
59262 * _('fred').vowels().value();
59265 * _.mixin({ 'vowels': vowels }, { 'chain': false });
59266 * _('fred').vowels();
59270 function mixin(object, source, options) {
59271 var props = keys(source),
59272 methodNames = baseFunctions(source, props);
59274 if (options == null && !(isObject(source) && (methodNames.length || !props.length))) {
59278 methodNames = baseFunctions(source, keys(source));
59281 var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
59282 isFunc = isFunction(object);
59283 arrayEach(methodNames, function (methodName) {
59284 var func = source[methodName];
59285 object[methodName] = func;
59288 object.prototype[methodName] = function () {
59289 var chainAll = this.__chain__;
59291 if (chain || chainAll) {
59292 var result = object(this.__wrapped__),
59293 actions = result.__actions__ = copyArray(this.__actions__);
59299 result.__chain__ = chainAll;
59303 return func.apply(object, arrayPush([this.value()], arguments));
59310 * Reverts the `_` variable to its previous value and returns a reference to
59311 * the `lodash` function.
59317 * @returns {Function} Returns the `lodash` function.
59320 * var lodash = _.noConflict();
59324 function noConflict() {
59325 if (root._ === this) {
59332 * This method returns `undefined`.
59340 * _.times(2, _.noop);
59341 * // => [undefined, undefined]
59345 function noop() {// No operation performed.
59348 * Creates a function that gets the argument at index `n`. If `n` is negative,
59349 * the nth argument from the end is returned.
59355 * @param {number} [n=0] The index of the argument to return.
59356 * @returns {Function} Returns the new pass-thru function.
59359 * var func = _.nthArg(1);
59360 * func('a', 'b', 'c', 'd');
59363 * var func = _.nthArg(-2);
59364 * func('a', 'b', 'c', 'd');
59369 function nthArg(n) {
59371 return baseRest(function (args) {
59372 return baseNth(args, n);
59376 * Creates a function that invokes `iteratees` with the arguments it receives
59377 * and returns their results.
59383 * @param {...(Function|Function[])} [iteratees=[_.identity]]
59384 * The iteratees to invoke.
59385 * @returns {Function} Returns the new function.
59388 * var func = _.over([Math.max, Math.min]);
59390 * func(1, 2, 3, 4);
59395 var over = createOver(arrayMap);
59397 * Creates a function that checks if **all** of the `predicates` return
59398 * truthy when invoked with the arguments it receives.
59400 * Following shorthands are possible for providing predicates.
59401 * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
59402 * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
59408 * @param {...(Function|Function[])} [predicates=[_.identity]]
59409 * The predicates to check.
59410 * @returns {Function} Returns the new function.
59413 * var func = _.overEvery([Boolean, isFinite]);
59425 var overEvery = createOver(arrayEvery);
59427 * Creates a function that checks if **any** of the `predicates` return
59428 * truthy when invoked with the arguments it receives.
59430 * Following shorthands are possible for providing predicates.
59431 * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
59432 * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
59438 * @param {...(Function|Function[])} [predicates=[_.identity]]
59439 * The predicates to check.
59440 * @returns {Function} Returns the new function.
59443 * var func = _.overSome([Boolean, isFinite]);
59454 * var matchesFunc = _.overSome([{ 'a': 1 }, { 'a': 2 }])
59455 * var matchesPropertyFunc = _.overSome([['a', 1], ['a', 2]])
59458 var overSome = createOver(arraySome);
59460 * Creates a function that returns the value at `path` of a given object.
59466 * @param {Array|string} path The path of the property to get.
59467 * @returns {Function} Returns the new accessor function.
59471 * { 'a': { 'b': 2 } },
59472 * { 'a': { 'b': 1 } }
59475 * _.map(objects, _.property('a.b'));
59478 * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
59482 function property(path) {
59483 return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
59486 * The opposite of `_.property`; this method creates a function that returns
59487 * the value at a given path of `object`.
59493 * @param {Object} object The object to query.
59494 * @returns {Function} Returns the new accessor function.
59497 * var array = [0, 1, 2],
59498 * object = { 'a': array, 'b': array, 'c': array };
59500 * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
59503 * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
59508 function propertyOf(object) {
59509 return function (path) {
59510 return object == null ? undefined$1 : baseGet(object, path);
59514 * Creates an array of numbers (positive and/or negative) progressing from
59515 * `start` up to, but not including, `end`. A step of `-1` is used if a negative
59516 * `start` is specified without an `end` or `step`. If `end` is not specified,
59517 * it's set to `start` with `start` then set to `0`.
59519 * **Note:** JavaScript follows the IEEE-754 standard for resolving
59520 * floating-point values which can produce unexpected results.
59526 * @param {number} [start=0] The start of the range.
59527 * @param {number} end The end of the range.
59528 * @param {number} [step=1] The value to increment or decrement by.
59529 * @returns {Array} Returns the range of numbers.
59530 * @see _.inRange, _.rangeRight
59534 * // => [0, 1, 2, 3]
59537 * // => [0, -1, -2, -3]
59540 * // => [1, 2, 3, 4]
59542 * _.range(0, 20, 5);
59543 * // => [0, 5, 10, 15]
59545 * _.range(0, -4, -1);
59546 * // => [0, -1, -2, -3]
59548 * _.range(1, 4, 0);
59556 var range = createRange();
59558 * This method is like `_.range` except that it populates values in
59559 * descending order.
59565 * @param {number} [start=0] The start of the range.
59566 * @param {number} end The end of the range.
59567 * @param {number} [step=1] The value to increment or decrement by.
59568 * @returns {Array} Returns the range of numbers.
59569 * @see _.inRange, _.range
59573 * // => [3, 2, 1, 0]
59575 * _.rangeRight(-4);
59576 * // => [-3, -2, -1, 0]
59578 * _.rangeRight(1, 5);
59579 * // => [4, 3, 2, 1]
59581 * _.rangeRight(0, 20, 5);
59582 * // => [15, 10, 5, 0]
59584 * _.rangeRight(0, -4, -1);
59585 * // => [-3, -2, -1, 0]
59587 * _.rangeRight(1, 4, 0);
59594 var rangeRight = createRange(true);
59596 * This method returns a new empty array.
59602 * @returns {Array} Returns the new empty array.
59605 * var arrays = _.times(2, _.stubArray);
59607 * console.log(arrays);
59610 * console.log(arrays[0] === arrays[1]);
59614 function stubArray() {
59618 * This method returns `false`.
59624 * @returns {boolean} Returns `false`.
59627 * _.times(2, _.stubFalse);
59628 * // => [false, false]
59632 function stubFalse() {
59636 * This method returns a new empty object.
59642 * @returns {Object} Returns the new empty object.
59645 * var objects = _.times(2, _.stubObject);
59647 * console.log(objects);
59650 * console.log(objects[0] === objects[1]);
59655 function stubObject() {
59659 * This method returns an empty string.
59665 * @returns {string} Returns the empty string.
59668 * _.times(2, _.stubString);
59673 function stubString() {
59677 * This method returns `true`.
59683 * @returns {boolean} Returns `true`.
59686 * _.times(2, _.stubTrue);
59687 * // => [true, true]
59691 function stubTrue() {
59695 * Invokes the iteratee `n` times, returning an array of the results of
59696 * each invocation. The iteratee is invoked with one argument; (index).
59702 * @param {number} n The number of times to invoke `iteratee`.
59703 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
59704 * @returns {Array} Returns the array of results.
59707 * _.times(3, String);
59708 * // => ['0', '1', '2']
59710 * _.times(4, _.constant(0));
59711 * // => [0, 0, 0, 0]
59715 function times(n, iteratee) {
59718 if (n < 1 || n > MAX_SAFE_INTEGER) {
59722 var index = MAX_ARRAY_LENGTH,
59723 length = nativeMin(n, MAX_ARRAY_LENGTH);
59724 iteratee = getIteratee(iteratee);
59725 n -= MAX_ARRAY_LENGTH;
59726 var result = baseTimes(length, iteratee);
59728 while (++index < n) {
59735 * Converts `value` to a property path array.
59741 * @param {*} value The value to convert.
59742 * @returns {Array} Returns the new property path array.
59745 * _.toPath('a.b.c');
59746 * // => ['a', 'b', 'c']
59748 * _.toPath('a[0].b.c');
59749 * // => ['a', '0', 'b', 'c']
59753 function toPath(value) {
59754 if (isArray(value)) {
59755 return arrayMap(value, toKey);
59758 return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
59761 * Generates a unique ID. If `prefix` is given, the ID is appended to it.
59767 * @param {string} [prefix=''] The value to prefix the ID with.
59768 * @returns {string} Returns the unique ID.
59771 * _.uniqueId('contact_');
59772 * // => 'contact_104'
59779 function uniqueId(prefix) {
59780 var id = ++idCounter;
59781 return toString(prefix) + id;
59783 /*------------------------------------------------------------------------*/
59786 * Adds two numbers.
59792 * @param {number} augend The first number in an addition.
59793 * @param {number} addend The second number in an addition.
59794 * @returns {number} Returns the total.
59802 var add = createMathOperation(function (augend, addend) {
59803 return augend + addend;
59806 * Computes `number` rounded up to `precision`.
59812 * @param {number} number The number to round up.
59813 * @param {number} [precision=0] The precision to round up to.
59814 * @returns {number} Returns the rounded up number.
59820 * _.ceil(6.004, 2);
59823 * _.ceil(6040, -2);
59827 var ceil = createRound('ceil');
59829 * Divide two numbers.
59835 * @param {number} dividend The first number in a division.
59836 * @param {number} divisor The second number in a division.
59837 * @returns {number} Returns the quotient.
59844 var divide = createMathOperation(function (dividend, divisor) {
59845 return dividend / divisor;
59848 * Computes `number` rounded down to `precision`.
59854 * @param {number} number The number to round down.
59855 * @param {number} [precision=0] The precision to round down to.
59856 * @returns {number} Returns the rounded down number.
59862 * _.floor(0.046, 2);
59865 * _.floor(4060, -2);
59869 var floor = createRound('floor');
59871 * Computes the maximum value of `array`. If `array` is empty or falsey,
59872 * `undefined` is returned.
59878 * @param {Array} array The array to iterate over.
59879 * @returns {*} Returns the maximum value.
59882 * _.max([4, 2, 8, 6]);
59889 function max(array) {
59890 return array && array.length ? baseExtremum(array, identity, baseGt) : undefined$1;
59893 * This method is like `_.max` except that it accepts `iteratee` which is
59894 * invoked for each element in `array` to generate the criterion by which
59895 * the value is ranked. The iteratee is invoked with one argument: (value).
59901 * @param {Array} array The array to iterate over.
59902 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
59903 * @returns {*} Returns the maximum value.
59906 * var objects = [{ 'n': 1 }, { 'n': 2 }];
59908 * _.maxBy(objects, function(o) { return o.n; });
59911 * // The `_.property` iteratee shorthand.
59912 * _.maxBy(objects, 'n');
59917 function maxBy(array, iteratee) {
59918 return array && array.length ? baseExtremum(array, getIteratee(iteratee, 2), baseGt) : undefined$1;
59921 * Computes the mean of the values in `array`.
59927 * @param {Array} array The array to iterate over.
59928 * @returns {number} Returns the mean.
59931 * _.mean([4, 2, 8, 6]);
59936 function mean(array) {
59937 return baseMean(array, identity);
59940 * This method is like `_.mean` except that it accepts `iteratee` which is
59941 * invoked for each element in `array` to generate the value to be averaged.
59942 * The iteratee is invoked with one argument: (value).
59948 * @param {Array} array The array to iterate over.
59949 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
59950 * @returns {number} Returns the mean.
59953 * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
59955 * _.meanBy(objects, function(o) { return o.n; });
59958 * // The `_.property` iteratee shorthand.
59959 * _.meanBy(objects, 'n');
59964 function meanBy(array, iteratee) {
59965 return baseMean(array, getIteratee(iteratee, 2));
59968 * Computes the minimum value of `array`. If `array` is empty or falsey,
59969 * `undefined` is returned.
59975 * @param {Array} array The array to iterate over.
59976 * @returns {*} Returns the minimum value.
59979 * _.min([4, 2, 8, 6]);
59987 function min(array) {
59988 return array && array.length ? baseExtremum(array, identity, baseLt) : undefined$1;
59991 * This method is like `_.min` except that it accepts `iteratee` which is
59992 * invoked for each element in `array` to generate the criterion by which
59993 * the value is ranked. The iteratee is invoked with one argument: (value).
59999 * @param {Array} array The array to iterate over.
60000 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
60001 * @returns {*} Returns the minimum value.
60004 * var objects = [{ 'n': 1 }, { 'n': 2 }];
60006 * _.minBy(objects, function(o) { return o.n; });
60009 * // The `_.property` iteratee shorthand.
60010 * _.minBy(objects, 'n');
60015 function minBy(array, iteratee) {
60016 return array && array.length ? baseExtremum(array, getIteratee(iteratee, 2), baseLt) : undefined$1;
60019 * Multiply two numbers.
60025 * @param {number} multiplier The first number in a multiplication.
60026 * @param {number} multiplicand The second number in a multiplication.
60027 * @returns {number} Returns the product.
60030 * _.multiply(6, 4);
60035 var multiply = createMathOperation(function (multiplier, multiplicand) {
60036 return multiplier * multiplicand;
60039 * Computes `number` rounded to `precision`.
60045 * @param {number} number The number to round.
60046 * @param {number} [precision=0] The precision to round to.
60047 * @returns {number} Returns the rounded number.
60053 * _.round(4.006, 2);
60056 * _.round(4060, -2);
60060 var round = createRound('round');
60062 * Subtract two numbers.
60068 * @param {number} minuend The first number in a subtraction.
60069 * @param {number} subtrahend The second number in a subtraction.
60070 * @returns {number} Returns the difference.
60073 * _.subtract(6, 4);
60077 var subtract = createMathOperation(function (minuend, subtrahend) {
60078 return minuend - subtrahend;
60081 * Computes the sum of the values in `array`.
60087 * @param {Array} array The array to iterate over.
60088 * @returns {number} Returns the sum.
60091 * _.sum([4, 2, 8, 6]);
60095 function sum(array) {
60096 return array && array.length ? baseSum(array, identity) : 0;
60099 * This method is like `_.sum` except that it accepts `iteratee` which is
60100 * invoked for each element in `array` to generate the value to be summed.
60101 * The iteratee is invoked with one argument: (value).
60107 * @param {Array} array The array to iterate over.
60108 * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
60109 * @returns {number} Returns the sum.
60112 * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
60114 * _.sumBy(objects, function(o) { return o.n; });
60117 * // The `_.property` iteratee shorthand.
60118 * _.sumBy(objects, 'n');
60123 function sumBy(array, iteratee) {
60124 return array && array.length ? baseSum(array, getIteratee(iteratee, 2)) : 0;
60126 /*------------------------------------------------------------------------*/
60127 // Add methods that return wrapped values in chain sequences.
60130 lodash.after = after;
60132 lodash.assign = assign;
60133 lodash.assignIn = assignIn;
60134 lodash.assignInWith = assignInWith;
60135 lodash.assignWith = assignWith;
60137 lodash.before = before;
60138 lodash.bind = bind;
60139 lodash.bindAll = bindAll;
60140 lodash.bindKey = bindKey;
60141 lodash.castArray = castArray;
60142 lodash.chain = chain;
60143 lodash.chunk = chunk;
60144 lodash.compact = compact;
60145 lodash.concat = concat;
60146 lodash.cond = cond;
60147 lodash.conforms = conforms;
60148 lodash.constant = constant;
60149 lodash.countBy = countBy;
60150 lodash.create = create;
60151 lodash.curry = curry;
60152 lodash.curryRight = curryRight;
60153 lodash.debounce = debounce;
60154 lodash.defaults = defaults;
60155 lodash.defaultsDeep = defaultsDeep;
60156 lodash.defer = defer;
60157 lodash.delay = delay;
60158 lodash.difference = difference;
60159 lodash.differenceBy = differenceBy;
60160 lodash.differenceWith = differenceWith;
60161 lodash.drop = drop;
60162 lodash.dropRight = dropRight;
60163 lodash.dropRightWhile = dropRightWhile;
60164 lodash.dropWhile = dropWhile;
60165 lodash.fill = fill;
60166 lodash.filter = filter;
60167 lodash.flatMap = flatMap;
60168 lodash.flatMapDeep = flatMapDeep;
60169 lodash.flatMapDepth = flatMapDepth;
60170 lodash.flatten = flatten;
60171 lodash.flattenDeep = flattenDeep;
60172 lodash.flattenDepth = flattenDepth;
60173 lodash.flip = flip;
60174 lodash.flow = flow;
60175 lodash.flowRight = flowRight;
60176 lodash.fromPairs = fromPairs;
60177 lodash.functions = functions;
60178 lodash.functionsIn = functionsIn;
60179 lodash.groupBy = groupBy;
60180 lodash.initial = initial;
60181 lodash.intersection = intersection;
60182 lodash.intersectionBy = intersectionBy;
60183 lodash.intersectionWith = intersectionWith;
60184 lodash.invert = invert;
60185 lodash.invertBy = invertBy;
60186 lodash.invokeMap = invokeMap;
60187 lodash.iteratee = iteratee;
60188 lodash.keyBy = keyBy;
60189 lodash.keys = keys;
60190 lodash.keysIn = keysIn;
60192 lodash.mapKeys = mapKeys;
60193 lodash.mapValues = mapValues;
60194 lodash.matches = matches;
60195 lodash.matchesProperty = matchesProperty;
60196 lodash.memoize = memoize;
60197 lodash.merge = merge;
60198 lodash.mergeWith = mergeWith;
60199 lodash.method = method;
60200 lodash.methodOf = methodOf;
60201 lodash.mixin = mixin;
60202 lodash.negate = negate;
60203 lodash.nthArg = nthArg;
60204 lodash.omit = omit;
60205 lodash.omitBy = omitBy;
60206 lodash.once = once;
60207 lodash.orderBy = orderBy;
60208 lodash.over = over;
60209 lodash.overArgs = overArgs;
60210 lodash.overEvery = overEvery;
60211 lodash.overSome = overSome;
60212 lodash.partial = partial;
60213 lodash.partialRight = partialRight;
60214 lodash.partition = partition;
60215 lodash.pick = pick;
60216 lodash.pickBy = pickBy;
60217 lodash.property = property;
60218 lodash.propertyOf = propertyOf;
60219 lodash.pull = pull;
60220 lodash.pullAll = pullAll;
60221 lodash.pullAllBy = pullAllBy;
60222 lodash.pullAllWith = pullAllWith;
60223 lodash.pullAt = pullAt;
60224 lodash.range = range;
60225 lodash.rangeRight = rangeRight;
60226 lodash.rearg = rearg;
60227 lodash.reject = reject;
60228 lodash.remove = remove;
60229 lodash.rest = rest;
60230 lodash.reverse = reverse;
60231 lodash.sampleSize = sampleSize;
60233 lodash.setWith = setWith;
60234 lodash.shuffle = shuffle;
60235 lodash.slice = slice;
60236 lodash.sortBy = sortBy;
60237 lodash.sortedUniq = sortedUniq;
60238 lodash.sortedUniqBy = sortedUniqBy;
60239 lodash.split = split;
60240 lodash.spread = spread;
60241 lodash.tail = tail;
60242 lodash.take = take;
60243 lodash.takeRight = takeRight;
60244 lodash.takeRightWhile = takeRightWhile;
60245 lodash.takeWhile = takeWhile;
60247 lodash.throttle = throttle;
60248 lodash.thru = thru;
60249 lodash.toArray = toArray;
60250 lodash.toPairs = toPairs;
60251 lodash.toPairsIn = toPairsIn;
60252 lodash.toPath = toPath;
60253 lodash.toPlainObject = toPlainObject;
60254 lodash.transform = transform;
60255 lodash.unary = unary;
60256 lodash.union = union;
60257 lodash.unionBy = unionBy;
60258 lodash.unionWith = unionWith;
60259 lodash.uniq = uniq;
60260 lodash.uniqBy = uniqBy;
60261 lodash.uniqWith = uniqWith;
60262 lodash.unset = unset;
60263 lodash.unzip = unzip;
60264 lodash.unzipWith = unzipWith;
60265 lodash.update = update;
60266 lodash.updateWith = updateWith;
60267 lodash.values = values;
60268 lodash.valuesIn = valuesIn;
60269 lodash.without = without;
60270 lodash.words = words;
60271 lodash.wrap = wrap;
60273 lodash.xorBy = xorBy;
60274 lodash.xorWith = xorWith;
60276 lodash.zipObject = zipObject;
60277 lodash.zipObjectDeep = zipObjectDeep;
60278 lodash.zipWith = zipWith; // Add aliases.
60280 lodash.entries = toPairs;
60281 lodash.entriesIn = toPairsIn;
60282 lodash.extend = assignIn;
60283 lodash.extendWith = assignInWith; // Add methods to `lodash.prototype`.
60285 mixin(lodash, lodash);
60286 /*------------------------------------------------------------------------*/
60287 // Add methods that return unwrapped values in chain sequences.
60290 lodash.attempt = attempt;
60291 lodash.camelCase = camelCase;
60292 lodash.capitalize = capitalize;
60293 lodash.ceil = ceil;
60294 lodash.clamp = clamp;
60295 lodash.clone = clone;
60296 lodash.cloneDeep = cloneDeep;
60297 lodash.cloneDeepWith = cloneDeepWith;
60298 lodash.cloneWith = cloneWith;
60299 lodash.conformsTo = conformsTo;
60300 lodash.deburr = deburr;
60301 lodash.defaultTo = defaultTo;
60302 lodash.divide = divide;
60303 lodash.endsWith = endsWith;
60305 lodash.escape = escape;
60306 lodash.escapeRegExp = escapeRegExp;
60307 lodash.every = every;
60308 lodash.find = find;
60309 lodash.findIndex = findIndex;
60310 lodash.findKey = findKey;
60311 lodash.findLast = findLast;
60312 lodash.findLastIndex = findLastIndex;
60313 lodash.findLastKey = findLastKey;
60314 lodash.floor = floor;
60315 lodash.forEach = forEach;
60316 lodash.forEachRight = forEachRight;
60317 lodash.forIn = forIn;
60318 lodash.forInRight = forInRight;
60319 lodash.forOwn = forOwn;
60320 lodash.forOwnRight = forOwnRight;
60325 lodash.hasIn = hasIn;
60326 lodash.head = head;
60327 lodash.identity = identity;
60328 lodash.includes = includes;
60329 lodash.indexOf = indexOf;
60330 lodash.inRange = inRange;
60331 lodash.invoke = invoke;
60332 lodash.isArguments = isArguments;
60333 lodash.isArray = isArray;
60334 lodash.isArrayBuffer = isArrayBuffer;
60335 lodash.isArrayLike = isArrayLike;
60336 lodash.isArrayLikeObject = isArrayLikeObject;
60337 lodash.isBoolean = isBoolean;
60338 lodash.isBuffer = isBuffer;
60339 lodash.isDate = isDate;
60340 lodash.isElement = isElement;
60341 lodash.isEmpty = isEmpty;
60342 lodash.isEqual = isEqual;
60343 lodash.isEqualWith = isEqualWith;
60344 lodash.isError = isError;
60345 lodash.isFinite = isFinite;
60346 lodash.isFunction = isFunction;
60347 lodash.isInteger = isInteger;
60348 lodash.isLength = isLength;
60349 lodash.isMap = isMap;
60350 lodash.isMatch = isMatch;
60351 lodash.isMatchWith = isMatchWith;
60352 lodash.isNaN = isNaN;
60353 lodash.isNative = isNative;
60354 lodash.isNil = isNil;
60355 lodash.isNull = isNull;
60356 lodash.isNumber = isNumber;
60357 lodash.isObject = isObject;
60358 lodash.isObjectLike = isObjectLike;
60359 lodash.isPlainObject = isPlainObject;
60360 lodash.isRegExp = isRegExp;
60361 lodash.isSafeInteger = isSafeInteger;
60362 lodash.isSet = isSet;
60363 lodash.isString = isString;
60364 lodash.isSymbol = isSymbol;
60365 lodash.isTypedArray = isTypedArray;
60366 lodash.isUndefined = isUndefined;
60367 lodash.isWeakMap = isWeakMap;
60368 lodash.isWeakSet = isWeakSet;
60369 lodash.join = join;
60370 lodash.kebabCase = kebabCase;
60371 lodash.last = last;
60372 lodash.lastIndexOf = lastIndexOf;
60373 lodash.lowerCase = lowerCase;
60374 lodash.lowerFirst = lowerFirst;
60378 lodash.maxBy = maxBy;
60379 lodash.mean = mean;
60380 lodash.meanBy = meanBy;
60382 lodash.minBy = minBy;
60383 lodash.stubArray = stubArray;
60384 lodash.stubFalse = stubFalse;
60385 lodash.stubObject = stubObject;
60386 lodash.stubString = stubString;
60387 lodash.stubTrue = stubTrue;
60388 lodash.multiply = multiply;
60390 lodash.noConflict = noConflict;
60391 lodash.noop = noop;
60394 lodash.padEnd = padEnd;
60395 lodash.padStart = padStart;
60396 lodash.parseInt = parseInt;
60397 lodash.random = random;
60398 lodash.reduce = reduce;
60399 lodash.reduceRight = reduceRight;
60400 lodash.repeat = repeat;
60401 lodash.replace = replace;
60402 lodash.result = result;
60403 lodash.round = round;
60404 lodash.runInContext = runInContext;
60405 lodash.sample = sample;
60406 lodash.size = size;
60407 lodash.snakeCase = snakeCase;
60408 lodash.some = some;
60409 lodash.sortedIndex = sortedIndex;
60410 lodash.sortedIndexBy = sortedIndexBy;
60411 lodash.sortedIndexOf = sortedIndexOf;
60412 lodash.sortedLastIndex = sortedLastIndex;
60413 lodash.sortedLastIndexBy = sortedLastIndexBy;
60414 lodash.sortedLastIndexOf = sortedLastIndexOf;
60415 lodash.startCase = startCase;
60416 lodash.startsWith = startsWith;
60417 lodash.subtract = subtract;
60419 lodash.sumBy = sumBy;
60420 lodash.template = template;
60421 lodash.times = times;
60422 lodash.toFinite = toFinite;
60423 lodash.toInteger = toInteger;
60424 lodash.toLength = toLength;
60425 lodash.toLower = toLower;
60426 lodash.toNumber = toNumber;
60427 lodash.toSafeInteger = toSafeInteger;
60428 lodash.toString = toString;
60429 lodash.toUpper = toUpper;
60430 lodash.trim = trim;
60431 lodash.trimEnd = trimEnd;
60432 lodash.trimStart = trimStart;
60433 lodash.truncate = truncate;
60434 lodash.unescape = unescape;
60435 lodash.uniqueId = uniqueId;
60436 lodash.upperCase = upperCase;
60437 lodash.upperFirst = upperFirst; // Add aliases.
60439 lodash.each = forEach;
60440 lodash.eachRight = forEachRight;
60441 lodash.first = head;
60442 mixin(lodash, function () {
60444 baseForOwn(lodash, function (func, methodName) {
60445 if (!hasOwnProperty.call(lodash.prototype, methodName)) {
60446 source[methodName] = func;
60453 /*------------------------------------------------------------------------*/
60456 * The semantic version number.
60463 lodash.VERSION = VERSION; // Assign default placeholders.
60465 arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function (methodName) {
60466 lodash[methodName].placeholder = lodash;
60467 }); // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
60469 arrayEach(['drop', 'take'], function (methodName, index) {
60470 LazyWrapper.prototype[methodName] = function (n) {
60471 n = n === undefined$1 ? 1 : nativeMax(toInteger(n), 0);
60472 var result = this.__filtered__ && !index ? new LazyWrapper(this) : this.clone();
60474 if (result.__filtered__) {
60475 result.__takeCount__ = nativeMin(n, result.__takeCount__);
60477 result.__views__.push({
60478 'size': nativeMin(n, MAX_ARRAY_LENGTH),
60479 'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
60486 LazyWrapper.prototype[methodName + 'Right'] = function (n) {
60487 return this.reverse()[methodName](n).reverse();
60489 }); // Add `LazyWrapper` methods that accept an `iteratee` value.
60491 arrayEach(['filter', 'map', 'takeWhile'], function (methodName, index) {
60492 var type = index + 1,
60493 isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
60495 LazyWrapper.prototype[methodName] = function (iteratee) {
60496 var result = this.clone();
60498 result.__iteratees__.push({
60499 'iteratee': getIteratee(iteratee, 3),
60503 result.__filtered__ = result.__filtered__ || isFilter;
60506 }); // Add `LazyWrapper` methods for `_.head` and `_.last`.
60508 arrayEach(['head', 'last'], function (methodName, index) {
60509 var takeName = 'take' + (index ? 'Right' : '');
60511 LazyWrapper.prototype[methodName] = function () {
60512 return this[takeName](1).value()[0];
60514 }); // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
60516 arrayEach(['initial', 'tail'], function (methodName, index) {
60517 var dropName = 'drop' + (index ? '' : 'Right');
60519 LazyWrapper.prototype[methodName] = function () {
60520 return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
60524 LazyWrapper.prototype.compact = function () {
60525 return this.filter(identity);
60528 LazyWrapper.prototype.find = function (predicate) {
60529 return this.filter(predicate).head();
60532 LazyWrapper.prototype.findLast = function (predicate) {
60533 return this.reverse().find(predicate);
60536 LazyWrapper.prototype.invokeMap = baseRest(function (path, args) {
60537 if (typeof path == 'function') {
60538 return new LazyWrapper(this);
60541 return this.map(function (value) {
60542 return baseInvoke(value, path, args);
60546 LazyWrapper.prototype.reject = function (predicate) {
60547 return this.filter(negate(getIteratee(predicate)));
60550 LazyWrapper.prototype.slice = function (start, end) {
60551 start = toInteger(start);
60554 if (result.__filtered__ && (start > 0 || end < 0)) {
60555 return new LazyWrapper(result);
60559 result = result.takeRight(-start);
60560 } else if (start) {
60561 result = result.drop(start);
60564 if (end !== undefined$1) {
60565 end = toInteger(end);
60566 result = end < 0 ? result.dropRight(-end) : result.take(end - start);
60572 LazyWrapper.prototype.takeRightWhile = function (predicate) {
60573 return this.reverse().takeWhile(predicate).reverse();
60576 LazyWrapper.prototype.toArray = function () {
60577 return this.take(MAX_ARRAY_LENGTH);
60578 }; // Add `LazyWrapper` methods to `lodash.prototype`.
60581 baseForOwn(LazyWrapper.prototype, function (func, methodName) {
60582 var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
60583 isTaker = /^(?:head|last)$/.test(methodName),
60584 lodashFunc = lodash[isTaker ? 'take' + (methodName == 'last' ? 'Right' : '') : methodName],
60585 retUnwrapped = isTaker || /^find/.test(methodName);
60591 lodash.prototype[methodName] = function () {
60592 var value = this.__wrapped__,
60593 args = isTaker ? [1] : arguments,
60594 isLazy = value instanceof LazyWrapper,
60595 iteratee = args[0],
60596 useLazy = isLazy || isArray(value);
60598 var interceptor = function interceptor(value) {
60599 var result = lodashFunc.apply(lodash, arrayPush([value], args));
60600 return isTaker && chainAll ? result[0] : result;
60603 if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
60604 // Avoid lazy use if the iteratee has a "length" value other than `1`.
60605 isLazy = useLazy = false;
60608 var chainAll = this.__chain__,
60609 isHybrid = !!this.__actions__.length,
60610 isUnwrapped = retUnwrapped && !chainAll,
60611 onlyLazy = isLazy && !isHybrid;
60613 if (!retUnwrapped && useLazy) {
60614 value = onlyLazy ? value : new LazyWrapper(this);
60615 var result = func.apply(value, args);
60617 result.__actions__.push({
60619 'args': [interceptor],
60620 'thisArg': undefined$1
60623 return new LodashWrapper(result, chainAll);
60626 if (isUnwrapped && onlyLazy) {
60627 return func.apply(this, args);
60630 result = this.thru(interceptor);
60631 return isUnwrapped ? isTaker ? result.value()[0] : result.value() : result;
60633 }); // Add `Array` methods to `lodash.prototype`.
60635 arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function (methodName) {
60636 var func = arrayProto[methodName],
60637 chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
60638 retUnwrapped = /^(?:pop|shift)$/.test(methodName);
60640 lodash.prototype[methodName] = function () {
60641 var args = arguments;
60643 if (retUnwrapped && !this.__chain__) {
60644 var value = this.value();
60645 return func.apply(isArray(value) ? value : [], args);
60648 return this[chainName](function (value) {
60649 return func.apply(isArray(value) ? value : [], args);
60652 }); // Map minified method names to their real names.
60654 baseForOwn(LazyWrapper.prototype, function (func, methodName) {
60655 var lodashFunc = lodash[methodName];
60658 var key = lodashFunc.name + '';
60660 if (!hasOwnProperty.call(realNames, key)) {
60661 realNames[key] = [];
60664 realNames[key].push({
60665 'name': methodName,
60670 realNames[createHybrid(undefined$1, WRAP_BIND_KEY_FLAG).name] = [{
60672 'func': undefined$1
60673 }]; // Add methods to `LazyWrapper`.
60675 LazyWrapper.prototype.clone = lazyClone;
60676 LazyWrapper.prototype.reverse = lazyReverse;
60677 LazyWrapper.prototype.value = lazyValue; // Add chain sequence methods to the `lodash` wrapper.
60679 lodash.prototype.at = wrapperAt;
60680 lodash.prototype.chain = wrapperChain;
60681 lodash.prototype.commit = wrapperCommit;
60682 lodash.prototype.next = wrapperNext;
60683 lodash.prototype.plant = wrapperPlant;
60684 lodash.prototype.reverse = wrapperReverse;
60685 lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; // Add lazy aliases.
60687 lodash.prototype.first = lodash.prototype.head;
60690 lodash.prototype[symIterator] = wrapperToIterator;
60695 /*--------------------------------------------------------------------------*/
60699 var _ = runInContext(); // Some AMD build optimizers, like r.js, check for condition patterns like:
60703 // Export for Node.js.
60704 (freeModule.exports = _)._ = _; // Export for CommonJS support.
60708 // Export to the global object.
60711 }).call(commonjsGlobal);
60712 })(lodash, lodash.exports);
60714 function actionMergeRemoteChanges(id, localGraph, remoteGraph, discardTags, formatUser) {
60715 discardTags = discardTags || {};
60716 var _option = 'safe'; // 'safe', 'force_local', 'force_remote'
60718 var _conflicts = [];
60721 return typeof formatUser === 'function' ? formatUser(d) : lodash.exports.escape(d);
60724 function mergeLocation(remote, target) {
60725 function pointEqual(a, b) {
60726 var epsilon = 1e-6;
60727 return Math.abs(a[0] - b[0]) < epsilon && Math.abs(a[1] - b[1]) < epsilon;
60730 if (_option === 'force_local' || pointEqual(target.loc, remote.loc)) {
60734 if (_option === 'force_remote') {
60735 return target.update({
60740 _conflicts.push(_t.html('merge_remote_changes.conflict.location', {
60742 html: user(remote.user)
60749 function mergeNodes(base, remote, target) {
60750 if (_option === 'force_local' || fastDeepEqual(target.nodes, remote.nodes)) {
60754 if (_option === 'force_remote') {
60755 return target.update({
60756 nodes: remote.nodes
60760 var ccount = _conflicts.length;
60761 var o = base.nodes || [];
60762 var a = target.nodes || [];
60763 var b = remote.nodes || [];
60765 var hunks = diff3Merge(a, o, b, {
60766 excludeFalseConflicts: true
60769 for (var i = 0; i < hunks.length; i++) {
60770 var hunk = hunks[i];
60773 nodes.push.apply(nodes, hunk.ok);
60775 // for all conflicts, we can assume c.a !== c.b
60776 // because `diff3Merge` called with `true` option to exclude false conflicts..
60777 var c = hunk.conflict;
60779 if (fastDeepEqual(c.o, c.a)) {
60780 // only changed remotely
60781 nodes.push.apply(nodes, c.b);
60782 } else if (fastDeepEqual(c.o, c.b)) {
60783 // only changed locally
60784 nodes.push.apply(nodes, c.a);
60786 // changed both locally and remotely
60787 _conflicts.push(_t.html('merge_remote_changes.conflict.nodelist', {
60789 html: user(remote.user)
60798 return _conflicts.length === ccount ? target.update({
60803 function mergeChildren(targetWay, children, updates, graph) {
60804 function isUsed(node, targetWay) {
60805 var hasInterestingParent = graph.parentWays(node).some(function (way) {
60806 return way.id !== targetWay.id;
60808 return node.hasInterestingTags() || hasInterestingParent || graph.parentRelations(node).length > 0;
60811 var ccount = _conflicts.length;
60813 for (var i = 0; i < children.length; i++) {
60814 var id = children[i];
60815 var node = graph.hasEntity(id); // remove unused childNodes..
60817 if (targetWay.nodes.indexOf(id) === -1) {
60818 if (node && !isUsed(node, targetWay)) {
60819 updates.removeIds.push(id);
60823 } // restore used childNodes..
60826 var local = localGraph.hasEntity(id);
60827 var remote = remoteGraph.hasEntity(id);
60830 if (_option === 'force_remote' && remote && remote.visible) {
60831 updates.replacements.push(remote);
60832 } else if (_option === 'force_local' && local) {
60833 target = osmEntity(local);
60836 target = target.update({
60837 version: remote.version
60841 updates.replacements.push(target);
60842 } else if (_option === 'safe' && local && remote && local.version !== remote.version) {
60843 target = osmEntity(local, {
60844 version: remote.version
60847 if (remote.visible) {
60848 target = mergeLocation(remote, target);
60850 _conflicts.push(_t.html('merge_remote_changes.conflict.deleted', {
60852 html: user(remote.user)
60857 if (_conflicts.length !== ccount) break;
60858 updates.replacements.push(target);
60865 function updateChildren(updates, graph) {
60866 for (var i = 0; i < updates.replacements.length; i++) {
60867 graph = graph.replace(updates.replacements[i]);
60870 if (updates.removeIds.length) {
60871 graph = actionDeleteMultiple(updates.removeIds)(graph);
60877 function mergeMembers(remote, target) {
60878 if (_option === 'force_local' || fastDeepEqual(target.members, remote.members)) {
60882 if (_option === 'force_remote') {
60883 return target.update({
60884 members: remote.members
60888 _conflicts.push(_t.html('merge_remote_changes.conflict.memberlist', {
60890 html: user(remote.user)
60897 function mergeTags(base, remote, target) {
60898 if (_option === 'force_local' || fastDeepEqual(target.tags, remote.tags)) {
60902 if (_option === 'force_remote') {
60903 return target.update({
60908 var ccount = _conflicts.length;
60909 var o = base.tags || {};
60910 var a = target.tags || {};
60911 var b = remote.tags || {};
60912 var keys = utilArrayUnion(utilArrayUnion(Object.keys(o), Object.keys(a)), Object.keys(b)).filter(function (k) {
60913 return !discardTags[k];
60915 var tags = Object.assign({}, a); // shallow copy
60917 var changed = false;
60919 for (var i = 0; i < keys.length; i++) {
60922 if (o[k] !== b[k] && a[k] !== b[k]) {
60923 // changed remotely..
60924 if (o[k] !== a[k]) {
60925 // changed locally..
60926 _conflicts.push(_t.html('merge_remote_changes.conflict.tags', {
60931 html: user(remote.user)
60935 // unchanged locally, accept remote change..
60936 if (b.hasOwnProperty(k)) {
60947 return changed && _conflicts.length === ccount ? target.update({
60950 } // `graph.base()` is the common ancestor of the two graphs.
60951 // `localGraph` contains user's edits up to saving
60952 // `remoteGraph` contains remote edits to modified nodes
60953 // `graph` must be a descendent of `localGraph` and may include
60954 // some conflict resolution actions performed on it.
60956 // --- ... --- `localGraph` -- ... -- `graph`
60958 // `graph.base()` --- ... --- `remoteGraph`
60962 var action = function action(graph) {
60967 var base = graph.base().entities[id];
60968 var local = localGraph.entity(id);
60969 var remote = remoteGraph.entity(id);
60970 var target = osmEntity(local, {
60971 version: remote.version
60972 }); // delete/undelete
60974 if (!remote.visible) {
60975 if (_option === 'force_remote') {
60976 return actionDeleteMultiple([id])(graph);
60977 } else if (_option === 'force_local') {
60978 if (target.type === 'way') {
60979 target = mergeChildren(target, utilArrayUniq(local.nodes), updates, graph);
60980 graph = updateChildren(updates, graph);
60983 return graph.replace(target);
60985 _conflicts.push(_t.html('merge_remote_changes.conflict.deleted', {
60987 html: user(remote.user)
60991 return graph; // do nothing
60996 if (target.type === 'node') {
60997 target = mergeLocation(remote, target);
60998 } else if (target.type === 'way') {
60999 // pull in any child nodes that may not be present locally..
61000 graph.rebase(remoteGraph.childNodes(remote), [graph], false);
61001 target = mergeNodes(base, remote, target);
61002 target = mergeChildren(target, utilArrayUnion(local.nodes, remote.nodes), updates, graph);
61003 } else if (target.type === 'relation') {
61004 target = mergeMembers(remote, target);
61007 target = mergeTags(base, remote, target);
61009 if (!_conflicts.length) {
61010 graph = updateChildren(updates, graph).replace(target);
61016 action.withOption = function (opt) {
61021 action.conflicts = function () {
61028 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
61030 function actionMove(moveIDs, tryDelta, projection, cache) {
61031 var _delta = tryDelta;
61033 function setupCache(graph) {
61034 function canMove(nodeID) {
61035 // Allow movement of any node that is in the selectedIDs list..
61036 if (moveIDs.indexOf(nodeID) !== -1) return true; // Allow movement of a vertex where 2 ways meet..
61038 var parents = graph.parentWays(graph.entity(nodeID));
61039 if (parents.length < 3) return true; // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too..
61041 var parentsMoving = parents.every(function (way) {
61042 return cache.moving[way.id];
61044 if (!parentsMoving) delete cache.moving[nodeID];
61045 return parentsMoving;
61048 function cacheEntities(ids) {
61049 for (var i = 0; i < ids.length; i++) {
61051 if (cache.moving[id]) continue;
61052 cache.moving[id] = true;
61053 var entity = graph.hasEntity(id);
61054 if (!entity) continue;
61056 if (entity.type === 'node') {
61057 cache.nodes.push(id);
61058 cache.startLoc[id] = entity.loc;
61059 } else if (entity.type === 'way') {
61060 cache.ways.push(id);
61061 cacheEntities(entity.nodes);
61063 cacheEntities(entity.members.map(function (member) {
61070 function cacheIntersections(ids) {
61071 function isEndpoint(way, id) {
61072 return !way.isClosed() && !!way.affix(id);
61075 for (var i = 0; i < ids.length; i++) {
61076 var id = ids[i]; // consider only intersections with 1 moved and 1 unmoved way.
61078 var childNodes = graph.childNodes(graph.entity(id));
61080 for (var j = 0; j < childNodes.length; j++) {
61081 var node = childNodes[j];
61082 var parents = graph.parentWays(node);
61083 if (parents.length !== 2) continue;
61084 var moved = graph.entity(id);
61085 var unmoved = null;
61087 for (var k = 0; k < parents.length; k++) {
61088 var way = parents[k];
61090 if (!cache.moving[way.id]) {
61096 if (!unmoved) continue; // exclude ways that are overly connected..
61098 if (utilArrayIntersection(moved.nodes, unmoved.nodes).length > 2) continue;
61099 if (moved.isArea() || unmoved.isArea()) continue;
61100 cache.intersections.push({
61103 unmovedId: unmoved.id,
61104 movedIsEP: isEndpoint(moved, node.id),
61105 unmovedIsEP: isEndpoint(unmoved, node.id)
61117 cache.intersections = [];
61118 cache.replacedVertex = {};
61119 cache.startLoc = {};
61122 cacheEntities(moveIDs);
61123 cacheIntersections(cache.ways);
61124 cache.nodes = cache.nodes.filter(canMove);
61127 } // Place a vertex where the moved vertex used to be, to preserve way shape..
61136 // * node '*' added to preserve shape
61138 // / b ---- e way `b,e` moved here:
61145 function replaceMovedVertex(nodeId, wayId, graph, delta) {
61146 var way = graph.entity(wayId);
61147 var moved = graph.entity(nodeId);
61148 var movedIndex = way.nodes.indexOf(nodeId);
61149 var len, prevIndex, nextIndex;
61151 if (way.isClosed()) {
61152 len = way.nodes.length - 1;
61153 prevIndex = (movedIndex + len - 1) % len;
61154 nextIndex = (movedIndex + len + 1) % len;
61156 len = way.nodes.length;
61157 prevIndex = movedIndex - 1;
61158 nextIndex = movedIndex + 1;
61161 var prev = graph.hasEntity(way.nodes[prevIndex]);
61162 var next = graph.hasEntity(way.nodes[nextIndex]); // Don't add orig vertex at endpoint..
61164 if (!prev || !next) return graph;
61165 var key = wayId + '_' + nodeId;
61166 var orig = cache.replacedVertex[key];
61170 cache.replacedVertex[key] = orig;
61171 cache.startLoc[orig.id] = cache.startLoc[nodeId];
61177 start = projection(cache.startLoc[nodeId]);
61178 end = projection.invert(geoVecAdd(start, delta));
61180 end = cache.startLoc[nodeId];
61183 orig = orig.move(end);
61184 var angle = Math.abs(geoAngle(orig, prev, projection) - geoAngle(orig, next, projection)) * 180 / Math.PI; // Don't add orig vertex if it would just make a straight line..
61186 if (angle > 175 && angle < 185) return graph; // moving forward or backward along way?
61188 var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection);
61189 var p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection);
61190 var d1 = geoPathLength(p1);
61191 var d2 = geoPathLength(p2);
61192 var insertAt = d1 <= d2 ? movedIndex : nextIndex; // moving around closed loop?
61194 if (way.isClosed() && insertAt === 0) insertAt = len;
61195 way = way.addNode(orig.id, insertAt);
61196 return graph.replace(orig).replace(way);
61197 } // Remove duplicate vertex that might have been added by
61198 // replaceMovedVertex. This is done after the unzorro checks.
61201 function removeDuplicateVertices(wayId, graph) {
61202 var way = graph.entity(wayId);
61203 var epsilon = 1e-6;
61206 function isInteresting(node, graph) {
61207 return graph.parentWays(node).length > 1 || graph.parentRelations(node).length || node.hasInterestingTags();
61210 for (var i = 0; i < way.nodes.length; i++) {
61211 curr = graph.entity(way.nodes[i]);
61213 if (prev && curr && geoVecEqual(prev.loc, curr.loc, epsilon)) {
61214 if (!isInteresting(prev, graph)) {
61215 way = way.removeNode(prev.id);
61216 graph = graph.replace(way).remove(prev);
61217 } else if (!isInteresting(curr, graph)) {
61218 way = way.removeNode(curr.id);
61219 graph = graph.replace(way).remove(curr);
61227 } // Reorder nodes around intersections that have moved..
61229 // Start: way1.nodes: b,e (moving)
61230 // a - b - c ----- d way2.nodes: a,b,c,d (static)
61232 // e isEP1: true, isEP2, false
61234 // way1 `b,e` moved here:
61235 // a ----- c = b - d
61239 // reorder nodes way1.nodes: b,e
61240 // a ----- c - b - d way2.nodes: a,c,b,d
61246 function unZorroIntersection(intersection, graph) {
61247 var vertex = graph.entity(intersection.nodeId);
61248 var way1 = graph.entity(intersection.movedId);
61249 var way2 = graph.entity(intersection.unmovedId);
61250 var isEP1 = intersection.movedIsEP;
61251 var isEP2 = intersection.unmovedIsEP; // don't move the vertex if it is the endpoint of both ways.
61253 if (isEP1 && isEP2) return graph;
61254 var nodes1 = graph.childNodes(way1).filter(function (n) {
61255 return n !== vertex;
61257 var nodes2 = graph.childNodes(way2).filter(function (n) {
61258 return n !== vertex;
61260 if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
61261 if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
61262 var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection);
61263 var edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection);
61264 var loc; // snap vertex to nearest edge (or some point between them)..
61266 if (!isEP1 && !isEP2) {
61267 var epsilon = 1e-6,
61270 for (var i = 0; i < maxIter; i++) {
61271 loc = geoVecInterp(edge1.loc, edge2.loc, 0.5);
61272 edge1 = geoChooseEdge(nodes1, projection(loc), projection);
61273 edge2 = geoChooseEdge(nodes2, projection(loc), projection);
61274 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
61276 } else if (!isEP1) {
61282 graph = graph.replace(vertex.move(loc)); // if zorro happened, reorder nodes..
61284 if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
61285 way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
61286 graph = graph.replace(way1);
61289 if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
61290 way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
61291 graph = graph.replace(way2);
61297 function cleanupIntersections(graph) {
61298 for (var i = 0; i < cache.intersections.length; i++) {
61299 var obj = cache.intersections[i];
61300 graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, _delta);
61301 graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
61302 graph = unZorroIntersection(obj, graph);
61303 graph = removeDuplicateVertices(obj.movedId, graph);
61304 graph = removeDuplicateVertices(obj.unmovedId, graph);
61308 } // check if moving way endpoint can cross an unmoved way, if so limit delta..
61311 function limitDelta(graph) {
61312 function moveNode(loc) {
61313 return geoVecAdd(projection(loc), _delta);
61316 for (var i = 0; i < cache.intersections.length; i++) {
61317 var obj = cache.intersections[i]; // Don't limit movement if this is vertex joins 2 endpoints..
61319 if (obj.movedIsEP && obj.unmovedIsEP) continue; // Don't limit movement if this vertex is not an endpoint anyway..
61321 if (!obj.movedIsEP) continue;
61322 var node = graph.entity(obj.nodeId);
61323 var start = projection(node.loc);
61324 var end = geoVecAdd(start, _delta);
61325 var movedNodes = graph.childNodes(graph.entity(obj.movedId));
61326 var movedPath = movedNodes.map(function (n) {
61327 return moveNode(n.loc);
61329 var unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId));
61330 var unmovedPath = unmovedNodes.map(function (n) {
61331 return projection(n.loc);
61333 var hits = geoPathIntersections(movedPath, unmovedPath);
61335 for (var j = 0; i < hits.length; i++) {
61336 if (geoVecEqual(hits[j], end)) continue;
61337 var edge = geoChooseEdge(unmovedNodes, end, projection);
61338 _delta = geoVecSubtract(projection(edge.loc), start);
61343 var action = function action(graph) {
61344 if (_delta[0] === 0 && _delta[1] === 0) return graph;
61347 if (cache.intersections.length) {
61351 for (var i = 0; i < cache.nodes.length; i++) {
61352 var node = graph.entity(cache.nodes[i]);
61353 var start = projection(node.loc);
61354 var end = geoVecAdd(start, _delta);
61355 graph = graph.replace(node.move(projection.invert(end)));
61358 if (cache.intersections.length) {
61359 graph = cleanupIntersections(graph);
61365 action.delta = function () {
61372 function actionMoveMember(relationId, fromIndex, toIndex) {
61373 return function (graph) {
61374 return graph.replace(graph.entity(relationId).moveMember(fromIndex, toIndex));
61378 function actionMoveNode(nodeID, toLoc) {
61379 var action = function action(graph, t) {
61380 if (t === null || !isFinite(t)) t = 1;
61381 t = Math.min(Math.max(+t, 0), 1);
61382 var node = graph.entity(nodeID);
61383 return graph.replace(node.move(geoVecInterp(node.loc, toLoc, t)));
61386 action.transitionable = true;
61390 function actionNoop() {
61391 return function (graph) {
61396 function actionOrthogonalize(wayID, projection, vertexID, degThresh, ep) {
61397 var epsilon = ep || 1e-4;
61398 var threshold = degThresh || 13; // degrees within right or straight to alter
61399 // We test normalized dot products so we can compare as cos(angle)
61401 var lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180);
61402 var upperThreshold = Math.cos(threshold * Math.PI / 180);
61404 var action = function action(graph, t) {
61405 if (t === null || !isFinite(t)) t = 1;
61406 t = Math.min(Math.max(+t, 0), 1);
61407 var way = graph.entity(wayID);
61408 way = way.removeNode(''); // sanity check - remove any consecutive duplicates
61410 if (way.tags.nonsquare) {
61411 var tags = Object.assign({}, way.tags); // since we're squaring, remove indication that this is physically unsquare
61413 delete tags.nonsquare;
61419 graph = graph.replace(way);
61420 var isClosed = way.isClosed();
61421 var nodes = graph.childNodes(way).slice(); // shallow copy
61423 if (isClosed) nodes.pop();
61425 if (vertexID !== undefined) {
61426 nodes = nodeSubset(nodes, vertexID, isClosed);
61427 if (nodes.length !== 3) return graph;
61428 } // note: all geometry functions here use the unclosed node/point/coord list
61431 var nodeCount = {};
61437 var node, point, loc, score, motions, i, j;
61439 for (i = 0; i < nodes.length; i++) {
61441 nodeCount[node.id] = (nodeCount[node.id] || 0) + 1;
61444 coord: projection(node.loc)
61448 if (points.length === 3) {
61449 // move only one vertex for right triangle
61450 for (i = 0; i < 1000; i++) {
61451 motions = points.map(calcMotion);
61452 points[corner.i].coord = geoVecAdd(points[corner.i].coord, motions[corner.i]);
61453 score = corner.dotp;
61455 if (score < epsilon) {
61460 node = graph.entity(nodes[corner.i].id);
61461 loc = projection.invert(points[corner.i].coord);
61462 graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
61464 var straights = [];
61465 var simplified = []; // Remove points from nearly straight sections..
61466 // This produces a simplified shape to orthogonalize
61468 for (i = 0; i < points.length; i++) {
61472 if (isClosed || i > 0 && i < points.length - 1) {
61473 var a = points[(i - 1 + points.length) % points.length];
61474 var b = points[(i + 1) % points.length];
61475 dotp = Math.abs(geoOrthoNormalizedDotProduct(a.coord, b.coord, point.coord));
61478 if (dotp > upperThreshold) {
61479 straights.push(point);
61481 simplified.push(point);
61483 } // Orthogonalize the simplified shape
61486 var bestPoints = clonePoints(simplified);
61487 var originalPoints = clonePoints(simplified);
61490 for (i = 0; i < 1000; i++) {
61491 motions = simplified.map(calcMotion);
61493 for (j = 0; j < motions.length; j++) {
61494 simplified[j].coord = geoVecAdd(simplified[j].coord, motions[j]);
61497 var newScore = geoOrthoCalcScore(simplified, isClosed, epsilon, threshold);
61499 if (newScore < score) {
61500 bestPoints = clonePoints(simplified);
61504 if (score < epsilon) {
61509 var bestCoords = bestPoints.map(function (p) {
61512 if (isClosed) bestCoords.push(bestCoords[0]); // move the nodes that should move
61514 for (i = 0; i < bestPoints.length; i++) {
61515 point = bestPoints[i];
61517 if (!geoVecEqual(originalPoints[i].coord, point.coord)) {
61518 node = graph.entity(point.id);
61519 loc = projection.invert(point.coord);
61520 graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
61522 } // move the nodes along straight segments
61525 for (i = 0; i < straights.length; i++) {
61526 point = straights[i];
61527 if (nodeCount[point.id] > 1) continue; // skip self-intersections
61529 node = graph.entity(point.id);
61531 if (t === 1 && graph.parentWays(node).length === 1 && graph.parentRelations(node).length === 0 && !node.hasInterestingTags()) {
61532 // remove uninteresting points..
61533 graph = actionDeleteNode(node.id)(graph);
61535 // move interesting points to the nearest edge..
61536 var choice = geoVecProject(point.coord, bestCoords);
61539 loc = projection.invert(choice.target);
61540 graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
61548 function clonePoints(array) {
61549 return array.map(function (p) {
61552 coord: [p.coord[0], p.coord[1]]
61557 function calcMotion(point, i, array) {
61558 // don't try to move the endpoints of a non-closed way.
61559 if (!isClosed && (i === 0 || i === array.length - 1)) return [0, 0]; // don't try to move a node that appears more than once (self intersection)
61561 if (nodeCount[array[i].id] > 1) return [0, 0];
61562 var a = array[(i - 1 + array.length) % array.length].coord;
61563 var origin = point.coord;
61564 var b = array[(i + 1) % array.length].coord;
61565 var p = geoVecSubtract(a, origin);
61566 var q = geoVecSubtract(b, origin);
61567 var scale = 2 * Math.min(geoVecLength(p), geoVecLength(q));
61568 p = geoVecNormalize(p);
61569 q = geoVecNormalize(q);
61570 var dotp = p[0] * q[0] + p[1] * q[1];
61571 var val = Math.abs(dotp);
61573 if (val < lowerThreshold) {
61574 // nearly orthogonal
61577 var vec = geoVecNormalize(geoVecAdd(p, q));
61578 return geoVecScale(vec, 0.1 * dotp * scale);
61581 return [0, 0]; // do nothing
61583 }; // if we are only orthogonalizing one vertex,
61584 // get that vertex and the previous and next
61587 function nodeSubset(nodes, vertexID, isClosed) {
61588 var first = isClosed ? 0 : 1;
61589 var last = isClosed ? nodes.length : nodes.length - 1;
61591 for (var i = first; i < last; i++) {
61592 if (nodes[i].id === vertexID) {
61593 return [nodes[(i - 1 + nodes.length) % nodes.length], nodes[i], nodes[(i + 1) % nodes.length]];
61600 action.disabled = function (graph) {
61601 var way = graph.entity(wayID);
61602 way = way.removeNode(''); // sanity check - remove any consecutive duplicates
61604 graph = graph.replace(way);
61605 var isClosed = way.isClosed();
61606 var nodes = graph.childNodes(way).slice(); // shallow copy
61608 if (isClosed) nodes.pop();
61609 var allowStraightAngles = false;
61611 if (vertexID !== undefined) {
61612 allowStraightAngles = true;
61613 nodes = nodeSubset(nodes, vertexID, isClosed);
61614 if (nodes.length !== 3) return 'end_vertex';
61617 var coords = nodes.map(function (n) {
61618 return projection(n.loc);
61620 var score = geoOrthoCanOrthogonalize(coords, isClosed, epsilon, threshold, allowStraightAngles);
61622 if (score === null) {
61623 return 'not_squarish';
61624 } else if (score === 0) {
61625 return 'square_enough';
61631 action.transitionable = true;
61636 // `turn` must be an `osmTurn` object
61637 // see osm/intersection.js, pathToTurn()
61639 // This specifies a restriction of type `restriction` when traveling from
61640 // `turn.from.way` toward `turn.to.way` via `turn.via.node` OR `turn.via.ways`.
61641 // (The action does not check that these entities form a valid intersection.)
61643 // From, to, and via ways should be split before calling this action.
61644 // (old versions of the code would split the ways here, but we no longer do it)
61646 // For testing convenience, accepts a restrictionID to assign to the new
61647 // relation. Normally, this will be undefined and the relation will
61648 // automatically be assigned a new ID.
61651 function actionRestrictTurn(turn, restrictionType, restrictionID) {
61652 return function (graph) {
61653 var fromWay = graph.entity(turn.from.way);
61654 var toWay = graph.entity(turn.to.way);
61655 var viaNode = turn.via.node && graph.entity(turn.via.node);
61656 var viaWays = turn.via.ways && turn.via.ways.map(function (id) {
61657 return graph.entity(id);
61672 } else if (viaWays) {
61673 viaWays.forEach(function (viaWay) {
61687 return graph.replace(osmRelation({
61690 type: 'restriction',
61691 restriction: restrictionType
61698 function actionRevert(id) {
61699 var action = function action(graph) {
61700 var entity = graph.hasEntity(id),
61701 base = graph.base().entities[id];
61703 if (entity && !base) {
61704 // entity will be removed..
61705 if (entity.type === 'node') {
61706 graph.parentWays(entity).forEach(function (parent) {
61707 parent = parent.removeNode(id);
61708 graph = graph.replace(parent);
61710 if (parent.isDegenerate()) {
61711 graph = actionDeleteWay(parent.id)(graph);
61716 graph.parentRelations(entity).forEach(function (parent) {
61717 parent = parent.removeMembersWithID(id);
61718 graph = graph.replace(parent);
61720 if (parent.isDegenerate()) {
61721 graph = actionDeleteRelation(parent.id)(graph);
61726 return graph.revert(id);
61732 function actionRotate(rotateIds, pivot, angle, projection) {
61733 var action = function action(graph) {
61734 return graph.update(function (graph) {
61735 utilGetAllNodes(rotateIds, graph).forEach(function (node) {
61736 var point = geoRotate([projection(node.loc)], angle, pivot)[0];
61737 graph = graph.replace(node.move(projection.invert(point)));
61745 function actionScale(ids, pivotLoc, scaleFactor, projection) {
61746 return function (graph) {
61747 return graph.update(function (graph) {
61749 utilGetAllNodes(ids, graph).forEach(function (node) {
61750 point = projection(node.loc);
61751 radial = [point[0] - pivotLoc[0], point[1] - pivotLoc[1]];
61752 point = [pivotLoc[0] + scaleFactor * radial[0], pivotLoc[1] + scaleFactor * radial[1]];
61753 graph = graph.replace(node.move(projection.invert(point)));
61759 /* Align nodes along their common axis */
61761 function actionStraightenNodes(nodeIDs, projection) {
61762 function positionAlongWay(a, o, b) {
61763 return geoVecDot(a, b, o) / geoVecDot(b, b, o);
61764 } // returns the endpoints of the long axis of symmetry of the `points` bounding rect
61767 function getEndpoints(points) {
61768 var ssr = geoGetSmallestSurroundingRectangle(points); // Choose line pq = axis of symmetry.
61769 // The shape's surrounding rectangle has 2 axes of symmetry.
61770 // Snap points to the long axis
61772 var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2];
61773 var q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2];
61774 var p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2];
61775 var q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2];
61776 var isLong = geoVecLength(p1, q1) > geoVecLength(p2, q2);
61785 var action = function action(graph, t) {
61786 if (t === null || !isFinite(t)) t = 1;
61787 t = Math.min(Math.max(+t, 0), 1);
61788 var nodes = nodeIDs.map(function (id) {
61789 return graph.entity(id);
61791 var points = nodes.map(function (n) {
61792 return projection(n.loc);
61794 var endpoints = getEndpoints(points);
61795 var startPoint = endpoints[0];
61796 var endPoint = endpoints[1]; // Move points onto the line connecting the endpoints
61798 for (var i = 0; i < points.length; i++) {
61799 var node = nodes[i];
61800 var point = points[i];
61801 var u = positionAlongWay(point, startPoint, endPoint);
61802 var point2 = geoVecInterp(startPoint, endPoint, u);
61803 var loc2 = projection.invert(point2);
61804 graph = graph.replace(node.move(geoVecInterp(node.loc, loc2, t)));
61810 action.disabled = function (graph) {
61811 var nodes = nodeIDs.map(function (id) {
61812 return graph.entity(id);
61814 var points = nodes.map(function (n) {
61815 return projection(n.loc);
61817 var endpoints = getEndpoints(points);
61818 var startPoint = endpoints[0];
61819 var endPoint = endpoints[1];
61820 var maxDistance = 0;
61822 for (var i = 0; i < points.length; i++) {
61823 var point = points[i];
61824 var u = positionAlongWay(point, startPoint, endPoint);
61825 var p = geoVecInterp(startPoint, endPoint, u);
61826 var dist = geoVecLength(p, point);
61828 if (!isNaN(dist) && dist > maxDistance) {
61829 maxDistance = dist;
61833 if (maxDistance < 0.0001) {
61834 return 'straight_enough';
61838 action.transitionable = true;
61843 * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
61846 function actionStraightenWay(selectedIDs, projection) {
61847 function positionAlongWay(a, o, b) {
61848 return geoVecDot(a, b, o) / geoVecDot(b, b, o);
61849 } // Return all selected ways as a continuous, ordered array of nodes
61852 function allNodes(graph) {
61854 var startNodes = [];
61856 var remainingWays = [];
61857 var selectedWays = selectedIDs.filter(function (w) {
61858 return graph.entity(w).type === 'way';
61860 var selectedNodes = selectedIDs.filter(function (n) {
61861 return graph.entity(n).type === 'node';
61864 for (var i = 0; i < selectedWays.length; i++) {
61865 var way = graph.entity(selectedWays[i]);
61866 nodes = way.nodes.slice(0);
61867 remainingWays.push(nodes);
61868 startNodes.push(nodes[0]);
61869 endNodes.push(nodes[nodes.length - 1]);
61870 } // Remove duplicate end/startNodes (duplicate nodes cannot be at the line end,
61871 // and need to be removed so currNode difference calculation below works)
61872 // i.e. ["n-1", "n-1", "n-2"] => ["n-2"]
61875 startNodes = startNodes.filter(function (n) {
61876 return startNodes.indexOf(n) === startNodes.lastIndexOf(n);
61878 endNodes = endNodes.filter(function (n) {
61879 return endNodes.indexOf(n) === endNodes.lastIndexOf(n);
61880 }); // Choose the initial endpoint to start from
61882 var currNode = utilArrayDifference(startNodes, endNodes).concat(utilArrayDifference(endNodes, startNodes))[0];
61884 nodes = []; // Create nested function outside of loop to avoid "function in loop" lint error
61886 var getNextWay = function getNextWay(currNode, remainingWays) {
61887 return remainingWays.filter(function (way) {
61888 return way[0] === currNode || way[way.length - 1] === currNode;
61890 }; // Add nodes to end of nodes array, until all ways are added
61893 while (remainingWays.length) {
61894 nextWay = getNextWay(currNode, remainingWays);
61895 remainingWays = utilArrayDifference(remainingWays, [nextWay]);
61897 if (nextWay[0] !== currNode) {
61901 nodes = nodes.concat(nextWay);
61902 currNode = nodes[nodes.length - 1];
61903 } // If user selected 2 nodes to straighten between, then slice nodes array to those nodes
61906 if (selectedNodes.length === 2) {
61907 var startNodeIdx = nodes.indexOf(selectedNodes[0]);
61908 var endNodeIdx = nodes.indexOf(selectedNodes[1]);
61909 var sortedStartEnd = [startNodeIdx, endNodeIdx];
61910 sortedStartEnd.sort(function (a, b) {
61913 nodes = nodes.slice(sortedStartEnd[0], sortedStartEnd[1] + 1);
61916 return nodes.map(function (n) {
61917 return graph.entity(n);
61921 function shouldKeepNode(node, graph) {
61922 return graph.parentWays(node).length > 1 || graph.parentRelations(node).length || node.hasInterestingTags();
61925 var action = function action(graph, t) {
61926 if (t === null || !isFinite(t)) t = 1;
61927 t = Math.min(Math.max(+t, 0), 1);
61928 var nodes = allNodes(graph);
61929 var points = nodes.map(function (n) {
61930 return projection(n.loc);
61932 var startPoint = points[0];
61933 var endPoint = points[points.length - 1];
61937 for (i = 1; i < points.length - 1; i++) {
61938 var node = nodes[i];
61939 var point = points[i];
61941 if (t < 1 || shouldKeepNode(node, graph)) {
61942 var u = positionAlongWay(point, startPoint, endPoint);
61943 var p = geoVecInterp(startPoint, endPoint, u);
61944 var loc2 = projection.invert(p);
61945 graph = graph.replace(node.move(geoVecInterp(node.loc, loc2, t)));
61948 if (toDelete.indexOf(node) === -1) {
61949 toDelete.push(node);
61954 for (i = 0; i < toDelete.length; i++) {
61955 graph = actionDeleteNode(toDelete[i].id)(graph);
61961 action.disabled = function (graph) {
61962 // check way isn't too bendy
61963 var nodes = allNodes(graph);
61964 var points = nodes.map(function (n) {
61965 return projection(n.loc);
61967 var startPoint = points[0];
61968 var endPoint = points[points.length - 1];
61969 var threshold = 0.2 * geoVecLength(startPoint, endPoint);
61972 if (threshold === 0) {
61973 return 'too_bendy';
61976 var maxDistance = 0;
61978 for (i = 1; i < points.length - 1; i++) {
61979 var point = points[i];
61980 var u = positionAlongWay(point, startPoint, endPoint);
61981 var p = geoVecInterp(startPoint, endPoint, u);
61982 var dist = geoVecLength(p, point); // to bendy if point is off by 20% of total start/end distance in projected space
61984 if (isNaN(dist) || dist > threshold) {
61985 return 'too_bendy';
61986 } else if (dist > maxDistance) {
61987 maxDistance = dist;
61991 var keepingAllNodes = nodes.every(function (node, i) {
61992 return i === 0 || i === nodes.length - 1 || shouldKeepNode(node, graph);
61995 if (maxDistance < 0.0001 && // Allow straightening even if already straight in order to remove extraneous nodes
61997 return 'straight_enough';
62001 action.transitionable = true;
62006 // `turn` must be an `osmTurn` object with a `restrictionID` property.
62007 // see osm/intersection.js, pathToTurn()
62010 function actionUnrestrictTurn(turn) {
62011 return function (graph) {
62012 return actionDeleteRelation(turn.restrictionID)(graph);
62016 /* Reflect the given area around its axis of symmetry */
62018 function actionReflect(reflectIds, projection) {
62019 var _useLongAxis = true;
62021 var action = function action(graph, t) {
62022 if (t === null || !isFinite(t)) t = 1;
62023 t = Math.min(Math.max(+t, 0), 1);
62024 var nodes = utilGetAllNodes(reflectIds, graph);
62025 var points = nodes.map(function (n) {
62026 return projection(n.loc);
62028 var ssr = geoGetSmallestSurroundingRectangle(points); // Choose line pq = axis of symmetry.
62029 // The shape's surrounding rectangle has 2 axes of symmetry.
62030 // Reflect across the longer axis by default.
62032 var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2];
62033 var q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2];
62034 var p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2];
62035 var q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2];
62037 var isLong = geoVecLength(p1, q1) > geoVecLength(p2, q2);
62039 if (_useLongAxis && isLong || !_useLongAxis && !isLong) {
62045 } // reflect c across pq
62046 // http://math.stackexchange.com/questions/65503/point-reflection-over-a-line
62049 var dx = q[0] - p[0];
62050 var dy = q[1] - p[1];
62051 var a = (dx * dx - dy * dy) / (dx * dx + dy * dy);
62052 var b = 2 * dx * dy / (dx * dx + dy * dy);
62054 for (var i = 0; i < nodes.length; i++) {
62055 var node = nodes[i];
62056 var c = projection(node.loc);
62057 var c2 = [a * (c[0] - p[0]) + b * (c[1] - p[1]) + p[0], b * (c[0] - p[0]) - a * (c[1] - p[1]) + p[1]];
62058 var loc2 = projection.invert(c2);
62059 node = node.move(geoVecInterp(node.loc, loc2, t));
62060 graph = graph.replace(node);
62066 action.useLongAxis = function (val) {
62067 if (!arguments.length) return _useLongAxis;
62068 _useLongAxis = val;
62072 action.transitionable = true;
62076 function actionUpgradeTags(entityId, oldTags, replaceTags) {
62077 return function (graph) {
62078 var entity = graph.entity(entityId);
62079 var tags = Object.assign({}, entity.tags); // shallow copy
62084 for (var oldTagKey in oldTags) {
62085 if (!(oldTagKey in tags)) continue; // wildcard match
62087 if (oldTags[oldTagKey] === '*') {
62088 // note the value since we might need to transfer it
62089 transferValue = tags[oldTagKey];
62090 delete tags[oldTagKey]; // exact match
62091 } else if (oldTags[oldTagKey] === tags[oldTagKey]) {
62092 delete tags[oldTagKey]; // match is within semicolon-delimited values
62094 var vals = tags[oldTagKey].split(';').filter(Boolean);
62095 var oldIndex = vals.indexOf(oldTags[oldTagKey]);
62097 if (vals.length === 1 || oldIndex === -1) {
62098 delete tags[oldTagKey];
62100 if (replaceTags && replaceTags[oldTagKey]) {
62101 // replacing a value within a semicolon-delimited value, note the index
62102 semiIndex = oldIndex;
62105 vals.splice(oldIndex, 1);
62106 tags[oldTagKey] = vals.join(';');
62112 for (var replaceKey in replaceTags) {
62113 var replaceValue = replaceTags[replaceKey];
62115 if (replaceValue === '*') {
62116 if (tags[replaceKey] && tags[replaceKey] !== 'no') {
62117 // allow any pre-existing value except `no` (troll tag)
62120 // otherwise assume `yes` is okay
62121 tags[replaceKey] = 'yes';
62123 } else if (replaceValue === '$1') {
62124 tags[replaceKey] = transferValue;
62126 if (tags[replaceKey] && oldTags[replaceKey] && semiIndex !== undefined) {
62127 // don't override preexisting values
62128 var existingVals = tags[replaceKey].split(';').filter(Boolean);
62130 if (existingVals.indexOf(replaceValue) === -1) {
62131 existingVals.splice(semiIndex, 0, replaceValue);
62132 tags[replaceKey] = existingVals.join(';');
62135 tags[replaceKey] = replaceValue;
62141 return graph.replace(entity.update({
62147 function behaviorEdit(context) {
62148 function behavior() {
62149 context.map().minzoom(context.minEditableZoom());
62152 behavior.off = function () {
62153 context.map().minzoom(0);
62160 The hover behavior adds the `.hover` class on pointerover to all elements to which
62161 the identical datum is bound, and removes it on pointerout.
62163 The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
62164 representation may consist of several elements scattered throughout the DOM hierarchy.
62165 Only one of these elements can have the :hover pseudo-class, but all of them will
62166 have the .hover class.
62169 function behaviorHover(context) {
62170 var dispatch = dispatch$8('hover');
62172 var _selection = select(null);
62174 var _newNodeId = null;
62175 var _initialNodeID = null;
62181 var _targets = []; // use pointer events on supported platforms; fallback to mouse events
62183 var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
62185 function keydown(d3_event) {
62186 if (_altDisables && d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
62187 _selection.selectAll('.hover').classed('hover-suppressed', true).classed('hover', false);
62189 _selection.classed('hover-disabled', true);
62191 dispatch.call('hover', this, null);
62195 function keyup(d3_event) {
62196 if (_altDisables && d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
62197 _selection.selectAll('.hover-suppressed').classed('hover-suppressed', false).classed('hover', true);
62199 _selection.classed('hover-disabled', false);
62201 dispatch.call('hover', this, _targets);
62205 function behavior(selection) {
62206 _selection = selection;
62209 if (_initialNodeID) {
62210 _newNodeId = _initialNodeID;
62211 _initialNodeID = null;
62216 _selection.on(_pointerPrefix + 'over.hover', pointerover).on(_pointerPrefix + 'out.hover', pointerout) // treat pointerdown as pointerover for touch devices
62217 .on(_pointerPrefix + 'down.hover', pointerover);
62219 select(window).on(_pointerPrefix + 'up.hover pointercancel.hover', pointerout, true).on('keydown.hover', keydown).on('keyup.hover', keyup);
62221 function eventTarget(d3_event) {
62222 var datum = d3_event.target && d3_event.target.__data__;
62223 if (_typeof(datum) !== 'object') return null;
62225 if (!(datum instanceof osmEntity) && datum.properties && datum.properties.entity instanceof osmEntity) {
62226 return datum.properties.entity;
62232 function pointerover(d3_event) {
62233 // ignore mouse hovers with buttons pressed unless dragging
62234 if (context.mode().id.indexOf('drag') === -1 && (!d3_event.pointerType || d3_event.pointerType === 'mouse') && d3_event.buttons) return;
62235 var target = eventTarget(d3_event);
62237 if (target && _targets.indexOf(target) === -1) {
62238 _targets.push(target);
62240 updateHover(d3_event, _targets);
62244 function pointerout(d3_event) {
62245 var target = eventTarget(d3_event);
62247 var index = _targets.indexOf(target);
62249 if (index !== -1) {
62250 _targets.splice(index);
62252 updateHover(d3_event, _targets);
62256 function allowsVertex(d) {
62257 return d.geometry(context.graph()) === 'vertex' || _mainPresetIndex.allowsVertex(d, context.graph());
62260 function modeAllowsHover(target) {
62261 var mode = context.mode();
62263 if (mode.id === 'add-point') {
62264 return mode.preset.matchGeometry('vertex') || target.type !== 'way' && target.geometry(context.graph()) !== 'vertex';
62270 function updateHover(d3_event, targets) {
62271 _selection.selectAll('.hover').classed('hover', false);
62273 _selection.selectAll('.hover-suppressed').classed('hover-suppressed', false);
62275 var mode = context.mode();
62277 if (!_newNodeId && (mode.id === 'draw-line' || mode.id === 'draw-area')) {
62278 var node = targets.find(function (target) {
62279 return target instanceof osmEntity && target.type === 'node';
62281 _newNodeId = node && node.id;
62284 targets = targets.filter(function (datum) {
62285 if (datum instanceof osmEntity) {
62286 // If drawing a way, don't hover on a node that was just placed. #3974
62287 return datum.id !== _newNodeId && (datum.type !== 'node' || !_ignoreVertex || allowsVertex(datum)) && modeAllowsHover(datum);
62294 for (var i in targets) {
62295 var datum = targets[i]; // What are we hovering over?
62297 if (datum.__featurehash__) {
62298 // hovering custom data
62299 selector += ', .data' + datum.__featurehash__;
62300 } else if (datum instanceof QAItem) {
62301 selector += ', .' + datum.service + '.itemId-' + datum.id;
62302 } else if (datum instanceof osmNote) {
62303 selector += ', .note-' + datum.id;
62304 } else if (datum instanceof osmEntity) {
62305 selector += ', .' + datum.id;
62307 if (datum.type === 'relation') {
62308 for (var j in datum.members) {
62309 selector += ', .' + datum.members[j].id;
62315 var suppressed = _altDisables && d3_event && d3_event.altKey;
62317 if (selector.trim().length) {
62318 // remove the first comma
62319 selector = selector.slice(1);
62321 _selection.selectAll(selector).classed(suppressed ? 'hover-suppressed' : 'hover', true);
62324 dispatch.call('hover', this, !suppressed && targets);
62328 behavior.off = function (selection) {
62329 selection.selectAll('.hover').classed('hover', false);
62330 selection.selectAll('.hover-suppressed').classed('hover-suppressed', false);
62331 selection.classed('hover-disabled', false);
62332 selection.on(_pointerPrefix + 'over.hover', null).on(_pointerPrefix + 'out.hover', null).on(_pointerPrefix + 'down.hover', null);
62333 select(window).on(_pointerPrefix + 'up.hover pointercancel.hover', null, true).on('keydown.hover', null).on('keyup.hover', null);
62336 behavior.altDisables = function (val) {
62337 if (!arguments.length) return _altDisables;
62338 _altDisables = val;
62342 behavior.ignoreVertex = function (val) {
62343 if (!arguments.length) return _ignoreVertex;
62344 _ignoreVertex = val;
62348 behavior.initialNodeID = function (nodeId) {
62349 _initialNodeID = nodeId;
62353 return utilRebind(behavior, dispatch, 'on');
62356 var _disableSpace = false;
62357 var _lastSpace = null;
62358 function behaviorDraw(context) {
62359 var dispatch = dispatch$8('move', 'down', 'downcancel', 'click', 'clickWay', 'clickNode', 'undo', 'cancel', 'finish');
62360 var keybinding = utilKeybinding('draw');
62362 var _hover = behaviorHover(context).altDisables(true).ignoreVertex(true).on('hover', context.ui().sidebar.hover);
62364 var _edit = behaviorEdit(context);
62366 var _closeTolerance = 4;
62367 var _tolerance = 12;
62368 var _mouseLeave = false;
62369 var _lastMouse = null;
62371 var _lastPointerUpEvent;
62373 var _downPointer; // use pointer events on supported platforms; fallback to mouse events
62376 var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse'; // related code
62377 // - `mode/drag_node.js` `datum()`
62380 function datum(d3_event) {
62381 var mode = context.mode();
62382 var isNote = mode && mode.id.indexOf('note') !== -1;
62383 if (d3_event.altKey || isNote) return {};
62386 if (d3_event.type === 'keydown') {
62387 element = _lastMouse && _lastMouse.target;
62389 element = d3_event.target;
62390 } // When drawing, snap only to touch targets..
62391 // (this excludes area fills and active drawing elements)
62394 var d = element.__data__;
62395 return d && d.properties && d.properties.target ? d : {};
62398 function pointerdown(d3_event) {
62399 if (_downPointer) return;
62400 var pointerLocGetter = utilFastMouse(this);
62402 id: d3_event.pointerId || 'mouse',
62403 pointerLocGetter: pointerLocGetter,
62404 downTime: +new Date(),
62405 downLoc: pointerLocGetter(d3_event)
62407 dispatch.call('down', this, d3_event, datum(d3_event));
62410 function pointerup(d3_event) {
62411 if (!_downPointer || _downPointer.id !== (d3_event.pointerId || 'mouse')) return;
62412 var downPointer = _downPointer;
62413 _downPointer = null;
62414 _lastPointerUpEvent = d3_event;
62415 if (downPointer.isCancelled) return;
62416 var t2 = +new Date();
62417 var p2 = downPointer.pointerLocGetter(d3_event);
62418 var dist = geoVecLength(downPointer.downLoc, p2);
62420 if (dist < _closeTolerance || dist < _tolerance && t2 - downPointer.downTime < 500) {
62421 // Prevent a quick second click
62422 select(window).on('click.draw-block', function () {
62423 d3_event.stopPropagation();
62425 context.map().dblclickZoomEnable(false);
62426 window.setTimeout(function () {
62427 context.map().dblclickZoomEnable(true);
62428 select(window).on('click.draw-block', null);
62430 click(d3_event, p2);
62434 function pointermove(d3_event) {
62435 if (_downPointer && _downPointer.id === (d3_event.pointerId || 'mouse') && !_downPointer.isCancelled) {
62436 var p2 = _downPointer.pointerLocGetter(d3_event);
62438 var dist = geoVecLength(_downPointer.downLoc, p2);
62440 if (dist >= _closeTolerance) {
62441 _downPointer.isCancelled = true;
62442 dispatch.call('downcancel', this);
62446 if (d3_event.pointerType && d3_event.pointerType !== 'mouse' || d3_event.buttons || _downPointer) return; // HACK: Mobile Safari likes to send one or more `mouse` type pointermove
62447 // events immediately after non-mouse pointerup events; detect and ignore them.
62449 if (_lastPointerUpEvent && _lastPointerUpEvent.pointerType !== 'mouse' && d3_event.timeStamp - _lastPointerUpEvent.timeStamp < 100) return;
62450 _lastMouse = d3_event;
62451 dispatch.call('move', this, d3_event, datum(d3_event));
62454 function pointercancel(d3_event) {
62455 if (_downPointer && _downPointer.id === (d3_event.pointerId || 'mouse')) {
62456 if (!_downPointer.isCancelled) {
62457 dispatch.call('downcancel', this);
62460 _downPointer = null;
62464 function mouseenter() {
62465 _mouseLeave = false;
62468 function mouseleave() {
62469 _mouseLeave = true;
62472 function allowsVertex(d) {
62473 return d.geometry(context.graph()) === 'vertex' || _mainPresetIndex.allowsVertex(d, context.graph());
62475 // - `mode/drag_node.js` `doMove()`
62476 // - `behavior/draw.js` `click()`
62477 // - `behavior/draw_way.js` `move()`
62480 function click(d3_event, loc) {
62481 var d = datum(d3_event);
62482 var target = d && d.properties && d.properties.entity;
62483 var mode = context.mode();
62485 if (target && target.type === 'node' && allowsVertex(target)) {
62487 dispatch.call('clickNode', this, target, d);
62489 } else if (target && target.type === 'way' && (mode.id !== 'add-point' || mode.preset.matchGeometry('vertex'))) {
62491 var choice = geoChooseEdge(context.graph().childNodes(target), loc, context.projection, context.activeID());
62494 var edge = [target.nodes[choice.index - 1], target.nodes[choice.index]];
62495 dispatch.call('clickWay', this, choice.loc, edge, d);
62498 } else if (mode.id !== 'add-point' || mode.preset.matchGeometry('point')) {
62499 var locLatLng = context.projection.invert(loc);
62500 dispatch.call('click', this, locLatLng, d);
62502 } // treat a spacebar press like a click
62505 function space(d3_event) {
62506 d3_event.preventDefault();
62507 d3_event.stopPropagation();
62508 var currSpace = context.map().mouse();
62510 if (_disableSpace && _lastSpace) {
62511 var dist = geoVecLength(_lastSpace, currSpace);
62513 if (dist > _tolerance) {
62514 _disableSpace = false;
62518 if (_disableSpace || _mouseLeave || !_lastMouse) return; // user must move mouse or release space bar to allow another click
62520 _lastSpace = currSpace;
62521 _disableSpace = true;
62522 select(window).on('keyup.space-block', function () {
62523 d3_event.preventDefault();
62524 d3_event.stopPropagation();
62525 _disableSpace = false;
62526 select(window).on('keyup.space-block', null);
62527 }); // get the current mouse position
62529 var loc = context.map().mouse() || // or the map center if the mouse has never entered the map
62530 context.projection(context.map().center());
62531 click(d3_event, loc);
62534 function backspace(d3_event) {
62535 d3_event.preventDefault();
62536 dispatch.call('undo');
62539 function del(d3_event) {
62540 d3_event.preventDefault();
62541 dispatch.call('cancel');
62544 function ret(d3_event) {
62545 d3_event.preventDefault();
62546 dispatch.call('finish');
62549 function behavior(selection) {
62550 context.install(_hover);
62551 context.install(_edit);
62552 _downPointer = null;
62553 keybinding.on('⌫', backspace).on('⌦', del).on('⎋', ret).on('↩', ret).on('space', space).on('⌥space', space);
62554 selection.on('mouseenter.draw', mouseenter).on('mouseleave.draw', mouseleave).on(_pointerPrefix + 'down.draw', pointerdown).on(_pointerPrefix + 'move.draw', pointermove);
62555 select(window).on(_pointerPrefix + 'up.draw', pointerup, true).on('pointercancel.draw', pointercancel, true);
62556 select(document).call(keybinding);
62560 behavior.off = function (selection) {
62561 context.ui().sidebar.hover.cancel();
62562 context.uninstall(_hover);
62563 context.uninstall(_edit);
62564 selection.on('mouseenter.draw', null).on('mouseleave.draw', null).on(_pointerPrefix + 'down.draw', null).on(_pointerPrefix + 'move.draw', null);
62565 select(window).on(_pointerPrefix + 'up.draw', null).on('pointercancel.draw', null); // note: keyup.space-block, click.draw-block should remain
62567 select(document).call(keybinding.unbind);
62570 behavior.hover = function () {
62574 return utilRebind(behavior, dispatch, 'on');
62577 function initRange(domain, range) {
62578 switch (arguments.length) {
62583 this.range(domain);
62587 this.range(range).domain(domain);
62594 function constants(x) {
62595 return function () {
62600 function number(x) {
62605 function identity$1(x) {
62609 function normalize(a, b) {
62610 return (b -= a = +a) ? function (x) {
62611 return (x - a) / b;
62612 } : constants(isNaN(b) ? NaN : 0.5);
62615 function clamper(a, b) {
62617 if (a > b) t = a, a = b, b = t;
62618 return function (x) {
62619 return Math.max(a, Math.min(b, x));
62621 } // normalize(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
62622 // interpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding range value x in [a,b].
62625 function bimap(domain, range, interpolate) {
62626 var d0 = domain[0],
62630 if (d1 < d0) d0 = normalize(d1, d0), r0 = interpolate(r1, r0);else d0 = normalize(d0, d1), r0 = interpolate(r0, r1);
62631 return function (x) {
62636 function polymap(domain, range, interpolate) {
62637 var j = Math.min(domain.length, range.length) - 1,
62640 i = -1; // Reverse descending domains.
62642 if (domain[j] < domain[0]) {
62643 domain = domain.slice().reverse();
62644 range = range.slice().reverse();
62648 d[i] = normalize(domain[i], domain[i + 1]);
62649 r[i] = interpolate(range[i], range[i + 1]);
62652 return function (x) {
62653 var i = bisectRight(domain, x, 1, j) - 1;
62654 return r[i](d[i](x));
62658 function copy(source, target) {
62659 return target.domain(source.domain()).range(source.range()).interpolate(source.interpolate()).clamp(source.clamp()).unknown(source.unknown());
62661 function transformer() {
62664 interpolate = interpolate$1,
62668 clamp = identity$1,
62673 function rescale() {
62674 var n = Math.min(domain.length, range.length);
62675 if (clamp !== identity$1) clamp = clamper(domain[0], domain[n - 1]);
62676 piecewise = n > 2 ? polymap : bimap;
62677 output = input = null;
62681 function scale(x) {
62682 return x == null || isNaN(x = +x) ? unknown : (output || (output = piecewise(domain.map(transform), range, interpolate)))(transform(clamp(x)));
62685 scale.invert = function (y) {
62686 return clamp(untransform((input || (input = piecewise(range, domain.map(transform), d3_interpolateNumber)))(y)));
62689 scale.domain = function (_) {
62690 return arguments.length ? (domain = Array.from(_, number), rescale()) : domain.slice();
62693 scale.range = function (_) {
62694 return arguments.length ? (range = Array.from(_), rescale()) : range.slice();
62697 scale.rangeRound = function (_) {
62698 return range = Array.from(_), interpolate = interpolateRound, rescale();
62701 scale.clamp = function (_) {
62702 return arguments.length ? (clamp = _ ? true : identity$1, rescale()) : clamp !== identity$1;
62705 scale.interpolate = function (_) {
62706 return arguments.length ? (interpolate = _, rescale()) : interpolate;
62709 scale.unknown = function (_) {
62710 return arguments.length ? (unknown = _, scale) : unknown;
62713 return function (t, u) {
62714 transform = t, untransform = u;
62718 function continuous() {
62719 return transformer()(identity$1, identity$1);
62722 function formatDecimal (x) {
62723 return Math.abs(x = Math.round(x)) >= 1e21 ? x.toLocaleString("en").replace(/,/g, "") : x.toString(10);
62724 } // Computes the decimal coefficient and exponent of the specified number x with
62725 // significant digits p, where x is positive and p is in [1, 21] or undefined.
62726 // For example, formatDecimalParts(1.23) returns ["123", 0].
62728 function formatDecimalParts(x, p) {
62729 if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
62732 coefficient = x.slice(0, i); // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
62733 // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
62735 return [coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, +x.slice(i + 1)];
62738 function exponent (x) {
62739 return x = formatDecimalParts(Math.abs(x)), x ? x[1] : NaN;
62742 function formatGroup (grouping, thousands) {
62743 return function (value, width) {
62744 var i = value.length,
62750 while (i > 0 && g > 0) {
62751 if (length + g + 1 > width) g = Math.max(1, width - length);
62752 t.push(value.substring(i -= g, i + g));
62753 if ((length += g + 1) > width) break;
62754 g = grouping[j = (j + 1) % grouping.length];
62757 return t.reverse().join(thousands);
62761 function formatNumerals (numerals) {
62762 return function (value) {
62763 return value.replace(/[0-9]/g, function (i) {
62764 return numerals[+i];
62769 // [[fill]align][sign][symbol][0][width][,][.precision][~][type]
62770 var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
62771 function formatSpecifier(specifier) {
62772 if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
62774 return new FormatSpecifier({
62782 precision: match[8] && match[8].slice(1),
62787 formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
62789 function FormatSpecifier(specifier) {
62790 this.fill = specifier.fill === undefined ? " " : specifier.fill + "";
62791 this.align = specifier.align === undefined ? ">" : specifier.align + "";
62792 this.sign = specifier.sign === undefined ? "-" : specifier.sign + "";
62793 this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + "";
62794 this.zero = !!specifier.zero;
62795 this.width = specifier.width === undefined ? undefined : +specifier.width;
62796 this.comma = !!specifier.comma;
62797 this.precision = specifier.precision === undefined ? undefined : +specifier.precision;
62798 this.trim = !!specifier.trim;
62799 this.type = specifier.type === undefined ? "" : specifier.type + "";
62802 FormatSpecifier.prototype.toString = function () {
62803 return this.fill + this.align + this.sign + this.symbol + (this.zero ? "0" : "") + (this.width === undefined ? "" : Math.max(1, this.width | 0)) + (this.comma ? "," : "") + (this.precision === undefined ? "" : "." + Math.max(0, this.precision | 0)) + (this.trim ? "~" : "") + this.type;
62806 // Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
62807 function formatTrim (s) {
62808 out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
62815 if (i0 === 0) i0 = i;
62820 if (!+s[i]) break out;
62821 if (i0 > 0) i0 = 0;
62826 return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
62830 var uncurryThis$3 = functionUncurryThis;
62831 var fails$3 = fails$V;
62832 var thisNumberValue = thisNumberValue$3;
62834 var un$ToPrecision = uncurryThis$3(1.0.toPrecision);
62836 var FORCED$1 = fails$3(function () {
62838 return un$ToPrecision(1, undefined) !== '1';
62839 }) || !fails$3(function () {
62840 // V8 ~ Android 4.3-
62841 un$ToPrecision({});
62844 // `Number.prototype.toPrecision` method
62845 // https://tc39.es/ecma262/#sec-number.prototype.toprecision
62846 $$5({ target: 'Number', proto: true, forced: FORCED$1 }, {
62847 toPrecision: function toPrecision(precision) {
62848 return precision === undefined
62849 ? un$ToPrecision(thisNumberValue(this))
62850 : un$ToPrecision(thisNumberValue(this), precision);
62854 var prefixExponent;
62855 function formatPrefixAuto (x, p) {
62856 var d = formatDecimalParts(x, p);
62857 if (!d) return x + "";
62858 var coefficient = d[0],
62860 i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
62861 n = coefficient.length;
62862 return i === n ? coefficient : i > n ? coefficient + new Array(i - n + 1).join("0") : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) : "0." + new Array(1 - i).join("0") + formatDecimalParts(x, Math.max(0, p + i - 1))[0]; // less than 1y!
62865 function formatRounded (x, p) {
62866 var d = formatDecimalParts(x, p);
62867 if (!d) return x + "";
62868 var coefficient = d[0],
62870 return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) : coefficient + new Array(exponent - coefficient.length + 2).join("0");
62873 var formatTypes = {
62874 "%": function _(x, p) {
62875 return (x * 100).toFixed(p);
62877 "b": function b(x) {
62878 return Math.round(x).toString(2);
62880 "c": function c(x) {
62883 "d": formatDecimal,
62884 "e": function e(x, p) {
62885 return x.toExponential(p);
62887 "f": function f(x, p) {
62888 return x.toFixed(p);
62890 "g": function g(x, p) {
62891 return x.toPrecision(p);
62893 "o": function o(x) {
62894 return Math.round(x).toString(8);
62896 "p": function p(x, _p) {
62897 return formatRounded(x * 100, _p);
62899 "r": formatRounded,
62900 "s": formatPrefixAuto,
62901 "X": function X(x) {
62902 return Math.round(x).toString(16).toUpperCase();
62904 "x": function x(_x) {
62905 return Math.round(_x).toString(16);
62909 function identity (x) {
62913 var map$1 = Array.prototype.map,
62914 prefixes = ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"];
62915 function formatLocale (locale) {
62916 var group = locale.grouping === undefined || locale.thousands === undefined ? identity : formatGroup(map$1.call(locale.grouping, Number), locale.thousands + ""),
62917 currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "",
62918 currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "",
62919 decimal = locale.decimal === undefined ? "." : locale.decimal + "",
62920 numerals = locale.numerals === undefined ? identity : formatNumerals(map$1.call(locale.numerals, String)),
62921 percent = locale.percent === undefined ? "%" : locale.percent + "",
62922 minus = locale.minus === undefined ? "−" : locale.minus + "",
62923 nan = locale.nan === undefined ? "NaN" : locale.nan + "";
62925 function newFormat(specifier) {
62926 specifier = formatSpecifier(specifier);
62927 var fill = specifier.fill,
62928 align = specifier.align,
62929 sign = specifier.sign,
62930 symbol = specifier.symbol,
62931 zero = specifier.zero,
62932 width = specifier.width,
62933 comma = specifier.comma,
62934 precision = specifier.precision,
62935 trim = specifier.trim,
62936 type = specifier.type; // The "n" type is an alias for ",g".
62938 if (type === "n") comma = true, type = "g"; // The "" type, and any invalid type, is an alias for ".12~g".
62939 else if (!formatTypes[type]) precision === undefined && (precision = 12), trim = true, type = "g"; // If zero fill is specified, padding goes after sign and before digits.
62941 if (zero || fill === "0" && align === "=") zero = true, fill = "0", align = "="; // Compute the prefix and suffix.
62942 // For SI-prefix, the suffix is lazily computed.
62944 var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
62945 suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : ""; // What format function should we use?
62946 // Is this an integer type?
62947 // Can this type generate exponential notation?
62949 var formatType = formatTypes[type],
62950 maybeSuffix = /[defgprs%]/.test(type); // Set the default precision if not specified,
62951 // or clamp the specified precision to the supported range.
62952 // For significant precision, it must be in [1, 21].
62953 // For fixed precision, it must be in [0, 20].
62955 precision = precision === undefined ? 6 : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) : Math.max(0, Math.min(20, precision));
62957 function format(value) {
62958 var valuePrefix = prefix,
62959 valueSuffix = suffix,
62964 if (type === "c") {
62965 valueSuffix = formatType(value) + valueSuffix;
62968 value = +value; // Determine the sign. -0 is not less than 0, but 1 / -0 is!
62970 var valueNegative = value < 0 || 1 / value < 0; // Perform the initial formatting.
62972 value = isNaN(value) ? nan : formatType(Math.abs(value), precision); // Trim insignificant zeros.
62974 if (trim) value = formatTrim(value); // If a negative value rounds to zero after formatting, and no explicit positive sign is requested, hide the sign.
62976 if (valueNegative && +value === 0 && sign !== "+") valueNegative = false; // Compute the prefix and suffix.
62978 valuePrefix = (valueNegative ? sign === "(" ? sign : minus : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
62979 valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); // Break the formatted value into the integer “value” part that can be
62980 // grouped, and fractional or exponential “suffix” part that is not.
62983 i = -1, n = value.length;
62986 if (c = value.charCodeAt(i), 48 > c || c > 57) {
62987 valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
62988 value = value.slice(0, i);
62993 } // If the fill character is not "0", grouping is applied before padding.
62996 if (comma && !zero) value = group(value, Infinity); // Compute the padding.
62998 var length = valuePrefix.length + value.length + valueSuffix.length,
62999 padding = length < width ? new Array(width - length + 1).join(fill) : ""; // If the fill character is "0", grouping is applied after padding.
63001 if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; // Reconstruct the final output based on the desired alignment.
63005 value = valuePrefix + value + valueSuffix + padding;
63009 value = valuePrefix + padding + value + valueSuffix;
63013 value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
63017 value = padding + valuePrefix + value + valueSuffix;
63021 return numerals(value);
63024 format.toString = function () {
63025 return specifier + "";
63031 function formatPrefix(specifier, value) {
63032 var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
63033 e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
63034 k = Math.pow(10, -e),
63035 prefix = prefixes[8 + e / 3];
63036 return function (value) {
63037 return f(k * value) + prefix;
63043 formatPrefix: formatPrefix
63053 currency: ["$", ""]
63055 function defaultLocale(definition) {
63056 locale = formatLocale(definition);
63057 format$1 = locale.format;
63058 formatPrefix = locale.formatPrefix;
63062 function precisionFixed (step) {
63063 return Math.max(0, -exponent(Math.abs(step)));
63066 function precisionPrefix (step, value) {
63067 return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
63070 function precisionRound (step, max) {
63071 step = Math.abs(step), max = Math.abs(max) - step;
63072 return Math.max(0, exponent(max) - exponent(step)) + 1;
63075 function tickFormat(start, stop, count, specifier) {
63076 var step = tickStep(start, stop, count),
63078 specifier = formatSpecifier(specifier == null ? ",f" : specifier);
63080 switch (specifier.type) {
63083 var value = Math.max(Math.abs(start), Math.abs(stop));
63084 if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
63085 return formatPrefix(specifier, value);
63094 if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
63101 if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
63106 return format$1(specifier);
63109 function linearish(scale) {
63110 var domain = scale.domain;
63112 scale.ticks = function (count) {
63114 return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
63117 scale.tickFormat = function (count, specifier) {
63119 return tickFormat(d[0], d[d.length - 1], count == null ? 10 : count, specifier);
63122 scale.nice = function (count) {
63123 if (count == null) count = 10;
63126 var i1 = d.length - 1;
63133 if (stop < start) {
63134 step = start, start = stop, stop = step;
63135 step = i0, i0 = i1, i1 = step;
63138 while (maxIter-- > 0) {
63139 step = tickIncrement(start, stop, count);
63141 if (step === prestep) {
63145 } else if (step > 0) {
63146 start = Math.floor(start / step) * step;
63147 stop = Math.ceil(stop / step) * step;
63148 } else if (step < 0) {
63149 start = Math.ceil(start * step) / step;
63150 stop = Math.floor(stop * step) / step;
63163 function linear() {
63164 var scale = continuous();
63166 scale.copy = function () {
63167 return copy(scale, linear());
63170 initRange.apply(scale, arguments);
63171 return linearish(scale);
63174 // eslint-disable-next-line es/no-math-expm1 -- safe
63175 var $expm1 = Math.expm1;
63176 var exp$1 = Math.exp;
63178 // `Math.expm1` method implementation
63179 // https://tc39.es/ecma262/#sec-math.expm1
63180 var mathExpm1 = (!$expm1
63182 || $expm1(10) > 22025.465794806719 || $expm1(10) < 22025.4657948067165168
63184 || $expm1(-2e-17) != -2e-17
63185 ) ? function expm1(x) {
63186 return (x = +x) == 0 ? x : x > -1e-6 && x < 1e-6 ? x + x * x / 2 : exp$1(x) - 1;
63189 function quantize() {
63197 function scale(x) {
63198 return x != null && x <= x ? range[bisectRight(domain, x, 0, n)] : unknown;
63201 function rescale() {
63203 domain = new Array(n);
63206 domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
63212 scale.domain = function (_) {
63215 return arguments.length ? ((_ref = _, _ref2 = _slicedToArray(_ref, 2), x0 = _ref2[0], x1 = _ref2[1], _ref), x0 = +x0, x1 = +x1, rescale()) : [x0, x1];
63218 scale.range = function (_) {
63219 return arguments.length ? (n = (range = Array.from(_)).length - 1, rescale()) : range.slice();
63222 scale.invertExtent = function (y) {
63223 var i = range.indexOf(y);
63224 return i < 0 ? [NaN, NaN] : i < 1 ? [x0, domain[0]] : i >= n ? [domain[n - 1], x1] : [domain[i - 1], domain[i]];
63227 scale.unknown = function (_) {
63228 return arguments.length ? (unknown = _, scale) : scale;
63231 scale.thresholds = function () {
63232 return domain.slice();
63235 scale.copy = function () {
63236 return quantize().domain([x0, x1]).range(range).unknown(unknown);
63239 return initRange.apply(linearish(scale), arguments);
63242 var global$3 = global$1o;
63243 var uncurryThis$2 = functionUncurryThis;
63244 var fails$2 = fails$V;
63245 var padStart = stringPad.start;
63247 var RangeError$2 = global$3.RangeError;
63248 var abs$1 = Math.abs;
63249 var DatePrototype = Date.prototype;
63250 var n$DateToISOString = DatePrototype.toISOString;
63251 var getTime = uncurryThis$2(DatePrototype.getTime);
63252 var getUTCDate = uncurryThis$2(DatePrototype.getUTCDate);
63253 var getUTCFullYear = uncurryThis$2(DatePrototype.getUTCFullYear);
63254 var getUTCHours = uncurryThis$2(DatePrototype.getUTCHours);
63255 var getUTCMilliseconds = uncurryThis$2(DatePrototype.getUTCMilliseconds);
63256 var getUTCMinutes = uncurryThis$2(DatePrototype.getUTCMinutes);
63257 var getUTCMonth = uncurryThis$2(DatePrototype.getUTCMonth);
63258 var getUTCSeconds = uncurryThis$2(DatePrototype.getUTCSeconds);
63260 // `Date.prototype.toISOString` method implementation
63261 // https://tc39.es/ecma262/#sec-date.prototype.toisostring
63262 // PhantomJS / old WebKit fails here:
63263 var dateToIsoString = (fails$2(function () {
63264 return n$DateToISOString.call(new Date(-5e13 - 1)) != '0385-07-25T07:06:39.999Z';
63265 }) || !fails$2(function () {
63266 n$DateToISOString.call(new Date(NaN));
63267 })) ? function toISOString() {
63268 if (!isFinite(getTime(this))) throw RangeError$2('Invalid time value');
63270 var year = getUTCFullYear(date);
63271 var milliseconds = getUTCMilliseconds(date);
63272 var sign = year < 0 ? '-' : year > 9999 ? '+' : '';
63273 return sign + padStart(abs$1(year), sign ? 6 : 4, 0) +
63274 '-' + padStart(getUTCMonth(date) + 1, 2, 0) +
63275 '-' + padStart(getUTCDate(date), 2, 0) +
63276 'T' + padStart(getUTCHours(date), 2, 0) +
63277 ':' + padStart(getUTCMinutes(date), 2, 0) +
63278 ':' + padStart(getUTCSeconds(date), 2, 0) +
63279 '.' + padStart(milliseconds, 3, 0) +
63281 } : n$DateToISOString;
63284 var toISOString = dateToIsoString;
63286 // `Date.prototype.toISOString` method
63287 // https://tc39.es/ecma262/#sec-date.prototype.toisostring
63288 // PhantomJS / old WebKit has a broken implementations
63289 $$4({ target: 'Date', proto: true, forced: Date.prototype.toISOString !== toISOString }, {
63290 toISOString: toISOString
63293 function behaviorBreathe() {
63294 var duration = 800;
63296 var selector = '.selected.shadow, .selected .shadow';
63298 var _selected = select(null);
63306 function ratchetyInterpolator(a, b, steps, units) {
63309 var sample = quantize().domain([0, 1]).range(d3_quantize(d3_interpolateNumber(a, b), steps));
63310 return function (t) {
63311 return String(sample(t)) + (units || '');
63315 function reset(selection) {
63316 selection.style('stroke-opacity', null).style('stroke-width', null).style('fill-opacity', null).style('r', null);
63319 function setAnimationParams(transition, fromTo) {
63320 var toFrom = fromTo === 'from' ? 'to' : 'from';
63321 transition.styleTween('stroke-opacity', function (d) {
63322 return ratchetyInterpolator(_params[d.id][toFrom].opacity, _params[d.id][fromTo].opacity, steps);
63323 }).styleTween('stroke-width', function (d) {
63324 return ratchetyInterpolator(_params[d.id][toFrom].width, _params[d.id][fromTo].width, steps, 'px');
63325 }).styleTween('fill-opacity', function (d) {
63326 return ratchetyInterpolator(_params[d.id][toFrom].opacity, _params[d.id][fromTo].opacity, steps);
63327 }).styleTween('r', function (d) {
63328 return ratchetyInterpolator(_params[d.id][toFrom].width, _params[d.id][fromTo].width, steps, 'px');
63332 function calcAnimationParams(selection) {
63333 selection.call(reset).each(function (d) {
63334 var s = select(this);
63335 var tag = s.node().tagName;
63341 var width; // determine base opacity and width
63343 if (tag === 'circle') {
63344 opacity = parseFloat(s.style('fill-opacity') || 0.5);
63345 width = parseFloat(s.style('r') || 15.5);
63347 opacity = parseFloat(s.style('stroke-opacity') || 0.7);
63348 width = parseFloat(s.style('stroke-width') || 10);
63349 } // calculate from/to interpolation params..
63353 p.from.opacity = opacity * 0.6;
63354 p.to.opacity = opacity * 1.25;
63355 p.from.width = width * 0.7;
63356 p.to.width = width * (tag === 'circle' ? 1.5 : 1);
63361 function run(surface, fromTo) {
63362 var toFrom = fromTo === 'from' ? 'to' : 'from';
63363 var currSelected = surface.selectAll(selector);
63364 var currClassed = surface.attr('class');
63366 if (_done || currSelected.empty()) {
63367 _selected.call(reset);
63369 _selected = select(null);
63373 if (!fastDeepEqual(currSelected.data(), _selected.data()) || currClassed !== _classed) {
63374 _selected.call(reset);
63376 _classed = currClassed;
63377 _selected = currSelected.call(calcAnimationParams);
63380 var didCallNextRun = false;
63382 _selected.transition().duration(duration).call(setAnimationParams, fromTo).on('end', function () {
63383 // `end` event is called for each selected element, but we want
63384 // it to run only once
63385 if (!didCallNextRun) {
63386 surface.call(run, toFrom);
63387 didCallNextRun = true;
63388 } // if entity was deselected, remove breathe styling
63391 if (!select(this).classed('selected')) {
63392 reset(select(this));
63397 function behavior(surface) {
63399 _timer = timer(function () {
63400 // wait for elements to actually become selected
63401 if (surface.selectAll(selector).empty()) {
63405 surface.call(run, 'from');
63413 behavior.restartIfNeeded = function (surface) {
63414 if (_selected.empty()) {
63415 surface.call(run, 'from');
63423 behavior.off = function () {
63430 _selected.interrupt().call(reset);
63436 /* Creates a keybinding behavior for an operation */
63437 function behaviorOperation(context) {
63440 function keypress(d3_event) {
63441 // prevent operations during low zoom selection
63442 if (!context.map().withinEditableZoom()) return;
63443 if (_operation.availableForKeypress && !_operation.availableForKeypress()) return;
63444 d3_event.preventDefault();
63446 var disabled = _operation.disabled();
63449 context.ui().flash.duration(4000).iconName('#iD-operation-' + _operation.id).iconClass('operation disabled').label(_operation.tooltip)();
63451 context.ui().flash.duration(2000).iconName('#iD-operation-' + _operation.id).iconClass('operation').label(_operation.annotation() || _operation.title)();
63452 if (_operation.point) _operation.point(null);
63458 function behavior() {
63459 if (_operation && _operation.available()) {
63460 context.keybinding().on(_operation.keys, keypress);
63466 behavior.off = function () {
63467 context.keybinding().off(_operation.keys);
63470 behavior.which = function (_) {
63471 if (!arguments.length) return _operation;
63479 function operationCircularize(context, selectedIDs) {
63482 var _actions = selectedIDs.map(getAction).filter(Boolean);
63484 var _amount = _actions.length === 1 ? 'single' : 'multiple';
63486 var _coords = utilGetAllNodes(selectedIDs, context.graph()).map(function (n) {
63490 function getAction(entityID) {
63491 var entity = context.entity(entityID);
63492 if (entity.type !== 'way' || new Set(entity.nodes).size <= 1) return null;
63495 _extent = entity.extent(context.graph());
63497 _extent = _extent.extend(entity.extent(context.graph()));
63500 return actionCircularize(entityID, context.projection);
63503 var operation = function operation() {
63504 if (!_actions.length) return;
63506 var combinedAction = function combinedAction(graph, t) {
63507 _actions.forEach(function (action) {
63508 if (!action.disabled(graph)) {
63509 graph = action(graph, t);
63516 combinedAction.transitionable = true;
63517 context.perform(combinedAction, operation.annotation());
63518 window.setTimeout(function () {
63519 context.validator().validate();
63520 }, 300); // after any transition
63523 operation.available = function () {
63524 return _actions.length && selectedIDs.length === _actions.length;
63525 }; // don't cache this because the visible extent could change
63528 operation.disabled = function () {
63529 if (!_actions.length) return '';
63531 var actionDisableds = _actions.map(function (action) {
63532 return action.disabled(context.graph());
63533 }).filter(Boolean);
63535 if (actionDisableds.length === _actions.length) {
63536 // none of the features can be circularized
63537 if (new Set(actionDisableds).size > 1) {
63538 return 'multiple_blockers';
63541 return actionDisableds[0];
63542 } else if (_extent.percentContainedIn(context.map().extent()) < 0.8) {
63543 return 'too_large';
63544 } else if (someMissing()) {
63545 return 'not_downloaded';
63546 } else if (selectedIDs.some(context.hasHiddenConnections)) {
63547 return 'connected_to_hidden';
63552 function someMissing() {
63553 if (context.inIntro()) return false;
63554 var osm = context.connection();
63557 var missing = _coords.filter(function (loc) {
63558 return !osm.isDataLoaded(loc);
63561 if (missing.length) {
63562 missing.forEach(function (loc) {
63563 context.loadTileAtLoc(loc);
63573 operation.tooltip = function () {
63574 var disable = operation.disabled();
63575 return disable ? _t('operations.circularize.' + disable + '.' + _amount) : _t('operations.circularize.description.' + _amount);
63578 operation.annotation = function () {
63579 return _t('operations.circularize.annotation.feature', {
63584 operation.id = 'circularize';
63585 operation.keys = [_t('operations.circularize.key')];
63586 operation.title = _t('operations.circularize.title');
63587 operation.behavior = behaviorOperation(context).which(operation);
63591 // For example, ⌘Z -> Ctrl+Z
63593 var uiCmd = function uiCmd(code) {
63594 var detected = utilDetect();
63596 if (detected.os === 'mac') {
63600 if (detected.os === 'win') {
63601 if (code === '⌘⇧Z') return 'Ctrl+Y';
63613 for (var i = 0; i < code.length; i++) {
63614 if (code[i] in replacements) {
63615 result += replacements[code[i]] + (i < code.length - 1 ? '+' : '');
63622 }; // return a display-focused string for a given keyboard code
63624 uiCmd.display = function (code) {
63625 if (code.length !== 1) return code;
63626 var detected = utilDetect();
63627 var mac = detected.os === 'mac';
63628 var replacements = {
63629 '⌘': mac ? '⌘ ' + _t('shortcuts.key.cmd') : _t('shortcuts.key.ctrl'),
63630 '⇧': mac ? '⇧ ' + _t('shortcuts.key.shift') : _t('shortcuts.key.shift'),
63631 '⌥': mac ? '⌥ ' + _t('shortcuts.key.option') : _t('shortcuts.key.alt'),
63632 '⌃': mac ? '⌃ ' + _t('shortcuts.key.ctrl') : _t('shortcuts.key.ctrl'),
63633 '⌫': mac ? '⌫ ' + _t('shortcuts.key.delete') : _t('shortcuts.key.backspace'),
63634 '⌦': mac ? '⌦ ' + _t('shortcuts.key.del') : _t('shortcuts.key.del'),
63635 '↖': mac ? '↖ ' + _t('shortcuts.key.pgup') : _t('shortcuts.key.pgup'),
63636 '↘': mac ? '↘ ' + _t('shortcuts.key.pgdn') : _t('shortcuts.key.pgdn'),
63637 '⇞': mac ? '⇞ ' + _t('shortcuts.key.home') : _t('shortcuts.key.home'),
63638 '⇟': mac ? '⇟ ' + _t('shortcuts.key.end') : _t('shortcuts.key.end'),
63639 '↵': mac ? '⏎ ' + _t('shortcuts.key.return') : _t('shortcuts.key.enter'),
63640 '⎋': mac ? '⎋ ' + _t('shortcuts.key.esc') : _t('shortcuts.key.esc'),
63641 '☰': mac ? '☰ ' + _t('shortcuts.key.menu') : _t('shortcuts.key.menu')
63643 return replacements[code] || code;
63646 function operationDelete(context, selectedIDs) {
63647 var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
63648 var action = actionDeleteMultiple(selectedIDs);
63649 var nodes = utilGetAllNodes(selectedIDs, context.graph());
63650 var coords = nodes.map(function (n) {
63653 var extent = utilTotalExtent(selectedIDs, context.graph());
63655 var operation = function operation() {
63656 var nextSelectedID;
63657 var nextSelectedLoc;
63659 if (selectedIDs.length === 1) {
63660 var id = selectedIDs[0];
63661 var entity = context.entity(id);
63662 var geometry = entity.geometry(context.graph());
63663 var parents = context.graph().parentWays(entity);
63664 var parent = parents[0]; // Select the next closest node in the way.
63666 if (geometry === 'vertex') {
63667 var nodes = parent.nodes;
63668 var i = nodes.indexOf(id);
63672 } else if (i === nodes.length - 1) {
63675 var a = geoSphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc);
63676 var b = geoSphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
63677 i = a < b ? i - 1 : i + 1;
63680 nextSelectedID = nodes[i];
63681 nextSelectedLoc = context.entity(nextSelectedID).loc;
63685 context.perform(action, operation.annotation());
63686 context.validator().validate();
63688 if (nextSelectedID && nextSelectedLoc) {
63689 if (context.hasEntity(nextSelectedID)) {
63690 context.enter(modeSelect(context, [nextSelectedID]).follow(true));
63692 context.map().centerEase(nextSelectedLoc);
63693 context.enter(modeBrowse(context));
63696 context.enter(modeBrowse(context));
63700 operation.available = function () {
63704 operation.disabled = function () {
63705 if (extent.percentContainedIn(context.map().extent()) < 0.8) {
63706 return 'too_large';
63707 } else if (someMissing()) {
63708 return 'not_downloaded';
63709 } else if (selectedIDs.some(context.hasHiddenConnections)) {
63710 return 'connected_to_hidden';
63711 } else if (selectedIDs.some(protectedMember)) {
63712 return 'part_of_relation';
63713 } else if (selectedIDs.some(incompleteRelation)) {
63714 return 'incomplete_relation';
63715 } else if (selectedIDs.some(hasWikidataTag)) {
63716 return 'has_wikidata_tag';
63721 function someMissing() {
63722 if (context.inIntro()) return false;
63723 var osm = context.connection();
63726 var missing = coords.filter(function (loc) {
63727 return !osm.isDataLoaded(loc);
63730 if (missing.length) {
63731 missing.forEach(function (loc) {
63732 context.loadTileAtLoc(loc);
63741 function hasWikidataTag(id) {
63742 var entity = context.entity(id);
63743 return entity.tags.wikidata && entity.tags.wikidata.trim().length > 0;
63746 function incompleteRelation(id) {
63747 var entity = context.entity(id);
63748 return entity.type === 'relation' && !entity.isComplete(context.graph());
63751 function protectedMember(id) {
63752 var entity = context.entity(id);
63753 if (entity.type !== 'way') return false;
63754 var parents = context.graph().parentRelations(entity);
63756 for (var i = 0; i < parents.length; i++) {
63757 var parent = parents[i];
63758 var type = parent.tags.type;
63759 var role = parent.memberById(id).role || 'outer';
63761 if (type === 'route' || type === 'boundary' || type === 'multipolygon' && role === 'outer') {
63770 operation.tooltip = function () {
63771 var disable = operation.disabled();
63772 return disable ? _t('operations.delete.' + disable + '.' + multi) : _t('operations.delete.description.' + multi);
63775 operation.annotation = function () {
63776 return selectedIDs.length === 1 ? _t('operations.delete.annotation.' + context.graph().geometry(selectedIDs[0])) : _t('operations.delete.annotation.feature', {
63777 n: selectedIDs.length
63781 operation.id = 'delete';
63782 operation.keys = [uiCmd('⌘⌫'), uiCmd('⌘⌦'), uiCmd('⌦')];
63783 operation.title = _t('operations.delete.title');
63784 operation.behavior = behaviorOperation(context).which(operation);
63788 function operationOrthogonalize(context, selectedIDs) {
63793 var _actions = selectedIDs.map(chooseAction).filter(Boolean);
63795 var _amount = _actions.length === 1 ? 'single' : 'multiple';
63797 var _coords = utilGetAllNodes(selectedIDs, context.graph()).map(function (n) {
63801 function chooseAction(entityID) {
63802 var entity = context.entity(entityID);
63803 var geometry = entity.geometry(context.graph());
63806 _extent = entity.extent(context.graph());
63808 _extent = _extent.extend(entity.extent(context.graph()));
63809 } // square a line/area
63812 if (entity.type === 'way' && new Set(entity.nodes).size > 2) {
63813 if (_type && _type !== 'feature') return null;
63815 return actionOrthogonalize(entityID, context.projection); // square a single vertex
63816 } else if (geometry === 'vertex') {
63817 if (_type && _type !== 'corner') return null;
63819 var graph = context.graph();
63820 var parents = graph.parentWays(entity);
63822 if (parents.length === 1) {
63823 var way = parents[0];
63825 if (way.nodes.indexOf(entityID) !== -1) {
63826 return actionOrthogonalize(way.id, context.projection, entityID);
63834 var operation = function operation() {
63835 if (!_actions.length) return;
63837 var combinedAction = function combinedAction(graph, t) {
63838 _actions.forEach(function (action) {
63839 if (!action.disabled(graph)) {
63840 graph = action(graph, t);
63847 combinedAction.transitionable = true;
63848 context.perform(combinedAction, operation.annotation());
63849 window.setTimeout(function () {
63850 context.validator().validate();
63851 }, 300); // after any transition
63854 operation.available = function () {
63855 return _actions.length && selectedIDs.length === _actions.length;
63856 }; // don't cache this because the visible extent could change
63859 operation.disabled = function () {
63860 if (!_actions.length) return '';
63862 var actionDisableds = _actions.map(function (action) {
63863 return action.disabled(context.graph());
63864 }).filter(Boolean);
63866 if (actionDisableds.length === _actions.length) {
63867 // none of the features can be squared
63868 if (new Set(actionDisableds).size > 1) {
63869 return 'multiple_blockers';
63872 return actionDisableds[0];
63873 } else if (_extent && _extent.percentContainedIn(context.map().extent()) < 0.8) {
63874 return 'too_large';
63875 } else if (someMissing()) {
63876 return 'not_downloaded';
63877 } else if (selectedIDs.some(context.hasHiddenConnections)) {
63878 return 'connected_to_hidden';
63883 function someMissing() {
63884 if (context.inIntro()) return false;
63885 var osm = context.connection();
63888 var missing = _coords.filter(function (loc) {
63889 return !osm.isDataLoaded(loc);
63892 if (missing.length) {
63893 missing.forEach(function (loc) {
63894 context.loadTileAtLoc(loc);
63904 operation.tooltip = function () {
63905 var disable = operation.disabled();
63906 return disable ? _t('operations.orthogonalize.' + disable + '.' + _amount) : _t('operations.orthogonalize.description.' + _type + '.' + _amount);
63909 operation.annotation = function () {
63910 return _t('operations.orthogonalize.annotation.' + _type, {
63915 operation.id = 'orthogonalize';
63916 operation.keys = [_t('operations.orthogonalize.key')];
63917 operation.title = _t('operations.orthogonalize.title');
63918 operation.behavior = behaviorOperation(context).which(operation);
63922 function operationReflectShort(context, selectedIDs) {
63923 return operationReflect(context, selectedIDs, 'short');
63925 function operationReflectLong(context, selectedIDs) {
63926 return operationReflect(context, selectedIDs, 'long');
63928 function operationReflect(context, selectedIDs, axis) {
63929 axis = axis || 'long';
63930 var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
63931 var nodes = utilGetAllNodes(selectedIDs, context.graph());
63932 var coords = nodes.map(function (n) {
63935 var extent = utilTotalExtent(selectedIDs, context.graph());
63937 var operation = function operation() {
63938 var action = actionReflect(selectedIDs, context.projection).useLongAxis(Boolean(axis === 'long'));
63939 context.perform(action, operation.annotation());
63940 window.setTimeout(function () {
63941 context.validator().validate();
63942 }, 300); // after any transition
63945 operation.available = function () {
63946 return nodes.length >= 3;
63947 }; // don't cache this because the visible extent could change
63950 operation.disabled = function () {
63951 if (extent.percentContainedIn(context.map().extent()) < 0.8) {
63952 return 'too_large';
63953 } else if (someMissing()) {
63954 return 'not_downloaded';
63955 } else if (selectedIDs.some(context.hasHiddenConnections)) {
63956 return 'connected_to_hidden';
63957 } else if (selectedIDs.some(incompleteRelation)) {
63958 return 'incomplete_relation';
63963 function someMissing() {
63964 if (context.inIntro()) return false;
63965 var osm = context.connection();
63968 var missing = coords.filter(function (loc) {
63969 return !osm.isDataLoaded(loc);
63972 if (missing.length) {
63973 missing.forEach(function (loc) {
63974 context.loadTileAtLoc(loc);
63983 function incompleteRelation(id) {
63984 var entity = context.entity(id);
63985 return entity.type === 'relation' && !entity.isComplete(context.graph());
63989 operation.tooltip = function () {
63990 var disable = operation.disabled();
63991 return disable ? _t('operations.reflect.' + disable + '.' + multi) : _t('operations.reflect.description.' + axis + '.' + multi);
63994 operation.annotation = function () {
63995 return _t('operations.reflect.annotation.' + axis + '.feature', {
63996 n: selectedIDs.length
64000 operation.id = 'reflect-' + axis;
64001 operation.keys = [_t('operations.reflect.key.' + axis)];
64002 operation.title = _t('operations.reflect.title.' + axis);
64003 operation.behavior = behaviorOperation(context).which(operation);
64007 function operationMove(context, selectedIDs) {
64008 var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
64009 var nodes = utilGetAllNodes(selectedIDs, context.graph());
64010 var coords = nodes.map(function (n) {
64013 var extent = utilTotalExtent(selectedIDs, context.graph());
64015 var operation = function operation() {
64016 context.enter(modeMove(context, selectedIDs));
64019 operation.available = function () {
64020 return selectedIDs.length > 0;
64023 operation.disabled = function () {
64024 if (extent.percentContainedIn(context.map().extent()) < 0.8) {
64025 return 'too_large';
64026 } else if (someMissing()) {
64027 return 'not_downloaded';
64028 } else if (selectedIDs.some(context.hasHiddenConnections)) {
64029 return 'connected_to_hidden';
64030 } else if (selectedIDs.some(incompleteRelation)) {
64031 return 'incomplete_relation';
64036 function someMissing() {
64037 if (context.inIntro()) return false;
64038 var osm = context.connection();
64041 var missing = coords.filter(function (loc) {
64042 return !osm.isDataLoaded(loc);
64045 if (missing.length) {
64046 missing.forEach(function (loc) {
64047 context.loadTileAtLoc(loc);
64056 function incompleteRelation(id) {
64057 var entity = context.entity(id);
64058 return entity.type === 'relation' && !entity.isComplete(context.graph());
64062 operation.tooltip = function () {
64063 var disable = operation.disabled();
64064 return disable ? _t('operations.move.' + disable + '.' + multi) : _t('operations.move.description.' + multi);
64067 operation.annotation = function () {
64068 return selectedIDs.length === 1 ? _t('operations.move.annotation.' + context.graph().geometry(selectedIDs[0])) : _t('operations.move.annotation.feature', {
64069 n: selectedIDs.length
64073 operation.id = 'move';
64074 operation.keys = [_t('operations.move.key')];
64075 operation.title = _t('operations.move.title');
64076 operation.behavior = behaviorOperation(context).which(operation);
64077 operation.mouseOnly = true;
64081 function modeRotate(context, entityIDs) {
64082 var _tolerancePx = 4; // see also behaviorDrag, behaviorSelect, modeMove
64088 var keybinding = utilKeybinding('rotate');
64089 var behaviors = [behaviorEdit(context), operationCircularize(context, entityIDs).behavior, operationDelete(context, entityIDs).behavior, operationMove(context, entityIDs).behavior, operationOrthogonalize(context, entityIDs).behavior, operationReflectLong(context, entityIDs).behavior, operationReflectShort(context, entityIDs).behavior];
64090 var annotation = entityIDs.length === 1 ? _t('operations.rotate.annotation.' + context.graph().geometry(entityIDs[0])) : _t('operations.rotate.annotation.feature', {
64091 n: entityIDs.length
64098 var _prevTransform;
64100 var _pivot; // use pointer events on supported platforms; fallback to mouse events
64103 var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
64105 function doRotate(d3_event) {
64108 if (context.graph() !== _prevGraph) {
64109 fn = context.perform;
64111 fn = context.replace;
64112 } // projection changed, recalculate _pivot
64115 var projection = context.projection;
64116 var currTransform = projection.transform();
64118 if (!_prevTransform || currTransform.k !== _prevTransform.k || currTransform.x !== _prevTransform.x || currTransform.y !== _prevTransform.y) {
64119 var nodes = utilGetAllNodes(entityIDs, context.graph());
64120 var points = nodes.map(function (n) {
64121 return projection(n.loc);
64123 _pivot = getPivot(points);
64124 _prevAngle = undefined;
64127 var currMouse = context.map().mouse(d3_event);
64128 var currAngle = Math.atan2(currMouse[1] - _pivot[1], currMouse[0] - _pivot[0]);
64129 if (typeof _prevAngle === 'undefined') _prevAngle = currAngle;
64130 var delta = currAngle - _prevAngle;
64131 fn(actionRotate(entityIDs, _pivot, delta, projection));
64132 _prevTransform = currTransform;
64133 _prevAngle = currAngle;
64134 _prevGraph = context.graph();
64137 function getPivot(points) {
64140 if (points.length === 1) {
64141 _pivot = points[0];
64142 } else if (points.length === 2) {
64143 _pivot = geoVecInterp(points[0], points[1], 0.5);
64145 var polygonHull = d3_polygonHull(points);
64147 if (polygonHull.length === 2) {
64148 _pivot = geoVecInterp(points[0], points[1], 0.5);
64150 _pivot = d3_polygonCentroid(d3_polygonHull(points));
64157 function finish(d3_event) {
64158 d3_event.stopPropagation();
64159 context.replace(actionNoop(), annotation);
64160 context.enter(modeSelect(context, entityIDs));
64163 function cancel() {
64164 if (_prevGraph) context.pop(); // remove the rotate
64166 context.enter(modeSelect(context, entityIDs));
64169 function undone() {
64170 context.enter(modeBrowse(context));
64173 mode.enter = function () {
64175 context.features().forceVisible(entityIDs);
64176 behaviors.forEach(context.install);
64178 context.surface().on(_pointerPrefix + 'down.modeRotate', function (d3_event) {
64179 downEvent = d3_event;
64181 select(window).on(_pointerPrefix + 'move.modeRotate', doRotate, true).on(_pointerPrefix + 'up.modeRotate', function (d3_event) {
64182 if (!downEvent) return;
64183 var mapNode = context.container().select('.main-map').node();
64184 var pointGetter = utilFastMouse(mapNode);
64185 var p1 = pointGetter(downEvent);
64186 var p2 = pointGetter(d3_event);
64187 var dist = geoVecLength(p1, p2);
64188 if (dist <= _tolerancePx) finish(d3_event);
64191 context.history().on('undone.modeRotate', undone);
64192 keybinding.on('⎋', cancel).on('↩', finish);
64193 select(document).call(keybinding);
64196 mode.exit = function () {
64197 behaviors.forEach(context.uninstall);
64198 context.surface().on(_pointerPrefix + 'down.modeRotate', null);
64199 select(window).on(_pointerPrefix + 'move.modeRotate', null, true).on(_pointerPrefix + 'up.modeRotate', null, true);
64200 context.history().on('undone.modeRotate', null);
64201 select(document).call(keybinding.unbind);
64202 context.features().forceVisible([]);
64205 mode.selectedIDs = function () {
64206 if (!arguments.length) return entityIDs; // no assign
64214 function operationRotate(context, selectedIDs) {
64215 var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
64216 var nodes = utilGetAllNodes(selectedIDs, context.graph());
64217 var coords = nodes.map(function (n) {
64220 var extent = utilTotalExtent(selectedIDs, context.graph());
64222 var operation = function operation() {
64223 context.enter(modeRotate(context, selectedIDs));
64226 operation.available = function () {
64227 return nodes.length >= 2;
64230 operation.disabled = function () {
64231 if (extent.percentContainedIn(context.map().extent()) < 0.8) {
64232 return 'too_large';
64233 } else if (someMissing()) {
64234 return 'not_downloaded';
64235 } else if (selectedIDs.some(context.hasHiddenConnections)) {
64236 return 'connected_to_hidden';
64237 } else if (selectedIDs.some(incompleteRelation)) {
64238 return 'incomplete_relation';
64243 function someMissing() {
64244 if (context.inIntro()) return false;
64245 var osm = context.connection();
64248 var missing = coords.filter(function (loc) {
64249 return !osm.isDataLoaded(loc);
64252 if (missing.length) {
64253 missing.forEach(function (loc) {
64254 context.loadTileAtLoc(loc);
64263 function incompleteRelation(id) {
64264 var entity = context.entity(id);
64265 return entity.type === 'relation' && !entity.isComplete(context.graph());
64269 operation.tooltip = function () {
64270 var disable = operation.disabled();
64271 return disable ? _t('operations.rotate.' + disable + '.' + multi) : _t('operations.rotate.description.' + multi);
64274 operation.annotation = function () {
64275 return selectedIDs.length === 1 ? _t('operations.rotate.annotation.' + context.graph().geometry(selectedIDs[0])) : _t('operations.rotate.annotation.feature', {
64276 n: selectedIDs.length
64280 operation.id = 'rotate';
64281 operation.keys = [_t('operations.rotate.key')];
64282 operation.title = _t('operations.rotate.title');
64283 operation.behavior = behaviorOperation(context).which(operation);
64284 operation.mouseOnly = true;
64288 function modeMove(context, entityIDs, baseGraph) {
64289 var _tolerancePx = 4; // see also behaviorDrag, behaviorSelect, modeRotate
64295 var keybinding = utilKeybinding('move');
64296 var behaviors = [behaviorEdit(context), operationCircularize(context, entityIDs).behavior, operationDelete(context, entityIDs).behavior, operationOrthogonalize(context, entityIDs).behavior, operationReflectLong(context, entityIDs).behavior, operationReflectShort(context, entityIDs).behavior, operationRotate(context, entityIDs).behavior];
64297 var annotation = entityIDs.length === 1 ? _t('operations.move.annotation.' + context.graph().geometry(entityIDs[0])) : _t('operations.move.annotation.feature', {
64298 n: entityIDs.length
64307 var _nudgeInterval; // use pointer events on supported platforms; fallback to mouse events
64310 var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
64312 function doMove(nudge) {
64313 nudge = nudge || [0, 0];
64316 if (_prevGraph !== context.graph()) {
64318 _origin = context.map().mouseCoordinates();
64319 fn = context.perform;
64321 fn = context.overwrite;
64324 var currMouse = context.map().mouse();
64325 var origMouse = context.projection(_origin);
64326 var delta = geoVecSubtract(geoVecSubtract(currMouse, origMouse), nudge);
64327 fn(actionMove(entityIDs, delta, context.projection, _cache));
64328 _prevGraph = context.graph();
64331 function startNudge(nudge) {
64332 if (_nudgeInterval) window.clearInterval(_nudgeInterval);
64333 _nudgeInterval = window.setInterval(function () {
64334 context.map().pan(nudge);
64339 function stopNudge() {
64340 if (_nudgeInterval) {
64341 window.clearInterval(_nudgeInterval);
64342 _nudgeInterval = null;
64348 var nudge = geoViewportEdge(context.map().mouse(), context.map().dimensions());
64357 function finish(d3_event) {
64358 d3_event.stopPropagation();
64359 context.replace(actionNoop(), annotation);
64360 context.enter(modeSelect(context, entityIDs));
64364 function cancel() {
64366 while (context.graph() !== baseGraph) {
64368 } // reset to baseGraph
64371 context.enter(modeBrowse(context));
64373 if (_prevGraph) context.pop(); // remove the move
64375 context.enter(modeSelect(context, entityIDs));
64381 function undone() {
64382 context.enter(modeBrowse(context));
64385 mode.enter = function () {
64386 _origin = context.map().mouseCoordinates();
64389 context.features().forceVisible(entityIDs);
64390 behaviors.forEach(context.install);
64392 context.surface().on(_pointerPrefix + 'down.modeMove', function (d3_event) {
64393 downEvent = d3_event;
64395 select(window).on(_pointerPrefix + 'move.modeMove', move, true).on(_pointerPrefix + 'up.modeMove', function (d3_event) {
64396 if (!downEvent) return;
64397 var mapNode = context.container().select('.main-map').node();
64398 var pointGetter = utilFastMouse(mapNode);
64399 var p1 = pointGetter(downEvent);
64400 var p2 = pointGetter(d3_event);
64401 var dist = geoVecLength(p1, p2);
64402 if (dist <= _tolerancePx) finish(d3_event);
64405 context.history().on('undone.modeMove', undone);
64406 keybinding.on('⎋', cancel).on('↩', finish);
64407 select(document).call(keybinding);
64410 mode.exit = function () {
64412 behaviors.forEach(function (behavior) {
64413 context.uninstall(behavior);
64415 context.surface().on(_pointerPrefix + 'down.modeMove', null);
64416 select(window).on(_pointerPrefix + 'move.modeMove', null, true).on(_pointerPrefix + 'up.modeMove', null, true);
64417 context.history().on('undone.modeMove', null);
64418 select(document).call(keybinding.unbind);
64419 context.features().forceVisible([]);
64422 mode.selectedIDs = function () {
64423 if (!arguments.length) return entityIDs; // no assign
64431 function behaviorPaste(context) {
64432 function doPaste(d3_event) {
64433 // prevent paste during low zoom selection
64434 if (!context.map().withinEditableZoom()) return;
64435 d3_event.preventDefault();
64436 var baseGraph = context.graph();
64437 var mouse = context.map().mouse();
64438 var projection = context.projection;
64439 var viewport = geoExtent(projection.clipExtent()).polygon();
64440 if (!geoPointInPolygon(mouse, viewport)) return;
64441 var oldIDs = context.copyIDs();
64442 if (!oldIDs.length) return;
64443 var extent = geoExtent();
64444 var oldGraph = context.copyGraph();
64446 var action = actionCopyEntities(oldIDs, oldGraph);
64447 context.perform(action);
64448 var copies = action.copies();
64449 var originals = new Set();
64450 Object.values(copies).forEach(function (entity) {
64451 originals.add(entity.id);
64454 for (var id in copies) {
64455 var oldEntity = oldGraph.entity(id);
64456 var newEntity = copies[id];
64458 extent._extend(oldEntity.extent(oldGraph)); // Exclude child nodes from newIDs if their parent way was also copied.
64461 var parents = context.graph().parentWays(newEntity);
64462 var parentCopied = parents.some(function (parent) {
64463 return originals.has(parent.id);
64466 if (!parentCopied) {
64467 newIDs.push(newEntity.id);
64469 } // Put pasted objects where mouse pointer is..
64472 var copyPoint = context.copyLonLat() && projection(context.copyLonLat()) || projection(extent.center());
64473 var delta = geoVecSubtract(mouse, copyPoint);
64474 context.perform(actionMove(newIDs, delta, projection));
64475 context.enter(modeMove(context, newIDs, baseGraph));
64478 function behavior() {
64479 context.keybinding().on(uiCmd('⌘V'), doPaste);
64483 behavior.off = function () {
64484 context.keybinding().off(uiCmd('⌘V'));
64491 `behaviorDrag` is like `d3_behavior.drag`, with the following differences:
64493 * The `origin` function is expected to return an [x, y] tuple rather than an
64495 * The events are `start`, `move`, and `end`.
64496 (https://github.com/mbostock/d3/issues/563)
64497 * The `start` event is not dispatched until the first cursor movement occurs.
64498 (https://github.com/mbostock/d3/pull/368)
64499 * The `move` event has a `point` and `delta` [x, y] tuple properties rather
64500 than `x`, `y`, `dx`, and `dy` properties.
64501 * The `end` event is not dispatched if no movement occurs.
64502 * An `off` function is available that unbinds the drag's internal event handlers.
64505 function behaviorDrag() {
64506 var dispatch = dispatch$8('start', 'move', 'end'); // see also behaviorSelect
64508 var _tolerancePx = 1; // keep this low to facilitate pixel-perfect micromapping
64510 var _penTolerancePx = 4; // styluses can be touchy so require greater movement - #1981
64512 var _origin = null;
64513 var _selector = '';
64521 var _pointerId; // use pointer events on supported platforms; fallback to mouse events
64524 var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
64526 var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect');
64528 var d3_event_userSelectSuppress = function d3_event_userSelectSuppress() {
64529 var selection$1 = selection();
64530 var select = selection$1.style(d3_event_userSelectProperty);
64531 selection$1.style(d3_event_userSelectProperty, 'none');
64532 return function () {
64533 selection$1.style(d3_event_userSelectProperty, select);
64537 function pointerdown(d3_event) {
64538 if (_pointerId) return;
64539 _pointerId = d3_event.pointerId || 'mouse';
64540 _targetNode = this; // only force reflow once per drag
64542 var pointerLocGetter = utilFastMouse(_surface || _targetNode.parentNode);
64544 var startOrigin = pointerLocGetter(d3_event);
64545 var started = false;
64546 var selectEnable = d3_event_userSelectSuppress();
64547 select(window).on(_pointerPrefix + 'move.drag', pointermove).on(_pointerPrefix + 'up.drag pointercancel.drag', pointerup, true);
64550 offset = _origin.call(_targetNode, _targetEntity);
64551 offset = [offset[0] - startOrigin[0], offset[1] - startOrigin[1]];
64556 d3_event.stopPropagation();
64558 function pointermove(d3_event) {
64559 if (_pointerId !== (d3_event.pointerId || 'mouse')) return;
64560 var p = pointerLocGetter(d3_event);
64563 var dist = geoVecLength(startOrigin, p);
64564 var tolerance = d3_event.pointerType === 'pen' ? _penTolerancePx : _tolerancePx; // don't start until the drag has actually moved somewhat
64566 if (dist < tolerance) return;
64568 dispatch.call('start', this, d3_event, _targetEntity); // Don't send a `move` event in the same cycle as `start` since dragging
64569 // a midpoint will convert the target to a node.
64572 d3_event.stopPropagation();
64573 d3_event.preventDefault();
64574 var dx = p[0] - startOrigin[0];
64575 var dy = p[1] - startOrigin[1];
64576 dispatch.call('move', this, d3_event, _targetEntity, [p[0] + offset[0], p[1] + offset[1]], [dx, dy]);
64580 function pointerup(d3_event) {
64581 if (_pointerId !== (d3_event.pointerId || 'mouse')) return;
64585 dispatch.call('end', this, d3_event, _targetEntity);
64586 d3_event.preventDefault();
64589 select(window).on(_pointerPrefix + 'move.drag', null).on(_pointerPrefix + 'up.drag pointercancel.drag', null);
64594 function behavior(selection) {
64595 var matchesSelector = utilPrefixDOMProperty('matchesSelector');
64596 var delegate = pointerdown;
64599 delegate = function delegate(d3_event) {
64601 var target = d3_event.target;
64603 for (; target && target !== root; target = target.parentNode) {
64604 var datum = target.__data__;
64605 _targetEntity = datum instanceof osmNote ? datum : datum && datum.properties && datum.properties.entity;
64607 if (_targetEntity && target[matchesSelector](_selector)) {
64608 return pointerdown.call(target, d3_event);
64614 selection.on(_pointerPrefix + 'down.drag' + _selector, delegate);
64617 behavior.off = function (selection) {
64618 selection.on(_pointerPrefix + 'down.drag' + _selector, null);
64621 behavior.selector = function (_) {
64622 if (!arguments.length) return _selector;
64627 behavior.origin = function (_) {
64628 if (!arguments.length) return _origin;
64633 behavior.cancel = function () {
64634 select(window).on(_pointerPrefix + 'move.drag', null).on(_pointerPrefix + 'up.drag pointercancel.drag', null);
64638 behavior.targetNode = function (_) {
64639 if (!arguments.length) return _targetNode;
64644 behavior.targetEntity = function (_) {
64645 if (!arguments.length) return _targetEntity;
64650 behavior.surface = function (_) {
64651 if (!arguments.length) return _surface;
64656 return utilRebind(behavior, dispatch, 'on');
64659 function modeDragNode(context) {
64664 var hover = behaviorHover(context).altDisables(true).on('hover', context.ui().sidebar.hover);
64665 var edit = behaviorEdit(context);
64667 var _nudgeInterval;
64669 var _restoreSelectedIDs = [];
64670 var _wasMidpoint = false;
64671 var _isCancelled = false;
64679 function startNudge(d3_event, entity, nudge) {
64680 if (_nudgeInterval) window.clearInterval(_nudgeInterval);
64681 _nudgeInterval = window.setInterval(function () {
64682 context.map().pan(nudge);
64683 doMove(d3_event, entity, nudge);
64687 function stopNudge() {
64688 if (_nudgeInterval) {
64689 window.clearInterval(_nudgeInterval);
64690 _nudgeInterval = null;
64694 function moveAnnotation(entity) {
64695 return _t('operations.move.annotation.' + entity.geometry(context.graph()));
64698 function connectAnnotation(nodeEntity, targetEntity) {
64699 var nodeGeometry = nodeEntity.geometry(context.graph());
64700 var targetGeometry = targetEntity.geometry(context.graph());
64702 if (nodeGeometry === 'vertex' && targetGeometry === 'vertex') {
64703 var nodeParentWayIDs = context.graph().parentWays(nodeEntity);
64704 var targetParentWayIDs = context.graph().parentWays(targetEntity);
64705 var sharedParentWays = utilArrayIntersection(nodeParentWayIDs, targetParentWayIDs); // if both vertices are part of the same way
64707 if (sharedParentWays.length !== 0) {
64708 // if the nodes are next to each other, they are merged
64709 if (sharedParentWays[0].areAdjacent(nodeEntity.id, targetEntity.id)) {
64710 return _t('operations.connect.annotation.from_vertex.to_adjacent_vertex');
64713 return _t('operations.connect.annotation.from_vertex.to_sibling_vertex');
64717 return _t('operations.connect.annotation.from_' + nodeGeometry + '.to_' + targetGeometry);
64720 function shouldSnapToNode(target) {
64721 if (!_activeEntity) return false;
64722 return _activeEntity.geometry(context.graph()) !== 'vertex' || target.geometry(context.graph()) === 'vertex' || _mainPresetIndex.allowsVertex(target, context.graph());
64725 function origin(entity) {
64726 return context.projection(entity.loc);
64729 function keydown(d3_event) {
64730 if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
64731 if (context.surface().classed('nope')) {
64732 context.surface().classed('nope-suppressed', true);
64735 context.surface().classed('nope', false).classed('nope-disabled', true);
64739 function keyup(d3_event) {
64740 if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
64741 if (context.surface().classed('nope-suppressed')) {
64742 context.surface().classed('nope', true);
64745 context.surface().classed('nope-suppressed', false).classed('nope-disabled', false);
64749 function start(d3_event, entity) {
64750 _wasMidpoint = entity.type === 'midpoint';
64751 var hasHidden = context.features().hasHiddenConnections(entity, context.graph());
64752 _isCancelled = !context.editable() || d3_event.shiftKey || hasHidden;
64754 if (_isCancelled) {
64756 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t('modes.drag_node.connected_to_hidden'))();
64759 return drag.cancel();
64762 if (_wasMidpoint) {
64763 var midpoint = entity;
64764 entity = osmNode();
64765 context.perform(actionAddMidpoint(midpoint, entity));
64766 entity = context.entity(entity.id); // get post-action entity
64768 var vertex = context.surface().selectAll('.' + entity.id);
64769 drag.targetNode(vertex.node()).targetEntity(entity);
64771 context.perform(actionNoop());
64774 _activeEntity = entity;
64775 _startLoc = entity.loc;
64776 hover.ignoreVertex(entity.geometry(context.graph()) === 'vertex');
64777 context.surface().selectAll('.' + _activeEntity.id).classed('active', true);
64778 context.enter(mode);
64780 // - `behavior/draw.js` `datum()`
64783 function datum(d3_event) {
64784 if (!d3_event || d3_event.altKey) {
64787 // When dragging, snap only to touch targets..
64788 // (this excludes area fills and active drawing elements)
64789 var d = d3_event.target.__data__;
64790 return d && d.properties && d.properties.target ? d : {};
64794 function doMove(d3_event, entity, nudge) {
64795 nudge = nudge || [0, 0];
64796 var currPoint = d3_event && d3_event.point || context.projection(_lastLoc);
64797 var currMouse = geoVecSubtract(currPoint, nudge);
64798 var loc = context.projection.invert(currMouse);
64801 if (!_nudgeInterval) {
64802 // If not nudging at the edge of the viewport, try to snap..
64804 // - `mode/drag_node.js` `doMove()`
64805 // - `behavior/draw.js` `click()`
64806 // - `behavior/draw_way.js` `move()`
64807 var d = datum(d3_event);
64808 target = d && d.properties && d.properties.entity;
64809 var targetLoc = target && target.loc;
64810 var targetNodes = d && d.properties && d.properties.nodes;
64813 // snap to node/vertex - a point target with `.loc`
64814 if (shouldSnapToNode(target)) {
64817 } else if (targetNodes) {
64818 // snap to way - a line target with `.nodes`
64819 edge = geoChooseEdge(targetNodes, context.map().mouse(), context.projection, end.id);
64827 context.replace(actionMoveNode(entity.id, loc)); // Below here: validations
64829 var isInvalid = false; // Check if this connection to `target` could cause relations to break..
64832 isInvalid = hasRelationConflict(entity, target, edge, context.graph());
64833 } // Check if this drag causes the geometry to break..
64837 isInvalid = hasInvalidGeometry(entity, context.graph());
64840 var nope = context.surface().classed('nope');
64842 if (isInvalid === 'relation' || isInvalid === 'restriction') {
64844 // about to nope - show hint
64845 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html('operations.connect.' + isInvalid, {
64846 relation: _mainPresetIndex.item('type/restriction').name()
64849 } else if (isInvalid) {
64850 var errorID = isInvalid === 'line' ? 'lines' : 'areas';
64851 context.ui().flash.duration(3000).iconName('#iD-icon-no').label(_t.html('self_intersection.error.' + errorID))();
64854 // about to un-nope, remove hint
64855 context.ui().flash.duration(1).label('')();
64859 var nopeDisabled = context.surface().classed('nope-disabled');
64861 if (nopeDisabled) {
64862 context.surface().classed('nope', false).classed('nope-suppressed', isInvalid);
64864 context.surface().classed('nope', isInvalid).classed('nope-suppressed', false);
64868 } // Uses `actionConnect.disabled()` to know whether this connection is ok..
64871 function hasRelationConflict(entity, target, edge, graph) {
64872 var testGraph = graph.update(); // copy
64873 // if snapping to way - add midpoint there and consider that the target..
64876 var midpoint = osmNode();
64877 var action = actionAddMidpoint({
64879 edge: [target.nodes[edge.index - 1], target.nodes[edge.index]]
64881 testGraph = action(testGraph);
64883 } // can we connect to it?
64886 var ids = [entity.id, target.id];
64887 return actionConnect(ids).disabled(testGraph);
64890 function hasInvalidGeometry(entity, graph) {
64891 var parents = graph.parentWays(entity);
64894 for (i = 0; i < parents.length; i++) {
64895 var parent = parents[i];
64897 var activeIndex = null; // which multipolygon ring contains node being dragged
64898 // test any parent multipolygons for valid geometry
64900 var relations = graph.parentRelations(parent);
64902 for (j = 0; j < relations.length; j++) {
64903 if (!relations[j].isMultipolygon()) continue;
64904 var rings = osmJoinWays(relations[j].members, graph); // find active ring and test it for self intersections
64906 for (k = 0; k < rings.length; k++) {
64907 nodes = rings[k].nodes;
64909 if (nodes.find(function (n) {
64910 return n.id === entity.id;
64914 if (geoHasSelfIntersections(nodes, entity.id)) {
64915 return 'multipolygonMember';
64919 rings[k].coords = nodes.map(function (n) {
64922 } // test active ring for intersections with other rings in the multipolygon
64925 for (k = 0; k < rings.length; k++) {
64926 if (k === activeIndex) continue; // make sure active ring doesn't cross passive rings
64928 if (geoHasLineIntersections(rings[activeIndex].nodes, rings[k].nodes, entity.id)) {
64929 return 'multipolygonRing';
64932 } // If we still haven't tested this node's parent way for self-intersections.
64933 // (because it's not a member of a multipolygon), test it now.
64936 if (activeIndex === null) {
64937 nodes = parent.nodes.map(function (nodeID) {
64938 return graph.entity(nodeID);
64941 if (nodes.length && geoHasSelfIntersections(nodes, entity.id)) {
64942 return parent.geometry(graph);
64950 function move(d3_event, entity, point) {
64951 if (_isCancelled) return;
64952 d3_event.stopPropagation();
64953 context.surface().classed('nope-disabled', d3_event.altKey);
64954 _lastLoc = context.projection.invert(point);
64955 doMove(d3_event, entity);
64956 var nudge = geoViewportEdge(point, context.map().dimensions());
64959 startNudge(d3_event, entity, nudge);
64965 function end(d3_event, entity) {
64966 if (_isCancelled) return;
64967 var wasPoint = entity.geometry(context.graph()) === 'point';
64968 var d = datum(d3_event);
64969 var nope = d && d.properties && d.properties.nope || context.surface().classed('nope');
64970 var target = d && d.properties && d.properties.entity; // entity to snap to
64974 context.perform(_actionBounceBack(entity.id, _startLoc));
64975 } else if (target && target.type === 'way') {
64976 var choice = geoChooseEdge(context.graph().childNodes(target), context.map().mouse(), context.projection, entity.id);
64977 context.replace(actionAddMidpoint({
64979 edge: [target.nodes[choice.index - 1], target.nodes[choice.index]]
64980 }, entity), connectAnnotation(entity, target));
64981 } else if (target && target.type === 'node' && shouldSnapToNode(target)) {
64982 context.replace(actionConnect([target.id, entity.id]), connectAnnotation(entity, target));
64983 } else if (_wasMidpoint) {
64984 context.replace(actionNoop(), _t('operations.add.annotation.vertex'));
64986 context.replace(actionNoop(), moveAnnotation(entity));
64990 context.enter(modeSelect(context, [entity.id]));
64992 var reselection = _restoreSelectedIDs.filter(function (id) {
64993 return context.graph().hasEntity(id);
64996 if (reselection.length) {
64997 context.enter(modeSelect(context, reselection));
64999 context.enter(modeBrowse(context));
65004 function _actionBounceBack(nodeID, toLoc) {
65005 var moveNode = actionMoveNode(nodeID, toLoc);
65007 var action = function action(graph, t) {
65008 // last time through, pop off the bounceback perform.
65009 // it will then overwrite the initial perform with a moveNode that does nothing
65010 if (t === 1) context.pop();
65011 return moveNode(graph, t);
65014 action.transitionable = true;
65018 function cancel() {
65020 context.enter(modeBrowse(context));
65023 var drag = behaviorDrag().selector('.layer-touch.points .target').surface(context.container().select('.main-map').node()).origin(origin).on('start', start).on('move', move).on('end', end);
65025 mode.enter = function () {
65026 context.install(hover);
65027 context.install(edit);
65028 select(window).on('keydown.dragNode', keydown).on('keyup.dragNode', keyup);
65029 context.history().on('undone.drag-node', cancel);
65032 mode.exit = function () {
65033 context.ui().sidebar.hover.cancel();
65034 context.uninstall(hover);
65035 context.uninstall(edit);
65036 select(window).on('keydown.dragNode', null).on('keyup.dragNode', null);
65037 context.history().on('undone.drag-node', null);
65038 _activeEntity = null;
65039 context.surface().classed('nope', false).classed('nope-suppressed', false).classed('nope-disabled', false).selectAll('.active').classed('active', false);
65043 mode.selectedIDs = function () {
65044 if (!arguments.length) return _activeEntity ? [_activeEntity.id] : []; // no assign
65049 mode.activeID = function () {
65050 if (!arguments.length) return _activeEntity && _activeEntity.id; // no assign
65055 mode.restoreSelectedIDs = function (_) {
65056 if (!arguments.length) return _restoreSelectedIDs;
65057 _restoreSelectedIDs = _;
65061 mode.behavior = drag;
65066 var NativePromise = nativePromiseConstructor;
65067 var fails$1 = fails$V;
65068 var getBuiltIn = getBuiltIn$b;
65069 var isCallable = isCallable$r;
65070 var speciesConstructor = speciesConstructor$5;
65071 var promiseResolve = promiseResolve$2;
65072 var redefine$1 = redefine$h.exports;
65074 // Safari bug https://bugs.webkit.org/show_bug.cgi?id=200829
65075 var NON_GENERIC = !!NativePromise && fails$1(function () {
65076 // eslint-disable-next-line unicorn/no-thenable -- required for testing
65077 NativePromise.prototype['finally'].call({ then: function () { /* empty */ } }, function () { /* empty */ });
65080 // `Promise.prototype.finally` method
65081 // https://tc39.es/ecma262/#sec-promise.prototype.finally
65082 $$3({ target: 'Promise', proto: true, real: true, forced: NON_GENERIC }, {
65083 'finally': function (onFinally) {
65084 var C = speciesConstructor(this, getBuiltIn('Promise'));
65085 var isFunction = isCallable(onFinally);
65087 isFunction ? function (x) {
65088 return promiseResolve(C, onFinally()).then(function () { return x; });
65090 isFunction ? function (e) {
65091 return promiseResolve(C, onFinally()).then(function () { throw e; });
65097 // makes sure that native promise-based APIs `Promise#finally` properly works with patched `Promise#then`
65098 if (isCallable(NativePromise)) {
65099 var method = getBuiltIn('Promise').prototype['finally'];
65100 if (NativePromise.prototype['finally'] !== method) {
65101 redefine$1(NativePromise.prototype, 'finally', method, { unsafe: true });
65105 function quickselect(arr, k, left, right, compare) {
65106 quickselectStep(arr, k, left || 0, right || arr.length - 1, compare || defaultCompare);
65109 function quickselectStep(arr, k, left, right, compare) {
65110 while (right > left) {
65111 if (right - left > 600) {
65112 var n = right - left + 1;
65113 var m = k - left + 1;
65114 var z = Math.log(n);
65115 var s = 0.5 * Math.exp(2 * z / 3);
65116 var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
65117 var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
65118 var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
65119 quickselectStep(arr, k, newLeft, newRight, compare);
65125 swap(arr, left, k);
65126 if (compare(arr[right], t) > 0) swap(arr, left, right);
65133 while (compare(arr[i], t) < 0) {
65137 while (compare(arr[j], t) > 0) {
65142 if (compare(arr[left], t) === 0) swap(arr, left, j);else {
65144 swap(arr, j, right);
65146 if (j <= k) left = j + 1;
65147 if (k <= j) right = j - 1;
65151 function swap(arr, i, j) {
65157 function defaultCompare(a, b) {
65158 return a < b ? -1 : a > b ? 1 : 0;
65161 var RBush = /*#__PURE__*/function () {
65163 var maxEntries = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 9;
65165 _classCallCheck$1(this, RBush);
65167 // max entries in a node is 9 by default; min node fill is 40% for best performance
65168 this._maxEntries = Math.max(4, maxEntries);
65169 this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
65173 _createClass$1(RBush, [{
65175 value: function all() {
65176 return this._all(this.data, []);
65180 value: function search(bbox) {
65181 var node = this.data;
65183 if (!intersects(bbox, node)) return result;
65184 var toBBox = this.toBBox;
65185 var nodesToSearch = [];
65188 for (var i = 0; i < node.children.length; i++) {
65189 var child = node.children[i];
65190 var childBBox = node.leaf ? toBBox(child) : child;
65192 if (intersects(bbox, childBBox)) {
65193 if (node.leaf) result.push(child);else if (contains(bbox, childBBox)) this._all(child, result);else nodesToSearch.push(child);
65197 node = nodesToSearch.pop();
65204 value: function collides(bbox) {
65205 var node = this.data;
65206 if (!intersects(bbox, node)) return false;
65207 var nodesToSearch = [];
65210 for (var i = 0; i < node.children.length; i++) {
65211 var child = node.children[i];
65212 var childBBox = node.leaf ? this.toBBox(child) : child;
65214 if (intersects(bbox, childBBox)) {
65215 if (node.leaf || contains(bbox, childBBox)) return true;
65216 nodesToSearch.push(child);
65220 node = nodesToSearch.pop();
65227 value: function load(data) {
65228 if (!(data && data.length)) return this;
65230 if (data.length < this._minEntries) {
65231 for (var i = 0; i < data.length; i++) {
65232 this.insert(data[i]);
65236 } // recursively build the tree with the given data from scratch using OMT algorithm
65239 var node = this._build(data.slice(), 0, data.length - 1, 0);
65241 if (!this.data.children.length) {
65242 // save as is if tree is empty
65244 } else if (this.data.height === node.height) {
65245 // split root if trees have the same height
65246 this._splitRoot(this.data, node);
65248 if (this.data.height < node.height) {
65249 // swap trees if inserted one is bigger
65250 var tmpNode = this.data;
65253 } // insert the small tree into the large tree at appropriate level
65256 this._insert(node, this.data.height - node.height - 1, true);
65263 value: function insert(item) {
65264 if (item) this._insert(item, this.data.height - 1);
65269 value: function clear() {
65270 this.data = createNode([]);
65275 value: function remove(item, equalsFn) {
65276 if (!item) return this;
65277 var node = this.data;
65278 var bbox = this.toBBox(item);
65281 var i, parent, goingUp; // depth-first iterative tree traversal
65283 while (node || path.length) {
65287 parent = path[path.length - 1];
65293 // check current node
65294 var index = findItem(item, node.children, equalsFn);
65296 if (index !== -1) {
65297 // item found, remove the item and condense tree upwards
65298 node.children.splice(index, 1);
65301 this._condense(path);
65307 if (!goingUp && !node.leaf && contains(node, bbox)) {
65313 node = node.children[0];
65314 } else if (parent) {
65317 node = parent.children[i];
65319 } else node = null; // nothing found
65327 value: function toBBox(item) {
65331 key: "compareMinX",
65332 value: function compareMinX(a, b) {
65333 return a.minX - b.minX;
65336 key: "compareMinY",
65337 value: function compareMinY(a, b) {
65338 return a.minY - b.minY;
65342 value: function toJSON() {
65347 value: function fromJSON(data) {
65353 value: function _all(node, result) {
65354 var nodesToSearch = [];
65357 if (node.leaf) result.push.apply(result, _toConsumableArray(node.children));else nodesToSearch.push.apply(nodesToSearch, _toConsumableArray(node.children));
65358 node = nodesToSearch.pop();
65365 value: function _build(items, left, right, height) {
65366 var N = right - left + 1;
65367 var M = this._maxEntries;
65371 // reached leaf level; return leaf
65372 node = createNode(items.slice(left, right + 1));
65373 calcBBox(node, this.toBBox);
65378 // target height of the bulk-loaded tree
65379 height = Math.ceil(Math.log(N) / Math.log(M)); // target number of root entries to maximize storage utilization
65381 M = Math.ceil(N / Math.pow(M, height - 1));
65384 node = createNode([]);
65386 node.height = height; // split the items into M mostly square tiles
65388 var N2 = Math.ceil(N / M);
65389 var N1 = N2 * Math.ceil(Math.sqrt(M));
65390 multiSelect(items, left, right, N1, this.compareMinX);
65392 for (var i = left; i <= right; i += N1) {
65393 var right2 = Math.min(i + N1 - 1, right);
65394 multiSelect(items, i, right2, N2, this.compareMinY);
65396 for (var j = i; j <= right2; j += N2) {
65397 var right3 = Math.min(j + N2 - 1, right2); // pack each entry recursively
65399 node.children.push(this._build(items, j, right3, height - 1));
65403 calcBBox(node, this.toBBox);
65407 key: "_chooseSubtree",
65408 value: function _chooseSubtree(bbox, node, level, path) {
65411 if (node.leaf || path.length - 1 === level) break;
65412 var minArea = Infinity;
65413 var minEnlargement = Infinity;
65414 var targetNode = void 0;
65416 for (var i = 0; i < node.children.length; i++) {
65417 var child = node.children[i];
65418 var area = bboxArea(child);
65419 var enlargement = enlargedArea(bbox, child) - area; // choose entry with the least area enlargement
65421 if (enlargement < minEnlargement) {
65422 minEnlargement = enlargement;
65423 minArea = area < minArea ? area : minArea;
65424 targetNode = child;
65425 } else if (enlargement === minEnlargement) {
65426 // otherwise choose one with the smallest area
65427 if (area < minArea) {
65429 targetNode = child;
65434 node = targetNode || node.children[0];
65441 value: function _insert(item, level, isNode) {
65442 var bbox = isNode ? item : this.toBBox(item);
65443 var insertPath = []; // find the best node for accommodating the item, saving all nodes along the path too
65445 var node = this._chooseSubtree(bbox, this.data, level, insertPath); // put the item into the node
65448 node.children.push(item);
65449 extend$1(node, bbox); // split on node overflow; propagate upwards if necessary
65451 while (level >= 0) {
65452 if (insertPath[level].children.length > this._maxEntries) {
65453 this._split(insertPath, level);
65457 } // adjust bboxes along the insertion path
65460 this._adjustParentBBoxes(bbox, insertPath, level);
65461 } // split overflowed node into two
65465 value: function _split(insertPath, level) {
65466 var node = insertPath[level];
65467 var M = node.children.length;
65468 var m = this._minEntries;
65470 this._chooseSplitAxis(node, m, M);
65472 var splitIndex = this._chooseSplitIndex(node, m, M);
65474 var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
65475 newNode.height = node.height;
65476 newNode.leaf = node.leaf;
65477 calcBBox(node, this.toBBox);
65478 calcBBox(newNode, this.toBBox);
65479 if (level) insertPath[level - 1].children.push(newNode);else this._splitRoot(node, newNode);
65483 value: function _splitRoot(node, newNode) {
65485 this.data = createNode([node, newNode]);
65486 this.data.height = node.height + 1;
65487 this.data.leaf = false;
65488 calcBBox(this.data, this.toBBox);
65491 key: "_chooseSplitIndex",
65492 value: function _chooseSplitIndex(node, m, M) {
65494 var minOverlap = Infinity;
65495 var minArea = Infinity;
65497 for (var i = m; i <= M - m; i++) {
65498 var bbox1 = distBBox(node, 0, i, this.toBBox);
65499 var bbox2 = distBBox(node, i, M, this.toBBox);
65500 var overlap = intersectionArea(bbox1, bbox2);
65501 var area = bboxArea(bbox1) + bboxArea(bbox2); // choose distribution with minimum overlap
65503 if (overlap < minOverlap) {
65504 minOverlap = overlap;
65506 minArea = area < minArea ? area : minArea;
65507 } else if (overlap === minOverlap) {
65508 // otherwise choose distribution with minimum area
65509 if (area < minArea) {
65516 return index || M - m;
65517 } // sorts node children by the best axis for split
65520 key: "_chooseSplitAxis",
65521 value: function _chooseSplitAxis(node, m, M) {
65522 var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;
65523 var compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;
65525 var xMargin = this._allDistMargin(node, m, M, compareMinX);
65527 var yMargin = this._allDistMargin(node, m, M, compareMinY); // if total distributions margin value is minimal for x, sort by minX,
65528 // otherwise it's already sorted by minY
65531 if (xMargin < yMargin) node.children.sort(compareMinX);
65532 } // total margin of all possible split distributions where each node is at least m full
65535 key: "_allDistMargin",
65536 value: function _allDistMargin(node, m, M, compare) {
65537 node.children.sort(compare);
65538 var toBBox = this.toBBox;
65539 var leftBBox = distBBox(node, 0, m, toBBox);
65540 var rightBBox = distBBox(node, M - m, M, toBBox);
65541 var margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);
65543 for (var i = m; i < M - m; i++) {
65544 var child = node.children[i];
65545 extend$1(leftBBox, node.leaf ? toBBox(child) : child);
65546 margin += bboxMargin(leftBBox);
65549 for (var _i = M - m - 1; _i >= m; _i--) {
65550 var _child = node.children[_i];
65551 extend$1(rightBBox, node.leaf ? toBBox(_child) : _child);
65552 margin += bboxMargin(rightBBox);
65558 key: "_adjustParentBBoxes",
65559 value: function _adjustParentBBoxes(bbox, path, level) {
65560 // adjust bboxes along the given tree path
65561 for (var i = level; i >= 0; i--) {
65562 extend$1(path[i], bbox);
65567 value: function _condense(path) {
65568 // go through the path, removing empty nodes and updating bboxes
65569 for (var i = path.length - 1, siblings; i >= 0; i--) {
65570 if (path[i].children.length === 0) {
65572 siblings = path[i - 1].children;
65573 siblings.splice(siblings.indexOf(path[i]), 1);
65574 } else this.clear();
65575 } else calcBBox(path[i], this.toBBox);
65583 function findItem(item, items, equalsFn) {
65584 if (!equalsFn) return items.indexOf(item);
65586 for (var i = 0; i < items.length; i++) {
65587 if (equalsFn(item, items[i])) return i;
65591 } // calculate node's bbox from bboxes of its children
65594 function calcBBox(node, toBBox) {
65595 distBBox(node, 0, node.children.length, toBBox, node);
65596 } // min bounding rectangle of node children from k to p-1
65599 function distBBox(node, k, p, toBBox, destNode) {
65600 if (!destNode) destNode = createNode(null);
65601 destNode.minX = Infinity;
65602 destNode.minY = Infinity;
65603 destNode.maxX = -Infinity;
65604 destNode.maxY = -Infinity;
65606 for (var i = k; i < p; i++) {
65607 var child = node.children[i];
65608 extend$1(destNode, node.leaf ? toBBox(child) : child);
65614 function extend$1(a, b) {
65615 a.minX = Math.min(a.minX, b.minX);
65616 a.minY = Math.min(a.minY, b.minY);
65617 a.maxX = Math.max(a.maxX, b.maxX);
65618 a.maxY = Math.max(a.maxY, b.maxY);
65622 function compareNodeMinX(a, b) {
65623 return a.minX - b.minX;
65626 function compareNodeMinY(a, b) {
65627 return a.minY - b.minY;
65630 function bboxArea(a) {
65631 return (a.maxX - a.minX) * (a.maxY - a.minY);
65634 function bboxMargin(a) {
65635 return a.maxX - a.minX + (a.maxY - a.minY);
65638 function enlargedArea(a, b) {
65639 return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) * (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
65642 function intersectionArea(a, b) {
65643 var minX = Math.max(a.minX, b.minX);
65644 var minY = Math.max(a.minY, b.minY);
65645 var maxX = Math.min(a.maxX, b.maxX);
65646 var maxY = Math.min(a.maxY, b.maxY);
65647 return Math.max(0, maxX - minX) * Math.max(0, maxY - minY);
65650 function contains(a, b) {
65651 return a.minX <= b.minX && a.minY <= b.minY && b.maxX <= a.maxX && b.maxY <= a.maxY;
65654 function intersects(a, b) {
65655 return b.minX <= a.maxX && b.minY <= a.maxY && b.maxX >= a.minX && b.maxY >= a.minY;
65658 function createNode(children) {
65660 children: children,
65668 } // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
65669 // combines selection algorithm with binary divide & conquer approach
65672 function multiSelect(arr, left, right, n, compare) {
65673 var stack = [left, right];
65675 while (stack.length) {
65676 right = stack.pop();
65677 left = stack.pop();
65678 if (right - left <= n) continue;
65679 var mid = left + Math.ceil((right - left) / n / 2) * n;
65680 quickselect(arr, mid, left, right, compare);
65681 stack.push(left, mid, mid, right);
65685 function responseText(response) {
65686 if (!response.ok) throw new Error(response.status + " " + response.statusText);
65687 return response.text();
65690 function d3_text (input, init) {
65691 return fetch(input, init).then(responseText);
65694 function responseJson(response) {
65695 if (!response.ok) throw new Error(response.status + " " + response.statusText);
65696 if (response.status === 204 || response.status === 205) return;
65697 return response.json();
65700 function d3_json (input, init) {
65701 return fetch(input, init).then(responseJson);
65704 function parser(type) {
65705 return function (input, init) {
65706 return d3_text(input, init).then(function (text) {
65707 return new DOMParser().parseFromString(text, type);
65712 var d3_xml = parser("application/xml");
65713 var svg = parser("image/svg+xml");
65715 var tiler$6 = utilTiler();
65716 var dispatch$7 = dispatch$8('loaded');
65717 var _tileZoom$3 = 14;
65718 var _krUrlRoot = 'https://www.keepright.at';
65721 localizeStrings: {}
65722 }; // This gets reassigned if reset
65726 var _krRuleset = [// no 20 - multiple node on same spot - these are mostly boundaries overlapping roads
65727 30, 40, 50, 60, 70, 90, 100, 110, 120, 130, 150, 160, 170, 180, 190, 191, 192, 193, 194, 195, 196, 197, 198, 200, 201, 202, 203, 204, 205, 206, 207, 208, 210, 220, 230, 231, 232, 270, 280, 281, 282, 283, 284, 285, 290, 291, 292, 293, 294, 295, 296, 297, 298, 300, 310, 311, 312, 313, 320, 350, 360, 370, 380, 390, 400, 401, 402, 410, 411, 412, 413];
65729 function abortRequest$6(controller) {
65731 controller.abort();
65735 function abortUnwantedRequests$3(cache, tiles) {
65736 Object.keys(cache.inflightTile).forEach(function (k) {
65737 var wanted = tiles.find(function (tile) {
65738 return k === tile.id;
65742 abortRequest$6(cache.inflightTile[k]);
65743 delete cache.inflightTile[k];
65748 function encodeIssueRtree$2(d) {
65756 } // Replace or remove QAItem from rtree
65759 function updateRtree$3(item, replace) {
65760 _cache$2.rtree.remove(item, function (a, b) {
65761 return a.data.id === b.data.id;
65765 _cache$2.rtree.insert(item);
65769 function tokenReplacements(d) {
65770 if (!(d instanceof QAItem)) return;
65771 var replacements = {};
65772 var issueTemplate = _krData.errorTypes[d.whichType];
65774 if (!issueTemplate) {
65775 /* eslint-disable no-console */
65776 console.log('No Template: ', d.whichType);
65777 console.log(' ', d.description);
65778 /* eslint-enable no-console */
65781 } // some descriptions are just fixed text
65784 if (!issueTemplate.regex) return; // regex pattern should match description with variable details captured
65786 var errorRegex = new RegExp(issueTemplate.regex, 'i');
65787 var errorMatch = errorRegex.exec(d.description);
65790 /* eslint-disable no-console */
65791 console.log('Unmatched: ', d.whichType);
65792 console.log(' ', d.description);
65793 console.log(' ', errorRegex);
65794 /* eslint-enable no-console */
65799 for (var i = 1; i < errorMatch.length; i++) {
65801 var capture = errorMatch[i];
65802 var idType = void 0;
65803 idType = 'IDs' in issueTemplate ? issueTemplate.IDs[i - 1] : '';
65805 if (idType && capture) {
65806 // link IDs if present in the capture
65807 capture = parseError(capture, idType);
65809 var compare = capture.toLowerCase();
65811 if (_krData.localizeStrings[compare]) {
65812 // some replacement strings can be localized
65813 capture = _t('QA.keepRight.error_parts.' + _krData.localizeStrings[compare]);
65815 capture = unescape$3(capture);
65819 replacements['var' + i] = capture;
65822 return replacements;
65825 function parseError(capture, idType) {
65826 var compare = capture.toLowerCase();
65828 if (_krData.localizeStrings[compare]) {
65829 // some replacement strings can be localized
65830 capture = _t('QA.keepRight.error_parts.' + _krData.localizeStrings[compare]);
65834 // link a string like "this node"
65836 capture = linkErrorObject(capture);
65840 capture = linkURL(capture);
65842 // link an entity ID
65847 capture = linkEntity(idType + capture);
65849 // some errors have more complex ID lists/variance
65852 capture = parse20(capture);
65856 capture = parse211(capture);
65860 capture = parse231(capture);
65864 capture = parse294(capture);
65868 capture = parse370(capture);
65874 function linkErrorObject(d) {
65876 html: "<a class=\"error_object_link\">".concat(d, "</a>")
65880 function linkEntity(d) {
65882 html: "<a class=\"error_entity_link\">".concat(d, "</a>")
65886 function linkURL(d) {
65888 html: "<a class=\"kr_external_link\" target=\"_blank\" href=\"".concat(d, "\">").concat(d, "</a>")
65890 } // arbitrary node list of form: #ID, #ID, #ID...
65893 function parse211(capture) {
65895 var items = capture.split(', ');
65896 items.forEach(function (item) {
65897 // ID has # at the front
65898 var id = linkEntity('n' + item.slice(1));
65901 return newList.join(', ');
65902 } // arbitrary way list of form: #ID(layer),#ID(layer),#ID(layer)...
65905 function parse231(capture) {
65906 var newList = []; // unfortunately 'layer' can itself contain commas, so we split on '),'
65908 var items = capture.split('),');
65909 items.forEach(function (item) {
65910 var match = item.match(/\#(\d+)\((.+)\)?/);
65912 if (match !== null && match.length > 2) {
65913 newList.push(linkEntity('w' + match[1]) + ' ' + _t('QA.keepRight.errorTypes.231.layer', {
65918 return newList.join(', ');
65919 } // arbitrary node/relation list of form: from node #ID,to relation #ID,to node #ID...
65922 function parse294(capture) {
65924 var items = capture.split(',');
65925 items.forEach(function (item) {
65926 // item of form "from/to node/relation #ID"
65927 item = item.split(' '); // to/from role is more clear in quotes
65929 var role = "\"".concat(item[0], "\""); // first letter of node/relation provides the type
65931 var idType = item[1].slice(0, 1); // ID has # at the front
65933 var id = item[2].slice(1);
65934 id = linkEntity(idType + id);
65935 newList.push("".concat(role, " ").concat(item[1], " ").concat(id));
65937 return newList.join(', ');
65938 } // may or may not include the string "(including the name 'name')"
65941 function parse370(capture) {
65942 if (!capture) return '';
65943 var match = capture.match(/\(including the name (\'.+\')\)/);
65945 if (match && match.length) {
65946 return _t('QA.keepRight.errorTypes.370.including_the_name', {
65952 } // arbitrary node list of form: #ID,#ID,#ID...
65955 function parse20(capture) {
65957 var items = capture.split(',');
65958 items.forEach(function (item) {
65959 // ID has # at the front
65960 var id = linkEntity('n' + item.slice(1));
65963 return newList.join(', ');
65967 var serviceKeepRight = {
65968 title: 'keepRight',
65969 init: function init() {
65970 _mainFileFetcher.get('keepRight').then(function (d) {
65971 return _krData = d;
65978 this.event = utilRebind(this, dispatch$7, 'on');
65980 reset: function reset() {
65982 Object.values(_cache$2.inflightTile).forEach(abortRequest$6);
65994 // KeepRight API: http://osm.mueschelsoft.de/keepright/interfacing.php
65995 loadIssues: function loadIssues(projection) {
66001 }; // determine the needed tiles to cover the view
66003 var tiles = tiler$6.zoomExtent([_tileZoom$3, _tileZoom$3]).getTiles(projection); // abort inflight requests that are no longer needed
66005 abortUnwantedRequests$3(_cache$2, tiles); // issue new requests..
66007 tiles.forEach(function (tile) {
66008 if (_cache$2.loadedTile[tile.id] || _cache$2.inflightTile[tile.id]) return;
66010 var _tile$extent$rectangl = tile.extent.rectangle(),
66011 _tile$extent$rectangl2 = _slicedToArray(_tile$extent$rectangl, 4),
66012 left = _tile$extent$rectangl2[0],
66013 top = _tile$extent$rectangl2[1],
66014 right = _tile$extent$rectangl2[2],
66015 bottom = _tile$extent$rectangl2[3];
66017 var params = Object.assign({}, options, {
66023 var url = "".concat(_krUrlRoot, "/export.php?") + utilQsString(params);
66024 var controller = new AbortController();
66025 _cache$2.inflightTile[tile.id] = controller;
66027 signal: controller.signal
66028 }).then(function (data) {
66029 delete _cache$2.inflightTile[tile.id];
66030 _cache$2.loadedTile[tile.id] = true;
66032 if (!data || !data.features || !data.features.length) {
66033 throw new Error('No Data');
66036 data.features.forEach(function (feature) {
66037 var _feature$properties = feature.properties,
66038 itemType = _feature$properties.error_type,
66039 id = _feature$properties.error_id,
66040 _feature$properties$c = _feature$properties.comment,
66041 comment = _feature$properties$c === void 0 ? null : _feature$properties$c,
66042 objectId = _feature$properties.object_id,
66043 objectType = _feature$properties.object_type,
66044 schema = _feature$properties.schema,
66045 title = _feature$properties.title;
66046 var loc = feature.geometry.coordinates,
66047 _feature$properties$d = feature.properties.description,
66048 description = _feature$properties$d === void 0 ? '' : _feature$properties$d; // if there is a parent, save its error type e.g.:
66049 // Error 191 = "highway-highway"
66050 // Error 190 = "intersections without junctions" (parent)
66052 var issueTemplate = _krData.errorTypes[itemType];
66053 var parentIssueType = (Math.floor(itemType / 10) * 10).toString(); // try to handle error type directly, fallback to parent error type.
66055 var whichType = issueTemplate ? itemType : parentIssueType;
66056 var whichTemplate = _krData.errorTypes[whichType]; // Rewrite a few of the errors at this point..
66057 // This is done to make them easier to linkify and translate.
66059 switch (whichType) {
66061 description = "This feature has a FIXME tag: ".concat(description);
66066 description = description.replace('A turn-', 'This turn-');
66074 description = "This turn-restriction~".concat(description);
66078 description = 'This highway is missing a maxspeed tag';
66084 description = "This feature~".concat(description);
66086 } // move markers slightly so it doesn't obscure the geometry,
66087 // then move markers away from other coincident markers
66090 var coincident = false;
66093 // first time, move marker up. after that, move marker right.
66094 var delta = coincident ? [0.00001, 0] : [0, 0.00001];
66095 loc = geoVecAdd(loc, delta);
66096 var bbox = geoExtent(loc).bbox();
66097 coincident = _cache$2.rtree.search(bbox).length;
66098 } while (coincident);
66100 var d = new QAItem(loc, _this, itemType, id, {
66102 description: description,
66103 whichType: whichType,
66104 parentIssueType: parentIssueType,
66105 severity: whichTemplate.severity || 'error',
66106 objectId: objectId,
66107 objectType: objectType,
66111 d.replacements = tokenReplacements(d);
66112 _cache$2.data[id] = d;
66114 _cache$2.rtree.insert(encodeIssueRtree$2(d));
66116 dispatch$7.call('loaded');
66117 })["catch"](function () {
66118 delete _cache$2.inflightTile[tile.id];
66119 _cache$2.loadedTile[tile.id] = true;
66123 postUpdate: function postUpdate(d, callback) {
66126 if (_cache$2.inflightPost[d.id]) {
66128 message: 'Error update already inflight',
66139 params.st = d.newStatus;
66142 if (d.newComment !== undefined) {
66143 params.co = d.newComment;
66144 } // NOTE: This throws a CORS err, but it seems successful.
66145 // We don't care too much about the response, so this is fine.
66148 var url = "".concat(_krUrlRoot, "/comment.php?") + utilQsString(params);
66149 var controller = new AbortController();
66150 _cache$2.inflightPost[d.id] = controller; // Since this is expected to throw an error just continue as if it worked
66151 // (worst case scenario the request truly fails and issue will show up if iD restarts)
66154 signal: controller.signal
66155 })["finally"](function () {
66156 delete _cache$2.inflightPost[d.id];
66158 if (d.newStatus === 'ignore') {
66159 // ignore permanently (false positive)
66160 _this2.removeItem(d);
66161 } else if (d.newStatus === 'ignore_t') {
66162 // ignore temporarily (error fixed)
66163 _this2.removeItem(d);
66165 _cache$2.closed["".concat(d.schema, ":").concat(d.id)] = true;
66167 d = _this2.replaceItem(d.update({
66168 comment: d.newComment,
66169 newComment: undefined,
66170 newState: undefined
66174 if (callback) callback(null, d);
66177 // Get all cached QAItems covering the viewport
66178 getItems: function getItems(projection) {
66179 var viewport = projection.clipExtent();
66180 var min = [viewport[0][0], viewport[1][1]];
66181 var max = [viewport[1][0], viewport[0][1]];
66182 var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
66183 return _cache$2.rtree.search(bbox).map(function (d) {
66187 // Get a QAItem from cache
66188 // NOTE: Don't change method name until UI v3 is merged
66189 getError: function getError(id) {
66190 return _cache$2.data[id];
66192 // Replace a single QAItem in the cache
66193 replaceItem: function replaceItem(item) {
66194 if (!(item instanceof QAItem) || !item.id) return;
66195 _cache$2.data[item.id] = item;
66196 updateRtree$3(encodeIssueRtree$2(item), true); // true = replace
66200 // Remove a single QAItem from the cache
66201 removeItem: function removeItem(item) {
66202 if (!(item instanceof QAItem) || !item.id) return;
66203 delete _cache$2.data[item.id];
66204 updateRtree$3(encodeIssueRtree$2(item), false); // false = remove
66206 issueURL: function issueURL(item) {
66207 return "".concat(_krUrlRoot, "/report_map.php?schema=").concat(item.schema, "&error=").concat(item.id);
66209 // Get an array of issues closed during this session.
66210 // Used to populate `closed:keepright` changeset tag
66211 getClosedIDs: function getClosedIDs() {
66212 return Object.keys(_cache$2.closed).sort();
66216 var tiler$5 = utilTiler();
66217 var dispatch$6 = dispatch$8('loaded');
66218 var _tileZoom$2 = 14;
66219 var _impOsmUrls = {
66220 ow: 'https://grab.community.improve-osm.org/directionOfFlowService',
66221 mr: 'https://grab.community.improve-osm.org/missingGeoService',
66222 tr: 'https://grab.community.improve-osm.org/turnRestrictionService'
66224 var _impOsmData = {
66226 }; // This gets reassigned if reset
66230 function abortRequest$5(i) {
66231 Object.values(i).forEach(function (controller) {
66233 controller.abort();
66238 function abortUnwantedRequests$2(cache, tiles) {
66239 Object.keys(cache.inflightTile).forEach(function (k) {
66240 var wanted = tiles.find(function (tile) {
66241 return k === tile.id;
66245 abortRequest$5(cache.inflightTile[k]);
66246 delete cache.inflightTile[k];
66251 function encodeIssueRtree$1(d) {
66259 } // Replace or remove QAItem from rtree
66262 function updateRtree$2(item, replace) {
66263 _cache$1.rtree.remove(item, function (a, b) {
66264 return a.data.id === b.data.id;
66268 _cache$1.rtree.insert(item);
66272 function linkErrorObject(d) {
66274 html: "<a class=\"error_object_link\">".concat(d, "</a>")
66278 function linkEntity(d) {
66280 html: "<a class=\"error_entity_link\">".concat(d, "</a>")
66284 function pointAverage(points) {
66285 if (points.length) {
66286 var sum = points.reduce(function (acc, point) {
66287 return geoVecAdd(acc, [point.lon, point.lat]);
66289 return geoVecScale(sum, 1 / points.length);
66295 function relativeBearing(p1, p2) {
66296 var angle = Math.atan2(p2.lon - p1.lon, p2.lat - p1.lat);
66299 angle += 2 * Math.PI;
66300 } // Return degrees
66303 return angle * 180 / Math.PI;
66304 } // Assuming range [0,360)
66307 function cardinalDirection(bearing) {
66308 var dir = 45 * Math.round(bearing / 45);
66320 return _t("QA.improveOSM.directions.".concat(compass[dir]));
66321 } // Errors shouldn't obscure each other
66324 function preventCoincident$1(loc, bumpUp) {
66325 var coincident = false;
66328 // first time, move marker up. after that, move marker right.
66329 var delta = coincident ? [0.00001, 0] : bumpUp ? [0, 0.00001] : [0, 0];
66330 loc = geoVecAdd(loc, delta);
66331 var bbox = geoExtent(loc).bbox();
66332 coincident = _cache$1.rtree.search(bbox).length;
66333 } while (coincident);
66338 var serviceImproveOSM = {
66339 title: 'improveOSM',
66340 init: function init() {
66341 _mainFileFetcher.get('qa_data').then(function (d) {
66342 return _impOsmData = d.improveOSM;
66349 this.event = utilRebind(this, dispatch$6, 'on');
66351 reset: function reset() {
66353 Object.values(_cache$1.inflightTile).forEach(abortRequest$5);
66365 loadIssues: function loadIssues(projection) {
66371 zoom: '19' // Use a high zoom so that clusters aren't returned
66373 }; // determine the needed tiles to cover the view
66375 var tiles = tiler$5.zoomExtent([_tileZoom$2, _tileZoom$2]).getTiles(projection); // abort inflight requests that are no longer needed
66377 abortUnwantedRequests$2(_cache$1, tiles); // issue new requests..
66379 tiles.forEach(function (tile) {
66380 if (_cache$1.loadedTile[tile.id] || _cache$1.inflightTile[tile.id]) return;
66382 var _tile$extent$rectangl = tile.extent.rectangle(),
66383 _tile$extent$rectangl2 = _slicedToArray(_tile$extent$rectangl, 4),
66384 east = _tile$extent$rectangl2[0],
66385 north = _tile$extent$rectangl2[1],
66386 west = _tile$extent$rectangl2[2],
66387 south = _tile$extent$rectangl2[3];
66389 var params = Object.assign({}, options, {
66394 }); // 3 separate requests to store for each tile
66397 Object.keys(_impOsmUrls).forEach(function (k) {
66398 // We exclude WATER from missing geometry as it doesn't seem useful
66399 // We use most confident one-way and turn restrictions only, still have false positives
66400 var kParams = Object.assign({}, params, k === 'mr' ? {
66401 type: 'PARKING,ROAD,BOTH,PATH'
66403 confidenceLevel: 'C1'
66405 var url = "".concat(_impOsmUrls[k], "/search?") + utilQsString(kParams);
66406 var controller = new AbortController();
66407 requests[k] = controller;
66409 signal: controller.signal
66410 }).then(function (data) {
66411 delete _cache$1.inflightTile[tile.id][k];
66413 if (!Object.keys(_cache$1.inflightTile[tile.id]).length) {
66414 delete _cache$1.inflightTile[tile.id];
66415 _cache$1.loadedTile[tile.id] = true;
66416 } // Road segments at high zoom == oneways
66419 if (data.roadSegments) {
66420 data.roadSegments.forEach(function (feature) {
66421 // Position error at the approximate middle of the segment
66422 var points = feature.points,
66423 wayId = feature.wayId,
66424 fromNodeId = feature.fromNodeId,
66425 toNodeId = feature.toNodeId;
66426 var itemId = "".concat(wayId).concat(fromNodeId).concat(toNodeId);
66427 var mid = points.length / 2;
66428 var loc; // Even number of points, find midpoint of the middle two
66429 // Odd number of points, use position of very middle point
66431 if (mid % 1 === 0) {
66432 loc = pointAverage([points[mid - 1], points[mid]]);
66434 mid = points[Math.floor(mid)];
66435 loc = [mid.lon, mid.lat];
66436 } // One-ways can land on same segment in opposite direction
66439 loc = preventCoincident$1(loc, false);
66440 var d = new QAItem(loc, _this, k, itemId, {
66442 // used as a category
66444 // used to post changes
66446 fromNodeId: fromNodeId,
66451 }); // Variables used in the description
66454 percentage: feature.percentOfTrips,
66455 num_trips: feature.numberOfTrips,
66456 highway: linkErrorObject(_t('QA.keepRight.error_parts.highway')),
66457 from_node: linkEntity('n' + feature.fromNodeId),
66458 to_node: linkEntity('n' + feature.toNodeId)
66460 _cache$1.data[d.id] = d;
66462 _cache$1.rtree.insert(encodeIssueRtree$1(d));
66464 } // Tiles at high zoom == missing roads
66468 data.tiles.forEach(function (feature) {
66469 var type = feature.type,
66472 numberOfTrips = feature.numberOfTrips;
66473 var geoType = type.toLowerCase();
66474 var itemId = "".concat(geoType).concat(x).concat(y).concat(numberOfTrips); // Average of recorded points should land on the missing geometry
66475 // Missing geometry could happen to land on another error
66477 var loc = pointAverage(feature.points);
66478 loc = preventCoincident$1(loc, false);
66479 var d = new QAItem(loc, _this, "".concat(k, "-").concat(geoType), itemId, {
66487 num_trips: numberOfTrips,
66488 geometry_type: _t("QA.improveOSM.geometry_types.".concat(geoType))
66489 }; // -1 trips indicates data came from a 3rd party
66491 if (numberOfTrips === -1) {
66492 d.desc = _t('QA.improveOSM.error_types.mr.description_alt', d.replacements);
66495 _cache$1.data[d.id] = d;
66497 _cache$1.rtree.insert(encodeIssueRtree$1(d));
66499 } // Entities at high zoom == turn restrictions
66502 if (data.entities) {
66503 data.entities.forEach(function (feature) {
66504 var point = feature.point,
66506 segments = feature.segments,
66507 numberOfPasses = feature.numberOfPasses,
66508 turnType = feature.turnType;
66509 var itemId = "".concat(id.replace(/[,:+#]/g, '_')); // Turn restrictions could be missing at same junction
66510 // We also want to bump the error up so node is accessible
66512 var loc = preventCoincident$1([point.lon, point.lat], true); // Elements are presented in a strange way
66514 var ids = id.split(',');
66515 var from_way = ids[0];
66516 var via_node = ids[3];
66517 var to_way = ids[2].split(':')[1];
66518 var d = new QAItem(loc, _this, k, itemId, {
66521 objectId: via_node,
66523 }); // Travel direction along from_way clarifies the turn restriction
66525 var _segments$0$points = _slicedToArray(segments[0].points, 2),
66526 p1 = _segments$0$points[0],
66527 p2 = _segments$0$points[1];
66529 var dir_of_travel = cardinalDirection(relativeBearing(p1, p2)); // Variables used in the description
66532 num_passed: numberOfPasses,
66533 num_trips: segments[0].numberOfTrips,
66534 turn_restriction: turnType.toLowerCase(),
66535 from_way: linkEntity('w' + from_way),
66536 to_way: linkEntity('w' + to_way),
66537 travel_direction: dir_of_travel,
66538 junction: linkErrorObject(_t('QA.keepRight.error_parts.this_node'))
66540 _cache$1.data[d.id] = d;
66542 _cache$1.rtree.insert(encodeIssueRtree$1(d));
66544 dispatch$6.call('loaded');
66547 })["catch"](function () {
66548 delete _cache$1.inflightTile[tile.id][k];
66550 if (!Object.keys(_cache$1.inflightTile[tile.id]).length) {
66551 delete _cache$1.inflightTile[tile.id];
66552 _cache$1.loadedTile[tile.id] = true;
66556 _cache$1.inflightTile[tile.id] = requests;
66559 getComments: function getComments(item) {
66562 // If comments already retrieved no need to do so again
66563 if (item.comments) {
66564 return Promise.resolve(item);
66567 var key = item.issueKey;
66570 if (key === 'ow') {
66571 qParams = item.identifier;
66572 } else if (key === 'mr') {
66573 qParams.tileX = item.identifier.x;
66574 qParams.tileY = item.identifier.y;
66575 } else if (key === 'tr') {
66576 qParams.targetId = item.identifier;
66579 var url = "".concat(_impOsmUrls[key], "/retrieveComments?") + utilQsString(qParams);
66581 var cacheComments = function cacheComments(data) {
66582 // Assign directly for immediate use afterwards
66583 // comments are served newest to oldest
66584 item.comments = data.comments ? data.comments.reverse() : [];
66586 _this2.replaceItem(item);
66589 return d3_json(url).then(cacheComments).then(function () {
66593 postUpdate: function postUpdate(d, callback) {
66594 if (!serviceOsm.authenticated()) {
66595 // Username required in payload
66597 message: 'Not Authenticated',
66602 if (_cache$1.inflightPost[d.id]) {
66604 message: 'Error update already inflight',
66607 } // Payload can only be sent once username is established
66610 serviceOsm.userDetails(sendPayload.bind(this));
66612 function sendPayload(err, user) {
66616 return callback(err, d);
66619 var key = d.issueKey;
66620 var url = "".concat(_impOsmUrls[key], "/comment");
66622 username: user.display_name,
66623 targetIds: [d.identifier]
66627 payload.status = d.newStatus;
66628 payload.text = 'status changed';
66629 } // Comment take place of default text
66632 if (d.newComment) {
66633 payload.text = d.newComment;
66636 var controller = new AbortController();
66637 _cache$1.inflightPost[d.id] = controller;
66640 signal: controller.signal,
66641 body: JSON.stringify(payload)
66643 d3_json(url, options).then(function () {
66644 delete _cache$1.inflightPost[d.id]; // Just a comment, update error in cache
66646 if (!d.newStatus) {
66647 var now = new Date();
66648 var comments = d.comments ? d.comments : [];
66650 username: payload.username,
66651 text: payload.text,
66652 timestamp: now.getTime() / 1000
66655 _this3.replaceItem(d.update({
66656 comments: comments,
66657 newComment: undefined
66660 _this3.removeItem(d);
66662 if (d.newStatus === 'SOLVED') {
66663 // Keep track of the number of issues closed per type to tag the changeset
66664 if (!(d.issueKey in _cache$1.closed)) {
66665 _cache$1.closed[d.issueKey] = 0;
66668 _cache$1.closed[d.issueKey] += 1;
66672 if (callback) callback(null, d);
66673 })["catch"](function (err) {
66674 delete _cache$1.inflightPost[d.id];
66675 if (callback) callback(err.message);
66679 // Get all cached QAItems covering the viewport
66680 getItems: function getItems(projection) {
66681 var viewport = projection.clipExtent();
66682 var min = [viewport[0][0], viewport[1][1]];
66683 var max = [viewport[1][0], viewport[0][1]];
66684 var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
66685 return _cache$1.rtree.search(bbox).map(function (d) {
66689 // Get a QAItem from cache
66690 // NOTE: Don't change method name until UI v3 is merged
66691 getError: function getError(id) {
66692 return _cache$1.data[id];
66694 // get the name of the icon to display for this item
66695 getIcon: function getIcon(itemType) {
66696 return _impOsmData.icons[itemType];
66698 // Replace a single QAItem in the cache
66699 replaceItem: function replaceItem(issue) {
66700 if (!(issue instanceof QAItem) || !issue.id) return;
66701 _cache$1.data[issue.id] = issue;
66702 updateRtree$2(encodeIssueRtree$1(issue), true); // true = replace
66706 // Remove a single QAItem from the cache
66707 removeItem: function removeItem(issue) {
66708 if (!(issue instanceof QAItem) || !issue.id) return;
66709 delete _cache$1.data[issue.id];
66710 updateRtree$2(encodeIssueRtree$1(issue), false); // false = remove
66712 // Used to populate `closed:improveosm:*` changeset tags
66713 getClosedCounts: function getClosedCounts() {
66714 return _cache$1.closed;
66718 var defaults$5 = {exports: {}};
66720 function getDefaults$1() {
66728 langPrefix: 'language-',
66736 smartypants: false,
66743 function changeDefaults$1(newDefaults) {
66744 defaults$5.exports.defaults = newDefaults;
66747 defaults$5.exports = {
66748 defaults: getDefaults$1(),
66749 getDefaults: getDefaults$1,
66750 changeDefaults: changeDefaults$1
66753 var escapeTest = /[&<>"']/;
66754 var escapeReplace = /[&<>"']/g;
66755 var escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/;
66756 var escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g;
66757 var escapeReplacements = {
66765 var getEscapeReplacement = function getEscapeReplacement(ch) {
66766 return escapeReplacements[ch];
66769 function escape$3(html, encode) {
66771 if (escapeTest.test(html)) {
66772 return html.replace(escapeReplace, getEscapeReplacement);
66775 if (escapeTestNoEncode.test(html)) {
66776 return html.replace(escapeReplaceNoEncode, getEscapeReplacement);
66783 var unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;
66785 function unescape$2(html) {
66786 // explicitly match decimal, hex, and named HTML entities
66787 return html.replace(unescapeTest, function (_, n) {
66788 n = n.toLowerCase();
66789 if (n === 'colon') return ':';
66791 if (n.charAt(0) === '#') {
66792 return n.charAt(1) === 'x' ? String.fromCharCode(parseInt(n.substring(2), 16)) : String.fromCharCode(+n.substring(1));
66799 var caret = /(^|[^\[])\^/g;
66801 function edit$1(regex, opt) {
66802 regex = regex.source || regex;
66805 replace: function replace(name, val) {
66806 val = val.source || val;
66807 val = val.replace(caret, '$1');
66808 regex = regex.replace(name, val);
66811 getRegex: function getRegex() {
66812 return new RegExp(regex, opt);
66818 var nonWordAndColonTest = /[^\w:]/g;
66819 var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
66821 function cleanUrl$1(sanitize, base, href) {
66826 prot = decodeURIComponent(unescape$2(href)).replace(nonWordAndColonTest, '').toLowerCase();
66831 if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
66836 if (base && !originIndependentUrl.test(href)) {
66837 href = resolveUrl$2(base, href);
66841 href = encodeURI(href).replace(/%25/g, '%');
66850 var justDomain = /^[^:]+:\/*[^/]*$/;
66851 var protocol = /^([^:]+:)[\s\S]*$/;
66852 var domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
66854 function resolveUrl$2(base, href) {
66855 if (!baseUrls[' ' + base]) {
66856 // we can ignore everything in base after the last slash of its path component,
66857 // but we might need to add _that_
66858 // https://tools.ietf.org/html/rfc3986#section-3
66859 if (justDomain.test(base)) {
66860 baseUrls[' ' + base] = base + '/';
66862 baseUrls[' ' + base] = rtrim$1(base, '/', true);
66866 base = baseUrls[' ' + base];
66867 var relativeBase = base.indexOf(':') === -1;
66869 if (href.substring(0, 2) === '//') {
66870 if (relativeBase) {
66874 return base.replace(protocol, '$1') + href;
66875 } else if (href.charAt(0) === '/') {
66876 if (relativeBase) {
66880 return base.replace(domain, '$1') + href;
66882 return base + href;
66887 exec: function noopTest() {}
66890 function merge$2(obj) {
66895 for (; i < arguments.length; i++) {
66896 target = arguments[i];
66898 for (key in target) {
66899 if (Object.prototype.hasOwnProperty.call(target, key)) {
66900 obj[key] = target[key];
66908 function splitCells$1(tableRow, count) {
66909 // ensure that every cell-delimiting pipe has a space
66910 // before it to distinguish it from an escaped pipe
66911 var row = tableRow.replace(/\|/g, function (match, offset, str) {
66912 var escaped = false,
66915 while (--curr >= 0 && str[curr] === '\\') {
66916 escaped = !escaped;
66920 // odd number of slashes means | is escaped
66921 // so we leave it alone
66924 // add space before unescaped |
66928 cells = row.split(/ \|/);
66931 if (cells.length > count) {
66932 cells.splice(count);
66934 while (cells.length < count) {
66939 for (; i < cells.length; i++) {
66940 // leading or trailing whitespace is ignored per the gfm spec
66941 cells[i] = cells[i].trim().replace(/\\\|/g, '|');
66945 } // Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
66946 // /c*$/ is vulnerable to REDOS.
66947 // invert: Remove suffix of non-c chars instead. Default falsey.
66950 function rtrim$1(str, c, invert) {
66951 var l = str.length;
66955 } // Length of suffix matching the invert condition.
66958 var suffLen = 0; // Step left until we fail to match the invert condition.
66960 while (suffLen < l) {
66961 var currChar = str.charAt(l - suffLen - 1);
66963 if (currChar === c && !invert) {
66965 } else if (currChar !== c && invert) {
66972 return str.substr(0, l - suffLen);
66975 function findClosingBracket$1(str, b) {
66976 if (str.indexOf(b[1]) === -1) {
66980 var l = str.length;
66984 for (; i < l; i++) {
66985 if (str[i] === '\\') {
66987 } else if (str[i] === b[0]) {
66989 } else if (str[i] === b[1]) {
67001 function checkSanitizeDeprecation$1(opt) {
67002 if (opt && opt.sanitize && !opt.silent) {
67003 console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options');
67005 } // copied from https://stackoverflow.com/a/5450113/806777
67008 function repeatString$1(pattern, count) {
67015 while (count > 1) {
67021 pattern += pattern;
67024 return result + pattern;
67029 unescape: unescape$2,
67031 cleanUrl: cleanUrl$1,
67032 resolveUrl: resolveUrl$2,
67033 noopTest: noopTest$1,
67035 splitCells: splitCells$1,
67037 findClosingBracket: findClosingBracket$1,
67038 checkSanitizeDeprecation: checkSanitizeDeprecation$1,
67039 repeatString: repeatString$1
67042 var defaults$4 = defaults$5.exports.defaults;
67043 var rtrim = helpers.rtrim,
67044 splitCells = helpers.splitCells,
67045 _escape = helpers.escape,
67046 findClosingBracket = helpers.findClosingBracket;
67048 function outputLink(cap, link, raw) {
67049 var href = link.href;
67050 var title = link.title ? _escape(link.title) : null;
67051 var text = cap[1].replace(/\\([\[\]])/g, '$1');
67053 if (cap[0].charAt(0) !== '!') {
67067 text: _escape(text)
67072 function indentCodeCompensation(raw, text) {
67073 var matchIndentToCode = raw.match(/^(\s+)(?:```)/);
67075 if (matchIndentToCode === null) {
67079 var indentToCode = matchIndentToCode[1];
67080 return text.split('\n').map(function (node) {
67081 var matchIndentInNode = node.match(/^\s+/);
67083 if (matchIndentInNode === null) {
67087 var _matchIndentInNode = _slicedToArray(matchIndentInNode, 1),
67088 indentInNode = _matchIndentInNode[0];
67090 if (indentInNode.length >= indentToCode.length) {
67091 return node.slice(indentToCode.length);
67102 var Tokenizer_1 = /*#__PURE__*/function () {
67103 function Tokenizer(options) {
67104 _classCallCheck$1(this, Tokenizer);
67106 this.options = options || defaults$4;
67109 _createClass$1(Tokenizer, [{
67111 value: function space(src) {
67112 var cap = this.rules.block.newline.exec(src);
67115 if (cap[0].length > 1) {
67129 value: function code(src) {
67130 var cap = this.rules.block.code.exec(src);
67133 var text = cap[0].replace(/^ {1,4}/gm, '');
67137 codeBlockStyle: 'indented',
67138 text: !this.options.pedantic ? rtrim(text, '\n') : text
67144 value: function fences(src) {
67145 var cap = this.rules.block.fences.exec(src);
67149 var text = indentCodeCompensation(raw, cap[3] || '');
67153 lang: cap[2] ? cap[2].trim() : cap[2],
67160 value: function heading(src) {
67161 var cap = this.rules.block.heading.exec(src);
67164 var text = cap[2].trim(); // remove trailing #s
67166 if (/#$/.test(text)) {
67167 var trimmed = rtrim(text, '#');
67169 if (this.options.pedantic) {
67170 text = trimmed.trim();
67171 } else if (!trimmed || / $/.test(trimmed)) {
67172 // CommonMark requires space before trailing #s
67173 text = trimmed.trim();
67180 depth: cap[1].length,
67187 value: function nptable(src) {
67188 var cap = this.rules.block.nptable.exec(src);
67193 header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
67194 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
67195 cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [],
67199 if (item.header.length === item.align.length) {
67200 var l = item.align.length;
67203 for (i = 0; i < l; i++) {
67204 if (/^ *-+: *$/.test(item.align[i])) {
67205 item.align[i] = 'right';
67206 } else if (/^ *:-+: *$/.test(item.align[i])) {
67207 item.align[i] = 'center';
67208 } else if (/^ *:-+ *$/.test(item.align[i])) {
67209 item.align[i] = 'left';
67211 item.align[i] = null;
67215 l = item.cells.length;
67217 for (i = 0; i < l; i++) {
67218 item.cells[i] = splitCells(item.cells[i], item.header.length);
67227 value: function hr(src) {
67228 var cap = this.rules.block.hr.exec(src);
67239 value: function blockquote(src) {
67240 var cap = this.rules.block.blockquote.exec(src);
67243 var text = cap[0].replace(/^ *> ?/gm, '');
67245 type: 'blockquote',
67253 value: function list(src) {
67254 var cap = this.rules.block.list.exec(src);
67259 var isordered = bull.length > 1;
67263 ordered: isordered,
67264 start: isordered ? +bull.slice(0, -1) : '',
67267 }; // Get each top-level item.
67269 var itemMatch = cap[0].match(this.rules.block.item);
67280 var l = itemMatch.length;
67281 bcurr = this.rules.block.listItemStart.exec(itemMatch[0]);
67283 for (var i = 0; i < l; i++) {
67284 item = itemMatch[i];
67287 if (!this.options.pedantic) {
67288 // Determine if current item contains the end of the list
67289 endMatch = item.match(new RegExp('\\n\\s*\\n {0,' + (bcurr[0].length - 1) + '}\\S'));
67292 addBack = item.length - endMatch.index + itemMatch.slice(i + 1).join('\n').length;
67293 list.raw = list.raw.substring(0, list.raw.length - addBack);
67294 item = item.substring(0, endMatch.index);
67298 } // Determine whether the next list item belongs here.
67299 // Backpedal if it does not belong in this list.
67303 bnext = this.rules.block.listItemStart.exec(itemMatch[i + 1]);
67305 if (!this.options.pedantic ? bnext[1].length >= bcurr[0].length || bnext[1].length > 3 : bnext[1].length > bcurr[1].length) {
67306 // nested list or continuation
67307 itemMatch.splice(i, 2, itemMatch[i] + (!this.options.pedantic && bnext[1].length < bcurr[0].length && !itemMatch[i].match(/\n$/) ? '' : '\n') + itemMatch[i + 1]);
67311 } else if ( // different bullet style
67312 !this.options.pedantic || this.options.smartLists ? bnext[2][bnext[2].length - 1] !== bull[bull.length - 1] : isordered === (bnext[2].length === 1)) {
67313 addBack = itemMatch.slice(i + 1).join('\n').length;
67314 list.raw = list.raw.substring(0, list.raw.length - addBack);
67319 } // Remove the list item's bullet
67320 // so it is seen as the next token.
67323 space = item.length;
67324 item = item.replace(/^ *([*+-]|\d+[.)]) ?/, ''); // Outdent whatever the
67325 // list item contains. Hacky.
67327 if (~item.indexOf('\n ')) {
67328 space -= item.length;
67329 item = !this.options.pedantic ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') : item.replace(/^ {1,4}/gm, '');
67330 } // trim item newlines at end
67333 item = rtrim(item, '\n');
67337 } // Determine whether item is loose or not.
67338 // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
67339 // for discount behavior.
67342 loose = next || /\n\n(?!\s*$)/.test(raw);
67345 next = raw.slice(-2) === '\n\n';
67346 if (!loose) loose = next;
67351 } // Check for task list items
67354 if (this.options.gfm) {
67355 istask = /^\[[ xX]\] /.test(item);
67356 ischecked = undefined;
67359 ischecked = item[1] !== ' ';
67360 item = item.replace(/^\[[ xX]\] +/, '');
67368 checked: ischecked,
67379 value: function html(src) {
67380 var cap = this.rules.block.html.exec(src);
67384 type: this.options.sanitize ? 'paragraph' : 'html',
67386 pre: !this.options.sanitizer && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
67387 text: this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : _escape(cap[0]) : cap[0]
67393 value: function def(src) {
67394 var cap = this.rules.block.def.exec(src);
67397 if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1);
67398 var tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
67410 value: function table(src) {
67411 var cap = this.rules.block.table.exec(src);
67416 header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
67417 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
67418 cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []
67421 if (item.header.length === item.align.length) {
67423 var l = item.align.length;
67426 for (i = 0; i < l; i++) {
67427 if (/^ *-+: *$/.test(item.align[i])) {
67428 item.align[i] = 'right';
67429 } else if (/^ *:-+: *$/.test(item.align[i])) {
67430 item.align[i] = 'center';
67431 } else if (/^ *:-+ *$/.test(item.align[i])) {
67432 item.align[i] = 'left';
67434 item.align[i] = null;
67438 l = item.cells.length;
67440 for (i = 0; i < l; i++) {
67441 item.cells[i] = splitCells(item.cells[i].replace(/^ *\| *| *\| *$/g, ''), item.header.length);
67450 value: function lheading(src) {
67451 var cap = this.rules.block.lheading.exec(src);
67457 depth: cap[2].charAt(0) === '=' ? 1 : 2,
67464 value: function paragraph(src) {
67465 var cap = this.rules.block.paragraph.exec(src);
67471 text: cap[1].charAt(cap[1].length - 1) === '\n' ? cap[1].slice(0, -1) : cap[1]
67477 value: function text(src) {
67478 var cap = this.rules.block.text.exec(src);
67490 value: function escape(src) {
67491 var cap = this.rules.inline.escape.exec(src);
67497 text: _escape(cap[1])
67503 value: function tag(src, inLink, inRawBlock) {
67504 var cap = this.rules.inline.tag.exec(src);
67507 if (!inLink && /^<a /i.test(cap[0])) {
67509 } else if (inLink && /^<\/a>/i.test(cap[0])) {
67513 if (!inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
67515 } else if (inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
67516 inRawBlock = false;
67520 type: this.options.sanitize ? 'text' : 'html',
67523 inRawBlock: inRawBlock,
67524 text: this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : _escape(cap[0]) : cap[0]
67530 value: function link(src) {
67531 var cap = this.rules.inline.link.exec(src);
67534 var trimmedUrl = cap[2].trim();
67536 if (!this.options.pedantic && /^</.test(trimmedUrl)) {
67537 // commonmark requires matching angle brackets
67538 if (!/>$/.test(trimmedUrl)) {
67540 } // ending angle bracket cannot be escaped
67543 var rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\');
67545 if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
67549 // find closing parenthesis
67550 var lastParenIndex = findClosingBracket(cap[2], '()');
67552 if (lastParenIndex > -1) {
67553 var start = cap[0].indexOf('!') === 0 ? 5 : 4;
67554 var linkLen = start + cap[1].length + lastParenIndex;
67555 cap[2] = cap[2].substring(0, lastParenIndex);
67556 cap[0] = cap[0].substring(0, linkLen).trim();
67564 if (this.options.pedantic) {
67565 // split pedantic href and title
67566 var link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
67573 title = cap[3] ? cap[3].slice(1, -1) : '';
67576 href = href.trim();
67578 if (/^</.test(href)) {
67579 if (this.options.pedantic && !/>$/.test(trimmedUrl)) {
67580 // pedantic allows starting angle bracket without ending angle bracket
67581 href = href.slice(1);
67583 href = href.slice(1, -1);
67587 return outputLink(cap, {
67588 href: href ? href.replace(this.rules.inline._escapes, '$1') : href,
67589 title: title ? title.replace(this.rules.inline._escapes, '$1') : title
67595 value: function reflink(src, links) {
67598 if ((cap = this.rules.inline.reflink.exec(src)) || (cap = this.rules.inline.nolink.exec(src))) {
67599 var link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
67600 link = links[link.toLowerCase()];
67602 if (!link || !link.href) {
67603 var text = cap[0].charAt(0);
67611 return outputLink(cap, link, cap[0]);
67616 value: function emStrong(src, maskedSrc) {
67617 var prevChar = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
67618 var match = this.rules.inline.emStrong.lDelim.exec(src);
67619 if (!match) return; // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well
67621 if (match[3] && prevChar.match(/(?:[0-9A-Za-z\xAA\xB2\xB3\xB5\xB9\xBA\xBC-\xBE\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09F4-\u09F9\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71-\u0B77\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BF2\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5D\u0C60\u0C61\u0C66-\u0C6F\u0C78-\u0C7E\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D58-\u0D61\u0D66-\u0D78\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F33\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1369-\u137C\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2070\u2071\u2074-\u2079\u207F-\u2089\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2150-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2CFD\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u3192-\u3195\u31A0-\u31BF\u31F0-\u31FF\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA830-\uA835\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDE80-\uDE9C\uDEA0-\uDED0\uDEE1-\uDEFB\uDF00-\uDF23\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC58-\uDC76\uDC79-\uDC9E\uDCA7-\uDCAF\uDCE0-\uDCF2\uDCF4\uDCF5\uDCFB-\uDD1B\uDD20-\uDD39\uDD80-\uDDB7\uDDBC-\uDDCF\uDDD2-\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE40-\uDE48\uDE60-\uDE7E\uDE80-\uDE9F\uDEC0-\uDEC7\uDEC9-\uDEE4\uDEEB-\uDEEF\uDF00-\uDF35\uDF40-\uDF55\uDF58-\uDF72\uDF78-\uDF91\uDFA9-\uDFAF]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDCFA-\uDD23\uDD30-\uDD39\uDE60-\uDE7E\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF27\uDF30-\uDF45\uDF51-\uDF54\uDF70-\uDF81\uDFB0-\uDFCB\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC52-\uDC6F\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDDE1-\uDDF4\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF3B\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCF2\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC6C\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2\uDFB0\uDFC0-\uDFD4]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDE70-\uDEBE\uDEC0-\uDEC9\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF5B-\uDF61\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE96\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD834[\uDEE0-\uDEF3\uDF60-\uDF78]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD837[\uDF00-\uDF1E]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD40-\uDD49\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB\uDEF0-\uDEF9]|\uD839[\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDCC7-\uDCCF\uDD00-\uDD43\uDD4B\uDD50-\uDD59]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDD01-\uDD2D\uDD2F-\uDD3D\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83C[\uDD00-\uDD0C]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])/)) return;
67622 var nextChar = match[1] || match[2] || '';
67624 if (!nextChar || nextChar && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))) {
67625 var lLength = match[0].length - 1;
67628 delimTotal = lLength,
67630 var endReg = match[0][0] === '*' ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
67631 endReg.lastIndex = 0; // Clip maskedSrc to same section of string as src (move to lexer?)
67633 maskedSrc = maskedSrc.slice(-1 * src.length + lLength);
67635 while ((match = endReg.exec(maskedSrc)) != null) {
67636 rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
67637 if (!rDelim) continue; // skip single * in __abc*abc__
67639 rLength = rDelim.length;
67641 if (match[3] || match[4]) {
67642 // found another Left Delim
67643 delimTotal += rLength;
67645 } else if (match[5] || match[6]) {
67646 // either Left or Right Delim
67647 if (lLength % 3 && !((lLength + rLength) % 3)) {
67648 midDelimTotal += rLength;
67649 continue; // CommonMark Emphasis Rules 9-10
67653 delimTotal -= rLength;
67654 if (delimTotal > 0) continue; // Haven't found enough closing delimiters
67655 // Remove extra characters. *a*** -> *a*
67657 rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal); // Create `em` if smallest delimiter has odd char count. *a***
67659 if (Math.min(lLength, rLength) % 2) {
67662 raw: src.slice(0, lLength + match.index + rLength + 1),
67663 text: src.slice(1, lLength + match.index + rLength)
67665 } // Create 'strong' if smallest delimiter has even char count. **a***
67670 raw: src.slice(0, lLength + match.index + rLength + 1),
67671 text: src.slice(2, lLength + match.index + rLength - 1)
67678 value: function codespan(src) {
67679 var cap = this.rules.inline.code.exec(src);
67682 var text = cap[2].replace(/\n/g, ' ');
67683 var hasNonSpaceChars = /[^ ]/.test(text);
67684 var hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text);
67686 if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
67687 text = text.substring(1, text.length - 1);
67690 text = _escape(text, true);
67700 value: function br(src) {
67701 var cap = this.rules.inline.br.exec(src);
67712 value: function del(src) {
67713 var cap = this.rules.inline.del.exec(src);
67725 value: function autolink(src, mangle) {
67726 var cap = this.rules.inline.autolink.exec(src);
67731 if (cap[2] === '@') {
67732 text = _escape(this.options.mangle ? mangle(cap[1]) : cap[1]);
67733 href = 'mailto:' + text;
67735 text = _escape(cap[1]);
67754 value: function url(src, mangle) {
67757 if (cap = this.rules.inline.url.exec(src)) {
67760 if (cap[2] === '@') {
67761 text = _escape(this.options.mangle ? mangle(cap[0]) : cap[0]);
67762 href = 'mailto:' + text;
67764 // do extended autolink path validation
67768 prevCapZero = cap[0];
67769 cap[0] = this.rules.inline._backpedal.exec(cap[0])[0];
67770 } while (prevCapZero !== cap[0]);
67772 text = _escape(cap[0]);
67774 if (cap[1] === 'www.') {
67775 href = 'http://' + text;
67796 value: function inlineText(src, inRawBlock, smartypants) {
67797 var cap = this.rules.inline.text.exec(src);
67803 text = this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : _escape(cap[0]) : cap[0];
67805 text = _escape(this.options.smartypants ? smartypants(cap[0]) : cap[0]);
67820 var noopTest = helpers.noopTest,
67821 edit = helpers.edit,
67822 merge$1 = helpers.merge;
67824 * Block-Level Grammar
67828 newline: /^(?: *(?:\n|$))+/,
67829 code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
67830 fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,
67831 hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,
67832 heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
67833 blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
67834 list: /^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?! {0,3}bull )\n*|\s*$)/,
67835 html: '^ {0,3}(?:' // optional indentation
67836 + '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
67837 + '|comment[^\\n]*(\\n+|$)' // (2)
67838 + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3)
67839 + '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4)
67840 + '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5)
67841 + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (6)
67842 + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) open tag
67843 + '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) closing tag
67845 def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,
67848 lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
67849 // regex template, placeholders will be replaced according to different paragraph
67850 // interruption rules of commonmark and the original markdown spec:
67851 _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/,
67854 block$1._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/;
67855 block$1._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
67856 block$1.def = edit(block$1.def).replace('label', block$1._label).replace('title', block$1._title).getRegex();
67857 block$1.bullet = /(?:[*+-]|\d{1,9}[.)])/;
67858 block$1.item = /^( *)(bull) ?[^\n]*(?:\n(?! *bull ?)[^\n]*)*/;
67859 block$1.item = edit(block$1.item, 'gm').replace(/bull/g, block$1.bullet).getRegex();
67860 block$1.listItemStart = edit(/^( *)(bull) */).replace('bull', block$1.bullet).getRegex();
67861 block$1.list = edit(block$1.list).replace(/bull/g, block$1.bullet).replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))').replace('def', '\\n+(?=' + block$1.def.source + ')').getRegex();
67862 block$1._tag = 'address|article|aside|base|basefont|blockquote|body|caption' + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr' + '|track|ul';
67863 block$1._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/;
67864 block$1.html = edit(block$1.html, 'i').replace('comment', block$1._comment).replace('tag', block$1._tag).replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
67865 block$1.paragraph = edit(block$1._paragraph).replace('hr', block$1.hr).replace('heading', ' {0,3}#{1,6} ').replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
67866 .replace('blockquote', ' {0,3}>').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
67867 .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)').replace('tag', block$1._tag) // pars can be interrupted by type (6) html blocks
67869 block$1.blockquote = edit(block$1.blockquote).replace('paragraph', block$1.paragraph).getRegex();
67871 * Normal Block Grammar
67874 block$1.normal = merge$1({}, block$1);
67876 * GFM Block Grammar
67879 block$1.gfm = merge$1({}, block$1.normal, {
67880 nptable: '^ *([^|\\n ].*\\|.*)\\n' // Header
67881 + ' {0,3}([-:]+ *\\|[-| :]*)' // Align
67882 + '(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)',
67884 table: '^ *\\|(.+)\\n' // Header
67885 + ' {0,3}\\|?( *[-:]+[-| :]*)' // Align
67886 + '(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells
67889 block$1.gfm.nptable = edit(block$1.gfm.nptable).replace('hr', block$1.hr).replace('heading', ' {0,3}#{1,6} ').replace('blockquote', ' {0,3}>').replace('code', ' {4}[^\\n]').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
67890 .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)').replace('tag', block$1._tag) // tables can be interrupted by type (6) html blocks
67892 block$1.gfm.table = edit(block$1.gfm.table).replace('hr', block$1.hr).replace('heading', ' {0,3}#{1,6} ').replace('blockquote', ' {0,3}>').replace('code', ' {4}[^\\n]').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
67893 .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)').replace('tag', block$1._tag) // tables can be interrupted by type (6) html blocks
67896 * Pedantic grammar (original John Gruber's loose markdown specification)
67899 block$1.pedantic = merge$1({}, block$1.normal, {
67900 html: edit('^ *(?:comment *(?:\\n|\\s*$)' + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
67901 + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))').replace('comment', block$1._comment).replace(/tag/g, '(?!(?:' + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub' + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)' + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b').getRegex(),
67902 def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
67903 heading: /^(#{1,6})(.*)(?:\n+|$)/,
67905 // fences not supported
67906 paragraph: edit(block$1.normal._paragraph).replace('hr', block$1.hr).replace('heading', ' *#{1,6} *[^\n]').replace('lheading', block$1.lheading).replace('blockquote', ' {0,3}>').replace('|fences', '').replace('|list', '').replace('|html', '').getRegex()
67909 * Inline-Level Grammar
67913 escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
67914 autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
67916 tag: '^comment' + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
67917 + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
67918 + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
67919 + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
67920 + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>',
67922 link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
67923 reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
67924 nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
67925 reflinkSearch: 'reflink|nolink(?!\\()',
67927 lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,
67928 // (1) and (2) can only be a Right Delimiter. (3) and (4) can only be Left. (5) and (6) can be either Left or Right.
67929 // () Skip other delimiter (1) #*** (2) a***#, a*** (3) #***a, ***a (4) ***# (5) #***# (6) a***a
67930 rDelimAst: /\_\_[^_*]*?\*[^_*]*?\_\_|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/,
67931 rDelimUnd: /\*\*[^_*]*?\_[^_*]*?\*\*|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/ // ^- Not allowed for _
67934 code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
67935 br: /^( {2,}|\\)\n(?!\s*$)/,
67937 text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,
67938 punctuation: /^([\spunctuation])/
67939 }; // list of punctuation marks from CommonMark spec
67940 // without * and _ to handle the different emphasis markers * and _
67942 inline$1._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~';
67943 inline$1.punctuation = edit(inline$1.punctuation).replace(/punctuation/g, inline$1._punctuation).getRegex(); // sequences em should skip over [title](link), `code`, <html>
67945 inline$1.blockSkip = /\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g;
67946 inline$1.escapedEmSt = /\\\*|\\_/g;
67947 inline$1._comment = edit(block$1._comment).replace('(?:-->|$)', '-->').getRegex();
67948 inline$1.emStrong.lDelim = edit(inline$1.emStrong.lDelim).replace(/punct/g, inline$1._punctuation).getRegex();
67949 inline$1.emStrong.rDelimAst = edit(inline$1.emStrong.rDelimAst, 'g').replace(/punct/g, inline$1._punctuation).getRegex();
67950 inline$1.emStrong.rDelimUnd = edit(inline$1.emStrong.rDelimUnd, 'g').replace(/punct/g, inline$1._punctuation).getRegex();
67951 inline$1._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
67952 inline$1._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
67953 inline$1._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
67954 inline$1.autolink = edit(inline$1.autolink).replace('scheme', inline$1._scheme).replace('email', inline$1._email).getRegex();
67955 inline$1._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;
67956 inline$1.tag = edit(inline$1.tag).replace('comment', inline$1._comment).replace('attribute', inline$1._attribute).getRegex();
67957 inline$1._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
67958 inline$1._href = /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/;
67959 inline$1._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
67960 inline$1.link = edit(inline$1.link).replace('label', inline$1._label).replace('href', inline$1._href).replace('title', inline$1._title).getRegex();
67961 inline$1.reflink = edit(inline$1.reflink).replace('label', inline$1._label).getRegex();
67962 inline$1.reflinkSearch = edit(inline$1.reflinkSearch, 'g').replace('reflink', inline$1.reflink).replace('nolink', inline$1.nolink).getRegex();
67964 * Normal Inline Grammar
67967 inline$1.normal = merge$1({}, inline$1);
67969 * Pedantic Inline Grammar
67972 inline$1.pedantic = merge$1({}, inline$1.normal, {
67975 middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
67976 endAst: /\*\*(?!\*)/g,
67981 middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
67982 endAst: /\*(?!\*)/g,
67985 link: edit(/^!?\[(label)\]\((.*?)\)/).replace('label', inline$1._label).getRegex(),
67986 reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace('label', inline$1._label).getRegex()
67989 * GFM Inline Grammar
67992 inline$1.gfm = merge$1({}, inline$1.normal, {
67993 escape: edit(inline$1.escape).replace('])', '~|])').getRegex(),
67994 _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,
67995 url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
67996 _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
67997 del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
67998 text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
68000 inline$1.gfm.url = edit(inline$1.gfm.url, 'i').replace('email', inline$1.gfm._extended_email).getRegex();
68002 * GFM + Line Breaks Inline Grammar
68005 inline$1.breaks = merge$1({}, inline$1.gfm, {
68006 br: edit(inline$1.br).replace('{2,}', '*').getRegex(),
68007 text: edit(inline$1.gfm.text).replace('\\b_', '\\b_| {2,}\\n').replace(/\{2,\}/g, '*').getRegex()
68014 var Tokenizer$1 = Tokenizer_1;
68015 var defaults$3 = defaults$5.exports.defaults;
68016 var block = rules.block,
68017 inline = rules.inline;
68018 var repeatString = helpers.repeatString;
68020 * smartypants text replacement
68023 function smartypants(text) {
68024 return text // em-dashes
68025 .replace(/---/g, "\u2014") // en-dashes
68026 .replace(/--/g, "\u2013") // opening singles
68027 .replace(/(^|[-\u2014/(\[{"\s])'/g, "$1\u2018") // closing singles & apostrophes
68028 .replace(/'/g, "\u2019") // opening doubles
68029 .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, "$1\u201C") // closing doubles
68030 .replace(/"/g, "\u201D") // ellipses
68031 .replace(/\.{3}/g, "\u2026");
68034 * mangle email addresses
68038 function mangle(text) {
68042 var l = text.length;
68044 for (i = 0; i < l; i++) {
68045 ch = text.charCodeAt(i);
68047 if (Math.random() > 0.5) {
68048 ch = 'x' + ch.toString(16);
68051 out += '&#' + ch + ';';
68061 var Lexer_1 = /*#__PURE__*/function () {
68062 function Lexer(options) {
68063 _classCallCheck$1(this, Lexer);
68066 this.tokens.links = Object.create(null);
68067 this.options = options || defaults$3;
68068 this.options.tokenizer = this.options.tokenizer || new Tokenizer$1();
68069 this.tokenizer = this.options.tokenizer;
68070 this.tokenizer.options = this.options;
68072 block: block.normal,
68073 inline: inline.normal
68076 if (this.options.pedantic) {
68077 rules.block = block.pedantic;
68078 rules.inline = inline.pedantic;
68079 } else if (this.options.gfm) {
68080 rules.block = block.gfm;
68082 if (this.options.breaks) {
68083 rules.inline = inline.breaks;
68085 rules.inline = inline.gfm;
68089 this.tokenizer.rules = rules;
68096 _createClass$1(Lexer, [{
68102 function lex(src) {
68103 src = src.replace(/\r\n|\r/g, '\n').replace(/\t/g, ' ');
68104 this.blockTokens(src, this.tokens, true);
68105 this.inline(this.tokens);
68106 return this.tokens;
68113 key: "blockTokens",
68114 value: function blockTokens(src) {
68115 var tokens = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
68116 var top = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
68118 if (this.options.pedantic) {
68119 src = src.replace(/^ +$/gm, '');
68122 var token, i, l, lastToken;
68126 if (token = this.tokenizer.space(src)) {
68127 src = src.substring(token.raw.length);
68130 tokens.push(token);
68137 if (token = this.tokenizer.code(src)) {
68138 src = src.substring(token.raw.length);
68139 lastToken = tokens[tokens.length - 1]; // An indented code block cannot interrupt a paragraph.
68141 if (lastToken && lastToken.type === 'paragraph') {
68142 lastToken.raw += '\n' + token.raw;
68143 lastToken.text += '\n' + token.text;
68145 tokens.push(token);
68152 if (token = this.tokenizer.fences(src)) {
68153 src = src.substring(token.raw.length);
68154 tokens.push(token);
68159 if (token = this.tokenizer.heading(src)) {
68160 src = src.substring(token.raw.length);
68161 tokens.push(token);
68163 } // table no leading pipe (gfm)
68166 if (token = this.tokenizer.nptable(src)) {
68167 src = src.substring(token.raw.length);
68168 tokens.push(token);
68173 if (token = this.tokenizer.hr(src)) {
68174 src = src.substring(token.raw.length);
68175 tokens.push(token);
68180 if (token = this.tokenizer.blockquote(src)) {
68181 src = src.substring(token.raw.length);
68182 token.tokens = this.blockTokens(token.text, [], top);
68183 tokens.push(token);
68188 if (token = this.tokenizer.list(src)) {
68189 src = src.substring(token.raw.length);
68190 l = token.items.length;
68192 for (i = 0; i < l; i++) {
68193 token.items[i].tokens = this.blockTokens(token.items[i].text, [], false);
68196 tokens.push(token);
68201 if (token = this.tokenizer.html(src)) {
68202 src = src.substring(token.raw.length);
68203 tokens.push(token);
68208 if (top && (token = this.tokenizer.def(src))) {
68209 src = src.substring(token.raw.length);
68211 if (!this.tokens.links[token.tag]) {
68212 this.tokens.links[token.tag] = {
68222 if (token = this.tokenizer.table(src)) {
68223 src = src.substring(token.raw.length);
68224 tokens.push(token);
68229 if (token = this.tokenizer.lheading(src)) {
68230 src = src.substring(token.raw.length);
68231 tokens.push(token);
68233 } // top-level paragraph
68236 if (top && (token = this.tokenizer.paragraph(src))) {
68237 src = src.substring(token.raw.length);
68238 tokens.push(token);
68243 if (token = this.tokenizer.text(src)) {
68244 src = src.substring(token.raw.length);
68245 lastToken = tokens[tokens.length - 1];
68247 if (lastToken && lastToken.type === 'text') {
68248 lastToken.raw += '\n' + token.raw;
68249 lastToken.text += '\n' + token.text;
68251 tokens.push(token);
68258 var errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
68260 if (this.options.silent) {
68261 console.error(errMsg);
68264 throw new Error(errMsg);
68273 value: function inline(tokens) {
68274 var i, j, k, l2, row, token;
68275 var l = tokens.length;
68277 for (i = 0; i < l; i++) {
68280 switch (token.type) {
68286 this.inlineTokens(token.text, token.tokens);
68297 l2 = token.header.length;
68299 for (j = 0; j < l2; j++) {
68300 token.tokens.header[j] = [];
68301 this.inlineTokens(token.header[j], token.tokens.header[j]);
68305 l2 = token.cells.length;
68307 for (j = 0; j < l2; j++) {
68308 row = token.cells[j];
68309 token.tokens.cells[j] = [];
68311 for (k = 0; k < row.length; k++) {
68312 token.tokens.cells[j][k] = [];
68313 this.inlineTokens(row[k], token.tokens.cells[j][k]);
68322 this.inline(token.tokens);
68328 l2 = token.items.length;
68330 for (j = 0; j < l2; j++) {
68331 this.inline(token.items[j].tokens);
68346 key: "inlineTokens",
68347 value: function inlineTokens(src) {
68348 var tokens = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
68349 var inLink = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
68350 var inRawBlock = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
68351 var token, lastToken; // String with links masked to avoid interference with em and strong
68353 var maskedSrc = src;
68355 var keepPrevChar, prevChar; // Mask out reflinks
68357 if (this.tokens.links) {
68358 var links = Object.keys(this.tokens.links);
68360 if (links.length > 0) {
68361 while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
68362 if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
68363 maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
68367 } // Mask out other blocks
68370 while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
68371 maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
68372 } // Mask out escaped em & strong delimiters
68375 while ((match = this.tokenizer.rules.inline.escapedEmSt.exec(maskedSrc)) != null) {
68376 maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.escapedEmSt.lastIndex);
68380 if (!keepPrevChar) {
68384 keepPrevChar = false; // escape
68386 if (token = this.tokenizer.escape(src)) {
68387 src = src.substring(token.raw.length);
68388 tokens.push(token);
68393 if (token = this.tokenizer.tag(src, inLink, inRawBlock)) {
68394 src = src.substring(token.raw.length);
68395 inLink = token.inLink;
68396 inRawBlock = token.inRawBlock;
68397 var _lastToken = tokens[tokens.length - 1];
68399 if (_lastToken && token.type === 'text' && _lastToken.type === 'text') {
68400 _lastToken.raw += token.raw;
68401 _lastToken.text += token.text;
68403 tokens.push(token);
68410 if (token = this.tokenizer.link(src)) {
68411 src = src.substring(token.raw.length);
68413 if (token.type === 'link') {
68414 token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
68417 tokens.push(token);
68419 } // reflink, nolink
68422 if (token = this.tokenizer.reflink(src, this.tokens.links)) {
68423 src = src.substring(token.raw.length);
68424 var _lastToken2 = tokens[tokens.length - 1];
68426 if (token.type === 'link') {
68427 token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
68428 tokens.push(token);
68429 } else if (_lastToken2 && token.type === 'text' && _lastToken2.type === 'text') {
68430 _lastToken2.raw += token.raw;
68431 _lastToken2.text += token.text;
68433 tokens.push(token);
68440 if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
68441 src = src.substring(token.raw.length);
68442 token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
68443 tokens.push(token);
68448 if (token = this.tokenizer.codespan(src)) {
68449 src = src.substring(token.raw.length);
68450 tokens.push(token);
68455 if (token = this.tokenizer.br(src)) {
68456 src = src.substring(token.raw.length);
68457 tokens.push(token);
68462 if (token = this.tokenizer.del(src)) {
68463 src = src.substring(token.raw.length);
68464 token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
68465 tokens.push(token);
68470 if (token = this.tokenizer.autolink(src, mangle)) {
68471 src = src.substring(token.raw.length);
68472 tokens.push(token);
68477 if (!inLink && (token = this.tokenizer.url(src, mangle))) {
68478 src = src.substring(token.raw.length);
68479 tokens.push(token);
68484 if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) {
68485 src = src.substring(token.raw.length);
68487 if (token.raw.slice(-1) !== '_') {
68488 // Track prevChar before string of ____ started
68489 prevChar = token.raw.slice(-1);
68492 keepPrevChar = true;
68493 lastToken = tokens[tokens.length - 1];
68495 if (lastToken && lastToken.type === 'text') {
68496 lastToken.raw += token.raw;
68497 lastToken.text += token.text;
68499 tokens.push(token);
68506 var errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
68508 if (this.options.silent) {
68509 console.error(errMsg);
68512 throw new Error(errMsg);
68521 get: function get() {
68528 * Static Lex Method
68533 value: function lex(src, options) {
68534 var lexer = new Lexer(options);
68535 return lexer.lex(src);
68538 * Static Lex Inline Method
68543 value: function lexInline(src, options) {
68544 var lexer = new Lexer(options);
68545 return lexer.inlineTokens(src);
68552 var defaults$2 = defaults$5.exports.defaults;
68553 var cleanUrl = helpers.cleanUrl,
68554 escape$2 = helpers.escape;
68559 var Renderer_1 = /*#__PURE__*/function () {
68560 function Renderer(options) {
68561 _classCallCheck$1(this, Renderer);
68563 this.options = options || defaults$2;
68566 _createClass$1(Renderer, [{
68568 value: function code(_code, infostring, escaped) {
68569 var lang = (infostring || '').match(/\S*/)[0];
68571 if (this.options.highlight) {
68572 var out = this.options.highlight(_code, lang);
68574 if (out != null && out !== _code) {
68580 _code = _code.replace(/\n$/, '') + '\n';
68583 return '<pre><code>' + (escaped ? _code : escape$2(_code, true)) + '</code></pre>\n';
68586 return '<pre><code class="' + this.options.langPrefix + escape$2(lang, true) + '">' + (escaped ? _code : escape$2(_code, true)) + '</code></pre>\n';
68590 value: function blockquote(quote) {
68591 return '<blockquote>\n' + quote + '</blockquote>\n';
68595 value: function html(_html) {
68600 value: function heading(text, level, raw, slugger) {
68601 if (this.options.headerIds) {
68602 return '<h' + level + ' id="' + this.options.headerPrefix + slugger.slug(raw) + '">' + text + '</h' + level + '>\n';
68606 return '<h' + level + '>' + text + '</h' + level + '>\n';
68610 value: function hr() {
68611 return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
68615 value: function list(body, ordered, start) {
68616 var type = ordered ? 'ol' : 'ul',
68617 startatt = ordered && start !== 1 ? ' start="' + start + '"' : '';
68618 return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
68622 value: function listitem(text) {
68623 return '<li>' + text + '</li>\n';
68627 value: function checkbox(checked) {
68628 return '<input ' + (checked ? 'checked="" ' : '') + 'disabled="" type="checkbox"' + (this.options.xhtml ? ' /' : '') + '> ';
68632 value: function paragraph(text) {
68633 return '<p>' + text + '</p>\n';
68637 value: function table(header, body) {
68638 if (body) body = '<tbody>' + body + '</tbody>';
68639 return '<table>\n' + '<thead>\n' + header + '</thead>\n' + body + '</table>\n';
68643 value: function tablerow(content) {
68644 return '<tr>\n' + content + '</tr>\n';
68648 value: function tablecell(content, flags) {
68649 var type = flags.header ? 'th' : 'td';
68650 var tag = flags.align ? '<' + type + ' align="' + flags.align + '">' : '<' + type + '>';
68651 return tag + content + '</' + type + '>\n';
68652 } // span level renderer
68656 value: function strong(text) {
68657 return '<strong>' + text + '</strong>';
68661 value: function em(text) {
68662 return '<em>' + text + '</em>';
68666 value: function codespan(text) {
68667 return '<code>' + text + '</code>';
68671 value: function br() {
68672 return this.options.xhtml ? '<br/>' : '<br>';
68676 value: function del(text) {
68677 return '<del>' + text + '</del>';
68681 value: function link(href, title, text) {
68682 href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
68684 if (href === null) {
68688 var out = '<a href="' + escape$2(href) + '"';
68691 out += ' title="' + title + '"';
68694 out += '>' + text + '</a>';
68699 value: function image(href, title, text) {
68700 href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
68702 if (href === null) {
68706 var out = '<img src="' + href + '" alt="' + text + '"';
68709 out += ' title="' + title + '"';
68712 out += this.options.xhtml ? '/>' : '>';
68717 value: function text(_text) {
68725 var TextRenderer_1 = /*#__PURE__*/function () {
68726 function TextRenderer() {
68727 _classCallCheck$1(this, TextRenderer);
68730 _createClass$1(TextRenderer, [{
68732 value: // no need for block level renderers
68733 function strong(text) {
68738 value: function em(text) {
68743 value: function codespan(text) {
68748 value: function del(text) {
68753 value: function html(text) {
68758 value: function text(_text) {
68763 value: function link(href, title, text) {
68768 value: function image(href, title, text) {
68773 value: function br() {
68778 return TextRenderer;
68781 var Slugger_1 = /*#__PURE__*/function () {
68782 function Slugger() {
68783 _classCallCheck$1(this, Slugger);
68788 _createClass$1(Slugger, [{
68790 value: function serialize(value) {
68791 return value.toLowerCase().trim() // remove html tags
68792 .replace(/<[!\/a-z].*?>/ig, '') // remove unwanted chars
68793 .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '').replace(/\s/g, '-');
68796 * Finds the next safe (unique) slug to use
68800 key: "getNextSafeSlug",
68801 value: function getNextSafeSlug(originalSlug, isDryRun) {
68802 var slug = originalSlug;
68803 var occurenceAccumulator = 0;
68805 if (this.seen.hasOwnProperty(slug)) {
68806 occurenceAccumulator = this.seen[originalSlug];
68809 occurenceAccumulator++;
68810 slug = originalSlug + '-' + occurenceAccumulator;
68811 } while (this.seen.hasOwnProperty(slug));
68815 this.seen[originalSlug] = occurenceAccumulator;
68816 this.seen[slug] = 0;
68822 * Convert string to unique id
68823 * @param {object} options
68824 * @param {boolean} options.dryrun Generates the next unique slug without updating the internal accumulator.
68829 value: function slug(value) {
68830 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
68831 var slug = this.serialize(value);
68832 return this.getNextSafeSlug(slug, options.dryrun);
68839 var Renderer$1 = Renderer_1;
68840 var TextRenderer$1 = TextRenderer_1;
68841 var Slugger$1 = Slugger_1;
68842 var defaults$1 = defaults$5.exports.defaults;
68843 var unescape$1 = helpers.unescape;
68845 * Parsing & Compiling
68848 var Parser_1 = /*#__PURE__*/function () {
68849 function Parser(options) {
68850 _classCallCheck$1(this, Parser);
68852 this.options = options || defaults$1;
68853 this.options.renderer = this.options.renderer || new Renderer$1();
68854 this.renderer = this.options.renderer;
68855 this.renderer.options = this.options;
68856 this.textRenderer = new TextRenderer$1();
68857 this.slugger = new Slugger$1();
68860 * Static Parse Method
68864 _createClass$1(Parser, [{
68870 function parse(tokens) {
68871 var top = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
68891 var l = tokens.length;
68893 for (i = 0; i < l; i++) {
68896 switch (token.type) {
68904 out += this.renderer.hr();
68910 out += this.renderer.heading(this.parseInline(token.tokens), token.depth, unescape$1(this.parseInline(token.tokens, this.textRenderer)), this.slugger);
68916 out += this.renderer.code(token.text, token.lang, token.escaped);
68922 header = ''; // header
68925 l2 = token.header.length;
68927 for (j = 0; j < l2; j++) {
68928 cell += this.renderer.tablecell(this.parseInline(token.tokens.header[j]), {
68930 align: token.align[j]
68934 header += this.renderer.tablerow(cell);
68936 l2 = token.cells.length;
68938 for (j = 0; j < l2; j++) {
68939 row = token.tokens.cells[j];
68943 for (k = 0; k < l3; k++) {
68944 cell += this.renderer.tablecell(this.parseInline(row[k]), {
68946 align: token.align[k]
68950 body += this.renderer.tablerow(cell);
68953 out += this.renderer.table(header, body);
68959 body = this.parse(token.tokens);
68960 out += this.renderer.blockquote(body);
68966 ordered = token.ordered;
68967 start = token.start;
68968 loose = token.loose;
68969 l2 = token.items.length;
68972 for (j = 0; j < l2; j++) {
68973 item = token.items[j];
68974 checked = item.checked;
68979 checkbox = this.renderer.checkbox(checked);
68982 if (item.tokens.length > 0 && item.tokens[0].type === 'text') {
68983 item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
68985 if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
68986 item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
68989 item.tokens.unshift({
68995 itemBody += checkbox;
68999 itemBody += this.parse(item.tokens, loose);
69000 body += this.renderer.listitem(itemBody, task, checked);
69003 out += this.renderer.list(body, ordered, start);
69009 // TODO parse inline content if parameter markdown=1
69010 out += this.renderer.html(token.text);
69016 out += this.renderer.paragraph(this.parseInline(token.tokens));
69022 body = token.tokens ? this.parseInline(token.tokens) : token.text;
69024 while (i + 1 < l && tokens[i + 1].type === 'text') {
69025 token = tokens[++i];
69026 body += '\n' + (token.tokens ? this.parseInline(token.tokens) : token.text);
69029 out += top ? this.renderer.paragraph(body) : body;
69035 var errMsg = 'Token with "' + token.type + '" type was not found.';
69037 if (this.options.silent) {
69038 console.error(errMsg);
69041 throw new Error(errMsg);
69050 * Parse Inline Tokens
69054 key: "parseInline",
69055 value: function parseInline(tokens, renderer) {
69056 renderer = renderer || this.renderer;
69060 var l = tokens.length;
69062 for (i = 0; i < l; i++) {
69065 switch (token.type) {
69068 out += renderer.text(token.text);
69074 out += renderer.html(token.text);
69080 out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer));
69086 out += renderer.image(token.href, token.title, token.text);
69092 out += renderer.strong(this.parseInline(token.tokens, renderer));
69098 out += renderer.em(this.parseInline(token.tokens, renderer));
69104 out += renderer.codespan(token.text);
69110 out += renderer.br();
69116 out += renderer.del(this.parseInline(token.tokens, renderer));
69122 out += renderer.text(token.text);
69128 var errMsg = 'Token with "' + token.type + '" type was not found.';
69130 if (this.options.silent) {
69131 console.error(errMsg);
69134 throw new Error(errMsg);
69144 value: function parse(tokens, options) {
69145 var parser = new Parser(options);
69146 return parser.parse(tokens);
69149 * Static Parse Inline Method
69153 key: "parseInline",
69154 value: function parseInline(tokens, options) {
69155 var parser = new Parser(options);
69156 return parser.parseInline(tokens);
69163 var Lexer = Lexer_1;
69164 var Parser = Parser_1;
69165 var Tokenizer = Tokenizer_1;
69166 var Renderer = Renderer_1;
69167 var TextRenderer = TextRenderer_1;
69168 var Slugger = Slugger_1;
69169 var merge = helpers.merge,
69170 checkSanitizeDeprecation = helpers.checkSanitizeDeprecation,
69171 escape$1 = helpers.escape;
69172 var getDefaults = defaults$5.exports.getDefaults,
69173 changeDefaults = defaults$5.exports.changeDefaults,
69174 defaults = defaults$5.exports.defaults;
69179 function marked(src, opt, callback) {
69180 // throw error in case of non string input
69181 if (typeof src === 'undefined' || src === null) {
69182 throw new Error('marked(): input parameter is undefined or null');
69185 if (typeof src !== 'string') {
69186 throw new Error('marked(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected');
69189 if (typeof opt === 'function') {
69194 opt = merge({}, marked.defaults, opt || {});
69195 checkSanitizeDeprecation(opt);
69198 var highlight = opt.highlight;
69202 tokens = Lexer.lex(src, opt);
69204 return callback(e);
69207 var done = function done(err) {
69212 if (opt.walkTokens) {
69213 marked.walkTokens(tokens, opt.walkTokens);
69216 out = Parser.parse(tokens, opt);
69222 opt.highlight = highlight;
69223 return err ? callback(err) : callback(null, out);
69226 if (!highlight || highlight.length < 3) {
69230 delete opt.highlight;
69231 if (!tokens.length) return done();
69233 marked.walkTokens(tokens, function (token) {
69234 if (token.type === 'code') {
69236 setTimeout(function () {
69237 highlight(token.text, token.lang, function (err, code) {
69242 if (code != null && code !== token.text) {
69244 token.escaped = true;
69249 if (pending === 0) {
69257 if (pending === 0) {
69265 var _tokens = Lexer.lex(src, opt);
69267 if (opt.walkTokens) {
69268 marked.walkTokens(_tokens, opt.walkTokens);
69271 return Parser.parse(_tokens, opt);
69273 e.message += '\nPlease report this to https://github.com/markedjs/marked.';
69276 return '<p>An error occurred:</p><pre>' + escape$1(e.message + '', true) + '</pre>';
69287 marked.options = marked.setOptions = function (opt) {
69288 merge(marked.defaults, opt);
69289 changeDefaults(marked.defaults);
69293 marked.getDefaults = getDefaults;
69294 marked.defaults = defaults;
69299 marked.use = function (extension) {
69300 var opts = merge({}, extension);
69302 if (extension.renderer) {
69304 var renderer = marked.defaults.renderer || new Renderer();
69306 var _loop = function _loop(prop) {
69307 var prevRenderer = renderer[prop];
69309 renderer[prop] = function () {
69310 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
69311 args[_key] = arguments[_key];
69314 var ret = extension.renderer[prop].apply(renderer, args);
69316 if (ret === false) {
69317 ret = prevRenderer.apply(renderer, args);
69324 for (var prop in extension.renderer) {
69328 opts.renderer = renderer;
69332 if (extension.tokenizer) {
69334 var tokenizer = marked.defaults.tokenizer || new Tokenizer();
69336 var _loop2 = function _loop2(prop) {
69337 var prevTokenizer = tokenizer[prop];
69339 tokenizer[prop] = function () {
69340 for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
69341 args[_key2] = arguments[_key2];
69344 var ret = extension.tokenizer[prop].apply(tokenizer, args);
69346 if (ret === false) {
69347 ret = prevTokenizer.apply(tokenizer, args);
69354 for (var prop in extension.tokenizer) {
69358 opts.tokenizer = tokenizer;
69362 if (extension.walkTokens) {
69363 var walkTokens = marked.defaults.walkTokens;
69365 opts.walkTokens = function (token) {
69366 extension.walkTokens(token);
69374 marked.setOptions(opts);
69377 * Run callback for every token
69381 marked.walkTokens = function (tokens, callback) {
69382 var _iterator = _createForOfIteratorHelper(tokens),
69386 for (_iterator.s(); !(_step = _iterator.n()).done;) {
69387 var token = _step.value;
69390 switch (token.type) {
69393 var _iterator2 = _createForOfIteratorHelper(token.tokens.header),
69397 for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
69398 var cell = _step2.value;
69399 marked.walkTokens(cell, callback);
69407 var _iterator3 = _createForOfIteratorHelper(token.tokens.cells),
69411 for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
69412 var row = _step3.value;
69414 var _iterator4 = _createForOfIteratorHelper(row),
69418 for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
69419 var _cell = _step4.value;
69420 marked.walkTokens(_cell, callback);
69439 marked.walkTokens(token.items, callback);
69445 if (token.tokens) {
69446 marked.walkTokens(token.tokens, callback);
69462 marked.parseInline = function (src, opt) {
69463 // throw error in case of non string input
69464 if (typeof src === 'undefined' || src === null) {
69465 throw new Error('marked.parseInline(): input parameter is undefined or null');
69468 if (typeof src !== 'string') {
69469 throw new Error('marked.parseInline(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected');
69472 opt = merge({}, marked.defaults, opt || {});
69473 checkSanitizeDeprecation(opt);
69476 var tokens = Lexer.lexInline(src, opt);
69478 if (opt.walkTokens) {
69479 marked.walkTokens(tokens, opt.walkTokens);
69482 return Parser.parseInline(tokens, opt);
69484 e.message += '\nPlease report this to https://github.com/markedjs/marked.';
69487 return '<p>An error occurred:</p><pre>' + escape$1(e.message + '', true) + '</pre>';
69498 marked.Parser = Parser;
69499 marked.parser = Parser.parse;
69500 marked.Renderer = Renderer;
69501 marked.TextRenderer = TextRenderer;
69502 marked.Lexer = Lexer;
69503 marked.lexer = Lexer.lex;
69504 marked.Tokenizer = Tokenizer;
69505 marked.Slugger = Slugger;
69506 marked.parse = marked;
69507 var marked_1 = marked;
69509 var tiler$4 = utilTiler();
69510 var dispatch$5 = dispatch$8('loaded');
69511 var _tileZoom$1 = 14;
69512 var _osmoseUrlRoot = 'https://osmose.openstreetmap.fr/api/0.3';
69513 var _osmoseData = {
69516 }; // This gets reassigned if reset
69520 function abortRequest$4(controller) {
69522 controller.abort();
69526 function abortUnwantedRequests$1(cache, tiles) {
69527 Object.keys(cache.inflightTile).forEach(function (k) {
69528 var wanted = tiles.find(function (tile) {
69529 return k === tile.id;
69533 abortRequest$4(cache.inflightTile[k]);
69534 delete cache.inflightTile[k];
69539 function encodeIssueRtree(d) {
69547 } // Replace or remove QAItem from rtree
69550 function updateRtree$1(item, replace) {
69551 _cache.rtree.remove(item, function (a, b) {
69552 return a.data.id === b.data.id;
69556 _cache.rtree.insert(item);
69558 } // Issues shouldn't obscure each other
69561 function preventCoincident(loc) {
69562 var coincident = false;
69565 // first time, move marker up. after that, move marker right.
69566 var delta = coincident ? [0.00001, 0] : [0, 0.00001];
69567 loc = geoVecAdd(loc, delta);
69568 var bbox = geoExtent(loc).bbox();
69569 coincident = _cache.rtree.search(bbox).length;
69570 } while (coincident);
69575 var serviceOsmose = {
69577 init: function init() {
69578 _mainFileFetcher.get('qa_data').then(function (d) {
69579 _osmoseData = d.osmose;
69580 _osmoseData.items = Object.keys(d.osmose.icons).map(function (s) {
69581 return s.split('-')[0];
69582 }).reduce(function (unique, item) {
69583 return unique.indexOf(item) !== -1 ? unique : [].concat(_toConsumableArray(unique), [item]);
69591 this.event = utilRebind(this, dispatch$5, 'on');
69593 reset: function reset() {
69598 Object.values(_cache.inflightTile).forEach(abortRequest$4); // Strings and colors are static and should not be re-populated
69600 _strings = _cache.strings;
69601 _colors = _cache.colors;
69610 rtree: new RBush(),
69615 loadIssues: function loadIssues(projection) {
69619 // Tiles return a maximum # of issues
69620 // So we want to filter our request for only types iD supports
69621 item: _osmoseData.items
69622 }; // determine the needed tiles to cover the view
69624 var tiles = tiler$4.zoomExtent([_tileZoom$1, _tileZoom$1]).getTiles(projection); // abort inflight requests that are no longer needed
69626 abortUnwantedRequests$1(_cache, tiles); // issue new requests..
69628 tiles.forEach(function (tile) {
69629 if (_cache.loadedTile[tile.id] || _cache.inflightTile[tile.id]) return;
69631 var _tile$xyz = _slicedToArray(tile.xyz, 3),
69636 var url = "".concat(_osmoseUrlRoot, "/issues/").concat(z, "/").concat(x, "/").concat(y, ".json?") + utilQsString(params);
69637 var controller = new AbortController();
69638 _cache.inflightTile[tile.id] = controller;
69640 signal: controller.signal
69641 }).then(function (data) {
69642 delete _cache.inflightTile[tile.id];
69643 _cache.loadedTile[tile.id] = true;
69645 if (data.features) {
69646 data.features.forEach(function (issue) {
69647 var _issue$properties = issue.properties,
69648 item = _issue$properties.item,
69649 cl = _issue$properties["class"],
69650 id = _issue$properties.uuid;
69651 /* Osmose issues are uniquely identified by a unique
69652 `item` and `class` combination (both integer values) */
69654 var itemType = "".concat(item, "-").concat(cl); // Filter out unsupported issue types (some are too specific or advanced)
69656 if (itemType in _osmoseData.icons) {
69657 var loc = issue.geometry.coordinates; // lon, lat
69659 loc = preventCoincident(loc);
69660 var d = new QAItem(loc, _this, itemType, id, {
69662 }); // Setting elems here prevents UI detail requests
69664 if (item === 8300 || item === 8360) {
69668 _cache.data[d.id] = d;
69670 _cache.rtree.insert(encodeIssueRtree(d));
69675 dispatch$5.call('loaded');
69676 })["catch"](function () {
69677 delete _cache.inflightTile[tile.id];
69678 _cache.loadedTile[tile.id] = true;
69682 loadIssueDetail: function loadIssueDetail(issue) {
69685 // Issue details only need to be fetched once
69686 if (issue.elems !== undefined) {
69687 return Promise.resolve(issue);
69690 var url = "".concat(_osmoseUrlRoot, "/issue/").concat(issue.id, "?langs=").concat(_mainLocalizer.localeCode());
69692 var cacheDetails = function cacheDetails(data) {
69693 // Associated elements used for highlighting
69694 // Assign directly for immediate use in the callback
69695 issue.elems = data.elems.map(function (e) {
69696 return e.type.substring(0, 1) + e.id;
69697 }); // Some issues have instance specific detail in a subtitle
69699 issue.detail = data.subtitle ? marked_1(data.subtitle.auto) : '';
69701 _this2.replaceItem(issue);
69704 return d3_json(url).then(cacheDetails).then(function () {
69708 loadStrings: function loadStrings() {
69709 var locale = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _mainLocalizer.localeCode();
69710 var items = Object.keys(_osmoseData.icons);
69712 if (locale in _cache.strings && Object.keys(_cache.strings[locale]).length === items.length) {
69713 return Promise.resolve(_cache.strings[locale]);
69714 } // May be partially populated already if some requests were successful
69717 if (!(locale in _cache.strings)) {
69718 _cache.strings[locale] = {};
69719 } // Only need to cache strings for supported issue types
69720 // Using multiple individual item + class requests to reduce fetched data size
69723 var allRequests = items.map(function (itemType) {
69724 // No need to request data we already have
69725 if (itemType in _cache.strings[locale]) return null;
69727 var cacheData = function cacheData(data) {
69728 // Bunch of nested single value arrays of objects
69729 var _data$categories = _slicedToArray(data.categories, 1),
69730 _data$categories$ = _data$categories[0],
69731 cat = _data$categories$ === void 0 ? {
69733 } : _data$categories$;
69735 var _cat$items = _slicedToArray(cat.items, 1),
69736 _cat$items$ = _cat$items[0],
69737 item = _cat$items$ === void 0 ? {
69741 var _item$class = _slicedToArray(item["class"], 1),
69742 _item$class$ = _item$class[0],
69743 cl = _item$class$ === void 0 ? null : _item$class$; // If null default value is reached, data wasn't as expected (or was empty)
69747 /* eslint-disable no-console */
69748 console.log("Osmose strings request (".concat(itemType, ") had unexpected data"));
69749 /* eslint-enable no-console */
69752 } // Cache served item colors to automatically style issue markers later
69755 var itemInt = item.item,
69756 color = item.color;
69758 if (/^#[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/.test(color)) {
69759 _cache.colors[itemInt] = color;
69760 } // Value of root key will be null if no string exists
69761 // If string exists, value is an object with key 'auto' for string
69764 var title = cl.title,
69765 detail = cl.detail,
69767 trap = cl.trap; // Osmose titles shouldn't contain markdown
69769 var issueStrings = {};
69770 if (title) issueStrings.title = title.auto;
69771 if (detail) issueStrings.detail = marked_1(detail.auto);
69772 if (trap) issueStrings.trap = marked_1(trap.auto);
69773 if (fix) issueStrings.fix = marked_1(fix.auto);
69774 _cache.strings[locale][itemType] = issueStrings;
69777 var _itemType$split = itemType.split('-'),
69778 _itemType$split2 = _slicedToArray(_itemType$split, 2),
69779 item = _itemType$split2[0],
69780 cl = _itemType$split2[1]; // Osmose API falls back to English strings where untranslated or if locale doesn't exist
69783 var url = "".concat(_osmoseUrlRoot, "/items/").concat(item, "/class/").concat(cl, "?langs=").concat(locale);
69784 return d3_json(url).then(cacheData);
69785 }).filter(Boolean);
69786 return Promise.all(allRequests).then(function () {
69787 return _cache.strings[locale];
69790 getStrings: function getStrings(itemType) {
69791 var locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _mainLocalizer.localeCode();
69792 // No need to fallback to English, Osmose API handles this for us
69793 return locale in _cache.strings ? _cache.strings[locale][itemType] : {};
69795 getColor: function getColor(itemType) {
69796 return itemType in _cache.colors ? _cache.colors[itemType] : '#FFFFFF';
69798 postUpdate: function postUpdate(issue, callback) {
69801 if (_cache.inflightPost[issue.id]) {
69803 message: 'Issue update already inflight',
69806 } // UI sets the status to either 'done' or 'false'
69809 var url = "".concat(_osmoseUrlRoot, "/issue/").concat(issue.id, "/").concat(issue.newStatus);
69810 var controller = new AbortController();
69812 var after = function after() {
69813 delete _cache.inflightPost[issue.id];
69815 _this3.removeItem(issue);
69817 if (issue.newStatus === 'done') {
69818 // Keep track of the number of issues closed per `item` to tag the changeset
69819 if (!(issue.item in _cache.closed)) {
69820 _cache.closed[issue.item] = 0;
69823 _cache.closed[issue.item] += 1;
69826 if (callback) callback(null, issue);
69829 _cache.inflightPost[issue.id] = controller;
69831 signal: controller.signal
69832 }).then(after)["catch"](function (err) {
69833 delete _cache.inflightPost[issue.id];
69834 if (callback) callback(err.message);
69837 // Get all cached QAItems covering the viewport
69838 getItems: function getItems(projection) {
69839 var viewport = projection.clipExtent();
69840 var min = [viewport[0][0], viewport[1][1]];
69841 var max = [viewport[1][0], viewport[0][1]];
69842 var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
69843 return _cache.rtree.search(bbox).map(function (d) {
69847 // Get a QAItem from cache
69848 // NOTE: Don't change method name until UI v3 is merged
69849 getError: function getError(id) {
69850 return _cache.data[id];
69852 // get the name of the icon to display for this item
69853 getIcon: function getIcon(itemType) {
69854 return _osmoseData.icons[itemType];
69856 // Replace a single QAItem in the cache
69857 replaceItem: function replaceItem(item) {
69858 if (!(item instanceof QAItem) || !item.id) return;
69859 _cache.data[item.id] = item;
69860 updateRtree$1(encodeIssueRtree(item), true); // true = replace
69864 // Remove a single QAItem from the cache
69865 removeItem: function removeItem(item) {
69866 if (!(item instanceof QAItem) || !item.id) return;
69867 delete _cache.data[item.id];
69868 updateRtree$1(encodeIssueRtree(item), false); // false = remove
69870 // Used to populate `closed:osmose:*` changeset tags
69871 getClosedCounts: function getClosedCounts() {
69872 return _cache.closed;
69874 itemURL: function itemURL(item) {
69875 return "https://osmose.openstreetmap.fr/en/error/".concat(item.id);
69879 var ieee754$1 = {};
69881 /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
69883 ieee754$1.read = function (buffer, offset, isLE, mLen, nBytes) {
69885 var eLen = nBytes * 8 - mLen - 1;
69886 var eMax = (1 << eLen) - 1;
69887 var eBias = eMax >> 1;
69889 var i = isLE ? nBytes - 1 : 0;
69890 var d = isLE ? -1 : 1;
69891 var s = buffer[offset + i];
69893 e = s & (1 << -nBits) - 1;
69897 for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
69899 m = e & (1 << -nBits) - 1;
69903 for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
69907 } else if (e === eMax) {
69908 return m ? NaN : (s ? -1 : 1) * Infinity;
69910 m = m + Math.pow(2, mLen);
69914 return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
69917 ieee754$1.write = function (buffer, value, offset, isLE, mLen, nBytes) {
69919 var eLen = nBytes * 8 - mLen - 1;
69920 var eMax = (1 << eLen) - 1;
69921 var eBias = eMax >> 1;
69922 var rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0;
69923 var i = isLE ? 0 : nBytes - 1;
69924 var d = isLE ? 1 : -1;
69925 var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0;
69926 value = Math.abs(value);
69928 if (isNaN(value) || value === Infinity) {
69929 m = isNaN(value) ? 1 : 0;
69932 e = Math.floor(Math.log(value) / Math.LN2);
69934 if (value * (c = Math.pow(2, -e)) < 1) {
69939 if (e + eBias >= 1) {
69942 value += rt * Math.pow(2, 1 - eBias);
69945 if (value * c >= 2) {
69950 if (e + eBias >= eMax) {
69953 } else if (e + eBias >= 1) {
69954 m = (value * c - 1) * Math.pow(2, mLen);
69957 m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
69962 for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
69967 for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
69969 buffer[offset + i - d] |= s * 128;
69973 var ieee754 = ieee754$1;
69975 function Pbf(buf) {
69976 this.buf = ArrayBuffer.isView && ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf || 0);
69979 this.length = this.buf.length;
69982 Pbf.Varint = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum
69984 Pbf.Fixed64 = 1; // 64-bit: double, fixed64, sfixed64
69986 Pbf.Bytes = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields
69988 Pbf.Fixed32 = 5; // 32-bit: float, fixed32, sfixed32
69990 var SHIFT_LEFT_32 = (1 << 16) * (1 << 16),
69991 SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32; // Threshold chosen based on both benchmarking and knowledge about browser string
69992 // data structures (which currently switch structure types at 12 bytes or more)
69994 var TEXT_DECODER_MIN_LENGTH = 12;
69995 var utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf8');
69997 destroy: function destroy() {
70000 // === READING =================================================================
70001 readFields: function readFields(readField, result, end) {
70002 end = end || this.length;
70004 while (this.pos < end) {
70005 var val = this.readVarint(),
70007 startPos = this.pos;
70008 this.type = val & 0x7;
70009 readField(tag, result, this);
70010 if (this.pos === startPos) this.skip(val);
70015 readMessage: function readMessage(readField, result) {
70016 return this.readFields(readField, result, this.readVarint() + this.pos);
70018 readFixed32: function readFixed32() {
70019 var val = readUInt32(this.buf, this.pos);
70023 readSFixed32: function readSFixed32() {
70024 var val = readInt32(this.buf, this.pos);
70028 // 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)
70029 readFixed64: function readFixed64() {
70030 var val = readUInt32(this.buf, this.pos) + readUInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
70034 readSFixed64: function readSFixed64() {
70035 var val = readUInt32(this.buf, this.pos) + readInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
70039 readFloat: function readFloat() {
70040 var val = ieee754.read(this.buf, this.pos, true, 23, 4);
70044 readDouble: function readDouble() {
70045 var val = ieee754.read(this.buf, this.pos, true, 52, 8);
70049 readVarint: function readVarint(isSigned) {
70050 var buf = this.buf,
70053 b = buf[this.pos++];
70055 if (b < 0x80) return val;
70056 b = buf[this.pos++];
70057 val |= (b & 0x7f) << 7;
70058 if (b < 0x80) return val;
70059 b = buf[this.pos++];
70060 val |= (b & 0x7f) << 14;
70061 if (b < 0x80) return val;
70062 b = buf[this.pos++];
70063 val |= (b & 0x7f) << 21;
70064 if (b < 0x80) return val;
70066 val |= (b & 0x0f) << 28;
70067 return readVarintRemainder(val, isSigned, this);
70069 readVarint64: function readVarint64() {
70070 // for compatibility with v2.0.1
70071 return this.readVarint(true);
70073 readSVarint: function readSVarint() {
70074 var num = this.readVarint();
70075 return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding
70077 readBoolean: function readBoolean() {
70078 return Boolean(this.readVarint());
70080 readString: function readString() {
70081 var end = this.readVarint() + this.pos;
70082 var pos = this.pos;
70085 if (end - pos >= TEXT_DECODER_MIN_LENGTH && utf8TextDecoder) {
70086 // longer strings are fast with the built-in browser TextDecoder API
70087 return readUtf8TextDecoder(this.buf, pos, end);
70088 } // short strings are fast with our custom implementation
70091 return readUtf8(this.buf, pos, end);
70093 readBytes: function readBytes() {
70094 var end = this.readVarint() + this.pos,
70095 buffer = this.buf.subarray(this.pos, end);
70099 // verbose for performance reasons; doesn't affect gzipped size
70100 readPackedVarint: function readPackedVarint(arr, isSigned) {
70101 if (this.type !== Pbf.Bytes) return arr.push(this.readVarint(isSigned));
70102 var end = readPackedEnd(this);
70105 while (this.pos < end) {
70106 arr.push(this.readVarint(isSigned));
70111 readPackedSVarint: function readPackedSVarint(arr) {
70112 if (this.type !== Pbf.Bytes) return arr.push(this.readSVarint());
70113 var end = readPackedEnd(this);
70116 while (this.pos < end) {
70117 arr.push(this.readSVarint());
70122 readPackedBoolean: function readPackedBoolean(arr) {
70123 if (this.type !== Pbf.Bytes) return arr.push(this.readBoolean());
70124 var end = readPackedEnd(this);
70127 while (this.pos < end) {
70128 arr.push(this.readBoolean());
70133 readPackedFloat: function readPackedFloat(arr) {
70134 if (this.type !== Pbf.Bytes) return arr.push(this.readFloat());
70135 var end = readPackedEnd(this);
70138 while (this.pos < end) {
70139 arr.push(this.readFloat());
70144 readPackedDouble: function readPackedDouble(arr) {
70145 if (this.type !== Pbf.Bytes) return arr.push(this.readDouble());
70146 var end = readPackedEnd(this);
70149 while (this.pos < end) {
70150 arr.push(this.readDouble());
70155 readPackedFixed32: function readPackedFixed32(arr) {
70156 if (this.type !== Pbf.Bytes) return arr.push(this.readFixed32());
70157 var end = readPackedEnd(this);
70160 while (this.pos < end) {
70161 arr.push(this.readFixed32());
70166 readPackedSFixed32: function readPackedSFixed32(arr) {
70167 if (this.type !== Pbf.Bytes) return arr.push(this.readSFixed32());
70168 var end = readPackedEnd(this);
70171 while (this.pos < end) {
70172 arr.push(this.readSFixed32());
70177 readPackedFixed64: function readPackedFixed64(arr) {
70178 if (this.type !== Pbf.Bytes) return arr.push(this.readFixed64());
70179 var end = readPackedEnd(this);
70182 while (this.pos < end) {
70183 arr.push(this.readFixed64());
70188 readPackedSFixed64: function readPackedSFixed64(arr) {
70189 if (this.type !== Pbf.Bytes) return arr.push(this.readSFixed64());
70190 var end = readPackedEnd(this);
70193 while (this.pos < end) {
70194 arr.push(this.readSFixed64());
70199 skip: function skip(val) {
70200 var type = val & 0x7;
70201 if (type === Pbf.Varint) while (this.buf[this.pos++] > 0x7f) {} else if (type === Pbf.Bytes) this.pos = this.readVarint() + this.pos;else if (type === Pbf.Fixed32) this.pos += 4;else if (type === Pbf.Fixed64) this.pos += 8;else throw new Error('Unimplemented type: ' + type);
70203 // === WRITING =================================================================
70204 writeTag: function writeTag(tag, type) {
70205 this.writeVarint(tag << 3 | type);
70207 realloc: function realloc(min) {
70208 var length = this.length || 16;
70210 while (length < this.pos + min) {
70214 if (length !== this.length) {
70215 var buf = new Uint8Array(length);
70218 this.length = length;
70221 finish: function finish() {
70222 this.length = this.pos;
70224 return this.buf.subarray(0, this.length);
70226 writeFixed32: function writeFixed32(val) {
70228 writeInt32(this.buf, val, this.pos);
70231 writeSFixed32: function writeSFixed32(val) {
70233 writeInt32(this.buf, val, this.pos);
70236 writeFixed64: function writeFixed64(val) {
70238 writeInt32(this.buf, val & -1, this.pos);
70239 writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
70242 writeSFixed64: function writeSFixed64(val) {
70244 writeInt32(this.buf, val & -1, this.pos);
70245 writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
70248 writeVarint: function writeVarint(val) {
70251 if (val > 0xfffffff || val < 0) {
70252 writeBigVarint(val, this);
70257 this.buf[this.pos++] = val & 0x7f | (val > 0x7f ? 0x80 : 0);
70258 if (val <= 0x7f) return;
70259 this.buf[this.pos++] = (val >>>= 7) & 0x7f | (val > 0x7f ? 0x80 : 0);
70260 if (val <= 0x7f) return;
70261 this.buf[this.pos++] = (val >>>= 7) & 0x7f | (val > 0x7f ? 0x80 : 0);
70262 if (val <= 0x7f) return;
70263 this.buf[this.pos++] = val >>> 7 & 0x7f;
70265 writeSVarint: function writeSVarint(val) {
70266 this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
70268 writeBoolean: function writeBoolean(val) {
70269 this.writeVarint(Boolean(val));
70271 writeString: function writeString(str) {
70273 this.realloc(str.length * 4);
70274 this.pos++; // reserve 1 byte for short string length
70276 var startPos = this.pos; // write the string directly to the buffer and see how much was written
70278 this.pos = writeUtf8(this.buf, str, this.pos);
70279 var len = this.pos - startPos;
70280 if (len >= 0x80) makeRoomForExtraLength(startPos, len, this); // finally, write the message length in the reserved place and restore the position
70282 this.pos = startPos - 1;
70283 this.writeVarint(len);
70286 writeFloat: function writeFloat(val) {
70288 ieee754.write(this.buf, val, this.pos, true, 23, 4);
70291 writeDouble: function writeDouble(val) {
70293 ieee754.write(this.buf, val, this.pos, true, 52, 8);
70296 writeBytes: function writeBytes(buffer) {
70297 var len = buffer.length;
70298 this.writeVarint(len);
70301 for (var i = 0; i < len; i++) {
70302 this.buf[this.pos++] = buffer[i];
70305 writeRawMessage: function writeRawMessage(fn, obj) {
70306 this.pos++; // reserve 1 byte for short message length
70307 // write the message directly to the buffer and see how much was written
70309 var startPos = this.pos;
70311 var len = this.pos - startPos;
70312 if (len >= 0x80) makeRoomForExtraLength(startPos, len, this); // finally, write the message length in the reserved place and restore the position
70314 this.pos = startPos - 1;
70315 this.writeVarint(len);
70318 writeMessage: function writeMessage(tag, fn, obj) {
70319 this.writeTag(tag, Pbf.Bytes);
70320 this.writeRawMessage(fn, obj);
70322 writePackedVarint: function writePackedVarint(tag, arr) {
70323 if (arr.length) this.writeMessage(tag, _writePackedVarint, arr);
70325 writePackedSVarint: function writePackedSVarint(tag, arr) {
70326 if (arr.length) this.writeMessage(tag, _writePackedSVarint, arr);
70328 writePackedBoolean: function writePackedBoolean(tag, arr) {
70329 if (arr.length) this.writeMessage(tag, _writePackedBoolean, arr);
70331 writePackedFloat: function writePackedFloat(tag, arr) {
70332 if (arr.length) this.writeMessage(tag, _writePackedFloat, arr);
70334 writePackedDouble: function writePackedDouble(tag, arr) {
70335 if (arr.length) this.writeMessage(tag, _writePackedDouble, arr);
70337 writePackedFixed32: function writePackedFixed32(tag, arr) {
70338 if (arr.length) this.writeMessage(tag, _writePackedFixed, arr);
70340 writePackedSFixed32: function writePackedSFixed32(tag, arr) {
70341 if (arr.length) this.writeMessage(tag, _writePackedSFixed, arr);
70343 writePackedFixed64: function writePackedFixed64(tag, arr) {
70344 if (arr.length) this.writeMessage(tag, _writePackedFixed2, arr);
70346 writePackedSFixed64: function writePackedSFixed64(tag, arr) {
70347 if (arr.length) this.writeMessage(tag, _writePackedSFixed2, arr);
70349 writeBytesField: function writeBytesField(tag, buffer) {
70350 this.writeTag(tag, Pbf.Bytes);
70351 this.writeBytes(buffer);
70353 writeFixed32Field: function writeFixed32Field(tag, val) {
70354 this.writeTag(tag, Pbf.Fixed32);
70355 this.writeFixed32(val);
70357 writeSFixed32Field: function writeSFixed32Field(tag, val) {
70358 this.writeTag(tag, Pbf.Fixed32);
70359 this.writeSFixed32(val);
70361 writeFixed64Field: function writeFixed64Field(tag, val) {
70362 this.writeTag(tag, Pbf.Fixed64);
70363 this.writeFixed64(val);
70365 writeSFixed64Field: function writeSFixed64Field(tag, val) {
70366 this.writeTag(tag, Pbf.Fixed64);
70367 this.writeSFixed64(val);
70369 writeVarintField: function writeVarintField(tag, val) {
70370 this.writeTag(tag, Pbf.Varint);
70371 this.writeVarint(val);
70373 writeSVarintField: function writeSVarintField(tag, val) {
70374 this.writeTag(tag, Pbf.Varint);
70375 this.writeSVarint(val);
70377 writeStringField: function writeStringField(tag, str) {
70378 this.writeTag(tag, Pbf.Bytes);
70379 this.writeString(str);
70381 writeFloatField: function writeFloatField(tag, val) {
70382 this.writeTag(tag, Pbf.Fixed32);
70383 this.writeFloat(val);
70385 writeDoubleField: function writeDoubleField(tag, val) {
70386 this.writeTag(tag, Pbf.Fixed64);
70387 this.writeDouble(val);
70389 writeBooleanField: function writeBooleanField(tag, val) {
70390 this.writeVarintField(tag, Boolean(val));
70394 function readVarintRemainder(l, s, p) {
70399 h = (b & 0x70) >> 4;
70400 if (b < 0x80) return toNum(l, h, s);
70402 h |= (b & 0x7f) << 3;
70403 if (b < 0x80) return toNum(l, h, s);
70405 h |= (b & 0x7f) << 10;
70406 if (b < 0x80) return toNum(l, h, s);
70408 h |= (b & 0x7f) << 17;
70409 if (b < 0x80) return toNum(l, h, s);
70411 h |= (b & 0x7f) << 24;
70412 if (b < 0x80) return toNum(l, h, s);
70414 h |= (b & 0x01) << 31;
70415 if (b < 0x80) return toNum(l, h, s);
70416 throw new Error('Expected varint not more than 10 bytes');
70419 function readPackedEnd(pbf) {
70420 return pbf.type === Pbf.Bytes ? pbf.readVarint() + pbf.pos : pbf.pos + 1;
70423 function toNum(low, high, isSigned) {
70425 return high * 0x100000000 + (low >>> 0);
70428 return (high >>> 0) * 0x100000000 + (low >>> 0);
70431 function writeBigVarint(val, pbf) {
70435 low = val % 0x100000000 | 0;
70436 high = val / 0x100000000 | 0;
70438 low = ~(-val % 0x100000000);
70439 high = ~(-val / 0x100000000);
70441 if (low ^ 0xffffffff) {
70445 high = high + 1 | 0;
70449 if (val >= 0x10000000000000000 || val < -0x10000000000000000) {
70450 throw new Error('Given varint doesn\'t fit into 10 bytes');
70454 writeBigVarintLow(low, high, pbf);
70455 writeBigVarintHigh(high, pbf);
70458 function writeBigVarintLow(low, high, pbf) {
70459 pbf.buf[pbf.pos++] = low & 0x7f | 0x80;
70461 pbf.buf[pbf.pos++] = low & 0x7f | 0x80;
70463 pbf.buf[pbf.pos++] = low & 0x7f | 0x80;
70465 pbf.buf[pbf.pos++] = low & 0x7f | 0x80;
70467 pbf.buf[pbf.pos] = low & 0x7f;
70470 function writeBigVarintHigh(high, pbf) {
70471 var lsb = (high & 0x07) << 4;
70472 pbf.buf[pbf.pos++] |= lsb | ((high >>>= 3) ? 0x80 : 0);
70474 pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);
70476 pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);
70478 pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);
70480 pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);
70482 pbf.buf[pbf.pos++] = high & 0x7f;
70485 function makeRoomForExtraLength(startPos, len, pbf) {
70486 var extraLen = len <= 0x3fff ? 1 : len <= 0x1fffff ? 2 : len <= 0xfffffff ? 3 : Math.floor(Math.log(len) / (Math.LN2 * 7)); // if 1 byte isn't enough for encoding message length, shift the data to the right
70488 pbf.realloc(extraLen);
70490 for (var i = pbf.pos - 1; i >= startPos; i--) {
70491 pbf.buf[i + extraLen] = pbf.buf[i];
70495 function _writePackedVarint(arr, pbf) {
70496 for (var i = 0; i < arr.length; i++) {
70497 pbf.writeVarint(arr[i]);
70501 function _writePackedSVarint(arr, pbf) {
70502 for (var i = 0; i < arr.length; i++) {
70503 pbf.writeSVarint(arr[i]);
70507 function _writePackedFloat(arr, pbf) {
70508 for (var i = 0; i < arr.length; i++) {
70509 pbf.writeFloat(arr[i]);
70513 function _writePackedDouble(arr, pbf) {
70514 for (var i = 0; i < arr.length; i++) {
70515 pbf.writeDouble(arr[i]);
70519 function _writePackedBoolean(arr, pbf) {
70520 for (var i = 0; i < arr.length; i++) {
70521 pbf.writeBoolean(arr[i]);
70525 function _writePackedFixed(arr, pbf) {
70526 for (var i = 0; i < arr.length; i++) {
70527 pbf.writeFixed32(arr[i]);
70531 function _writePackedSFixed(arr, pbf) {
70532 for (var i = 0; i < arr.length; i++) {
70533 pbf.writeSFixed32(arr[i]);
70537 function _writePackedFixed2(arr, pbf) {
70538 for (var i = 0; i < arr.length; i++) {
70539 pbf.writeFixed64(arr[i]);
70543 function _writePackedSFixed2(arr, pbf) {
70544 for (var i = 0; i < arr.length; i++) {
70545 pbf.writeSFixed64(arr[i]);
70547 } // Buffer code below from https://github.com/feross/buffer, MIT-licensed
70550 function readUInt32(buf, pos) {
70551 return (buf[pos] | buf[pos + 1] << 8 | buf[pos + 2] << 16) + buf[pos + 3] * 0x1000000;
70554 function writeInt32(buf, val, pos) {
70556 buf[pos + 1] = val >>> 8;
70557 buf[pos + 2] = val >>> 16;
70558 buf[pos + 3] = val >>> 24;
70561 function readInt32(buf, pos) {
70562 return (buf[pos] | buf[pos + 1] << 8 | buf[pos + 2] << 16) + (buf[pos + 3] << 24);
70565 function readUtf8(buf, pos, end) {
70571 var c = null; // codepoint
70573 var bytesPerSequence = b0 > 0xEF ? 4 : b0 > 0xDF ? 3 : b0 > 0xBF ? 2 : 1;
70574 if (i + bytesPerSequence > end) break;
70577 if (bytesPerSequence === 1) {
70581 } else if (bytesPerSequence === 2) {
70584 if ((b1 & 0xC0) === 0x80) {
70585 c = (b0 & 0x1F) << 0x6 | b1 & 0x3F;
70591 } else if (bytesPerSequence === 3) {
70595 if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80) {
70596 c = (b0 & 0xF) << 0xC | (b1 & 0x3F) << 0x6 | b2 & 0x3F;
70598 if (c <= 0x7FF || c >= 0xD800 && c <= 0xDFFF) {
70602 } else if (bytesPerSequence === 4) {
70607 if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {
70608 c = (b0 & 0xF) << 0x12 | (b1 & 0x3F) << 0xC | (b2 & 0x3F) << 0x6 | b3 & 0x3F;
70610 if (c <= 0xFFFF || c >= 0x110000) {
70618 bytesPerSequence = 1;
70619 } else if (c > 0xFFFF) {
70621 str += String.fromCharCode(c >>> 10 & 0x3FF | 0xD800);
70622 c = 0xDC00 | c & 0x3FF;
70625 str += String.fromCharCode(c);
70626 i += bytesPerSequence;
70632 function readUtf8TextDecoder(buf, pos, end) {
70633 return utf8TextDecoder.decode(buf.subarray(pos, end));
70636 function writeUtf8(buf, str, pos) {
70637 for (var i = 0, c, lead; i < str.length; i++) {
70638 c = str.charCodeAt(i); // code point
70640 if (c > 0xD7FF && c < 0xE000) {
70649 c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000;
70653 if (c > 0xDBFF || i + 1 === str.length) {
70674 buf[pos++] = c >> 0x6 | 0xC0;
70677 buf[pos++] = c >> 0xC | 0xE0;
70679 buf[pos++] = c >> 0x12 | 0xF0;
70680 buf[pos++] = c >> 0xC & 0x3F | 0x80;
70683 buf[pos++] = c >> 0x6 & 0x3F | 0x80;
70686 buf[pos++] = c & 0x3F | 0x80;
70693 var vectorTile = {};
70695 var pointGeometry = Point$1;
70697 * A standalone point geometry with useful accessor, comparison, and
70698 * modification methods.
70701 * @param {Number} x the x-coordinate. this could be longitude or screen
70702 * pixels, or any other sort of unit.
70703 * @param {Number} y the y-coordinate. this could be latitude or screen
70704 * pixels, or any other sort of unit.
70706 * var point = new Point(-77, 38);
70709 function Point$1(x, y) {
70714 Point$1.prototype = {
70716 * Clone this point, returning a new point that can be modified
70717 * without affecting the old one.
70718 * @return {Point} the clone
70720 clone: function clone() {
70721 return new Point$1(this.x, this.y);
70725 * Add this point's x & y coordinates to another point,
70726 * yielding a new point.
70727 * @param {Point} p the other point
70728 * @return {Point} output point
70730 add: function add(p) {
70731 return this.clone()._add(p);
70735 * Subtract this point's x & y coordinates to from point,
70736 * yielding a new point.
70737 * @param {Point} p the other point
70738 * @return {Point} output point
70740 sub: function sub(p) {
70741 return this.clone()._sub(p);
70745 * Multiply this point's x & y coordinates by point,
70746 * yielding a new point.
70747 * @param {Point} p the other point
70748 * @return {Point} output point
70750 multByPoint: function multByPoint(p) {
70751 return this.clone()._multByPoint(p);
70755 * Divide this point's x & y coordinates by point,
70756 * yielding a new point.
70757 * @param {Point} p the other point
70758 * @return {Point} output point
70760 divByPoint: function divByPoint(p) {
70761 return this.clone()._divByPoint(p);
70765 * Multiply this point's x & y coordinates by a factor,
70766 * yielding a new point.
70767 * @param {Point} k factor
70768 * @return {Point} output point
70770 mult: function mult(k) {
70771 return this.clone()._mult(k);
70775 * Divide this point's x & y coordinates by a factor,
70776 * yielding a new point.
70777 * @param {Point} k factor
70778 * @return {Point} output point
70780 div: function div(k) {
70781 return this.clone()._div(k);
70785 * Rotate this point around the 0, 0 origin by an angle a,
70787 * @param {Number} a angle to rotate around, in radians
70788 * @return {Point} output point
70790 rotate: function rotate(a) {
70791 return this.clone()._rotate(a);
70795 * Rotate this point around p point by an angle a,
70797 * @param {Number} a angle to rotate around, in radians
70798 * @param {Point} p Point to rotate around
70799 * @return {Point} output point
70801 rotateAround: function rotateAround(a, p) {
70802 return this.clone()._rotateAround(a, p);
70806 * Multiply this point by a 4x1 transformation matrix
70807 * @param {Array<Number>} m transformation matrix
70808 * @return {Point} output point
70810 matMult: function matMult(m) {
70811 return this.clone()._matMult(m);
70815 * Calculate this point but as a unit vector from 0, 0, meaning
70816 * that the distance from the resulting point to the 0, 0
70817 * coordinate will be equal to 1 and the angle from the resulting
70818 * point to the 0, 0 coordinate will be the same as before.
70819 * @return {Point} unit vector point
70821 unit: function unit() {
70822 return this.clone()._unit();
70826 * Compute a perpendicular point, where the new y coordinate
70827 * is the old x coordinate and the new x coordinate is the old y
70828 * coordinate multiplied by -1
70829 * @return {Point} perpendicular point
70831 perp: function perp() {
70832 return this.clone()._perp();
70836 * Return a version of this point with the x & y coordinates
70837 * rounded to integers.
70838 * @return {Point} rounded point
70840 round: function round() {
70841 return this.clone()._round();
70845 * Return the magitude of this point: this is the Euclidean
70846 * distance from the 0, 0 coordinate to this point's x and y
70848 * @return {Number} magnitude
70850 mag: function mag() {
70851 return Math.sqrt(this.x * this.x + this.y * this.y);
70855 * Judge whether this point is equal to another point, returning
70857 * @param {Point} other the other point
70858 * @return {boolean} whether the points are equal
70860 equals: function equals(other) {
70861 return this.x === other.x && this.y === other.y;
70865 * Calculate the distance from this point to another point
70866 * @param {Point} p the other point
70867 * @return {Number} distance
70869 dist: function dist(p) {
70870 return Math.sqrt(this.distSqr(p));
70874 * Calculate the distance from this point to another point,
70875 * without the square root step. Useful if you're comparing
70876 * relative distances.
70877 * @param {Point} p the other point
70878 * @return {Number} distance
70880 distSqr: function distSqr(p) {
70881 var dx = p.x - this.x,
70883 return dx * dx + dy * dy;
70887 * Get the angle from the 0, 0 coordinate to this point, in radians
70889 * @return {Number} angle
70891 angle: function angle() {
70892 return Math.atan2(this.y, this.x);
70896 * Get the angle from this point to another point, in radians
70897 * @param {Point} b the other point
70898 * @return {Number} angle
70900 angleTo: function angleTo(b) {
70901 return Math.atan2(this.y - b.y, this.x - b.x);
70905 * Get the angle between this point and another point, in radians
70906 * @param {Point} b the other point
70907 * @return {Number} angle
70909 angleWith: function angleWith(b) {
70910 return this.angleWithSep(b.x, b.y);
70914 * Find the angle of the two vectors, solving the formula for
70915 * the cross product a x b = |a||b|sin(θ) for θ.
70916 * @param {Number} x the x-coordinate
70917 * @param {Number} y the y-coordinate
70918 * @return {Number} the angle in radians
70920 angleWithSep: function angleWithSep(x, y) {
70921 return Math.atan2(this.x * y - this.y * x, this.x * x + this.y * y);
70923 _matMult: function _matMult(m) {
70924 var x = m[0] * this.x + m[1] * this.y,
70925 y = m[2] * this.x + m[3] * this.y;
70930 _add: function _add(p) {
70935 _sub: function _sub(p) {
70940 _mult: function _mult(k) {
70945 _div: function _div(k) {
70950 _multByPoint: function _multByPoint(p) {
70955 _divByPoint: function _divByPoint(p) {
70960 _unit: function _unit() {
70961 this._div(this.mag());
70965 _perp: function _perp() {
70971 _rotate: function _rotate(angle) {
70972 var cos = Math.cos(angle),
70973 sin = Math.sin(angle),
70974 x = cos * this.x - sin * this.y,
70975 y = sin * this.x + cos * this.y;
70980 _rotateAround: function _rotateAround(angle, p) {
70981 var cos = Math.cos(angle),
70982 sin = Math.sin(angle),
70983 x = p.x + cos * (this.x - p.x) - sin * (this.y - p.y),
70984 y = p.y + sin * (this.x - p.x) + cos * (this.y - p.y);
70989 _round: function _round() {
70990 this.x = Math.round(this.x);
70991 this.y = Math.round(this.y);
70996 * Construct a point from an array if necessary, otherwise if the input
70997 * is already a Point, or an unknown type, return it unchanged
70998 * @param {Array<Number>|Point|*} a any kind of input value
70999 * @return {Point} constructed point, or passed-through value.
71002 * var point = Point.convert([0, 1]);
71003 * // is equivalent to
71004 * var point = new Point(0, 1);
71007 Point$1.convert = function (a) {
71008 if (a instanceof Point$1) {
71012 if (Array.isArray(a)) {
71013 return new Point$1(a[0], a[1]);
71019 var Point = pointGeometry;
71020 var vectortilefeature = VectorTileFeature$1;
71022 function VectorTileFeature$1(pbf, end, extent, keys, values) {
71024 this.properties = {};
71025 this.extent = extent;
71026 this.type = 0; // Private
71029 this._geometry = -1;
71031 this._values = values;
71032 pbf.readFields(readFeature, this, end);
71035 function readFeature(tag, feature, pbf) {
71036 if (tag == 1) feature.id = pbf.readVarint();else if (tag == 2) readTag(pbf, feature);else if (tag == 3) feature.type = pbf.readVarint();else if (tag == 4) feature._geometry = pbf.pos;
71039 function readTag(pbf, feature) {
71040 var end = pbf.readVarint() + pbf.pos;
71042 while (pbf.pos < end) {
71043 var key = feature._keys[pbf.readVarint()],
71044 value = feature._values[pbf.readVarint()];
71046 feature.properties[key] = value;
71050 VectorTileFeature$1.types = ['Unknown', 'Point', 'LineString', 'Polygon'];
71052 VectorTileFeature$1.prototype.loadGeometry = function () {
71053 var pbf = this._pbf;
71054 pbf.pos = this._geometry;
71055 var end = pbf.readVarint() + pbf.pos,
71063 while (pbf.pos < end) {
71065 var cmdLen = pbf.readVarint();
71066 cmd = cmdLen & 0x7;
71067 length = cmdLen >> 3;
71072 if (cmd === 1 || cmd === 2) {
71073 x += pbf.readSVarint();
71074 y += pbf.readSVarint();
71078 if (line) lines.push(line);
71082 line.push(new Point(x, y));
71083 } else if (cmd === 7) {
71084 // Workaround for https://github.com/mapbox/mapnik-vector-tile/issues/90
71086 line.push(line[0].clone()); // closePolygon
71089 throw new Error('unknown command ' + cmd);
71093 if (line) lines.push(line);
71097 VectorTileFeature$1.prototype.bbox = function () {
71098 var pbf = this._pbf;
71099 pbf.pos = this._geometry;
71100 var end = pbf.readVarint() + pbf.pos,
71110 while (pbf.pos < end) {
71112 var cmdLen = pbf.readVarint();
71113 cmd = cmdLen & 0x7;
71114 length = cmdLen >> 3;
71119 if (cmd === 1 || cmd === 2) {
71120 x += pbf.readSVarint();
71121 y += pbf.readSVarint();
71122 if (x < x1) x1 = x;
71123 if (x > x2) x2 = x;
71124 if (y < y1) y1 = y;
71125 if (y > y2) y2 = y;
71126 } else if (cmd !== 7) {
71127 throw new Error('unknown command ' + cmd);
71131 return [x1, y1, x2, y2];
71134 VectorTileFeature$1.prototype.toGeoJSON = function (x, y, z) {
71135 var size = this.extent * Math.pow(2, z),
71136 x0 = this.extent * x,
71137 y0 = this.extent * y,
71138 coords = this.loadGeometry(),
71139 type = VectorTileFeature$1.types[this.type],
71143 function project(line) {
71144 for (var j = 0; j < line.length; j++) {
71146 y2 = 180 - (p.y + y0) * 360 / size;
71147 line[j] = [(p.x + x0) * 360 / size - 180, 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90];
71151 switch (this.type) {
71155 for (i = 0; i < coords.length; i++) {
71156 points[i] = coords[i][0];
71164 for (i = 0; i < coords.length; i++) {
71165 project(coords[i]);
71171 coords = classifyRings(coords);
71173 for (i = 0; i < coords.length; i++) {
71174 for (j = 0; j < coords[i].length; j++) {
71175 project(coords[i][j]);
71182 if (coords.length === 1) {
71183 coords = coords[0];
71185 type = 'Multi' + type;
71192 coordinates: coords
71194 properties: this.properties
71197 if ('id' in this) {
71198 result.id = this.id;
71202 }; // classifies an array of rings into polygons with outer rings and holes
71205 function classifyRings(rings) {
71206 var len = rings.length;
71207 if (len <= 1) return [rings];
71212 for (var i = 0; i < len; i++) {
71213 var area = signedArea(rings[i]);
71214 if (area === 0) continue;
71215 if (ccw === undefined) ccw = area < 0;
71217 if (ccw === area < 0) {
71218 if (polygon) polygons.push(polygon);
71219 polygon = [rings[i]];
71221 polygon.push(rings[i]);
71225 if (polygon) polygons.push(polygon);
71229 function signedArea(ring) {
71232 for (var i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
71235 sum += (p2.x - p1.x) * (p1.y + p2.y);
71241 var VectorTileFeature = vectortilefeature;
71242 var vectortilelayer = VectorTileLayer$1;
71244 function VectorTileLayer$1(pbf, end) {
71248 this.extent = 4096;
71249 this.length = 0; // Private
71254 this._features = [];
71255 pbf.readFields(readLayer, this, end);
71256 this.length = this._features.length;
71259 function readLayer(tag, layer, pbf) {
71260 if (tag === 15) layer.version = pbf.readVarint();else if (tag === 1) layer.name = pbf.readString();else if (tag === 5) layer.extent = pbf.readVarint();else if (tag === 2) layer._features.push(pbf.pos);else if (tag === 3) layer._keys.push(pbf.readString());else if (tag === 4) layer._values.push(readValueMessage(pbf));
71263 function readValueMessage(pbf) {
71265 end = pbf.readVarint() + pbf.pos;
71267 while (pbf.pos < end) {
71268 var tag = pbf.readVarint() >> 3;
71269 value = tag === 1 ? pbf.readString() : tag === 2 ? pbf.readFloat() : tag === 3 ? pbf.readDouble() : tag === 4 ? pbf.readVarint64() : tag === 5 ? pbf.readVarint() : tag === 6 ? pbf.readSVarint() : tag === 7 ? pbf.readBoolean() : null;
71273 } // return feature `i` from this layer as a `VectorTileFeature`
71276 VectorTileLayer$1.prototype.feature = function (i) {
71277 if (i < 0 || i >= this._features.length) throw new Error('feature index out of bounds');
71278 this._pbf.pos = this._features[i];
71280 var end = this._pbf.readVarint() + this._pbf.pos;
71282 return new VectorTileFeature(this._pbf, end, this.extent, this._keys, this._values);
71285 var VectorTileLayer = vectortilelayer;
71286 var vectortile = VectorTile$1;
71288 function VectorTile$1(pbf, end) {
71289 this.layers = pbf.readFields(readTile, {}, end);
71292 function readTile(tag, layers, pbf) {
71294 var layer = new VectorTileLayer(pbf, pbf.readVarint() + pbf.pos);
71295 if (layer.length) layers[layer.name] = layer;
71299 var VectorTile = vectorTile.VectorTile = vectortile;
71300 vectorTile.VectorTileFeature = vectortilefeature;
71301 vectorTile.VectorTileLayer = vectortilelayer;
71303 var accessToken = 'MLY|4100327730013843|5bb78b81720791946a9a7b956c57b7cf';
71304 var apiUrl = 'https://graph.mapillary.com/';
71305 var baseTileUrl = 'https://tiles.mapillary.com/maps/vtp';
71306 var mapFeatureTileUrl = "".concat(baseTileUrl, "/mly_map_feature_point/2/{z}/{x}/{y}?access_token=").concat(accessToken);
71307 var tileUrl = "".concat(baseTileUrl, "/mly1_public/2/{z}/{x}/{y}?access_token=").concat(accessToken);
71308 var trafficSignTileUrl = "".concat(baseTileUrl, "/mly_map_feature_traffic_sign/2/{z}/{x}/{y}?access_token=").concat(accessToken);
71309 var viewercss = 'mapillary-js/mapillary.css';
71310 var viewerjs = 'mapillary-js/mapillary.js';
71311 var minZoom$1 = 14;
71312 var dispatch$4 = dispatch$8('change', 'loadedImages', 'loadedSigns', 'loadedMapFeatures', 'bearingChanged', 'imageChanged');
71314 var _loadViewerPromise$2;
71316 var _mlyActiveImage;
71320 var _mlyFallback = false;
71322 var _mlyHighlightedDetection;
71324 var _mlyShowFeatureDetections = false;
71325 var _mlyShowSignDetections = false;
71329 var _mlyViewerFilter = ['all']; // Load all data for the specified type from Mapillary vector tiles
71331 function loadTiles$2(which, url, maxZoom, projection) {
71332 var tiler = utilTiler().zoomExtent([minZoom$1, maxZoom]).skipNullIsland(true);
71333 var tiles = tiler.getTiles(projection);
71334 tiles.forEach(function (tile) {
71335 loadTile$1(which, url, tile);
71337 } // Load all data for the specified type from one vector tile
71340 function loadTile$1(which, url, tile) {
71341 var cache = _mlyCache.requests;
71342 var tileId = "".concat(tile.id, "-").concat(which);
71343 if (cache.loaded[tileId] || cache.inflight[tileId]) return;
71344 var controller = new AbortController();
71345 cache.inflight[tileId] = controller;
71346 var requestUrl = url.replace('{x}', tile.xyz[0]).replace('{y}', tile.xyz[1]).replace('{z}', tile.xyz[2]);
71347 fetch(requestUrl, {
71348 signal: controller.signal
71349 }).then(function (response) {
71350 if (!response.ok) {
71351 throw new Error(response.status + ' ' + response.statusText);
71354 cache.loaded[tileId] = true;
71355 delete cache.inflight[tileId];
71356 return response.arrayBuffer();
71357 }).then(function (data) {
71359 throw new Error('No Data');
71362 loadTileDataToCache(data, tile, which);
71364 if (which === 'images') {
71365 dispatch$4.call('loadedImages');
71366 } else if (which === 'signs') {
71367 dispatch$4.call('loadedSigns');
71368 } else if (which === 'points') {
71369 dispatch$4.call('loadedMapFeatures');
71371 })["catch"](function () {
71372 cache.loaded[tileId] = true;
71373 delete cache.inflight[tileId];
71375 } // Load the data from the vector tile into cache
71378 function loadTileDataToCache(data, tile, which) {
71379 var vectorTile = new VectorTile(new pbf(data));
71380 var features, cache, layer, i, feature, loc, d;
71382 if (vectorTile.layers.hasOwnProperty('image')) {
71384 cache = _mlyCache.images;
71385 layer = vectorTile.layers.image;
71387 for (i = 0; i < layer.length; i++) {
71388 feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
71389 loc = feature.geometry.coordinates;
71392 captured_at: feature.properties.captured_at,
71393 ca: feature.properties.compass_angle,
71394 id: feature.properties.id,
71395 is_pano: feature.properties.is_pano,
71396 sequence_id: feature.properties.sequence_id
71398 cache.forImageId[d.id] = d;
71409 cache.rtree.load(features);
71413 if (vectorTile.layers.hasOwnProperty('sequence')) {
71415 cache = _mlyCache.sequences;
71416 layer = vectorTile.layers.sequence;
71418 for (i = 0; i < layer.length; i++) {
71419 feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
71421 if (cache.lineString[feature.properties.id]) {
71422 cache.lineString[feature.properties.id].push(feature);
71424 cache.lineString[feature.properties.id] = [feature];
71429 if (vectorTile.layers.hasOwnProperty('point')) {
71431 cache = _mlyCache[which];
71432 layer = vectorTile.layers.point;
71434 for (i = 0; i < layer.length; i++) {
71435 feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
71436 loc = feature.geometry.coordinates;
71439 id: feature.properties.id,
71440 first_seen_at: feature.properties.first_seen_at,
71441 last_seen_at: feature.properties.last_seen_at,
71442 value: feature.properties.value
71454 cache.rtree.load(features);
71458 if (vectorTile.layers.hasOwnProperty('traffic_sign')) {
71460 cache = _mlyCache[which];
71461 layer = vectorTile.layers.traffic_sign;
71463 for (i = 0; i < layer.length; i++) {
71464 feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
71465 loc = feature.geometry.coordinates;
71468 id: feature.properties.id,
71469 first_seen_at: feature.properties.first_seen_at,
71470 last_seen_at: feature.properties.last_seen_at,
71471 value: feature.properties.value
71483 cache.rtree.load(features);
71486 } // Get data from the API
71489 function loadData(url) {
71490 return fetch(url).then(function (response) {
71491 if (!response.ok) {
71492 throw new Error(response.status + ' ' + response.statusText);
71495 return response.json();
71496 }).then(function (result) {
71501 return result.data || [];
71503 } // Partition viewport into higher zoom tiles
71506 function partitionViewport$2(projection) {
71507 var z = geoScaleToZoom(projection.scale());
71508 var z2 = Math.ceil(z * 2) / 2 + 2.5; // round to next 0.5 and add 2.5
71510 var tiler = utilTiler().zoomExtent([z2, z2]);
71511 return tiler.getTiles(projection).map(function (tile) {
71512 return tile.extent;
71514 } // Return no more than `limit` results per partition.
71517 function searchLimited$2(limit, projection, rtree) {
71518 limit = limit || 5;
71519 return partitionViewport$2(projection).reduce(function (result, extent) {
71520 var found = rtree.search(extent.bbox()).slice(0, limit).map(function (d) {
71523 return found.length ? result.concat(found) : result;
71527 var serviceMapillary = {
71528 // Initialize Mapillary
71529 init: function init() {
71534 this.event = utilRebind(this, dispatch$4, 'on');
71536 // Reset cache and state
71537 reset: function reset() {
71539 Object.values(_mlyCache.requests.inflight).forEach(function (request) {
71546 rtree: new RBush(),
71549 image_detections: {
71559 rtree: new RBush(),
71567 _mlyActiveImage = null;
71569 // Get visible images
71570 images: function images(projection) {
71572 return searchLimited$2(limit, projection, _mlyCache.images.rtree);
71574 // Get visible traffic signs
71575 signs: function signs(projection) {
71577 return searchLimited$2(limit, projection, _mlyCache.signs.rtree);
71579 // Get visible map (point) features
71580 mapFeatures: function mapFeatures(projection) {
71582 return searchLimited$2(limit, projection, _mlyCache.points.rtree);
71584 // Get cached image by id
71585 cachedImage: function cachedImage(imageId) {
71586 return _mlyCache.images.forImageId[imageId];
71588 // Get visible sequences
71589 sequences: function sequences(projection) {
71590 var viewport = projection.clipExtent();
71591 var min = [viewport[0][0], viewport[1][1]];
71592 var max = [viewport[1][0], viewport[0][1]];
71593 var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
71594 var sequenceIds = {};
71595 var lineStrings = [];
71597 _mlyCache.images.rtree.search(bbox).forEach(function (d) {
71598 if (d.data.sequence_id) {
71599 sequenceIds[d.data.sequence_id] = true;
71603 Object.keys(sequenceIds).forEach(function (sequenceId) {
71604 if (_mlyCache.sequences.lineString[sequenceId]) {
71605 lineStrings = lineStrings.concat(_mlyCache.sequences.lineString[sequenceId]);
71608 return lineStrings;
71610 // Load images in the visible area
71611 loadImages: function loadImages(projection) {
71612 loadTiles$2('images', tileUrl, 14, projection);
71614 // Load traffic signs in the visible area
71615 loadSigns: function loadSigns(projection) {
71616 loadTiles$2('signs', trafficSignTileUrl, 14, projection);
71618 // Load map (point) features in the visible area
71619 loadMapFeatures: function loadMapFeatures(projection) {
71620 loadTiles$2('points', mapFeatureTileUrl, 14, projection);
71622 // Return a promise that resolves when the image viewer (Mapillary JS) library has finished loading
71623 ensureViewerLoaded: function ensureViewerLoaded(context) {
71624 if (_loadViewerPromise$2) return _loadViewerPromise$2; // add mly-wrapper
71626 var wrap = context.container().select('.photoviewer').selectAll('.mly-wrapper').data([0]);
71627 wrap.enter().append('div').attr('id', 'ideditor-mly').attr('class', 'photo-wrapper mly-wrapper').classed('hide', true);
71629 _loadViewerPromise$2 = new Promise(function (resolve, reject) {
71630 var loadedCount = 0;
71632 function loaded() {
71633 loadedCount += 1; // wait until both files are loaded
71635 if (loadedCount === 2) resolve();
71638 var head = select('head'); // load mapillary-viewercss
71640 head.selectAll('#ideditor-mapillary-viewercss').data([0]).enter().append('link').attr('id', 'ideditor-mapillary-viewercss').attr('rel', 'stylesheet').attr('crossorigin', 'anonymous').attr('href', context.asset(viewercss)).on('load.serviceMapillary', loaded).on('error.serviceMapillary', function () {
71642 }); // load mapillary-viewerjs
71644 head.selectAll('#ideditor-mapillary-viewerjs').data([0]).enter().append('script').attr('id', 'ideditor-mapillary-viewerjs').attr('crossorigin', 'anonymous').attr('src', context.asset(viewerjs)).on('load.serviceMapillary', loaded).on('error.serviceMapillary', function () {
71647 })["catch"](function () {
71648 _loadViewerPromise$2 = null;
71649 }).then(function () {
71650 that.initViewer(context);
71652 return _loadViewerPromise$2;
71654 // Load traffic sign image sprites
71655 loadSignResources: function loadSignResources(context) {
71656 context.ui().svgDefs.addSprites(['mapillary-sprite'], false
71657 /* don't override colors */
71661 // Load map (point) feature image sprites
71662 loadObjectResources: function loadObjectResources(context) {
71663 context.ui().svgDefs.addSprites(['mapillary-object-sprite'], false
71664 /* don't override colors */
71668 // Remove previous detections in image viewer
71669 resetTags: function resetTags() {
71670 if (_mlyViewer && !_mlyFallback) {
71671 _mlyViewer.getComponent('tag').removeAll();
71674 // Show map feature detections in image viewer
71675 showFeatureDetections: function showFeatureDetections(value) {
71676 _mlyShowFeatureDetections = value;
71678 if (!_mlyShowFeatureDetections && !_mlyShowSignDetections) {
71682 // Show traffic sign detections in image viewer
71683 showSignDetections: function showSignDetections(value) {
71684 _mlyShowSignDetections = value;
71686 if (!_mlyShowFeatureDetections && !_mlyShowSignDetections) {
71690 // Apply filter to image viewer
71691 filterViewer: function filterViewer(context) {
71692 var showsPano = context.photos().showsPanoramic();
71693 var showsFlat = context.photos().showsFlat();
71694 var fromDate = context.photos().fromDate();
71695 var toDate = context.photos().toDate();
71696 var filter = ['all'];
71697 if (!showsPano) filter.push(['!=', 'cameraType', 'spherical']);
71698 if (!showsFlat && showsPano) filter.push(['==', 'pano', true]);
71701 filter.push(['>=', 'capturedAt', new Date(fromDate).getTime()]);
71705 filter.push(['>=', 'capturedAt', new Date(toDate).getTime()]);
71709 _mlyViewer.setFilter(filter);
71712 _mlyViewerFilter = filter;
71715 // Make the image viewer visible
71716 showViewer: function showViewer(context) {
71717 var wrap = context.container().select('.photoviewer').classed('hide', false);
71718 var isHidden = wrap.selectAll('.photo-wrapper.mly-wrapper.hide').size();
71720 if (isHidden && _mlyViewer) {
71721 wrap.selectAll('.photo-wrapper:not(.mly-wrapper)').classed('hide', true);
71722 wrap.selectAll('.photo-wrapper.mly-wrapper').classed('hide', false);
71724 _mlyViewer.resize();
71729 // Hide the image viewer and resets map markers
71730 hideViewer: function hideViewer(context) {
71731 _mlyActiveImage = null;
71733 if (!_mlyFallback && _mlyViewer) {
71734 _mlyViewer.getComponent('sequence').stop();
71737 var viewer = context.container().select('.photoviewer');
71738 if (!viewer.empty()) viewer.datum(null);
71739 viewer.classed('hide', true).selectAll('.photo-wrapper').classed('hide', true);
71740 this.updateUrlImage(null);
71741 dispatch$4.call('imageChanged');
71742 dispatch$4.call('loadedMapFeatures');
71743 dispatch$4.call('loadedSigns');
71744 return this.setStyles(context, null);
71746 // Update the URL with current image id
71747 updateUrlImage: function updateUrlImage(imageId) {
71748 if (!window.mocha) {
71749 var hash = utilStringQs(window.location.hash);
71752 hash.photo = 'mapillary/' + imageId;
71757 window.location.replace('#' + utilQsString(hash, true));
71760 // Highlight the detection in the viewer that is related to the clicked map feature
71761 highlightDetection: function highlightDetection(detection) {
71763 _mlyHighlightedDetection = detection.id;
71768 // Initialize image viewer (Mapillar JS)
71769 initViewer: function initViewer(context) {
71771 if (!window.mapillary) return;
71773 accessToken: accessToken,
71779 container: 'ideditor-mly'
71780 }; // Disable components requiring WebGL support
71782 if (!mapillary.isSupported() && mapillary.isFallbackSupported()) {
71783 _mlyFallback = true;
71794 navigation: true // fallback
71799 _mlyViewer = new mapillary.Viewer(opts);
71801 _mlyViewer.on('image', imageChanged);
71803 _mlyViewer.on('bearing', bearingChanged);
71805 if (_mlyViewerFilter) {
71806 _mlyViewer.setFilter(_mlyViewerFilter);
71807 } // Register viewer resize handler
71810 context.ui().photoviewer.on('resize.mapillary', function () {
71811 if (_mlyViewer) _mlyViewer.resize();
71812 }); // imageChanged: called after the viewer has changed images and is ready.
71814 function imageChanged(node) {
71816 var image = node.image;
71817 that.setActiveImage(image);
71818 that.setStyles(context, null);
71819 var loc = [image.originalLngLat.lng, image.originalLngLat.lat];
71820 context.map().centerEase(loc);
71821 that.updateUrlImage(image.id);
71823 if (_mlyShowFeatureDetections || _mlyShowSignDetections) {
71824 that.updateDetections(image.id, "".concat(apiUrl, "/").concat(image.id, "/detections?access_token=").concat(accessToken, "&fields=id,image,geometry,value"));
71827 dispatch$4.call('imageChanged');
71828 } // bearingChanged: called when the bearing changes in the image viewer.
71831 function bearingChanged(e) {
71832 dispatch$4.call('bearingChanged', undefined, e);
71835 // Move to an image
71836 selectImage: function selectImage(context, imageId) {
71837 if (_mlyViewer && imageId) {
71838 _mlyViewer.moveTo(imageId)["catch"](function (e) {
71839 console.error('mly3', e); // eslint-disable-line no-console
71845 // Return the currently displayed image
71846 getActiveImage: function getActiveImage() {
71847 return _mlyActiveImage;
71849 // Return a list of detection objects for the given id
71850 getDetections: function getDetections(id) {
71851 return loadData("".concat(apiUrl, "/").concat(id, "/detections?access_token=").concat(accessToken, "&fields=id,value,image"));
71853 // Set the currently visible image
71854 setActiveImage: function setActiveImage(image) {
71856 _mlyActiveImage = {
71857 ca: image.originalCompassAngle,
71859 loc: [image.originalLngLat.lng, image.originalLngLat.lat],
71860 is_pano: image.cameraType === 'spherical',
71861 sequence_id: image.sequenceId
71864 _mlyActiveImage = null;
71867 // Update the currently highlighted sequence and selected bubble.
71868 setStyles: function setStyles(context, hovered) {
71869 var hoveredImageId = hovered && hovered.id;
71870 var hoveredSequenceId = hovered && hovered.sequence_id;
71871 var selectedSequenceId = _mlyActiveImage && _mlyActiveImage.sequence_id;
71872 context.container().selectAll('.layer-mapillary .viewfield-group').classed('highlighted', function (d) {
71873 return d.sequence_id === selectedSequenceId || d.id === hoveredImageId;
71874 }).classed('hovered', function (d) {
71875 return d.id === hoveredImageId;
71877 context.container().selectAll('.layer-mapillary .sequence').classed('highlighted', function (d) {
71878 return d.properties.id === hoveredSequenceId;
71879 }).classed('currentView', function (d) {
71880 return d.properties.id === selectedSequenceId;
71884 // Get detections for the current image and shows them in the image viewer
71885 updateDetections: function updateDetections(imageId, url) {
71886 if (!_mlyViewer || _mlyFallback) return;
71887 if (!imageId) return;
71888 var cache = _mlyCache.image_detections;
71890 if (cache.forImageId[imageId]) {
71891 showDetections(_mlyCache.image_detections.forImageId[imageId]);
71893 loadData(url).then(function (detections) {
71894 detections.forEach(function (detection) {
71895 if (!cache.forImageId[imageId]) {
71896 cache.forImageId[imageId] = [];
71899 cache.forImageId[imageId].push({
71900 geometry: detection.geometry,
71903 value: detection.value
71906 showDetections(_mlyCache.image_detections.forImageId[imageId] || []);
71908 } // Create a tag for each detection and shows it in the image viewer
71911 function showDetections(detections) {
71912 var tagComponent = _mlyViewer.getComponent('tag');
71914 detections.forEach(function (data) {
71915 var tag = makeTag(data);
71918 tagComponent.add([tag]);
71921 } // Create a Mapillary JS tag object
71924 function makeTag(data) {
71925 var valueParts = data.value.split('--');
71926 if (!valueParts.length) return;
71929 var color = 0xffffff;
71931 if (_mlyHighlightedDetection === data.id) {
71933 text = valueParts[1];
71935 if (text === 'flat' || text === 'discrete' || text === 'sign') {
71936 text = valueParts[2];
71939 text = text.replace(/-/g, ' ');
71940 text = text.charAt(0).toUpperCase() + text.slice(1);
71941 _mlyHighlightedDetection = null;
71944 var decodedGeometry = window.atob(data.geometry);
71945 var uintArray = new Uint8Array(decodedGeometry.length);
71947 for (var i = 0; i < decodedGeometry.length; i++) {
71948 uintArray[i] = decodedGeometry.charCodeAt(i);
71951 var tile = new VectorTile(new pbf(uintArray.buffer));
71952 var layer = tile.layers['mpy-or'];
71953 var geometries = layer.feature(0).loadGeometry();
71954 var polygon = geometries.map(function (ring) {
71955 return ring.map(function (point) {
71956 return [point.x / layer.extent, point.y / layer.extent];
71959 tag = new mapillary.OutlineTag(data.id, new mapillary.PolygonGeometry(polygon[0]), {
71970 // Return the current cache
71971 cache: function cache() {
71976 function validationIssue(attrs) {
71977 this.type = attrs.type; // required - name of rule that created the issue (e.g. 'missing_tag')
71979 this.subtype = attrs.subtype; // optional - category of the issue within the type (e.g. 'relation_type' under 'missing_tag')
71981 this.severity = attrs.severity; // required - 'warning' or 'error'
71983 this.message = attrs.message; // required - function returning localized string
71985 this.reference = attrs.reference; // optional - function(selection) to render reference information
71987 this.entityIds = attrs.entityIds; // optional - array of IDs of entities involved in the issue
71989 this.loc = attrs.loc; // optional - [lon, lat] to zoom in on to see the issue
71991 this.data = attrs.data; // optional - object containing extra data for the fixes
71993 this.dynamicFixes = attrs.dynamicFixes; // optional - function(context) returning fixes
71995 this.hash = attrs.hash; // optional - string to further differentiate the issue
71997 this.id = generateID.apply(this); // generated - see below
71999 this.key = generateKey.apply(this); // generated - see below (call after generating this.id)
72001 this.autoFix = null; // generated - if autofix exists, will be set below
72002 // A unique, deterministic string hash.
72003 // Issues with identical id values are considered identical.
72005 function generateID() {
72006 var parts = [this.type];
72009 // subclasses can pass in their own differentiator
72010 parts.push(this.hash);
72013 if (this.subtype) {
72014 parts.push(this.subtype);
72015 } // include the entities this issue is for
72016 // (sort them so the id is deterministic)
72019 if (this.entityIds) {
72020 var entityKeys = this.entityIds.slice().sort();
72021 parts.push.apply(parts, entityKeys);
72024 return parts.join(':');
72025 } // An identifier suitable for use as the second argument to d3.selection#data().
72026 // (i.e. this should change whenever the data needs to be refreshed)
72029 function generateKey() {
72030 return this.id + ':' + Date.now().toString(); // include time of creation
72033 this.extent = function (resolver) {
72035 return geoExtent(this.loc);
72038 if (this.entityIds && this.entityIds.length) {
72039 return this.entityIds.reduce(function (extent, entityId) {
72040 return extent.extend(resolver.entity(entityId).extent(resolver));
72047 this.fixes = function (context) {
72048 var fixes = this.dynamicFixes ? this.dynamicFixes(context) : [];
72051 if (issue.severity === 'warning') {
72052 // allow ignoring any issue that's not an error
72053 fixes.push(new validationIssueFix({
72054 title: _t.html('issues.fix.ignore_issue.title'),
72055 icon: 'iD-icon-close',
72056 onClick: function onClick() {
72057 context.validator().ignoreIssue(this.issue.id);
72062 fixes.forEach(function (fix) {
72063 // the id doesn't matter as long as it's unique to this issue/fix
72064 fix.id = fix.title; // add a reference to the issue for use in actions
72068 if (fix.autoArgs) {
72069 issue.autoFix = fix;
72075 function validationIssueFix(attrs) {
72076 this.title = attrs.title; // Required
72078 this.onClick = attrs.onClick; // Optional - the function to run to apply the fix
72080 this.disabledReason = attrs.disabledReason; // Optional - a string explaining why the fix is unavailable, if any
72082 this.icon = attrs.icon; // Optional - shows 'iD-icon-wrench' if not set
72084 this.entityIds = attrs.entityIds || []; // Optional - used for hover-higlighting.
72086 this.autoArgs = attrs.autoArgs; // Optional - pass [actions, annotation] arglist if this fix can automatically run
72088 this.issue = null; // Generated link - added by validationIssue
72091 var buildRuleChecks = function buildRuleChecks() {
72093 equals: function equals(_equals) {
72094 return function (tags) {
72095 return Object.keys(_equals).every(function (k) {
72096 return _equals[k] === tags[k];
72100 notEquals: function notEquals(_notEquals) {
72101 return function (tags) {
72102 return Object.keys(_notEquals).some(function (k) {
72103 return _notEquals[k] !== tags[k];
72107 absence: function absence(_absence) {
72108 return function (tags) {
72109 return Object.keys(tags).indexOf(_absence) === -1;
72112 presence: function presence(_presence) {
72113 return function (tags) {
72114 return Object.keys(tags).indexOf(_presence) > -1;
72117 greaterThan: function greaterThan(_greaterThan) {
72118 var key = Object.keys(_greaterThan)[0];
72119 var value = _greaterThan[key];
72120 return function (tags) {
72121 return tags[key] > value;
72124 greaterThanEqual: function greaterThanEqual(_greaterThanEqual) {
72125 var key = Object.keys(_greaterThanEqual)[0];
72126 var value = _greaterThanEqual[key];
72127 return function (tags) {
72128 return tags[key] >= value;
72131 lessThan: function lessThan(_lessThan) {
72132 var key = Object.keys(_lessThan)[0];
72133 var value = _lessThan[key];
72134 return function (tags) {
72135 return tags[key] < value;
72138 lessThanEqual: function lessThanEqual(_lessThanEqual) {
72139 var key = Object.keys(_lessThanEqual)[0];
72140 var value = _lessThanEqual[key];
72141 return function (tags) {
72142 return tags[key] <= value;
72145 positiveRegex: function positiveRegex(_positiveRegex) {
72146 var tagKey = Object.keys(_positiveRegex)[0];
72148 var expression = _positiveRegex[tagKey].join('|');
72150 var regex = new RegExp(expression);
72151 return function (tags) {
72152 return regex.test(tags[tagKey]);
72155 negativeRegex: function negativeRegex(_negativeRegex) {
72156 var tagKey = Object.keys(_negativeRegex)[0];
72158 var expression = _negativeRegex[tagKey].join('|');
72160 var regex = new RegExp(expression);
72161 return function (tags) {
72162 return !regex.test(tags[tagKey]);
72168 var buildLineKeys = function buildLineKeys() {
72184 var serviceMapRules = {
72185 init: function init() {
72186 this._ruleChecks = buildRuleChecks();
72187 this._validationRules = [];
72188 this._areaKeys = osmAreaKeys;
72189 this._lineKeys = buildLineKeys();
72191 // list of rules only relevant to tag checks...
72192 filterRuleChecks: function filterRuleChecks(selector) {
72193 var _ruleChecks = this._ruleChecks;
72194 return Object.keys(selector).reduce(function (rules, key) {
72195 if (['geometry', 'error', 'warning'].indexOf(key) === -1) {
72196 rules.push(_ruleChecks[key](selector[key]));
72202 // builds tagMap from mapcss-parse selector object...
72203 buildTagMap: function buildTagMap(selector) {
72204 var getRegexValues = function getRegexValues(regexes) {
72205 return regexes.map(function (regex) {
72206 return regex.replace(/\$|\^/g, '');
72210 var tagMap = Object.keys(selector).reduce(function (expectedTags, key) {
72212 var isRegex = /regex/gi.test(key);
72213 var isEqual = /equals/gi.test(key);
72215 if (isRegex || isEqual) {
72216 Object.keys(selector[key]).forEach(function (selectorKey) {
72217 values = isEqual ? [selector[key][selectorKey]] : getRegexValues(selector[key][selectorKey]);
72219 if (expectedTags.hasOwnProperty(selectorKey)) {
72220 values = values.concat(expectedTags[selectorKey]);
72223 expectedTags[selectorKey] = values;
72225 } else if (/(greater|less)Than(Equal)?|presence/g.test(key)) {
72226 var tagKey = /presence/.test(key) ? selector[key] : Object.keys(selector[key])[0];
72227 values = [selector[key][tagKey]];
72229 if (expectedTags.hasOwnProperty(tagKey)) {
72230 values = values.concat(expectedTags[tagKey]);
72233 expectedTags[tagKey] = values;
72236 return expectedTags;
72240 // inspired by osmWay#isArea()
72241 inferGeometry: function inferGeometry(tagMap) {
72242 var _lineKeys = this._lineKeys;
72243 var _areaKeys = this._areaKeys;
72245 var keyValueDoesNotImplyArea = function keyValueDoesNotImplyArea(key) {
72246 return utilArrayIntersection(tagMap[key], Object.keys(_areaKeys[key])).length > 0;
72249 var keyValueImpliesLine = function keyValueImpliesLine(key) {
72250 return utilArrayIntersection(tagMap[key], Object.keys(_lineKeys[key])).length > 0;
72253 if (tagMap.hasOwnProperty('area')) {
72254 if (tagMap.area.indexOf('yes') > -1) {
72258 if (tagMap.area.indexOf('no') > -1) {
72263 for (var key in tagMap) {
72264 if (key in _areaKeys && !keyValueDoesNotImplyArea(key)) {
72268 if (key in _lineKeys && keyValueImpliesLine(key)) {
72275 // adds from mapcss-parse selector check...
72276 addRule: function addRule(selector) {
72278 // checks relevant to mapcss-selector
72279 checks: this.filterRuleChecks(selector),
72280 // true if all conditions for a tag error are true..
72281 matches: function matches(entity) {
72282 return this.checks.every(function (check) {
72283 return check(entity.tags);
72286 // borrowed from Way#isArea()
72287 inferredGeometry: this.inferGeometry(this.buildTagMap(selector), this._areaKeys),
72288 geometryMatches: function geometryMatches(entity, graph) {
72289 if (entity.type === 'node' || entity.type === 'relation') {
72290 return selector.geometry === entity.type;
72291 } else if (entity.type === 'way') {
72292 return this.inferredGeometry === entity.geometry(graph);
72295 // when geometries match and tag matches are present, return a warning...
72296 findIssues: function findIssues(entity, graph, issues) {
72297 if (this.geometryMatches(entity, graph) && this.matches(entity)) {
72298 var severity = Object.keys(selector).indexOf('error') > -1 ? 'error' : 'warning';
72299 var _message = selector[severity];
72300 issues.push(new validationIssue({
72302 severity: severity,
72303 message: function message() {
72306 entityIds: [entity.id]
72312 this._validationRules.push(rule);
72314 clearRules: function clearRules() {
72315 this._validationRules = [];
72317 // returns validationRules...
72318 validationRules: function validationRules() {
72319 return this._validationRules;
72321 // returns ruleChecks
72322 ruleChecks: function ruleChecks() {
72323 return this._ruleChecks;
72327 var apibase$2 = 'https://nominatim.openstreetmap.org/';
72328 var _inflight$2 = {};
72330 var _nominatimCache;
72332 var serviceNominatim = {
72333 init: function init() {
72335 _nominatimCache = new RBush();
72337 reset: function reset() {
72338 Object.values(_inflight$2).forEach(function (controller) {
72339 controller.abort();
72342 _nominatimCache = new RBush();
72344 countryCode: function countryCode(location, callback) {
72345 this.reverse(location, function (err, result) {
72347 return callback(err);
72348 } else if (result.address) {
72349 return callback(null, result.address.country_code);
72351 return callback('Unable to geocode', null);
72355 reverse: function reverse(loc, callback) {
72356 var cached = _nominatimCache.search({
72363 if (cached.length > 0) {
72364 if (callback) callback(null, cached[0].data);
72375 var url = apibase$2 + 'reverse?' + utilQsString(params);
72376 if (_inflight$2[url]) return;
72377 var controller = new AbortController();
72378 _inflight$2[url] = controller;
72380 signal: controller.signal
72381 }).then(function (result) {
72382 delete _inflight$2[url];
72384 if (result && result.error) {
72385 throw new Error(result.error);
72388 var extent = geoExtent(loc).padByMeters(200);
72390 _nominatimCache.insert(Object.assign(extent.bbox(), {
72394 if (callback) callback(null, result);
72395 })["catch"](function (err) {
72396 delete _inflight$2[url];
72397 if (err.name === 'AbortError') return;
72398 if (callback) callback(err.message);
72401 search: function search(val, callback) {
72402 var searchVal = encodeURIComponent(val);
72403 var url = apibase$2 + 'search/' + searchVal + '?limit=10&format=json';
72404 if (_inflight$2[url]) return;
72405 var controller = new AbortController();
72406 _inflight$2[url] = controller;
72408 signal: controller.signal
72409 }).then(function (result) {
72410 delete _inflight$2[url];
72412 if (result && result.error) {
72413 throw new Error(result.error);
72416 if (callback) callback(null, result);
72417 })["catch"](function (err) {
72418 delete _inflight$2[url];
72419 if (err.name === 'AbortError') return;
72420 if (callback) callback(err.message);
72425 // for punction see https://stackoverflow.com/a/21224179
72427 function simplify$1(str) {
72428 if (typeof str !== 'string') return '';
72429 return diacritics.remove(str.replace(/&/g, 'and').replace(/İ/ig, 'i') // for BİM, İşbank - #5017
72430 .replace(/[\s\-=_!"#%'*{},.\/:;?\(\)\[\]@\\$\^*+<>«»~`’\u00a1\u00a7\u00b6\u00b7\u00bf\u037e\u0387\u055a-\u055f\u0589\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964\u0965\u0970\u0af0\u0df4\u0e4f\u0e5a\u0e5b\u0f04-\u0f12\u0f14\u0f85\u0fd0-\u0fd4\u0fd9\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u166d\u166e\u16eb-\u16ed\u1735\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u1805\u1807-\u180a\u1944\u1945\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e\u1c7f\u1cc0-\u1cc7\u1cd3\u2000-\u206f\u2cf9-\u2cfc\u2cfe\u2cff\u2d70\u2e00-\u2e7f\u3001-\u3003\u303d\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uaaf0\uaaf1\uabeb\ufe10-\ufe16\ufe19\ufe30\ufe45\ufe46\ufe49-\ufe4c\ufe50-\ufe52\ufe54-\ufe57\ufe5f-\ufe61\ufe68\ufe6a\ufe6b\ufeff\uff01-\uff03\uff05-\uff07\uff0a\uff0c\uff0e\uff0f\uff1a\uff1b\uff1f\uff20\uff3c\uff61\uff64\uff65]+/g, '').toLowerCase());
72433 var matchGroups$1 = {adult_gaming_centre:["amenity/casino","amenity/gambling","leisure/adult_gaming_centre"],beauty:["shop/beauty","shop/hairdresser_supply"],bed:["shop/bed","shop/furniture"],beverages:["shop/alcohol","shop/beer","shop/beverages","shop/wine"],camping:["leisure/park","tourism/camp_site","tourism/caravan_site"],car_parts:["shop/car_parts","shop/car_repair","shop/tires","shop/tyres"],clinic:["amenity/clinic","amenity/doctors","healthcare/clinic","healthcare/laboratory","healthcare/physiotherapist","healthcare/sample_collection","healthcare/dialysis"],confectionery:["shop/candy","shop/chocolate","shop/confectionery"],convenience:["shop/beauty","shop/chemist","shop/convenience","shop/cosmetics","shop/grocery","shop/newsagent","shop/perfumery"],coworking:["amenity/coworking_space","office/coworking","office/coworking_space"],dentist:["amenity/dentist","amenity/doctors","healthcare/dentist"],electronics:["office/telecommunication","shop/computer","shop/electronics","shop/hifi","shop/mobile","shop/mobile_phone","shop/telecommunication"],fabric:["shop/fabric","shop/haberdashery","shop/sewing"],fashion:["shop/accessories","shop/bag","shop/boutique","shop/clothes","shop/department_store","shop/fashion","shop/fashion_accessories","shop/sports","shop/shoes"],financial:["amenity/bank","office/accountant","office/financial","office/financial_advisor","office/tax_advisor","shop/tax"],fitness:["leisure/fitness_centre","leisure/fitness_center","leisure/sports_centre","leisure/sports_center"],food:["amenity/pub","amenity/bar","amenity/cafe","amenity/fast_food","amenity/ice_cream","amenity/restaurant","shop/bakery","shop/ice_cream","shop/pastry","shop/tea","shop/coffee"],fuel:["amenity/fuel","shop/gas","shop/convenience;gas","shop/gas;convenience"],gift:["shop/gift","shop/card","shop/cards","shop/stationery"],hardware:["shop/bathroom_furnishing","shop/carpet","shop/diy","shop/doityourself","shop/doors","shop/electrical","shop/flooring","shop/hardware","shop/hardware_store","shop/power_tools","shop/tool_hire","shop/tools","shop/trade"],health_food:["shop/health","shop/health_food","shop/herbalist","shop/nutrition_supplements"],hobby:["shop/electronics","shop/hobby","shop/books","shop/games","shop/collector","shop/toys","shop/model","shop/video_games","shop/anime"],hospital:["amenity/doctors","amenity/hospital","healthcare/hospital"],houseware:["shop/houseware","shop/interior_decoration"],lifeboat_station:["amenity/lifeboat_station","emergency/lifeboat_station","emergency/marine_rescue"],lodging:["tourism/hotel","tourism/motel"],money_transfer:["amenity/money_transfer","shop/money_transfer"],office_supplies:["shop/office_supplies","shop/stationary","shop/stationery"],outdoor:["shop/outdoor","shop/sports"],parcel_locker:["amenity/parcel_locker","amenity/vending_machine"],pharmacy:["amenity/doctors","amenity/pharmacy","healthcare/pharmacy"],playground:["amenity/theme_park","leisure/amusement_arcade","leisure/playground"],rental:["amenity/bicycle_rental","amenity/boat_rental","amenity/car_rental","amenity/truck_rental","amenity/vehicle_rental","shop/rental"],school:["amenity/childcare","amenity/college","amenity/kindergarten","amenity/language_school","amenity/prep_school","amenity/school","amenity/university"],storage:["shop/storage_units","shop/storage_rental"],substation:["power/station","power/substation","power/sub_station"],supermarket:["shop/food","shop/frozen_food","shop/greengrocer","shop/grocery","shop/supermarket","shop/wholesale"],variety_store:["shop/variety_store","shop/discount","shop/convenience"],vending:["amenity/vending_machine","shop/vending_machine"],weight_loss:["amenity/clinic","amenity/doctors","amenity/weight_clinic","healthcare/counselling","leisure/fitness_centre","office/therapist","shop/beauty","shop/diet","shop/food","shop/health_food","shop/herbalist","shop/nutrition","shop/nutrition_supplements","shop/weight_loss"],wholesale:["shop/wholesale","shop/supermarket","shop/department_store"]};
72434 var matchGroupsJSON = {
72435 matchGroups: matchGroups$1
72438 var genericWords = ["^(barn|bazaa?r|bench|bou?tique|building|casa|church)$","^(baseball|basketball|football|soccer|softball|tennis(halle)?)\\s?(field|court)?$","^(club|green|out|ware)\\s?house$","^(driveway|el árbol|fountain|golf|government|graveyard)$","^(fixme|n\\s?\\/?\\s?a|name|no\\s?name|none|null|temporary|test|unknown)$","^(hofladen|librairie|magazine?|maison)$","^(mobile home|skate)?\\s?park$","^(obuwie|pond|pool|sale|shops?|sklep|stores?)$","^\\?+$","^private$","^tattoo( studio)?$","^windmill$","^церковная( лавка)?$"];
72439 var genericWordsJSON = {
72440 genericWords: genericWords
72443 var trees$1 = {brands:{emoji:"🍔",mainTag:"brand:wikidata",sourceTags:["brand","name"],nameTags:{primary:"^(name|name:\\w+)$",alternate:"^(brand|brand:\\w+|operator|operator:\\w+|\\w+_name|\\w+_name:\\w+)$"}},flags:{emoji:"🚩",mainTag:"flag:wikidata",nameTags:{primary:"^(flag:name|flag:name:\\w+)$",alternate:"^(country|country:\\w+|flag|flag:\\w+|subject|subject:\\w+)$"}},operators:{emoji:"💼",mainTag:"operator:wikidata",sourceTags:["operator"],nameTags:{primary:"^(name|name:\\w+|operator|operator:\\w+)$",alternate:"^(brand|brand:\\w+|\\w+_name|\\w+_name:\\w+)$"}},transit:{emoji:"🚇",mainTag:"network:wikidata",sourceTags:["network"],nameTags:{primary:"^network$",alternate:"^(operator|operator:\\w+|network:\\w+|\\w+_name|\\w+_name:\\w+)$"}}};
72448 var matchGroups = matchGroupsJSON.matchGroups;
72449 var trees = treesJSON.trees;
72450 var Matcher = /*#__PURE__*/function () {
72453 // initialize the genericWords regexes
72454 function Matcher() {
72457 _classCallCheck$1(this, Matcher);
72459 // The `matchIndex` is a specialized structure that allows us to quickly answer
72460 // _"Given a [key/value tagpair, name, location], what canonical items (brands etc) can match it?"_
72462 // The index contains all valid combinations of k/v tagpairs and names
72466 // 'primary': Map (String 'nsimple' -> Set (itemIDs…), // matches for tags like `name`, `name:xx`, etc.
72467 // 'alternate': Map (String 'nsimple' -> Set (itemIDs…), // matches for tags like `alt_name`, `brand`, etc.
72468 // 'excludeNamed': Map (String 'pattern' -> RegExp),
72469 // 'excludeGeneric': Map (String 'pattern' -> RegExp)
72474 // 'amenity/bank': {
72476 // 'firstbank': Set ("firstbank-978cca", "firstbank-9794e6", "firstbank-f17495", …),
72480 // '1stbank': Set ("firstbank-f17495"),
72484 // 'shop/supermarket': {
72486 // 'coop': Set ("coop-76454b", "coop-ebf2d9", "coop-36e991", …),
72487 // 'coopfood': Set ("coopfood-a8278b", …),
72491 // 'coop': Set ("coopfood-a8278b", …),
72492 // 'federatedcooperatives': Set ("coop-76454b", …),
72493 // 'thecooperative': Set ("coopfood-a8278b", …),
72499 this.matchIndex = undefined; // The `genericWords` structure matches the contents of genericWords.json to instantiated RegExp objects
72500 // Map (String 'pattern' -> RegExp),
72502 this.genericWords = new Map();
72503 (genericWordsJSON.genericWords || []).forEach(function (s) {
72504 return _this.genericWords.set(s, new RegExp(s, 'i'));
72505 }); // The `itemLocation` structure maps itemIDs to locationSetIDs:
72507 // 'firstbank-f17495': '+[first_bank_western_us.geojson]',
72508 // 'firstbank-978cca': '+[first_bank_carolinas.geojson]',
72509 // 'coop-76454b': '+[Q16]',
72510 // 'coopfood-a8278b': '+[Q23666]',
72514 this.itemLocation = undefined; // The `locationSets` structure maps locationSetIDs to *resolved* locationSets:
72516 // '+[first_bank_western_us.geojson]': GeoJSON {…},
72517 // '+[first_bank_carolinas.geojson]': GeoJSON {…},
72518 // '+[Q16]': GeoJSON {…},
72519 // '+[Q23666]': GeoJSON {…},
72523 this.locationSets = undefined; // The `locationIndex` is an instance of which-polygon spatial index for the locationSets.
72525 this.locationIndex = undefined; // Array of match conflict pairs (currently unused)
72527 this.warnings = [];
72529 // `buildMatchIndex()`
72530 // Call this to prepare the matcher for use
72532 // `data` needs to be an Object indexed on a 'tree/key/value' path.
72533 // (e.g. cache filled by `fileTree.read` or data found in `dist/nsi.json`)
72535 // 'brands/amenity/bank': { properties: {}, items: [ {}, {}, … ] },
72536 // 'brands/amenity/bar': { properties: {}, items: [ {}, {}, … ] },
72542 _createClass$1(Matcher, [{
72543 key: "buildMatchIndex",
72544 value: function buildMatchIndex(data) {
72546 if (that.matchIndex) return; // it was built already
72548 that.matchIndex = new Map();
72549 var seenTree = new Map(); // warn if the same [k, v, nsimple] appears in multiple trees - #5625
72551 Object.keys(data).forEach(function (tkv) {
72552 var category = data[tkv];
72553 var parts = tkv.split('/', 3); // tkv = "tree/key/value"
72558 var thiskv = "".concat(k, "/").concat(v);
72559 var tree = trees[t];
72560 var branch = that.matchIndex.get(thiskv);
72564 primary: new Map(),
72565 alternate: new Map(),
72566 excludeGeneric: new Map(),
72567 excludeNamed: new Map()
72569 that.matchIndex.set(thiskv, branch);
72570 } // ADD EXCLUSIONS
72573 var properties = category.properties || {};
72574 var exclude = properties.exclude || {};
72575 (exclude.generic || []).forEach(function (s) {
72576 return branch.excludeGeneric.set(s, new RegExp(s, 'i'));
72578 (exclude.named || []).forEach(function (s) {
72579 return branch.excludeNamed.set(s, new RegExp(s, 'i'));
72581 var excludeRegexes = [].concat(_toConsumableArray(branch.excludeGeneric.values()), _toConsumableArray(branch.excludeNamed.values())); // ADD ITEMS
72583 var items = category.items;
72584 if (!Array.isArray(items) || !items.length) return; // Primary name patterns, match tags to take first
72585 // e.g. `name`, `name:ru`
72587 var primaryName = new RegExp(tree.nameTags.primary, 'i'); // Alternate name patterns, match tags to consider after primary
72588 // e.g. `alt_name`, `short_name`, `brand`, `brand:ru`, etc..
72590 var alternateName = new RegExp(tree.nameTags.alternate, 'i'); // There are a few exceptions to the name matching regexes.
72591 // Usually a tag suffix contains a language code like `name:en`, `name:ru`
72592 // but we want to exclude things like `operator:type`, `name:etymology`, etc..
72594 var notName = /:(colou?r|type|forward|backward|left|right|etymology|pronunciation|wikipedia)$/i; // For certain categories we do not want to match generic KV pairs like `building/yes` or `amenity/yes`
72596 var skipGenericKV = skipGenericKVMatches(t, k, v); // We will collect the generic KV pairs anyway (for the purpose of filtering them out of matchTags)
72598 var genericKV = new Set(["".concat(k, "/yes"), "building/yes"]); // Collect alternate tagpairs for this kv category from matchGroups.
72599 // We might also pick up a few more generic KVs (like `shop/yes`)
72601 var matchGroupKV = new Set();
72602 Object.values(matchGroups).forEach(function (matchGroup) {
72603 var inGroup = matchGroup.some(function (otherkv) {
72604 return otherkv === thiskv;
72606 if (!inGroup) return;
72607 matchGroup.forEach(function (otherkv) {
72608 if (otherkv === thiskv) return; // skip self
72610 matchGroupKV.add(otherkv);
72611 var otherk = otherkv.split('/', 2)[0]; // we might pick up a `shop/yes`
72613 genericKV.add("".concat(otherk, "/yes"));
72615 }); // For each item, insert all [key, value, name] combinations into the match index
72617 items.forEach(function (item) {
72618 if (!item.id) return; // Automatically remove redundant `matchTags` - #3417
72619 // (i.e. This kv is already covered by matchGroups, so it doesn't need to be in `item.matchTags`)
72621 if (Array.isArray(item.matchTags) && item.matchTags.length) {
72622 item.matchTags = item.matchTags.filter(function (matchTag) {
72623 return !matchGroupKV.has(matchTag) && !genericKV.has(matchTag);
72625 if (!item.matchTags.length) delete item.matchTags;
72626 } // key/value tagpairs to insert into the match index..
72629 var kvTags = ["".concat(thiskv)].concat(item.matchTags || []);
72631 if (!skipGenericKV) {
72632 kvTags = kvTags.concat(Array.from(genericKV)); // #3454 - match some generic tags
72633 } // Index all the namelike tag values
72636 Object.keys(item.tags).forEach(function (osmkey) {
72637 if (notName.test(osmkey)) return; // osmkey is not a namelike tag, skip
72639 var osmvalue = item.tags[osmkey];
72640 if (!osmvalue || excludeRegexes.some(function (regex) {
72641 return regex.test(osmvalue);
72642 })) return; // osmvalue missing or excluded
72644 if (primaryName.test(osmkey)) {
72645 kvTags.forEach(function (kv) {
72646 return insertName('primary', t, kv, simplify$1(osmvalue), item.id);
72648 } else if (alternateName.test(osmkey)) {
72649 kvTags.forEach(function (kv) {
72650 return insertName('alternate', t, kv, simplify$1(osmvalue), item.id);
72653 }); // Index `matchNames` after indexing all other names..
72655 var keepMatchNames = new Set();
72656 (item.matchNames || []).forEach(function (matchName) {
72657 // If this matchname isn't already indexed, add it to the alternate index
72658 var nsimple = simplify$1(matchName);
72659 kvTags.forEach(function (kv) {
72660 var branch = that.matchIndex.get(kv);
72661 var primaryLeaf = branch && branch.primary.get(nsimple);
72662 var alternateLeaf = branch && branch.alternate.get(nsimple);
72663 var inPrimary = primaryLeaf && primaryLeaf.has(item.id);
72664 var inAlternate = alternateLeaf && alternateLeaf.has(item.id);
72666 if (!inPrimary && !inAlternate) {
72667 insertName('alternate', t, kv, nsimple, item.id);
72668 keepMatchNames.add(matchName);
72671 }); // Automatically remove redundant `matchNames` - #3417
72672 // (i.e. This name got indexed some other way, so it doesn't need to be in `item.matchNames`)
72674 if (keepMatchNames.size) {
72675 item.matchNames = Array.from(keepMatchNames);
72677 delete item.matchNames;
72681 // Insert this item into the matchIndex
72683 function insertName(which, t, kv, nsimple, itemID) {
72685 that.warnings.push("Warning: skipping empty ".concat(which, " name for item ").concat(t, "/").concat(kv, ": ").concat(itemID));
72689 var branch = that.matchIndex.get(kv);
72693 primary: new Map(),
72694 alternate: new Map(),
72695 excludeGeneric: new Map(),
72696 excludeNamed: new Map()
72698 that.matchIndex.set(kv, branch);
72701 var leaf = branch[which].get(nsimple);
72705 branch[which].set(nsimple, leaf);
72708 leaf.add(itemID); // insert
72709 // check for duplicates - #5625
72711 if (!/yes$/.test(kv)) {
72712 // ignore genericKV like amenity/yes, building/yes, etc
72713 var kvnsimple = "".concat(kv, "/").concat(nsimple);
72714 var existing = seenTree.get(kvnsimple);
72716 if (existing && existing !== t) {
72717 var items = Array.from(leaf);
72718 that.warnings.push("Duplicate cache key \"".concat(kvnsimple, "\" in trees \"").concat(t, "\" and \"").concat(existing, "\", check items: ").concat(items));
72722 seenTree.set(kvnsimple, t);
72724 } // For certain categories we do not want to match generic KV pairs like `building/yes` or `amenity/yes`
72727 function skipGenericKVMatches(t, k, v) {
72728 return t === 'flags' || t === 'transit' || k === 'landuse' || v === 'atm' || v === 'bicycle_parking' || v === 'car_sharing' || v === 'caravan_site' || v === 'charging_station' || v === 'dog_park' || v === 'parking' || v === 'phone' || v === 'playground' || v === 'post_box' || v === 'public_bookcase' || v === 'recycling' || v === 'vending_machine';
72731 // `buildLocationIndex()`
72732 // Call this to prepare a which-polygon location index.
72733 // This *resolves* all the locationSets into GeoJSON, which takes some time.
72734 // You can skip this step if you don't care about matching within a location.
72736 // `data` needs to be an Object indexed on a 'tree/key/value' path.
72737 // (e.g. cache filled by `fileTree.read` or data found in `dist/nsi.json`)
72739 // 'brands/amenity/bank': { properties: {}, items: [ {}, {}, … ] },
72740 // 'brands/amenity/bar': { properties: {}, items: [ {}, {}, … ] },
72746 key: "buildLocationIndex",
72747 value: function buildLocationIndex(data, loco) {
72749 if (that.locationIndex) return; // it was built already
72751 that.itemLocation = new Map();
72752 that.locationSets = new Map();
72753 Object.keys(data).forEach(function (tkv) {
72754 var items = data[tkv].items;
72755 if (!Array.isArray(items) || !items.length) return;
72756 items.forEach(function (item) {
72757 if (that.itemLocation.has(item.id)) return; // we've seen item id already - shouldn't be possible?
72762 resolved = loco.resolveLocationSet(item.locationSet); // resolve a feature for this locationSet
72764 console.warn("buildLocationIndex: ".concat(err.message)); // couldn't resolve
72767 if (!resolved || !resolved.id) return;
72768 that.itemLocation.set(item.id, resolved.id); // link it to the item
72770 if (that.locationSets.has(resolved.id)) return; // we've seen this locationSet feature before..
72771 // First time seeing this locationSet feature, make a copy and add to locationSet cache..
72773 var feature = _cloneDeep(resolved.feature);
72775 feature.id = resolved.id; // Important: always use the locationSet `id` (`+[Q30]`), not the feature `id` (`Q30`)
72777 feature.properties.id = resolved.id;
72779 if (!feature.geometry.coordinates.length || !feature.properties.area) {
72780 console.warn("buildLocationIndex: locationSet ".concat(resolved.id, " for ").concat(item.id, " resolves to an empty feature:"));
72781 console.warn(JSON.stringify(feature));
72785 that.locationSets.set(resolved.id, feature);
72788 that.locationIndex = whichPolygon_1({
72789 type: 'FeatureCollection',
72790 features: _toConsumableArray(that.locationSets.values())
72793 function _cloneDeep(obj) {
72794 return JSON.parse(JSON.stringify(obj));
72798 // Pass parts and return an Array of matches.
72802 // `loc` - optional - [lon,lat] location to search
72804 // 1. If the [k,v,n] tuple matches a canonical item…
72805 // Return an Array of match results.
72806 // Each result will include the area in km² that the item is valid.
72808 // Order of results:
72809 // Primary ordering will be on the "match" column:
72810 // "primary" - where the query matches the `name` tag, followed by
72811 // "alternate" - where the query matches an alternate name tag (e.g. short_name, brand, operator, etc)
72812 // Secondary ordering will be on the "area" column:
72813 // "area descending" if no location was provided, (worldwide before local)
72814 // "area ascending" if location was provided (local before worldwide)
72817 // { match: 'primary', itemID: String, area: Number, kv: String, nsimple: String },
72818 // { match: 'primary', itemID: String, area: Number, kv: String, nsimple: String },
72819 // { match: 'alternate', itemID: String, area: Number, kv: String, nsimple: String },
72820 // { match: 'alternate', itemID: String, area: Number, kv: String, nsimple: String },
72826 // 2. If the [k,v,n] tuple matches an exclude pattern…
72827 // Return an Array with a single exclude result, either
72829 // [ { match: 'excludeGeneric', pattern: String, kv: String } ] // "generic" e.g. "Food Court"
72831 // [ { match: 'excludeNamed', pattern: String, kv: String } ] // "named", e.g. "Kebabai"
72834 // "generic" - a generic word that is probably not really a name.
72835 // For these, iD should warn the user "Hey don't put 'food court' in the name tag".
72836 // "named" - a real name like "Kebabai" that is just common, but not a brand.
72837 // For these, iD should just let it be. We don't include these in NSI, but we don't want to nag users about it either.
72841 // 3. If the [k,v,n] tuple matches nothing of any kind, return `null`
72847 value: function match(k, v, n, loc) {
72850 if (!that.matchIndex) {
72851 throw new Error('match: matchIndex not built.');
72852 } // If we were supplied a location, and a that.locationIndex has been set up,
72853 // get the locationSets that are valid there so we can filter results.
72856 var matchLocations;
72858 if (Array.isArray(loc) && that.locationIndex) {
72859 // which-polygon query returns an array of GeoJSON properties, pass true to return all results
72860 matchLocations = that.locationIndex([loc[0], loc[1], loc[0], loc[1]], true);
72863 var nsimple = simplify$1(n);
72864 var seen = new Set();
72866 gatherResults('primary');
72867 gatherResults('alternate');
72868 if (results.length) return results;
72869 gatherResults('exclude');
72870 return results.length ? results : null;
72872 function gatherResults(which) {
72873 // First try an exact match on k/v
72874 var kv = "".concat(k, "/").concat(v);
72875 var didMatch = tryMatch(which, kv);
72876 if (didMatch) return; // If that didn't work, look in match groups for other pairs considered equivalent to k/v..
72878 for (var mg in matchGroups) {
72879 var matchGroup = matchGroups[mg];
72880 var inGroup = matchGroup.some(function (otherkv) {
72881 return otherkv === kv;
72883 if (!inGroup) continue;
72885 for (var i = 0; i < matchGroup.length; i++) {
72886 var otherkv = matchGroup[i];
72887 if (otherkv === kv) continue; // skip self
72889 didMatch = tryMatch(which, otherkv);
72890 if (didMatch) return;
72892 } // If finished 'exclude' pass and still haven't matched anything, try the global `genericWords.json` patterns
72895 if (which === 'exclude') {
72896 var regex = _toConsumableArray(that.genericWords.values()).find(function (regex) {
72897 return regex.test(n);
72902 match: 'excludeGeneric',
72903 pattern: String(regex)
72904 }); // note no `branch`, no `kv`
72911 function tryMatch(which, kv) {
72912 var branch = that.matchIndex.get(kv);
72913 if (!branch) return;
72915 if (which === 'exclude') {
72916 // Test name `n` against named and generic exclude patterns
72917 var regex = _toConsumableArray(branch.excludeNamed.values()).find(function (regex) {
72918 return regex.test(n);
72923 match: 'excludeNamed',
72924 pattern: String(regex),
72930 regex = _toConsumableArray(branch.excludeGeneric.values()).find(function (regex) {
72931 return regex.test(n);
72936 match: 'excludeGeneric',
72937 pattern: String(regex),
72946 var leaf = branch[which].get(nsimple);
72947 if (!leaf || !leaf.size) return; // If we get here, we matched something..
72948 // Prepare the results, calculate areas (if location index was set up)
72950 var hits = Array.from(leaf).map(function (itemID) {
72951 var area = Infinity;
72953 if (that.itemLocation && that.locationSets) {
72954 var location = that.locationSets.get(that.itemLocation.get(itemID));
72955 area = location && location.properties.area || Infinity;
72966 var sortFn = byAreaDescending; // Filter the match to include only results valid in the requested `loc`..
72968 if (matchLocations) {
72969 hits = hits.filter(isValidLocation);
72970 sortFn = byAreaAscending;
72973 if (!hits.length) return; // push results
72975 hits.sort(sortFn).forEach(function (hit) {
72976 if (seen.has(hit.itemID)) return;
72977 seen.add(hit.itemID);
72982 function isValidLocation(hit) {
72983 if (!that.itemLocation) return true;
72984 return matchLocations.find(function (props) {
72985 return props.id === that.itemLocation.get(hit.itemID);
72987 } // Sort smaller (more local) locations first.
72990 function byAreaAscending(hitA, hitB) {
72991 return hitA.area - hitB.area;
72992 } // Sort larger (more worldwide) locations first.
72995 function byAreaDescending(hitA, hitB) {
72996 return hitB.area - hitA.area;
73001 // Return any warnings discovered when buiding the index.
73002 // (currently this does nothing)
73006 key: "getWarnings",
73007 value: function getWarnings() {
73008 return this.warnings;
73016 iD.coreDifference represents the difference between two graphs.
73017 It knows how to calculate the set of entities that were
73018 created, modified, or deleted, and also contains the logic
73019 for recursively extending a difference to the complete set
73020 of entities that will require a redraw, taking into account
73021 child and parent relationships.
73024 function coreDifference(base, head) {
73026 var _didChange = {}; // 'addition', 'deletion', 'geometry', 'properties'
73030 function checkEntityID(id) {
73031 var h = head.entities[id];
73032 var b = base.entities[id];
73033 if (h === b) return;
73034 if (_changes[id]) return;
73041 _didChange.deletion = true;
73050 _didChange.addition = true;
73055 if (h.members && b.members && !fastDeepEqual(h.members, b.members)) {
73060 _didChange.geometry = true;
73061 _didChange.properties = true;
73065 if (h.loc && b.loc && !geoVecEqual(h.loc, b.loc)) {
73070 _didChange.geometry = true;
73073 if (h.nodes && b.nodes && !fastDeepEqual(h.nodes, b.nodes)) {
73078 _didChange.geometry = true;
73081 if (h.tags && b.tags && !fastDeepEqual(h.tags, b.tags)) {
73086 _didChange.properties = true;
73092 // HOT CODE: there can be many thousands of downloaded entities, so looping
73093 // through them all can become a performance bottleneck. Optimize by
73094 // resolving duplicates and using a basic `for` loop
73095 var ids = utilArrayUniq(Object.keys(head.entities).concat(Object.keys(base.entities)));
73097 for (var i = 0; i < ids.length; i++) {
73098 checkEntityID(ids[i]);
73104 _diff.length = function length() {
73105 return Object.keys(_changes).length;
73108 _diff.changes = function changes() {
73112 _diff.didChange = _didChange; // pass true to include affected relation members
73114 _diff.extantIDs = function extantIDs(includeRelMembers) {
73115 var result = new Set();
73116 Object.keys(_changes).forEach(function (id) {
73117 if (_changes[id].head) {
73121 var h = _changes[id].head;
73122 var b = _changes[id].base;
73123 var entity = h || b;
73125 if (includeRelMembers && entity.type === 'relation') {
73126 var mh = h ? h.members.map(function (m) {
73129 var mb = b ? b.members.map(function (m) {
73132 utilArrayUnion(mh, mb).forEach(function (memberID) {
73133 if (head.hasEntity(memberID)) {
73134 result.add(memberID);
73139 return Array.from(result);
73142 _diff.modified = function modified() {
73144 Object.values(_changes).forEach(function (change) {
73145 if (change.base && change.head) {
73146 result.push(change.head);
73152 _diff.created = function created() {
73154 Object.values(_changes).forEach(function (change) {
73155 if (!change.base && change.head) {
73156 result.push(change.head);
73162 _diff.deleted = function deleted() {
73164 Object.values(_changes).forEach(function (change) {
73165 if (change.base && !change.head) {
73166 result.push(change.base);
73172 _diff.summary = function summary() {
73174 var keys = Object.keys(_changes);
73176 for (var i = 0; i < keys.length; i++) {
73177 var change = _changes[keys[i]];
73179 if (change.head && change.head.geometry(head) !== 'vertex') {
73180 addEntity(change.head, head, change.base ? 'modified' : 'created');
73181 } else if (change.base && change.base.geometry(base) !== 'vertex') {
73182 addEntity(change.base, base, 'deleted');
73183 } else if (change.base && change.head) {
73185 var moved = !fastDeepEqual(change.base.loc, change.head.loc);
73186 var retagged = !fastDeepEqual(change.base.tags, change.head.tags);
73189 addParents(change.head);
73192 if (retagged || moved && change.head.hasInterestingTags()) {
73193 addEntity(change.head, head, 'modified');
73195 } else if (change.head && change.head.hasInterestingTags()) {
73197 addEntity(change.head, head, 'created');
73198 } else if (change.base && change.base.hasInterestingTags()) {
73200 addEntity(change.base, base, 'deleted');
73204 return Object.values(relevant);
73206 function addEntity(entity, graph, changeType) {
73207 relevant[entity.id] = {
73210 changeType: changeType
73214 function addParents(entity) {
73215 var parents = head.parentWays(entity);
73217 for (var j = parents.length - 1; j >= 0; j--) {
73218 var parent = parents[j];
73220 if (!(parent.id in relevant)) {
73221 addEntity(parent, head, 'modified');
73225 }; // returns complete set of entities that require a redraw
73226 // (optionally within given `extent`)
73229 _diff.complete = function complete(extent) {
73233 for (id in _changes) {
73234 change = _changes[id];
73235 var h = change.head;
73236 var b = change.base;
73237 var entity = h || b;
73240 if (extent && (!h || !h.intersects(extent, head)) && (!b || !b.intersects(extent, base))) {
73246 if (entity.type === 'way') {
73247 var nh = h ? h.nodes : [];
73248 var nb = b ? b.nodes : [];
73250 diff = utilArrayDifference(nh, nb);
73252 for (i = 0; i < diff.length; i++) {
73253 result[diff[i]] = head.hasEntity(diff[i]);
73256 diff = utilArrayDifference(nb, nh);
73258 for (i = 0; i < diff.length; i++) {
73259 result[diff[i]] = head.hasEntity(diff[i]);
73263 if (entity.type === 'relation' && entity.isMultipolygon()) {
73264 var mh = h ? h.members.map(function (m) {
73267 var mb = b ? b.members.map(function (m) {
73270 var ids = utilArrayUnion(mh, mb);
73272 for (i = 0; i < ids.length; i++) {
73273 var member = head.hasEntity(ids[i]);
73274 if (!member) continue; // not downloaded
73276 if (extent && !member.intersects(extent, head)) continue; // not visible
73278 result[ids[i]] = member;
73282 addParents(head.parentWays(entity), result);
73283 addParents(head.parentRelations(entity), result);
73288 function addParents(parents, result) {
73289 for (var i = 0; i < parents.length; i++) {
73290 var parent = parents[i];
73291 if (parent.id in result) continue;
73292 result[parent.id] = parent;
73293 addParents(head.parentRelations(parent), result);
73301 function coreTree(head) {
73302 // tree for entities
73303 var _rtree = new RBush();
73305 var _bboxes = {}; // maintain a separate tree for granular way segments
73307 var _segmentsRTree = new RBush();
73309 var _segmentsBBoxes = {};
73310 var _segmentsByWayId = {};
73313 function entityBBox(entity) {
73314 var bbox = entity.extent(head).bbox();
73315 bbox.id = entity.id;
73316 _bboxes[entity.id] = bbox;
73320 function segmentBBox(segment) {
73321 var extent = segment.extent(head); // extent can be null if the node entities aren't in the graph for some reason
73323 if (!extent) return null;
73324 var bbox = extent.bbox();
73325 bbox.segment = segment;
73326 _segmentsBBoxes[segment.id] = bbox;
73330 function removeEntity(entity) {
73331 _rtree.remove(_bboxes[entity.id]);
73333 delete _bboxes[entity.id];
73335 if (_segmentsByWayId[entity.id]) {
73336 _segmentsByWayId[entity.id].forEach(function (segment) {
73337 _segmentsRTree.remove(_segmentsBBoxes[segment.id]);
73339 delete _segmentsBBoxes[segment.id];
73342 delete _segmentsByWayId[entity.id];
73346 function loadEntities(entities) {
73347 _rtree.load(entities.map(entityBBox));
73350 entities.forEach(function (entity) {
73351 if (entity.segments) {
73352 var entitySegments = entity.segments(head); // cache these to make them easy to remove later
73354 _segmentsByWayId[entity.id] = entitySegments;
73355 segments = segments.concat(entitySegments);
73358 if (segments.length) _segmentsRTree.load(segments.map(segmentBBox).filter(Boolean));
73361 function updateParents(entity, insertions, memo) {
73362 head.parentWays(entity).forEach(function (way) {
73363 if (_bboxes[way.id]) {
73365 insertions[way.id] = way;
73368 updateParents(way, insertions, memo);
73370 head.parentRelations(entity).forEach(function (relation) {
73371 if (memo[entity.id]) return;
73372 memo[entity.id] = true;
73374 if (_bboxes[relation.id]) {
73375 removeEntity(relation);
73376 insertions[relation.id] = relation;
73379 updateParents(relation, insertions, memo);
73383 tree.rebase = function (entities, force) {
73384 var insertions = {};
73386 for (var i = 0; i < entities.length; i++) {
73387 var entity = entities[i];
73388 if (!entity.visible) continue;
73390 if (head.entities.hasOwnProperty(entity.id) || _bboxes[entity.id]) {
73393 } else if (_bboxes[entity.id]) {
73394 removeEntity(entity);
73398 insertions[entity.id] = entity;
73399 updateParents(entity, insertions, {});
73402 loadEntities(Object.values(insertions));
73406 function updateToGraph(graph) {
73407 if (graph === head) return;
73408 var diff = coreDifference(head, graph);
73410 var changed = diff.didChange;
73411 if (!changed.addition && !changed.deletion && !changed.geometry) return;
73412 var insertions = {};
73414 if (changed.deletion) {
73415 diff.deleted().forEach(function (entity) {
73416 removeEntity(entity);
73420 if (changed.geometry) {
73421 diff.modified().forEach(function (entity) {
73422 removeEntity(entity);
73423 insertions[entity.id] = entity;
73424 updateParents(entity, insertions, {});
73428 if (changed.addition) {
73429 diff.created().forEach(function (entity) {
73430 insertions[entity.id] = entity;
73434 loadEntities(Object.values(insertions));
73435 } // returns an array of entities with bounding boxes overlapping `extent` for the given `graph`
73438 tree.intersects = function (extent, graph) {
73439 updateToGraph(graph);
73440 return _rtree.search(extent.bbox()).map(function (bbox) {
73441 return graph.entity(bbox.id);
73443 }; // returns an array of segment objects with bounding boxes overlapping `extent` for the given `graph`
73446 tree.waySegments = function (extent, graph) {
73447 updateToGraph(graph);
73448 return _segmentsRTree.search(extent.bbox()).map(function (bbox) {
73449 return bbox.segment;
73456 function svgIcon(name, svgklass, useklass) {
73457 return function drawIcon(selection) {
73458 selection.selectAll('svg.icon' + (svgklass ? '.' + svgklass.split(' ')[0] : '')).data([0]).enter().append('svg').attr('class', 'icon ' + (svgklass || '')).append('use').attr('xlink:href', name).attr('class', useklass);
73462 function uiModal(selection, blocking) {
73465 var keybinding = utilKeybinding('modal');
73466 var previous = selection.select('div.modal');
73467 var animate = previous.empty();
73468 previous.transition().duration(200).style('opacity', 0).remove();
73469 var shaded = selection.append('div').attr('class', 'shaded').style('opacity', 0);
73471 shaded.close = function () {
73472 shaded.transition().duration(200).style('opacity', 0).remove();
73473 modal.transition().duration(200).style('top', '0px');
73474 select(document).call(keybinding.unbind);
73477 var modal = shaded.append('div').attr('class', 'modal fillL');
73478 modal.append('input').attr('class', 'keytrap keytrap-first').on('focus.keytrap', moveFocusToLast);
73481 shaded.on('click.remove-modal', function (d3_event) {
73482 if (d3_event.target === _this) {
73486 modal.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', shaded.close).call(svgIcon('#iD-icon-close'));
73487 keybinding.on('⌫', shaded.close).on('⎋', shaded.close);
73488 select(document).call(keybinding);
73491 modal.append('div').attr('class', 'content');
73492 modal.append('input').attr('class', 'keytrap keytrap-last').on('focus.keytrap', moveFocusToFirst);
73495 shaded.transition().style('opacity', 1);
73497 shaded.style('opacity', 1);
73502 function moveFocusToFirst() {
73503 var node = modal // there are additional rules about what's focusable, but this suits our purposes
73504 .select('a, button, input:not(.keytrap), select, textarea').node();
73509 select(this).node().blur();
73513 function moveFocusToLast() {
73514 var nodes = modal.selectAll('a, button, input:not(.keytrap), select, textarea').nodes();
73516 if (nodes.length) {
73517 nodes[nodes.length - 1].focus();
73519 select(this).node().blur();
73524 function uiLoading(context) {
73525 var _modalSelection = select(null);
73528 var _blocking = false;
73530 var loading = function loading(selection) {
73531 _modalSelection = uiModal(selection, _blocking);
73533 var loadertext = _modalSelection.select('.content').classed('loading-modal', true).append('div').attr('class', 'modal-section fillL');
73535 loadertext.append('img').attr('class', 'loader').attr('src', context.imagePath('loader-white.gif'));
73536 loadertext.append('h3').html(_message);
73538 _modalSelection.select('button.close').attr('class', 'hide');
73543 loading.message = function (val) {
73544 if (!arguments.length) return _message;
73549 loading.blocking = function (val) {
73550 if (!arguments.length) return _blocking;
73555 loading.close = function () {
73556 _modalSelection.remove();
73559 loading.isShown = function () {
73560 return _modalSelection && !_modalSelection.empty() && _modalSelection.node().parentNode;
73566 function coreHistory(context) {
73567 var dispatch = dispatch$8('reset', 'change', 'merge', 'restore', 'undone', 'redone', 'storage_error');
73569 var _lock = utilSessionMutex('lock'); // restorable if iD not open in another window/tab and a saved history exists in localStorage
73572 var _hasUnresolvedRestorableChanges = _lock.lock() && !!corePreferences(getKey('saved_history'));
73574 var duration = 150;
73575 var _imageryUsed = [];
73576 var _photoOverlaysUsed = [];
73577 var _checkpoints = {};
73585 var _tree; // internal _act, accepts list of actions and eased time
73588 function _act(actions, t) {
73589 actions = Array.prototype.slice.call(actions);
73592 if (typeof actions[actions.length - 1] !== 'function') {
73593 annotation = actions.pop();
73596 var graph = _stack[_index].graph;
73598 for (var i = 0; i < actions.length; i++) {
73599 graph = actions[i](graph, t);
73604 annotation: annotation,
73605 imageryUsed: _imageryUsed,
73606 photoOverlaysUsed: _photoOverlaysUsed,
73607 transform: context.projection.transform(),
73608 selectedIDs: context.selectedIDs()
73610 } // internal _perform with eased time
73613 function _perform(args, t) {
73614 var previous = _stack[_index].graph;
73615 _stack = _stack.slice(0, _index + 1);
73617 var actionResult = _act(args, t);
73619 _stack.push(actionResult);
73622 return change(previous);
73623 } // internal _replace with eased time
73626 function _replace(args, t) {
73627 var previous = _stack[_index].graph; // assert(_index == _stack.length - 1)
73629 var actionResult = _act(args, t);
73631 _stack[_index] = actionResult;
73632 return change(previous);
73633 } // internal _overwrite with eased time
73636 function _overwrite(args, t) {
73637 var previous = _stack[_index].graph;
73645 _stack = _stack.slice(0, _index + 1);
73647 var actionResult = _act(args, t);
73649 _stack.push(actionResult);
73652 return change(previous);
73653 } // determine difference and dispatch a change event
73656 function change(previous) {
73657 var difference = coreDifference(previous, history.graph());
73659 if (!_pausedGraph) {
73660 dispatch.call('change', this, difference);
73664 } // iD uses namespaced keys so multiple installations do not conflict
73667 function getKey(n) {
73668 return 'iD_' + window.location.origin + '_' + n;
73672 graph: function graph() {
73673 return _stack[_index].graph;
73675 tree: function tree() {
73678 base: function base() {
73679 return _stack[0].graph;
73681 merge: function merge(entities
73684 var stack = _stack.map(function (state) {
73685 return state.graph;
73688 _stack[0].graph.rebase(entities, stack, false);
73690 _tree.rebase(entities, false);
73692 dispatch.call('merge', this, entities);
73694 perform: function perform() {
73695 // complete any transition already in progress
73696 select(document).interrupt('history.perform');
73697 var transitionable = false;
73698 var action0 = arguments[0];
73700 if (arguments.length === 1 || arguments.length === 2 && typeof arguments[1] !== 'function') {
73701 transitionable = !!action0.transitionable;
73704 if (transitionable) {
73705 var origArguments = arguments;
73706 select(document).transition('history.perform').duration(duration).ease(linear$1).tween('history.tween', function () {
73707 return function (t) {
73708 if (t < 1) _overwrite([action0], t);
73710 }).on('start', function () {
73711 _perform([action0], 0);
73712 }).on('end interrupt', function () {
73713 _overwrite(origArguments, 1);
73716 return _perform(arguments);
73719 replace: function replace() {
73720 select(document).interrupt('history.perform');
73721 return _replace(arguments, 1);
73723 // Same as calling pop and then perform
73724 overwrite: function overwrite() {
73725 select(document).interrupt('history.perform');
73726 return _overwrite(arguments, 1);
73728 pop: function pop(n) {
73729 select(document).interrupt('history.perform');
73730 var previous = _stack[_index].graph;
73732 if (isNaN(+n) || +n < 0) {
73736 while (n-- > 0 && _index > 0) {
73742 return change(previous);
73744 // Back to the previous annotated state or _index = 0.
73745 undo: function undo() {
73746 select(document).interrupt('history.perform');
73747 var previousStack = _stack[_index];
73748 var previous = previousStack.graph;
73750 while (_index > 0) {
73752 if (_stack[_index].annotation) break;
73755 dispatch.call('undone', this, _stack[_index], previousStack);
73756 return change(previous);
73758 // Forward to the next annotated state.
73759 redo: function redo() {
73760 select(document).interrupt('history.perform');
73761 var previousStack = _stack[_index];
73762 var previous = previousStack.graph;
73763 var tryIndex = _index;
73765 while (tryIndex < _stack.length - 1) {
73768 if (_stack[tryIndex].annotation) {
73770 dispatch.call('redone', this, _stack[_index], previousStack);
73775 return change(previous);
73777 pauseChangeDispatch: function pauseChangeDispatch() {
73778 if (!_pausedGraph) {
73779 _pausedGraph = _stack[_index].graph;
73782 resumeChangeDispatch: function resumeChangeDispatch() {
73783 if (_pausedGraph) {
73784 var previous = _pausedGraph;
73785 _pausedGraph = null;
73786 return change(previous);
73789 undoAnnotation: function undoAnnotation() {
73793 if (_stack[i].annotation) return _stack[i].annotation;
73797 redoAnnotation: function redoAnnotation() {
73798 var i = _index + 1;
73800 while (i <= _stack.length - 1) {
73801 if (_stack[i].annotation) return _stack[i].annotation;
73805 // Returns the entities from the active graph with bounding boxes
73806 // overlapping the given `extent`.
73807 intersects: function intersects(extent) {
73808 return _tree.intersects(extent, _stack[_index].graph);
73810 difference: function difference() {
73811 var base = _stack[0].graph;
73812 var head = _stack[_index].graph;
73813 return coreDifference(base, head);
73815 changes: function changes(action) {
73816 var base = _stack[0].graph;
73817 var head = _stack[_index].graph;
73820 head = action(head);
73823 var difference = coreDifference(base, head);
73825 modified: difference.modified(),
73826 created: difference.created(),
73827 deleted: difference.deleted()
73830 hasChanges: function hasChanges() {
73831 return this.difference().length() > 0;
73833 imageryUsed: function imageryUsed(sources) {
73835 _imageryUsed = sources;
73840 _stack.slice(1, _index + 1).forEach(function (state) {
73841 state.imageryUsed.forEach(function (source) {
73842 if (source !== 'Custom') {
73848 return Array.from(s);
73851 photoOverlaysUsed: function photoOverlaysUsed(sources) {
73853 _photoOverlaysUsed = sources;
73858 _stack.slice(1, _index + 1).forEach(function (state) {
73859 if (state.photoOverlaysUsed && Array.isArray(state.photoOverlaysUsed)) {
73860 state.photoOverlaysUsed.forEach(function (photoOverlay) {
73861 s.add(photoOverlay);
73866 return Array.from(s);
73869 // save the current history state
73870 checkpoint: function checkpoint(key) {
73871 _checkpoints[key] = {
73877 // restore history state to a given checkpoint or reset completely
73878 reset: function reset(key) {
73879 if (key !== undefined && _checkpoints.hasOwnProperty(key)) {
73880 _stack = _checkpoints[key].stack;
73881 _index = _checkpoints[key].index;
73887 _tree = coreTree(_stack[0].graph);
73891 dispatch.call('reset');
73892 dispatch.call('change');
73895 // `toIntroGraph()` is used to export the intro graph used by the walkthrough.
73898 // 1. Start the walkthrough.
73899 // 2. Get to a "free editing" tutorial step
73900 // 3. Make your edits to the walkthrough map
73901 // 4. In your browser dev console run:
73902 // `id.history().toIntroGraph()`
73903 // 5. This outputs stringified JSON to the browser console
73904 // 6. Copy it to `data/intro_graph.json` and prettify it in your code editor
73905 toIntroGraph: function toIntroGraph() {
73912 var graph = this.graph();
73913 var baseEntities = {}; // clone base entities..
73915 Object.values(graph.base().entities).forEach(function (entity) {
73916 var copy = copyIntroEntity(entity);
73917 baseEntities[copy.id] = copy;
73918 }); // replace base entities with head entities..
73920 Object.keys(graph.entities).forEach(function (id) {
73921 var entity = graph.entities[id];
73924 var copy = copyIntroEntity(entity);
73925 baseEntities[copy.id] = copy;
73927 delete baseEntities[id];
73929 }); // swap temporary for permanent ids..
73931 Object.values(baseEntities).forEach(function (entity) {
73932 if (Array.isArray(entity.nodes)) {
73933 entity.nodes = entity.nodes.map(function (node) {
73934 return permIDs[node] || node;
73938 if (Array.isArray(entity.members)) {
73939 entity.members = entity.members.map(function (member) {
73940 member.id = permIDs[member.id] || member.id;
73945 return JSON.stringify({
73946 dataIntroGraph: baseEntities
73949 function copyIntroEntity(source) {
73950 var copy = utilObjectOmit(source, ['type', 'user', 'v', 'version', 'visible']); // Note: the copy is no longer an osmEntity, so it might not have `tags`
73952 if (copy.tags && !Object.keys(copy.tags)) {
73956 if (Array.isArray(copy.loc)) {
73957 copy.loc[0] = +copy.loc[0].toFixed(6);
73958 copy.loc[1] = +copy.loc[1].toFixed(6);
73961 var match = source.id.match(/([nrw])-\d*/); // temporary id
73963 if (match !== null) {
73964 var nrw = match[1];
73968 permID = nrw + ++nextID[nrw];
73969 } while (baseEntities.hasOwnProperty(permID));
73971 copy.id = permIDs[source.id] = permID;
73977 toJSON: function toJSON() {
73978 if (!this.hasChanges()) return;
73979 var allEntities = {};
73980 var baseEntities = {};
73981 var base = _stack[0];
73983 var s = _stack.map(function (i) {
73986 Object.keys(i.graph.entities).forEach(function (id) {
73987 var entity = i.graph.entities[id];
73990 var key = osmEntity.key(entity);
73991 allEntities[key] = entity;
73992 modified.push(key);
73995 } // make sure that the originals of changed or deleted entities get merged
73996 // into the base of the _stack after restoring the data from JSON.
73999 if (id in base.graph.entities) {
74000 baseEntities[id] = base.graph.entities[id];
74003 if (entity && entity.nodes) {
74004 // get originals of pre-existing child nodes
74005 entity.nodes.forEach(function (nodeID) {
74006 if (nodeID in base.graph.entities) {
74007 baseEntities[nodeID] = base.graph.entities[nodeID];
74010 } // get originals of parent entities too
74013 var baseParents = base.graph._parentWays[id];
74016 baseParents.forEach(function (parentID) {
74017 if (parentID in base.graph.entities) {
74018 baseEntities[parentID] = base.graph.entities[parentID];
74024 if (modified.length) x.modified = modified;
74025 if (deleted.length) x.deleted = deleted;
74026 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
74027 if (i.photoOverlaysUsed) x.photoOverlaysUsed = i.photoOverlaysUsed;
74028 if (i.annotation) x.annotation = i.annotation;
74029 if (i.transform) x.transform = i.transform;
74030 if (i.selectedIDs) x.selectedIDs = i.selectedIDs;
74034 return JSON.stringify({
74036 entities: Object.values(allEntities),
74037 baseEntities: Object.values(baseEntities),
74039 nextIDs: osmEntity.id.next,
74041 // note the time the changes were saved
74042 timestamp: new Date().getTime()
74045 fromJSON: function fromJSON(json, loadChildNodes) {
74046 var h = JSON.parse(json);
74047 var loadComplete = true;
74048 osmEntity.id.next = h.nextIDs;
74051 if (h.version === 2 || h.version === 3) {
74052 var allEntities = {};
74053 h.entities.forEach(function (entity) {
74054 allEntities[osmEntity.key(entity)] = osmEntity(entity);
74057 if (h.version === 3) {
74058 // This merges originals for changed entities into the base of
74059 // the _stack even if the current _stack doesn't have them (for
74060 // example when iD has been restarted in a different region)
74061 var baseEntities = h.baseEntities.map(function (d) {
74062 return osmEntity(d);
74065 var stack = _stack.map(function (state) {
74066 return state.graph;
74069 _stack[0].graph.rebase(baseEntities, stack, true);
74071 _tree.rebase(baseEntities, true); // When we restore a modified way, we also need to fetch any missing
74072 // childnodes that would normally have been downloaded with it.. #2142
74075 if (loadChildNodes) {
74076 var osm = context.connection();
74077 var baseWays = baseEntities.filter(function (e) {
74078 return e.type === 'way';
74080 var nodeIDs = baseWays.reduce(function (acc, way) {
74081 return utilArrayUnion(acc, way.nodes);
74083 var missing = nodeIDs.filter(function (n) {
74084 return !_stack[0].graph.hasEntity(n);
74087 if (missing.length && osm) {
74088 loadComplete = false;
74089 context.map().redrawEnable(false);
74090 var loading = uiLoading(context).blocking(true);
74091 context.container().call(loading);
74093 var childNodesLoaded = function childNodesLoaded(err, result) {
74095 var visibleGroups = utilArrayGroupBy(result.data, 'visible');
74096 var visibles = visibleGroups["true"] || []; // alive nodes
74098 var invisibles = visibleGroups["false"] || []; // deleted nodes
74100 if (visibles.length) {
74101 var visibleIDs = visibles.map(function (entity) {
74105 var stack = _stack.map(function (state) {
74106 return state.graph;
74109 missing = utilArrayDifference(missing, visibleIDs);
74111 _stack[0].graph.rebase(visibles, stack, true);
74113 _tree.rebase(visibles, true);
74114 } // fetch older versions of nodes that were deleted..
74117 invisibles.forEach(function (entity) {
74118 osm.loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
74122 if (err || !missing.length) {
74124 context.map().redrawEnable(true);
74125 dispatch.call('change');
74126 dispatch.call('restore', this);
74130 osm.loadMultiple(missing, childNodesLoaded);
74135 _stack = h.stack.map(function (d) {
74140 d.modified.forEach(function (key) {
74141 entity = allEntities[key];
74142 entities[entity.id] = entity;
74147 d.deleted.forEach(function (id) {
74148 entities[id] = undefined;
74153 graph: coreGraph(_stack[0].graph).load(entities),
74154 annotation: d.annotation,
74155 imageryUsed: d.imageryUsed,
74156 photoOverlaysUsed: d.photoOverlaysUsed,
74157 transform: d.transform,
74158 selectedIDs: d.selectedIDs
74162 // original version
74163 _stack = h.stack.map(function (d) {
74166 for (var i in d.entities) {
74167 var entity = d.entities[i];
74168 entities[i] = entity === 'undefined' ? undefined : osmEntity(entity);
74171 d.graph = coreGraph(_stack[0].graph).load(entities);
74176 var transform = _stack[_index].transform;
74179 context.map().transformEase(transform, 0); // 0 = immediate, no easing
74182 if (loadComplete) {
74183 dispatch.call('change');
74184 dispatch.call('restore', this);
74189 lock: function lock() {
74190 return _lock.lock();
74192 unlock: function unlock() {
74195 save: function save() {
74196 if (_lock.locked() && // don't overwrite existing, unresolved changes
74197 !_hasUnresolvedRestorableChanges) {
74198 var success = corePreferences(getKey('saved_history'), history.toJSON() || null);
74199 if (!success) dispatch.call('storage_error');
74204 // delete the history version saved in localStorage
74205 clearSaved: function clearSaved() {
74206 context.debouncedSave.cancel();
74208 if (_lock.locked()) {
74209 _hasUnresolvedRestorableChanges = false;
74210 corePreferences(getKey('saved_history'), null); // clear the changeset metadata associated with the saved history
74212 corePreferences('comment', null);
74213 corePreferences('hashtags', null);
74214 corePreferences('source', null);
74219 savedHistoryJSON: function savedHistoryJSON() {
74220 return corePreferences(getKey('saved_history'));
74222 hasRestorableChanges: function hasRestorableChanges() {
74223 return _hasUnresolvedRestorableChanges;
74225 // load history from a version stored in localStorage
74226 restore: function restore() {
74227 if (_lock.locked()) {
74228 _hasUnresolvedRestorableChanges = false;
74229 var json = this.savedHistoryJSON();
74230 if (json) history.fromJSON(json, true);
74236 return utilRebind(history, dispatch, 'on');
74240 * Look for roads that can be connected to other roads with a short extension
74243 function validationAlmostJunction(context) {
74244 var type = 'almost_junction';
74245 var EXTEND_TH_METERS = 5;
74246 var WELD_TH_METERS = 0.75; // Comes from considering bounding case of parallel ways
74248 var CLOSE_NODE_TH = EXTEND_TH_METERS - WELD_TH_METERS; // Comes from considering bounding case of perpendicular ways
74250 var SIG_ANGLE_TH = Math.atan(WELD_TH_METERS / EXTEND_TH_METERS);
74252 function isHighway(entity) {
74253 return entity.type === 'way' && osmRoutableHighwayTagValues[entity.tags.highway];
74256 function isTaggedAsNotContinuing(node) {
74257 return node.tags.noexit === 'yes' || node.tags.amenity === 'parking_entrance' || node.tags.entrance && node.tags.entrance !== 'no';
74260 var validation = function checkAlmostJunction(entity, graph) {
74261 if (!isHighway(entity)) return [];
74262 if (entity.isDegenerate()) return [];
74263 var tree = context.history().tree();
74264 var extendableNodeInfos = findConnectableEndNodesByExtension(entity);
74266 extendableNodeInfos.forEach(function (extendableNodeInfo) {
74267 issues.push(new validationIssue({
74269 subtype: 'highway-highway',
74270 severity: 'warning',
74271 message: function message(context) {
74272 var entity1 = context.hasEntity(this.entityIds[0]);
74274 if (this.entityIds[0] === this.entityIds[2]) {
74275 return entity1 ? _t.html('issues.almost_junction.self.message', {
74276 feature: utilDisplayLabel(entity1, context.graph())
74279 var entity2 = context.hasEntity(this.entityIds[2]);
74280 return entity1 && entity2 ? _t.html('issues.almost_junction.message', {
74281 feature: utilDisplayLabel(entity1, context.graph()),
74282 feature2: utilDisplayLabel(entity2, context.graph())
74286 reference: showReference,
74287 entityIds: [entity.id, extendableNodeInfo.node.id, extendableNodeInfo.wid],
74288 loc: extendableNodeInfo.node.loc,
74289 hash: JSON.stringify(extendableNodeInfo.node.loc),
74291 midId: extendableNodeInfo.mid.id,
74292 edge: extendableNodeInfo.edge,
74293 cross_loc: extendableNodeInfo.cross_loc
74295 dynamicFixes: makeFixes
74300 function makeFixes(context) {
74301 var fixes = [new validationIssueFix({
74302 icon: 'iD-icon-abutment',
74303 title: _t.html('issues.fix.connect_features.title'),
74304 onClick: function onClick(context) {
74305 var annotation = _t('issues.fix.connect_almost_junction.annotation');
74307 var _this$issue$entityIds = _slicedToArray(this.issue.entityIds, 3),
74308 endNodeId = _this$issue$entityIds[1],
74309 crossWayId = _this$issue$entityIds[2];
74311 var midNode = context.entity(this.issue.data.midId);
74312 var endNode = context.entity(endNodeId);
74313 var crossWay = context.entity(crossWayId); // When endpoints are close, just join if resulting small change in angle (#7201)
74315 var nearEndNodes = findNearbyEndNodes(endNode, crossWay);
74317 if (nearEndNodes.length > 0) {
74318 var collinear = findSmallJoinAngle(midNode, endNode, nearEndNodes);
74321 context.perform(actionMergeNodes([collinear.id, endNode.id], collinear.loc), annotation);
74326 var targetEdge = this.issue.data.edge;
74327 var crossLoc = this.issue.data.cross_loc;
74328 var edgeNodes = [context.entity(targetEdge[0]), context.entity(targetEdge[1])];
74329 var closestNodeInfo = geoSphericalClosestNode(edgeNodes, crossLoc); // already a point nearby, just connect to that
74331 if (closestNodeInfo.distance < WELD_TH_METERS) {
74332 context.perform(actionMergeNodes([closestNodeInfo.node.id, endNode.id], closestNodeInfo.node.loc), annotation); // else add the end node to the edge way
74334 context.perform(actionAddMidpoint({
74337 }, endNode), annotation);
74341 var node = context.hasEntity(this.entityIds[1]);
74343 if (node && !node.hasInterestingTags()) {
74344 // node has no descriptive tags, suggest noexit fix
74345 fixes.push(new validationIssueFix({
74346 icon: 'maki-barrier',
74347 title: _t.html('issues.fix.tag_as_disconnected.title'),
74348 onClick: function onClick(context) {
74349 var nodeID = this.issue.entityIds[1];
74350 var tags = Object.assign({}, context.entity(nodeID).tags);
74351 tags.noexit = 'yes';
74352 context.perform(actionChangeTags(nodeID, tags), _t('issues.fix.tag_as_disconnected.annotation'));
74360 function showReference(selection) {
74361 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.almost_junction.highway-highway.reference'));
74364 function isExtendableCandidate(node, way) {
74365 // can not accurately test vertices on tiles not downloaded from osm - #5938
74366 var osm = services.osm;
74368 if (osm && !osm.isDataLoaded(node.loc)) {
74372 if (isTaggedAsNotContinuing(node) || graph.parentWays(node).length !== 1) {
74376 var occurrences = 0;
74378 for (var index in way.nodes) {
74379 if (way.nodes[index] === node.id) {
74382 if (occurrences > 1) {
74391 function findConnectableEndNodesByExtension(way) {
74393 if (way.isClosed()) return results;
74395 var indices = [0, way.nodes.length - 1];
74396 indices.forEach(function (nodeIndex) {
74397 var nodeID = way.nodes[nodeIndex];
74398 var node = graph.entity(nodeID);
74399 if (!isExtendableCandidate(node, way)) return;
74400 var connectionInfo = canConnectByExtend(way, nodeIndex);
74401 if (!connectionInfo) return;
74402 testNodes = graph.childNodes(way).slice(); // shallow copy
74404 testNodes[nodeIndex] = testNodes[nodeIndex].move(connectionInfo.cross_loc); // don't flag issue if connecting the ways would cause self-intersection
74406 if (geoHasSelfIntersections(testNodes, nodeID)) return;
74407 results.push(connectionInfo);
74412 function findNearbyEndNodes(node, way) {
74413 return [way.nodes[0], way.nodes[way.nodes.length - 1]].map(function (d) {
74414 return graph.entity(d);
74415 }).filter(function (d) {
74416 // Node cannot be near to itself, but other endnode of same way could be
74417 return d.id !== node.id && geoSphericalDistance(node.loc, d.loc) <= CLOSE_NODE_TH;
74421 function findSmallJoinAngle(midNode, tipNode, endNodes) {
74422 // Both nodes could be close, so want to join whichever is closest to collinear
74424 var minAngle = Infinity; // Checks midNode -> tipNode -> endNode for collinearity
74426 endNodes.forEach(function (endNode) {
74427 var a1 = geoAngle(midNode, tipNode, context.projection) + Math.PI;
74428 var a2 = geoAngle(midNode, endNode, context.projection) + Math.PI;
74429 var diff = Math.max(a1, a2) - Math.min(a1, a2);
74431 if (diff < minAngle) {
74436 /* Threshold set by considering right angle triangle
74437 based on node joining threshold and extension distance */
74439 if (minAngle <= SIG_ANGLE_TH) return joinTo;
74443 function hasTag(tags, key) {
74444 return tags[key] !== undefined && tags[key] !== 'no';
74447 function canConnectWays(way, way2) {
74448 // allow self-connections
74449 if (way.id === way2.id) return true; // if one is bridge or tunnel, both must be bridge or tunnel
74451 if ((hasTag(way.tags, 'bridge') || hasTag(way2.tags, 'bridge')) && !(hasTag(way.tags, 'bridge') && hasTag(way2.tags, 'bridge'))) return false;
74452 if ((hasTag(way.tags, 'tunnel') || hasTag(way2.tags, 'tunnel')) && !(hasTag(way.tags, 'tunnel') && hasTag(way2.tags, 'tunnel'))) return false; // must have equivalent layers and levels
74454 var layer1 = way.tags.layer || '0',
74455 layer2 = way2.tags.layer || '0';
74456 if (layer1 !== layer2) return false;
74457 var level1 = way.tags.level || '0',
74458 level2 = way2.tags.level || '0';
74459 if (level1 !== level2) return false;
74463 function canConnectByExtend(way, endNodeIdx) {
74464 var tipNid = way.nodes[endNodeIdx]; // the 'tip' node for extension point
74466 var midNid = endNodeIdx === 0 ? way.nodes[1] : way.nodes[way.nodes.length - 2]; // the other node of the edge
74468 var tipNode = graph.entity(tipNid);
74469 var midNode = graph.entity(midNid);
74470 var lon = tipNode.loc[0];
74471 var lat = tipNode.loc[1];
74472 var lon_range = geoMetersToLon(EXTEND_TH_METERS, lat) / 2;
74473 var lat_range = geoMetersToLat(EXTEND_TH_METERS) / 2;
74474 var queryExtent = geoExtent([[lon - lon_range, lat - lat_range], [lon + lon_range, lat + lat_range]]); // first, extend the edge of [midNode -> tipNode] by EXTEND_TH_METERS and find the "extended tip" location
74476 var edgeLen = geoSphericalDistance(midNode.loc, tipNode.loc);
74477 var t = EXTEND_TH_METERS / edgeLen + 1.0;
74478 var extTipLoc = geoVecInterp(midNode.loc, tipNode.loc, t); // then, check if the extension part [tipNode.loc -> extTipLoc] intersects any other ways
74480 var segmentInfos = tree.waySegments(queryExtent, graph);
74482 for (var i = 0; i < segmentInfos.length; i++) {
74483 var segmentInfo = segmentInfos[i];
74484 var way2 = graph.entity(segmentInfo.wayId);
74485 if (!isHighway(way2)) continue;
74486 if (!canConnectWays(way, way2)) continue;
74487 var nAid = segmentInfo.nodes[0],
74488 nBid = segmentInfo.nodes[1];
74489 if (nAid === tipNid || nBid === tipNid) continue;
74490 var nA = graph.entity(nAid),
74491 nB = graph.entity(nBid);
74492 var crossLoc = geoLineIntersection([tipNode.loc, extTipLoc], [nA.loc, nB.loc]);
74499 edge: [nA.id, nB.id],
74500 cross_loc: crossLoc
74509 validation.type = type;
74513 function validationCloseNodes(context) {
74514 var type = 'close_nodes';
74515 var pointThresholdMeters = 0.2;
74517 var validation = function validation(entity, graph) {
74518 if (entity.type === 'node') {
74519 return getIssuesForNode(entity);
74520 } else if (entity.type === 'way') {
74521 return getIssuesForWay(entity);
74526 function getIssuesForNode(node) {
74527 var parentWays = graph.parentWays(node);
74529 if (parentWays.length) {
74530 return getIssuesForVertex(node, parentWays);
74532 return getIssuesForDetachedPoint(node);
74536 function wayTypeFor(way) {
74537 if (way.tags.boundary && way.tags.boundary !== 'no') return 'boundary';
74538 if (way.tags.indoor && way.tags.indoor !== 'no') return 'indoor';
74539 if (way.tags.building && way.tags.building !== 'no' || way.tags['building:part'] && way.tags['building:part'] !== 'no') return 'building';
74540 if (osmPathHighwayTagValues[way.tags.highway]) return 'path';
74541 var parentRelations = graph.parentRelations(way);
74543 for (var i in parentRelations) {
74544 var relation = parentRelations[i];
74545 if (relation.tags.type === 'boundary') return 'boundary';
74547 if (relation.isMultipolygon()) {
74548 if (relation.tags.indoor && relation.tags.indoor !== 'no') return 'indoor';
74549 if (relation.tags.building && relation.tags.building !== 'no' || relation.tags['building:part'] && relation.tags['building:part'] !== 'no') return 'building';
74556 function shouldCheckWay(way) {
74557 // don't flag issues where merging would create degenerate ways
74558 if (way.nodes.length <= 2 || way.isClosed() && way.nodes.length <= 4) return false;
74559 var bbox = way.extent(graph).bbox();
74560 var hypotenuseMeters = geoSphericalDistance([bbox.minX, bbox.minY], [bbox.maxX, bbox.maxY]); // don't flag close nodes in very small ways
74562 if (hypotenuseMeters < 1.5) return false;
74566 function getIssuesForWay(way) {
74567 if (!shouldCheckWay(way)) return [];
74569 nodes = graph.childNodes(way);
74571 for (var i = 0; i < nodes.length - 1; i++) {
74572 var node1 = nodes[i];
74573 var node2 = nodes[i + 1];
74574 var issue = getWayIssueIfAny(node1, node2, way);
74575 if (issue) issues.push(issue);
74581 function getIssuesForVertex(node, parentWays) {
74584 function checkForCloseness(node1, node2, way) {
74585 var issue = getWayIssueIfAny(node1, node2, way);
74586 if (issue) issues.push(issue);
74589 for (var i = 0; i < parentWays.length; i++) {
74590 var parentWay = parentWays[i];
74591 if (!shouldCheckWay(parentWay)) continue;
74592 var lastIndex = parentWay.nodes.length - 1;
74594 for (var j = 0; j < parentWay.nodes.length; j++) {
74596 if (parentWay.nodes[j - 1] === node.id) {
74597 checkForCloseness(node, graph.entity(parentWay.nodes[j]), parentWay);
74601 if (j !== lastIndex) {
74602 if (parentWay.nodes[j + 1] === node.id) {
74603 checkForCloseness(graph.entity(parentWay.nodes[j]), node, parentWay);
74612 function thresholdMetersForWay(way) {
74613 if (!shouldCheckWay(way)) return 0;
74614 var wayType = wayTypeFor(way); // don't flag boundaries since they might be highly detailed and can't be easily verified
74616 if (wayType === 'boundary') return 0; // expect some features to be mapped with higher levels of detail
74618 if (wayType === 'indoor') return 0.01;
74619 if (wayType === 'building') return 0.05;
74620 if (wayType === 'path') return 0.1;
74624 function getIssuesForDetachedPoint(node) {
74626 var lon = node.loc[0];
74627 var lat = node.loc[1];
74628 var lon_range = geoMetersToLon(pointThresholdMeters, lat) / 2;
74629 var lat_range = geoMetersToLat(pointThresholdMeters) / 2;
74630 var queryExtent = geoExtent([[lon - lon_range, lat - lat_range], [lon + lon_range, lat + lat_range]]);
74631 var intersected = context.history().tree().intersects(queryExtent, graph);
74633 for (var j = 0; j < intersected.length; j++) {
74634 var nearby = intersected[j];
74635 if (nearby.id === node.id) continue;
74636 if (nearby.type !== 'node' || nearby.geometry(graph) !== 'point') continue;
74638 if (nearby.loc === node.loc || geoSphericalDistance(node.loc, nearby.loc) < pointThresholdMeters) {
74639 // allow very close points if tags indicate the z-axis might vary
74643 'addr:housenumber': true,
74646 var zAxisDifferentiates = false;
74648 for (var key in zAxisKeys) {
74649 var nodeValue = node.tags[key] || '0';
74650 var nearbyValue = nearby.tags[key] || '0';
74652 if (nodeValue !== nearbyValue) {
74653 zAxisDifferentiates = true;
74658 if (zAxisDifferentiates) continue;
74659 issues.push(new validationIssue({
74661 subtype: 'detached',
74662 severity: 'warning',
74663 message: function message(context) {
74664 var entity = context.hasEntity(this.entityIds[0]),
74665 entity2 = context.hasEntity(this.entityIds[1]);
74666 return entity && entity2 ? _t.html('issues.close_nodes.detached.message', {
74667 feature: utilDisplayLabel(entity, context.graph()),
74668 feature2: utilDisplayLabel(entity2, context.graph())
74671 reference: showReference,
74672 entityIds: [node.id, nearby.id],
74673 dynamicFixes: function dynamicFixes() {
74674 return [new validationIssueFix({
74675 icon: 'iD-operation-disconnect',
74676 title: _t.html('issues.fix.move_points_apart.title')
74677 }), new validationIssueFix({
74678 icon: 'iD-icon-layers',
74679 title: _t.html('issues.fix.use_different_layers_or_levels.title')
74688 function showReference(selection) {
74689 var referenceText = _t('issues.close_nodes.detached.reference');
74690 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').html(referenceText);
74694 function getWayIssueIfAny(node1, node2, way) {
74695 if (node1.id === node2.id || node1.hasInterestingTags() && node2.hasInterestingTags()) {
74699 if (node1.loc !== node2.loc) {
74700 var parentWays1 = graph.parentWays(node1);
74701 var parentWays2 = new Set(graph.parentWays(node2));
74702 var sharedWays = parentWays1.filter(function (parentWay) {
74703 return parentWays2.has(parentWay);
74705 var thresholds = sharedWays.map(function (parentWay) {
74706 return thresholdMetersForWay(parentWay);
74708 var threshold = Math.min.apply(Math, _toConsumableArray(thresholds));
74709 var distance = geoSphericalDistance(node1.loc, node2.loc);
74710 if (distance > threshold) return null;
74713 return new validationIssue({
74715 subtype: 'vertices',
74716 severity: 'warning',
74717 message: function message(context) {
74718 var entity = context.hasEntity(this.entityIds[0]);
74719 return entity ? _t.html('issues.close_nodes.message', {
74720 way: utilDisplayLabel(entity, context.graph())
74723 reference: showReference,
74724 entityIds: [way.id, node1.id, node2.id],
74726 dynamicFixes: function dynamicFixes() {
74727 return [new validationIssueFix({
74728 icon: 'iD-icon-plus',
74729 title: _t.html('issues.fix.merge_points.title'),
74730 onClick: function onClick(context) {
74731 var entityIds = this.issue.entityIds;
74732 var action = actionMergeNodes([entityIds[1], entityIds[2]]);
74733 context.perform(action, _t('issues.fix.merge_close_vertices.annotation'));
74735 }), new validationIssueFix({
74736 icon: 'iD-operation-disconnect',
74737 title: _t.html('issues.fix.move_points_apart.title')
74742 function showReference(selection) {
74743 var referenceText = _t('issues.close_nodes.reference');
74744 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').html(referenceText);
74749 validation.type = type;
74753 function validationCrossingWays(context) {
74754 var type = 'crossing_ways'; // returns the way or its parent relation, whichever has a useful feature type
74756 function getFeatureWithFeatureTypeTagsForWay(way, graph) {
74757 if (getFeatureType(way, graph) === null) {
74758 // if the way doesn't match a feature type, check its parent relations
74759 var parentRels = graph.parentRelations(way);
74761 for (var i = 0; i < parentRels.length; i++) {
74762 var rel = parentRels[i];
74764 if (getFeatureType(rel, graph) !== null) {
74773 function hasTag(tags, key) {
74774 return tags[key] !== undefined && tags[key] !== 'no';
74777 function taggedAsIndoor(tags) {
74778 return hasTag(tags, 'indoor') || hasTag(tags, 'level') || tags.highway === 'corridor';
74781 function allowsBridge(featureType) {
74782 return featureType === 'highway' || featureType === 'railway' || featureType === 'waterway';
74785 function allowsTunnel(featureType) {
74786 return featureType === 'highway' || featureType === 'railway' || featureType === 'waterway';
74790 var ignoredBuildings = {
74797 function getFeatureType(entity, graph) {
74798 var geometry = entity.geometry(graph);
74799 if (geometry !== 'line' && geometry !== 'area') return null;
74800 var tags = entity.tags;
74801 if (hasTag(tags, 'building') && !ignoredBuildings[tags.building]) return 'building';
74802 if (hasTag(tags, 'highway') && osmRoutableHighwayTagValues[tags.highway]) return 'highway'; // don't check railway or waterway areas
74804 if (geometry !== 'line') return null;
74805 if (hasTag(tags, 'railway') && osmRailwayTrackTagValues[tags.railway]) return 'railway';
74806 if (hasTag(tags, 'waterway') && osmFlowingWaterwayTagValues[tags.waterway]) return 'waterway';
74810 function isLegitCrossing(tags1, featureType1, tags2, featureType2) {
74811 // assume 0 by default
74812 var level1 = tags1.level || '0';
74813 var level2 = tags2.level || '0';
74815 if (taggedAsIndoor(tags1) && taggedAsIndoor(tags2) && level1 !== level2) {
74816 // assume features don't interact if they're indoor on different levels
74818 } // assume 0 by default; don't use way.layer() since we account for structures here
74821 var layer1 = tags1.layer || '0';
74822 var layer2 = tags2.layer || '0';
74824 if (allowsBridge(featureType1) && allowsBridge(featureType2)) {
74825 if (hasTag(tags1, 'bridge') && !hasTag(tags2, 'bridge')) return true;
74826 if (!hasTag(tags1, 'bridge') && hasTag(tags2, 'bridge')) return true; // crossing bridges must use different layers
74828 if (hasTag(tags1, 'bridge') && hasTag(tags2, 'bridge') && layer1 !== layer2) return true;
74829 } else if (allowsBridge(featureType1) && hasTag(tags1, 'bridge')) return true;else if (allowsBridge(featureType2) && hasTag(tags2, 'bridge')) return true;
74831 if (allowsTunnel(featureType1) && allowsTunnel(featureType2)) {
74832 if (hasTag(tags1, 'tunnel') && !hasTag(tags2, 'tunnel')) return true;
74833 if (!hasTag(tags1, 'tunnel') && hasTag(tags2, 'tunnel')) return true; // crossing tunnels must use different layers
74835 if (hasTag(tags1, 'tunnel') && hasTag(tags2, 'tunnel') && layer1 !== layer2) return true;
74836 } else if (allowsTunnel(featureType1) && hasTag(tags1, 'tunnel')) return true;else if (allowsTunnel(featureType2) && hasTag(tags2, 'tunnel')) return true; // don't flag crossing waterways and pier/highways
74839 if (featureType1 === 'waterway' && featureType2 === 'highway' && tags2.man_made === 'pier') return true;
74840 if (featureType2 === 'waterway' && featureType1 === 'highway' && tags1.man_made === 'pier') return true;
74842 if (featureType1 === 'building' || featureType2 === 'building') {
74843 // for building crossings, different layers are enough
74844 if (layer1 !== layer2) return true;
74848 } // highway values for which we shouldn't recommend connecting to waterways
74851 var highwaysDisallowingFords = {
74853 motorway_link: true,
74857 primary_link: true,
74859 secondary_link: true
74861 var nonCrossingHighways = {
74865 function tagsForConnectionNodeIfAllowed(entity1, entity2, graph) {
74866 var featureType1 = getFeatureType(entity1, graph);
74867 var featureType2 = getFeatureType(entity2, graph);
74868 var geometry1 = entity1.geometry(graph);
74869 var geometry2 = entity2.geometry(graph);
74870 var bothLines = geometry1 === 'line' && geometry2 === 'line';
74872 if (featureType1 === featureType2) {
74873 if (featureType1 === 'highway') {
74874 var entity1IsPath = osmPathHighwayTagValues[entity1.tags.highway];
74875 var entity2IsPath = osmPathHighwayTagValues[entity2.tags.highway];
74877 if ((entity1IsPath || entity2IsPath) && entity1IsPath !== entity2IsPath) {
74878 // one feature is a path but not both
74879 var roadFeature = entity1IsPath ? entity2 : entity1;
74881 if (nonCrossingHighways[roadFeature.tags.highway]) {
74882 // don't mark path connections with certain roads as crossings
74886 var pathFeature = entity1IsPath ? entity1 : entity2;
74888 if (['marked', 'unmarked'].indexOf(pathFeature.tags.crossing) !== -1) {
74889 // if the path is a crossing, match the crossing type
74890 return bothLines ? {
74891 highway: 'crossing',
74892 crossing: pathFeature.tags.crossing
74894 } // don't add a `crossing` subtag to ambiguous crossings
74897 return bothLines ? {
74898 highway: 'crossing'
74905 if (featureType1 === 'waterway') return {};
74906 if (featureType1 === 'railway') return {};
74908 var featureTypes = [featureType1, featureType2];
74910 if (featureTypes.indexOf('highway') !== -1) {
74911 if (featureTypes.indexOf('railway') !== -1) {
74912 if (!bothLines) return {};
74913 var isTram = entity1.tags.railway === 'tram' || entity2.tags.railway === 'tram';
74915 if (osmPathHighwayTagValues[entity1.tags.highway] || osmPathHighwayTagValues[entity2.tags.highway]) {
74916 // path-tram connections use this tag
74917 if (isTram) return {
74918 railway: 'tram_crossing'
74919 }; // other path-rail connections use this tag
74922 railway: 'crossing'
74925 // path-tram connections use this tag
74926 if (isTram) return {
74927 railway: 'tram_level_crossing'
74928 }; // other road-rail connections use this tag
74931 railway: 'level_crossing'
74936 if (featureTypes.indexOf('waterway') !== -1) {
74937 // do not allow fords on structures
74938 if (hasTag(entity1.tags, 'tunnel') && hasTag(entity2.tags, 'tunnel')) return null;
74939 if (hasTag(entity1.tags, 'bridge') && hasTag(entity2.tags, 'bridge')) return null;
74941 if (highwaysDisallowingFords[entity1.tags.highway] || highwaysDisallowingFords[entity2.tags.highway]) {
74942 // do not allow fords on major highways
74946 return bothLines ? {
74956 function findCrossingsByWay(way1, graph, tree) {
74957 var edgeCrossInfos = [];
74958 if (way1.type !== 'way') return edgeCrossInfos;
74959 var taggedFeature1 = getFeatureWithFeatureTypeTagsForWay(way1, graph);
74960 var way1FeatureType = getFeatureType(taggedFeature1, graph);
74961 if (way1FeatureType === null) return edgeCrossInfos;
74962 var checkedSingleCrossingWays = {}; // declare vars ahead of time to reduce garbage collection
74966 var n1, n2, nA, nB, nAId, nBId;
74967 var segment1, segment2;
74969 var segmentInfos, segment2Info, way2, taggedFeature2, way2FeatureType;
74970 var way1Nodes = graph.childNodes(way1);
74971 var comparedWays = {};
74973 for (i = 0; i < way1Nodes.length - 1; i++) {
74975 n2 = way1Nodes[i + 1];
74976 extent = geoExtent([[Math.min(n1.loc[0], n2.loc[0]), Math.min(n1.loc[1], n2.loc[1])], [Math.max(n1.loc[0], n2.loc[0]), Math.max(n1.loc[1], n2.loc[1])]]); // Optimize by only checking overlapping segments, not every segment
74977 // of overlapping ways
74979 segmentInfos = tree.waySegments(extent, graph);
74981 for (j = 0; j < segmentInfos.length; j++) {
74982 segment2Info = segmentInfos[j]; // don't check for self-intersection in this validation
74984 if (segment2Info.wayId === way1.id) continue; // skip if this way was already checked and only one issue is needed
74986 if (checkedSingleCrossingWays[segment2Info.wayId]) continue; // mark this way as checked even if there are no crossings
74988 comparedWays[segment2Info.wayId] = true;
74989 way2 = graph.hasEntity(segment2Info.wayId);
74990 if (!way2) continue;
74991 taggedFeature2 = getFeatureWithFeatureTypeTagsForWay(way2, graph); // only check crossing highway, waterway, building, and railway
74993 way2FeatureType = getFeatureType(taggedFeature2, graph);
74995 if (way2FeatureType === null || isLegitCrossing(taggedFeature1.tags, way1FeatureType, taggedFeature2.tags, way2FeatureType)) {
74997 } // create only one issue for building crossings
75000 oneOnly = way1FeatureType === 'building' || way2FeatureType === 'building';
75001 nAId = segment2Info.nodes[0];
75002 nBId = segment2Info.nodes[1];
75004 if (nAId === n1.id || nAId === n2.id || nBId === n1.id || nBId === n2.id) {
75005 // n1 or n2 is a connection node; skip
75009 nA = graph.hasEntity(nAId);
75011 nB = graph.hasEntity(nBId);
75013 segment1 = [n1.loc, n2.loc];
75014 segment2 = [nA.loc, nB.loc];
75015 var point = geoLineIntersection(segment1, segment2);
75018 edgeCrossInfos.push({
75021 featureType: way1FeatureType,
75022 edge: [n1.id, n2.id]
75025 featureType: way2FeatureType,
75026 edge: [nA.id, nB.id]
75032 checkedSingleCrossingWays[way2.id] = true;
75039 return edgeCrossInfos;
75042 function waysToCheck(entity, graph) {
75043 var featureType = getFeatureType(entity, graph);
75044 if (!featureType) return [];
75046 if (entity.type === 'way') {
75048 } else if (entity.type === 'relation') {
75049 return entity.members.reduce(function (array, member) {
75050 if (member.type === 'way' && ( // only look at geometry ways
75051 !member.role || member.role === 'outer' || member.role === 'inner')) {
75052 var entity = graph.hasEntity(member.id); // don't add duplicates
75054 if (entity && array.indexOf(entity) === -1) {
75055 array.push(entity);
75066 var validation = function checkCrossingWays(entity, graph) {
75067 var tree = context.history().tree();
75068 var ways = waysToCheck(entity, graph);
75069 var issues = []; // declare these here to reduce garbage collection
75071 var wayIndex, crossingIndex, crossings;
75073 for (wayIndex in ways) {
75074 crossings = findCrossingsByWay(ways[wayIndex], graph, tree);
75076 for (crossingIndex in crossings) {
75077 issues.push(createIssue(crossings[crossingIndex], graph));
75084 function createIssue(crossing, graph) {
75085 // use the entities with the tags that define the feature type
75086 crossing.wayInfos.sort(function (way1Info, way2Info) {
75087 var type1 = way1Info.featureType;
75088 var type2 = way2Info.featureType;
75090 if (type1 === type2) {
75091 return utilDisplayLabel(way1Info.way, graph) > utilDisplayLabel(way2Info.way, graph);
75092 } else if (type1 === 'waterway') {
75094 } else if (type2 === 'waterway') {
75098 return type1 < type2;
75100 var entities = crossing.wayInfos.map(function (wayInfo) {
75101 return getFeatureWithFeatureTypeTagsForWay(wayInfo.way, graph);
75103 var edges = [crossing.wayInfos[0].edge, crossing.wayInfos[1].edge];
75104 var featureTypes = [crossing.wayInfos[0].featureType, crossing.wayInfos[1].featureType];
75105 var connectionTags = tagsForConnectionNodeIfAllowed(entities[0], entities[1], graph);
75106 var featureType1 = crossing.wayInfos[0].featureType;
75107 var featureType2 = crossing.wayInfos[1].featureType;
75108 var isCrossingIndoors = taggedAsIndoor(entities[0].tags) && taggedAsIndoor(entities[1].tags);
75109 var isCrossingTunnels = allowsTunnel(featureType1) && hasTag(entities[0].tags, 'tunnel') && allowsTunnel(featureType2) && hasTag(entities[1].tags, 'tunnel');
75110 var isCrossingBridges = allowsBridge(featureType1) && hasTag(entities[0].tags, 'bridge') && allowsBridge(featureType2) && hasTag(entities[1].tags, 'bridge');
75111 var subtype = [featureType1, featureType2].sort().join('-');
75112 var crossingTypeID = subtype;
75114 if (isCrossingIndoors) {
75115 crossingTypeID = 'indoor-indoor';
75116 } else if (isCrossingTunnels) {
75117 crossingTypeID = 'tunnel-tunnel';
75118 } else if (isCrossingBridges) {
75119 crossingTypeID = 'bridge-bridge';
75122 if (connectionTags && (isCrossingIndoors || isCrossingTunnels || isCrossingBridges)) {
75123 crossingTypeID += '_connectable';
75124 } // Differentiate based on the loc rounded to 4 digits, since two ways can cross multiple times.
75127 var uniqueID = crossing.crossPoint[0].toFixed(4) + ',' + crossing.crossPoint[1].toFixed(4);
75128 return new validationIssue({
75131 severity: 'warning',
75132 message: function message(context) {
75133 var graph = context.graph();
75134 var entity1 = graph.hasEntity(this.entityIds[0]),
75135 entity2 = graph.hasEntity(this.entityIds[1]);
75136 return entity1 && entity2 ? _t.html('issues.crossing_ways.message', {
75137 feature: utilDisplayLabel(entity1, graph),
75138 feature2: utilDisplayLabel(entity2, graph)
75141 reference: showReference,
75142 entityIds: entities.map(function (entity) {
75147 featureTypes: featureTypes,
75148 connectionTags: connectionTags
75151 loc: crossing.crossPoint,
75152 dynamicFixes: function dynamicFixes(context) {
75153 var mode = context.mode();
75154 if (!mode || mode.id !== 'select' || mode.selectedIDs().length !== 1) return [];
75155 var selectedIndex = this.entityIds[0] === mode.selectedIDs()[0] ? 0 : 1;
75156 var selectedFeatureType = this.data.featureTypes[selectedIndex];
75157 var otherFeatureType = this.data.featureTypes[selectedIndex === 0 ? 1 : 0];
75160 if (connectionTags) {
75161 fixes.push(makeConnectWaysFix(this.data.connectionTags));
75164 if (isCrossingIndoors) {
75165 fixes.push(new validationIssueFix({
75166 icon: 'iD-icon-layers',
75167 title: _t.html('issues.fix.use_different_levels.title')
75169 } else if (isCrossingTunnels || isCrossingBridges || featureType1 === 'building' || featureType2 === 'building') {
75170 fixes.push(makeChangeLayerFix('higher'));
75171 fixes.push(makeChangeLayerFix('lower')); // can only add bridge/tunnel if both features are lines
75172 } else if (context.graph().geometry(this.entityIds[0]) === 'line' && context.graph().geometry(this.entityIds[1]) === 'line') {
75173 // don't recommend adding bridges to waterways since they're uncommon
75174 if (allowsBridge(selectedFeatureType) && selectedFeatureType !== 'waterway') {
75175 fixes.push(makeAddBridgeOrTunnelFix('add_a_bridge', 'temaki-bridge', 'bridge'));
75176 } // don't recommend adding tunnels under waterways since they're uncommon
75179 var skipTunnelFix = otherFeatureType === 'waterway' && selectedFeatureType !== 'waterway';
75181 if (allowsTunnel(selectedFeatureType) && !skipTunnelFix) {
75182 fixes.push(makeAddBridgeOrTunnelFix('add_a_tunnel', 'temaki-tunnel', 'tunnel'));
75184 } // repositioning the features is always an option
75187 fixes.push(new validationIssueFix({
75188 icon: 'iD-operation-move',
75189 title: _t.html('issues.fix.reposition_features.title')
75195 function showReference(selection) {
75196 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.crossing_ways.' + crossingTypeID + '.reference'));
75200 function makeAddBridgeOrTunnelFix(fixTitleID, iconName, bridgeOrTunnel) {
75201 return new validationIssueFix({
75203 title: _t.html('issues.fix.' + fixTitleID + '.title'),
75204 onClick: function onClick(context) {
75205 var mode = context.mode();
75206 if (!mode || mode.id !== 'select') return;
75207 var selectedIDs = mode.selectedIDs();
75208 if (selectedIDs.length !== 1) return;
75209 var selectedWayID = selectedIDs[0];
75210 if (!context.hasEntity(selectedWayID)) return;
75211 var resultWayIDs = [selectedWayID];
75212 var edge, crossedEdge, crossedWayID;
75214 if (this.issue.entityIds[0] === selectedWayID) {
75215 edge = this.issue.data.edges[0];
75216 crossedEdge = this.issue.data.edges[1];
75217 crossedWayID = this.issue.entityIds[1];
75219 edge = this.issue.data.edges[1];
75220 crossedEdge = this.issue.data.edges[0];
75221 crossedWayID = this.issue.entityIds[0];
75224 var crossingLoc = this.issue.loc;
75225 var projection = context.projection;
75227 var action = function actionAddStructure(graph) {
75228 var edgeNodes = [graph.entity(edge[0]), graph.entity(edge[1])];
75229 var crossedWay = graph.hasEntity(crossedWayID); // use the explicit width of the crossed feature as the structure length, if available
75231 var structLengthMeters = crossedWay && crossedWay.tags.width && parseFloat(crossedWay.tags.width);
75233 if (!structLengthMeters) {
75234 // if no explicit width is set, approximate the width based on the tags
75235 structLengthMeters = crossedWay && crossedWay.impliedLineWidthMeters();
75238 if (structLengthMeters) {
75239 if (getFeatureType(crossedWay, graph) === 'railway') {
75240 // bridges over railways are generally much longer than the rail bed itself, compensate
75241 structLengthMeters *= 2;
75244 // should ideally never land here since all rail/water/road tags should have an implied width
75245 structLengthMeters = 8;
75248 var a1 = geoAngle(edgeNodes[0], edgeNodes[1], projection) + Math.PI;
75249 var a2 = geoAngle(graph.entity(crossedEdge[0]), graph.entity(crossedEdge[1]), projection) + Math.PI;
75250 var crossingAngle = Math.max(a1, a2) - Math.min(a1, a2);
75251 if (crossingAngle > Math.PI) crossingAngle -= Math.PI; // lengthen the structure to account for the angle of the crossing
75253 structLengthMeters = structLengthMeters / 2 / Math.sin(crossingAngle) * 2; // add padding since the structure must extend past the edges of the crossed feature
75255 structLengthMeters += 4; // clamp the length to a reasonable range
75257 structLengthMeters = Math.min(Math.max(structLengthMeters, 4), 50);
75259 function geomToProj(geoPoint) {
75260 return [geoLonToMeters(geoPoint[0], geoPoint[1]), geoLatToMeters(geoPoint[1])];
75263 function projToGeom(projPoint) {
75264 var lat = geoMetersToLat(projPoint[1]);
75265 return [geoMetersToLon(projPoint[0], lat), lat];
75268 var projEdgeNode1 = geomToProj(edgeNodes[0].loc);
75269 var projEdgeNode2 = geomToProj(edgeNodes[1].loc);
75270 var projectedAngle = geoVecAngle(projEdgeNode1, projEdgeNode2);
75271 var projectedCrossingLoc = geomToProj(crossingLoc);
75272 var linearToSphericalMetersRatio = geoVecLength(projEdgeNode1, projEdgeNode2) / geoSphericalDistance(edgeNodes[0].loc, edgeNodes[1].loc);
75274 function locSphericalDistanceFromCrossingLoc(angle, distanceMeters) {
75275 var lengthSphericalMeters = distanceMeters * linearToSphericalMetersRatio;
75276 return projToGeom([projectedCrossingLoc[0] + Math.cos(angle) * lengthSphericalMeters, projectedCrossingLoc[1] + Math.sin(angle) * lengthSphericalMeters]);
75279 var endpointLocGetter1 = function endpointLocGetter1(lengthMeters) {
75280 return locSphericalDistanceFromCrossingLoc(projectedAngle, lengthMeters);
75283 var endpointLocGetter2 = function endpointLocGetter2(lengthMeters) {
75284 return locSphericalDistanceFromCrossingLoc(projectedAngle + Math.PI, lengthMeters);
75285 }; // avoid creating very short edges from splitting too close to another node
75288 var minEdgeLengthMeters = 0.55; // decide where to bound the structure along the way, splitting as necessary
75290 function determineEndpoint(edge, endNode, locGetter) {
75292 var idealLengthMeters = structLengthMeters / 2; // distance between the crossing location and the end of the edge,
75293 // the maximum length of this side of the structure
75295 var crossingToEdgeEndDistance = geoSphericalDistance(crossingLoc, endNode.loc);
75297 if (crossingToEdgeEndDistance - idealLengthMeters > minEdgeLengthMeters) {
75298 // the edge is long enough to insert a new node
75299 // the loc that would result in the full expected length
75300 var idealNodeLoc = locGetter(idealLengthMeters);
75301 newNode = osmNode();
75302 graph = actionAddMidpoint({
75305 }, newNode)(graph);
75308 endNode.parentIntersectionWays(graph).forEach(function (way) {
75309 way.nodes.forEach(function (nodeID) {
75310 if (nodeID === endNode.id) {
75311 if (endNode.id === way.first() && endNode.id !== way.last() || endNode.id === way.last() && endNode.id !== way.first()) {
75320 if (edgeCount >= 3) {
75321 // the end node is a junction, try to leave a segment
75322 // between it and the structure - #7202
75323 var insetLength = crossingToEdgeEndDistance - minEdgeLengthMeters;
75325 if (insetLength > minEdgeLengthMeters) {
75326 var insetNodeLoc = locGetter(insetLength);
75327 newNode = osmNode();
75328 graph = actionAddMidpoint({
75331 }, newNode)(graph);
75334 } // if the edge is too short to subdivide as desired, then
75335 // just bound the structure at the existing end node
75338 if (!newNode) newNode = endNode;
75339 var splitAction = actionSplit([newNode.id]).limitWays(resultWayIDs); // only split selected or created ways
75342 graph = splitAction(graph);
75344 if (splitAction.getCreatedWayIDs().length) {
75345 resultWayIDs.push(splitAction.getCreatedWayIDs()[0]);
75351 var structEndNode1 = determineEndpoint(edge, edgeNodes[1], endpointLocGetter1);
75352 var structEndNode2 = determineEndpoint([edgeNodes[0].id, structEndNode1.id], edgeNodes[0], endpointLocGetter2);
75353 var structureWay = resultWayIDs.map(function (id) {
75354 return graph.entity(id);
75355 }).find(function (way) {
75356 return way.nodes.indexOf(structEndNode1.id) !== -1 && way.nodes.indexOf(structEndNode2.id) !== -1;
75358 var tags = Object.assign({}, structureWay.tags); // copy tags
75360 if (bridgeOrTunnel === 'bridge') {
75361 tags.bridge = 'yes';
75364 var tunnelValue = 'yes';
75366 if (getFeatureType(structureWay, graph) === 'waterway') {
75367 // use `tunnel=culvert` for waterways by default
75368 tunnelValue = 'culvert';
75371 tags.tunnel = tunnelValue;
75373 } // apply the structure tags to the way
75376 graph = actionChangeTags(structureWay.id, tags)(graph);
75380 context.perform(action, _t('issues.fix.' + fixTitleID + '.annotation'));
75381 context.enter(modeSelect(context, resultWayIDs));
75386 function makeConnectWaysFix(connectionTags) {
75387 var fixTitleID = 'connect_features';
75389 if (connectionTags.ford) {
75390 fixTitleID = 'connect_using_ford';
75393 return new validationIssueFix({
75394 icon: 'iD-icon-crossing',
75395 title: _t.html('issues.fix.' + fixTitleID + '.title'),
75396 onClick: function onClick(context) {
75397 var loc = this.issue.loc;
75398 var connectionTags = this.issue.data.connectionTags;
75399 var edges = this.issue.data.edges;
75400 context.perform(function actionConnectCrossingWays(graph) {
75401 // create the new node for the points
75402 var node = osmNode({
75404 tags: connectionTags
75406 graph = graph.replace(node);
75407 var nodesToMerge = [node.id];
75408 var mergeThresholdInMeters = 0.75;
75409 edges.forEach(function (edge) {
75410 var edgeNodes = [graph.entity(edge[0]), graph.entity(edge[1])];
75411 var nearby = geoSphericalClosestNode(edgeNodes, loc); // if there is already a suitable node nearby, use that
75412 // use the node if node has no interesting tags or if it is a crossing node #8326
75414 if ((!nearby.node.hasInterestingTags() || nearby.node.isCrossing()) && nearby.distance < mergeThresholdInMeters) {
75415 nodesToMerge.push(nearby.node.id); // else add the new node to the way
75417 graph = actionAddMidpoint({
75424 if (nodesToMerge.length > 1) {
75425 // if we're using nearby nodes, merge them with the new node
75426 graph = actionMergeNodes(nodesToMerge, loc)(graph);
75430 }, _t('issues.fix.connect_crossing_features.annotation'));
75435 function makeChangeLayerFix(higherOrLower) {
75436 return new validationIssueFix({
75437 icon: 'iD-icon-' + (higherOrLower === 'higher' ? 'up' : 'down'),
75438 title: _t.html('issues.fix.tag_this_as_' + higherOrLower + '.title'),
75439 onClick: function onClick(context) {
75440 var mode = context.mode();
75441 if (!mode || mode.id !== 'select') return;
75442 var selectedIDs = mode.selectedIDs();
75443 if (selectedIDs.length !== 1) return;
75444 var selectedID = selectedIDs[0];
75445 if (!this.issue.entityIds.some(function (entityId) {
75446 return entityId === selectedID;
75448 var entity = context.hasEntity(selectedID);
75449 if (!entity) return;
75450 var tags = Object.assign({}, entity.tags); // shallow copy
75452 var layer = tags.layer && Number(tags.layer);
75454 if (layer && !isNaN(layer)) {
75455 if (higherOrLower === 'higher') {
75461 if (higherOrLower === 'higher') {
75468 tags.layer = layer.toString();
75469 context.perform(actionChangeTags(entity.id, tags), _t('operations.change_tags.annotation'));
75474 validation.type = type;
75478 function behaviorDrawWay(context, wayID, mode, startGraph) {
75479 var keybinding = utilKeybinding('drawWay');
75480 var dispatch = dispatch$8('rejectedSelfIntersection');
75481 var behavior = behaviorDraw(context); // Must be set by `drawWay.nodeIndex` before each install of this behavior.
75493 var _pointerHasMoved = false; // The osmNode to be placed.
75494 // This is temporary and just follows the mouse cursor until an "add" event occurs.
75498 var _didResolveTempEdit = false;
75500 function createDrawNode(loc) {
75501 // don't make the draw node until we actually need it
75502 _drawNode = osmNode({
75505 context.pauseChangeDispatch();
75506 context.replace(function actionAddDrawNode(graph) {
75507 // add the draw node to the graph and insert it into the way
75508 var way = graph.entity(wayID);
75509 return graph.replace(_drawNode).replace(way.addNode(_drawNode.id, _nodeIndex));
75511 context.resumeChangeDispatch();
75512 setActiveElements();
75515 function removeDrawNode() {
75516 context.pauseChangeDispatch();
75517 context.replace(function actionDeleteDrawNode(graph) {
75518 var way = graph.entity(wayID);
75519 return graph.replace(way.removeNode(_drawNode.id)).remove(_drawNode);
75521 _drawNode = undefined;
75522 context.resumeChangeDispatch();
75525 function keydown(d3_event) {
75526 if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
75527 if (context.surface().classed('nope')) {
75528 context.surface().classed('nope-suppressed', true);
75531 context.surface().classed('nope', false).classed('nope-disabled', true);
75535 function keyup(d3_event) {
75536 if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
75537 if (context.surface().classed('nope-suppressed')) {
75538 context.surface().classed('nope', true);
75541 context.surface().classed('nope-suppressed', false).classed('nope-disabled', false);
75545 function allowsVertex(d) {
75546 return d.geometry(context.graph()) === 'vertex' || _mainPresetIndex.allowsVertex(d, context.graph());
75548 // - `mode/drag_node.js` `doMove()`
75549 // - `behavior/draw.js` `click()`
75550 // - `behavior/draw_way.js` `move()`
75553 function move(d3_event, datum) {
75554 var loc = context.map().mouseCoordinates();
75555 if (!_drawNode) createDrawNode(loc);
75556 context.surface().classed('nope-disabled', d3_event.altKey);
75557 var targetLoc = datum && datum.properties && datum.properties.entity && allowsVertex(datum.properties.entity) && datum.properties.entity.loc;
75558 var targetNodes = datum && datum.properties && datum.properties.nodes;
75561 // snap to node/vertex - a point target with `.loc`
75563 } else if (targetNodes) {
75564 // snap to way - a line target with `.nodes`
75565 var choice = geoChooseEdge(targetNodes, context.map().mouse(), context.projection, _drawNode.id);
75572 context.replace(actionMoveNode(_drawNode.id, loc), _annotation);
75573 _drawNode = context.entity(_drawNode.id);
75575 /* includeDrawNode */
75577 } // Check whether this edit causes the geometry to break.
75578 // If so, class the surface with a nope cursor.
75579 // `includeDrawNode` - Only check the relevant line segments if finishing drawing
75582 function checkGeometry(includeDrawNode) {
75583 var nopeDisabled = context.surface().classed('nope-disabled');
75584 var isInvalid = isInvalidGeometry(includeDrawNode);
75586 if (nopeDisabled) {
75587 context.surface().classed('nope', false).classed('nope-suppressed', isInvalid);
75589 context.surface().classed('nope', isInvalid).classed('nope-suppressed', false);
75593 function isInvalidGeometry(includeDrawNode) {
75594 var testNode = _drawNode; // we only need to test the single way we're drawing
75596 var parentWay = context.graph().entity(wayID);
75597 var nodes = context.graph().childNodes(parentWay).slice(); // shallow copy
75599 if (includeDrawNode) {
75600 if (parentWay.isClosed()) {
75601 // don't test the last segment for closed ways - #4655
75602 // (still test the first segment)
75606 // discount the draw node
75607 if (parentWay.isClosed()) {
75608 if (nodes.length < 3) return false;
75609 if (_drawNode) nodes.splice(-2, 1);
75610 testNode = nodes[nodes.length - 2];
75612 // there's nothing we need to test if we ignore the draw node on open ways
75617 return testNode && geoHasSelfIntersections(nodes, testNode.id);
75620 function undone() {
75621 // undoing removed the temp edit
75622 _didResolveTempEdit = true;
75623 context.pauseChangeDispatch();
75626 if (context.graph() === startGraph) {
75627 // We've undone back to the initial state before we started drawing.
75628 // Just exit the draw mode without undoing whatever we did before
75629 // we entered the draw mode.
75630 nextMode = modeSelect(context, [wayID]);
75632 // The `undo` only removed the temporary edit, so here we have to
75633 // manually undo to actually remove the last node we added. We can't
75634 // use the `undo` function since the initial "add" graph doesn't have
75635 // an annotation and so cannot be undone to.
75636 context.pop(1); // continue drawing
75639 } // clear the redo stack by adding and removing a blank edit
75642 context.perform(actionNoop());
75644 context.resumeChangeDispatch();
75645 context.enter(nextMode);
75648 function setActiveElements() {
75649 if (!_drawNode) return;
75650 context.surface().selectAll('.' + _drawNode.id).classed('active', true);
75653 function resetToStartGraph() {
75654 while (context.graph() !== startGraph) {
75659 var drawWay = function drawWay(surface) {
75660 _drawNode = undefined;
75661 _didResolveTempEdit = false;
75662 _origWay = context.entity(wayID);
75664 if (typeof _nodeIndex === 'number') {
75665 _headNodeID = _origWay.nodes[_nodeIndex];
75666 } else if (_origWay.isClosed()) {
75667 _headNodeID = _origWay.nodes[_origWay.nodes.length - 2];
75669 _headNodeID = _origWay.nodes[_origWay.nodes.length - 1];
75672 _wayGeometry = _origWay.geometry(context.graph());
75673 _annotation = _t((_origWay.nodes.length === (_origWay.isClosed() ? 2 : 1) ? 'operations.start.annotation.' : 'operations.continue.annotation.') + _wayGeometry);
75674 _pointerHasMoved = false; // Push an annotated state for undo to return back to.
75675 // We must make sure to replace or remove it later.
75677 context.pauseChangeDispatch();
75678 context.perform(actionNoop(), _annotation);
75679 context.resumeChangeDispatch();
75680 behavior.hover().initialNodeID(_headNodeID);
75681 behavior.on('move', function () {
75682 _pointerHasMoved = true;
75683 move.apply(this, arguments);
75684 }).on('down', function () {
75685 move.apply(this, arguments);
75686 }).on('downcancel', function () {
75687 if (_drawNode) removeDrawNode();
75688 }).on('click', drawWay.add).on('clickWay', drawWay.addWay).on('clickNode', drawWay.addNode).on('undo', context.undo).on('cancel', drawWay.cancel).on('finish', drawWay.finish);
75689 select(window).on('keydown.drawWay', keydown).on('keyup.drawWay', keyup);
75690 context.map().dblclickZoomEnable(false).on('drawn.draw', setActiveElements);
75691 setActiveElements();
75692 surface.call(behavior);
75693 context.history().on('undone.draw', undone);
75696 drawWay.off = function (surface) {
75697 if (!_didResolveTempEdit) {
75698 // Drawing was interrupted unexpectedly.
75699 // This can happen if the user changes modes,
75700 // clicks geolocate button, a hashchange event occurs, etc.
75701 context.pauseChangeDispatch();
75702 resetToStartGraph();
75703 context.resumeChangeDispatch();
75706 _drawNode = undefined;
75707 _nodeIndex = undefined;
75708 context.map().on('drawn.draw', null);
75709 surface.call(behavior.off).selectAll('.active').classed('active', false);
75710 surface.classed('nope', false).classed('nope-suppressed', false).classed('nope-disabled', false);
75711 select(window).on('keydown.drawWay', null).on('keyup.drawWay', null);
75712 context.history().on('undone.draw', null);
75715 function attemptAdd(d, loc, doAdd) {
75717 // move the node to the final loc in case move wasn't called
75718 // consistently (e.g. on touch devices)
75719 context.replace(actionMoveNode(_drawNode.id, loc), _annotation);
75720 _drawNode = context.entity(_drawNode.id);
75722 createDrawNode(loc);
75726 /* includeDrawNode */
75729 if (d && d.properties && d.properties.nope || context.surface().classed('nope')) {
75730 if (!_pointerHasMoved) {
75731 // prevent the temporary draw node from appearing on touch devices
75735 dispatch.call('rejectedSelfIntersection', this);
75736 return; // can't click here
75739 context.pauseChangeDispatch();
75740 doAdd(); // we just replaced the temporary edit with the real one
75742 _didResolveTempEdit = true;
75743 context.resumeChangeDispatch();
75744 context.enter(mode);
75745 } // Accept the current position of the drawing node
75748 drawWay.add = function (loc, d) {
75749 attemptAdd(d, loc, function () {// don't need to do anything extra
75751 }; // Connect the way to an existing way
75754 drawWay.addWay = function (loc, edge, d) {
75755 attemptAdd(d, loc, function () {
75756 context.replace(actionAddMidpoint({
75759 }, _drawNode), _annotation);
75761 }; // Connect the way to an existing node
75764 drawWay.addNode = function (node, d) {
75765 // finish drawing if the mapper targets the prior node
75766 if (node.id === _headNodeID || // or the first node when drawing an area
75767 _origWay.isClosed() && node.id === _origWay.first()) {
75772 attemptAdd(d, node.loc, function () {
75773 context.replace(function actionReplaceDrawNode(graph) {
75774 // remove the temporary draw node and insert the existing node
75775 // at the same index
75776 graph = graph.replace(graph.entity(wayID).removeNode(_drawNode.id)).remove(_drawNode);
75777 return graph.replace(graph.entity(wayID).addNode(node.id, _nodeIndex));
75782 * @param {(typeof osmWay)[]} ways
75783 * @returns {"line" | "area" | "generic"}
75787 function getFeatureType(ways) {
75788 if (ways.every(function (way) {
75789 return way.isClosed();
75791 if (ways.every(function (way) {
75792 return !way.isClosed();
75796 /** see PR #8671 */
75799 function followMode() {
75800 if (_didResolveTempEdit) return;
75803 // get the last 2 added nodes.
75804 // check if they are both part of only oneway (the same one)
75805 // check if the ways that they're part of are the same way
75806 // find index of the last two nodes, to determine the direction to travel around the existing way
75807 // add the next node to the way we are drawing
75808 // if we're drawing an area, the first node = last node.
75809 var isDrawingArea = _origWay.nodes[0] === _origWay.nodes.slice(-1)[0];
75811 var _origWay$nodes$slice = _origWay.nodes.slice(isDrawingArea ? -3 : -2),
75812 _origWay$nodes$slice2 = _slicedToArray(_origWay$nodes$slice, 2),
75813 secondLastNodeId = _origWay$nodes$slice2[0],
75814 lastNodeId = _origWay$nodes$slice2[1]; // Unlike startGraph, the full history graph may contain unsaved vertices to follow.
75815 // https://github.com/openstreetmap/iD/issues/8749
75818 var historyGraph = context.history().graph();
75820 if (!lastNodeId || !secondLastNodeId || !historyGraph.hasEntity(lastNodeId) || !historyGraph.hasEntity(secondLastNodeId)) {
75821 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html('operations.follow.error.needs_more_initial_nodes'))();
75823 } // If the way has looped over itself, follow some other way.
75826 var lastNodesParents = historyGraph.parentWays(historyGraph.entity(lastNodeId)).filter(function (w) {
75827 return w.id !== wayID;
75829 var secondLastNodesParents = historyGraph.parentWays(historyGraph.entity(secondLastNodeId)).filter(function (w) {
75830 return w.id !== wayID;
75832 var featureType = getFeatureType(lastNodesParents);
75834 if (lastNodesParents.length !== 1 || secondLastNodesParents.length === 0) {
75835 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html("operations.follow.error.intersection_of_multiple_ways.".concat(featureType)))();
75837 } // Check if the last node's parent is also the parent of the second last node.
75838 // The last node must only have one parent, but the second last node can have
75839 // multiple parents.
75842 if (!secondLastNodesParents.some(function (n) {
75843 return n.id === lastNodesParents[0].id;
75845 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html("operations.follow.error.intersection_of_different_ways.".concat(featureType)))();
75849 var way = lastNodesParents[0];
75850 var indexOfLast = way.nodes.indexOf(lastNodeId);
75851 var indexOfSecondLast = way.nodes.indexOf(secondLastNodeId); // for a closed way, the first/last node is the same so it appears twice in the array,
75852 // but indexOf always finds the first occurrence. This is only an issue when following a way
75853 // in descending order
75855 var isDescendingPastZero = indexOfLast === way.nodes.length - 2 && indexOfSecondLast === 0;
75856 var nextNodeIndex = indexOfLast + (indexOfLast > indexOfSecondLast && !isDescendingPastZero ? 1 : -1); // if we're following a closed way and we pass the first/last node, the next index will be -1
75858 if (nextNodeIndex === -1) nextNodeIndex = indexOfSecondLast === 1 ? way.nodes.length - 2 : 1;
75859 var nextNode = historyGraph.entity(way.nodes[nextNodeIndex]);
75860 drawWay.addNode(nextNode, {
75863 coordinates: nextNode.loc
75872 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html('operations.follow.error.unknown'))();
75876 keybinding.on(_t('operations.follow.key'), followMode);
75877 select(document).call(keybinding); // Finish the draw operation, removing the temporary edit.
75878 // If the way has enough nodes to be valid, it's selected.
75879 // Otherwise, delete everything and return to browse mode.
75881 drawWay.finish = function () {
75882 checkGeometry(false
75883 /* includeDrawNode */
75886 if (context.surface().classed('nope')) {
75887 dispatch.call('rejectedSelfIntersection', this);
75888 return; // can't click here
75891 context.pauseChangeDispatch(); // remove the temporary edit
75894 _didResolveTempEdit = true;
75895 context.resumeChangeDispatch();
75896 var way = context.hasEntity(wayID);
75898 if (!way || way.isDegenerate()) {
75903 window.setTimeout(function () {
75904 context.map().dblclickZoomEnable(true);
75906 var isNewFeature = !mode.isContinuing;
75907 context.enter(modeSelect(context, [wayID]).newFeature(isNewFeature));
75908 }; // Cancel the draw operation, delete everything, and return to browse mode.
75911 drawWay.cancel = function () {
75912 context.pauseChangeDispatch();
75913 resetToStartGraph();
75914 context.resumeChangeDispatch();
75915 window.setTimeout(function () {
75916 context.map().dblclickZoomEnable(true);
75918 context.surface().classed('nope', false).classed('nope-disabled', false).classed('nope-suppressed', false);
75919 context.enter(modeBrowse(context));
75922 drawWay.nodeIndex = function (val) {
75923 if (!arguments.length) return _nodeIndex;
75928 drawWay.activeID = function () {
75929 if (!arguments.length) return _drawNode && _drawNode.id; // no assign
75934 return utilRebind(drawWay, dispatch, 'on');
75937 function modeDrawLine(context, wayID, startGraph, button, affix, continuing) {
75942 var behavior = behaviorDrawWay(context, wayID, mode, startGraph).on('rejectedSelfIntersection.modeDrawLine', function () {
75943 context.ui().flash.iconName('#iD-icon-no').label(_t.html('self_intersection.error.lines'))();
75945 mode.wayID = wayID;
75946 mode.isContinuing = continuing;
75948 mode.enter = function () {
75949 behavior.nodeIndex(affix === 'prefix' ? 0 : undefined);
75950 context.install(behavior);
75953 mode.exit = function () {
75954 context.uninstall(behavior);
75957 mode.selectedIDs = function () {
75961 mode.activeID = function () {
75962 return behavior && behavior.activeID() || [];
75968 function validationDisconnectedWay() {
75969 var type = 'disconnected_way';
75971 function isTaggedAsHighway(entity) {
75972 return osmRoutableHighwayTagValues[entity.tags.highway];
75975 var validation = function checkDisconnectedWay(entity, graph) {
75976 var routingIslandWays = routingIslandForEntity(entity);
75977 if (!routingIslandWays) return [];
75978 return [new validationIssue({
75980 subtype: 'highway',
75981 severity: 'warning',
75982 message: function message(context) {
75983 var entity = this.entityIds.length && context.hasEntity(this.entityIds[0]);
75984 var label = entity && utilDisplayLabel(entity, context.graph());
75985 return _t.html('issues.disconnected_way.routable.message', {
75986 count: this.entityIds.length,
75990 reference: showReference,
75991 entityIds: Array.from(routingIslandWays).map(function (way) {
75994 dynamicFixes: makeFixes
75997 function makeFixes(context) {
75999 var singleEntity = this.entityIds.length === 1 && context.hasEntity(this.entityIds[0]);
76001 if (singleEntity) {
76002 if (singleEntity.type === 'way' && !singleEntity.isClosed()) {
76003 var textDirection = _mainLocalizer.textDirection();
76004 var startFix = makeContinueDrawingFixIfAllowed(textDirection, singleEntity.first(), 'start');
76005 if (startFix) fixes.push(startFix);
76006 var endFix = makeContinueDrawingFixIfAllowed(textDirection, singleEntity.last(), 'end');
76007 if (endFix) fixes.push(endFix);
76010 if (!fixes.length) {
76011 fixes.push(new validationIssueFix({
76012 title: _t.html('issues.fix.connect_feature.title')
76016 fixes.push(new validationIssueFix({
76017 icon: 'iD-operation-delete',
76018 title: _t.html('issues.fix.delete_feature.title'),
76019 entityIds: [singleEntity.id],
76020 onClick: function onClick(context) {
76021 var id = this.issue.entityIds[0];
76022 var operation = operationDelete(context, [id]);
76024 if (!operation.disabled()) {
76030 fixes.push(new validationIssueFix({
76031 title: _t.html('issues.fix.connect_features.title')
76038 function showReference(selection) {
76039 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.disconnected_way.routable.reference'));
76042 function routingIslandForEntity(entity) {
76043 var routingIsland = new Set(); // the interconnected routable features
76045 var waysToCheck = []; // the queue of remaining routable ways to traverse
76047 function queueParentWays(node) {
76048 graph.parentWays(node).forEach(function (parentWay) {
76049 if (!routingIsland.has(parentWay) && // only check each feature once
76050 isRoutableWay(parentWay, false)) {
76051 // only check routable features
76052 routingIsland.add(parentWay);
76053 waysToCheck.push(parentWay);
76058 if (entity.type === 'way' && isRoutableWay(entity, true)) {
76059 routingIsland.add(entity);
76060 waysToCheck.push(entity);
76061 } else if (entity.type === 'node' && isRoutableNode(entity)) {
76062 routingIsland.add(entity);
76063 queueParentWays(entity);
76065 // this feature isn't routable, cannot be a routing island
76069 while (waysToCheck.length) {
76070 var wayToCheck = waysToCheck.pop();
76071 var childNodes = graph.childNodes(wayToCheck);
76073 for (var i in childNodes) {
76074 var vertex = childNodes[i];
76076 if (isConnectedVertex(vertex)) {
76077 // found a link to the wider network, not a routing island
76081 if (isRoutableNode(vertex)) {
76082 routingIsland.add(vertex);
76085 queueParentWays(vertex);
76087 } // no network link found, this is a routing island, return its members
76090 return routingIsland;
76093 function isConnectedVertex(vertex) {
76094 // assume ways overlapping unloaded tiles are connected to the wider road network - #5938
76095 var osm = services.osm;
76096 if (osm && !osm.isDataLoaded(vertex.loc)) return true; // entrances are considered connected
76098 if (vertex.tags.entrance && vertex.tags.entrance !== 'no') return true;
76099 if (vertex.tags.amenity === 'parking_entrance') return true;
76103 function isRoutableNode(node) {
76104 // treat elevators as distinct features in the highway network
76105 if (node.tags.highway === 'elevator') return true;
76109 function isRoutableWay(way, ignoreInnerWays) {
76110 if (isTaggedAsHighway(way) || way.tags.route === 'ferry') return true;
76111 return graph.parentRelations(way).some(function (parentRelation) {
76112 if (parentRelation.tags.type === 'route' && parentRelation.tags.route === 'ferry') return true;
76113 if (parentRelation.isMultipolygon() && isTaggedAsHighway(parentRelation) && (!ignoreInnerWays || parentRelation.memberById(way.id).role !== 'inner')) return true;
76118 function makeContinueDrawingFixIfAllowed(textDirection, vertexID, whichEnd) {
76119 var vertex = graph.hasEntity(vertexID);
76120 if (!vertex || vertex.tags.noexit === 'yes') return null;
76121 var useLeftContinue = whichEnd === 'start' && textDirection === 'ltr' || whichEnd === 'end' && textDirection === 'rtl';
76122 return new validationIssueFix({
76123 icon: 'iD-operation-continue' + (useLeftContinue ? '-left' : ''),
76124 title: _t.html('issues.fix.continue_from_' + whichEnd + '.title'),
76125 entityIds: [vertexID],
76126 onClick: function onClick(context) {
76127 var wayId = this.issue.entityIds[0];
76128 var way = context.hasEntity(wayId);
76129 var vertexId = this.entityIds[0];
76130 var vertex = context.hasEntity(vertexId);
76131 if (!way || !vertex) return; // make sure the vertex is actually visible and editable
76133 var map = context.map();
76135 if (!context.editable() || !map.trimmedExtent().contains(vertex.loc)) {
76136 map.zoomToEase(vertex);
76139 context.enter(modeDrawLine(context, wayId, context.graph(), 'line', way.affix(vertexId), true));
76145 validation.type = type;
76149 function validationFormatting() {
76150 var type = 'invalid_format';
76152 var validation = function validation(entity) {
76155 function isValidEmail(email) {
76156 // Emails in OSM are going to be official so they should be pretty simple
76157 // Using negated lists to better support all possible unicode characters (#6494)
76158 var valid_email = /^[^\(\)\\,":;<>@\[\]]+@[^\(\)\\,":;<>@\[\]\.]+(?:\.[a-z0-9-]+)*$/i; // An empty value is also acceptable
76160 return !email || valid_email.test(email);
76163 function showReferenceEmail(selection) {
76164 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.invalid_format.email.reference'));
76166 /* see https://github.com/openstreetmap/iD/issues/6831#issuecomment-537121379
76167 function isSchemePresent(url) {
76168 var valid_scheme = /^https?:\/\//i;
76169 return (!url || valid_scheme.test(url));
76171 function showReferenceWebsite(selection) {
76172 selection.selectAll('.issue-reference')
76176 .attr('class', 'issue-reference')
76177 .call(t.append('issues.invalid_format.website.reference'));
76179 if (entity.tags.website) {
76180 // Multiple websites are possible
76181 // If ever we support ES6, arrow functions make this nicer
76182 var websites = entity.tags.website
76184 .map(function(s) { return s.trim(); })
76185 .filter(function(x) { return !isSchemePresent(x); });
76186 if (websites.length) {
76187 issues.push(new validationIssue({
76189 subtype: 'website',
76190 severity: 'warning',
76191 message: function(context) {
76192 var entity = context.hasEntity(this.entityIds[0]);
76193 return entity ? t.html('issues.invalid_format.website.message' + this.data,
76194 { feature: utilDisplayLabel(entity, context.graph()), site: websites.join(', ') }) : '';
76196 reference: showReferenceWebsite,
76197 entityIds: [entity.id],
76198 hash: websites.join(),
76199 data: (websites.length > 1) ? '_multi' : ''
76205 if (entity.tags.email) {
76206 // Multiple emails are possible
76207 var emails = entity.tags.email.split(';').map(function (s) {
76209 }).filter(function (x) {
76210 return !isValidEmail(x);
76213 if (emails.length) {
76214 issues.push(new validationIssue({
76217 severity: 'warning',
76218 message: function message(context) {
76219 var entity = context.hasEntity(this.entityIds[0]);
76220 return entity ? _t.html('issues.invalid_format.email.message' + this.data, {
76221 feature: utilDisplayLabel(entity, context.graph()),
76222 email: emails.join(', ')
76225 reference: showReferenceEmail,
76226 entityIds: [entity.id],
76227 hash: emails.join(),
76228 data: emails.length > 1 ? '_multi' : ''
76236 validation.type = type;
76240 function validationHelpRequest(context) {
76241 var type = 'help_request';
76243 var validation = function checkFixmeTag(entity) {
76244 if (!entity.tags.fixme) return []; // don't flag fixmes on features added by the user
76246 if (entity.version === undefined) return [];
76248 if (entity.v !== undefined) {
76249 var baseEntity = context.history().base().hasEntity(entity.id); // don't flag fixmes added by the user on existing features
76251 if (!baseEntity || !baseEntity.tags.fixme) return [];
76254 return [new validationIssue({
76256 subtype: 'fixme_tag',
76257 severity: 'warning',
76258 message: function message(context) {
76259 var entity = context.hasEntity(this.entityIds[0]);
76260 return entity ? _t.html('issues.fixme_tag.message', {
76261 feature: utilDisplayLabel(entity, context.graph(), true
76266 dynamicFixes: function dynamicFixes() {
76267 return [new validationIssueFix({
76268 title: _t.html('issues.fix.address_the_concern.title')
76271 reference: showReference,
76272 entityIds: [entity.id]
76275 function showReference(selection) {
76276 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.fixme_tag.reference'));
76280 validation.type = type;
76284 function validationImpossibleOneway() {
76285 var type = 'impossible_oneway';
76287 var validation = function checkImpossibleOneway(entity, graph) {
76288 if (entity.type !== 'way' || entity.geometry(graph) !== 'line') return [];
76289 if (entity.isClosed()) return [];
76290 if (!typeForWay(entity)) return [];
76291 if (!isOneway(entity)) return [];
76292 var firstIssues = issuesForNode(entity, entity.first());
76293 var lastIssues = issuesForNode(entity, entity.last());
76294 return firstIssues.concat(lastIssues);
76296 function typeForWay(way) {
76297 if (way.geometry(graph) !== 'line') return null;
76298 if (osmRoutableHighwayTagValues[way.tags.highway]) return 'highway';
76299 if (osmFlowingWaterwayTagValues[way.tags.waterway]) return 'waterway';
76303 function isOneway(way) {
76304 if (way.tags.oneway === 'yes') return true;
76305 if (way.tags.oneway) return false;
76307 for (var key in way.tags) {
76308 if (osmOneWayTags[key] && osmOneWayTags[key][way.tags[key]]) {
76316 function nodeOccursMoreThanOnce(way, nodeID) {
76317 var occurrences = 0;
76319 for (var index in way.nodes) {
76320 if (way.nodes[index] === nodeID) {
76322 if (occurrences > 1) return true;
76329 function isConnectedViaOtherTypes(way, node) {
76330 var wayType = typeForWay(way);
76332 if (wayType === 'highway') {
76333 // entrances are considered connected
76334 if (node.tags.entrance && node.tags.entrance !== 'no') return true;
76335 if (node.tags.amenity === 'parking_entrance') return true;
76336 } else if (wayType === 'waterway') {
76337 if (node.id === way.first()) {
76338 // multiple waterways may start at the same spring
76339 if (node.tags.natural === 'spring') return true;
76341 // multiple waterways may end at the same drain
76342 if (node.tags.manhole === 'drain') return true;
76346 return graph.parentWays(node).some(function (parentWay) {
76347 if (parentWay.id === way.id) return false;
76349 if (wayType === 'highway') {
76350 // allow connections to highway areas
76351 if (parentWay.geometry(graph) === 'area' && osmRoutableHighwayTagValues[parentWay.tags.highway]) return true; // count connections to ferry routes as connected
76353 if (parentWay.tags.route === 'ferry') return true;
76354 return graph.parentRelations(parentWay).some(function (parentRelation) {
76355 if (parentRelation.tags.type === 'route' && parentRelation.tags.route === 'ferry') return true; // allow connections to highway multipolygons
76357 return parentRelation.isMultipolygon() && osmRoutableHighwayTagValues[parentRelation.tags.highway];
76359 } else if (wayType === 'waterway') {
76360 // multiple waterways may start or end at a water body at the same node
76361 if (parentWay.tags.natural === 'water' || parentWay.tags.natural === 'coastline') return true;
76368 function issuesForNode(way, nodeID) {
76369 var isFirst = nodeID === way.first();
76370 var wayType = typeForWay(way); // ignore if this way is self-connected at this node
76372 if (nodeOccursMoreThanOnce(way, nodeID)) return [];
76373 var osm = services.osm;
76374 if (!osm) return [];
76375 var node = graph.hasEntity(nodeID); // ignore if this node or its tile are unloaded
76377 if (!node || !osm.isDataLoaded(node.loc)) return [];
76378 if (isConnectedViaOtherTypes(way, node)) return [];
76379 var attachedWaysOfSameType = graph.parentWays(node).filter(function (parentWay) {
76380 if (parentWay.id === way.id) return false;
76381 return typeForWay(parentWay) === wayType;
76382 }); // assume it's okay for waterways to start or end disconnected for now
76384 if (wayType === 'waterway' && attachedWaysOfSameType.length === 0) return [];
76385 var attachedOneways = attachedWaysOfSameType.filter(function (attachedWay) {
76386 return isOneway(attachedWay);
76387 }); // ignore if the way is connected to some non-oneway features
76389 if (attachedOneways.length < attachedWaysOfSameType.length) return [];
76391 if (attachedOneways.length) {
76392 var connectedEndpointsOkay = attachedOneways.some(function (attachedOneway) {
76393 if ((isFirst ? attachedOneway.first() : attachedOneway.last()) !== nodeID) return true;
76394 if (nodeOccursMoreThanOnce(attachedOneway, nodeID)) return true;
76397 if (connectedEndpointsOkay) return [];
76400 var placement = isFirst ? 'start' : 'end',
76401 messageID = wayType + '.',
76402 referenceID = wayType + '.';
76404 if (wayType === 'waterway') {
76405 messageID += 'connected.' + placement;
76406 referenceID += 'connected';
76408 messageID += placement;
76409 referenceID += placement;
76412 return [new validationIssue({
76415 severity: 'warning',
76416 message: function message(context) {
76417 var entity = context.hasEntity(this.entityIds[0]);
76418 return entity ? _t.html('issues.impossible_oneway.' + messageID + '.message', {
76419 feature: utilDisplayLabel(entity, context.graph())
76422 reference: getReference(referenceID),
76423 entityIds: [way.id, node.id],
76424 dynamicFixes: function dynamicFixes() {
76427 if (attachedOneways.length) {
76428 fixes.push(new validationIssueFix({
76429 icon: 'iD-operation-reverse',
76430 title: _t.html('issues.fix.reverse_feature.title'),
76431 entityIds: [way.id],
76432 onClick: function onClick(context) {
76433 var id = this.issue.entityIds[0];
76434 context.perform(actionReverse(id), _t('operations.reverse.annotation.line', {
76441 if (node.tags.noexit !== 'yes') {
76442 var textDirection = _mainLocalizer.textDirection();
76443 var useLeftContinue = isFirst && textDirection === 'ltr' || !isFirst && textDirection === 'rtl';
76444 fixes.push(new validationIssueFix({
76445 icon: 'iD-operation-continue' + (useLeftContinue ? '-left' : ''),
76446 title: _t.html('issues.fix.continue_from_' + (isFirst ? 'start' : 'end') + '.title'),
76447 onClick: function onClick(context) {
76448 var entityID = this.issue.entityIds[0];
76449 var vertexID = this.issue.entityIds[1];
76450 var way = context.entity(entityID);
76451 var vertex = context.entity(vertexID);
76452 continueDrawing(way, vertex, context);
76462 function getReference(referenceID) {
76463 return function showReference(selection) {
76464 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.impossible_oneway.' + referenceID + '.reference'));
76470 function continueDrawing(way, vertex, context) {
76471 // make sure the vertex is actually visible and editable
76472 var map = context.map();
76474 if (!context.editable() || !map.trimmedExtent().contains(vertex.loc)) {
76475 map.zoomToEase(vertex);
76478 context.enter(modeDrawLine(context, way.id, context.graph(), 'line', way.affix(vertex.id), true));
76481 validation.type = type;
76485 function validationIncompatibleSource() {
76486 var type = 'incompatible_source';
76487 var incompatibleRules = [{
76489 regex: /(^amap$|^amap\.com|autonavi|mapabc|高德)/i
76492 regex: /(baidu|mapbar|百度)/i
76496 exceptRegex: /((books|drive)\.google|google\s?(books|drive|plus))|(esri\/Google_Africa_Buildings)/i
76499 var validation = function checkIncompatibleSource(entity) {
76500 var entitySources = entity.tags && entity.tags.source && entity.tags.source.split(';');
76501 if (!entitySources) return [];
76502 var entityID = entity.id;
76503 return entitySources.map(function (source) {
76504 var matchRule = incompatibleRules.find(function (rule) {
76505 if (!rule.regex.test(source)) return false;
76506 if (rule.exceptRegex && rule.exceptRegex.test(source)) return false;
76509 if (!matchRule) return null;
76510 return new validationIssue({
76512 severity: 'warning',
76513 message: function message(context) {
76514 var entity = context.hasEntity(entityID);
76515 return entity ? _t.html('issues.incompatible_source.feature.message', {
76516 feature: utilDisplayLabel(entity, context.graph(), true
76522 reference: getReference(matchRule.id),
76523 entityIds: [entityID],
76525 dynamicFixes: function dynamicFixes() {
76526 return [new validationIssueFix({
76527 title: _t.html('issues.fix.remove_proprietary_data.title')
76531 }).filter(Boolean);
76533 function getReference(id) {
76534 return function showReference(selection) {
76535 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append("issues.incompatible_source.reference.".concat(id)));
76540 validation.type = type;
76544 function validationMaprules() {
76545 var type = 'maprules';
76547 var validation = function checkMaprules(entity, graph) {
76548 if (!services.maprules) return [];
76549 var rules = services.maprules.validationRules();
76552 for (var i = 0; i < rules.length; i++) {
76553 var rule = rules[i];
76554 rule.findIssues(entity, graph, issues);
76560 validation.type = type;
76564 function validationMismatchedGeometry() {
76565 var type = 'mismatched_geometry';
76567 function tagSuggestingLineIsArea(entity) {
76568 if (entity.type !== 'way' || entity.isClosed()) return null;
76569 var tagSuggestingArea = entity.tagSuggestingArea();
76571 if (!tagSuggestingArea) {
76575 var asLine = _mainPresetIndex.matchTags(tagSuggestingArea, 'line');
76576 var asArea = _mainPresetIndex.matchTags(tagSuggestingArea, 'area');
76578 if (asLine && asArea && asLine === asArea) {
76579 // these tags also allow lines and making this an area wouldn't matter
76583 return tagSuggestingArea;
76586 function makeConnectEndpointsFixOnClick(way, graph) {
76587 // must have at least three nodes to close this automatically
76588 if (way.nodes.length < 3) return null;
76589 var nodes = graph.childNodes(way),
76591 var firstToLastDistanceMeters = geoSphericalDistance(nodes[0].loc, nodes[nodes.length - 1].loc); // if the distance is very small, attempt to merge the endpoints
76593 if (firstToLastDistanceMeters < 0.75) {
76594 testNodes = nodes.slice(); // shallow copy
76597 testNodes.push(testNodes[0]); // make sure this will not create a self-intersection
76599 if (!geoHasSelfIntersections(testNodes, testNodes[0].id)) {
76600 return function (context) {
76601 var way = context.entity(this.issue.entityIds[0]);
76602 context.perform(actionMergeNodes([way.nodes[0], way.nodes[way.nodes.length - 1]], nodes[0].loc), _t('issues.fix.connect_endpoints.annotation'));
76605 } // if the points were not merged, attempt to close the way
76608 testNodes = nodes.slice(); // shallow copy
76610 testNodes.push(testNodes[0]); // make sure this will not create a self-intersection
76612 if (!geoHasSelfIntersections(testNodes, testNodes[0].id)) {
76613 return function (context) {
76614 var wayId = this.issue.entityIds[0];
76615 var way = context.entity(wayId);
76616 var nodeId = way.nodes[0];
76617 var index = way.nodes.length;
76618 context.perform(actionAddVertex(wayId, nodeId, index), _t('issues.fix.connect_endpoints.annotation'));
76623 function lineTaggedAsAreaIssue(entity) {
76624 var tagSuggestingArea = tagSuggestingLineIsArea(entity);
76625 if (!tagSuggestingArea) return null;
76626 return new validationIssue({
76628 subtype: 'area_as_line',
76629 severity: 'warning',
76630 message: function message(context) {
76631 var entity = context.hasEntity(this.entityIds[0]);
76632 return entity ? _t.html('issues.tag_suggests_area.message', {
76633 feature: utilDisplayLabel(entity, 'area', true
76637 tags: tagSuggestingArea
76641 reference: showReference,
76642 entityIds: [entity.id],
76643 hash: JSON.stringify(tagSuggestingArea),
76644 dynamicFixes: function dynamicFixes(context) {
76646 var entity = context.entity(this.entityIds[0]);
76647 var connectEndsOnClick = makeConnectEndpointsFixOnClick(entity, context.graph());
76648 fixes.push(new validationIssueFix({
76649 title: _t.html('issues.fix.connect_endpoints.title'),
76650 onClick: connectEndsOnClick
76652 fixes.push(new validationIssueFix({
76653 icon: 'iD-operation-delete',
76654 title: _t.html('issues.fix.remove_tag.title'),
76655 onClick: function onClick(context) {
76656 var entityId = this.issue.entityIds[0];
76657 var entity = context.entity(entityId);
76658 var tags = Object.assign({}, entity.tags); // shallow copy
76660 for (var key in tagSuggestingArea) {
76664 context.perform(actionChangeTags(entityId, tags), _t('issues.fix.remove_tag.annotation'));
76671 function showReference(selection) {
76672 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.tag_suggests_area.reference'));
76676 function vertexPointIssue(entity, graph) {
76677 // we only care about nodes
76678 if (entity.type !== 'node') return null; // ignore tagless points
76680 if (Object.keys(entity.tags).length === 0) return null; // address lines are special so just ignore them
76682 if (entity.isOnAddressLine(graph)) return null;
76683 var geometry = entity.geometry(graph);
76684 var allowedGeometries = osmNodeGeometriesForTags(entity.tags);
76686 if (geometry === 'point' && !allowedGeometries.point && allowedGeometries.vertex) {
76687 return new validationIssue({
76689 subtype: 'vertex_as_point',
76690 severity: 'warning',
76691 message: function message(context) {
76692 var entity = context.hasEntity(this.entityIds[0]);
76693 return entity ? _t.html('issues.vertex_as_point.message', {
76694 feature: utilDisplayLabel(entity, 'vertex', true
76699 reference: function showReference(selection) {
76700 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.vertex_as_point.reference'));
76702 entityIds: [entity.id]
76704 } else if (geometry === 'vertex' && !allowedGeometries.vertex && allowedGeometries.point) {
76705 return new validationIssue({
76707 subtype: 'point_as_vertex',
76708 severity: 'warning',
76709 message: function message(context) {
76710 var entity = context.hasEntity(this.entityIds[0]);
76711 return entity ? _t.html('issues.point_as_vertex.message', {
76712 feature: utilDisplayLabel(entity, 'point', true
76717 reference: function showReference(selection) {
76718 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.point_as_vertex.reference'));
76720 entityIds: [entity.id],
76721 dynamicFixes: extractPointDynamicFixes
76728 function otherMismatchIssue(entity, graph) {
76729 // ignore boring features
76730 if (!entity.hasInterestingTags()) return null;
76731 if (entity.type !== 'node' && entity.type !== 'way') return null; // address lines are special so just ignore them
76733 if (entity.type === 'node' && entity.isOnAddressLine(graph)) return null;
76734 var sourceGeom = entity.geometry(graph);
76735 var targetGeoms = entity.type === 'way' ? ['point', 'vertex'] : ['line', 'area'];
76736 if (sourceGeom === 'area') targetGeoms.unshift('line');
76737 var asSource = _mainPresetIndex.match(entity, graph);
76738 var targetGeom = targetGeoms.find(function (nodeGeom) {
76739 var asTarget = _mainPresetIndex.matchTags(entity.tags, nodeGeom);
76740 if (!asSource || !asTarget || asSource === asTarget || // sometimes there are two presets with the same tags for different geometries
76741 fastDeepEqual(asSource.tags, asTarget.tags)) return false;
76742 if (asTarget.isFallback()) return false;
76743 var primaryKey = Object.keys(asTarget.tags)[0]; // special case: buildings-as-points are discouraged by iD, but common in OSM, so ignore them
76745 if (primaryKey === 'building') return false;
76746 if (asTarget.tags[primaryKey] === '*') return false;
76747 return asSource.isFallback() || asSource.tags[primaryKey] === '*';
76749 if (!targetGeom) return null;
76750 var subtype = targetGeom + '_as_' + sourceGeom;
76751 if (targetGeom === 'vertex') targetGeom = 'point';
76752 if (sourceGeom === 'vertex') sourceGeom = 'point';
76753 var referenceId = targetGeom + '_as_' + sourceGeom;
76756 if (targetGeom === 'point') {
76757 dynamicFixes = extractPointDynamicFixes;
76758 } else if (sourceGeom === 'area' && targetGeom === 'line') {
76759 dynamicFixes = lineToAreaDynamicFixes;
76762 return new validationIssue({
76765 severity: 'warning',
76766 message: function message(context) {
76767 var entity = context.hasEntity(this.entityIds[0]);
76768 return entity ? _t.html('issues.' + referenceId + '.message', {
76769 feature: utilDisplayLabel(entity, targetGeom, true
76774 reference: function showReference(selection) {
76775 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.mismatched_geometry.reference'));
76777 entityIds: [entity.id],
76778 dynamicFixes: dynamicFixes
76782 function lineToAreaDynamicFixes(context) {
76783 var convertOnClick;
76784 var entityId = this.entityIds[0];
76785 var entity = context.entity(entityId);
76786 var tags = Object.assign({}, entity.tags); // shallow copy
76790 if (!osmTagSuggestingArea(tags)) {
76791 // if removing the area tag would make this a line, offer that as a quick fix
76792 convertOnClick = function convertOnClick(context) {
76793 var entityId = this.issue.entityIds[0];
76794 var entity = context.entity(entityId);
76795 var tags = Object.assign({}, entity.tags); // shallow copy
76801 context.perform(actionChangeTags(entityId, tags), _t('issues.fix.convert_to_line.annotation'));
76805 return [new validationIssueFix({
76806 icon: 'iD-icon-line',
76807 title: _t.html('issues.fix.convert_to_line.title'),
76808 onClick: convertOnClick
76812 function extractPointDynamicFixes(context) {
76813 var entityId = this.entityIds[0];
76814 var extractOnClick = null;
76816 if (!context.hasHiddenConnections(entityId)) {
76817 extractOnClick = function extractOnClick(context) {
76818 var entityId = this.issue.entityIds[0];
76819 var action = actionExtract(entityId, context.projection);
76820 context.perform(action, _t('operations.extract.annotation', {
76822 })); // re-enter mode to trigger updates
76824 context.enter(modeSelect(context, [action.getExtractedNodeID()]));
76828 return [new validationIssueFix({
76829 icon: 'iD-operation-extract',
76830 title: _t.html('issues.fix.extract_point.title'),
76831 onClick: extractOnClick
76835 function unclosedMultipolygonPartIssues(entity, graph) {
76836 if (entity.type !== 'relation' || !entity.isMultipolygon() || entity.isDegenerate() || // cannot determine issues for incompletely-downloaded relations
76837 !entity.isComplete(graph)) return [];
76838 var sequences = osmJoinWays(entity.members, graph);
76841 for (var i in sequences) {
76842 var sequence = sequences[i];
76843 if (!sequence.nodes) continue;
76844 var firstNode = sequence.nodes[0];
76845 var lastNode = sequence.nodes[sequence.nodes.length - 1]; // part is closed if the first and last nodes are the same
76847 if (firstNode === lastNode) continue;
76848 var issue = new validationIssue({
76850 subtype: 'unclosed_multipolygon_part',
76851 severity: 'warning',
76852 message: function message(context) {
76853 var entity = context.hasEntity(this.entityIds[0]);
76854 return entity ? _t.html('issues.unclosed_multipolygon_part.message', {
76855 feature: utilDisplayLabel(entity, context.graph(), true
76860 reference: showReference,
76861 loc: sequence.nodes[0].loc,
76862 entityIds: [entity.id],
76863 hash: sequence.map(function (way) {
76867 issues.push(issue);
76872 function showReference(selection) {
76873 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.unclosed_multipolygon_part.reference'));
76877 var validation = function checkMismatchedGeometry(entity, graph) {
76878 var vertexPoint = vertexPointIssue(entity, graph);
76879 if (vertexPoint) return [vertexPoint];
76880 var lineAsArea = lineTaggedAsAreaIssue(entity);
76881 if (lineAsArea) return [lineAsArea];
76882 var mismatch = otherMismatchIssue(entity, graph);
76883 if (mismatch) return [mismatch];
76884 return unclosedMultipolygonPartIssues(entity, graph);
76887 validation.type = type;
76891 function validationMissingRole() {
76892 var type = 'missing_role';
76894 var validation = function checkMissingRole(entity, graph) {
76897 if (entity.type === 'way') {
76898 graph.parentRelations(entity).forEach(function (relation) {
76899 if (!relation.isMultipolygon()) return;
76900 var member = relation.memberById(entity.id);
76902 if (member && isMissingRole(member)) {
76903 issues.push(makeIssue(entity, relation, member));
76906 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
76907 entity.indexedMembers().forEach(function (member) {
76908 var way = graph.hasEntity(member.id);
76910 if (way && isMissingRole(member)) {
76911 issues.push(makeIssue(way, entity, member));
76919 function isMissingRole(member) {
76920 return !member.role || !member.role.trim().length;
76923 function makeIssue(way, relation, member) {
76924 return new validationIssue({
76926 severity: 'warning',
76927 message: function message(context) {
76928 var member = context.hasEntity(this.entityIds[1]),
76929 relation = context.hasEntity(this.entityIds[0]);
76930 return member && relation ? _t.html('issues.missing_role.message', {
76931 member: utilDisplayLabel(member, context.graph()),
76932 relation: utilDisplayLabel(relation, context.graph())
76935 reference: showReference,
76936 entityIds: [relation.id, way.id],
76940 hash: member.index.toString(),
76941 dynamicFixes: function dynamicFixes() {
76942 return [makeAddRoleFix('inner'), makeAddRoleFix('outer'), new validationIssueFix({
76943 icon: 'iD-operation-delete',
76944 title: _t.html('issues.fix.remove_from_relation.title'),
76945 onClick: function onClick(context) {
76946 context.perform(actionDeleteMember(this.issue.entityIds[0], this.issue.data.member.index), _t('operations.delete_member.annotation', {
76954 function showReference(selection) {
76955 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.missing_role.multipolygon.reference'));
76959 function makeAddRoleFix(role) {
76960 return new validationIssueFix({
76961 title: _t.html('issues.fix.set_as_' + role + '.title'),
76962 onClick: function onClick(context) {
76963 var oldMember = this.issue.data.member;
76965 id: this.issue.entityIds[1],
76966 type: oldMember.type,
76969 context.perform(actionChangeMember(this.issue.entityIds[0], member, oldMember.index), _t('operations.change_role.annotation', {
76976 validation.type = type;
76980 function validationMissingTag(context) {
76981 var type = 'missing_tag';
76983 function hasDescriptiveTags(entity, graph) {
76984 var onlyAttributeKeys = ['description', 'name', 'note', 'start_date'];
76985 var entityDescriptiveKeys = Object.keys(entity.tags).filter(function (k) {
76986 if (k === 'area' || !osmIsInterestingTag(k)) return false;
76987 return !onlyAttributeKeys.some(function (attributeKey) {
76988 return k === attributeKey || k.indexOf(attributeKey + ':') === 0;
76992 if (entity.type === 'relation' && entityDescriptiveKeys.length === 1 && entity.tags.type === 'multipolygon') {
76993 // this relation's only interesting tag just says its a multipolygon,
76994 // which is not descriptive enough
76995 // It's okay for a simple multipolygon to have no descriptive tags
76996 // if its outer way has them (old model, see `outdated_tags.js`)
76997 return osmOldMultipolygonOuterMemberOfRelation(entity, graph);
77000 return entityDescriptiveKeys.length > 0;
77003 function isUnknownRoad(entity) {
77004 return entity.type === 'way' && entity.tags.highway === 'road';
77007 function isUntypedRelation(entity) {
77008 return entity.type === 'relation' && !entity.tags.type;
77011 var validation = function checkMissingTag(entity, graph) {
77013 var osm = context.connection();
77014 var isUnloadedNode = entity.type === 'node' && osm && !osm.isDataLoaded(entity.loc); // we can't know if the node is a vertex if the tile is undownloaded
77016 if (!isUnloadedNode && // allow untagged nodes that are part of ways
77017 entity.geometry(graph) !== 'vertex' && // allow untagged entities that are part of relations
77018 !entity.hasParentRelations(graph)) {
77019 if (Object.keys(entity.tags).length === 0) {
77021 } else if (!hasDescriptiveTags(entity, graph)) {
77022 subtype = 'descriptive';
77023 } else if (isUntypedRelation(entity)) {
77024 subtype = 'relation_type';
77026 } // flag an unknown road even if it's a member of a relation
77029 if (!subtype && isUnknownRoad(entity)) {
77030 subtype = 'highway_classification';
77033 if (!subtype) return [];
77034 var messageID = subtype === 'highway_classification' ? 'unknown_road' : 'missing_tag.' + subtype;
77035 var referenceID = subtype === 'highway_classification' ? 'unknown_road' : 'missing_tag'; // can always delete if the user created it in the first place..
77037 var canDelete = entity.version === undefined || entity.v !== undefined;
77038 var severity = canDelete && subtype !== 'highway_classification' ? 'error' : 'warning';
77039 return [new validationIssue({
77042 severity: severity,
77043 message: function message(context) {
77044 var entity = context.hasEntity(this.entityIds[0]);
77045 return entity ? _t.html('issues.' + messageID + '.message', {
77046 feature: utilDisplayLabel(entity, context.graph())
77049 reference: showReference,
77050 entityIds: [entity.id],
77051 dynamicFixes: function dynamicFixes(context) {
77053 var selectFixType = subtype === 'highway_classification' ? 'select_road_type' : 'select_preset';
77054 fixes.push(new validationIssueFix({
77055 icon: 'iD-icon-search',
77056 title: _t.html('issues.fix.' + selectFixType + '.title'),
77057 onClick: function onClick(context) {
77058 context.ui().sidebar.showPresetList();
77062 var id = this.entityIds[0];
77063 var operation = operationDelete(context, [id]);
77064 var disabledReasonID = operation.disabled();
77066 if (!disabledReasonID) {
77067 deleteOnClick = function deleteOnClick(context) {
77068 var id = this.issue.entityIds[0];
77069 var operation = operationDelete(context, [id]);
77071 if (!operation.disabled()) {
77077 fixes.push(new validationIssueFix({
77078 icon: 'iD-operation-delete',
77079 title: _t.html('issues.fix.delete_feature.title'),
77080 disabledReason: disabledReasonID ? _t('operations.delete.' + disabledReasonID + '.single') : undefined,
77081 onClick: deleteOnClick
77087 function showReference(selection) {
77088 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.' + referenceID + '.reference'));
77092 validation.type = type;
77096 function validationOutdatedTags() {
77097 var type = 'outdated_tags';
77098 var _waitingForDeprecated = true;
77100 var _dataDeprecated; // fetch deprecated tags
77103 _mainFileFetcher.get('deprecated').then(function (d) {
77104 return _dataDeprecated = d;
77105 })["catch"](function () {
77107 })["finally"](function () {
77108 return _waitingForDeprecated = false;
77111 function oldTagIssues(entity, graph) {
77112 var oldTags = Object.assign({}, entity.tags); // shallow copy
77114 var preset = _mainPresetIndex.match(entity, graph);
77115 var subtype = 'deprecated_tags';
77116 if (!preset) return [];
77117 if (!entity.hasInterestingTags()) return []; // Upgrade preset, if a replacement is available..
77119 if (preset.replacement) {
77120 var newPreset = _mainPresetIndex.item(preset.replacement);
77121 graph = actionChangePreset(entity.id, preset, newPreset, true
77122 /* skip field defaults */
77124 entity = graph.entity(entity.id);
77125 preset = newPreset;
77126 } // Upgrade deprecated tags..
77129 if (_dataDeprecated) {
77130 var deprecatedTags = entity.deprecatedTags(_dataDeprecated);
77132 if (deprecatedTags.length) {
77133 deprecatedTags.forEach(function (tag) {
77134 graph = actionUpgradeTags(entity.id, tag.old, tag.replace)(graph);
77136 entity = graph.entity(entity.id);
77138 } // Add missing addTags from the detected preset
77141 var newTags = Object.assign({}, entity.tags); // shallow copy
77143 if (preset.tags !== preset.addTags) {
77144 Object.keys(preset.addTags).forEach(function (k) {
77146 if (preset.addTags[k] === '*') {
77147 newTags[k] = 'yes';
77149 newTags[k] = preset.addTags[k];
77153 } // Attempt to match a canonical record in the name-suggestion-index.
77156 var nsi = services.nsi;
77157 var waitingForNsi = false;
77161 waitingForNsi = nsi.status() === 'loading';
77163 if (!waitingForNsi) {
77164 var loc = entity.extent(graph).center();
77165 nsiResult = nsi.upgradeTags(newTags, loc);
77168 newTags = nsiResult.newTags;
77169 subtype = 'noncanonical_brand';
77175 issues.provisional = _waitingForDeprecated || waitingForNsi; // determine diff
77177 var tagDiff = utilTagDiff(oldTags, newTags);
77178 if (!tagDiff.length) return issues;
77179 var isOnlyAddingTags = tagDiff.every(function (d) {
77180 return d.type === '+';
77185 prefix = 'noncanonical_brand.';
77186 } else if (subtype === 'deprecated_tags' && isOnlyAddingTags) {
77187 subtype = 'incomplete_tags';
77188 prefix = 'incomplete.';
77189 } // don't allow autofixing brand tags
77192 var autoArgs = subtype !== 'noncanonical_brand' ? [doUpgrade, _t('issues.fix.upgrade_tags.annotation')] : null;
77193 issues.push(new validationIssue({
77196 severity: 'warning',
77197 message: showMessage,
77198 reference: showReference,
77199 entityIds: [entity.id],
77200 hash: utilHashcode(JSON.stringify(tagDiff)),
77201 dynamicFixes: function dynamicFixes() {
77202 var fixes = [new validationIssueFix({
77203 autoArgs: autoArgs,
77204 title: _t.html('issues.fix.upgrade_tags.title'),
77205 onClick: function onClick(context) {
77206 context.perform(doUpgrade, _t('issues.fix.upgrade_tags.annotation'));
77209 var item = nsiResult && nsiResult.matched;
77212 fixes.push(new validationIssueFix({
77213 title: _t.html('issues.fix.tag_as_not.title', {
77214 name: item.displayName
77216 onClick: function onClick(context) {
77217 context.perform(addNotTag, _t('issues.fix.tag_as_not.annotation'));
77227 function doUpgrade(graph) {
77228 var currEntity = graph.hasEntity(entity.id);
77229 if (!currEntity) return graph;
77230 var newTags = Object.assign({}, currEntity.tags); // shallow copy
77232 tagDiff.forEach(function (diff) {
77233 if (diff.type === '-') {
77234 delete newTags[diff.key];
77235 } else if (diff.type === '+') {
77236 newTags[diff.key] = diff.newVal;
77239 return actionChangeTags(currEntity.id, newTags)(graph);
77242 function addNotTag(graph) {
77243 var currEntity = graph.hasEntity(entity.id);
77244 if (!currEntity) return graph;
77245 var item = nsiResult && nsiResult.matched;
77246 if (!item) return graph;
77247 var newTags = Object.assign({}, currEntity.tags); // shallow copy
77249 var wd = item.mainTag; // e.g. `brand:wikidata`
77251 var notwd = "not:".concat(wd); // e.g. `not:brand:wikidata`
77253 var qid = item.tags[wd];
77254 newTags[notwd] = qid;
77256 if (newTags[wd] === qid) {
77257 // if `brand:wikidata` was set to that qid
77258 var wp = item.mainTag.replace('wikidata', 'wikipedia');
77259 delete newTags[wd]; // remove `brand:wikidata`
77261 delete newTags[wp]; // remove `brand:wikipedia`
77264 return actionChangeTags(currEntity.id, newTags)(graph);
77267 function showMessage(context) {
77268 var currEntity = context.hasEntity(entity.id);
77269 if (!currEntity) return '';
77270 var messageID = "issues.outdated_tags.".concat(prefix, "message");
77272 if (subtype === 'noncanonical_brand' && isOnlyAddingTags) {
77273 messageID += '_incomplete';
77276 return _t.html(messageID, {
77277 feature: utilDisplayLabel(currEntity, context.graph(), true
77283 function showReference(selection) {
77284 var enter = selection.selectAll('.issue-reference').data([0]).enter();
77285 enter.append('div').attr('class', 'issue-reference').call(_t.append("issues.outdated_tags.".concat(prefix, "reference")));
77286 enter.append('strong').call(_t.append('issues.suggested'));
77287 enter.append('table').attr('class', 'tagDiff-table').selectAll('.tagDiff-row').data(tagDiff).enter().append('tr').attr('class', 'tagDiff-row').append('td').attr('class', function (d) {
77288 var klass = d.type === '+' ? 'add' : 'remove';
77289 return "tagDiff-cell tagDiff-cell-".concat(klass);
77290 }).html(function (d) {
77296 function oldMultipolygonIssues(entity, graph) {
77297 var multipolygon, outerWay;
77299 if (entity.type === 'relation') {
77300 outerWay = osmOldMultipolygonOuterMemberOfRelation(entity, graph);
77301 multipolygon = entity;
77302 } else if (entity.type === 'way') {
77303 multipolygon = osmIsOldMultipolygonOuterMember(entity, graph);
77309 if (!multipolygon || !outerWay) return [];
77310 return [new validationIssue({
77312 subtype: 'old_multipolygon',
77313 severity: 'warning',
77314 message: showMessage,
77315 reference: showReference,
77316 entityIds: [outerWay.id, multipolygon.id],
77317 dynamicFixes: function dynamicFixes() {
77318 return [new validationIssueFix({
77319 autoArgs: [doUpgrade, _t('issues.fix.move_tags.annotation')],
77320 title: _t.html('issues.fix.move_tags.title'),
77321 onClick: function onClick(context) {
77322 context.perform(doUpgrade, _t('issues.fix.move_tags.annotation'));
77328 function doUpgrade(graph) {
77329 var currMultipolygon = graph.hasEntity(multipolygon.id);
77330 var currOuterWay = graph.hasEntity(outerWay.id);
77331 if (!currMultipolygon || !currOuterWay) return graph;
77332 currMultipolygon = currMultipolygon.mergeTags(currOuterWay.tags);
77333 graph = graph.replace(currMultipolygon);
77334 return actionChangeTags(currOuterWay.id, {})(graph);
77337 function showMessage(context) {
77338 var currMultipolygon = context.hasEntity(multipolygon.id);
77339 if (!currMultipolygon) return '';
77340 return _t.html('issues.old_multipolygon.message', {
77341 multipolygon: utilDisplayLabel(currMultipolygon, context.graph(), true
77347 function showReference(selection) {
77348 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.old_multipolygon.reference'));
77352 var validation = function checkOutdatedTags(entity, graph) {
77353 var issues = oldMultipolygonIssues(entity, graph);
77354 if (!issues.length) issues = oldTagIssues(entity, graph);
77358 validation.type = type;
77362 function validationPrivateData() {
77363 var type = 'private_data'; // assume that some buildings are private
77365 var privateBuildingValues = {
77371 semidetached_house: true,
77372 static_caravan: true
77373 }; // but they might be public if they have one of these other tags
77383 }; // these tags may contain personally identifying info
77385 var personalTags = {
77386 'contact:email': true,
77387 'contact:fax': true,
77388 'contact:phone': true,
77394 var validation = function checkPrivateData(entity) {
77395 var tags = entity.tags;
77396 if (!tags.building || !privateBuildingValues[tags.building]) return [];
77399 for (var k in tags) {
77400 if (publicKeys[k]) return []; // probably a public feature
77402 if (!personalTags[k]) {
77403 keepTags[k] = tags[k];
77407 var tagDiff = utilTagDiff(tags, keepTags);
77408 if (!tagDiff.length) return [];
77409 var fixID = tagDiff.length === 1 ? 'remove_tag' : 'remove_tags';
77410 return [new validationIssue({
77412 severity: 'warning',
77413 message: showMessage,
77414 reference: showReference,
77415 entityIds: [entity.id],
77416 dynamicFixes: function dynamicFixes() {
77417 return [new validationIssueFix({
77418 icon: 'iD-operation-delete',
77419 title: _t.html('issues.fix.' + fixID + '.title'),
77420 onClick: function onClick(context) {
77421 context.perform(doUpgrade, _t('issues.fix.upgrade_tags.annotation'));
77427 function doUpgrade(graph) {
77428 var currEntity = graph.hasEntity(entity.id);
77429 if (!currEntity) return graph;
77430 var newTags = Object.assign({}, currEntity.tags); // shallow copy
77432 tagDiff.forEach(function (diff) {
77433 if (diff.type === '-') {
77434 delete newTags[diff.key];
77435 } else if (diff.type === '+') {
77436 newTags[diff.key] = diff.newVal;
77439 return actionChangeTags(currEntity.id, newTags)(graph);
77442 function showMessage(context) {
77443 var currEntity = context.hasEntity(this.entityIds[0]);
77444 if (!currEntity) return '';
77445 return _t.html('issues.private_data.contact.message', {
77446 feature: utilDisplayLabel(currEntity, context.graph())
77450 function showReference(selection) {
77451 var enter = selection.selectAll('.issue-reference').data([0]).enter();
77452 enter.append('div').attr('class', 'issue-reference').call(_t.append('issues.private_data.reference'));
77453 enter.append('strong').call(_t.append('issues.suggested'));
77454 enter.append('table').attr('class', 'tagDiff-table').selectAll('.tagDiff-row').data(tagDiff).enter().append('tr').attr('class', 'tagDiff-row').append('td').attr('class', function (d) {
77455 var klass = d.type === '+' ? 'add' : 'remove';
77456 return 'tagDiff-cell tagDiff-cell-' + klass;
77457 }).html(function (d) {
77463 validation.type = type;
77467 function validationSuspiciousName() {
77468 var type = 'suspicious_name';
77469 var keysToTestForGenericValues = ['aerialway', 'aeroway', 'amenity', 'building', 'craft', 'highway', 'leisure', 'railway', 'man_made', 'office', 'shop', 'tourism', 'waterway'];
77470 var _waitingForNsi = false; // Attempt to match a generic record in the name-suggestion-index.
77472 function isGenericMatchInNsi(tags) {
77473 var nsi = services.nsi;
77476 _waitingForNsi = nsi.status() === 'loading';
77478 if (!_waitingForNsi) {
77479 return nsi.isGenericName(tags);
77484 } // Test if the name is just the key or tag value (e.g. "park")
77487 function nameMatchesRawTag(lowercaseName, tags) {
77488 for (var i = 0; i < keysToTestForGenericValues.length; i++) {
77489 var key = keysToTestForGenericValues[i];
77490 var val = tags[key];
77493 val = val.toLowerCase();
77495 if (key === lowercaseName || val === lowercaseName || key.replace(/\_/g, ' ') === lowercaseName || val.replace(/\_/g, ' ') === lowercaseName) {
77504 function isGenericName(name, tags) {
77505 name = name.toLowerCase();
77506 return nameMatchesRawTag(name, tags) || isGenericMatchInNsi(tags);
77509 function makeGenericNameIssue(entityId, nameKey, genericName, langCode) {
77510 return new validationIssue({
77512 subtype: 'generic_name',
77513 severity: 'warning',
77514 message: function message(context) {
77515 var entity = context.hasEntity(this.entityIds[0]);
77516 if (!entity) return '';
77517 var preset = _mainPresetIndex.match(entity, context.graph());
77518 var langName = langCode && _mainLocalizer.languageName(langCode);
77519 return _t.html('issues.generic_name.message' + (langName ? '_language' : ''), {
77520 feature: preset.name(),
77525 reference: showReference,
77526 entityIds: [entityId],
77527 hash: "".concat(nameKey, "=").concat(genericName),
77528 dynamicFixes: function dynamicFixes() {
77529 return [new validationIssueFix({
77530 icon: 'iD-operation-delete',
77531 title: _t.html('issues.fix.remove_the_name.title'),
77532 onClick: function onClick(context) {
77533 var entityId = this.issue.entityIds[0];
77534 var entity = context.entity(entityId);
77535 var tags = Object.assign({}, entity.tags); // shallow copy
77537 delete tags[nameKey];
77538 context.perform(actionChangeTags(entityId, tags), _t('issues.fix.remove_generic_name.annotation'));
77544 function showReference(selection) {
77545 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.generic_name.reference'));
77549 function makeIncorrectNameIssue(entityId, nameKey, incorrectName, langCode) {
77550 return new validationIssue({
77552 subtype: 'not_name',
77553 severity: 'warning',
77554 message: function message(context) {
77555 var entity = context.hasEntity(this.entityIds[0]);
77556 if (!entity) return '';
77557 var preset = _mainPresetIndex.match(entity, context.graph());
77558 var langName = langCode && _mainLocalizer.languageName(langCode);
77559 return _t.html('issues.incorrect_name.message' + (langName ? '_language' : ''), {
77560 feature: preset.name(),
77561 name: incorrectName,
77565 reference: showReference,
77566 entityIds: [entityId],
77567 hash: "".concat(nameKey, "=").concat(incorrectName),
77568 dynamicFixes: function dynamicFixes() {
77569 return [new validationIssueFix({
77570 icon: 'iD-operation-delete',
77571 title: _t.html('issues.fix.remove_the_name.title'),
77572 onClick: function onClick(context) {
77573 var entityId = this.issue.entityIds[0];
77574 var entity = context.entity(entityId);
77575 var tags = Object.assign({}, entity.tags); // shallow copy
77577 delete tags[nameKey];
77578 context.perform(actionChangeTags(entityId, tags), _t('issues.fix.remove_mistaken_name.annotation'));
77584 function showReference(selection) {
77585 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.generic_name.reference'));
77589 var validation = function checkGenericName(entity) {
77590 var tags = entity.tags; // a generic name is allowed if it's a known brand or entity
77592 var hasWikidata = !!tags.wikidata || !!tags['brand:wikidata'] || !!tags['operator:wikidata'];
77593 if (hasWikidata) return [];
77595 var notNames = (tags['not:name'] || '').split(';');
77597 for (var key in tags) {
77598 var m = key.match(/^name(?:(?::)([a-zA-Z_-]+))?$/);
77600 var langCode = m.length >= 2 ? m[1] : null;
77601 var value = tags[key];
77603 if (notNames.length) {
77604 for (var i in notNames) {
77605 var notName = notNames[i];
77607 if (notName && value === notName) {
77608 issues.push(makeIncorrectNameIssue(entity.id, key, value, langCode));
77614 if (isGenericName(value, tags)) {
77615 issues.provisional = _waitingForNsi; // retry later if we are waiting on NSI to finish loading
77617 issues.push(makeGenericNameIssue(entity.id, key, value, langCode));
77624 validation.type = type;
77628 function validationUnsquareWay(context) {
77629 var type = 'unsquare_way';
77630 var DEFAULT_DEG_THRESHOLD = 5; // see also issues.js
77631 // use looser epsilon for detection to reduce warnings of buildings that are essentially square already
77633 var epsilon = 0.05;
77634 var nodeThreshold = 10;
77636 function isBuilding(entity, graph) {
77637 if (entity.type !== 'way' || entity.geometry(graph) !== 'area') return false;
77638 return entity.tags.building && entity.tags.building !== 'no';
77641 var validation = function checkUnsquareWay(entity, graph) {
77642 if (!isBuilding(entity, graph)) return []; // don't flag ways marked as physically unsquare
77644 if (entity.tags.nonsquare === 'yes') return [];
77645 var isClosed = entity.isClosed();
77646 if (!isClosed) return []; // this building has bigger problems
77647 // don't flag ways with lots of nodes since they are likely detail-mapped
77649 var nodes = graph.childNodes(entity).slice(); // shallow copy
77651 if (nodes.length > nodeThreshold + 1) return []; // +1 because closing node appears twice
77652 // ignore if not all nodes are fully downloaded
77654 var osm = services.osm;
77655 if (!osm || nodes.some(function (node) {
77656 return !osm.isDataLoaded(node.loc);
77657 })) return []; // don't flag connected ways to avoid unresolvable unsquare loops
77659 var hasConnectedSquarableWays = nodes.some(function (node) {
77660 return graph.parentWays(node).some(function (way) {
77661 if (way.id === entity.id) return false;
77662 if (isBuilding(way, graph)) return true;
77663 return graph.parentRelations(way).some(function (parentRelation) {
77664 return parentRelation.isMultipolygon() && parentRelation.tags.building && parentRelation.tags.building !== 'no';
77668 if (hasConnectedSquarableWays) return []; // user-configurable square threshold
77670 var storedDegreeThreshold = corePreferences('validate-square-degrees');
77671 var degreeThreshold = isNaN(storedDegreeThreshold) ? DEFAULT_DEG_THRESHOLD : parseFloat(storedDegreeThreshold);
77672 var points = nodes.map(function (node) {
77673 return context.projection(node.loc);
77675 if (!geoOrthoCanOrthogonalize(points, isClosed, epsilon, degreeThreshold, true)) return [];
77676 var autoArgs; // don't allow autosquaring features linked to wikidata
77678 if (!entity.tags.wikidata) {
77679 // use same degree threshold as for detection
77680 var autoAction = actionOrthogonalize(entity.id, context.projection, undefined, degreeThreshold);
77681 autoAction.transitionable = false; // when autofixing, do it instantly
77683 autoArgs = [autoAction, _t('operations.orthogonalize.annotation.feature', {
77688 return [new validationIssue({
77690 subtype: 'building',
77691 severity: 'warning',
77692 message: function message(context) {
77693 var entity = context.hasEntity(this.entityIds[0]);
77694 return entity ? _t.html('issues.unsquare_way.message', {
77695 feature: utilDisplayLabel(entity, context.graph())
77698 reference: showReference,
77699 entityIds: [entity.id],
77700 hash: degreeThreshold,
77701 dynamicFixes: function dynamicFixes() {
77702 return [new validationIssueFix({
77703 icon: 'iD-operation-orthogonalize',
77704 title: _t.html('issues.fix.square_feature.title'),
77705 autoArgs: autoArgs,
77706 onClick: function onClick(context, completionHandler) {
77707 var entityId = this.issue.entityIds[0]; // use same degree threshold as for detection
77709 context.perform(actionOrthogonalize(entityId, context.projection, undefined, degreeThreshold), _t('operations.orthogonalize.annotation.feature', {
77711 })); // run after the squaring transition (currently 150ms)
77713 window.setTimeout(function () {
77714 completionHandler();
77719 new validationIssueFix({
77720 title: t.html('issues.fix.tag_as_unsquare.title'),
77721 onClick: function(context) {
77722 var entityId = this.issue.entityIds[0];
77723 var entity = context.entity(entityId);
77724 var tags = Object.assign({}, entity.tags); // shallow copy
77725 tags.nonsquare = 'yes';
77727 actionChangeTags(entityId, tags),
77728 t('issues.fix.tag_as_unsquare.annotation')
77737 function showReference(selection) {
77738 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.unsquare_way.buildings.reference'));
77742 validation.type = type;
77746 var Validations = /*#__PURE__*/Object.freeze({
77748 validationAlmostJunction: validationAlmostJunction,
77749 validationCloseNodes: validationCloseNodes,
77750 validationCrossingWays: validationCrossingWays,
77751 validationDisconnectedWay: validationDisconnectedWay,
77752 validationFormatting: validationFormatting,
77753 validationHelpRequest: validationHelpRequest,
77754 validationImpossibleOneway: validationImpossibleOneway,
77755 validationIncompatibleSource: validationIncompatibleSource,
77756 validationMaprules: validationMaprules,
77757 validationMismatchedGeometry: validationMismatchedGeometry,
77758 validationMissingRole: validationMissingRole,
77759 validationMissingTag: validationMissingTag,
77760 validationOutdatedTags: validationOutdatedTags,
77761 validationPrivateData: validationPrivateData,
77762 validationSuspiciousName: validationSuspiciousName,
77763 validationUnsquareWay: validationUnsquareWay
77766 function coreValidator(context) {
77769 var dispatch = dispatch$8('validated', 'focusedIssue');
77770 var validator = utilRebind({}, dispatch, 'on');
77772 var _disabledRules = {};
77774 var _ignoredIssueIDs = new Set();
77776 var _resolvedIssueIDs = new Set();
77778 var _baseCache = validationCache('base'); // issues before any user edits
77781 var _headCache = validationCache('head'); // issues after all user edits
77784 var _completeDiff = {}; // complete diff base -> head of what the user changed
77786 var _headIsCurrent = false;
77788 var _deferredRIC = new Set(); // Set( RequestIdleCallback handles )
77791 var _deferredST = new Set(); // Set( SetTimeout handles )
77794 var _headPromise; // Promise fulfilled when validation is performed up to headGraph snapshot
77797 var RETRY = 5000; // wait 5sec before revalidating provisional entities
77798 // Allow validation severity to be overridden by url queryparams...
77799 // See: https://github.com/openstreetmap/iD/pull/8243
77801 // Each param should contain a urlencoded comma separated list of
77802 // `type/subtype` rules. `*` may be used as a wildcard..
77804 // `validationError=disconnected_way/*`
77805 // `validationError=disconnected_way/highway`
77806 // `validationError=crossing_ways/bridge*`
77807 // `validationError=crossing_ways/bridge*,crossing_ways/tunnel*`
77809 var _errorOverrides = parseHashParam(context.initialHashParams.validationError);
77811 var _warningOverrides = parseHashParam(context.initialHashParams.validationWarning);
77813 var _disableOverrides = parseHashParam(context.initialHashParams.validationDisable); // `parseHashParam()` (private)
77814 // Checks hash parameters for severity overrides
77816 // `param` - a url hash parameter (`validationError`, `validationWarning`, or `validationDisable`)
77818 // Array of Objects like { type: RegExp, subtype: RegExp }
77822 function parseHashParam(param) {
77824 var rules = (param || '').split(',');
77825 rules.forEach(function (rule) {
77826 rule = rule.trim();
77827 var parts = rule.split('/', 2); // "type/subtype"
77829 var type = parts[0];
77830 var subtype = parts[1] || '*';
77831 if (!type || !subtype) return;
77833 type: makeRegExp(type),
77834 subtype: makeRegExp(subtype)
77839 function makeRegExp(str) {
77840 var escaped = str.replace(/[-\/\\^$+?.()|[\]{}]/g, '\\$&') // escape all reserved chars except for the '*'
77841 .replace(/\*/g, '.*'); // treat a '*' like '.*'
77843 return new RegExp('^' + escaped + '$');
77846 // Initialize the validator, called once on iD startup
77850 validator.init = function () {
77851 Object.values(Validations).forEach(function (validation) {
77852 if (typeof validation !== 'function') return;
77853 var fn = validation(context);
77857 var disabledRules = corePreferences('validate-disabledRules');
77859 if (disabledRules) {
77860 disabledRules.split(',').forEach(function (k) {
77861 return _disabledRules[k] = true;
77864 }; // `reset()` (private)
77865 // Cancels deferred work and resets all caches
77868 // `resetIgnored` - `true` to clear the list of user-ignored issues
77872 function reset(resetIgnored) {
77873 // cancel deferred work
77874 _deferredRIC.forEach(window.cancelIdleCallback);
77876 _deferredRIC.clear();
77878 _deferredST.forEach(window.clearTimeout);
77880 _deferredST.clear(); // empty queues and resolve any pending promise
77883 _baseCache.queue = [];
77884 _headCache.queue = [];
77885 processQueue(_headCache);
77886 processQueue(_baseCache); // clear caches
77888 if (resetIgnored) _ignoredIssueIDs.clear();
77890 _resolvedIssueIDs.clear();
77892 _baseCache = validationCache('base');
77893 _headCache = validationCache('head');
77894 _completeDiff = {};
77895 _headIsCurrent = false;
77897 // clear caches, called whenever iD resets after a save or switches sources
77898 // (clears out the _ignoredIssueIDs set also)
77902 validator.reset = function () {
77904 }; // `resetIgnoredIssues()`
77905 // clears out the _ignoredIssueIDs Set
77909 validator.resetIgnoredIssues = function () {
77910 _ignoredIssueIDs.clear();
77912 dispatch.call('validated'); // redraw UI
77913 }; // `revalidateUnsquare()`
77914 // Called whenever the user changes the unsquare threshold
77915 // It reruns just the "unsquare_way" validation on all buildings.
77919 validator.revalidateUnsquare = function () {
77920 revalidateUnsquare(_headCache);
77921 revalidateUnsquare(_baseCache);
77922 dispatch.call('validated');
77925 function revalidateUnsquare(cache) {
77926 var checkUnsquareWay = _rules.unsquare_way;
77927 if (!cache.graph || typeof checkUnsquareWay !== 'function') return; // uncache existing
77929 cache.uncacheIssuesOfType('unsquare_way');
77930 var buildings = context.history().tree().intersects(geoExtent([-180, -90], [180, 90]), cache.graph) // everywhere
77931 .filter(function (entity) {
77932 return entity.type === 'way' && entity.tags.building && entity.tags.building !== 'no';
77933 }); // rerun for all buildings
77935 buildings.forEach(function (entity) {
77936 var detected = checkUnsquareWay(entity, cache.graph);
77937 if (!detected.length) return;
77938 cache.cacheIssues(detected);
77941 // Gets all issues that match the given options
77942 // This is called by many other places
77945 // `options` Object like:
77947 // what: 'all', // 'all' or 'edited'
77948 // where: 'all', // 'all' or 'visible'
77949 // includeIgnored: false, // true, false, or 'only'
77950 // includeDisabledRules: false // true, false, or 'only'
77954 // An Array containing the issues
77958 validator.getIssues = function (options) {
77959 var opts = Object.assign({
77962 includeIgnored: false,
77963 includeDisabledRules: false
77965 var view = context.map().extent();
77966 var seen = new Set();
77967 var results = []; // collect head issues - present in the user edits
77969 if (_headCache.graph && _headCache.graph !== _baseCache.graph) {
77970 Object.values(_headCache.issuesByIssueID).forEach(function (issue) {
77971 // In the head cache, only count features that the user is responsible for - #8632
77972 // For example, a user can undo some work and an issue will still present in the
77973 // head graph, but we don't want to credit the user for causing that issue.
77974 var userModified = (issue.entityIds || []).some(function (id) {
77975 return _completeDiff.hasOwnProperty(id);
77977 if (opts.what === 'edited' && !userModified) return; // present in head but user didn't touch it
77979 if (!filter(issue)) return;
77980 seen.add(issue.id);
77981 results.push(issue);
77983 } // collect base issues - present before user edits
77986 if (opts.what === 'all') {
77987 Object.values(_baseCache.issuesByIssueID).forEach(function (issue) {
77988 if (!filter(issue)) return;
77989 seen.add(issue.id);
77990 results.push(issue);
77994 return results; // Filter the issue set to include only what the calling code wants to see.
77995 // Note that we use `context.graph()`/`context.hasEntity()` here, not `cache.graph`,
77996 // because that is the graph that the calling code will be using.
77998 function filter(issue) {
77999 if (!issue) return false;
78000 if (seen.has(issue.id)) return false;
78001 if (_resolvedIssueIDs.has(issue.id)) return false;
78002 if (opts.includeDisabledRules === 'only' && !_disabledRules[issue.type]) return false;
78003 if (!opts.includeDisabledRules && _disabledRules[issue.type]) return false;
78004 if (opts.includeIgnored === 'only' && !_ignoredIssueIDs.has(issue.id)) return false;
78005 if (!opts.includeIgnored && _ignoredIssueIDs.has(issue.id)) return false; // This issue may involve an entity that doesn't exist in context.graph()
78006 // This can happen because validation is async and rendering the issue lists is async.
78008 if ((issue.entityIds || []).some(function (id) {
78009 return !context.hasEntity(id);
78012 if (opts.where === 'visible') {
78013 var extent = issue.extent(context.graph());
78014 if (!view.intersects(extent)) return false;
78019 }; // `getResolvedIssues()`
78020 // Gets the issues that have been fixed by the user.
78022 // Resolved issues are tracked in the `_resolvedIssueIDs` Set,
78023 // and they should all be issues that exist in the _baseCache.
78026 // An Array containing the issues
78030 validator.getResolvedIssues = function () {
78031 return Array.from(_resolvedIssueIDs).map(function (issueID) {
78032 return _baseCache.issuesByIssueID[issueID];
78033 }).filter(Boolean);
78034 }; // `focusIssue()`
78035 // Adjusts the map to focus on the given issue.
78036 // (requires the issue to have a reasonable extent defined)
78039 // `issue` - the issue to focus on
78043 validator.focusIssue = function (issue) {
78044 // Note that we use `context.graph()`/`context.hasEntity()` here, not `cache.graph`,
78045 // because that is the graph that the calling code will be using.
78046 var graph = context.graph();
78048 var focusCenter; // Try to focus the map at the center of the issue..
78050 var issueExtent = issue.extent(graph);
78053 focusCenter = issueExtent.center();
78054 } // Try to select the first entity in the issue..
78057 if (issue.entityIds && issue.entityIds.length) {
78058 selectID = issue.entityIds[0]; // If a relation, focus on one of its members instead.
78059 // Otherwise we might be focusing on a part of map where the relation is not visible.
78061 if (selectID && selectID.charAt(0) === 'r') {
78063 var ids = utilEntityAndDeepMemberIDs([selectID], graph);
78064 var nodeID = ids.find(function (id) {
78065 return id.charAt(0) === 'n' && graph.hasEntity(id);
78069 // relation has no downloaded nodes to focus on
78070 var wayID = ids.find(function (id) {
78071 return id.charAt(0) === 'w' && graph.hasEntity(id);
78075 nodeID = graph.entity(wayID).first(); // focus on the first node of this way
78080 focusCenter = graph.entity(nodeID).loc;
78087 var setZoom = Math.max(context.map().zoom(), 19);
78088 context.map().unobscuredCenterZoomEase(focusCenter, setZoom);
78092 // Enter select mode
78093 window.setTimeout(function () {
78094 context.enter(modeSelect(context, [selectID]));
78095 dispatch.call('focusedIssue', _this, issue);
78096 }, 250); // after ease
78098 }; // `getIssuesBySeverity()`
78099 // Gets the issues then groups them by error/warning
78100 // (This just calls getIssues, then puts issues in groups)
78103 // `options` - (see `getIssues`)
78105 // Object result like:
78107 // error: Array of errors,
78108 // warning: Array of warnings
78113 validator.getIssuesBySeverity = function (options) {
78114 var groups = utilArrayGroupBy(validator.getIssues(options), 'severity');
78115 groups.error = groups.error || [];
78116 groups.warning = groups.warning || [];
78118 }; // `getEntityIssues()`
78119 // Gets the issues that the given entity IDs have in common, matching the given options
78120 // (This just calls getIssues, then filters for the given entity IDs)
78121 // The issues are sorted for relevance
78124 // `entityIDs` - Array or Set of entityIDs to get issues for
78125 // `options` - (see `getIssues`)
78127 // An Array containing the issues
78131 validator.getSharedEntityIssues = function (entityIDs, options) {
78132 var orderedIssueTypes = [// Show some issue types in a particular order:
78133 'missing_tag', 'missing_role', // - missing data first
78134 'outdated_tags', 'mismatched_geometry', // - identity issues
78135 'crossing_ways', 'almost_junction', // - geometry issues where fixing them might solve connectivity issues
78136 'disconnected_way', 'impossible_oneway' // - finally connectivity issues
78138 var allIssues = validator.getIssues(options);
78139 var forEntityIDs = new Set(entityIDs);
78140 return allIssues.filter(function (issue) {
78141 return (issue.entityIds || []).some(function (entityID) {
78142 return forEntityIDs.has(entityID);
78144 }).sort(function (issue1, issue2) {
78145 if (issue1.type === issue2.type) {
78146 // issues of the same type, sort deterministically
78147 return issue1.id < issue2.id ? -1 : 1;
78150 var index1 = orderedIssueTypes.indexOf(issue1.type);
78151 var index2 = orderedIssueTypes.indexOf(issue2.type);
78153 if (index1 !== -1 && index2 !== -1) {
78154 // both issue types have explicit sort orders
78155 return index1 - index2;
78156 } else if (index1 === -1 && index2 === -1) {
78157 // neither issue type has an explicit sort order, sort by type
78158 return issue1.type < issue2.type ? -1 : 1;
78160 // order explicit types before everything else
78161 return index1 !== -1 ? -1 : 1;
78164 }; // `getEntityIssues()`
78165 // Get an array of detected issues for the given entityID.
78166 // (This just calls getSharedEntityIssues for a single entity)
78169 // `entityID` - the entity ID to get the issues for
78170 // `options` - (see `getIssues`)
78172 // An Array containing the issues
78176 validator.getEntityIssues = function (entityID, options) {
78177 return validator.getSharedEntityIssues([entityID], options);
78178 }; // `getRuleKeys()`
78181 // An Array containing the rule keys
78185 validator.getRuleKeys = function () {
78186 return Object.keys(_rules);
78187 }; // `isRuleEnabled()`
78190 // `key` - the rule to check (e.g. 'crossing_ways')
78196 validator.isRuleEnabled = function (key) {
78197 return !_disabledRules[key];
78198 }; // `toggleRule()`
78199 // Toggles a single validation rule,
78200 // then reruns the validation so that the user sees something happen in the UI
78203 // `key` - the rule to toggle (e.g. 'crossing_ways')
78207 validator.toggleRule = function (key) {
78208 if (_disabledRules[key]) {
78209 delete _disabledRules[key];
78211 _disabledRules[key] = true;
78214 corePreferences('validate-disabledRules', Object.keys(_disabledRules).join(','));
78215 validator.validate();
78216 }; // `disableRules()`
78217 // Disables given validation rules,
78218 // then reruns the validation so that the user sees something happen in the UI
78221 // `keys` - Array or Set containing rule keys to disable
78225 validator.disableRules = function (keys) {
78226 _disabledRules = {};
78227 keys.forEach(function (k) {
78228 return _disabledRules[k] = true;
78230 corePreferences('validate-disabledRules', Object.keys(_disabledRules).join(','));
78231 validator.validate();
78232 }; // `ignoreIssue()`
78233 // Don't show the given issue in lists
78236 // `issueID` - the issueID
78240 validator.ignoreIssue = function (issueID) {
78241 _ignoredIssueIDs.add(issueID);
78243 // Validates anything that has changed in the head graph since the last time it was run.
78244 // (head graph contains user's edits)
78247 // A Promise fulfilled when the validation has completed and then dispatches a `validated` event.
78248 // This may take time but happen in the background during browser idle time.
78252 validator.validate = function () {
78253 // Make sure the caches have graphs assigned to them.
78254 // (we don't do this in `reset` because context is still resetting things and `history.base()` is unstable then)
78255 var baseGraph = context.history().base();
78256 if (!_headCache.graph) _headCache.graph = baseGraph;
78257 if (!_baseCache.graph) _baseCache.graph = baseGraph;
78258 var prevGraph = _headCache.graph;
78259 var currGraph = context.graph();
78261 if (currGraph === prevGraph) {
78262 // _headCache.graph is current - we are caught up
78263 _headIsCurrent = true;
78264 dispatch.call('validated');
78265 return Promise.resolve();
78268 if (_headPromise) {
78269 // Validation already in process, but we aren't caught up to current
78270 _headIsCurrent = false; // We will need to catch up after the validation promise fulfills
78272 return _headPromise;
78273 } // If we get here, its time to start validating stuff.
78276 _headCache.graph = currGraph; // take snapshot
78278 _completeDiff = context.history().difference().complete();
78279 var incrementalDiff = coreDifference(prevGraph, currGraph);
78280 var entityIDs = Object.keys(incrementalDiff.complete());
78281 entityIDs = _headCache.withAllRelatedEntities(entityIDs); // expand set
78283 if (!entityIDs.size) {
78284 dispatch.call('validated');
78285 return Promise.resolve();
78288 _headPromise = validateEntitiesAsync(entityIDs, _headCache).then(function () {
78289 return updateResolvedIssues(entityIDs);
78290 }).then(function () {
78291 return dispatch.call('validated');
78292 })["catch"](function () {
78294 }).then(function () {
78295 _headPromise = null;
78297 if (!_headIsCurrent) {
78298 validator.validate(); // run it again to catch up to current graph
78301 return _headPromise;
78302 }; // register event handlers:
78303 // WHEN TO RUN VALIDATION:
78304 // When history changes:
78307 context.history().on('restore.validator', validator.validate) // on restore saved history
78308 .on('undone.validator', validator.validate) // on undo
78309 .on('redone.validator', validator.validate) // on redo
78310 .on('reset.validator', function () {
78311 // on history reset - happens after save, or enter/exit walkthrough
78312 reset(false); // cached issues aren't valid any longer if the history has been reset
78314 validator.validate();
78315 }); // but not on 'change' (e.g. while drawing)
78316 // When user changes editing modes (to catch recent changes e.g. drawing)
78318 context.on('exit.validator', validator.validate); // When merging fetched data, validate base graph:
78320 context.history().on('merge.validator', function (entities) {
78321 if (!entities) return; // Make sure the caches have graphs assigned to them.
78322 // (we don't do this in `reset` because context is still resetting things and `history.base()` is unstable then)
78324 var baseGraph = context.history().base();
78325 if (!_headCache.graph) _headCache.graph = baseGraph;
78326 if (!_baseCache.graph) _baseCache.graph = baseGraph;
78327 var entityIDs = entities.map(function (entity) {
78330 entityIDs = _baseCache.withAllRelatedEntities(entityIDs); // expand set
78332 validateEntitiesAsync(entityIDs, _baseCache);
78333 }); // `validateEntity()` (private)
78334 // Runs all validation rules on a single entity.
78335 // Some things to note:
78336 // - Graph is passed in from whenever the validation was started. Validators shouldn't use
78337 // `context.graph()` because this all happens async, and the graph might have changed
78338 // (for example, nodes getting deleted before the validation can run)
78339 // - Validator functions may still be waiting on something and return a "provisional" result.
78340 // In this situation, we will schedule to revalidate the entity sometime later.
78343 // `entity` - The entity
78344 // `graph` - graph containing the entity
78347 // Object result like:
78349 // issues: Array of detected issues
78350 // provisional: `true` if provisional result, `false` if final result
78354 function validateEntity(entity, graph) {
78359 Object.keys(_rules).forEach(runValidation); // run all rules
78361 return result; // runs validation and appends resulting issues
78363 function runValidation(key) {
78364 var fn = _rules[key];
78366 if (typeof fn !== 'function') {
78367 console.error('no such validation rule = ' + key); // eslint-disable-line no-console
78372 var detected = fn(entity, graph);
78374 if (detected.provisional) {
78375 // this validation should be run again later
78376 result.provisional = true;
78379 detected = detected.filter(applySeverityOverrides);
78380 result.issues = result.issues.concat(detected); // If there are any override rules that match the issue type/subtype,
78381 // adjust severity (or disable it) and keep/discard as quickly as possible.
78383 function applySeverityOverrides(issue) {
78384 var type = issue.type;
78385 var subtype = issue.subtype || '';
78388 for (i = 0; i < _errorOverrides.length; i++) {
78389 if (_errorOverrides[i].type.test(type) && _errorOverrides[i].subtype.test(subtype)) {
78390 issue.severity = 'error';
78395 for (i = 0; i < _warningOverrides.length; i++) {
78396 if (_warningOverrides[i].type.test(type) && _warningOverrides[i].subtype.test(subtype)) {
78397 issue.severity = 'warning';
78402 for (i = 0; i < _disableOverrides.length; i++) {
78403 if (_disableOverrides[i].type.test(type) && _disableOverrides[i].subtype.test(subtype)) {
78411 } // `updateResolvedIssues()` (private)
78412 // Determine if any issues were resolved for the given entities.
78413 // This is called by `validate()` after validation of the head graph
78415 // Give the user credit for fixing an issue if:
78416 // - the issue is in the base cache
78417 // - the issue is not in the head cache
78418 // - the user did something to one of the entities involved in the issue
78421 // `entityIDs` - Array or Set containing entity IDs.
78425 function updateResolvedIssues(entityIDs) {
78426 entityIDs.forEach(function (entityID) {
78427 var baseIssues = _baseCache.issuesByEntityID[entityID];
78428 if (!baseIssues) return;
78429 baseIssues.forEach(function (issueID) {
78430 // Check if the user did something to one of the entities involved in this issue.
78431 // (This issue could involve multiple entities, e.g. disconnected routable features)
78432 var issue = _baseCache.issuesByIssueID[issueID];
78433 var userModified = (issue.entityIds || []).some(function (id) {
78434 return _completeDiff.hasOwnProperty(id);
78437 if (userModified && !_headCache.issuesByIssueID[issueID]) {
78438 // issue seems fixed
78439 _resolvedIssueIDs.add(issueID);
78441 // issue still not resolved
78442 _resolvedIssueIDs["delete"](issueID); // (did undo, or possibly fixed and then re-caused the issue)
78447 } // `validateEntitiesAsync()` (private)
78448 // Schedule validation for many entities.
78451 // `entityIDs` - Array or Set containing entityIDs.
78452 // `graph` - the graph to validate that contains those entities
78453 // `cache` - the cache to store results in (_headCache or _baseCache)
78456 // A Promise fulfilled when the validation has completed.
78457 // This may take time but happen in the background during browser idle time.
78461 function validateEntitiesAsync(entityIDs, cache) {
78462 // Enqueue the work
78463 var jobs = Array.from(entityIDs).map(function (entityID) {
78464 if (cache.queuedEntityIDs.has(entityID)) return null; // queued already
78466 cache.queuedEntityIDs.add(entityID); // Clear caches for existing issues related to this entity
78468 cache.uncacheEntityID(entityID);
78469 return function () {
78470 cache.queuedEntityIDs["delete"](entityID);
78471 var graph = cache.graph;
78472 if (!graph) return; // was reset?
78474 var entity = graph.hasEntity(entityID); // Sanity check: don't validate deleted entities
78476 if (!entity) return; // detect new issues and update caches
78478 var result = validateEntity(entity, graph);
78480 if (result.provisional) {
78481 // provisional result
78482 cache.provisionalEntityIDs.add(entityID); // we'll need to revalidate this entity again later
78485 cache.cacheIssues(result.issues); // update cache
78487 }).filter(Boolean); // Perform the work in chunks.
78488 // Because this will happen during idle callbacks, we want to choose a chunk size
78489 // that won't make the browser stutter too badly.
78491 cache.queue = cache.queue.concat(utilArrayChunk(jobs, 100)); // Perform the work
78493 if (cache.queuePromise) return cache.queuePromise;
78494 cache.queuePromise = processQueue(cache).then(function () {
78495 return revalidateProvisionalEntities(cache);
78496 })["catch"](function () {
78498 })["finally"](function () {
78499 return cache.queuePromise = null;
78501 return cache.queuePromise;
78502 } // `revalidateProvisionalEntities()` (private)
78503 // Sometimes a validator will return a "provisional" result.
78504 // In this situation, we'll need to revalidate the entity later.
78505 // This function waits a delay, then places them back into the validation queue.
78508 // `cache` - The cache (_headCache or _baseCache)
78512 function revalidateProvisionalEntities(cache) {
78513 if (!cache.provisionalEntityIDs.size) return; // nothing to do
78515 var handle = window.setTimeout(function () {
78516 _deferredST["delete"](handle);
78518 if (!cache.provisionalEntityIDs.size) return; // nothing to do
78520 validateEntitiesAsync(Array.from(cache.provisionalEntityIDs), cache);
78523 _deferredST.add(handle);
78524 } // `processQueue(queue)` (private)
78525 // Process the next chunk of deferred validation work
78528 // `cache` - The cache (_headCache or _baseCache)
78531 // A Promise fulfilled when the validation has completed.
78532 // This may take time but happen in the background during browser idle time.
78536 function processQueue(cache) {
78537 // console.log(`${cache.which} queue length ${cache.queue.length}`);
78538 if (!cache.queue.length) return Promise.resolve(); // we're done
78540 var chunk = cache.queue.pop();
78541 return new Promise(function (resolvePromise) {
78542 var handle = window.requestIdleCallback(function () {
78543 _deferredRIC["delete"](handle); // const t0 = performance.now();
78546 chunk.forEach(function (job) {
78548 }); // const t1 = performance.now();
78549 // console.log('chunk processed in ' + (t1 - t0) + ' ms');
78554 _deferredRIC.add(handle);
78555 }).then(function () {
78556 // dispatch an event sometimes to redraw various UI things
78557 if (cache.queue.length % 25 === 0) dispatch.call('validated');
78558 }).then(function () {
78559 return processQueue(cache);
78564 } // `validationCache()` (private)
78565 // Creates a cache to store validation state
78566 // We create 2 of these:
78567 // `_baseCache` for validation on the base graph (unedited)
78568 // `_headCache` for validation on the head graph (user edits applied)
78571 // `which` - just a String 'base' or 'head' to keep track of it
78574 function validationCache(which) {
78579 queuePromise: null,
78580 queuedEntityIDs: new Set(),
78581 provisionalEntityIDs: new Set(),
78582 issuesByIssueID: {},
78583 // issue.id -> issue
78584 issuesByEntityID: {} // entity.id -> Set(issue.id)
78588 cache.cacheIssue = function (issue) {
78589 (issue.entityIds || []).forEach(function (entityID) {
78590 if (!cache.issuesByEntityID[entityID]) {
78591 cache.issuesByEntityID[entityID] = new Set();
78594 cache.issuesByEntityID[entityID].add(issue.id);
78596 cache.issuesByIssueID[issue.id] = issue;
78599 cache.uncacheIssue = function (issue) {
78600 (issue.entityIds || []).forEach(function (entityID) {
78601 if (cache.issuesByEntityID[entityID]) {
78602 cache.issuesByEntityID[entityID]["delete"](issue.id);
78605 delete cache.issuesByIssueID[issue.id];
78608 cache.cacheIssues = function (issues) {
78609 issues.forEach(cache.cacheIssue);
78612 cache.uncacheIssues = function (issues) {
78613 issues.forEach(cache.uncacheIssue);
78616 cache.uncacheIssuesOfType = function (type) {
78617 var issuesOfType = Object.values(cache.issuesByIssueID).filter(function (issue) {
78618 return issue.type === type;
78620 cache.uncacheIssues(issuesOfType);
78621 }; // Remove a single entity and all its related issues from the caches
78624 cache.uncacheEntityID = function (entityID) {
78625 var entityIssueIDs = cache.issuesByEntityID[entityID];
78627 if (entityIssueIDs) {
78628 entityIssueIDs.forEach(function (issueID) {
78629 var issue = cache.issuesByIssueID[issueID];
78632 cache.uncacheIssue(issue);
78634 // shouldn't happen, clean up
78635 delete cache.issuesByIssueID[issueID];
78640 delete cache.issuesByEntityID[entityID];
78641 cache.provisionalEntityIDs["delete"](entityID);
78642 }; // Return the expandeded set of entityIDs related to issues for the given entityIDs
78645 // `entityIDs` - Array or Set containing entityIDs.
78649 cache.withAllRelatedEntities = function (entityIDs) {
78650 var result = new Set();
78651 (entityIDs || []).forEach(function (entityID) {
78652 result.add(entityID); // include self
78654 var entityIssueIDs = cache.issuesByEntityID[entityID];
78656 if (entityIssueIDs) {
78657 entityIssueIDs.forEach(function (issueID) {
78658 var issue = cache.issuesByIssueID[issueID];
78661 (issue.entityIds || []).forEach(function (relatedID) {
78662 return result.add(relatedID);
78665 // shouldn't happen, clean up
78666 delete cache.issuesByIssueID[issueID];
78677 function coreUploader(context) {
78678 var dispatch = dispatch$8( // Start and end events are dispatched exactly once each per legitimate outside call to `save`
78679 'saveStarted', // dispatched as soon as a call to `save` has been deemed legitimate
78680 'saveEnded', // dispatched after the result event has been dispatched
78681 'willAttemptUpload', // dispatched before the actual upload call occurs, if it will
78682 'progressChanged', // Each save results in one of these outcomes:
78683 'resultNoChanges', // upload wasn't attempted since there were no edits
78684 'resultErrors', // upload failed due to errors
78685 'resultConflicts', // upload failed due to data conflicts
78686 'resultSuccess' // upload completed without errors
78688 var _isSaving = false;
78689 var _conflicts = [];
78694 var _discardTags = {};
78695 _mainFileFetcher.get('discarded').then(function (d) {
78697 })["catch"](function () {
78700 var uploader = utilRebind({}, dispatch, 'on');
78702 uploader.isSaving = function () {
78706 uploader.save = function (changeset, tryAgain, checkConflicts) {
78707 // Guard against accidentally entering save code twice - #4641
78708 if (_isSaving && !tryAgain) {
78712 var osm = context.connection();
78713 if (!osm) return; // If user somehow got logged out mid-save, try to reauthenticate..
78714 // This can happen if they were logged in from before, but the tokens are no longer valid.
78716 if (!osm.authenticated()) {
78717 osm.authenticate(function (err) {
78719 uploader.save(changeset, tryAgain, checkConflicts); // continue where we left off..
78727 dispatch.call('saveStarted', this);
78730 var history = context.history();
78732 _errors = []; // Store original changes, in case user wants to download them as an .osc file
78734 _origChanges = history.changes(actionDiscardTags(history.difference(), _discardTags)); // First time, `history.perform` a no-op action.
78735 // Any conflict resolutions will be done as `history.replace`
78736 // Remember to pop this later if needed
78739 history.perform(actionNoop());
78740 } // Attempt a fast upload.. If there are conflicts, re-enter with `checkConflicts = true`
78743 if (!checkConflicts) {
78744 upload(changeset); // Do the full (slow) conflict check..
78746 performFullConflictCheck(changeset);
78750 function performFullConflictCheck(changeset) {
78751 var osm = context.connection();
78753 var history = context.history();
78754 var localGraph = context.graph();
78755 var remoteGraph = coreGraph(history.base(), true);
78756 var summary = history.difference().summary();
78759 for (var i = 0; i < summary.length; i++) {
78760 var item = summary[i];
78762 if (item.changeType === 'modified') {
78763 _toCheck.push(item.entity.id);
78767 var _toLoad = withChildNodes(_toCheck, localGraph);
78770 var _toLoadCount = 0;
78771 var _toLoadTotal = _toLoad.length;
78773 if (_toCheck.length) {
78774 dispatch.call('progressChanged', this, _toLoadCount, _toLoadTotal);
78776 _toLoad.forEach(function (id) {
78777 _loaded[id] = false;
78780 osm.loadMultiple(_toLoad, loaded);
78787 function withChildNodes(ids, graph) {
78788 var s = new Set(ids);
78789 ids.forEach(function (id) {
78790 var entity = graph.entity(id);
78791 if (entity.type !== 'way') return;
78792 graph.childNodes(entity).forEach(function (child) {
78793 if (child.version !== undefined) {
78798 return Array.from(s);
78799 } // Reload modified entities into an alternate graph and check for conflicts..
78802 function loaded(err, result) {
78803 if (_errors.length) return;
78807 msg: err.message || err.responseText,
78808 details: [_t('save.status_code', {
78813 didResultInErrors();
78816 result.data.forEach(function (entity) {
78817 remoteGraph.replace(entity);
78818 _loaded[entity.id] = true;
78819 _toLoad = _toLoad.filter(function (val) {
78820 return val !== entity.id;
78822 if (!entity.visible) return; // Because loadMultiple doesn't download /full like loadEntity,
78823 // need to also load children that aren't already being checked..
78827 if (entity.type === 'way') {
78828 for (i = 0; i < entity.nodes.length; i++) {
78829 id = entity.nodes[i];
78831 if (_loaded[id] === undefined) {
78832 _loaded[id] = false;
78836 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
78837 for (i = 0; i < entity.members.length; i++) {
78838 id = entity.members[i].id;
78840 if (_loaded[id] === undefined) {
78841 _loaded[id] = false;
78847 _toLoadCount += result.data.length;
78848 _toLoadTotal += loadMore.length;
78849 dispatch.call('progressChanged', this, _toLoadCount, _toLoadTotal);
78851 if (loadMore.length) {
78852 _toLoad.push.apply(_toLoad, loadMore);
78854 osm.loadMultiple(loadMore, loaded);
78857 if (!_toLoad.length) {
78864 function detectConflicts() {
78865 function choice(id, text, _action) {
78869 action: function action() {
78870 history.replace(_action);
78875 function formatUser(d) {
78876 return '<a href="' + osm.userURL(d) + '" target="_blank">' + escape$4(d) + '</a>';
78879 function entityName(entity) {
78880 return utilDisplayName(entity) || utilDisplayType(entity.id) + ' ' + entity.id;
78883 function sameVersions(local, remote) {
78884 if (local.version !== remote.version) return false;
78886 if (local.type === 'way') {
78887 var children = utilArrayUnion(local.nodes, remote.nodes);
78889 for (var i = 0; i < children.length; i++) {
78890 var a = localGraph.hasEntity(children[i]);
78891 var b = remoteGraph.hasEntity(children[i]);
78892 if (a && b && a.version !== b.version) return false;
78899 _toCheck.forEach(function (id) {
78900 var local = localGraph.entity(id);
78901 var remote = remoteGraph.entity(id);
78902 if (sameVersions(local, remote)) return;
78903 var merge = actionMergeRemoteChanges(id, localGraph, remoteGraph, _discardTags, formatUser);
78904 history.replace(merge);
78905 var mergeConflicts = merge.conflicts();
78906 if (!mergeConflicts.length) return; // merged safely
78908 var forceLocal = actionMergeRemoteChanges(id, localGraph, remoteGraph, _discardTags).withOption('force_local');
78909 var forceRemote = actionMergeRemoteChanges(id, localGraph, remoteGraph, _discardTags).withOption('force_remote');
78910 var keepMine = _t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore'));
78911 var keepTheirs = _t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
78915 name: entityName(local),
78916 details: mergeConflicts,
78918 choices: [choice(id, keepMine, forceLocal), choice(id, keepTheirs, forceRemote)]
78924 function upload(changeset) {
78925 var osm = context.connection();
78929 msg: 'No OSM Service'
78933 if (_conflicts.length) {
78934 didResultInConflicts(changeset);
78935 } else if (_errors.length) {
78936 didResultInErrors();
78938 var history = context.history();
78939 var changes = history.changes(actionDiscardTags(history.difference(), _discardTags));
78941 if (changes.modified.length || changes.created.length || changes.deleted.length) {
78942 dispatch.call('willAttemptUpload', this);
78943 osm.putChangeset(changeset, changes, uploadCallback);
78945 // changes were insignificant or reverted by user
78946 didResultInNoChanges();
78951 function uploadCallback(err, changeset) {
78953 if (err.status === 409) {
78955 uploader.save(changeset, true, true); // tryAgain = true, checkConflicts = true
78958 msg: err.message || err.responseText,
78959 details: [_t('save.status_code', {
78964 didResultInErrors();
78967 didResultInSuccess(changeset);
78971 function didResultInNoChanges() {
78972 dispatch.call('resultNoChanges', this);
78974 context.flush(); // reset iD
78977 function didResultInErrors() {
78978 context.history().pop();
78979 dispatch.call('resultErrors', this, _errors);
78983 function didResultInConflicts(changeset) {
78984 _conflicts.sort(function (a, b) {
78985 return b.id.localeCompare(a.id);
78988 dispatch.call('resultConflicts', this, changeset, _conflicts, _origChanges);
78992 function didResultInSuccess(changeset) {
78993 // delete the edit stack cached to local storage
78994 context.history().clearSaved();
78995 dispatch.call('resultSuccess', this, changeset); // Add delay to allow for postgres replication #1646 #2678
78997 window.setTimeout(function () {
78999 context.flush(); // reset iD
79003 function endSave() {
79005 dispatch.call('saveEnded', this);
79008 uploader.cancelConflictResolution = function () {
79009 context.history().pop();
79012 uploader.processResolvedConflicts = function (changeset) {
79013 var history = context.history();
79015 for (var i = 0; i < _conflicts.length; i++) {
79016 if (_conflicts[i].chosen === 1) {
79017 // user chose "use theirs"
79018 var entity = context.hasEntity(_conflicts[i].id);
79020 if (entity && entity.type === 'way') {
79021 var children = utilArrayUniq(entity.nodes);
79023 for (var j = 0; j < children.length; j++) {
79024 history.replace(actionRevert(children[j]));
79028 history.replace(actionRevert(_conflicts[i].id));
79032 uploader.save(changeset, true, false); // tryAgain = true, checkConflicts = false
79035 uploader.reset = function () {};
79041 var fails = fails$V;
79042 var expm1 = mathExpm1;
79044 var abs = Math.abs;
79045 var exp = Math.exp;
79048 var FORCED = fails(function () {
79049 // eslint-disable-next-line es/no-math-sinh -- required for testing
79050 return Math.sinh(-2e-17) != -2e-17;
79053 // `Math.sinh` method
79054 // https://tc39.es/ecma262/#sec-math.sinh
79055 // V8 near Chromium 38 has a problem with very small numbers
79056 $$2({ target: 'Math', stat: true, forced: FORCED }, {
79057 sinh: function sinh(x) {
79058 return abs(x = +x) < 1 ? (expm1(x) - expm1(-x)) / 2 : (exp(x - 1) - exp(-x - 1)) * (E / 2);
79062 var isRetina = window.devicePixelRatio && window.devicePixelRatio >= 2; // listen for DPI change, e.g. when dragging a browser window from a retina to non-retina screen
79064 window.matchMedia("\n (-webkit-min-device-pixel-ratio: 2), /* Safari */\n (min-resolution: 2dppx), /* standard */\n (min-resolution: 192dpi) /* fallback */\n ").addListener(function () {
79065 isRetina = window.devicePixelRatio && window.devicePixelRatio >= 2;
79068 function localeDateString(s) {
79069 if (!s) return null;
79075 var d = new Date(s);
79076 if (isNaN(d.getTime())) return null;
79077 return d.toLocaleDateString(_mainLocalizer.localeCode(), options);
79080 function vintageRange(vintage) {
79083 if (vintage.start || vintage.end) {
79084 s = vintage.start || '?';
79086 if (vintage.start !== vintage.end) {
79087 s += ' - ' + (vintage.end || '?');
79094 function rendererBackgroundSource(data) {
79095 var source = Object.assign({}, data); // shallow copy
79097 var _offset = [0, 0];
79098 var _name = source.name;
79099 var _description = source.description;
79101 var _best = !!source.best;
79103 var _template = source.encrypted ? utilAesDecrypt(source.template) : source.template;
79105 source.tileSize = data.tileSize || 256;
79106 source.zoomExtent = data.zoomExtent || [0, 22];
79107 source.overzoom = data.overzoom !== false;
79109 source.offset = function (val) {
79110 if (!arguments.length) return _offset;
79115 source.nudge = function (val, zoomlevel) {
79116 _offset[0] += val[0] / Math.pow(2, zoomlevel);
79117 _offset[1] += val[1] / Math.pow(2, zoomlevel);
79121 source.name = function () {
79122 var id_safe = source.id.replace(/\./g, '<TX_DOT>');
79123 return _t('imagery.' + id_safe + '.name', {
79124 "default": lodash.exports.escape(_name)
79128 source.label = function () {
79129 var id_safe = source.id.replace(/\./g, '<TX_DOT>');
79130 return _t.html('imagery.' + id_safe + '.name', {
79131 "default": lodash.exports.escape(_name)
79135 source.description = function () {
79136 var id_safe = source.id.replace(/\./g, '<TX_DOT>');
79137 return _t.html('imagery.' + id_safe + '.description', {
79138 "default": lodash.exports.escape(_description)
79142 source.best = function () {
79146 source.area = function () {
79147 if (!data.polygon) return Number.MAX_VALUE; // worldwide
79149 var area = d3_geoArea({
79150 type: 'MultiPolygon',
79151 coordinates: [data.polygon]
79153 return isNaN(area) ? 0 : area;
79156 source.imageryUsed = function () {
79157 return _name || source.id;
79160 source.template = function (val) {
79161 if (!arguments.length) return _template;
79163 if (source.id === 'custom' || source.id === 'Bing') {
79170 source.url = function (coord) {
79171 var result = _template;
79172 if (result === '') return result; // source 'none'
79173 // Guess a type based on the tokens present in the template
79174 // (This is for 'custom' source, where we don't know)
79176 if (!source.type || source.id === 'custom') {
79177 if (/SERVICE=WMS|\{(proj|wkid|bbox)\}/.test(_template)) {
79178 source.type = 'wms';
79179 source.projection = 'EPSG:3857'; // guess
79180 } else if (/\{(x|y)\}/.test(_template)) {
79181 source.type = 'tms';
79182 } else if (/\{u\}/.test(_template)) {
79183 source.type = 'bing';
79187 if (source.type === 'wms') {
79188 var tileToProjectedCoords = function tileToProjectedCoords(x, y, z) {
79189 //polyfill for IE11, PhantomJS
79190 var sinh = Math.sinh || function (x) {
79191 var y = Math.exp(x);
79192 return (y - 1 / y) / 2;
79195 var zoomSize = Math.pow(2, z);
79196 var lon = x / zoomSize * Math.PI * 2 - Math.PI;
79197 var lat = Math.atan(sinh(Math.PI * (1 - 2 * y / zoomSize)));
79199 switch (source.projection) {
79202 x: lon * 180 / Math.PI,
79203 y: lat * 180 / Math.PI
79207 // EPSG:3857 and synonyms
79208 var mercCoords = mercatorRaw(lon, lat);
79210 x: 20037508.34 / Math.PI * mercCoords[0],
79211 y: 20037508.34 / Math.PI * mercCoords[1]
79216 var tileSize = source.tileSize;
79217 var projection = source.projection;
79218 var minXmaxY = tileToProjectedCoords(coord[0], coord[1], coord[2]);
79219 var maxXminY = tileToProjectedCoords(coord[0] + 1, coord[1] + 1, coord[2]);
79220 result = result.replace(/\{(\w+)\}/g, function (token, key) {
79230 return projection.replace(/^EPSG:/, '');
79233 // WMS 1.3 flips x/y for some coordinate systems including EPSG:4326 - #7557
79234 if (projection === 'EPSG:4326' && // The CRS parameter implies version 1.3 (prior versions use SRS)
79235 /VERSION=1.3|CRS={proj}/.test(source.template().toUpperCase())) {
79236 return maxXminY.y + ',' + minXmaxY.x + ',' + minXmaxY.y + ',' + maxXminY.x;
79238 return minXmaxY.x + ',' + maxXminY.y + ',' + maxXminY.x + ',' + minXmaxY.y;
79257 } else if (source.type === 'tms') {
79258 result = result.replace('{x}', coord[0]).replace('{y}', coord[1]) // TMS-flipped y coordinate
79259 .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1).replace(/\{z(oom)?\}/, coord[2]) // only fetch retina tiles for retina screens
79260 .replace(/\{@2x\}|\{r\}/, isRetina ? '@2x' : '');
79261 } else if (source.type === 'bing') {
79262 result = result.replace('{u}', function () {
79265 for (var zoom = coord[2]; zoom > 0; zoom--) {
79267 var mask = 1 << zoom - 1;
79268 if ((coord[0] & mask) !== 0) b++;
79269 if ((coord[1] & mask) !== 0) b += 2;
79275 } // these apply to any type..
79278 result = result.replace(/\{switch:([^}]+)\}/, function (s, r) {
79279 var subdomains = r.split(',');
79280 return subdomains[(coord[0] + coord[1]) % subdomains.length];
79285 source.validZoom = function (z) {
79286 return source.zoomExtent[0] <= z && (source.overzoom || source.zoomExtent[1] > z);
79289 source.isLocatorOverlay = function () {
79290 return source.id === 'mapbox_locator_overlay';
79292 /* hides a source from the list, but leaves it available for use */
79295 source.isHidden = function () {
79296 return source.id === 'DigitalGlobe-Premium-vintage' || source.id === 'DigitalGlobe-Standard-vintage';
79299 source.copyrightNotices = function () {};
79301 source.getMetadata = function (center, tileCoord, callback) {
79303 start: localeDateString(source.startDate),
79304 end: localeDateString(source.endDate)
79306 vintage.range = vintageRange(vintage);
79310 callback(null, metadata);
79316 rendererBackgroundSource.Bing = function (data, dispatch) {
79317 // https://docs.microsoft.com/en-us/bingmaps/rest-services/imagery/get-imagery-metadata
79318 // https://docs.microsoft.com/en-us/bingmaps/rest-services/directly-accessing-the-bing-maps-tiles
79319 //fallback url template
79320 data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&n=z';
79321 var bing = rendererBackgroundSource(data); //var key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU'; // P2, JOSM, etc
79323 var key = 'Ak5oTE46TUbjRp08OFVcGpkARErDobfpuyNKa-W2mQ8wbt1K1KL8p1bIRwWwcF-Q'; // iD
79326 missing tile image strictness param (n=)
79327 • n=f -> (Fail) returns a 404
79328 • n=z -> (Empty) returns a 200 with 0 bytes (no content)
79329 • n=t -> (Transparent) returns a 200 with a transparent (png) tile
79332 var strictParam = 'n';
79333 var url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&uriScheme=https&key=' + key;
79336 var providers = [];
79337 d3_json(url).then(function (json) {
79338 var imageryResource = json.resourceSets[0].resources[0]; //retrieve and prepare up to date imagery template
79340 var template = imageryResource.imageUrl; //https://ecn.{subdomain}.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=10339
79342 var subDomains = imageryResource.imageUrlSubdomains; //["t0, t1, t2, t3"]
79344 var subDomainNumbers = subDomains.map(function (subDomain) {
79345 return subDomain.substring(1);
79347 template = template.replace('{subdomain}', "t{switch:".concat(subDomainNumbers, "}")).replace('{quadkey}', '{u}');
79349 if (!new URLSearchParams(template).has(strictParam)) {
79350 template += "&".concat(strictParam, "=z");
79353 bing.template(template);
79354 providers = imageryResource.imageryProviders.map(function (provider) {
79356 attribution: provider.attribution,
79357 areas: provider.coverageAreas.map(function (area) {
79359 zoom: [area.zoomMin, area.zoomMax],
79360 extent: geoExtent([area.bbox[1], area.bbox[0]], [area.bbox[3], area.bbox[2]])
79365 dispatch.call('change');
79366 })["catch"](function () {
79370 bing.copyrightNotices = function (zoom, extent) {
79371 zoom = Math.min(zoom, 21);
79372 return providers.filter(function (provider) {
79373 return provider.areas.some(function (area) {
79374 return extent.intersects(area.extent) && area.zoom[0] <= zoom && area.zoom[1] >= zoom;
79376 }).map(function (provider) {
79377 return provider.attribution;
79381 bing.getMetadata = function (center, tileCoord, callback) {
79382 var tileID = tileCoord.slice(0, 3).join('/');
79383 var zoom = Math.min(tileCoord[2], 21);
79384 var centerPoint = center[1] + ',' + center[0]; // lat,lng
79386 var url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/' + centerPoint + '?zl=' + zoom + '&key=' + key;
79387 if (inflight[tileID]) return;
79389 if (!cache[tileID]) {
79390 cache[tileID] = {};
79393 if (cache[tileID] && cache[tileID].metadata) {
79394 return callback(null, cache[tileID].metadata);
79397 inflight[tileID] = true;
79398 d3_json(url).then(function (result) {
79399 delete inflight[tileID];
79402 throw new Error('Unknown Error');
79406 start: localeDateString(result.resourceSets[0].resources[0].vintageStart),
79407 end: localeDateString(result.resourceSets[0].resources[0].vintageEnd)
79409 vintage.range = vintageRange(vintage);
79413 cache[tileID].metadata = metadata;
79414 if (callback) callback(null, metadata);
79415 })["catch"](function (err) {
79416 delete inflight[tileID];
79417 if (callback) callback(err.message);
79421 bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
79425 rendererBackgroundSource.Esri = function (data) {
79426 // in addition to using the tilemap at zoom level 20, overzoom real tiles - #4327 (deprecated technique, but it works)
79427 if (data.template.match(/blankTile/) === null) {
79428 data.template = data.template + '?blankTile=false';
79431 var esri = rendererBackgroundSource(data);
79435 var _prevCenter; // use a tilemap service to set maximum zoom for esri tiles dynamically
79436 // https://developers.arcgis.com/documentation/tiled-elevation-service/
79439 esri.fetchTilemap = function (center) {
79440 // skip if we have already fetched a tilemap within 5km
79441 if (_prevCenter && geoSphericalDistance(center, _prevCenter) < 5000) return;
79442 _prevCenter = center; // tiles are available globally to zoom level 19, afterward they may or may not be present
79444 var z = 20; // first generate a random url using the template
79446 var dummyUrl = esri.url([1, 2, 3]); // calculate url z/y/x from the lat/long of the center of the map
79448 var x = Math.floor((center[0] + 180) / 360 * Math.pow(2, z));
79449 var y = Math.floor((1 - Math.log(Math.tan(center[1] * Math.PI / 180) + 1 / Math.cos(center[1] * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, z)); // fetch an 8x8 grid to leverage cache
79451 var tilemapUrl = dummyUrl.replace(/tile\/[0-9]+\/[0-9]+\/[0-9]+\?blankTile=false/, 'tilemap') + '/' + z + '/' + y + '/' + x + '/8/8'; // make the request and introspect the response from the tilemap server
79453 d3_json(tilemapUrl).then(function (tilemap) {
79455 throw new Error('Unknown Error');
79458 var hasTiles = true;
79460 for (var i = 0; i < tilemap.data.length; i++) {
79461 // 0 means an individual tile in the grid doesn't exist
79462 if (!tilemap.data[i]) {
79466 } // if any tiles are missing at level 20 we restrict maxZoom to 19
79469 esri.zoomExtent[1] = hasTiles ? 22 : 19;
79470 })["catch"](function () {
79475 esri.getMetadata = function (center, tileCoord, callback) {
79476 if (esri.id !== 'EsriWorldImagery') {
79477 // rest endpoint is not available for ESRI's "clarity" imagery
79478 return callback(null, {});
79481 var tileID = tileCoord.slice(0, 3).join('/');
79482 var zoom = Math.min(tileCoord[2], esri.zoomExtent[1]);
79483 var centerPoint = center[0] + ',' + center[1]; // long, lat (as it should be)
79485 var unknown = _t('info_panels.background.unknown');
79488 if (inflight[tileID]) return; // build up query using the layer appropriate to the current zoom
79490 var url = 'https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/4/query';
79491 url += '?returnGeometry=false&geometry=' + centerPoint + '&inSR=4326&geometryType=esriGeometryPoint&outFields=*&f=json';
79493 if (!cache[tileID]) {
79494 cache[tileID] = {};
79497 if (cache[tileID] && cache[tileID].metadata) {
79498 return callback(null, cache[tileID].metadata);
79501 inflight[tileID] = true;
79502 d3_json(url).then(function (result) {
79503 delete inflight[tileID];
79504 result = result.features.map(function (f) {
79505 return f.attributes;
79506 }).filter(function (a) {
79507 return a.MinMapLevel <= zoom && a.MaxMapLevel >= zoom;
79511 throw new Error('Unknown Error');
79512 } else if (result.features && result.features.length < 1) {
79513 throw new Error('No Results');
79514 } else if (result.error && result.error.message) {
79515 throw new Error(result.error.message);
79516 } // pass through the discrete capture date from metadata
79519 var captureDate = localeDateString(result.SRC_DATE2);
79521 start: captureDate,
79527 source: clean(result.NICE_NAME),
79528 description: clean(result.NICE_DESC),
79529 resolution: clean(+parseFloat(result.SRC_RES).toFixed(4)),
79530 accuracy: clean(+parseFloat(result.SRC_ACC).toFixed(4))
79531 }; // append units - meters
79533 if (isFinite(metadata.resolution)) {
79534 metadata.resolution += ' m';
79537 if (isFinite(metadata.accuracy)) {
79538 metadata.accuracy += ' m';
79541 cache[tileID].metadata = metadata;
79542 if (callback) callback(null, metadata);
79543 })["catch"](function (err) {
79544 delete inflight[tileID];
79545 if (callback) callback(err.message);
79548 function clean(val) {
79549 return String(val).trim() || unknown;
79556 rendererBackgroundSource.None = function () {
79557 var source = rendererBackgroundSource({
79562 source.name = function () {
79563 return _t('background.none');
79566 source.label = function () {
79567 return _t.html('background.none');
79570 source.imageryUsed = function () {
79574 source.area = function () {
79575 return -1; // sources in background pane are sorted by area
79581 rendererBackgroundSource.Custom = function (template) {
79582 var source = rendererBackgroundSource({
79587 source.name = function () {
79588 return _t('background.custom');
79591 source.label = function () {
79592 return _t.html('background.custom');
79595 source.imageryUsed = function () {
79596 // sanitize personal connection tokens - #6801
79597 var cleaned = source.template(); // from query string parameters
79599 if (cleaned.indexOf('?') !== -1) {
79600 var parts = cleaned.split('?', 2);
79601 var qs = utilStringQs(parts[1]);
79602 ['access_token', 'connectId', 'token'].forEach(function (param) {
79604 qs[param] = '{apikey}';
79607 cleaned = parts[0] + '?' + utilQsString(qs, true); // true = soft encode
79608 } // from wms/wmts api path parameters
79611 cleaned = cleaned.replace(/token\/(\w+)/, 'token/{apikey}');
79612 return 'Custom (' + cleaned + ' )';
79615 source.area = function () {
79616 return -2; // sources in background pane are sorted by area
79622 function rendererTileLayer(context) {
79623 var transformProp = utilPrefixCSSProperty('Transform');
79624 var tiler = utilTiler();
79625 var _tileSize = 256;
79637 function tileSizeAtZoom(d, z) {
79638 var EPSILON = 0.002; // close seams
79640 return _tileSize * Math.pow(2, z - d[2]) / _tileSize + EPSILON;
79643 function atZoom(t, distance) {
79644 var power = Math.pow(2, distance);
79645 return [Math.floor(t[0] * power), Math.floor(t[1] * power), t[2] + distance];
79648 function lookUp(d) {
79649 for (var up = -1; up > -d[2]; up--) {
79650 var tile = atZoom(d, up);
79652 if (_cache[_source.url(tile)] !== false) {
79658 function uniqueBy(a, n) {
79662 for (var i = 0; i < a.length; i++) {
79663 if (seen[a[i][n]] === undefined) {
79665 seen[a[i][n]] = true;
79672 function addSource(d) {
79673 d.push(_source.url(d));
79675 } // Update tiles based on current state of `projection`.
79678 function background(selection) {
79679 _zoom = geoScaleToZoom(_projection.scale(), _tileSize);
79683 pixelOffset = [_source.offset()[0] * Math.pow(2, _zoom), _source.offset()[1] * Math.pow(2, _zoom)];
79685 pixelOffset = [0, 0];
79688 var translate = [_projection.translate()[0] + pixelOffset[0], _projection.translate()[1] + pixelOffset[1]];
79689 tiler.scale(_projection.scale() * 2 * Math.PI).translate(translate);
79690 _tileOrigin = [_projection.scale() * Math.PI - translate[0], _projection.scale() * Math.PI - translate[1]];
79692 } // Derive the tiles onscreen, remove those offscreen and position them.
79693 // Important that this part not depend on `_projection` because it's
79694 // rentered when tiles load/error (see #644).
79697 function render(selection) {
79698 if (!_source) return;
79700 var showDebug = context.getDebug('tile') && !_source.overlay;
79702 if (_source.validZoom(_zoom)) {
79703 tiler.skipNullIsland(!!_source.overlay);
79704 tiler().forEach(function (d) {
79706 if (d[3] === '') return;
79707 if (typeof d[3] !== 'string') return; // Workaround for #2295
79711 if (_cache[d[3]] === false && lookUp(d)) {
79712 requests.push(addSource(lookUp(d)));
79715 requests = uniqueBy(requests, 3).filter(function (r) {
79716 // don't re-request tiles which have failed in the past
79717 return _cache[r[3]] !== false;
79721 function load(d3_event, d) {
79722 _cache[d[3]] = true;
79723 select(this).on('error', null).on('load', null).classed('tile-loaded', true);
79727 function error(d3_event, d) {
79728 _cache[d[3]] = false;
79729 select(this).on('error', null).on('load', null).remove();
79733 function imageTransform(d) {
79734 var ts = _tileSize * Math.pow(2, _zoom - d[2]);
79736 var scale = tileSizeAtZoom(d, _zoom);
79737 return 'translate(' + (d[0] * ts - _tileOrigin[0]) + 'px,' + (d[1] * ts - _tileOrigin[1]) + 'px) ' + 'scale(' + scale + ',' + scale + ')';
79740 function tileCenter(d) {
79741 var ts = _tileSize * Math.pow(2, _zoom - d[2]);
79743 return [d[0] * ts - _tileOrigin[0] + ts / 2, d[1] * ts - _tileOrigin[1] + ts / 2];
79746 function debugTransform(d) {
79747 var coord = tileCenter(d);
79748 return 'translate(' + coord[0] + 'px,' + coord[1] + 'px)';
79749 } // Pick a representative tile near the center of the viewport
79750 // (This is useful for sampling the imagery vintage)
79753 var dims = tiler.size();
79754 var mapCenter = [dims[0] / 2, dims[1] / 2];
79755 var minDist = Math.max(dims[0], dims[1]);
79757 requests.forEach(function (d) {
79758 var c = tileCenter(d);
79759 var dist = geoVecLength(c, mapCenter);
79761 if (dist < minDist) {
79766 var image = selection.selectAll('img').data(requests, function (d) {
79769 image.exit().style(transformProp, imageTransform).classed('tile-removing', true).classed('tile-center', false).each(function () {
79770 var tile = select(this);
79771 window.setTimeout(function () {
79772 if (tile.classed('tile-removing')) {
79777 image.enter().append('img').attr('class', 'tile').attr('alt', '').attr('draggable', 'false').style('width', _tileSize + 'px').style('height', _tileSize + 'px').attr('src', function (d) {
79779 }).on('error', error).on('load', load).merge(image).style(transformProp, imageTransform).classed('tile-debug', showDebug).classed('tile-removing', false).classed('tile-center', function (d) {
79780 return d === nearCenter;
79782 var debug = selection.selectAll('.tile-label-debug').data(showDebug ? requests : [], function (d) {
79785 debug.exit().remove();
79788 var debugEnter = debug.enter().append('div').attr('class', 'tile-label-debug');
79789 debugEnter.append('div').attr('class', 'tile-label-debug-coord');
79790 debugEnter.append('div').attr('class', 'tile-label-debug-vintage');
79791 debug = debug.merge(debugEnter);
79792 debug.style(transformProp, debugTransform);
79793 debug.selectAll('.tile-label-debug-coord').text(function (d) {
79794 return d[2] + ' / ' + d[0] + ' / ' + d[1];
79796 debug.selectAll('.tile-label-debug-vintage').each(function (d) {
79797 var span = select(this);
79798 var center = context.projection.invert(tileCenter(d));
79800 _source.getMetadata(center, d, function (err, result) {
79801 if (result && result.vintage && result.vintage.range) {
79802 span.text(result.vintage.range);
79804 span.html(_t.html('info_panels.background.vintage') + ': ' + _t.html('info_panels.background.unknown'));
79811 background.projection = function (val) {
79812 if (!arguments.length) return _projection;
79817 background.dimensions = function (val) {
79818 if (!arguments.length) return tiler.size();
79823 background.source = function (val) {
79824 if (!arguments.length) return _source;
79826 _tileSize = _source.tileSize;
79828 tiler.tileSize(_source.tileSize).zoomExtent(_source.zoomExtent);
79835 var _imageryIndex = null;
79836 function rendererBackground(context) {
79837 var dispatch = dispatch$8('change');
79838 var detected = utilDetect();
79839 var baseLayer = rendererTileLayer(context).projection(context.projection);
79840 var _checkedBlocklists = [];
79841 var _isValid = true;
79842 var _overlayLayers = [];
79843 var _brightness = 1;
79845 var _saturation = 1;
79846 var _sharpness = 1;
79848 function ensureImageryIndex() {
79849 return _mainFileFetcher.get('imagery').then(function (sources) {
79850 if (_imageryIndex) return _imageryIndex;
79854 }; // use which-polygon to support efficient index and querying for imagery
79856 var features = sources.map(function (source) {
79857 if (!source.polygon) return null; // workaround for editor-layer-index weirdness..
79858 // Add an extra array nest to each element in `source.polygon`
79859 // so the rings are not treated as a bunch of holes:
79860 // what we have: [ [[outer],[hole],[hole]] ]
79861 // what we want: [ [[outer]],[[outer]],[[outer]] ]
79863 var rings = source.polygon.map(function (ring) {
79872 type: 'MultiPolygon',
79876 _imageryIndex.features[source.id] = feature;
79878 }).filter(Boolean);
79879 _imageryIndex.query = whichPolygon_1({
79880 type: 'FeatureCollection',
79882 }); // Instantiate `rendererBackgroundSource` objects for each source
79884 _imageryIndex.backgrounds = sources.map(function (source) {
79885 if (source.type === 'bing') {
79886 return rendererBackgroundSource.Bing(source, dispatch);
79887 } else if (/^EsriWorldImagery/.test(source.id)) {
79888 return rendererBackgroundSource.Esri(source);
79890 return rendererBackgroundSource(source);
79894 _imageryIndex.backgrounds.unshift(rendererBackgroundSource.None()); // Add 'Custom'
79897 var template = corePreferences('background-custom-template') || '';
79898 var custom = rendererBackgroundSource.Custom(template);
79900 _imageryIndex.backgrounds.unshift(custom);
79902 return _imageryIndex;
79906 function background(selection) {
79907 var currSource = baseLayer.source(); // If we are displaying an Esri basemap at high zoom,
79908 // check its tilemap to see how high the zoom can go
79910 if (context.map().zoom() > 18) {
79911 if (currSource && /^EsriWorldImagery/.test(currSource.id)) {
79912 var center = context.map().center();
79913 currSource.fetchTilemap(center);
79915 } // Is the imagery valid here? - #4827
79918 var sources = background.sources(context.map().extent());
79919 var wasValid = _isValid;
79920 _isValid = !!sources.filter(function (d) {
79921 return d === currSource;
79924 if (wasValid !== _isValid) {
79925 // change in valid status
79926 background.updateImagery();
79929 var baseFilter = '';
79931 if (detected.cssfilters) {
79932 if (_brightness !== 1) {
79933 baseFilter += " brightness(".concat(_brightness, ")");
79936 if (_contrast !== 1) {
79937 baseFilter += " contrast(".concat(_contrast, ")");
79940 if (_saturation !== 1) {
79941 baseFilter += " saturate(".concat(_saturation, ")");
79944 if (_sharpness < 1) {
79946 var blur = d3_interpolateNumber(0.5, 5)(1 - _sharpness);
79947 baseFilter += " blur(".concat(blur, "px)");
79951 var base = selection.selectAll('.layer-background').data([0]);
79952 base = base.enter().insert('div', '.layer-data').attr('class', 'layer layer-background').merge(base);
79954 if (detected.cssfilters) {
79955 base.style('filter', baseFilter || null);
79957 base.style('opacity', _brightness);
79960 var imagery = base.selectAll('.layer-imagery').data([0]);
79961 imagery.enter().append('div').attr('class', 'layer layer-imagery').merge(imagery).call(baseLayer);
79962 var maskFilter = '';
79963 var mixBlendMode = '';
79965 if (detected.cssfilters && _sharpness > 1) {
79966 // apply unsharp mask
79967 mixBlendMode = 'overlay';
79968 maskFilter = 'saturate(0) blur(3px) invert(1)';
79969 var contrast = _sharpness - 1;
79970 maskFilter += " contrast(".concat(contrast, ")");
79971 var brightness = d3_interpolateNumber(1, 0.85)(_sharpness - 1);
79972 maskFilter += " brightness(".concat(brightness, ")");
79975 var mask = base.selectAll('.layer-unsharp-mask').data(detected.cssfilters && _sharpness > 1 ? [0] : []);
79976 mask.exit().remove();
79977 mask.enter().append('div').attr('class', 'layer layer-mask layer-unsharp-mask').merge(mask).call(baseLayer).style('filter', maskFilter || null).style('mix-blend-mode', mixBlendMode || null);
79978 var overlays = selection.selectAll('.layer-overlay').data(_overlayLayers, function (d) {
79979 return d.source().name();
79981 overlays.exit().remove();
79982 overlays.enter().insert('div', '.layer-data').attr('class', 'layer layer-overlay').merge(overlays).each(function (layer, i, nodes) {
79983 return select(nodes[i]).call(layer);
79987 background.updateImagery = function () {
79988 var currSource = baseLayer.source();
79989 if (context.inIntro() || !currSource) return;
79991 var o = _overlayLayers.filter(function (d) {
79992 return !d.source().isLocatorOverlay() && !d.source().isHidden();
79993 }).map(function (d) {
79994 return d.source().id;
79997 var meters = geoOffsetToMeters(currSource.offset());
79998 var EPSILON = 0.01;
79999 var x = +meters[0].toFixed(2);
80000 var y = +meters[1].toFixed(2);
80001 var hash = utilStringQs(window.location.hash);
80002 var id = currSource.id;
80004 if (id === 'custom') {
80005 id = "custom:".concat(currSource.template());
80009 hash.background = id;
80011 delete hash.background;
80017 delete hash.overlays;
80020 if (Math.abs(x) > EPSILON || Math.abs(y) > EPSILON) {
80021 hash.offset = "".concat(x, ",").concat(y);
80023 delete hash.offset;
80026 if (!window.mocha) {
80027 window.location.replace('#' + utilQsString(hash, true));
80030 var imageryUsed = [];
80031 var photoOverlaysUsed = [];
80032 var currUsed = currSource.imageryUsed();
80034 if (currUsed && _isValid) {
80035 imageryUsed.push(currUsed);
80038 _overlayLayers.filter(function (d) {
80039 return !d.source().isLocatorOverlay() && !d.source().isHidden();
80040 }).forEach(function (d) {
80041 return imageryUsed.push(d.source().imageryUsed());
80044 var dataLayer = context.layers().layer('data');
80046 if (dataLayer && dataLayer.enabled() && dataLayer.hasData()) {
80047 imageryUsed.push(dataLayer.getSrc());
80050 var photoOverlayLayers = {
80051 streetside: 'Bing Streetside',
80052 mapillary: 'Mapillary Images',
80053 'mapillary-map-features': 'Mapillary Map Features',
80054 'mapillary-signs': 'Mapillary Signs',
80055 kartaview: 'KartaView Images'
80058 for (var layerID in photoOverlayLayers) {
80059 var layer = context.layers().layer(layerID);
80061 if (layer && layer.enabled()) {
80062 photoOverlaysUsed.push(layerID);
80063 imageryUsed.push(photoOverlayLayers[layerID]);
80067 context.history().imageryUsed(imageryUsed);
80068 context.history().photoOverlaysUsed(photoOverlaysUsed);
80071 background.sources = function (extent, zoom, includeCurrent) {
80072 if (!_imageryIndex) return []; // called before init()?
80075 (_imageryIndex.query.bbox(extent.rectangle(), true) || []).forEach(function (d) {
80076 return visible[d.id] = true;
80078 var currSource = baseLayer.source(); // Recheck blocked sources only if we detect new blocklists pulled from the OSM API.
80080 var osm = context.connection();
80081 var blocklists = osm && osm.imageryBlocklists() || [];
80082 var blocklistChanged = blocklists.length !== _checkedBlocklists.length || blocklists.some(function (regex, index) {
80083 return String(regex) !== _checkedBlocklists[index];
80086 if (blocklistChanged) {
80087 _imageryIndex.backgrounds.forEach(function (source) {
80088 source.isBlocked = blocklists.some(function (regex) {
80089 return regex.test(source.template());
80093 _checkedBlocklists = blocklists.map(function (regex) {
80094 return String(regex);
80098 return _imageryIndex.backgrounds.filter(function (source) {
80099 if (includeCurrent && currSource === source) return true; // optionally always include the current imagery
80101 if (source.isBlocked) return false; // even bundled sources may be blocked - #7905
80103 if (!source.polygon) return true; // always include imagery with worldwide coverage
80105 if (zoom && zoom < 6) return false; // optionally exclude local imagery at low zooms
80107 return visible[source.id]; // include imagery visible in given extent
80111 background.dimensions = function (val) {
80113 baseLayer.dimensions(val);
80115 _overlayLayers.forEach(function (layer) {
80116 return layer.dimensions(val);
80120 background.baseLayerSource = function (d) {
80121 if (!arguments.length) return baseLayer.source(); // test source against OSM imagery blocklists..
80123 var osm = context.connection();
80124 if (!osm) return background;
80125 var blocklists = osm.imageryBlocklists();
80126 var template = d.template();
80131 for (var i = 0; i < blocklists.length; i++) {
80132 regex = blocklists[i];
80133 fail = regex.test(template);
80136 } // ensure at least one test was run.
80140 regex = /.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/;
80141 fail = regex.test(template);
80144 baseLayer.source(!fail ? d : background.findSource('none'));
80145 dispatch.call('change');
80146 background.updateImagery();
80150 background.findSource = function (id) {
80151 if (!id || !_imageryIndex) return null; // called before init()?
80153 return _imageryIndex.backgrounds.find(function (d) {
80154 return d.id && d.id === id;
80158 background.bing = function () {
80159 background.baseLayerSource(background.findSource('Bing'));
80162 background.showsLayer = function (d) {
80163 var currSource = baseLayer.source();
80164 if (!d || !currSource) return false;
80165 return d.id === currSource.id || _overlayLayers.some(function (layer) {
80166 return d.id === layer.source().id;
80170 background.overlayLayerSources = function () {
80171 return _overlayLayers.map(function (layer) {
80172 return layer.source();
80176 background.toggleOverlayLayer = function (d) {
80179 for (var i = 0; i < _overlayLayers.length; i++) {
80180 layer = _overlayLayers[i];
80182 if (layer.source() === d) {
80183 _overlayLayers.splice(i, 1);
80185 dispatch.call('change');
80186 background.updateImagery();
80191 layer = rendererTileLayer(context).source(d).projection(context.projection).dimensions(baseLayer.dimensions());
80193 _overlayLayers.push(layer);
80195 dispatch.call('change');
80196 background.updateImagery();
80199 background.nudge = function (d, zoom) {
80200 var currSource = baseLayer.source();
80203 currSource.nudge(d, zoom);
80204 dispatch.call('change');
80205 background.updateImagery();
80211 background.offset = function (d) {
80212 var currSource = baseLayer.source();
80214 if (!arguments.length) {
80215 return currSource && currSource.offset() || [0, 0];
80219 currSource.offset(d);
80220 dispatch.call('change');
80221 background.updateImagery();
80227 background.brightness = function (d) {
80228 if (!arguments.length) return _brightness;
80230 if (context.mode()) dispatch.call('change');
80234 background.contrast = function (d) {
80235 if (!arguments.length) return _contrast;
80237 if (context.mode()) dispatch.call('change');
80241 background.saturation = function (d) {
80242 if (!arguments.length) return _saturation;
80244 if (context.mode()) dispatch.call('change');
80248 background.sharpness = function (d) {
80249 if (!arguments.length) return _sharpness;
80251 if (context.mode()) dispatch.call('change');
80257 background.ensureLoaded = function () {
80258 if (_loadPromise) return _loadPromise;
80260 function parseMapParams(qmap) {
80261 if (!qmap) return false;
80262 var params = qmap.split('/').map(Number);
80263 if (params.length < 3 || params.some(isNaN)) return false;
80264 return geoExtent([params[2], params[1]]); // lon,lat
80267 var hash = utilStringQs(window.location.hash);
80268 var requested = hash.background || hash.layer;
80269 var extent = parseMapParams(hash.map);
80270 return _loadPromise = ensureImageryIndex().then(function (imageryIndex) {
80271 var first = imageryIndex.backgrounds.length && imageryIndex.backgrounds[0];
80274 if (!requested && extent) {
80275 best = background.sources(extent).find(function (s) {
80278 } // Decide which background layer to display
80281 if (requested && requested.indexOf('custom:') === 0) {
80282 var template = requested.replace(/^custom:/, '');
80283 var custom = background.findSource('custom');
80284 background.baseLayerSource(custom.template(template));
80285 corePreferences('background-custom-template', template);
80287 background.baseLayerSource(background.findSource(requested) || best || background.findSource(corePreferences('background-last-used')) || background.findSource('Bing') || first || background.findSource('none'));
80290 var locator = imageryIndex.backgrounds.find(function (d) {
80291 return d.overlay && d["default"];
80295 background.toggleOverlayLayer(locator);
80298 var overlays = (hash.overlays || '').split(',');
80299 overlays.forEach(function (overlay) {
80300 overlay = background.findSource(overlay);
80303 background.toggleOverlayLayer(overlay);
80308 var gpx = context.layers().layer('data');
80311 gpx.url(hash.gpx, '.gpx');
80316 var offset = hash.offset.replace(/;/g, ',').split(',').map(function (n) {
80317 return !isNaN(n) && n;
80320 if (offset.length === 2) {
80321 background.offset(geoMetersToOffset(offset));
80324 })["catch"](function () {
80329 return utilRebind(background, dispatch, 'on');
80332 function rendererFeatures(context) {
80333 var dispatch = dispatch$8('change', 'redraw');
80334 var features = utilRebind({}, dispatch, 'on');
80336 var _deferred = new Set();
80338 var traffic_roads = {
80340 'motorway_link': true,
80342 'trunk_link': true,
80344 'primary_link': true,
80346 'secondary_link': true,
80348 'tertiary_link': true,
80349 'residential': true,
80350 'unclassified': true,
80351 'living_street': true
80353 var service_roads = {
80366 var past_futures = {
80368 'construction': true,
80370 'dismantled': true,
80373 'demolished': true,
80374 'obliterated': true
80376 var _cullFactor = 1;
80382 var _forceVisible = {};
80384 function update() {
80385 if (!window.mocha) {
80386 var hash = utilStringQs(window.location.hash);
80387 var disabled = features.disabled();
80389 if (disabled.length) {
80390 hash.disable_features = disabled.join(',');
80392 delete hash.disable_features;
80395 window.location.replace('#' + utilQsString(hash, true));
80396 corePreferences('disabled-features', disabled.join(','));
80399 _hidden = features.hidden();
80400 dispatch.call('change');
80401 dispatch.call('redraw');
80404 function defineRule(k, filter, max) {
80405 var isEnabled = true;
80411 enabled: isEnabled,
80412 // whether the user wants it enabled..
80414 currentMax: max || Infinity,
80415 defaultMax: max || Infinity,
80416 enable: function enable() {
80417 this.enabled = true;
80418 this.currentMax = this.defaultMax;
80420 disable: function disable() {
80421 this.enabled = false;
80422 this.currentMax = 0;
80424 hidden: function hidden() {
80425 return this.count === 0 && !this.enabled || this.count > this.currentMax * _cullFactor;
80427 autoHidden: function autoHidden() {
80428 return this.hidden() && this.currentMax > 0;
80433 defineRule('points', function isPoint(tags, geometry) {
80434 return geometry === 'point';
80436 defineRule('traffic_roads', function isTrafficRoad(tags) {
80437 return traffic_roads[tags.highway];
80439 defineRule('service_roads', function isServiceRoad(tags) {
80440 return service_roads[tags.highway];
80442 defineRule('paths', function isPath(tags) {
80443 return paths[tags.highway];
80445 defineRule('buildings', function isBuilding(tags) {
80446 return !!tags.building && tags.building !== 'no' || tags.parking === 'multi-storey' || tags.parking === 'sheds' || tags.parking === 'carports' || tags.parking === 'garage_boxes';
80448 defineRule('building_parts', function isBuildingPart(tags) {
80449 return tags['building:part'];
80451 defineRule('indoor', function isIndoor(tags) {
80452 return tags.indoor;
80454 defineRule('landuse', function isLanduse(tags, geometry) {
80455 return geometry === 'area' && !_rules.buildings.filter(tags) && !_rules.building_parts.filter(tags) && !_rules.indoor.filter(tags) && !_rules.water.filter(tags) && !_rules.pistes.filter(tags);
80457 defineRule('boundaries', function isBoundary(tags) {
80458 return !!tags.boundary && !(traffic_roads[tags.highway] || service_roads[tags.highway] || paths[tags.highway] || tags.waterway || tags.railway || tags.landuse || tags.natural || tags.building || tags.power);
80460 defineRule('water', function isWater(tags) {
80461 return !!tags.waterway || tags.natural === 'water' || tags.natural === 'coastline' || tags.natural === 'bay' || tags.landuse === 'pond' || tags.landuse === 'basin' || tags.landuse === 'reservoir' || tags.landuse === 'salt_pond';
80463 defineRule('rail', function isRail(tags) {
80464 return (!!tags.railway || tags.landuse === 'railway') && !(traffic_roads[tags.highway] || service_roads[tags.highway] || paths[tags.highway]);
80466 defineRule('pistes', function isPiste(tags) {
80467 return tags['piste:type'];
80469 defineRule('aerialways', function isPiste(tags) {
80470 return tags.aerialway && tags.aerialway !== 'yes' && tags.aerialway !== 'station';
80472 defineRule('power', function isPower(tags) {
80473 return !!tags.power;
80474 }); // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
80476 defineRule('past_future', function isPastFuture(tags) {
80477 if (traffic_roads[tags.highway] || service_roads[tags.highway] || paths[tags.highway]) {
80481 var strings = Object.keys(tags);
80483 for (var i = 0; i < strings.length; i++) {
80484 var s = strings[i];
80486 if (past_futures[s] || past_futures[tags[s]]) {
80492 }); // Lines or areas that don't match another feature filter.
80493 // IMPORTANT: The 'others' feature must be the last one defined,
80494 // so that code in getMatches can skip this test if `hasMatch = true`
80496 defineRule('others', function isOther(tags, geometry) {
80497 return geometry === 'line' || geometry === 'area';
80500 features.features = function () {
80504 features.keys = function () {
80508 features.enabled = function (k) {
80509 if (!arguments.length) {
80510 return _keys.filter(function (k) {
80511 return _rules[k].enabled;
80515 return _rules[k] && _rules[k].enabled;
80518 features.disabled = function (k) {
80519 if (!arguments.length) {
80520 return _keys.filter(function (k) {
80521 return !_rules[k].enabled;
80525 return _rules[k] && !_rules[k].enabled;
80528 features.hidden = function (k) {
80529 if (!arguments.length) {
80530 return _keys.filter(function (k) {
80531 return _rules[k].hidden();
80535 return _rules[k] && _rules[k].hidden();
80538 features.autoHidden = function (k) {
80539 if (!arguments.length) {
80540 return _keys.filter(function (k) {
80541 return _rules[k].autoHidden();
80545 return _rules[k] && _rules[k].autoHidden();
80548 features.enable = function (k) {
80549 if (_rules[k] && !_rules[k].enabled) {
80550 _rules[k].enable();
80556 features.enableAll = function () {
80557 var didEnable = false;
80559 for (var k in _rules) {
80560 if (!_rules[k].enabled) {
80563 _rules[k].enable();
80567 if (didEnable) update();
80570 features.disable = function (k) {
80571 if (_rules[k] && _rules[k].enabled) {
80572 _rules[k].disable();
80578 features.disableAll = function () {
80579 var didDisable = false;
80581 for (var k in _rules) {
80582 if (_rules[k].enabled) {
80585 _rules[k].disable();
80589 if (didDisable) update();
80592 features.toggle = function (k) {
80595 return f.enabled ? f.disable() : f.enable();
80602 features.resetStats = function () {
80603 for (var i = 0; i < _keys.length; i++) {
80604 _rules[_keys[i]].count = 0;
80607 dispatch.call('change');
80610 features.gatherStats = function (d, resolver, dimensions) {
80611 var needsRedraw = false;
80612 var types = utilArrayGroupBy(d, 'type');
80613 var entities = [].concat(types.relation || [], types.way || [], types.node || []);
80614 var currHidden, geometry, matches, i, j;
80616 for (i = 0; i < _keys.length; i++) {
80617 _rules[_keys[i]].count = 0;
80618 } // adjust the threshold for point/building culling based on viewport size..
80619 // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
80622 _cullFactor = dimensions[0] * dimensions[1] / 1000000;
80624 for (i = 0; i < entities.length; i++) {
80625 geometry = entities[i].geometry(resolver);
80626 matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
80628 for (j = 0; j < matches.length; j++) {
80629 _rules[matches[j]].count++;
80633 currHidden = features.hidden();
80635 if (currHidden !== _hidden) {
80636 _hidden = currHidden;
80637 needsRedraw = true;
80638 dispatch.call('change');
80641 return needsRedraw;
80644 features.stats = function () {
80645 for (var i = 0; i < _keys.length; i++) {
80646 _stats[_keys[i]] = _rules[_keys[i]].count;
80652 features.clear = function (d) {
80653 for (var i = 0; i < d.length; i++) {
80654 features.clearEntity(d[i]);
80658 features.clearEntity = function (entity) {
80659 delete _cache[osmEntity.key(entity)];
80662 features.reset = function () {
80663 Array.from(_deferred).forEach(function (handle) {
80664 window.cancelIdleCallback(handle);
80666 _deferred["delete"](handle);
80669 }; // only certain relations are worth checking
80672 function relationShouldBeChecked(relation) {
80673 // multipolygon features have `area` geometry and aren't checked here
80674 return relation.tags.type === 'boundary';
80677 features.getMatches = function (entity, resolver, geometry) {
80678 if (geometry === 'vertex' || geometry === 'relation' && !relationShouldBeChecked(entity)) return {};
80679 var ent = osmEntity.key(entity);
80681 if (!_cache[ent]) {
80685 if (!_cache[ent].matches) {
80687 var hasMatch = false;
80689 for (var i = 0; i < _keys.length; i++) {
80690 if (_keys[i] === 'others') {
80691 if (hasMatch) continue; // If an entity...
80692 // 1. is a way that hasn't matched other 'interesting' feature rules,
80694 if (entity.type === 'way') {
80695 var parents = features.getParents(entity, resolver, geometry); // 2a. belongs only to a single multipolygon relation
80697 if (parents.length === 1 && parents[0].isMultipolygon() || // 2b. or belongs only to boundary relations
80698 parents.length > 0 && parents.every(function (parent) {
80699 return parent.tags.type === 'boundary';
80701 // ...then match whatever feature rules the parent relation has matched.
80702 // see #2548, #2887
80705 // For this to work, getMatches must be called on relations before ways.
80707 var pkey = osmEntity.key(parents[0]);
80709 if (_cache[pkey] && _cache[pkey].matches) {
80710 matches = Object.assign({}, _cache[pkey].matches); // shallow copy
80718 if (_rules[_keys[i]].filter(entity.tags, geometry)) {
80719 matches[_keys[i]] = hasMatch = true;
80723 _cache[ent].matches = matches;
80726 return _cache[ent].matches;
80729 features.getParents = function (entity, resolver, geometry) {
80730 if (geometry === 'point') return [];
80731 var ent = osmEntity.key(entity);
80733 if (!_cache[ent]) {
80737 if (!_cache[ent].parents) {
80740 if (geometry === 'vertex') {
80741 parents = resolver.parentWays(entity);
80743 // 'line', 'area', 'relation'
80744 parents = resolver.parentRelations(entity);
80747 _cache[ent].parents = parents;
80750 return _cache[ent].parents;
80753 features.isHiddenPreset = function (preset, geometry) {
80754 if (!_hidden.length) return false;
80755 if (!preset.tags) return false;
80756 var test = preset.setTags({}, geometry);
80758 for (var key in _rules) {
80759 if (_rules[key].filter(test, geometry)) {
80760 if (_hidden.indexOf(key) !== -1) {
80771 features.isHiddenFeature = function (entity, resolver, geometry) {
80772 if (!_hidden.length) return false;
80773 if (!entity.version) return false;
80774 if (_forceVisible[entity.id]) return false;
80775 var matches = Object.keys(features.getMatches(entity, resolver, geometry));
80776 return matches.length && matches.every(function (k) {
80777 return features.hidden(k);
80781 features.isHiddenChild = function (entity, resolver, geometry) {
80782 if (!_hidden.length) return false;
80783 if (!entity.version || geometry === 'point') return false;
80784 if (_forceVisible[entity.id]) return false;
80785 var parents = features.getParents(entity, resolver, geometry);
80786 if (!parents.length) return false;
80788 for (var i = 0; i < parents.length; i++) {
80789 if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
80797 features.hasHiddenConnections = function (entity, resolver) {
80798 if (!_hidden.length) return false;
80799 var childNodes, connections;
80801 if (entity.type === 'midpoint') {
80802 childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
80805 childNodes = entity.nodes ? resolver.childNodes(entity) : [];
80806 connections = features.getParents(entity, resolver, entity.geometry(resolver));
80807 } // gather ways connected to child nodes..
80810 connections = childNodes.reduce(function (result, e) {
80811 return resolver.isShared(e) ? utilArrayUnion(result, resolver.parentWays(e)) : result;
80813 return connections.some(function (e) {
80814 return features.isHidden(e, resolver, e.geometry(resolver));
80818 features.isHidden = function (entity, resolver, geometry) {
80819 if (!_hidden.length) return false;
80820 if (!entity.version) return false;
80821 var fn = geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature;
80822 return fn(entity, resolver, geometry);
80825 features.filter = function (d, resolver) {
80826 if (!_hidden.length) return d;
80829 for (var i = 0; i < d.length; i++) {
80832 if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
80833 result.push(entity);
80840 features.forceVisible = function (entityIDs) {
80841 if (!arguments.length) return Object.keys(_forceVisible);
80842 _forceVisible = {};
80844 for (var i = 0; i < entityIDs.length; i++) {
80845 _forceVisible[entityIDs[i]] = true;
80846 var entity = context.hasEntity(entityIDs[i]);
80848 if (entity && entity.type === 'relation') {
80849 // also show relation members (one level deep)
80850 for (var j in entity.members) {
80851 _forceVisible[entity.members[j].id] = true;
80859 features.init = function () {
80860 var storage = corePreferences('disabled-features');
80863 var storageDisabled = storage.replace(/;/g, ',').split(',');
80864 storageDisabled.forEach(features.disable);
80867 var hash = utilStringQs(window.location.hash);
80869 if (hash.disable_features) {
80870 var hashDisabled = hash.disable_features.replace(/;/g, ',').split(',');
80871 hashDisabled.forEach(features.disable);
80873 }; // warm up the feature matching cache upon merging fetched data
80876 context.history().on('merge.features', function (newEntities) {
80877 if (!newEntities) return;
80878 var handle = window.requestIdleCallback(function () {
80879 var graph = context.graph();
80880 var types = utilArrayGroupBy(newEntities, 'type'); // ensure that getMatches is called on relations before ways
80882 var entities = [].concat(types.relation || [], types.way || [], types.node || []);
80884 for (var i = 0; i < entities.length; i++) {
80885 var geometry = entities[i].geometry(graph);
80886 features.getMatches(entities[i], graph, geometry);
80890 _deferred.add(handle);
80896 // - the activeID - nope
80897 // - 1 away (adjacent) to the activeID - yes (vertices will be merged)
80898 // - 2 away from the activeID - nope (would create a self intersecting segment)
80899 // - all others on a linear way - yes
80900 // - all others on a closed way - nope (would create a self intersecting polygon)
80903 // 0 = active vertex - no touch/connect
80904 // 1 = passive vertex - yes touch/connect
80905 // 2 = adjacent vertex - yes but pay attention segmenting a line here
80908 function svgPassiveVertex(node, graph, activeID) {
80909 if (!activeID) return 1;
80910 if (activeID === node.id) return 0;
80911 var parents = graph.parentWays(node);
80912 var i, j, nodes, isClosed, ix1, ix2, ix3, ix4, max;
80914 for (i = 0; i < parents.length; i++) {
80915 nodes = parents[i].nodes;
80916 isClosed = parents[i].isClosed();
80918 for (j = 0; j < nodes.length; j++) {
80919 // find this vertex, look nearby
80920 if (nodes[j] === node.id) {
80927 // wraparound if needed
80928 max = nodes.length - 1;
80929 if (ix1 < 0) ix1 = max + ix1;
80930 if (ix2 < 0) ix2 = max + ix2;
80931 if (ix3 > max) ix3 = ix3 - max;
80932 if (ix4 > max) ix4 = ix4 - max;
80935 if (nodes[ix1] === activeID) return 0; // no - prevent self intersect
80936 else if (nodes[ix2] === activeID) return 2; // ok - adjacent
80937 else if (nodes[ix3] === activeID) return 2; // ok - adjacent
80938 else if (nodes[ix4] === activeID) return 0; // no - prevent self intersect
80939 else if (isClosed && nodes.indexOf(activeID) !== -1) return 0; // no - prevent self intersect
80946 function svgMarkerSegments(projection, graph, dt, shouldReverse, bothDirections) {
80947 return function (entity) {
80951 var clip = d3_geoIdentity().clipExtent(projection.clipExtent()).stream;
80952 var coordinates = graph.childNodes(entity).map(function (n) {
80957 if (shouldReverse(entity)) {
80958 coordinates.reverse();
80962 type: 'LineString',
80963 coordinates: coordinates
80964 }, projection.stream(clip({
80965 lineStart: function lineStart() {},
80966 lineEnd: function lineEnd() {
80969 point: function point(x, y) {
80973 var span = geoVecLength(a, b) - offset;
80976 var heading = geoVecAngle(a, b);
80977 var dx = dt * Math.cos(heading);
80978 var dy = dt * Math.sin(heading);
80979 var p = [a[0] + offset * Math.cos(heading), a[1] + offset * Math.sin(heading)]; // gather coordinates
80981 var coord = [a, p];
80983 for (span -= dt; span >= 0; span -= dt) {
80984 p = geoVecAdd(p, [dx, dy]);
80988 coord.push(b); // generate svg paths
80993 for (j = 0; j < coord.length; j++) {
80994 segment += (j === 0 ? 'M' : 'L') + coord[j][0] + ',' + coord[j][1];
81003 if (bothDirections(entity)) {
81006 for (j = coord.length - 1; j >= 0; j--) {
81007 segment += (j === coord.length - 1 ? 'M' : 'L') + coord[j][0] + ',' + coord[j][1];
81027 function svgPath(projection, graph, isArea) {
81028 // Explanation of magic numbers:
81029 // "padding" here allows space for strokes to extend beyond the viewport,
81030 // so that the stroke isn't drawn along the edge of the viewport when
81031 // the shape is clipped.
81033 // When drawing lines, pad viewport by 5px.
81034 // When drawing areas, pad viewport by 65px in each direction to allow
81035 // for 60px area fill stroke (see ".fill-partial path.fill" css rule)
81037 var padding = isArea ? 65 : 5;
81038 var viewport = projection.clipExtent();
81039 var paddedExtent = [[viewport[0][0] - padding, viewport[0][1] - padding], [viewport[1][0] + padding, viewport[1][1] + padding]];
81040 var clip = d3_geoIdentity().clipExtent(paddedExtent).stream;
81041 var project = projection.stream;
81042 var path = d3_geoPath().projection({
81043 stream: function stream(output) {
81044 return project(clip(output));
81048 var svgpath = function svgpath(entity) {
81049 if (entity.id in cache) {
81050 return cache[entity.id];
81052 return cache[entity.id] = path(entity.asGeoJSON(graph));
81056 svgpath.geojson = function (d) {
81057 if (d.__featurehash__ !== undefined) {
81058 if (d.__featurehash__ in cache) {
81059 return cache[d.__featurehash__];
81061 return cache[d.__featurehash__] = path(d);
81070 function svgPointTransform(projection) {
81071 var svgpoint = function svgpoint(entity) {
81072 // http://jsperf.com/short-array-join
81073 var pt = projection(entity.loc);
81074 return 'translate(' + pt[0] + ',' + pt[1] + ')';
81077 svgpoint.geojson = function (d) {
81078 return svgpoint(d.properties.entity);
81083 function svgRelationMemberTags(graph) {
81084 return function (entity) {
81085 var tags = entity.tags;
81086 var shouldCopyMultipolygonTags = !entity.hasInterestingTags();
81087 graph.parentRelations(entity).forEach(function (relation) {
81088 var type = relation.tags.type;
81090 if (type === 'multipolygon' && shouldCopyMultipolygonTags || type === 'boundary') {
81091 tags = Object.assign({}, relation.tags, tags);
81097 function svgSegmentWay(way, graph, activeID) {
81098 // When there is no activeID, we can memoize this expensive computation
81099 if (activeID === undefined) {
81100 return graph["transient"](way, 'waySegments', getWaySegments);
81102 return getWaySegments();
81105 function getWaySegments() {
81106 var isActiveWay = way.nodes.indexOf(activeID) !== -1;
81115 for (var i = 0; i < way.nodes.length; i++) {
81116 node = graph.entity(way.nodes[i]);
81117 type = svgPassiveVertex(node, graph, activeID);
81123 if (start.type !== undefined) {
81124 if (start.node.id === activeID || end.node.id === activeID) ; else if (isActiveWay && (start.type === 2 || end.type === 2)) {
81125 // one adjacent vertex
81126 pushActive(start, end, i);
81127 } else if (start.type === 0 && end.type === 0) {
81128 // both active vertices
81129 pushActive(start, end, i);
81131 pushPassive(start, end, i);
81140 function pushActive(start, end, index) {
81141 features.active.push({
81143 id: way.id + '-' + index + '-nope',
81148 nodes: [start.node, end.node],
81152 type: 'LineString',
81153 coordinates: [start.node.loc, end.node.loc]
81158 function pushPassive(start, end, index) {
81159 features.passive.push({
81161 id: way.id + '-' + index,
81165 nodes: [start.node, end.node],
81169 type: 'LineString',
81170 coordinates: [start.node.loc, end.node.loc]
81177 function svgTagClasses() {
81178 var primaries = ['building', 'highway', 'railway', 'waterway', 'aeroway', 'aerialway', 'piste:type', 'boundary', 'power', 'amenity', 'natural', 'landuse', 'leisure', 'military', 'place', 'man_made', 'route', 'attraction', 'building:part', 'indoor'];
81179 var statuses = [// nonexistent, might be built
81180 'proposed', 'planned', // under maintentance or between groundbreaking and opening
81181 'construction', // existent but not functional
81182 'disused', // dilapidated to nonexistent
81183 'abandoned', // nonexistent, still may appear in imagery
81184 'dismantled', 'razed', 'demolished', 'obliterated', // existent occasionally, e.g. stormwater drainage basin
81186 var secondaries = ['oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier', 'surface', 'tracktype', 'footway', 'crossing', 'service', 'sport', 'public_transport', 'location', 'parking', 'golf', 'type', 'leisure', 'man_made', 'indoor', 'construction', 'proposed'];
81188 var _tags = function _tags(entity) {
81189 return entity.tags;
81192 var tagClasses = function tagClasses(selection) {
81193 selection.each(function tagClassesEach(entity) {
81194 var value = this.className;
81196 if (value.baseVal !== undefined) {
81197 value = value.baseVal;
81200 var t = _tags(entity);
81202 var computed = tagClasses.getClassesString(t, value);
81204 if (computed !== value) {
81205 select(this).attr('class', computed);
81210 tagClasses.getClassesString = function (t, value) {
81211 var primary, status;
81212 var i, j, k, v; // in some situations we want to render perimeter strokes a certain way
81214 var overrideGeometry;
81216 if (/\bstroke\b/.test(value)) {
81217 if (!!t.barrier && t.barrier !== 'no') {
81218 overrideGeometry = 'line';
81220 } // preserve base classes (nothing with `tag-`)
81223 var classes = value.trim().split(/\s+/).filter(function (klass) {
81224 return klass.length && !/^tag-/.test(klass);
81225 }).map(function (klass) {
81226 // special overrides for some perimeter strokes
81227 return klass === 'line' || klass === 'area' ? overrideGeometry || klass : klass;
81228 }); // pick at most one primary classification tag..
81230 for (i = 0; i < primaries.length; i++) {
81233 if (!v || v === 'no') continue;
81235 if (k === 'piste:type') {
81236 // avoid a ':' in the class name
81238 } else if (k === 'building:part') {
81239 // avoid a ':' in the class name
81240 k = 'building_part';
81245 if (statuses.indexOf(v) !== -1) {
81246 // e.g. `railway=abandoned`
81248 classes.push('tag-' + k);
81250 classes.push('tag-' + k);
81251 classes.push('tag-' + k + '-' + v);
81258 for (i = 0; i < statuses.length; i++) {
81259 for (j = 0; j < primaries.length; j++) {
81260 k = statuses[i] + ':' + primaries[j]; // e.g. `demolished:building=yes`
81263 if (!v || v === 'no') continue;
81264 status = statuses[i];
81268 } // add at most one status tag, only if relates to primary tag..
81272 for (i = 0; i < statuses.length; i++) {
81275 if (!v || v === 'no') continue;
81278 // e.g. `railway=rail + abandoned=yes`
81280 } else if (primary && primary === v) {
81281 // e.g. `railway=rail + abandoned=railway`
81283 } else if (!primary && primaries.indexOf(v) !== -1) {
81284 // e.g. `abandoned=railway`
81287 classes.push('tag-' + v);
81288 } // else ignore e.g. `highway=path + abandoned=railway`
81296 classes.push('tag-status');
81297 classes.push('tag-status-' + status);
81298 } // add any secondary tags
81301 for (i = 0; i < secondaries.length; i++) {
81302 k = secondaries[i];
81304 if (!v || v === 'no' || k === primary) continue;
81305 classes.push('tag-' + k);
81306 classes.push('tag-' + k + '-' + v);
81307 } // For highways, look for surface tagging..
81310 if (primary === 'highway' && !osmPathHighwayTagValues[t.highway] || primary === 'aeroway') {
81311 var surface = t.highway === 'track' ? 'unpaved' : 'paved';
81316 if (k in osmPavedTags) {
81317 surface = osmPavedTags[k][v] ? 'paved' : 'unpaved';
81320 if (k in osmSemipavedTags && !!osmSemipavedTags[k][v]) {
81321 surface = 'semipaved';
81325 classes.push('tag-' + surface);
81326 } // If this is a wikidata-tagged item, add a class for that..
81329 var qid = t.wikidata || t['flag:wikidata'] || t['brand:wikidata'] || t['network:wikidata'] || t['operator:wikidata'];
81332 classes.push('tag-wikidata');
81335 return classes.join(' ').trim();
81338 tagClasses.tags = function (val) {
81339 if (!arguments.length) return _tags;
81347 // Patterns only work in Firefox when set directly on element.
81348 // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
81350 // tag - pattern name
81352 // tag - value - pattern name
81354 // tag - value - rules (optional tag-values, pattern name)
81355 // (matches earlier rules first, so fallback should be last entry)
81357 grave_yard: 'cemetery',
81358 fountain: 'water_standing'
81362 religion: 'christian',
81363 pattern: 'cemetery_christian'
81365 religion: 'buddhist',
81366 pattern: 'cemetery_buddhist'
81368 religion: 'muslim',
81369 pattern: 'cemetery_muslim'
81371 religion: 'jewish',
81372 pattern: 'cemetery_jewish'
81374 pattern: 'cemetery'
81376 construction: 'construction',
81377 farmland: 'farmland',
81378 farmyard: 'farmyard',
81380 leaf_type: 'broadleaved',
81381 pattern: 'forest_broadleaved'
81383 leaf_type: 'needleleaved',
81384 pattern: 'forest_needleleaved'
81386 leaf_type: 'leafless',
81387 pattern: 'forest_leafless'
81390 } // same as 'leaf_type:mixed'
81392 grave_yard: 'cemetery',
81395 pattern: 'golf_green'
81399 landfill: 'landfill',
81401 military: 'construction',
81402 orchard: 'orchard',
81404 vineyard: 'vineyard'
81408 grassland: 'grass',
81415 water: 'reservoir',
81416 pattern: 'water_standing'
81422 pattern: 'wetland_marsh'
81425 pattern: 'wetland_swamp'
81428 pattern: 'wetland_bog'
81430 wetland: 'reedbed',
81431 pattern: 'wetland_reedbed'
81436 leaf_type: 'broadleaved',
81437 pattern: 'forest_broadleaved'
81439 leaf_type: 'needleleaved',
81440 pattern: 'forest_needleleaved'
81442 leaf_type: 'leafless',
81443 pattern: 'forest_leafless'
81446 } // same as 'leaf_type:mixed'
81464 function svgTagPattern(tags) {
81465 // Skip pattern filling if this is a building (buildings don't get patterns applied)
81466 if (tags.building && tags.building !== 'no') {
81470 for (var tag in patterns) {
81471 var entityValue = tags[tag];
81472 if (!entityValue) continue;
81474 if (typeof patterns[tag] === 'string') {
81475 // extra short syntax (just tag) - pattern name
81476 return 'pattern-' + patterns[tag];
81478 var values = patterns[tag];
81480 for (var value in values) {
81481 if (entityValue !== value) continue;
81482 var rules = values[value];
81484 if (typeof rules === 'string') {
81485 // short syntax - pattern name
81486 return 'pattern-' + rules;
81487 } // long syntax - rule array
81490 for (var ruleKey in rules) {
81491 var rule = rules[ruleKey];
81494 for (var criterion in rule) {
81495 if (criterion !== 'pattern') {
81496 // reserved for pattern name
81497 // The only rule is a required tag-value pair
81498 var v = tags[criterion];
81500 if (!v || v !== rule[criterion]) {
81508 return 'pattern-' + rule.pattern;
81518 function svgAreas(projection, context) {
81519 function getPatternStyle(tags) {
81520 var imageID = svgTagPattern(tags);
81523 return 'url("#ideditor-' + imageID + '")';
81529 function drawTargets(selection, graph, entities, filter) {
81530 var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
81531 var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor ';
81532 var getPath = svgPath(projection).geojson;
81533 var activeID = context.activeID();
81534 var base = context.history().base(); // The targets and nopes will be MultiLineString sub-segments of the ways
81540 entities.forEach(function (way) {
81541 var features = svgSegmentWay(way, graph, activeID);
81542 data.targets.push.apply(data.targets, features.passive);
81543 data.nopes.push.apply(data.nopes, features.active);
81544 }); // Targets allow hover and vertex snapping
81546 var targetData = data.targets.filter(getPath);
81547 var targets = selection.selectAll('.area.target-allowed').filter(function (d) {
81548 return filter(d.properties.entity);
81549 }).data(targetData, function key(d) {
81553 targets.exit().remove();
81555 var segmentWasEdited = function segmentWasEdited(d) {
81556 var wayID = d.properties.entity.id; // if the whole line was edited, don't draw segment changes
81558 if (!base.entities[wayID] || !fastDeepEqual(graph.entities[wayID].nodes, base.entities[wayID].nodes)) {
81562 return d.properties.nodes.some(function (n) {
81563 return !base.entities[n.id] || !fastDeepEqual(graph.entities[n.id].loc, base.entities[n.id].loc);
81568 targets.enter().append('path').merge(targets).attr('d', getPath).attr('class', function (d) {
81569 return 'way area target target-allowed ' + targetClass + d.id;
81570 }).classed('segment-edited', segmentWasEdited); // NOPE
81572 var nopeData = data.nopes.filter(getPath);
81573 var nopes = selection.selectAll('.area.target-nope').filter(function (d) {
81574 return filter(d.properties.entity);
81575 }).data(nopeData, function key(d) {
81579 nopes.exit().remove(); // enter/update
81581 nopes.enter().append('path').merge(nopes).attr('d', getPath).attr('class', function (d) {
81582 return 'way area target target-nope ' + nopeClass + d.id;
81583 }).classed('segment-edited', segmentWasEdited);
81586 function drawAreas(selection, graph, entities, filter) {
81587 var path = svgPath(projection, graph, true);
81590 var base = context.history().base();
81592 for (var i = 0; i < entities.length; i++) {
81593 var entity = entities[i];
81594 if (entity.geometry(graph) !== 'area') continue;
81595 multipolygon = osmIsOldMultipolygonOuterMember(entity, graph);
81597 if (multipolygon) {
81598 areas[multipolygon.id] = {
81599 entity: multipolygon.mergeTags(entity.tags),
81600 area: Math.abs(entity.area(graph))
81602 } else if (!areas[entity.id]) {
81603 areas[entity.id] = {
81605 area: Math.abs(entity.area(graph))
81610 var fills = Object.values(areas).filter(function hasPath(a) {
81611 return path(a.entity);
81613 fills.sort(function areaSort(a, b) {
81614 return b.area - a.area;
81616 fills = fills.map(function (a) {
81619 var strokes = fills.filter(function (area) {
81620 return area.type === 'way';
81628 var clipPaths = context.surface().selectAll('defs').selectAll('.clipPath-osm').filter(filter).data(data.clip, osmEntity.key);
81629 clipPaths.exit().remove();
81630 var clipPathsEnter = clipPaths.enter().append('clipPath').attr('class', 'clipPath-osm').attr('id', function (entity) {
81631 return 'ideditor-' + entity.id + '-clippath';
81633 clipPathsEnter.append('path');
81634 clipPaths.merge(clipPathsEnter).selectAll('path').attr('d', path);
81635 var drawLayer = selection.selectAll('.layer-osm.areas');
81636 var touchLayer = selection.selectAll('.layer-touch.areas'); // Draw areas..
81638 var areagroup = drawLayer.selectAll('g.areagroup').data(['fill', 'shadow', 'stroke']);
81639 areagroup = areagroup.enter().append('g').attr('class', function (d) {
81640 return 'areagroup area-' + d;
81641 }).merge(areagroup);
81642 var paths = areagroup.selectAll('path').filter(filter).data(function (layer) {
81643 return data[layer];
81645 paths.exit().remove();
81646 var fillpaths = selection.selectAll('.area-fill path.area').nodes();
81647 var bisect = d3_bisector(function (node) {
81648 return -node.__data__.area(graph);
81651 function sortedByArea(entity) {
81652 if (this._parent.__data__ === 'fill') {
81653 return fillpaths[bisect(fillpaths, -entity.area(graph))];
81657 paths = paths.enter().insert('path', sortedByArea).merge(paths).each(function (entity) {
81658 var layer = this.parentNode.__data__;
81659 this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
81661 if (layer === 'fill') {
81662 this.setAttribute('clip-path', 'url(#ideditor-' + entity.id + '-clippath)');
81663 this.style.fill = this.style.stroke = getPatternStyle(entity.tags);
81665 }).classed('added', function (d) {
81666 return !base.entities[d.id];
81667 }).classed('geometry-edited', function (d) {
81668 return graph.entities[d.id] && base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].nodes, base.entities[d.id].nodes);
81669 }).classed('retagged', function (d) {
81670 return graph.entities[d.id] && base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].tags, base.entities[d.id].tags);
81671 }).call(svgTagClasses()).attr('d', path); // Draw touch targets..
81673 touchLayer.call(drawTargets, graph, data.stroke, filter);
81679 var fastJsonStableStringify = function fastJsonStableStringify(data, opts) {
81680 if (!opts) opts = {};
81681 if (typeof opts === 'function') opts = {
81684 var cycles = typeof opts.cycles === 'boolean' ? opts.cycles : false;
81686 var cmp = opts.cmp && function (f) {
81687 return function (node) {
81688 return function (a, b) {
81697 return f(aobj, bobj);
81703 return function stringify(node) {
81704 if (node && node.toJSON && typeof node.toJSON === 'function') {
81705 node = node.toJSON();
81708 if (node === undefined) return;
81709 if (typeof node == 'number') return isFinite(node) ? '' + node : 'null';
81710 if (_typeof(node) !== 'object') return JSON.stringify(node);
81713 if (Array.isArray(node)) {
81716 for (i = 0; i < node.length; i++) {
81718 out += stringify(node[i]) || 'null';
81724 if (node === null) return 'null';
81726 if (seen.indexOf(node) !== -1) {
81727 if (cycles) return JSON.stringify('__cycle__');
81728 throw new TypeError('Converting circular structure to JSON');
81731 var seenIndex = seen.push(node) - 1;
81732 var keys = Object.keys(node).sort(cmp && cmp(node));
81735 for (i = 0; i < keys.length; i++) {
81737 var value = stringify(node[key]);
81738 if (!value) continue;
81739 if (out) out += ',';
81740 out += JSON.stringify(key) + ':' + value;
81743 seen.splice(seenIndex, 1);
81744 return '{' + out + '}';
81749 var $entries = objectToArray.entries;
81751 // `Object.entries` method
81752 // https://tc39.es/ecma262/#sec-object.entries
81753 $$1({ target: 'Object', stat: true }, {
81754 entries: function entries(O) {
81755 return $entries(O);
81759 var _marked = /*#__PURE__*/regeneratorRuntime.mark(gpxGen),
81760 _marked3 = /*#__PURE__*/regeneratorRuntime.mark(kmlGen);
81762 // cast array x into numbers
81763 // get the content of a text node, if any
81764 function nodeVal(x) {
81765 if (x && x.normalize) {
81769 return x && x.textContent || "";
81770 } // one Y child of X, if any, otherwise null
81773 function get1(x, y) {
81774 var n = x.getElementsByTagName(y);
81775 return n.length ? n[0] : null;
81778 function getLineStyle(extensions) {
81782 var lineStyle = get1(extensions, "line");
81785 var color = nodeVal(get1(lineStyle, "color")),
81786 opacity = parseFloat(nodeVal(get1(lineStyle, "opacity"))),
81787 width = parseFloat(nodeVal(get1(lineStyle, "width")));
81788 if (color) style.stroke = color;
81789 if (!isNaN(opacity)) style["stroke-opacity"] = opacity; // GPX width is in mm, convert to px with 96 px per inch
81791 if (!isNaN(width)) style["stroke-width"] = width * 96 / 25.4;
81796 } // get the contents of multiple text nodes, if present
81799 function getMulti(x, ys) {
81804 for (k = 0; k < ys.length; k++) {
81805 n = get1(x, ys[k]);
81806 if (n) o[ys[k]] = nodeVal(n);
81812 function getProperties$1(node) {
81813 var prop = getMulti(node, ["name", "cmt", "desc", "type", "time", "keywords"]); // Parse additional data from our Garmin extension(s)
81815 var extensions = node.getElementsByTagNameNS("http://www.garmin.com/xmlschemas/GpxExtensions/v3", "*");
81817 for (var i = 0; i < extensions.length; i++) {
81818 var extension = extensions[i]; // Ignore nested extensions, like those on routepoints or trackpoints
81820 if (extension.parentNode.parentNode === node) {
81821 prop[extension.tagName.replace(":", "_")] = nodeVal(extension);
81825 var links = node.getElementsByTagName("link");
81826 if (links.length) prop.links = [];
81828 for (var _i = 0; _i < links.length; _i++) {
81829 prop.links.push(Object.assign({
81830 href: links[_i].getAttribute("href")
81831 }, getMulti(links[_i], ["text", "type"])));
81837 function coordPair$1(x) {
81838 var ll = [parseFloat(x.getAttribute("lon")), parseFloat(x.getAttribute("lat"))];
81839 var ele = get1(x, "ele"); // handle namespaced attribute in browser
81841 var heart = get1(x, "gpxtpx:hr") || get1(x, "hr");
81842 var time = get1(x, "time");
81846 e = parseFloat(nodeVal(ele));
81855 time: time ? nodeVal(time) : null,
81860 result.extendedValues.push(["heart", parseFloat(nodeVal(heart))]);
81863 var extensions = get1(x, "extensions");
81865 if (extensions !== null) {
81866 for (var _i2 = 0, _arr = ["speed", "course", "hAcc", "vAcc"]; _i2 < _arr.length; _i2++) {
81867 var name = _arr[_i2];
81868 var v = parseFloat(nodeVal(get1(extensions, name)));
81871 result.extendedValues.push([name, v]);
81879 function getRoute(node) {
81880 var line = getPoints$1(node, "rtept");
81884 properties: Object.assign(getProperties$1(node), getLineStyle(get1(node, "extensions")), {
81888 type: "LineString",
81889 coordinates: line.line
81894 function getPoints$1(node, pointname) {
81895 var pts = node.getElementsByTagName(pointname);
81896 if (pts.length < 2) return; // Invalid line in GeoJSON
81900 var extendedValues = {};
81902 for (var i = 0; i < pts.length; i++) {
81903 var c = coordPair$1(pts[i]);
81904 line.push(c.coordinates);
81905 if (c.time) times.push(c.time);
81907 for (var j = 0; j < c.extendedValues.length; j++) {
81908 var _c$extendedValues$j = _slicedToArray(c.extendedValues[j], 2),
81909 name = _c$extendedValues$j[0],
81910 val = _c$extendedValues$j[1];
81912 var plural = name === "heart" ? name : name + "s";
81914 if (!extendedValues[plural]) {
81915 extendedValues[plural] = Array(pts.length).fill(null);
81918 extendedValues[plural][i] = val;
81925 extendedValues: extendedValues
81929 function getTrack(node) {
81930 var segments = node.getElementsByTagName("trkseg");
81933 var extractedLines = [];
81935 for (var i = 0; i < segments.length; i++) {
81936 var line = getPoints$1(segments[i], "trkpt");
81939 extractedLines.push(line);
81940 if (line.times && line.times.length) times.push(line.times);
81944 if (extractedLines.length === 0) return;
81945 var multi = extractedLines.length > 1;
81946 var properties = Object.assign(getProperties$1(node), getLineStyle(get1(node, "extensions")), {
81948 }, times.length ? {
81949 coordinateProperties: {
81950 times: multi ? times : times[0]
81954 for (var _i3 = 0; _i3 < extractedLines.length; _i3++) {
81955 var _line = extractedLines[_i3];
81956 track.push(_line.line);
81958 for (var _i4 = 0, _Object$entries = Object.entries(_line.extendedValues); _i4 < _Object$entries.length; _i4++) {
81959 var _Object$entries$_i = _slicedToArray(_Object$entries[_i4], 2),
81960 name = _Object$entries$_i[0],
81961 val = _Object$entries$_i[1];
81963 var props = properties;
81965 if (name === "heart") {
81966 if (!properties.coordinateProperties) {
81967 properties.coordinateProperties = {};
81970 props = properties.coordinateProperties;
81974 if (!props[name]) props[name] = extractedLines.map(function (line) {
81975 return new Array(line.line.length).fill(null);
81977 props[name][_i3] = val;
81986 properties: properties,
81987 geometry: multi ? {
81988 type: "MultiLineString",
81991 type: "LineString",
81992 coordinates: track[0]
81997 function getPoint(node) {
82000 properties: Object.assign(getProperties$1(node), getMulti(node, ["sym"])),
82003 coordinates: coordPair$1(node).coordinates
82008 function gpxGen(doc) {
82009 var tracks, routes, waypoints, i, feature, _i5, _feature, _i6;
82011 return regeneratorRuntime.wrap(function gpxGen$(_context) {
82013 switch (_context.prev = _context.next) {
82015 tracks = doc.getElementsByTagName("trk");
82016 routes = doc.getElementsByTagName("rte");
82017 waypoints = doc.getElementsByTagName("wpt");
82021 if (!(i < tracks.length)) {
82022 _context.next = 12;
82026 feature = getTrack(tracks[i]);
82045 if (!(_i5 < routes.length)) {
82046 _context.next = 21;
82050 _feature = getRoute(routes[_i5]);
82053 _context.next = 18;
82057 _context.next = 18;
82062 _context.next = 13;
82069 if (!(_i6 < waypoints.length)) {
82070 _context.next = 28;
82074 _context.next = 25;
82075 return getPoint(waypoints[_i6]);
82079 _context.next = 22;
82084 return _context.stop();
82090 function gpx(doc) {
82092 type: "FeatureCollection",
82093 features: Array.from(gpxGen(doc))
82097 var removeSpace = /\s*/g;
82098 var trimSpace = /^\s*|\s*$/g;
82099 var splitSpace = /\s+/; // generate a short, numeric hash of a string
82101 function okhash(x) {
82102 if (!x || !x.length) return 0;
82105 for (var i = 0; i < x.length; i++) {
82106 h = (h << 5) - h + x.charCodeAt(i) | 0;
82110 } // get one coordinate from a coordinate array, if any
82113 function coord1(v) {
82114 return v.replace(removeSpace, "").split(",").map(parseFloat);
82115 } // get all coordinates from a coordinate array as [[],[]]
82118 function coord(v) {
82119 return v.replace(trimSpace, "").split(splitSpace).map(coord1);
82122 function xml2str(node) {
82123 if (node.xml !== undefined) return node.xml;
82125 if (node.tagName) {
82126 var output = node.tagName;
82128 for (var i = 0; i < node.attributes.length; i++) {
82129 output += node.attributes[i].name + node.attributes[i].value;
82132 for (var _i9 = 0; _i9 < node.childNodes.length; _i9++) {
82133 output += xml2str(node.childNodes[_i9]);
82139 if (node.nodeName === "#text") {
82140 return (node.nodeValue || node.value || "").trim();
82143 if (node.nodeName === "#cdata-section") {
82144 return node.nodeValue;
82150 var geotypes = ["Polygon", "LineString", "Point", "Track", "gx:Track"];
82152 function kmlColor(properties, elem, prefix) {
82153 var v = nodeVal(get1(elem, "color")) || "";
82154 var colorProp = prefix == "stroke" || prefix === "fill" ? prefix : prefix + "-color";
82156 if (v.substr(0, 1) === "#") {
82160 if (v.length === 6 || v.length === 3) {
82161 properties[colorProp] = v;
82162 } else if (v.length === 8) {
82163 properties[prefix + "-opacity"] = parseInt(v.substr(0, 2), 16) / 255;
82164 properties[colorProp] = "#" + v.substr(6, 2) + v.substr(4, 2) + v.substr(2, 2);
82168 function numericProperty(properties, elem, source, target) {
82169 var val = parseFloat(nodeVal(get1(elem, source)));
82170 if (!isNaN(val)) properties[target] = val;
82173 function gxCoords(root) {
82174 var elems = root.getElementsByTagName("coord");
82177 if (elems.length === 0) elems = root.getElementsByTagName("gx:coord");
82179 for (var i = 0; i < elems.length; i++) {
82180 coords.push(nodeVal(elems[i]).split(" ").map(parseFloat));
82183 var timeElems = root.getElementsByTagName("when");
82185 for (var j = 0; j < timeElems.length; j++) {
82186 times.push(nodeVal(timeElems[j]));
82195 function getGeometry(root) {
82202 var coordTimes = [];
82204 if (get1(root, "MultiGeometry")) {
82205 return getGeometry(get1(root, "MultiGeometry"));
82208 if (get1(root, "MultiTrack")) {
82209 return getGeometry(get1(root, "MultiTrack"));
82212 if (get1(root, "gx:MultiTrack")) {
82213 return getGeometry(get1(root, "gx:MultiTrack"));
82216 for (i = 0; i < geotypes.length; i++) {
82217 geomNodes = root.getElementsByTagName(geotypes[i]);
82220 for (j = 0; j < geomNodes.length; j++) {
82221 geomNode = geomNodes[j];
82223 if (geotypes[i] === "Point") {
82226 coordinates: coord1(nodeVal(get1(geomNode, "coordinates")))
82228 } else if (geotypes[i] === "LineString") {
82230 type: "LineString",
82231 coordinates: coord(nodeVal(get1(geomNode, "coordinates")))
82233 } else if (geotypes[i] === "Polygon") {
82234 var rings = geomNode.getElementsByTagName("LinearRing"),
82237 for (k = 0; k < rings.length; k++) {
82238 coords.push(coord(nodeVal(get1(rings[k], "coordinates"))));
82243 coordinates: coords
82245 } else if (geotypes[i] === "Track" || geotypes[i] === "gx:Track") {
82246 var track = gxCoords(geomNode);
82248 type: "LineString",
82249 coordinates: track.coords
82251 if (track.times.length) coordTimes.push(track.times);
82259 coordTimes: coordTimes
82263 function getPlacemark(root, styleIndex, styleMapIndex, styleByHash) {
82264 var geomsAndTimes = getGeometry(root);
82266 var properties = {};
82267 var name = nodeVal(get1(root, "name"));
82268 var address = nodeVal(get1(root, "address"));
82269 var styleUrl = nodeVal(get1(root, "styleUrl"));
82270 var description = nodeVal(get1(root, "description"));
82271 var timeSpan = get1(root, "TimeSpan");
82272 var timeStamp = get1(root, "TimeStamp");
82273 var extendedData = get1(root, "ExtendedData");
82274 var iconStyle = get1(root, "IconStyle");
82275 var labelStyle = get1(root, "LabelStyle");
82276 var lineStyle = get1(root, "LineStyle");
82277 var polyStyle = get1(root, "PolyStyle");
82278 var visibility = get1(root, "visibility");
82279 if (name) properties.name = name;
82280 if (address) properties.address = address;
82283 if (styleUrl[0] !== "#") {
82284 styleUrl = "#" + styleUrl;
82287 properties.styleUrl = styleUrl;
82289 if (styleIndex[styleUrl]) {
82290 properties.styleHash = styleIndex[styleUrl];
82293 if (styleMapIndex[styleUrl]) {
82294 properties.styleMapHash = styleMapIndex[styleUrl];
82295 properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal];
82296 } // Try to populate the lineStyle or polyStyle since we got the style hash
82299 var style = styleByHash[properties.styleHash];
82302 if (!iconStyle) iconStyle = get1(style, "IconStyle");
82303 if (!labelStyle) labelStyle = get1(style, "LabelStyle");
82304 if (!lineStyle) lineStyle = get1(style, "LineStyle");
82305 if (!polyStyle) polyStyle = get1(style, "PolyStyle");
82309 if (description) properties.description = description;
82312 var begin = nodeVal(get1(timeSpan, "begin"));
82313 var end = nodeVal(get1(timeSpan, "end"));
82314 properties.timespan = {
82321 properties.timestamp = nodeVal(get1(timeStamp, "when"));
82325 kmlColor(properties, iconStyle, "icon");
82326 numericProperty(properties, iconStyle, "scale", "icon-scale");
82327 numericProperty(properties, iconStyle, "heading", "icon-heading");
82328 var hotspot = get1(iconStyle, "hotSpot");
82331 var left = parseFloat(hotspot.getAttribute("x"));
82332 var top = parseFloat(hotspot.getAttribute("y"));
82333 if (!isNaN(left) && !isNaN(top)) properties["icon-offset"] = [left, top];
82336 var icon = get1(iconStyle, "Icon");
82339 var href = nodeVal(get1(icon, "href"));
82340 if (href) properties.icon = href;
82345 kmlColor(properties, labelStyle, "label");
82346 numericProperty(properties, labelStyle, "scale", "label-scale");
82350 kmlColor(properties, lineStyle, "stroke");
82351 numericProperty(properties, lineStyle, "width", "stroke-width");
82355 kmlColor(properties, polyStyle, "fill");
82356 var fill = nodeVal(get1(polyStyle, "fill"));
82357 var outline = nodeVal(get1(polyStyle, "outline"));
82358 if (fill) properties["fill-opacity"] = fill === "1" ? properties["fill-opacity"] || 1 : 0;
82359 if (outline) properties["stroke-opacity"] = outline === "1" ? properties["stroke-opacity"] || 1 : 0;
82362 if (extendedData) {
82363 var datas = extendedData.getElementsByTagName("Data"),
82364 simpleDatas = extendedData.getElementsByTagName("SimpleData");
82366 for (i = 0; i < datas.length; i++) {
82367 properties[datas[i].getAttribute("name")] = nodeVal(get1(datas[i], "value"));
82370 for (i = 0; i < simpleDatas.length; i++) {
82371 properties[simpleDatas[i].getAttribute("name")] = nodeVal(simpleDatas[i]);
82376 properties.visibility = nodeVal(visibility);
82379 if (geomsAndTimes.coordTimes.length) {
82380 properties.coordinateProperties = {
82381 times: geomsAndTimes.coordTimes.length === 1 ? geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes
82387 geometry: geomsAndTimes.geoms.length === 0 ? null : geomsAndTimes.geoms.length === 1 ? geomsAndTimes.geoms[0] : {
82388 type: "GeometryCollection",
82389 geometries: geomsAndTimes.geoms
82391 properties: properties
82393 if (root.getAttribute("id")) feature.id = root.getAttribute("id");
82397 function kmlGen(doc) {
82398 var styleIndex, styleByHash, styleMapIndex, placemarks, styles, styleMaps, k, hash, l, pairs, pairsMap, m, j, feature;
82399 return regeneratorRuntime.wrap(function kmlGen$(_context3) {
82401 switch (_context3.prev = _context3.next) {
82403 // styleindex keeps track of hashed styles in order to match feature
82405 styleByHash = {}; // stylemapindex keeps track of style maps to expose in properties
82407 styleMapIndex = {}; // atomic geospatial types supported by KML - MultiGeometry is
82408 // handled separately
82409 // all root placemarks in the file
82411 placemarks = doc.getElementsByTagName("Placemark");
82412 styles = doc.getElementsByTagName("Style");
82413 styleMaps = doc.getElementsByTagName("StyleMap");
82415 for (k = 0; k < styles.length; k++) {
82416 hash = okhash(xml2str(styles[k])).toString(16);
82417 styleIndex["#" + styles[k].getAttribute("id")] = hash;
82418 styleByHash[hash] = styles[k];
82421 for (l = 0; l < styleMaps.length; l++) {
82422 styleIndex["#" + styleMaps[l].getAttribute("id")] = okhash(xml2str(styleMaps[l])).toString(16);
82423 pairs = styleMaps[l].getElementsByTagName("Pair");
82426 for (m = 0; m < pairs.length; m++) {
82427 pairsMap[nodeVal(get1(pairs[m], "key"))] = nodeVal(get1(pairs[m], "styleUrl"));
82430 styleMapIndex["#" + styleMaps[l].getAttribute("id")] = pairsMap;
82436 if (!(j < placemarks.length)) {
82437 _context3.next = 17;
82441 feature = getPlacemark(placemarks[j], styleIndex, styleMapIndex, styleByHash);
82444 _context3.next = 14;
82448 _context3.next = 14;
82453 _context3.next = 9;
82458 return _context3.stop();
82464 function kml(doc) {
82466 type: "FeatureCollection",
82467 features: Array.from(kmlGen(doc))
82471 var _initialized = false;
82472 var _enabled = false;
82476 function svgData(projection, context, dispatch) {
82477 var throttledRedraw = throttle(function () {
82478 dispatch.call('change');
82481 var _showLabels = true;
82482 var detected = utilDetect();
82483 var layer = select(null);
82494 if (_initialized) return; // run once
82499 function over(d3_event) {
82500 d3_event.stopPropagation();
82501 d3_event.preventDefault();
82502 d3_event.dataTransfer.dropEffect = 'copy';
82505 context.container().attr('dropzone', 'copy').on('drop.svgData', function (d3_event) {
82506 d3_event.stopPropagation();
82507 d3_event.preventDefault();
82508 if (!detected.filedrop) return;
82509 drawData.fileList(d3_event.dataTransfer.files);
82510 }).on('dragenter.svgData', over).on('dragexit.svgData', over).on('dragover.svgData', over);
82511 _initialized = true;
82514 function getService() {
82515 if (services.vectorTile && !_vtService) {
82516 _vtService = services.vectorTile;
82518 _vtService.event.on('loadedData', throttledRedraw);
82519 } else if (!services.vectorTile && _vtService) {
82526 function showLayer() {
82528 layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () {
82529 dispatch.call('change');
82533 function hideLayer() {
82534 throttledRedraw.cancel();
82535 layer.transition().duration(250).style('opacity', 0).on('end', layerOff);
82538 function layerOn() {
82539 layer.style('display', 'block');
82542 function layerOff() {
82543 layer.selectAll('.viewfield-group').remove();
82544 layer.style('display', 'none');
82545 } // ensure that all geojson features in a collection have IDs
82548 function ensureIDs(gj) {
82549 if (!gj) return null;
82551 if (gj.type === 'FeatureCollection') {
82552 for (var i = 0; i < gj.features.length; i++) {
82553 ensureFeatureID(gj.features[i]);
82556 ensureFeatureID(gj);
82560 } // ensure that each single Feature object has a unique ID
82563 function ensureFeatureID(feature) {
82564 if (!feature) return;
82565 feature.__featurehash__ = utilHashcode(fastJsonStableStringify(feature));
82567 } // Prefer an array of Features instead of a FeatureCollection
82570 function getFeatures(gj) {
82571 if (!gj) return [];
82573 if (gj.type === 'FeatureCollection') {
82574 return gj.features;
82580 function featureKey(d) {
82581 return d.__featurehash__;
82584 function isPolygon(d) {
82585 return d.geometry.type === 'Polygon' || d.geometry.type === 'MultiPolygon';
82588 function clipPathID(d) {
82589 return 'ideditor-data-' + d.__featurehash__ + '-clippath';
82592 function featureClasses(d) {
82593 return ['data' + d.__featurehash__, d.geometry.type, isPolygon(d) ? 'area' : '', d.__layerID__ || ''].filter(Boolean).join(' ');
82596 function drawData(selection) {
82597 var vtService = getService();
82598 var getPath = svgPath(projection).geojson;
82599 var getAreaPath = svgPath(projection, null, true).geojson;
82600 var hasData = drawData.hasData();
82601 layer = selection.selectAll('.layer-mapdata').data(_enabled && hasData ? [0] : []);
82602 layer.exit().remove();
82603 layer = layer.enter().append('g').attr('class', 'layer-mapdata').merge(layer);
82604 var surface = context.surface();
82605 if (!surface || surface.empty()) return; // not ready to draw yet, starting up
82608 var geoData, polygonData;
82610 if (_template && vtService) {
82611 // fetch data from vector tile service
82612 var sourceID = _template;
82613 vtService.loadTiles(sourceID, _template, projection);
82614 geoData = vtService.data(sourceID, projection);
82616 geoData = getFeatures(_geojson);
82619 geoData = geoData.filter(getPath);
82620 polygonData = geoData.filter(isPolygon); // Draw clip paths for polygons
82622 var clipPaths = surface.selectAll('defs').selectAll('.clipPath-data').data(polygonData, featureKey);
82623 clipPaths.exit().remove();
82624 var clipPathsEnter = clipPaths.enter().append('clipPath').attr('class', 'clipPath-data').attr('id', clipPathID);
82625 clipPathsEnter.append('path');
82626 clipPaths.merge(clipPathsEnter).selectAll('path').attr('d', getAreaPath); // Draw fill, shadow, stroke layers
82628 var datagroups = layer.selectAll('g.datagroup').data(['fill', 'shadow', 'stroke']);
82629 datagroups = datagroups.enter().append('g').attr('class', function (d) {
82630 return 'datagroup datagroup-' + d;
82631 }).merge(datagroups); // Draw paths
82638 var paths = datagroups.selectAll('path').data(function (layer) {
82639 return pathData[layer];
82640 }, featureKey); // exit
82642 paths.exit().remove(); // enter/update
82644 paths = paths.enter().append('path').attr('class', function (d) {
82645 var datagroup = this.parentNode.__data__;
82646 return 'pathdata ' + datagroup + ' ' + featureClasses(d);
82647 }).attr('clip-path', function (d) {
82648 var datagroup = this.parentNode.__data__;
82649 return datagroup === 'fill' ? 'url(#' + clipPathID(d) + ')' : null;
82650 }).merge(paths).attr('d', function (d) {
82651 var datagroup = this.parentNode.__data__;
82652 return datagroup === 'fill' ? getAreaPath(d) : getPath(d);
82655 layer.call(drawLabels, 'label-halo', geoData).call(drawLabels, 'label', geoData);
82657 function drawLabels(selection, textClass, data) {
82658 var labelPath = d3_geoPath(projection);
82659 var labelData = data.filter(function (d) {
82660 return _showLabels && d.properties && (d.properties.desc || d.properties.name);
82662 var labels = selection.selectAll('text.' + textClass).data(labelData, featureKey); // exit
82664 labels.exit().remove(); // enter/update
82666 labels = labels.enter().append('text').attr('class', function (d) {
82667 return textClass + ' ' + featureClasses(d);
82668 }).merge(labels).text(function (d) {
82669 return d.properties.desc || d.properties.name;
82670 }).attr('x', function (d) {
82671 var centroid = labelPath.centroid(d);
82672 return centroid[0] + 11;
82673 }).attr('y', function (d) {
82674 var centroid = labelPath.centroid(d);
82675 return centroid[1];
82680 function getExtension(fileName) {
82681 if (!fileName) return;
82682 var re = /\.(gpx|kml|(geo)?json)$/i;
82683 var match = fileName.toLowerCase().match(re);
82684 return match && match.length && match[0];
82687 function xmlToDom(textdata) {
82688 return new DOMParser().parseFromString(textdata, 'text/xml');
82691 function stringifyGeojsonProperties(feature) {
82692 var properties = feature.properties;
82694 for (var key in properties) {
82695 var property = properties[key];
82697 if (typeof property === 'number' || typeof property === 'boolean' || Array.isArray(property)) {
82698 properties[key] = property.toString();
82699 } else if (property === null) {
82700 properties[key] = 'null';
82701 } else if (_typeof(property) === 'object') {
82702 properties[key] = JSON.stringify(property);
82707 drawData.setFile = function (extension, data) {
82714 switch (extension) {
82716 gj = gpx(xmlToDom(data));
82720 gj = kml(xmlToDom(data));
82725 gj = JSON.parse(data);
82727 if (gj.type === 'FeatureCollection') {
82728 gj.features.forEach(stringifyGeojsonProperties);
82729 } else if (gj.type === 'Feature') {
82730 stringifyGeojsonProperties(gj);
82738 if (Object.keys(gj).length) {
82739 _geojson = ensureIDs(gj);
82740 _src = extension + ' data file';
82744 dispatch.call('change');
82748 drawData.showLabels = function (val) {
82749 if (!arguments.length) return _showLabels;
82754 drawData.enabled = function (val) {
82755 if (!arguments.length) return _enabled;
82764 dispatch.call('change');
82768 drawData.hasData = function () {
82769 var gj = _geojson || {};
82770 return !!(_template || Object.keys(gj).length);
82773 drawData.template = function (val, src) {
82774 if (!arguments.length) return _template; // test source against OSM imagery blocklists..
82776 var osm = context.connection();
82779 var blocklists = osm.imageryBlocklists();
82784 for (var i = 0; i < blocklists.length; i++) {
82785 regex = blocklists[i];
82786 fail = regex.test(val);
82789 } // ensure at least one test was run.
82793 regex = /.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/;
82794 fail = regex.test(val);
82800 _geojson = null; // strip off the querystring/hash from the template,
82801 // it often includes the access token
82803 _src = src || 'vectortile:' + val.split(/[?#]/)[0];
82804 dispatch.call('change');
82808 drawData.geojson = function (gj, src) {
82809 if (!arguments.length) return _geojson;
82816 if (Object.keys(gj).length) {
82817 _geojson = ensureIDs(gj);
82818 _src = src || 'unknown.geojson';
82821 dispatch.call('change');
82825 drawData.fileList = function (fileList) {
82826 if (!arguments.length) return _fileList;
82828 _fileList = fileList;
82831 if (!fileList || !fileList.length) return this;
82832 var f = fileList[0];
82833 var extension = getExtension(f.name);
82834 var reader = new FileReader();
82836 reader.onload = function () {
82837 return function (e) {
82838 drawData.setFile(extension, e.target.result);
82842 reader.readAsText(f);
82846 drawData.url = function (url, defaultExtension) {
82850 _src = null; // strip off any querystring/hash from the url before checking extension
82852 var testUrl = url.split(/[?#]/)[0];
82853 var extension = getExtension(testUrl) || defaultExtension;
82857 d3_text(url).then(function (data) {
82858 drawData.setFile(extension, data);
82859 })["catch"](function () {
82863 drawData.template(url);
82869 drawData.getSrc = function () {
82873 drawData.fitZoom = function () {
82874 var features = getFeatures(_geojson);
82875 if (!features.length) return;
82876 var map = context.map();
82877 var viewport = map.trimmedExtent().polygon();
82878 var coords = features.reduce(function (coords, feature) {
82879 var geom = feature.geometry;
82880 if (!geom) return coords;
82881 var c = geom.coordinates;
82882 /* eslint-disable no-fallthrough */
82884 switch (geom.type) {
82892 case 'MultiPolygon':
82893 c = utilArrayFlatten(c);
82896 case 'MultiLineString':
82897 c = utilArrayFlatten(c);
82900 /* eslint-enable no-fallthrough */
82903 return utilArrayUnion(coords, c);
82906 if (!geoPolygonIntersectsPolygon(viewport, coords, true)) {
82907 var extent = geoExtent(d3_geoBounds({
82908 type: 'LineString',
82909 coordinates: coords
82911 map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
82921 function svgDebug(projection, context) {
82922 function drawDebug(selection) {
82923 var showTile = context.getDebug('tile');
82924 var showCollision = context.getDebug('collision');
82925 var showImagery = context.getDebug('imagery');
82926 var showTouchTargets = context.getDebug('target');
82927 var showDownloaded = context.getDebug('downloaded');
82928 var debugData = [];
82937 if (showCollision) {
82951 if (showTouchTargets) {
82954 label: 'touchTargets'
82958 if (showDownloaded) {
82961 label: 'downloaded'
82965 var legend = context.container().select('.main-content').selectAll('.debug-legend').data(debugData.length ? [0] : []);
82966 legend.exit().remove();
82967 legend = legend.enter().append('div').attr('class', 'fillD debug-legend').merge(legend);
82968 var legendItems = legend.selectAll('.debug-legend-item').data(debugData, function (d) {
82971 legendItems.exit().remove();
82972 legendItems.enter().append('span').attr('class', function (d) {
82973 return "debug-legend-item ".concat(d["class"]);
82974 }).text(function (d) {
82977 var layer = selection.selectAll('.layer-debug').data(showImagery || showDownloaded ? [0] : []);
82978 layer.exit().remove();
82979 layer = layer.enter().append('g').attr('class', 'layer-debug').merge(layer); // imagery
82981 var extent = context.map().extent();
82982 _mainFileFetcher.get('imagery').then(function (d) {
82983 var hits = showImagery && d.query.bbox(extent.rectangle(), true) || [];
82984 var features = hits.map(function (d) {
82985 return d.features[d.id];
82987 var imagery = layer.selectAll('path.debug-imagery').data(features);
82988 imagery.exit().remove();
82989 imagery.enter().append('path').attr('class', 'debug-imagery debug orange');
82990 })["catch"](function () {
82994 var osm = context.connection();
82995 var dataDownloaded = [];
82997 if (osm && showDownloaded) {
82998 var rtree = osm.caches('get').tile.rtree;
82999 dataDownloaded = rtree.all().map(function (bbox) {
83007 coordinates: [[[bbox.minX, bbox.minY], [bbox.minX, bbox.maxY], [bbox.maxX, bbox.maxY], [bbox.maxX, bbox.minY], [bbox.minX, bbox.minY]]]
83013 var downloaded = layer.selectAll('path.debug-downloaded').data(showDownloaded ? dataDownloaded : []);
83014 downloaded.exit().remove();
83015 downloaded.enter().append('path').attr('class', 'debug-downloaded debug purple'); // update
83017 layer.selectAll('path').attr('d', svgPath(projection).geojson);
83018 } // This looks strange because `enabled` methods on other layers are
83019 // chainable getter/setters, and this one is just a getter.
83022 drawDebug.enabled = function () {
83023 if (!arguments.length) {
83024 return context.getDebug('tile') || context.getDebug('collision') || context.getDebug('imagery') || context.getDebug('target') || context.getDebug('downloaded');
83034 A standalone SVG element that contains only a `defs` sub-element. To be
83035 used once globally, since defs IDs must be unique within a document.
83038 function svgDefs(context) {
83039 var _defsSelection = select(null);
83041 var _spritesheetIds = ['iD-sprite', 'maki-sprite', 'temaki-sprite', 'fa-sprite', 'community-sprite'];
83043 function drawDefs(selection) {
83044 _defsSelection = selection.append('defs'); // add markers
83046 _defsSelection.append('marker').attr('id', 'ideditor-oneway-marker').attr('viewBox', '0 0 10 5').attr('refX', 2.5).attr('refY', 2.5).attr('markerWidth', 2).attr('markerHeight', 2).attr('markerUnits', 'strokeWidth').attr('orient', 'auto').append('path').attr('class', 'oneway-marker-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('stroke', 'none').attr('fill', '#000').attr('opacity', '0.75'); // SVG markers have to be given a colour where they're defined
83047 // (they can't inherit it from the line they're attached to),
83048 // so we need to manually define markers for each color of tag
83049 // (also, it's slightly nicer if we can control the
83050 // positioning for different tags)
83053 function addSidedMarker(name, color, offset) {
83054 _defsSelection.append('marker').attr('id', 'ideditor-sided-marker-' + name).attr('viewBox', '0 0 2 2').attr('refX', 1).attr('refY', -offset).attr('markerWidth', 1.5).attr('markerHeight', 1.5).attr('markerUnits', 'strokeWidth').attr('orient', 'auto').append('path').attr('class', 'sided-marker-path sided-marker-' + name + '-path').attr('d', 'M 0,0 L 1,1 L 2,0 z').attr('stroke', 'none').attr('fill', color);
83057 addSidedMarker('natural', 'rgb(170, 170, 170)', 0); // for a coastline, the arrows are (somewhat unintuitively) on
83058 // the water side, so let's color them blue (with a gap) to
83059 // give a stronger indication
83061 addSidedMarker('coastline', '#77dede', 1);
83062 addSidedMarker('waterway', '#77dede', 1); // barriers have a dashed line, and separating the triangle
83063 // from the line visually suits that
83065 addSidedMarker('barrier', '#ddd', 1);
83066 addSidedMarker('man_made', '#fff', 0);
83068 _defsSelection.append('marker').attr('id', 'ideditor-viewfield-marker').attr('viewBox', '0 0 16 16').attr('refX', 8).attr('refY', 16).attr('markerWidth', 4).attr('markerHeight', 4).attr('markerUnits', 'strokeWidth').attr('orient', 'auto').append('path').attr('class', 'viewfield-marker-path').attr('d', 'M 6,14 C 8,13.4 8,13.4 10,14 L 16,3 C 12,0 4,0 0,3 z').attr('fill', '#333').attr('fill-opacity', '0.75').attr('stroke', '#fff').attr('stroke-width', '0.5px').attr('stroke-opacity', '0.75');
83070 _defsSelection.append('marker').attr('id', 'ideditor-viewfield-marker-wireframe').attr('viewBox', '0 0 16 16').attr('refX', 8).attr('refY', 16).attr('markerWidth', 4).attr('markerHeight', 4).attr('markerUnits', 'strokeWidth').attr('orient', 'auto').append('path').attr('class', 'viewfield-marker-path').attr('d', 'M 6,14 C 8,13.4 8,13.4 10,14 L 16,3 C 12,0 4,0 0,3 z').attr('fill', 'none').attr('stroke', '#fff').attr('stroke-width', '0.5px').attr('stroke-opacity', '0.75'); // add patterns
83073 var patterns = _defsSelection.selectAll('pattern').data([// pattern name, pattern image name
83074 ['beach', 'dots'], ['construction', 'construction'], ['cemetery', 'cemetery'], ['cemetery_christian', 'cemetery_christian'], ['cemetery_buddhist', 'cemetery_buddhist'], ['cemetery_muslim', 'cemetery_muslim'], ['cemetery_jewish', 'cemetery_jewish'], ['farmland', 'farmland'], ['farmyard', 'farmyard'], ['forest', 'forest'], ['forest_broadleaved', 'forest_broadleaved'], ['forest_needleleaved', 'forest_needleleaved'], ['forest_leafless', 'forest_leafless'], ['golf_green', 'grass'], ['grass', 'grass'], ['landfill', 'landfill'], ['meadow', 'grass'], ['orchard', 'orchard'], ['pond', 'pond'], ['quarry', 'quarry'], ['scrub', 'bushes'], ['vineyard', 'vineyard'], ['water_standing', 'lines'], ['waves', 'waves'], ['wetland', 'wetland'], ['wetland_marsh', 'wetland_marsh'], ['wetland_swamp', 'wetland_swamp'], ['wetland_bog', 'wetland_bog'], ['wetland_reedbed', 'wetland_reedbed']]).enter().append('pattern').attr('id', function (d) {
83075 return 'ideditor-pattern-' + d[0];
83076 }).attr('width', 32).attr('height', 32).attr('patternUnits', 'userSpaceOnUse');
83078 patterns.append('rect').attr('x', 0).attr('y', 0).attr('width', 32).attr('height', 32).attr('class', function (d) {
83079 return 'pattern-color-' + d[0];
83081 patterns.append('image').attr('x', 0).attr('y', 0).attr('width', 32).attr('height', 32).attr('xlink:href', function (d) {
83082 return context.imagePath('pattern/' + d[1] + '.png');
83083 }); // add clip paths
83085 _defsSelection.selectAll('clipPath').data([12, 18, 20, 32, 45]).enter().append('clipPath').attr('id', function (d) {
83086 return 'ideditor-clip-square-' + d;
83087 }).append('rect').attr('x', 0).attr('y', 0).attr('width', function (d) {
83089 }).attr('height', function (d) {
83091 }); // add symbol spritesheets
83094 addSprites(_spritesheetIds, true);
83097 function addSprites(ids, overrideColors) {
83098 _spritesheetIds = utilArrayUniq(_spritesheetIds.concat(ids));
83100 var spritesheets = _defsSelection.selectAll('.spritesheet').data(_spritesheetIds);
83102 spritesheets.enter().append('g').attr('class', function (d) {
83103 return 'spritesheet spritesheet-' + d;
83104 }).each(function (d) {
83105 var url = context.imagePath(d + '.svg');
83106 var node = select(this).node();
83107 svg(url).then(function (svg) {
83108 node.appendChild(select(svg.documentElement).attr('id', 'ideditor-' + d).node());
83110 if (overrideColors && d !== 'iD-sprite') {
83111 // allow icon colors to be overridden..
83112 select(node).selectAll('path').attr('fill', 'currentColor');
83114 })["catch"](function () {
83118 spritesheets.exit().remove();
83121 drawDefs.addSprites = addSprites;
83125 var _layerEnabled$2 = false;
83129 function svgKeepRight(projection, context, dispatch) {
83130 var throttledRedraw = throttle(function () {
83131 return dispatch.call('change');
83135 var touchLayer = select(null);
83136 var drawLayer = select(null);
83137 var layerVisible = false;
83139 function markerPath(selection, klass) {
83140 selection.attr('class', klass).attr('transform', 'translate(-4, -24)').attr('d', 'M11.6,6.2H7.1l1.4-5.1C8.6,0.6,8.1,0,7.5,0H2.2C1.7,0,1.3,0.3,1.3,0.8L0,10.2c-0.1,0.6,0.4,1.1,0.9,1.1h4.6l-1.8,7.6C3.6,19.4,4.1,20,4.7,20c0.3,0,0.6-0.2,0.8-0.5l6.9-11.9C12.7,7,12.3,6.2,11.6,6.2z');
83141 } // Loosely-coupled keepRight service for fetching issues.
83144 function getService() {
83145 if (services.keepRight && !_qaService$2) {
83146 _qaService$2 = services.keepRight;
83148 _qaService$2.on('loaded', throttledRedraw);
83149 } else if (!services.keepRight && _qaService$2) {
83150 _qaService$2 = null;
83153 return _qaService$2;
83154 } // Show the markers
83157 function editOn() {
83158 if (!layerVisible) {
83159 layerVisible = true;
83160 drawLayer.style('display', 'block');
83162 } // Immediately remove the markers and their touch targets
83165 function editOff() {
83166 if (layerVisible) {
83167 layerVisible = false;
83168 drawLayer.style('display', 'none');
83169 drawLayer.selectAll('.qaItem.keepRight').remove();
83170 touchLayer.selectAll('.qaItem.keepRight').remove();
83172 } // Enable the layer. This shows the markers and transitions them to visible.
83175 function layerOn() {
83177 drawLayer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
83178 return dispatch.call('change');
83180 } // Disable the layer. This transitions the layer invisible and then hides the markers.
83183 function layerOff() {
83184 throttledRedraw.cancel();
83185 drawLayer.interrupt();
83186 touchLayer.selectAll('.qaItem.keepRight').remove();
83187 drawLayer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
83189 dispatch.call('change');
83191 } // Update the issue markers
83194 function updateMarkers() {
83195 if (!layerVisible || !_layerEnabled$2) return;
83196 var service = getService();
83197 var selectedID = context.selectedErrorID();
83198 var data = service ? service.getItems(projection) : [];
83199 var getTransform = svgPointTransform(projection); // Draw markers..
83201 var markers = drawLayer.selectAll('.qaItem.keepRight').data(data, function (d) {
83205 markers.exit().remove(); // enter
83207 var markersEnter = markers.enter().append('g').attr('class', function (d) {
83208 return "qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.parentIssueType);
83210 markersEnter.append('ellipse').attr('cx', 0.5).attr('cy', 1).attr('rx', 6.5).attr('ry', 3).attr('class', 'stroke');
83211 markersEnter.append('path').call(markerPath, 'shadow');
83212 markersEnter.append('use').attr('class', 'qaItem-fill').attr('width', '20px').attr('height', '20px').attr('x', '-8px').attr('y', '-22px').attr('xlink:href', '#iD-icon-bolt'); // update
83214 markers.merge(markersEnter).sort(sortY).classed('selected', function (d) {
83215 return d.id === selectedID;
83216 }).attr('transform', getTransform); // Draw targets..
83218 if (touchLayer.empty()) return;
83219 var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
83220 var targets = touchLayer.selectAll('.qaItem.keepRight').data(data, function (d) {
83224 targets.exit().remove(); // enter/update
83226 targets.enter().append('rect').attr('width', '20px').attr('height', '20px').attr('x', '-8px').attr('y', '-22px').merge(targets).sort(sortY).attr('class', function (d) {
83227 return "qaItem ".concat(d.service, " target ").concat(fillClass, " itemId-").concat(d.id);
83228 }).attr('transform', getTransform);
83230 function sortY(a, b) {
83231 return a.id === selectedID ? 1 : b.id === selectedID ? -1 : a.severity === 'error' && b.severity !== 'error' ? 1 : b.severity === 'error' && a.severity !== 'error' ? -1 : b.loc[1] - a.loc[1];
83233 } // Draw the keepRight layer and schedule loading issues and updating markers.
83236 function drawKeepRight(selection) {
83237 var service = getService();
83238 var surface = context.surface();
83240 if (surface && !surface.empty()) {
83241 touchLayer = surface.selectAll('.data-layer.touch .layer-touch.markers');
83244 drawLayer = selection.selectAll('.layer-keepRight').data(service ? [0] : []);
83245 drawLayer.exit().remove();
83246 drawLayer = drawLayer.enter().append('g').attr('class', 'layer-keepRight').style('display', _layerEnabled$2 ? 'block' : 'none').merge(drawLayer);
83248 if (_layerEnabled$2) {
83249 if (service && ~~context.map().zoom() >= minZoom) {
83251 service.loadIssues(projection);
83257 } // Toggles the layer on and off
83260 drawKeepRight.enabled = function (val) {
83261 if (!arguments.length) return _layerEnabled$2;
83262 _layerEnabled$2 = val;
83264 if (_layerEnabled$2) {
83269 if (context.selectedErrorID()) {
83270 context.enter(modeBrowse(context));
83274 dispatch.call('change');
83278 drawKeepRight.supported = function () {
83279 return !!getService();
83282 return drawKeepRight;
83285 function svgGeolocate(projection) {
83286 var layer = select(null);
83291 if (svgGeolocate.initialized) return; // run once
83293 svgGeolocate.enabled = false;
83294 svgGeolocate.initialized = true;
83297 function showLayer() {
83298 layer.style('display', 'block');
83301 function hideLayer() {
83302 layer.transition().duration(250).style('opacity', 0);
83305 function layerOn() {
83306 layer.style('opacity', 0).transition().duration(250).style('opacity', 1);
83309 function layerOff() {
83310 layer.style('display', 'none');
83313 function transform(d) {
83314 return svgPointTransform(projection)(d);
83317 function accuracy(accuracy, loc) {
83318 // converts accuracy to pixels...
83319 var degreesRadius = geoMetersToLat(accuracy),
83320 tangentLoc = [loc[0], loc[1] + degreesRadius],
83321 projectedTangent = projection(tangentLoc),
83322 projectedLoc = projection([loc[0], loc[1]]); // southern most point will have higher pixel value...
83324 return Math.round(projectedLoc[1] - projectedTangent[1]).toString();
83327 function update() {
83328 var geolocation = {
83329 loc: [_position.coords.longitude, _position.coords.latitude]
83331 var groups = layer.selectAll('.geolocations').selectAll('.geolocation').data([geolocation]);
83332 groups.exit().remove();
83333 var pointsEnter = groups.enter().append('g').attr('class', 'geolocation');
83334 pointsEnter.append('circle').attr('class', 'geolocate-radius').attr('dx', '0').attr('dy', '0').attr('fill', 'rgb(15,128,225)').attr('fill-opacity', '0.3').attr('r', '0');
83335 pointsEnter.append('circle').attr('dx', '0').attr('dy', '0').attr('fill', 'rgb(15,128,225)').attr('stroke', 'white').attr('stroke-width', '1.5').attr('r', '6');
83336 groups.merge(pointsEnter).attr('transform', transform);
83337 layer.select('.geolocate-radius').attr('r', accuracy(_position.coords.accuracy, geolocation.loc));
83340 function drawLocation(selection) {
83341 var enabled = svgGeolocate.enabled;
83342 layer = selection.selectAll('.layer-geolocate').data([0]);
83343 layer.exit().remove();
83344 var layerEnter = layer.enter().append('g').attr('class', 'layer-geolocate').style('display', enabled ? 'block' : 'none');
83345 layerEnter.append('g').attr('class', 'geolocations');
83346 layer = layerEnter.merge(layer);
83355 drawLocation.enabled = function (position, enabled) {
83356 if (!arguments.length) return svgGeolocate.enabled;
83357 _position = position;
83358 svgGeolocate.enabled = enabled;
83360 if (svgGeolocate.enabled) {
83371 return drawLocation;
83374 function svgLabels(projection, context) {
83375 var path = d3_geoPath(projection);
83376 var detected = utilDetect();
83377 var baselineHack = detected.ie || detected.browser.toLowerCase() === 'edge' || detected.browser.toLowerCase() === 'firefox' && detected.version >= 70;
83379 var _rdrawn = new RBush();
83381 var _rskipped = new RBush();
83383 var _textWidthCache = {};
83384 var _entitybboxes = {}; // Listed from highest to lowest priority
83386 var labelStack = [['line', 'aeroway', '*', 12], ['line', 'highway', 'motorway', 12], ['line', 'highway', 'trunk', 12], ['line', 'highway', 'primary', 12], ['line', 'highway', 'secondary', 12], ['line', 'highway', 'tertiary', 12], ['line', 'highway', '*', 12], ['line', 'railway', '*', 12], ['line', 'waterway', '*', 12], ['area', 'aeroway', '*', 12], ['area', 'amenity', '*', 12], ['area', 'building', '*', 12], ['area', 'historic', '*', 12], ['area', 'leisure', '*', 12], ['area', 'man_made', '*', 12], ['area', 'natural', '*', 12], ['area', 'shop', '*', 12], ['area', 'tourism', '*', 12], ['area', 'camp_site', '*', 12], ['point', 'aeroway', '*', 10], ['point', 'amenity', '*', 10], ['point', 'building', '*', 10], ['point', 'historic', '*', 10], ['point', 'leisure', '*', 10], ['point', 'man_made', '*', 10], ['point', 'natural', '*', 10], ['point', 'shop', '*', 10], ['point', 'tourism', '*', 10], ['point', 'camp_site', '*', 10], ['line', 'name', '*', 12], ['area', 'name', '*', 12], ['point', 'name', '*', 10]];
83388 function shouldSkipIcon(preset) {
83389 var noIcons = ['building', 'landuse', 'natural'];
83390 return noIcons.some(function (s) {
83391 return preset.id.indexOf(s) >= 0;
83395 function get(array, prop) {
83396 return function (d, i) {
83397 return array[i][prop];
83401 function textWidth(text, size, elem) {
83402 var c = _textWidthCache[size];
83403 if (!c) c = _textWidthCache[size] = {};
83408 c[text] = elem.getComputedTextLength();
83411 var str = encodeURIComponent(text).match(/%[CDEFcdef]/g);
83413 if (str === null) {
83414 return size / 3 * 2 * text.length;
83416 return size / 3 * (2 * text.length + str.length);
83421 function drawLinePaths(selection, entities, filter, classes, labels) {
83422 var paths = selection.selectAll('path').filter(filter).data(entities, osmEntity.key); // exit
83424 paths.exit().remove(); // enter/update
83426 paths.enter().append('path').style('stroke-width', get(labels, 'font-size')).attr('id', function (d) {
83427 return 'ideditor-labelpath-' + d.id;
83428 }).attr('class', classes).merge(paths).attr('d', get(labels, 'lineString'));
83431 function drawLineLabels(selection, entities, filter, classes, labels) {
83432 var texts = selection.selectAll('text.' + classes).filter(filter).data(entities, osmEntity.key); // exit
83434 texts.exit().remove(); // enter
83436 texts.enter().append('text').attr('class', function (d, i) {
83437 return classes + ' ' + labels[i].classes + ' ' + d.id;
83438 }).attr('dy', baselineHack ? '0.35em' : null).append('textPath').attr('class', 'textpath'); // update
83440 selection.selectAll('text.' + classes).selectAll('.textpath').filter(filter).data(entities, osmEntity.key).attr('startOffset', '50%').attr('xlink:href', function (d) {
83441 return '#ideditor-labelpath-' + d.id;
83442 }).text(utilDisplayNameForPath);
83445 function drawPointLabels(selection, entities, filter, classes, labels) {
83446 var texts = selection.selectAll('text.' + classes).filter(filter).data(entities, osmEntity.key); // exit
83448 texts.exit().remove(); // enter/update
83450 texts.enter().append('text').attr('class', function (d, i) {
83451 return classes + ' ' + labels[i].classes + ' ' + d.id;
83452 }).merge(texts).attr('x', get(labels, 'x')).attr('y', get(labels, 'y')).style('text-anchor', get(labels, 'textAnchor')).text(utilDisplayName).each(function (d, i) {
83453 textWidth(utilDisplayName(d), labels[i].height, this);
83457 function drawAreaLabels(selection, entities, filter, classes, labels) {
83458 entities = entities.filter(hasText);
83459 labels = labels.filter(hasText);
83460 drawPointLabels(selection, entities, filter, classes, labels);
83462 function hasText(d, i) {
83463 return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
83467 function drawAreaIcons(selection, entities, filter, classes, labels) {
83468 var icons = selection.selectAll('use.' + classes).filter(filter).data(entities, osmEntity.key); // exit
83470 icons.exit().remove(); // enter/update
83472 icons.enter().append('use').attr('class', 'icon ' + classes).attr('width', '17px').attr('height', '17px').merge(icons).attr('transform', get(labels, 'transform')).attr('xlink:href', function (d) {
83473 var preset = _mainPresetIndex.match(d, context.graph());
83474 var picon = preset && preset.icon;
83479 var isMaki = /^maki-/.test(picon);
83480 return '#' + picon + (isMaki ? '-15' : '');
83485 function drawCollisionBoxes(selection, rtree, which) {
83486 var classes = 'debug ' + which + ' ' + (which === 'debug-skipped' ? 'orange' : 'yellow');
83489 if (context.getDebug('collision')) {
83490 gj = rtree.all().map(function (d) {
83493 coordinates: [[[d.minX, d.minY], [d.maxX, d.minY], [d.maxX, d.maxY], [d.minX, d.maxY], [d.minX, d.minY]]]
83498 var boxes = selection.selectAll('.' + which).data(gj); // exit
83500 boxes.exit().remove(); // enter/update
83502 boxes.enter().append('path').attr('class', classes).merge(boxes).attr('d', d3_geoPath());
83505 function drawLabels(selection, graph, entities, filter, dimensions, fullRedraw) {
83506 var wireframe = context.surface().classed('fill-wireframe');
83507 var zoom = geoScaleToZoom(projection.scale());
83508 var labelable = [];
83509 var renderNodeAs = {};
83510 var i, j, k, entity, geometry;
83512 for (i = 0; i < labelStack.length; i++) {
83513 labelable.push([]);
83521 _entitybboxes = {};
83523 for (i = 0; i < entities.length; i++) {
83524 entity = entities[i];
83525 var toRemove = [].concat(_entitybboxes[entity.id] || []).concat(_entitybboxes[entity.id + 'I'] || []);
83527 for (j = 0; j < toRemove.length; j++) {
83528 _rdrawn.remove(toRemove[j]);
83530 _rskipped.remove(toRemove[j]);
83533 } // Loop through all the entities to do some preprocessing
83536 for (i = 0; i < entities.length; i++) {
83537 entity = entities[i];
83538 geometry = entity.geometry(graph); // Insert collision boxes around interesting points/vertices
83540 if (geometry === 'point' || geometry === 'vertex' && isInterestingVertex(entity)) {
83541 var hasDirections = entity.directions(graph, projection).length;
83544 if (!wireframe && geometry === 'point' && !(zoom >= 18 && hasDirections)) {
83545 renderNodeAs[entity.id] = 'point';
83546 markerPadding = 20; // extra y for marker height
83548 renderNodeAs[entity.id] = 'vertex';
83552 var coord = projection(entity.loc);
83553 var nodePadding = 10;
83555 minX: coord[0] - nodePadding,
83556 minY: coord[1] - nodePadding - markerPadding,
83557 maxX: coord[0] + nodePadding,
83558 maxY: coord[1] + nodePadding
83560 doInsert(bbox, entity.id + 'P');
83561 } // From here on, treat vertices like points
83564 if (geometry === 'vertex') {
83565 geometry = 'point';
83566 } // Determine which entities are label-able
83569 var preset = geometry === 'area' && _mainPresetIndex.match(entity, graph);
83570 var icon = preset && !shouldSkipIcon(preset) && preset.icon;
83571 if (!icon && !utilDisplayName(entity)) continue;
83573 for (k = 0; k < labelStack.length; k++) {
83574 var matchGeom = labelStack[k][0];
83575 var matchKey = labelStack[k][1];
83576 var matchVal = labelStack[k][2];
83577 var hasVal = entity.tags[matchKey];
83579 if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) {
83580 labelable[k].push(entity);
83595 }; // Try and find a valid label for labellable entities
83597 for (k = 0; k < labelable.length; k++) {
83598 var fontSize = labelStack[k][3];
83600 for (i = 0; i < labelable[k].length; i++) {
83601 entity = labelable[k][i];
83602 geometry = entity.geometry(graph);
83603 var getName = geometry === 'line' ? utilDisplayNameForPath : utilDisplayName;
83604 var name = getName(entity);
83605 var width = name && textWidth(name, fontSize);
83608 if (geometry === 'point' || geometry === 'vertex') {
83609 // no point or vertex labels in wireframe mode
83610 // no vertex labels at low zooms (vertices have no icons)
83611 if (wireframe) continue;
83612 var renderAs = renderNodeAs[entity.id];
83613 if (renderAs === 'vertex' && zoom < 17) continue;
83614 p = getPointLabel(entity, width, fontSize, renderAs);
83615 } else if (geometry === 'line') {
83616 p = getLineLabel(entity, width, fontSize);
83617 } else if (geometry === 'area') {
83618 p = getAreaLabel(entity, width, fontSize);
83622 if (geometry === 'vertex') {
83623 geometry = 'point';
83624 } // treat vertex like point
83627 p.classes = geometry + ' tag-' + labelStack[k][1];
83628 positions[geometry].push(p);
83629 labelled[geometry].push(entity);
83634 function isInterestingVertex(entity) {
83635 var selectedIDs = context.selectedIDs();
83636 return entity.hasInterestingTags() || entity.isEndpoint(graph) || entity.isConnected(graph) || selectedIDs.indexOf(entity.id) !== -1 || graph.parentWays(entity).some(function (parent) {
83637 return selectedIDs.indexOf(parent.id) !== -1;
83641 function getPointLabel(entity, width, height, geometry) {
83642 var y = geometry === 'point' ? -12 : 0;
83643 var pointOffsets = {
83644 ltr: [15, y, 'start'],
83645 rtl: [-15, y, 'end']
83647 var textDirection = _mainLocalizer.textDirection();
83648 var coord = projection(entity.loc);
83649 var textPadding = 2;
83650 var offset = pointOffsets[textDirection];
83654 x: coord[0] + offset[0],
83655 y: coord[1] + offset[1],
83656 textAnchor: offset[2]
83657 }; // insert a collision box for the text label..
83661 if (textDirection === 'rtl') {
83663 minX: p.x - width - textPadding,
83664 minY: p.y - height / 2 - textPadding,
83665 maxX: p.x + textPadding,
83666 maxY: p.y + height / 2 + textPadding
83670 minX: p.x - textPadding,
83671 minY: p.y - height / 2 - textPadding,
83672 maxX: p.x + width + textPadding,
83673 maxY: p.y + height / 2 + textPadding
83677 if (tryInsert([bbox], entity.id, true)) {
83682 function getLineLabel(entity, width, height) {
83683 var viewport = geoExtent(context.projection.clipExtent()).polygon();
83684 var points = graph.childNodes(entity).map(function (node) {
83685 return projection(node.loc);
83687 var length = geoPathLength(points);
83688 if (length < width + 20) return; // % along the line to attempt to place the label
83690 var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70, 25, 75, 20, 80, 15, 95, 10, 90, 5, 95];
83693 for (var i = 0; i < lineOffsets.length; i++) {
83694 var offset = lineOffsets[i];
83695 var middle = offset / 100 * length;
83696 var start = middle - width / 2;
83697 if (start < 0 || start + width > length) continue; // generate subpath and ignore paths that are invalid or don't cross viewport.
83699 var sub = subpath(points, start, start + width);
83701 if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
83705 var isReverse = reverse(sub);
83708 sub = sub.reverse();
83712 var boxsize = (height + 2) / 2;
83714 for (var j = 0; j < sub.length - 1; j++) {
83716 var b = sub[j + 1]; // split up the text into small collision boxes
83718 var num = Math.max(1, Math.floor(geoVecLength(a, b) / boxsize / 2));
83720 for (var box = 0; box < num; box++) {
83721 var p = geoVecInterp(a, b, box / num);
83722 var x0 = p[0] - boxsize - padding;
83723 var y0 = p[1] - boxsize - padding;
83724 var x1 = p[0] + boxsize + padding;
83725 var y1 = p[1] + boxsize + padding;
83727 minX: Math.min(x0, x1),
83728 minY: Math.min(y0, y1),
83729 maxX: Math.max(x0, x1),
83730 maxY: Math.max(y0, y1)
83735 if (tryInsert(bboxes, entity.id, false)) {
83738 'font-size': height + 2,
83739 lineString: lineString(sub),
83740 startOffset: offset + '%'
83745 function reverse(p) {
83746 var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
83747 return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI / 2 && angle > -Math.PI / 2);
83750 function lineString(points) {
83751 return 'M' + points.join('L');
83754 function subpath(points, from, to) {
83756 var start, end, i0, i1;
83758 for (var i = 0; i < points.length - 1; i++) {
83760 var b = points[i + 1];
83761 var current = geoVecLength(a, b);
83764 if (!start && sofar + current >= from) {
83765 portion = (from - sofar) / current;
83766 start = [a[0] + portion * (b[0] - a[0]), a[1] + portion * (b[1] - a[1])];
83770 if (!end && sofar + current >= to) {
83771 portion = (to - sofar) / current;
83772 end = [a[0] + portion * (b[0] - a[0]), a[1] + portion * (b[1] - a[1])];
83779 var result = points.slice(i0, i1);
83780 result.unshift(start);
83786 function getAreaLabel(entity, width, height) {
83787 var centroid = path.centroid(entity.asGeoJSON(graph));
83788 var extent = entity.extent(graph);
83789 var areaWidth = projection(extent[1])[0] - projection(extent[0])[0];
83790 if (isNaN(centroid[0]) || areaWidth < 20) return;
83791 var preset = _mainPresetIndex.match(entity, context.graph());
83792 var picon = preset && preset.icon;
83798 // icon and label..
83800 addLabel(iconSize + padding);
83810 function addIcon() {
83811 var iconX = centroid[0] - iconSize / 2;
83812 var iconY = centroid[1] - iconSize / 2;
83816 maxX: iconX + iconSize,
83817 maxY: iconY + iconSize
83820 if (tryInsert([bbox], entity.id + 'I', true)) {
83821 p.transform = 'translate(' + iconX + ',' + iconY + ')';
83828 function addLabel(yOffset) {
83829 if (width && areaWidth >= width + 20) {
83830 var labelX = centroid[0];
83831 var labelY = centroid[1] + yOffset;
83833 minX: labelX - width / 2 - padding,
83834 minY: labelY - height / 2 - padding,
83835 maxX: labelX + width / 2 + padding,
83836 maxY: labelY + height / 2 + padding
83839 if (tryInsert([bbox], entity.id, true)) {
83842 p.textAnchor = 'middle';
83850 } // force insert a singular bounding box
83851 // singular box only, no array, id better be unique
83854 function doInsert(bbox, id) {
83856 var oldbox = _entitybboxes[id];
83859 _rdrawn.remove(oldbox);
83862 _entitybboxes[id] = bbox;
83864 _rdrawn.insert(bbox);
83867 function tryInsert(bboxes, id, saveSkipped) {
83868 var skipped = false;
83870 for (var i = 0; i < bboxes.length; i++) {
83871 var bbox = bboxes[i];
83872 bbox.id = id; // Check that label is visible
83874 if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) {
83879 if (_rdrawn.collides(bbox)) {
83885 _entitybboxes[id] = bboxes;
83889 _rskipped.load(bboxes);
83892 _rdrawn.load(bboxes);
83898 var layer = selection.selectAll('.layer-osm.labels');
83899 layer.selectAll('.labels-group').data(['halo', 'label', 'debug']).enter().append('g').attr('class', function (d) {
83900 return 'labels-group ' + d;
83902 var halo = layer.selectAll('.labels-group.halo');
83903 var label = layer.selectAll('.labels-group.label');
83904 var debug = layer.selectAll('.labels-group.debug'); // points
83906 drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
83907 drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point); // lines
83909 drawLinePaths(layer, labelled.line, filter, '', positions.line);
83910 drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
83911 drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line); // areas
83913 drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
83914 drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
83915 drawAreaIcons(label, labelled.area, filter, 'areaicon', positions.area);
83916 drawAreaIcons(halo, labelled.area, filter, 'areaicon-halo', positions.area); // debug
83918 drawCollisionBoxes(debug, _rskipped, 'debug-skipped');
83919 drawCollisionBoxes(debug, _rdrawn, 'debug-drawn');
83920 layer.call(filterLabels);
83923 function filterLabels(selection) {
83924 var drawLayer = selection.selectAll('.layer-osm.labels');
83925 var layers = drawLayer.selectAll('.labels-group.halo, .labels-group.label');
83926 layers.selectAll('.nolabel').classed('nolabel', false);
83927 var mouse = context.map().mouse();
83928 var graph = context.graph();
83929 var selectedIDs = context.selectedIDs();
83931 var pad, bbox; // hide labels near the mouse
83936 minX: mouse[0] - pad,
83937 minY: mouse[1] - pad,
83938 maxX: mouse[0] + pad,
83939 maxY: mouse[1] + pad
83942 var nearMouse = _rdrawn.search(bbox).map(function (entity) {
83946 ids.push.apply(ids, nearMouse);
83947 } // hide labels on selected nodes (they look weird when dragging / haloed)
83950 for (var i = 0; i < selectedIDs.length; i++) {
83951 var entity = graph.hasEntity(selectedIDs[i]);
83953 if (entity && entity.type === 'node') {
83954 ids.push(selectedIDs[i]);
83958 layers.selectAll(utilEntitySelector(ids)).classed('nolabel', true); // draw the mouse bbox if debugging is on..
83960 var debug = selection.selectAll('.labels-group.debug');
83963 if (context.getDebug('collision')) {
83966 coordinates: [[[bbox.minX, bbox.minY], [bbox.maxX, bbox.minY], [bbox.maxX, bbox.maxY], [bbox.minX, bbox.maxY], [bbox.minX, bbox.minY]]]
83970 var box = debug.selectAll('.debug-mouse').data(gj); // exit
83972 box.exit().remove(); // enter/update
83974 box.enter().append('path').attr('class', 'debug debug-mouse yellow').merge(box).attr('d', d3_geoPath());
83977 var throttleFilterLabels = throttle(filterLabels, 100);
83979 drawLabels.observe = function (selection) {
83980 var listener = function listener() {
83981 throttleFilterLabels(selection);
83984 selection.on('mousemove.hidelabels', listener);
83985 context.on('enter.hidelabels', listener);
83988 drawLabels.off = function (selection) {
83989 throttleFilterLabels.cancel();
83990 selection.on('mousemove.hidelabels', null);
83991 context.on('enter.hidelabels', null);
83997 var _layerEnabled$1 = false;
84001 function svgImproveOSM(projection, context, dispatch) {
84002 var throttledRedraw = throttle(function () {
84003 return dispatch.call('change');
84007 var touchLayer = select(null);
84008 var drawLayer = select(null);
84009 var layerVisible = false;
84011 function markerPath(selection, klass) {
84012 selection.attr('class', klass).attr('transform', 'translate(-10, -28)').attr('points', '16,3 4,3 1,6 1,17 4,20 7,20 10,27 13,20 16,20 19,17.033 19,6');
84013 } // Loosely-coupled improveOSM service for fetching issues
84016 function getService() {
84017 if (services.improveOSM && !_qaService$1) {
84018 _qaService$1 = services.improveOSM;
84020 _qaService$1.on('loaded', throttledRedraw);
84021 } else if (!services.improveOSM && _qaService$1) {
84022 _qaService$1 = null;
84025 return _qaService$1;
84026 } // Show the markers
84029 function editOn() {
84030 if (!layerVisible) {
84031 layerVisible = true;
84032 drawLayer.style('display', 'block');
84034 } // Immediately remove the markers and their touch targets
84037 function editOff() {
84038 if (layerVisible) {
84039 layerVisible = false;
84040 drawLayer.style('display', 'none');
84041 drawLayer.selectAll('.qaItem.improveOSM').remove();
84042 touchLayer.selectAll('.qaItem.improveOSM').remove();
84044 } // Enable the layer. This shows the markers and transitions them to visible.
84047 function layerOn() {
84049 drawLayer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
84050 return dispatch.call('change');
84052 } // Disable the layer. This transitions the layer invisible and then hides the markers.
84055 function layerOff() {
84056 throttledRedraw.cancel();
84057 drawLayer.interrupt();
84058 touchLayer.selectAll('.qaItem.improveOSM').remove();
84059 drawLayer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
84061 dispatch.call('change');
84063 } // Update the issue markers
84066 function updateMarkers() {
84067 if (!layerVisible || !_layerEnabled$1) return;
84068 var service = getService();
84069 var selectedID = context.selectedErrorID();
84070 var data = service ? service.getItems(projection) : [];
84071 var getTransform = svgPointTransform(projection); // Draw markers..
84073 var markers = drawLayer.selectAll('.qaItem.improveOSM').data(data, function (d) {
84077 markers.exit().remove(); // enter
84079 var markersEnter = markers.enter().append('g').attr('class', function (d) {
84080 return "qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.itemType);
84082 markersEnter.append('polygon').call(markerPath, 'shadow');
84083 markersEnter.append('ellipse').attr('cx', 0).attr('cy', 0).attr('rx', 4.5).attr('ry', 2).attr('class', 'stroke');
84084 markersEnter.append('polygon').attr('fill', 'currentColor').call(markerPath, 'qaItem-fill');
84085 markersEnter.append('use').attr('transform', 'translate(-6.5, -23)').attr('class', 'icon-annotation').attr('width', '13px').attr('height', '13px').attr('xlink:href', function (d) {
84086 var picon = d.icon;
84091 var isMaki = /^maki-/.test(picon);
84092 return "#".concat(picon).concat(isMaki ? '-11' : '');
84096 markers.merge(markersEnter).sort(sortY).classed('selected', function (d) {
84097 return d.id === selectedID;
84098 }).attr('transform', getTransform); // Draw targets..
84100 if (touchLayer.empty()) return;
84101 var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
84102 var targets = touchLayer.selectAll('.qaItem.improveOSM').data(data, function (d) {
84106 targets.exit().remove(); // enter/update
84108 targets.enter().append('rect').attr('width', '20px').attr('height', '30px').attr('x', '-10px').attr('y', '-28px').merge(targets).sort(sortY).attr('class', function (d) {
84109 return "qaItem ".concat(d.service, " target ").concat(fillClass, " itemId-").concat(d.id);
84110 }).attr('transform', getTransform);
84112 function sortY(a, b) {
84113 return a.id === selectedID ? 1 : b.id === selectedID ? -1 : b.loc[1] - a.loc[1];
84115 } // Draw the ImproveOSM layer and schedule loading issues and updating markers.
84118 function drawImproveOSM(selection) {
84119 var service = getService();
84120 var surface = context.surface();
84122 if (surface && !surface.empty()) {
84123 touchLayer = surface.selectAll('.data-layer.touch .layer-touch.markers');
84126 drawLayer = selection.selectAll('.layer-improveOSM').data(service ? [0] : []);
84127 drawLayer.exit().remove();
84128 drawLayer = drawLayer.enter().append('g').attr('class', 'layer-improveOSM').style('display', _layerEnabled$1 ? 'block' : 'none').merge(drawLayer);
84130 if (_layerEnabled$1) {
84131 if (service && ~~context.map().zoom() >= minZoom) {
84133 service.loadIssues(projection);
84139 } // Toggles the layer on and off
84142 drawImproveOSM.enabled = function (val) {
84143 if (!arguments.length) return _layerEnabled$1;
84144 _layerEnabled$1 = val;
84146 if (_layerEnabled$1) {
84151 if (context.selectedErrorID()) {
84152 context.enter(modeBrowse(context));
84156 dispatch.call('change');
84160 drawImproveOSM.supported = function () {
84161 return !!getService();
84164 return drawImproveOSM;
84167 var _layerEnabled = false;
84171 function svgOsmose(projection, context, dispatch) {
84172 var throttledRedraw = throttle(function () {
84173 return dispatch.call('change');
84177 var touchLayer = select(null);
84178 var drawLayer = select(null);
84179 var layerVisible = false;
84181 function markerPath(selection, klass) {
84182 selection.attr('class', klass).attr('transform', 'translate(-10, -28)').attr('points', '16,3 4,3 1,6 1,17 4,20 7,20 10,27 13,20 16,20 19,17.033 19,6');
84183 } // Loosely-coupled osmose service for fetching issues
84186 function getService() {
84187 if (services.osmose && !_qaService) {
84188 _qaService = services.osmose;
84190 _qaService.on('loaded', throttledRedraw);
84191 } else if (!services.osmose && _qaService) {
84196 } // Show the markers
84199 function editOn() {
84200 if (!layerVisible) {
84201 layerVisible = true;
84202 drawLayer.style('display', 'block');
84204 } // Immediately remove the markers and their touch targets
84207 function editOff() {
84208 if (layerVisible) {
84209 layerVisible = false;
84210 drawLayer.style('display', 'none');
84211 drawLayer.selectAll('.qaItem.osmose').remove();
84212 touchLayer.selectAll('.qaItem.osmose').remove();
84214 } // Enable the layer. This shows the markers and transitions them to visible.
84217 function layerOn() {
84219 drawLayer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
84220 return dispatch.call('change');
84222 } // Disable the layer. This transitions the layer invisible and then hides the markers.
84225 function layerOff() {
84226 throttledRedraw.cancel();
84227 drawLayer.interrupt();
84228 touchLayer.selectAll('.qaItem.osmose').remove();
84229 drawLayer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
84231 dispatch.call('change');
84233 } // Update the issue markers
84236 function updateMarkers() {
84237 if (!layerVisible || !_layerEnabled) return;
84238 var service = getService();
84239 var selectedID = context.selectedErrorID();
84240 var data = service ? service.getItems(projection) : [];
84241 var getTransform = svgPointTransform(projection); // Draw markers..
84243 var markers = drawLayer.selectAll('.qaItem.osmose').data(data, function (d) {
84247 markers.exit().remove(); // enter
84249 var markersEnter = markers.enter().append('g').attr('class', function (d) {
84250 return "qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.itemType);
84252 markersEnter.append('polygon').call(markerPath, 'shadow');
84253 markersEnter.append('ellipse').attr('cx', 0).attr('cy', 0).attr('rx', 4.5).attr('ry', 2).attr('class', 'stroke');
84254 markersEnter.append('polygon').attr('fill', function (d) {
84255 return service.getColor(d.item);
84256 }).call(markerPath, 'qaItem-fill');
84257 markersEnter.append('use').attr('transform', 'translate(-6.5, -23)').attr('class', 'icon-annotation').attr('width', '13px').attr('height', '13px').attr('xlink:href', function (d) {
84258 var picon = d.icon;
84263 var isMaki = /^maki-/.test(picon);
84264 return "#".concat(picon).concat(isMaki ? '-11' : '');
84268 markers.merge(markersEnter).sort(sortY).classed('selected', function (d) {
84269 return d.id === selectedID;
84270 }).attr('transform', getTransform); // Draw targets..
84272 if (touchLayer.empty()) return;
84273 var fillClass = context.getDebug('target') ? 'pink' : 'nocolor';
84274 var targets = touchLayer.selectAll('.qaItem.osmose').data(data, function (d) {
84278 targets.exit().remove(); // enter/update
84280 targets.enter().append('rect').attr('width', '20px').attr('height', '30px').attr('x', '-10px').attr('y', '-28px').merge(targets).sort(sortY).attr('class', function (d) {
84281 return "qaItem ".concat(d.service, " target ").concat(fillClass, " itemId-").concat(d.id);
84282 }).attr('transform', getTransform);
84284 function sortY(a, b) {
84285 return a.id === selectedID ? 1 : b.id === selectedID ? -1 : b.loc[1] - a.loc[1];
84287 } // Draw the Osmose layer and schedule loading issues and updating markers.
84290 function drawOsmose(selection) {
84291 var service = getService();
84292 var surface = context.surface();
84294 if (surface && !surface.empty()) {
84295 touchLayer = surface.selectAll('.data-layer.touch .layer-touch.markers');
84298 drawLayer = selection.selectAll('.layer-osmose').data(service ? [0] : []);
84299 drawLayer.exit().remove();
84300 drawLayer = drawLayer.enter().append('g').attr('class', 'layer-osmose').style('display', _layerEnabled ? 'block' : 'none').merge(drawLayer);
84302 if (_layerEnabled) {
84303 if (service && ~~context.map().zoom() >= minZoom) {
84305 service.loadIssues(projection);
84311 } // Toggles the layer on and off
84314 drawOsmose.enabled = function (val) {
84315 if (!arguments.length) return _layerEnabled;
84316 _layerEnabled = val;
84318 if (_layerEnabled) {
84319 // Strings supplied by Osmose fetched before showing layer for first time
84320 // NOTE: Currently no way to change locale in iD at runtime, would need to re-call this method if that's ever implemented
84321 // Also, If layer is toggled quickly multiple requests are sent
84322 getService().loadStrings().then(layerOn)["catch"](function (err) {
84323 console.log(err); // eslint-disable-line no-console
84328 if (context.selectedErrorID()) {
84329 context.enter(modeBrowse(context));
84333 dispatch.call('change');
84337 drawOsmose.supported = function () {
84338 return !!getService();
84344 function svgStreetside(projection, context, dispatch) {
84345 var throttledRedraw = throttle(function () {
84346 dispatch.call('change');
84350 var minMarkerZoom = 16;
84351 var minViewfieldZoom = 18;
84352 var layer = select(null);
84353 var _viewerYaw = 0;
84354 var _selectedSequence = null;
84363 if (svgStreetside.initialized) return; // run once
84365 svgStreetside.enabled = false;
84366 svgStreetside.initialized = true;
84373 function getService() {
84374 if (services.streetside && !_streetside) {
84375 _streetside = services.streetside;
84377 _streetside.event.on('viewerChanged.svgStreetside', viewerChanged).on('loadedImages.svgStreetside', throttledRedraw);
84378 } else if (!services.streetside && _streetside) {
84379 _streetside = null;
84382 return _streetside;
84389 function showLayer() {
84390 var service = getService();
84391 if (!service) return;
84393 layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () {
84394 dispatch.call('change');
84402 function hideLayer() {
84403 throttledRedraw.cancel();
84404 layer.transition().duration(250).style('opacity', 0).on('end', editOff);
84411 function editOn() {
84412 layer.style('display', 'block');
84419 function editOff() {
84420 layer.selectAll('.viewfield-group').remove();
84421 layer.style('display', 'none');
84424 * click() Handles 'bubble' point click event.
84428 function click(d3_event, d) {
84429 var service = getService();
84430 if (!service) return; // try to preserve the viewer rotation when staying on the same sequence
84432 if (d.sequenceKey !== _selectedSequence) {
84433 _viewerYaw = 0; // reset
84436 _selectedSequence = d.sequenceKey;
84437 service.ensureViewerLoaded(context).then(function () {
84438 service.selectImage(context, d.key).yaw(_viewerYaw).showViewer(context);
84440 context.map().centerEase(d.loc);
84447 function mouseover(d3_event, d) {
84448 var service = getService();
84449 if (service) service.setStyles(context, d);
84456 function mouseout() {
84457 var service = getService();
84458 if (service) service.setStyles(context, null);
84465 function transform(d) {
84466 var t = svgPointTransform(projection)(d);
84467 var rot = d.ca + _viewerYaw;
84470 t += ' rotate(' + Math.floor(rot) + ',0,0)';
84476 function viewerChanged() {
84477 var service = getService();
84478 if (!service) return;
84479 var viewer = service.viewer();
84480 if (!viewer) return; // update viewfield rotation
84482 _viewerYaw = viewer.getYaw(); // avoid updating if the map is currently transformed
84483 // e.g. during drags or easing.
84485 if (context.map().isTransformed()) return;
84486 layer.selectAll('.viewfield-group.currentView').attr('transform', transform);
84489 function filterBubbles(bubbles) {
84490 var fromDate = context.photos().fromDate();
84491 var toDate = context.photos().toDate();
84492 var usernames = context.photos().usernames();
84495 var fromTimestamp = new Date(fromDate).getTime();
84496 bubbles = bubbles.filter(function (bubble) {
84497 return new Date(bubble.captured_at).getTime() >= fromTimestamp;
84502 var toTimestamp = new Date(toDate).getTime();
84503 bubbles = bubbles.filter(function (bubble) {
84504 return new Date(bubble.captured_at).getTime() <= toTimestamp;
84509 bubbles = bubbles.filter(function (bubble) {
84510 return usernames.indexOf(bubble.captured_by) !== -1;
84517 function filterSequences(sequences) {
84518 var fromDate = context.photos().fromDate();
84519 var toDate = context.photos().toDate();
84520 var usernames = context.photos().usernames();
84523 var fromTimestamp = new Date(fromDate).getTime();
84524 sequences = sequences.filter(function (sequences) {
84525 return new Date(sequences.properties.captured_at).getTime() >= fromTimestamp;
84530 var toTimestamp = new Date(toDate).getTime();
84531 sequences = sequences.filter(function (sequences) {
84532 return new Date(sequences.properties.captured_at).getTime() <= toTimestamp;
84537 sequences = sequences.filter(function (sequences) {
84538 return usernames.indexOf(sequences.properties.captured_by) !== -1;
84549 function update() {
84550 var viewer = context.container().select('.photoviewer');
84551 var selected = viewer.empty() ? undefined : viewer.datum();
84552 var z = ~~context.map().zoom();
84553 var showMarkers = z >= minMarkerZoom;
84554 var showViewfields = z >= minViewfieldZoom;
84555 var service = getService();
84556 var sequences = [];
84559 if (context.photos().showsPanoramic()) {
84560 sequences = service ? service.sequences(projection) : [];
84561 bubbles = service && showMarkers ? service.bubbles(projection) : [];
84562 sequences = filterSequences(sequences);
84563 bubbles = filterBubbles(bubbles);
84566 var traces = layer.selectAll('.sequences').selectAll('.sequence').data(sequences, function (d) {
84567 return d.properties.key;
84570 traces.exit().remove(); // enter/update
84572 traces = traces.enter().append('path').attr('class', 'sequence').merge(traces).attr('d', svgPath(projection).geojson);
84573 var groups = layer.selectAll('.markers').selectAll('.viewfield-group').data(bubbles, function (d) {
84574 // force reenter once bubbles are attached to a sequence
84575 return d.key + (d.sequenceKey ? 'v1' : 'v0');
84578 groups.exit().remove(); // enter
84580 var groupsEnter = groups.enter().append('g').attr('class', 'viewfield-group').on('mouseenter', mouseover).on('mouseleave', mouseout).on('click', click);
84581 groupsEnter.append('g').attr('class', 'viewfield-scale'); // update
84583 var markers = groups.merge(groupsEnter).sort(function (a, b) {
84584 return a === selected ? 1 : b === selected ? -1 : b.loc[1] - a.loc[1];
84585 }).attr('transform', transform).select('.viewfield-scale');
84586 markers.selectAll('circle').data([0]).enter().append('circle').attr('dx', '0').attr('dy', '0').attr('r', '6');
84587 var viewfields = markers.selectAll('.viewfield').data(showViewfields ? [0] : []);
84588 viewfields.exit().remove(); // viewfields may or may not be drawn...
84589 // but if they are, draw below the circles
84591 viewfields.enter().insert('path', 'circle').attr('class', 'viewfield').attr('transform', 'scale(1.5,1.5),translate(-8, -13)').attr('d', viewfieldPath);
84593 function viewfieldPath() {
84594 var d = this.parentNode.__data__;
84597 return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
84599 return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
84605 * drawImages is the method that is returned (and that runs) every time 'svgStreetside()' is called.
84606 * 'svgStreetside()' is called from index.js
84610 function drawImages(selection) {
84611 var enabled = svgStreetside.enabled;
84612 var service = getService();
84613 layer = selection.selectAll('.layer-streetside-images').data(service ? [0] : []);
84614 layer.exit().remove();
84615 var layerEnter = layer.enter().append('g').attr('class', 'layer-streetside-images').style('display', enabled ? 'block' : 'none');
84616 layerEnter.append('g').attr('class', 'sequences');
84617 layerEnter.append('g').attr('class', 'markers');
84618 layer = layerEnter.merge(layer);
84621 if (service && ~~context.map().zoom() >= minZoom) {
84624 service.loadBubbles(projection);
84631 * drawImages.enabled().
84635 drawImages.enabled = function (_) {
84636 if (!arguments.length) return svgStreetside.enabled;
84637 svgStreetside.enabled = _;
84639 if (svgStreetside.enabled) {
84641 context.photos().on('change.streetside', update);
84644 context.photos().on('change.streetside', null);
84647 dispatch.call('change');
84651 * drawImages.supported().
84655 drawImages.supported = function () {
84656 return !!getService();
84663 function svgMapillaryImages(projection, context, dispatch) {
84664 var throttledRedraw = throttle(function () {
84665 dispatch.call('change');
84669 var minMarkerZoom = 16;
84670 var minViewfieldZoom = 18;
84671 var layer = select(null);
84676 if (svgMapillaryImages.initialized) return; // run once
84678 svgMapillaryImages.enabled = false;
84679 svgMapillaryImages.initialized = true;
84682 function getService() {
84683 if (services.mapillary && !_mapillary) {
84684 _mapillary = services.mapillary;
84686 _mapillary.event.on('loadedImages', throttledRedraw);
84687 } else if (!services.mapillary && _mapillary) {
84694 function showLayer() {
84695 var service = getService();
84696 if (!service) return;
84698 layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () {
84699 dispatch.call('change');
84703 function hideLayer() {
84704 throttledRedraw.cancel();
84705 layer.transition().duration(250).style('opacity', 0).on('end', editOff);
84708 function editOn() {
84709 layer.style('display', 'block');
84712 function editOff() {
84713 layer.selectAll('.viewfield-group').remove();
84714 layer.style('display', 'none');
84717 function click(d3_event, image) {
84718 var service = getService();
84719 if (!service) return;
84720 service.ensureViewerLoaded(context).then(function () {
84721 service.selectImage(context, image.id).showViewer(context);
84723 context.map().centerEase(image.loc);
84726 function mouseover(d3_event, image) {
84727 var service = getService();
84728 if (service) service.setStyles(context, image);
84731 function mouseout() {
84732 var service = getService();
84733 if (service) service.setStyles(context, null);
84736 function transform(d) {
84737 var t = svgPointTransform(projection)(d);
84740 t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
84746 function filterImages(images) {
84747 var showsPano = context.photos().showsPanoramic();
84748 var showsFlat = context.photos().showsFlat();
84749 var fromDate = context.photos().fromDate();
84750 var toDate = context.photos().toDate();
84752 if (!showsPano || !showsFlat) {
84753 images = images.filter(function (image) {
84754 if (image.is_pano) return showsPano;
84760 images = images.filter(function (image) {
84761 return new Date(image.captured_at).getTime() >= new Date(fromDate).getTime();
84766 images = images.filter(function (image) {
84767 return new Date(image.captured_at).getTime() <= new Date(toDate).getTime();
84774 function filterSequences(sequences) {
84775 var showsPano = context.photos().showsPanoramic();
84776 var showsFlat = context.photos().showsFlat();
84777 var fromDate = context.photos().fromDate();
84778 var toDate = context.photos().toDate();
84780 if (!showsPano || !showsFlat) {
84781 sequences = sequences.filter(function (sequence) {
84782 if (sequence.properties.hasOwnProperty('is_pano')) {
84783 if (sequence.properties.is_pano) return showsPano;
84792 sequences = sequences.filter(function (sequence) {
84793 return new Date(sequence.properties.captured_at).getTime() >= new Date(fromDate).getTime().toString();
84798 sequences = sequences.filter(function (sequence) {
84799 return new Date(sequence.properties.captured_at).getTime() <= new Date(toDate).getTime().toString();
84806 function update() {
84807 var z = ~~context.map().zoom();
84808 var showMarkers = z >= minMarkerZoom;
84809 var showViewfields = z >= minViewfieldZoom;
84810 var service = getService();
84811 var sequences = service ? service.sequences(projection) : [];
84812 var images = service && showMarkers ? service.images(projection) : [];
84813 images = filterImages(images);
84814 sequences = filterSequences(sequences);
84815 service.filterViewer(context);
84816 var traces = layer.selectAll('.sequences').selectAll('.sequence').data(sequences, function (d) {
84817 return d.properties.id;
84820 traces.exit().remove(); // enter/update
84822 traces = traces.enter().append('path').attr('class', 'sequence').merge(traces).attr('d', svgPath(projection).geojson);
84823 var groups = layer.selectAll('.markers').selectAll('.viewfield-group').data(images, function (d) {
84827 groups.exit().remove(); // enter
84829 var groupsEnter = groups.enter().append('g').attr('class', 'viewfield-group').on('mouseenter', mouseover).on('mouseleave', mouseout).on('click', click);
84830 groupsEnter.append('g').attr('class', 'viewfield-scale'); // update
84832 var markers = groups.merge(groupsEnter).sort(function (a, b) {
84833 return b.loc[1] - a.loc[1]; // sort Y
84834 }).attr('transform', transform).select('.viewfield-scale');
84835 markers.selectAll('circle').data([0]).enter().append('circle').attr('dx', '0').attr('dy', '0').attr('r', '6');
84836 var viewfields = markers.selectAll('.viewfield').data(showViewfields ? [0] : []);
84837 viewfields.exit().remove();
84838 viewfields.enter() // viewfields may or may not be drawn...
84839 .insert('path', 'circle') // but if they are, draw below the circles
84840 .attr('class', 'viewfield').classed('pano', function () {
84841 return this.parentNode.__data__.is_pano;
84842 }).attr('transform', 'scale(1.5,1.5),translate(-8, -13)').attr('d', viewfieldPath);
84844 function viewfieldPath() {
84845 if (this.parentNode.__data__.is_pano) {
84846 return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
84848 return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
84853 function drawImages(selection) {
84854 var enabled = svgMapillaryImages.enabled;
84855 var service = getService();
84856 layer = selection.selectAll('.layer-mapillary').data(service ? [0] : []);
84857 layer.exit().remove();
84858 var layerEnter = layer.enter().append('g').attr('class', 'layer-mapillary').style('display', enabled ? 'block' : 'none');
84859 layerEnter.append('g').attr('class', 'sequences');
84860 layerEnter.append('g').attr('class', 'markers');
84861 layer = layerEnter.merge(layer);
84864 if (service && ~~context.map().zoom() >= minZoom) {
84867 service.loadImages(projection);
84874 drawImages.enabled = function (_) {
84875 if (!arguments.length) return svgMapillaryImages.enabled;
84876 svgMapillaryImages.enabled = _;
84878 if (svgMapillaryImages.enabled) {
84880 context.photos().on('change.mapillary_images', update);
84883 context.photos().on('change.mapillary_images', null);
84886 dispatch.call('change');
84890 drawImages.supported = function () {
84891 return !!getService();
84898 function svgMapillaryPosition(projection, context) {
84899 var throttledRedraw = throttle(function () {
84904 var minViewfieldZoom = 18;
84905 var layer = select(null);
84909 var viewerCompassAngle;
84912 if (svgMapillaryPosition.initialized) return; // run once
84914 svgMapillaryPosition.initialized = true;
84917 function getService() {
84918 if (services.mapillary && !_mapillary) {
84919 _mapillary = services.mapillary;
84921 _mapillary.event.on('imageChanged', throttledRedraw);
84923 _mapillary.event.on('bearingChanged', function (e) {
84924 viewerCompassAngle = e.bearing;
84925 if (context.map().isTransformed()) return;
84926 layer.selectAll('.viewfield-group.currentView').filter(function (d) {
84928 }).attr('transform', transform);
84930 } else if (!services.mapillary && _mapillary) {
84937 function editOn() {
84938 layer.style('display', 'block');
84941 function editOff() {
84942 layer.selectAll('.viewfield-group').remove();
84943 layer.style('display', 'none');
84946 function transform(d) {
84947 var t = svgPointTransform(projection)(d);
84949 if (d.is_pano && viewerCompassAngle !== null && isFinite(viewerCompassAngle)) {
84950 t += ' rotate(' + Math.floor(viewerCompassAngle) + ',0,0)';
84952 t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
84958 function update() {
84959 var z = ~~context.map().zoom();
84960 var showViewfields = z >= minViewfieldZoom;
84961 var service = getService();
84962 var image = service && service.getActiveImage();
84963 var groups = layer.selectAll('.markers').selectAll('.viewfield-group').data(image ? [image] : [], function (d) {
84967 groups.exit().remove(); // enter
84969 var groupsEnter = groups.enter().append('g').attr('class', 'viewfield-group currentView highlighted');
84970 groupsEnter.append('g').attr('class', 'viewfield-scale'); // update
84972 var markers = groups.merge(groupsEnter).attr('transform', transform).select('.viewfield-scale');
84973 markers.selectAll('circle').data([0]).enter().append('circle').attr('dx', '0').attr('dy', '0').attr('r', '6');
84974 var viewfields = markers.selectAll('.viewfield').data(showViewfields ? [0] : []);
84975 viewfields.exit().remove();
84976 viewfields.enter().insert('path', 'circle').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');
84979 function drawImages(selection) {
84980 var service = getService();
84981 layer = selection.selectAll('.layer-mapillary-position').data(service ? [0] : []);
84982 layer.exit().remove();
84983 var layerEnter = layer.enter().append('g').attr('class', 'layer-mapillary-position');
84984 layerEnter.append('g').attr('class', 'markers');
84985 layer = layerEnter.merge(layer);
84987 if (service && ~~context.map().zoom() >= minZoom) {
84995 drawImages.enabled = function () {
85000 drawImages.supported = function () {
85001 return !!getService();
85008 function svgMapillarySigns(projection, context, dispatch) {
85009 var throttledRedraw = throttle(function () {
85010 dispatch.call('change');
85014 var layer = select(null);
85019 if (svgMapillarySigns.initialized) return; // run once
85021 svgMapillarySigns.enabled = false;
85022 svgMapillarySigns.initialized = true;
85025 function getService() {
85026 if (services.mapillary && !_mapillary) {
85027 _mapillary = services.mapillary;
85029 _mapillary.event.on('loadedSigns', throttledRedraw);
85030 } else if (!services.mapillary && _mapillary) {
85037 function showLayer() {
85038 var service = getService();
85039 if (!service) return;
85040 service.loadSignResources(context);
85044 function hideLayer() {
85045 throttledRedraw.cancel();
85049 function editOn() {
85050 layer.style('display', 'block');
85053 function editOff() {
85054 layer.selectAll('.icon-sign').remove();
85055 layer.style('display', 'none');
85058 function click(d3_event, d) {
85059 var service = getService();
85060 if (!service) return;
85061 context.map().centerEase(d.loc);
85062 var selectedImageId = service.getActiveImage() && service.getActiveImage().id;
85063 service.getDetections(d.id).then(function (detections) {
85064 if (detections.length) {
85065 var imageId = detections[0].image.id;
85067 if (imageId === selectedImageId) {
85068 service.highlightDetection(detections[0]).selectImage(context, imageId);
85070 service.ensureViewerLoaded(context).then(function () {
85071 service.highlightDetection(detections[0]).selectImage(context, imageId).showViewer(context);
85078 function filterData(detectedFeatures) {
85079 var fromDate = context.photos().fromDate();
85080 var toDate = context.photos().toDate();
85083 var fromTimestamp = new Date(fromDate).getTime();
85084 detectedFeatures = detectedFeatures.filter(function (feature) {
85085 return new Date(feature.last_seen_at).getTime() >= fromTimestamp;
85090 var toTimestamp = new Date(toDate).getTime();
85091 detectedFeatures = detectedFeatures.filter(function (feature) {
85092 return new Date(feature.first_seen_at).getTime() <= toTimestamp;
85096 return detectedFeatures;
85099 function update() {
85100 var service = getService();
85101 var data = service ? service.signs(projection) : [];
85102 data = filterData(data);
85103 var transform = svgPointTransform(projection);
85104 var signs = layer.selectAll('.icon-sign').data(data, function (d) {
85108 signs.exit().remove(); // enter
85110 var enter = signs.enter().append('g').attr('class', 'icon-sign icon-detected').on('click', click);
85111 enter.append('use').attr('width', '24px').attr('height', '24px').attr('x', '-12px').attr('y', '-12px').attr('xlink:href', function (d) {
85112 return '#' + d.value;
85114 enter.append('rect').attr('width', '24px').attr('height', '24px').attr('x', '-12px').attr('y', '-12px'); // update
85116 signs.merge(enter).attr('transform', transform);
85119 function drawSigns(selection) {
85120 var enabled = svgMapillarySigns.enabled;
85121 var service = getService();
85122 layer = selection.selectAll('.layer-mapillary-signs').data(service ? [0] : []);
85123 layer.exit().remove();
85124 layer = layer.enter().append('g').attr('class', 'layer-mapillary-signs layer-mapillary-detections').style('display', enabled ? 'block' : 'none').merge(layer);
85127 if (service && ~~context.map().zoom() >= minZoom) {
85130 service.loadSigns(projection);
85131 service.showSignDetections(true);
85135 } else if (service) {
85136 service.showSignDetections(false);
85140 drawSigns.enabled = function (_) {
85141 if (!arguments.length) return svgMapillarySigns.enabled;
85142 svgMapillarySigns.enabled = _;
85144 if (svgMapillarySigns.enabled) {
85146 context.photos().on('change.mapillary_signs', update);
85149 context.photos().on('change.mapillary_signs', null);
85152 dispatch.call('change');
85156 drawSigns.supported = function () {
85157 return !!getService();
85164 function svgMapillaryMapFeatures(projection, context, dispatch) {
85165 var throttledRedraw = throttle(function () {
85166 dispatch.call('change');
85170 var layer = select(null);
85175 if (svgMapillaryMapFeatures.initialized) return; // run once
85177 svgMapillaryMapFeatures.enabled = false;
85178 svgMapillaryMapFeatures.initialized = true;
85181 function getService() {
85182 if (services.mapillary && !_mapillary) {
85183 _mapillary = services.mapillary;
85185 _mapillary.event.on('loadedMapFeatures', throttledRedraw);
85186 } else if (!services.mapillary && _mapillary) {
85193 function showLayer() {
85194 var service = getService();
85195 if (!service) return;
85196 service.loadObjectResources(context);
85200 function hideLayer() {
85201 throttledRedraw.cancel();
85205 function editOn() {
85206 layer.style('display', 'block');
85209 function editOff() {
85210 layer.selectAll('.icon-map-feature').remove();
85211 layer.style('display', 'none');
85214 function click(d3_event, d) {
85215 var service = getService();
85216 if (!service) return;
85217 context.map().centerEase(d.loc);
85218 var selectedImageId = service.getActiveImage() && service.getActiveImage().id;
85219 service.getDetections(d.id).then(function (detections) {
85220 if (detections.length) {
85221 var imageId = detections[0].image.id;
85223 if (imageId === selectedImageId) {
85224 service.highlightDetection(detections[0]).selectImage(context, imageId);
85226 service.ensureViewerLoaded(context).then(function () {
85227 service.highlightDetection(detections[0]).selectImage(context, imageId).showViewer(context);
85234 function filterData(detectedFeatures) {
85235 var fromDate = context.photos().fromDate();
85236 var toDate = context.photos().toDate();
85239 detectedFeatures = detectedFeatures.filter(function (feature) {
85240 return new Date(feature.last_seen_at).getTime() >= new Date(fromDate).getTime();
85245 detectedFeatures = detectedFeatures.filter(function (feature) {
85246 return new Date(feature.first_seen_at).getTime() <= new Date(toDate).getTime();
85250 return detectedFeatures;
85253 function update() {
85254 var service = getService();
85255 var data = service ? service.mapFeatures(projection) : [];
85256 data = filterData(data);
85257 var transform = svgPointTransform(projection);
85258 var mapFeatures = layer.selectAll('.icon-map-feature').data(data, function (d) {
85262 mapFeatures.exit().remove(); // enter
85264 var enter = mapFeatures.enter().append('g').attr('class', 'icon-map-feature icon-detected').on('click', click);
85265 enter.append('title').text(function (d) {
85266 var id = d.value.replace(/--/g, '.').replace(/-/g, '_');
85267 return _t('mapillary_map_features.' + id);
85269 enter.append('use').attr('width', '24px').attr('height', '24px').attr('x', '-12px').attr('y', '-12px').attr('xlink:href', function (d) {
85270 if (d.value === 'object--billboard') {
85271 // no billboard icon right now, so use the advertisement icon
85272 return '#object--sign--advertisement';
85275 return '#' + d.value;
85277 enter.append('rect').attr('width', '24px').attr('height', '24px').attr('x', '-12px').attr('y', '-12px'); // update
85279 mapFeatures.merge(enter).attr('transform', transform);
85282 function drawMapFeatures(selection) {
85283 var enabled = svgMapillaryMapFeatures.enabled;
85284 var service = getService();
85285 layer = selection.selectAll('.layer-mapillary-map-features').data(service ? [0] : []);
85286 layer.exit().remove();
85287 layer = layer.enter().append('g').attr('class', 'layer-mapillary-map-features layer-mapillary-detections').style('display', enabled ? 'block' : 'none').merge(layer);
85290 if (service && ~~context.map().zoom() >= minZoom) {
85293 service.loadMapFeatures(projection);
85294 service.showFeatureDetections(true);
85298 } else if (service) {
85299 service.showFeatureDetections(false);
85303 drawMapFeatures.enabled = function (_) {
85304 if (!arguments.length) return svgMapillaryMapFeatures.enabled;
85305 svgMapillaryMapFeatures.enabled = _;
85307 if (svgMapillaryMapFeatures.enabled) {
85309 context.photos().on('change.mapillary_map_features', update);
85312 context.photos().on('change.mapillary_map_features', null);
85315 dispatch.call('change');
85319 drawMapFeatures.supported = function () {
85320 return !!getService();
85324 return drawMapFeatures;
85327 function svgKartaviewImages(projection, context, dispatch) {
85328 var throttledRedraw = throttle(function () {
85329 dispatch.call('change');
85333 var minMarkerZoom = 16;
85334 var minViewfieldZoom = 18;
85335 var layer = select(null);
85340 if (svgKartaviewImages.initialized) return; // run once
85342 svgKartaviewImages.enabled = false;
85343 svgKartaviewImages.initialized = true;
85346 function getService() {
85347 if (services.kartaview && !_kartaview) {
85348 _kartaview = services.kartaview;
85350 _kartaview.event.on('loadedImages', throttledRedraw);
85351 } else if (!services.kartaview && _kartaview) {
85358 function showLayer() {
85359 var service = getService();
85360 if (!service) return;
85362 layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () {
85363 dispatch.call('change');
85367 function hideLayer() {
85368 throttledRedraw.cancel();
85369 layer.transition().duration(250).style('opacity', 0).on('end', editOff);
85372 function editOn() {
85373 layer.style('display', 'block');
85376 function editOff() {
85377 layer.selectAll('.viewfield-group').remove();
85378 layer.style('display', 'none');
85381 function click(d3_event, d) {
85382 var service = getService();
85383 if (!service) return;
85384 service.ensureViewerLoaded(context).then(function () {
85385 service.selectImage(context, d.key).showViewer(context);
85387 context.map().centerEase(d.loc);
85390 function mouseover(d3_event, d) {
85391 var service = getService();
85392 if (service) service.setStyles(context, d);
85395 function mouseout() {
85396 var service = getService();
85397 if (service) service.setStyles(context, null);
85400 function transform(d) {
85401 var t = svgPointTransform(projection)(d);
85404 t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
85410 function filterImages(images) {
85411 var fromDate = context.photos().fromDate();
85412 var toDate = context.photos().toDate();
85413 var usernames = context.photos().usernames();
85416 var fromTimestamp = new Date(fromDate).getTime();
85417 images = images.filter(function (item) {
85418 return new Date(item.captured_at).getTime() >= fromTimestamp;
85423 var toTimestamp = new Date(toDate).getTime();
85424 images = images.filter(function (item) {
85425 return new Date(item.captured_at).getTime() <= toTimestamp;
85430 images = images.filter(function (item) {
85431 return usernames.indexOf(item.captured_by) !== -1;
85438 function filterSequences(sequences) {
85439 var fromDate = context.photos().fromDate();
85440 var toDate = context.photos().toDate();
85441 var usernames = context.photos().usernames();
85444 var fromTimestamp = new Date(fromDate).getTime();
85445 sequences = sequences.filter(function (image) {
85446 return new Date(image.properties.captured_at).getTime() >= fromTimestamp;
85451 var toTimestamp = new Date(toDate).getTime();
85452 sequences = sequences.filter(function (image) {
85453 return new Date(image.properties.captured_at).getTime() <= toTimestamp;
85458 sequences = sequences.filter(function (image) {
85459 return usernames.indexOf(image.properties.captured_by) !== -1;
85466 function update() {
85467 var viewer = context.container().select('.photoviewer');
85468 var selected = viewer.empty() ? undefined : viewer.datum();
85469 var z = ~~context.map().zoom();
85470 var showMarkers = z >= minMarkerZoom;
85471 var showViewfields = z >= minViewfieldZoom;
85472 var service = getService();
85473 var sequences = [];
85476 if (context.photos().showsFlat()) {
85477 sequences = service ? service.sequences(projection) : [];
85478 images = service && showMarkers ? service.images(projection) : [];
85479 sequences = filterSequences(sequences);
85480 images = filterImages(images);
85483 var traces = layer.selectAll('.sequences').selectAll('.sequence').data(sequences, function (d) {
85484 return d.properties.key;
85487 traces.exit().remove(); // enter/update
85489 traces = traces.enter().append('path').attr('class', 'sequence').merge(traces).attr('d', svgPath(projection).geojson);
85490 var groups = layer.selectAll('.markers').selectAll('.viewfield-group').data(images, function (d) {
85494 groups.exit().remove(); // enter
85496 var groupsEnter = groups.enter().append('g').attr('class', 'viewfield-group').on('mouseenter', mouseover).on('mouseleave', mouseout).on('click', click);
85497 groupsEnter.append('g').attr('class', 'viewfield-scale'); // update
85499 var markers = groups.merge(groupsEnter).sort(function (a, b) {
85500 return a === selected ? 1 : b === selected ? -1 : b.loc[1] - a.loc[1]; // sort Y
85501 }).attr('transform', transform).select('.viewfield-scale');
85502 markers.selectAll('circle').data([0]).enter().append('circle').attr('dx', '0').attr('dy', '0').attr('r', '6');
85503 var viewfields = markers.selectAll('.viewfield').data(showViewfields ? [0] : []);
85504 viewfields.exit().remove();
85505 viewfields.enter() // viewfields may or may not be drawn...
85506 .insert('path', 'circle') // but if they are, draw below the circles
85507 .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');
85510 function drawImages(selection) {
85511 var enabled = svgKartaviewImages.enabled,
85512 service = getService();
85513 layer = selection.selectAll('.layer-kartaview').data(service ? [0] : []);
85514 layer.exit().remove();
85515 var layerEnter = layer.enter().append('g').attr('class', 'layer-kartaview').style('display', enabled ? 'block' : 'none');
85516 layerEnter.append('g').attr('class', 'sequences');
85517 layerEnter.append('g').attr('class', 'markers');
85518 layer = layerEnter.merge(layer);
85521 if (service && ~~context.map().zoom() >= minZoom) {
85524 service.loadImages(projection);
85531 drawImages.enabled = function (_) {
85532 if (!arguments.length) return svgKartaviewImages.enabled;
85533 svgKartaviewImages.enabled = _;
85535 if (svgKartaviewImages.enabled) {
85537 context.photos().on('change.kartaview_images', update);
85540 context.photos().on('change.kartaview_images', null);
85543 dispatch.call('change');
85547 drawImages.supported = function () {
85548 return !!getService();
85555 function svgOsm(projection, context, dispatch) {
85556 var enabled = true;
85558 function drawOsm(selection) {
85559 selection.selectAll('.layer-osm').data(['covered', 'areas', 'lines', 'points', 'labels']).enter().append('g').attr('class', function (d) {
85560 return 'layer-osm ' + d;
85562 selection.selectAll('.layer-osm.points').selectAll('.points-group').data(['points', 'midpoints', 'vertices', 'turns']).enter().append('g').attr('class', function (d) {
85563 return 'points-group ' + d;
85567 function showLayer() {
85568 var layer = context.surface().selectAll('.data-layer.osm');
85570 layer.classed('disabled', false).style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
85571 dispatch.call('change');
85575 function hideLayer() {
85576 var layer = context.surface().selectAll('.data-layer.osm');
85578 layer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
85579 layer.classed('disabled', true);
85580 dispatch.call('change');
85584 drawOsm.enabled = function (val) {
85585 if (!arguments.length) return enabled;
85594 dispatch.call('change');
85601 var _notesEnabled = false;
85605 function svgNotes(projection, context, dispatch) {
85607 dispatch = dispatch$8('change');
85610 var throttledRedraw = throttle(function () {
85611 dispatch.call('change');
85615 var touchLayer = select(null);
85616 var drawLayer = select(null);
85617 var _notesVisible = false;
85619 function markerPath(selection, klass) {
85620 selection.attr('class', klass).attr('transform', 'translate(-8, -22)').attr('d', 'm17.5,0l-15,0c-1.37,0 -2.5,1.12 -2.5,2.5l0,11.25c0,1.37 1.12,2.5 2.5,2.5l3.75,0l0,3.28c0,0.38 0.43,0.6 0.75,0.37l4.87,-3.65l5.62,0c1.37,0 2.5,-1.12 2.5,-2.5l0,-11.25c0,-1.37 -1.12,-2.5 -2.5,-2.5z');
85621 } // Loosely-coupled osm service for fetching notes.
85624 function getService() {
85625 if (services.osm && !_osmService) {
85626 _osmService = services.osm;
85628 _osmService.on('loadedNotes', throttledRedraw);
85629 } else if (!services.osm && _osmService) {
85630 _osmService = null;
85633 return _osmService;
85634 } // Show the notes
85637 function editOn() {
85638 if (!_notesVisible) {
85639 _notesVisible = true;
85640 drawLayer.style('display', 'block');
85642 } // Immediately remove the notes and their touch targets
85645 function editOff() {
85646 if (_notesVisible) {
85647 _notesVisible = false;
85648 drawLayer.style('display', 'none');
85649 drawLayer.selectAll('.note').remove();
85650 touchLayer.selectAll('.note').remove();
85652 } // Enable the layer. This shows the notes and transitions them to visible.
85655 function layerOn() {
85657 drawLayer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
85658 dispatch.call('change');
85660 } // Disable the layer. This transitions the layer invisible and then hides the notes.
85663 function layerOff() {
85664 throttledRedraw.cancel();
85665 drawLayer.interrupt();
85666 touchLayer.selectAll('.note').remove();
85667 drawLayer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
85669 dispatch.call('change');
85671 } // Update the note markers
85674 function updateMarkers() {
85675 if (!_notesVisible || !_notesEnabled) return;
85676 var service = getService();
85677 var selectedID = context.selectedNoteID();
85678 var data = service ? service.notes(projection) : [];
85679 var getTransform = svgPointTransform(projection); // Draw markers..
85681 var notes = drawLayer.selectAll('.note').data(data, function (d) {
85682 return d.status + d.id;
85685 notes.exit().remove(); // enter
85687 var notesEnter = notes.enter().append('g').attr('class', function (d) {
85688 return 'note note-' + d.id + ' ' + d.status;
85689 }).classed('new', function (d) {
85692 notesEnter.append('ellipse').attr('cx', 0.5).attr('cy', 1).attr('rx', 6.5).attr('ry', 3).attr('class', 'stroke');
85693 notesEnter.append('path').call(markerPath, 'shadow');
85694 notesEnter.append('use').attr('class', 'note-fill').attr('width', '20px').attr('height', '20px').attr('x', '-8px').attr('y', '-22px').attr('xlink:href', '#iD-icon-note');
85695 notesEnter.selectAll('.icon-annotation').data(function (d) {
85697 }).enter().append('use').attr('class', 'icon-annotation').attr('width', '10px').attr('height', '10px').attr('x', '-3px').attr('y', '-19px').attr('xlink:href', function (d) {
85698 if (d.id < 0) return '#iD-icon-plus';
85699 if (d.status === 'open') return '#iD-icon-close';
85700 return '#iD-icon-apply';
85703 notes.merge(notesEnter).sort(sortY).classed('selected', function (d) {
85704 var mode = context.mode();
85705 var isMoving = mode && mode.id === 'drag-note'; // no shadows when dragging
85707 return !isMoving && d.id === selectedID;
85708 }).attr('transform', getTransform); // Draw targets..
85710 if (touchLayer.empty()) return;
85711 var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
85712 var targets = touchLayer.selectAll('.note').data(data, function (d) {
85716 targets.exit().remove(); // enter/update
85718 targets.enter().append('rect').attr('width', '20px').attr('height', '20px').attr('x', '-8px').attr('y', '-22px').merge(targets).sort(sortY).attr('class', function (d) {
85719 var newClass = d.id < 0 ? 'new' : '';
85720 return 'note target note-' + d.id + ' ' + fillClass + newClass;
85721 }).attr('transform', getTransform);
85723 function sortY(a, b) {
85724 if (a.id === selectedID) return 1;
85725 if (b.id === selectedID) return -1;
85726 return b.loc[1] - a.loc[1];
85728 } // Draw the notes layer and schedule loading notes and updating markers.
85731 function drawNotes(selection) {
85732 var service = getService();
85733 var surface = context.surface();
85735 if (surface && !surface.empty()) {
85736 touchLayer = surface.selectAll('.data-layer.touch .layer-touch.markers');
85739 drawLayer = selection.selectAll('.layer-notes').data(service ? [0] : []);
85740 drawLayer.exit().remove();
85741 drawLayer = drawLayer.enter().append('g').attr('class', 'layer-notes').style('display', _notesEnabled ? 'block' : 'none').merge(drawLayer);
85743 if (_notesEnabled) {
85744 if (service && ~~context.map().zoom() >= minZoom) {
85746 service.loadNotes(projection);
85752 } // Toggles the layer on and off
85755 drawNotes.enabled = function (val) {
85756 if (!arguments.length) return _notesEnabled;
85757 _notesEnabled = val;
85759 if (_notesEnabled) {
85764 if (context.selectedNoteID()) {
85765 context.enter(modeBrowse(context));
85769 dispatch.call('change');
85776 function svgTouch() {
85777 function drawTouch(selection) {
85778 selection.selectAll('.layer-touch').data(['areas', 'lines', 'points', 'turns', 'markers']).enter().append('g').attr('class', function (d) {
85779 return 'layer-touch ' + d;
85786 function refresh(selection, node) {
85787 var cr = node.getBoundingClientRect();
85788 var prop = [cr.width, cr.height];
85789 selection.property('__dimensions__', prop);
85793 function utilGetDimensions(selection, force) {
85794 if (!selection || selection.empty()) {
85798 var node = selection.node(),
85799 cached = selection.property('__dimensions__');
85800 return !cached || force ? refresh(selection, node) : cached;
85802 function utilSetDimensions(selection, dimensions) {
85803 if (!selection || selection.empty()) {
85807 var node = selection.node();
85809 if (dimensions === null) {
85810 refresh(selection, node);
85814 return selection.property('__dimensions__', [dimensions[0], dimensions[1]]).attr('width', dimensions[0]).attr('height', dimensions[1]);
85817 function svgLayers(projection, context) {
85818 var dispatch = dispatch$8('change');
85819 var svg = select(null);
85822 layer: svgOsm(projection, context, dispatch)
85825 layer: svgNotes(projection, context, dispatch)
85828 layer: svgData(projection, context, dispatch)
85831 layer: svgKeepRight(projection, context, dispatch)
85834 layer: svgImproveOSM(projection, context, dispatch)
85837 layer: svgOsmose(projection, context, dispatch)
85840 layer: svgStreetside(projection, context, dispatch)
85843 layer: svgMapillaryImages(projection, context, dispatch)
85845 id: 'mapillary-position',
85846 layer: svgMapillaryPosition(projection, context)
85848 id: 'mapillary-map-features',
85849 layer: svgMapillaryMapFeatures(projection, context, dispatch)
85851 id: 'mapillary-signs',
85852 layer: svgMapillarySigns(projection, context, dispatch)
85855 layer: svgKartaviewImages(projection, context, dispatch)
85858 layer: svgDebug(projection, context)
85861 layer: svgGeolocate(projection)
85867 function drawLayers(selection) {
85868 svg = selection.selectAll('.surface').data([0]);
85869 svg = svg.enter().append('svg').attr('class', 'surface').merge(svg);
85870 var defs = svg.selectAll('.surface-defs').data([0]);
85871 defs.enter().append('defs').attr('class', 'surface-defs');
85872 var groups = svg.selectAll('.data-layer').data(_layers);
85873 groups.exit().remove();
85874 groups.enter().append('g').attr('class', function (d) {
85875 return 'data-layer ' + d.id;
85876 }).merge(groups).each(function (d) {
85877 select(this).call(d.layer);
85881 drawLayers.all = function () {
85885 drawLayers.layer = function (id) {
85886 var obj = _layers.find(function (o) {
85887 return o.id === id;
85890 return obj && obj.layer;
85893 drawLayers.only = function (what) {
85894 var arr = [].concat(what);
85896 var all = _layers.map(function (layer) {
85900 return drawLayers.remove(utilArrayDifference(all, arr));
85903 drawLayers.remove = function (what) {
85904 var arr = [].concat(what);
85905 arr.forEach(function (id) {
85906 _layers = _layers.filter(function (o) {
85907 return o.id !== id;
85910 dispatch.call('change');
85914 drawLayers.add = function (what) {
85915 var arr = [].concat(what);
85916 arr.forEach(function (obj) {
85917 if ('id' in obj && 'layer' in obj) {
85921 dispatch.call('change');
85925 drawLayers.dimensions = function (val) {
85926 if (!arguments.length) return utilGetDimensions(svg);
85927 utilSetDimensions(svg, val);
85931 return utilRebind(drawLayers, dispatch, 'on');
85934 function svgLines(projection, context) {
85935 var detected = utilDetect();
85936 var highway_stack = {
85951 function drawTargets(selection, graph, entities, filter) {
85952 var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
85953 var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor ';
85954 var getPath = svgPath(projection).geojson;
85955 var activeID = context.activeID();
85956 var base = context.history().base(); // The targets and nopes will be MultiLineString sub-segments of the ways
85962 entities.forEach(function (way) {
85963 var features = svgSegmentWay(way, graph, activeID);
85964 data.targets.push.apply(data.targets, features.passive);
85965 data.nopes.push.apply(data.nopes, features.active);
85966 }); // Targets allow hover and vertex snapping
85968 var targetData = data.targets.filter(getPath);
85969 var targets = selection.selectAll('.line.target-allowed').filter(function (d) {
85970 return filter(d.properties.entity);
85971 }).data(targetData, function key(d) {
85975 targets.exit().remove();
85977 var segmentWasEdited = function segmentWasEdited(d) {
85978 var wayID = d.properties.entity.id; // if the whole line was edited, don't draw segment changes
85980 if (!base.entities[wayID] || !fastDeepEqual(graph.entities[wayID].nodes, base.entities[wayID].nodes)) {
85984 return d.properties.nodes.some(function (n) {
85985 return !base.entities[n.id] || !fastDeepEqual(graph.entities[n.id].loc, base.entities[n.id].loc);
85990 targets.enter().append('path').merge(targets).attr('d', getPath).attr('class', function (d) {
85991 return 'way line target target-allowed ' + targetClass + d.id;
85992 }).classed('segment-edited', segmentWasEdited); // NOPE
85994 var nopeData = data.nopes.filter(getPath);
85995 var nopes = selection.selectAll('.line.target-nope').filter(function (d) {
85996 return filter(d.properties.entity);
85997 }).data(nopeData, function key(d) {
86001 nopes.exit().remove(); // enter/update
86003 nopes.enter().append('path').merge(nopes).attr('d', getPath).attr('class', function (d) {
86004 return 'way line target target-nope ' + nopeClass + d.id;
86005 }).classed('segment-edited', segmentWasEdited);
86008 function drawLines(selection, graph, entities, filter) {
86009 var base = context.history().base();
86011 function waystack(a, b) {
86012 var selected = context.selectedIDs();
86013 var scoreA = selected.indexOf(a.id) !== -1 ? 20 : 0;
86014 var scoreB = selected.indexOf(b.id) !== -1 ? 20 : 0;
86016 if (a.tags.highway) {
86017 scoreA -= highway_stack[a.tags.highway];
86020 if (b.tags.highway) {
86021 scoreB -= highway_stack[b.tags.highway];
86024 return scoreA - scoreB;
86027 function drawLineGroup(selection, klass, isSelected) {
86028 // Note: Don't add `.selected` class in draw modes
86029 var mode = context.mode();
86030 var isDrawing = mode && /^draw/.test(mode.id);
86031 var selectedClass = !isDrawing && isSelected ? 'selected ' : '';
86032 var lines = selection.selectAll('path').filter(filter).data(getPathData(isSelected), osmEntity.key);
86033 lines.exit().remove(); // Optimization: Call expensive TagClasses only on enter selection. This
86034 // works because osmEntity.key is defined to include the entity v attribute.
86036 lines.enter().append('path').attr('class', function (d) {
86037 var prefix = 'way line'; // if this line isn't styled by its own tags
86039 if (!d.hasInterestingTags()) {
86040 var parentRelations = graph.parentRelations(d);
86041 var parentMultipolygons = parentRelations.filter(function (relation) {
86042 return relation.isMultipolygon();
86043 }); // and if it's a member of at least one multipolygon relation
86045 if (parentMultipolygons.length > 0 && // and only multipolygon relations
86046 parentRelations.length === parentMultipolygons.length) {
86047 // then fudge the classes to style this as an area edge
86048 prefix = 'relation area';
86052 var oldMPClass = oldMultiPolygonOuters[d.id] ? 'old-multipolygon ' : '';
86053 return prefix + ' ' + klass + ' ' + selectedClass + oldMPClass + d.id;
86054 }).classed('added', function (d) {
86055 return !base.entities[d.id];
86056 }).classed('geometry-edited', function (d) {
86057 return graph.entities[d.id] && base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].nodes, base.entities[d.id].nodes);
86058 }).classed('retagged', function (d) {
86059 return graph.entities[d.id] && base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].tags, base.entities[d.id].tags);
86060 }).call(svgTagClasses()).merge(lines).sort(waystack).attr('d', getPath).call(svgTagClasses().tags(svgRelationMemberTags(graph)));
86064 function getPathData(isSelected) {
86065 return function () {
86066 var layer = this.parentNode.__data__;
86067 var data = pathdata[layer] || [];
86068 return data.filter(function (d) {
86070 return context.selectedIDs().indexOf(d.id) !== -1;
86072 return context.selectedIDs().indexOf(d.id) === -1;
86078 function addMarkers(layergroup, pathclass, groupclass, groupdata, marker) {
86079 var markergroup = layergroup.selectAll('g.' + groupclass).data([pathclass]);
86080 markergroup = markergroup.enter().append('g').attr('class', groupclass).merge(markergroup);
86081 var markers = markergroup.selectAll('path').filter(filter).data(function data() {
86082 return groupdata[this.parentNode.__data__] || [];
86083 }, function key(d) {
86084 return [d.id, d.index];
86086 markers.exit().remove();
86087 markers = markers.enter().append('path').attr('class', pathclass).merge(markers).attr('marker-mid', marker).attr('d', function (d) {
86092 markers.each(function () {
86093 this.parentNode.insertBefore(this, this);
86098 var getPath = svgPath(projection, graph);
86100 var onewaydata = {};
86101 var sideddata = {};
86102 var oldMultiPolygonOuters = {};
86104 for (var i = 0; i < entities.length; i++) {
86105 var entity = entities[i];
86106 var outer = osmOldMultipolygonOuterMember(entity, graph);
86109 ways.push(entity.mergeTags(outer.tags));
86110 oldMultiPolygonOuters[outer.id] = true;
86111 } else if (entity.geometry(graph) === 'line') {
86116 ways = ways.filter(getPath);
86117 var pathdata = utilArrayGroupBy(ways, function (way) {
86118 return way.layer();
86120 Object.keys(pathdata).forEach(function (k) {
86121 var v = pathdata[k];
86122 var onewayArr = v.filter(function (d) {
86123 return d.isOneWay();
86125 var onewaySegments = svgMarkerSegments(projection, graph, 35, function shouldReverse(entity) {
86126 return entity.tags.oneway === '-1';
86127 }, function bothDirections(entity) {
86128 return entity.tags.oneway === 'reversible' || entity.tags.oneway === 'alternating';
86130 onewaydata[k] = utilArrayFlatten(onewayArr.map(onewaySegments));
86131 var sidedArr = v.filter(function (d) {
86132 return d.isSided();
86134 var sidedSegments = svgMarkerSegments(projection, graph, 30, function shouldReverse() {
86136 }, function bothDirections() {
86139 sideddata[k] = utilArrayFlatten(sidedArr.map(sidedSegments));
86141 var covered = selection.selectAll('.layer-osm.covered'); // under areas
86143 var uncovered = selection.selectAll('.layer-osm.lines'); // over areas
86145 var touchLayer = selection.selectAll('.layer-touch.lines'); // Draw lines..
86147 [covered, uncovered].forEach(function (selection) {
86148 var range = selection === covered ? range$1(-10, 0) : range$1(0, 11);
86149 var layergroup = selection.selectAll('g.layergroup').data(range);
86150 layergroup = layergroup.enter().append('g').attr('class', function (d) {
86151 return 'layergroup layer' + String(d);
86152 }).merge(layergroup);
86153 layergroup.selectAll('g.linegroup').data(['shadow', 'casing', 'stroke', 'shadow-highlighted', 'casing-highlighted', 'stroke-highlighted']).enter().append('g').attr('class', function (d) {
86154 return 'linegroup line-' + d;
86156 layergroup.selectAll('g.line-shadow').call(drawLineGroup, 'shadow', false);
86157 layergroup.selectAll('g.line-casing').call(drawLineGroup, 'casing', false);
86158 layergroup.selectAll('g.line-stroke').call(drawLineGroup, 'stroke', false);
86159 layergroup.selectAll('g.line-shadow-highlighted').call(drawLineGroup, 'shadow', true);
86160 layergroup.selectAll('g.line-casing-highlighted').call(drawLineGroup, 'casing', true);
86161 layergroup.selectAll('g.line-stroke-highlighted').call(drawLineGroup, 'stroke', true);
86162 addMarkers(layergroup, 'oneway', 'onewaygroup', onewaydata, 'url(#ideditor-oneway-marker)');
86163 addMarkers(layergroup, 'sided', 'sidedgroup', sideddata, function marker(d) {
86164 var category = graph.entity(d.id).sidednessIdentifier();
86165 return 'url(#ideditor-sided-marker-' + category + ')';
86167 }); // Draw touch targets..
86169 touchLayer.call(drawTargets, graph, ways, filter);
86175 function svgMidpoints(projection, context) {
86176 var targetRadius = 8;
86178 function drawTargets(selection, graph, entities, filter) {
86179 var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
86180 var getTransform = svgPointTransform(projection).geojson;
86181 var data = entities.map(function (midpoint) {
86191 coordinates: midpoint.loc
86195 var targets = selection.selectAll('.midpoint.target').filter(function (d) {
86196 return filter(d.properties.entity);
86197 }).data(data, function key(d) {
86201 targets.exit().remove(); // enter/update
86203 targets.enter().append('circle').attr('r', targetRadius).merge(targets).attr('class', function (d) {
86204 return 'node midpoint target ' + fillClass + d.id;
86205 }).attr('transform', getTransform);
86208 function drawMidpoints(selection, graph, entities, filter, extent) {
86209 var drawLayer = selection.selectAll('.layer-osm.points .points-group.midpoints');
86210 var touchLayer = selection.selectAll('.layer-touch.points');
86211 var mode = context.mode();
86213 if (mode && mode.id !== 'select' || !context.map().withinEditableZoom()) {
86214 drawLayer.selectAll('.midpoint').remove();
86215 touchLayer.selectAll('.midpoint.target').remove();
86219 var poly = extent.polygon();
86220 var midpoints = {};
86222 for (var i = 0; i < entities.length; i++) {
86223 var entity = entities[i];
86224 if (entity.type !== 'way') continue;
86225 if (!filter(entity)) continue;
86226 if (context.selectedIDs().indexOf(entity.id) < 0) continue;
86227 var nodes = graph.childNodes(entity);
86229 for (var j = 0; j < nodes.length - 1; j++) {
86231 var b = nodes[j + 1];
86232 var id = [a.id, b.id].sort().join('-');
86234 if (midpoints[id]) {
86235 midpoints[id].parents.push(entity);
86236 } else if (geoVecLength(projection(a.loc), projection(b.loc)) > 40) {
86237 var point = geoVecInterp(a.loc, b.loc, 0.5);
86240 if (extent.intersects(point)) {
86243 for (var k = 0; k < 4; k++) {
86244 point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
86246 if (point && geoVecLength(projection(a.loc), projection(point)) > 20 && geoVecLength(projection(b.loc), projection(point)) > 20) {
86258 edge: [a.id, b.id],
86266 function midpointFilter(d) {
86267 if (midpoints[d.id]) return true;
86269 for (var i = 0; i < d.parents.length; i++) {
86270 if (filter(d.parents[i])) {
86278 var groups = drawLayer.selectAll('.midpoint').filter(midpointFilter).data(Object.values(midpoints), function (d) {
86281 groups.exit().remove();
86282 var enter = groups.enter().insert('g', ':first-child').attr('class', 'midpoint');
86283 enter.append('polygon').attr('points', '-6,8 10,0 -6,-8').attr('class', 'shadow');
86284 enter.append('polygon').attr('points', '-3,4 5,0 -3,-4').attr('class', 'fill');
86285 groups = groups.merge(enter).attr('transform', function (d) {
86286 var translate = svgPointTransform(projection);
86287 var a = graph.entity(d.edge[0]);
86288 var b = graph.entity(d.edge[1]);
86289 var angle = geoAngle(a, b, projection) * (180 / Math.PI);
86290 return translate(d) + ' rotate(' + angle + ')';
86291 }).call(svgTagClasses().tags(function (d) {
86292 return d.parents[0].tags;
86293 })); // Propagate data bindings.
86295 groups.select('polygon.shadow');
86296 groups.select('polygon.fill'); // Draw touch targets..
86298 touchLayer.call(drawTargets, graph, Object.values(midpoints), midpointFilter);
86301 return drawMidpoints;
86304 function svgPoints(projection, context) {
86305 function markerPath(selection, klass) {
86306 selection.attr('class', klass).attr('transform', 'translate(-8, -23)').attr('d', 'M 17,8 C 17,13 11,21 8.5,23.5 C 6,21 0,13 0,8 C 0,4 4,-0.5 8.5,-0.5 C 13,-0.5 17,4 17,8 z');
86309 function sortY(a, b) {
86310 return b.loc[1] - a.loc[1];
86311 } // Avoid exit/enter if we're just moving stuff around.
86312 // The node will get a new version but we only need to run the update selection.
86315 function fastEntityKey(d) {
86316 var mode = context.mode();
86317 var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
86318 return isMoving ? d.id : osmEntity.key(d);
86321 function drawTargets(selection, graph, entities, filter) {
86322 var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
86323 var getTransform = svgPointTransform(projection).geojson;
86324 var activeID = context.activeID();
86326 entities.forEach(function (node) {
86327 if (activeID === node.id) return; // draw no target on the activeID
86336 geometry: node.asGeoJSON()
86339 var targets = selection.selectAll('.point.target').filter(function (d) {
86340 return filter(d.properties.entity);
86341 }).data(data, function key(d) {
86345 targets.exit().remove(); // enter/update
86347 targets.enter().append('rect').attr('x', -10).attr('y', -26).attr('width', 20).attr('height', 30).merge(targets).attr('class', function (d) {
86348 return 'node point target ' + fillClass + d.id;
86349 }).attr('transform', getTransform);
86352 function drawPoints(selection, graph, entities, filter) {
86353 var wireframe = context.surface().classed('fill-wireframe');
86354 var zoom = geoScaleToZoom(projection.scale());
86355 var base = context.history().base(); // Points with a direction will render as vertices at higher zooms..
86357 function renderAsPoint(entity) {
86358 return entity.geometry(graph) === 'point' && !(zoom >= 18 && entity.directions(graph, projection).length);
86359 } // All points will render as vertices in wireframe mode too..
86362 var points = wireframe ? [] : entities.filter(renderAsPoint);
86363 points.sort(sortY);
86364 var drawLayer = selection.selectAll('.layer-osm.points .points-group.points');
86365 var touchLayer = selection.selectAll('.layer-touch.points'); // Draw points..
86367 var groups = drawLayer.selectAll('g.point').filter(filter).data(points, fastEntityKey);
86368 groups.exit().remove();
86369 var enter = groups.enter().append('g').attr('class', function (d) {
86370 return 'node point ' + d.id;
86372 enter.append('path').call(markerPath, 'shadow');
86373 enter.append('ellipse').attr('cx', 0.5).attr('cy', 1).attr('rx', 6.5).attr('ry', 3).attr('class', 'stroke');
86374 enter.append('path').call(markerPath, 'stroke');
86375 enter.append('use').attr('transform', 'translate(-5, -19)').attr('class', 'icon').attr('width', '11px').attr('height', '11px');
86376 groups = groups.merge(enter).attr('transform', svgPointTransform(projection)).classed('added', function (d) {
86377 return !base.entities[d.id]; // if it doesn't exist in the base graph, it's new
86378 }).classed('moved', function (d) {
86379 return base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].loc, base.entities[d.id].loc);
86380 }).classed('retagged', function (d) {
86381 return base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].tags, base.entities[d.id].tags);
86382 }).call(svgTagClasses());
86383 groups.select('.shadow'); // propagate bound data
86385 groups.select('.stroke'); // propagate bound data
86387 groups.select('.icon') // propagate bound data
86388 .attr('xlink:href', function (entity) {
86389 var preset = _mainPresetIndex.match(entity, graph);
86390 var picon = preset && preset.icon;
86395 var isMaki = /^maki-/.test(picon);
86396 return '#' + picon + (isMaki ? '-11' : '');
86398 }); // Draw touch targets..
86400 touchLayer.call(drawTargets, graph, points, filter);
86406 function svgTurns(projection, context) {
86407 function icon(turn) {
86408 var u = turn.u ? '-u' : '';
86409 if (turn.no) return '#iD-turn-no' + u;
86410 if (turn.only) return '#iD-turn-only' + u;
86411 return '#iD-turn-yes' + u;
86414 function drawTurns(selection, graph, turns) {
86415 function turnTransform(d) {
86417 var toWay = graph.entity(d.to.way);
86418 var toPoints = graph.childNodes(toWay).map(function (n) {
86420 }).map(projection);
86421 var toLength = geoPathLength(toPoints);
86422 var mid = toLength / 2; // midpoint of destination way
86424 var toNode = graph.entity(d.to.node);
86425 var toVertex = graph.entity(d.to.vertex);
86426 var a = geoAngle(toVertex, toNode, projection);
86427 var o = projection(toVertex.loc);
86428 var r = d.u ? 0 // u-turn: no radius
86429 : !toWay.__via ? pxRadius // leaf way: put marker at pxRadius
86430 : Math.min(mid, pxRadius); // via way: prefer pxRadius, fallback to mid for very short ways
86432 return 'translate(' + (r * Math.cos(a) + o[0]) + ',' + (r * Math.sin(a) + o[1]) + ') ' + 'rotate(' + a * 180 / Math.PI + ')';
86435 var drawLayer = selection.selectAll('.layer-osm.points .points-group.turns');
86436 var touchLayer = selection.selectAll('.layer-touch.turns'); // Draw turns..
86438 var groups = drawLayer.selectAll('g.turn').data(turns, function (d) {
86442 groups.exit().remove(); // enter
86444 var groupsEnter = groups.enter().append('g').attr('class', function (d) {
86445 return 'turn ' + d.key;
86447 var turnsEnter = groupsEnter.filter(function (d) {
86450 turnsEnter.append('rect').attr('transform', 'translate(-22, -12)').attr('width', '44').attr('height', '24');
86451 turnsEnter.append('use').attr('transform', 'translate(-22, -12)').attr('width', '44').attr('height', '24');
86452 var uEnter = groupsEnter.filter(function (d) {
86455 uEnter.append('circle').attr('r', '16');
86456 uEnter.append('use').attr('transform', 'translate(-16, -16)').attr('width', '32').attr('height', '32'); // update
86458 groups = groups.merge(groupsEnter).attr('opacity', function (d) {
86459 return d.direct === false ? '0.7' : null;
86460 }).attr('transform', turnTransform);
86461 groups.select('use').attr('xlink:href', icon);
86462 groups.select('rect'); // propagate bound data
86464 groups.select('circle'); // propagate bound data
86465 // Draw touch targets..
86467 var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
86468 groups = touchLayer.selectAll('g.turn').data(turns, function (d) {
86472 groups.exit().remove(); // enter
86474 groupsEnter = groups.enter().append('g').attr('class', function (d) {
86475 return 'turn ' + d.key;
86477 turnsEnter = groupsEnter.filter(function (d) {
86480 turnsEnter.append('rect').attr('class', 'target ' + fillClass).attr('transform', 'translate(-22, -12)').attr('width', '44').attr('height', '24');
86481 uEnter = groupsEnter.filter(function (d) {
86484 uEnter.append('circle').attr('class', 'target ' + fillClass).attr('r', '16'); // update
86486 groups = groups.merge(groupsEnter).attr('transform', turnTransform);
86487 groups.select('rect'); // propagate bound data
86489 groups.select('circle'); // propagate bound data
86497 function svgVertices(projection, context) {
86499 // z16-, z17, z18+, w/icon
86500 shadow: [6, 7.5, 7.5, 12],
86501 stroke: [2.5, 3.5, 3.5, 8],
86502 fill: [1, 1.5, 1.5, 1.5]
86505 var _currHoverTarget;
86507 var _currPersistent = {};
86508 var _currHover = {};
86509 var _prevHover = {};
86510 var _currSelected = {};
86511 var _prevSelected = {};
86514 function sortY(a, b) {
86515 return b.loc[1] - a.loc[1];
86516 } // Avoid exit/enter if we're just moving stuff around.
86517 // The node will get a new version but we only need to run the update selection.
86520 function fastEntityKey(d) {
86521 var mode = context.mode();
86522 var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
86523 return isMoving ? d.id : osmEntity.key(d);
86526 function draw(selection, graph, vertices, sets, filter) {
86533 var directions = {};
86534 var wireframe = context.surface().classed('fill-wireframe');
86535 var zoom = geoScaleToZoom(projection.scale());
86536 var z = zoom < 17 ? 0 : zoom < 18 ? 1 : 2;
86537 var activeID = context.activeID();
86538 var base = context.history().base();
86540 function getIcon(d) {
86541 // always check latest entity, as fastEntityKey avoids enter/exit now
86542 var entity = graph.entity(d.id);
86543 if (entity.id in icons) return icons[entity.id];
86544 icons[entity.id] = entity.hasInterestingTags() && _mainPresetIndex.match(entity, graph).icon;
86545 return icons[entity.id];
86546 } // memoize directions results, return false for empty arrays (for use in filter)
86549 function getDirections(entity) {
86550 if (entity.id in directions) return directions[entity.id];
86551 var angles = entity.directions(graph, projection);
86552 directions[entity.id] = angles.length ? angles : false;
86556 function updateAttributes(selection) {
86557 ['shadow', 'stroke', 'fill'].forEach(function (klass) {
86558 var rads = radiuses[klass];
86559 selection.selectAll('.' + klass).each(function (entity) {
86560 var i = z && getIcon(entity);
86561 var r = rads[i ? 3 : z]; // slightly increase the size of unconnected endpoints #3775
86563 if (entity.id !== activeID && entity.isEndpoint(graph) && !entity.isConnected(graph)) {
86567 if (klass === 'shadow') {
86568 // remember this value, so we don't need to
86569 _radii[entity.id] = r; // recompute it when we draw the touch targets
86572 select(this).attr('r', r).attr('visibility', i && klass === 'fill' ? 'hidden' : null);
86577 vertices.sort(sortY);
86578 var groups = selection.selectAll('g.vertex').filter(filter).data(vertices, fastEntityKey); // exit
86580 groups.exit().remove(); // enter
86582 var enter = groups.enter().append('g').attr('class', function (d) {
86583 return 'node vertex ' + d.id;
86585 enter.append('circle').attr('class', 'shadow');
86586 enter.append('circle').attr('class', 'stroke'); // Vertices with tags get a fill.
86588 enter.filter(function (d) {
86589 return d.hasInterestingTags();
86590 }).append('circle').attr('class', 'fill'); // update
86592 groups = groups.merge(enter).attr('transform', svgPointTransform(projection)).classed('sibling', function (d) {
86593 return d.id in sets.selected;
86594 }).classed('shared', function (d) {
86595 return graph.isShared(d);
86596 }).classed('endpoint', function (d) {
86597 return d.isEndpoint(graph);
86598 }).classed('added', function (d) {
86599 return !base.entities[d.id]; // if it doesn't exist in the base graph, it's new
86600 }).classed('moved', function (d) {
86601 return base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].loc, base.entities[d.id].loc);
86602 }).classed('retagged', function (d) {
86603 return base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].tags, base.entities[d.id].tags);
86604 }).call(updateAttributes); // Vertices with icons get a `use`.
86606 var iconUse = groups.selectAll('.icon').data(function data(d) {
86607 return zoom >= 17 && getIcon(d) ? [d] : [];
86608 }, fastEntityKey); // exit
86610 iconUse.exit().remove(); // enter
86612 iconUse.enter().append('use').attr('class', 'icon').attr('width', '11px').attr('height', '11px').attr('transform', 'translate(-5.5, -5.5)').attr('xlink:href', function (d) {
86613 var picon = getIcon(d);
86614 var isMaki = /^maki-/.test(picon);
86615 return '#' + picon + (isMaki ? '-11' : '');
86616 }); // Vertices with directions get viewfields
86618 var dgroups = groups.selectAll('.viewfieldgroup').data(function data(d) {
86619 return zoom >= 18 && getDirections(d) ? [d] : [];
86620 }, fastEntityKey); // exit
86622 dgroups.exit().remove(); // enter/update
86624 dgroups = dgroups.enter().insert('g', '.shadow').attr('class', 'viewfieldgroup').merge(dgroups);
86625 var viewfields = dgroups.selectAll('.viewfield').data(getDirections, function key(d) {
86626 return osmEntity.key(d);
86629 viewfields.exit().remove(); // enter/update
86631 viewfields.enter().append('path').attr('class', 'viewfield').attr('d', 'M0,0H0').merge(viewfields).attr('marker-start', 'url(#ideditor-viewfield-marker' + (wireframe ? '-wireframe' : '') + ')').attr('transform', function (d) {
86632 return 'rotate(' + d + ')';
86636 function drawTargets(selection, graph, entities, filter) {
86637 var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
86638 var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor ';
86639 var getTransform = svgPointTransform(projection).geojson;
86640 var activeID = context.activeID();
86645 entities.forEach(function (node) {
86646 if (activeID === node.id) return; // draw no target on the activeID
86648 var vertexType = svgPassiveVertex(node, graph, activeID);
86650 if (vertexType !== 0) {
86651 // passive or adjacent - allow to connect
86652 data.targets.push({
86659 geometry: node.asGeoJSON()
86664 id: node.id + '-nope',
86670 geometry: node.asGeoJSON()
86673 }); // Targets allow hover and vertex snapping
86675 var targets = selection.selectAll('.vertex.target-allowed').filter(function (d) {
86676 return filter(d.properties.entity);
86677 }).data(data.targets, function key(d) {
86681 targets.exit().remove(); // enter/update
86683 targets.enter().append('circle').attr('r', function (d) {
86684 return _radii[d.id] || radiuses.shadow[3];
86685 }).merge(targets).attr('class', function (d) {
86686 return 'node vertex target target-allowed ' + targetClass + d.id;
86687 }).attr('transform', getTransform); // NOPE
86689 var nopes = selection.selectAll('.vertex.target-nope').filter(function (d) {
86690 return filter(d.properties.entity);
86691 }).data(data.nopes, function key(d) {
86695 nopes.exit().remove(); // enter/update
86697 nopes.enter().append('circle').attr('r', function (d) {
86698 return _radii[d.properties.entity.id] || radiuses.shadow[3];
86699 }).merge(nopes).attr('class', function (d) {
86700 return 'node vertex target target-nope ' + nopeClass + d.id;
86701 }).attr('transform', getTransform);
86702 } // Points can also render as vertices:
86703 // 1. in wireframe mode or
86704 // 2. at higher zooms if they have a direction
86707 function renderAsVertex(entity, graph, wireframe, zoom) {
86708 var geometry = entity.geometry(graph);
86709 return geometry === 'vertex' || geometry === 'point' && (wireframe || zoom >= 18 && entity.directions(graph, projection).length);
86712 function isEditedNode(node, base, head) {
86713 var baseNode = base.entities[node.id];
86714 var headNode = head.entities[node.id];
86715 return !headNode || !baseNode || !fastDeepEqual(headNode.tags, baseNode.tags) || !fastDeepEqual(headNode.loc, baseNode.loc);
86718 function getSiblingAndChildVertices(ids, graph, wireframe, zoom) {
86722 function addChildVertices(entity) {
86723 // avoid redundant work and infinite recursion of circular relations
86724 if (seenIds[entity.id]) return;
86725 seenIds[entity.id] = true;
86726 var geometry = entity.geometry(graph);
86728 if (!context.features().isHiddenFeature(entity, graph, geometry)) {
86731 if (entity.type === 'way') {
86732 for (i = 0; i < entity.nodes.length; i++) {
86733 var child = graph.hasEntity(entity.nodes[i]);
86736 addChildVertices(child);
86739 } else if (entity.type === 'relation') {
86740 for (i = 0; i < entity.members.length; i++) {
86741 var member = graph.hasEntity(entity.members[i].id);
86744 addChildVertices(member);
86747 } else if (renderAsVertex(entity, graph, wireframe, zoom)) {
86748 results[entity.id] = entity;
86753 ids.forEach(function (id) {
86754 var entity = graph.hasEntity(id);
86755 if (!entity) return;
86757 if (entity.type === 'node') {
86758 if (renderAsVertex(entity, graph, wireframe, zoom)) {
86759 results[entity.id] = entity;
86760 graph.parentWays(entity).forEach(function (entity) {
86761 addChildVertices(entity);
86766 addChildVertices(entity);
86772 function drawVertices(selection, graph, entities, filter, extent, fullRedraw) {
86773 var wireframe = context.surface().classed('fill-wireframe');
86774 var visualDiff = context.surface().classed('highlight-edited');
86775 var zoom = geoScaleToZoom(projection.scale());
86776 var mode = context.mode();
86777 var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
86778 var base = context.history().base();
86779 var drawLayer = selection.selectAll('.layer-osm.points .points-group.vertices');
86780 var touchLayer = selection.selectAll('.layer-touch.points');
86783 _currPersistent = {};
86785 } // Collect important vertices from the `entities` list..
86786 // (during a partial redraw, it will not contain everything)
86789 for (var i = 0; i < entities.length; i++) {
86790 var entity = entities[i];
86791 var geometry = entity.geometry(graph);
86792 var keep = false; // a point that looks like a vertex..
86794 if (geometry === 'point' && renderAsVertex(entity, graph, wireframe, zoom)) {
86795 _currPersistent[entity.id] = entity;
86796 keep = true; // a vertex of some importance..
86797 } else if (geometry === 'vertex' && (entity.hasInterestingTags() || entity.isEndpoint(graph) || entity.isConnected(graph) || visualDiff && isEditedNode(entity, base, graph))) {
86798 _currPersistent[entity.id] = entity;
86800 } // whatever this is, it's not a persistent vertex..
86803 if (!keep && !fullRedraw) {
86804 delete _currPersistent[entity.id];
86806 } // 3 sets of vertices to consider:
86810 persistent: _currPersistent,
86811 // persistent = important vertices (render always)
86812 selected: _currSelected,
86813 // selected + siblings of selected (render always)
86814 hovered: _currHover // hovered + siblings of hovered (render only in draw modes)
86817 var all = Object.assign({}, isMoving ? _currHover : {}, _currSelected, _currPersistent); // Draw the vertices..
86818 // The filter function controls the scope of what objects d3 will touch (exit/enter/update)
86819 // Adjust the filter function to expand the scope beyond whatever entities were passed in.
86821 var filterRendered = function filterRendered(d) {
86822 return d.id in _currPersistent || d.id in _currSelected || d.id in _currHover || filter(d);
86825 drawLayer.call(draw, graph, currentVisible(all), sets, filterRendered); // Draw touch targets..
86826 // When drawing, render all targets (not just those affected by a partial redraw)
86828 var filterTouch = function filterTouch(d) {
86829 return isMoving ? true : filterRendered(d);
86832 touchLayer.call(drawTargets, graph, currentVisible(all), filterTouch);
86834 function currentVisible(which) {
86835 return Object.keys(which).map(graph.hasEntity, graph) // the current version of this entity
86836 .filter(function (entity) {
86837 return entity && entity.intersects(extent, graph);
86840 } // partial redraw - only update the selected items..
86843 drawVertices.drawSelected = function (selection, graph, extent) {
86844 var wireframe = context.surface().classed('fill-wireframe');
86845 var zoom = geoScaleToZoom(projection.scale());
86846 _prevSelected = _currSelected || {};
86848 if (context.map().isInWideSelection()) {
86849 _currSelected = {};
86850 context.selectedIDs().forEach(function (id) {
86851 var entity = graph.hasEntity(id);
86852 if (!entity) return;
86854 if (entity.type === 'node') {
86855 if (renderAsVertex(entity, graph, wireframe, zoom)) {
86856 _currSelected[entity.id] = entity;
86861 _currSelected = getSiblingAndChildVertices(context.selectedIDs(), graph, wireframe, zoom);
86862 } // note that drawVertices will add `_currSelected` automatically if needed..
86865 var filter = function filter(d) {
86866 return d.id in _prevSelected;
86869 drawVertices(selection, graph, Object.values(_prevSelected), filter, extent, false);
86870 }; // partial redraw - only update the hovered items..
86873 drawVertices.drawHover = function (selection, graph, target, extent) {
86874 if (target === _currHoverTarget) return; // continue only if something changed
86876 var wireframe = context.surface().classed('fill-wireframe');
86877 var zoom = geoScaleToZoom(projection.scale());
86878 _prevHover = _currHover || {};
86879 _currHoverTarget = target;
86880 var entity = target && target.properties && target.properties.entity;
86883 _currHover = getSiblingAndChildVertices([entity.id], graph, wireframe, zoom);
86886 } // note that drawVertices will add `_currHover` automatically if needed..
86889 var filter = function filter(d) {
86890 return d.id in _prevHover;
86893 drawVertices(selection, graph, Object.values(_prevHover), filter, extent, false);
86896 return drawVertices;
86899 function utilBindOnce(target, type, listener, capture) {
86900 var typeOnce = type + '.once';
86903 target.on(typeOnce, null);
86904 listener.apply(this, arguments);
86907 target.on(typeOnce, one, capture);
86911 function defaultFilter(d3_event) {
86912 return !d3_event.ctrlKey && !d3_event.button;
86915 function defaultExtent() {
86918 if (e instanceof SVGElement) {
86919 e = e.ownerSVGElement || e;
86921 if (e.hasAttribute('viewBox')) {
86922 e = e.viewBox.baseVal;
86923 return [[e.x, e.y], [e.x + e.width, e.y + e.height]];
86926 return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]];
86929 return [[0, 0], [e.clientWidth, e.clientHeight]];
86932 function defaultWheelDelta(d3_event) {
86933 return -d3_event.deltaY * (d3_event.deltaMode === 1 ? 0.05 : d3_event.deltaMode ? 1 : 0.002);
86936 function defaultConstrain(transform, extent, translateExtent) {
86937 var dx0 = transform.invertX(extent[0][0]) - translateExtent[0][0],
86938 dx1 = transform.invertX(extent[1][0]) - translateExtent[1][0],
86939 dy0 = transform.invertY(extent[0][1]) - translateExtent[0][1],
86940 dy1 = transform.invertY(extent[1][1]) - translateExtent[1][1];
86941 return transform.translate(dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1));
86944 function utilZoomPan() {
86945 var filter = defaultFilter,
86946 extent = defaultExtent,
86947 constrain = defaultConstrain,
86948 wheelDelta = defaultWheelDelta,
86949 scaleExtent = [0, Infinity],
86950 translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]],
86951 interpolate = interpolateZoom,
86952 dispatch = dispatch$8('start', 'zoom', 'end'),
86954 _transform = identity$2,
86957 function zoom(selection) {
86958 selection.on('pointerdown.zoom', pointerdown).on('wheel.zoom', wheeled).style('touch-action', 'none').style('-webkit-tap-highlight-color', 'rgba(0,0,0,0)');
86959 select(window).on('pointermove.zoompan', pointermove).on('pointerup.zoompan pointercancel.zoompan', pointerup);
86962 zoom.transform = function (collection, transform, point) {
86963 var selection = collection.selection ? collection.selection() : collection;
86965 if (collection !== selection) {
86966 schedule(collection, transform, point);
86968 selection.interrupt().each(function () {
86969 gesture(this, arguments).start(null).zoom(null, null, typeof transform === 'function' ? transform.apply(this, arguments) : transform).end(null);
86974 zoom.scaleBy = function (selection, k, p) {
86975 zoom.scaleTo(selection, function () {
86976 var k0 = _transform.k,
86977 k1 = typeof k === 'function' ? k.apply(this, arguments) : k;
86982 zoom.scaleTo = function (selection, k, p) {
86983 zoom.transform(selection, function () {
86984 var e = extent.apply(this, arguments),
86986 p0 = !p ? centroid(e) : typeof p === 'function' ? p.apply(this, arguments) : p,
86987 p1 = t0.invert(p0),
86988 k1 = typeof k === 'function' ? k.apply(this, arguments) : k;
86989 return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent);
86993 zoom.translateBy = function (selection, x, y) {
86994 zoom.transform(selection, function () {
86995 return constrain(_transform.translate(typeof x === 'function' ? x.apply(this, arguments) : x, typeof y === 'function' ? y.apply(this, arguments) : y), extent.apply(this, arguments), translateExtent);
86999 zoom.translateTo = function (selection, x, y, p) {
87000 zoom.transform(selection, function () {
87001 var e = extent.apply(this, arguments),
87003 p0 = !p ? centroid(e) : typeof p === 'function' ? p.apply(this, arguments) : p;
87004 return constrain(identity$2.translate(p0[0], p0[1]).scale(t.k).translate(typeof x === 'function' ? -x.apply(this, arguments) : -x, typeof y === 'function' ? -y.apply(this, arguments) : -y), e, translateExtent);
87008 function scale(transform, k) {
87009 k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k));
87010 return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
87013 function translate(transform, p0, p1) {
87014 var x = p0[0] - p1[0] * transform.k,
87015 y = p0[1] - p1[1] * transform.k;
87016 return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
87019 function centroid(extent) {
87020 return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
87023 function schedule(transition, transform, point) {
87024 transition.on('start.zoom', function () {
87025 gesture(this, arguments).start(null);
87026 }).on('interrupt.zoom end.zoom', function () {
87027 gesture(this, arguments).end(null);
87028 }).tween('zoom', function () {
87031 g = gesture(that, args),
87032 e = extent.apply(that, args),
87033 p = !point ? centroid(e) : typeof point === 'function' ? point.apply(that, args) : point,
87034 w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
87036 b = typeof transform === 'function' ? transform.apply(that, args) : transform,
87037 i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
87038 return function (t) {
87040 // Avoid rounding error on end.
87045 t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k);
87048 g.zoom(null, null, t);
87053 function gesture(that, args, clean) {
87054 return !clean && _activeGesture || new Gesture(that, args);
87057 function Gesture(that, args) {
87061 this.extent = extent.apply(that, args);
87064 Gesture.prototype = {
87065 start: function start(d3_event) {
87066 if (++this.active === 1) {
87067 _activeGesture = this;
87068 dispatch.call('start', this, d3_event);
87073 zoom: function zoom(d3_event, key, transform) {
87074 if (this.mouse && key !== 'mouse') this.mouse[1] = transform.invert(this.mouse[0]);
87075 if (this.pointer0 && key !== 'touch') this.pointer0[1] = transform.invert(this.pointer0[0]);
87076 if (this.pointer1 && key !== 'touch') this.pointer1[1] = transform.invert(this.pointer1[0]);
87077 _transform = transform;
87078 dispatch.call('zoom', this, d3_event, key, transform);
87081 end: function end(d3_event) {
87082 if (--this.active === 0) {
87083 _activeGesture = null;
87084 dispatch.call('end', this, d3_event);
87091 function wheeled(d3_event) {
87092 if (!filter.apply(this, arguments)) return;
87093 var g = gesture(this, arguments),
87095 k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))),
87096 p = utilFastMouse(this)(d3_event); // If the mouse is in the same location as before, reuse it.
87097 // If there were recent wheel events, reset the wheel idle timeout.
87100 if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
87101 g.mouse[1] = t.invert(g.mouse[0] = p);
87104 clearTimeout(g.wheel); // Otherwise, capture the mouse point and location at the start.
87106 g.mouse = [p, t.invert(p)];
87111 d3_event.preventDefault();
87112 d3_event.stopImmediatePropagation();
87113 g.wheel = setTimeout(wheelidled, _wheelDelay);
87114 g.zoom(d3_event, 'mouse', constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent));
87116 function wheelidled() {
87122 var _downPointerIDs = new Set();
87124 var _pointerLocGetter;
87126 function pointerdown(d3_event) {
87127 _downPointerIDs.add(d3_event.pointerId);
87129 if (!filter.apply(this, arguments)) return;
87130 var g = gesture(this, arguments, _downPointerIDs.size === 1);
87132 d3_event.stopImmediatePropagation();
87133 _pointerLocGetter = utilFastMouse(this);
87135 var loc = _pointerLocGetter(d3_event);
87137 var p = [loc, _transform.invert(loc), d3_event.pointerId];
87142 } else if (!g.pointer1 && g.pointer0[2] !== p[2]) {
87152 function pointermove(d3_event) {
87153 if (!_downPointerIDs.has(d3_event.pointerId)) return;
87154 if (!_activeGesture || !_pointerLocGetter) return;
87155 var g = gesture(this, arguments);
87156 var isPointer0 = g.pointer0 && g.pointer0[2] === d3_event.pointerId;
87157 var isPointer1 = !isPointer0 && g.pointer1 && g.pointer1[2] === d3_event.pointerId;
87159 if ((isPointer0 || isPointer1) && 'buttons' in d3_event && !d3_event.buttons) {
87160 // The pointer went up without ending the gesture somehow, e.g.
87161 // a down mouse was moved off the map and released. End it here.
87162 if (g.pointer0) _downPointerIDs["delete"](g.pointer0[2]);
87163 if (g.pointer1) _downPointerIDs["delete"](g.pointer1[2]);
87168 d3_event.preventDefault();
87169 d3_event.stopImmediatePropagation();
87171 var loc = _pointerLocGetter(d3_event);
87174 if (isPointer0) g.pointer0[0] = loc;else if (isPointer1) g.pointer1[0] = loc;
87178 var p0 = g.pointer0[0],
87179 l0 = g.pointer0[1],
87180 p1 = g.pointer1[0],
87181 l1 = g.pointer1[1],
87182 dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
87183 dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
87184 t = scale(t, Math.sqrt(dp / dl));
87185 p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
87186 l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
87187 } else if (g.pointer0) {
87194 g.zoom(d3_event, 'touch', constrain(translate(t, p, l), g.extent, translateExtent));
87197 function pointerup(d3_event) {
87198 if (!_downPointerIDs.has(d3_event.pointerId)) return;
87200 _downPointerIDs["delete"](d3_event.pointerId);
87202 if (!_activeGesture) return;
87203 var g = gesture(this, arguments);
87204 d3_event.stopImmediatePropagation();
87205 if (g.pointer0 && g.pointer0[2] === d3_event.pointerId) delete g.pointer0;else if (g.pointer1 && g.pointer1[2] === d3_event.pointerId) delete g.pointer1;
87207 if (g.pointer1 && !g.pointer0) {
87208 g.pointer0 = g.pointer1;
87213 g.pointer0[1] = _transform.invert(g.pointer0[0]);
87219 zoom.wheelDelta = function (_) {
87220 return arguments.length ? (wheelDelta = utilFunctor(+_), zoom) : wheelDelta;
87223 zoom.filter = function (_) {
87224 return arguments.length ? (filter = utilFunctor(!!_), zoom) : filter;
87227 zoom.extent = function (_) {
87228 return arguments.length ? (extent = utilFunctor([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
87231 zoom.scaleExtent = function (_) {
87232 return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]];
87235 zoom.translateExtent = function (_) {
87236 return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]];
87239 zoom.constrain = function (_) {
87240 return arguments.length ? (constrain = _, zoom) : constrain;
87243 zoom.interpolate = function (_) {
87244 return arguments.length ? (interpolate = _, zoom) : interpolate;
87247 zoom._transform = function (_) {
87248 return arguments.length ? (_transform = _, zoom) : _transform;
87251 return utilRebind(zoom, dispatch, 'on');
87254 // if pointer events are supported. Falls back to default `dblclick` event.
87256 function utilDoubleUp() {
87257 var dispatch = dispatch$8('doubleUp');
87258 var _maxTimespan = 500; // milliseconds
87260 var _maxDistance = 20; // web pixels; be somewhat generous to account for touch devices
87262 var _pointer; // object representing the pointer that could trigger double up
87265 function pointerIsValidFor(loc) {
87266 // second pointerup must occur within a small timeframe after the first pointerdown
87267 return new Date().getTime() - _pointer.startTime <= _maxTimespan && // all pointer events must occur within a small distance of the first pointerdown
87268 geoVecLength(_pointer.startLoc, loc) <= _maxDistance;
87271 function pointerdown(d3_event) {
87272 // ignore right-click
87273 if (d3_event.ctrlKey || d3_event.button === 2) return;
87274 var loc = [d3_event.clientX, d3_event.clientY]; // Don't rely on pointerId here since it can change between pointerdown
87275 // events on touch devices
87277 if (_pointer && !pointerIsValidFor(loc)) {
87278 // if this pointer is no longer valid, clear it so another can be started
87279 _pointer = undefined;
87285 startTime: new Date().getTime(),
87287 pointerId: d3_event.pointerId
87291 _pointer.pointerId = d3_event.pointerId;
87295 function pointerup(d3_event) {
87296 // ignore right-click
87297 if (d3_event.ctrlKey || d3_event.button === 2) return;
87298 if (!_pointer || _pointer.pointerId !== d3_event.pointerId) return;
87299 _pointer.upCount += 1;
87301 if (_pointer.upCount === 2) {
87303 var loc = [d3_event.clientX, d3_event.clientY];
87305 if (pointerIsValidFor(loc)) {
87306 var locInThis = utilFastMouse(this)(d3_event);
87307 dispatch.call('doubleUp', this, d3_event, locInThis);
87308 } // clear the pointer info in any case
87311 _pointer = undefined;
87315 function doubleUp(selection) {
87316 if ('PointerEvent' in window) {
87317 // dblclick isn't well supported on touch devices so manually use
87318 // pointer events if they're available
87319 selection.on('pointerdown.doubleUp', pointerdown).on('pointerup.doubleUp', pointerup);
87321 // fallback to dblclick
87322 selection.on('dblclick.doubleUp', function (d3_event) {
87323 dispatch.call('doubleUp', this, d3_event, utilFastMouse(this)(d3_event));
87328 doubleUp.off = function (selection) {
87329 selection.on('pointerdown.doubleUp', null).on('pointerup.doubleUp', null).on('dblclick.doubleUp', null);
87332 return utilRebind(doubleUp, dispatch, 'on');
87335 var TILESIZE = 256;
87338 var kMin = geoZoomToScale(minZoom, TILESIZE);
87339 var kMax = geoZoomToScale(maxZoom, TILESIZE);
87341 function clamp$1(num, min, max) {
87342 return Math.max(min, Math.min(num, max));
87345 function rendererMap(context) {
87346 var dispatch = dispatch$8('move', 'drawn', 'crossEditableZoom', 'hitMinZoom', 'changeHighlighting', 'changeAreaFill');
87347 var projection = context.projection;
87348 var curtainProjection = context.curtainProjection;
87357 var _selection = select(null);
87359 var supersurface = select(null);
87360 var wrapper = select(null);
87361 var surface = select(null);
87362 var _dimensions = [1, 1];
87363 var _dblClickZoomEnabled = true;
87364 var _redrawEnabled = true;
87366 var _gestureTransformStart;
87368 var _transformStart = projection.transform();
87370 var _transformLast;
87372 var _isTransformed = false;
87375 var _getMouseCoords;
87377 var _lastPointerEvent;
87379 var _lastWithinEditableZoom; // whether a pointerdown event started the zoom
87382 var _pointerDown = false; // use pointer events on supported platforms; fallback to mouse events
87384 var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse'; // use pointer event interaction if supported; fallback to touch/mouse events in d3-zoom
87387 var _zoomerPannerFunction = 'PointerEvent' in window ? utilZoomPan : d3_zoom;
87389 var _zoomerPanner = _zoomerPannerFunction().scaleExtent([kMin, kMax]).interpolate(interpolate$1).filter(zoomEventFilter).on('zoom.map', zoomPan).on('start.map', function (d3_event) {
87390 _pointerDown = d3_event && (d3_event.type === 'pointerdown' || d3_event.sourceEvent && d3_event.sourceEvent.type === 'pointerdown');
87391 }).on('end.map', function () {
87392 _pointerDown = false;
87395 var _doubleUpHandler = utilDoubleUp();
87397 var scheduleRedraw = throttle(redraw, 750); // var isRedrawScheduled = false;
87398 // var pendingRedrawCall;
87399 // function scheduleRedraw() {
87400 // // Only schedule the redraw if one has not already been set.
87401 // if (isRedrawScheduled) return;
87402 // isRedrawScheduled = true;
87403 // var that = this;
87404 // var args = arguments;
87405 // pendingRedrawCall = window.requestIdleCallback(function () {
87406 // // Reset the boolean so future redraws can be set.
87407 // isRedrawScheduled = false;
87408 // redraw.apply(that, args);
87409 // }, { timeout: 1400 });
87413 function cancelPendingRedraw() {
87414 scheduleRedraw.cancel(); // isRedrawScheduled = false;
87415 // window.cancelIdleCallback(pendingRedrawCall);
87418 function map(selection) {
87419 _selection = selection;
87420 context.on('change.map', immediateRedraw);
87421 var osm = context.connection();
87424 osm.on('change.map', immediateRedraw);
87427 function didUndoOrRedo(targetTransform) {
87428 var mode = context.mode().id;
87429 if (mode !== 'browse' && mode !== 'select') return;
87431 if (targetTransform) {
87432 map.transformEase(targetTransform);
87436 context.history().on('merge.map', function () {
87438 }).on('change.map', immediateRedraw).on('undone.map', function (stack, fromStack) {
87439 didUndoOrRedo(fromStack.transform);
87440 }).on('redone.map', function (stack) {
87441 didUndoOrRedo(stack.transform);
87443 context.background().on('change.map', immediateRedraw);
87444 context.features().on('redraw.map', immediateRedraw);
87445 drawLayers.on('change.map', function () {
87446 context.background().updateImagery();
87449 selection.on('wheel.map mousewheel.map', function (d3_event) {
87450 // disable swipe-to-navigate browser pages on trackpad/magic mouse – #5552
87451 d3_event.preventDefault();
87452 }).call(_zoomerPanner).call(_zoomerPanner.transform, projection.transform()).on('dblclick.zoom', null); // override d3-zoom dblclick handling
87454 map.supersurface = supersurface = selection.append('div').attr('class', 'supersurface').call(utilSetTransform, 0, 0); // Need a wrapper div because Opera can't cope with an absolutely positioned
87455 // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
87457 wrapper = supersurface.append('div').attr('class', 'layer layer-data');
87458 map.surface = surface = wrapper.call(drawLayers).selectAll('.surface');
87459 surface.call(drawLabels.observe).call(_doubleUpHandler).on(_pointerPrefix + 'down.zoom', function (d3_event) {
87460 _lastPointerEvent = d3_event;
87462 if (d3_event.button === 2) {
87463 d3_event.stopPropagation();
87465 }, true).on(_pointerPrefix + 'up.zoom', function (d3_event) {
87466 _lastPointerEvent = d3_event;
87468 if (resetTransform()) {
87471 }).on(_pointerPrefix + 'move.map', function (d3_event) {
87472 _lastPointerEvent = d3_event;
87473 }).on(_pointerPrefix + 'over.vertices', function (d3_event) {
87474 if (map.editableDataEnabled() && !_isTransformed) {
87475 var hover = d3_event.target.__data__;
87476 surface.call(drawVertices.drawHover, context.graph(), hover, map.extent());
87477 dispatch.call('drawn', this, {
87481 }).on(_pointerPrefix + 'out.vertices', function (d3_event) {
87482 if (map.editableDataEnabled() && !_isTransformed) {
87483 var hover = d3_event.relatedTarget && d3_event.relatedTarget.__data__;
87484 surface.call(drawVertices.drawHover, context.graph(), hover, map.extent());
87485 dispatch.call('drawn', this, {
87490 var detected = utilDetect(); // only WebKit supports gesture events
87492 if ('GestureEvent' in window && // Listening for gesture events on iOS 13.4+ breaks double-tapping,
87493 // but we only need to do this on desktop Safari anyway. – #7694
87494 !detected.isMobileWebKit) {
87495 // Desktop Safari sends gesture events for multitouch trackpad pinches.
87496 // We can listen for these and translate them into map zooms.
87497 surface.on('gesturestart.surface', function (d3_event) {
87498 d3_event.preventDefault();
87499 _gestureTransformStart = projection.transform();
87500 }).on('gesturechange.surface', gestureChange);
87501 } // must call after surface init
87506 _doubleUpHandler.on('doubleUp.map', function (d3_event, p0) {
87507 if (!_dblClickZoomEnabled) return; // don't zoom if targeting something other than the map itself
87509 if (_typeof(d3_event.target.__data__) === 'object' && // or area fills
87510 !select(d3_event.target).classed('fill')) return;
87511 var zoomOut = d3_event.shiftKey;
87512 var t = projection.transform();
87513 var p1 = t.invert(p0);
87514 t = t.scale(zoomOut ? 0.5 : 2);
87515 t.x = p0[0] - p1[0] * t.k;
87516 t.y = p0[1] - p1[1] * t.k;
87517 map.transformEase(t);
87520 context.on('enter.map', function () {
87521 if (!map.editableDataEnabled(true
87522 /* skip zoom check */
87524 if (_isTransformed) return; // redraw immediately any objects affected by a change in selectedIDs.
87526 var graph = context.graph();
87527 var selectedAndParents = {};
87528 context.selectedIDs().forEach(function (id) {
87529 var entity = graph.hasEntity(id);
87532 selectedAndParents[entity.id] = entity;
87534 if (entity.type === 'node') {
87535 graph.parentWays(entity).forEach(function (parent) {
87536 selectedAndParents[parent.id] = parent;
87541 var data = Object.values(selectedAndParents);
87543 var filter = function filter(d) {
87544 return d.id in selectedAndParents;
87547 data = context.features().filter(data, graph);
87548 surface.call(drawVertices.drawSelected, graph, map.extent()).call(drawLines, graph, data, filter).call(drawAreas, graph, data, filter).call(drawMidpoints, graph, data, filter, map.trimmedExtent());
87549 dispatch.call('drawn', this, {
87551 }); // redraw everything else later
87555 map.dimensions(utilGetDimensions(selection));
87558 function zoomEventFilter(d3_event) {
87559 // Fix for #2151, (see also d3/d3-zoom#60, d3/d3-brush#18)
87560 // Intercept `mousedown` and check if there is an orphaned zoom gesture.
87561 // This can happen if a previous `mousedown` occurred without a `mouseup`.
87562 // If we detect this, dispatch `mouseup` to complete the orphaned gesture,
87563 // so that d3-zoom won't stop propagation of new `mousedown` events.
87564 if (d3_event.type === 'mousedown') {
87565 var hasOrphan = false;
87566 var listeners = window.__on;
87568 for (var i = 0; i < listeners.length; i++) {
87569 var listener = listeners[i];
87571 if (listener.name === 'zoom' && listener.type === 'mouseup') {
87578 var event = window.CustomEvent;
87581 event = new event('mouseup');
87583 event = window.document.createEvent('Event');
87584 event.initEvent('mouseup', false, false);
87585 } // Event needs to be dispatched with an event.view property.
87588 event.view = window;
87589 window.dispatchEvent(event);
87593 return d3_event.button !== 2; // ignore right clicks
87596 function pxCenter() {
87597 return [_dimensions[0] / 2, _dimensions[1] / 2];
87600 function drawEditable(difference, extent) {
87601 var mode = context.mode();
87602 var graph = context.graph();
87603 var features = context.features();
87604 var all = context.history().intersects(map.extent());
87605 var fullRedraw = false;
87609 var applyFeatureLayerFilters = true;
87611 if (map.isInWideSelection()) {
87613 utilEntityAndDeepMemberIDs(mode.selectedIDs(), context.graph()).forEach(function (id) {
87614 var entity = context.hasEntity(id);
87615 if (entity) data.push(entity);
87618 filter = utilFunctor(true); // selected features should always be visible, so we can skip filtering
87620 applyFeatureLayerFilters = false;
87621 } else if (difference) {
87622 var complete = difference.complete(map.extent());
87623 data = Object.values(complete).filter(Boolean);
87624 set = new Set(Object.keys(complete));
87626 filter = function filter(d) {
87627 return set.has(d.id);
87630 features.clear(data);
87632 // force a full redraw if gatherStats detects that a feature
87633 // should be auto-hidden (e.g. points or buildings)..
87634 if (features.gatherStats(all, graph, _dimensions)) {
87635 extent = undefined;
87639 data = context.history().intersects(map.extent().intersection(extent));
87640 set = new Set(data.map(function (entity) {
87644 filter = function filter(d) {
87645 return set.has(d.id);
87650 filter = utilFunctor(true);
87654 if (applyFeatureLayerFilters) {
87655 data = features.filter(data, graph);
87657 context.features().resetStats();
87660 if (mode && mode.id === 'select') {
87661 // update selected vertices - the user might have just double-clicked a way,
87662 // creating a new vertex, triggering a partial redraw without a mode change
87663 surface.call(drawVertices.drawSelected, graph, map.extent());
87666 surface.call(drawVertices, graph, data, filter, map.extent(), fullRedraw).call(drawLines, graph, data, filter).call(drawAreas, graph, data, filter).call(drawMidpoints, graph, data, filter, map.trimmedExtent()).call(drawLabels, graph, data, filter, _dimensions, fullRedraw).call(drawPoints, graph, data, filter);
87667 dispatch.call('drawn', this, {
87672 map.init = function () {
87673 drawLayers = svgLayers(projection, context);
87674 drawPoints = svgPoints(projection, context);
87675 drawVertices = svgVertices(projection, context);
87676 drawLines = svgLines(projection, context);
87677 drawAreas = svgAreas(projection, context);
87678 drawMidpoints = svgMidpoints(projection, context);
87679 drawLabels = svgLabels(projection, context);
87682 function editOff() {
87683 context.features().resetStats();
87684 surface.selectAll('.layer-osm *').remove();
87685 surface.selectAll('.layer-touch:not(.markers) *').remove();
87689 'select-note': true,
87690 'select-data': true,
87691 'select-error': true
87693 var mode = context.mode();
87695 if (mode && !allowed[mode.id]) {
87696 context.enter(modeBrowse(context));
87699 dispatch.call('drawn', this, {
87704 function gestureChange(d3_event) {
87705 // Remap Safari gesture events to wheel events - #5492
87706 // We want these disabled most places, but enabled for zoom/unzoom on map surface
87707 // https://developer.mozilla.org/en-US/docs/Web/API/GestureEvent
87709 e.preventDefault();
87712 // dummy values to ignore in zoomPan
87714 // dummy values to ignore in zoomPan
87715 clientX: e.clientX,
87716 clientY: e.clientY,
87717 screenX: e.screenX,
87718 screenY: e.screenY,
87722 var e2 = new WheelEvent('wheel', props);
87723 e2._scale = e.scale; // preserve the original scale
87725 e2._rotation = e.rotation; // preserve the original rotation
87727 _selection.node().dispatchEvent(e2);
87730 function zoomPan(event, key, transform) {
87731 var source = event && event.sourceEvent || event;
87732 var eventTransform = transform || event && event.transform;
87733 var x = eventTransform.x;
87734 var y = eventTransform.y;
87735 var k = eventTransform.k; // Special handling of 'wheel' events:
87736 // They might be triggered by the user scrolling the mouse wheel,
87737 // or 2-finger pinch/zoom gestures, the transform may need adjustment.
87739 if (source && source.type === 'wheel') {
87740 // assume that the gesture is already handled by pointer events
87741 if (_pointerDown) return;
87742 var detected = utilDetect();
87743 var dX = source.deltaX;
87744 var dY = source.deltaY;
87748 var t0, p0, p1; // Normalize mousewheel scroll speed (Firefox) - #3029
87749 // If wheel delta is provided in LINE units, recalculate it in PIXEL units
87750 // We are essentially redoing the calculations that occur here:
87751 // https://github.com/d3/d3-zoom/blob/78563a8348aa4133b07cac92e2595c2227ca7cd7/src/zoom.js#L203
87752 // See this for more info:
87753 // https://github.com/basilfx/normalize-wheel/blob/master/src/normalizeWheel.js
87755 if (source.deltaMode === 1
87758 // Convert from lines to pixels, more if the user is scrolling fast.
87759 // (I made up the exp function to roughly match Firefox to what Chrome does)
87760 // These numbers should be floats, because integers are treated as pan gesture below.
87761 var lines = Math.abs(source.deltaY);
87762 var sign = source.deltaY > 0 ? 1 : -1;
87763 dY = sign * clamp$1(Math.exp((lines - 1) * 0.75) * 4.000244140625, 4.000244140625, // min
87764 350.000244140625 // max
87765 ); // On Firefox Windows and Linux we always get +/- the scroll line amount (default 3)
87766 // There doesn't seem to be any scroll acceleration.
87767 // This multiplier increases the speed a little bit - #5512
87769 if (detected.os !== 'mac') {
87771 } // recalculate x2,y2,k2
87774 t0 = _isTransformed ? _transformLast : _transformStart;
87775 p0 = _getMouseCoords(source);
87776 p1 = t0.invert(p0);
87777 k2 = t0.k * Math.pow(2, -dY / 500);
87778 k2 = clamp$1(k2, kMin, kMax);
87779 x2 = p0[0] - p1[0] * k2;
87780 y2 = p0[1] - p1[1] * k2; // 2 finger map pinch zooming (Safari) - #5492
87781 // These are fake `wheel` events we made from Safari `gesturechange` events..
87782 } else if (source._scale) {
87783 // recalculate x2,y2,k2
87784 t0 = _gestureTransformStart;
87785 p0 = _getMouseCoords(source);
87786 p1 = t0.invert(p0);
87787 k2 = t0.k * source._scale;
87788 k2 = clamp$1(k2, kMin, kMax);
87789 x2 = p0[0] - p1[0] * k2;
87790 y2 = p0[1] - p1[1] * k2; // 2 finger map pinch zooming (all browsers except Safari) - #5492
87791 // Pinch zooming via the `wheel` event will always have:
87792 // - `ctrlKey = true`
87793 // - `deltaY` is not round integer pixels (ignore `deltaX`)
87794 } else if (source.ctrlKey && !isInteger(dY)) {
87795 dY *= 6; // slightly scale up whatever the browser gave us
87796 // recalculate x2,y2,k2
87798 t0 = _isTransformed ? _transformLast : _transformStart;
87799 p0 = _getMouseCoords(source);
87800 p1 = t0.invert(p0);
87801 k2 = t0.k * Math.pow(2, -dY / 500);
87802 k2 = clamp$1(k2, kMin, kMax);
87803 x2 = p0[0] - p1[0] * k2;
87804 y2 = p0[1] - p1[1] * k2; // Trackpad scroll zooming with shift or alt/option key down
87805 } else if ((source.altKey || source.shiftKey) && isInteger(dY)) {
87806 // recalculate x2,y2,k2
87807 t0 = _isTransformed ? _transformLast : _transformStart;
87808 p0 = _getMouseCoords(source);
87809 p1 = t0.invert(p0);
87810 k2 = t0.k * Math.pow(2, -dY / 500);
87811 k2 = clamp$1(k2, kMin, kMax);
87812 x2 = p0[0] - p1[0] * k2;
87813 y2 = p0[1] - p1[1] * k2; // 2 finger map panning (Mac only, all browsers except Firefox #8595) - #5492, #5512
87814 // Panning via the `wheel` event will always have:
87815 // - `ctrlKey = false`
87816 // - `deltaX`,`deltaY` are round integer pixels
87817 } else if (detected.os === 'mac' && detected.browser !== 'Firefox' && !source.ctrlKey && isInteger(dX) && isInteger(dY)) {
87818 p1 = projection.translate();
87821 k2 = projection.scale();
87822 k2 = clamp$1(k2, kMin, kMax);
87823 } // something changed - replace the event transform
87826 if (x2 !== x || y2 !== y || k2 !== k) {
87830 eventTransform = identity$2.translate(x2, y2).scale(k2);
87832 if (_zoomerPanner._transform) {
87833 // utilZoomPan interface
87834 _zoomerPanner._transform(eventTransform);
87836 // d3_zoom interface
87837 _selection.node().__zoom = eventTransform;
87842 if (_transformStart.x === x && _transformStart.y === y && _transformStart.k === k) {
87843 return; // no change
87846 if (geoScaleToZoom(k, TILESIZE) < _minzoom) {
87847 surface.interrupt();
87848 dispatch.call('hitMinZoom', this, map);
87849 setCenterZoom(map.center(), context.minEditableZoom(), 0, true);
87851 dispatch.call('move', this, map);
87855 projection.transform(eventTransform);
87856 var withinEditableZoom = map.withinEditableZoom();
87858 if (_lastWithinEditableZoom !== withinEditableZoom) {
87859 if (_lastWithinEditableZoom !== undefined) {
87860 // notify that the map zoomed in or out over the editable zoom threshold
87861 dispatch.call('crossEditableZoom', this, withinEditableZoom);
87864 _lastWithinEditableZoom = withinEditableZoom;
87867 var scale = k / _transformStart.k;
87868 var tX = (x / scale - _transformStart.x) * scale;
87869 var tY = (y / scale - _transformStart.y) * scale;
87871 if (context.inIntro()) {
87872 curtainProjection.transform({
87880 _lastPointerEvent = event;
87883 _isTransformed = true;
87884 _transformLast = eventTransform;
87885 utilSetTransform(supersurface, tX, tY, scale);
87887 dispatch.call('move', this, map);
87889 function isInteger(val) {
87890 return typeof val === 'number' && isFinite(val) && Math.floor(val) === val;
87894 function resetTransform() {
87895 if (!_isTransformed) return false;
87896 utilSetTransform(supersurface, 0, 0);
87897 _isTransformed = false;
87899 if (context.inIntro()) {
87900 curtainProjection.transform(projection.transform());
87906 function redraw(difference, extent) {
87907 if (surface.empty() || !_redrawEnabled) return; // If we are in the middle of a zoom/pan, we can't do differenced redraws.
87908 // It would result in artifacts where differenced entities are redrawn with
87909 // one transform and unchanged entities with another.
87911 if (resetTransform()) {
87912 difference = extent = undefined;
87915 var zoom = map.zoom();
87916 var z = String(~~zoom);
87918 if (surface.attr('data-zoom') !== z) {
87919 surface.attr('data-zoom', z);
87920 } // class surface as `lowzoom` around z17-z18.5 (based on latitude)
87923 var lat = map.center()[1];
87924 var lowzoom = linear().domain([-60, 0, 60]).range([17, 18.5, 17]).clamp(true);
87925 surface.classed('low-zoom', zoom <= lowzoom(lat));
87928 supersurface.call(context.background());
87929 wrapper.call(drawLayers);
87933 if (map.editableDataEnabled() || map.isInWideSelection()) {
87934 context.loadTiles(projection);
87935 drawEditable(difference, extent);
87940 _transformStart = projection.transform();
87944 var immediateRedraw = function immediateRedraw(difference, extent) {
87945 if (!difference && !extent) cancelPendingRedraw();
87946 redraw(difference, extent);
87949 map.lastPointerEvent = function () {
87950 return _lastPointerEvent;
87953 map.mouse = function (d3_event) {
87954 var event = d3_event || _lastPointerEvent;
87959 while (s = event.sourceEvent) {
87963 return _getMouseCoords(event);
87967 }; // returns Lng/Lat
87970 map.mouseCoordinates = function () {
87971 var coord = map.mouse() || pxCenter();
87972 return projection.invert(coord);
87975 map.dblclickZoomEnable = function (val) {
87976 if (!arguments.length) return _dblClickZoomEnabled;
87977 _dblClickZoomEnabled = val;
87981 map.redrawEnable = function (val) {
87982 if (!arguments.length) return _redrawEnabled;
87983 _redrawEnabled = val;
87987 map.isTransformed = function () {
87988 return _isTransformed;
87991 function setTransform(t2, duration, force) {
87992 var t = projection.transform();
87993 if (!force && t2.k === t.k && t2.x === t.x && t2.y === t.y) return false;
87996 _selection.transition().duration(duration).on('start', function () {
87998 }).call(_zoomerPanner.transform, identity$2.translate(t2.x, t2.y).scale(t2.k));
88000 projection.transform(t2);
88001 _transformStart = t2;
88003 _selection.call(_zoomerPanner.transform, _transformStart);
88009 function setCenterZoom(loc2, z2, duration, force) {
88010 var c = map.center();
88011 var z = map.zoom();
88012 if (loc2[0] === c[0] && loc2[1] === c[1] && z2 === z && !force) return false;
88013 var proj = geoRawMercator().transform(projection.transform()); // copy projection
88015 var k2 = clamp$1(geoZoomToScale(z2, TILESIZE), kMin, kMax);
88017 var t = proj.translate();
88018 var point = proj(loc2);
88019 var center = pxCenter();
88020 t[0] += center[0] - point[0];
88021 t[1] += center[1] - point[1];
88022 return setTransform(identity$2.translate(t[0], t[1]).scale(k2), duration, force);
88025 map.pan = function (delta, duration) {
88026 var t = projection.translate();
88027 var k = projection.scale();
88032 _selection.transition().duration(duration).on('start', function () {
88034 }).call(_zoomerPanner.transform, identity$2.translate(t[0], t[1]).scale(k));
88036 projection.translate(t);
88037 _transformStart = projection.transform();
88039 _selection.call(_zoomerPanner.transform, _transformStart);
88041 dispatch.call('move', this, map);
88048 map.dimensions = function (val) {
88049 if (!arguments.length) return _dimensions;
88051 drawLayers.dimensions(_dimensions);
88052 context.background().dimensions(_dimensions);
88053 projection.clipExtent([[0, 0], _dimensions]);
88054 _getMouseCoords = utilFastMouse(supersurface.node());
88059 function zoomIn(delta) {
88060 setCenterZoom(map.center(), ~~map.zoom() + delta, 250, true);
88063 function zoomOut(delta) {
88064 setCenterZoom(map.center(), ~~map.zoom() - delta, 250, true);
88067 map.zoomIn = function () {
88071 map.zoomInFurther = function () {
88075 map.canZoomIn = function () {
88076 return map.zoom() < maxZoom;
88079 map.zoomOut = function () {
88083 map.zoomOutFurther = function () {
88087 map.canZoomOut = function () {
88088 return map.zoom() > minZoom;
88091 map.center = function (loc2) {
88092 if (!arguments.length) {
88093 return projection.invert(pxCenter());
88096 if (setCenterZoom(loc2, map.zoom())) {
88097 dispatch.call('move', this, map);
88104 map.unobscuredCenterZoomEase = function (loc, zoom) {
88105 var offset = map.unobscuredOffsetPx();
88106 var proj = geoRawMercator().transform(projection.transform()); // copy projection
88107 // use the target zoom to calculate the offset center
88109 proj.scale(geoZoomToScale(zoom, TILESIZE));
88110 var locPx = proj(loc);
88111 var offsetLocPx = [locPx[0] + offset[0], locPx[1] + offset[1]];
88112 var offsetLoc = proj.invert(offsetLocPx);
88113 map.centerZoomEase(offsetLoc, zoom);
88116 map.unobscuredOffsetPx = function () {
88117 var openPane = context.container().select('.map-panes .map-pane.shown');
88119 if (!openPane.empty()) {
88120 return [openPane.node().offsetWidth / 2, 0];
88126 map.zoom = function (z2) {
88127 if (!arguments.length) {
88128 return Math.max(geoScaleToZoom(projection.scale(), TILESIZE), 0);
88131 if (z2 < _minzoom) {
88132 surface.interrupt();
88133 dispatch.call('hitMinZoom', this, map);
88134 z2 = context.minEditableZoom();
88137 if (setCenterZoom(map.center(), z2)) {
88138 dispatch.call('move', this, map);
88145 map.centerZoom = function (loc2, z2) {
88146 if (setCenterZoom(loc2, z2)) {
88147 dispatch.call('move', this, map);
88154 map.zoomTo = function (entity) {
88155 var extent = entity.extent(context.graph());
88156 if (!isFinite(extent.area())) return map;
88157 var z2 = clamp$1(map.trimmedExtentZoom(extent), 0, 20);
88158 return map.centerZoom(extent.center(), z2);
88161 map.centerEase = function (loc2, duration) {
88162 duration = duration || 250;
88163 setCenterZoom(loc2, map.zoom(), duration);
88167 map.zoomEase = function (z2, duration) {
88168 duration = duration || 250;
88169 setCenterZoom(map.center(), z2, duration, false);
88173 map.centerZoomEase = function (loc2, z2, duration) {
88174 duration = duration || 250;
88175 setCenterZoom(loc2, z2, duration, false);
88179 map.transformEase = function (t2, duration) {
88180 duration = duration || 250;
88181 setTransform(t2, duration, false
88187 map.zoomToEase = function (obj, duration) {
88190 if (Array.isArray(obj)) {
88191 obj.forEach(function (entity) {
88192 var entityExtent = entity.extent(context.graph());
88195 extent = entityExtent;
88197 extent = extent.extend(entityExtent);
88201 extent = obj.extent(context.graph());
88204 if (!isFinite(extent.area())) return map;
88205 var z2 = clamp$1(map.trimmedExtentZoom(extent), 0, 20);
88206 return map.centerZoomEase(extent.center(), z2, duration);
88209 map.startEase = function () {
88210 utilBindOnce(surface, _pointerPrefix + 'down.ease', function () {
88216 map.cancelEase = function () {
88217 _selection.interrupt();
88222 map.extent = function (val) {
88223 if (!arguments.length) {
88224 return new geoExtent(projection.invert([0, _dimensions[1]]), projection.invert([_dimensions[0], 0]));
88226 var extent = geoExtent(val);
88227 map.centerZoom(extent.center(), map.extentZoom(extent));
88231 map.trimmedExtent = function (val) {
88232 if (!arguments.length) {
88236 return new geoExtent(projection.invert([pad, _dimensions[1] - footerY - pad]), projection.invert([_dimensions[0] - pad, headerY + pad]));
88238 var extent = geoExtent(val);
88239 map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
88243 function calcExtentZoom(extent, dim) {
88244 var tl = projection([extent[0][0], extent[1][1]]);
88245 var br = projection([extent[1][0], extent[0][1]]); // Calculate maximum zoom that fits extent
88247 var hFactor = (br[0] - tl[0]) / dim[0];
88248 var vFactor = (br[1] - tl[1]) / dim[1];
88249 var hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2;
88250 var vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2;
88251 var newZoom = map.zoom() - Math.max(hZoomDiff, vZoomDiff);
88255 map.extentZoom = function (val) {
88256 return calcExtentZoom(geoExtent(val), _dimensions);
88259 map.trimmedExtentZoom = function (val) {
88262 var trimmed = [_dimensions[0] - trimX, _dimensions[1] - trimY];
88263 return calcExtentZoom(geoExtent(val), trimmed);
88266 map.withinEditableZoom = function () {
88267 return map.zoom() >= context.minEditableZoom();
88270 map.isInWideSelection = function () {
88271 return !map.withinEditableZoom() && context.selectedIDs().length;
88274 map.editableDataEnabled = function (skipZoomCheck) {
88275 var layer = context.layers().layer('osm');
88276 if (!layer || !layer.enabled()) return false;
88277 return skipZoomCheck || map.withinEditableZoom();
88280 map.notesEditable = function () {
88281 var layer = context.layers().layer('notes');
88282 if (!layer || !layer.enabled()) return false;
88283 return map.withinEditableZoom();
88286 map.minzoom = function (val) {
88287 if (!arguments.length) return _minzoom;
88292 map.toggleHighlightEdited = function () {
88293 surface.classed('highlight-edited', !surface.classed('highlight-edited'));
88294 map.pan([0, 0]); // trigger a redraw
88296 dispatch.call('changeHighlighting', this);
88299 map.areaFillOptions = ['wireframe', 'partial', 'full'];
88301 map.activeAreaFill = function (val) {
88302 if (!arguments.length) return corePreferences('area-fill') || 'partial';
88303 corePreferences('area-fill', val);
88305 if (val !== 'wireframe') {
88306 corePreferences('area-fill-toggle', val);
88310 map.pan([0, 0]); // trigger a redraw
88312 dispatch.call('changeAreaFill', this);
88316 map.toggleWireframe = function () {
88317 var activeFill = map.activeAreaFill();
88319 if (activeFill === 'wireframe') {
88320 activeFill = corePreferences('area-fill-toggle') || 'partial';
88322 activeFill = 'wireframe';
88325 map.activeAreaFill(activeFill);
88328 function updateAreaFill() {
88329 var activeFill = map.activeAreaFill();
88330 map.areaFillOptions.forEach(function (opt) {
88331 surface.classed('fill-' + opt, Boolean(opt === activeFill));
88335 map.layers = function () {
88339 map.doubleUpHandler = function () {
88340 return _doubleUpHandler;
88343 return utilRebind(map, dispatch, 'on');
88346 function rendererPhotos(context) {
88347 var dispatch = dispatch$8('change');
88348 var _layerIDs = ['streetside', 'mapillary', 'mapillary-map-features', 'mapillary-signs', 'kartaview'];
88349 var _allPhotoTypes = ['flat', 'panoramic'];
88351 var _shownPhotoTypes = _allPhotoTypes.slice(); // shallow copy
88354 var _dateFilters = ['fromDate', 'toDate'];
88362 function photos() {}
88364 function updateStorage() {
88365 if (window.mocha) return;
88366 var hash = utilStringQs(window.location.hash);
88367 var enabled = context.layers().all().filter(function (d) {
88368 return _layerIDs.indexOf(d.id) !== -1 && d.layer && d.layer.supported() && d.layer.enabled();
88369 }).map(function (d) {
88373 if (enabled.length) {
88374 hash.photo_overlay = enabled.join(',');
88376 delete hash.photo_overlay;
88379 window.location.replace('#' + utilQsString(hash, true));
88382 photos.overlayLayerIDs = function () {
88386 photos.allPhotoTypes = function () {
88387 return _allPhotoTypes;
88390 photos.dateFilters = function () {
88391 return _dateFilters;
88394 photos.dateFilterValue = function (val) {
88395 return val === _dateFilters[0] ? _fromDate : _toDate;
88398 photos.setDateFilter = function (type, val, updateUrl) {
88399 // validate the date
88400 var date = val && new Date(val);
88402 if (date && !isNaN(date)) {
88403 val = date.toISOString().substr(0, 10);
88408 if (type === _dateFilters[0]) {
88411 if (_fromDate && _toDate && new Date(_toDate) < new Date(_fromDate)) {
88412 _toDate = _fromDate;
88416 if (type === _dateFilters[1]) {
88419 if (_fromDate && _toDate && new Date(_toDate) < new Date(_fromDate)) {
88420 _fromDate = _toDate;
88424 dispatch.call('change', this);
88429 if (_fromDate || _toDate) {
88430 rangeString = (_fromDate || '') + '_' + (_toDate || '');
88433 setUrlFilterValue('photo_dates', rangeString);
88437 photos.setUsernameFilter = function (val, updateUrl) {
88438 if (val && typeof val === 'string') val = val.replace(/;/g, ',').split(',');
88441 val = val.map(function (d) {
88443 }).filter(Boolean);
88451 dispatch.call('change', this);
88457 hashString = _usernames.join(',');
88460 setUrlFilterValue('photo_username', hashString);
88464 function setUrlFilterValue(property, val) {
88465 if (!window.mocha) {
88466 var hash = utilStringQs(window.location.hash);
88469 if (hash[property] === val) return;
88470 hash[property] = val;
88472 if (!(property in hash)) return;
88473 delete hash[property];
88476 window.location.replace('#' + utilQsString(hash, true));
88480 function showsLayer(id) {
88481 var layer = context.layers().layer(id);
88482 return layer && layer.supported() && layer.enabled();
88485 photos.shouldFilterByDate = function () {
88486 return showsLayer('mapillary') || showsLayer('kartaview') || showsLayer('streetside');
88489 photos.shouldFilterByPhotoType = function () {
88490 return showsLayer('mapillary') || showsLayer('streetside') && showsLayer('kartaview');
88493 photos.shouldFilterByUsername = function () {
88494 return !showsLayer('mapillary') && showsLayer('kartaview') && !showsLayer('streetside');
88497 photos.showsPhotoType = function (val) {
88498 if (!photos.shouldFilterByPhotoType()) return true;
88499 return _shownPhotoTypes.indexOf(val) !== -1;
88502 photos.showsFlat = function () {
88503 return photos.showsPhotoType('flat');
88506 photos.showsPanoramic = function () {
88507 return photos.showsPhotoType('panoramic');
88510 photos.fromDate = function () {
88514 photos.toDate = function () {
88518 photos.togglePhotoType = function (val) {
88519 var index = _shownPhotoTypes.indexOf(val);
88521 if (index !== -1) {
88522 _shownPhotoTypes.splice(index, 1);
88524 _shownPhotoTypes.push(val);
88527 dispatch.call('change', this);
88531 photos.usernames = function () {
88535 photos.init = function () {
88536 var hash = utilStringQs(window.location.hash);
88538 if (hash.photo_dates) {
88539 // expect format like `photo_dates=2019-01-01_2020-12-31`, but allow a couple different separators
88540 var parts = /^(.*)[–_](.*)$/g.exec(hash.photo_dates.trim());
88541 this.setDateFilter('fromDate', parts && parts.length >= 2 && parts[1], false);
88542 this.setDateFilter('toDate', parts && parts.length >= 3 && parts[2], false);
88545 if (hash.photo_username) {
88546 this.setUsernameFilter(hash.photo_username, false);
88549 if (hash.photo_overlay) {
88550 // support enabling photo layers by default via a URL parameter, e.g. `photo_overlay=kartaview;mapillary;streetside`
88551 var hashOverlayIDs = hash.photo_overlay.replace(/;/g, ',').split(',');
88552 hashOverlayIDs.forEach(function (id) {
88553 if (id === 'openstreetcam') id = 'kartaview'; // legacy alias
88555 var layer = _layerIDs.indexOf(id) !== -1 && context.layers().layer(id);
88556 if (layer && !layer.enabled()) layer.enabled(true);
88561 // support opening a photo via a URL parameter, e.g. `photo=mapillary-fztgSDtLpa08ohPZFZjeRQ`
88562 var photoIds = hash.photo.replace(/;/g, ',').split(',');
88563 var photoId = photoIds.length && photoIds[0].trim();
88564 var results = /(.*)\/(.*)/g.exec(photoId);
88566 if (results && results.length >= 3) {
88567 var serviceId = results[1];
88568 if (serviceId === 'openstreetcam') serviceId = 'kartaview'; // legacy alias
88570 var photoKey = results[2];
88571 var service = services[serviceId];
88573 if (service && service.ensureViewerLoaded) {
88574 // if we're showing a photo then make sure its layer is enabled too
88575 var layer = _layerIDs.indexOf(serviceId) !== -1 && context.layers().layer(serviceId);
88576 if (layer && !layer.enabled()) layer.enabled(true);
88577 var baselineTime = Date.now();
88578 service.on('loadedImages.rendererPhotos', function () {
88579 // don't open the viewer if too much time has elapsed
88580 if (Date.now() - baselineTime > 45000) {
88581 service.on('loadedImages.rendererPhotos', null);
88585 if (!service.cachedImage(photoKey)) return;
88586 service.on('loadedImages.rendererPhotos', null);
88587 service.ensureViewerLoaded(context).then(function () {
88588 service.selectImage(context, photoKey).showViewer(context);
88595 context.layers().on('change.rendererPhotos', updateStorage);
88598 return utilRebind(photos, dispatch, 'on');
88601 function uiAccount(context) {
88602 var osm = context.connection();
88604 function update(selection) {
88607 if (!osm.authenticated()) {
88608 selection.selectAll('.userLink, .logoutLink').classed('hide', true);
88612 osm.userDetails(function (err, details) {
88613 var userLink = selection.select('.userLink'),
88614 logoutLink = selection.select('.logoutLink');
88616 logoutLink.html('');
88617 if (err || !details) return;
88618 selection.selectAll('.userLink, .logoutLink').classed('hide', false); // Link
88620 var userLinkA = userLink.append('a').attr('href', osm.userURL(details.display_name)).attr('target', '_blank'); // Add thumbnail or dont
88622 if (details.image_url) {
88623 userLinkA.append('img').attr('class', 'icon pre-text user-icon').attr('src', details.image_url);
88625 userLinkA.call(svgIcon('#iD-icon-avatar', 'pre-text light'));
88629 userLinkA.append('span').attr('class', 'label').html(details.display_name);
88630 logoutLink.append('a').attr('class', 'logout').attr('href', '#').call(_t.append('logout')).on('click.logout', function (d3_event) {
88631 d3_event.preventDefault();
88637 return function (selection) {
88638 selection.append('li').attr('class', 'userLink').classed('hide', true);
88639 selection.append('li').attr('class', 'logoutLink').classed('hide', true);
88642 osm.on('change.account', function () {
88650 function uiAttribution(context) {
88651 var _selection = select(null);
88653 function render(selection, data, klass) {
88654 var div = selection.selectAll(".".concat(klass)).data([0]);
88655 div = div.enter().append('div').attr('class', klass).merge(div);
88656 var attributions = div.selectAll('.attribution').data(data, function (d) {
88659 attributions.exit().remove();
88660 attributions = attributions.enter().append('span').attr('class', 'attribution').each(function (d, i, nodes) {
88661 var attribution = select(nodes[i]);
88663 if (d.terms_html) {
88664 attribution.html(d.terms_html);
88669 attribution = attribution.append('a').attr('href', d.terms_url).attr('target', '_blank');
88672 var sourceID = d.id.replace(/\./g, '<TX_DOT>');
88673 var terms_text = _t("imagery.".concat(sourceID, ".attribution.text"), {
88674 "default": d.terms_text || d.id || d.name()
88677 if (d.icon && !d.overlay) {
88678 attribution.append('img').attr('class', 'source-image').attr('src', d.icon);
88681 attribution.append('span').attr('class', 'attribution-text').text(terms_text);
88682 }).merge(attributions);
88683 var copyright = attributions.selectAll('.copyright-notice').data(function (d) {
88684 var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
88685 return notice ? [notice] : [];
88687 copyright.exit().remove();
88688 copyright = copyright.enter().append('span').attr('class', 'copyright-notice').merge(copyright);
88689 copyright.text(String);
88692 function update() {
88693 var baselayer = context.background().baseLayerSource();
88695 _selection.call(render, baselayer ? [baselayer] : [], 'base-layer-attribution');
88697 var z = context.map().zoom();
88698 var overlays = context.background().overlayLayerSources() || [];
88700 _selection.call(render, overlays.filter(function (s) {
88701 return s.validZoom(z);
88702 }), 'overlay-layer-attribution');
88705 return function (selection) {
88706 _selection = selection;
88707 context.background().on('change.attribution', update);
88708 context.map().on('move.attribution', throttle(update, 400, {
88715 function uiContributors(context) {
88716 var osm = context.connection(),
88717 debouncedUpdate = debounce(function () {
88722 wrap = select(null);
88724 function update() {
88727 entities = context.history().intersects(context.map().extent());
88728 entities.forEach(function (entity) {
88729 if (entity && entity.user) users[entity.user] = true;
88731 var u = Object.keys(users),
88732 subset = u.slice(0, u.length > limit ? limit - 1 : limit);
88733 wrap.html('').call(svgIcon('#iD-icon-nearby', 'pre-text light'));
88734 var userList = select(document.createElement('span'));
88735 userList.selectAll().data(subset).enter().append('a').attr('class', 'user-link').attr('href', function (d) {
88736 return osm.userURL(d);
88737 }).attr('target', '_blank').text(String);
88739 if (u.length > limit) {
88740 var count = select(document.createElement('span'));
88741 var othersNum = u.length - limit + 1;
88742 count.append('a').attr('target', '_blank').attr('href', function () {
88743 return osm.changesetsURL(context.map().center(), context.map().zoom());
88744 }).text(othersNum);
88745 wrap.append('span').html(_t.html('contributors.truncated_list', {
88748 html: userList.html()
88755 wrap.append('span').html(_t.html('contributors.list', {
88757 html: userList.html()
88764 wrap.transition().style('opacity', 0);
88765 } else if (hidden) {
88766 wrap.transition().style('opacity', 1);
88770 return function (selection) {
88774 osm.on('loaded.contributors', debouncedUpdate);
88775 context.map().on('move.contributors', debouncedUpdate);
88779 var _popoverID = 0;
88780 function uiPopover(klass) {
88781 var _id = _popoverID++;
88783 var _anchorSelection = select(null);
88785 var popover = function popover(selection) {
88786 _anchorSelection = selection;
88787 selection.each(setup);
88790 var _animation = utilFunctor(false);
88792 var _placement = utilFunctor('top'); // top, bottom, left, right
88795 var _alignment = utilFunctor('center'); // leading, center, trailing
88798 var _scrollContainer = utilFunctor(select(null));
88802 var _displayType = utilFunctor('');
88804 var _hasArrow = utilFunctor(true); // use pointer events on supported platforms; fallback to mouse events
88807 var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
88809 popover.displayType = function (val) {
88810 if (arguments.length) {
88811 _displayType = utilFunctor(val);
88814 return _displayType;
88818 popover.hasArrow = function (val) {
88819 if (arguments.length) {
88820 _hasArrow = utilFunctor(val);
88827 popover.placement = function (val) {
88828 if (arguments.length) {
88829 _placement = utilFunctor(val);
88836 popover.alignment = function (val) {
88837 if (arguments.length) {
88838 _alignment = utilFunctor(val);
88845 popover.scrollContainer = function (val) {
88846 if (arguments.length) {
88847 _scrollContainer = utilFunctor(val);
88850 return _scrollContainer;
88854 popover.content = function (val) {
88855 if (arguments.length) {
88863 popover.isShown = function () {
88864 var popoverSelection = _anchorSelection.select('.popover-' + _id);
88866 return !popoverSelection.empty() && popoverSelection.classed('in');
88869 popover.show = function () {
88870 _anchorSelection.each(show);
88873 popover.updateContent = function () {
88874 _anchorSelection.each(updateContent);
88877 popover.hide = function () {
88878 _anchorSelection.each(hide);
88881 popover.toggle = function () {
88882 _anchorSelection.each(toggle);
88885 popover.destroy = function (selection, selector) {
88886 // by default, just destroy the current popover
88887 selector = selector || '.popover-' + _id;
88888 selection.on(_pointerPrefix + 'enter.popover', null).on(_pointerPrefix + 'leave.popover', null).on(_pointerPrefix + 'up.popover', null).on(_pointerPrefix + 'down.popover', null).on('click.popover', null).attr('title', function () {
88889 return this.getAttribute('data-original-title') || this.getAttribute('title');
88890 }).attr('data-original-title', null).selectAll(selector).remove();
88893 popover.destroyAny = function (selection) {
88894 selection.call(popover.destroy, '.popover');
88898 var anchor = select(this);
88900 var animate = _animation.apply(this, arguments);
88902 var popoverSelection = anchor.selectAll('.popover-' + _id).data([0]);
88903 var enter = popoverSelection.enter().append('div').attr('class', 'popover popover-' + _id + ' ' + (klass ? klass : '')).classed('arrowed', _hasArrow.apply(this, arguments));
88904 enter.append('div').attr('class', 'popover-arrow');
88905 enter.append('div').attr('class', 'popover-inner');
88906 popoverSelection = enter.merge(popoverSelection);
88909 popoverSelection.classed('fade', true);
88912 var display = _displayType.apply(this, arguments);
88914 if (display === 'hover') {
88915 var _lastNonMouseEnterTime;
88917 anchor.on(_pointerPrefix + 'enter.popover', function (d3_event) {
88918 if (d3_event.pointerType) {
88919 if (d3_event.pointerType !== 'mouse') {
88920 _lastNonMouseEnterTime = d3_event.timeStamp; // only allow hover behavior for mouse input
88923 } else if (_lastNonMouseEnterTime && d3_event.timeStamp - _lastNonMouseEnterTime < 1500) {
88924 // HACK: iOS 13.4 sends an erroneous `mouse` type pointerenter
88925 // event for non-mouse interactions right after sending
88926 // the correct type pointerenter event. Workaround by discarding
88927 // any mouse event that occurs immediately after a non-mouse event.
88930 } // don't show if buttons are pressed, e.g. during click and drag of map
88933 if (d3_event.buttons !== 0) return;
88934 show.apply(this, arguments);
88935 }).on(_pointerPrefix + 'leave.popover', function () {
88936 hide.apply(this, arguments);
88937 }) // show on focus too for better keyboard navigation support
88938 .on('focus.popover', function () {
88939 show.apply(this, arguments);
88940 }).on('blur.popover', function () {
88941 hide.apply(this, arguments);
88943 } else if (display === 'clickFocus') {
88944 anchor.on(_pointerPrefix + 'down.popover', function (d3_event) {
88945 d3_event.preventDefault();
88946 d3_event.stopPropagation();
88947 }).on(_pointerPrefix + 'up.popover', function (d3_event) {
88948 d3_event.preventDefault();
88949 d3_event.stopPropagation();
88950 }).on('click.popover', toggle);
88951 popoverSelection // This attribute lets the popover take focus
88952 .attr('tabindex', 0).on('blur.popover', function () {
88953 anchor.each(function () {
88954 hide.apply(this, arguments);
88961 var anchor = select(this);
88962 var popoverSelection = anchor.selectAll('.popover-' + _id);
88964 if (popoverSelection.empty()) {
88965 // popover was removed somehow, put it back
88966 anchor.call(popover.destroy);
88967 anchor.each(setup);
88968 popoverSelection = anchor.selectAll('.popover-' + _id);
88971 popoverSelection.classed('in', true);
88973 var displayType = _displayType.apply(this, arguments);
88975 if (displayType === 'clickFocus') {
88976 anchor.classed('active', true);
88977 popoverSelection.node().focus();
88980 anchor.each(updateContent);
88983 function updateContent() {
88984 var anchor = select(this);
88987 anchor.selectAll('.popover-' + _id + ' > .popover-inner').call(_content.apply(this, arguments));
88990 updatePosition.apply(this, arguments); // hack: update multiple times to fix instances where the absolute offset is
88991 // set before the dynamic popover size is calculated by the browser
88993 updatePosition.apply(this, arguments);
88994 updatePosition.apply(this, arguments);
88997 function updatePosition() {
88998 var anchor = select(this);
88999 var popoverSelection = anchor.selectAll('.popover-' + _id);
89001 var scrollContainer = _scrollContainer && _scrollContainer.apply(this, arguments);
89003 var scrollNode = scrollContainer && !scrollContainer.empty() && scrollContainer.node();
89004 var scrollLeft = scrollNode ? scrollNode.scrollLeft : 0;
89005 var scrollTop = scrollNode ? scrollNode.scrollTop : 0;
89007 var placement = _placement.apply(this, arguments);
89009 popoverSelection.classed('left', false).classed('right', false).classed('top', false).classed('bottom', false).classed(placement, true);
89011 var alignment = _alignment.apply(this, arguments);
89013 var alignFactor = 0.5;
89015 if (alignment === 'leading') {
89017 } else if (alignment === 'trailing') {
89021 var anchorFrame = getFrame(anchor.node());
89022 var popoverFrame = getFrame(popoverSelection.node());
89025 switch (placement) {
89028 x: anchorFrame.x + (anchorFrame.w - popoverFrame.w) * alignFactor,
89029 y: anchorFrame.y - popoverFrame.h
89035 x: anchorFrame.x + (anchorFrame.w - popoverFrame.w) * alignFactor,
89036 y: anchorFrame.y + anchorFrame.h
89042 x: anchorFrame.x - popoverFrame.w,
89043 y: anchorFrame.y + (anchorFrame.h - popoverFrame.h) * alignFactor
89049 x: anchorFrame.x + anchorFrame.w,
89050 y: anchorFrame.y + (anchorFrame.h - popoverFrame.h) * alignFactor
89056 if (scrollNode && (placement === 'top' || placement === 'bottom')) {
89057 var initialPosX = position.x;
89059 if (position.x + popoverFrame.w > scrollNode.offsetWidth - 10) {
89060 position.x = scrollNode.offsetWidth - 10 - popoverFrame.w;
89061 } else if (position.x < 10) {
89065 var arrow = anchor.selectAll('.popover-' + _id + ' > .popover-arrow'); // keep the arrow centered on the button, or as close as possible
89067 var arrowPosX = Math.min(Math.max(popoverFrame.w / 2 - (position.x - initialPosX), 10), popoverFrame.w - 10);
89068 arrow.style('left', ~~arrowPosX + 'px');
89071 popoverSelection.style('left', ~~position.x + 'px').style('top', ~~position.y + 'px');
89073 popoverSelection.style('left', null).style('top', null);
89076 function getFrame(node) {
89077 var positionStyle = select(node).style('position');
89079 if (positionStyle === 'absolute' || positionStyle === 'static') {
89081 x: node.offsetLeft - scrollLeft,
89082 y: node.offsetTop - scrollTop,
89083 w: node.offsetWidth,
89084 h: node.offsetHeight
89090 w: node.offsetWidth,
89091 h: node.offsetHeight
89098 var anchor = select(this);
89100 if (_displayType.apply(this, arguments) === 'clickFocus') {
89101 anchor.classed('active', false);
89104 anchor.selectAll('.popover-' + _id).classed('in', false);
89107 function toggle() {
89108 if (select(this).select('.popover-' + _id).classed('in')) {
89109 hide.apply(this, arguments);
89111 show.apply(this, arguments);
89118 function uiTooltip(klass) {
89119 var tooltip = uiPopover((klass || '') + ' tooltip').displayType('hover');
89121 var _title = function _title() {
89122 var title = this.getAttribute('data-original-title');
89127 title = this.getAttribute('title');
89128 this.removeAttribute('title');
89129 this.setAttribute('data-original-title', title);
89135 var _heading = utilFunctor(null);
89137 var _keys = utilFunctor(null);
89139 tooltip.title = function (val) {
89140 if (!arguments.length) return _title;
89141 _title = utilFunctor(val);
89145 tooltip.heading = function (val) {
89146 if (!arguments.length) return _heading;
89147 _heading = utilFunctor(val);
89151 tooltip.keys = function (val) {
89152 if (!arguments.length) return _keys;
89153 _keys = utilFunctor(val);
89157 tooltip.content(function () {
89158 var heading = _heading.apply(this, arguments);
89160 var text = _title.apply(this, arguments);
89162 var keys = _keys.apply(this, arguments);
89164 return function (selection) {
89165 var headingSelect = selection.selectAll('.tooltip-heading').data(heading ? [heading] : []);
89166 headingSelect.exit().remove();
89167 headingSelect.enter().append('div').attr('class', 'tooltip-heading').merge(headingSelect).html(heading);
89168 var textSelect = selection.selectAll('.tooltip-text').data(text ? [text] : []);
89169 textSelect.exit().remove();
89170 textSelect.enter().append('div').attr('class', 'tooltip-text').merge(textSelect).html(text);
89171 var keyhintWrap = selection.selectAll('.keyhint-wrap').data(keys && keys.length ? [0] : []);
89172 keyhintWrap.exit().remove();
89173 var keyhintWrapEnter = keyhintWrap.enter().append('div').attr('class', 'keyhint-wrap');
89174 keyhintWrapEnter.append('span').call(_t.append('tooltip_keyhint'));
89175 keyhintWrap = keyhintWrapEnter.merge(keyhintWrap);
89176 keyhintWrap.selectAll('kbd.shortcut').data(keys && keys.length ? keys : []).enter().append('kbd').attr('class', 'shortcut').html(function (d) {
89184 function uiEditMenu(context) {
89185 var dispatch = dispatch$8('toggled');
89187 var _menu = select(null);
89189 var _operations = []; // the position the menu should be displayed relative to
89191 var _anchorLoc = [0, 0];
89192 var _anchorLocLonLat = [0, 0]; // a string indicating how the menu was opened
89194 var _triggerType = '';
89195 var _vpTopMargin = 85; // viewport top margin
89197 var _vpBottomMargin = 45; // viewport bottom margin
89199 var _vpSideMargin = 35; // viewport side margin
89201 var _menuTop = false;
89205 var _menuWidth; // hardcode these values to make menu positioning easier
89208 var _verticalPadding = 4; // see also `.edit-menu .tooltip` CSS; include margin
89210 var _tooltipWidth = 210; // offset the menu slightly from the target location
89212 var _menuSideMargin = 10;
89213 var _tooltips = [];
89215 var editMenu = function editMenu(selection) {
89216 var isTouchMenu = _triggerType.includes('touch') || _triggerType.includes('pen');
89218 var ops = _operations.filter(function (op) {
89219 return !isTouchMenu || !op.mouseOnly;
89222 if (!ops.length) return;
89223 _tooltips = []; // Position the menu above the anchor for stylus and finger input
89224 // since the mapper's hand likely obscures the screen below the anchor
89226 _menuTop = isTouchMenu; // Show labels for touch input since there aren't hover tooltips
89228 var showLabels = isTouchMenu;
89229 var buttonHeight = showLabels ? 32 : 34;
89232 // Get a general idea of the width based on the length of the label
89233 _menuWidth = 52 + Math.min(120, 6 * Math.max.apply(Math, ops.map(function (op) {
89234 return op.title.length;
89240 _menuHeight = _verticalPadding * 2 + ops.length * buttonHeight;
89241 _menu = selection.append('div').attr('class', 'edit-menu').classed('touch-menu', isTouchMenu).style('padding', _verticalPadding + 'px 0');
89243 var buttons = _menu.selectAll('.edit-menu-item').data(ops); // enter
89246 var buttonsEnter = buttons.enter().append('button').attr('class', function (d) {
89247 return 'edit-menu-item edit-menu-item-' + d.id;
89248 }).style('height', buttonHeight + 'px').on('click', click) // don't listen for `mouseup` because we only care about non-mouse pointer types
89249 .on('pointerup', pointerup).on('pointerdown mousedown', function pointerdown(d3_event) {
89250 // don't let button presses also act as map input - #1869
89251 d3_event.stopPropagation();
89252 }).on('mouseenter.highlight', function (d3_event, d) {
89253 if (!d.relatedEntityIds || select(this).classed('disabled')) return;
89254 utilHighlightEntities(d.relatedEntityIds(), true, context);
89255 }).on('mouseleave.highlight', function (d3_event, d) {
89256 if (!d.relatedEntityIds) return;
89257 utilHighlightEntities(d.relatedEntityIds(), false, context);
89259 buttonsEnter.each(function (d) {
89260 var tooltip = uiTooltip().heading(d.title).title(d.tooltip()).keys([d.keys[0]]);
89262 _tooltips.push(tooltip);
89264 select(this).call(tooltip).append('div').attr('class', 'icon-wrap').call(svgIcon(d.icon && d.icon() || '#iD-operation-' + d.id, 'operation'));
89268 buttonsEnter.append('span').attr('class', 'label').html(function (d) {
89274 buttonsEnter.merge(buttons).classed('disabled', function (d) {
89275 return d.disabled();
89278 var initialScale = context.projection.scale();
89279 context.map().on('move.edit-menu', function () {
89280 if (initialScale !== context.projection.scale()) {
89283 }).on('drawn.edit-menu', function (info) {
89284 if (info.full) updatePosition();
89286 var lastPointerUpType; // `pointerup` is always called before `click`
89288 function pointerup(d3_event) {
89289 lastPointerUpType = d3_event.pointerType;
89292 function click(d3_event, operation) {
89293 d3_event.stopPropagation();
89295 if (operation.relatedEntityIds) {
89296 utilHighlightEntities(operation.relatedEntityIds(), false, context);
89299 if (operation.disabled()) {
89300 if (lastPointerUpType === 'touch' || lastPointerUpType === 'pen') {
89301 // there are no tooltips for touch interactions so flash feedback instead
89302 context.ui().flash.duration(4000).iconName('#iD-operation-' + operation.id).iconClass('operation disabled').label(operation.tooltip)();
89305 if (lastPointerUpType === 'touch' || lastPointerUpType === 'pen') {
89306 context.ui().flash.duration(2000).iconName('#iD-operation-' + operation.id).iconClass('operation').label(operation.annotation() || operation.title)();
89313 lastPointerUpType = null;
89316 dispatch.call('toggled', this, true);
89319 function updatePosition() {
89320 if (!_menu || _menu.empty()) return;
89321 var anchorLoc = context.projection(_anchorLocLonLat);
89322 var viewport = context.surfaceRect();
89324 if (anchorLoc[0] < 0 || anchorLoc[0] > viewport.width || anchorLoc[1] < 0 || anchorLoc[1] > viewport.height) {
89325 // close the menu if it's gone offscreen
89330 var menuLeft = displayOnLeft(viewport);
89331 var offset = [0, 0];
89332 offset[0] = menuLeft ? -1 * (_menuSideMargin + _menuWidth) : _menuSideMargin;
89335 if (anchorLoc[1] - _menuHeight < _vpTopMargin) {
89336 // menu is near top viewport edge, shift downward
89337 offset[1] = -anchorLoc[1] + _vpTopMargin;
89339 offset[1] = -_menuHeight;
89342 if (anchorLoc[1] + _menuHeight > viewport.height - _vpBottomMargin) {
89343 // menu is near bottom viewport edge, shift upwards
89344 offset[1] = -anchorLoc[1] - _menuHeight + viewport.height - _vpBottomMargin;
89350 var origin = geoVecAdd(anchorLoc, offset);
89352 _menu.style('left', origin[0] + 'px').style('top', origin[1] + 'px');
89354 var tooltipSide = tooltipPosition(viewport, menuLeft);
89356 _tooltips.forEach(function (tooltip) {
89357 tooltip.placement(tooltipSide);
89360 function displayOnLeft(viewport) {
89361 if (_mainLocalizer.textDirection() === 'ltr') {
89362 if (anchorLoc[0] + _menuSideMargin + _menuWidth > viewport.width - _vpSideMargin) {
89363 // right menu would be too close to the right viewport edge, go left
89365 } // prefer right menu
89371 if (anchorLoc[0] - _menuSideMargin - _menuWidth < _vpSideMargin) {
89372 // left menu would be too close to the left viewport edge, go right
89374 } // prefer left menu
89381 function tooltipPosition(viewport, menuLeft) {
89382 if (_mainLocalizer.textDirection() === 'ltr') {
89384 // if there's not room for a right-side menu then there definitely
89385 // isn't room for right-side tooltips
89389 if (anchorLoc[0] + _menuSideMargin + _menuWidth + _tooltipWidth > viewport.width - _vpSideMargin) {
89390 // right tooltips would be too close to the right viewport edge, go left
89392 } // prefer right tooltips
89402 if (anchorLoc[0] - _menuSideMargin - _menuWidth - _tooltipWidth < _vpSideMargin) {
89403 // left tooltips would be too close to the left viewport edge, go right
89405 } // prefer left tooltips
89413 editMenu.close = function () {
89414 context.map().on('move.edit-menu', null).on('drawn.edit-menu', null);
89419 dispatch.call('toggled', this, false);
89422 editMenu.anchorLoc = function (val) {
89423 if (!arguments.length) return _anchorLoc;
89425 _anchorLocLonLat = context.projection.invert(_anchorLoc);
89429 editMenu.triggerType = function (val) {
89430 if (!arguments.length) return _triggerType;
89431 _triggerType = val;
89435 editMenu.operations = function (val) {
89436 if (!arguments.length) return _operations;
89441 return utilRebind(editMenu, dispatch, 'on');
89444 function uiFeatureInfo(context) {
89445 function update(selection) {
89446 var features = context.features();
89447 var stats = features.stats();
89449 var hiddenList = features.hidden().map(function (k) {
89452 return _t.html('inspector.title_count', {
89454 html: _t.html('feature.' + k + '.description')
89461 }).filter(Boolean);
89462 selection.html('');
89464 if (hiddenList.length) {
89465 var tooltipBehavior = uiTooltip().placement('top').title(function () {
89466 return hiddenList.join('<br/>');
89468 selection.append('a').attr('class', 'chip').attr('href', '#').call(_t.append('feature_info.hidden_warning', {
89470 })).call(tooltipBehavior).on('click', function (d3_event) {
89471 tooltipBehavior.hide();
89472 d3_event.preventDefault(); // open the Map Data pane
89474 context.ui().togglePanes(context.container().select('.map-panes .map-data-pane'));
89478 selection.classed('hide', !hiddenList.length);
89481 return function (selection) {
89483 context.features().on('change.feature_info', function () {
89489 function uiFlash(context) {
89492 var _duration = 2000;
89493 var _iconName = '#iD-icon-no';
89494 var _iconClass = 'disabled';
89499 _flashTimer.stop();
89502 context.container().select('.main-footer-wrap').classed('footer-hide', true).classed('footer-show', false);
89503 context.container().select('.flash-wrap').classed('footer-hide', false).classed('footer-show', true);
89504 var content = context.container().select('.flash-wrap').selectAll('.flash-content').data([0]); // Enter
89506 var contentEnter = content.enter().append('div').attr('class', 'flash-content');
89507 var iconEnter = contentEnter.append('svg').attr('class', 'flash-icon icon').append('g').attr('transform', 'translate(10,10)');
89508 iconEnter.append('circle').attr('r', 9);
89509 iconEnter.append('use').attr('transform', 'translate(-7,-7)').attr('width', '14').attr('height', '14');
89510 contentEnter.append('div').attr('class', 'flash-text'); // Update
89512 content = content.merge(contentEnter);
89513 content.selectAll('.flash-icon').attr('class', 'icon flash-icon ' + (_iconClass || ''));
89514 content.selectAll('.flash-icon use').attr('xlink:href', _iconName);
89515 content.selectAll('.flash-text').attr('class', 'flash-text').html(_label);
89516 _flashTimer = d3_timeout(function () {
89517 _flashTimer = null;
89518 context.container().select('.main-footer-wrap').classed('footer-hide', false).classed('footer-show', true);
89519 context.container().select('.flash-wrap').classed('footer-hide', true).classed('footer-show', false);
89524 flash.duration = function (_) {
89525 if (!arguments.length) return _duration;
89530 flash.label = function (_) {
89531 if (!arguments.length) return _label;
89536 flash.iconName = function (_) {
89537 if (!arguments.length) return _iconName;
89542 flash.iconClass = function (_) {
89543 if (!arguments.length) return _iconClass;
89551 function uiFullScreen(context) {
89552 var element = context.container().node(); // var button = d3_select(null);
89554 function getFullScreenFn() {
89555 if (element.requestFullscreen) {
89556 return element.requestFullscreen;
89557 } else if (element.msRequestFullscreen) {
89558 return element.msRequestFullscreen;
89559 } else if (element.mozRequestFullScreen) {
89560 return element.mozRequestFullScreen;
89561 } else if (element.webkitRequestFullscreen) {
89562 return element.webkitRequestFullscreen;
89566 function getExitFullScreenFn() {
89567 if (document.exitFullscreen) {
89568 return document.exitFullscreen;
89569 } else if (document.msExitFullscreen) {
89570 return document.msExitFullscreen;
89571 } else if (document.mozCancelFullScreen) {
89572 return document.mozCancelFullScreen;
89573 } else if (document.webkitExitFullscreen) {
89574 return document.webkitExitFullscreen;
89578 function isFullScreen() {
89579 return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement;
89582 function isSupported() {
89583 return !!getFullScreenFn();
89586 function fullScreen(d3_event) {
89587 d3_event.preventDefault();
89589 if (!isFullScreen()) {
89590 // button.classed('active', true);
89591 getFullScreenFn().apply(element);
89593 // button.classed('active', false);
89594 getExitFullScreenFn().apply(document);
89598 return function () {
89600 if (!isSupported()) return; // button = selection.append('button')
89601 // .attr('title', t('full_screen'))
89602 // .on('click', fullScreen)
89604 // button.append('span')
89605 // .attr('class', 'icon full-screen');
89607 var detected = utilDetect();
89608 var keys = detected.os === 'mac' ? [uiCmd('⌃⌘F'), 'f11'] : ['f11'];
89609 context.keybinding().on(keys, fullScreen);
89613 function uiGeolocate(context) {
89614 var _geolocationOptions = {
89615 // prioritize speed and power usage over precision
89616 enableHighAccuracy: false,
89617 // don't hang indefinitely getting the location
89618 timeout: 6000 // 6sec
89622 var _locating = uiLoading(context).message(_t.html('geolocate.locating')).blocking(true);
89624 var _layer = context.layers().layer('geolocate');
89632 var _button = select(null);
89635 if (context.inIntro()) return;
89637 if (!_layer.enabled() && !_locating.isShown()) {
89638 // This timeout ensures that we still call finish() even if
89639 // the user declines to share their location in Firefox
89640 _timeoutID = setTimeout(error, 10000
89643 context.container().call(_locating); // get the latest position even if we already have one
89645 navigator.geolocation.getCurrentPosition(success, error, _geolocationOptions);
89649 _layer.enabled(null, false);
89651 updateButtonState();
89655 function zoomTo() {
89656 context.enter(modeBrowse(context));
89657 var map = context.map();
89659 _layer.enabled(_position, true);
89661 updateButtonState();
89662 map.centerZoomEase(_extent.center(), Math.min(20, map.extentZoom(_extent)));
89665 function success(geolocation) {
89666 _position = geolocation;
89667 var coords = _position.coords;
89668 _extent = geoExtent([coords.longitude, coords.latitude]).padByMeters(coords.accuracy);
89675 // use the position from a previous call if we have one
89678 context.ui().flash.label(_t.html('geolocate.location_unavailable')).iconName('#iD-icon-geolocate')();
89684 function finish() {
89685 _locating.close(); // unblock ui
89689 clearTimeout(_timeoutID);
89692 _timeoutID = undefined;
89695 function updateButtonState() {
89696 _button.classed('active', _layer.enabled());
89698 _button.attr('aria-pressed', _layer.enabled());
89701 return function (selection) {
89702 if (!navigator.geolocation || !navigator.geolocation.getCurrentPosition) return;
89703 _button = selection.append('button').on('click', click).attr('aria-pressed', false).call(svgIcon('#iD-icon-geolocate', 'light')).call(uiTooltip().placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left').title(_t.html('geolocate.title')).keys([_t('geolocate.key')]));
89704 context.keybinding().on(_t('geolocate.key'), click);
89708 function uiPanelBackground(context) {
89709 var background = context.background();
89710 var _currSourceName = null;
89711 var _metadata = {};
89712 var _metadataKeys = ['zoom', 'vintage', 'source', 'description', 'resolution', 'accuracy'];
89714 var debouncedRedraw = debounce(redraw, 250);
89716 function redraw(selection) {
89717 var source = background.baseLayerSource();
89718 if (!source) return;
89719 var isDG = source.id.match(/^DigitalGlobe/i) !== null;
89720 var sourceLabel = source.label();
89722 if (_currSourceName !== sourceLabel) {
89723 _currSourceName = sourceLabel;
89727 selection.html('');
89728 var list = selection.append('ul').attr('class', 'background-info');
89729 list.append('li').html(_currSourceName);
89731 _metadataKeys.forEach(function (k) {
89732 // DigitalGlobe vintage is available in raster layers for now.
89733 if (isDG && k === 'vintage') return;
89734 list.append('li').attr('class', 'background-info-list-' + k).classed('hide', !_metadata[k]).call(_t.append('info_panels.background.' + k, {
89736 })).append('span').attr('class', 'background-info-span-' + k).text(_metadata[k]);
89739 debouncedGetMetadata(selection);
89740 var toggleTiles = context.getDebug('tile') ? 'hide_tiles' : 'show_tiles';
89741 selection.append('a').call(_t.append('info_panels.background.' + toggleTiles)).attr('href', '#').attr('class', 'button button-toggle-tiles').on('click', function (d3_event) {
89742 d3_event.preventDefault();
89743 context.setDebug('tile', !context.getDebug('tile'));
89744 selection.call(redraw);
89748 var key = source.id + '-vintage';
89749 var sourceVintage = context.background().findSource(key);
89750 var showsVintage = context.background().showsLayer(sourceVintage);
89751 var toggleVintage = showsVintage ? 'hide_vintage' : 'show_vintage';
89752 selection.append('a').call(_t.append('info_panels.background.' + toggleVintage)).attr('href', '#').attr('class', 'button button-toggle-vintage').on('click', function (d3_event) {
89753 d3_event.preventDefault();
89754 context.background().toggleOverlayLayer(sourceVintage);
89755 selection.call(redraw);
89757 } // disable if necessary
89760 ['DigitalGlobe-Premium', 'DigitalGlobe-Standard'].forEach(function (layerId) {
89761 if (source.id !== layerId) {
89762 var key = layerId + '-vintage';
89763 var sourceVintage = context.background().findSource(key);
89765 if (context.background().showsLayer(sourceVintage)) {
89766 context.background().toggleOverlayLayer(sourceVintage);
89772 var debouncedGetMetadata = debounce(getMetadata, 250);
89774 function getMetadata(selection) {
89775 var tile = context.container().select('.layer-background img.tile-center'); // tile near viewport center
89777 if (tile.empty()) return;
89778 var sourceName = _currSourceName;
89779 var d = tile.datum();
89780 var zoom = d && d.length >= 3 && d[2] || Math.floor(context.map().zoom());
89781 var center = context.map().center(); // update zoom
89783 _metadata.zoom = String(zoom);
89784 selection.selectAll('.background-info-list-zoom').classed('hide', false).selectAll('.background-info-span-zoom').text(_metadata.zoom);
89785 if (!d || !d.length >= 3) return;
89786 background.baseLayerSource().getMetadata(center, d, function (err, result) {
89787 if (err || _currSourceName !== sourceName) return; // update vintage
89789 var vintage = result.vintage;
89790 _metadata.vintage = vintage && vintage.range || _t('info_panels.background.unknown');
89791 selection.selectAll('.background-info-list-vintage').classed('hide', false).selectAll('.background-info-span-vintage').text(_metadata.vintage); // update other _metadata
89793 _metadataKeys.forEach(function (k) {
89794 if (k === 'zoom' || k === 'vintage') return; // done already
89796 var val = result[k];
89797 _metadata[k] = val;
89798 selection.selectAll('.background-info-list-' + k).classed('hide', !val).selectAll('.background-info-span-' + k).text(val);
89803 var panel = function panel(selection) {
89804 selection.call(redraw);
89805 context.map().on('drawn.info-background', function () {
89806 selection.call(debouncedRedraw);
89807 }).on('move.info-background', function () {
89808 selection.call(debouncedGetMetadata);
89812 panel.off = function () {
89813 context.map().on('drawn.info-background', null).on('move.info-background', null);
89816 panel.id = 'background';
89817 panel.label = _t.html('info_panels.background.title');
89818 panel.key = _t('info_panels.background.key');
89822 function uiPanelHistory(context) {
89825 function displayTimestamp(timestamp) {
89826 if (!timestamp) return _t('info_panels.history.unknown');
89835 var d = new Date(timestamp);
89836 if (isNaN(d.getTime())) return _t('info_panels.history.unknown');
89837 return d.toLocaleString(_mainLocalizer.localeCode(), options);
89840 function displayUser(selection, userName) {
89842 selection.append('span').call(_t.append('info_panels.history.unknown'));
89846 selection.append('span').attr('class', 'user-name').text(userName);
89847 var links = selection.append('div').attr('class', 'links');
89850 links.append('a').attr('class', 'user-osm-link').attr('href', osm.userURL(userName)).attr('target', '_blank').call(_t.append('info_panels.history.profile_link'));
89853 links.append('a').attr('class', 'user-hdyc-link').attr('href', 'https://hdyc.neis-one.org/?' + userName).attr('target', '_blank').attr('tabindex', -1).text('HDYC');
89856 function displayChangeset(selection, changeset) {
89858 selection.append('span').call(_t.append('info_panels.history.unknown'));
89862 selection.append('span').attr('class', 'changeset-id').text(changeset);
89863 var links = selection.append('div').attr('class', 'links');
89866 links.append('a').attr('class', 'changeset-osm-link').attr('href', osm.changesetURL(changeset)).attr('target', '_blank').call(_t.append('info_panels.history.changeset_link'));
89869 links.append('a').attr('class', 'changeset-osmcha-link').attr('href', 'https://osmcha.org/changesets/' + changeset).attr('target', '_blank').text('OSMCha');
89870 links.append('a').attr('class', 'changeset-achavi-link').attr('href', 'https://overpass-api.de/achavi/?changeset=' + changeset).attr('target', '_blank').text('Achavi');
89873 function redraw(selection) {
89874 var selectedNoteID = context.selectedNoteID();
89875 osm = context.connection();
89876 var selected, note, entity;
89878 if (selectedNoteID && osm) {
89880 selected = [_t.html('note.note') + ' ' + selectedNoteID];
89881 note = osm.getNote(selectedNoteID);
89883 // selected 1..n entities
89884 selected = context.selectedIDs().filter(function (e) {
89885 return context.hasEntity(e);
89888 if (selected.length) {
89889 entity = context.entity(selected[0]);
89893 var singular = selected.length === 1 ? selected[0] : null;
89894 selection.html('');
89897 selection.append('h4').attr('class', 'history-heading').html(singular);
89899 selection.append('h4').attr('class', 'history-heading').call(_t.append('info_panels.selected', {
89904 if (!singular) return;
89907 selection.call(redrawEntity, entity);
89909 selection.call(redrawNote, note);
89913 function redrawNote(selection, note) {
89914 if (!note || note.isNew()) {
89915 selection.append('div').call(_t.append('info_panels.history.note_no_history'));
89919 var list = selection.append('ul');
89920 list.append('li').call(_t.append('info_panels.history.note_comments', {
89922 })).append('span').text(note.comments.length);
89924 if (note.comments.length) {
89925 list.append('li').call(_t.append('info_panels.history.note_created_date', {
89927 })).append('span').text(displayTimestamp(note.comments[0].date));
89928 list.append('li').call(_t.append('info_panels.history.note_created_user', {
89930 })).call(displayUser, note.comments[0].user);
89934 selection.append('a').attr('class', 'view-history-on-osm').attr('target', '_blank').attr('href', osm.noteURL(note)).call(svgIcon('#iD-icon-out-link', 'inline')).append('span').call(_t.append('info_panels.history.note_link_text'));
89938 function redrawEntity(selection, entity) {
89939 if (!entity || entity.isNew()) {
89940 selection.append('div').call(_t.append('info_panels.history.no_history'));
89944 var links = selection.append('div').attr('class', 'links');
89947 links.append('a').attr('class', 'view-history-on-osm').attr('href', osm.historyURL(entity)).attr('target', '_blank').call(_t.append('info_panels.history.history_link'));
89950 links.append('a').attr('class', 'pewu-history-viewer-link').attr('href', 'https://pewu.github.io/osm-history/#/' + entity.type + '/' + entity.osmId()).attr('target', '_blank').attr('tabindex', -1).text('PeWu');
89951 var list = selection.append('ul');
89952 list.append('li').call(_t.append('info_panels.history.version', {
89954 })).append('span').text(entity.version);
89955 list.append('li').call(_t.append('info_panels.history.last_edit', {
89957 })).append('span').text(displayTimestamp(entity.timestamp));
89958 list.append('li').call(_t.append('info_panels.history.edited_by', {
89960 })).call(displayUser, entity.user);
89961 list.append('li').call(_t.append('info_panels.history.changeset', {
89963 })).call(displayChangeset, entity.changeset);
89966 var panel = function panel(selection) {
89967 selection.call(redraw);
89968 context.map().on('drawn.info-history', function () {
89969 selection.call(redraw);
89971 context.on('enter.info-history', function () {
89972 selection.call(redraw);
89976 panel.off = function () {
89977 context.map().on('drawn.info-history', null);
89978 context.on('enter.info-history', null);
89981 panel.id = 'history';
89982 panel.label = _t.html('info_panels.history.title');
89983 panel.key = _t('info_panels.history.key');
89987 var OSM_PRECISION = 7;
89989 * Returns a localized representation of the given length measurement.
89991 * @param {Number} m area in meters
89992 * @param {Boolean} isImperial true for U.S. customary units; false for metric
89995 function displayLength(m, isImperial) {
89996 var d = m * (isImperial ? 3.28084 : 1);
90009 unit = 'kilometers';
90015 return _t('units.' + unit, {
90016 quantity: d.toLocaleString(_mainLocalizer.localeCode(), {
90017 maximumSignificantDigits: 4
90022 * Returns a localized representation of the given area measurement.
90024 * @param {Number} m2 area in square meters
90025 * @param {Boolean} isImperial true for U.S. customary units; false for metric
90028 function displayArea(m2, isImperial) {
90029 var locale = _mainLocalizer.localeCode();
90030 var d = m2 * (isImperial ? 10.7639111056 : 1);
90036 if (d >= 6969600) {
90037 // > 0.25mi² show mi²
90039 unit1 = 'square_miles';
90042 unit1 = 'square_feet';
90045 if (d > 4356 && d < 43560000) {
90046 // 0.1 - 1000 acres
90052 // > 0.25km² show km²
90054 unit1 = 'square_kilometers';
90057 unit1 = 'square_meters';
90060 if (d > 1000 && d < 10000000) {
90061 // 0.1 - 1000 hectares
90063 unit2 = 'hectares';
90067 area = _t('units.' + unit1, {
90068 quantity: d1.toLocaleString(locale, {
90069 maximumSignificantDigits: 4
90074 return _t('units.area_pair', {
90076 area2: _t('units.' + unit2, {
90077 quantity: d2.toLocaleString(locale, {
90078 maximumSignificantDigits: 2
90087 function wrap(x, min, max) {
90089 return ((x - min) % d + d) % d + min;
90092 function clamp(x, min, max) {
90093 return Math.max(min, Math.min(x, max));
90096 function displayCoordinate(deg, pos, neg) {
90097 var locale = _mainLocalizer.localeCode();
90098 var min = (Math.abs(deg) - Math.floor(Math.abs(deg))) * 60;
90099 var sec = (min - Math.floor(min)) * 60;
90100 var displayDegrees = _t('units.arcdegrees', {
90101 quantity: Math.floor(Math.abs(deg)).toLocaleString(locale)
90103 var displayCoordinate;
90105 if (Math.floor(sec) > 0) {
90106 displayCoordinate = displayDegrees + _t('units.arcminutes', {
90107 quantity: Math.floor(min).toLocaleString(locale)
90108 }) + _t('units.arcseconds', {
90109 quantity: Math.round(sec).toLocaleString(locale)
90111 } else if (Math.floor(min) > 0) {
90112 displayCoordinate = displayDegrees + _t('units.arcminutes', {
90113 quantity: Math.round(min).toLocaleString(locale)
90116 displayCoordinate = _t('units.arcdegrees', {
90117 quantity: Math.round(Math.abs(deg)).toLocaleString(locale)
90122 return displayCoordinate;
90124 return _t('units.coordinate', {
90125 coordinate: displayCoordinate,
90126 direction: _t('units.' + (deg > 0 ? pos : neg))
90131 * Returns given coordinate pair in degree-minute-second format.
90133 * @param {Array<Number>} coord longitude and latitude
90137 function dmsCoordinatePair(coord) {
90138 return _t('units.coordinate_pair', {
90139 latitude: displayCoordinate(clamp(coord[1], -90, 90), 'north', 'south'),
90140 longitude: displayCoordinate(wrap(coord[0], -180, 180), 'east', 'west')
90144 * Returns the given coordinate pair in decimal format.
90145 * note: unlocalized to avoid comma ambiguity - see #4765
90147 * @param {Array<Number>} coord longitude and latitude
90150 function decimalCoordinatePair(coord) {
90151 return _t('units.coordinate_pair', {
90152 latitude: clamp(coord[1], -90, 90).toFixed(OSM_PRECISION),
90153 longitude: wrap(coord[0], -180, 180).toFixed(OSM_PRECISION)
90157 function uiPanelLocation(context) {
90158 var currLocation = '';
90160 function redraw(selection) {
90161 selection.html('');
90162 var list = selection.append('ul'); // Mouse coordinates
90164 var coord = context.map().mouseCoordinates();
90166 if (coord.some(isNaN)) {
90167 coord = context.map().center();
90170 list.append('li').text(dmsCoordinatePair(coord)).append('li').text(decimalCoordinatePair(coord)); // Location Info
90172 selection.append('div').attr('class', 'location-info').text(currLocation || ' ');
90173 debouncedGetLocation(selection, coord);
90176 var debouncedGetLocation = debounce(getLocation, 250);
90178 function getLocation(selection, coord) {
90179 if (!services.geocoder) {
90180 currLocation = _t('info_panels.location.unknown_location');
90181 selection.selectAll('.location-info').text(currLocation);
90183 services.geocoder.reverse(coord, function (err, result) {
90184 currLocation = result ? result.display_name : _t('info_panels.location.unknown_location');
90185 selection.selectAll('.location-info').text(currLocation);
90190 var panel = function panel(selection) {
90191 selection.call(redraw);
90192 context.surface().on(('PointerEvent' in window ? 'pointer' : 'mouse') + 'move.info-location', function () {
90193 selection.call(redraw);
90197 panel.off = function () {
90198 context.surface().on('.info-location', null);
90201 panel.id = 'location';
90202 panel.label = _t.html('info_panels.location.title');
90203 panel.key = _t('info_panels.location.key');
90207 function uiPanelMeasurement(context) {
90208 function radiansToMeters(r) {
90209 // using WGS84 authalic radius (6371007.1809 m)
90210 return r * 6371007.1809;
90213 function steradiansToSqmeters(r) {
90214 // http://gis.stackexchange.com/a/124857/40446
90215 return r / (4 * Math.PI) * 510065621724000;
90218 function toLineString(feature) {
90219 if (feature.type === 'LineString') return feature;
90221 type: 'LineString',
90225 if (feature.type === 'Polygon') {
90226 result.coordinates = feature.coordinates[0];
90227 } else if (feature.type === 'MultiPolygon') {
90228 result.coordinates = feature.coordinates[0][0];
90234 var _isImperial = !_mainLocalizer.usesMetric();
90236 function redraw(selection) {
90237 var graph = context.graph();
90238 var selectedNoteID = context.selectedNoteID();
90239 var osm = services.osm;
90240 var localeCode = _mainLocalizer.localeCode();
90242 var center, location, centroid;
90243 var closed, geometry;
90244 var totalNodeCount,
90249 if (selectedNoteID && osm) {
90251 var note = osm.getNote(selectedNoteID);
90252 heading = _t.html('note.note') + ' ' + selectedNoteID;
90253 location = note.loc;
90256 // selected 1..n entities
90257 var selectedIDs = context.selectedIDs().filter(function (id) {
90258 return context.hasEntity(id);
90260 var selected = selectedIDs.map(function (id) {
90261 return context.entity(id);
90263 heading = selected.length === 1 ? selected[0].id : _t.html('info_panels.selected', {
90267 if (selected.length) {
90268 var extent = geoExtent();
90270 for (var i in selected) {
90271 var entity = selected[i];
90273 extent._extend(entity.extent(graph));
90275 geometry = entity.geometry(graph);
90277 if (geometry === 'line' || geometry === 'area') {
90278 closed = entity.type === 'relation' || entity.isClosed() && !entity.isDegenerate();
90279 var feature = entity.asGeoJSON(graph);
90280 length += radiansToMeters(d3_geoLength(toLineString(feature)));
90281 centroid = d3_geoPath(context.projection).centroid(entity.asGeoJSON(graph));
90282 centroid = centroid && context.projection.invert(centroid);
90284 if (!centroid || !isFinite(centroid[0]) || !isFinite(centroid[1])) {
90285 centroid = entity.extent(graph).center();
90289 area += steradiansToSqmeters(entity.area(graph));
90294 if (selected.length > 1) {
90300 if (selected.length === 2 && selected[0].type === 'node' && selected[1].type === 'node') {
90301 distance = geoSphericalDistance(selected[0].loc, selected[1].loc);
90304 if (selected.length === 1 && selected[0].type === 'node') {
90305 location = selected[0].loc;
90307 totalNodeCount = utilGetAllNodes(selectedIDs, context.graph()).length;
90310 if (!location && !centroid) {
90311 center = extent.center();
90316 selection.html('');
90319 selection.append('h4').attr('class', 'measurement-heading').html(heading);
90322 var list = selection.append('ul');
90326 list.append('li').call(_t.append('info_panels.measurement.geometry', {
90328 })).append('span').html(closed ? _t.html('info_panels.measurement.closed_' + geometry) : _t.html('geometry.' + geometry));
90331 if (totalNodeCount) {
90332 list.append('li').call(_t.append('info_panels.measurement.node_count', {
90334 })).append('span').text(totalNodeCount.toLocaleString(localeCode));
90338 list.append('li').call(_t.append('info_panels.measurement.area', {
90340 })).append('span').text(displayArea(area, _isImperial));
90344 list.append('li').call(_t.append('info_panels.measurement.' + (closed ? 'perimeter' : 'length'), {
90346 })).append('span').text(displayLength(length, _isImperial));
90349 if (typeof distance === 'number') {
90350 list.append('li').call(_t.append('info_panels.measurement.distance', {
90352 })).append('span').text(displayLength(distance, _isImperial));
90356 coordItem = list.append('li').call(_t.append('info_panels.measurement.location', {
90359 coordItem.append('span').text(dmsCoordinatePair(location));
90360 coordItem.append('span').text(decimalCoordinatePair(location));
90364 coordItem = list.append('li').call(_t.append('info_panels.measurement.centroid', {
90367 coordItem.append('span').text(dmsCoordinatePair(centroid));
90368 coordItem.append('span').text(decimalCoordinatePair(centroid));
90372 coordItem = list.append('li').call(_t.append('info_panels.measurement.center', {
90375 coordItem.append('span').text(dmsCoordinatePair(center));
90376 coordItem.append('span').text(decimalCoordinatePair(center));
90379 if (length || area || typeof distance === 'number') {
90380 var toggle = _isImperial ? 'imperial' : 'metric';
90381 selection.append('a').call(_t.append('info_panels.measurement.' + toggle)).attr('href', '#').attr('class', 'button button-toggle-units').on('click', function (d3_event) {
90382 d3_event.preventDefault();
90383 _isImperial = !_isImperial;
90384 selection.call(redraw);
90389 var panel = function panel(selection) {
90390 selection.call(redraw);
90391 context.map().on('drawn.info-measurement', function () {
90392 selection.call(redraw);
90394 context.on('enter.info-measurement', function () {
90395 selection.call(redraw);
90399 panel.off = function () {
90400 context.map().on('drawn.info-measurement', null);
90401 context.on('enter.info-measurement', null);
90404 panel.id = 'measurement';
90405 panel.label = _t.html('info_panels.measurement.title');
90406 panel.key = _t('info_panels.measurement.key');
90410 var uiInfoPanels = {
90411 background: uiPanelBackground,
90412 history: uiPanelHistory,
90413 location: uiPanelLocation,
90414 measurement: uiPanelMeasurement
90417 function uiInfo(context) {
90418 var ids = Object.keys(uiInfoPanels);
90419 var wasActive = ['measurement'];
90421 var active = {}; // create panels
90423 ids.forEach(function (k) {
90425 panels[k] = uiInfoPanels[k](context);
90430 function info(selection) {
90431 function redraw() {
90432 var activeids = ids.filter(function (k) {
90435 var containers = infoPanels.selectAll('.panel-container').data(activeids, function (k) {
90438 containers.exit().style('opacity', 1).transition().duration(200).style('opacity', 0).on('end', function (d) {
90439 select(this).call(panels[d].off).remove();
90441 var enter = containers.enter().append('div').attr('class', function (d) {
90442 return 'fillD2 panel-container panel-container-' + d;
90444 enter.style('opacity', 0).transition().duration(200).style('opacity', 1);
90445 var title = enter.append('div').attr('class', 'panel-title fillD2');
90446 title.append('h3').html(function (d) {
90447 return panels[d].label;
90449 title.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function (d3_event, d) {
90450 d3_event.stopImmediatePropagation();
90451 d3_event.preventDefault();
90453 }).call(svgIcon('#iD-icon-close'));
90454 enter.append('div').attr('class', function (d) {
90455 return 'panel-content panel-content-' + d;
90456 }); // redraw the panels
90458 infoPanels.selectAll('.panel-content').each(function (d) {
90459 select(this).call(panels[d]);
90463 info.toggle = function (which) {
90464 var activeids = ids.filter(function (k) {
90470 active[which] = !active[which];
90472 if (activeids.length === 1 && activeids[0] === which) {
90473 // none active anymore
90474 wasActive = [which];
90477 context.container().select('.' + which + '-panel-toggle-item').classed('active', active[which]).select('input').property('checked', active[which]);
90480 if (activeids.length) {
90481 wasActive = activeids;
90482 activeids.forEach(function (k) {
90486 wasActive.forEach(function (k) {
90495 var infoPanels = selection.selectAll('.info-panels').data([0]);
90496 infoPanels = infoPanels.enter().append('div').attr('class', 'info-panels').merge(infoPanels);
90498 context.keybinding().on(uiCmd('⌘' + _t('info_panels.key')), function (d3_event) {
90499 d3_event.stopImmediatePropagation();
90500 d3_event.preventDefault();
90503 ids.forEach(function (k) {
90504 var key = _t('info_panels.' + k + '.key', {
90508 context.keybinding().on(uiCmd('⌘⇧' + key), function (d3_event) {
90509 d3_event.stopImmediatePropagation();
90510 d3_event.preventDefault();
90519 function pointBox(loc, context) {
90520 var rect = context.surfaceRect();
90521 var point = context.curtainProjection(loc);
90523 left: point[0] + rect.left - 40,
90524 top: point[1] + rect.top - 60,
90529 function pad(locOrBox, padding, context) {
90532 if (locOrBox instanceof Array) {
90533 var rect = context.surfaceRect();
90534 var point = context.curtainProjection(locOrBox);
90536 left: point[0] + rect.left,
90537 top: point[1] + rect.top
90544 left: box.left - padding,
90545 top: box.top - padding,
90546 width: (box.width || 0) + 2 * padding,
90547 height: (box.width || 0) + 2 * padding
90550 function icon(name, svgklass, useklass) {
90551 return '<svg class="icon ' + (svgklass || '') + '">' + '<use xlink:href="' + name + '"' + (useklass ? ' class="' + useklass + '"' : '') + '></use></svg>';
90553 var helpStringReplacements; // Returns the localized HTML element for `id` with a standardized set of icon, key, and
90554 // label replacements suitable for tutorials and documentation. Optionally supplemented
90555 // with custom `replacements`
90557 function helpHtml(id, replacements) {
90558 // only load these the first time
90559 if (!helpStringReplacements) {
90560 helpStringReplacements = {
90561 // insert icons corresponding to various UI elements
90562 point_icon: icon('#iD-icon-point', 'inline'),
90563 line_icon: icon('#iD-icon-line', 'inline'),
90564 area_icon: icon('#iD-icon-area', 'inline'),
90565 note_icon: icon('#iD-icon-note', 'inline add-note'),
90566 plus: icon('#iD-icon-plus', 'inline'),
90567 minus: icon('#iD-icon-minus', 'inline'),
90568 layers_icon: icon('#iD-icon-layers', 'inline'),
90569 data_icon: icon('#iD-icon-data', 'inline'),
90570 inspect: icon('#iD-icon-inspect', 'inline'),
90571 help_icon: icon('#iD-icon-help', 'inline'),
90572 undo_icon: icon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-redo' : '#iD-icon-undo', 'inline'),
90573 redo_icon: icon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-undo' : '#iD-icon-redo', 'inline'),
90574 save_icon: icon('#iD-icon-save', 'inline'),
90576 circularize_icon: icon('#iD-operation-circularize', 'inline operation'),
90577 continue_icon: icon('#iD-operation-continue', 'inline operation'),
90578 copy_icon: icon('#iD-operation-copy', 'inline operation'),
90579 delete_icon: icon('#iD-operation-delete', 'inline operation'),
90580 disconnect_icon: icon('#iD-operation-disconnect', 'inline operation'),
90581 downgrade_icon: icon('#iD-operation-downgrade', 'inline operation'),
90582 extract_icon: icon('#iD-operation-extract', 'inline operation'),
90583 merge_icon: icon('#iD-operation-merge', 'inline operation'),
90584 move_icon: icon('#iD-operation-move', 'inline operation'),
90585 orthogonalize_icon: icon('#iD-operation-orthogonalize', 'inline operation'),
90586 paste_icon: icon('#iD-operation-paste', 'inline operation'),
90587 reflect_long_icon: icon('#iD-operation-reflect-long', 'inline operation'),
90588 reflect_short_icon: icon('#iD-operation-reflect-short', 'inline operation'),
90589 reverse_icon: icon('#iD-operation-reverse', 'inline operation'),
90590 rotate_icon: icon('#iD-operation-rotate', 'inline operation'),
90591 split_icon: icon('#iD-operation-split', 'inline operation'),
90592 straighten_icon: icon('#iD-operation-straighten', 'inline operation'),
90593 // interaction icons
90594 leftclick: icon('#iD-walkthrough-mouse-left', 'inline operation'),
90595 rightclick: icon('#iD-walkthrough-mouse-right', 'inline operation'),
90596 mousewheel_icon: icon('#iD-walkthrough-mousewheel', 'inline operation'),
90597 tap_icon: icon('#iD-walkthrough-tap', 'inline operation'),
90598 doubletap_icon: icon('#iD-walkthrough-doubletap', 'inline operation'),
90599 longpress_icon: icon('#iD-walkthrough-longpress', 'inline operation'),
90600 touchdrag_icon: icon('#iD-walkthrough-touchdrag', 'inline operation'),
90601 pinch_icon: icon('#iD-walkthrough-pinch-apart', 'inline operation'),
90602 // insert keys; may be localized and platform-dependent
90603 shift: uiCmd.display('⇧'),
90604 alt: uiCmd.display('⌥'),
90605 "return": uiCmd.display('↵'),
90606 esc: _t.html('shortcuts.key.esc'),
90607 space: _t.html('shortcuts.key.space'),
90608 add_note_key: _t.html('modes.add_note.key'),
90609 help_key: _t.html('help.key'),
90610 shortcuts_key: _t.html('shortcuts.toggle.key'),
90611 // reference localized UI labels directly so that they'll always match
90612 save: _t.html('save.title'),
90613 undo: _t.html('undo.title'),
90614 redo: _t.html('redo.title'),
90615 upload: _t.html('commit.save'),
90616 point: _t.html('modes.add_point.title'),
90617 line: _t.html('modes.add_line.title'),
90618 area: _t.html('modes.add_area.title'),
90619 note: _t.html('modes.add_note.label'),
90620 circularize: _t.html('operations.circularize.title'),
90621 "continue": _t.html('operations.continue.title'),
90622 copy: _t.html('operations.copy.title'),
90623 "delete": _t.html('operations.delete.title'),
90624 disconnect: _t.html('operations.disconnect.title'),
90625 downgrade: _t.html('operations.downgrade.title'),
90626 extract: _t.html('operations.extract.title'),
90627 merge: _t.html('operations.merge.title'),
90628 move: _t.html('operations.move.title'),
90629 orthogonalize: _t.html('operations.orthogonalize.title'),
90630 paste: _t.html('operations.paste.title'),
90631 reflect_long: _t.html('operations.reflect.title.long'),
90632 reflect_short: _t.html('operations.reflect.title.short'),
90633 reverse: _t.html('operations.reverse.title'),
90634 rotate: _t.html('operations.rotate.title'),
90635 split: _t.html('operations.split.title'),
90636 straighten: _t.html('operations.straighten.title'),
90637 map_data: _t.html('map_data.title'),
90638 osm_notes: _t.html('map_data.layers.notes.title'),
90639 fields: _t.html('inspector.fields'),
90640 tags: _t.html('inspector.tags'),
90641 relations: _t.html('inspector.relations'),
90642 new_relation: _t.html('inspector.new_relation'),
90643 turn_restrictions: _t.html('_tagging.presets.fields.restrictions.label'),
90644 background_settings: _t.html('background.description'),
90645 imagery_offset: _t.html('background.fix_misalignment'),
90646 start_the_walkthrough: _t.html('splash.walkthrough'),
90647 help: _t.html('help.title'),
90648 ok: _t.html('intro.ok')
90651 for (var key in helpStringReplacements) {
90652 helpStringReplacements[key] = {
90653 html: helpStringReplacements[key]
90660 if (replacements) {
90661 reps = Object.assign(replacements, helpStringReplacements);
90663 reps = helpStringReplacements;
90666 return _t.html(id, reps) // use keyboard key styling for shortcuts
90667 .replace(/\`(.*?)\`/g, '<kbd>$1</kbd>');
90670 function slugify(text) {
90671 return text.toString().toLowerCase().replace(/\s+/g, '-') // Replace spaces with -
90672 .replace(/[^\w\-]+/g, '') // Remove all non-word chars
90673 .replace(/\-\-+/g, '-') // Replace multiple - with single -
90674 .replace(/^-+/, '') // Trim - from start of text
90675 .replace(/-+$/, ''); // Trim - from end of text
90676 } // console warning for missing walkthrough names
90679 var missingStrings = {};
90681 function checkKey(key, text) {
90683 "default": undefined
90684 }) === undefined) {
90685 if (missingStrings.hasOwnProperty(key)) return; // warn once
90687 missingStrings[key] = text;
90688 var missing = key + ': ' + text;
90689 if (typeof console !== 'undefined') console.log(missing); // eslint-disable-line
90693 function localize(obj) {
90694 var key; // Assign name if entity has one..
90696 var name = obj.tags && obj.tags.name;
90699 key = 'intro.graph.name.' + slugify(name);
90700 obj.tags.name = _t(key, {
90703 checkKey(key, name);
90704 } // Assign street name if entity has one..
90707 var street = obj.tags && obj.tags['addr:street'];
90710 key = 'intro.graph.name.' + slugify(street);
90711 obj.tags['addr:street'] = _t(key, {
90714 checkKey(key, street); // Add address details common across walkthrough..
90716 var addrTags = ['block_number', 'city', 'county', 'district', 'hamlet', 'neighbourhood', 'postcode', 'province', 'quarter', 'state', 'subdistrict', 'suburb'];
90717 addrTags.forEach(function (k) {
90718 var key = 'intro.graph.' + k;
90719 var tag = 'addr:' + k;
90720 var val = obj.tags && obj.tags[tag];
90721 var str = _t(key, {
90726 if (str.match(/^<.*>$/) !== null) {
90727 delete obj.tags[tag];
90729 obj.tags[tag] = str;
90736 } // Used to detect squareness.. some duplicataion of code from actionOrthogonalize.
90738 function isMostlySquare(points) {
90739 // note: uses 15 here instead of the 12 from actionOrthogonalize because
90740 // actionOrthogonalize can actually straighten some larger angles as it iterates
90741 var threshold = 15; // degrees within right or straight
90743 var lowerBound = Math.cos((90 - threshold) * Math.PI / 180); // near right
90745 var upperBound = Math.cos(threshold * Math.PI / 180); // near straight
90747 for (var i = 0; i < points.length; i++) {
90748 var a = points[(i - 1 + points.length) % points.length];
90749 var origin = points[i];
90750 var b = points[(i + 1) % points.length];
90751 var dotp = geoVecNormalizedDot(a, b, origin);
90752 var mag = Math.abs(dotp);
90754 if (mag > lowerBound && mag < upperBound) {
90761 function selectMenuItem(context, operation) {
90762 return context.container().select('.edit-menu .edit-menu-item-' + operation);
90764 function transitionTime(point1, point2) {
90765 var distance = geoSphericalDistance(point1, point2);
90767 if (distance === 0) {
90769 } else if (distance < 80) {
90776 // hide class, which sets display=none, and a d3 transition for opacity.
90777 // this will cause blinking when called repeatedly, so check that the
90778 // value actually changes between calls.
90780 function uiToggle(show, callback) {
90781 return function (selection) {
90782 selection.style('opacity', show ? 0 : 1).classed('hide', false).transition().style('opacity', show ? 1 : 0).on('end', function () {
90783 select(this).classed('hide', !show).style('opacity', null);
90784 if (callback) callback.apply(this);
90789 function uiCurtain(containerNode) {
90790 var surface = select(null),
90791 tooltip = select(null),
90792 darkness = select(null);
90794 function curtain(selection) {
90795 surface = selection.append('svg').attr('class', 'curtain').style('top', 0).style('left', 0);
90796 darkness = surface.append('path').attr('x', 0).attr('y', 0).attr('class', 'curtain-darkness');
90797 select(window).on('resize.curtain', resize);
90798 tooltip = selection.append('div').attr('class', 'tooltip');
90799 tooltip.append('div').attr('class', 'popover-arrow');
90800 tooltip.append('div').attr('class', 'popover-inner');
90803 function resize() {
90804 surface.attr('width', containerNode.clientWidth).attr('height', containerNode.clientHeight);
90805 curtain.cut(darkness.datum());
90809 * Reveal cuts the curtain to highlight the given box,
90810 * and shows a tooltip with instructions next to the box.
90812 * @param {String|ClientRect} [box] box used to cut the curtain
90813 * @param {String} [text] text for a tooltip
90814 * @param {Object} [options]
90815 * @param {string} [options.tooltipClass] optional class to add to the tooltip
90816 * @param {integer} [options.duration] transition time in milliseconds
90817 * @param {string} [options.buttonText] if set, create a button with this text label
90818 * @param {function} [options.buttonCallback] if set, the callback for the button
90819 * @param {function} [options.padding] extra margin in px to put around bbox
90820 * @param {String|ClientRect} [options.tooltipBox] box for tooltip position, if different from box for the curtain
90824 curtain.reveal = function (box, html, options) {
90825 options = options || {};
90827 if (typeof box === 'string') {
90828 box = select(box).node();
90831 if (box && box.getBoundingClientRect) {
90832 box = copyBox(box.getBoundingClientRect());
90833 var containerRect = containerNode.getBoundingClientRect();
90834 box.top -= containerRect.top;
90835 box.left -= containerRect.left;
90838 if (box && options.padding) {
90839 box.top -= options.padding;
90840 box.left -= options.padding;
90841 box.bottom += options.padding;
90842 box.right += options.padding;
90843 box.height += options.padding * 2;
90844 box.width += options.padding * 2;
90849 if (options.tooltipBox) {
90850 tooltipBox = options.tooltipBox;
90852 if (typeof tooltipBox === 'string') {
90853 tooltipBox = select(tooltipBox).node();
90856 if (tooltipBox && tooltipBox.getBoundingClientRect) {
90857 tooltipBox = copyBox(tooltipBox.getBoundingClientRect());
90863 if (tooltipBox && html) {
90864 if (html.indexOf('**') !== -1) {
90865 if (html.indexOf('<span') === 0) {
90866 html = html.replace(/^(<span.*?>)(.+?)(\*\*)/, '$1<span>$2</span>$3');
90868 html = html.replace(/^(.+?)(\*\*)/, '<span>$1</span>$2');
90869 } // pseudo markdown bold text for the instruction section..
90872 html = html.replace(/\*\*(.*?)\*\*/g, '<span class="instruction">$1</span>');
90875 html = html.replace(/\*(.*?)\*/g, '<em>$1</em>'); // emphasis
90877 html = html.replace(/\{br\}/g, '<br/><br/>'); // linebreak
90879 if (options.buttonText && options.buttonCallback) {
90880 html += '<div class="button-section">' + '<button href="#" class="button action">' + options.buttonText + '</button></div>';
90883 var classes = 'curtain-tooltip popover tooltip arrowed in ' + (options.tooltipClass || '');
90884 tooltip.classed(classes, true).selectAll('.popover-inner').html(html);
90886 if (options.buttonText && options.buttonCallback) {
90887 var button = tooltip.selectAll('.button-section .button.action');
90888 button.on('click', function (d3_event) {
90889 d3_event.preventDefault();
90890 options.buttonCallback();
90894 var tip = copyBox(tooltip.node().getBoundingClientRect()),
90895 w = containerNode.clientWidth,
90896 h = containerNode.clientHeight,
90897 tooltipWidth = 200,
90900 pos; // hack: this will have bottom placement,
90901 // so need to reserve extra space for the tooltip illustration.
90903 if (options.tooltipClass === 'intro-mouse') {
90905 } // trim box dimensions to just the portion that fits in the container..
90908 if (tooltipBox.top + tooltipBox.height > h) {
90909 tooltipBox.height -= tooltipBox.top + tooltipBox.height - h;
90912 if (tooltipBox.left + tooltipBox.width > w) {
90913 tooltipBox.width -= tooltipBox.left + tooltipBox.width - w;
90914 } // determine tooltip placement..
90917 if (tooltipBox.top + tooltipBox.height < 100) {
90918 // tooltip below box..
90920 pos = [tooltipBox.left + tooltipBox.width / 2 - tip.width / 2, tooltipBox.top + tooltipBox.height];
90921 } else if (tooltipBox.top > h - 140) {
90922 // tooltip above box..
90924 pos = [tooltipBox.left + tooltipBox.width / 2 - tip.width / 2, tooltipBox.top - tip.height];
90926 // tooltip to the side of the tooltipBox..
90927 var tipY = tooltipBox.top + tooltipBox.height / 2 - tip.height / 2;
90929 if (_mainLocalizer.textDirection() === 'rtl') {
90930 if (tooltipBox.left - tooltipWidth - tooltipArrow < 70) {
90932 pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
90935 pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
90938 if (tooltipBox.left + tooltipBox.width + tooltipArrow + tooltipWidth > w - 70) {
90940 pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
90943 pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
90948 if (options.duration !== 0 || !tooltip.classed(side)) {
90949 tooltip.call(uiToggle(true));
90952 tooltip.style('top', pos[1] + 'px').style('left', pos[0] + 'px').attr('class', classes + ' ' + side); // shift popover-inner if it is very close to the top or bottom edge
90953 // (doesn't affect the placement of the popover-arrow)
90957 if (side === 'left' || side === 'right') {
90959 shiftY = 60 - pos[1];
90960 } else if (pos[1] + tip.height > h - 100) {
90961 shiftY = h - pos[1] - tip.height - 100;
90965 tooltip.selectAll('.popover-inner').style('top', shiftY + 'px');
90967 tooltip.classed('in', false).call(uiToggle(false));
90970 curtain.cut(box, options.duration);
90974 curtain.cut = function (datum, duration) {
90975 darkness.datum(datum).interrupt();
90978 if (duration === 0) {
90979 selection = darkness;
90981 selection = darkness.transition().duration(duration || 600).ease(linear$1);
90984 selection.attr('d', function (d) {
90985 var containerWidth = containerNode.clientWidth;
90986 var containerHeight = containerNode.clientHeight;
90987 var string = 'M 0,0 L 0,' + containerHeight + ' L ' + containerWidth + ',' + containerHeight + 'L' + containerWidth + ',0 Z';
90988 if (!d) return string;
90989 return string + 'M' + d.left + ',' + d.top + 'L' + d.left + ',' + (d.top + d.height) + 'L' + (d.left + d.width) + ',' + (d.top + d.height) + 'L' + (d.left + d.width) + ',' + d.top + 'Z';
90993 curtain.remove = function () {
90996 select(window).on('resize.curtain', null);
90997 }; // ClientRects are immutable, so copy them to an object,
90998 // in case we need to trim the height/width.
91001 function copyBox(src) {
91005 bottom: src.bottom,
91015 function uiIntroWelcome(context, reveal) {
91016 var dispatch = dispatch$8('done');
91018 title: 'intro.welcome.title'
91021 function welcome() {
91022 context.map().centerZoom([-85.63591, 41.94285], 19);
91023 reveal('.intro-nav-wrap .chapter-welcome', helpHtml('intro.welcome.welcome'), {
91024 buttonText: _t.html('intro.ok'),
91025 buttonCallback: practice
91029 function practice() {
91030 reveal('.intro-nav-wrap .chapter-welcome', helpHtml('intro.welcome.practice'), {
91031 buttonText: _t.html('intro.ok'),
91032 buttonCallback: words
91037 reveal('.intro-nav-wrap .chapter-welcome', helpHtml('intro.welcome.words'), {
91038 buttonText: _t.html('intro.ok'),
91039 buttonCallback: chapters
91043 function chapters() {
91044 dispatch.call('done');
91045 reveal('.intro-nav-wrap .chapter-navigation', helpHtml('intro.welcome.chapters', {
91046 next: _t('intro.navigation.title')
91050 chapter.enter = function () {
91054 chapter.exit = function () {
91055 context.container().select('.curtain-tooltip.intro-mouse').selectAll('.counter').remove();
91058 chapter.restart = function () {
91063 return utilRebind(chapter, dispatch, 'on');
91066 function uiIntroNavigation(context, reveal) {
91067 var dispatch = dispatch$8('done');
91069 var hallId = 'n2061';
91070 var townHall = [-85.63591, 41.94285];
91071 var springStreetId = 'w397';
91072 var springStreetEndId = 'n1834';
91073 var springStreet = [-85.63582, 41.94255];
91074 var onewayField = _mainPresetIndex.field('oneway');
91075 var maxspeedField = _mainPresetIndex.field('maxspeed');
91077 title: 'intro.navigation.title'
91080 function timeout(f, t) {
91081 timeouts.push(window.setTimeout(f, t));
91084 function eventCancel(d3_event) {
91085 d3_event.stopPropagation();
91086 d3_event.preventDefault();
91089 function isTownHallSelected() {
91090 var ids = context.selectedIDs();
91091 return ids.length === 1 && ids[0] === hallId;
91094 function dragMap() {
91095 context.enter(modeBrowse(context));
91096 context.history().reset('initial');
91097 var msec = transitionTime(townHall, context.map().center());
91100 reveal(null, null, {
91105 context.map().centerZoomEase(townHall, 19, msec);
91106 timeout(function () {
91107 var centerStart = context.map().center();
91108 var textId = context.lastPointerType() === 'mouse' ? 'drag' : 'drag_touch';
91109 var dragString = helpHtml('intro.navigation.map_info') + '{br}' + helpHtml('intro.navigation.' + textId);
91110 reveal('.surface', dragString);
91111 context.map().on('drawn.intro', function () {
91112 reveal('.surface', dragString, {
91116 context.map().on('move.intro', function () {
91117 var centerNow = context.map().center();
91119 if (centerStart[0] !== centerNow[0] || centerStart[1] !== centerNow[1]) {
91120 context.map().on('move.intro', null);
91121 timeout(function () {
91122 continueTo(zoomMap);
91128 function continueTo(nextStep) {
91129 context.map().on('move.intro drawn.intro', null);
91134 function zoomMap() {
91135 var zoomStart = context.map().zoom();
91136 var textId = context.lastPointerType() === 'mouse' ? 'zoom' : 'zoom_touch';
91137 var zoomString = helpHtml('intro.navigation.' + textId);
91138 reveal('.surface', zoomString);
91139 context.map().on('drawn.intro', function () {
91140 reveal('.surface', zoomString, {
91144 context.map().on('move.intro', function () {
91145 if (context.map().zoom() !== zoomStart) {
91146 context.map().on('move.intro', null);
91147 timeout(function () {
91148 continueTo(features);
91153 function continueTo(nextStep) {
91154 context.map().on('move.intro drawn.intro', null);
91159 function features() {
91160 var onClick = function onClick() {
91161 continueTo(pointsLinesAreas);
91164 reveal('.surface', helpHtml('intro.navigation.features'), {
91165 buttonText: _t.html('intro.ok'),
91166 buttonCallback: onClick
91168 context.map().on('drawn.intro', function () {
91169 reveal('.surface', helpHtml('intro.navigation.features'), {
91171 buttonText: _t.html('intro.ok'),
91172 buttonCallback: onClick
91176 function continueTo(nextStep) {
91177 context.map().on('drawn.intro', null);
91182 function pointsLinesAreas() {
91183 var onClick = function onClick() {
91184 continueTo(nodesWays);
91187 reveal('.surface', helpHtml('intro.navigation.points_lines_areas'), {
91188 buttonText: _t.html('intro.ok'),
91189 buttonCallback: onClick
91191 context.map().on('drawn.intro', function () {
91192 reveal('.surface', helpHtml('intro.navigation.points_lines_areas'), {
91194 buttonText: _t.html('intro.ok'),
91195 buttonCallback: onClick
91199 function continueTo(nextStep) {
91200 context.map().on('drawn.intro', null);
91205 function nodesWays() {
91206 var onClick = function onClick() {
91207 continueTo(clickTownHall);
91210 reveal('.surface', helpHtml('intro.navigation.nodes_ways'), {
91211 buttonText: _t.html('intro.ok'),
91212 buttonCallback: onClick
91214 context.map().on('drawn.intro', function () {
91215 reveal('.surface', helpHtml('intro.navigation.nodes_ways'), {
91217 buttonText: _t.html('intro.ok'),
91218 buttonCallback: onClick
91222 function continueTo(nextStep) {
91223 context.map().on('drawn.intro', null);
91228 function clickTownHall() {
91229 context.enter(modeBrowse(context));
91230 context.history().reset('initial');
91231 var entity = context.hasEntity(hallId);
91232 if (!entity) return;
91233 reveal(null, null, {
91236 context.map().centerZoomEase(entity.loc, 19, 500);
91237 timeout(function () {
91238 var entity = context.hasEntity(hallId);
91239 if (!entity) return;
91240 var box = pointBox(entity.loc, context);
91241 var textId = context.lastPointerType() === 'mouse' ? 'click_townhall' : 'tap_townhall';
91242 reveal(box, helpHtml('intro.navigation.' + textId));
91243 context.map().on('move.intro drawn.intro', function () {
91244 var entity = context.hasEntity(hallId);
91245 if (!entity) return;
91246 var box = pointBox(entity.loc, context);
91247 reveal(box, helpHtml('intro.navigation.' + textId), {
91251 context.on('enter.intro', function () {
91252 if (isTownHallSelected()) continueTo(selectedTownHall);
91254 }, 550); // after centerZoomEase
91256 context.history().on('change.intro', function () {
91257 if (!context.hasEntity(hallId)) {
91258 continueTo(clickTownHall);
91262 function continueTo(nextStep) {
91263 context.on('enter.intro', null);
91264 context.map().on('move.intro drawn.intro', null);
91265 context.history().on('change.intro', null);
91270 function selectedTownHall() {
91271 if (!isTownHallSelected()) return clickTownHall();
91272 var entity = context.hasEntity(hallId);
91273 if (!entity) return clickTownHall();
91274 var box = pointBox(entity.loc, context);
91276 var onClick = function onClick() {
91277 continueTo(editorTownHall);
91280 reveal(box, helpHtml('intro.navigation.selected_townhall'), {
91281 buttonText: _t.html('intro.ok'),
91282 buttonCallback: onClick
91284 context.map().on('move.intro drawn.intro', function () {
91285 var entity = context.hasEntity(hallId);
91286 if (!entity) return;
91287 var box = pointBox(entity.loc, context);
91288 reveal(box, helpHtml('intro.navigation.selected_townhall'), {
91290 buttonText: _t.html('intro.ok'),
91291 buttonCallback: onClick
91294 context.history().on('change.intro', function () {
91295 if (!context.hasEntity(hallId)) {
91296 continueTo(clickTownHall);
91300 function continueTo(nextStep) {
91301 context.map().on('move.intro drawn.intro', null);
91302 context.history().on('change.intro', null);
91307 function editorTownHall() {
91308 if (!isTownHallSelected()) return clickTownHall(); // disallow scrolling
91310 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91312 var onClick = function onClick() {
91313 continueTo(presetTownHall);
91316 reveal('.entity-editor-pane', helpHtml('intro.navigation.editor_townhall'), {
91317 buttonText: _t.html('intro.ok'),
91318 buttonCallback: onClick
91320 context.on('exit.intro', function () {
91321 continueTo(clickTownHall);
91323 context.history().on('change.intro', function () {
91324 if (!context.hasEntity(hallId)) {
91325 continueTo(clickTownHall);
91329 function continueTo(nextStep) {
91330 context.on('exit.intro', null);
91331 context.history().on('change.intro', null);
91332 context.container().select('.inspector-wrap').on('wheel.intro', null);
91337 function presetTownHall() {
91338 if (!isTownHallSelected()) return clickTownHall(); // reset pane, in case user happened to change it..
91340 context.container().select('.inspector-wrap .panewrap').style('right', '0%'); // disallow scrolling
91342 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel); // preset match, in case the user happened to change it.
91344 var entity = context.entity(context.selectedIDs()[0]);
91345 var preset = _mainPresetIndex.match(entity, context.graph());
91347 var onClick = function onClick() {
91348 continueTo(fieldsTownHall);
91351 reveal('.entity-editor-pane .section-feature-type', helpHtml('intro.navigation.preset_townhall', {
91352 preset: preset.name()
91354 buttonText: _t.html('intro.ok'),
91355 buttonCallback: onClick
91357 context.on('exit.intro', function () {
91358 continueTo(clickTownHall);
91360 context.history().on('change.intro', function () {
91361 if (!context.hasEntity(hallId)) {
91362 continueTo(clickTownHall);
91366 function continueTo(nextStep) {
91367 context.on('exit.intro', null);
91368 context.history().on('change.intro', null);
91369 context.container().select('.inspector-wrap').on('wheel.intro', null);
91374 function fieldsTownHall() {
91375 if (!isTownHallSelected()) return clickTownHall(); // reset pane, in case user happened to change it..
91377 context.container().select('.inspector-wrap .panewrap').style('right', '0%'); // disallow scrolling
91379 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91381 var onClick = function onClick() {
91382 continueTo(closeTownHall);
91385 reveal('.entity-editor-pane .section-preset-fields', helpHtml('intro.navigation.fields_townhall'), {
91386 buttonText: _t.html('intro.ok'),
91387 buttonCallback: onClick
91389 context.on('exit.intro', function () {
91390 continueTo(clickTownHall);
91392 context.history().on('change.intro', function () {
91393 if (!context.hasEntity(hallId)) {
91394 continueTo(clickTownHall);
91398 function continueTo(nextStep) {
91399 context.on('exit.intro', null);
91400 context.history().on('change.intro', null);
91401 context.container().select('.inspector-wrap').on('wheel.intro', null);
91406 function closeTownHall() {
91407 if (!isTownHallSelected()) return clickTownHall();
91408 var selector = '.entity-editor-pane button.close svg use';
91409 var href = select(selector).attr('href') || '#iD-icon-close';
91410 reveal('.entity-editor-pane', helpHtml('intro.navigation.close_townhall', {
91412 html: icon(href, 'inline')
91415 context.on('exit.intro', function () {
91416 continueTo(searchStreet);
91418 context.history().on('change.intro', function () {
91419 // update the close icon in the tooltip if the user edits something.
91420 var selector = '.entity-editor-pane button.close svg use';
91421 var href = select(selector).attr('href') || '#iD-icon-close';
91422 reveal('.entity-editor-pane', helpHtml('intro.navigation.close_townhall', {
91424 html: icon(href, 'inline')
91431 function continueTo(nextStep) {
91432 context.on('exit.intro', null);
91433 context.history().on('change.intro', null);
91438 function searchStreet() {
91439 context.enter(modeBrowse(context));
91440 context.history().reset('initial'); // ensure spring street exists
91442 var msec = transitionTime(springStreet, context.map().center());
91445 reveal(null, null, {
91450 context.map().centerZoomEase(springStreet, 19, msec); // ..and user can see it
91452 timeout(function () {
91453 reveal('.search-header input', helpHtml('intro.navigation.search_street', {
91454 name: _t('intro.graph.name.spring-street')
91456 context.container().select('.search-header input').on('keyup.intro', checkSearchResult);
91460 function checkSearchResult() {
91461 var first = context.container().select('.feature-list-item:nth-child(0n+2)'); // skip "No Results" item
91463 var firstName = first.select('.entity-name');
91464 var name = _t('intro.graph.name.spring-street');
91466 if (!firstName.empty() && firstName.html() === name) {
91467 reveal(first.node(), helpHtml('intro.navigation.choose_street', {
91472 context.on('exit.intro', function () {
91473 continueTo(selectedStreet);
91475 context.container().select('.search-header input').on('keydown.intro', eventCancel, true).on('keyup.intro', null);
91478 function continueTo(nextStep) {
91479 context.on('exit.intro', null);
91480 context.container().select('.search-header input').on('keydown.intro', null).on('keyup.intro', null);
91485 function selectedStreet() {
91486 if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
91487 return searchStreet();
91490 var onClick = function onClick() {
91491 continueTo(editorStreet);
91494 var entity = context.entity(springStreetEndId);
91495 var box = pointBox(entity.loc, context);
91497 reveal(box, helpHtml('intro.navigation.selected_street', {
91498 name: _t('intro.graph.name.spring-street')
91501 buttonText: _t.html('intro.ok'),
91502 buttonCallback: onClick
91504 timeout(function () {
91505 context.map().on('move.intro drawn.intro', function () {
91506 var entity = context.hasEntity(springStreetEndId);
91507 if (!entity) return;
91508 var box = pointBox(entity.loc, context);
91510 reveal(box, helpHtml('intro.navigation.selected_street', {
91511 name: _t('intro.graph.name.spring-street')
91514 buttonText: _t.html('intro.ok'),
91515 buttonCallback: onClick
91518 }, 600); // after reveal.
91520 context.on('enter.intro', function (mode) {
91521 if (!context.hasEntity(springStreetId)) {
91522 return continueTo(searchStreet);
91525 var ids = context.selectedIDs();
91527 if (mode.id !== 'select' || !ids.length || ids[0] !== springStreetId) {
91528 // keep Spring Street selected..
91529 context.enter(modeSelect(context, [springStreetId]));
91532 context.history().on('change.intro', function () {
91533 if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
91534 timeout(function () {
91535 continueTo(searchStreet);
91536 }, 300); // after any transition (e.g. if user deleted intersection)
91540 function continueTo(nextStep) {
91541 context.map().on('move.intro drawn.intro', null);
91542 context.on('enter.intro', null);
91543 context.history().on('change.intro', null);
91548 function editorStreet() {
91549 var selector = '.entity-editor-pane button.close svg use';
91550 var href = select(selector).attr('href') || '#iD-icon-close';
91551 reveal('.entity-editor-pane', helpHtml('intro.navigation.street_different_fields') + '{br}' + helpHtml('intro.navigation.editor_street', {
91553 html: icon(href, 'inline')
91556 html: onewayField.label()
91559 html: maxspeedField.label()
91562 context.on('exit.intro', function () {
91565 context.history().on('change.intro', function () {
91566 // update the close icon in the tooltip if the user edits something.
91567 var selector = '.entity-editor-pane button.close svg use';
91568 var href = select(selector).attr('href') || '#iD-icon-close';
91569 reveal('.entity-editor-pane', helpHtml('intro.navigation.street_different_fields') + '{br}' + helpHtml('intro.navigation.editor_street', {
91571 html: icon(href, 'inline')
91574 html: onewayField.label()
91577 html: maxspeedField.label()
91584 function continueTo(nextStep) {
91585 context.on('exit.intro', null);
91586 context.history().on('change.intro', null);
91592 dispatch.call('done');
91593 reveal('.ideditor', helpHtml('intro.navigation.play', {
91594 next: _t('intro.points.title')
91596 tooltipBox: '.intro-nav-wrap .chapter-point',
91597 buttonText: _t.html('intro.ok'),
91598 buttonCallback: function buttonCallback() {
91599 reveal('.ideditor');
91604 chapter.enter = function () {
91608 chapter.exit = function () {
91609 timeouts.forEach(window.clearTimeout);
91610 context.on('enter.intro exit.intro', null);
91611 context.map().on('move.intro drawn.intro', null);
91612 context.history().on('change.intro', null);
91613 context.container().select('.inspector-wrap').on('wheel.intro', null);
91614 context.container().select('.search-header input').on('keydown.intro keyup.intro', null);
91617 chapter.restart = function () {
91622 return utilRebind(chapter, dispatch, 'on');
91625 function uiIntroPoint(context, reveal) {
91626 var dispatch = dispatch$8('done');
91628 var intersection = [-85.63279, 41.94394];
91629 var building = [-85.632422, 41.944045];
91630 var cafePreset = _mainPresetIndex.item('amenity/cafe');
91631 var _pointID = null;
91633 title: 'intro.points.title'
91636 function timeout(f, t) {
91637 timeouts.push(window.setTimeout(f, t));
91640 function eventCancel(d3_event) {
91641 d3_event.stopPropagation();
91642 d3_event.preventDefault();
91645 function addPoint() {
91646 context.enter(modeBrowse(context));
91647 context.history().reset('initial');
91648 var msec = transitionTime(intersection, context.map().center());
91651 reveal(null, null, {
91656 context.map().centerZoomEase(intersection, 19, msec);
91657 timeout(function () {
91658 var tooltip = reveal('button.add-point', helpHtml('intro.points.points_info') + '{br}' + helpHtml('intro.points.add_point'));
91660 tooltip.selectAll('.popover-inner').insert('svg', 'span').attr('class', 'tooltip-illustration').append('use').attr('xlink:href', '#iD-graphic-points');
91661 context.on('enter.intro', function (mode) {
91662 if (mode.id !== 'add-point') return;
91663 continueTo(placePoint);
91667 function continueTo(nextStep) {
91668 context.on('enter.intro', null);
91673 function placePoint() {
91674 if (context.mode().id !== 'add-point') {
91675 return chapter.restart();
91678 var pointBox = pad(building, 150, context);
91679 var textId = context.lastPointerType() === 'mouse' ? 'place_point' : 'place_point_touch';
91680 reveal(pointBox, helpHtml('intro.points.' + textId));
91681 context.map().on('move.intro drawn.intro', function () {
91682 pointBox = pad(building, 150, context);
91683 reveal(pointBox, helpHtml('intro.points.' + textId), {
91687 context.on('enter.intro', function (mode) {
91688 if (mode.id !== 'select') return chapter.restart();
91689 _pointID = context.mode().selectedIDs()[0];
91690 continueTo(searchPreset);
91693 function continueTo(nextStep) {
91694 context.map().on('move.intro drawn.intro', null);
91695 context.on('enter.intro', null);
91700 function searchPreset() {
91701 if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91703 } // disallow scrolling
91706 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91707 context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
91708 reveal('.preset-search-input', helpHtml('intro.points.search_cafe', {
91709 preset: cafePreset.name()
91711 context.on('enter.intro', function (mode) {
91712 if (!_pointID || !context.hasEntity(_pointID)) {
91713 return continueTo(addPoint);
91716 var ids = context.selectedIDs();
91718 if (mode.id !== 'select' || !ids.length || ids[0] !== _pointID) {
91719 // keep the user's point selected..
91720 context.enter(modeSelect(context, [_pointID])); // disallow scrolling
91722 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91723 context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
91724 reveal('.preset-search-input', helpHtml('intro.points.search_cafe', {
91725 preset: cafePreset.name()
91727 context.history().on('change.intro', null);
91731 function checkPresetSearch() {
91732 var first = context.container().select('.preset-list-item:first-child');
91734 if (first.classed('preset-amenity-cafe')) {
91735 context.container().select('.preset-search-input').on('keydown.intro', eventCancel, true).on('keyup.intro', null);
91736 reveal(first.select('.preset-list-button').node(), helpHtml('intro.points.choose_cafe', {
91737 preset: cafePreset.name()
91741 context.history().on('change.intro', function () {
91742 continueTo(aboutFeatureEditor);
91747 function continueTo(nextStep) {
91748 context.on('enter.intro', null);
91749 context.history().on('change.intro', null);
91750 context.container().select('.inspector-wrap').on('wheel.intro', null);
91751 context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
91756 function aboutFeatureEditor() {
91757 if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91761 timeout(function () {
91762 reveal('.entity-editor-pane', helpHtml('intro.points.feature_editor'), {
91763 tooltipClass: 'intro-points-describe',
91764 buttonText: _t.html('intro.ok'),
91765 buttonCallback: function buttonCallback() {
91766 continueTo(addName);
91770 context.on('exit.intro', function () {
91771 // if user leaves select mode here, just continue with the tutorial.
91772 continueTo(reselectPoint);
91775 function continueTo(nextStep) {
91776 context.on('exit.intro', null);
91781 function addName() {
91782 if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91784 } // reset pane, in case user happened to change it..
91787 context.container().select('.inspector-wrap .panewrap').style('right', '0%');
91788 var addNameString = helpHtml('intro.points.fields_info') + '{br}' + helpHtml('intro.points.add_name');
91789 timeout(function () {
91790 // It's possible for the user to add a name in a previous step..
91791 // If so, don't tell them to add the name in this step.
91792 // Give them an OK button instead.
91793 var entity = context.entity(_pointID);
91795 if (entity.tags.name) {
91796 var tooltip = reveal('.entity-editor-pane', addNameString, {
91797 tooltipClass: 'intro-points-describe',
91798 buttonText: _t.html('intro.ok'),
91799 buttonCallback: function buttonCallback() {
91800 continueTo(addCloseEditor);
91803 tooltip.select('.instruction').style('display', 'none');
91805 reveal('.entity-editor-pane', addNameString, {
91806 tooltipClass: 'intro-points-describe'
91810 context.history().on('change.intro', function () {
91811 continueTo(addCloseEditor);
91813 context.on('exit.intro', function () {
91814 // if user leaves select mode here, just continue with the tutorial.
91815 continueTo(reselectPoint);
91818 function continueTo(nextStep) {
91819 context.on('exit.intro', null);
91820 context.history().on('change.intro', null);
91825 function addCloseEditor() {
91826 // reset pane, in case user happened to change it..
91827 context.container().select('.inspector-wrap .panewrap').style('right', '0%');
91828 var selector = '.entity-editor-pane button.close svg use';
91829 var href = select(selector).attr('href') || '#iD-icon-close';
91830 context.on('exit.intro', function () {
91831 continueTo(reselectPoint);
91833 reveal('.entity-editor-pane', helpHtml('intro.points.add_close', {
91835 html: icon(href, 'inline')
91839 function continueTo(nextStep) {
91840 context.on('exit.intro', null);
91845 function reselectPoint() {
91846 if (!_pointID) return chapter.restart();
91847 var entity = context.hasEntity(_pointID);
91848 if (!entity) return chapter.restart(); // make sure it's still a cafe, in case user somehow changed it..
91850 var oldPreset = _mainPresetIndex.match(entity, context.graph());
91851 context.replace(actionChangePreset(_pointID, oldPreset, cafePreset));
91852 context.enter(modeBrowse(context));
91853 var msec = transitionTime(entity.loc, context.map().center());
91856 reveal(null, null, {
91861 context.map().centerEase(entity.loc, msec);
91862 timeout(function () {
91863 var box = pointBox(entity.loc, context);
91864 reveal(box, helpHtml('intro.points.reselect'), {
91867 timeout(function () {
91868 context.map().on('move.intro drawn.intro', function () {
91869 var entity = context.hasEntity(_pointID);
91870 if (!entity) return chapter.restart();
91871 var box = pointBox(entity.loc, context);
91872 reveal(box, helpHtml('intro.points.reselect'), {
91876 }, 600); // after reveal..
91878 context.on('enter.intro', function (mode) {
91879 if (mode.id !== 'select') return;
91880 continueTo(updatePoint);
91884 function continueTo(nextStep) {
91885 context.map().on('move.intro drawn.intro', null);
91886 context.on('enter.intro', null);
91891 function updatePoint() {
91892 if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91893 return continueTo(reselectPoint);
91894 } // reset pane, in case user happened to untag the point..
91897 context.container().select('.inspector-wrap .panewrap').style('right', '0%');
91898 context.on('exit.intro', function () {
91899 continueTo(reselectPoint);
91901 context.history().on('change.intro', function () {
91902 continueTo(updateCloseEditor);
91904 timeout(function () {
91905 reveal('.entity-editor-pane', helpHtml('intro.points.update'), {
91906 tooltipClass: 'intro-points-describe'
91910 function continueTo(nextStep) {
91911 context.on('exit.intro', null);
91912 context.history().on('change.intro', null);
91917 function updateCloseEditor() {
91918 if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91919 return continueTo(reselectPoint);
91920 } // reset pane, in case user happened to change it..
91923 context.container().select('.inspector-wrap .panewrap').style('right', '0%');
91924 context.on('exit.intro', function () {
91925 continueTo(rightClickPoint);
91927 timeout(function () {
91928 reveal('.entity-editor-pane', helpHtml('intro.points.update_close', {
91930 html: icon('#iD-icon-close', 'inline')
91935 function continueTo(nextStep) {
91936 context.on('exit.intro', null);
91941 function rightClickPoint() {
91942 if (!_pointID) return chapter.restart();
91943 var entity = context.hasEntity(_pointID);
91944 if (!entity) return chapter.restart();
91945 context.enter(modeBrowse(context));
91946 var box = pointBox(entity.loc, context);
91947 var textId = context.lastPointerType() === 'mouse' ? 'rightclick' : 'edit_menu_touch';
91948 reveal(box, helpHtml('intro.points.' + textId), {
91951 timeout(function () {
91952 context.map().on('move.intro', function () {
91953 var entity = context.hasEntity(_pointID);
91954 if (!entity) return chapter.restart();
91955 var box = pointBox(entity.loc, context);
91956 reveal(box, helpHtml('intro.points.' + textId), {
91960 }, 600); // after reveal
91962 context.on('enter.intro', function (mode) {
91963 if (mode.id !== 'select') return;
91964 var ids = context.selectedIDs();
91965 if (ids.length !== 1 || ids[0] !== _pointID) return;
91966 timeout(function () {
91967 var node = selectMenuItem(context, 'delete').node();
91969 continueTo(enterDelete);
91970 }, 50); // after menu visible
91973 function continueTo(nextStep) {
91974 context.on('enter.intro', null);
91975 context.map().on('move.intro', null);
91980 function enterDelete() {
91981 if (!_pointID) return chapter.restart();
91982 var entity = context.hasEntity(_pointID);
91983 if (!entity) return chapter.restart();
91984 var node = selectMenuItem(context, 'delete').node();
91987 return continueTo(rightClickPoint);
91990 reveal('.edit-menu', helpHtml('intro.points.delete'), {
91993 timeout(function () {
91994 context.map().on('move.intro', function () {
91995 reveal('.edit-menu', helpHtml('intro.points.delete'), {
92000 }, 300); // after menu visible
92002 context.on('exit.intro', function () {
92003 if (!_pointID) return chapter.restart();
92004 var entity = context.hasEntity(_pointID);
92005 if (entity) return continueTo(rightClickPoint); // point still exists
92007 context.history().on('change.intro', function (changed) {
92008 if (changed.deleted().length) {
92013 function continueTo(nextStep) {
92014 context.map().on('move.intro', null);
92015 context.history().on('change.intro', null);
92016 context.on('exit.intro', null);
92022 context.history().on('change.intro', function () {
92025 reveal('.top-toolbar button.undo-button', helpHtml('intro.points.undo'));
92027 function continueTo(nextStep) {
92028 context.history().on('change.intro', null);
92034 dispatch.call('done');
92035 reveal('.ideditor', helpHtml('intro.points.play', {
92036 next: _t('intro.areas.title')
92038 tooltipBox: '.intro-nav-wrap .chapter-area',
92039 buttonText: _t.html('intro.ok'),
92040 buttonCallback: function buttonCallback() {
92041 reveal('.ideditor');
92046 chapter.enter = function () {
92050 chapter.exit = function () {
92051 timeouts.forEach(window.clearTimeout);
92052 context.on('enter.intro exit.intro', null);
92053 context.map().on('move.intro drawn.intro', null);
92054 context.history().on('change.intro', null);
92055 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92056 context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
92059 chapter.restart = function () {
92064 return utilRebind(chapter, dispatch, 'on');
92067 function uiIntroArea(context, reveal) {
92068 var dispatch = dispatch$8('done');
92069 var playground = [-85.63552, 41.94159];
92070 var playgroundPreset = _mainPresetIndex.item('leisure/playground');
92071 var nameField = _mainPresetIndex.field('name');
92072 var descriptionField = _mainPresetIndex.field('description');
92078 title: 'intro.areas.title'
92081 function timeout(f, t) {
92082 timeouts.push(window.setTimeout(f, t));
92085 function eventCancel(d3_event) {
92086 d3_event.stopPropagation();
92087 d3_event.preventDefault();
92090 function revealPlayground(center, text, options) {
92091 var padding = 180 * Math.pow(2, context.map().zoom() - 19.5);
92092 var box = pad(center, padding, context);
92093 reveal(box, text, options);
92096 function addArea() {
92097 context.enter(modeBrowse(context));
92098 context.history().reset('initial');
92100 var msec = transitionTime(playground, context.map().center());
92103 reveal(null, null, {
92108 context.map().centerZoomEase(playground, 19, msec);
92109 timeout(function () {
92110 var tooltip = reveal('button.add-area', helpHtml('intro.areas.add_playground'));
92111 tooltip.selectAll('.popover-inner').insert('svg', 'span').attr('class', 'tooltip-illustration').append('use').attr('xlink:href', '#iD-graphic-areas');
92112 context.on('enter.intro', function (mode) {
92113 if (mode.id !== 'add-area') return;
92114 continueTo(startPlayground);
92118 function continueTo(nextStep) {
92119 context.on('enter.intro', null);
92124 function startPlayground() {
92125 if (context.mode().id !== 'add-area') {
92126 return chapter.restart();
92130 context.map().zoomEase(19.5, 500);
92131 timeout(function () {
92132 var textId = context.lastPointerType() === 'mouse' ? 'starting_node_click' : 'starting_node_tap';
92133 var startDrawString = helpHtml('intro.areas.start_playground') + helpHtml('intro.areas.' + textId);
92134 revealPlayground(playground, startDrawString, {
92137 timeout(function () {
92138 context.map().on('move.intro drawn.intro', function () {
92139 revealPlayground(playground, startDrawString, {
92143 context.on('enter.intro', function (mode) {
92144 if (mode.id !== 'draw-area') return chapter.restart();
92145 continueTo(continuePlayground);
92147 }, 250); // after reveal
92148 }, 550); // after easing
92150 function continueTo(nextStep) {
92151 context.map().on('move.intro drawn.intro', null);
92152 context.on('enter.intro', null);
92157 function continuePlayground() {
92158 if (context.mode().id !== 'draw-area') {
92159 return chapter.restart();
92163 revealPlayground(playground, helpHtml('intro.areas.continue_playground'), {
92166 timeout(function () {
92167 context.map().on('move.intro drawn.intro', function () {
92168 revealPlayground(playground, helpHtml('intro.areas.continue_playground'), {
92172 }, 250); // after reveal
92174 context.on('enter.intro', function (mode) {
92175 if (mode.id === 'draw-area') {
92176 var entity = context.hasEntity(context.selectedIDs()[0]);
92178 if (entity && entity.nodes.length >= 6) {
92179 return continueTo(finishPlayground);
92183 } else if (mode.id === 'select') {
92184 _areaID = context.selectedIDs()[0];
92185 return continueTo(searchPresets);
92187 return chapter.restart();
92191 function continueTo(nextStep) {
92192 context.map().on('move.intro drawn.intro', null);
92193 context.on('enter.intro', null);
92198 function finishPlayground() {
92199 if (context.mode().id !== 'draw-area') {
92200 return chapter.restart();
92204 var finishString = helpHtml('intro.areas.finish_area_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) + helpHtml('intro.areas.finish_playground');
92205 revealPlayground(playground, finishString, {
92208 timeout(function () {
92209 context.map().on('move.intro drawn.intro', function () {
92210 revealPlayground(playground, finishString, {
92214 }, 250); // after reveal
92216 context.on('enter.intro', function (mode) {
92217 if (mode.id === 'draw-area') {
92219 } else if (mode.id === 'select') {
92220 _areaID = context.selectedIDs()[0];
92221 return continueTo(searchPresets);
92223 return chapter.restart();
92227 function continueTo(nextStep) {
92228 context.map().on('move.intro drawn.intro', null);
92229 context.on('enter.intro', null);
92234 function searchPresets() {
92235 if (!_areaID || !context.hasEntity(_areaID)) {
92239 var ids = context.selectedIDs();
92241 if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92242 context.enter(modeSelect(context, [_areaID]));
92243 } // disallow scrolling
92246 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92247 timeout(function () {
92248 // reset pane, in case user somehow happened to change it..
92249 context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
92250 context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
92251 reveal('.preset-search-input', helpHtml('intro.areas.search_playground', {
92252 preset: playgroundPreset.name()
92254 }, 400); // after preset list pane visible..
92256 context.on('enter.intro', function (mode) {
92257 if (!_areaID || !context.hasEntity(_areaID)) {
92258 return continueTo(addArea);
92261 var ids = context.selectedIDs();
92263 if (mode.id !== 'select' || !ids.length || ids[0] !== _areaID) {
92264 // keep the user's area selected..
92265 context.enter(modeSelect(context, [_areaID])); // reset pane, in case user somehow happened to change it..
92267 context.container().select('.inspector-wrap .panewrap').style('right', '-100%'); // disallow scrolling
92269 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92270 context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
92271 reveal('.preset-search-input', helpHtml('intro.areas.search_playground', {
92272 preset: playgroundPreset.name()
92274 context.history().on('change.intro', null);
92278 function checkPresetSearch() {
92279 var first = context.container().select('.preset-list-item:first-child');
92281 if (first.classed('preset-leisure-playground')) {
92282 reveal(first.select('.preset-list-button').node(), helpHtml('intro.areas.choose_playground', {
92283 preset: playgroundPreset.name()
92287 context.container().select('.preset-search-input').on('keydown.intro', eventCancel, true).on('keyup.intro', null);
92288 context.history().on('change.intro', function () {
92289 continueTo(clickAddField);
92294 function continueTo(nextStep) {
92295 context.container().select('.inspector-wrap').on('wheel.intro', null);
92296 context.on('enter.intro', null);
92297 context.history().on('change.intro', null);
92298 context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
92303 function clickAddField() {
92304 if (!_areaID || !context.hasEntity(_areaID)) {
92308 var ids = context.selectedIDs();
92310 if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92311 return searchPresets();
92314 if (!context.container().select('.form-field-description').empty()) {
92315 return continueTo(describePlayground);
92316 } // disallow scrolling
92319 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92320 timeout(function () {
92321 // reset pane, in case user somehow happened to change it..
92322 context.container().select('.inspector-wrap .panewrap').style('right', '0%'); // It's possible for the user to add a description in a previous step..
92323 // If they did this already, just continue to next step.
92325 var entity = context.entity(_areaID);
92327 if (entity.tags.description) {
92328 return continueTo(play);
92329 } // scroll "Add field" into view
92332 var box = context.container().select('.more-fields').node().getBoundingClientRect();
92334 if (box.top > 300) {
92335 var pane = context.container().select('.entity-editor-pane .inspector-body');
92336 var start = pane.node().scrollTop;
92337 var end = start + (box.top - 300);
92338 pane.transition().duration(250).tween('scroll.inspector', function () {
92340 var i = d3_interpolateNumber(start, end);
92341 return function (t) {
92342 node.scrollTop = i(t);
92347 timeout(function () {
92348 reveal('.more-fields .combobox-input', helpHtml('intro.areas.add_field', {
92350 html: nameField.label()
92353 html: descriptionField.label()
92358 context.container().select('.more-fields .combobox-input').on('click.intro', function () {
92359 // Watch for the combobox to appear...
92361 watcher = window.setInterval(function () {
92362 if (!context.container().select('div.combobox').empty()) {
92363 window.clearInterval(watcher);
92364 continueTo(chooseDescriptionField);
92368 }, 300); // after "Add Field" visible
92369 }, 400); // after editor pane visible
92371 context.on('exit.intro', function () {
92372 return continueTo(searchPresets);
92375 function continueTo(nextStep) {
92376 context.container().select('.inspector-wrap').on('wheel.intro', null);
92377 context.container().select('.more-fields .combobox-input').on('click.intro', null);
92378 context.on('exit.intro', null);
92383 function chooseDescriptionField() {
92384 if (!_areaID || !context.hasEntity(_areaID)) {
92388 var ids = context.selectedIDs();
92390 if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92391 return searchPresets();
92394 if (!context.container().select('.form-field-description').empty()) {
92395 return continueTo(describePlayground);
92396 } // Make sure combobox is ready..
92399 if (context.container().select('div.combobox').empty()) {
92400 return continueTo(clickAddField);
92401 } // Watch for the combobox to go away..
92405 watcher = window.setInterval(function () {
92406 if (context.container().select('div.combobox').empty()) {
92407 window.clearInterval(watcher);
92408 timeout(function () {
92409 if (context.container().select('.form-field-description').empty()) {
92410 continueTo(retryChooseDescription);
92412 continueTo(describePlayground);
92414 }, 300); // after description field added.
92417 reveal('div.combobox', helpHtml('intro.areas.choose_field', {
92419 html: descriptionField.label()
92424 context.on('exit.intro', function () {
92425 return continueTo(searchPresets);
92428 function continueTo(nextStep) {
92429 if (watcher) window.clearInterval(watcher);
92430 context.on('exit.intro', null);
92435 function describePlayground() {
92436 if (!_areaID || !context.hasEntity(_areaID)) {
92440 var ids = context.selectedIDs();
92442 if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92443 return searchPresets();
92444 } // reset pane, in case user happened to change it..
92447 context.container().select('.inspector-wrap .panewrap').style('right', '0%');
92449 if (context.container().select('.form-field-description').empty()) {
92450 return continueTo(retryChooseDescription);
92453 context.on('exit.intro', function () {
92456 reveal('.entity-editor-pane', helpHtml('intro.areas.describe_playground', {
92458 html: icon('#iD-icon-close', 'inline')
92464 function continueTo(nextStep) {
92465 context.on('exit.intro', null);
92470 function retryChooseDescription() {
92471 if (!_areaID || !context.hasEntity(_areaID)) {
92475 var ids = context.selectedIDs();
92477 if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92478 return searchPresets();
92479 } // reset pane, in case user happened to change it..
92482 context.container().select('.inspector-wrap .panewrap').style('right', '0%');
92483 reveal('.entity-editor-pane', helpHtml('intro.areas.retry_add_field', {
92485 html: descriptionField.label()
92488 buttonText: _t.html('intro.ok'),
92489 buttonCallback: function buttonCallback() {
92490 continueTo(clickAddField);
92493 context.on('exit.intro', function () {
92494 return continueTo(searchPresets);
92497 function continueTo(nextStep) {
92498 context.on('exit.intro', null);
92504 dispatch.call('done');
92505 reveal('.ideditor', helpHtml('intro.areas.play', {
92506 next: _t('intro.lines.title')
92508 tooltipBox: '.intro-nav-wrap .chapter-line',
92509 buttonText: _t.html('intro.ok'),
92510 buttonCallback: function buttonCallback() {
92511 reveal('.ideditor');
92516 chapter.enter = function () {
92520 chapter.exit = function () {
92521 timeouts.forEach(window.clearTimeout);
92522 context.on('enter.intro exit.intro', null);
92523 context.map().on('move.intro drawn.intro', null);
92524 context.history().on('change.intro', null);
92525 context.container().select('.inspector-wrap').on('wheel.intro', null);
92526 context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
92527 context.container().select('.more-fields .combobox-input').on('click.intro', null);
92530 chapter.restart = function () {
92535 return utilRebind(chapter, dispatch, 'on');
92538 function uiIntroLine(context, reveal) {
92539 var dispatch = dispatch$8('done');
92541 var _tulipRoadID = null;
92542 var flowerRoadID = 'w646';
92543 var tulipRoadStart = [-85.6297754121684, 41.95805253325314];
92544 var tulipRoadMidpoint = [-85.62975395449628, 41.95787501510204];
92545 var tulipRoadIntersection = [-85.62974496187628, 41.95742515554585];
92546 var roadCategory = _mainPresetIndex.item('category-road_minor');
92547 var residentialPreset = _mainPresetIndex.item('highway/residential');
92548 var woodRoadID = 'w525';
92549 var woodRoadEndID = 'n2862';
92550 var woodRoadAddNode = [-85.62390110349587, 41.95397111462291];
92551 var woodRoadDragEndpoint = [-85.623867390213, 41.95466987786487];
92552 var woodRoadDragMidpoint = [-85.62386254803509, 41.95430395953872];
92553 var washingtonStreetID = 'w522';
92554 var twelfthAvenueID = 'w1';
92555 var eleventhAvenueEndID = 'n3550';
92556 var twelfthAvenueEndID = 'n5';
92557 var _washingtonSegmentID = null;
92558 var eleventhAvenueEnd = context.entity(eleventhAvenueEndID).loc;
92559 var twelfthAvenueEnd = context.entity(twelfthAvenueEndID).loc;
92560 var deleteLinesLoc = [-85.6219395542764, 41.95228033922477];
92561 var twelfthAvenue = [-85.62219310052491, 41.952505413152956];
92563 title: 'intro.lines.title'
92566 function timeout(f, t) {
92567 timeouts.push(window.setTimeout(f, t));
92570 function eventCancel(d3_event) {
92571 d3_event.stopPropagation();
92572 d3_event.preventDefault();
92575 function addLine() {
92576 context.enter(modeBrowse(context));
92577 context.history().reset('initial');
92578 var msec = transitionTime(tulipRoadStart, context.map().center());
92581 reveal(null, null, {
92586 context.map().centerZoomEase(tulipRoadStart, 18.5, msec);
92587 timeout(function () {
92588 var tooltip = reveal('button.add-line', helpHtml('intro.lines.add_line'));
92589 tooltip.selectAll('.popover-inner').insert('svg', 'span').attr('class', 'tooltip-illustration').append('use').attr('xlink:href', '#iD-graphic-lines');
92590 context.on('enter.intro', function (mode) {
92591 if (mode.id !== 'add-line') return;
92592 continueTo(startLine);
92596 function continueTo(nextStep) {
92597 context.on('enter.intro', null);
92602 function startLine() {
92603 if (context.mode().id !== 'add-line') return chapter.restart();
92604 _tulipRoadID = null;
92605 var padding = 70 * Math.pow(2, context.map().zoom() - 18);
92606 var box = pad(tulipRoadStart, padding, context);
92607 box.height = box.height + 100;
92608 var textId = context.lastPointerType() === 'mouse' ? 'start_line' : 'start_line_tap';
92609 var startLineString = helpHtml('intro.lines.missing_road') + '{br}' + helpHtml('intro.lines.line_draw_info') + helpHtml('intro.lines.' + textId);
92610 reveal(box, startLineString);
92611 context.map().on('move.intro drawn.intro', function () {
92612 padding = 70 * Math.pow(2, context.map().zoom() - 18);
92613 box = pad(tulipRoadStart, padding, context);
92614 box.height = box.height + 100;
92615 reveal(box, startLineString, {
92619 context.on('enter.intro', function (mode) {
92620 if (mode.id !== 'draw-line') return chapter.restart();
92621 continueTo(drawLine);
92624 function continueTo(nextStep) {
92625 context.map().on('move.intro drawn.intro', null);
92626 context.on('enter.intro', null);
92631 function drawLine() {
92632 if (context.mode().id !== 'draw-line') return chapter.restart();
92633 _tulipRoadID = context.mode().selectedIDs()[0];
92634 context.map().centerEase(tulipRoadMidpoint, 500);
92635 timeout(function () {
92636 var padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
92637 var box = pad(tulipRoadMidpoint, padding, context);
92638 box.height = box.height * 2;
92639 reveal(box, helpHtml('intro.lines.intersect', {
92640 name: _t('intro.graph.name.flower-street')
92642 context.map().on('move.intro drawn.intro', function () {
92643 padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
92644 box = pad(tulipRoadMidpoint, padding, context);
92645 box.height = box.height * 2;
92646 reveal(box, helpHtml('intro.lines.intersect', {
92647 name: _t('intro.graph.name.flower-street')
92652 }, 550); // after easing..
92654 context.history().on('change.intro', function () {
92655 if (isLineConnected()) {
92656 continueTo(continueLine);
92659 context.on('enter.intro', function (mode) {
92660 if (mode.id === 'draw-line') {
92662 } else if (mode.id === 'select') {
92663 continueTo(retryIntersect);
92666 return chapter.restart();
92670 function continueTo(nextStep) {
92671 context.map().on('move.intro drawn.intro', null);
92672 context.history().on('change.intro', null);
92673 context.on('enter.intro', null);
92678 function isLineConnected() {
92679 var entity = _tulipRoadID && context.hasEntity(_tulipRoadID);
92681 if (!entity) return false;
92682 var drawNodes = context.graph().childNodes(entity);
92683 return drawNodes.some(function (node) {
92684 return context.graph().parentWays(node).some(function (parent) {
92685 return parent.id === flowerRoadID;
92690 function retryIntersect() {
92691 select(window).on('pointerdown.intro mousedown.intro', eventCancel, true);
92692 var box = pad(tulipRoadIntersection, 80, context);
92693 reveal(box, helpHtml('intro.lines.retry_intersect', {
92694 name: _t('intro.graph.name.flower-street')
92696 timeout(chapter.restart, 3000);
92699 function continueLine() {
92700 if (context.mode().id !== 'draw-line') return chapter.restart();
92702 var entity = _tulipRoadID && context.hasEntity(_tulipRoadID);
92704 if (!entity) return chapter.restart();
92705 context.map().centerEase(tulipRoadIntersection, 500);
92706 var continueLineText = helpHtml('intro.lines.continue_line') + '{br}' + helpHtml('intro.lines.finish_line_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) + helpHtml('intro.lines.finish_road');
92707 reveal('.surface', continueLineText);
92708 context.on('enter.intro', function (mode) {
92709 if (mode.id === 'draw-line') {
92711 } else if (mode.id === 'select') {
92712 return continueTo(chooseCategoryRoad);
92714 return chapter.restart();
92718 function continueTo(nextStep) {
92719 context.on('enter.intro', null);
92724 function chooseCategoryRoad() {
92725 if (context.mode().id !== 'select') return chapter.restart();
92726 context.on('exit.intro', function () {
92727 return chapter.restart();
92729 var button = context.container().select('.preset-category-road_minor .preset-list-button');
92730 if (button.empty()) return chapter.restart(); // disallow scrolling
92732 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92733 timeout(function () {
92734 // reset pane, in case user somehow happened to change it..
92735 context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
92736 reveal(button.node(), helpHtml('intro.lines.choose_category_road', {
92737 category: roadCategory.name()
92739 button.on('click.intro', function () {
92740 continueTo(choosePresetResidential);
92742 }, 400); // after editor pane visible
92744 function continueTo(nextStep) {
92745 context.container().select('.inspector-wrap').on('wheel.intro', null);
92746 context.container().select('.preset-list-button').on('click.intro', null);
92747 context.on('exit.intro', null);
92752 function choosePresetResidential() {
92753 if (context.mode().id !== 'select') return chapter.restart();
92754 context.on('exit.intro', function () {
92755 return chapter.restart();
92757 var subgrid = context.container().select('.preset-category-road_minor .subgrid');
92758 if (subgrid.empty()) return chapter.restart();
92759 subgrid.selectAll(':not(.preset-highway-residential) .preset-list-button').on('click.intro', function () {
92760 continueTo(retryPresetResidential);
92762 subgrid.selectAll('.preset-highway-residential .preset-list-button').on('click.intro', function () {
92763 continueTo(nameRoad);
92765 timeout(function () {
92766 reveal(subgrid.node(), helpHtml('intro.lines.choose_preset_residential', {
92767 preset: residentialPreset.name()
92769 tooltipBox: '.preset-highway-residential .preset-list-button',
92774 function continueTo(nextStep) {
92775 context.container().select('.preset-list-button').on('click.intro', null);
92776 context.on('exit.intro', null);
92779 } // selected wrong road type
92782 function retryPresetResidential() {
92783 if (context.mode().id !== 'select') return chapter.restart();
92784 context.on('exit.intro', function () {
92785 return chapter.restart();
92786 }); // disallow scrolling
92788 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92789 timeout(function () {
92790 var button = context.container().select('.entity-editor-pane .preset-list-button');
92791 reveal(button.node(), helpHtml('intro.lines.retry_preset_residential', {
92792 preset: residentialPreset.name()
92794 button.on('click.intro', function () {
92795 continueTo(chooseCategoryRoad);
92799 function continueTo(nextStep) {
92800 context.container().select('.inspector-wrap').on('wheel.intro', null);
92801 context.container().select('.preset-list-button').on('click.intro', null);
92802 context.on('exit.intro', null);
92807 function nameRoad() {
92808 context.on('exit.intro', function () {
92809 continueTo(didNameRoad);
92811 timeout(function () {
92812 reveal('.entity-editor-pane', helpHtml('intro.lines.name_road', {
92814 html: icon('#iD-icon-close', 'inline')
92817 tooltipClass: 'intro-lines-name_road'
92821 function continueTo(nextStep) {
92822 context.on('exit.intro', null);
92827 function didNameRoad() {
92828 context.history().checkpoint('doneAddLine');
92829 timeout(function () {
92830 reveal('.surface', helpHtml('intro.lines.did_name_road'), {
92831 buttonText: _t.html('intro.ok'),
92832 buttonCallback: function buttonCallback() {
92833 continueTo(updateLine);
92838 function continueTo(nextStep) {
92843 function updateLine() {
92844 context.history().reset('doneAddLine');
92846 if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92847 return chapter.restart();
92850 var msec = transitionTime(woodRoadDragMidpoint, context.map().center());
92853 reveal(null, null, {
92858 context.map().centerZoomEase(woodRoadDragMidpoint, 19, msec);
92859 timeout(function () {
92860 var padding = 250 * Math.pow(2, context.map().zoom() - 19);
92861 var box = pad(woodRoadDragMidpoint, padding, context);
92863 var advance = function advance() {
92864 continueTo(addNode);
92867 reveal(box, helpHtml('intro.lines.update_line'), {
92868 buttonText: _t.html('intro.ok'),
92869 buttonCallback: advance
92871 context.map().on('move.intro drawn.intro', function () {
92872 var padding = 250 * Math.pow(2, context.map().zoom() - 19);
92873 var box = pad(woodRoadDragMidpoint, padding, context);
92874 reveal(box, helpHtml('intro.lines.update_line'), {
92876 buttonText: _t.html('intro.ok'),
92877 buttonCallback: advance
92882 function continueTo(nextStep) {
92883 context.map().on('move.intro drawn.intro', null);
92888 function addNode() {
92889 context.history().reset('doneAddLine');
92891 if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92892 return chapter.restart();
92895 var padding = 40 * Math.pow(2, context.map().zoom() - 19);
92896 var box = pad(woodRoadAddNode, padding, context);
92897 var addNodeString = helpHtml('intro.lines.add_node' + (context.lastPointerType() === 'mouse' ? '' : '_touch'));
92898 reveal(box, addNodeString);
92899 context.map().on('move.intro drawn.intro', function () {
92900 var padding = 40 * Math.pow(2, context.map().zoom() - 19);
92901 var box = pad(woodRoadAddNode, padding, context);
92902 reveal(box, addNodeString, {
92906 context.history().on('change.intro', function (changed) {
92907 if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92908 return continueTo(updateLine);
92911 if (changed.created().length === 1) {
92912 timeout(function () {
92913 continueTo(startDragEndpoint);
92917 context.on('enter.intro', function (mode) {
92918 if (mode.id !== 'select') {
92919 continueTo(updateLine);
92923 function continueTo(nextStep) {
92924 context.map().on('move.intro drawn.intro', null);
92925 context.history().on('change.intro', null);
92926 context.on('enter.intro', null);
92931 function startDragEndpoint() {
92932 if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92933 return continueTo(updateLine);
92936 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92937 var box = pad(woodRoadDragEndpoint, padding, context);
92938 var startDragString = helpHtml('intro.lines.start_drag_endpoint' + (context.lastPointerType() === 'mouse' ? '' : '_touch')) + helpHtml('intro.lines.drag_to_intersection');
92939 reveal(box, startDragString);
92940 context.map().on('move.intro drawn.intro', function () {
92941 if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92942 return continueTo(updateLine);
92945 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92946 var box = pad(woodRoadDragEndpoint, padding, context);
92947 reveal(box, startDragString, {
92950 var entity = context.entity(woodRoadEndID);
92952 if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) <= 4) {
92953 continueTo(finishDragEndpoint);
92957 function continueTo(nextStep) {
92958 context.map().on('move.intro drawn.intro', null);
92963 function finishDragEndpoint() {
92964 if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92965 return continueTo(updateLine);
92968 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92969 var box = pad(woodRoadDragEndpoint, padding, context);
92970 var finishDragString = helpHtml('intro.lines.spot_looks_good') + helpHtml('intro.lines.finish_drag_endpoint' + (context.lastPointerType() === 'mouse' ? '' : '_touch'));
92971 reveal(box, finishDragString);
92972 context.map().on('move.intro drawn.intro', function () {
92973 if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92974 return continueTo(updateLine);
92977 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92978 var box = pad(woodRoadDragEndpoint, padding, context);
92979 reveal(box, finishDragString, {
92982 var entity = context.entity(woodRoadEndID);
92984 if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) > 4) {
92985 continueTo(startDragEndpoint);
92988 context.on('enter.intro', function () {
92989 continueTo(startDragMidpoint);
92992 function continueTo(nextStep) {
92993 context.map().on('move.intro drawn.intro', null);
92994 context.on('enter.intro', null);
92999 function startDragMidpoint() {
93000 if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
93001 return continueTo(updateLine);
93004 if (context.selectedIDs().indexOf(woodRoadID) === -1) {
93005 context.enter(modeSelect(context, [woodRoadID]));
93008 var padding = 80 * Math.pow(2, context.map().zoom() - 19);
93009 var box = pad(woodRoadDragMidpoint, padding, context);
93010 reveal(box, helpHtml('intro.lines.start_drag_midpoint'));
93011 context.map().on('move.intro drawn.intro', function () {
93012 if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
93013 return continueTo(updateLine);
93016 var padding = 80 * Math.pow(2, context.map().zoom() - 19);
93017 var box = pad(woodRoadDragMidpoint, padding, context);
93018 reveal(box, helpHtml('intro.lines.start_drag_midpoint'), {
93022 context.history().on('change.intro', function (changed) {
93023 if (changed.created().length === 1) {
93024 continueTo(continueDragMidpoint);
93027 context.on('enter.intro', function (mode) {
93028 if (mode.id !== 'select') {
93029 // keep Wood Road selected so midpoint triangles are drawn..
93030 context.enter(modeSelect(context, [woodRoadID]));
93034 function continueTo(nextStep) {
93035 context.map().on('move.intro drawn.intro', null);
93036 context.history().on('change.intro', null);
93037 context.on('enter.intro', null);
93042 function continueDragMidpoint() {
93043 if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
93044 return continueTo(updateLine);
93047 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
93048 var box = pad(woodRoadDragEndpoint, padding, context);
93051 var advance = function advance() {
93052 context.history().checkpoint('doneUpdateLine');
93053 continueTo(deleteLines);
93056 reveal(box, helpHtml('intro.lines.continue_drag_midpoint'), {
93057 buttonText: _t.html('intro.ok'),
93058 buttonCallback: advance
93060 context.map().on('move.intro drawn.intro', function () {
93061 if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
93062 return continueTo(updateLine);
93065 var padding = 100 * Math.pow(2, context.map().zoom() - 19);
93066 var box = pad(woodRoadDragEndpoint, padding, context);
93068 reveal(box, helpHtml('intro.lines.continue_drag_midpoint'), {
93070 buttonText: _t.html('intro.ok'),
93071 buttonCallback: advance
93075 function continueTo(nextStep) {
93076 context.map().on('move.intro drawn.intro', null);
93081 function deleteLines() {
93082 context.history().reset('doneUpdateLine');
93083 context.enter(modeBrowse(context));
93085 if (!context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93086 return chapter.restart();
93089 var msec = transitionTime(deleteLinesLoc, context.map().center());
93092 reveal(null, null, {
93097 context.map().centerZoomEase(deleteLinesLoc, 18, msec);
93098 timeout(function () {
93099 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93100 var box = pad(deleteLinesLoc, padding, context);
93104 var advance = function advance() {
93105 continueTo(rightClickIntersection);
93108 reveal(box, helpHtml('intro.lines.delete_lines', {
93109 street: _t('intro.graph.name.12th-avenue')
93111 buttonText: _t.html('intro.ok'),
93112 buttonCallback: advance
93114 context.map().on('move.intro drawn.intro', function () {
93115 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93116 var box = pad(deleteLinesLoc, padding, context);
93119 reveal(box, helpHtml('intro.lines.delete_lines', {
93120 street: _t('intro.graph.name.12th-avenue')
93123 buttonText: _t.html('intro.ok'),
93124 buttonCallback: advance
93127 context.history().on('change.intro', function () {
93128 timeout(function () {
93129 continueTo(deleteLines);
93130 }, 500); // after any transition (e.g. if user deleted intersection)
93134 function continueTo(nextStep) {
93135 context.map().on('move.intro drawn.intro', null);
93136 context.history().on('change.intro', null);
93141 function rightClickIntersection() {
93142 context.history().reset('doneUpdateLine');
93143 context.enter(modeBrowse(context));
93144 context.map().centerZoomEase(eleventhAvenueEnd, 18, 500);
93145 var rightClickString = helpHtml('intro.lines.split_street', {
93146 street1: _t('intro.graph.name.11th-avenue'),
93147 street2: _t('intro.graph.name.washington-street')
93148 }) + helpHtml('intro.lines.' + (context.lastPointerType() === 'mouse' ? 'rightclick_intersection' : 'edit_menu_intersection_touch'));
93149 timeout(function () {
93150 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
93151 var box = pad(eleventhAvenueEnd, padding, context);
93152 reveal(box, rightClickString);
93153 context.map().on('move.intro drawn.intro', function () {
93154 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
93155 var box = pad(eleventhAvenueEnd, padding, context);
93156 reveal(box, rightClickString, {
93160 context.on('enter.intro', function (mode) {
93161 if (mode.id !== 'select') return;
93162 var ids = context.selectedIDs();
93163 if (ids.length !== 1 || ids[0] !== eleventhAvenueEndID) return;
93164 timeout(function () {
93165 var node = selectMenuItem(context, 'split').node();
93167 continueTo(splitIntersection);
93168 }, 50); // after menu visible
93170 context.history().on('change.intro', function () {
93171 timeout(function () {
93172 continueTo(deleteLines);
93173 }, 300); // after any transition (e.g. if user deleted intersection)
93177 function continueTo(nextStep) {
93178 context.map().on('move.intro drawn.intro', null);
93179 context.on('enter.intro', null);
93180 context.history().on('change.intro', null);
93185 function splitIntersection() {
93186 if (!context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93187 return continueTo(deleteLines);
93190 var node = selectMenuItem(context, 'split').node();
93193 return continueTo(rightClickIntersection);
93196 var wasChanged = false;
93197 _washingtonSegmentID = null;
93198 reveal('.edit-menu', helpHtml('intro.lines.split_intersection', {
93199 street: _t('intro.graph.name.washington-street')
93203 context.map().on('move.intro drawn.intro', function () {
93204 var node = selectMenuItem(context, 'split').node();
93206 if (!wasChanged && !node) {
93207 return continueTo(rightClickIntersection);
93210 reveal('.edit-menu', helpHtml('intro.lines.split_intersection', {
93211 street: _t('intro.graph.name.washington-street')
93217 context.history().on('change.intro', function (changed) {
93219 timeout(function () {
93220 if (context.history().undoAnnotation() === _t('operations.split.annotation.line', {
93223 _washingtonSegmentID = changed.created()[0].id;
93224 continueTo(didSplit);
93226 _washingtonSegmentID = null;
93227 continueTo(retrySplit);
93229 }, 300); // after any transition (e.g. if user deleted intersection)
93232 function continueTo(nextStep) {
93233 context.map().on('move.intro drawn.intro', null);
93234 context.history().on('change.intro', null);
93239 function retrySplit() {
93240 context.enter(modeBrowse(context));
93241 context.map().centerZoomEase(eleventhAvenueEnd, 18, 500);
93243 var advance = function advance() {
93244 continueTo(rightClickIntersection);
93247 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
93248 var box = pad(eleventhAvenueEnd, padding, context);
93249 reveal(box, helpHtml('intro.lines.retry_split'), {
93250 buttonText: _t.html('intro.ok'),
93251 buttonCallback: advance
93253 context.map().on('move.intro drawn.intro', function () {
93254 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
93255 var box = pad(eleventhAvenueEnd, padding, context);
93256 reveal(box, helpHtml('intro.lines.retry_split'), {
93258 buttonText: _t.html('intro.ok'),
93259 buttonCallback: advance
93263 function continueTo(nextStep) {
93264 context.map().on('move.intro drawn.intro', null);
93269 function didSplit() {
93270 if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93271 return continueTo(rightClickIntersection);
93274 var ids = context.selectedIDs();
93275 var string = 'intro.lines.did_split_' + (ids.length > 1 ? 'multi' : 'single');
93276 var street = _t('intro.graph.name.washington-street');
93277 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93278 var box = pad(twelfthAvenue, padding, context);
93279 box.width = box.width / 2;
93280 reveal(box, helpHtml(string, {
93286 timeout(function () {
93287 context.map().centerZoomEase(twelfthAvenue, 18, 500);
93288 context.map().on('move.intro drawn.intro', function () {
93289 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93290 var box = pad(twelfthAvenue, padding, context);
93291 box.width = box.width / 2;
93292 reveal(box, helpHtml(string, {
93299 }, 600); // after initial reveal and curtain cut
93301 context.on('enter.intro', function () {
93302 var ids = context.selectedIDs();
93304 if (ids.length === 1 && ids[0] === _washingtonSegmentID) {
93305 continueTo(multiSelect);
93308 context.history().on('change.intro', function () {
93309 if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93310 return continueTo(rightClickIntersection);
93314 function continueTo(nextStep) {
93315 context.map().on('move.intro drawn.intro', null);
93316 context.on('enter.intro', null);
93317 context.history().on('change.intro', null);
93322 function multiSelect() {
93323 if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93324 return continueTo(rightClickIntersection);
93327 var ids = context.selectedIDs();
93328 var hasWashington = ids.indexOf(_washingtonSegmentID) !== -1;
93329 var hasTwelfth = ids.indexOf(twelfthAvenueID) !== -1;
93331 if (hasWashington && hasTwelfth) {
93332 return continueTo(multiRightClick);
93333 } else if (!hasWashington && !hasTwelfth) {
93334 return continueTo(didSplit);
93337 context.map().centerZoomEase(twelfthAvenue, 18, 500);
93338 timeout(function () {
93339 var selected, other, padding, box;
93341 if (hasWashington) {
93342 selected = _t('intro.graph.name.washington-street');
93343 other = _t('intro.graph.name.12th-avenue');
93344 padding = 60 * Math.pow(2, context.map().zoom() - 18);
93345 box = pad(twelfthAvenueEnd, padding, context);
93348 selected = _t('intro.graph.name.12th-avenue');
93349 other = _t('intro.graph.name.washington-street');
93350 padding = 200 * Math.pow(2, context.map().zoom() - 18);
93351 box = pad(twelfthAvenue, padding, context);
93355 reveal(box, helpHtml('intro.lines.multi_select', {
93356 selected: selected,
93358 }) + ' ' + helpHtml('intro.lines.add_to_selection_' + (context.lastPointerType() === 'mouse' ? 'click' : 'touch'), {
93359 selected: selected,
93362 context.map().on('move.intro drawn.intro', function () {
93363 if (hasWashington) {
93364 selected = _t('intro.graph.name.washington-street');
93365 other = _t('intro.graph.name.12th-avenue');
93366 padding = 60 * Math.pow(2, context.map().zoom() - 18);
93367 box = pad(twelfthAvenueEnd, padding, context);
93370 selected = _t('intro.graph.name.12th-avenue');
93371 other = _t('intro.graph.name.washington-street');
93372 padding = 200 * Math.pow(2, context.map().zoom() - 18);
93373 box = pad(twelfthAvenue, padding, context);
93377 reveal(box, helpHtml('intro.lines.multi_select', {
93378 selected: selected,
93380 }) + ' ' + helpHtml('intro.lines.add_to_selection_' + (context.lastPointerType() === 'mouse' ? 'click' : 'touch'), {
93381 selected: selected,
93387 context.on('enter.intro', function () {
93388 continueTo(multiSelect);
93390 context.history().on('change.intro', function () {
93391 if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93392 return continueTo(rightClickIntersection);
93397 function continueTo(nextStep) {
93398 context.map().on('move.intro drawn.intro', null);
93399 context.on('enter.intro', null);
93400 context.history().on('change.intro', null);
93405 function multiRightClick() {
93406 if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93407 return continueTo(rightClickIntersection);
93410 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93411 var box = pad(twelfthAvenue, padding, context);
93412 var rightClickString = helpHtml('intro.lines.multi_select_success') + helpHtml('intro.lines.multi_' + (context.lastPointerType() === 'mouse' ? 'rightclick' : 'edit_menu_touch'));
93413 reveal(box, rightClickString);
93414 context.map().on('move.intro drawn.intro', function () {
93415 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93416 var box = pad(twelfthAvenue, padding, context);
93417 reveal(box, rightClickString, {
93421 context.ui().editMenu().on('toggled.intro', function (open) {
93423 timeout(function () {
93424 var ids = context.selectedIDs();
93426 if (ids.length === 2 && ids.indexOf(twelfthAvenueID) !== -1 && ids.indexOf(_washingtonSegmentID) !== -1) {
93427 var node = selectMenuItem(context, 'delete').node();
93429 continueTo(multiDelete);
93430 } else if (ids.length === 1 && ids.indexOf(_washingtonSegmentID) !== -1) {
93431 return continueTo(multiSelect);
93433 return continueTo(didSplit);
93435 }, 300); // after edit menu visible
93437 context.history().on('change.intro', function () {
93438 if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93439 return continueTo(rightClickIntersection);
93443 function continueTo(nextStep) {
93444 context.map().on('move.intro drawn.intro', null);
93445 context.ui().editMenu().on('toggled.intro', null);
93446 context.history().on('change.intro', null);
93451 function multiDelete() {
93452 if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93453 return continueTo(rightClickIntersection);
93456 var node = selectMenuItem(context, 'delete').node();
93457 if (!node) return continueTo(multiRightClick);
93458 reveal('.edit-menu', helpHtml('intro.lines.multi_delete'), {
93461 context.map().on('move.intro drawn.intro', function () {
93462 reveal('.edit-menu', helpHtml('intro.lines.multi_delete'), {
93467 context.on('exit.intro', function () {
93468 if (context.hasEntity(_washingtonSegmentID) || context.hasEntity(twelfthAvenueID)) {
93469 return continueTo(multiSelect); // left select mode but roads still exist
93472 context.history().on('change.intro', function () {
93473 if (context.hasEntity(_washingtonSegmentID) || context.hasEntity(twelfthAvenueID)) {
93474 continueTo(retryDelete); // changed something but roads still exist
93480 function continueTo(nextStep) {
93481 context.map().on('move.intro drawn.intro', null);
93482 context.on('exit.intro', null);
93483 context.history().on('change.intro', null);
93488 function retryDelete() {
93489 context.enter(modeBrowse(context));
93490 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93491 var box = pad(twelfthAvenue, padding, context);
93492 reveal(box, helpHtml('intro.lines.retry_delete'), {
93493 buttonText: _t.html('intro.ok'),
93494 buttonCallback: function buttonCallback() {
93495 continueTo(multiSelect);
93499 function continueTo(nextStep) {
93505 dispatch.call('done');
93506 reveal('.ideditor', helpHtml('intro.lines.play', {
93507 next: _t('intro.buildings.title')
93509 tooltipBox: '.intro-nav-wrap .chapter-building',
93510 buttonText: _t.html('intro.ok'),
93511 buttonCallback: function buttonCallback() {
93512 reveal('.ideditor');
93517 chapter.enter = function () {
93521 chapter.exit = function () {
93522 timeouts.forEach(window.clearTimeout);
93523 select(window).on('pointerdown.intro mousedown.intro', null, true);
93524 context.on('enter.intro exit.intro', null);
93525 context.map().on('move.intro drawn.intro', null);
93526 context.history().on('change.intro', null);
93527 context.container().select('.inspector-wrap').on('wheel.intro', null);
93528 context.container().select('.preset-list-button').on('click.intro', null);
93531 chapter.restart = function () {
93536 return utilRebind(chapter, dispatch, 'on');
93539 function uiIntroBuilding(context, reveal) {
93540 var dispatch = dispatch$8('done');
93541 var house = [-85.62815, 41.95638];
93542 var tank = [-85.62732, 41.95347];
93543 var buildingCatetory = _mainPresetIndex.item('category-building');
93544 var housePreset = _mainPresetIndex.item('building/house');
93545 var tankPreset = _mainPresetIndex.item('man_made/storage_tank');
93547 var _houseID = null;
93548 var _tankID = null;
93550 title: 'intro.buildings.title'
93553 function timeout(f, t) {
93554 timeouts.push(window.setTimeout(f, t));
93557 function eventCancel(d3_event) {
93558 d3_event.stopPropagation();
93559 d3_event.preventDefault();
93562 function revealHouse(center, text, options) {
93563 var padding = 160 * Math.pow(2, context.map().zoom() - 20);
93564 var box = pad(center, padding, context);
93565 reveal(box, text, options);
93568 function revealTank(center, text, options) {
93569 var padding = 190 * Math.pow(2, context.map().zoom() - 19.5);
93570 var box = pad(center, padding, context);
93571 reveal(box, text, options);
93574 function addHouse() {
93575 context.enter(modeBrowse(context));
93576 context.history().reset('initial');
93578 var msec = transitionTime(house, context.map().center());
93581 reveal(null, null, {
93586 context.map().centerZoomEase(house, 19, msec);
93587 timeout(function () {
93588 var tooltip = reveal('button.add-area', helpHtml('intro.buildings.add_building'));
93589 tooltip.selectAll('.popover-inner').insert('svg', 'span').attr('class', 'tooltip-illustration').append('use').attr('xlink:href', '#iD-graphic-buildings');
93590 context.on('enter.intro', function (mode) {
93591 if (mode.id !== 'add-area') return;
93592 continueTo(startHouse);
93596 function continueTo(nextStep) {
93597 context.on('enter.intro', null);
93602 function startHouse() {
93603 if (context.mode().id !== 'add-area') {
93604 return continueTo(addHouse);
93608 context.map().zoomEase(20, 500);
93609 timeout(function () {
93610 var startString = helpHtml('intro.buildings.start_building') + helpHtml('intro.buildings.building_corner_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap'));
93611 revealHouse(house, startString);
93612 context.map().on('move.intro drawn.intro', function () {
93613 revealHouse(house, startString, {
93617 context.on('enter.intro', function (mode) {
93618 if (mode.id !== 'draw-area') return chapter.restart();
93619 continueTo(continueHouse);
93621 }, 550); // after easing
93623 function continueTo(nextStep) {
93624 context.map().on('move.intro drawn.intro', null);
93625 context.on('enter.intro', null);
93630 function continueHouse() {
93631 if (context.mode().id !== 'draw-area') {
93632 return continueTo(addHouse);
93636 var continueString = helpHtml('intro.buildings.continue_building') + '{br}' + helpHtml('intro.areas.finish_area_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) + helpHtml('intro.buildings.finish_building');
93637 revealHouse(house, continueString);
93638 context.map().on('move.intro drawn.intro', function () {
93639 revealHouse(house, continueString, {
93643 context.on('enter.intro', function (mode) {
93644 if (mode.id === 'draw-area') {
93646 } else if (mode.id === 'select') {
93647 var graph = context.graph();
93648 var way = context.entity(context.selectedIDs()[0]);
93649 var nodes = graph.childNodes(way);
93650 var points = utilArrayUniq(nodes).map(function (n) {
93651 return context.projection(n.loc);
93654 if (isMostlySquare(points)) {
93656 return continueTo(chooseCategoryBuilding);
93658 return continueTo(retryHouse);
93661 return chapter.restart();
93665 function continueTo(nextStep) {
93666 context.map().on('move.intro drawn.intro', null);
93667 context.on('enter.intro', null);
93672 function retryHouse() {
93673 var onClick = function onClick() {
93674 continueTo(addHouse);
93677 revealHouse(house, helpHtml('intro.buildings.retry_building'), {
93678 buttonText: _t.html('intro.ok'),
93679 buttonCallback: onClick
93681 context.map().on('move.intro drawn.intro', function () {
93682 revealHouse(house, helpHtml('intro.buildings.retry_building'), {
93684 buttonText: _t.html('intro.ok'),
93685 buttonCallback: onClick
93689 function continueTo(nextStep) {
93690 context.map().on('move.intro drawn.intro', null);
93695 function chooseCategoryBuilding() {
93696 if (!_houseID || !context.hasEntity(_houseID)) {
93700 var ids = context.selectedIDs();
93702 if (context.mode().id !== 'select' || !ids.length || ids[0] !== _houseID) {
93703 context.enter(modeSelect(context, [_houseID]));
93704 } // disallow scrolling
93707 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
93708 timeout(function () {
93709 // reset pane, in case user somehow happened to change it..
93710 context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
93711 var button = context.container().select('.preset-category-building .preset-list-button');
93712 reveal(button.node(), helpHtml('intro.buildings.choose_category_building', {
93713 category: buildingCatetory.name()
93715 button.on('click.intro', function () {
93716 button.on('click.intro', null);
93717 continueTo(choosePresetHouse);
93719 }, 400); // after preset list pane visible..
93721 context.on('enter.intro', function (mode) {
93722 if (!_houseID || !context.hasEntity(_houseID)) {
93723 return continueTo(addHouse);
93726 var ids = context.selectedIDs();
93728 if (mode.id !== 'select' || !ids.length || ids[0] !== _houseID) {
93729 return continueTo(chooseCategoryBuilding);
93733 function continueTo(nextStep) {
93734 context.container().select('.inspector-wrap').on('wheel.intro', null);
93735 context.container().select('.preset-list-button').on('click.intro', null);
93736 context.on('enter.intro', null);
93741 function choosePresetHouse() {
93742 if (!_houseID || !context.hasEntity(_houseID)) {
93746 var ids = context.selectedIDs();
93748 if (context.mode().id !== 'select' || !ids.length || ids[0] !== _houseID) {
93749 context.enter(modeSelect(context, [_houseID]));
93750 } // disallow scrolling
93753 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
93754 timeout(function () {
93755 // reset pane, in case user somehow happened to change it..
93756 context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
93757 var button = context.container().select('.preset-building-house .preset-list-button');
93758 reveal(button.node(), helpHtml('intro.buildings.choose_preset_house', {
93759 preset: housePreset.name()
93763 button.on('click.intro', function () {
93764 button.on('click.intro', null);
93765 continueTo(closeEditorHouse);
93767 }, 400); // after preset list pane visible..
93769 context.on('enter.intro', function (mode) {
93770 if (!_houseID || !context.hasEntity(_houseID)) {
93771 return continueTo(addHouse);
93774 var ids = context.selectedIDs();
93776 if (mode.id !== 'select' || !ids.length || ids[0] !== _houseID) {
93777 return continueTo(chooseCategoryBuilding);
93781 function continueTo(nextStep) {
93782 context.container().select('.inspector-wrap').on('wheel.intro', null);
93783 context.container().select('.preset-list-button').on('click.intro', null);
93784 context.on('enter.intro', null);
93789 function closeEditorHouse() {
93790 if (!_houseID || !context.hasEntity(_houseID)) {
93794 var ids = context.selectedIDs();
93796 if (context.mode().id !== 'select' || !ids.length || ids[0] !== _houseID) {
93797 context.enter(modeSelect(context, [_houseID]));
93800 context.history().checkpoint('hasHouse');
93801 context.on('exit.intro', function () {
93802 continueTo(rightClickHouse);
93804 timeout(function () {
93805 reveal('.entity-editor-pane', helpHtml('intro.buildings.close', {
93807 html: icon('#iD-icon-close', 'inline')
93812 function continueTo(nextStep) {
93813 context.on('exit.intro', null);
93818 function rightClickHouse() {
93819 if (!_houseID) return chapter.restart();
93820 context.enter(modeBrowse(context));
93821 context.history().reset('hasHouse');
93822 var zoom = context.map().zoom();
93828 context.map().centerZoomEase(house, zoom, 500);
93829 context.on('enter.intro', function (mode) {
93830 if (mode.id !== 'select') return;
93831 var ids = context.selectedIDs();
93832 if (ids.length !== 1 || ids[0] !== _houseID) return;
93833 timeout(function () {
93834 var node = selectMenuItem(context, 'orthogonalize').node();
93836 continueTo(clickSquare);
93837 }, 50); // after menu visible
93839 context.map().on('move.intro drawn.intro', function () {
93840 var rightclickString = helpHtml('intro.buildings.' + (context.lastPointerType() === 'mouse' ? 'rightclick_building' : 'edit_menu_building_touch'));
93841 revealHouse(house, rightclickString, {
93845 context.history().on('change.intro', function () {
93846 continueTo(rightClickHouse);
93849 function continueTo(nextStep) {
93850 context.on('enter.intro', null);
93851 context.map().on('move.intro drawn.intro', null);
93852 context.history().on('change.intro', null);
93857 function clickSquare() {
93858 if (!_houseID) return chapter.restart();
93859 var entity = context.hasEntity(_houseID);
93860 if (!entity) return continueTo(rightClickHouse);
93861 var node = selectMenuItem(context, 'orthogonalize').node();
93864 return continueTo(rightClickHouse);
93867 var wasChanged = false;
93868 reveal('.edit-menu', helpHtml('intro.buildings.square_building'), {
93871 context.on('enter.intro', function (mode) {
93872 if (mode.id === 'browse') {
93873 continueTo(rightClickHouse);
93874 } else if (mode.id === 'move' || mode.id === 'rotate') {
93875 continueTo(retryClickSquare);
93878 context.map().on('move.intro', function () {
93879 var node = selectMenuItem(context, 'orthogonalize').node();
93881 if (!wasChanged && !node) {
93882 return continueTo(rightClickHouse);
93885 reveal('.edit-menu', helpHtml('intro.buildings.square_building'), {
93890 context.history().on('change.intro', function () {
93892 context.history().on('change.intro', null); // Something changed. Wait for transition to complete and check undo annotation.
93894 timeout(function () {
93895 if (context.history().undoAnnotation() === _t('operations.orthogonalize.annotation.feature', {
93898 continueTo(doneSquare);
93900 continueTo(retryClickSquare);
93902 }, 500); // after transitioned actions
93905 function continueTo(nextStep) {
93906 context.on('enter.intro', null);
93907 context.map().on('move.intro', null);
93908 context.history().on('change.intro', null);
93913 function retryClickSquare() {
93914 context.enter(modeBrowse(context));
93915 revealHouse(house, helpHtml('intro.buildings.retry_square'), {
93916 buttonText: _t.html('intro.ok'),
93917 buttonCallback: function buttonCallback() {
93918 continueTo(rightClickHouse);
93922 function continueTo(nextStep) {
93927 function doneSquare() {
93928 context.history().checkpoint('doneSquare');
93929 revealHouse(house, helpHtml('intro.buildings.done_square'), {
93930 buttonText: _t.html('intro.ok'),
93931 buttonCallback: function buttonCallback() {
93932 continueTo(addTank);
93936 function continueTo(nextStep) {
93941 function addTank() {
93942 context.enter(modeBrowse(context));
93943 context.history().reset('doneSquare');
93945 var msec = transitionTime(tank, context.map().center());
93948 reveal(null, null, {
93953 context.map().centerZoomEase(tank, 19.5, msec);
93954 timeout(function () {
93955 reveal('button.add-area', helpHtml('intro.buildings.add_tank'));
93956 context.on('enter.intro', function (mode) {
93957 if (mode.id !== 'add-area') return;
93958 continueTo(startTank);
93962 function continueTo(nextStep) {
93963 context.on('enter.intro', null);
93968 function startTank() {
93969 if (context.mode().id !== 'add-area') {
93970 return continueTo(addTank);
93974 timeout(function () {
93975 var startString = helpHtml('intro.buildings.start_tank') + helpHtml('intro.buildings.tank_edge_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap'));
93976 revealTank(tank, startString);
93977 context.map().on('move.intro drawn.intro', function () {
93978 revealTank(tank, startString, {
93982 context.on('enter.intro', function (mode) {
93983 if (mode.id !== 'draw-area') return chapter.restart();
93984 continueTo(continueTank);
93986 }, 550); // after easing
93988 function continueTo(nextStep) {
93989 context.map().on('move.intro drawn.intro', null);
93990 context.on('enter.intro', null);
93995 function continueTank() {
93996 if (context.mode().id !== 'draw-area') {
93997 return continueTo(addTank);
94001 var continueString = helpHtml('intro.buildings.continue_tank') + '{br}' + helpHtml('intro.areas.finish_area_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) + helpHtml('intro.buildings.finish_tank');
94002 revealTank(tank, continueString);
94003 context.map().on('move.intro drawn.intro', function () {
94004 revealTank(tank, continueString, {
94008 context.on('enter.intro', function (mode) {
94009 if (mode.id === 'draw-area') {
94011 } else if (mode.id === 'select') {
94012 _tankID = context.selectedIDs()[0];
94013 return continueTo(searchPresetTank);
94015 return continueTo(addTank);
94019 function continueTo(nextStep) {
94020 context.map().on('move.intro drawn.intro', null);
94021 context.on('enter.intro', null);
94026 function searchPresetTank() {
94027 if (!_tankID || !context.hasEntity(_tankID)) {
94031 var ids = context.selectedIDs();
94033 if (context.mode().id !== 'select' || !ids.length || ids[0] !== _tankID) {
94034 context.enter(modeSelect(context, [_tankID]));
94035 } // disallow scrolling
94038 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
94039 timeout(function () {
94040 // reset pane, in case user somehow happened to change it..
94041 context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
94042 context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
94043 reveal('.preset-search-input', helpHtml('intro.buildings.search_tank', {
94044 preset: tankPreset.name()
94046 }, 400); // after preset list pane visible..
94048 context.on('enter.intro', function (mode) {
94049 if (!_tankID || !context.hasEntity(_tankID)) {
94050 return continueTo(addTank);
94053 var ids = context.selectedIDs();
94055 if (mode.id !== 'select' || !ids.length || ids[0] !== _tankID) {
94056 // keep the user's area selected..
94057 context.enter(modeSelect(context, [_tankID])); // reset pane, in case user somehow happened to change it..
94059 context.container().select('.inspector-wrap .panewrap').style('right', '-100%'); // disallow scrolling
94061 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
94062 context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
94063 reveal('.preset-search-input', helpHtml('intro.buildings.search_tank', {
94064 preset: tankPreset.name()
94066 context.history().on('change.intro', null);
94070 function checkPresetSearch() {
94071 var first = context.container().select('.preset-list-item:first-child');
94073 if (first.classed('preset-man_made-storage_tank')) {
94074 reveal(first.select('.preset-list-button').node(), helpHtml('intro.buildings.choose_tank', {
94075 preset: tankPreset.name()
94079 context.container().select('.preset-search-input').on('keydown.intro', eventCancel, true).on('keyup.intro', null);
94080 context.history().on('change.intro', function () {
94081 continueTo(closeEditorTank);
94086 function continueTo(nextStep) {
94087 context.container().select('.inspector-wrap').on('wheel.intro', null);
94088 context.on('enter.intro', null);
94089 context.history().on('change.intro', null);
94090 context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
94095 function closeEditorTank() {
94096 if (!_tankID || !context.hasEntity(_tankID)) {
94100 var ids = context.selectedIDs();
94102 if (context.mode().id !== 'select' || !ids.length || ids[0] !== _tankID) {
94103 context.enter(modeSelect(context, [_tankID]));
94106 context.history().checkpoint('hasTank');
94107 context.on('exit.intro', function () {
94108 continueTo(rightClickTank);
94110 timeout(function () {
94111 reveal('.entity-editor-pane', helpHtml('intro.buildings.close', {
94113 html: icon('#iD-icon-close', 'inline')
94118 function continueTo(nextStep) {
94119 context.on('exit.intro', null);
94124 function rightClickTank() {
94125 if (!_tankID) return continueTo(addTank);
94126 context.enter(modeBrowse(context));
94127 context.history().reset('hasTank');
94128 context.map().centerEase(tank, 500);
94129 timeout(function () {
94130 context.on('enter.intro', function (mode) {
94131 if (mode.id !== 'select') return;
94132 var ids = context.selectedIDs();
94133 if (ids.length !== 1 || ids[0] !== _tankID) return;
94134 timeout(function () {
94135 var node = selectMenuItem(context, 'circularize').node();
94137 continueTo(clickCircle);
94138 }, 50); // after menu visible
94140 var rightclickString = helpHtml('intro.buildings.' + (context.lastPointerType() === 'mouse' ? 'rightclick_tank' : 'edit_menu_tank_touch'));
94141 revealTank(tank, rightclickString);
94142 context.map().on('move.intro drawn.intro', function () {
94143 revealTank(tank, rightclickString, {
94147 context.history().on('change.intro', function () {
94148 continueTo(rightClickTank);
94152 function continueTo(nextStep) {
94153 context.on('enter.intro', null);
94154 context.map().on('move.intro drawn.intro', null);
94155 context.history().on('change.intro', null);
94160 function clickCircle() {
94161 if (!_tankID) return chapter.restart();
94162 var entity = context.hasEntity(_tankID);
94163 if (!entity) return continueTo(rightClickTank);
94164 var node = selectMenuItem(context, 'circularize').node();
94167 return continueTo(rightClickTank);
94170 var wasChanged = false;
94171 reveal('.edit-menu', helpHtml('intro.buildings.circle_tank'), {
94174 context.on('enter.intro', function (mode) {
94175 if (mode.id === 'browse') {
94176 continueTo(rightClickTank);
94177 } else if (mode.id === 'move' || mode.id === 'rotate') {
94178 continueTo(retryClickCircle);
94181 context.map().on('move.intro', function () {
94182 var node = selectMenuItem(context, 'circularize').node();
94184 if (!wasChanged && !node) {
94185 return continueTo(rightClickTank);
94188 reveal('.edit-menu', helpHtml('intro.buildings.circle_tank'), {
94193 context.history().on('change.intro', function () {
94195 context.history().on('change.intro', null); // Something changed. Wait for transition to complete and check undo annotation.
94197 timeout(function () {
94198 if (context.history().undoAnnotation() === _t('operations.circularize.annotation.feature', {
94203 continueTo(retryClickCircle);
94205 }, 500); // after transitioned actions
94208 function continueTo(nextStep) {
94209 context.on('enter.intro', null);
94210 context.map().on('move.intro', null);
94211 context.history().on('change.intro', null);
94216 function retryClickCircle() {
94217 context.enter(modeBrowse(context));
94218 revealTank(tank, helpHtml('intro.buildings.retry_circle'), {
94219 buttonText: _t.html('intro.ok'),
94220 buttonCallback: function buttonCallback() {
94221 continueTo(rightClickTank);
94225 function continueTo(nextStep) {
94231 dispatch.call('done');
94232 reveal('.ideditor', helpHtml('intro.buildings.play', {
94233 next: _t('intro.startediting.title')
94235 tooltipBox: '.intro-nav-wrap .chapter-startEditing',
94236 buttonText: _t.html('intro.ok'),
94237 buttonCallback: function buttonCallback() {
94238 reveal('.ideditor');
94243 chapter.enter = function () {
94247 chapter.exit = function () {
94248 timeouts.forEach(window.clearTimeout);
94249 context.on('enter.intro exit.intro', null);
94250 context.map().on('move.intro drawn.intro', null);
94251 context.history().on('change.intro', null);
94252 context.container().select('.inspector-wrap').on('wheel.intro', null);
94253 context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
94254 context.container().select('.more-fields .combobox-input').on('click.intro', null);
94257 chapter.restart = function () {
94262 return utilRebind(chapter, dispatch, 'on');
94265 function uiIntroStartEditing(context, reveal) {
94266 var dispatch = dispatch$8('done', 'startEditing');
94267 var modalSelection = select(null);
94269 title: 'intro.startediting.title'
94272 function showHelp() {
94273 reveal('.map-control.help-control', helpHtml('intro.startediting.help'), {
94274 buttonText: _t.html('intro.ok'),
94275 buttonCallback: function buttonCallback() {
94281 function shortcuts() {
94282 reveal('.map-control.help-control', helpHtml('intro.startediting.shortcuts'), {
94283 buttonText: _t.html('intro.ok'),
94284 buttonCallback: function buttonCallback() {
94290 function showSave() {
94291 context.container().selectAll('.shaded').remove(); // in case user opened keyboard shortcuts
94293 reveal('.top-toolbar button.save', helpHtml('intro.startediting.save'), {
94294 buttonText: _t.html('intro.ok'),
94295 buttonCallback: function buttonCallback() {
94301 function showStart() {
94302 context.container().selectAll('.shaded').remove(); // in case user opened keyboard shortcuts
94304 modalSelection = uiModal(context.container());
94305 modalSelection.select('.modal').attr('class', 'modal-splash modal');
94306 modalSelection.selectAll('.close').remove();
94307 var startbutton = modalSelection.select('.content').attr('class', 'fillL').append('button').attr('class', 'modal-section huge-modal-button').on('click', function () {
94308 modalSelection.remove();
94310 startbutton.append('svg').attr('class', 'illustration').append('use').attr('xlink:href', '#iD-logo-walkthrough');
94311 startbutton.append('h2').call(_t.append('intro.startediting.start'));
94312 dispatch.call('startEditing');
94315 chapter.enter = function () {
94319 chapter.exit = function () {
94320 modalSelection.remove();
94321 context.container().selectAll('.shaded').remove(); // in case user opened keyboard shortcuts
94324 return utilRebind(chapter, dispatch, 'on');
94328 welcome: uiIntroWelcome,
94329 navigation: uiIntroNavigation,
94330 point: uiIntroPoint,
94333 building: uiIntroBuilding,
94334 startEditing: uiIntroStartEditing
94336 var chapterFlow = ['welcome', 'navigation', 'point', 'area', 'line', 'building', 'startEditing'];
94337 function uiIntro(context) {
94338 var INTRO_IMAGERY = 'EsriWorldImageryClarity';
94339 var _introGraph = {};
94343 function intro(selection) {
94344 _mainFileFetcher.get('intro_graph').then(function (dataIntroGraph) {
94345 // create entities for intro graph and localize names
94346 for (var id in dataIntroGraph) {
94347 if (!_introGraph[id]) {
94348 _introGraph[id] = osmEntity(localize(dataIntroGraph[id]));
94352 selection.call(startIntro);
94353 })["catch"](function () {
94358 function startIntro(selection) {
94359 context.enter(modeBrowse(context)); // Save current map state
94361 var osm = context.connection();
94362 var history = context.history().toJSON();
94363 var hash = window.location.hash;
94364 var center = context.map().center();
94365 var zoom = context.map().zoom();
94366 var background = context.background().baseLayerSource();
94367 var overlays = context.background().overlayLayerSources();
94368 var opacity = context.container().selectAll('.main-map .layer-background').style('opacity');
94369 var caches = osm && osm.caches();
94370 var baseEntities = context.history().graph().base().entities; // Show sidebar and disable the sidebar resizing button
94371 // (this needs to be before `context.inIntro(true)`)
94373 context.ui().sidebar.expand();
94374 context.container().selectAll('button.sidebar-toggle').classed('disabled', true); // Block saving
94376 context.inIntro(true); // Load semi-real data used in intro
94379 osm.toggle(false).reset();
94382 context.history().reset();
94383 context.history().merge(Object.values(coreGraph().load(_introGraph).entities));
94384 context.history().checkpoint('initial'); // Setup imagery
94386 var imagery = context.background().findSource(INTRO_IMAGERY);
94389 context.background().baseLayerSource(imagery);
94391 context.background().bing();
94394 overlays.forEach(function (d) {
94395 return context.background().toggleOverlayLayer(d);
94396 }); // Setup data layers (only OSM)
94398 var layers = context.layers();
94399 layers.all().forEach(function (item) {
94400 // if the layer has the function `enabled`
94401 if (typeof item.layer.enabled === 'function') {
94402 item.layer.enabled(item.id === 'osm');
94405 context.container().selectAll('.main-map .layer-background').style('opacity', 1);
94406 var curtain = uiCurtain(context.container().node());
94407 selection.call(curtain); // Store that the user started the walkthrough..
94409 corePreferences('walkthrough_started', 'yes'); // Restore previous walkthrough progress..
94411 var storedProgress = corePreferences('walkthrough_progress') || '';
94412 var progress = storedProgress.split(';').filter(Boolean);
94413 var chapters = chapterFlow.map(function (chapter, i) {
94414 var s = chapterUi[chapter](context, curtain.reveal).on('done', function () {
94415 buttons.filter(function (d) {
94416 return d.title === s.title;
94417 }).classed('finished', true);
94419 if (i < chapterFlow.length - 1) {
94420 var next = chapterFlow[i + 1];
94421 context.container().select("button.chapter-".concat(next)).classed('next', true);
94422 } // Store walkthrough progress..
94425 progress.push(chapter);
94426 corePreferences('walkthrough_progress', utilArrayUniq(progress).join(';'));
94430 chapters[chapters.length - 1].on('startEditing', function () {
94431 // Store walkthrough progress..
94432 progress.push('startEditing');
94433 corePreferences('walkthrough_progress', utilArrayUniq(progress).join(';')); // Store if walkthrough is completed..
94435 var incomplete = utilArrayDifference(chapterFlow, progress);
94437 if (!incomplete.length) {
94438 corePreferences('walkthrough_completed', 'yes');
94443 context.container().selectAll('.main-map .layer-background').style('opacity', opacity);
94444 context.container().selectAll('button.sidebar-toggle').classed('disabled', false);
94447 osm.toggle(true).reset().caches(caches);
94450 context.history().reset().merge(Object.values(baseEntities));
94451 context.background().baseLayerSource(background);
94452 overlays.forEach(function (d) {
94453 return context.background().toggleOverlayLayer(d);
94457 context.history().fromJSON(history, false);
94460 context.map().centerZoom(center, zoom);
94461 window.location.replace(hash);
94462 context.inIntro(false);
94464 var navwrap = selection.append('div').attr('class', 'intro-nav-wrap fillD');
94465 navwrap.append('svg').attr('class', 'intro-nav-wrap-logo').append('use').attr('xlink:href', '#iD-logo-walkthrough');
94466 var buttonwrap = navwrap.append('div').attr('class', 'joined').selectAll('button.chapter');
94467 var buttons = buttonwrap.data(chapters).enter().append('button').attr('class', function (d, i) {
94468 return "chapter chapter-".concat(chapterFlow[i]);
94469 }).on('click', enterChapter);
94470 buttons.append('span').html(function (d) {
94471 return _t.html(d.title);
94473 buttons.append('span').attr('class', 'status').call(svgIcon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward', 'inline'));
94474 enterChapter(null, chapters[0]);
94476 function enterChapter(d3_event, newChapter) {
94477 if (_currChapter) {
94478 _currChapter.exit();
94481 context.enter(modeBrowse(context));
94482 _currChapter = newChapter;
94484 _currChapter.enter();
94486 buttons.classed('next', false).classed('active', function (d) {
94487 return d.title === _currChapter.title;
94495 function uiIssuesInfo(context) {
94496 var warningsItem = {
94499 iconID: 'iD-icon-alert',
94500 descriptionID: 'issues.warnings_and_errors'
94502 var resolvedItem = {
94505 iconID: 'iD-icon-apply',
94506 descriptionID: 'issues.user_resolved_issues'
94509 function update(selection) {
94510 var shownItems = [];
94511 var liveIssues = context.validator().getIssues({
94512 what: corePreferences('validate-what') || 'edited',
94513 where: corePreferences('validate-where') || 'all'
94516 if (liveIssues.length) {
94517 warningsItem.count = liveIssues.length;
94518 shownItems.push(warningsItem);
94521 if (corePreferences('validate-what') === 'all') {
94522 var resolvedIssues = context.validator().getResolvedIssues();
94524 if (resolvedIssues.length) {
94525 resolvedItem.count = resolvedIssues.length;
94526 shownItems.push(resolvedItem);
94530 var chips = selection.selectAll('.chip').data(shownItems, function (d) {
94533 chips.exit().remove();
94534 var enter = chips.enter().append('a').attr('class', function (d) {
94535 return 'chip ' + d.id + '-count';
94536 }).attr('href', '#').each(function (d) {
94537 var chipSelection = select(this);
94538 var tooltipBehavior = uiTooltip().placement('top').title(_t.html(d.descriptionID));
94539 chipSelection.call(tooltipBehavior).on('click', function (d3_event) {
94540 d3_event.preventDefault();
94541 tooltipBehavior.hide(select(this)); // open the Issues pane
94543 context.ui().togglePanes(context.container().select('.map-panes .issues-pane'));
94545 chipSelection.call(svgIcon('#' + d.iconID));
94547 enter.append('span').attr('class', 'count');
94548 enter.merge(chips).selectAll('span.count').text(function (d) {
94549 return d.count.toString();
94553 return function (selection) {
94555 context.validator().on('validated.infobox', function () {
94561 function uiMapInMap(context) {
94562 function mapInMap(selection) {
94563 var backgroundLayer = rendererTileLayer(context);
94564 var overlayLayers = {};
94565 var projection = geoRawMercator();
94566 var dataLayer = svgData(projection, context).showLabels(false);
94567 var debugLayer = svgDebug(projection, context);
94568 var zoom = d3_zoom().scaleExtent([geoZoomToScale(0.5), geoZoomToScale(24)]).on('start', zoomStarted).on('zoom', zoomed).on('end', zoomEnded);
94569 var wrap = select(null);
94570 var tiles = select(null);
94571 var viewport = select(null);
94572 var _isTransformed = false;
94573 var _isHidden = true;
94574 var _skipEvents = false;
94575 var _gesture = null;
94576 var _zDiff = 6; // by default, minimap renders at (main zoom - 6)
94578 var _dMini; // dimensions of minimap
94581 var _cMini; // center pixel of minimap
94584 var _tStart; // transform at start of gesture
94587 var _tCurr; // transform at most recent event
94592 function zoomStarted() {
94593 if (_skipEvents) return;
94594 _tStart = _tCurr = projection.transform();
94598 function zoomed(d3_event) {
94599 if (_skipEvents) return;
94600 var x = d3_event.transform.x;
94601 var y = d3_event.transform.y;
94602 var k = d3_event.transform.k;
94603 var isZooming = k !== _tStart.k;
94604 var isPanning = x !== _tStart.x || y !== _tStart.y;
94606 if (!isZooming && !isPanning) {
94607 return; // no change
94608 } // lock in either zooming or panning, don't allow both in minimap.
94612 _gesture = isZooming ? 'zoom' : 'pan';
94615 var tMini = projection.transform();
94618 if (_gesture === 'zoom') {
94619 scale = k / tMini.k;
94620 tX = (_cMini[0] / scale - _cMini[0]) * scale;
94621 tY = (_cMini[1] / scale - _cMini[1]) * scale;
94629 utilSetTransform(tiles, tX, tY, scale);
94630 utilSetTransform(viewport, 0, 0, scale);
94631 _isTransformed = true;
94632 _tCurr = identity$2.translate(x, y).scale(k);
94633 var zMain = geoScaleToZoom(context.projection.scale());
94634 var zMini = geoScaleToZoom(k);
94635 _zDiff = zMain - zMini;
94639 function zoomEnded() {
94640 if (_skipEvents) return;
94641 if (_gesture !== 'pan') return;
94642 updateProjection();
94644 context.map().center(projection.invert(_cMini)); // recenter main map..
94647 function updateProjection() {
94648 var loc = context.map().center();
94649 var tMain = context.projection.transform();
94650 var zMain = geoScaleToZoom(tMain.k);
94651 var zMini = Math.max(zMain - _zDiff, 0.5);
94652 var kMini = geoZoomToScale(zMini);
94653 projection.translate([tMain.x, tMain.y]).scale(kMini);
94654 var point = projection(loc);
94655 var mouse = _gesture === 'pan' ? geoVecSubtract([_tCurr.x, _tCurr.y], [_tStart.x, _tStart.y]) : [0, 0];
94656 var xMini = _cMini[0] - point[0] + tMain.x + mouse[0];
94657 var yMini = _cMini[1] - point[1] + tMain.y + mouse[1];
94658 projection.translate([xMini, yMini]).clipExtent([[0, 0], _dMini]);
94659 _tCurr = projection.transform();
94661 if (_isTransformed) {
94662 utilSetTransform(tiles, 0, 0);
94663 utilSetTransform(viewport, 0, 0);
94664 _isTransformed = false;
94667 zoom.scaleExtent([geoZoomToScale(0.5), geoZoomToScale(zMain - 3)]);
94668 _skipEvents = true;
94669 wrap.call(zoom.transform, _tCurr);
94670 _skipEvents = false;
94673 function redraw() {
94674 clearTimeout(_timeoutID);
94675 if (_isHidden) return;
94676 updateProjection();
94677 var zMini = geoScaleToZoom(projection.scale()); // setup tile container
94679 tiles = wrap.selectAll('.map-in-map-tiles').data([0]);
94680 tiles = tiles.enter().append('div').attr('class', 'map-in-map-tiles').merge(tiles); // redraw background
94682 backgroundLayer.source(context.background().baseLayerSource()).projection(projection).dimensions(_dMini);
94683 var background = tiles.selectAll('.map-in-map-background').data([0]);
94684 background.enter().append('div').attr('class', 'map-in-map-background').merge(background).call(backgroundLayer); // redraw overlay
94686 var overlaySources = context.background().overlayLayerSources();
94687 var activeOverlayLayers = [];
94689 for (var i = 0; i < overlaySources.length; i++) {
94690 if (overlaySources[i].validZoom(zMini)) {
94691 if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context);
94692 activeOverlayLayers.push(overlayLayers[i].source(overlaySources[i]).projection(projection).dimensions(_dMini));
94696 var overlay = tiles.selectAll('.map-in-map-overlay').data([0]);
94697 overlay = overlay.enter().append('div').attr('class', 'map-in-map-overlay').merge(overlay);
94698 var overlays = overlay.selectAll('div').data(activeOverlayLayers, function (d) {
94699 return d.source().name();
94701 overlays.exit().remove();
94702 overlays = overlays.enter().append('div').merge(overlays).each(function (layer) {
94703 select(this).call(layer);
94705 var dataLayers = tiles.selectAll('.map-in-map-data').data([0]);
94706 dataLayers.exit().remove();
94707 dataLayers = dataLayers.enter().append('svg').attr('class', 'map-in-map-data').merge(dataLayers).call(dataLayer).call(debugLayer); // redraw viewport bounding box
94709 if (_gesture !== 'pan') {
94710 var getPath = d3_geoPath(projection);
94713 coordinates: [context.map().extent().polygon()]
94715 viewport = wrap.selectAll('.map-in-map-viewport').data([0]);
94716 viewport = viewport.enter().append('svg').attr('class', 'map-in-map-viewport').merge(viewport);
94717 var path = viewport.selectAll('.map-in-map-bbox').data([bbox]);
94718 path.enter().append('path').attr('class', 'map-in-map-bbox').merge(path).attr('d', getPath).classed('thick', function (d) {
94719 return getPath.area(d) < 30;
94724 function queueRedraw() {
94725 clearTimeout(_timeoutID);
94726 _timeoutID = setTimeout(function () {
94731 function toggle(d3_event) {
94732 if (d3_event) d3_event.preventDefault();
94733 _isHidden = !_isHidden;
94734 context.container().select('.minimap-toggle-item').classed('active', !_isHidden).select('input').property('checked', !_isHidden);
94737 wrap.style('display', 'block').style('opacity', '1').transition().duration(200).style('opacity', '0').on('end', function () {
94738 selection.selectAll('.map-in-map').style('display', 'none');
94741 wrap.style('display', 'block').style('opacity', '0').transition().duration(200).style('opacity', '1').on('end', function () {
94747 uiMapInMap.toggle = toggle;
94748 wrap = selection.selectAll('.map-in-map').data([0]);
94749 wrap = wrap.enter().append('div').attr('class', 'map-in-map').style('display', _isHidden ? 'none' : 'block').call(zoom).on('dblclick.zoom', null).merge(wrap); // reflow warning: Hardcode dimensions - currently can't resize it anyway..
94751 _dMini = [200, 150]; //utilGetDimensions(wrap);
94753 _cMini = geoVecScale(_dMini, 0.5);
94754 context.map().on('drawn.map-in-map', function (drawn) {
94755 if (drawn.full === true) {
94760 context.keybinding().on(_t('background.minimap.key'), toggle);
94766 function uiNotice(context) {
94767 return function (selection) {
94768 var div = selection.append('div').attr('class', 'notice');
94769 var button = div.append('button').attr('class', 'zoom-to notice fillD').on('click', function () {
94770 context.map().zoomEase(context.minEditableZoom());
94771 }).on('wheel', function (d3_event) {
94772 // let wheel events pass through #4482
94773 var e2 = new WheelEvent(d3_event.type, d3_event);
94774 context.surface().node().dispatchEvent(e2);
94776 button.call(svgIcon('#iD-icon-plus', 'pre-text')).append('span').attr('class', 'label').call(_t.append('zoom_in_edit'));
94778 function disableTooHigh() {
94779 var canEdit = context.map().zoom() >= context.minEditableZoom();
94780 div.style('display', canEdit ? 'none' : 'block');
94783 context.map().on('move.notice', debounce(disableTooHigh, 500));
94788 function uiPhotoviewer(context) {
94789 var dispatch = dispatch$8('resize');
94791 var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
94793 function photoviewer(selection) {
94794 selection.append('button').attr('class', 'thumb-hide').attr('title', _t('icons.close')).on('click', function () {
94795 if (services.streetside) {
94796 services.streetside.hideViewer(context);
94799 if (services.mapillary) {
94800 services.mapillary.hideViewer(context);
94803 if (services.kartaview) {
94804 services.kartaview.hideViewer(context);
94806 }).append('div').call(svgIcon('#iD-icon-close'));
94808 function preventDefault(d3_event) {
94809 d3_event.preventDefault();
94812 selection.append('button').attr('class', 'resize-handle-xy').on('touchstart touchdown touchend', preventDefault).on(_pointerPrefix + 'down', buildResizeListener(selection, 'resize', dispatch, {
94816 selection.append('button').attr('class', 'resize-handle-x').on('touchstart touchdown touchend', preventDefault).on(_pointerPrefix + 'down', buildResizeListener(selection, 'resize', dispatch, {
94819 selection.append('button').attr('class', 'resize-handle-y').on('touchstart touchdown touchend', preventDefault).on(_pointerPrefix + 'down', buildResizeListener(selection, 'resize', dispatch, {
94823 function buildResizeListener(target, eventName, dispatch, options) {
94824 var resizeOnX = !!options.resizeOnX;
94825 var resizeOnY = !!options.resizeOnY;
94826 var minHeight = options.minHeight || 240;
94827 var minWidth = options.minWidth || 320;
94834 function startResize(d3_event) {
94835 if (pointerId !== (d3_event.pointerId || 'mouse')) return;
94836 d3_event.preventDefault();
94837 d3_event.stopPropagation();
94838 var mapSize = context.map().dimensions();
94841 var maxWidth = mapSize[0];
94842 var newWidth = clamp(startWidth + d3_event.clientX - startX, minWidth, maxWidth);
94843 target.style('width', newWidth + 'px');
94847 var maxHeight = mapSize[1] - 90; // preserve space at top/bottom of map
94849 var newHeight = clamp(startHeight + startY - d3_event.clientY, minHeight, maxHeight);
94850 target.style('height', newHeight + 'px');
94853 dispatch.call(eventName, target, utilGetDimensions(target, true));
94856 function clamp(num, min, max) {
94857 return Math.max(min, Math.min(num, max));
94860 function stopResize(d3_event) {
94861 if (pointerId !== (d3_event.pointerId || 'mouse')) return;
94862 d3_event.preventDefault();
94863 d3_event.stopPropagation(); // remove all the listeners we added
94865 select(window).on('.' + eventName, null);
94868 return function initResize(d3_event) {
94869 d3_event.preventDefault();
94870 d3_event.stopPropagation();
94871 pointerId = d3_event.pointerId || 'mouse';
94872 startX = d3_event.clientX;
94873 startY = d3_event.clientY;
94874 var targetRect = target.node().getBoundingClientRect();
94875 startWidth = targetRect.width;
94876 startHeight = targetRect.height;
94877 select(window).on(_pointerPrefix + 'move.' + eventName, startResize, false).on(_pointerPrefix + 'up.' + eventName, stopResize, false);
94879 if (_pointerPrefix === 'pointer') {
94880 select(window).on('pointercancel.' + eventName, stopResize, false);
94886 photoviewer.onMapResize = function () {
94887 var photoviewer = context.container().select('.photoviewer');
94888 var content = context.container().select('.main-content');
94889 var mapDimensions = utilGetDimensions(content, true); // shrink photo viewer if it is too big
94890 // (-90 preserves space at top and bottom of map used by menus)
94892 var photoDimensions = utilGetDimensions(photoviewer, true);
94894 if (photoDimensions[0] > mapDimensions[0] || photoDimensions[1] > mapDimensions[1] - 90) {
94895 var setPhotoDimensions = [Math.min(photoDimensions[0], mapDimensions[0]), Math.min(photoDimensions[1], mapDimensions[1] - 90)];
94896 photoviewer.style('width', setPhotoDimensions[0] + 'px').style('height', setPhotoDimensions[1] + 'px');
94897 dispatch.call('resize', photoviewer, setPhotoDimensions);
94901 return utilRebind(photoviewer, dispatch, 'on');
94904 function uiRestore(context) {
94905 return function (selection) {
94906 if (!context.history().hasRestorableChanges()) return;
94907 var modalSelection = uiModal(selection, true);
94908 modalSelection.select('.modal').attr('class', 'modal fillL');
94909 var introModal = modalSelection.select('.content');
94910 introModal.append('div').attr('class', 'modal-section').append('h3').call(_t.append('restore.heading'));
94911 introModal.append('div').attr('class', 'modal-section').append('p').call(_t.append('restore.description'));
94912 var buttonWrap = introModal.append('div').attr('class', 'modal-actions');
94913 var restore = buttonWrap.append('button').attr('class', 'restore').on('click', function () {
94914 context.history().restore();
94915 modalSelection.remove();
94917 restore.append('svg').attr('class', 'logo logo-restore').append('use').attr('xlink:href', '#iD-logo-restore');
94918 restore.append('div').call(_t.append('restore.restore'));
94919 var reset = buttonWrap.append('button').attr('class', 'reset').on('click', function () {
94920 context.history().clearSaved();
94921 modalSelection.remove();
94923 reset.append('svg').attr('class', 'logo logo-reset').append('use').attr('xlink:href', '#iD-logo-reset');
94924 reset.append('div').call(_t.append('restore.reset'));
94925 restore.node().focus();
94929 function uiScale(context) {
94930 var projection = context.projection,
94931 isImperial = !_mainLocalizer.usesMetric(),
94935 function scaleDefs(loc1, loc2) {
94936 var lat = (loc2[1] + loc1[1]) / 2,
94937 conversion = isImperial ? 3.28084 : 1,
94938 dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion,
94950 buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
94952 buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
94953 } // determine a user-friendly endpoint for the scale
94956 for (i = 0; i < buckets.length; i++) {
94960 scale.dist = Math.floor(dist / val) * val;
94963 scale.dist = +dist.toFixed(2);
94967 dLon = geoMetersToLon(scale.dist / conversion, lat);
94968 scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
94969 scale.text = displayLength(scale.dist / conversion, isImperial);
94973 function update(selection) {
94974 // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
94975 var dims = context.map().dimensions(),
94976 loc1 = projection.invert([0, dims[1]]),
94977 loc2 = projection.invert([maxLength, dims[1]]),
94978 scale = scaleDefs(loc1, loc2);
94979 selection.select('.scale-path').attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
94980 selection.select('.scale-text').style(_mainLocalizer.textDirection() === 'ltr' ? 'left' : 'right', scale.px + 16 + 'px').text(scale.text);
94983 return function (selection) {
94984 function switchUnits() {
94985 isImperial = !isImperial;
94986 selection.call(update);
94989 var scalegroup = selection.append('svg').attr('class', 'scale').on('click', switchUnits).append('g').attr('transform', 'translate(10,11)');
94990 scalegroup.append('path').attr('class', 'scale-path');
94991 selection.append('div').attr('class', 'scale-text');
94992 selection.call(update);
94993 context.map().on('move.scale', function () {
94999 function uiShortcuts(context) {
95000 var detected = utilDetect();
95001 var _activeTab = 0;
95003 var _modalSelection;
95005 var _selection = select(null);
95007 var _dataShortcuts;
95009 function shortcutsModal(_modalSelection) {
95010 _modalSelection.select('.modal').classed('modal-shortcuts', true);
95012 var content = _modalSelection.select('.content');
95014 content.append('div').attr('class', 'modal-section header').append('h2').call(_t.append('shortcuts.title'));
95015 _mainFileFetcher.get('shortcuts').then(function (data) {
95016 _dataShortcuts = data;
95017 content.call(render);
95018 })["catch"](function () {
95023 function render(selection) {
95024 if (!_dataShortcuts) return;
95025 var wrapper = selection.selectAll('.wrapper').data([0]);
95026 var wrapperEnter = wrapper.enter().append('div').attr('class', 'wrapper modal-section');
95027 var tabsBar = wrapperEnter.append('div').attr('class', 'tabs-bar');
95028 var shortcutsList = wrapperEnter.append('div').attr('class', 'shortcuts-list');
95029 wrapper = wrapper.merge(wrapperEnter);
95030 var tabs = tabsBar.selectAll('.tab').data(_dataShortcuts);
95031 var tabsEnter = tabs.enter().append('a').attr('class', 'tab').attr('href', '#').on('click', function (d3_event, d) {
95032 d3_event.preventDefault();
95034 var i = _dataShortcuts.indexOf(d);
95039 tabsEnter.append('span').html(function (d) {
95040 return _t.html(d.text);
95043 wrapper.selectAll('.tab').classed('active', function (d, i) {
95044 return i === _activeTab;
95046 var shortcuts = shortcutsList.selectAll('.shortcut-tab').data(_dataShortcuts);
95047 var shortcutsEnter = shortcuts.enter().append('div').attr('class', function (d) {
95048 return 'shortcut-tab shortcut-tab-' + d.tab;
95050 var columnsEnter = shortcutsEnter.selectAll('.shortcut-column').data(function (d) {
95052 }).enter().append('table').attr('class', 'shortcut-column');
95053 var rowsEnter = columnsEnter.selectAll('.shortcut-row').data(function (d) {
95055 }).enter().append('tr').attr('class', 'shortcut-row');
95056 var sectionRows = rowsEnter.filter(function (d) {
95057 return !d.shortcuts;
95059 sectionRows.append('td');
95060 sectionRows.append('td').attr('class', 'shortcut-section').append('h3').html(function (d) {
95061 return _t.html(d.text);
95063 var shortcutRows = rowsEnter.filter(function (d) {
95064 return d.shortcuts;
95066 var shortcutKeys = shortcutRows.append('td').attr('class', 'shortcut-keys');
95067 var modifierKeys = shortcutKeys.filter(function (d) {
95068 return d.modifiers;
95070 modifierKeys.selectAll('kbd.modifier').data(function (d) {
95071 if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') {
95073 } else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') {
95076 return d.modifiers;
95078 }).enter().each(function () {
95079 var selection = select(this);
95080 selection.append('kbd').attr('class', 'modifier').text(function (d) {
95081 return uiCmd.display(d);
95083 selection.append('span').text('+');
95085 shortcutKeys.selectAll('kbd.shortcut').data(function (d) {
95086 var arr = d.shortcuts;
95088 if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') {
95090 } else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') {
95092 } // replace translations
95095 arr = arr.map(function (s) {
95096 return uiCmd.display(s.indexOf('.') !== -1 ? _t(s) : s);
95098 return utilArrayUniq(arr).map(function (s) {
95101 separator: d.separator,
95105 }).enter().each(function (d, i, nodes) {
95106 var selection = select(this);
95107 var click = d.shortcut.toLowerCase().match(/(.*).click/);
95109 if (click && click[1]) {
95110 // replace "left_click", "right_click" with mouse icon
95111 selection.call(svgIcon('#iD-walkthrough-mouse-' + click[1], 'operation'));
95112 } else if (d.shortcut.toLowerCase() === 'long-press') {
95113 selection.call(svgIcon('#iD-walkthrough-longpress', 'longpress operation'));
95114 } else if (d.shortcut.toLowerCase() === 'tap') {
95115 selection.call(svgIcon('#iD-walkthrough-tap', 'tap operation'));
95117 selection.append('kbd').attr('class', 'shortcut').text(function (d) {
95122 if (i < nodes.length - 1) {
95123 selection.append('span').html(d.separator || "\xA0" + _t.html('shortcuts.or') + "\xA0");
95124 } else if (i === nodes.length - 1 && d.suffix) {
95125 selection.append('span').text(d.suffix);
95128 shortcutKeys.filter(function (d) {
95130 }).each(function () {
95131 var selection = select(this);
95132 selection.append('span').text('+');
95133 selection.append('span').attr('class', 'gesture').html(function (d) {
95134 return _t.html(d.gesture);
95137 shortcutRows.append('td').attr('class', 'shortcut-desc').html(function (d) {
95138 return d.text ? _t.html(d.text) : "\xA0";
95141 wrapper.selectAll('.shortcut-tab').style('display', function (d, i) {
95142 return i === _activeTab ? 'flex' : 'none';
95146 return function (selection, show) {
95147 _selection = selection;
95150 _modalSelection = uiModal(selection);
95152 _modalSelection.call(shortcutsModal);
95154 context.keybinding().on([_t('shortcuts.toggle.key'), '?'], function () {
95155 if (context.container().selectAll('.modal-shortcuts').size()) {
95157 if (_modalSelection) {
95158 _modalSelection.close();
95160 _modalSelection = null;
95163 _modalSelection = uiModal(_selection);
95165 _modalSelection.call(shortcutsModal);
95172 function uiDataHeader() {
95175 function dataHeader(selection) {
95176 var header = selection.selectAll('.data-header').data(_datum ? [_datum] : [], function (d) {
95177 return d.__featurehash__;
95179 header.exit().remove();
95180 var headerEnter = header.enter().append('div').attr('class', 'data-header');
95181 var iconEnter = headerEnter.append('div').attr('class', 'data-header-icon');
95182 iconEnter.append('div').attr('class', 'preset-icon-28').call(svgIcon('#iD-icon-data', 'note-fill'));
95183 headerEnter.append('div').attr('class', 'data-header-label').call(_t.append('map_data.layers.custom.title'));
95186 dataHeader.datum = function (val) {
95187 if (!arguments.length) return _datum;
95195 // It is keyed on the `value` of the entry. Data should be an array of objects like:
95197 // value: 'string value', // required
95198 // display: 'label html' // optional
95199 // title: 'hover text' // optional
95200 // terms: ['search terms'] // optional
95203 var _comboHideTimerID;
95205 function uiCombobox(context, klass) {
95206 var dispatch = dispatch$8('accept', 'cancel');
95207 var container = context.container();
95208 var _suggestions = [];
95211 var _selected = null;
95212 var _canAutocomplete = true;
95213 var _caseSensitive = false;
95214 var _cancelFetch = false;
95218 var _mouseEnterHandler, _mouseLeaveHandler;
95220 var _fetcher = function _fetcher(val, cb) {
95221 cb(_data.filter(function (d) {
95222 var terms = d.terms || [];
95223 terms.push(d.value);
95224 return terms.some(function (term) {
95225 return term.toString().toLowerCase().indexOf(val.toLowerCase()) !== -1;
95230 var combobox = function combobox(input, attachTo) {
95231 if (!input || input.empty()) return;
95232 input.classed('combobox-input', true).on('focus.combo-input', focus).on('blur.combo-input', blur).on('keydown.combo-input', keydown).on('keyup.combo-input', keyup).on('input.combo-input', change).on('mousedown.combo-input', mousedown).each(function () {
95233 var parent = this.parentNode;
95234 var sibling = this.nextSibling;
95235 select(parent).selectAll('.combobox-caret').filter(function (d) {
95236 return d === input.node();
95237 }).data([input.node()]).enter().insert('div', function () {
95239 }).attr('class', 'combobox-caret').on('mousedown.combo-caret', function (d3_event) {
95240 d3_event.preventDefault(); // don't steal focus from input
95242 input.node().focus(); // focus the input as if it was clicked
95244 mousedown(d3_event);
95245 }).on('mouseup.combo-caret', function (d3_event) {
95246 d3_event.preventDefault(); // don't steal focus from input
95252 function mousedown(d3_event) {
95253 if (d3_event.button !== 0) return; // left click only
95255 if (input.classed('disabled')) return;
95256 _tDown = +new Date(); // clear selection
95258 var start = input.property('selectionStart');
95259 var end = input.property('selectionEnd');
95261 if (start !== end) {
95262 var val = utilGetSetValue(input);
95263 input.node().setSelectionRange(val.length, val.length);
95267 input.on('mouseup.combo-input', mouseup);
95270 function mouseup(d3_event) {
95271 input.on('mouseup.combo-input', null);
95272 if (d3_event.button !== 0) return; // left click only
95274 if (input.classed('disabled')) return;
95275 if (input.node() !== document.activeElement) return; // exit if this input is not focused
95277 var start = input.property('selectionStart');
95278 var end = input.property('selectionEnd');
95279 if (start !== end) return; // exit if user is selecting
95280 // not showing or showing for a different field - try to show it.
95282 var combo = container.selectAll('.combobox');
95284 if (combo.empty() || combo.datum() !== input.node()) {
95285 var tOrig = _tDown;
95286 window.setTimeout(function () {
95287 if (tOrig !== _tDown) return; // exit if user double clicked
95289 fetchComboData('', function () {
95300 fetchComboData(''); // prefetch values (may warm taginfo cache)
95304 _comboHideTimerID = window.setTimeout(hide, 75);
95308 hide(); // remove any existing
95310 container.insert('div', ':first-child').datum(input.node()).attr('class', 'combobox' + (klass ? ' combobox-' + klass : '')).style('position', 'absolute').style('display', 'block').style('left', '0px').on('mousedown.combo-container', function (d3_event) {
95311 // prevent moving focus out of the input field
95312 d3_event.preventDefault();
95314 container.on('scroll.combo-scroll', render, true);
95318 if (_comboHideTimerID) {
95319 window.clearTimeout(_comboHideTimerID);
95320 _comboHideTimerID = undefined;
95323 container.selectAll('.combobox').remove();
95324 container.on('scroll.combo-scroll', null);
95327 function keydown(d3_event) {
95328 var shown = !container.selectAll('.combobox').empty();
95329 var tagName = input.node() ? input.node().tagName.toLowerCase() : '';
95331 switch (d3_event.keyCode) {
95332 case 8: // ⌫ Backspace
95336 d3_event.stopPropagation();
95339 input.on('input.combo-input', function () {
95340 var start = input.property('selectionStart');
95341 input.node().setSelectionRange(start, start);
95342 input.on('input.combo-input', change);
95353 d3_event.preventDefault();
95354 d3_event.stopPropagation();
95359 if (tagName === 'textarea' && !shown) return;
95360 d3_event.preventDefault();
95362 if (tagName === 'input' && !shown) {
95371 if (tagName === 'textarea' && !shown) return;
95372 d3_event.preventDefault();
95374 if (tagName === 'input' && !shown) {
95383 function keyup(d3_event) {
95384 switch (d3_event.keyCode) {
95395 } // Called whenever the input value is changed (e.g. on typing)
95398 function change() {
95399 fetchComboData(value(), function () {
95401 var val = input.property('value');
95403 if (_suggestions.length) {
95404 if (input.property('selectionEnd') === val.length) {
95405 _selected = tryAutocomplete();
95414 var combo = container.selectAll('.combobox');
95416 if (combo.empty()) {
95425 } // Called when the user presses up/down arrows to navigate the list
95428 function nav(dir) {
95429 if (_suggestions.length) {
95430 // try to determine previously selected index..
95433 for (var i = 0; i < _suggestions.length; i++) {
95434 if (_selected && _suggestions[i].value === _selected) {
95438 } // pick new _selected
95441 index = Math.max(Math.min(index + dir, _suggestions.length - 1), 0);
95442 _selected = _suggestions[index].value;
95443 input.property('value', _selected);
95450 function ensureVisible() {
95451 var combo = container.selectAll('.combobox');
95452 if (combo.empty()) return;
95453 var containerRect = container.node().getBoundingClientRect();
95454 var comboRect = combo.node().getBoundingClientRect();
95456 if (comboRect.bottom > containerRect.bottom) {
95457 var node = attachTo ? attachTo.node() : input.node();
95458 node.scrollIntoView({
95459 behavior: 'instant',
95463 } // https://stackoverflow.com/questions/11039885/scrollintoview-causing-the-whole-page-to-move
95466 var selected = combo.selectAll('.combobox-option.selected').node();
95469 selected.scrollIntoView({
95470 behavior: 'smooth',
95477 var value = input.property('value');
95478 var start = input.property('selectionStart');
95479 var end = input.property('selectionEnd');
95481 if (start && end) {
95482 value = value.substring(0, start);
95488 function fetchComboData(v, cb) {
95489 _cancelFetch = false;
95491 _fetcher.call(input, v, function (results) {
95492 // already chose a value, don't overwrite or autocomplete it
95493 if (_cancelFetch) return;
95494 _suggestions = results;
95495 results.forEach(function (d) {
95496 _fetched[d.value] = d;
95505 function tryAutocomplete() {
95506 if (!_canAutocomplete) return;
95507 var val = _caseSensitive ? value() : value().toLowerCase();
95508 if (!val) return; // Don't autocomplete if user is typing a number - #4935
95510 if (!isNaN(parseFloat(val)) && isFinite(val)) return;
95511 var bestIndex = -1;
95513 for (var i = 0; i < _suggestions.length; i++) {
95514 var suggestion = _suggestions[i].value;
95515 var compare = _caseSensitive ? suggestion : suggestion.toLowerCase(); // if search string matches suggestion exactly, pick it..
95517 if (compare === val) {
95519 break; // otherwise lock in the first result that starts with the search string..
95520 } else if (bestIndex === -1 && compare.indexOf(val) === 0) {
95525 if (bestIndex !== -1) {
95526 var bestVal = _suggestions[bestIndex].value;
95527 input.property('value', bestVal);
95528 input.node().setSelectionRange(val.length, bestVal.length);
95533 function render() {
95534 if (_suggestions.length < _minItems || document.activeElement !== input.node()) {
95539 var shown = !container.selectAll('.combobox').empty();
95540 if (!shown) return;
95541 var combo = container.selectAll('.combobox');
95542 var options = combo.selectAll('.combobox-option').data(_suggestions, function (d) {
95545 options.exit().remove(); // enter/update
95547 options.enter().append('a').attr('class', function (d) {
95548 return 'combobox-option ' + (d.klass || '');
95549 }).attr('title', function (d) {
95551 }).html(function (d) {
95552 return d.display || d.value;
95553 }).on('mouseenter', _mouseEnterHandler).on('mouseleave', _mouseLeaveHandler).merge(options).classed('selected', function (d) {
95554 return d.value === _selected;
95555 }).on('click.combo-option', accept).order();
95556 var node = attachTo ? attachTo.node() : input.node();
95557 var containerRect = container.node().getBoundingClientRect();
95558 var rect = node.getBoundingClientRect();
95559 combo.style('left', rect.left + 5 - containerRect.left + 'px').style('width', rect.width - 10 + 'px').style('top', rect.height + rect.top - containerRect.top + 'px');
95560 } // Dispatches an 'accept' event
95561 // Then hides the combobox.
95564 function accept(d3_event, d) {
95565 _cancelFetch = true;
95566 var thiz = input.node();
95569 // user clicked on a suggestion
95570 utilGetSetValue(input, d.value); // replace field contents
95572 utilTriggerEvent(input, 'change');
95573 } // clear (and keep) selection
95576 var val = utilGetSetValue(input);
95577 thiz.setSelectionRange(val.length, val.length);
95579 dispatch.call('accept', thiz, d, val);
95581 } // Dispatches an 'cancel' event
95582 // Then hides the combobox.
95585 function cancel() {
95586 _cancelFetch = true;
95587 var thiz = input.node(); // clear (and remove) selection, and replace field contents
95589 var val = utilGetSetValue(input);
95590 var start = input.property('selectionStart');
95591 var end = input.property('selectionEnd');
95592 val = val.slice(0, start) + val.slice(end);
95593 utilGetSetValue(input, val);
95594 thiz.setSelectionRange(val.length, val.length);
95595 dispatch.call('cancel', thiz);
95600 combobox.canAutocomplete = function (val) {
95601 if (!arguments.length) return _canAutocomplete;
95602 _canAutocomplete = val;
95606 combobox.caseSensitive = function (val) {
95607 if (!arguments.length) return _caseSensitive;
95608 _caseSensitive = val;
95612 combobox.data = function (val) {
95613 if (!arguments.length) return _data;
95618 combobox.fetcher = function (val) {
95619 if (!arguments.length) return _fetcher;
95624 combobox.minItems = function (val) {
95625 if (!arguments.length) return _minItems;
95630 combobox.itemsMouseEnter = function (val) {
95631 if (!arguments.length) return _mouseEnterHandler;
95632 _mouseEnterHandler = val;
95636 combobox.itemsMouseLeave = function (val) {
95637 if (!arguments.length) return _mouseLeaveHandler;
95638 _mouseLeaveHandler = val;
95642 return utilRebind(combobox, dispatch, 'on');
95645 uiCombobox.off = function (input, context) {
95646 input.on('focus.combo-input', null).on('blur.combo-input', null).on('keydown.combo-input', null).on('keyup.combo-input', null).on('input.combo-input', null).on('mousedown.combo-input', null).on('mouseup.combo-input', null);
95647 context.container().on('scroll.combo-scroll', null);
95650 function uiDisclosure(context, key, expandedDefault) {
95651 var dispatch = dispatch$8('toggled');
95655 var _label = utilFunctor('');
95657 var _updatePreference = true;
95659 var _content = function _content() {};
95661 var disclosure = function disclosure(selection) {
95662 if (_expanded === undefined || _expanded === null) {
95663 // loading _expanded here allows it to be reset by calling `disclosure.expanded(null)`
95664 var preference = corePreferences('disclosure.' + key + '.expanded');
95665 _expanded = preference === null ? !!expandedDefault : preference === 'true';
95668 var hideToggle = selection.selectAll('.hide-toggle-' + key).data([0]); // enter
95670 var hideToggleEnter = hideToggle.enter().append('h3').append('a').attr('role', 'button').attr('href', '#').attr('class', 'hide-toggle hide-toggle-' + key).call(svgIcon('', 'pre-text', 'hide-toggle-icon'));
95671 hideToggleEnter.append('span').attr('class', 'hide-toggle-text'); // update
95673 hideToggle = hideToggleEnter.merge(hideToggle);
95674 hideToggle.on('click', toggle).attr('title', _t("icons.".concat(_expanded ? 'collapse' : 'expand'))).attr('aria-expanded', _expanded).classed('expanded', _expanded);
95675 hideToggle.selectAll('.hide-toggle-text').html(_label());
95676 hideToggle.selectAll('.hide-toggle-icon').attr('xlink:href', _expanded ? '#iD-icon-down' : _mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward');
95677 var wrap = selection.selectAll('.disclosure-wrap').data([0]); // enter/update
95679 wrap = wrap.enter().append('div').attr('class', 'disclosure-wrap disclosure-wrap-' + key).merge(wrap).classed('hide', !_expanded);
95682 wrap.call(_content);
95685 function toggle(d3_event) {
95686 d3_event.preventDefault();
95687 _expanded = !_expanded;
95689 if (_updatePreference) {
95690 corePreferences('disclosure.' + key + '.expanded', _expanded);
95693 hideToggle.classed('expanded', _expanded).attr('aria-expanded', _expanded).attr('title', _t("icons.".concat(_expanded ? 'collapse' : 'expand')));
95694 hideToggle.selectAll('.hide-toggle-icon').attr('xlink:href', _expanded ? '#iD-icon-down' : _mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward');
95695 wrap.call(uiToggle(_expanded));
95698 wrap.call(_content);
95701 dispatch.call('toggled', this, _expanded);
95705 disclosure.label = function (val) {
95706 if (!arguments.length) return _label;
95707 _label = utilFunctor(val);
95711 disclosure.expanded = function (val) {
95712 if (!arguments.length) return _expanded;
95717 disclosure.updatePreference = function (val) {
95718 if (!arguments.length) return _updatePreference;
95719 _updatePreference = val;
95723 disclosure.content = function (val) {
95724 if (!arguments.length) return _content;
95729 return utilRebind(disclosure, dispatch, 'on');
95732 // Can be labeled and collapsible.
95734 function uiSection(id, context) {
95735 var _classes = utilFunctor('');
95737 var _shouldDisplay;
95745 var _expandedByDefault = utilFunctor(true);
95747 var _disclosureContent;
95749 var _disclosureExpanded;
95751 var _containerSelection = select(null);
95757 section.classes = function (val) {
95758 if (!arguments.length) return _classes;
95759 _classes = utilFunctor(val);
95763 section.label = function (val) {
95764 if (!arguments.length) return _label;
95765 _label = utilFunctor(val);
95769 section.expandedByDefault = function (val) {
95770 if (!arguments.length) return _expandedByDefault;
95771 _expandedByDefault = utilFunctor(val);
95775 section.shouldDisplay = function (val) {
95776 if (!arguments.length) return _shouldDisplay;
95777 _shouldDisplay = utilFunctor(val);
95781 section.content = function (val) {
95782 if (!arguments.length) return _content;
95787 section.disclosureContent = function (val) {
95788 if (!arguments.length) return _disclosureContent;
95789 _disclosureContent = val;
95793 section.disclosureExpanded = function (val) {
95794 if (!arguments.length) return _disclosureExpanded;
95795 _disclosureExpanded = val;
95797 }; // may be called multiple times
95800 section.render = function (selection) {
95801 _containerSelection = selection.selectAll('.section-' + id).data([0]);
95803 var sectionEnter = _containerSelection.enter().append('div').attr('class', 'section section-' + id + ' ' + (_classes && _classes() || ''));
95805 _containerSelection = sectionEnter.merge(_containerSelection);
95807 _containerSelection.call(renderContent);
95810 section.reRender = function () {
95811 _containerSelection.call(renderContent);
95814 section.selection = function () {
95815 return _containerSelection;
95818 section.disclosure = function () {
95819 return _disclosure;
95820 }; // may be called multiple times
95823 function renderContent(selection) {
95824 if (_shouldDisplay) {
95825 var shouldDisplay = _shouldDisplay();
95827 selection.classed('hide', !shouldDisplay);
95829 if (!shouldDisplay) {
95830 selection.html('');
95835 if (_disclosureContent) {
95836 if (!_disclosure) {
95837 _disclosure = uiDisclosure(context, id.replace(/-/g, '_'), _expandedByDefault()).label(_label || '')
95838 /*.on('toggled', function(expanded) {
95839 if (expanded) { selection.node().parentNode.scrollTop += 200; }
95841 .content(_disclosureContent);
95844 if (_disclosureExpanded !== undefined) {
95845 _disclosure.expanded(_disclosureExpanded);
95847 _disclosureExpanded = undefined;
95850 selection.call(_disclosure);
95855 selection.call(_content);
95863 // key: 'string', // required
95864 // value: 'string' // optional
95868 // qid: 'string' // brand wikidata (e.g. 'Q37158')
95872 function uiTagReference(what) {
95873 var wikibase = what.qid ? services.wikidata : services.osmWikibase;
95874 var tagReference = {};
95876 var _button = select(null);
95878 var _body = select(null);
95885 if (!wikibase) return;
95887 _button.classed('tag-reference-loading', true);
95889 wikibase.getDocs(what, gotDocs);
95892 function gotDocs(err, docs) {
95895 if (!docs || !docs.title) {
95896 _body.append('p').attr('class', 'tag-reference-description').call(_t.append('inspector.no_documentation_key'));
95902 if (docs.imageURL) {
95903 _body.append('img').attr('class', 'tag-reference-wiki-image').attr('alt', docs.description).attr('src', docs.imageURL).on('load', function () {
95905 }).on('error', function () {
95906 select(this).remove();
95913 var tagReferenceDescription = _body.append('p').attr('class', 'tag-reference-description').append('span');
95915 if (docs.description) {
95916 tagReferenceDescription = tagReferenceDescription.attr('class', 'localized-text').attr('lang', docs.descriptionLocaleCode || 'und').text(docs.description);
95918 tagReferenceDescription = tagReferenceDescription.call(_t.append('inspector.no_documentation_key'));
95921 tagReferenceDescription.append('a').attr('class', 'tag-reference-edit').attr('target', '_blank').attr('title', _t('inspector.edit_reference')).attr('href', docs.editURL).call(svgIcon('#iD-icon-edit', 'inline'));
95924 _body.append('a').attr('class', 'tag-reference-link').attr('target', '_blank').attr('href', docs.wiki.url).call(svgIcon('#iD-icon-out-link', 'inline')).append('span').call(_t.append(docs.wiki.text));
95925 } // Add link to info about "good changeset comments" - #2923
95928 if (what.key === 'comment') {
95929 _body.append('a').attr('class', 'tag-reference-comment-link').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).attr('href', _t('commit.about_changeset_comments_link')).append('span').call(_t.append('commit.about_changeset_comments'));
95936 _button.classed('tag-reference-loading', false);
95938 _body.classed('expanded', true).transition().duration(200).style('max-height', '200px').style('opacity', '1');
95942 _button.selectAll('svg.icon use').each(function () {
95943 var iconUse = select(this);
95945 if (iconUse.attr('href') === '#iD-icon-info') {
95946 iconUse.attr('href', '#iD-icon-info-filled');
95952 _body.transition().duration(200).style('max-height', '0px').style('opacity', '0').on('end', function () {
95953 _body.classed('expanded', false);
95958 _button.selectAll('svg.icon use').each(function () {
95959 var iconUse = select(this);
95961 if (iconUse.attr('href') === '#iD-icon-info-filled') {
95962 iconUse.attr('href', '#iD-icon-info');
95967 tagReference.button = function (selection, klass, iconName) {
95968 _button = selection.selectAll('.tag-reference-button').data([0]);
95969 _button = _button.enter().append('button').attr('class', 'tag-reference-button ' + (klass || '')).attr('title', _t('icons.information')).call(svgIcon('#iD-icon-' + (iconName || 'inspect'))).merge(_button);
95971 _button.on('click', function (d3_event) {
95972 d3_event.stopPropagation();
95973 d3_event.preventDefault();
95974 this.blur(); // avoid keeping focus on the button - #4641
95978 } else if (_loaded) {
95986 tagReference.body = function (selection) {
95987 var itemID = what.qid || what.key + '-' + (what.value || '');
95988 _body = selection.selectAll('.tag-reference-body').data([itemID], function (d) {
95992 _body.exit().remove();
95994 _body = _body.enter().append('div').attr('class', 'tag-reference-body').style('max-height', '0').style('opacity', '0').merge(_body);
95996 if (_showing === false) {
96001 tagReference.showing = function (val) {
96002 if (!arguments.length) return _showing;
96004 return tagReference;
96007 return tagReference;
96010 // It borrows some code from uiHelp
96012 function uiFieldHelp(context, fieldName) {
96013 var fieldHelp = {};
96015 var _inspector = select(null);
96017 var _wrap = select(null);
96019 var _body = select(null);
96021 var fieldHelpKeys = {
96022 restrictions: [['about', ['about', 'from_via_to', 'maxdist', 'maxvia']], ['inspecting', ['about', 'from_shadow', 'allow_shadow', 'restrict_shadow', 'only_shadow', 'restricted', 'only']], ['modifying', ['about', 'indicators', 'allow_turn', 'restrict_turn', 'only_turn']], ['tips', ['simple', 'simple_example', 'indirect', 'indirect_example', 'indirect_noedit']]]
96024 var fieldHelpHeadings = {};
96025 var replacements = {
96027 html: _t.html('restriction.controls.distance')
96030 html: _t.html('restriction.controls.via')
96033 html: icon('#iD-turn-shadow', 'inline shadow from')
96036 html: icon('#iD-turn-shadow', 'inline shadow allow')
96039 html: icon('#iD-turn-shadow', 'inline shadow restrict')
96042 html: icon('#iD-turn-shadow', 'inline shadow only')
96045 html: icon('#iD-turn-yes', 'inline turn')
96048 html: icon('#iD-turn-no', 'inline turn')
96051 html: icon('#iD-turn-only', 'inline turn')
96053 }; // For each section, squash all the texts into a single markdown document
96055 var docs = fieldHelpKeys[fieldName].map(function (key) {
96056 var helpkey = 'help.field.' + fieldName + '.' + key[0];
96057 var text = key[1].reduce(function (all, part) {
96058 var subkey = helpkey + '.' + part;
96059 var depth = fieldHelpHeadings[subkey]; // is this subkey a heading?
96061 var hhh = depth ? Array(depth + 1).join('#') + ' ' : ''; // if so, prepend with some ##'s
96063 return all + hhh + _t.html(subkey, replacements) + '\n\n';
96067 title: _t.html(helpkey + '.title'),
96068 html: marked_1(text.trim())
96075 _body.classed('hide', false).style('opacity', '0').transition().duration(200).style('opacity', '1');
96079 _body.classed('hide', true).transition().duration(200).style('opacity', '0').on('end', function () {
96080 _body.classed('hide', true);
96084 function clickHelp(index) {
96085 var d = docs[index];
96086 var tkeys = fieldHelpKeys[fieldName][index][1];
96088 _body.selectAll('.field-help-nav-item').classed('active', function (d, i) {
96089 return i === index;
96092 var content = _body.selectAll('.field-help-content').html(d.html); // class the paragraphs so we can find and style them
96095 content.selectAll('p').attr('class', function (d, i) {
96097 }); // insert special content for certain help sections
96099 if (d.key === 'help.field.restrictions.inspecting') {
96100 content.insert('img', 'p.from_shadow').attr('class', 'field-help-image cf').attr('src', context.imagePath('tr_inspect.gif'));
96101 } else if (d.key === 'help.field.restrictions.modifying') {
96102 content.insert('img', 'p.allow_turn').attr('class', 'field-help-image cf').attr('src', context.imagePath('tr_modify.gif'));
96106 fieldHelp.button = function (selection) {
96107 if (_body.empty()) return;
96108 var button = selection.selectAll('.field-help-button').data([0]); // enter/update
96110 button.enter().append('button').attr('class', 'field-help-button').call(svgIcon('#iD-icon-help')).merge(button).on('click', function (d3_event) {
96111 d3_event.stopPropagation();
96112 d3_event.preventDefault();
96114 if (_body.classed('hide')) {
96122 function updatePosition() {
96123 var wrap = _wrap.node();
96125 var inspector = _inspector.node();
96127 var wRect = wrap.getBoundingClientRect();
96128 var iRect = inspector.getBoundingClientRect();
96130 _body.style('top', wRect.top + inspector.scrollTop - iRect.top + 'px');
96133 fieldHelp.body = function (selection) {
96134 // This control expects the field to have a form-field-input-wrap div
96135 _wrap = selection.selectAll('.form-field-input-wrap');
96136 if (_wrap.empty()) return; // absolute position relative to the inspector, so it "floats" above the fields
96138 _inspector = context.container().select('.sidebar .entity-editor-pane .inspector-body');
96139 if (_inspector.empty()) return;
96140 _body = _inspector.selectAll('.field-help-body').data([0]);
96142 var enter = _body.enter().append('div').attr('class', 'field-help-body hide'); // initially hidden
96145 var titleEnter = enter.append('div').attr('class', 'field-help-title cf');
96146 titleEnter.append('h2').attr('class', _mainLocalizer.textDirection() === 'rtl' ? 'fr' : 'fl').call(_t.append('help.field.' + fieldName + '.title'));
96147 titleEnter.append('button').attr('class', 'fr close').attr('title', _t('icons.close')).on('click', function (d3_event) {
96148 d3_event.stopPropagation();
96149 d3_event.preventDefault();
96151 }).call(svgIcon('#iD-icon-close'));
96152 var navEnter = enter.append('div').attr('class', 'field-help-nav cf');
96153 var titles = docs.map(function (d) {
96156 navEnter.selectAll('.field-help-nav-item').data(titles).enter().append('div').attr('class', 'field-help-nav-item').html(function (d) {
96158 }).on('click', function (d3_event, d) {
96159 d3_event.stopPropagation();
96160 d3_event.preventDefault();
96161 clickHelp(titles.indexOf(d));
96163 enter.append('div').attr('class', 'field-help-content');
96164 _body = _body.merge(enter);
96171 function uiFieldCheck(field, context) {
96172 var dispatch = dispatch$8('change');
96173 var options = field.options;
96179 var input = select(null);
96180 var text = select(null);
96181 var label = select(null);
96182 var reverser = select(null);
96186 var _entityIDs = [];
96191 for (var i in options) {
96192 var v = options[i];
96193 values.push(v === 'undefined' ? undefined : v);
96194 texts.push(field.t.html('options.' + v, {
96199 values = [undefined, 'yes'];
96200 texts = [_t.html('inspector.unknown'), _t.html('inspector.check.yes')];
96202 if (field.type !== 'defaultCheck') {
96204 texts.push(_t.html('inspector.check.no'));
96206 } // Checks tags to see whether an undefined value is "Assumed to be Yes"
96209 function checkImpliedYes() {
96210 _impliedYes = field.id === 'oneway_yes'; // hack: pretend `oneway` field is a `oneway_yes` field
96211 // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
96213 if (field.id === 'oneway') {
96214 var entity = context.entity(_entityIDs[0]);
96216 for (var key in entity.tags) {
96217 if (key in osmOneWayTags && entity.tags[key] in osmOneWayTags[key]) {
96218 _impliedYes = true;
96219 texts[0] = _t.html('_tagging.presets.fields.oneway_yes.options.undefined');
96226 function reverserHidden() {
96227 if (!context.container().select('div.inspector-hover').empty()) return true;
96228 return !(_value === 'yes' || _impliedYes && !_value);
96231 function reverserSetText(selection) {
96232 var entity = _entityIDs.length && context.hasEntity(_entityIDs[0]);
96233 if (reverserHidden() || !entity) return selection;
96234 var first = entity.first();
96235 var last = entity.isClosed() ? entity.nodes[entity.nodes.length - 2] : entity.last();
96236 var pseudoDirection = first < last;
96237 var icon = pseudoDirection ? '#iD-icon-forward' : '#iD-icon-backward';
96238 selection.selectAll('.reverser-span').html('').call(_t.append('inspector.check.reverser')).call(svgIcon(icon, 'inline'));
96242 var check = function check(selection) {
96244 label = selection.selectAll('.form-field-input-wrap').data([0]);
96245 var enter = label.enter().append('label').attr('class', 'form-field-input-wrap form-field-input-check');
96246 enter.append('input').property('indeterminate', field.type !== 'defaultCheck').attr('type', 'checkbox').attr('id', field.domId);
96247 enter.append('span').html(texts[0]).attr('class', 'value');
96249 if (field.type === 'onewayCheck') {
96250 enter.append('button').attr('class', 'reverser' + (reverserHidden() ? ' hide' : '')).append('span').attr('class', 'reverser-span');
96253 label = label.merge(enter);
96254 input = label.selectAll('input');
96255 text = label.selectAll('span.value');
96256 input.on('click', function (d3_event) {
96257 d3_event.stopPropagation();
96260 if (Array.isArray(_tags[field.key])) {
96261 if (values.indexOf('yes') !== -1) {
96262 t[field.key] = 'yes';
96264 t[field.key] = values[0];
96267 t[field.key] = values[(values.indexOf(_value) + 1) % values.length];
96268 } // Don't cycle through `alternating` or `reversible` states - #4970
96269 // (They are supported as translated strings, but should not toggle with clicks)
96272 if (t[field.key] === 'reversible' || t[field.key] === 'alternating') {
96273 t[field.key] = values[0];
96276 dispatch.call('change', this, t);
96279 if (field.type === 'onewayCheck') {
96280 reverser = label.selectAll('.reverser');
96281 reverser.call(reverserSetText).on('click', function (d3_event) {
96282 d3_event.preventDefault();
96283 d3_event.stopPropagation();
96284 context.perform(function (graph) {
96285 for (var i in _entityIDs) {
96286 graph = actionReverse(_entityIDs[i])(graph);
96290 }, _t('operations.reverse.annotation.line', {
96292 })); // must manually revalidate since no 'change' event was called
96294 context.validator().validate();
96295 select(this).call(reverserSetText);
96300 check.entityIDs = function (val) {
96301 if (!arguments.length) return _entityIDs;
96306 check.tags = function (tags) {
96309 function isChecked(val) {
96310 return val !== 'no' && val !== '' && val !== undefined && val !== null;
96313 function textFor(val) {
96314 if (val === '') val = undefined;
96315 var index = values.indexOf(val);
96316 return index !== -1 ? texts[index] : '"' + val + '"';
96320 var isMixed = Array.isArray(tags[field.key]);
96321 _value = !isMixed && tags[field.key] && tags[field.key].toLowerCase();
96323 if (field.type === 'onewayCheck' && (_value === '1' || _value === '-1')) {
96327 input.property('indeterminate', isMixed || field.type !== 'defaultCheck' && !_value).property('checked', isChecked(_value));
96328 text.html(isMixed ? _t.html('inspector.multiple_values') : textFor(_value)).classed('mixed', isMixed);
96329 label.classed('set', !!_value);
96331 if (field.type === 'onewayCheck') {
96332 reverser.classed('hide', reverserHidden()).call(reverserSetText);
96336 check.focus = function () {
96337 input.node().focus();
96340 return utilRebind(check, dispatch, 'on');
96343 function uiFieldCombo(field, context) {
96344 var dispatch = dispatch$8('change');
96346 var _isMulti = field.type === 'multiCombo' || field.type === 'manyCombo';
96348 var _isNetwork = field.type === 'networkCombo';
96350 var _isSemi = field.type === 'semiCombo';
96352 var _optarray = field.options;
96354 var _showTagInfoSuggestions = field.type !== 'manyCombo' && field.autoSuggestions !== false;
96356 var _allowCustomValues = field.type !== 'manyCombo' && field.customValues !== false;
96358 var _snake_case = field.snake_case || field.snake_case === undefined;
96360 var _combobox = uiCombobox(context, 'combo-' + field.safeid).caseSensitive(field.caseSensitive).minItems(_isMulti || _isSemi ? 1 : 2);
96362 var _container = select(null);
96364 var _inputWrap = select(null);
96366 var _input = select(null);
96368 var _comboData = [];
96369 var _multiData = [];
96370 var _entityIDs = [];
96376 var _staticPlaceholder; // initialize deprecated tags array
96379 var _dataDeprecated = [];
96380 _mainFileFetcher.get('deprecated').then(function (d) {
96381 _dataDeprecated = d;
96382 })["catch"](function () {
96384 }); // ensure multiCombo field.key ends with a ':'
96386 if (_isMulti && field.key && /[^:]$/.test(field.key)) {
96390 function snake(s) {
96391 return s.replace(/\s+/g, '_').toLowerCase();
96394 function clean(s) {
96395 return s.split(';').map(function (s) {
96398 } // returns the tag value for a display value
96399 // (for multiCombo, dval should be the key suffix, not the entire key)
96402 function tagValue(dval) {
96403 dval = clean(dval || '');
96405 var found = _comboData.find(function (o) {
96406 return o.key && clean(o.value) === dval;
96409 if (found) return found.key;
96411 if (field.type === 'typeCombo' && !dval) {
96415 return (_snake_case ? snake(dval) : dval) || undefined;
96416 } // returns the display value for a tag value
96417 // (for multiCombo, tval should be the key suffix, not the entire key)
96420 function displayValue(tval) {
96423 if (field.hasTextForStringId('options.' + tval)) {
96424 return field.t('options.' + tval, {
96429 if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
96434 } // Compute the difference between arrays of objects by `value` property
96436 // objectDifference([{value:1}, {value:2}, {value:3}], [{value:2}])
96437 // > [{value:1}, {value:3}]
96441 function objectDifference(a, b) {
96442 return a.filter(function (d1) {
96443 return !b.some(function (d2) {
96444 return !d2.isMixed && d1.value === d2.value;
96449 function initCombo(selection, attachTo) {
96450 if (!_allowCustomValues) {
96451 selection.attr('readonly', 'readonly');
96454 if (_showTagInfoSuggestions && services.taginfo) {
96455 selection.call(_combobox.fetcher(setTaginfoValues), attachTo);
96456 setTaginfoValues('', setPlaceholder);
96458 selection.call(_combobox, attachTo);
96459 setStaticValues(setPlaceholder);
96463 function setStaticValues(callback) {
96464 if (!_optarray) return;
96465 _comboData = _optarray.map(function (v) {
96468 value: field.t('options.' + v, {
96472 display: field.t.html('options.' + v, {
96475 klass: field.hasTextForStringId('options.' + v) ? '' : 'raw-option'
96479 _combobox.data(objectDifference(_comboData, _multiData));
96481 if (callback) callback(_comboData);
96484 function setTaginfoValues(q, callback) {
96485 var fn = _isMulti ? 'multikeys' : 'values';
96486 var query = (_isMulti ? field.key : '') + q;
96487 var hasCountryPrefix = _isNetwork && _countryCode && _countryCode.indexOf(q.toLowerCase()) === 0;
96489 if (hasCountryPrefix) {
96490 query = _countryCode + ':';
96494 debounce: q !== '',
96499 if (_entityIDs.length) {
96500 params.geometry = context.graph().geometry(_entityIDs[0]);
96503 services.taginfo[fn](params, function (err, data) {
96505 data = data.filter(function (d) {
96506 if (field.type === 'typeCombo' && d.value === 'yes') {
96507 // don't show the fallback value
96509 } // don't show values with very low usage
96512 return !d.count || d.count > 10;
96514 var deprecatedValues = osmEntity.deprecatedTagValuesByKey(_dataDeprecated)[field.key];
96516 if (deprecatedValues) {
96517 // don't suggest deprecated tag values
96518 data = data.filter(function (d) {
96519 return deprecatedValues.indexOf(d.value) === -1;
96523 if (hasCountryPrefix) {
96524 data = data.filter(function (d) {
96525 return d.value.toLowerCase().indexOf(_countryCode + ':') === 0;
96527 } // hide the caret if there are no suggestions
96530 _container.classed('empty-combobox', data.length === 0);
96532 _comboData = data.map(function (d) {
96534 if (_isMulti) k = k.replace(field.key, '');
96535 var label = field.t('options.' + k, {
96541 display: field.t.html('options.' + k, {
96544 title: d.title || label,
96545 klass: field.hasTextForStringId('options.' + k) ? '' : 'raw-option'
96548 _comboData = objectDifference(_comboData, _multiData);
96549 if (callback) callback(_comboData);
96553 function setPlaceholder(values) {
96554 if (_isMulti || _isSemi) {
96555 _staticPlaceholder = field.placeholder() || _t('inspector.add');
96557 var vals = values.map(function (d) {
96559 }).filter(function (s) {
96560 return s.length < 20;
96562 var placeholders = vals.length > 1 ? vals : values.map(function (d) {
96565 _staticPlaceholder = field.placeholder() || placeholders.slice(0, 3).join(', ');
96568 if (!/(…|\.\.\.)$/.test(_staticPlaceholder)) {
96569 _staticPlaceholder += '…';
96574 if (!_isMulti && !_isSemi && _tags && Array.isArray(_tags[field.key])) {
96575 ph = _t('inspector.multiple_values');
96577 ph = _staticPlaceholder;
96580 _container.selectAll('input').attr('placeholder', ph);
96583 function change() {
96587 if (_isMulti || _isSemi) {
96588 val = tagValue(utilGetSetValue(_input).replace(/,/g, ';')) || '';
96590 _container.classed('active', false);
96592 utilGetSetValue(_input, '');
96593 var vals = val.split(';').filter(Boolean);
96594 if (!vals.length) return;
96597 utilArrayUniq(vals).forEach(function (v) {
96598 var key = (field.key || '') + v;
96601 // don't set a multicombo value to 'yes' if it already has a non-'no' value
96602 // e.g. `language:de=main`
96603 var old = _tags[key];
96604 if (typeof old === 'string' && old.toLowerCase() !== 'no') return;
96607 key = context.cleanTagKey(key);
96608 field.keys.push(key);
96611 } else if (_isSemi) {
96612 var arr = _multiData.map(function (d) {
96616 arr = arr.concat(vals);
96617 t[field.key] = context.cleanTagValue(utilArrayUniq(arr).filter(Boolean).join(';'));
96620 window.setTimeout(function () {
96621 _input.node().focus();
96624 var rawValue = utilGetSetValue(_input); // don't override multiple values with blank string
96626 if (!rawValue && Array.isArray(_tags[field.key])) return;
96627 val = context.cleanTagValue(tagValue(rawValue));
96628 t[field.key] = val || undefined;
96631 dispatch.call('change', this, t);
96634 function removeMultikey(d3_event, d) {
96635 d3_event.preventDefault();
96636 d3_event.stopPropagation();
96640 t[d.key] = undefined;
96641 } else if (_isSemi) {
96642 var arr = _multiData.map(function (md) {
96643 return md.key === d.key ? null : md.key;
96644 }).filter(Boolean);
96646 arr = utilArrayUniq(arr);
96647 t[field.key] = arr.length ? arr.join(';') : undefined;
96650 dispatch.call('change', this, t);
96653 function combo(selection) {
96654 _container = selection.selectAll('.form-field-input-wrap').data([0]);
96655 var type = _isMulti || _isSemi ? 'multicombo' : 'combo';
96656 _container = _container.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + type).merge(_container);
96658 if (_isMulti || _isSemi) {
96659 _container = _container.selectAll('.chiplist').data([0]);
96660 var listClass = 'chiplist'; // Use a separate line for each value in the Destinations and Via fields
96661 // to mimic highway exit signs
96663 if (field.key === 'destination' || field.key === 'via') {
96664 listClass += ' full-line-chips';
96667 _container = _container.enter().append('ul').attr('class', listClass).on('click', function () {
96668 window.setTimeout(function () {
96669 _input.node().focus();
96671 }).merge(_container);
96672 _inputWrap = _container.selectAll('.input-wrap').data([0]);
96673 _inputWrap = _inputWrap.enter().append('li').attr('class', 'input-wrap').merge(_inputWrap);
96674 _input = _inputWrap.selectAll('input').data([0]);
96676 _input = _container.selectAll('input').data([0]);
96679 _input = _input.enter().append('input').attr('type', 'text').attr('id', field.domId).call(utilNoAuto).call(initCombo, selection).merge(_input);
96682 var extent = combinedEntityExtent();
96683 var countryCode = extent && iso1A2Code(extent.center());
96684 _countryCode = countryCode && countryCode.toLowerCase();
96687 _input.on('change', change).on('blur', change);
96689 _input.on('keydown.field', function (d3_event) {
96690 switch (d3_event.keyCode) {
96693 _input.node().blur(); // blurring also enters the value
96696 d3_event.stopPropagation();
96701 if (_isMulti || _isSemi) {
96702 _combobox.on('accept', function () {
96703 _input.node().blur();
96705 _input.node().focus();
96708 _input.on('focus', function () {
96709 _container.classed('active', true);
96714 combo.tags = function (tags) {
96717 if (_isMulti || _isSemi) {
96722 // Build _multiData array containing keys already set..
96723 for (var k in tags) {
96724 if (field.key && k.indexOf(field.key) !== 0) continue;
96725 if (!field.key && field.keys.indexOf(k) === -1) continue;
96727 if (!v || typeof v === 'string' && v.toLowerCase() === 'no') continue;
96728 var suffix = field.key ? k.substr(field.key.length) : k;
96732 value: displayValue(suffix),
96733 isMixed: Array.isArray(v)
96738 // Set keys for form-field modified (needed for undo and reset buttons)..
96739 field.keys = _multiData.map(function (d) {
96741 }); // limit the input length so it fits after prepending the key prefix
96743 maxLength = context.maxCharsForTagKey() - utilUnicodeCharsCount(field.key);
96745 maxLength = context.maxCharsForTagKey();
96747 } else if (_isSemi) {
96748 var allValues = [];
96751 if (Array.isArray(tags[field.key])) {
96752 tags[field.key].forEach(function (tagVal) {
96753 var thisVals = utilArrayUniq((tagVal || '').split(';')).filter(Boolean);
96754 allValues = allValues.concat(thisVals);
96756 if (!commonValues) {
96757 commonValues = thisVals;
96759 commonValues = commonValues.filter(function (value) {
96760 return thisVals.includes(value);
96764 allValues = utilArrayUniq(allValues).filter(Boolean);
96766 allValues = utilArrayUniq((tags[field.key] || '').split(';')).filter(Boolean);
96767 commonValues = allValues;
96770 _multiData = allValues.map(function (v) {
96773 value: displayValue(v),
96774 isMixed: !commonValues.includes(v)
96777 var currLength = utilUnicodeCharsCount(commonValues.join(';')); // limit the input length to the remaining available characters
96779 maxLength = context.maxCharsForTagValue() - currLength;
96781 if (currLength > 0) {
96782 // account for the separator if a new value will be appended to existing
96785 } // a negative maxlength doesn't make sense
96788 maxLength = Math.max(0, maxLength);
96789 var allowDragAndDrop = _isSemi // only semiCombo values are ordered
96790 && !Array.isArray(tags[field.key]); // Exclude existing multikeys from combo options..
96792 var available = objectDifference(_comboData, _multiData);
96794 _combobox.data(available); // Hide 'Add' button if this field uses fixed set of
96795 // options and they're all currently used,
96796 // or if the field is already at its character limit
96799 var hideAdd = !_allowCustomValues && !available.length || maxLength <= 0;
96801 _container.selectAll('.chiplist .input-wrap').style('display', hideAdd ? 'none' : null); // Render chips
96804 var chips = _container.selectAll('.chip').data(_multiData);
96806 chips.exit().remove();
96807 var enter = chips.enter().insert('li', '.input-wrap').attr('class', 'chip');
96808 enter.append('span');
96810 chips = chips.merge(enter).order().classed('raw-value', function (d) {
96812 if (_isMulti) k = k.replace(field.key, '');
96813 return !field.hasTextForStringId('options.' + k);
96814 }).classed('draggable', allowDragAndDrop).classed('mixed', function (d) {
96816 }).attr('title', function (d) {
96817 return d.isMixed ? _t('inspector.unshared_value_tooltip') : null;
96820 if (allowDragAndDrop) {
96821 registerDragAndDrop(chips);
96824 chips.select('span').text(function (d) {
96827 chips.select('a').attr('href', '#').on('click', removeMultikey).attr('class', 'remove').text('×');
96829 var isMixed = Array.isArray(tags[field.key]);
96830 var mixedValues = isMixed && tags[field.key].map(function (val) {
96831 return displayValue(val);
96832 }).filter(Boolean);
96833 var showsValue = !isMixed && tags[field.key] && !(field.type === 'typeCombo' && tags[field.key] === 'yes');
96834 var isRawValue = showsValue && !field.hasTextForStringId('options.' + tags[field.key]);
96835 var isKnownValue = showsValue && !isRawValue;
96836 var isReadOnly = !_allowCustomValues || isKnownValue;
96837 utilGetSetValue(_input, !isMixed ? displayValue(tags[field.key]) : '').classed('raw-value', isRawValue).classed('known-value', isKnownValue).attr('readonly', isReadOnly ? 'readonly' : undefined).attr('title', isMixed ? mixedValues.join('\n') : undefined).attr('placeholder', isMixed ? _t('inspector.multiple_values') : _staticPlaceholder || '').classed('mixed', isMixed).on('keydown.deleteCapture', function (d3_event) {
96838 if (isReadOnly && isKnownValue && (d3_event.keyCode === utilKeybinding.keyCodes['⌫'] || d3_event.keyCode === utilKeybinding.keyCodes['⌦'])) {
96839 d3_event.preventDefault();
96840 d3_event.stopPropagation();
96842 t[field.key] = undefined;
96843 dispatch.call('change', this, t);
96849 function registerDragAndDrop(selection) {
96850 // allow drag and drop re-ordering of chips
96851 var dragOrigin, targetIndex;
96852 selection.call(d3_drag().on('start', function (d3_event) {
96857 targetIndex = null;
96858 }).on('drag', function (d3_event) {
96859 var x = d3_event.x - dragOrigin.x,
96860 y = d3_event.y - dragOrigin.y;
96861 if (!select(this).classed('dragging') && // don't display drag until dragging beyond a distance threshold
96862 Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) <= 5) return;
96863 var index = selection.nodes().indexOf(this);
96864 select(this).classed('dragging', true);
96865 targetIndex = null;
96866 var targetIndexOffsetTop = null;
96867 var draggedTagWidth = select(this).node().offsetWidth;
96869 if (field.key === 'destination' || field.key === 'via') {
96870 // meaning tags are full width
96871 _container.selectAll('.chip').style('transform', function (d2, index2) {
96872 var node = select(this).node();
96874 if (index === index2) {
96875 return 'translate(' + x + 'px, ' + y + 'px)'; // move the dragged tag up the order
96876 } else if (index2 > index && d3_event.y > node.offsetTop) {
96877 if (targetIndex === null || index2 > targetIndex) {
96878 targetIndex = index2;
96881 return 'translateY(-100%)'; // move the dragged tag down the order
96882 } else if (index2 < index && d3_event.y < node.offsetTop + node.offsetHeight) {
96883 if (targetIndex === null || index2 < targetIndex) {
96884 targetIndex = index2;
96887 return 'translateY(100%)';
96893 _container.selectAll('.chip').each(function (d2, index2) {
96894 var node = select(this).node(); // check the cursor is in the bounding box
96896 if (index !== index2 && d3_event.x < node.offsetLeft + node.offsetWidth + 5 && d3_event.x > node.offsetLeft && d3_event.y < node.offsetTop + node.offsetHeight && d3_event.y > node.offsetTop) {
96897 targetIndex = index2;
96898 targetIndexOffsetTop = node.offsetTop;
96900 }).style('transform', function (d2, index2) {
96901 var node = select(this).node();
96903 if (index === index2) {
96904 return 'translate(' + x + 'px, ' + y + 'px)';
96905 } // only translate tags in the same row
96908 if (node.offsetTop === targetIndexOffsetTop) {
96909 if (index2 < index && index2 >= targetIndex) {
96910 return 'translateX(' + draggedTagWidth + 'px)';
96911 } else if (index2 > index && index2 <= targetIndex) {
96912 return 'translateX(-' + draggedTagWidth + 'px)';
96919 }).on('end', function () {
96920 if (!select(this).classed('dragging')) {
96924 var index = selection.nodes().indexOf(this);
96925 select(this).classed('dragging', false);
96927 _container.selectAll('.chip').style('transform', null);
96929 if (typeof targetIndex === 'number') {
96930 var element = _multiData[index];
96932 _multiData.splice(index, 1);
96934 _multiData.splice(targetIndex, 0, element);
96938 if (_multiData.length) {
96939 t[field.key] = _multiData.map(function (element) {
96940 return element.key;
96943 t[field.key] = undefined;
96946 dispatch.call('change', this, t);
96949 dragOrigin = undefined;
96950 targetIndex = undefined;
96954 combo.focus = function () {
96955 _input.node().focus();
96958 combo.entityIDs = function (val) {
96959 if (!arguments.length) return _entityIDs;
96964 function combinedEntityExtent() {
96965 return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
96968 return utilRebind(combo, dispatch, 'on');
96971 // based on https://github.com/bestiejs/punycode.js/blob/master/punycode.js
96972 var global$2 = global$1o;
96973 var uncurryThis$1 = functionUncurryThis;
96975 var maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1
96981 var initialBias = 72;
96982 var initialN = 128; // 0x80
96983 var delimiter = '-'; // '\x2D'
96984 var regexNonASCII = /[^\0-\u007E]/; // non-ASCII chars
96985 var regexSeparators = /[.\u3002\uFF0E\uFF61]/g; // RFC 3490 separators
96986 var OVERFLOW_ERROR = 'Overflow: input needs wider integers to process';
96987 var baseMinusTMin = base - tMin;
96989 var RangeError$1 = global$2.RangeError;
96990 var exec$1 = uncurryThis$1(regexSeparators.exec);
96991 var floor$1 = Math.floor;
96992 var fromCharCode = String.fromCharCode;
96993 var charCodeAt = uncurryThis$1(''.charCodeAt);
96994 var join$1 = uncurryThis$1([].join);
96995 var push$1 = uncurryThis$1([].push);
96996 var replace$1 = uncurryThis$1(''.replace);
96997 var split$1 = uncurryThis$1(''.split);
96998 var toLowerCase$1 = uncurryThis$1(''.toLowerCase);
97001 * Creates an array containing the numeric code points of each Unicode
97002 * character in the string. While JavaScript uses UCS-2 internally,
97003 * this function will convert a pair of surrogate halves (each of which
97004 * UCS-2 exposes as separate characters) into a single code point,
97007 var ucs2decode = function (string) {
97010 var length = string.length;
97011 while (counter < length) {
97012 var value = charCodeAt(string, counter++);
97013 if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
97014 // It's a high surrogate, and there is a next character.
97015 var extra = charCodeAt(string, counter++);
97016 if ((extra & 0xFC00) == 0xDC00) { // Low surrogate.
97017 push$1(output, ((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
97019 // It's an unmatched surrogate; only append this code unit, in case the
97020 // next code unit is the high surrogate of a surrogate pair.
97021 push$1(output, value);
97025 push$1(output, value);
97032 * Converts a digit/integer into a basic code point.
97034 var digitToBasic = function (digit) {
97035 // 0..25 map to ASCII a..z or A..Z
97036 // 26..35 map to ASCII 0..9
97037 return digit + 22 + 75 * (digit < 26);
97041 * Bias adaptation function as per section 3.4 of RFC 3492.
97042 * https://tools.ietf.org/html/rfc3492#section-3.4
97044 var adapt = function (delta, numPoints, firstTime) {
97046 delta = firstTime ? floor$1(delta / damp) : delta >> 1;
97047 delta += floor$1(delta / numPoints);
97048 while (delta > baseMinusTMin * tMax >> 1) {
97049 delta = floor$1(delta / baseMinusTMin);
97052 return floor$1(k + (baseMinusTMin + 1) * delta / (delta + skew));
97056 * Converts a string of Unicode symbols (e.g. a domain name label) to a
97057 * Punycode string of ASCII-only symbols.
97059 var encode = function (input) {
97062 // Convert the input in UCS-2 to an array of Unicode code points.
97063 input = ucs2decode(input);
97065 // Cache the length.
97066 var inputLength = input.length;
97068 // Initialize the state.
97071 var bias = initialBias;
97072 var i, currentValue;
97074 // Handle the basic code points.
97075 for (i = 0; i < input.length; i++) {
97076 currentValue = input[i];
97077 if (currentValue < 0x80) {
97078 push$1(output, fromCharCode(currentValue));
97082 var basicLength = output.length; // number of basic code points.
97083 var handledCPCount = basicLength; // number of code points that have been handled;
97085 // Finish the basic string with a delimiter unless it's empty.
97087 push$1(output, delimiter);
97090 // Main encoding loop:
97091 while (handledCPCount < inputLength) {
97092 // All non-basic code points < n have been handled already. Find the next larger one:
97094 for (i = 0; i < input.length; i++) {
97095 currentValue = input[i];
97096 if (currentValue >= n && currentValue < m) {
97101 // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>, but guard against overflow.
97102 var handledCPCountPlusOne = handledCPCount + 1;
97103 if (m - n > floor$1((maxInt - delta) / handledCPCountPlusOne)) {
97104 throw RangeError$1(OVERFLOW_ERROR);
97107 delta += (m - n) * handledCPCountPlusOne;
97110 for (i = 0; i < input.length; i++) {
97111 currentValue = input[i];
97112 if (currentValue < n && ++delta > maxInt) {
97113 throw RangeError$1(OVERFLOW_ERROR);
97115 if (currentValue == n) {
97116 // Represent delta as a generalized variable-length integer.
97120 var t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
97122 var qMinusT = q - t;
97123 var baseMinusT = base - t;
97124 push$1(output, fromCharCode(digitToBasic(t + qMinusT % baseMinusT)));
97125 q = floor$1(qMinusT / baseMinusT);
97129 push$1(output, fromCharCode(digitToBasic(q)));
97130 bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
97139 return join$1(output, '');
97142 var stringPunycodeToAscii = function (input) {
97144 var labels = split$1(replace$1(toLowerCase$1(input), regexSeparators, '\u002E'), '.');
97146 for (i = 0; i < labels.length; i++) {
97148 push$1(encoded, exec$1(regexNonASCII, label) ? 'xn--' + encode(label) : label);
97150 return join$1(encoded, '.');
97153 // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env`
97156 var DESCRIPTORS = descriptors;
97157 var USE_NATIVE_URL = nativeUrl;
97158 var global$1 = global$1o;
97159 var bind$2 = functionBindContext;
97160 var uncurryThis = functionUncurryThis;
97161 var defineProperties = objectDefineProperties.f;
97162 var redefine = redefine$h.exports;
97163 var anInstance = anInstance$7;
97164 var hasOwn = hasOwnProperty_1;
97165 var assign$1 = objectAssign;
97166 var arrayFrom = arrayFrom$1;
97167 var arraySlice = arraySliceSimple;
97168 var codeAt = stringMultibyte.codeAt;
97169 var toASCII = stringPunycodeToAscii;
97170 var $toString = toString$k;
97171 var setToStringTag = setToStringTag$a;
97172 var validateArgumentsLength = validateArgumentsLength$4;
97173 var URLSearchParamsModule = web_urlSearchParams;
97174 var InternalStateModule = internalState;
97176 var setInternalState = InternalStateModule.set;
97177 var getInternalURLState = InternalStateModule.getterFor('URL');
97178 var URLSearchParams$1 = URLSearchParamsModule.URLSearchParams;
97179 var getInternalSearchParamsState = URLSearchParamsModule.getState;
97181 var NativeURL = global$1.URL;
97182 var TypeError$1 = global$1.TypeError;
97183 var parseInt$1 = global$1.parseInt;
97184 var floor = Math.floor;
97185 var pow = Math.pow;
97186 var charAt = uncurryThis(''.charAt);
97187 var exec = uncurryThis(/./.exec);
97188 var join = uncurryThis([].join);
97189 var numberToString = uncurryThis(1.0.toString);
97190 var pop = uncurryThis([].pop);
97191 var push = uncurryThis([].push);
97192 var replace = uncurryThis(''.replace);
97193 var shift = uncurryThis([].shift);
97194 var split = uncurryThis(''.split);
97195 var stringSlice = uncurryThis(''.slice);
97196 var toLowerCase = uncurryThis(''.toLowerCase);
97197 var unshift = uncurryThis([].unshift);
97199 var INVALID_AUTHORITY = 'Invalid authority';
97200 var INVALID_SCHEME = 'Invalid scheme';
97201 var INVALID_HOST = 'Invalid host';
97202 var INVALID_PORT = 'Invalid port';
97204 var ALPHA = /[a-z]/i;
97205 // eslint-disable-next-line regexp/no-obscure-range -- safe
97206 var ALPHANUMERIC = /[\d+-.a-z]/i;
97208 var HEX_START = /^0x/i;
97209 var OCT = /^[0-7]+$/;
97211 var HEX = /^[\da-f]+$/i;
97212 /* eslint-disable regexp/no-control-character -- safe */
97213 var FORBIDDEN_HOST_CODE_POINT = /[\0\t\n\r #%/:<>?@[\\\]^|]/;
97214 var FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT = /[\0\t\n\r #/:<>?@[\\\]^|]/;
97215 var LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE = /^[\u0000-\u0020]+|[\u0000-\u0020]+$/g;
97216 var TAB_AND_NEW_LINE = /[\t\n\r]/g;
97217 /* eslint-enable regexp/no-control-character -- safe */
97220 // https://url.spec.whatwg.org/#ipv4-number-parser
97221 var parseIPv4 = function (input) {
97222 var parts = split(input, '.');
97223 var partsLength, numbers, index, part, radix, number, ipv4;
97224 if (parts.length && parts[parts.length - 1] == '') {
97227 partsLength = parts.length;
97228 if (partsLength > 4) return input;
97230 for (index = 0; index < partsLength; index++) {
97231 part = parts[index];
97232 if (part == '') return input;
97234 if (part.length > 1 && charAt(part, 0) == '0') {
97235 radix = exec(HEX_START, part) ? 16 : 8;
97236 part = stringSlice(part, radix == 8 ? 1 : 2);
97241 if (!exec(radix == 10 ? DEC : radix == 8 ? OCT : HEX, part)) return input;
97242 number = parseInt$1(part, radix);
97244 push(numbers, number);
97246 for (index = 0; index < partsLength; index++) {
97247 number = numbers[index];
97248 if (index == partsLength - 1) {
97249 if (number >= pow(256, 5 - partsLength)) return null;
97250 } else if (number > 255) return null;
97252 ipv4 = pop(numbers);
97253 for (index = 0; index < numbers.length; index++) {
97254 ipv4 += numbers[index] * pow(256, 3 - index);
97259 // https://url.spec.whatwg.org/#concept-ipv6-parser
97260 // eslint-disable-next-line max-statements -- TODO
97261 var parseIPv6 = function (input) {
97262 var address = [0, 0, 0, 0, 0, 0, 0, 0];
97263 var pieceIndex = 0;
97264 var compress = null;
97266 var value, length, numbersSeen, ipv4Piece, number, swaps, swap;
97268 var chr = function () {
97269 return charAt(input, pointer);
97272 if (chr() == ':') {
97273 if (charAt(input, 1) != ':') return;
97276 compress = pieceIndex;
97279 if (pieceIndex == 8) return;
97280 if (chr() == ':') {
97281 if (compress !== null) return;
97284 compress = pieceIndex;
97287 value = length = 0;
97288 while (length < 4 && exec(HEX, chr())) {
97289 value = value * 16 + parseInt$1(chr(), 16);
97293 if (chr() == '.') {
97294 if (length == 0) return;
97296 if (pieceIndex > 6) return;
97300 if (numbersSeen > 0) {
97301 if (chr() == '.' && numbersSeen < 4) pointer++;
97304 if (!exec(DIGIT, chr())) return;
97305 while (exec(DIGIT, chr())) {
97306 number = parseInt$1(chr(), 10);
97307 if (ipv4Piece === null) ipv4Piece = number;
97308 else if (ipv4Piece == 0) return;
97309 else ipv4Piece = ipv4Piece * 10 + number;
97310 if (ipv4Piece > 255) return;
97313 address[pieceIndex] = address[pieceIndex] * 256 + ipv4Piece;
97315 if (numbersSeen == 2 || numbersSeen == 4) pieceIndex++;
97317 if (numbersSeen != 4) return;
97319 } else if (chr() == ':') {
97321 if (!chr()) return;
97322 } else if (chr()) return;
97323 address[pieceIndex++] = value;
97325 if (compress !== null) {
97326 swaps = pieceIndex - compress;
97328 while (pieceIndex != 0 && swaps > 0) {
97329 swap = address[pieceIndex];
97330 address[pieceIndex--] = address[compress + swaps - 1];
97331 address[compress + --swaps] = swap;
97333 } else if (pieceIndex != 8) return;
97337 var findLongestZeroSequence = function (ipv6) {
97338 var maxIndex = null;
97340 var currStart = null;
97341 var currLength = 0;
97343 for (; index < 8; index++) {
97344 if (ipv6[index] !== 0) {
97345 if (currLength > maxLength) {
97346 maxIndex = currStart;
97347 maxLength = currLength;
97352 if (currStart === null) currStart = index;
97356 if (currLength > maxLength) {
97357 maxIndex = currStart;
97358 maxLength = currLength;
97363 // https://url.spec.whatwg.org/#host-serializing
97364 var serializeHost = function (host) {
97365 var result, index, compress, ignore0;
97367 if (typeof host == 'number') {
97369 for (index = 0; index < 4; index++) {
97370 unshift(result, host % 256);
97371 host = floor(host / 256);
97372 } return join(result, '.');
97374 } else if (typeof host == 'object') {
97376 compress = findLongestZeroSequence(host);
97377 for (index = 0; index < 8; index++) {
97378 if (ignore0 && host[index] === 0) continue;
97379 if (ignore0) ignore0 = false;
97380 if (compress === index) {
97381 result += index ? ':' : '::';
97384 result += numberToString(host[index], 16);
97385 if (index < 7) result += ':';
97388 return '[' + result + ']';
97392 var C0ControlPercentEncodeSet = {};
97393 var fragmentPercentEncodeSet = assign$1({}, C0ControlPercentEncodeSet, {
97394 ' ': 1, '"': 1, '<': 1, '>': 1, '`': 1
97396 var pathPercentEncodeSet = assign$1({}, fragmentPercentEncodeSet, {
97397 '#': 1, '?': 1, '{': 1, '}': 1
97399 var userinfoPercentEncodeSet = assign$1({}, pathPercentEncodeSet, {
97400 '/': 1, ':': 1, ';': 1, '=': 1, '@': 1, '[': 1, '\\': 1, ']': 1, '^': 1, '|': 1
97403 var percentEncode = function (chr, set) {
97404 var code = codeAt(chr, 0);
97405 return code > 0x20 && code < 0x7F && !hasOwn(set, chr) ? chr : encodeURIComponent(chr);
97408 // https://url.spec.whatwg.org/#special-scheme
97409 var specialSchemes = {
97418 // https://url.spec.whatwg.org/#windows-drive-letter
97419 var isWindowsDriveLetter = function (string, normalized) {
97421 return string.length == 2 && exec(ALPHA, charAt(string, 0))
97422 && ((second = charAt(string, 1)) == ':' || (!normalized && second == '|'));
97425 // https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
97426 var startsWithWindowsDriveLetter = function (string) {
97428 return string.length > 1 && isWindowsDriveLetter(stringSlice(string, 0, 2)) && (
97429 string.length == 2 ||
97430 ((third = charAt(string, 2)) === '/' || third === '\\' || third === '?' || third === '#')
97434 // https://url.spec.whatwg.org/#single-dot-path-segment
97435 var isSingleDot = function (segment) {
97436 return segment === '.' || toLowerCase(segment) === '%2e';
97439 // https://url.spec.whatwg.org/#double-dot-path-segment
97440 var isDoubleDot = function (segment) {
97441 segment = toLowerCase(segment);
97442 return segment === '..' || segment === '%2e.' || segment === '.%2e' || segment === '%2e%2e';
97446 var SCHEME_START = {};
97448 var NO_SCHEME = {};
97449 var SPECIAL_RELATIVE_OR_AUTHORITY = {};
97450 var PATH_OR_AUTHORITY = {};
97452 var RELATIVE_SLASH = {};
97453 var SPECIAL_AUTHORITY_SLASHES = {};
97454 var SPECIAL_AUTHORITY_IGNORE_SLASHES = {};
97455 var AUTHORITY = {};
97460 var FILE_SLASH = {};
97461 var FILE_HOST = {};
97462 var PATH_START = {};
97464 var CANNOT_BE_A_BASE_URL_PATH = {};
97468 var URLState = function (url, isBase, base) {
97469 var urlString = $toString(url);
97470 var baseState, failure, searchParams;
97472 failure = this.parse(urlString);
97473 if (failure) throw TypeError$1(failure);
97474 this.searchParams = null;
97476 if (base !== undefined) baseState = new URLState(base, true);
97477 failure = this.parse(urlString, null, baseState);
97478 if (failure) throw TypeError$1(failure);
97479 searchParams = getInternalSearchParamsState(new URLSearchParams$1());
97480 searchParams.bindURL(this);
97481 this.searchParams = searchParams;
97485 URLState.prototype = {
97487 // https://url.spec.whatwg.org/#url-parsing
97488 // eslint-disable-next-line max-statements -- TODO
97489 parse: function (input, stateOverride, base) {
97491 var state = stateOverride || SCHEME_START;
97494 var seenAt = false;
97495 var seenBracket = false;
97496 var seenPasswordToken = false;
97497 var codePoints, chr, bufferCodePoints, failure;
97499 input = $toString(input);
97501 if (!stateOverride) {
97509 url.fragment = null;
97510 url.cannotBeABaseURL = false;
97511 input = replace(input, LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE, '');
97514 input = replace(input, TAB_AND_NEW_LINE, '');
97516 codePoints = arrayFrom(input);
97518 while (pointer <= codePoints.length) {
97519 chr = codePoints[pointer];
97522 if (chr && exec(ALPHA, chr)) {
97523 buffer += toLowerCase(chr);
97525 } else if (!stateOverride) {
97528 } else return INVALID_SCHEME;
97532 if (chr && (exec(ALPHANUMERIC, chr) || chr == '+' || chr == '-' || chr == '.')) {
97533 buffer += toLowerCase(chr);
97534 } else if (chr == ':') {
97535 if (stateOverride && (
97536 (url.isSpecial() != hasOwn(specialSchemes, buffer)) ||
97537 (buffer == 'file' && (url.includesCredentials() || url.port !== null)) ||
97538 (url.scheme == 'file' && !url.host)
97540 url.scheme = buffer;
97541 if (stateOverride) {
97542 if (url.isSpecial() && specialSchemes[url.scheme] == url.port) url.port = null;
97546 if (url.scheme == 'file') {
97548 } else if (url.isSpecial() && base && base.scheme == url.scheme) {
97549 state = SPECIAL_RELATIVE_OR_AUTHORITY;
97550 } else if (url.isSpecial()) {
97551 state = SPECIAL_AUTHORITY_SLASHES;
97552 } else if (codePoints[pointer + 1] == '/') {
97553 state = PATH_OR_AUTHORITY;
97556 url.cannotBeABaseURL = true;
97557 push(url.path, '');
97558 state = CANNOT_BE_A_BASE_URL_PATH;
97560 } else if (!stateOverride) {
97565 } else return INVALID_SCHEME;
97569 if (!base || (base.cannotBeABaseURL && chr != '#')) return INVALID_SCHEME;
97570 if (base.cannotBeABaseURL && chr == '#') {
97571 url.scheme = base.scheme;
97572 url.path = arraySlice(base.path);
97573 url.query = base.query;
97575 url.cannotBeABaseURL = true;
97579 state = base.scheme == 'file' ? FILE : RELATIVE;
97582 case SPECIAL_RELATIVE_OR_AUTHORITY:
97583 if (chr == '/' && codePoints[pointer + 1] == '/') {
97584 state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
97591 case PATH_OR_AUTHORITY:
97601 url.scheme = base.scheme;
97603 url.username = base.username;
97604 url.password = base.password;
97605 url.host = base.host;
97606 url.port = base.port;
97607 url.path = arraySlice(base.path);
97608 url.query = base.query;
97609 } else if (chr == '/' || (chr == '\\' && url.isSpecial())) {
97610 state = RELATIVE_SLASH;
97611 } else if (chr == '?') {
97612 url.username = base.username;
97613 url.password = base.password;
97614 url.host = base.host;
97615 url.port = base.port;
97616 url.path = arraySlice(base.path);
97619 } else if (chr == '#') {
97620 url.username = base.username;
97621 url.password = base.password;
97622 url.host = base.host;
97623 url.port = base.port;
97624 url.path = arraySlice(base.path);
97625 url.query = base.query;
97629 url.username = base.username;
97630 url.password = base.password;
97631 url.host = base.host;
97632 url.port = base.port;
97633 url.path = arraySlice(base.path);
97639 case RELATIVE_SLASH:
97640 if (url.isSpecial() && (chr == '/' || chr == '\\')) {
97641 state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
97642 } else if (chr == '/') {
97645 url.username = base.username;
97646 url.password = base.password;
97647 url.host = base.host;
97648 url.port = base.port;
97653 case SPECIAL_AUTHORITY_SLASHES:
97654 state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
97655 if (chr != '/' || charAt(buffer, pointer + 1) != '/') continue;
97659 case SPECIAL_AUTHORITY_IGNORE_SLASHES:
97660 if (chr != '/' && chr != '\\') {
97667 if (seenAt) buffer = '%40' + buffer;
97669 bufferCodePoints = arrayFrom(buffer);
97670 for (var i = 0; i < bufferCodePoints.length; i++) {
97671 var codePoint = bufferCodePoints[i];
97672 if (codePoint == ':' && !seenPasswordToken) {
97673 seenPasswordToken = true;
97676 var encodedCodePoints = percentEncode(codePoint, userinfoPercentEncodeSet);
97677 if (seenPasswordToken) url.password += encodedCodePoints;
97678 else url.username += encodedCodePoints;
97682 chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
97683 (chr == '\\' && url.isSpecial())
97685 if (seenAt && buffer == '') return INVALID_AUTHORITY;
97686 pointer -= arrayFrom(buffer).length + 1;
97689 } else buffer += chr;
97694 if (stateOverride && url.scheme == 'file') {
97697 } else if (chr == ':' && !seenBracket) {
97698 if (buffer == '') return INVALID_HOST;
97699 failure = url.parseHost(buffer);
97700 if (failure) return failure;
97703 if (stateOverride == HOSTNAME) return;
97705 chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
97706 (chr == '\\' && url.isSpecial())
97708 if (url.isSpecial() && buffer == '') return INVALID_HOST;
97709 if (stateOverride && buffer == '' && (url.includesCredentials() || url.port !== null)) return;
97710 failure = url.parseHost(buffer);
97711 if (failure) return failure;
97713 state = PATH_START;
97714 if (stateOverride) return;
97717 if (chr == '[') seenBracket = true;
97718 else if (chr == ']') seenBracket = false;
97723 if (exec(DIGIT, chr)) {
97726 chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
97727 (chr == '\\' && url.isSpecial()) ||
97730 if (buffer != '') {
97731 var port = parseInt$1(buffer, 10);
97732 if (port > 0xFFFF) return INVALID_PORT;
97733 url.port = (url.isSpecial() && port === specialSchemes[url.scheme]) ? null : port;
97736 if (stateOverride) return;
97737 state = PATH_START;
97739 } else return INVALID_PORT;
97743 url.scheme = 'file';
97744 if (chr == '/' || chr == '\\') state = FILE_SLASH;
97745 else if (base && base.scheme == 'file') {
97747 url.host = base.host;
97748 url.path = arraySlice(base.path);
97749 url.query = base.query;
97750 } else if (chr == '?') {
97751 url.host = base.host;
97752 url.path = arraySlice(base.path);
97755 } else if (chr == '#') {
97756 url.host = base.host;
97757 url.path = arraySlice(base.path);
97758 url.query = base.query;
97762 if (!startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) {
97763 url.host = base.host;
97764 url.path = arraySlice(base.path);
97776 if (chr == '/' || chr == '\\') {
97780 if (base && base.scheme == 'file' && !startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) {
97781 if (isWindowsDriveLetter(base.path[0], true)) push(url.path, base.path[0]);
97782 else url.host = base.host;
97788 if (chr == EOF || chr == '/' || chr == '\\' || chr == '?' || chr == '#') {
97789 if (!stateOverride && isWindowsDriveLetter(buffer)) {
97791 } else if (buffer == '') {
97793 if (stateOverride) return;
97794 state = PATH_START;
97796 failure = url.parseHost(buffer);
97797 if (failure) return failure;
97798 if (url.host == 'localhost') url.host = '';
97799 if (stateOverride) return;
97801 state = PATH_START;
97803 } else buffer += chr;
97807 if (url.isSpecial()) {
97809 if (chr != '/' && chr != '\\') continue;
97810 } else if (!stateOverride && chr == '?') {
97813 } else if (!stateOverride && chr == '#') {
97816 } else if (chr != EOF) {
97818 if (chr != '/') continue;
97823 chr == EOF || chr == '/' ||
97824 (chr == '\\' && url.isSpecial()) ||
97825 (!stateOverride && (chr == '?' || chr == '#'))
97827 if (isDoubleDot(buffer)) {
97829 if (chr != '/' && !(chr == '\\' && url.isSpecial())) {
97830 push(url.path, '');
97832 } else if (isSingleDot(buffer)) {
97833 if (chr != '/' && !(chr == '\\' && url.isSpecial())) {
97834 push(url.path, '');
97837 if (url.scheme == 'file' && !url.path.length && isWindowsDriveLetter(buffer)) {
97838 if (url.host) url.host = '';
97839 buffer = charAt(buffer, 0) + ':'; // normalize windows drive letter
97841 push(url.path, buffer);
97844 if (url.scheme == 'file' && (chr == EOF || chr == '?' || chr == '#')) {
97845 while (url.path.length > 1 && url.path[0] === '') {
97852 } else if (chr == '#') {
97857 buffer += percentEncode(chr, pathPercentEncodeSet);
97860 case CANNOT_BE_A_BASE_URL_PATH:
97864 } else if (chr == '#') {
97867 } else if (chr != EOF) {
97868 url.path[0] += percentEncode(chr, C0ControlPercentEncodeSet);
97872 if (!stateOverride && chr == '#') {
97875 } else if (chr != EOF) {
97876 if (chr == "'" && url.isSpecial()) url.query += '%27';
97877 else if (chr == '#') url.query += '%23';
97878 else url.query += percentEncode(chr, C0ControlPercentEncodeSet);
97882 if (chr != EOF) url.fragment += percentEncode(chr, fragmentPercentEncodeSet);
97889 // https://url.spec.whatwg.org/#host-parsing
97890 parseHost: function (input) {
97891 var result, codePoints, index;
97892 if (charAt(input, 0) == '[') {
97893 if (charAt(input, input.length - 1) != ']') return INVALID_HOST;
97894 result = parseIPv6(stringSlice(input, 1, -1));
97895 if (!result) return INVALID_HOST;
97896 this.host = result;
97898 } else if (!this.isSpecial()) {
97899 if (exec(FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT, input)) return INVALID_HOST;
97901 codePoints = arrayFrom(input);
97902 for (index = 0; index < codePoints.length; index++) {
97903 result += percentEncode(codePoints[index], C0ControlPercentEncodeSet);
97905 this.host = result;
97907 input = toASCII(input);
97908 if (exec(FORBIDDEN_HOST_CODE_POINT, input)) return INVALID_HOST;
97909 result = parseIPv4(input);
97910 if (result === null) return INVALID_HOST;
97911 this.host = result;
97914 // https://url.spec.whatwg.org/#cannot-have-a-username-password-port
97915 cannotHaveUsernamePasswordPort: function () {
97916 return !this.host || this.cannotBeABaseURL || this.scheme == 'file';
97918 // https://url.spec.whatwg.org/#include-credentials
97919 includesCredentials: function () {
97920 return this.username != '' || this.password != '';
97922 // https://url.spec.whatwg.org/#is-special
97923 isSpecial: function () {
97924 return hasOwn(specialSchemes, this.scheme);
97926 // https://url.spec.whatwg.org/#shorten-a-urls-path
97927 shortenPath: function () {
97928 var path = this.path;
97929 var pathSize = path.length;
97930 if (pathSize && (this.scheme != 'file' || pathSize != 1 || !isWindowsDriveLetter(path[0], true))) {
97934 // https://url.spec.whatwg.org/#concept-url-serializer
97935 serialize: function () {
97937 var scheme = url.scheme;
97938 var username = url.username;
97939 var password = url.password;
97940 var host = url.host;
97941 var port = url.port;
97942 var path = url.path;
97943 var query = url.query;
97944 var fragment = url.fragment;
97945 var output = scheme + ':';
97946 if (host !== null) {
97948 if (url.includesCredentials()) {
97949 output += username + (password ? ':' + password : '') + '@';
97951 output += serializeHost(host);
97952 if (port !== null) output += ':' + port;
97953 } else if (scheme == 'file') output += '//';
97954 output += url.cannotBeABaseURL ? path[0] : path.length ? '/' + join(path, '/') : '';
97955 if (query !== null) output += '?' + query;
97956 if (fragment !== null) output += '#' + fragment;
97959 // https://url.spec.whatwg.org/#dom-url-href
97960 setHref: function (href) {
97961 var failure = this.parse(href);
97962 if (failure) throw TypeError$1(failure);
97963 this.searchParams.update();
97965 // https://url.spec.whatwg.org/#dom-url-origin
97966 getOrigin: function () {
97967 var scheme = this.scheme;
97968 var port = this.port;
97969 if (scheme == 'blob') try {
97970 return new URLConstructor(scheme.path[0]).origin;
97974 if (scheme == 'file' || !this.isSpecial()) return 'null';
97975 return scheme + '://' + serializeHost(this.host) + (port !== null ? ':' + port : '');
97977 // https://url.spec.whatwg.org/#dom-url-protocol
97978 getProtocol: function () {
97979 return this.scheme + ':';
97981 setProtocol: function (protocol) {
97982 this.parse($toString(protocol) + ':', SCHEME_START);
97984 // https://url.spec.whatwg.org/#dom-url-username
97985 getUsername: function () {
97986 return this.username;
97988 setUsername: function (username) {
97989 var codePoints = arrayFrom($toString(username));
97990 if (this.cannotHaveUsernamePasswordPort()) return;
97991 this.username = '';
97992 for (var i = 0; i < codePoints.length; i++) {
97993 this.username += percentEncode(codePoints[i], userinfoPercentEncodeSet);
97996 // https://url.spec.whatwg.org/#dom-url-password
97997 getPassword: function () {
97998 return this.password;
98000 setPassword: function (password) {
98001 var codePoints = arrayFrom($toString(password));
98002 if (this.cannotHaveUsernamePasswordPort()) return;
98003 this.password = '';
98004 for (var i = 0; i < codePoints.length; i++) {
98005 this.password += percentEncode(codePoints[i], userinfoPercentEncodeSet);
98008 // https://url.spec.whatwg.org/#dom-url-host
98009 getHost: function () {
98010 var host = this.host;
98011 var port = this.port;
98012 return host === null ? ''
98013 : port === null ? serializeHost(host)
98014 : serializeHost(host) + ':' + port;
98016 setHost: function (host) {
98017 if (this.cannotBeABaseURL) return;
98018 this.parse(host, HOST);
98020 // https://url.spec.whatwg.org/#dom-url-hostname
98021 getHostname: function () {
98022 var host = this.host;
98023 return host === null ? '' : serializeHost(host);
98025 setHostname: function (hostname) {
98026 if (this.cannotBeABaseURL) return;
98027 this.parse(hostname, HOSTNAME);
98029 // https://url.spec.whatwg.org/#dom-url-port
98030 getPort: function () {
98031 var port = this.port;
98032 return port === null ? '' : $toString(port);
98034 setPort: function (port) {
98035 if (this.cannotHaveUsernamePasswordPort()) return;
98036 port = $toString(port);
98037 if (port == '') this.port = null;
98038 else this.parse(port, PORT);
98040 // https://url.spec.whatwg.org/#dom-url-pathname
98041 getPathname: function () {
98042 var path = this.path;
98043 return this.cannotBeABaseURL ? path[0] : path.length ? '/' + join(path, '/') : '';
98045 setPathname: function (pathname) {
98046 if (this.cannotBeABaseURL) return;
98048 this.parse(pathname, PATH_START);
98050 // https://url.spec.whatwg.org/#dom-url-search
98051 getSearch: function () {
98052 var query = this.query;
98053 return query ? '?' + query : '';
98055 setSearch: function (search) {
98056 search = $toString(search);
98057 if (search == '') {
98060 if ('?' == charAt(search, 0)) search = stringSlice(search, 1);
98062 this.parse(search, QUERY);
98064 this.searchParams.update();
98066 // https://url.spec.whatwg.org/#dom-url-searchparams
98067 getSearchParams: function () {
98068 return this.searchParams.facade;
98070 // https://url.spec.whatwg.org/#dom-url-hash
98071 getHash: function () {
98072 var fragment = this.fragment;
98073 return fragment ? '#' + fragment : '';
98075 setHash: function (hash) {
98076 hash = $toString(hash);
98078 this.fragment = null;
98081 if ('#' == charAt(hash, 0)) hash = stringSlice(hash, 1);
98082 this.fragment = '';
98083 this.parse(hash, FRAGMENT);
98085 update: function () {
98086 this.query = this.searchParams.serialize() || null;
98090 // `URL` constructor
98091 // https://url.spec.whatwg.org/#url-class
98092 var URLConstructor = function URL(url /* , base */) {
98093 var that = anInstance(this, URLPrototype);
98094 var base = validateArgumentsLength(arguments.length, 1) > 1 ? arguments[1] : undefined;
98095 var state = setInternalState(that, new URLState(url, false, base));
98096 if (!DESCRIPTORS) {
98097 that.href = state.serialize();
98098 that.origin = state.getOrigin();
98099 that.protocol = state.getProtocol();
98100 that.username = state.getUsername();
98101 that.password = state.getPassword();
98102 that.host = state.getHost();
98103 that.hostname = state.getHostname();
98104 that.port = state.getPort();
98105 that.pathname = state.getPathname();
98106 that.search = state.getSearch();
98107 that.searchParams = state.getSearchParams();
98108 that.hash = state.getHash();
98112 var URLPrototype = URLConstructor.prototype;
98114 var accessorDescriptor = function (getter, setter) {
98117 return getInternalURLState(this)[getter]();
98119 set: setter && function (value) {
98120 return getInternalURLState(this)[setter](value);
98122 configurable: true,
98128 defineProperties(URLPrototype, {
98129 // `URL.prototype.href` accessors pair
98130 // https://url.spec.whatwg.org/#dom-url-href
98131 href: accessorDescriptor('serialize', 'setHref'),
98132 // `URL.prototype.origin` getter
98133 // https://url.spec.whatwg.org/#dom-url-origin
98134 origin: accessorDescriptor('getOrigin'),
98135 // `URL.prototype.protocol` accessors pair
98136 // https://url.spec.whatwg.org/#dom-url-protocol
98137 protocol: accessorDescriptor('getProtocol', 'setProtocol'),
98138 // `URL.prototype.username` accessors pair
98139 // https://url.spec.whatwg.org/#dom-url-username
98140 username: accessorDescriptor('getUsername', 'setUsername'),
98141 // `URL.prototype.password` accessors pair
98142 // https://url.spec.whatwg.org/#dom-url-password
98143 password: accessorDescriptor('getPassword', 'setPassword'),
98144 // `URL.prototype.host` accessors pair
98145 // https://url.spec.whatwg.org/#dom-url-host
98146 host: accessorDescriptor('getHost', 'setHost'),
98147 // `URL.prototype.hostname` accessors pair
98148 // https://url.spec.whatwg.org/#dom-url-hostname
98149 hostname: accessorDescriptor('getHostname', 'setHostname'),
98150 // `URL.prototype.port` accessors pair
98151 // https://url.spec.whatwg.org/#dom-url-port
98152 port: accessorDescriptor('getPort', 'setPort'),
98153 // `URL.prototype.pathname` accessors pair
98154 // https://url.spec.whatwg.org/#dom-url-pathname
98155 pathname: accessorDescriptor('getPathname', 'setPathname'),
98156 // `URL.prototype.search` accessors pair
98157 // https://url.spec.whatwg.org/#dom-url-search
98158 search: accessorDescriptor('getSearch', 'setSearch'),
98159 // `URL.prototype.searchParams` getter
98160 // https://url.spec.whatwg.org/#dom-url-searchparams
98161 searchParams: accessorDescriptor('getSearchParams'),
98162 // `URL.prototype.hash` accessors pair
98163 // https://url.spec.whatwg.org/#dom-url-hash
98164 hash: accessorDescriptor('getHash', 'setHash')
98168 // `URL.prototype.toJSON` method
98169 // https://url.spec.whatwg.org/#dom-url-tojson
98170 redefine(URLPrototype, 'toJSON', function toJSON() {
98171 return getInternalURLState(this).serialize();
98172 }, { enumerable: true });
98174 // `URL.prototype.toString` method
98175 // https://url.spec.whatwg.org/#URL-stringification-behavior
98176 redefine(URLPrototype, 'toString', function toString() {
98177 return getInternalURLState(this).serialize();
98178 }, { enumerable: true });
98181 var nativeCreateObjectURL = NativeURL.createObjectURL;
98182 var nativeRevokeObjectURL = NativeURL.revokeObjectURL;
98183 // `URL.createObjectURL` method
98184 // https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
98185 if (nativeCreateObjectURL) redefine(URLConstructor, 'createObjectURL', bind$2(nativeCreateObjectURL, NativeURL));
98186 // `URL.revokeObjectURL` method
98187 // https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
98188 if (nativeRevokeObjectURL) redefine(URLConstructor, 'revokeObjectURL', bind$2(nativeRevokeObjectURL, NativeURL));
98191 setToStringTag(URLConstructor, 'URL');
98193 $({ global: true, forced: !USE_NATIVE_URL, sham: !DESCRIPTORS }, {
98194 URL: URLConstructor
98197 function uiFieldText(field, context) {
98198 var dispatch = dispatch$8('change');
98199 var input = select(null);
98200 var outlinkButton = select(null);
98201 var wrap = select(null);
98202 var _entityIDs = [];
98206 var _phoneFormats = {};
98208 if (field.type === 'tel') {
98209 _mainFileFetcher.get('phone_formats').then(function (d) {
98211 updatePhonePlaceholder();
98212 })["catch"](function () {
98217 function calcLocked() {
98218 // Protect certain fields that have a companion `*:wikidata` value
98219 var isLocked = (field.id === 'brand' || field.id === 'network' || field.id === 'operator' || field.id === 'flag') && _entityIDs.length && _entityIDs.some(function (entityID) {
98220 var entity = context.graph().hasEntity(entityID);
98221 if (!entity) return false; // Features linked to Wikidata are likely important and should be protected
98223 if (entity.tags.wikidata) return true;
98224 var preset = _mainPresetIndex.match(entity, context.graph());
98225 var isSuggestion = preset && preset.suggestion; // Lock the field if there is a value and a companion `*:wikidata` value
98227 var which = field.id; // 'brand', 'network', 'operator', 'flag'
98229 return isSuggestion && !!entity.tags[which] && !!entity.tags[which + ':wikidata'];
98232 field.locked(isLocked);
98235 function i(selection) {
98237 var isLocked = field.locked();
98238 wrap = selection.selectAll('.form-field-input-wrap').data([0]);
98239 wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
98240 input = wrap.selectAll('input').data([0]);
98241 input = input.enter().append('input').attr('type', field.type === 'identifier' ? 'text' : field.type).attr('id', field.domId).classed(field.type, true).call(utilNoAuto).merge(input);
98242 input.classed('disabled', !!isLocked).attr('readonly', isLocked || null).on('input', change(true)).on('blur', change()).on('change', change());
98244 if (field.type === 'tel') {
98245 updatePhonePlaceholder();
98246 } else if (field.type === 'number') {
98247 var rtl = _mainLocalizer.textDirection() === 'rtl';
98248 input.attr('type', 'text');
98249 var inc = field.increment;
98250 var buttons = wrap.selectAll('.increment, .decrement').data(rtl ? [inc, -inc] : [-inc, inc]);
98251 buttons.enter().append('button').attr('class', function (d) {
98252 var which = d > 0 ? 'increment' : 'decrement';
98253 return 'form-field-button ' + which;
98254 }).attr('title', function (d) {
98255 var which = d > 0 ? 'increment' : 'decrement';
98256 return _t("inspector.".concat(which));
98257 }).merge(buttons).on('click', function (d3_event, d) {
98258 d3_event.preventDefault();
98259 var raw_vals = input.node().value || '0';
98260 var vals = raw_vals.split(';');
98261 vals = vals.map(function (v) {
98262 var num = parseFloat(v.trim(), 10);
98263 return isFinite(num) ? clamped(num + d) : v.trim();
98265 input.node().value = vals.join(';');
98268 } else if (field.type === 'identifier' && field.urlFormat && field.pattern) {
98269 input.attr('type', 'text');
98270 outlinkButton = wrap.selectAll('.foreign-id-permalink').data([0]);
98271 outlinkButton.enter().append('button').call(svgIcon('#iD-icon-out-link')).attr('class', 'form-field-button foreign-id-permalink').attr('title', function () {
98272 var domainResults = /^https?:\/\/(.{1,}?)\//.exec(field.urlFormat);
98274 if (domainResults.length >= 2 && domainResults[1]) {
98275 var domain = domainResults[1];
98276 return _t('icons.view_on', {
98282 }).on('click', function (d3_event) {
98283 d3_event.preventDefault();
98284 var value = validIdentifierValueForLink();
98287 var url = field.urlFormat.replace(/{value}/, encodeURIComponent(value));
98288 window.open(url, '_blank');
98290 }).merge(outlinkButton);
98291 } else if (field.type === 'url') {
98292 input.attr('type', 'text');
98293 outlinkButton = wrap.selectAll('.foreign-id-permalink').data([0]);
98294 outlinkButton.enter().append('button').call(svgIcon('#iD-icon-out-link')).attr('class', 'form-field-button foreign-id-permalink').attr('title', function () {
98295 return _t('icons.visit_website');
98296 }).on('click', function (d3_event) {
98297 d3_event.preventDefault();
98298 var value = validIdentifierValueForLink();
98299 if (value) window.open(value, '_blank');
98300 }).merge(outlinkButton);
98301 } else if (field.key.split(':').includes('colour')) {
98302 input.attr('type', 'text');
98303 updateColourPreview();
98307 function isColourValid(colour) {
98308 if (!colour.match(/^(#([0-9a-fA-F]{3}){1,2}|\w+)$/)) {
98309 // OSM only supports hex or named colors
98311 } else if (!CSS.supports('color', colour) || ['unset', 'inherit', 'initial', 'revert'].includes(colour)) {
98312 // see https://stackoverflow.com/a/68217760/1627467
98319 function updateColourPreview() {
98320 wrap.selectAll('.colour-preview').remove();
98321 var colour = utilGetSetValue(input);
98322 if (!isColourValid(colour) && colour !== '') return;
98323 var colourSelector = wrap.selectAll('.colour-selector').data([0]);
98324 outlinkButton = wrap.selectAll('.colour-preview').data([colour]);
98325 colourSelector.enter().append('input').attr('type', 'color').attr('class', 'form-field-button colour-selector').attr('value', colour).on('input', debounce(function (d3_event) {
98326 d3_event.preventDefault();
98327 var colour = this.value;
98328 if (!isColourValid(colour)) return;
98329 utilGetSetValue(input, this.value);
98331 updateColourPreview();
98333 outlinkButton = outlinkButton.enter().append('div').attr('class', 'form-field-button colour-preview').append('div').style('background-color', function (d) {
98335 }).attr('class', 'colour-box');
98337 if (colour === '') {
98338 outlinkButton = outlinkButton.call(svgIcon('#iD-icon-edit'));
98341 outlinkButton.on('click', function () {
98342 return wrap.select('.colour-selector').node().click();
98343 }).merge(outlinkButton);
98346 function updatePhonePlaceholder() {
98347 if (input.empty() || !Object.keys(_phoneFormats).length) return;
98348 var extent = combinedEntityExtent();
98349 var countryCode = extent && iso1A2Code(extent.center());
98351 var format = countryCode && _phoneFormats[countryCode.toLowerCase()];
98353 if (format) input.attr('placeholder', format);
98356 function validIdentifierValueForLink() {
98357 var value = utilGetSetValue(input).trim();
98359 if (field.type === 'url' && value) {
98361 return new URL(value).href;
98367 if (field.type === 'identifier' && field.pattern) {
98368 return value && value.match(new RegExp(field.pattern))[0];
98372 } // clamp number to min/max
98375 function clamped(num) {
98376 if (field.minValue !== undefined) {
98377 num = Math.max(num, field.minValue);
98380 if (field.maxValue !== undefined) {
98381 num = Math.min(num, field.maxValue);
98387 function change(onInput) {
98388 return function () {
98390 var val = utilGetSetValue(input);
98391 if (!onInput) val = context.cleanTagValue(val); // don't override multiple values with blank string
98393 if (!val && Array.isArray(_tags[field.key])) return;
98396 if (field.type === 'number' && val) {
98397 var vals = val.split(';');
98398 vals = vals.map(function (v) {
98399 var num = parseFloat(v.trim(), 10);
98400 return isFinite(num) ? clamped(num) : v.trim();
98402 val = vals.join(';');
98405 utilGetSetValue(input, val);
98408 t[field.key] = val || undefined;
98409 dispatch.call('change', this, t, onInput);
98413 i.entityIDs = function (val) {
98414 if (!arguments.length) return _entityIDs;
98419 i.tags = function (tags) {
98421 var isMixed = Array.isArray(tags[field.key]);
98422 utilGetSetValue(input, !isMixed && tags[field.key] ? tags[field.key] : '').attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : undefined).attr('placeholder', isMixed ? _t('inspector.multiple_values') : field.placeholder() || _t('inspector.unknown')).classed('mixed', isMixed);
98423 if (field.key.split(':').includes('colour')) updateColourPreview();
98425 if (outlinkButton && !outlinkButton.empty()) {
98426 var disabled = !validIdentifierValueForLink();
98427 outlinkButton.classed('disabled', disabled);
98431 i.focus = function () {
98432 var node = input.node();
98433 if (node) node.focus();
98436 function combinedEntityExtent() {
98437 return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
98440 return utilRebind(i, dispatch, 'on');
98443 function uiFieldAccess(field, context) {
98444 var dispatch = dispatch$8('change');
98445 var items = select(null);
98449 function access(selection) {
98450 var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
98451 wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
98452 var list = wrap.selectAll('ul').data([0]);
98453 list = list.enter().append('ul').attr('class', 'rows').merge(list);
98454 items = list.selectAll('li').data(field.keys); // Enter
98456 var enter = items.enter().append('li').attr('class', function (d) {
98457 return 'labeled-input preset-access-' + d;
98459 enter.append('span').attr('class', 'label preset-label-access').attr('for', function (d) {
98460 return 'preset-input-access-' + d;
98461 }).html(function (d) {
98462 return field.t.html('types.' + d);
98464 enter.append('div').attr('class', 'preset-input-access-wrap').append('input').attr('type', 'text').attr('class', function (d) {
98465 return 'preset-input-access preset-input-access-' + d;
98466 }).call(utilNoAuto).each(function (d) {
98467 select(this).call(uiCombobox(context, 'access-' + d).data(access.options(d)));
98470 items = items.merge(enter);
98471 wrap.selectAll('.preset-input-access').on('change', change).on('blur', change);
98474 function change(d3_event, d) {
98476 var value = context.cleanTagValue(utilGetSetValue(select(this))); // don't override multiple values with blank string
98478 if (!value && typeof _tags[d] !== 'string') return;
98479 tag[d] = value || undefined;
98480 dispatch.call('change', this, tag);
98483 access.options = function (type) {
98484 var options = ['no', 'permissive', 'private', 'permit', 'destination', 'customers', 'unknown'];
98486 if (type !== 'access') {
98487 options.unshift('yes');
98488 options.push('designated');
98490 if (type === 'bicycle') {
98491 options.push('dismount');
98495 return options.map(function (option) {
98497 title: field.t('options.' + option + '.description'),
98503 var placeholdersByHighway = {
98505 foot: 'designated',
98506 motor_vehicle: 'no'
98510 motor_vehicle: 'no',
98516 motor_vehicle: 'no'
98519 motor_vehicle: 'no',
98520 bicycle: 'designated'
98523 motor_vehicle: 'no',
98524 horse: 'designated'
98528 motor_vehicle: 'no',
98534 motor_vehicle: 'yes',
98539 motor_vehicle: 'yes'
98543 motor_vehicle: 'yes',
98549 motor_vehicle: 'yes',
98555 motor_vehicle: 'yes',
98561 motor_vehicle: 'yes',
98567 motor_vehicle: 'yes',
98573 motor_vehicle: 'yes',
98579 motor_vehicle: 'yes',
98584 motor_vehicle: 'yes'
98588 motor_vehicle: 'yes',
98594 motor_vehicle: 'yes',
98600 motor_vehicle: 'yes',
98606 access.tags = function (tags) {
98608 utilGetSetValue(items.selectAll('.preset-input-access'), function (d) {
98609 return typeof tags[d] === 'string' ? tags[d] : '';
98610 }).classed('mixed', function (d) {
98611 return tags[d] && Array.isArray(tags[d]);
98612 }).attr('title', function (d) {
98613 return tags[d] && Array.isArray(tags[d]) && tags[d].filter(Boolean).join('\n');
98614 }).attr('placeholder', function (d) {
98615 if (tags[d] && Array.isArray(tags[d])) {
98616 return _t('inspector.multiple_values');
98619 if (d === 'access') {
98623 if (tags.access && typeof tags.access === 'string') {
98624 return tags.access;
98627 if (tags.highway) {
98628 if (typeof tags.highway === 'string') {
98629 if (placeholdersByHighway[tags.highway] && placeholdersByHighway[tags.highway][d]) {
98630 return placeholdersByHighway[tags.highway][d];
98633 var impliedAccesses = tags.highway.filter(Boolean).map(function (highwayVal) {
98634 return placeholdersByHighway[highwayVal] && placeholdersByHighway[highwayVal][d];
98635 }).filter(Boolean);
98637 if (impliedAccesses.length === tags.highway.length && new Set(impliedAccesses).size === 1) {
98638 // if all the highway values have the same implied access for this type then use that
98639 return impliedAccesses[0];
98644 return field.placeholder();
98648 access.focus = function () {
98649 items.selectAll('.preset-input-access').node().focus();
98652 return utilRebind(access, dispatch, 'on');
98655 function uiFieldAddress(field, context) {
98656 var dispatch = dispatch$8('change');
98658 var _selection = select(null);
98660 var _wrap = select(null);
98662 var addrField = _mainPresetIndex.field('address'); // needed for placeholder strings
98664 var _entityIDs = [];
98670 var _addressFormats = [{
98671 format: [['housenumber', 'street'], ['city', 'postcode']]
98673 _mainFileFetcher.get('address_formats').then(function (d) {
98674 _addressFormats = d;
98676 if (!_selection.empty()) {
98677 _selection.call(address);
98679 })["catch"](function () {
98683 function getNearStreets() {
98684 var extent = combinedEntityExtent();
98685 var l = extent.center();
98686 var box = geoExtent(l).padByMeters(200);
98687 var streets = context.history().intersects(box).filter(isAddressable).map(function (d) {
98688 var loc = context.projection([(extent[0][0] + extent[1][0]) / 2, (extent[0][1] + extent[1][1]) / 2]);
98689 var choice = geoChooseEdge(context.graph().childNodes(d), loc, context.projection);
98691 title: d.tags.name,
98692 value: d.tags.name,
98693 dist: choice.distance
98695 }).sort(function (a, b) {
98696 return a.dist - b.dist;
98698 return utilArrayUniqBy(streets, 'value');
98700 function isAddressable(d) {
98701 return d.tags.highway && d.tags.name && d.type === 'way';
98705 function getNearCities() {
98706 var extent = combinedEntityExtent();
98707 var l = extent.center();
98708 var box = geoExtent(l).padByMeters(200);
98709 var cities = context.history().intersects(box).filter(isAddressable).map(function (d) {
98711 title: d.tags['addr:city'] || d.tags.name,
98712 value: d.tags['addr:city'] || d.tags.name,
98713 dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
98715 }).sort(function (a, b) {
98716 return a.dist - b.dist;
98718 return utilArrayUniqBy(cities, 'value');
98720 function isAddressable(d) {
98722 if (d.tags.admin_level === '8' && d.tags.boundary === 'administrative') return true;
98723 if (d.tags.border_type === 'city') return true;
98724 if (d.tags.place === 'city' || d.tags.place === 'town' || d.tags.place === 'village') return true;
98727 if (d.tags['addr:city']) return true;
98732 function getNearValues(key) {
98733 var extent = combinedEntityExtent();
98734 var l = extent.center();
98735 var box = geoExtent(l).padByMeters(200);
98736 var results = context.history().intersects(box).filter(function hasTag(d) {
98737 return _entityIDs.indexOf(d.id) === -1 && d.tags[key];
98738 }).map(function (d) {
98740 title: d.tags[key],
98741 value: d.tags[key],
98742 dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
98744 }).sort(function (a, b) {
98745 return a.dist - b.dist;
98747 return utilArrayUniqBy(results, 'value');
98750 function updateForCountryCode() {
98751 if (!_countryCode) return;
98754 for (var i = 0; i < _addressFormats.length; i++) {
98755 var format = _addressFormats[i];
98757 if (!format.countryCodes) {
98758 addressFormat = format; // choose the default format, keep going
98759 } else if (format.countryCodes.indexOf(_countryCode) !== -1) {
98760 addressFormat = format; // choose the country format, stop here
98766 var dropdowns = addressFormat.dropdowns || ['city', 'county', 'country', 'district', 'hamlet', 'neighbourhood', 'place', 'postcode', 'province', 'quarter', 'state', 'street', 'subdistrict', 'suburb'];
98767 var widths = addressFormat.widths || {
98768 housenumber: 1 / 3,
98776 // Normalize widths.
98777 var total = r.reduce(function (sum, key) {
98778 return sum + (widths[key] || 0.5);
98780 return r.map(function (key) {
98783 width: (widths[key] || 0.5) / total
98788 var rows = _wrap.selectAll('.addr-row').data(addressFormat.format, function (d) {
98789 return d.toString();
98792 rows.exit().remove();
98793 rows.enter().append('div').attr('class', 'addr-row').selectAll('input').data(row).enter().append('input').property('type', 'text').call(updatePlaceholder).attr('class', function (d) {
98794 return 'addr-' + d.id;
98795 }).call(utilNoAuto).each(addDropdown).style('width', function (d) {
98796 return d.width * 100 + '%';
98799 function addDropdown(d) {
98800 if (dropdowns.indexOf(d.id) === -1) return; // not a dropdown
98802 var nearValues = d.id === 'street' ? getNearStreets : d.id === 'city' ? getNearCities : getNearValues;
98803 select(this).call(uiCombobox(context, 'address-' + d.id).minItems(1).caseSensitive(true).fetcher(function (value, callback) {
98804 callback(nearValues('addr:' + d.id));
98808 _wrap.selectAll('input').on('blur', change()).on('change', change());
98810 _wrap.selectAll('input:not(.combobox-input)').on('input', change(true));
98812 if (_tags) updateTags(_tags);
98815 function address(selection) {
98816 _selection = selection;
98817 _wrap = selection.selectAll('.form-field-input-wrap').data([0]);
98818 _wrap = _wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(_wrap);
98819 var extent = combinedEntityExtent();
98824 if (context.inIntro()) {
98825 // localize the address format for the walkthrough
98826 countryCode = _t('intro.graph.countrycode');
98828 var center = extent.center();
98829 countryCode = iso1A2Code(center);
98833 _countryCode = countryCode.toLowerCase();
98834 updateForCountryCode();
98839 function change(onInput) {
98840 return function () {
98843 _wrap.selectAll('input').each(function (subfield) {
98844 var key = field.key + ':' + subfield.id;
98845 var value = this.value;
98846 if (!onInput) value = context.cleanTagValue(value); // don't override multiple values with blank string
98848 if (Array.isArray(_tags[key]) && !value) return;
98849 tags[key] = value || undefined;
98852 dispatch.call('change', this, tags, onInput);
98856 function updatePlaceholder(inputSelection) {
98857 return inputSelection.attr('placeholder', function (subfield) {
98858 if (_tags && Array.isArray(_tags[field.key + ':' + subfield.id])) {
98859 return _t('inspector.multiple_values');
98862 if (_countryCode) {
98863 var localkey = subfield.id + '!' + _countryCode;
98864 var tkey = addrField.hasTextForStringId('placeholders.' + localkey) ? localkey : subfield.id;
98865 return addrField.t('placeholders.' + tkey);
98870 function updateTags(tags) {
98871 utilGetSetValue(_wrap.selectAll('input'), function (subfield) {
98872 var val = tags[field.key + ':' + subfield.id];
98873 return typeof val === 'string' ? val : '';
98874 }).attr('title', function (subfield) {
98875 var val = tags[field.key + ':' + subfield.id];
98876 return val && Array.isArray(val) ? val.filter(Boolean).join('\n') : undefined;
98877 }).classed('mixed', function (subfield) {
98878 return Array.isArray(tags[field.key + ':' + subfield.id]);
98879 }).call(updatePlaceholder);
98882 function combinedEntityExtent() {
98883 return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
98886 address.entityIDs = function (val) {
98887 if (!arguments.length) return _entityIDs;
98892 address.tags = function (tags) {
98897 address.focus = function () {
98898 var node = _wrap.selectAll('input').node();
98900 if (node) node.focus();
98903 return utilRebind(address, dispatch, 'on');
98906 function uiFieldCycleway(field, context) {
98907 var dispatch = dispatch$8('change');
98908 var items = select(null);
98909 var wrap = select(null);
98913 function cycleway(selection) {
98914 function stripcolon(s) {
98915 return s.replace(':', '');
98918 wrap = selection.selectAll('.form-field-input-wrap').data([0]);
98919 wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
98920 var div = wrap.selectAll('ul').data([0]);
98921 div = div.enter().append('ul').attr('class', 'rows').merge(div);
98922 var keys = ['cycleway:left', 'cycleway:right'];
98923 items = div.selectAll('li').data(keys);
98924 var enter = items.enter().append('li').attr('class', function (d) {
98925 return 'labeled-input preset-cycleway-' + stripcolon(d);
98927 enter.append('span').attr('class', 'label preset-label-cycleway').attr('for', function (d) {
98928 return 'preset-input-cycleway-' + stripcolon(d);
98929 }).html(function (d) {
98930 return field.t.html('types.' + d);
98932 enter.append('div').attr('class', 'preset-input-cycleway-wrap').append('input').attr('type', 'text').attr('class', function (d) {
98933 return 'preset-input-cycleway preset-input-' + stripcolon(d);
98934 }).call(utilNoAuto).each(function (d) {
98935 select(this).call(uiCombobox(context, 'cycleway-' + stripcolon(d)).data(cycleway.options(d)));
98937 items = items.merge(enter); // Update
98939 wrap.selectAll('.preset-input-cycleway').on('change', change).on('blur', change);
98942 function change(d3_event, key) {
98943 var newValue = context.cleanTagValue(utilGetSetValue(select(this))); // don't override multiple values with blank string
98945 if (!newValue && (Array.isArray(_tags.cycleway) || Array.isArray(_tags[key]))) return;
98947 if (newValue === 'none' || newValue === '') {
98948 newValue = undefined;
98951 var otherKey = key === 'cycleway:left' ? 'cycleway:right' : 'cycleway:left';
98952 var otherValue = typeof _tags.cycleway === 'string' ? _tags.cycleway : _tags[otherKey];
98954 if (otherValue && Array.isArray(otherValue)) {
98955 // we must always have an explicit value for comparison
98956 otherValue = otherValue[0];
98959 if (otherValue === 'none' || otherValue === '') {
98960 otherValue = undefined;
98963 var tag = {}; // If the left and right tags match, use the cycleway tag to tag both
98964 // sides the same way
98966 if (newValue === otherValue) {
98968 cycleway: newValue,
98969 'cycleway:left': undefined,
98970 'cycleway:right': undefined
98973 // Always set both left and right as changing one can affect the other
98975 cycleway: undefined
98977 tag[key] = newValue;
98978 tag[otherKey] = otherValue;
98981 dispatch.call('change', this, tag);
98984 cycleway.options = function () {
98985 return field.options.map(function (option) {
98987 title: field.t('options.' + option + '.description'),
98993 cycleway.tags = function (tags) {
98994 _tags = tags; // If cycleway is set, use that instead of individual values
98996 var commonValue = typeof tags.cycleway === 'string' && tags.cycleway;
98997 utilGetSetValue(items.selectAll('.preset-input-cycleway'), function (d) {
98998 if (commonValue) return commonValue;
98999 return !tags.cycleway && typeof tags[d] === 'string' ? tags[d] : '';
99000 }).attr('title', function (d) {
99001 if (Array.isArray(tags.cycleway) || Array.isArray(tags[d])) {
99004 if (Array.isArray(tags.cycleway)) {
99005 vals = vals.concat(tags.cycleway);
99008 if (Array.isArray(tags[d])) {
99009 vals = vals.concat(tags[d]);
99012 return vals.filter(Boolean).join('\n');
99016 }).attr('placeholder', function (d) {
99017 if (Array.isArray(tags.cycleway) || Array.isArray(tags[d])) {
99018 return _t('inspector.multiple_values');
99021 return field.placeholder();
99022 }).classed('mixed', function (d) {
99023 return Array.isArray(tags.cycleway) || Array.isArray(tags[d]);
99027 cycleway.focus = function () {
99028 var node = wrap.selectAll('input').node();
99029 if (node) node.focus();
99032 return utilRebind(cycleway, dispatch, 'on');
99035 function uiFieldLanes(field, context) {
99036 var dispatch = dispatch$8('change');
99037 var LANE_WIDTH = 40;
99038 var LANE_HEIGHT = 200;
99039 var _entityIDs = [];
99041 function lanes(selection) {
99042 var lanesData = context.entity(_entityIDs[0]).lanes();
99044 if (!context.container().select('.inspector-wrap.inspector-hidden').empty() || !selection.node().parentNode) {
99045 selection.call(lanes.off);
99049 var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
99050 wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
99051 var surface = wrap.selectAll('.surface').data([0]);
99052 var d = utilGetDimensions(wrap);
99053 var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
99054 surface = surface.enter().append('svg').attr('width', d[0]).attr('height', 300).attr('class', 'surface').merge(surface);
99055 var lanesSelection = surface.selectAll('.lanes').data([0]);
99056 lanesSelection = lanesSelection.enter().append('g').attr('class', 'lanes').merge(lanesSelection);
99057 lanesSelection.attr('transform', function () {
99058 return 'translate(' + freeSpace / 2 + ', 0)';
99060 var lane = lanesSelection.selectAll('.lane').data(lanesData.lanes);
99061 lane.exit().remove();
99062 var enter = lane.enter().append('g').attr('class', 'lane');
99063 enter.append('g').append('rect').attr('y', 50).attr('width', LANE_WIDTH).attr('height', LANE_HEIGHT);
99064 enter.append('g').attr('class', 'forward').append('text').attr('y', 40).attr('x', 14).text('▲');
99065 enter.append('g').attr('class', 'bothways').append('text').attr('y', 40).attr('x', 14).text('▲▼');
99066 enter.append('g').attr('class', 'backward').append('text').attr('y', 40).attr('x', 14).text('▼');
99067 lane = lane.merge(enter);
99068 lane.attr('transform', function (d) {
99069 return 'translate(' + LANE_WIDTH * d.index * 1.5 + ', 0)';
99071 lane.select('.forward').style('visibility', function (d) {
99072 return d.direction === 'forward' ? 'visible' : 'hidden';
99074 lane.select('.bothways').style('visibility', function (d) {
99075 return d.direction === 'bothways' ? 'visible' : 'hidden';
99077 lane.select('.backward').style('visibility', function (d) {
99078 return d.direction === 'backward' ? 'visible' : 'hidden';
99082 lanes.entityIDs = function (val) {
99086 lanes.tags = function () {};
99088 lanes.focus = function () {};
99090 lanes.off = function () {};
99092 return utilRebind(lanes, dispatch, 'on');
99094 uiFieldLanes.supportsMultiselection = false;
99096 var _languagesArray = [];
99097 function uiFieldLocalized(field, context) {
99098 var dispatch = dispatch$8('change', 'input');
99099 var wikipedia = services.wikipedia;
99100 var input = select(null);
99101 var localizedInputs = select(null);
99105 var _tags; // A concern here in switching to async data means that _languagesArray will not
99106 // be available the first time through, so things like the fetchers and
99107 // the language() function will not work immediately.
99110 _mainFileFetcher.get('languages').then(loadLanguagesArray)["catch"](function () {
99113 var _territoryLanguages = {};
99114 _mainFileFetcher.get('territory_languages').then(function (d) {
99115 _territoryLanguages = d;
99116 })["catch"](function () {
99118 }); // reuse these combos
99120 var langCombo = uiCombobox(context, 'localized-lang').fetcher(fetchLanguages).minItems(0);
99122 var _selection = select(null);
99124 var _multilingual = [];
99126 var _buttonTip = uiTooltip().title(_t.html('translate.translate')).placement('left');
99130 var _entityIDs = [];
99132 function loadLanguagesArray(dataLanguages) {
99133 if (_languagesArray.length !== 0) return; // some conversion is needed to ensure correct OSM tags are used
99135 var replacements = {
99137 // in OSM, `sr` implies Cyrillic
99138 'sr-Cyrl': false // `sr-Cyrl` isn't used in OSM
99142 for (var code in dataLanguages) {
99143 if (replacements[code] === false) continue;
99144 var metaCode = code;
99145 if (replacements[code]) metaCode = replacements[code];
99147 _languagesArray.push({
99148 localName: _mainLocalizer.languageName(metaCode, {
99151 nativeName: dataLanguages[metaCode].nativeName,
99153 label: _mainLocalizer.languageName(metaCode)
99158 function calcLocked() {
99159 // Protect name field for suggestion presets that don't display a brand/operator field
99160 var isLocked = field.id === 'name' && _entityIDs.length && _entityIDs.some(function (entityID) {
99161 var entity = context.graph().hasEntity(entityID);
99162 if (!entity) return false; // Features linked to Wikidata are likely important and should be protected
99164 if (entity.tags.wikidata) return true; // Assume the name has already been confirmed if its source has been researched
99166 if (entity.tags['name:etymology:wikidata']) return true; // Lock the `name` if this is a suggestion preset that assigns the name,
99167 // and the preset does not display a `brand` or `operator` field.
99168 // (For presets like hotels, car dealerships, post offices, the `name` should remain editable)
99169 // see also similar logic in `outdated_tags.js`
99171 var preset = _mainPresetIndex.match(entity, context.graph());
99174 var isSuggestion = preset.suggestion;
99175 var fields = preset.fields();
99176 var showsBrandField = fields.some(function (d) {
99177 return d.id === 'brand';
99179 var showsOperatorField = fields.some(function (d) {
99180 return d.id === 'operator';
99182 var setsName = preset.addTags.name;
99183 var setsBrandWikidata = preset.addTags['brand:wikidata'];
99184 var setsOperatorWikidata = preset.addTags['operator:wikidata'];
99185 return isSuggestion && setsName && (setsBrandWikidata && !showsBrandField || setsOperatorWikidata && !showsOperatorField);
99191 field.locked(isLocked);
99192 } // update _multilingual, maintaining the existing order
99195 function calcMultilingual(tags) {
99196 var existingLangsOrdered = _multilingual.map(function (item) {
99200 var existingLangs = new Set(existingLangsOrdered.filter(Boolean));
99202 for (var k in tags) {
99203 var m = k.match(/^(.*):(.*)$/);
99205 if (m && m[1] === field.key && m[2]) {
99211 if (existingLangs.has(item.lang)) {
99212 // update the value
99213 _multilingual[existingLangsOrdered.indexOf(item.lang)].value = item.value;
99214 existingLangs["delete"](item.lang);
99216 _multilingual.push(item);
99219 } // Don't remove items based on deleted tags, since this makes the UI
99220 // disappear unexpectedly when clearing values - #8164
99223 _multilingual.forEach(function (item) {
99224 if (item.lang && existingLangs.has(item.lang)) {
99230 function localized(selection) {
99231 _selection = selection;
99233 var isLocked = field.locked();
99234 var wrap = selection.selectAll('.form-field-input-wrap').data([0]); // enter/update
99236 wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
99237 input = wrap.selectAll('.localized-main').data([0]); // enter/update
99239 input = input.enter().append('input').attr('type', 'text').attr('id', field.domId).attr('class', 'localized-main').call(utilNoAuto).merge(input);
99240 input.classed('disabled', !!isLocked).attr('readonly', isLocked || null).on('input', change(true)).on('blur', change()).on('change', change());
99241 var translateButton = wrap.selectAll('.localized-add').data([0]);
99242 translateButton = translateButton.enter().append('button').attr('class', 'localized-add form-field-button').attr('aria-label', _t('icons.plus')).call(svgIcon('#iD-icon-plus')).merge(translateButton);
99243 translateButton.classed('disabled', !!isLocked).call(isLocked ? _buttonTip.destroy : _buttonTip).on('click', addNew);
99245 if (_tags && !_multilingual.length) {
99246 calcMultilingual(_tags);
99249 localizedInputs = selection.selectAll('.localized-multilingual').data([0]);
99250 localizedInputs = localizedInputs.enter().append('div').attr('class', 'localized-multilingual').merge(localizedInputs);
99251 localizedInputs.call(renderMultilingual);
99252 localizedInputs.selectAll('button, input').classed('disabled', !!isLocked).attr('readonly', isLocked || null);
99253 selection.selectAll('.combobox-caret').classed('nope', true);
99255 function addNew(d3_event) {
99256 d3_event.preventDefault();
99257 if (field.locked()) return;
99258 var defaultLang = _mainLocalizer.languageCode().toLowerCase();
99260 var langExists = _multilingual.find(function (datum) {
99261 return datum.lang === defaultLang;
99264 var isLangEn = defaultLang.indexOf('en') > -1;
99266 if (isLangEn || langExists) {
99268 langExists = _multilingual.find(function (datum) {
99269 return datum.lang === defaultLang;
99274 // prepend the value so it appears at the top
99275 _multilingual.unshift({
99280 localizedInputs.call(renderMultilingual);
99284 function change(onInput) {
99285 return function (d3_event) {
99286 if (field.locked()) {
99287 d3_event.preventDefault();
99291 var val = utilGetSetValue(select(this));
99292 if (!onInput) val = context.cleanTagValue(val); // don't override multiple values with blank string
99294 if (!val && Array.isArray(_tags[field.key])) return;
99296 t[field.key] = val || undefined;
99297 dispatch.call('change', this, t, onInput);
99302 function key(lang) {
99303 return field.key + ':' + lang;
99306 function changeLang(d3_event, d) {
99307 var tags = {}; // make sure unrecognized suffixes are lowercase - #7156
99309 var lang = utilGetSetValue(select(this)).toLowerCase();
99311 var language = _languagesArray.find(function (d) {
99312 return d.label.toLowerCase() === lang || d.localName && d.localName.toLowerCase() === lang || d.nativeName && d.nativeName.toLowerCase() === lang;
99315 if (language) lang = language.code;
99317 if (d.lang && d.lang !== lang) {
99318 tags[key(d.lang)] = undefined;
99321 var newKey = lang && context.cleanTagKey(key(lang));
99322 var value = utilGetSetValue(select(this.parentNode).selectAll('.localized-value'));
99324 if (newKey && value) {
99325 tags[newKey] = value;
99326 } else if (newKey && _wikiTitles && _wikiTitles[d.lang]) {
99327 tags[newKey] = _wikiTitles[d.lang];
99331 dispatch.call('change', this, tags);
99334 function changeValue(d3_event, d) {
99335 if (!d.lang) return;
99336 var value = context.cleanTagValue(utilGetSetValue(select(this))) || undefined; // don't override multiple values with blank string
99338 if (!value && Array.isArray(d.value)) return;
99340 t[key(d.lang)] = value;
99342 dispatch.call('change', this, t);
99345 function fetchLanguages(value, cb) {
99346 var v = value.toLowerCase(); // show the user's language first
99348 var langCodes = [_mainLocalizer.localeCode(), _mainLocalizer.languageCode()];
99350 if (_countryCode && _territoryLanguages[_countryCode]) {
99351 langCodes = langCodes.concat(_territoryLanguages[_countryCode]);
99354 var langItems = [];
99355 langCodes.forEach(function (code) {
99356 var langItem = _languagesArray.find(function (item) {
99357 return item.code === code;
99360 if (langItem) langItems.push(langItem);
99362 langItems = utilArrayUniq(langItems.concat(_languagesArray));
99363 cb(langItems.filter(function (d) {
99364 return d.label.toLowerCase().indexOf(v) >= 0 || d.localName && d.localName.toLowerCase().indexOf(v) >= 0 || d.nativeName && d.nativeName.toLowerCase().indexOf(v) >= 0 || d.code.toLowerCase().indexOf(v) >= 0;
99365 }).map(function (d) {
99372 function renderMultilingual(selection) {
99373 var entries = selection.selectAll('div.entry').data(_multilingual, function (d) {
99376 entries.exit().style('top', '0').style('max-height', '240px').transition().duration(200).style('opacity', '0').style('max-height', '0px').remove();
99377 var entriesEnter = entries.enter().append('div').attr('class', 'entry').each(function (_, index) {
99378 var wrap = select(this);
99379 var domId = utilUniqueDomId(index);
99380 var label = wrap.append('label').attr('class', 'field-label').attr('for', domId);
99381 var text = label.append('span').attr('class', 'label-text');
99382 text.append('span').attr('class', 'label-textvalue').call(_t.append('translate.localized_translation_label'));
99383 text.append('span').attr('class', 'label-textannotation');
99384 label.append('button').attr('class', 'remove-icon-multilingual').attr('title', _t('icons.remove')).on('click', function (d3_event, d) {
99385 if (field.locked()) return;
99386 d3_event.preventDefault(); // remove the UI item manually
99388 _multilingual.splice(_multilingual.indexOf(d), 1);
99390 var langKey = d.lang && key(d.lang);
99392 if (langKey && langKey in _tags) {
99393 delete _tags[langKey]; // remove from entity tags
99396 t[langKey] = undefined;
99397 dispatch.call('change', this, t);
99401 renderMultilingual(selection);
99402 }).call(svgIcon('#iD-operation-delete'));
99403 wrap.append('input').attr('class', 'localized-lang').attr('id', domId).attr('type', 'text').attr('placeholder', _t('translate.localized_translation_language')).on('blur', changeLang).on('change', changeLang).call(langCombo);
99404 wrap.append('input').attr('type', 'text').attr('class', 'localized-value').on('blur', changeValue).on('change', changeValue);
99406 entriesEnter.style('margin-top', '0px').style('max-height', '0px').style('opacity', '0').transition().duration(200).style('margin-top', '10px').style('max-height', '240px').style('opacity', '1').on('end', function () {
99407 select(this).style('max-height', '').style('overflow', 'visible');
99409 entries = entries.merge(entriesEnter);
99410 entries.order(); // allow removing the entry UIs even if there isn't a tag to remove
99412 entries.classed('present', true);
99413 utilGetSetValue(entries.select('.localized-lang'), function (d) {
99414 var langItem = _languagesArray.find(function (item) {
99415 return item.code === d.lang;
99418 if (langItem) return langItem.label;
99421 utilGetSetValue(entries.select('.localized-value'), function (d) {
99422 return typeof d.value === 'string' ? d.value : '';
99423 }).attr('title', function (d) {
99424 return Array.isArray(d.value) ? d.value.filter(Boolean).join('\n') : null;
99425 }).attr('placeholder', function (d) {
99426 return Array.isArray(d.value) ? _t('inspector.multiple_values') : _t('translate.localized_translation_name');
99427 }).classed('mixed', function (d) {
99428 return Array.isArray(d.value);
99432 localized.tags = function (tags) {
99433 _tags = tags; // Fetch translations from wikipedia
99435 if (typeof tags.wikipedia === 'string' && !_wikiTitles) {
99437 var wm = tags.wikipedia.match(/([^:]+):(.+)/);
99439 if (wm && wm[0] && wm[1]) {
99440 wikipedia.translations(wm[1], wm[2], function (err, d) {
99441 if (err || !d) return;
99447 var isMixed = Array.isArray(tags[field.key]);
99448 utilGetSetValue(input, typeof tags[field.key] === 'string' ? tags[field.key] : '').attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : undefined).attr('placeholder', isMixed ? _t('inspector.multiple_values') : field.placeholder()).classed('mixed', isMixed);
99449 calcMultilingual(tags);
99451 _selection.call(localized);
99454 localized.focus = function () {
99455 input.node().focus();
99458 localized.entityIDs = function (val) {
99459 if (!arguments.length) return _entityIDs;
99461 _multilingual = [];
99466 function loadCountryCode() {
99467 var extent = combinedEntityExtent();
99468 var countryCode = extent && iso1A2Code(extent.center());
99469 _countryCode = countryCode && countryCode.toLowerCase();
99472 function combinedEntityExtent() {
99473 return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
99476 return utilRebind(localized, dispatch, 'on');
99479 function uiFieldRoadheight(field, context) {
99480 var dispatch = dispatch$8('change');
99481 var primaryUnitInput = select(null);
99482 var primaryInput = select(null);
99483 var secondaryInput = select(null);
99484 var secondaryUnitInput = select(null);
99485 var _entityIDs = [];
99491 var primaryUnits = [{
99493 title: _t('inspector.roadheight.meter')
99496 title: _t('inspector.roadheight.foot')
99498 var unitCombo = uiCombobox(context, 'roadheight-unit').data(primaryUnits);
99500 function roadheight(selection) {
99501 var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
99502 wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
99503 primaryInput = wrap.selectAll('input.roadheight-number').data([0]);
99504 primaryInput = primaryInput.enter().append('input').attr('type', 'text').attr('class', 'roadheight-number').attr('id', field.domId).call(utilNoAuto).merge(primaryInput);
99505 primaryInput.on('change', change).on('blur', change);
99506 var loc = combinedEntityExtent().center();
99507 _isImperial = roadHeightUnit(loc) === 'ft';
99508 primaryUnitInput = wrap.selectAll('input.roadheight-unit').data([0]);
99509 primaryUnitInput = primaryUnitInput.enter().append('input').attr('type', 'text').attr('class', 'roadheight-unit').call(unitCombo).merge(primaryUnitInput);
99510 primaryUnitInput.on('blur', changeUnits).on('change', changeUnits);
99511 secondaryInput = wrap.selectAll('input.roadheight-secondary-number').data([0]);
99512 secondaryInput = secondaryInput.enter().append('input').attr('type', 'text').attr('class', 'roadheight-secondary-number').call(utilNoAuto).merge(secondaryInput);
99513 secondaryInput.on('change', change).on('blur', change);
99514 secondaryUnitInput = wrap.selectAll('input.roadheight-secondary-unit').data([0]);
99515 secondaryUnitInput = secondaryUnitInput.enter().append('input').attr('type', 'text').call(utilNoAuto).classed('disabled', true).classed('roadheight-secondary-unit', true).attr('readonly', 'readonly').merge(secondaryUnitInput);
99517 function changeUnits() {
99518 _isImperial = utilGetSetValue(primaryUnitInput) === 'ft';
99519 utilGetSetValue(primaryUnitInput, _isImperial ? 'ft' : 'm');
99520 setUnitSuggestions();
99525 function setUnitSuggestions() {
99526 utilGetSetValue(primaryUnitInput, _isImperial ? 'ft' : 'm');
99529 function change() {
99531 var primaryValue = utilGetSetValue(primaryInput).trim();
99532 var secondaryValue = utilGetSetValue(secondaryInput).trim(); // don't override multiple values with blank string
99534 if (!primaryValue && !secondaryValue && Array.isArray(_tags[field.key])) return;
99536 if (!primaryValue && !secondaryValue) {
99537 tag[field.key] = undefined;
99538 } else if (isNaN(primaryValue) || isNaN(secondaryValue) || !_isImperial) {
99539 tag[field.key] = context.cleanTagValue(primaryValue);
99541 if (primaryValue !== '') {
99542 primaryValue = context.cleanTagValue(primaryValue + '\'');
99545 if (secondaryValue !== '') {
99546 secondaryValue = context.cleanTagValue(secondaryValue + '"');
99549 tag[field.key] = primaryValue + secondaryValue;
99552 dispatch.call('change', this, tag);
99555 roadheight.tags = function (tags) {
99557 var primaryValue = tags[field.key];
99558 var secondaryValue;
99559 var isMixed = Array.isArray(primaryValue);
99562 if (primaryValue && (primaryValue.indexOf('\'') >= 0 || primaryValue.indexOf('"') >= 0)) {
99563 secondaryValue = primaryValue.match(/(-?[\d.]+)"/);
99565 if (secondaryValue !== null) {
99566 secondaryValue = secondaryValue[1];
99569 primaryValue = primaryValue.match(/(-?[\d.]+)'/);
99571 if (primaryValue !== null) {
99572 primaryValue = primaryValue[1];
99575 _isImperial = true;
99576 } else if (primaryValue) {
99577 _isImperial = false;
99581 setUnitSuggestions();
99582 utilGetSetValue(primaryInput, typeof primaryValue === 'string' ? primaryValue : '').attr('title', isMixed ? primaryValue.filter(Boolean).join('\n') : null).attr('placeholder', isMixed ? _t('inspector.multiple_values') : _t('inspector.unknown')).classed('mixed', isMixed);
99583 utilGetSetValue(secondaryInput, typeof secondaryValue === 'string' ? secondaryValue : '').attr('placeholder', isMixed ? _t('inspector.multiple_values') : _isImperial ? '0' : null).classed('mixed', isMixed).classed('disabled', !_isImperial).attr('readonly', _isImperial ? null : 'readonly');
99584 secondaryUnitInput.attr('value', _isImperial ? _t('inspector.roadheight.inch') : null);
99587 roadheight.focus = function () {
99588 primaryInput.node().focus();
99591 roadheight.entityIDs = function (val) {
99595 function combinedEntityExtent() {
99596 return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
99599 return utilRebind(roadheight, dispatch, 'on');
99602 function uiFieldRoadspeed(field, context) {
99603 var dispatch = dispatch$8('change');
99604 var unitInput = select(null);
99605 var input = select(null);
99606 var _entityIDs = [];
99612 var speedCombo = uiCombobox(context, 'roadspeed');
99613 var unitCombo = uiCombobox(context, 'roadspeed-unit').data(['km/h', 'mph'].map(comboValues));
99614 var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120];
99615 var imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
99617 function roadspeed(selection) {
99618 var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
99619 wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
99620 input = wrap.selectAll('input.roadspeed-number').data([0]);
99621 input = input.enter().append('input').attr('type', 'text').attr('class', 'roadspeed-number').attr('id', field.domId).call(utilNoAuto).call(speedCombo).merge(input);
99622 input.on('change', change).on('blur', change);
99623 var loc = combinedEntityExtent().center();
99624 _isImperial = roadSpeedUnit(loc) === 'mph';
99625 unitInput = wrap.selectAll('input.roadspeed-unit').data([0]);
99626 unitInput = unitInput.enter().append('input').attr('type', 'text').attr('class', 'roadspeed-unit').attr('aria-label', _t('inspector.speed_unit')).call(unitCombo).merge(unitInput);
99627 unitInput.on('blur', changeUnits).on('change', changeUnits);
99629 function changeUnits() {
99630 _isImperial = utilGetSetValue(unitInput) === 'mph';
99631 utilGetSetValue(unitInput, _isImperial ? 'mph' : 'km/h');
99632 setUnitSuggestions();
99637 function setUnitSuggestions() {
99638 speedCombo.data((_isImperial ? imperialValues : metricValues).map(comboValues));
99639 utilGetSetValue(unitInput, _isImperial ? 'mph' : 'km/h');
99642 function comboValues(d) {
99644 value: d.toString(),
99645 title: d.toString()
99649 function change() {
99651 var value = utilGetSetValue(input).trim(); // don't override multiple values with blank string
99653 if (!value && Array.isArray(_tags[field.key])) return;
99656 tag[field.key] = undefined;
99657 } else if (isNaN(value) || !_isImperial) {
99658 tag[field.key] = context.cleanTagValue(value);
99660 tag[field.key] = context.cleanTagValue(value + ' mph');
99663 dispatch.call('change', this, tag);
99666 roadspeed.tags = function (tags) {
99668 var value = tags[field.key];
99669 var isMixed = Array.isArray(value);
99672 if (value && value.indexOf('mph') >= 0) {
99673 value = parseInt(value, 10).toString();
99674 _isImperial = true;
99675 } else if (value) {
99676 _isImperial = false;
99680 setUnitSuggestions();
99681 utilGetSetValue(input, typeof value === 'string' ? value : '').attr('title', isMixed ? value.filter(Boolean).join('\n') : null).attr('placeholder', isMixed ? _t('inspector.multiple_values') : field.placeholder()).classed('mixed', isMixed);
99684 roadspeed.focus = function () {
99685 input.node().focus();
99688 roadspeed.entityIDs = function (val) {
99692 function combinedEntityExtent() {
99693 return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
99696 return utilRebind(roadspeed, dispatch, 'on');
99699 function uiFieldRadio(field, context) {
99700 var dispatch = dispatch$8('change');
99701 var placeholder = select(null);
99702 var wrap = select(null);
99703 var labels = select(null);
99704 var radios = select(null);
99705 var radioData = (field.options || field.keys).slice(); // shallow copy
99710 var _entityIDs = [];
99712 function selectedKey() {
99713 var node = wrap.selectAll('.form-field-input-radio label.active input');
99714 return !node.empty() && node.datum();
99717 function radio(selection) {
99718 selection.classed('preset-radio', true);
99719 wrap = selection.selectAll('.form-field-input-wrap').data([0]);
99720 var enter = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-radio');
99721 enter.append('span').attr('class', 'placeholder');
99722 wrap = wrap.merge(enter);
99723 placeholder = wrap.selectAll('.placeholder');
99724 labels = wrap.selectAll('label').data(radioData);
99725 enter = labels.enter().append('label');
99726 enter.append('input').attr('type', 'radio').attr('name', field.id).attr('value', function (d) {
99727 return field.t('options.' + d, {
99730 }).attr('checked', false);
99731 enter.append('span').html(function (d) {
99732 return field.t.html('options.' + d, {
99736 labels = labels.merge(enter);
99737 radios = labels.selectAll('input').on('change', changeRadio);
99740 function structureExtras(selection, tags) {
99741 var selected = selectedKey() || tags.layer !== undefined;
99742 var type = _mainPresetIndex.field(selected);
99743 var layer = _mainPresetIndex.field('layer');
99744 var showLayer = selected === 'bridge' || selected === 'tunnel' || tags.layer !== undefined;
99745 var extrasWrap = selection.selectAll('.structure-extras-wrap').data(selected ? [0] : []);
99746 extrasWrap.exit().remove();
99747 extrasWrap = extrasWrap.enter().append('div').attr('class', 'structure-extras-wrap').merge(extrasWrap);
99748 var list = extrasWrap.selectAll('ul').data([0]);
99749 list = list.enter().append('ul').attr('class', 'rows').merge(list); // Type
99752 if (!typeField || typeField.id !== selected) {
99753 typeField = uiField(context, type, _entityIDs, {
99755 }).on('change', changeType);
99758 typeField.tags(tags);
99763 var typeItem = list.selectAll('.structure-type-item').data(typeField ? [typeField] : [], function (d) {
99767 typeItem.exit().remove(); // Enter
99769 var typeEnter = typeItem.enter().insert('li', ':first-child').attr('class', 'labeled-input structure-type-item');
99770 typeEnter.append('span').attr('class', 'label structure-label-type').attr('for', 'preset-input-' + selected).call(_t.append('inspector.radio.structure.type'));
99771 typeEnter.append('div').attr('class', 'structure-input-type-wrap'); // Update
99773 typeItem = typeItem.merge(typeEnter);
99776 typeItem.selectAll('.structure-input-type-wrap').call(typeField.render);
99780 if (layer && showLayer) {
99782 layerField = uiField(context, layer, _entityIDs, {
99784 }).on('change', changeLayer);
99787 layerField.tags(tags);
99788 field.keys = utilArrayUnion(field.keys, ['layer']);
99791 field.keys = field.keys.filter(function (k) {
99792 return k !== 'layer';
99796 var layerItem = list.selectAll('.structure-layer-item').data(layerField ? [layerField] : []); // Exit
99798 layerItem.exit().remove(); // Enter
99800 var layerEnter = layerItem.enter().append('li').attr('class', 'labeled-input structure-layer-item');
99801 layerEnter.append('span').attr('class', 'label structure-label-layer').attr('for', 'preset-input-layer').call(_t.append('inspector.radio.structure.layer'));
99802 layerEnter.append('div').attr('class', 'structure-input-layer-wrap'); // Update
99804 layerItem = layerItem.merge(layerEnter);
99807 layerItem.selectAll('.structure-input-layer-wrap').call(layerField.render);
99811 function changeType(t, onInput) {
99812 var key = selectedKey();
99816 if (val !== 'no') {
99817 _oldType[key] = val;
99820 if (field.type === 'structureRadio') {
99821 // remove layer if it should not be set
99822 if (val === 'no' || key !== 'bridge' && key !== 'tunnel' || key === 'tunnel' && val === 'building_passage') {
99823 t.layer = undefined;
99824 } // add layer if it should be set
99827 if (t.layer === undefined) {
99828 if (key === 'bridge' && val !== 'no') {
99832 if (key === 'tunnel' && val !== 'no' && val !== 'building_passage') {
99838 dispatch.call('change', this, t, onInput);
99841 function changeLayer(t, onInput) {
99842 if (t.layer === '0') {
99843 t.layer = undefined;
99846 dispatch.call('change', this, t, onInput);
99849 function changeRadio() {
99854 t[field.key] = undefined;
99857 radios.each(function (d) {
99858 var active = select(this).property('checked');
99859 if (active) activeKey = d;
99862 if (active) t[field.key] = d;
99864 var val = _oldType[activeKey] || 'yes';
99865 t[d] = active ? val : undefined;
99869 if (field.type === 'structureRadio') {
99870 if (activeKey === 'bridge') {
99872 } else if (activeKey === 'tunnel' && t.tunnel !== 'building_passage') {
99875 t.layer = undefined;
99879 dispatch.call('change', this, t);
99882 radio.tags = function (tags) {
99883 function isOptionChecked(d) {
99885 return tags[field.key] === d;
99888 return !!(typeof tags[d] === 'string' && tags[d].toLowerCase() !== 'no');
99891 function isMixed(d) {
99893 return Array.isArray(tags[field.key]) && tags[field.key].includes(d);
99896 return Array.isArray(tags[d]);
99899 radios.property('checked', function (d) {
99900 return isOptionChecked(d) && (field.key || field.options.filter(isOptionChecked).length === 1);
99902 labels.classed('active', function (d) {
99904 return Array.isArray(tags[field.key]) && tags[field.key].includes(d) || tags[field.key] === d;
99907 return Array.isArray(tags[d]) && tags[d].some(function (v) {
99908 return typeof v === 'string' && v.toLowerCase() !== 'no';
99909 }) || !!(typeof tags[d] === 'string' && tags[d].toLowerCase() !== 'no');
99910 }).classed('mixed', isMixed).attr('title', function (d) {
99911 return isMixed(d) ? _t('inspector.unshared_value_tooltip') : null;
99913 var selection = radios.filter(function () {
99914 return this.checked;
99917 if (selection.empty()) {
99918 placeholder.call(_t.append('inspector.none'));
99920 placeholder.text(selection.attr('value'));
99921 _oldType[selection.datum()] = tags[selection.datum()];
99924 if (field.type === 'structureRadio') {
99925 // For waterways without a tunnel tag, set 'culvert' as
99926 // the _oldType to default to if the user picks 'tunnel'
99927 if (!!tags.waterway && !_oldType.tunnel) {
99928 _oldType.tunnel = 'culvert';
99931 wrap.call(structureExtras, tags);
99935 radio.focus = function () {
99936 radios.node().focus();
99939 radio.entityIDs = function (val) {
99940 if (!arguments.length) return _entityIDs;
99946 radio.isAllowed = function () {
99947 return _entityIDs.length === 1;
99950 return utilRebind(radio, dispatch, 'on');
99953 function uiFieldRestrictions(field, context) {
99954 var dispatch = dispatch$8('change');
99955 var breathe = behaviorBreathe();
99956 corePreferences('turn-restriction-via-way', null); // remove old key
99958 var storedViaWay = corePreferences('turn-restriction-via-way0'); // use new key #6922
99960 var storedDistance = corePreferences('turn-restriction-distance');
99962 var _maxViaWay = storedViaWay !== null ? +storedViaWay : 0;
99964 var _maxDistance = storedDistance ? +storedDistance : 30;
99966 var _initialized = false;
99968 var _parent = select(null); // the entire field
99971 var _container = select(null); // just the map
99986 function restrictions(selection) {
99987 _parent = selection; // try to reuse the intersection, but always rebuild it if the graph has changed
99989 if (_vertexID && (context.graph() !== _graph || !_intersection)) {
99990 _graph = context.graph();
99991 _intersection = osmIntersection(_graph, _vertexID, _maxDistance);
99992 } // It's possible for there to be no actual intersection here.
99993 // for example, a vertex of two `highway=path`
99994 // In this case, hide the field.
99997 var isOK = _intersection && _intersection.vertices.length && // has vertices
99998 _intersection.vertices // has the vertex that the user selected
99999 .filter(function (vertex) {
100000 return vertex.id === _vertexID;
100001 }).length && _intersection.ways.length > 2 && // has more than 2 ways
100002 _intersection.ways // has more than 1 TO way
100003 .filter(function (way) {
100005 }).length > 1; // Also hide in the case where
100007 select(selection.node().parentNode).classed('hide', !isOK); // if form field is hidden or has detached from dom, clean up.
100009 if (!isOK || !context.container().select('.inspector-wrap.inspector-hidden').empty() || !selection.node().parentNode || !selection.node().parentNode.parentNode) {
100010 selection.call(restrictions.off);
100014 var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
100015 wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
100016 var container = wrap.selectAll('.restriction-container').data([0]); // enter
100018 var containerEnter = container.enter().append('div').attr('class', 'restriction-container');
100019 containerEnter.append('div').attr('class', 'restriction-help'); // update
100021 _container = containerEnter.merge(container).call(renderViewer);
100022 var controls = wrap.selectAll('.restriction-controls').data([0]); // enter/update
100024 controls.enter().append('div').attr('class', 'restriction-controls-container').append('div').attr('class', 'restriction-controls').merge(controls).call(renderControls);
100027 function renderControls(selection) {
100028 var distControl = selection.selectAll('.restriction-distance').data([0]);
100029 distControl.exit().remove();
100030 var distControlEnter = distControl.enter().append('div').attr('class', 'restriction-control restriction-distance');
100031 distControlEnter.append('span').attr('class', 'restriction-control-label restriction-distance-label').call(_t.append('restriction.controls.distance', {
100034 distControlEnter.append('input').attr('class', 'restriction-distance-input').attr('type', 'range').attr('min', '20').attr('max', '50').attr('step', '5');
100035 distControlEnter.append('span').attr('class', 'restriction-distance-text'); // update
100037 selection.selectAll('.restriction-distance-input').property('value', _maxDistance).on('input', function () {
100038 var val = select(this).property('value');
100042 _container.selectAll('.layer-osm .layer-turns *').remove();
100044 corePreferences('turn-restriction-distance', _maxDistance);
100046 _parent.call(restrictions);
100048 selection.selectAll('.restriction-distance-text').call(displayMaxDistance(_maxDistance));
100049 var viaControl = selection.selectAll('.restriction-via-way').data([0]);
100050 viaControl.exit().remove();
100051 var viaControlEnter = viaControl.enter().append('div').attr('class', 'restriction-control restriction-via-way');
100052 viaControlEnter.append('span').attr('class', 'restriction-control-label restriction-via-way-label').call(_t.append('restriction.controls.via', {
100055 viaControlEnter.append('input').attr('class', 'restriction-via-way-input').attr('type', 'range').attr('min', '0').attr('max', '2').attr('step', '1');
100056 viaControlEnter.append('span').attr('class', 'restriction-via-way-text'); // update
100058 selection.selectAll('.restriction-via-way-input').property('value', _maxViaWay).on('input', function () {
100059 var val = select(this).property('value');
100062 _container.selectAll('.layer-osm .layer-turns *').remove();
100064 corePreferences('turn-restriction-via-way0', _maxViaWay);
100066 _parent.call(restrictions);
100068 selection.selectAll('.restriction-via-way-text').call(displayMaxVia(_maxViaWay));
100071 function renderViewer(selection) {
100072 if (!_intersection) return;
100073 var vgraph = _intersection.graph;
100074 var filter = utilFunctor(true);
100075 var projection = geoRawMercator(); // Reflow warning: `utilGetDimensions` calls `getBoundingClientRect`
100076 // Instead of asking the restriction-container for its dimensions,
100077 // we can ask the .sidebar, which can have its dimensions cached.
100078 // width: calc as sidebar - padding
100079 // height: hardcoded (from `80_app.css`)
100080 // var d = utilGetDimensions(selection);
100082 var sdims = utilGetDimensions(context.container().select('.sidebar'));
100083 var d = [sdims[0] - 50, 370];
100084 var c = geoVecScale(d, 0.5);
100086 projection.scale(geoZoomToScale(z)); // Calculate extent of all key vertices
100088 var extent = geoExtent();
100090 for (var i = 0; i < _intersection.vertices.length; i++) {
100091 extent._extend(_intersection.vertices[i].extent());
100094 var padTop = 35; // reserve top space for hint text
100095 // If this is a large intersection, adjust zoom to fit extent
100097 if (_intersection.vertices.length > 1) {
100098 var hPadding = Math.min(160, Math.max(110, d[0] * 0.4));
100100 var tl = projection([extent[0][0], extent[1][1]]);
100101 var br = projection([extent[1][0], extent[0][1]]);
100102 var hFactor = (br[0] - tl[0]) / (d[0] - hPadding);
100103 var vFactor = (br[1] - tl[1]) / (d[1] - vPadding - padTop);
100104 var hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2;
100105 var vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2;
100106 z = z - Math.max(hZoomDiff, vZoomDiff);
100107 projection.scale(geoZoomToScale(z));
100110 var extentCenter = projection(extent.center());
100111 extentCenter[1] = extentCenter[1] - padTop / 2;
100112 projection.translate(geoVecSubtract(c, extentCenter)).clipExtent([[0, 0], d]);
100113 var drawLayers = svgLayers(projection, context).only(['osm', 'touch']).dimensions(d);
100114 var drawVertices = svgVertices(projection, context);
100115 var drawLines = svgLines(projection, context);
100116 var drawTurns = svgTurns(projection, context);
100117 var firstTime = selection.selectAll('.surface').empty();
100118 selection.call(drawLayers);
100119 var surface = selection.selectAll('.surface').classed('tr', true);
100124 } // This can happen if we've lowered the detail while a FROM way
100125 // is selected, and that way is no longer part of the intersection.
100128 if (_fromWayID && !vgraph.hasEntity(_fromWayID)) {
100133 surface.call(utilSetDimensions, d).call(drawVertices, vgraph, _intersection.vertices, filter, extent, z).call(drawLines, vgraph, _intersection.ways, filter).call(drawTurns, vgraph, _intersection.turns(_fromWayID, _maxViaWay));
100134 surface.on('click.restrictions', click).on('mouseover.restrictions', mouseover);
100135 surface.selectAll('.selected').classed('selected', false);
100136 surface.selectAll('.related').classed('related', false);
100140 way = vgraph.entity(_fromWayID);
100141 surface.selectAll('.' + _fromWayID).classed('selected', true).classed('related', true);
100144 document.addEventListener('resizeWindow', function () {
100145 utilSetDimensions(_container, null);
100150 function click(d3_event) {
100151 surface.call(breathe.off).call(breathe);
100152 var datum = d3_event.target.__data__;
100153 var entity = datum && datum.properties && datum.properties.entity;
100159 if (datum instanceof osmWay && (datum.__from || datum.__via)) {
100163 } else if (datum instanceof osmTurn) {
100164 var actions, extraActions, turns, i;
100165 var restrictionType = osmInferRestriction(vgraph, datum, projection);
100167 if (datum.restrictionID && !datum.direct) {
100169 } else if (datum.restrictionID && !datum.only) {
100172 var datumOnly = JSON.parse(JSON.stringify(datum)); // deep clone the datum
100174 datumOnly.only = true; // but change this property
100176 restrictionType = restrictionType.replace(/^no/, 'only'); // Adding an ONLY restriction should destroy all other direct restrictions from the FROM towards the VIA.
100177 // We will remember them in _oldTurns, and restore them if the user clicks again.
100179 turns = _intersection.turns(_fromWayID, 2);
100183 for (i = 0; i < turns.length; i++) {
100185 if (seen[turn.restrictionID]) continue; // avoid deleting the turn twice (#4968, #4928)
100187 if (turn.direct && turn.path[1] === datum.path[1]) {
100188 seen[turns[i].restrictionID] = true;
100189 turn.restrictionType = osmInferRestriction(vgraph, turn, projection);
100193 extraActions.push(actionUnrestrictTurn(turn));
100197 actions = _intersection.actions.concat(extraActions, [actionRestrictTurn(datumOnly, restrictionType), _t('operations.restriction.annotation.create')]);
100198 } else if (datum.restrictionID) {
100200 // Restore whatever restrictions we might have destroyed by cycling thru the ONLY state.
100201 // This relies on the assumption that the intersection was already split up when we
100202 // performed the previous action (NO -> ONLY), so the IDs in _oldTurns shouldn't have changed.
100203 turns = _oldTurns || [];
100206 for (i = 0; i < turns.length; i++) {
100207 if (turns[i].key !== datum.key) {
100208 extraActions.push(actionRestrictTurn(turns[i], turns[i].restrictionType));
100213 actions = _intersection.actions.concat(extraActions, [actionUnrestrictTurn(datum), _t('operations.restriction.annotation.delete')]);
100216 actions = _intersection.actions.concat([actionRestrictTurn(datum, restrictionType), _t('operations.restriction.annotation.create')]);
100219 context.perform.apply(context, actions); // At this point the datum will be changed, but will have same key..
100220 // Refresh it and update the help..
100222 var s = surface.selectAll('.' + datum.key);
100223 datum = s.empty() ? null : s.datum();
100232 function mouseover(d3_event) {
100233 var datum = d3_event.target.__data__;
100237 _lastXPos = _lastXPos || sdims[0];
100239 function redraw(minChange) {
100243 xPos = utilGetDimensions(context.container().select('.sidebar'))[0];
100246 if (!minChange || minChange && Math.abs(xPos - _lastXPos) >= minChange) {
100247 if (context.hasEntity(_vertexID)) {
100250 _container.call(renderViewer);
100255 function highlightPathsFrom(wayID) {
100256 surface.selectAll('.related').classed('related', false).classed('allow', false).classed('restrict', false).classed('only', false);
100257 surface.selectAll('.' + wayID).classed('related', true);
100260 var turns = _intersection.turns(wayID, _maxViaWay);
100262 for (var i = 0; i < turns.length; i++) {
100264 var ids = [turn.to.way];
100265 var klass = turn.no ? 'restrict' : turn.only ? 'only' : 'allow';
100267 if (turn.only || turns.length === 1) {
100269 ids = ids.concat(turn.via.ways);
100271 } else if (turn.to.way === wayID) {
100275 surface.selectAll(utilEntitySelector(ids)).classed('related', true).classed('allow', klass === 'allow').classed('restrict', klass === 'restrict').classed('only', klass === 'only');
100280 function updateHints(datum) {
100281 var help = _container.selectAll('.restriction-help').html('');
100284 ['from', 'via', 'to'].forEach(function (k) {
100286 html: '<span class="qualifier">' + _t('restriction.help.' + k) + '</span>'
100289 var entity = datum && datum.properties && datum.properties.entity;
100296 way = vgraph.entity(_fromWayID);
100297 surface.selectAll('.' + _fromWayID).classed('selected', true).classed('related', true);
100301 if (datum instanceof osmWay && datum.__from) {
100303 highlightPathsFrom(_fromWayID ? null : way.id);
100304 surface.selectAll('.' + way.id).classed('related', true);
100305 var clickSelect = !_fromWayID || _fromWayID !== way.id;
100306 help.append('div') // "Click to select FROM {fromName}." / "FROM {fromName}"
100307 .html(_t.html('restriction.help.' + (clickSelect ? 'select_from_name' : 'from_name'), {
100308 from: placeholders.from,
100309 fromName: displayName(way.id, vgraph)
100310 })); // Hovering a turn arrow
100311 } else if (datum instanceof osmTurn) {
100312 var restrictionType = osmInferRestriction(vgraph, datum, projection);
100313 var turnType = restrictionType.replace(/^(only|no)\_/, '');
100314 var indirect = datum.direct === false ? _t.html('restriction.help.indirect') : '';
100315 var klass, turnText, nextText;
100319 turnText = _t.html('restriction.help.turn.no_' + turnType, {
100322 nextText = _t.html('restriction.help.turn.only_' + turnType, {
100325 } else if (datum.only) {
100327 turnText = _t.html('restriction.help.turn.only_' + turnType, {
100330 nextText = _t.html('restriction.help.turn.allowed_' + turnType, {
100335 turnText = _t.html('restriction.help.turn.allowed_' + turnType, {
100338 nextText = _t.html('restriction.help.turn.no_' + turnType, {
100343 help.append('div') // "NO Right Turn (indirect)"
100344 .attr('class', 'qualifier ' + klass).html(turnText);
100345 help.append('div') // "FROM {fromName} TO {toName}"
100346 .html(_t.html('restriction.help.from_name_to_name', {
100347 from: placeholders.from,
100348 fromName: displayName(datum.from.way, vgraph),
100350 toName: displayName(datum.to.way, vgraph)
100353 if (datum.via.ways && datum.via.ways.length) {
100356 for (var i = 0; i < datum.via.ways.length; i++) {
100357 var prev = names[names.length - 1];
100358 var curr = displayName(datum.via.ways[i], vgraph);
100360 if (!prev || curr !== prev) {
100361 // collapse identical names
100366 help.append('div') // "VIA {viaNames}"
100367 .html(_t.html('restriction.help.via_names', {
100369 viaNames: names.join(', ')
100374 help.append('div') // Click for "No Right Turn"
100375 .html(_t.html('restriction.help.toggle', {
100382 highlightPathsFrom(null);
100383 var alongIDs = datum.path.slice();
100384 surface.selectAll(utilEntitySelector(alongIDs)).classed('related', true).classed('allow', klass === 'allow').classed('restrict', klass === 'restrict').classed('only', klass === 'only'); // Hovering empty surface
100386 highlightPathsFrom(null);
100389 help.append('div') // "FROM {fromName}"
100390 .html(_t.html('restriction.help.from_name', {
100391 from: placeholders.from,
100392 fromName: displayName(_fromWayID, vgraph)
100395 help.append('div') // "Click to select a FROM segment."
100396 .html(_t.html('restriction.help.select_from', {
100397 from: placeholders.from
100404 function displayMaxDistance(maxDist) {
100405 return function (selection) {
100406 var isImperial = !_mainLocalizer.usesMetric();
100411 // imprecise conversion for prettier display
100421 distance: _t('units.feet', {
100427 distance: _t('units.meters', {
100433 return selection.html('').call(_t.append('restriction.controls.distance_up_to', opts));
100437 function displayMaxVia(maxVia) {
100438 return function (selection) {
100439 selection = selection.html('');
100440 return maxVia === 0 ? selection.call(_t.append('restriction.controls.via_node_only')) : maxVia === 1 ? selection.call(_t.append('restriction.controls.via_up_to_one')) : selection.call(_t.append('restriction.controls.via_up_to_two'));
100444 function displayName(entityID, graph) {
100445 var entity = graph.entity(entityID);
100446 var name = utilDisplayName(entity) || '';
100447 var matched = _mainPresetIndex.match(entity, graph);
100448 var type = matched && matched.name() || utilDisplayType(entity.id);
100452 restrictions.entityIDs = function (val) {
100459 restrictions.tags = function () {};
100461 restrictions.focus = function () {};
100463 restrictions.off = function (selection) {
100464 if (!_initialized) return;
100465 selection.selectAll('.surface').call(breathe.off).on('click.restrictions', null).on('mouseover.restrictions', null);
100466 select(window).on('resize.restrictions', null);
100469 return utilRebind(restrictions, dispatch, 'on');
100471 uiFieldRestrictions.supportsMultiselection = false;
100473 function uiFieldTextarea(field, context) {
100474 var dispatch = dispatch$8('change');
100475 var input = select(null);
100479 function textarea(selection) {
100480 var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
100481 wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
100482 input = wrap.selectAll('textarea').data([0]);
100483 input = input.enter().append('textarea').attr('id', field.domId).call(utilNoAuto).on('input', change(true)).on('blur', change()).on('change', change()).merge(input);
100486 function change(onInput) {
100488 var val = utilGetSetValue(input);
100489 if (!onInput) val = context.cleanTagValue(val); // don't override multiple values with blank string
100491 if (!val && Array.isArray(_tags[field.key])) return;
100493 t[field.key] = val || undefined;
100494 dispatch.call('change', this, t, onInput);
100498 textarea.tags = function (tags) {
100500 var isMixed = Array.isArray(tags[field.key]);
100501 utilGetSetValue(input, !isMixed && tags[field.key] ? tags[field.key] : '').attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : undefined).attr('placeholder', isMixed ? _t('inspector.multiple_values') : field.placeholder() || _t('inspector.unknown')).classed('mixed', isMixed);
100504 textarea.focus = function () {
100508 return utilRebind(textarea, dispatch, 'on');
100511 function uiFieldWikidata(field, context) {
100512 var wikidata = services.wikidata;
100513 var dispatch = dispatch$8('change');
100515 var _selection = select(null);
100517 var _searchInput = select(null);
100520 var _wikidataEntity = null;
100524 var _wikipediaKey = field.keys && field.keys.find(function (key) {
100525 return key.includes('wikipedia');
100527 _hintKey = field.key === 'wikidata' ? 'name' : field.key.split(':')[0];
100529 var combobox = uiCombobox(context, 'combo-' + field.safeid).caseSensitive(true).minItems(1);
100531 function wiki(selection) {
100532 _selection = selection;
100533 var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
100534 wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
100535 var list = wrap.selectAll('ul').data([0]);
100536 list = list.enter().append('ul').attr('class', 'rows').merge(list);
100537 var searchRow = list.selectAll('li.wikidata-search').data([0]);
100538 var searchRowEnter = searchRow.enter().append('li').attr('class', 'wikidata-search');
100539 searchRowEnter.append('input').attr('type', 'text').attr('id', field.domId).style('flex', '1').call(utilNoAuto).on('focus', function () {
100540 var node = select(this).node();
100541 node.setSelectionRange(0, node.value.length);
100542 }).on('blur', function () {
100544 }).call(combobox.fetcher(fetchWikidataItems));
100545 combobox.on('accept', function (d) {
100550 }).on('cancel', function () {
100553 searchRowEnter.append('button').attr('class', 'form-field-button wiki-link').attr('title', _t('icons.view_on', {
100555 })).call(svgIcon('#iD-icon-out-link')).on('click', function (d3_event) {
100556 d3_event.preventDefault();
100557 if (_wikiURL) window.open(_wikiURL, '_blank');
100559 searchRow = searchRow.merge(searchRowEnter);
100560 _searchInput = searchRow.select('input');
100561 var wikidataProperties = ['description', 'identifier'];
100562 var items = list.selectAll('li.labeled-input').data(wikidataProperties); // Enter
100564 var enter = items.enter().append('li').attr('class', function (d) {
100565 return 'labeled-input preset-wikidata-' + d;
100567 enter.append('span').attr('class', 'label').html(function (d) {
100568 return _t.html('wikidata.' + d);
100570 enter.append('input').attr('type', 'text').call(utilNoAuto).classed('disabled', 'true').attr('readonly', 'true');
100571 enter.append('button').attr('class', 'form-field-button').attr('title', _t('icons.copy')).call(svgIcon('#iD-operation-copy')).on('click', function (d3_event) {
100572 d3_event.preventDefault();
100573 select(this.parentNode).select('input').node().select();
100574 document.execCommand('copy');
100578 function fetchWikidataItems(q, callback) {
100580 // other tags may be good search terms
100581 for (var i in _entityIDs) {
100582 var entity = context.hasEntity(_entityIDs[i]);
100584 if (entity.tags[_hintKey]) {
100585 q = entity.tags[_hintKey];
100591 wikidata.itemsForSearchQuery(q, function (err, data) {
100595 data[i].value = data[i].label + ' (' + data[i].id + ')';
100596 data[i].title = data[i].description;
100599 if (callback) callback(data);
100605 syncTags[field.key] = _qid;
100606 dispatch.call('change', this, syncTags); // attempt asynchronous update of wikidata tag..
100608 var initGraph = context.graph();
100609 var initEntityIDs = _entityIDs;
100610 wikidata.entityByQID(_qid, function (err, entity) {
100611 if (err) return; // If graph has changed, we can't apply this update.
100613 if (context.graph() !== initGraph) return;
100614 if (!entity.sitelinks) return;
100615 var langs = wikidata.languagesToQuery(); // use the label and description languages as fallbacks
100617 ['labels', 'descriptions'].forEach(function (key) {
100618 if (!entity[key]) return;
100619 var valueLangs = Object.keys(entity[key]);
100620 if (valueLangs.length === 0) return;
100621 var valueLang = valueLangs[0];
100623 if (langs.indexOf(valueLang) === -1) {
100634 var siteID = lang.replace('-', '_') + 'wiki';
100636 if (entity.sitelinks[siteID]) {
100638 newWikipediaValue = lang + ':' + entity.sitelinks[siteID].title; // use the first match
100645 // No wikipedia sites available in the user's language or the fallback languages,
100646 // default to any wikipedia sitelink
100647 var wikiSiteKeys = Object.keys(entity.sitelinks).filter(function (site) {
100648 return site.endsWith('wiki');
100651 if (wikiSiteKeys.length === 0) {
100652 // if no wikipedia pages are linked to this wikidata entity, delete that tag
100653 newWikipediaValue = null;
100655 var wikiLang = wikiSiteKeys[0].slice(0, -4).replace('_', '-');
100656 var wikiTitle = entity.sitelinks[wikiSiteKeys[0]].title;
100657 newWikipediaValue = wikiLang + ':' + wikiTitle;
100662 if (newWikipediaValue) {
100663 newWikipediaValue = context.cleanTagValue(newWikipediaValue);
100666 if (typeof newWikipediaValue === 'undefined') return;
100667 var actions = initEntityIDs.map(function (entityID) {
100668 var entity = context.hasEntity(entityID);
100669 if (!entity) return null;
100670 var currTags = Object.assign({}, entity.tags); // shallow copy
100672 if (newWikipediaValue === null) {
100673 if (!currTags[_wikipediaKey]) return null;
100674 delete currTags[_wikipediaKey];
100676 currTags[_wikipediaKey] = newWikipediaValue;
100679 return actionChangeTags(entityID, currTags);
100681 if (!actions.length) return; // Coalesce the update of wikidata tag into the previous tag change
100683 context.overwrite(function actionUpdateWikipediaTags(graph) {
100684 actions.forEach(function (action) {
100688 }, context.history().undoAnnotation()); // do not dispatch.call('change') here, because entity_editor
100689 // changeTags() is not intended to be called asynchronously
100693 function setLabelForEntity() {
100697 label = entityPropertyForDisplay(_wikidataEntity, 'labels');
100699 if (label.length === 0) {
100700 label = _wikidataEntity.id.toString();
100704 utilGetSetValue(_searchInput, label);
100707 wiki.tags = function (tags) {
100708 var isMixed = Array.isArray(tags[field.key]);
100710 _searchInput.attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : null).attr('placeholder', isMixed ? _t('inspector.multiple_values') : '').classed('mixed', isMixed);
100712 _qid = typeof tags[field.key] === 'string' && tags[field.key] || '';
100714 if (!/^Q[0-9]*$/.test(_qid)) {
100718 } // QID value in correct format
100721 _wikiURL = 'https://wikidata.org/wiki/' + _qid;
100722 wikidata.entityByQID(_qid, function (err, entity) {
100728 _wikidataEntity = entity;
100730 var description = entityPropertyForDisplay(entity, 'descriptions');
100732 _selection.select('button.wiki-link').classed('disabled', false);
100734 _selection.select('.preset-wikidata-description').style('display', function () {
100735 return description.length > 0 ? 'flex' : 'none';
100736 }).select('input').attr('value', description);
100738 _selection.select('.preset-wikidata-identifier').style('display', function () {
100739 return entity.id ? 'flex' : 'none';
100740 }).select('input').attr('value', entity.id);
100741 }); // not a proper QID
100743 function unrecognized() {
100744 _wikidataEntity = null;
100747 _selection.select('.preset-wikidata-description').style('display', 'none');
100749 _selection.select('.preset-wikidata-identifier').style('display', 'none');
100751 _selection.select('button.wiki-link').classed('disabled', true);
100753 if (_qid && _qid !== '') {
100754 _wikiURL = 'https://wikidata.org/wiki/Special:Search?search=' + _qid;
100761 function entityPropertyForDisplay(wikidataEntity, propKey) {
100762 if (!wikidataEntity[propKey]) return '';
100763 var propObj = wikidataEntity[propKey];
100764 var langKeys = Object.keys(propObj);
100765 if (langKeys.length === 0) return ''; // sorted by priority, since we want to show the user's language first if possible
100767 var langs = wikidata.languagesToQuery();
100771 var valueObj = propObj[lang];
100772 if (valueObj && valueObj.value && valueObj.value.length > 0) return valueObj.value;
100773 } // default to any available value
100776 return propObj[langKeys[0]].value;
100779 wiki.entityIDs = function (val) {
100780 if (!arguments.length) return _entityIDs;
100785 wiki.focus = function () {
100786 _searchInput.node().focus();
100789 return utilRebind(wiki, dispatch, 'on');
100792 function uiFieldWikipedia(field, context) {
100793 var _arguments = arguments;
100794 var dispatch = dispatch$8('change');
100795 var wikipedia = services.wikipedia;
100796 var wikidata = services.wikidata;
100798 var _langInput = select(null);
100800 var _titleInput = select(null);
100808 var _dataWikipedia = [];
100809 _mainFileFetcher.get('wmf_sitematrix').then(function (d) {
100811 if (_tags) updateForTags(_tags);
100812 })["catch"](function () {
100815 var langCombo = uiCombobox(context, 'wikipedia-lang').fetcher(function (value, callback) {
100816 var v = value.toLowerCase();
100817 callback(_dataWikipedia.filter(function (d) {
100818 return d[0].toLowerCase().indexOf(v) >= 0 || d[1].toLowerCase().indexOf(v) >= 0 || d[2].toLowerCase().indexOf(v) >= 0;
100825 var titleCombo = uiCombobox(context, 'wikipedia-title').fetcher(function (value, callback) {
100829 for (var i in _entityIDs) {
100830 var entity = context.hasEntity(_entityIDs[i]);
100832 if (entity.tags.name) {
100833 value = entity.tags.name;
100839 var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
100840 searchfn(language()[2], value, function (query, data) {
100841 callback(data.map(function (d) {
100849 function wiki(selection) {
100850 var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
100851 wrap = wrap.enter().append('div').attr('class', "form-field-input-wrap form-field-input-".concat(field.type)).merge(wrap);
100852 var langContainer = wrap.selectAll('.wiki-lang-container').data([0]);
100853 langContainer = langContainer.enter().append('div').attr('class', 'wiki-lang-container').merge(langContainer);
100854 _langInput = langContainer.selectAll('input.wiki-lang').data([0]);
100855 _langInput = _langInput.enter().append('input').attr('type', 'text').attr('class', 'wiki-lang').attr('placeholder', _t('translate.localized_translation_language')).call(utilNoAuto).call(langCombo).merge(_langInput);
100857 _langInput.on('blur', changeLang).on('change', changeLang);
100859 var titleContainer = wrap.selectAll('.wiki-title-container').data([0]);
100860 titleContainer = titleContainer.enter().append('div').attr('class', 'wiki-title-container').merge(titleContainer);
100861 _titleInput = titleContainer.selectAll('input.wiki-title').data([0]);
100862 _titleInput = _titleInput.enter().append('input').attr('type', 'text').attr('class', 'wiki-title').attr('id', field.domId).call(utilNoAuto).call(titleCombo).merge(_titleInput);
100864 _titleInput.on('blur', function () {
100866 }).on('change', function () {
100870 var link = titleContainer.selectAll('.wiki-link').data([0]);
100871 link = link.enter().append('button').attr('class', 'form-field-button wiki-link').attr('title', _t('icons.view_on', {
100872 domain: 'wikipedia.org'
100873 })).call(svgIcon('#iD-icon-out-link')).merge(link);
100874 link.on('click', function (d3_event) {
100875 d3_event.preventDefault();
100876 if (_wikiURL) window.open(_wikiURL, '_blank');
100880 function defaultLanguageInfo(skipEnglishFallback) {
100881 var langCode = _mainLocalizer.languageCode().toLowerCase();
100883 for (var i in _dataWikipedia) {
100884 var d = _dataWikipedia[i]; // default to the language of iD's current locale
100886 if (d[2] === langCode) return d;
100887 } // fallback to English
100890 return skipEnglishFallback ? ['', '', ''] : ['English', 'English', 'en'];
100893 function language(skipEnglishFallback) {
100894 var value = utilGetSetValue(_langInput).toLowerCase();
100896 for (var i in _dataWikipedia) {
100897 var d = _dataWikipedia[i]; // return the language already set in the UI, if supported
100899 if (d[0].toLowerCase() === value || d[1].toLowerCase() === value || d[2] === value) return d;
100900 } // fallback to English
100903 return defaultLanguageInfo(skipEnglishFallback);
100906 function changeLang() {
100907 utilGetSetValue(_langInput, language()[1]);
100911 function change(skipWikidata) {
100912 var value = utilGetSetValue(_titleInput);
100913 var m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/);
100915 var langInfo = m && _dataWikipedia.find(function (d) {
100922 var nativeLangName = langInfo[1]; // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
100924 value = decodeURIComponent(m[2]).replace(/_/g, ' ');
100928 // leave this out for now - #6232
100929 // Best-effort `anchordecode:` implementation
100930 // anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
100933 anchor = decodeURIComponent(m[3]); // }
100935 value += '#' + anchor.replace(/_/g, ' ');
100938 value = value.slice(0, 1).toUpperCase() + value.slice(1);
100939 utilGetSetValue(_langInput, nativeLangName);
100940 utilGetSetValue(_titleInput, value);
100944 syncTags.wikipedia = context.cleanTagValue(language()[2] + ':' + value);
100946 syncTags.wikipedia = undefined;
100949 dispatch.call('change', this, syncTags);
100950 if (skipWikidata || !value || !language()[2]) return; // attempt asynchronous update of wikidata tag..
100952 var initGraph = context.graph();
100953 var initEntityIDs = _entityIDs;
100954 wikidata.itemsByTitle(language()[2], value, function (err, data) {
100955 if (err || !data || !Object.keys(data).length) return; // If graph has changed, we can't apply this update.
100957 if (context.graph() !== initGraph) return;
100958 var qids = Object.keys(data);
100959 var value = qids && qids.find(function (id) {
100960 return id.match(/^Q\d+$/);
100962 var actions = initEntityIDs.map(function (entityID) {
100963 var entity = context.entity(entityID).tags;
100964 var currTags = Object.assign({}, entity); // shallow copy
100966 if (currTags.wikidata !== value) {
100967 currTags.wikidata = value;
100968 return actionChangeTags(entityID, currTags);
100973 if (!actions.length) return; // Coalesce the update of wikidata tag into the previous tag change
100975 context.overwrite(function actionUpdateWikidataTags(graph) {
100976 actions.forEach(function (action) {
100980 }, context.history().undoAnnotation()); // do not dispatch.call('change') here, because entity_editor
100981 // changeTags() is not intended to be called asynchronously
100985 wiki.tags = function (tags) {
100990 function updateForTags(tags) {
100991 var value = typeof tags[field.key] === 'string' ? tags[field.key] : ''; // Expect tag format of `tagLang:tagArticleTitle`, e.g. `fr:Paris`, with
100992 // optional suffix of `#anchor`
100994 var m = value.match(/([^:]+):([^#]+)(?:#(.+))?/);
100995 var tagLang = m && m[1];
100996 var tagArticleTitle = m && m[2];
100997 var anchor = m && m[3];
100999 var tagLangInfo = tagLang && _dataWikipedia.find(function (d) {
101000 return tagLang === d[2];
101001 }); // value in correct format
101005 var nativeLangName = tagLangInfo[1];
101006 utilGetSetValue(_langInput, nativeLangName);
101007 utilGetSetValue(_titleInput, tagArticleTitle + (anchor ? '#' + anchor : ''));
101011 // Best-effort `anchorencode:` implementation
101012 anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
101014 anchor = anchor.replace(/ /g, '_');
101018 _wikiURL = 'https://' + tagLang + '.wikipedia.org/wiki/' + tagArticleTitle.replace(/ /g, '_') + (anchor ? '#' + anchor : ''); // unrecognized value format
101020 utilGetSetValue(_titleInput, value);
101022 if (value && value !== '') {
101023 utilGetSetValue(_langInput, '');
101024 var defaultLangInfo = defaultLanguageInfo();
101025 _wikiURL = "https://".concat(defaultLangInfo[2], ".wikipedia.org/w/index.php?fulltext=1&search=").concat(value);
101027 var shownOrDefaultLangInfo = language(true
101028 /* skipEnglishFallback */
101030 utilGetSetValue(_langInput, shownOrDefaultLangInfo[1]);
101036 wiki.entityIDs = function (val) {
101037 if (!_arguments.length) return _entityIDs;
101042 wiki.focus = function () {
101043 _titleInput.node().focus();
101046 return utilRebind(wiki, dispatch, 'on');
101048 uiFieldWikipedia.supportsMultiselection = false;
101052 address: uiFieldAddress,
101055 cycleway: uiFieldCycleway,
101056 defaultCheck: uiFieldCheck,
101058 identifier: uiFieldText,
101060 localized: uiFieldLocalized,
101061 roadheight: uiFieldRoadheight,
101062 roadspeed: uiFieldRoadspeed,
101063 manyCombo: uiFieldCombo,
101064 multiCombo: uiFieldCombo,
101065 networkCombo: uiFieldCombo,
101067 onewayCheck: uiFieldCheck,
101069 restrictions: uiFieldRestrictions,
101070 semiCombo: uiFieldCombo,
101071 structureRadio: uiFieldRadio,
101074 textarea: uiFieldTextarea,
101075 typeCombo: uiFieldCombo,
101077 wikidata: uiFieldWikidata,
101078 wikipedia: uiFieldWikipedia
101081 function uiField(context, presetField, entityIDs, options) {
101082 options = Object.assign({
101089 var dispatch = dispatch$8('change', 'revert');
101090 var field = Object.assign({}, presetField); // shallow copy
101092 field.domId = utilUniqueDomId('form-field-' + field.safeid);
101093 var _show = options.show;
101099 if (entityIDs && entityIDs.length) {
101100 _entityExtent = entityIDs.reduce(function (extent, entityID) {
101101 var entity = context.graph().entity(entityID);
101102 return extent.extend(entity.extent(context.graph()));
101108 var _lockedTip = uiTooltip().title(_t.html('inspector.lock.suggestion', {
101110 })).placement('bottom');
101112 field.keys = field.keys || [field.key]; // only create the fields that are actually being shown
101114 if (_show && !field.impl) {
101116 } // Creates the field.. This is done lazily,
101117 // once we know that the field will be shown.
101120 function createField() {
101121 field.impl = uiFields[field.type](field, context).on('change', function (t, onInput) {
101122 dispatch.call('change', field, t, onInput);
101126 field.entityIDs = entityIDs; // if this field cares about the entities, pass them along
101128 if (field.impl.entityIDs) {
101129 field.impl.entityIDs(entityIDs);
101134 function isModified() {
101135 if (!entityIDs || !entityIDs.length) return false;
101136 return entityIDs.some(function (entityID) {
101137 var original = context.graph().base().entities[entityID];
101138 var latest = context.graph().entity(entityID);
101139 return field.keys.some(function (key) {
101140 return original ? latest.tags[key] !== original.tags[key] : latest.tags[key];
101145 function tagsContainFieldKey() {
101146 return field.keys.some(function (key) {
101147 if (field.type === 'multiCombo') {
101148 for (var tagKey in _tags) {
101149 if (tagKey.indexOf(key) === 0) {
101157 return _tags[key] !== undefined;
101161 function revert(d3_event, d) {
101162 d3_event.stopPropagation();
101163 d3_event.preventDefault();
101164 if (!entityIDs || _locked) return;
101165 dispatch.call('revert', d, d.keys);
101168 function remove(d3_event, d) {
101169 d3_event.stopPropagation();
101170 d3_event.preventDefault();
101173 d.keys.forEach(function (key) {
101176 dispatch.call('change', d, t);
101179 field.render = function (selection) {
101180 var container = selection.selectAll('.form-field').data([field]); // Enter
101182 var enter = container.enter().append('div').attr('class', function (d) {
101183 return 'form-field form-field-' + d.safeid;
101184 }).classed('nowrap', !options.wrap);
101187 var labelEnter = enter.append('label').attr('class', 'field-label').attr('for', function (d) {
101190 var textEnter = labelEnter.append('span').attr('class', 'label-text');
101191 textEnter.append('span').attr('class', 'label-textvalue').html(function (d) {
101194 textEnter.append('span').attr('class', 'label-textannotation');
101197 labelEnter.append('button').attr('class', 'remove-icon').attr('title', _t('icons.remove')).call(svgIcon('#iD-operation-delete'));
101201 labelEnter.append('button').attr('class', 'modified-icon').attr('title', _t('icons.undo')).call(svgIcon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-redo' : '#iD-icon-undo'));
101206 container = container.merge(enter);
101207 container.select('.field-label > .remove-icon') // propagate bound data
101209 container.select('.field-label > .modified-icon') // propagate bound data
101211 container.each(function (d) {
101212 var selection = select(this);
101218 var reference, help; // instantiate field help
101220 if (options.wrap && field.type === 'restrictions') {
101221 help = uiFieldHelp(context, 'restrictions');
101222 } // instantiate tag reference
101225 if (options.wrap && options.info) {
101226 var referenceKey = d.key || '';
101228 if (d.type === 'multiCombo') {
101229 // lookup key without the trailing ':'
101230 referenceKey = referenceKey.replace(/:$/, '');
101233 reference = uiTagReference(d.reference || {
101237 if (_state === 'hover') {
101238 reference.showing(false);
101242 selection.call(d.impl); // add field help components
101245 selection.call(help.body).select('.field-label').call(help.button);
101246 } // add tag reference components
101250 selection.call(reference.body).select('.field-label').call(reference.button);
101255 container.classed('locked', _locked).classed('modified', isModified()).classed('present', tagsContainFieldKey()); // show a tip and lock icon if the field is locked
101257 var annotation = container.selectAll('.field-label .label-textannotation');
101258 var icon = annotation.selectAll('.icon').data(_locked ? [0] : []);
101260 icon.enter().append('svg').attr('class', 'icon').append('use').attr('xlink:href', '#fas-lock');
101261 container.call(_locked ? _lockedTip : _lockedTip.destroy);
101264 field.state = function (val) {
101265 if (!arguments.length) return _state;
101270 field.tags = function (val) {
101271 if (!arguments.length) return _tags;
101274 if (tagsContainFieldKey() && !_show) {
101275 // always show a field if it has a value to display
101286 field.locked = function (val) {
101287 if (!arguments.length) return _locked;
101292 field.show = function () {
101299 if (field["default"] && field.key && _tags[field.key] !== field["default"]) {
101301 t[field.key] = field["default"];
101302 dispatch.call('change', this, t);
101304 }; // A shown field has a visible UI, a non-shown field is in the 'Add field' dropdown
101307 field.isShown = function () {
101309 }; // An allowed field can appear in the UI or in the 'Add field' dropdown.
101310 // A non-allowed field is hidden from the user altogether
101313 field.isAllowed = function () {
101314 if (entityIDs && entityIDs.length > 1 && uiFields[field.type].supportsMultiselection === false) return false;
101315 if (field.geometry && !entityIDs.every(function (entityID) {
101316 return field.matchGeometry(context.graph().geometry(entityID));
101319 if (entityIDs && _entityExtent && field.locationSetID) {
101320 // is field allowed in this location?
101321 var validLocations = _mainLocations.locationsAt(_entityExtent.center());
101322 if (!validLocations[field.locationSetID]) return false;
101325 var prerequisiteTag = field.prerequisiteTag;
101327 if (entityIDs && !tagsContainFieldKey() && // ignore tagging prerequisites if a value is already present
101329 if (!entityIDs.every(function (entityID) {
101330 var entity = context.graph().entity(entityID);
101332 if (prerequisiteTag.key) {
101333 var value = entity.tags[prerequisiteTag.key];
101334 if (!value) return false;
101336 if (prerequisiteTag.valueNot) {
101337 return prerequisiteTag.valueNot !== value;
101340 if (prerequisiteTag.value) {
101341 return prerequisiteTag.value === value;
101343 } else if (prerequisiteTag.keyNot) {
101344 if (entity.tags[prerequisiteTag.keyNot]) return false;
101354 field.focus = function () {
101360 return utilRebind(field, dispatch, 'on');
101363 function uiFormFields(context) {
101364 var moreCombo = uiCombobox(context, 'more-fields').minItems(1);
101366 var _lastPlaceholder = '';
101370 function formFields(selection) {
101371 var allowedFields = _fieldsArr.filter(function (field) {
101372 return field.isAllowed();
101375 var shown = allowedFields.filter(function (field) {
101376 return field.isShown();
101378 var notShown = allowedFields.filter(function (field) {
101379 return !field.isShown();
101381 var container = selection.selectAll('.form-fields-container').data([0]);
101382 container = container.enter().append('div').attr('class', 'form-fields-container ' + (_klass || '')).merge(container);
101383 var fields = container.selectAll('.wrap-form-field').data(shown, function (d) {
101384 return d.id + (d.entityIDs ? d.entityIDs.join() : '');
101386 fields.exit().remove(); // Enter
101388 var enter = fields.enter().append('div').attr('class', function (d) {
101389 return 'wrap-form-field wrap-form-field-' + d.safeid;
101392 fields = fields.merge(enter);
101393 fields.order().each(function (d) {
101394 select(this).call(d.render);
101397 var moreFields = notShown.map(function (field) {
101398 var title = field.title();
101400 var terms = field.terms();
101401 if (field.key) terms.push(field.key);
101402 if (field.keys) terms = terms.concat(field.keys);
101404 display: field.label(),
101411 var placeholder = titles.slice(0, 3).join(', ') + (titles.length > 3 ? '…' : '');
101412 var more = selection.selectAll('.more-fields').data(_state === 'hover' || moreFields.length === 0 ? [] : [0]);
101414 var moreEnter = more.enter().append('div').attr('class', 'more-fields').append('label');
101415 moreEnter.append('span').call(_t.append('inspector.add_fields'));
101416 more = moreEnter.merge(more);
101417 var input = more.selectAll('.value').data([0]);
101419 input = input.enter().append('input').attr('class', 'value').attr('type', 'text').attr('placeholder', placeholder).call(utilNoAuto).merge(input);
101420 input.call(utilGetSetValue, '').call(moreCombo.data(moreFields).on('accept', function (d) {
101421 if (!d) return; // user entered something that was not matched
101425 selection.call(formFields); // rerender
101428 })); // avoid updating placeholder excessively (triggers style recalc)
101430 if (_lastPlaceholder !== placeholder) {
101431 input.attr('placeholder', placeholder);
101432 _lastPlaceholder = placeholder;
101436 formFields.fieldsArr = function (val) {
101437 if (!arguments.length) return _fieldsArr;
101438 _fieldsArr = val || [];
101442 formFields.state = function (val) {
101443 if (!arguments.length) return _state;
101448 formFields.klass = function (val) {
101449 if (!arguments.length) return _klass;
101457 function uiChangesetEditor(context) {
101458 var dispatch = dispatch$8('change');
101459 var formFields = uiFormFields(context);
101460 var commentCombo = uiCombobox(context, 'comment').caseSensitive(true);
101468 function changesetEditor(selection) {
101472 function render(selection) {
101477 var presets = _mainPresetIndex;
101478 _fieldsArr = [uiField(context, presets.field('comment'), null, {
101481 }), uiField(context, presets.field('source'), null, {
101484 }), uiField(context, presets.field('hashtags'), null, {
101489 _fieldsArr.forEach(function (field) {
101490 field.on('change', function (t, onInput) {
101491 dispatch.call('change', field, undefined, t, onInput);
101496 _fieldsArr.forEach(function (field) {
101500 selection.call(formFields.fieldsArr(_fieldsArr));
101503 var commentField = selection.select('.form-field-comment textarea');
101504 var commentNode = commentField.node();
101509 } // trigger a 'blur' event so that comment field can be cleaned
101510 // and checked for hashtags, even if retrieved from localstorage
101513 utilTriggerEvent(commentField, 'blur');
101514 var osm = context.connection();
101517 osm.userChangesets(function (err, changesets) {
101519 var comments = changesets.map(function (changeset) {
101520 var comment = changeset.tags.comment;
101526 commentField.call(commentCombo.data(utilArrayUniqBy(comments, 'title')));
101529 } // Add warning if comment mentions Google
101532 var hasGoogle = _tags.comment.match(/google/i);
101534 var commentWarning = selection.select('.form-field-comment').selectAll('.comment-warning').data(hasGoogle ? [0] : []);
101535 commentWarning.exit().transition().duration(200).style('opacity', 0).remove();
101536 var commentEnter = commentWarning.enter().insert('div', '.tag-reference-body').attr('class', 'field-warning comment-warning').style('opacity', 0);
101537 commentEnter.append('a').attr('target', '_blank').call(svgIcon('#iD-icon-alert', 'inline')).attr('href', _t('commit.google_warning_link')).append('span').call(_t.append('commit.google_warning'));
101538 commentEnter.transition().duration(200).style('opacity', 1);
101541 changesetEditor.tags = function (_) {
101542 if (!arguments.length) return _tags;
101543 _tags = _; // Don't reset _fieldsArr here.
101545 return changesetEditor;
101548 changesetEditor.changesetID = function (_) {
101549 if (!arguments.length) return _changesetID;
101550 if (_changesetID === _) return changesetEditor;
101553 return changesetEditor;
101556 return utilRebind(changesetEditor, dispatch, 'on');
101559 var JXON = new function () {
101560 var sValueProp = 'keyValue',
101561 sAttributesProp = 'keyAttributes',
101564 /* you can customize these values */
101567 rIsBool = /^(?:true|false)$/i;
101569 function parseText(sValue) {
101570 if (rIsNull.test(sValue)) {
101574 if (rIsBool.test(sValue)) {
101575 return sValue.toLowerCase() === 'true';
101578 if (isFinite(sValue)) {
101579 return parseFloat(sValue);
101582 if (isFinite(Date.parse(sValue))) {
101583 return new Date(sValue);
101589 function EmptyTree() {}
101591 EmptyTree.prototype.toString = function () {
101595 EmptyTree.prototype.valueOf = function () {
101599 function objectify(vValue) {
101600 return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
101603 function createObjTree(oParentNode, nVerb, bFreeze, bNesteAttr) {
101604 var nLevelStart = aCache.length,
101605 bChildren = oParentNode.hasChildNodes(),
101606 bAttributes = oParentNode.hasAttributes(),
101607 bHighVerb = Boolean(nVerb & 2);
101612 vResult = bHighVerb ? {} :
101613 /* put here the default value for empty nodes: */
101617 for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
101618 oNode = oParentNode.childNodes.item(nItem);
101620 if (oNode.nodeType === 4) {
101621 /* nodeType is 'CDATASection' (4) */
101622 sCollectedTxt += oNode.nodeValue;
101623 } else if (oNode.nodeType === 3) {
101624 /* nodeType is 'Text' (3) */
101625 sCollectedTxt += oNode.nodeValue.trim();
101626 } else if (oNode.nodeType === 1 && !oNode.prefix) {
101627 /* nodeType is 'Element' (1) */
101633 var nLevelEnd = aCache.length,
101634 vBuiltVal = parseText(sCollectedTxt);
101636 if (!bHighVerb && (bChildren || bAttributes)) {
101637 vResult = nVerb === 0 ? objectify(vBuiltVal) : {};
101640 for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
101641 sProp = aCache[nElId].nodeName.toLowerCase();
101642 vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
101644 if (vResult.hasOwnProperty(sProp)) {
101645 if (vResult[sProp].constructor !== Array) {
101646 vResult[sProp] = [vResult[sProp]];
101649 vResult[sProp].push(vContent);
101651 vResult[sProp] = vContent;
101657 var nAttrLen = oParentNode.attributes.length,
101658 sAPrefix = bNesteAttr ? '' : sAttrPref,
101659 oAttrParent = bNesteAttr ? {} : vResult;
101661 for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
101662 oAttrib = oParentNode.attributes.item(nAttrib);
101663 oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
101668 Object.freeze(oAttrParent);
101671 vResult[sAttributesProp] = oAttrParent;
101672 nLength -= nAttrLen - 1;
101676 if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
101677 vResult[sValueProp] = vBuiltVal;
101678 } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
101682 if (bFreeze && (bHighVerb || nLength > 0)) {
101683 Object.freeze(vResult);
101686 aCache.length = nLevelStart;
101690 function loadObjTree(oXMLDoc, oParentEl, oParentObj) {
101693 if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
101694 oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString()));
101695 /* verbosity level is 0 */
101696 } else if (oParentObj.constructor === Date) {
101697 oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));
101700 for (var sName in oParentObj) {
101701 vValue = oParentObj[sName];
101703 if (isFinite(sName) || vValue instanceof Function) {
101706 /* verbosity level is 0 */
101709 if (sName === sValueProp) {
101710 if (vValue !== null && vValue !== true) {
101711 oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue)));
101713 } else if (sName === sAttributesProp) {
101714 /* verbosity level is 3 */
101715 for (var sAttrib in vValue) {
101716 oParentEl.setAttribute(sAttrib, vValue[sAttrib]);
101718 } else if (sName.charAt(0) === sAttrPref) {
101719 oParentEl.setAttribute(sName.slice(1), vValue);
101720 } else if (vValue.constructor === Array) {
101721 for (var nItem = 0; nItem < vValue.length; nItem++) {
101722 oChild = oXMLDoc.createElement(sName);
101723 loadObjTree(oXMLDoc, oChild, vValue[nItem]);
101724 oParentEl.appendChild(oChild);
101727 oChild = oXMLDoc.createElement(sName);
101729 if (vValue instanceof Object) {
101730 loadObjTree(oXMLDoc, oChild, vValue);
101731 } else if (vValue !== null && vValue !== true) {
101732 oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
101735 oParentEl.appendChild(oChild);
101740 this.build = function (oXMLParent, nVerbosity
101747 var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 :
101748 /* put here the default verbosity level: */
101751 return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);
101754 this.unbuild = function (oObjTree) {
101755 var oNewDoc = document.implementation.createDocument('', '', null);
101756 loadObjTree(oNewDoc, oNewDoc, oObjTree);
101760 this.stringify = function (oObjTree) {
101761 return new XMLSerializer().serializeToString(JXON.unbuild(oObjTree));
101763 }(); // var myObject = JXON.build(doc);
101764 // we got our javascript object! try: alert(JSON.stringify(myObject));
101765 // var newDoc = JXON.unbuild(myObject);
101766 // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
101768 function uiSectionChanges(context) {
101769 var detected = utilDetect();
101771 _mainFileFetcher.get('discarded').then(function (d) {
101773 })["catch"](function () {
101776 var section = uiSection('changes-list', context).label(function () {
101777 var history = context.history();
101778 var summary = history.difference().summary();
101779 return _t.html('inspector.title_count', {
101781 html: _t.html('commit.changes')
101785 }).disclosureContent(renderDisclosureContent);
101787 function renderDisclosureContent(selection) {
101788 var history = context.history();
101789 var summary = history.difference().summary();
101790 var container = selection.selectAll('.commit-section').data([0]);
101791 var containerEnter = container.enter().append('div').attr('class', 'commit-section');
101792 containerEnter.append('ul').attr('class', 'changeset-list');
101793 container = containerEnter.merge(container);
101794 var items = container.select('ul').selectAll('li').data(summary);
101795 var itemsEnter = items.enter().append('li').attr('class', 'change-item');
101796 var buttons = itemsEnter.append('button').on('mouseover', mouseover).on('mouseout', mouseout).on('click', click);
101797 buttons.each(function (d) {
101798 select(this).call(svgIcon('#iD-icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
101800 buttons.append('span').attr('class', 'change-type').html(function (d) {
101801 return _t.html('commit.' + d.changeType) + ' ';
101803 buttons.append('strong').attr('class', 'entity-type').text(function (d) {
101804 var matched = _mainPresetIndex.match(d.entity, d.graph);
101805 return matched && matched.name() || utilDisplayType(d.entity.id);
101807 buttons.append('span').attr('class', 'entity-name').text(function (d) {
101808 var name = utilDisplayName(d.entity) || '',
101815 return string += ' ' + name;
101817 items = itemsEnter.merge(items); // Download changeset link
101819 var changeset = new osmChangeset().update({
101822 var changes = history.changes(actionDiscardTags(history.difference(), _discardTags));
101823 delete changeset.id; // Export without chnageset_id
101825 var data = JXON.stringify(changeset.osmChangeJXON(changes));
101826 var blob = new Blob([data], {
101827 type: 'text/xml;charset=utf-8;'
101829 var fileName = 'changes.osc';
101830 var linkEnter = container.selectAll('.download-changes').data([0]).enter().append('a').attr('class', 'download-changes');
101832 if (detected.download) {
101833 // All except IE11 and Edge
101834 linkEnter // download the data as a file
101835 .attr('href', window.URL.createObjectURL(blob)).attr('download', fileName);
101838 linkEnter // open data uri in a new tab
101839 .attr('target', '_blank').on('click.download', function () {
101840 navigator.msSaveBlob(blob, fileName);
101844 linkEnter.call(svgIcon('#iD-icon-load', 'inline')).append('span').call(_t.append('commit.download_changes'));
101846 function mouseover(d) {
101848 context.surface().selectAll(utilEntityOrMemberSelector([d.entity.id], context.graph())).classed('hover', true);
101853 context.surface().selectAll('.hover').classed('hover', false);
101856 function click(d3_event, change) {
101857 if (change.changeType !== 'deleted') {
101858 var entity = change.entity;
101859 context.map().zoomToEase(entity);
101860 context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph())).classed('hover', true);
101868 function uiCommitWarnings(context) {
101869 function commitWarnings(selection) {
101870 var issuesBySeverity = context.validator().getIssuesBySeverity({
101873 includeDisabledRules: true
101876 for (var severity in issuesBySeverity) {
101877 var issues = issuesBySeverity[severity];
101879 if (severity !== 'error') {
101880 // exclude 'fixme' and similar - #8603
101881 issues = issues.filter(function (issue) {
101882 return issue.type !== 'help_request';
101886 var section = severity + '-section';
101887 var issueItem = severity + '-item';
101888 var container = selection.selectAll('.' + section).data(issues.length ? [0] : []);
101889 container.exit().remove();
101890 var containerEnter = container.enter().append('div').attr('class', 'modal-section ' + section + ' fillL2');
101891 containerEnter.append('h3').html(severity === 'warning' ? _t.html('commit.warnings') : _t.html('commit.errors'));
101892 containerEnter.append('ul').attr('class', 'changeset-list');
101893 container = containerEnter.merge(container);
101894 var items = container.select('ul').selectAll('li').data(issues, function (d) {
101898 var itemsEnter = items.enter().append('li').attr('class', issueItem);
101899 var buttons = itemsEnter.append('button').on('mouseover', function (d3_event, d) {
101901 context.surface().selectAll(utilEntityOrMemberSelector(d.entityIds, context.graph())).classed('hover', true);
101903 }).on('mouseout', function () {
101904 context.surface().selectAll('.hover').classed('hover', false);
101905 }).on('click', function (d3_event, d) {
101906 context.validator().focusIssue(d);
101908 buttons.call(svgIcon('#iD-icon-alert', 'pre-text'));
101909 buttons.append('strong').attr('class', 'issue-message');
101910 buttons.filter(function (d) {
101912 }).call(uiTooltip().title(function (d) {
101915 items = itemsEnter.merge(items);
101916 items.selectAll('.issue-message').html(function (d) {
101917 return d.message(context);
101925 var readOnlyTags = [/^changesets_count$/, /^created_by$/, /^ideditor:/, /^imagery_used$/, /^host$/, /^locale$/, /^warnings:/, /^resolved:/, /^closed:note$/, /^closed:keepright$/, /^closed:improveosm:/, /^closed:osmose:/]; // treat most punctuation (except -, _, +, &) as hashtag delimiters - #4398
101926 // from https://stackoverflow.com/a/25575009
101928 var hashtagRegex = /(#[^\u2000-\u206F\u2E00-\u2E7F\s\\'!"#$%()*,.\/:;<=>?@\[\]^`{|}~]+)/g;
101929 function uiCommit(context) {
101930 var dispatch = dispatch$8('cancel');
101936 var changesetEditor = uiChangesetEditor(context).on('change', changeTags);
101937 var rawTagEditor = uiSectionRawTagEditor('changeset-tag-editor', context).on('change', changeTags).readOnlyTags(readOnlyTags);
101938 var commitChanges = uiSectionChanges(context);
101939 var commitWarnings = uiCommitWarnings(context);
101941 function commit(selection) {
101942 _selection = selection; // Initialize changeset if one does not exist yet.
101944 if (!context.changeset) initChangeset();
101945 loadDerivedChangesetTags();
101946 selection.call(render);
101949 function initChangeset() {
101950 // expire stored comment, hashtags, source after cutoff datetime - #3947 #4899
101951 var commentDate = +corePreferences('commentDate') || 0;
101952 var currDate = Date.now();
101953 var cutoff = 2 * 86400 * 1000; // 2 days
101955 if (commentDate > currDate || currDate - commentDate > cutoff) {
101956 corePreferences('comment', null);
101957 corePreferences('hashtags', null);
101958 corePreferences('source', null);
101959 } // load in explicitly-set values, if any
101962 if (context.defaultChangesetComment()) {
101963 corePreferences('comment', context.defaultChangesetComment());
101964 corePreferences('commentDate', Date.now());
101967 if (context.defaultChangesetSource()) {
101968 corePreferences('source', context.defaultChangesetSource());
101969 corePreferences('commentDate', Date.now());
101972 if (context.defaultChangesetHashtags()) {
101973 corePreferences('hashtags', context.defaultChangesetHashtags());
101974 corePreferences('commentDate', Date.now());
101977 var detected = utilDetect();
101979 comment: corePreferences('comment') || '',
101980 created_by: context.cleanTagValue('iD ' + context.version),
101981 host: context.cleanTagValue(detected.host),
101982 locale: context.cleanTagValue(_mainLocalizer.localeCode())
101983 }; // call findHashtags initially - this will remove stored
101984 // hashtags if any hashtags are found in the comment - #4304
101986 findHashtags(tags, true);
101987 var hashtags = corePreferences('hashtags');
101990 tags.hashtags = hashtags;
101993 var source = corePreferences('source');
101999 var photoOverlaysUsed = context.history().photoOverlaysUsed();
102001 if (photoOverlaysUsed.length) {
102002 var sources = (tags.source || '').split(';'); // include this tag for any photo layer
102004 if (sources.indexOf('streetlevel imagery') === -1) {
102005 sources.push('streetlevel imagery');
102006 } // add the photo overlays used during editing as sources
102009 photoOverlaysUsed.forEach(function (photoOverlay) {
102010 if (sources.indexOf(photoOverlay) === -1) {
102011 sources.push(photoOverlay);
102014 tags.source = context.cleanTagValue(sources.join(';'));
102017 context.changeset = new osmChangeset({
102020 } // Calculates read-only metadata tags based on the user's editing session and applies
102021 // them to the changeset.
102024 function loadDerivedChangesetTags() {
102025 var osm = context.connection();
102027 var tags = Object.assign({}, context.changeset.tags); // shallow copy
102028 // assign tags for imagery used
102030 var imageryUsed = context.cleanTagValue(context.history().imageryUsed().join(';'));
102031 tags.imagery_used = imageryUsed || 'None'; // assign tags for closed issues and notes
102033 var osmClosed = osm.getClosedIDs();
102036 if (osmClosed.length) {
102037 tags['closed:note'] = context.cleanTagValue(osmClosed.join(';'));
102040 if (services.keepRight) {
102041 var krClosed = services.keepRight.getClosedIDs();
102044 tags['closed:keepright'] = context.cleanTagValue(krClosed.join(';'));
102048 if (services.improveOSM) {
102049 var iOsmClosed = services.improveOSM.getClosedCounts();
102051 for (itemType in iOsmClosed) {
102052 tags['closed:improveosm:' + itemType] = context.cleanTagValue(iOsmClosed[itemType].toString());
102057 var osmoseClosed = services.osmose.getClosedCounts();
102059 for (itemType in osmoseClosed) {
102060 tags['closed:osmose:' + itemType] = context.cleanTagValue(osmoseClosed[itemType].toString());
102062 } // remove existing issue counts
102065 for (var key in tags) {
102066 if (key.match(/(^warnings:)|(^resolved:)/)) {
102071 function addIssueCounts(issues, prefix) {
102072 var issuesByType = utilArrayGroupBy(issues, 'type');
102074 for (var issueType in issuesByType) {
102075 var issuesOfType = issuesByType[issueType];
102077 if (issuesOfType[0].subtype) {
102078 var issuesBySubtype = utilArrayGroupBy(issuesOfType, 'subtype');
102080 for (var issueSubtype in issuesBySubtype) {
102081 var issuesOfSubtype = issuesBySubtype[issueSubtype];
102082 tags[prefix + ':' + issueType + ':' + issueSubtype] = context.cleanTagValue(issuesOfSubtype.length.toString());
102085 tags[prefix + ':' + issueType] = context.cleanTagValue(issuesOfType.length.toString());
102088 } // add counts of warnings generated by the user's edits
102091 var warnings = context.validator().getIssuesBySeverity({
102095 includeDisabledRules: true
102096 }).warning.filter(function (issue) {
102097 return issue.type !== 'help_request';
102098 }); // exclude 'fixme' and similar - #8603
102100 addIssueCounts(warnings, 'warnings'); // add counts of issues resolved by the user's edits
102102 var resolvedIssues = context.validator().getResolvedIssues();
102103 addIssueCounts(resolvedIssues, 'resolved');
102104 context.changeset = context.changeset.update({
102109 function render(selection) {
102110 var osm = context.connection();
102112 var header = selection.selectAll('.header').data([0]);
102113 var headerTitle = header.enter().append('div').attr('class', 'header fillL');
102114 headerTitle.append('div').append('h2').call(_t.append('commit.title'));
102115 headerTitle.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
102116 dispatch.call('cancel', this);
102117 }).call(svgIcon('#iD-icon-close'));
102118 var body = selection.selectAll('.body').data([0]);
102119 body = body.enter().append('div').attr('class', 'body').merge(body); // Changeset Section
102121 var changesetSection = body.selectAll('.changeset-editor').data([0]);
102122 changesetSection = changesetSection.enter().append('div').attr('class', 'modal-section changeset-editor').merge(changesetSection);
102123 changesetSection.call(changesetEditor.changesetID(context.changeset.id).tags(context.changeset.tags)); // Warnings
102125 body.call(commitWarnings); // Upload Explanation
102127 var saveSection = body.selectAll('.save-section').data([0]);
102128 saveSection = saveSection.enter().append('div').attr('class', 'modal-section save-section fillL').merge(saveSection);
102129 var prose = saveSection.selectAll('.commit-info').data([0]);
102131 if (prose.enter().size()) {
102132 // first time, make sure to update user details in prose
102136 prose = prose.enter().append('p').attr('class', 'commit-info').call(_t.append('commit.upload_explanation')).merge(prose); // always check if this has changed, but only update prose.html()
102137 // if needed, because it can trigger a style recalculation
102139 osm.userDetails(function (err, user) {
102141 if (_userDetails === user) return; // no change
102144 var userLink = select(document.createElement('div'));
102147 userLink.append('img').attr('src', user.image_url).attr('class', 'icon pre-text user-icon');
102150 userLink.append('a').attr('class', 'user-info').text(user.display_name).attr('href', osm.userURL(user.display_name)).attr('target', '_blank');
102151 prose.html(_t.html('commit.upload_explanation_with_user', {
102158 var requestReview = saveSection.selectAll('.request-review').data([0]); // Enter
102160 var requestReviewEnter = requestReview.enter().append('div').attr('class', 'request-review');
102161 var requestReviewDomId = utilUniqueDomId('commit-input-request-review');
102162 var labelEnter = requestReviewEnter.append('label').attr('for', requestReviewDomId);
102164 if (!labelEnter.empty()) {
102165 labelEnter.call(uiTooltip().title(_t.html('commit.request_review_info')).placement('top'));
102168 labelEnter.append('input').attr('type', 'checkbox').attr('id', requestReviewDomId);
102169 labelEnter.append('span').call(_t.append('commit.request_review')); // Update
102171 requestReview = requestReview.merge(requestReviewEnter);
102172 var requestReviewInput = requestReview.selectAll('input').property('checked', isReviewRequested(context.changeset.tags)).on('change', toggleRequestReview); // Buttons
102174 var buttonSection = saveSection.selectAll('.buttons').data([0]); // enter
102176 var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons fillL');
102177 buttonEnter.append('button').attr('class', 'secondary-action button cancel-button').append('span').attr('class', 'label').call(_t.append('commit.cancel'));
102178 var uploadButton = buttonEnter.append('button').attr('class', 'action button save-button');
102179 uploadButton.append('span').attr('class', 'label').call(_t.append('commit.save'));
102180 var uploadBlockerTooltipText = getUploadBlockerMessage(); // update
102182 buttonSection = buttonSection.merge(buttonEnter);
102183 buttonSection.selectAll('.cancel-button').on('click.cancel', function () {
102184 dispatch.call('cancel', this);
102186 buttonSection.selectAll('.save-button').classed('disabled', uploadBlockerTooltipText !== null).on('click.save', function () {
102187 if (!select(this).classed('disabled')) {
102188 this.blur(); // avoid keeping focus on the button - #4641
102190 for (var key in context.changeset.tags) {
102191 // remove any empty keys before upload
102192 if (!key) delete context.changeset.tags[key];
102195 context.uploader().save(context.changeset);
102197 }); // remove any existing tooltip
102199 uiTooltip().destroyAny(buttonSection.selectAll('.save-button'));
102201 if (uploadBlockerTooltipText) {
102202 buttonSection.selectAll('.save-button').call(uiTooltip().title(uploadBlockerTooltipText).placement('top'));
102206 var tagSection = body.selectAll('.tag-section.raw-tag-editor').data([0]);
102207 tagSection = tagSection.enter().append('div').attr('class', 'modal-section tag-section raw-tag-editor').merge(tagSection);
102208 tagSection.call(rawTagEditor.tags(Object.assign({}, context.changeset.tags)) // shallow copy
102210 var changesSection = body.selectAll('.commit-changes-section').data([0]);
102211 changesSection = changesSection.enter().append('div').attr('class', 'modal-section commit-changes-section').merge(changesSection); // Change summary
102213 changesSection.call(commitChanges.render);
102215 function toggleRequestReview() {
102216 var rr = requestReviewInput.property('checked');
102218 review_requested: rr ? 'yes' : undefined
102220 tagSection.call(rawTagEditor.tags(Object.assign({}, context.changeset.tags)) // shallow copy
102225 function getUploadBlockerMessage() {
102226 var errors = context.validator().getIssuesBySeverity({
102232 return _t('commit.outstanding_errors_message', {
102236 var hasChangesetComment = context.changeset && context.changeset.tags.comment && context.changeset.tags.comment.trim().length;
102238 if (!hasChangesetComment) {
102239 return _t('commit.comment_needed_message');
102246 function changeTags(_, changed, onInput) {
102247 if (changed.hasOwnProperty('comment')) {
102248 if (changed.comment === undefined) {
102253 corePreferences('comment', changed.comment);
102254 corePreferences('commentDate', Date.now());
102258 if (changed.hasOwnProperty('source')) {
102259 if (changed.source === undefined) {
102260 corePreferences('source', null);
102262 corePreferences('source', changed.source);
102263 corePreferences('commentDate', Date.now());
102265 } // no need to update `prefs` for `hashtags` here since it's done in `updateChangeset`
102268 updateChangeset(changed, onInput);
102271 _selection.call(render);
102275 function findHashtags(tags, commentOnly) {
102276 var detectedHashtags = commentHashtags();
102278 if (detectedHashtags.length) {
102279 // always remove stored hashtags if there are hashtags in the comment - #4304
102280 corePreferences('hashtags', null);
102283 if (!detectedHashtags.length || !commentOnly) {
102284 detectedHashtags = detectedHashtags.concat(hashtagHashtags());
102287 var allLowerCase = new Set();
102288 return detectedHashtags.filter(function (hashtag) {
102289 // Compare tags as lowercase strings, but keep original case tags
102290 var lowerCase = hashtag.toLowerCase();
102292 if (!allLowerCase.has(lowerCase)) {
102293 allLowerCase.add(lowerCase);
102298 }); // Extract hashtags from `comment`
102300 function commentHashtags() {
102301 var matches = (tags.comment || '').replace(/http\S*/g, '') // drop anything that looks like a URL - #4289
102304 } // Extract and clean hashtags from `hashtags`
102307 function hashtagHashtags() {
102308 var matches = (tags.hashtags || '').split(/[,;\s]+/).map(function (s) {
102314 var matched = s.match(hashtagRegex);
102315 return matched && matched[0];
102316 }).filter(Boolean); // exclude falsy
102322 function isReviewRequested(tags) {
102323 var rr = tags.review_requested;
102324 if (rr === undefined) return false;
102325 rr = rr.trim().toLowerCase();
102326 return !(rr === '' || rr === 'no');
102329 function updateChangeset(changed, onInput) {
102330 var tags = Object.assign({}, context.changeset.tags); // shallow copy
102332 Object.keys(changed).forEach(function (k) {
102334 k = context.cleanTagKey(k);
102335 if (readOnlyTags.indexOf(k) !== -1) return;
102342 tags[k] = context.cleanTagValue(v);
102347 // when changing the comment, override hashtags with any found in comment.
102348 var commentOnly = changed.hasOwnProperty('comment') && changed.comment !== '';
102349 var arr = findHashtags(tags, commentOnly);
102352 tags.hashtags = context.cleanTagValue(arr.join(';'));
102353 corePreferences('hashtags', tags.hashtags);
102356 corePreferences('hashtags', null);
102358 } // always update userdetails, just in case user reauthenticates as someone else
102361 if (_userDetails && _userDetails.changesets_count !== undefined) {
102362 var changesetsCount = parseInt(_userDetails.changesets_count, 10) + 1; // #4283
102364 tags.changesets_count = String(changesetsCount); // first 100 edits - new user
102366 if (changesetsCount <= 100) {
102368 s = corePreferences('walkthrough_completed');
102371 tags['ideditor:walkthrough_completed'] = s;
102374 s = corePreferences('walkthrough_progress');
102377 tags['ideditor:walkthrough_progress'] = s;
102380 s = corePreferences('walkthrough_started');
102383 tags['ideditor:walkthrough_started'] = s;
102387 delete tags.changesets_count;
102390 if (!fastDeepEqual(context.changeset.tags, tags)) {
102391 context.changeset = context.changeset.update({
102397 commit.reset = function () {
102398 context.changeset = null;
102401 return utilRebind(commit, dispatch, 'on');
102404 function uiConfirm(selection) {
102405 var modalSelection = uiModal(selection);
102406 modalSelection.select('.modal').classed('modal-alert', true);
102407 var section = modalSelection.select('.content');
102408 section.append('div').attr('class', 'modal-section header');
102409 section.append('div').attr('class', 'modal-section message-text');
102410 var buttons = section.append('div').attr('class', 'modal-section buttons cf');
102412 modalSelection.okButton = function () {
102413 buttons.append('button').attr('class', 'button ok-button action').on('click.confirm', function () {
102414 modalSelection.remove();
102415 }).call(_t.append('confirm.okay')).node().focus();
102422 function uiConflicts(context) {
102423 var dispatch = dispatch$8('cancel', 'save');
102424 var keybinding = utilKeybinding('conflicts');
102430 var _shownConflictIndex;
102432 function keybindingOn() {
102433 select(document).call(keybinding.on('⎋', cancel, true));
102436 function keybindingOff() {
102437 select(document).call(keybinding.unbind);
102447 dispatch.call('cancel');
102450 function conflicts(selection) {
102452 var headerEnter = selection.selectAll('.header').data([0]).enter().append('div').attr('class', 'header fillL');
102453 headerEnter.append('button').attr('class', 'fr').attr('title', _t('icons.close')).on('click', cancel).call(svgIcon('#iD-icon-close'));
102454 headerEnter.append('h2').call(_t.append('save.conflict.header'));
102455 var bodyEnter = selection.selectAll('.body').data([0]).enter().append('div').attr('class', 'body fillL');
102456 var conflictsHelpEnter = bodyEnter.append('div').attr('class', 'conflicts-help').call(_t.append('save.conflict.help')); // Download changes link
102458 var detected = utilDetect();
102459 var changeset = new osmChangeset();
102460 delete changeset.id; // Export without changeset_id
102462 var data = JXON.stringify(changeset.osmChangeJXON(_origChanges));
102463 var blob = new Blob([data], {
102464 type: 'text/xml;charset=utf-8;'
102466 var fileName = 'changes.osc';
102467 var linkEnter = conflictsHelpEnter.selectAll('.download-changes').append('a').attr('class', 'download-changes');
102469 if (detected.download) {
102470 // All except IE11 and Edge
102471 linkEnter // download the data as a file
102472 .attr('href', window.URL.createObjectURL(blob)).attr('download', fileName);
102475 linkEnter // open data uri in a new tab
102476 .attr('target', '_blank').on('click.download', function () {
102477 navigator.msSaveBlob(blob, fileName);
102481 linkEnter.call(svgIcon('#iD-icon-load', 'inline')).append('span').call(_t.append('save.conflict.download_changes'));
102482 bodyEnter.append('div').attr('class', 'conflict-container fillL3').call(showConflict, 0);
102483 bodyEnter.append('div').attr('class', 'conflicts-done').attr('opacity', 0).style('display', 'none').call(_t.append('save.conflict.done'));
102484 var buttonsEnter = bodyEnter.append('div').attr('class', 'buttons col12 joined conflicts-buttons');
102485 buttonsEnter.append('button').attr('disabled', _conflictList.length > 1).attr('class', 'action conflicts-button col6').call(_t.append('save.title')).on('click.try_again', tryAgain);
102486 buttonsEnter.append('button').attr('class', 'secondary-action conflicts-button col6').call(_t.append('confirm.cancel')).on('click.cancel', cancel);
102489 function showConflict(selection, index) {
102490 index = utilWrap(index, _conflictList.length);
102491 _shownConflictIndex = index;
102492 var parent = select(selection.node().parentNode); // enable save button if this is the last conflict being reviewed..
102494 if (index === _conflictList.length - 1) {
102495 window.setTimeout(function () {
102496 parent.select('.conflicts-button').attr('disabled', null);
102497 parent.select('.conflicts-done').transition().attr('opacity', 1).style('display', 'block');
102501 var conflict = selection.selectAll('.conflict').data([_conflictList[index]]);
102502 conflict.exit().remove();
102503 var conflictEnter = conflict.enter().append('div').attr('class', 'conflict');
102504 conflictEnter.append('h4').attr('class', 'conflict-count').call(_t.append('save.conflict.count', {
102506 total: _conflictList.length
102508 conflictEnter.append('a').attr('class', 'conflict-description').attr('href', '#').text(function (d) {
102510 }).on('click', function (d3_event, d) {
102511 d3_event.preventDefault();
102514 var details = conflictEnter.append('div').attr('class', 'conflict-detail-container');
102515 details.append('ul').attr('class', 'conflict-detail-list').selectAll('li').data(function (d) {
102516 return d.details || [];
102517 }).enter().append('li').attr('class', 'conflict-detail-item').html(function (d) {
102520 details.append('div').attr('class', 'conflict-choices').call(addChoices);
102521 details.append('div').attr('class', 'conflict-nav-buttons joined cf').selectAll('button').data(['previous', 'next']).enter().append('button').html(function (d) {
102522 return _t.html('save.conflict.' + d);
102523 }).attr('class', 'conflict-nav-button action col6').attr('disabled', function (d, i) {
102524 return i === 0 && index === 0 || i === 1 && index === _conflictList.length - 1 || null;
102525 }).on('click', function (d3_event, d) {
102526 d3_event.preventDefault();
102527 var container = parent.selectAll('.conflict-container');
102528 var sign = d === 'previous' ? -1 : 1;
102529 container.selectAll('.conflict').remove();
102530 container.call(showConflict, index + sign);
102534 function addChoices(selection) {
102535 var choices = selection.append('ul').attr('class', 'layer-list').selectAll('li').data(function (d) {
102536 return d.choices || [];
102539 var choicesEnter = choices.enter().append('li').attr('class', 'layer');
102540 var labelEnter = choicesEnter.append('label');
102541 labelEnter.append('input').attr('type', 'radio').attr('name', function (d) {
102543 }).on('change', function (d3_event, d) {
102544 var ul = this.parentNode.parentNode.parentNode;
102545 ul.__data__.chosen = d.id;
102546 choose(d3_event, ul, d);
102548 labelEnter.append('span').text(function (d) {
102552 choicesEnter.merge(choices).each(function (d) {
102553 var ul = this.parentNode;
102555 if (ul.__data__.chosen === d.id) {
102561 function choose(d3_event, ul, datum) {
102562 if (d3_event) d3_event.preventDefault();
102563 select(ul).selectAll('li').classed('active', function (d) {
102565 }).selectAll('input').property('checked', function (d) {
102568 var extent = geoExtent();
102570 entity = context.graph().hasEntity(datum.id);
102571 if (entity) extent._extend(entity.extent(context.graph()));
102573 entity = context.graph().hasEntity(datum.id);
102574 if (entity) extent._extend(entity.extent(context.graph()));
102575 zoomToEntity(datum.id, extent);
102578 function zoomToEntity(id, extent) {
102579 context.surface().selectAll('.hover').classed('hover', false);
102580 var entity = context.graph().hasEntity(id);
102584 context.map().trimmedExtent(extent);
102586 context.map().zoomToEase(entity);
102589 context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph())).classed('hover', true);
102591 } // The conflict list should be an array of objects like:
102594 // name: entityName(local),
102595 // details: merge.conflicts(),
102598 // choice(id, keepMine, forceLocal),
102599 // choice(id, keepTheirs, forceRemote)
102604 conflicts.conflictList = function (_) {
102605 if (!arguments.length) return _conflictList;
102610 conflicts.origChanges = function (_) {
102611 if (!arguments.length) return _origChanges;
102616 conflicts.shownEntityIds = function () {
102617 if (_conflictList && typeof _shownConflictIndex === 'number') {
102618 return [_conflictList[_shownConflictIndex].id];
102624 return utilRebind(conflicts, dispatch, 'on');
102627 function uiSectionEntityIssues(context) {
102628 // Does the user prefer to expand the active issue? Useful for viewing tag diff.
102629 // Expand by default so first timers see it - #6408, #8143
102630 var preference = corePreferences('entity-issues.reference.expanded');
102632 var _expanded = preference === null ? true : preference === 'true';
102639 var section = uiSection('entity-issues', context).shouldDisplay(function () {
102640 return _issues.length > 0;
102642 return _t.html('inspector.title_count', {
102644 html: _t.html('issues.list_title')
102648 }).disclosureContent(renderDisclosureContent);
102649 context.validator().on('validated.entity_issues', function () {
102650 // Refresh on validated events
102653 }).on('focusedIssue.entity_issues', function (issue) {
102654 makeActiveIssue(issue.id);
102657 function reloadIssues() {
102658 _issues = context.validator().getSharedEntityIssues(_entityIDs, {
102659 includeDisabledRules: true
102663 function makeActiveIssue(issueID) {
102664 _activeIssueID = issueID;
102665 section.selection().selectAll('.issue-container').classed('active', function (d) {
102666 return d.id === _activeIssueID;
102670 function renderDisclosureContent(selection) {
102671 selection.classed('grouped-items-area', true);
102672 _activeIssueID = _issues.length > 0 ? _issues[0].id : null;
102673 var containers = selection.selectAll('.issue-container').data(_issues, function (d) {
102677 containers.exit().remove(); // Enter
102679 var containersEnter = containers.enter().append('div').attr('class', 'issue-container');
102680 var itemsEnter = containersEnter.append('div').attr('class', function (d) {
102681 return 'issue severity-' + d.severity;
102682 }).on('mouseover.highlight', function (d3_event, d) {
102683 // don't hover-highlight the selected entity
102684 var ids = d.entityIds.filter(function (e) {
102685 return _entityIDs.indexOf(e) === -1;
102687 utilHighlightEntities(ids, true, context);
102688 }).on('mouseout.highlight', function (d3_event, d) {
102689 var ids = d.entityIds.filter(function (e) {
102690 return _entityIDs.indexOf(e) === -1;
102692 utilHighlightEntities(ids, false, context);
102694 var labelsEnter = itemsEnter.append('div').attr('class', 'issue-label');
102695 var textEnter = labelsEnter.append('button').attr('class', 'issue-text').on('click', function (d3_event, d) {
102696 makeActiveIssue(d.id); // expand only the clicked item
102698 var extent = d.extent(context.graph());
102701 var setZoom = Math.max(context.map().zoom(), 19);
102702 context.map().unobscuredCenterZoomEase(extent.center(), setZoom);
102705 textEnter.each(function (d) {
102706 var iconName = '#iD-icon-' + (d.severity === 'warning' ? 'alert' : 'error');
102707 select(this).call(svgIcon(iconName, 'issue-icon'));
102709 textEnter.append('span').attr('class', 'issue-message');
102710 var infoButton = labelsEnter.append('button').attr('class', 'issue-info-button').attr('title', _t('icons.information')).call(svgIcon('#iD-icon-inspect'));
102711 infoButton.on('click', function (d3_event) {
102712 d3_event.stopPropagation();
102713 d3_event.preventDefault();
102714 this.blur(); // avoid keeping focus on the button - #4641
102716 var container = select(this.parentNode.parentNode.parentNode);
102717 var info = container.selectAll('.issue-info');
102718 var isExpanded = info.classed('expanded');
102719 _expanded = !isExpanded;
102720 corePreferences('entity-issues.reference.expanded', _expanded); // update preference
102723 info.transition().duration(200).style('max-height', '0px').style('opacity', '0').on('end', function () {
102724 info.classed('expanded', false);
102727 info.classed('expanded', true).transition().duration(200).style('max-height', '200px').style('opacity', '1').on('end', function () {
102728 info.style('max-height', null);
102732 itemsEnter.append('ul').attr('class', 'issue-fix-list');
102733 containersEnter.append('div').attr('class', 'issue-info' + (_expanded ? ' expanded' : '')).style('max-height', _expanded ? null : '0').style('opacity', _expanded ? '1' : '0').each(function (d) {
102734 if (typeof d.reference === 'function') {
102735 select(this).call(d.reference);
102737 select(this).call(_t.append('inspector.no_documentation_key'));
102741 containers = containers.merge(containersEnter).classed('active', function (d) {
102742 return d.id === _activeIssueID;
102744 containers.selectAll('.issue-message').html(function (d) {
102745 return d.message(context);
102748 var fixLists = containers.selectAll('.issue-fix-list');
102749 var fixes = fixLists.selectAll('.issue-fix-item').data(function (d) {
102750 return d.fixes ? d.fixes(context) : [];
102755 var fixesEnter = fixes.enter().append('li').attr('class', 'issue-fix-item');
102756 var buttons = fixesEnter.append('button').on('click', function (d3_event, d) {
102757 // not all fixes are actionable
102758 if (select(this).attr('disabled') || !d.onClick) return; // Don't run another fix for this issue within a second of running one
102759 // (Necessary for "Select a feature type" fix. Most fixes should only ever run once)
102761 if (d.issue.dateLastRanFix && new Date() - d.issue.dateLastRanFix < 1000) return;
102762 d.issue.dateLastRanFix = new Date(); // remove hover-highlighting
102764 utilHighlightEntities(d.issue.entityIds.concat(d.entityIds), false, context);
102765 new Promise(function (resolve, reject) {
102766 d.onClick(context, resolve, reject);
102768 if (d.onClick.length <= 1) {
102769 // if the fix doesn't take any completion parameters then consider it resolved
102773 // revalidate whenever the fix has finished running successfully
102774 context.validator().validate();
102776 }).on('mouseover.highlight', function (d3_event, d) {
102777 utilHighlightEntities(d.entityIds, true, context);
102778 }).on('mouseout.highlight', function (d3_event, d) {
102779 utilHighlightEntities(d.entityIds, false, context);
102781 buttons.each(function (d) {
102782 var iconName = d.icon || 'iD-icon-wrench';
102784 if (iconName.startsWith('maki')) {
102788 select(this).call(svgIcon('#' + iconName, 'fix-icon'));
102790 buttons.append('span').attr('class', 'fix-message').html(function (d) {
102793 fixesEnter.merge(fixes).selectAll('button').classed('actionable', function (d) {
102795 }).attr('disabled', function (d) {
102796 return d.onClick ? null : 'true';
102797 }).attr('title', function (d) {
102798 if (d.disabledReason) {
102799 return d.disabledReason;
102806 section.entityIDs = function (val) {
102807 if (!arguments.length) return _entityIDs;
102809 if (!_entityIDs || !val || !utilArrayIdentical(_entityIDs, val)) {
102821 function uiPresetIcon() {
102826 var _sizeClass = 'medium';
102829 return _sizeClass === 'small';
102832 function presetIcon(selection) {
102833 selection.each(render);
102836 function getIcon(p, geom) {
102837 if (isSmall() && p.isFallback && p.isFallback()) return 'iD-icon-' + p.id;
102838 if (p.icon) return p.icon;
102839 if (geom === 'line') return 'iD-other-line';
102840 if (geom === 'vertex') return p.isFallback() ? '' : 'temaki-vertex';
102841 if (isSmall() && geom === 'point') return '';
102842 return 'maki-marker-stroked';
102845 function renderPointBorder(container, drawPoint) {
102846 var pointBorder = container.selectAll('.preset-icon-point-border').data(drawPoint ? [0] : []);
102847 pointBorder.exit().remove();
102848 var pointBorderEnter = pointBorder.enter();
102851 pointBorderEnter.append('svg').attr('class', 'preset-icon-fill preset-icon-point-border').attr('width', w).attr('height', h).attr('viewBox', "0 0 ".concat(w, " ").concat(h)).append('path').attr('transform', 'translate(11.5, 8)').attr('d', 'M 17,8 C 17,13 11,21 8.5,23.5 C 6,21 0,13 0,8 C 0,4 4,-0.5 8.5,-0.5 C 13,-0.5 17,4 17,8 z');
102852 pointBorder = pointBorderEnter.merge(pointBorder);
102855 function renderCategoryBorder(container, category) {
102856 var categoryBorder = container.selectAll('.preset-icon-category-border').data(category ? [0] : []);
102857 categoryBorder.exit().remove();
102858 var categoryBorderEnter = categoryBorder.enter();
102860 var svgEnter = categoryBorderEnter.append('svg').attr('class', 'preset-icon-fill preset-icon-category-border').attr('width', d).attr('height', d).attr('viewBox', "0 0 ".concat(d, " ").concat(d));
102861 svgEnter.append('path').attr('class', 'area').attr('d', 'M9.5,7.5 L25.5,7.5 L28.5,12.5 L49.5,12.5 C51.709139,12.5 53.5,14.290861 53.5,16.5 L53.5,43.5 C53.5,45.709139 51.709139,47.5 49.5,47.5 L10.5,47.5 C8.290861,47.5 6.5,45.709139 6.5,43.5 L6.5,12.5 L9.5,7.5 Z');
102862 categoryBorder = categoryBorderEnter.merge(categoryBorder);
102865 categoryBorder.selectAll('path').attr('class', "area ".concat(category.id));
102869 function renderCircleFill(container, drawVertex) {
102870 var vertexFill = container.selectAll('.preset-icon-fill-vertex').data(drawVertex ? [0] : []);
102871 vertexFill.exit().remove();
102872 var vertexFillEnter = vertexFill.enter();
102876 vertexFillEnter.append('svg').attr('class', 'preset-icon-fill preset-icon-fill-vertex').attr('width', w).attr('height', h).attr('viewBox', "0 0 ".concat(w, " ").concat(h)).append('circle').attr('cx', w / 2).attr('cy', h / 2).attr('r', d / 2);
102877 vertexFill = vertexFillEnter.merge(vertexFill);
102880 function renderSquareFill(container, drawArea, tagClasses) {
102881 var fill = container.selectAll('.preset-icon-fill-area').data(drawArea ? [0] : []);
102883 var fillEnter = fill.enter();
102884 var d = isSmall() ? 40 : 60;
102890 fillEnter = fillEnter.append('svg').attr('class', 'preset-icon-fill preset-icon-fill-area').attr('width', w).attr('height', h).attr('viewBox', "0 0 ".concat(w, " ").concat(h));
102891 ['fill', 'stroke'].forEach(function (klass) {
102892 fillEnter.append('path').attr('d', "M".concat(c1, " ").concat(c1, " L").concat(c1, " ").concat(c2, " L").concat(c2, " ").concat(c2, " L").concat(c2, " ").concat(c1, " Z")).attr('class', "area ".concat(klass));
102895 [[c1, c1], [c1, c2], [c2, c2], [c2, c1]].forEach(function (point) {
102896 fillEnter.append('circle').attr('class', 'vertex').attr('cx', point[0]).attr('cy', point[1]).attr('r', rVertex);
102901 [[c1, w / 2], [c2, w / 2], [h / 2, c1], [h / 2, c2]].forEach(function (point) {
102902 fillEnter.append('circle').attr('class', 'midpoint').attr('cx', point[0]).attr('cy', point[1]).attr('r', rMidpoint);
102906 fill = fillEnter.merge(fill);
102907 fill.selectAll('path.stroke').attr('class', "area stroke ".concat(tagClasses));
102908 fill.selectAll('path.fill').attr('class', "area fill ".concat(tagClasses));
102911 function renderLine(container, drawLine, tagClasses) {
102912 var line = container.selectAll('.preset-icon-line').data(drawLine ? [0] : []);
102914 var lineEnter = line.enter();
102915 var d = isSmall() ? 40 : 60; // draw the line parametrically
102919 var y = Math.round(d * 0.72);
102920 var l = Math.round(d * 0.6);
102924 lineEnter = lineEnter.append('svg').attr('class', 'preset-icon-line').attr('width', w).attr('height', h).attr('viewBox', "0 0 ".concat(w, " ").concat(h));
102925 ['casing', 'stroke'].forEach(function (klass) {
102926 lineEnter.append('path').attr('d', "M".concat(x1, " ").concat(y, " L").concat(x2, " ").concat(y)).attr('class', "line ".concat(klass));
102928 [[x1 - 1, y], [x2 + 1, y]].forEach(function (point) {
102929 lineEnter.append('circle').attr('class', 'vertex').attr('cx', point[0]).attr('cy', point[1]).attr('r', r);
102931 line = lineEnter.merge(line);
102932 line.selectAll('path.stroke').attr('class', "line stroke ".concat(tagClasses));
102933 line.selectAll('path.casing').attr('class', "line casing ".concat(tagClasses));
102936 function renderRoute(container, drawRoute, p) {
102937 var route = container.selectAll('.preset-icon-route').data(drawRoute ? [0] : []);
102939 var routeEnter = route.enter();
102940 var d = isSmall() ? 40 : 60; // draw the route parametrically
102944 var y1 = Math.round(d * 0.80);
102945 var y2 = Math.round(d * 0.68);
102946 var l = Math.round(d * 0.6);
102952 routeEnter = routeEnter.append('svg').attr('class', 'preset-icon-route').attr('width', w).attr('height', h).attr('viewBox', "0 0 ".concat(w, " ").concat(h));
102953 ['casing', 'stroke'].forEach(function (klass) {
102954 routeEnter.append('path').attr('d', "M".concat(x1, " ").concat(y1, " L").concat(x2, " ").concat(y2)).attr('class', "segment0 line ".concat(klass));
102955 routeEnter.append('path').attr('d', "M".concat(x2, " ").concat(y2, " L").concat(x3, " ").concat(y1)).attr('class', "segment1 line ".concat(klass));
102956 routeEnter.append('path').attr('d', "M".concat(x3, " ").concat(y1, " L").concat(x4, " ").concat(y2)).attr('class', "segment2 line ".concat(klass));
102958 [[x1, y1], [x2, y2], [x3, y1], [x4, y2]].forEach(function (point) {
102959 routeEnter.append('circle').attr('class', 'vertex').attr('cx', point[0]).attr('cy', point[1]).attr('r', r);
102961 route = routeEnter.merge(route);
102964 var routeType = p.tags.type === 'waterway' ? 'waterway' : p.tags.route;
102965 var segmentPresetIDs = routeSegments[routeType];
102967 for (var i in segmentPresetIDs) {
102968 var segmentPreset = _mainPresetIndex.item(segmentPresetIDs[i]);
102969 var segmentTagClasses = svgTagClasses().getClassesString(segmentPreset.tags, '');
102970 route.selectAll("path.stroke.segment".concat(i)).attr('class', "segment".concat(i, " line stroke ").concat(segmentTagClasses));
102971 route.selectAll("path.casing.segment".concat(i)).attr('class', "segment".concat(i, " line casing ").concat(segmentTagClasses));
102976 function renderSvgIcon(container, picon, geom, isFramed, category, tagClasses) {
102977 var isMaki = picon && /^maki-/.test(picon);
102978 var isTemaki = picon && /^temaki-/.test(picon);
102979 var isFa = picon && /^fa[srb]-/.test(picon);
102980 var isiDIcon = picon && !(isMaki || isTemaki || isFa);
102981 var icon = container.selectAll('.preset-icon').data(picon ? [0] : []);
102983 icon = icon.enter().append('div').attr('class', 'preset-icon').call(svgIcon('')).merge(icon);
102984 icon.attr('class', 'preset-icon ' + (geom ? geom + '-geom' : '')).classed('category', category).classed('framed', isFramed).classed('preset-icon-iD', isiDIcon);
102985 icon.selectAll('svg').attr('class', 'icon ' + picon + ' ' + (!isiDIcon && geom !== 'line' ? '' : tagClasses));
102989 suffix = isSmall() && geom === 'point' ? '-11' : '-15';
102992 icon.selectAll('use').attr('href', '#' + picon + suffix);
102995 function renderImageIcon(container, imageURL) {
102996 var imageIcon = container.selectAll('img.image-icon').data(imageURL ? [0] : []);
102997 imageIcon.exit().remove();
102998 imageIcon = imageIcon.enter().append('img').attr('class', 'image-icon').on('load', function () {
102999 return container.classed('showing-img', true);
103000 }).on('error', function () {
103001 return container.classed('showing-img', false);
103003 imageIcon.attr('src', imageURL);
103004 } // Route icons are drawn with a zigzag annotation underneath:
103008 // This dataset defines the styles that are used to draw the zigzag segments.
103012 bicycle: ['highway/cycleway', 'highway/cycleway', 'highway/cycleway'],
103013 bus: ['highway/unclassified', 'highway/secondary', 'highway/primary'],
103014 trolleybus: ['highway/unclassified', 'highway/secondary', 'highway/primary'],
103015 detour: ['highway/tertiary', 'highway/residential', 'highway/unclassified'],
103016 ferry: ['route/ferry', 'route/ferry', 'route/ferry'],
103017 foot: ['highway/footway', 'highway/footway', 'highway/footway'],
103018 hiking: ['highway/path', 'highway/path', 'highway/path'],
103019 horse: ['highway/bridleway', 'highway/bridleway', 'highway/bridleway'],
103020 light_rail: ['railway/light_rail', 'railway/light_rail', 'railway/light_rail'],
103021 monorail: ['railway/monorail', 'railway/monorail', 'railway/monorail'],
103022 mtb: ['highway/path', 'highway/track', 'highway/bridleway'],
103023 pipeline: ['man_made/pipeline', 'man_made/pipeline', 'man_made/pipeline'],
103024 piste: ['piste/downhill', 'piste/hike', 'piste/nordic'],
103025 power: ['power/line', 'power/line', 'power/line'],
103026 road: ['highway/secondary', 'highway/primary', 'highway/trunk'],
103027 subway: ['railway/subway', 'railway/subway', 'railway/subway'],
103028 train: ['railway/rail', 'railway/rail', 'railway/rail'],
103029 tram: ['railway/tram', 'railway/tram', 'railway/tram'],
103030 waterway: ['waterway/stream', 'waterway/stream', 'waterway/stream']
103034 var p = _preset.apply(this, arguments);
103036 var geom = _geometry ? _geometry.apply(this, arguments) : null;
103038 if (geom === 'relation' && p.tags && (p.tags.type === 'route' && p.tags.route && routeSegments[p.tags.route] || p.tags.type === 'waterway')) {
103042 var showThirdPartyIcons = corePreferences('preferences.privacy.thirdpartyicons') || 'true';
103043 var isFallback = isSmall() && p.isFallback && p.isFallback();
103044 var imageURL = showThirdPartyIcons === 'true' && p.imageURL;
103045 var picon = getIcon(p, geom);
103046 var isCategory = !p.setTags;
103047 var drawPoint = picon && geom === 'point' && isSmall() && !isFallback;
103048 var drawVertex = picon !== null && geom === 'vertex' && (!isSmall() || !isFallback);
103049 var drawLine = picon && geom === 'line' && !isFallback && !isCategory;
103050 var drawArea = picon && geom === 'area' && !isFallback && !isCategory;
103051 var drawRoute = picon && geom === 'route';
103052 var isFramed = drawVertex || drawArea || drawLine || drawRoute || isCategory;
103053 var tags = !isCategory ? p.setTags({}, geom) : {};
103061 var tagClasses = svgTagClasses().getClassesString(tags, '');
103062 var selection = select(this);
103063 var container = selection.selectAll('.preset-icon-container').data([0]);
103064 container = container.enter().append('div').attr('class', "preset-icon-container ".concat(_sizeClass)).merge(container);
103065 container.classed('showing-img', !!imageURL).classed('fallback', isFallback);
103066 renderCategoryBorder(container, isCategory && p);
103067 renderPointBorder(container, drawPoint);
103068 renderCircleFill(container, drawVertex);
103069 renderSquareFill(container, drawArea, tagClasses);
103070 renderLine(container, drawLine, tagClasses);
103071 renderRoute(container, drawRoute, p);
103072 renderSvgIcon(container, picon, geom, isFramed, isCategory, tagClasses);
103073 renderImageIcon(container, imageURL);
103076 presetIcon.preset = function (val) {
103077 if (!arguments.length) return _preset;
103078 _preset = utilFunctor(val);
103082 presetIcon.geometry = function (val) {
103083 if (!arguments.length) return _geometry;
103084 _geometry = utilFunctor(val);
103088 presetIcon.sizeClass = function (val) {
103089 if (!arguments.length) return _sizeClass;
103097 function uiSectionFeatureType(context) {
103098 var dispatch = dispatch$8('choose');
103104 var section = uiSection('feature-type', context).label(_t.html('inspector.feature_type')).disclosureContent(renderDisclosureContent);
103106 function renderDisclosureContent(selection) {
103107 selection.classed('preset-list-item', true);
103108 selection.classed('mixed-types', _presets.length > 1);
103109 var presetButtonWrap = selection.selectAll('.preset-list-button-wrap').data([0]).enter().append('div').attr('class', 'preset-list-button-wrap');
103110 var presetButton = presetButtonWrap.append('button').attr('class', 'preset-list-button preset-reset').call(uiTooltip().title(_t.html('inspector.back_tooltip')).placement('bottom'));
103111 presetButton.append('div').attr('class', 'preset-icon-container');
103112 presetButton.append('div').attr('class', 'label').append('div').attr('class', 'label-inner');
103113 presetButtonWrap.append('div').attr('class', 'accessory-buttons');
103114 var tagReferenceBodyWrap = selection.selectAll('.tag-reference-body-wrap').data([0]);
103115 tagReferenceBodyWrap = tagReferenceBodyWrap.enter().append('div').attr('class', 'tag-reference-body-wrap').merge(tagReferenceBodyWrap); // update header
103118 selection.selectAll('.preset-list-button-wrap .accessory-buttons').style('display', _presets.length === 1 ? null : 'none').call(_tagReference.button);
103119 tagReferenceBodyWrap.style('display', _presets.length === 1 ? null : 'none').call(_tagReference.body);
103122 selection.selectAll('.preset-reset').on('click', function () {
103123 dispatch.call('choose', this, _presets);
103124 }).on('pointerdown pointerup mousedown mouseup', function (d3_event) {
103125 d3_event.preventDefault();
103126 d3_event.stopPropagation();
103128 var geometries = entityGeometries();
103129 selection.select('.preset-list-item button').call(uiPresetIcon().geometry(_presets.length === 1 ? geometries.length === 1 && geometries[0] : null).preset(_presets.length === 1 ? _presets[0] : _mainPresetIndex.item('point')));
103130 var names = _presets.length === 1 ? [_presets[0].nameLabel(), _presets[0].subtitleLabel()].filter(Boolean) : [_t('inspector.multiple_types')];
103131 var label = selection.select('.label-inner');
103132 var nameparts = label.selectAll('.namepart').data(names, function (d) {
103135 nameparts.exit().remove();
103136 nameparts.enter().append('div').attr('class', 'namepart').html(function (d) {
103141 section.entityIDs = function (val) {
103142 if (!arguments.length) return _entityIDs;
103147 section.presets = function (val) {
103148 if (!arguments.length) return _presets; // don't reload the same preset
103150 if (!utilArrayIdentical(val, _presets)) {
103153 if (_presets.length === 1) {
103154 _tagReference = uiTagReference(_presets[0].reference()).showing(false);
103161 function entityGeometries() {
103164 for (var i in _entityIDs) {
103165 var geometry = context.graph().geometry(_entityIDs[i]);
103166 if (!counts[geometry]) counts[geometry] = 0;
103170 return Object.keys(counts).sort(function (geom1, geom2) {
103171 return counts[geom2] - counts[geom1];
103175 return utilRebind(section, dispatch, 'on');
103178 function uiSectionPresetFields(context) {
103179 var section = uiSection('preset-fields', context).label(_t.html('inspector.fields')).disclosureContent(renderDisclosureContent);
103180 var dispatch = dispatch$8('change', 'revert');
103181 var formFields = uiFormFields(context);
103193 function renderDisclosureContent(selection) {
103195 var graph = context.graph();
103196 var geometries = Object.keys(_entityIDs.reduce(function (geoms, entityID) {
103197 geoms[graph.entity(entityID).geometry(graph)] = true;
103200 var presetsManager = _mainPresetIndex;
103202 var allMoreFields = [];
103205 _presets.forEach(function (preset) {
103206 var fields = preset.fields();
103207 var moreFields = preset.moreFields();
103208 allFields = utilArrayUnion(allFields, fields);
103209 allMoreFields = utilArrayUnion(allMoreFields, moreFields);
103211 if (!sharedTotalFields) {
103212 sharedTotalFields = utilArrayUnion(fields, moreFields);
103214 sharedTotalFields = sharedTotalFields.filter(function (field) {
103215 return fields.indexOf(field) !== -1 || moreFields.indexOf(field) !== -1;
103220 var sharedFields = allFields.filter(function (field) {
103221 return sharedTotalFields.indexOf(field) !== -1;
103223 var sharedMoreFields = allMoreFields.filter(function (field) {
103224 return sharedTotalFields.indexOf(field) !== -1;
103227 sharedFields.forEach(function (field) {
103228 if (field.matchAllGeometry(geometries)) {
103229 _fieldsArr.push(uiField(context, field, _entityIDs));
103232 var singularEntity = _entityIDs.length === 1 && graph.hasEntity(_entityIDs[0]);
103234 if (singularEntity && singularEntity.isHighwayIntersection(graph) && presetsManager.field('restrictions')) {
103235 _fieldsArr.push(uiField(context, presetsManager.field('restrictions'), _entityIDs));
103238 var additionalFields = utilArrayUnion(sharedMoreFields, presetsManager.universal());
103239 additionalFields.sort(function (field1, field2) {
103240 return field1.label().localeCompare(field2.label(), _mainLocalizer.localeCode());
103242 additionalFields.forEach(function (field) {
103243 if (sharedFields.indexOf(field) === -1 && field.matchAllGeometry(geometries)) {
103244 _fieldsArr.push(uiField(context, field, _entityIDs, {
103250 _fieldsArr.forEach(function (field) {
103251 field.on('change', function (t, onInput) {
103252 dispatch.call('change', field, _entityIDs, t, onInput);
103253 }).on('revert', function (keys) {
103254 dispatch.call('revert', field, keys);
103259 _fieldsArr.forEach(function (field) {
103260 field.state(_state).tags(_tags);
103263 selection.call(formFields.fieldsArr(_fieldsArr).state(_state).klass('grouped-items-area'));
103264 selection.selectAll('.wrap-form-field input').on('keydown', function (d3_event) {
103265 // if user presses enter, and combobox is not active, accept edits..
103266 if (d3_event.keyCode === 13 && // ↩ Return
103267 context.container().select('.combobox').empty()) {
103268 context.enter(modeBrowse(context));
103273 section.presets = function (val) {
103274 if (!arguments.length) return _presets;
103276 if (!_presets || !val || !utilArrayIdentical(_presets, val)) {
103284 section.state = function (val) {
103285 if (!arguments.length) return _state;
103290 section.tags = function (val) {
103291 if (!arguments.length) return _tags;
103292 _tags = val; // Don't reset _fieldsArr here.
103297 section.entityIDs = function (val) {
103298 if (!arguments.length) return _entityIDs;
103300 if (!val || !_entityIDs || !utilArrayIdentical(_entityIDs, val)) {
103308 return utilRebind(section, dispatch, 'on');
103311 function uiSectionRawMemberEditor(context) {
103312 var section = uiSection('raw-member-editor', context).shouldDisplay(function () {
103313 if (!_entityIDs || _entityIDs.length !== 1) return false;
103314 var entity = context.hasEntity(_entityIDs[0]);
103315 return entity && entity.type === 'relation';
103317 var entity = context.hasEntity(_entityIDs[0]);
103318 if (!entity) return '';
103319 var gt = entity.members.length > _maxMembers ? '>' : '';
103320 var count = gt + entity.members.slice(0, _maxMembers).length;
103321 return _t.html('inspector.title_count', {
103323 html: _t.html('inspector.members')
103327 }).disclosureContent(renderDisclosureContent);
103328 var taginfo = services.taginfo;
103332 var _maxMembers = 1000;
103334 function downloadMember(d3_event, d) {
103335 d3_event.preventDefault(); // display the loading indicator
103337 select(this.parentNode).classed('tag-reference-loading', true);
103338 context.loadEntity(d.id, function () {
103343 function zoomToMember(d3_event, d) {
103344 d3_event.preventDefault();
103345 var entity = context.entity(d.id);
103346 context.map().zoomToEase(entity); // highlight the feature in case it wasn't previously on-screen
103348 utilHighlightEntities([d.id], true, context);
103351 function selectMember(d3_event, d) {
103352 d3_event.preventDefault(); // remove the hover-highlight styling
103354 utilHighlightEntities([d.id], false, context);
103355 var entity = context.entity(d.id);
103356 var mapExtent = context.map().extent();
103358 if (!entity.intersects(mapExtent, context.graph())) {
103359 // zoom to the entity if its extent is not visible now
103360 context.map().zoomToEase(entity);
103363 context.enter(modeSelect(context, [d.id]));
103366 function changeRole(d3_event, d) {
103368 var newRole = context.cleanRelationRole(select(this).property('value'));
103370 if (oldRole !== newRole) {
103376 context.perform(actionChangeMember(d.relation.id, member, d.index), _t('operations.change_role.annotation', {
103379 context.validator().validate();
103383 function deleteMember(d3_event, d) {
103384 // remove the hover-highlight styling
103385 utilHighlightEntities([d.id], false, context);
103386 context.perform(actionDeleteMember(d.relation.id, d.index), _t('operations.delete_member.annotation', {
103390 if (!context.hasEntity(d.relation.id)) {
103391 // Removing the last member will also delete the relation.
103392 // If this happens we need to exit the selection mode
103393 context.enter(modeBrowse(context));
103395 // Changing the mode also runs `validate`, but otherwise we need to
103397 context.validator().validate();
103401 function renderDisclosureContent(selection) {
103402 var entityID = _entityIDs[0];
103404 var entity = context.entity(entityID);
103405 entity.members.slice(0, _maxMembers).forEach(function (member, index) {
103412 member: context.hasEntity(member.id),
103413 domId: utilUniqueDomId(entityID + '-member-' + index)
103416 var list = selection.selectAll('.member-list').data([0]);
103417 list = list.enter().append('ul').attr('class', 'member-list').merge(list);
103418 var items = list.selectAll('li').data(memberships, function (d) {
103419 return osmEntity.key(d.relation) + ',' + d.index + ',' + (d.member ? osmEntity.key(d.member) : 'incomplete');
103421 items.exit().each(unbind).remove();
103422 var itemsEnter = items.enter().append('li').attr('class', 'member-row form-field').classed('member-incomplete', function (d) {
103425 itemsEnter.each(function (d) {
103426 var item = select(this);
103427 var label = item.append('label').attr('class', 'field-label').attr('for', d.domId);
103430 // highlight the member feature in the map while hovering on the list item
103431 item.on('mouseover', function () {
103432 utilHighlightEntities([d.id], true, context);
103433 }).on('mouseout', function () {
103434 utilHighlightEntities([d.id], false, context);
103436 var labelLink = label.append('span').attr('class', 'label-text').append('a').attr('href', '#').on('click', selectMember);
103437 labelLink.append('span').attr('class', 'member-entity-type').text(function (d) {
103438 var matched = _mainPresetIndex.match(d.member, context.graph());
103439 return matched && matched.name() || utilDisplayType(d.member.id);
103441 labelLink.append('span').attr('class', 'member-entity-name').text(function (d) {
103442 return utilDisplayName(d.member);
103444 label.append('button').attr('title', _t('icons.remove')).attr('class', 'remove member-delete').call(svgIcon('#iD-operation-delete'));
103445 label.append('button').attr('class', 'member-zoom').attr('title', _t('icons.zoom_to')).call(svgIcon('#iD-icon-framed-dot', 'monochrome')).on('click', zoomToMember);
103447 var labelText = label.append('span').attr('class', 'label-text');
103448 labelText.append('span').attr('class', 'member-entity-type').call(_t.append('inspector.' + d.type, {
103451 labelText.append('span').attr('class', 'member-entity-name').call(_t.append('inspector.incomplete', {
103454 label.append('button').attr('class', 'member-download').attr('title', _t('icons.download')).call(svgIcon('#iD-icon-load')).on('click', downloadMember);
103457 var wrapEnter = itemsEnter.append('div').attr('class', 'form-field-input-wrap form-field-input-member');
103458 wrapEnter.append('input').attr('class', 'member-role').attr('id', function (d) {
103460 }).property('type', 'text').attr('placeholder', _t('inspector.role')).call(utilNoAuto);
103463 wrapEnter.each(bindTypeahead);
103467 items = items.merge(itemsEnter).order();
103468 items.select('input.member-role').property('value', function (d) {
103470 }).on('blur', changeRole).on('change', changeRole);
103471 items.select('button.member-delete').on('click', deleteMember);
103472 var dragOrigin, targetIndex;
103473 items.call(d3_drag().on('start', function (d3_event) {
103479 }).on('drag', function (d3_event) {
103480 var x = d3_event.x - dragOrigin.x,
103481 y = d3_event.y - dragOrigin.y;
103482 if (!select(this).classed('dragging') && // don't display drag until dragging beyond a distance threshold
103483 Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) <= 5) return;
103484 var index = items.nodes().indexOf(this);
103485 select(this).classed('dragging', true);
103487 selection.selectAll('li.member-row').style('transform', function (d2, index2) {
103488 var node = select(this).node();
103490 if (index === index2) {
103491 return 'translate(' + x + 'px, ' + y + 'px)';
103492 } else if (index2 > index && d3_event.y > node.offsetTop) {
103493 if (targetIndex === null || index2 > targetIndex) {
103497 return 'translateY(-100%)';
103498 } else if (index2 < index && d3_event.y < node.offsetTop + node.offsetHeight) {
103499 if (targetIndex === null || index2 < targetIndex) {
103503 return 'translateY(100%)';
103508 }).on('end', function (d3_event, d) {
103509 if (!select(this).classed('dragging')) return;
103510 var index = items.nodes().indexOf(this);
103511 select(this).classed('dragging', false);
103512 selection.selectAll('li.member-row').style('transform', null);
103514 if (targetIndex !== null) {
103515 // dragged to a new position, reorder
103516 context.perform(actionMoveMember(d.relation.id, index, targetIndex), _t('operations.reorder_members.annotation'));
103517 context.validator().validate();
103521 function bindTypeahead(d) {
103522 var row = select(this);
103523 var role = row.selectAll('input.member-role');
103524 var origValue = role.property('value');
103526 function sort(value, data) {
103530 for (var i = 0; i < data.length; i++) {
103531 if (data[i].value.substring(0, value.length) === value) {
103532 sameletter.push(data[i]);
103538 return sameletter.concat(other);
103541 role.call(uiCombobox(context, 'member-role').fetcher(function (role, callback) {
103542 // The `geometry` param is used in the `taginfo.js` interface for
103543 // filtering results, as a key into the `tag_members_fractions`
103544 // object. If we don't know the geometry because the member is
103545 // not yet downloaded, it's ok to guess based on type.
103549 geometry = context.graph().geometry(d.member.id);
103550 } else if (d.type === 'relation') {
103552 } else if (d.type === 'way') {
103558 var rtype = entity.tags.type;
103564 }, function (err, data) {
103565 if (!err) callback(sort(role, data));
103567 }).on('cancel', function () {
103568 role.property('value', origValue);
103573 var row = select(this);
103574 row.selectAll('input.member-role').call(uiCombobox.off, context);
103578 section.entityIDs = function (val) {
103579 if (!arguments.length) return _entityIDs;
103587 function actionDeleteMembers(relationId, memberIndexes) {
103588 return function (graph) {
103589 // Remove the members in descending order so removals won't shift what members
103590 // are at the remaining indexes
103591 memberIndexes.sort(function (a, b) {
103595 for (var i in memberIndexes) {
103596 graph = actionDeleteMember(relationId, memberIndexes[i])(graph);
103603 function uiSectionRawMembershipEditor(context) {
103604 var section = uiSection('raw-membership-editor', context).shouldDisplay(function () {
103605 return _entityIDs && _entityIDs.length;
103607 var parents = getSharedParentRelations();
103608 var gt = parents.length > _maxMemberships ? '>' : '';
103609 var count = gt + parents.slice(0, _maxMemberships).length;
103610 return _t.html('inspector.title_count', {
103612 html: _t.html('inspector.relations')
103616 }).disclosureContent(renderDisclosureContent);
103617 var taginfo = services.taginfo;
103618 var nearbyCombo = uiCombobox(context, 'parent-relation').minItems(1).fetcher(fetchNearbyRelations).itemsMouseEnter(function (d3_event, d) {
103619 if (d.relation) utilHighlightEntities([d.relation.id], true, context);
103620 }).itemsMouseLeave(function (d3_event, d) {
103621 if (d.relation) utilHighlightEntities([d.relation.id], false, context);
103628 var _maxMemberships = 1000;
103630 function getSharedParentRelations() {
103633 for (var i = 0; i < _entityIDs.length; i++) {
103634 var entity = context.graph().hasEntity(_entityIDs[i]);
103638 parents = context.graph().parentRelations(entity);
103640 parents = utilArrayIntersection(parents, context.graph().parentRelations(entity));
103643 if (!parents.length) break;
103649 function getMemberships() {
103651 var relations = getSharedParentRelations().slice(0, _maxMemberships);
103652 var isMultiselect = _entityIDs.length > 1;
103653 var i, relation, membership, index, member, indexedMember;
103655 for (i = 0; i < relations.length; i++) {
103656 relation = relations[i];
103660 hash: osmEntity.key(relation)
103663 for (index = 0; index < relation.members.length; index++) {
103664 member = relation.members[index];
103666 if (_entityIDs.indexOf(member.id) !== -1) {
103667 indexedMember = Object.assign({}, member, {
103670 membership.members.push(indexedMember);
103671 membership.hash += ',' + index.toString();
103674 // For single selections, list one entry per membership per relation.
103675 // For multiselections, list one entry per relation.
103676 memberships.push(membership);
103680 hash: osmEntity.key(relation)
103686 if (membership.members.length) memberships.push(membership);
103689 memberships.forEach(function (membership) {
103690 membership.domId = utilUniqueDomId('membership-' + membership.relation.id);
103692 membership.members.forEach(function (member) {
103693 if (roles.indexOf(member.role) === -1) roles.push(member.role);
103695 membership.role = roles.length === 1 ? roles[0] : roles;
103700 function selectRelation(d3_event, d) {
103701 d3_event.preventDefault(); // remove the hover-highlight styling
103703 utilHighlightEntities([d.relation.id], false, context);
103704 context.enter(modeSelect(context, [d.relation.id]));
103707 function zoomToRelation(d3_event, d) {
103708 d3_event.preventDefault();
103709 var entity = context.entity(d.relation.id);
103710 context.map().zoomToEase(entity); // highlight the relation in case it wasn't previously on-screen
103712 utilHighlightEntities([d.relation.id], true, context);
103715 function changeRole(d3_event, d) {
103716 if (d === 0) return; // called on newrow (shouldn't happen)
103718 if (_inChange) return; // avoid accidental recursive call #5731
103720 var newRole = context.cleanRelationRole(select(this).property('value'));
103721 if (!newRole.trim() && typeof d.role !== 'string') return;
103722 var membersToUpdate = d.members.filter(function (member) {
103723 return member.role !== newRole;
103726 if (membersToUpdate.length) {
103728 context.perform(function actionChangeMemberRoles(graph) {
103729 membersToUpdate.forEach(function (member) {
103730 var newMember = Object.assign({}, member, {
103733 delete newMember.index;
103734 graph = actionChangeMember(d.relation.id, newMember, member.index)(graph);
103737 }, _t('operations.change_role.annotation', {
103738 n: membersToUpdate.length
103740 context.validator().validate();
103746 function addMembership(d, role) {
103747 this.blur(); // avoid keeping focus on the button
103751 function actionAddMembers(relationId, ids, role) {
103752 return function (graph) {
103756 type: graph.entity(ids[i]).type,
103759 graph = actionAddMember(relationId, member)(graph);
103767 context.perform(actionAddMembers(d.relation.id, _entityIDs, role), _t('operations.add_member.annotation', {
103770 context.validator().validate();
103772 var relation = osmRelation();
103773 context.perform(actionAddEntity(relation), actionAddMembers(relation.id, _entityIDs, role), _t('operations.add.annotation.relation')); // changing the mode also runs `validate`
103775 context.enter(modeSelect(context, [relation.id]).newFeature(true));
103779 function deleteMembership(d3_event, d) {
103780 this.blur(); // avoid keeping focus on the button
103782 if (d === 0) return; // called on newrow (shouldn't happen)
103783 // remove the hover-highlight styling
103785 utilHighlightEntities([d.relation.id], false, context);
103786 var indexes = d.members.map(function (member) {
103789 context.perform(actionDeleteMembers(d.relation.id, indexes), _t('operations.delete_member.annotation', {
103792 context.validator().validate();
103795 function fetchNearbyRelations(q, callback) {
103798 value: _t('inspector.new_relation'),
103799 display: _t.html('inspector.new_relation')
103801 var entityID = _entityIDs[0];
103803 var graph = context.graph();
103805 function baseDisplayLabel(entity) {
103806 var matched = _mainPresetIndex.match(entity, graph);
103807 var presetName = matched && matched.name() || _t('inspector.relation');
103808 var entityName = utilDisplayName(entity) || '';
103809 return presetName + ' ' + entityName;
103812 var explicitRelation = q && context.hasEntity(q.toLowerCase());
103814 if (explicitRelation && explicitRelation.type === 'relation' && explicitRelation.id !== entityID) {
103815 // loaded relation is specified explicitly, only show that
103817 relation: explicitRelation,
103818 value: baseDisplayLabel(explicitRelation) + ' ' + explicitRelation.id
103821 context.history().intersects(context.map().extent()).forEach(function (entity) {
103822 if (entity.type !== 'relation' || entity.id === entityID) return;
103823 var value = baseDisplayLabel(entity);
103824 if (q && (value + ' ' + entity.id).toLowerCase().indexOf(q.toLowerCase()) === -1) return;
103830 result.sort(function (a, b) {
103831 return osmRelation.creationOrder(a.relation, b.relation);
103832 }); // Dedupe identical names by appending relation id - see #2891
103834 var dupeGroups = Object.values(utilArrayGroupBy(result, 'value')).filter(function (v) {
103837 dupeGroups.forEach(function (group) {
103838 group.forEach(function (obj) {
103839 obj.value += ' ' + obj.relation.id;
103844 result.forEach(function (obj) {
103847 result.unshift(newRelation);
103851 function renderDisclosureContent(selection) {
103852 var memberships = getMemberships();
103853 var list = selection.selectAll('.member-list').data([0]);
103854 list = list.enter().append('ul').attr('class', 'member-list').merge(list);
103855 var items = list.selectAll('li.member-row-normal').data(memberships, function (d) {
103858 items.exit().each(unbind).remove(); // Enter
103860 var itemsEnter = items.enter().append('li').attr('class', 'member-row member-row-normal form-field'); // highlight the relation in the map while hovering on the list item
103862 itemsEnter.on('mouseover', function (d3_event, d) {
103863 utilHighlightEntities([d.relation.id], true, context);
103864 }).on('mouseout', function (d3_event, d) {
103865 utilHighlightEntities([d.relation.id], false, context);
103867 var labelEnter = itemsEnter.append('label').attr('class', 'field-label').attr('for', function (d) {
103870 var labelLink = labelEnter.append('span').attr('class', 'label-text').append('a').attr('href', '#').on('click', selectRelation);
103871 labelLink.append('span').attr('class', 'member-entity-type').text(function (d) {
103872 var matched = _mainPresetIndex.match(d.relation, context.graph());
103873 return matched && matched.name() || _t.html('inspector.relation');
103875 labelLink.append('span').attr('class', 'member-entity-name').text(function (d) {
103876 return utilDisplayName(d.relation);
103878 labelEnter.append('button').attr('class', 'remove member-delete').attr('title', _t('icons.remove')).call(svgIcon('#iD-operation-delete')).on('click', deleteMembership);
103879 labelEnter.append('button').attr('class', 'member-zoom').attr('title', _t('icons.zoom_to')).call(svgIcon('#iD-icon-framed-dot', 'monochrome')).on('click', zoomToRelation);
103880 var wrapEnter = itemsEnter.append('div').attr('class', 'form-field-input-wrap form-field-input-member');
103881 wrapEnter.append('input').attr('class', 'member-role').attr('id', function (d) {
103883 }).property('type', 'text').property('value', function (d) {
103884 return typeof d.role === 'string' ? d.role : '';
103885 }).attr('title', function (d) {
103886 return Array.isArray(d.role) ? d.role.filter(Boolean).join('\n') : d.role;
103887 }).attr('placeholder', function (d) {
103888 return Array.isArray(d.role) ? _t('inspector.multiple_roles') : _t('inspector.role');
103889 }).classed('mixed', function (d) {
103890 return Array.isArray(d.role);
103891 }).call(utilNoAuto).on('blur', changeRole).on('change', changeRole);
103894 wrapEnter.each(bindTypeahead);
103897 var newMembership = list.selectAll('.member-row-new').data(_showBlank ? [0] : []); // Exit
103899 newMembership.exit().remove(); // Enter
103901 var newMembershipEnter = newMembership.enter().append('li').attr('class', 'member-row member-row-new form-field');
103902 var newLabelEnter = newMembershipEnter.append('label').attr('class', 'field-label');
103903 newLabelEnter.append('input').attr('placeholder', _t('inspector.choose_relation')).attr('type', 'text').attr('class', 'member-entity-input').call(utilNoAuto);
103904 newLabelEnter.append('button').attr('class', 'remove member-delete').attr('title', _t('icons.remove')).call(svgIcon('#iD-operation-delete')).on('click', function () {
103905 list.selectAll('.member-row-new').remove();
103907 var newWrapEnter = newMembershipEnter.append('div').attr('class', 'form-field-input-wrap form-field-input-member');
103908 newWrapEnter.append('input').attr('class', 'member-role').property('type', 'text').attr('placeholder', _t('inspector.role')).call(utilNoAuto); // Update
103910 newMembership = newMembership.merge(newMembershipEnter);
103911 newMembership.selectAll('.member-entity-input').on('blur', cancelEntity) // if it wasn't accepted normally, cancel it
103912 .call(nearbyCombo.on('accept', acceptEntity).on('cancel', cancelEntity)); // Container for the Add button
103914 var addRow = selection.selectAll('.add-row').data([0]); // enter
103916 var addRowEnter = addRow.enter().append('div').attr('class', 'add-row');
103917 var addRelationButton = addRowEnter.append('button').attr('class', 'add-relation').attr('aria-label', _t('inspector.add_to_relation'));
103918 addRelationButton.call(svgIcon('#iD-icon-plus', 'light'));
103919 addRelationButton.call(uiTooltip().title(_t.html('inspector.add_to_relation')).placement(_mainLocalizer.textDirection() === 'ltr' ? 'right' : 'left'));
103920 addRowEnter.append('div').attr('class', 'space-value'); // preserve space
103922 addRowEnter.append('div').attr('class', 'space-buttons'); // preserve space
103925 addRow = addRow.merge(addRowEnter);
103926 addRow.select('.add-relation').on('click', function () {
103929 list.selectAll('.member-entity-input').node().focus();
103932 function acceptEntity(d) {
103936 } // remove hover-higlighting
103939 if (d.relation) utilHighlightEntities([d.relation.id], false, context);
103940 var role = context.cleanRelationRole(list.selectAll('.member-row-new .member-role').property('value'));
103941 addMembership(d, role);
103944 function cancelEntity() {
103945 var input = newMembership.selectAll('.member-entity-input');
103946 input.property('value', ''); // remove hover-higlighting
103948 context.surface().selectAll('.highlighted').classed('highlighted', false);
103951 function bindTypeahead(d) {
103952 var row = select(this);
103953 var role = row.selectAll('input.member-role');
103954 var origValue = role.property('value');
103956 function sort(value, data) {
103960 for (var i = 0; i < data.length; i++) {
103961 if (data[i].value.substring(0, value.length) === value) {
103962 sameletter.push(data[i]);
103968 return sameletter.concat(other);
103971 role.call(uiCombobox(context, 'member-role').fetcher(function (role, callback) {
103972 var rtype = d.relation.tags.type;
103976 geometry: context.graph().geometry(_entityIDs[0]),
103978 }, function (err, data) {
103979 if (!err) callback(sort(role, data));
103981 }).on('cancel', function () {
103982 role.property('value', origValue);
103987 var row = select(this);
103988 row.selectAll('input.member-role').call(uiCombobox.off, context);
103992 section.entityIDs = function (val) {
103993 if (!arguments.length) return _entityIDs;
104002 function uiSectionSelectionList(context) {
104004 var section = uiSection('selected-features', context).shouldDisplay(function () {
104005 return _selectedIDs.length > 1;
104007 return _t.html('inspector.title_count', {
104009 html: _t.html('inspector.features')
104011 count: _selectedIDs.length
104013 }).disclosureContent(renderDisclosureContent);
104014 context.history().on('change.selectionList', function (difference) {
104020 section.entityIDs = function (val) {
104021 if (!arguments.length) return _selectedIDs;
104026 function selectEntity(d3_event, entity) {
104027 context.enter(modeSelect(context, [entity.id]));
104030 function deselectEntity(d3_event, entity) {
104031 var selectedIDs = _selectedIDs.slice();
104033 var index = selectedIDs.indexOf(entity.id);
104036 selectedIDs.splice(index, 1);
104037 context.enter(modeSelect(context, selectedIDs));
104041 function renderDisclosureContent(selection) {
104042 var list = selection.selectAll('.feature-list').data([0]);
104043 list = list.enter().append('ul').attr('class', 'feature-list').merge(list);
104045 var entities = _selectedIDs.map(function (id) {
104046 return context.hasEntity(id);
104049 var items = list.selectAll('.feature-list-item').data(entities, osmEntity.key);
104050 items.exit().remove(); // Enter
104052 var enter = items.enter().append('li').attr('class', 'feature-list-item').each(function (d) {
104053 select(this).on('mouseover', function () {
104054 utilHighlightEntities([d.id], true, context);
104055 }).on('mouseout', function () {
104056 utilHighlightEntities([d.id], false, context);
104059 var label = enter.append('button').attr('class', 'label').on('click', selectEntity);
104060 label.append('span').attr('class', 'entity-geom-icon').call(svgIcon('', 'pre-text'));
104061 label.append('span').attr('class', 'entity-type');
104062 label.append('span').attr('class', 'entity-name');
104063 enter.append('button').attr('class', 'close').attr('title', _t('icons.deselect')).on('click', deselectEntity).call(svgIcon('#iD-icon-close')); // Update
104065 items = items.merge(enter);
104066 items.selectAll('.entity-geom-icon use').attr('href', function () {
104067 var entity = this.parentNode.parentNode.__data__;
104068 return '#iD-icon-' + entity.geometry(context.graph());
104070 items.selectAll('.entity-type').text(function (entity) {
104071 return _mainPresetIndex.match(entity, context.graph()).name();
104073 items.selectAll('.entity-name').text(function (d) {
104075 var entity = context.entity(d.id);
104076 return utilDisplayName(entity);
104083 function uiEntityEditor(context) {
104084 var dispatch = dispatch$8('choose');
104086 var _coalesceChanges = false;
104093 var _activePresets = [];
104099 function entityEditor(selection) {
104100 var combinedTags = utilCombinedTags(_entityIDs, context.graph()); // Header
104102 var header = selection.selectAll('.header').data([0]); // Enter
104104 var headerEnter = header.enter().append('div').attr('class', 'header fillL');
104105 var direction = _mainLocalizer.textDirection() === 'rtl' ? 'forward' : 'backward';
104106 headerEnter.append('button').attr('class', 'preset-reset preset-choose').attr('title', _t("icons.".concat(direction))).call(svgIcon("#iD-icon-".concat(direction)));
104107 headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
104108 context.enter(modeBrowse(context));
104109 }).call(svgIcon(_modified ? '#iD-icon-apply' : '#iD-icon-close'));
104110 headerEnter.append('h2'); // Update
104112 header = header.merge(headerEnter);
104113 header.selectAll('h2').html(_entityIDs.length === 1 ? _t.html('inspector.edit') : _t.html('inspector.edit_features'));
104114 header.selectAll('.preset-reset').on('click', function () {
104115 dispatch.call('choose', this, _activePresets);
104118 var body = selection.selectAll('.inspector-body').data([0]); // Enter
104120 var bodyEnter = body.enter().append('div').attr('class', 'entity-editor inspector-body sep-top'); // Update
104122 body = body.merge(bodyEnter);
104125 _sections = [uiSectionSelectionList(context), uiSectionFeatureType(context).on('choose', function (presets) {
104126 dispatch.call('choose', this, presets);
104127 }), uiSectionEntityIssues(context), uiSectionPresetFields(context).on('change', changeTags).on('revert', revertTags), uiSectionRawTagEditor('raw-tag-editor', context).on('change', changeTags), uiSectionRawMemberEditor(context), uiSectionRawMembershipEditor(context)];
104130 _sections.forEach(function (section) {
104131 if (section.entityIDs) {
104132 section.entityIDs(_entityIDs);
104136 section.presets(_activePresets);
104140 section.tags(combinedTags);
104147 body.call(section.render);
104150 context.history().on('change.entity-editor', historyChanged);
104152 function historyChanged(difference) {
104153 if (selection.selectAll('.entity-editor').empty()) return;
104154 if (_state === 'hide') return;
104155 var significant = !difference || difference.didChange.properties || difference.didChange.addition || difference.didChange.deletion;
104156 if (!significant) return;
104157 _entityIDs = _entityIDs.filter(context.hasEntity);
104158 if (!_entityIDs.length) return;
104159 var priorActivePreset = _activePresets.length === 1 && _activePresets[0];
104161 var graph = context.graph();
104162 entityEditor.modified(_base !== graph);
104163 entityEditor(selection);
104165 if (priorActivePreset && _activePresets.length === 1 && priorActivePreset !== _activePresets[0]) {
104166 // flash the button to indicate the preset changed
104167 context.container().selectAll('.entity-editor button.preset-reset .label').style('background-color', '#fff').transition().duration(750).style('background-color', null);
104170 } // Tag changes that fire on input can all get coalesced into a single
104171 // history operation when the user leaves the field. #2342
104172 // Use explicit entityIDs in case the selection changes before the event is fired.
104175 function changeTags(entityIDs, changed, onInput) {
104178 for (var i in entityIDs) {
104179 var entityID = entityIDs[i];
104180 var entity = context.entity(entityID);
104181 var tags = Object.assign({}, entity.tags); // shallow copy
104183 for (var k in changed) {
104187 if (_typeof(v) === 'object') {
104188 // a "key only" tag change
104189 tags[k] = tags[v.oldKey];
104190 } else if (v !== undefined || tags.hasOwnProperty(k)) {
104196 tags = utilCleanTags(tags);
104199 if (!fastDeepEqual(entity.tags, tags)) {
104200 actions.push(actionChangeTags(entityID, tags));
104205 var combinedAction = function combinedAction(graph) {
104206 actions.forEach(function (action) {
104212 var annotation = _t('operations.change_tags.annotation');
104214 if (_coalesceChanges) {
104215 context.overwrite(combinedAction, annotation);
104217 context.perform(combinedAction, annotation);
104218 _coalesceChanges = !!onInput;
104220 } // if leaving field (blur event), rerun validation
104224 context.validator().validate();
104228 function revertTags(keys) {
104231 for (var i in _entityIDs) {
104232 var entityID = _entityIDs[i];
104233 var original = context.graph().base().entities[entityID];
104238 changed[key] = original ? original.tags[key] : undefined;
104241 var entity = context.entity(entityID);
104242 var tags = Object.assign({}, entity.tags); // shallow copy
104244 for (var k in changed) {
104248 if (v !== undefined || tags.hasOwnProperty(k)) {
104253 tags = utilCleanTags(tags);
104255 if (!fastDeepEqual(entity.tags, tags)) {
104256 actions.push(actionChangeTags(entityID, tags));
104261 var combinedAction = function combinedAction(graph) {
104262 actions.forEach(function (action) {
104268 var annotation = _t('operations.change_tags.annotation');
104270 if (_coalesceChanges) {
104271 context.overwrite(combinedAction, annotation);
104273 context.perform(combinedAction, annotation);
104274 _coalesceChanges = false;
104278 context.validator().validate();
104281 entityEditor.modified = function (val) {
104282 if (!arguments.length) return _modified;
104287 entityEditor.state = function (val) {
104288 if (!arguments.length) return _state;
104293 entityEditor.entityIDs = function (val) {
104294 if (!arguments.length) return _entityIDs; // always reload these even if the entityIDs are unchanged, since we
104295 // could be reselecting after something like dragging a node
104297 _base = context.graph();
104298 _coalesceChanges = false;
104299 if (val && _entityIDs && utilArrayIdentical(_entityIDs, val)) return entityEditor; // exit early if no change
104302 loadActivePresets(true);
104303 return entityEditor.modified(false);
104306 entityEditor.newFeature = function (val) {
104307 if (!arguments.length) return _newFeature;
104312 function loadActivePresets(isForNewSelection) {
104313 var graph = context.graph();
104316 for (var i in _entityIDs) {
104317 var entity = graph.hasEntity(_entityIDs[i]);
104319 var match = _mainPresetIndex.match(entity, graph);
104320 if (!counts[match.id]) counts[match.id] = 0;
104324 var matches = Object.keys(counts).sort(function (p1, p2) {
104325 return counts[p2] - counts[p1];
104326 }).map(function (pID) {
104327 return _mainPresetIndex.item(pID);
104330 if (!isForNewSelection) {
104331 // A "weak" preset doesn't set any tags. (e.g. "Address")
104332 var weakPreset = _activePresets.length === 1 && !_activePresets[0].isFallback() && Object.keys(_activePresets[0].addTags || {}).length === 0; // Don't replace a weak preset with a fallback preset (e.g. "Point")
104334 if (weakPreset && matches.length === 1 && matches[0].isFallback()) return;
104337 entityEditor.presets(matches);
104340 entityEditor.presets = function (val) {
104341 if (!arguments.length) return _activePresets; // don't reload the same preset
104343 if (!utilArrayIdentical(val, _activePresets)) {
104350 return utilRebind(entityEditor, dispatch, 'on');
104353 var sexagesimal = {exports: {}};
104355 sexagesimal.exports = element;
104356 var pair_1 = sexagesimal.exports.pair = pair;
104357 sexagesimal.exports.format = format;
104358 sexagesimal.exports.formatPair = formatPair;
104359 sexagesimal.exports.coordToDMS = coordToDMS;
104361 function element(input, dims) {
104362 var result = search(input, dims);
104363 return result === null ? null : result.val;
104366 function formatPair(input) {
104367 return format(input.lat, 'lat') + ' ' + format(input.lon, 'lon');
104368 } // Is 0 North or South?
104371 function format(input, dim) {
104372 var dms = coordToDMS(input, dim);
104373 return dms.whole + '° ' + (dms.minutes ? dms.minutes + '\' ' : '') + (dms.seconds ? dms.seconds + '" ' : '') + dms.dir;
104376 function coordToDMS(input, dim) {
104381 var dir = dirs[input >= 0 ? 0 : 1];
104382 var abs = Math.abs(input);
104383 var whole = Math.floor(abs);
104384 var fraction = abs - whole;
104385 var fractionMinutes = fraction * 60;
104386 var minutes = Math.floor(fractionMinutes);
104387 var seconds = Math.floor((fractionMinutes - minutes) * 60);
104396 function search(input, dims) {
104397 if (!dims) dims = 'NSEW';
104398 if (typeof input !== 'string') return null;
104399 input = input.toUpperCase();
104400 var regex = /^[\s\,]*([NSEW])?\s*([\-|\—|\―]?[0-9.]+)[°º˚]?\s*(?:([0-9.]+)['’′‘]\s*)?(?:([0-9.]+)(?:''|"|”|″)\s*)?([NSEW])?/;
104401 var m = input.match(regex);
104402 if (!m) return null; // no match
104404 var matched = m[0]; // extract dimension.. m[1] = leading, m[5] = trailing
104410 dim = m[1]; // keep leading
104412 matched = matched.slice(0, -1); // remove trailing dimension from match
104415 } // if unrecognized dimension
104418 if (dim && dims.indexOf(dim) === -1) return null; // extract DMS
104420 var deg = m[2] ? parseFloat(m[2]) : 0;
104421 var min = m[3] ? parseFloat(m[3]) / 60 : 0;
104422 var sec = m[4] ? parseFloat(m[4]) / 3600 : 0;
104423 var sign = deg < 0 ? -1 : 1;
104424 if (dim === 'S' || dim === 'W') sign *= -1;
104426 val: (Math.abs(deg) + min + sec) * sign,
104429 remain: input.slice(matched.length)
104433 function pair(input, dims) {
104435 var one = search(input, dims);
104437 input = one.remain.trim();
104438 var two = search(input, dims);
104439 if (!two || two.remain) return null;
104442 return swapdim(one.val, two.val, one.dim);
104444 return [one.val, two.val];
104448 function swapdim(a, b, dim) {
104449 if (dim === 'N' || dim === 'S') return [a, b];
104450 if (dim === 'W' || dim === 'E') return [b, a];
104453 function uiFeatureList(context) {
104456 function featureList(selection) {
104457 var header = selection.append('div').attr('class', 'header fillL');
104458 header.append('h2').call(_t.append('inspector.feature_list'));
104459 var searchWrap = selection.append('div').attr('class', 'search-header');
104460 searchWrap.call(svgIcon('#iD-icon-search', 'pre-text'));
104461 var search = searchWrap.append('input').attr('placeholder', _t('inspector.search')).attr('type', 'search').call(utilNoAuto).on('keypress', keypress).on('keydown', keydown).on('input', inputevent);
104462 var listWrap = selection.append('div').attr('class', 'inspector-body');
104463 var list = listWrap.append('div').attr('class', 'feature-list');
104464 context.on('exit.feature-list', clearSearch);
104465 context.map().on('drawn.feature-list', mapDrawn);
104466 context.keybinding().on(uiCmd('⌘F'), focusSearch);
104468 function focusSearch(d3_event) {
104469 var mode = context.mode() && context.mode().id;
104470 if (mode !== 'browse') return;
104471 d3_event.preventDefault();
104475 function keydown(d3_event) {
104476 if (d3_event.keyCode === 27) {
104482 function keypress(d3_event) {
104483 var q = search.property('value'),
104484 items = list.selectAll('.feature-list-item');
104486 if (d3_event.keyCode === 13 && // ↩ Return
104487 q.length && items.size()) {
104488 click(d3_event, items.datum());
104492 function inputevent() {
104493 _geocodeResults = undefined;
104497 function clearSearch() {
104498 search.property('value', '');
104510 var graph = context.graph();
104511 var visibleCenter = context.map().extent().center();
104512 var q = search.property('value').toLowerCase();
104514 var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
104517 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
104521 type: _t('inspector.location'),
104522 name: dmsCoordinatePair([loc[1], loc[0]]),
104525 } // A location search takes priority over an ID search
104528 var idMatch = !locationMatch && q.match(/(?:^|\W)(node|way|relation|[nwr])\W?0*([1-9]\d*)(?:\W|$)/i);
104531 var elemType = idMatch[1].charAt(0);
104532 var elemId = idMatch[2];
104535 geometry: elemType === 'n' ? 'point' : elemType === 'w' ? 'line' : 'relation',
104536 type: elemType === 'n' ? _t('inspector.node') : elemType === 'w' ? _t('inspector.way') : _t('inspector.relation'),
104541 var allEntities = graph.entities;
104544 for (var id in allEntities) {
104545 var entity = allEntities[id];
104547 var name = utilDisplayName(entity) || '';
104548 if (name.toLowerCase().indexOf(q) < 0) continue;
104549 var matched = _mainPresetIndex.match(entity, graph);
104550 var type = matched && matched.name() || utilDisplayType(entity.id);
104551 var extent = entity.extent(graph);
104552 var distance = extent ? geoSphericalDistance(visibleCenter, extent.center()) : 0;
104556 geometry: entity.geometry(graph),
104561 if (localResults.length > 100) break;
104564 localResults = localResults.sort(function byDistance(a, b) {
104565 return a.distance - b.distance;
104567 result = result.concat(localResults);
104569 (_geocodeResults || []).forEach(function (d) {
104570 if (d.osm_type && d.osm_id) {
104571 // some results may be missing these - #1890
104572 // Make a temporary osmEntity so we can preset match
104573 // and better localize the search result - #4725
104574 var id = osmEntity.id.fromOSM(d.osm_type, d.osm_id);
104576 tags[d["class"]] = d.type;
104583 if (d.osm_type === 'way') {
104584 // for ways, add some fake closed nodes
104585 attrs.nodes = ['a', 'a']; // so that geometry area is possible
104588 var tempEntity = osmEntity(attrs);
104589 var tempGraph = coreGraph([tempEntity]);
104590 var matched = _mainPresetIndex.match(tempEntity, tempGraph);
104591 var type = matched && matched.name() || utilDisplayType(id);
104594 geometry: tempEntity.geometry(tempGraph),
104597 extent: new geoExtent([parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])], [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
104602 if (q.match(/^[0-9]+$/)) {
104603 // if query is just a number, possibly an OSM ID without a prefix
104607 type: _t('inspector.node'),
104613 type: _t('inspector.way'),
104619 type: _t('inspector.relation'),
104628 var value = search.property('value');
104629 var results = features();
104630 list.classed('filtered', value.length);
104631 var resultsIndicator = list.selectAll('.no-results-item').data([0]).enter().append('button').property('disabled', true).attr('class', 'no-results-item').call(svgIcon('#iD-icon-alert', 'pre-text'));
104632 resultsIndicator.append('span').attr('class', 'entity-name');
104633 list.selectAll('.no-results-item .entity-name').html('').call(_t.append('geocoder.no_results_worldwide'));
104635 if (services.geocoder) {
104636 list.selectAll('.geocode-item').data([0]).enter().append('button').attr('class', 'geocode-item secondary-action').on('click', geocoderSearch).append('div').attr('class', 'label').append('span').attr('class', 'entity-name').call(_t.append('geocoder.search'));
104639 list.selectAll('.no-results-item').style('display', value.length && !results.length ? 'block' : 'none');
104640 list.selectAll('.geocode-item').style('display', value && _geocodeResults === undefined ? 'block' : 'none');
104641 list.selectAll('.feature-list-item').data([-1]).remove();
104642 var items = list.selectAll('.feature-list-item').data(results, function (d) {
104645 var enter = items.enter().insert('button', '.geocode-item').attr('class', 'feature-list-item').on('mouseover', mouseover).on('mouseout', mouseout).on('click', click);
104646 var label = enter.append('div').attr('class', 'label');
104647 label.each(function (d) {
104648 select(this).call(svgIcon('#iD-icon-' + d.geometry, 'pre-text'));
104650 label.append('span').attr('class', 'entity-type').text(function (d) {
104653 label.append('span').attr('class', 'entity-name').text(function (d) {
104656 enter.style('opacity', 0).transition().style('opacity', 1);
104661 function mouseover(d3_event, d) {
104662 if (d.id === -1) return;
104663 utilHighlightEntities([d.id], true, context);
104666 function mouseout(d3_event, d) {
104667 if (d.id === -1) return;
104668 utilHighlightEntities([d.id], false, context);
104671 function click(d3_event, d) {
104672 d3_event.preventDefault();
104675 context.map().centerZoomEase([d.location[1], d.location[0]], 19);
104677 utilHighlightEntities([d.id], false, context);
104678 context.enter(modeSelect(context, [d.entity.id]));
104679 context.map().zoomToEase(d.entity);
104681 // download, zoom to, and select the entity with the given ID
104682 context.zoomToEntity(d.id);
104686 function geocoderSearch() {
104687 services.geocoder.search(search.property('value'), function (err, resp) {
104688 _geocodeResults = resp || [];
104697 function uiImproveOsmComments() {
104700 function issueComments(selection) {
104701 // make the div immediately so it appears above the buttons
104702 var comments = selection.selectAll('.comments-container').data([0]);
104703 comments = comments.enter().append('div').attr('class', 'comments-container').merge(comments); // must retrieve comments from API before they can be displayed
104705 services.improveOSM.getComments(_qaItem).then(function (d) {
104706 if (!d.comments) return; // nothing to do here
104708 var commentEnter = comments.selectAll('.comment').data(d.comments).enter().append('div').attr('class', 'comment');
104709 commentEnter.append('div').attr('class', 'comment-avatar').call(svgIcon('#iD-icon-avatar', 'comment-avatar-icon'));
104710 var mainEnter = commentEnter.append('div').attr('class', 'comment-main');
104711 var metadataEnter = mainEnter.append('div').attr('class', 'comment-metadata');
104712 metadataEnter.append('div').attr('class', 'comment-author').each(function (d) {
104713 var osm = services.osm;
104714 var selection = select(this);
104716 if (osm && d.username) {
104717 selection = selection.append('a').attr('class', 'comment-author-link').attr('href', osm.userURL(d.username)).attr('target', '_blank');
104720 selection.text(function (d) {
104724 metadataEnter.append('div').attr('class', 'comment-date').html(function (d) {
104725 return _t.html('note.status.commented', {
104726 when: localeDateString(d.timestamp)
104729 mainEnter.append('div').attr('class', 'comment-text').append('p').text(function (d) {
104732 })["catch"](function (err) {
104733 console.log(err); // eslint-disable-line no-console
104737 function localeDateString(s) {
104744 var d = new Date(s * 1000); // timestamp is served in seconds, date takes ms
104746 if (isNaN(d.getTime())) return null;
104747 return d.toLocaleDateString(_mainLocalizer.localeCode(), options);
104750 issueComments.issue = function (val) {
104751 if (!arguments.length) return _qaItem;
104759 function uiImproveOsmDetails(context) {
104762 function issueDetail(d) {
104763 if (d.desc) return d.desc;
104764 var issueKey = d.issueKey;
104765 d.replacements = d.replacements || {};
104766 d.replacements["default"] = {
104767 html: _t.html('inspector.unknown')
104768 }; // special key `default` works as a fallback string
104770 return _t.html("QA.improveOSM.error_types.".concat(issueKey, ".description"), d.replacements);
104773 function improveOsmDetails(selection) {
104774 var details = selection.selectAll('.error-details').data(_qaItem ? [_qaItem] : [], function (d) {
104775 return "".concat(d.id, "-").concat(d.status || 0);
104777 details.exit().remove();
104778 var detailsEnter = details.enter().append('div').attr('class', 'error-details qa-details-container'); // description
104780 var descriptionEnter = detailsEnter.append('div').attr('class', 'qa-details-subsection');
104781 descriptionEnter.append('h4').call(_t.append('QA.keepRight.detail_description'));
104782 descriptionEnter.append('div').attr('class', 'qa-details-description-text').html(issueDetail); // If there are entity links in the error message..
104784 var relatedEntities = [];
104785 descriptionEnter.selectAll('.error_entity_link, .error_object_link').attr('href', '#').each(function () {
104786 var link = select(this);
104787 var isObjectLink = link.classed('error_object_link');
104788 var entityID = isObjectLink ? utilEntityRoot(_qaItem.objectType) + _qaItem.objectId : this.textContent;
104789 var entity = context.hasEntity(entityID);
104790 relatedEntities.push(entityID); // Add click handler
104792 link.on('mouseenter', function () {
104793 utilHighlightEntities([entityID], true, context);
104794 }).on('mouseleave', function () {
104795 utilHighlightEntities([entityID], false, context);
104796 }).on('click', function (d3_event) {
104797 d3_event.preventDefault();
104798 utilHighlightEntities([entityID], false, context);
104799 var osmlayer = context.layers().layer('osm');
104801 if (!osmlayer.enabled()) {
104802 osmlayer.enabled(true);
104805 context.map().centerZoom(_qaItem.loc, 20);
104808 context.enter(modeSelect(context, [entityID]));
104810 context.loadEntity(entityID, function (err, result) {
104812 var entity = result.data.find(function (e) {
104813 return e.id === entityID;
104815 if (entity) context.enter(modeSelect(context, [entityID]));
104818 }); // Replace with friendly name if possible
104819 // (The entity may not yet be loaded into the graph)
104822 var name = utilDisplayName(entity); // try to use common name
104824 if (!name && !isObjectLink) {
104825 var preset = _mainPresetIndex.match(entity, context.graph());
104826 name = preset && !preset.isFallback() && preset.name(); // fallback to preset name
104833 }); // Don't hide entities related to this error - #5880
104835 context.features().forceVisible(relatedEntities);
104836 context.map().pan([0, 0]); // trigger a redraw
104839 improveOsmDetails.issue = function (val) {
104840 if (!arguments.length) return _qaItem;
104842 return improveOsmDetails;
104845 return improveOsmDetails;
104848 function uiImproveOsmHeader() {
104851 function issueTitle(d) {
104852 var issueKey = d.issueKey;
104853 d.replacements = d.replacements || {};
104854 d.replacements["default"] = {
104855 html: _t.html('inspector.unknown')
104856 }; // special key `default` works as a fallback string
104858 return _t.html("QA.improveOSM.error_types.".concat(issueKey, ".title"), d.replacements);
104861 function improveOsmHeader(selection) {
104862 var header = selection.selectAll('.qa-header').data(_qaItem ? [_qaItem] : [], function (d) {
104863 return "".concat(d.id, "-").concat(d.status || 0);
104865 header.exit().remove();
104866 var headerEnter = header.enter().append('div').attr('class', 'qa-header');
104867 var svgEnter = headerEnter.append('div').attr('class', 'qa-header-icon').classed('new', function (d) {
104869 }).append('svg').attr('width', '20px').attr('height', '30px').attr('viewbox', '0 0 20 30').attr('class', function (d) {
104870 return "preset-icon-28 qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.itemType);
104872 svgEnter.append('polygon').attr('fill', 'currentColor').attr('class', 'qaItem-fill').attr('points', '16,3 4,3 1,6 1,17 4,20 7,20 10,27 13,20 16,20 19,17.033 19,6');
104873 svgEnter.append('use').attr('class', 'icon-annotation').attr('width', '13px').attr('height', '13px').attr('transform', 'translate(3.5, 5)').attr('xlink:href', function (d) {
104879 var isMaki = /^maki-/.test(picon);
104880 return "#".concat(picon).concat(isMaki ? '-11' : '');
104883 headerEnter.append('div').attr('class', 'qa-header-label').html(issueTitle);
104886 improveOsmHeader.issue = function (val) {
104887 if (!arguments.length) return _qaItem;
104889 return improveOsmHeader;
104892 return improveOsmHeader;
104895 function uiImproveOsmEditor(context) {
104896 var dispatch = dispatch$8('change');
104897 var qaDetails = uiImproveOsmDetails(context);
104898 var qaComments = uiImproveOsmComments();
104899 var qaHeader = uiImproveOsmHeader();
104903 function improveOsmEditor(selection) {
104904 var headerEnter = selection.selectAll('.header').data([0]).enter().append('div').attr('class', 'header fillL');
104905 headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
104906 return context.enter(modeBrowse(context));
104907 }).call(svgIcon('#iD-icon-close'));
104908 headerEnter.append('h2').call(_t.append('QA.improveOSM.title'));
104909 var body = selection.selectAll('.body').data([0]);
104910 body = body.enter().append('div').attr('class', 'body').merge(body);
104911 var editor = body.selectAll('.qa-editor').data([0]);
104912 editor.enter().append('div').attr('class', 'modal-section qa-editor').merge(editor).call(qaHeader.issue(_qaItem)).call(qaDetails.issue(_qaItem)).call(qaComments.issue(_qaItem)).call(improveOsmSaveSection);
104915 function improveOsmSaveSection(selection) {
104916 var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
104918 var isShown = _qaItem && (isSelected || _qaItem.newComment || _qaItem.comment);
104919 var saveSection = selection.selectAll('.qa-save').data(isShown ? [_qaItem] : [], function (d) {
104920 return "".concat(d.id, "-").concat(d.status || 0);
104923 saveSection.exit().remove(); // enter
104925 var saveSectionEnter = saveSection.enter().append('div').attr('class', 'qa-save save-section cf');
104926 saveSectionEnter.append('h4').attr('class', '.qa-save-header').call(_t.append('note.newComment'));
104927 saveSectionEnter.append('textarea').attr('class', 'new-comment-input').attr('placeholder', _t('QA.keepRight.comment_placeholder')).attr('maxlength', 1000).property('value', function (d) {
104929 }).call(utilNoAuto).on('input', changeInput).on('blur', changeInput); // update
104931 saveSection = saveSectionEnter.merge(saveSection).call(qaSaveButtons);
104933 function changeInput() {
104934 var input = select(this);
104935 var val = input.property('value').trim();
104939 } // store the unsaved comment with the issue itself
104942 _qaItem = _qaItem.update({
104945 var qaService = services.improveOSM;
104948 qaService.replaceItem(_qaItem);
104951 saveSection.call(qaSaveButtons);
104955 function qaSaveButtons(selection) {
104956 var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
104958 var buttonSection = selection.selectAll('.buttons').data(isSelected ? [_qaItem] : [], function (d) {
104959 return d.status + d.id;
104962 buttonSection.exit().remove(); // enter
104964 var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons');
104965 buttonEnter.append('button').attr('class', 'button comment-button action').call(_t.append('QA.keepRight.save_comment'));
104966 buttonEnter.append('button').attr('class', 'button close-button action');
104967 buttonEnter.append('button').attr('class', 'button ignore-button action'); // update
104969 buttonSection = buttonSection.merge(buttonEnter);
104970 buttonSection.select('.comment-button').attr('disabled', function (d) {
104971 return d.newComment ? null : true;
104972 }).on('click.comment', function (d3_event, d) {
104973 this.blur(); // avoid keeping focus on the button - #4641
104975 var qaService = services.improveOSM;
104978 qaService.postUpdate(d, function (err, item) {
104979 return dispatch.call('change', item);
104983 buttonSection.select('.close-button').html(function (d) {
104984 var andComment = d.newComment ? '_comment' : '';
104985 return _t.html("QA.keepRight.close".concat(andComment));
104986 }).on('click.close', function (d3_event, d) {
104987 this.blur(); // avoid keeping focus on the button - #4641
104989 var qaService = services.improveOSM;
104992 d.newStatus = 'SOLVED';
104993 qaService.postUpdate(d, function (err, item) {
104994 return dispatch.call('change', item);
104998 buttonSection.select('.ignore-button').html(function (d) {
104999 var andComment = d.newComment ? '_comment' : '';
105000 return _t.html("QA.keepRight.ignore".concat(andComment));
105001 }).on('click.ignore', function (d3_event, d) {
105002 this.blur(); // avoid keeping focus on the button - #4641
105004 var qaService = services.improveOSM;
105007 d.newStatus = 'INVALID';
105008 qaService.postUpdate(d, function (err, item) {
105009 return dispatch.call('change', item);
105013 } // NOTE: Don't change method name until UI v3 is merged
105016 improveOsmEditor.error = function (val) {
105017 if (!arguments.length) return _qaItem;
105019 return improveOsmEditor;
105022 return utilRebind(improveOsmEditor, dispatch, 'on');
105025 function uiPresetList(context) {
105026 var dispatch = dispatch$8('cancel', 'choose');
105034 var _autofocus = false;
105036 function presetList(selection) {
105037 if (!_entityIDs) return;
105038 var presets = _mainPresetIndex.matchAllGeometry(entityGeometries());
105040 var messagewrap = selection.append('div').attr('class', 'header fillL');
105041 var message = messagewrap.append('h2').call(_t.append('inspector.choose'));
105042 var direction = _mainLocalizer.textDirection() === 'rtl' ? 'backward' : 'forward';
105043 messagewrap.append('button').attr('class', 'preset-choose').attr('title', direction).on('click', function () {
105044 dispatch.call('cancel', this);
105045 }).call(svgIcon("#iD-icon-".concat(direction)));
105047 function initialKeydown(d3_event) {
105048 // hack to let delete shortcut work when search is autofocused
105049 if (search.property('value').length === 0 && (d3_event.keyCode === utilKeybinding.keyCodes['⌫'] || d3_event.keyCode === utilKeybinding.keyCodes['⌦'])) {
105050 d3_event.preventDefault();
105051 d3_event.stopPropagation();
105052 operationDelete(context, _entityIDs)(); // hack to let undo work when search is autofocused
105053 } else if (search.property('value').length === 0 && (d3_event.ctrlKey || d3_event.metaKey) && d3_event.keyCode === utilKeybinding.keyCodes.z) {
105054 d3_event.preventDefault();
105055 d3_event.stopPropagation();
105057 } else if (!d3_event.ctrlKey && !d3_event.metaKey) {
105058 // don't check for delete/undo hack on future keydown events
105059 select(this).on('keydown', keydown);
105060 keydown.call(this, d3_event);
105064 function keydown(d3_event) {
105066 if (d3_event.keyCode === utilKeybinding.keyCodes['↓'] && // if insertion point is at the end of the string
105067 search.node().selectionStart === search.property('value').length) {
105068 d3_event.preventDefault();
105069 d3_event.stopPropagation(); // move focus to the first item in the preset list
105071 var buttons = list.selectAll('.preset-list-button');
105072 if (!buttons.empty()) buttons.nodes()[0].focus();
105076 function keypress(d3_event) {
105078 var value = search.property('value');
105080 if (d3_event.keyCode === 13 && // ↩ Return
105082 list.selectAll('.preset-list-item:first-child').each(function (d) {
105088 function inputevent() {
105089 var value = search.property('value');
105090 list.classed('filtered', value.length);
105091 var results, messageText;
105094 results = presets.search(value, entityGeometries()[0], _currLoc);
105095 messageText = _t.html('inspector.results', {
105096 n: results.collection.length,
105100 results = _mainPresetIndex.defaults(entityGeometries()[0], 36, !context.inIntro(), _currLoc);
105101 messageText = _t.html('inspector.choose');
105104 list.call(drawList, results);
105105 message.html(messageText);
105108 var searchWrap = selection.append('div').attr('class', 'search-header');
105109 searchWrap.call(svgIcon('#iD-icon-search', 'pre-text'));
105110 var search = searchWrap.append('input').attr('class', 'preset-search-input').attr('placeholder', _t('inspector.search')).attr('type', 'search').call(utilNoAuto).on('keydown', initialKeydown).on('keypress', keypress).on('input', debounce(inputevent));
105113 search.node().focus(); // Safari 14 doesn't always like to focus immediately,
105114 // so try again on the next pass
105116 setTimeout(function () {
105121 var listWrap = selection.append('div').attr('class', 'inspector-body');
105122 var list = listWrap.append('div').attr('class', 'preset-list').call(drawList, _mainPresetIndex.defaults(entityGeometries()[0], 36, !context.inIntro(), _currLoc));
105123 context.features().on('change.preset-list', updateForFeatureHiddenState);
105126 function drawList(list, presets) {
105127 presets = presets.matchAllGeometry(entityGeometries());
105128 var collection = presets.collection.reduce(function (collection, preset) {
105129 if (!preset) return collection;
105132 if (preset.members.collection.filter(function (preset) {
105133 return preset.addable();
105135 collection.push(CategoryItem(preset));
105137 } else if (preset.addable()) {
105138 collection.push(PresetItem(preset));
105143 var items = list.selectAll('.preset-list-item').data(collection, function (d) {
105148 items.enter().append('div').attr('class', function (item) {
105149 return 'preset-list-item preset-' + item.preset.id.replace('/', '-');
105150 }).classed('current', function (item) {
105151 return _currentPresets.indexOf(item.preset) !== -1;
105152 }).each(function (item) {
105153 select(this).call(item);
105154 }).style('opacity', 0).transition().style('opacity', 1);
105155 updateForFeatureHiddenState();
105158 function itemKeydown(d3_event) {
105159 // the actively focused item
105160 var item = select(this.closest('.preset-list-item'));
105161 var parentItem = select(item.node().parentNode.closest('.preset-list-item')); // arrow down, move focus to the next, lower item
105163 if (d3_event.keyCode === utilKeybinding.keyCodes['↓']) {
105164 d3_event.preventDefault();
105165 d3_event.stopPropagation(); // the next item in the list at the same level
105167 var nextItem = select(item.node().nextElementSibling); // if there is no next item in this list
105169 if (nextItem.empty()) {
105170 // if there is a parent item
105171 if (!parentItem.empty()) {
105172 // the item is the last item of a sublist,
105173 // select the next item at the parent level
105174 nextItem = select(parentItem.node().nextElementSibling);
105175 } // if the focused item is expanded
105177 } else if (select(this).classed('expanded')) {
105178 // select the first subitem instead
105179 nextItem = item.select('.subgrid .preset-list-item:first-child');
105182 if (!nextItem.empty()) {
105183 // focus on the next item
105184 nextItem.select('.preset-list-button').node().focus();
105185 } // arrow up, move focus to the previous, higher item
105187 } else if (d3_event.keyCode === utilKeybinding.keyCodes['↑']) {
105188 d3_event.preventDefault();
105189 d3_event.stopPropagation(); // the previous item in the list at the same level
105191 var previousItem = select(item.node().previousElementSibling); // if there is no previous item in this list
105193 if (previousItem.empty()) {
105194 // if there is a parent item
105195 if (!parentItem.empty()) {
105196 // the item is the first subitem of a sublist select the parent item
105197 previousItem = parentItem;
105198 } // if the previous item is expanded
105200 } else if (previousItem.select('.preset-list-button').classed('expanded')) {
105201 // select the last subitem of the sublist of the previous item
105202 previousItem = previousItem.select('.subgrid .preset-list-item:last-child');
105205 if (!previousItem.empty()) {
105206 // focus on the previous item
105207 previousItem.select('.preset-list-button').node().focus();
105209 // the focus is at the top of the list, move focus back to the search field
105210 var search = select(this.closest('.preset-list-pane')).select('.preset-search-input');
105212 } // arrow left, move focus to the parent item if there is one
105214 } else if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === 'rtl' ? '→' : '←']) {
105215 d3_event.preventDefault();
105216 d3_event.stopPropagation(); // if there is a parent item, focus on the parent item
105218 if (!parentItem.empty()) {
105219 parentItem.select('.preset-list-button').node().focus();
105220 } // arrow right, choose this item
105222 } else if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === 'rtl' ? '←' : '→']) {
105223 d3_event.preventDefault();
105224 d3_event.stopPropagation();
105225 item.datum().choose.call(select(this).node());
105229 function CategoryItem(preset) {
105234 function item(selection) {
105235 var wrap = selection.append('div').attr('class', 'preset-list-button-wrap category');
105238 var isExpanded = select(this).classed('expanded');
105239 var iconName = isExpanded ? _mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward' : '#iD-icon-down';
105240 select(this).classed('expanded', !isExpanded).attr('title', !isExpanded ? _t('icons.collapse') : _t('icons.expand'));
105241 select(this).selectAll('div.label-inner svg.icon use').attr('href', iconName);
105245 var geometries = entityGeometries();
105246 var button = wrap.append('button').attr('class', 'preset-list-button').attr('title', _t('icons.expand')).classed('expanded', false).call(uiPresetIcon().geometry(geometries.length === 1 && geometries[0]).preset(preset)).on('click', click).on('keydown', function (d3_event) {
105247 // right arrow, expand the focused item
105248 if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === 'rtl' ? '←' : '→']) {
105249 d3_event.preventDefault();
105250 d3_event.stopPropagation(); // if the item isn't expanded
105252 if (!select(this).classed('expanded')) {
105253 // toggle expansion (expand the item)
105254 click.call(this, d3_event);
105255 } // left arrow, collapse the focused item
105257 } else if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === 'rtl' ? '→' : '←']) {
105258 d3_event.preventDefault();
105259 d3_event.stopPropagation(); // if the item is expanded
105261 if (select(this).classed('expanded')) {
105262 // toggle expansion (collapse the item)
105263 click.call(this, d3_event);
105266 itemKeydown.call(this, d3_event);
105269 var label = button.append('div').attr('class', 'label').append('div').attr('class', 'label-inner');
105270 label.append('div').attr('class', 'namepart').call(svgIcon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward', 'inline')).append('span').html(function () {
105271 return preset.nameLabel() + '…';
105273 box = selection.append('div').attr('class', 'subgrid').style('max-height', '0px').style('opacity', 0);
105274 box.append('div').attr('class', 'arrow');
105275 sublist = box.append('div').attr('class', 'preset-list fillL3');
105278 item.choose = function () {
105279 if (!box || !sublist) return;
105283 box.transition().duration(200).style('opacity', '0').style('max-height', '0px').style('padding-bottom', '0px');
105286 var members = preset.members.matchAllGeometry(entityGeometries());
105287 sublist.call(drawList, members);
105288 box.transition().duration(200).style('opacity', '1').style('max-height', 200 + members.collection.length * 190 + 'px').style('padding-bottom', '10px');
105296 function PresetItem(preset) {
105297 function item(selection) {
105298 var wrap = selection.append('div').attr('class', 'preset-list-button-wrap');
105299 var geometries = entityGeometries();
105300 var button = wrap.append('button').attr('class', 'preset-list-button').call(uiPresetIcon().geometry(geometries.length === 1 && geometries[0]).preset(preset)).on('click', item.choose).on('keydown', itemKeydown);
105301 var label = button.append('div').attr('class', 'label').append('div').attr('class', 'label-inner');
105302 var nameparts = [preset.nameLabel(), preset.subtitleLabel()].filter(Boolean);
105303 label.selectAll('.namepart').data(nameparts).enter().append('div').attr('class', 'namepart').html(function (d) {
105306 wrap.call(item.reference.button);
105307 selection.call(item.reference.body);
105310 item.choose = function () {
105311 if (select(this).classed('disabled')) return;
105313 if (!context.inIntro()) {
105314 _mainPresetIndex.setMostRecent(preset, entityGeometries()[0]);
105317 context.perform(function (graph) {
105318 for (var i in _entityIDs) {
105319 var entityID = _entityIDs[i];
105320 var oldPreset = _mainPresetIndex.match(graph.entity(entityID), graph);
105321 graph = actionChangePreset(entityID, oldPreset, preset)(graph);
105325 }, _t('operations.change_tags.annotation'));
105326 context.validator().validate(); // rerun validation
105328 dispatch.call('choose', this, preset);
105331 item.help = function (d3_event) {
105332 d3_event.stopPropagation();
105333 item.reference.toggle();
105337 item.reference = uiTagReference(preset.reference());
105341 function updateForFeatureHiddenState() {
105342 if (!_entityIDs.every(context.hasEntity)) return;
105343 var geometries = entityGeometries();
105344 var button = context.container().selectAll('.preset-list .preset-list-button'); // remove existing tooltips
105346 button.call(uiTooltip().destroyAny);
105347 button.each(function (item, index) {
105348 var hiddenPresetFeaturesId;
105350 for (var i in geometries) {
105351 hiddenPresetFeaturesId = context.features().isHiddenPreset(item.preset, geometries[i]);
105352 if (hiddenPresetFeaturesId) break;
105355 var isHiddenPreset = !context.inIntro() && !!hiddenPresetFeaturesId && (_currentPresets.length !== 1 || item.preset !== _currentPresets[0]);
105356 select(this).classed('disabled', isHiddenPreset);
105359 var isAutoHidden = context.features().autoHidden(hiddenPresetFeaturesId);
105360 select(this).call(uiTooltip().title(_t.html('inspector.hidden_preset.' + (isAutoHidden ? 'zoom' : 'manual'), {
105362 html: _t.html('feature.' + hiddenPresetFeaturesId + '.description')
105364 })).placement(index < 2 ? 'bottom' : 'top'));
105369 presetList.autofocus = function (val) {
105370 if (!arguments.length) return _autofocus;
105375 presetList.entityIDs = function (val) {
105376 if (!arguments.length) return _entityIDs;
105380 if (_entityIDs && _entityIDs.length) {
105381 // calculate current location
105382 var extent = _entityIDs.reduce(function (extent, entityID) {
105383 var entity = context.graph().entity(entityID);
105384 return extent.extend(entity.extent(context.graph()));
105387 _currLoc = extent.center(); // match presets
105389 var presets = _entityIDs.map(function (entityID) {
105390 return _mainPresetIndex.match(context.entity(entityID), context.graph());
105393 presetList.presets(presets);
105399 presetList.presets = function (val) {
105400 if (!arguments.length) return _currentPresets;
105405 function entityGeometries() {
105408 for (var i in _entityIDs) {
105409 var entityID = _entityIDs[i];
105410 var entity = context.entity(entityID);
105411 var geometry = entity.geometry(context.graph()); // Treat entities on addr:interpolation lines as points, not vertices (#3241)
105413 if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
105417 if (!counts[geometry]) counts[geometry] = 0;
105421 return Object.keys(counts).sort(function (geom1, geom2) {
105422 return counts[geom2] - counts[geom1];
105426 return utilRebind(presetList, dispatch, 'on');
105429 function uiViewOnOSM(context) {
105430 var _what; // an osmEntity or osmNote
105433 function viewOnOSM(selection) {
105436 if (_what instanceof osmEntity) {
105437 url = context.connection().entityURL(_what);
105438 } else if (_what instanceof osmNote) {
105439 url = context.connection().noteURL(_what);
105442 var data = !_what || _what.isNew() ? [] : [_what];
105443 var link = selection.selectAll('.view-on-osm').data(data, function (d) {
105447 link.exit().remove(); // enter
105449 var linkEnter = link.enter().append('a').attr('class', 'view-on-osm').attr('target', '_blank').attr('href', url).call(svgIcon('#iD-icon-out-link', 'inline'));
105450 linkEnter.append('span').call(_t.append('inspector.view_on_osm'));
105453 viewOnOSM.what = function (_) {
105454 if (!arguments.length) return _what;
105462 function uiInspector(context) {
105463 var presetList = uiPresetList(context);
105464 var entityEditor = uiEntityEditor(context);
105465 var wrap = select(null),
105466 presetPane = select(null),
105467 editorPane = select(null);
105472 var _newFeature = false;
105474 function inspector(selection) {
105475 presetList.entityIDs(_entityIDs).autofocus(_newFeature).on('choose', inspector.setPreset).on('cancel', function () {
105478 entityEditor.state(_state).entityIDs(_entityIDs).on('choose', inspector.showList);
105479 wrap = selection.selectAll('.panewrap').data([0]);
105480 var enter = wrap.enter().append('div').attr('class', 'panewrap');
105481 enter.append('div').attr('class', 'preset-list-pane pane');
105482 enter.append('div').attr('class', 'entity-editor-pane pane');
105483 wrap = wrap.merge(enter);
105484 presetPane = wrap.selectAll('.preset-list-pane');
105485 editorPane = wrap.selectAll('.entity-editor-pane');
105487 function shouldDefaultToPresetList() {
105488 // always show the inspector on hover
105489 if (_state !== 'select') return false; // can only change preset on single selection
105491 if (_entityIDs.length !== 1) return false;
105492 var entityID = _entityIDs[0];
105493 var entity = context.hasEntity(entityID);
105494 if (!entity) return false; // default to inspector if there are already tags
105496 if (entity.hasNonGeometryTags()) return false; // prompt to select preset if feature is new and untagged
105498 if (_newFeature) return true; // all existing features except vertices should default to inspector
105500 if (entity.geometry(context.graph()) !== 'vertex') return false; // show vertex relations if any
105502 if (context.graph().parentRelations(entity).length) return false; // show vertex issues if there are any
105504 if (context.validator().getEntityIssues(entityID).length) return false; // show turn retriction editor for junction vertices
105506 if (entity.isHighwayIntersection(context.graph())) return false; // otherwise show preset list for uninteresting vertices
105511 if (shouldDefaultToPresetList()) {
105512 wrap.style('right', '-100%');
105513 editorPane.classed('hide', true);
105514 presetPane.classed('hide', false).call(presetList);
105516 wrap.style('right', '0%');
105517 presetPane.classed('hide', true);
105518 editorPane.classed('hide', false).call(entityEditor);
105521 var footer = selection.selectAll('.footer').data([0]);
105522 footer = footer.enter().append('div').attr('class', 'footer').merge(footer);
105523 footer.call(uiViewOnOSM(context).what(context.hasEntity(_entityIDs.length === 1 && _entityIDs[0])));
105526 inspector.showList = function (presets) {
105527 presetPane.classed('hide', false);
105528 wrap.transition().styleTween('right', function () {
105529 return interpolate$1('0%', '-100%');
105530 }).on('end', function () {
105531 editorPane.classed('hide', true);
105535 presetList.presets(presets);
105538 presetPane.call(presetList.autofocus(true));
105541 inspector.setPreset = function (preset) {
105542 // upon setting multipolygon, go to the area preset list instead of the editor
105543 if (preset && preset.id === 'type/multipolygon') {
105544 presetPane.call(presetList.autofocus(true));
105546 editorPane.classed('hide', false);
105547 wrap.transition().styleTween('right', function () {
105548 return interpolate$1('-100%', '0%');
105549 }).on('end', function () {
105550 presetPane.classed('hide', true);
105554 entityEditor.presets([preset]);
105557 editorPane.call(entityEditor);
105561 inspector.state = function (val) {
105562 if (!arguments.length) return _state;
105564 entityEditor.state(_state); // remove any old field help overlay that might have gotten attached to the inspector
105566 context.container().selectAll('.field-help-body').remove();
105570 inspector.entityIDs = function (val) {
105571 if (!arguments.length) return _entityIDs;
105576 inspector.newFeature = function (val) {
105577 if (!arguments.length) return _newFeature;
105585 function uiKeepRightDetails(context) {
105588 function issueDetail(d) {
105589 var itemType = d.itemType,
105590 parentIssueType = d.parentIssueType;
105592 html: _t.html('inspector.unknown')
105594 var replacements = d.replacements || {};
105595 replacements["default"] = unknown; // special key `default` works as a fallback string
105597 var detail = _t.html("QA.keepRight.errorTypes.".concat(itemType, ".description"), replacements);
105599 if (detail === unknown.html) {
105600 detail = _t.html("QA.keepRight.errorTypes.".concat(parentIssueType, ".description"), replacements);
105606 function keepRightDetails(selection) {
105607 var details = selection.selectAll('.error-details').data(_qaItem ? [_qaItem] : [], function (d) {
105608 return "".concat(d.id, "-").concat(d.status || 0);
105610 details.exit().remove();
105611 var detailsEnter = details.enter().append('div').attr('class', 'error-details qa-details-container'); // description
105613 var descriptionEnter = detailsEnter.append('div').attr('class', 'qa-details-subsection');
105614 descriptionEnter.append('h4').call(_t.append('QA.keepRight.detail_description'));
105615 descriptionEnter.append('div').attr('class', 'qa-details-description-text').html(issueDetail); // If there are entity links in the error message..
105617 var relatedEntities = [];
105618 descriptionEnter.selectAll('.error_entity_link, .error_object_link').attr('href', '#').each(function () {
105619 var link = select(this);
105620 var isObjectLink = link.classed('error_object_link');
105621 var entityID = isObjectLink ? utilEntityRoot(_qaItem.objectType) + _qaItem.objectId : this.textContent;
105622 var entity = context.hasEntity(entityID);
105623 relatedEntities.push(entityID); // Add click handler
105625 link.on('mouseenter', function () {
105626 utilHighlightEntities([entityID], true, context);
105627 }).on('mouseleave', function () {
105628 utilHighlightEntities([entityID], false, context);
105629 }).on('click', function (d3_event) {
105630 d3_event.preventDefault();
105631 utilHighlightEntities([entityID], false, context);
105632 var osmlayer = context.layers().layer('osm');
105634 if (!osmlayer.enabled()) {
105635 osmlayer.enabled(true);
105638 context.map().centerZoomEase(_qaItem.loc, 20);
105641 context.enter(modeSelect(context, [entityID]));
105643 context.loadEntity(entityID, function (err, result) {
105645 var entity = result.data.find(function (e) {
105646 return e.id === entityID;
105648 if (entity) context.enter(modeSelect(context, [entityID]));
105651 }); // Replace with friendly name if possible
105652 // (The entity may not yet be loaded into the graph)
105655 var name = utilDisplayName(entity); // try to use common name
105657 if (!name && !isObjectLink) {
105658 var preset = _mainPresetIndex.match(entity, context.graph());
105659 name = preset && !preset.isFallback() && preset.name(); // fallback to preset name
105666 }); // Don't hide entities related to this issue - #5880
105668 context.features().forceVisible(relatedEntities);
105669 context.map().pan([0, 0]); // trigger a redraw
105672 keepRightDetails.issue = function (val) {
105673 if (!arguments.length) return _qaItem;
105675 return keepRightDetails;
105678 return keepRightDetails;
105681 function uiKeepRightHeader() {
105684 function issueTitle(d) {
105685 var itemType = d.itemType,
105686 parentIssueType = d.parentIssueType;
105687 var unknown = _t.html('inspector.unknown');
105688 var replacements = d.replacements || {};
105689 replacements["default"] = {
105691 }; // special key `default` works as a fallback string
105693 var title = _t.html("QA.keepRight.errorTypes.".concat(itemType, ".title"), replacements);
105695 if (title !== unknown) {
105696 return _t.apply("QA.keepRight.errorTypes.".concat(itemType, ".title"), replacements);
105698 return _t.apply("QA.keepRight.errorTypes.".concat(parentIssueType, ".title"), replacements);
105702 function keepRightHeader(selection) {
105703 var header = selection.selectAll('.qa-header').data(_qaItem ? [_qaItem] : [], function (d) {
105704 return "".concat(d.id, "-").concat(d.status || 0);
105706 header.exit().remove();
105707 var headerEnter = header.enter().append('div').attr('class', 'qa-header');
105708 var iconEnter = headerEnter.append('div').attr('class', 'qa-header-icon').classed('new', function (d) {
105711 iconEnter.append('div').attr('class', function (d) {
105712 return "preset-icon-28 qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.parentIssueType);
105713 }).call(svgIcon('#iD-icon-bolt', 'qaItem-fill'));
105714 headerEnter.append('div').attr('class', 'qa-header-label').html(issueTitle);
105717 keepRightHeader.issue = function (val) {
105718 if (!arguments.length) return _qaItem;
105720 return keepRightHeader;
105723 return keepRightHeader;
105726 function uiViewOnKeepRight() {
105729 function viewOnKeepRight(selection) {
105732 if (services.keepRight && _qaItem instanceof QAItem) {
105733 url = services.keepRight.issueURL(_qaItem);
105736 var link = selection.selectAll('.view-on-keepRight').data(url ? [url] : []); // exit
105738 link.exit().remove(); // enter
105740 var linkEnter = link.enter().append('a').attr('class', 'view-on-keepRight').attr('target', '_blank').attr('rel', 'noopener') // security measure
105741 .attr('href', function (d) {
105743 }).call(svgIcon('#iD-icon-out-link', 'inline'));
105744 linkEnter.append('span').call(_t.append('inspector.view_on_keepRight'));
105747 viewOnKeepRight.what = function (val) {
105748 if (!arguments.length) return _qaItem;
105750 return viewOnKeepRight;
105753 return viewOnKeepRight;
105756 function uiKeepRightEditor(context) {
105757 var dispatch = dispatch$8('change');
105758 var qaDetails = uiKeepRightDetails(context);
105759 var qaHeader = uiKeepRightHeader();
105763 function keepRightEditor(selection) {
105764 var headerEnter = selection.selectAll('.header').data([0]).enter().append('div').attr('class', 'header fillL');
105765 headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
105766 return context.enter(modeBrowse(context));
105767 }).call(svgIcon('#iD-icon-close'));
105768 headerEnter.append('h2').call(_t.append('QA.keepRight.title'));
105769 var body = selection.selectAll('.body').data([0]);
105770 body = body.enter().append('div').attr('class', 'body').merge(body);
105771 var editor = body.selectAll('.qa-editor').data([0]);
105772 editor.enter().append('div').attr('class', 'modal-section qa-editor').merge(editor).call(qaHeader.issue(_qaItem)).call(qaDetails.issue(_qaItem)).call(keepRightSaveSection);
105773 var footer = selection.selectAll('.footer').data([0]);
105774 footer.enter().append('div').attr('class', 'footer').merge(footer).call(uiViewOnKeepRight().what(_qaItem));
105777 function keepRightSaveSection(selection) {
105778 var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
105780 var isShown = _qaItem && (isSelected || _qaItem.newComment || _qaItem.comment);
105781 var saveSection = selection.selectAll('.qa-save').data(isShown ? [_qaItem] : [], function (d) {
105782 return "".concat(d.id, "-").concat(d.status || 0);
105785 saveSection.exit().remove(); // enter
105787 var saveSectionEnter = saveSection.enter().append('div').attr('class', 'qa-save save-section cf');
105788 saveSectionEnter.append('h4').attr('class', '.qa-save-header').call(_t.append('QA.keepRight.comment'));
105789 saveSectionEnter.append('textarea').attr('class', 'new-comment-input').attr('placeholder', _t('QA.keepRight.comment_placeholder')).attr('maxlength', 1000).property('value', function (d) {
105790 return d.newComment || d.comment;
105791 }).call(utilNoAuto).on('input', changeInput).on('blur', changeInput); // update
105793 saveSection = saveSectionEnter.merge(saveSection).call(qaSaveButtons);
105795 function changeInput() {
105796 var input = select(this);
105797 var val = input.property('value').trim();
105799 if (val === _qaItem.comment) {
105801 } // store the unsaved comment with the issue itself
105804 _qaItem = _qaItem.update({
105807 var qaService = services.keepRight;
105810 qaService.replaceItem(_qaItem); // update keepright cache
105813 saveSection.call(qaSaveButtons);
105817 function qaSaveButtons(selection) {
105818 var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
105820 var buttonSection = selection.selectAll('.buttons').data(isSelected ? [_qaItem] : [], function (d) {
105821 return d.status + d.id;
105824 buttonSection.exit().remove(); // enter
105826 var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons');
105827 buttonEnter.append('button').attr('class', 'button comment-button action').call(_t.append('QA.keepRight.save_comment'));
105828 buttonEnter.append('button').attr('class', 'button close-button action');
105829 buttonEnter.append('button').attr('class', 'button ignore-button action'); // update
105831 buttonSection = buttonSection.merge(buttonEnter);
105832 buttonSection.select('.comment-button') // select and propagate data
105833 .attr('disabled', function (d) {
105834 return d.newComment ? null : true;
105835 }).on('click.comment', function (d3_event, d) {
105836 this.blur(); // avoid keeping focus on the button - #4641
105838 var qaService = services.keepRight;
105841 qaService.postUpdate(d, function (err, item) {
105842 return dispatch.call('change', item);
105846 buttonSection.select('.close-button') // select and propagate data
105848 var andComment = d.newComment ? '_comment' : '';
105849 return _t.html("QA.keepRight.close".concat(andComment));
105850 }).on('click.close', function (d3_event, d) {
105851 this.blur(); // avoid keeping focus on the button - #4641
105853 var qaService = services.keepRight;
105856 d.newStatus = 'ignore_t'; // ignore temporarily (item fixed)
105858 qaService.postUpdate(d, function (err, item) {
105859 return dispatch.call('change', item);
105863 buttonSection.select('.ignore-button') // select and propagate data
105865 var andComment = d.newComment ? '_comment' : '';
105866 return _t.html("QA.keepRight.ignore".concat(andComment));
105867 }).on('click.ignore', function (d3_event, d) {
105868 this.blur(); // avoid keeping focus on the button - #4641
105870 var qaService = services.keepRight;
105873 d.newStatus = 'ignore'; // ignore permanently (false positive)
105875 qaService.postUpdate(d, function (err, item) {
105876 return dispatch.call('change', item);
105880 } // NOTE: Don't change method name until UI v3 is merged
105883 keepRightEditor.error = function (val) {
105884 if (!arguments.length) return _qaItem;
105886 return keepRightEditor;
105889 return utilRebind(keepRightEditor, dispatch, 'on');
105892 function uiLasso(context) {
105894 lasso.coordinates = [];
105896 function lasso(selection) {
105897 context.container().classed('lasso', true);
105898 group = selection.append('g').attr('class', 'lasso hide');
105899 polygon = group.append('path').attr('class', 'lasso-path');
105900 group.call(uiToggle(true));
105905 polygon.data([lasso.coordinates]).attr('d', function (d) {
105906 return 'M' + d.join(' L') + ' Z';
105911 lasso.extent = function () {
105912 return lasso.coordinates.reduce(function (extent, point) {
105913 return extent.extend(geoExtent(point));
105917 lasso.p = function (_) {
105918 if (!arguments.length) return lasso;
105919 lasso.coordinates.push(_);
105924 lasso.close = function () {
105926 group.call(uiToggle(false, function () {
105931 context.container().classed('lasso', false);
105937 function uiNoteComments() {
105940 function noteComments(selection) {
105941 if (_note.isNew()) return; // don't draw .comments-container
105943 var comments = selection.selectAll('.comments-container').data([0]);
105944 comments = comments.enter().append('div').attr('class', 'comments-container').merge(comments);
105945 var commentEnter = comments.selectAll('.comment').data(_note.comments).enter().append('div').attr('class', 'comment');
105946 commentEnter.append('div').attr('class', function (d) {
105947 return 'comment-avatar user-' + d.uid;
105948 }).call(svgIcon('#iD-icon-avatar', 'comment-avatar-icon'));
105949 var mainEnter = commentEnter.append('div').attr('class', 'comment-main');
105950 var metadataEnter = mainEnter.append('div').attr('class', 'comment-metadata');
105951 metadataEnter.append('div').attr('class', 'comment-author').each(function (d) {
105952 var selection = select(this);
105953 var osm = services.osm;
105956 selection = selection.append('a').attr('class', 'comment-author-link').attr('href', osm.userURL(d.user)).attr('target', '_blank');
105960 selection.text(d.user);
105962 selection.call(_t.append('note.anonymous'));
105965 metadataEnter.append('div').attr('class', 'comment-date').html(function (d) {
105966 return _t.html('note.status.' + d.action, {
105967 when: localeDateString(d.date)
105970 mainEnter.append('div').attr('class', 'comment-text').html(function (d) {
105972 }).selectAll('a').attr('rel', 'noopener nofollow').attr('target', '_blank');
105973 comments.call(replaceAvatars);
105976 function replaceAvatars(selection) {
105977 var showThirdPartyIcons = corePreferences('preferences.privacy.thirdpartyicons') || 'true';
105978 var osm = services.osm;
105979 if (showThirdPartyIcons !== 'true' || !osm) return;
105980 var uids = {}; // gather uids in the comment thread
105982 _note.comments.forEach(function (d) {
105983 if (d.uid) uids[d.uid] = true;
105986 Object.keys(uids).forEach(function (uid) {
105987 osm.loadUser(uid, function (err, user) {
105988 if (!user || !user.image_url) return;
105989 selection.selectAll('.comment-avatar.user-' + uid).html('').append('img').attr('class', 'icon comment-avatar-icon').attr('src', user.image_url).attr('alt', user.display_name);
105994 function localeDateString(s) {
106001 s = s.replace(/-/g, '/'); // fix browser-specific Date() issues
106004 if (isNaN(d.getTime())) return null;
106005 return d.toLocaleDateString(_mainLocalizer.localeCode(), options);
106008 noteComments.note = function (val) {
106009 if (!arguments.length) return _note;
106017 function uiNoteHeader() {
106020 function noteHeader(selection) {
106021 var header = selection.selectAll('.note-header').data(_note ? [_note] : [], function (d) {
106022 return d.status + d.id;
106024 header.exit().remove();
106025 var headerEnter = header.enter().append('div').attr('class', 'note-header');
106026 var iconEnter = headerEnter.append('div').attr('class', function (d) {
106027 return 'note-header-icon ' + d.status;
106028 }).classed('new', function (d) {
106031 iconEnter.append('div').attr('class', 'preset-icon-28').call(svgIcon('#iD-icon-note', 'note-fill'));
106032 iconEnter.each(function (d) {
106036 statusIcon = '#iD-icon-plus';
106037 } else if (d.status === 'open') {
106038 statusIcon = '#iD-icon-close';
106040 statusIcon = '#iD-icon-apply';
106043 iconEnter.append('div').attr('class', 'note-icon-annotation').attr('title', _t('icons.close')).call(svgIcon(statusIcon, 'icon-annotation'));
106045 headerEnter.append('div').attr('class', 'note-header-label').html(function (d) {
106047 return _t.html('note.new');
106050 return _t.html('note.note') + ' ' + d.id + ' ' + (d.status === 'closed' ? _t.html('note.closed') : '');
106054 noteHeader.note = function (val) {
106055 if (!arguments.length) return _note;
106063 function uiNoteReport() {
106066 function noteReport(selection) {
106069 if (services.osm && _note instanceof osmNote && !_note.isNew()) {
106070 url = services.osm.noteReportURL(_note);
106073 var link = selection.selectAll('.note-report').data(url ? [url] : []); // exit
106075 link.exit().remove(); // enter
106077 var linkEnter = link.enter().append('a').attr('class', 'note-report').attr('target', '_blank').attr('href', function (d) {
106079 }).call(svgIcon('#iD-icon-out-link', 'inline'));
106080 linkEnter.append('span').call(_t.append('note.report'));
106083 noteReport.note = function (val) {
106084 if (!arguments.length) return _note;
106092 function uiNoteEditor(context) {
106093 var dispatch = dispatch$8('change');
106094 var noteComments = uiNoteComments();
106095 var noteHeader = uiNoteHeader(); // var formFields = uiFormFields(context);
106099 var _newNote; // var _fieldsArr;
106102 function noteEditor(selection) {
106103 var header = selection.selectAll('.header').data([0]);
106104 var headerEnter = header.enter().append('div').attr('class', 'header fillL');
106105 headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
106106 context.enter(modeBrowse(context));
106107 }).call(svgIcon('#iD-icon-close'));
106108 headerEnter.append('h2').call(_t.append('note.title'));
106109 var body = selection.selectAll('.body').data([0]);
106110 body = body.enter().append('div').attr('class', 'body').merge(body);
106111 var editor = body.selectAll('.note-editor').data([0]);
106112 editor.enter().append('div').attr('class', 'modal-section note-editor').merge(editor).call(noteHeader.note(_note)).call(noteComments.note(_note)).call(noteSaveSection);
106113 var footer = selection.selectAll('.footer').data([0]);
106114 footer.enter().append('div').attr('class', 'footer').merge(footer).call(uiViewOnOSM(context).what(_note)).call(uiNoteReport().note(_note)); // rerender the note editor on any auth change
106116 var osm = services.osm;
106119 osm.on('change.note-save', function () {
106120 selection.call(noteEditor);
106125 function noteSaveSection(selection) {
106126 var isSelected = _note && _note.id === context.selectedNoteID();
106128 var noteSave = selection.selectAll('.note-save').data(isSelected ? [_note] : [], function (d) {
106129 return d.status + d.id;
106132 noteSave.exit().remove(); // enter
106134 var noteSaveEnter = noteSave.enter().append('div').attr('class', 'note-save save-section cf'); // // if new note, show categories to pick from
106135 // if (_note.isNew()) {
106136 // var presets = presetManager;
106137 // // NOTE: this key isn't a age and therefore there is no documentation (yet)
106139 // uiField(context, presets.field('category'), null, { show: true, revert: false }),
106141 // _fieldsArr.forEach(function(field) {
106143 // .on('change', changeCategory);
106147 // .attr('class', 'note-category')
106148 // .call(formFields.fieldsArr(_fieldsArr));
106150 // function changeCategory() {
106151 // // NOTE: perhaps there is a better way to get value
106152 // var val = context.container().select('input[name=\'category\']:checked').property('__data__') || undefined;
106153 // // store the unsaved category with the note itself
106154 // _note = _note.update({ newCategory: val });
106155 // var osm = services.osm;
106157 // osm.replaceNote(_note); // update note cache
106160 // .call(noteSaveButtons);
106163 noteSaveEnter.append('h4').attr('class', '.note-save-header').html(function () {
106164 return _note.isNew() ? _t.html('note.newDescription') : _t.html('note.newComment');
106166 var commentTextarea = noteSaveEnter.append('textarea').attr('class', 'new-comment-input').attr('placeholder', _t('note.inputPlaceholder')).attr('maxlength', 1000).property('value', function (d) {
106168 }).call(utilNoAuto).on('keydown.note-input', keydown).on('input.note-input', changeInput).on('blur.note-input', changeInput);
106170 if (!commentTextarea.empty() && _newNote) {
106171 // autofocus the comment field for new notes
106172 commentTextarea.node().focus();
106176 noteSave = noteSaveEnter.merge(noteSave).call(userDetails).call(noteSaveButtons); // fast submit if user presses cmd+enter
106178 function keydown(d3_event) {
106179 if (!(d3_event.keyCode === 13 && // ↩ Return
106180 d3_event.metaKey)) return;
106181 var osm = services.osm;
106183 var hasAuth = osm.authenticated();
106185 if (!_note.newComment) return;
106186 d3_event.preventDefault();
106187 select(this).on('keydown.note-input', null); // focus on button and submit
106189 window.setTimeout(function () {
106191 noteSave.selectAll('.save-button').node().focus();
106194 noteSave.selectAll('.comment-button').node().focus();
106200 function changeInput() {
106201 var input = select(this);
106202 var val = input.property('value').trim() || undefined; // store the unsaved comment with the note itself
106207 var osm = services.osm;
106210 osm.replaceNote(_note); // update note cache
106213 noteSave.call(noteSaveButtons);
106217 function userDetails(selection) {
106218 var detailSection = selection.selectAll('.detail-section').data([0]);
106219 detailSection = detailSection.enter().append('div').attr('class', 'detail-section').merge(detailSection);
106220 var osm = services.osm;
106221 if (!osm) return; // Add warning if user is not logged in
106223 var hasAuth = osm.authenticated();
106224 var authWarning = detailSection.selectAll('.auth-warning').data(hasAuth ? [] : [0]);
106225 authWarning.exit().transition().duration(200).style('opacity', 0).remove();
106226 var authEnter = authWarning.enter().insert('div', '.tag-reference-body').attr('class', 'field-warning auth-warning').style('opacity', 0);
106227 authEnter.call(svgIcon('#iD-icon-alert', 'inline'));
106228 authEnter.append('span').call(_t.append('note.login'));
106229 authEnter.append('a').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).append('span').call(_t.append('login')).on('click.note-login', function (d3_event) {
106230 d3_event.preventDefault();
106233 authEnter.transition().duration(200).style('opacity', 1);
106234 var prose = detailSection.selectAll('.note-save-prose').data(hasAuth ? [0] : []);
106236 prose = prose.enter().append('p').attr('class', 'note-save-prose').call(_t.append('note.upload_explanation')).merge(prose);
106237 osm.userDetails(function (err, user) {
106239 var userLink = select(document.createElement('div'));
106242 userLink.append('img').attr('src', user.image_url).attr('class', 'icon pre-text user-icon');
106245 userLink.append('a').attr('class', 'user-info').text(user.display_name).attr('href', osm.userURL(user.display_name)).attr('target', '_blank');
106246 prose.html(_t.html('note.upload_explanation_with_user', {
106254 function noteSaveButtons(selection) {
106255 var osm = services.osm;
106256 var hasAuth = osm && osm.authenticated();
106258 var isSelected = _note && _note.id === context.selectedNoteID();
106260 var buttonSection = selection.selectAll('.buttons').data(isSelected ? [_note] : [], function (d) {
106261 return d.status + d.id;
106264 buttonSection.exit().remove(); // enter
106266 var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons');
106269 buttonEnter.append('button').attr('class', 'button cancel-button secondary-action').call(_t.append('confirm.cancel'));
106270 buttonEnter.append('button').attr('class', 'button save-button action').call(_t.append('note.save'));
106272 buttonEnter.append('button').attr('class', 'button status-button action');
106273 buttonEnter.append('button').attr('class', 'button comment-button action').call(_t.append('note.comment'));
106277 buttonSection = buttonSection.merge(buttonEnter);
106278 buttonSection.select('.cancel-button') // select and propagate data
106279 .on('click.cancel', clickCancel);
106280 buttonSection.select('.save-button') // select and propagate data
106281 .attr('disabled', isSaveDisabled).on('click.save', clickSave);
106282 buttonSection.select('.status-button') // select and propagate data
106283 .attr('disabled', hasAuth ? null : true).html(function (d) {
106284 var action = d.status === 'open' ? 'close' : 'open';
106285 var andComment = d.newComment ? '_comment' : '';
106286 return _t.html('note.' + action + andComment);
106287 }).on('click.status', clickStatus);
106288 buttonSection.select('.comment-button') // select and propagate data
106289 .attr('disabled', isSaveDisabled).on('click.comment', clickComment);
106291 function isSaveDisabled(d) {
106292 return hasAuth && d.status === 'open' && d.newComment ? null : true;
106296 function clickCancel(d3_event, d) {
106297 this.blur(); // avoid keeping focus on the button - #4641
106299 var osm = services.osm;
106305 context.enter(modeBrowse(context));
106306 dispatch.call('change');
106309 function clickSave(d3_event, d) {
106310 this.blur(); // avoid keeping focus on the button - #4641
106312 var osm = services.osm;
106315 osm.postNoteCreate(d, function (err, note) {
106316 dispatch.call('change', note);
106321 function clickStatus(d3_event, d) {
106322 this.blur(); // avoid keeping focus on the button - #4641
106324 var osm = services.osm;
106327 var setStatus = d.status === 'open' ? 'closed' : 'open';
106328 osm.postNoteUpdate(d, setStatus, function (err, note) {
106329 dispatch.call('change', note);
106334 function clickComment(d3_event, d) {
106335 this.blur(); // avoid keeping focus on the button - #4641
106337 var osm = services.osm;
106340 osm.postNoteUpdate(d, d.status, function (err, note) {
106341 dispatch.call('change', note);
106346 noteEditor.note = function (val) {
106347 if (!arguments.length) return _note;
106352 noteEditor.newNote = function (val) {
106353 if (!arguments.length) return _newNote;
106358 return utilRebind(noteEditor, dispatch, 'on');
106361 function uiSourceSwitch(context) {
106364 function click(d3_event) {
106365 d3_event.preventDefault();
106366 var osm = context.connection();
106368 if (context.inIntro()) return;
106369 if (context.history().hasChanges() && !window.confirm(_t('source_switch.lose_changes'))) return;
106370 var isLive = select(this).classed('live');
106372 context.enter(modeBrowse(context));
106373 context.history().clearSaved(); // remove saved history
106375 context.flush(); // remove stored data
106377 select(this).html(isLive ? _t.html('source_switch.live') : _t.html('source_switch.dev')).classed('live', isLive).classed('chip', isLive);
106378 osm["switch"](isLive ? keys[0] : keys[1]); // switch connection (warning: dispatches 'change' event)
106381 var sourceSwitch = function sourceSwitch(selection) {
106382 selection.append('a').attr('href', '#').call(_t.append('source_switch.live')).attr('class', 'live chip').on('click', click);
106385 sourceSwitch.keys = function (_) {
106386 if (!arguments.length) return keys;
106394 function uiSpinner(context) {
106395 var osm = context.connection();
106396 return function (selection) {
106397 var img = selection.append('img').attr('src', context.imagePath('loader-black.gif')).style('opacity', 0);
106400 osm.on('loading.spinner', function () {
106401 img.transition().style('opacity', 1);
106402 }).on('loaded.spinner', function () {
106403 img.transition().style('opacity', 0);
106409 function uiSectionPrivacy(context) {
106410 var section = uiSection('preferences-third-party', context).label(_t.html('preferences.privacy.title')).disclosureContent(renderDisclosureContent);
106412 function renderDisclosureContent(selection) {
106414 selection.selectAll('.privacy-options-list').data([0]).enter().append('ul').attr('class', 'layer-list privacy-options-list');
106415 var thirdPartyIconsEnter = selection.select('.privacy-options-list').selectAll('.privacy-third-party-icons-item').data([corePreferences('preferences.privacy.thirdpartyicons') || 'true']).enter().append('li').attr('class', 'privacy-third-party-icons-item').append('label').call(uiTooltip().title(_t.html('preferences.privacy.third_party_icons.tooltip')).placement('bottom'));
106416 thirdPartyIconsEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
106417 d3_event.preventDefault();
106418 corePreferences('preferences.privacy.thirdpartyicons', d === 'true' ? 'false' : 'true');
106420 thirdPartyIconsEnter.append('span').call(_t.append('preferences.privacy.third_party_icons.description')); // update
106422 selection.selectAll('.privacy-third-party-icons-item').classed('active', function (d) {
106424 }).select('input').property('checked', function (d) {
106426 }); // Privacy Policy link
106428 selection.selectAll('.privacy-link').data([0]).enter().append('div').attr('class', 'privacy-link').append('a').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).attr('href', 'https://github.com/openstreetmap/iD/blob/release/PRIVACY.md').append('span').call(_t.append('preferences.privacy.privacy_link'));
106431 corePreferences.onChange('preferences.privacy.thirdpartyicons', section.reRender);
106435 function uiSplash(context) {
106436 return function (selection) {
106437 // Exception - if there are restorable changes, skip this splash screen.
106438 // This is because we currently only support one `uiModal` at a time
106439 // and we need to show them `uiRestore`` instead of this one.
106440 if (context.history().hasRestorableChanges()) return; // If user has not seen this version of the privacy policy, show the splash again.
106442 var updateMessage = '';
106443 var sawPrivacyVersion = corePreferences('sawPrivacyVersion');
106444 var showSplash = !corePreferences('sawSplash');
106446 if (sawPrivacyVersion !== context.privacyVersion) {
106447 updateMessage = _t('splash.privacy_update');
106451 if (!showSplash) return;
106452 corePreferences('sawSplash', true);
106453 corePreferences('sawPrivacyVersion', context.privacyVersion); // fetch intro graph data now, while user is looking at the splash screen
106455 _mainFileFetcher.get('intro_graph');
106456 var modalSelection = uiModal(selection);
106457 modalSelection.select('.modal').attr('class', 'modal-splash modal');
106458 var introModal = modalSelection.select('.content').append('div').attr('class', 'fillL');
106459 introModal.append('div').attr('class', 'modal-section').append('h3').call(_t.append('splash.welcome'));
106460 var modalSection = introModal.append('div').attr('class', 'modal-section');
106461 modalSection.append('p').html(_t.html('splash.text', {
106462 version: context.version,
106464 html: '<a target="_blank" href="https://github.com/openstreetmap/iD/blob/develop/CHANGELOG.md#whats-new">changelog</a>'
106467 html: '<a target="_blank" href="https://github.com/openstreetmap/iD/issues">github.com</a>'
106470 modalSection.append('p').html(_t.html('splash.privacy', {
106471 updateMessage: updateMessage,
106473 html: '<a target="_blank" href="https://github.com/openstreetmap/iD/blob/release/PRIVACY.md">' + _t('splash.privacy_policy') + '</a>'
106476 uiSectionPrivacy(context).label(_t.html('splash.privacy_settings')).render(modalSection);
106477 var buttonWrap = introModal.append('div').attr('class', 'modal-actions');
106478 var walkthrough = buttonWrap.append('button').attr('class', 'walkthrough').on('click', function () {
106479 context.container().call(uiIntro(context));
106480 modalSelection.close();
106482 walkthrough.append('svg').attr('class', 'logo logo-walkthrough').append('use').attr('xlink:href', '#iD-logo-walkthrough');
106483 walkthrough.append('div').call(_t.append('splash.walkthrough'));
106484 var startEditing = buttonWrap.append('button').attr('class', 'start-editing').on('click', modalSelection.close);
106485 startEditing.append('svg').attr('class', 'logo logo-features').append('use').attr('xlink:href', '#iD-logo-features');
106486 startEditing.append('div').call(_t.append('splash.start'));
106487 modalSelection.select('button.close').attr('class', 'hide');
106491 function uiStatus(context) {
106492 var osm = context.connection();
106493 return function (selection) {
106496 function update(err, apiStatus) {
106500 if (apiStatus === 'connectionSwitched') {
106501 // if the connection was just switched, we can't rely on
106502 // the status (we're getting the status of the previous api)
106504 } else if (apiStatus === 'rateLimited') {
106505 selection.call(_t.append('osm_api_status.message.rateLimit')).append('a').attr('href', '#').attr('class', 'api-status-login').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).append('span').call(_t.append('login')).on('click.login', function (d3_event) {
106506 d3_event.preventDefault();
106510 // don't allow retrying too rapidly
106511 var throttledRetry = throttle(function () {
106512 // try loading the visible tiles
106513 context.loadTiles(context.projection); // manually reload the status too in case all visible tiles were already loaded
106516 }, 2000); // eslint-disable-next-line no-warning-comments
106517 // TODO: nice messages for different error types
106520 selection.call(_t.append('osm_api_status.message.error', {
106522 })).append('a').attr('href', '#') // let the user manually retry their connection directly
106523 .call(_t.append('osm_api_status.retry')).on('click.retry', function (d3_event) {
106524 d3_event.preventDefault();
106528 } else if (apiStatus === 'readonly') {
106529 selection.call(_t.append('osm_api_status.message.readonly'));
106530 } else if (apiStatus === 'offline') {
106531 selection.call(_t.append('osm_api_status.message.offline'));
106534 selection.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
106537 osm.on('apiStatusChange.uiStatus', update);
106538 context.history().on('storage_error', function () {
106539 selection.selectAll('span.local-storage-full').remove();
106540 selection.append('span').attr('class', 'local-storage-full').call(_t.append('osm_api_status.message.local_storage_full'));
106541 selection.classed('error', true);
106542 }); // reload the status periodically regardless of other factors
106544 window.setInterval(function () {
106546 }, 90000); // load the initial status in case no OSM data was loaded yet
106552 // for punction see https://stackoverflow.com/a/21224179
106554 function simplify(str) {
106555 if (typeof str !== 'string') return '';
106556 return diacritics.remove(str.replace(/&/g, 'and').replace(/İ/ig, 'i').replace(/[\s\-=_!"#%'*{},.\/:;?\(\)\[\]@\\$\^*+<>«»~`’\u00a1\u00a7\u00b6\u00b7\u00bf\u037e\u0387\u055a-\u055f\u0589\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964\u0965\u0970\u0af0\u0df4\u0e4f\u0e5a\u0e5b\u0f04-\u0f12\u0f14\u0f85\u0fd0-\u0fd4\u0fd9\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u166d\u166e\u16eb-\u16ed\u1735\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u1805\u1807-\u180a\u1944\u1945\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e\u1c7f\u1cc0-\u1cc7\u1cd3\u200b-\u200f\u2016\u2017\u2020-\u2027\u2030-\u2038\u203b-\u203e\u2041-\u2043\u2047-\u2051\u2053\u2055-\u205e\u2cf9-\u2cfc\u2cfe\u2cff\u2d70\u2e00\u2e01\u2e06-\u2e08\u2e0b\u2e0e-\u2e16\u2e18\u2e19\u2e1b\u2e1e\u2e1f\u2e2a-\u2e2e\u2e30-\u2e39\u3001-\u3003\u303d\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uaaf0\uaaf1\uabeb\ufe10-\ufe16\ufe19\ufe30\ufe45\ufe46\ufe49-\ufe4c\ufe50-\ufe52\ufe54-\ufe57\ufe5f-\ufe61\ufe68\ufe6a\ufe6b\ufeff\uff01-\uff03\uff05-\uff07\uff0a\uff0c\uff0e\uff0f\uff1a\uff1b\uff1f\uff20\uff3c\uff61\uff64\uff65]+/g, '').toLowerCase());
106560 // Resolves the text strings for a given community index item
106563 // `item`: Object containing the community index item
106564 // `defaults`: Object containing the community index default strings
106565 // `localizerFn?`: optional function we will call to do the localization.
106566 // This function should be like the iD `t()` function that
106567 // accepts a `stringID` and returns a localized string
106570 // An Object containing all the resolved strings:
106572 // name: 'talk-ru Mailing List',
106573 // url: 'https://lists.openstreetmap.org/listinfo/talk-ru',
106574 // signupUrl: 'https://example.url/signup',
106575 // description: 'A one line description',
106576 // extendedDescription: 'Extended description',
106577 // nameHTML: '<a href="the url">the name</a>',
106578 // urlHTML: '<a href="the url">the url</a>',
106579 // signupUrlHTML: '<a href="the signupUrl">the signupUrl</a>',
106580 // descriptionHTML: the description, with urls and signupUrls linkified,
106581 // extendedDescriptionHTML: the extendedDescription with urls and signupUrls linkified
106585 function resolveStrings(item, defaults, localizerFn) {
106586 var itemStrings = Object.assign({}, item.strings); // shallow clone
106588 var defaultStrings = Object.assign({}, defaults[item.type]); // shallow clone
106590 var anyToken = new RegExp(/(\{\w+\})/, 'gi'); // Pre-localize the item and default strings
106593 if (itemStrings.community) {
106594 var communityID = simplify(itemStrings.community);
106595 itemStrings.community = localizerFn("_communities.".concat(communityID));
106598 ['name', 'description', 'extendedDescription'].forEach(function (prop) {
106599 if (defaultStrings[prop]) defaultStrings[prop] = localizerFn("_defaults.".concat(item.type, ".").concat(prop));
106600 if (itemStrings[prop]) itemStrings[prop] = localizerFn("".concat(item.id, ".").concat(prop));
106606 community: itemStrings.community,
106607 signupUrl: itemStrings.signupUrl,
106609 }; // Resolve URLs first (which may refer to {account})
106611 if (!replacements.signupUrl) {
106612 replacements.signupUrl = resolve(itemStrings.signupUrl || defaultStrings.signupUrl);
106615 if (!replacements.url) {
106616 replacements.url = resolve(itemStrings.url || defaultStrings.url);
106620 name: resolve(itemStrings.name || defaultStrings.name),
106621 url: resolve(itemStrings.url || defaultStrings.url),
106622 signupUrl: resolve(itemStrings.signupUrl || defaultStrings.signupUrl),
106623 description: resolve(itemStrings.description || defaultStrings.description),
106624 extendedDescription: resolve(itemStrings.extendedDescription || defaultStrings.extendedDescription)
106625 }; // Generate linkified strings
106627 resolved.nameHTML = linkify(resolved.url, resolved.name);
106628 resolved.urlHTML = linkify(resolved.url);
106629 resolved.signupUrlHTML = linkify(resolved.signupUrl);
106630 resolved.descriptionHTML = resolve(itemStrings.description || defaultStrings.description, true);
106631 resolved.extendedDescriptionHTML = resolve(itemStrings.extendedDescription || defaultStrings.extendedDescription, true);
106634 function resolve(s, addLinks) {
106635 if (!s) return undefined;
106638 for (var key in replacements) {
106639 var token = "{".concat(key, "}");
106640 var regex = new RegExp(token, 'g');
106642 if (regex.test(result)) {
106643 var replacement = replacements[key];
106646 throw new Error("Cannot resolve token: ".concat(token));
106648 if (addLinks && (key === 'signupUrl' || key === 'url')) {
106649 replacement = linkify(replacement);
106652 result = result.replace(regex, replacement);
106655 } // There shouldn't be any leftover tokens in a resolved string
106658 var leftovers = result.match(anyToken);
106661 throw new Error("Cannot resolve tokens: ".concat(leftovers));
106662 } // Linkify subreddits like `/r/openstreetmap`
106663 // https://github.com/osmlab/osm-community-index/issues/82
106664 // https://github.com/openstreetmap/iD/issues/4997
106667 if (addLinks && item.type === 'reddit') {
106668 result = result.replace(/(\/r\/\w+\/*)/i, function (match) {
106669 return linkify(resolved.url, match);
106676 function linkify(url, text) {
106677 if (!url) return undefined;
106679 return "<a target=\"_blank\" href=\"".concat(url, "\">").concat(text, "</a>");
106684 function uiSuccess(context) {
106686 var dispatch = dispatch$8('cancel');
106692 ensureOSMCommunityIndex(); // start fetching the data
106694 function ensureOSMCommunityIndex() {
106695 var data = _mainFileFetcher;
106696 return Promise.all([data.get('oci_features'), data.get('oci_resources'), data.get('oci_defaults')]).then(function (vals) {
106697 if (_oci) return _oci; // Merge Custom Features
106699 if (vals[0] && Array.isArray(vals[0].features)) {
106700 _mainLocations.mergeCustomGeoJSON(vals[0]);
106703 var ociResources = Object.values(vals[1].resources);
106705 if (ociResources.length) {
106706 // Resolve all locationSet features.
106707 return _mainLocations.mergeLocationSets(ociResources).then(function () {
106709 resources: ociResources,
106710 defaults: vals[2].defaults
106718 defaults: vals[2].defaults
106723 } // string-to-date parsing in JavaScript is weird
106726 function parseEventDate(when) {
106732 // if no trailing 'Z', add one
106733 raw += 'Z'; // this forces date to be parsed as a UTC date
106736 var parsed = new Date(raw);
106737 return new Date(parsed.toUTCString().substr(0, 25)); // convert to local timezone
106740 function success(selection) {
106741 var header = selection.append('div').attr('class', 'header fillL');
106742 header.append('h2').call(_t.append('success.just_edited'));
106743 header.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
106744 return dispatch.call('cancel');
106745 }).call(svgIcon('#iD-icon-close'));
106746 var body = selection.append('div').attr('class', 'body save-success fillL');
106747 var summary = body.append('div').attr('class', 'save-summary');
106748 summary.append('h3').call(_t.append('success.thank_you' + (_location ? '_location' : ''), {
106751 summary.append('p').call(_t.append('success.help_html')).append('a').attr('class', 'link-out').attr('target', '_blank').attr('href', _t('success.help_link_url')).call(svgIcon('#iD-icon-out-link', 'inline')).append('span').call(_t.append('success.help_link_text'));
106752 var osm = context.connection();
106754 var changesetURL = osm.changesetURL(_changeset.id);
106755 var table = summary.append('table').attr('class', 'summary-table');
106756 var row = table.append('tr').attr('class', 'summary-row');
106757 row.append('td').attr('class', 'cell-icon summary-icon').append('a').attr('target', '_blank').attr('href', changesetURL).append('svg').attr('class', 'logo-small').append('use').attr('xlink:href', '#iD-logo-osm');
106758 var summaryDetail = row.append('td').attr('class', 'cell-detail summary-detail');
106759 summaryDetail.append('a').attr('class', 'cell-detail summary-view-on-osm').attr('target', '_blank').attr('href', changesetURL).call(_t.append('success.view_on_osm'));
106760 summaryDetail.append('div').html(_t.html('success.changeset_id', {
106762 html: "<a href=\"".concat(changesetURL, "\" target=\"_blank\">").concat(_changeset.id, "</a>")
106764 })); // Get OSM community index features intersecting the map..
106766 ensureOSMCommunityIndex().then(function (oci) {
106767 var loc = context.map().center();
106768 var validLocations = _mainLocations.locationsAt(loc); // Gather the communities
106771 oci.resources.forEach(function (resource) {
106772 var area = validLocations[resource.locationSetID];
106773 if (!area) return; // Resolve strings
106775 var localizer = function localizer(stringID) {
106776 return _t.html("community.".concat(stringID));
106779 resource.resolved = resolveStrings(resource, oci.defaults, localizer);
106782 order: resource.order || 0,
106785 }); // sort communities by feature area ascending, community order descending
106787 communities.sort(function (a, b) {
106788 return a.area - b.area || b.order - a.order;
106790 body.call(showCommunityLinks, communities.map(function (c) {
106796 function showCommunityLinks(selection, resources) {
106797 var communityLinks = selection.append('div').attr('class', 'save-communityLinks');
106798 communityLinks.append('h3').call(_t.append('success.like_osm'));
106799 var table = communityLinks.append('table').attr('class', 'community-table');
106800 var row = table.selectAll('.community-row').data(resources);
106801 var rowEnter = row.enter().append('tr').attr('class', 'community-row');
106802 rowEnter.append('td').attr('class', 'cell-icon community-icon').append('a').attr('target', '_blank').attr('href', function (d) {
106804 }).append('svg').attr('class', 'logo-small').append('use').attr('xlink:href', function (d) {
106805 return "#community-".concat(d.type);
106807 var communityDetail = rowEnter.append('td').attr('class', 'cell-detail community-detail');
106808 communityDetail.each(showCommunityDetails);
106809 communityLinks.append('div').attr('class', 'community-missing').call(_t.append('success.missing')).append('a').attr('class', 'link-out').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).attr('href', 'https://github.com/osmlab/osm-community-index/issues').append('span').call(_t.append('success.tell_us'));
106812 function showCommunityDetails(d) {
106813 var selection = select(this);
106814 var communityID = d.id;
106815 selection.append('div').attr('class', 'community-name').html(d.resolved.nameHTML);
106816 selection.append('div').attr('class', 'community-description').html(d.resolved.descriptionHTML); // Create an expanding section if any of these are present..
106818 if (d.resolved.extendedDescriptionHTML || d.languageCodes && d.languageCodes.length) {
106819 selection.append('div').call(uiDisclosure(context, "community-more-".concat(d.id), false).expanded(false).updatePreference(false).label(_t.html('success.more')).content(showMore));
106822 var nextEvents = (d.events || []).map(function (event) {
106823 event.date = parseEventDate(event.when);
106825 }).filter(function (event) {
106826 // date is valid and future (or today)
106827 var t = event.date.getTime();
106828 var now = new Date().setHours(0, 0, 0, 0);
106829 return !isNaN(t) && t >= now;
106830 }).sort(function (a, b) {
106831 // sort by date ascending
106832 return a.date < b.date ? -1 : a.date > b.date ? 1 : 0;
106833 }).slice(0, MAXEVENTS); // limit number of events shown
106835 if (nextEvents.length) {
106836 selection.append('div').call(uiDisclosure(context, "community-events-".concat(d.id), false).expanded(false).updatePreference(false).label(_t.html('success.events')).content(showNextEvents)).select('.hide-toggle').append('span').attr('class', 'badge-text').text(nextEvents.length);
106839 function showMore(selection) {
106840 var more = selection.selectAll('.community-more').data([0]);
106841 var moreEnter = more.enter().append('div').attr('class', 'community-more');
106843 if (d.resolved.extendedDescriptionHTML) {
106844 moreEnter.append('div').attr('class', 'community-extended-description').html(d.resolved.extendedDescriptionHTML);
106847 if (d.languageCodes && d.languageCodes.length) {
106848 var languageList = d.languageCodes.map(function (code) {
106849 return _mainLocalizer.languageName(code);
106851 moreEnter.append('div').attr('class', 'community-languages').call(_t.append('success.languages', {
106852 languages: languageList
106857 function showNextEvents(selection) {
106858 var events = selection.append('div').attr('class', 'community-events');
106859 var item = events.selectAll('.community-event').data(nextEvents);
106860 var itemEnter = item.enter().append('div').attr('class', 'community-event');
106861 itemEnter.append('div').attr('class', 'community-event-name').append('a').attr('target', '_blank').attr('href', function (d) {
106867 name = _t("community.".concat(communityID, ".events.").concat(d.id, ".name"), {
106874 itemEnter.append('div').attr('class', 'community-event-when').text(function (d) {
106882 if (d.date.getHours() || d.date.getMinutes()) {
106883 // include time if it has one
106884 options.hour = 'numeric';
106885 options.minute = 'numeric';
106888 return d.date.toLocaleString(_mainLocalizer.localeCode(), options);
106890 itemEnter.append('div').attr('class', 'community-event-where').text(function (d) {
106894 where = _t("community.".concat(communityID, ".events.").concat(d.id, ".where"), {
106901 itemEnter.append('div').attr('class', 'community-event-description').text(function (d) {
106902 var description = d.description;
106905 description = _t("community.".concat(communityID, ".events.").concat(d.id, ".description"), {
106915 success.changeset = function (val) {
106916 if (!arguments.length) return _changeset;
106921 success.location = function (val) {
106922 if (!arguments.length) return _location;
106927 return utilRebind(success, dispatch, 'on');
106931 var isNewVersion = false;
106933 function uiVersion(context) {
106934 var currVersion = context.version;
106935 var matchedVersion = currVersion.match(/\d+\.\d+\.\d+.*/);
106937 if (sawVersion === null && matchedVersion !== null) {
106938 if (corePreferences('sawVersion')) {
106940 isNewVersion = corePreferences('sawVersion') !== currVersion && currVersion.indexOf('-') === -1;
106946 corePreferences('sawVersion', currVersion);
106947 sawVersion = currVersion;
106950 return function (selection) {
106951 selection.append('a').attr('target', '_blank').attr('href', 'https://github.com/openstreetmap/iD').text(currVersion); // only show new version indicator to users that have used iD before
106953 if (isNewVersion && !isNewUser) {
106954 selection.append('a').attr('class', 'badge').attr('target', '_blank').attr('href', 'https://github.com/openstreetmap/iD/blob/release/CHANGELOG.md#whats-new').call(svgIcon('#maki-gift-11')).call(uiTooltip().title(_t.html('version.whats_new', {
106956 })).placement('top').scrollContainer(context.container().select('.main-footer-wrap')));
106961 function uiZoom(context) {
106965 title: _t.html('zoom.in'),
106967 disabled: function disabled() {
106968 return !context.map().canZoomIn();
106970 disabledTitle: _t.html('zoom.disabled.in'),
106975 title: _t.html('zoom.out'),
106977 disabled: function disabled() {
106978 return !context.map().canZoomOut();
106980 disabledTitle: _t.html('zoom.disabled.out'),
106984 function zoomIn(d3_event) {
106985 if (d3_event.shiftKey) return;
106986 d3_event.preventDefault();
106987 context.map().zoomIn();
106990 function zoomOut(d3_event) {
106991 if (d3_event.shiftKey) return;
106992 d3_event.preventDefault();
106993 context.map().zoomOut();
106996 function zoomInFurther(d3_event) {
106997 if (d3_event.shiftKey) return;
106998 d3_event.preventDefault();
106999 context.map().zoomInFurther();
107002 function zoomOutFurther(d3_event) {
107003 if (d3_event.shiftKey) return;
107004 d3_event.preventDefault();
107005 context.map().zoomOutFurther();
107008 return function (selection) {
107009 var tooltipBehavior = uiTooltip().placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left').title(function (d) {
107011 return d.disabledTitle;
107019 var buttons = selection.selectAll('button').data(zooms).enter().append('button').attr('class', function (d) {
107021 }).on('pointerup.editor', function (d3_event) {
107022 lastPointerUpType = d3_event.pointerType;
107023 }).on('click.editor', function (d3_event, d) {
107026 } else if (lastPointerUpType === 'touch' || lastPointerUpType === 'pen') {
107027 context.ui().flash.duration(2000).iconName('#' + d.icon).iconClass('disabled').label(d.disabledTitle)();
107030 lastPointerUpType = null;
107031 }).call(tooltipBehavior);
107032 buttons.each(function (d) {
107033 select(this).call(svgIcon('#' + d.icon, 'light'));
107035 utilKeybinding.plusKeys.forEach(function (key) {
107036 context.keybinding().on([key], zoomIn);
107037 context.keybinding().on([uiCmd('⌥' + key)], zoomInFurther);
107039 utilKeybinding.minusKeys.forEach(function (key) {
107040 context.keybinding().on([key], zoomOut);
107041 context.keybinding().on([uiCmd('⌥' + key)], zoomOutFurther);
107044 function updateButtonStates() {
107045 buttons.classed('disabled', function (d) {
107048 var selection = select(this);
107050 if (!selection.select('.tooltip.in').empty()) {
107051 selection.call(tooltipBehavior.updateContent);
107057 context.map().on('move.uiZoom', updateButtonStates);
107061 function uiSectionRawTagEditor(id, context) {
107062 var section = uiSection(id, context).classes('raw-tag-editor').label(function () {
107063 var count = Object.keys(_tags).filter(function (d) {
107066 return _t.html('inspector.title_count', {
107068 html: _t.html('inspector.tags')
107072 }).expandedByDefault(false).disclosureContent(renderDisclosureContent);
107073 var taginfo = services.taginfo;
107074 var dispatch = dispatch$8('change');
107075 var availableViews = [{
107083 var _tagView = corePreferences('raw-tag-editor-view') || 'list'; // 'list, 'text'
107086 var _readOnlyTags = []; // the keys in the order we want them to display
107089 var _showBlank = false;
107090 var _pendingChange = null;
107100 var _didInteract = false;
107102 function interacted() {
107106 function renderDisclosureContent(wrap) {
107108 _orderedKeys = _orderedKeys.filter(function (key) {
107109 return _tags[key] !== undefined;
107110 }); // When switching to a different entity or changing the state (hover/select)
107111 // reorder the keys alphabetically.
107112 // We trigger this by emptying the `_orderedKeys` array, then it will be rebuilt here.
107113 // Otherwise leave their order alone - #5857, #5927
107115 var all = Object.keys(_tags).sort();
107116 var missingKeys = utilArrayDifference(all, _orderedKeys);
107118 for (var i in missingKeys) {
107119 _orderedKeys.push(missingKeys[i]);
107123 var rowData = _orderedKeys.map(function (key, i) {
107129 }); // append blank row last, if necessary
107132 if (!rowData.length || _showBlank) {
107142 var options = wrap.selectAll('.raw-tag-options').data([0]);
107143 options.exit().remove();
107144 var optionsEnter = options.enter().insert('div', ':first-child').attr('class', 'raw-tag-options').attr('role', 'tablist');
107145 var optionEnter = optionsEnter.selectAll('.raw-tag-option').data(availableViews, function (d) {
107148 optionEnter.append('button').attr('class', function (d) {
107149 return 'raw-tag-option raw-tag-option-' + d.id + (_tagView === d.id ? ' selected' : '');
107150 }).attr('aria-selected', function (d) {
107151 return _tagView === d.id;
107152 }).attr('role', 'tab').attr('title', function (d) {
107153 return _t('icons.' + d.id);
107154 }).on('click', function (d3_event, d) {
107156 corePreferences('raw-tag-editor-view', d.id);
107157 wrap.selectAll('.raw-tag-option').classed('selected', function (datum) {
107159 }).attr('aria-selected', function (datum) {
107162 wrap.selectAll('.tag-text').classed('hide', d.id !== 'text').each(setTextareaHeight);
107163 wrap.selectAll('.tag-list, .add-row').classed('hide', d.id !== 'list');
107165 select(this).call(svgIcon(d.icon));
107168 var textData = rowsToText(rowData);
107169 var textarea = wrap.selectAll('.tag-text').data([0]);
107170 textarea = textarea.enter().append('textarea').attr('class', 'tag-text' + (_tagView !== 'text' ? ' hide' : '')).call(utilNoAuto).attr('placeholder', _t('inspector.key_value')).attr('spellcheck', 'false').merge(textarea);
107171 textarea.call(utilGetSetValue, textData).each(setTextareaHeight).on('input', setTextareaHeight).on('focus', interacted).on('blur', textChanged).on('change', textChanged); // View as List
107173 var list = wrap.selectAll('.tag-list').data([0]);
107174 list = list.enter().append('ul').attr('class', 'tag-list' + (_tagView !== 'list' ? ' hide' : '')).merge(list); // Container for the Add button
107176 var addRowEnter = wrap.selectAll('.add-row').data([0]).enter().append('div').attr('class', 'add-row' + (_tagView !== 'list' ? ' hide' : ''));
107177 addRowEnter.append('button').attr('class', 'add-tag').attr('aria-label', _t('inspector.add_to_tag')).call(svgIcon('#iD-icon-plus', 'light')).call(uiTooltip().title(_t.html('inspector.add_to_tag')).placement(_mainLocalizer.textDirection() === 'ltr' ? 'right' : 'left')).on('click', addTag);
107178 addRowEnter.append('div').attr('class', 'space-value'); // preserve space
107180 addRowEnter.append('div').attr('class', 'space-buttons'); // preserve space
107183 var items = list.selectAll('.tag-row').data(rowData, function (d) {
107186 items.exit().each(unbind).remove(); // Enter
107188 var itemsEnter = items.enter().append('li').attr('class', 'tag-row').classed('readonly', isReadOnly);
107189 var innerWrap = itemsEnter.append('div').attr('class', 'inner-wrap');
107190 innerWrap.append('div').attr('class', 'key-wrap').append('input').property('type', 'text').attr('class', 'key').call(utilNoAuto).on('focus', interacted).on('blur', keyChange).on('change', keyChange);
107191 innerWrap.append('div').attr('class', 'value-wrap').append('input').property('type', 'text').attr('class', 'value').call(utilNoAuto).on('focus', interacted).on('blur', valueChange).on('change', valueChange).on('keydown.push-more', pushMore);
107192 innerWrap.append('button').attr('class', 'form-field-button remove').attr('title', _t('icons.remove')).call(svgIcon('#iD-operation-delete')); // Update
107194 items = items.merge(itemsEnter).sort(function (a, b) {
107195 return a.index - b.index;
107197 items.each(function (d) {
107198 var row = select(this);
107199 var key = row.select('input.key'); // propagate bound data
107201 var value = row.select('input.value'); // propagate bound data
107203 if (_entityIDs && taginfo && _state !== 'hover') {
107204 bindTypeahead(key, value);
107207 var referenceOptions = {
107211 if (typeof d.value === 'string') {
107212 referenceOptions.value = d.value;
107215 var reference = uiTagReference(referenceOptions);
107217 if (_state === 'hover') {
107218 reference.showing(false);
107221 row.select('.inner-wrap') // propagate bound data
107222 .call(reference.button);
107223 row.call(reference.body);
107224 row.select('button.remove'); // propagate bound data
107226 items.selectAll('input.key').attr('title', function (d) {
107228 }).call(utilGetSetValue, function (d) {
107230 }).attr('readonly', function (d) {
107231 return isReadOnly(d) || null;
107233 items.selectAll('input.value').attr('title', function (d) {
107234 return Array.isArray(d.value) ? d.value.filter(Boolean).join('\n') : d.value;
107235 }).classed('mixed', function (d) {
107236 return Array.isArray(d.value);
107237 }).attr('placeholder', function (d) {
107238 return typeof d.value === 'string' ? null : _t('inspector.multiple_values');
107239 }).call(utilGetSetValue, function (d) {
107240 return typeof d.value === 'string' ? d.value : '';
107241 }).attr('readonly', function (d) {
107242 return isReadOnly(d) || null;
107244 items.selectAll('button.remove').on(('PointerEvent' in window ? 'pointer' : 'mouse') + 'down', removeTag); // 'click' fires too late - #5878
107247 function isReadOnly(d) {
107248 for (var i = 0; i < _readOnlyTags.length; i++) {
107249 if (d.key.match(_readOnlyTags[i]) !== null) {
107257 function setTextareaHeight() {
107258 if (_tagView !== 'text') return;
107259 var selection = select(this);
107260 var matches = selection.node().value.match(/\n/g);
107261 var lineCount = 2 + Number(matches && matches.length);
107263 selection.style('height', lineCount * lineHeight + 'px');
107266 function stringify(s) {
107267 return JSON.stringify(s).slice(1, -1); // without leading/trailing "
107270 function unstringify(s) {
107274 if (s.length < 1 || s.charAt(0) !== '"') {
107278 if (s.length < 2 || s.charAt(s.length - 1) !== '"' || s.charAt(s.length - 1) === '"' && s.charAt(s.length - 2) === '\\') {
107282 return JSON.parse(leading + s + trailing);
107285 function rowsToText(rows) {
107286 var str = rows.filter(function (row) {
107287 return row.key && row.key.trim() !== '';
107288 }).map(function (row) {
107289 var rawVal = row.value;
107290 if (typeof rawVal !== 'string') rawVal = '*';
107291 var val = rawVal ? stringify(rawVal) : '';
107292 return stringify(row.key) + '=' + val;
107295 if (_state !== 'hover' && str.length) {
107302 function textChanged() {
107303 var newText = this.value.trim();
107305 newText.split('\n').forEach(function (row) {
107306 var m = row.match(/^\s*([^=]+)=(.*)$/);
107309 var k = context.cleanTagKey(unstringify(m[1].trim()));
107310 var v = context.cleanTagValue(unstringify(m[2].trim()));
107314 var tagDiff = utilTagDiff(_tags, newTags);
107315 if (!tagDiff.length) return;
107316 _pendingChange = _pendingChange || {};
107317 tagDiff.forEach(function (change) {
107320 })) return; // skip unchanged multiselection placeholders
107322 if (change.newVal === '*' && typeof change.oldVal !== 'string') return;
107324 if (change.type === '-') {
107325 _pendingChange[change.key] = undefined;
107326 } else if (change.type === '+') {
107327 _pendingChange[change.key] = change.newVal || '';
107331 if (Object.keys(_pendingChange).length === 0) {
107339 function pushMore(d3_event) {
107340 // if pressing Tab on the last value field with content, add a blank row
107341 if (d3_event.keyCode === 9 && !d3_event.shiftKey && section.selection().selectAll('.tag-list li:last-child input.value').node() === this && utilGetSetValue(select(this))) {
107346 function bindTypeahead(key, value) {
107347 if (isReadOnly(key.datum())) return;
107349 if (Array.isArray(value.datum().value)) {
107350 value.call(uiCombobox(context, 'tag-value').minItems(1).fetcher(function (value, callback) {
107351 var keyString = utilGetSetValue(key);
107352 if (!_tags[keyString]) return;
107354 var data = _tags[keyString].filter(Boolean).map(function (tagValue) {
107366 var geometry = context.graph().geometry(_entityIDs[0]);
107367 key.call(uiCombobox(context, 'tag-key').fetcher(function (value, callback) {
107372 }, function (err, data) {
107374 var filtered = data.filter(function (d) {
107375 return _tags[d.value] === undefined;
107377 callback(sort(value, filtered));
107381 value.call(uiCombobox(context, 'tag-value').fetcher(function (value, callback) {
107384 key: utilGetSetValue(key),
107387 }, function (err, data) {
107388 if (!err) callback(sort(value, data));
107392 function sort(value, data) {
107396 for (var i = 0; i < data.length; i++) {
107397 if (data[i].value.substring(0, value.length) === value) {
107398 sameletter.push(data[i]);
107404 return sameletter.concat(other);
107409 var row = select(this);
107410 row.selectAll('input.key').call(uiCombobox.off, context);
107411 row.selectAll('input.value').call(uiCombobox.off, context);
107414 function keyChange(d3_event, d) {
107415 if (select(this).attr('readonly')) return;
107416 var kOld = d.key; // exit if we are currently about to delete this row anyway - #6366
107418 if (_pendingChange && _pendingChange.hasOwnProperty(kOld) && _pendingChange[kOld] === undefined) return;
107419 var kNew = context.cleanTagKey(this.value.trim()); // allow no change if the key should be readonly
107428 if (kNew && kNew !== kOld && _tags[kNew] !== undefined) {
107429 // new key is already in use, switch focus to the existing row
107430 this.value = kOld; // reset the key
107432 section.selection().selectAll('.tag-list input.value').each(function (d) {
107434 // send focus to that other value combo instead
107435 var input = select(this).node();
107443 _pendingChange = _pendingChange || {};
107446 if (kOld === kNew) return; // a tag key was renamed
107448 _pendingChange[kNew] = _pendingChange[kOld] || {
107451 _pendingChange[kOld] = undefined;
107454 var row = this.parentNode.parentNode;
107455 var inputVal = select(row).selectAll('input.value');
107456 var vNew = context.cleanTagValue(utilGetSetValue(inputVal));
107457 _pendingChange[kNew] = vNew;
107458 utilGetSetValue(inputVal, vNew);
107459 } // update the ordered key index so this row doesn't change position
107462 var existingKeyIndex = _orderedKeys.indexOf(kOld);
107464 if (existingKeyIndex !== -1) _orderedKeys[existingKeyIndex] = kNew;
107465 d.key = kNew; // update datum to avoid exit/enter on tag update
107471 function valueChange(d3_event, d) {
107472 if (isReadOnly(d)) return; // exit if this is a multiselection and no value was entered
107474 if (typeof d.value !== 'string' && !this.value) return; // exit if we are currently about to delete this row anyway - #6366
107476 if (_pendingChange && _pendingChange.hasOwnProperty(d.key) && _pendingChange[d.key] === undefined) return;
107477 _pendingChange = _pendingChange || {};
107478 _pendingChange[d.key] = context.cleanTagValue(this.value);
107482 function removeTag(d3_event, d) {
107483 if (isReadOnly(d)) return;
107486 // removing the blank row
107490 // remove the key from the ordered key index
107491 _orderedKeys = _orderedKeys.filter(function (key) {
107494 _pendingChange = _pendingChange || {};
107495 _pendingChange[d.key] = undefined;
107501 // Delay render in case this click is blurring an edited combo.
107502 // Without the setTimeout, the `content` render would wipe out the pending tag change.
107503 window.setTimeout(function () {
107506 section.selection().selectAll('.tag-list li:last-child input.key').node().focus();
107510 function scheduleChange() {
107511 // Cache IDs in case the editor is reloaded before the change event is called. - #6028
107512 var entityIDs = _entityIDs; // Delay change in case this change is blurring an edited combo. - #5878
107514 window.setTimeout(function () {
107515 if (!_pendingChange) return;
107516 dispatch.call('change', this, entityIDs, _pendingChange);
107521 section.state = function (val) {
107522 if (!arguments.length) return _state;
107532 section.presets = function (val) {
107533 if (!arguments.length) return _presets;
107536 if (_presets && _presets.length && _presets[0].isFallback()) {
107537 section.disclosureExpanded(true); // don't collapse the disclosure if the mapper used the raw tag editor - #1881
107538 } else if (!_didInteract) {
107539 section.disclosureExpanded(null);
107545 section.tags = function (val) {
107546 if (!arguments.length) return _tags;
107551 section.entityIDs = function (val) {
107552 if (!arguments.length) return _entityIDs;
107554 if (!_entityIDs || !val || !utilArrayIdentical(_entityIDs, val)) {
107560 }; // pass an array of regular expressions to test against the tag key
107563 section.readOnlyTags = function (val) {
107564 if (!arguments.length) return _readOnlyTags;
107569 return utilRebind(section, dispatch, 'on');
107572 function uiDataEditor(context) {
107573 var dataHeader = uiDataHeader();
107574 var rawTagEditor = uiSectionRawTagEditor('custom-data-tag-editor', context).expandedByDefault(true).readOnlyTags([/./]);
107578 function dataEditor(selection) {
107579 var header = selection.selectAll('.header').data([0]);
107580 var headerEnter = header.enter().append('div').attr('class', 'header fillL');
107581 headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
107582 context.enter(modeBrowse(context));
107583 }).call(svgIcon('#iD-icon-close'));
107584 headerEnter.append('h2').call(_t.append('map_data.title'));
107585 var body = selection.selectAll('.body').data([0]);
107586 body = body.enter().append('div').attr('class', 'body').merge(body);
107587 var editor = body.selectAll('.data-editor').data([0]); // enter/update
107589 editor.enter().append('div').attr('class', 'modal-section data-editor').merge(editor).call(dataHeader.datum(_datum));
107590 var rte = body.selectAll('.raw-tag-editor').data([0]); // enter/update
107592 rte.enter().append('div').attr('class', 'raw-tag-editor data-editor').merge(rte).call(rawTagEditor.tags(_datum && _datum.properties || {}).state('hover').render).selectAll('textarea.tag-text').attr('readonly', true).classed('readonly', true);
107595 dataEditor.datum = function (val) {
107596 if (!arguments.length) return _datum;
107604 function uiOsmoseDetails(context) {
107607 function issueString(d, type) {
107608 if (!d) return ''; // Issue strings are cached from Osmose API
107610 var s = services.osmose.getStrings(d.itemType);
107611 return type in s ? s[type] : '';
107614 function osmoseDetails(selection) {
107615 var details = selection.selectAll('.error-details').data(_qaItem ? [_qaItem] : [], function (d) {
107616 return "".concat(d.id, "-").concat(d.status || 0);
107618 details.exit().remove();
107619 var detailsEnter = details.enter().append('div').attr('class', 'error-details qa-details-container'); // Description
107621 if (issueString(_qaItem, 'detail')) {
107622 var div = detailsEnter.append('div').attr('class', 'qa-details-subsection');
107623 div.append('h4').call(_t.append('QA.keepRight.detail_description'));
107624 div.append('p').attr('class', 'qa-details-description-text').html(function (d) {
107625 return issueString(d, 'detail');
107626 }).selectAll('a').attr('rel', 'noopener').attr('target', '_blank');
107627 } // Elements (populated later as data is requested)
107630 var detailsDiv = detailsEnter.append('div').attr('class', 'qa-details-subsection');
107631 var elemsDiv = detailsEnter.append('div').attr('class', 'qa-details-subsection'); // Suggested Fix (mustn't exist for every issue type)
107633 if (issueString(_qaItem, 'fix')) {
107634 var _div = detailsEnter.append('div').attr('class', 'qa-details-subsection');
107636 _div.append('h4').call(_t.append('QA.osmose.fix_title'));
107638 _div.append('p').html(function (d) {
107639 return issueString(d, 'fix');
107640 }).selectAll('a').attr('rel', 'noopener').attr('target', '_blank');
107641 } // Common Pitfalls (mustn't exist for every issue type)
107644 if (issueString(_qaItem, 'trap')) {
107645 var _div2 = detailsEnter.append('div').attr('class', 'qa-details-subsection');
107647 _div2.append('h4').call(_t.append('QA.osmose.trap_title'));
107649 _div2.append('p').html(function (d) {
107650 return issueString(d, 'trap');
107651 }).selectAll('a').attr('rel', 'noopener').attr('target', '_blank');
107652 } // Save current item to check if UI changed by time request resolves
107655 var thisItem = _qaItem;
107656 services.osmose.loadIssueDetail(_qaItem).then(function (d) {
107657 // No details to add if there are no associated issue elements
107658 if (!d.elems || d.elems.length === 0) return; // Do nothing if UI has moved on by the time this resolves
107660 if (context.selectedErrorID() !== thisItem.id && context.container().selectAll(".qaItem.osmose.hover.itemId-".concat(thisItem.id)).empty()) return; // Things like keys and values are dynamically added to a subtitle string
107663 detailsDiv.append('h4').call(_t.append('QA.osmose.detail_title'));
107664 detailsDiv.append('p').html(function (d) {
107666 }).selectAll('a').attr('rel', 'noopener').attr('target', '_blank');
107667 } // Create list of linked issue elements
107670 elemsDiv.append('h4').call(_t.append('QA.osmose.elems_title'));
107671 elemsDiv.append('ul').selectAll('li').data(d.elems).enter().append('li').append('a').attr('href', '#').attr('class', 'error_entity_link').text(function (d) {
107674 var link = select(this);
107675 var entityID = this.textContent;
107676 var entity = context.hasEntity(entityID); // Add click handler
107678 link.on('mouseenter', function () {
107679 utilHighlightEntities([entityID], true, context);
107680 }).on('mouseleave', function () {
107681 utilHighlightEntities([entityID], false, context);
107682 }).on('click', function (d3_event) {
107683 d3_event.preventDefault();
107684 utilHighlightEntities([entityID], false, context);
107685 var osmlayer = context.layers().layer('osm');
107687 if (!osmlayer.enabled()) {
107688 osmlayer.enabled(true);
107691 context.map().centerZoom(d.loc, 20);
107694 context.enter(modeSelect(context, [entityID]));
107696 context.loadEntity(entityID, function (err, result) {
107698 var entity = result.data.find(function (e) {
107699 return e.id === entityID;
107701 if (entity) context.enter(modeSelect(context, [entityID]));
107704 }); // Replace with friendly name if possible
107705 // (The entity may not yet be loaded into the graph)
107708 var name = utilDisplayName(entity); // try to use common name
107711 var preset = _mainPresetIndex.match(entity, context.graph());
107712 name = preset && !preset.isFallback() && preset.name(); // fallback to preset name
107719 }); // Don't hide entities related to this issue - #5880
107721 context.features().forceVisible(d.elems);
107722 context.map().pan([0, 0]); // trigger a redraw
107723 })["catch"](function (err) {
107724 console.log(err); // eslint-disable-line no-console
107728 osmoseDetails.issue = function (val) {
107729 if (!arguments.length) return _qaItem;
107737 function uiOsmoseHeader() {
107740 function issueTitle(d) {
107741 var unknown = _t('inspector.unknown');
107742 if (!d) return unknown; // Issue titles supplied by Osmose
107744 var s = services.osmose.getStrings(d.itemType);
107745 return 'title' in s ? s.title : unknown;
107748 function osmoseHeader(selection) {
107749 var header = selection.selectAll('.qa-header').data(_qaItem ? [_qaItem] : [], function (d) {
107750 return "".concat(d.id, "-").concat(d.status || 0);
107752 header.exit().remove();
107753 var headerEnter = header.enter().append('div').attr('class', 'qa-header');
107754 var svgEnter = headerEnter.append('div').attr('class', 'qa-header-icon').classed('new', function (d) {
107756 }).append('svg').attr('width', '20px').attr('height', '30px').attr('viewbox', '0 0 20 30').attr('class', function (d) {
107757 return "preset-icon-28 qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.itemType);
107759 svgEnter.append('polygon').attr('fill', function (d) {
107760 return services.osmose.getColor(d.item);
107761 }).attr('class', 'qaItem-fill').attr('points', '16,3 4,3 1,6 1,17 4,20 7,20 10,27 13,20 16,20 19,17.033 19,6');
107762 svgEnter.append('use').attr('class', 'icon-annotation').attr('width', '13px').attr('height', '13px').attr('transform', 'translate(3.5, 5)').attr('xlink:href', function (d) {
107768 var isMaki = /^maki-/.test(picon);
107769 return "#".concat(picon).concat(isMaki ? '-11' : '');
107772 headerEnter.append('div').attr('class', 'qa-header-label').text(issueTitle);
107775 osmoseHeader.issue = function (val) {
107776 if (!arguments.length) return _qaItem;
107784 function uiViewOnOsmose() {
107787 function viewOnOsmose(selection) {
107790 if (services.osmose && _qaItem instanceof QAItem) {
107791 url = services.osmose.itemURL(_qaItem);
107794 var link = selection.selectAll('.view-on-osmose').data(url ? [url] : []); // exit
107796 link.exit().remove(); // enter
107798 var linkEnter = link.enter().append('a').attr('class', 'view-on-osmose').attr('target', '_blank').attr('rel', 'noopener') // security measure
107799 .attr('href', function (d) {
107801 }).call(svgIcon('#iD-icon-out-link', 'inline'));
107802 linkEnter.append('span').call(_t.append('inspector.view_on_osmose'));
107805 viewOnOsmose.what = function (val) {
107806 if (!arguments.length) return _qaItem;
107814 function uiOsmoseEditor(context) {
107815 var dispatch = dispatch$8('change');
107816 var qaDetails = uiOsmoseDetails(context);
107817 var qaHeader = uiOsmoseHeader();
107821 function osmoseEditor(selection) {
107822 var header = selection.selectAll('.header').data([0]);
107823 var headerEnter = header.enter().append('div').attr('class', 'header fillL');
107824 headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
107825 return context.enter(modeBrowse(context));
107826 }).call(svgIcon('#iD-icon-close'));
107827 headerEnter.append('h2').call(_t.append('QA.osmose.title'));
107828 var body = selection.selectAll('.body').data([0]);
107829 body = body.enter().append('div').attr('class', 'body').merge(body);
107830 var editor = body.selectAll('.qa-editor').data([0]);
107831 editor.enter().append('div').attr('class', 'modal-section qa-editor').merge(editor).call(qaHeader.issue(_qaItem)).call(qaDetails.issue(_qaItem)).call(osmoseSaveSection);
107832 var footer = selection.selectAll('.footer').data([0]);
107833 footer.enter().append('div').attr('class', 'footer').merge(footer).call(uiViewOnOsmose().what(_qaItem));
107836 function osmoseSaveSection(selection) {
107837 var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
107839 var isShown = _qaItem && isSelected;
107840 var saveSection = selection.selectAll('.qa-save').data(isShown ? [_qaItem] : [], function (d) {
107841 return "".concat(d.id, "-").concat(d.status || 0);
107844 saveSection.exit().remove(); // enter
107846 var saveSectionEnter = saveSection.enter().append('div').attr('class', 'qa-save save-section cf'); // update
107848 saveSection = saveSectionEnter.merge(saveSection).call(qaSaveButtons);
107851 function qaSaveButtons(selection) {
107852 var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
107854 var buttonSection = selection.selectAll('.buttons').data(isSelected ? [_qaItem] : [], function (d) {
107855 return d.status + d.id;
107858 buttonSection.exit().remove(); // enter
107860 var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons');
107861 buttonEnter.append('button').attr('class', 'button close-button action');
107862 buttonEnter.append('button').attr('class', 'button ignore-button action'); // update
107864 buttonSection = buttonSection.merge(buttonEnter);
107865 buttonSection.select('.close-button').call(_t.append('QA.keepRight.close')).on('click.close', function (d3_event, d) {
107866 this.blur(); // avoid keeping focus on the button - #4641
107868 var qaService = services.osmose;
107872 qaService.postUpdate(d, function (err, item) {
107873 return dispatch.call('change', item);
107877 buttonSection.select('.ignore-button').call(_t.append('QA.keepRight.ignore')).on('click.ignore', function (d3_event, d) {
107878 this.blur(); // avoid keeping focus on the button - #4641
107880 var qaService = services.osmose;
107884 qaService.postUpdate(d, function (err, item) {
107885 return dispatch.call('change', item);
107889 } // NOTE: Don't change method name until UI v3 is merged
107892 osmoseEditor.error = function (val) {
107893 if (!arguments.length) return _qaItem;
107898 return utilRebind(osmoseEditor, dispatch, 'on');
107901 function uiSidebar(context) {
107902 var inspector = uiInspector(context);
107903 var dataEditor = uiDataEditor(context);
107904 var noteEditor = uiNoteEditor(context);
107905 var improveOsmEditor = uiImproveOsmEditor(context);
107906 var keepRightEditor = uiKeepRightEditor(context);
107907 var osmoseEditor = uiOsmoseEditor(context);
107913 var _wasQaItem = false; // use pointer events on supported platforms; fallback to mouse events
107915 var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
107917 function sidebar(selection) {
107918 var container = context.container();
107922 var dragOffset; // Set the initial width constraints
107924 selection.style('min-width', minWidth + 'px').style('max-width', '400px').style('width', '33.3333%');
107925 var resizer = selection.append('div').attr('class', 'sidebar-resizer').on(_pointerPrefix + 'down.sidebar-resizer', pointerdown);
107926 var downPointerId, lastClientX, containerLocGetter;
107928 function pointerdown(d3_event) {
107929 if (downPointerId) return;
107930 if ('button' in d3_event && d3_event.button !== 0) return;
107931 downPointerId = d3_event.pointerId || 'mouse';
107932 lastClientX = d3_event.clientX;
107933 containerLocGetter = utilFastMouse(container.node()); // offset from edge of sidebar-resizer
107935 dragOffset = utilFastMouse(resizer.node())(d3_event)[0] - 1;
107936 sidebarWidth = selection.node().getBoundingClientRect().width;
107937 containerWidth = container.node().getBoundingClientRect().width;
107938 var widthPct = sidebarWidth / containerWidth * 100;
107939 selection.style('width', widthPct + '%') // lock in current width
107940 .style('max-width', '85%'); // but allow larger widths
107942 resizer.classed('dragging', true);
107943 select(window).on('touchmove.sidebar-resizer', function (d3_event) {
107944 // disable page scrolling while resizing on touch input
107945 d3_event.preventDefault();
107948 }).on(_pointerPrefix + 'move.sidebar-resizer', pointermove).on(_pointerPrefix + 'up.sidebar-resizer pointercancel.sidebar-resizer', pointerup);
107951 function pointermove(d3_event) {
107952 if (downPointerId !== (d3_event.pointerId || 'mouse')) return;
107953 d3_event.preventDefault();
107954 var dx = d3_event.clientX - lastClientX;
107955 lastClientX = d3_event.clientX;
107956 var isRTL = _mainLocalizer.textDirection() === 'rtl';
107957 var scaleX = isRTL ? 0 : 1;
107958 var xMarginProperty = isRTL ? 'margin-right' : 'margin-left';
107959 var x = containerLocGetter(d3_event)[0] - dragOffset;
107960 sidebarWidth = isRTL ? containerWidth - x : x;
107961 var isCollapsed = selection.classed('collapsed');
107962 var shouldCollapse = sidebarWidth < minWidth;
107963 selection.classed('collapsed', shouldCollapse);
107967 selection.style(xMarginProperty, '-400px').style('width', '400px');
107968 context.ui().onResize([(sidebarWidth - dx) * scaleX, 0]);
107971 var widthPct = sidebarWidth / containerWidth * 100;
107972 selection.style(xMarginProperty, null).style('width', widthPct + '%');
107975 context.ui().onResize([-sidebarWidth * scaleX, 0]);
107977 context.ui().onResize([-dx * scaleX, 0]);
107982 function pointerup(d3_event) {
107983 if (downPointerId !== (d3_event.pointerId || 'mouse')) return;
107985 resizer.classed('dragging', false);
107986 select(window).on('touchmove.sidebar-resizer', null).on(_pointerPrefix + 'move.sidebar-resizer', null).on(_pointerPrefix + 'up.sidebar-resizer pointercancel.sidebar-resizer', null);
107989 var featureListWrap = selection.append('div').attr('class', 'feature-list-pane').call(uiFeatureList(context));
107990 var inspectorWrap = selection.append('div').attr('class', 'inspector-hidden inspector-wrap');
107992 var hoverModeSelect = function hoverModeSelect(targets) {
107993 context.container().selectAll('.feature-list-item button').classed('hover', false);
107995 if (context.selectedIDs().length > 1 && targets && targets.length) {
107996 var elements = context.container().selectAll('.feature-list-item button').filter(function (node) {
107997 return targets.indexOf(node) !== -1;
108000 if (!elements.empty()) {
108001 elements.classed('hover', true);
108006 sidebar.hoverModeSelect = throttle(hoverModeSelect, 200);
108008 function hover(targets) {
108009 var datum = targets && targets.length && targets[0];
108011 if (datum && datum.__featurehash__) {
108014 sidebar.show(dataEditor.datum(datum));
108015 selection.selectAll('.sidebar-component').classed('inspector-hover', true);
108016 } else if (datum instanceof osmNote) {
108017 if (context.mode().id === 'drag-note') return;
108019 var osm = services.osm;
108022 datum = osm.getNote(datum.id); // marker may contain stale data - get latest
108025 sidebar.show(noteEditor.note(datum));
108026 selection.selectAll('.sidebar-component').classed('inspector-hover', true);
108027 } else if (datum instanceof QAItem) {
108029 var errService = services[datum.service];
108032 // marker may contain stale data - get latest
108033 datum = errService.getError(datum.id);
108034 } // Currently only three possible services
108039 if (datum.service === 'keepRight') {
108040 errEditor = keepRightEditor;
108041 } else if (datum.service === 'osmose') {
108042 errEditor = osmoseEditor;
108044 errEditor = improveOsmEditor;
108047 context.container().selectAll('.qaItem.' + datum.service).classed('hover', function (d) {
108048 return d.id === datum.id;
108050 sidebar.show(errEditor.error(datum));
108051 selection.selectAll('.sidebar-component').classed('inspector-hover', true);
108052 } else if (!_current && datum instanceof osmEntity) {
108053 featureListWrap.classed('inspector-hidden', true);
108054 inspectorWrap.classed('inspector-hidden', false).classed('inspector-hover', true);
108056 if (!inspector.entityIDs() || !utilArrayIdentical(inspector.entityIDs(), [datum.id]) || inspector.state() !== 'hover') {
108057 inspector.state('hover').entityIDs([datum.id]).newFeature(false);
108058 inspectorWrap.call(inspector);
108060 } else if (!_current) {
108061 featureListWrap.classed('inspector-hidden', false);
108062 inspectorWrap.classed('inspector-hidden', true);
108063 inspector.state('hide');
108064 } else if (_wasData || _wasNote || _wasQaItem) {
108068 context.container().selectAll('.note').classed('hover', false);
108069 context.container().selectAll('.qaItem').classed('hover', false);
108074 sidebar.hover = throttle(hover, 200);
108076 sidebar.intersects = function (extent) {
108077 var rect = selection.node().getBoundingClientRect();
108078 return extent.intersects([context.projection.invert([0, rect.height]), context.projection.invert([rect.width, 0])]);
108081 sidebar.select = function (ids, newFeature) {
108084 if (ids && ids.length) {
108085 var entity = ids.length === 1 && context.entity(ids[0]);
108087 if (entity && newFeature && selection.classed('collapsed')) {
108088 // uncollapse the sidebar
108089 var extent = entity.extent(context.graph());
108090 sidebar.expand(sidebar.intersects(extent));
108093 featureListWrap.classed('inspector-hidden', true);
108094 inspectorWrap.classed('inspector-hidden', false).classed('inspector-hover', false); // reload the UI even if the ids are the same since the entities
108095 // themselves may have changed
108097 inspector.state('select').entityIDs(ids).newFeature(newFeature);
108098 inspectorWrap.call(inspector);
108100 inspector.state('hide');
108104 sidebar.showPresetList = function () {
108108 sidebar.show = function (component, element) {
108109 featureListWrap.classed('inspector-hidden', true);
108110 inspectorWrap.classed('inspector-hidden', true);
108111 if (_current) _current.remove();
108112 _current = selection.append('div').attr('class', 'sidebar-component').call(component, element);
108115 sidebar.hide = function () {
108116 featureListWrap.classed('inspector-hidden', false);
108117 inspectorWrap.classed('inspector-hidden', true);
108118 if (_current) _current.remove();
108122 sidebar.expand = function (moveMap) {
108123 if (selection.classed('collapsed')) {
108124 sidebar.toggle(moveMap);
108128 sidebar.collapse = function (moveMap) {
108129 if (!selection.classed('collapsed')) {
108130 sidebar.toggle(moveMap);
108134 sidebar.toggle = function (moveMap) {
108135 // Don't allow sidebar to toggle when the user is in the walkthrough.
108136 if (context.inIntro()) return;
108137 var isCollapsed = selection.classed('collapsed');
108138 var isCollapsing = !isCollapsed;
108139 var isRTL = _mainLocalizer.textDirection() === 'rtl';
108140 var scaleX = isRTL ? 0 : 1;
108141 var xMarginProperty = isRTL ? 'margin-right' : 'margin-left';
108142 sidebarWidth = selection.node().getBoundingClientRect().width; // switch from % to px
108144 selection.style('width', sidebarWidth + 'px');
108145 var startMargin, endMargin, lastMargin;
108148 startMargin = lastMargin = 0;
108149 endMargin = -sidebarWidth;
108151 startMargin = lastMargin = -sidebarWidth;
108156 // unhide the sidebar's content before it transitions onscreen
108157 selection.classed('collapsed', isCollapsing);
108160 selection.transition().style(xMarginProperty, endMargin + 'px').tween('panner', function () {
108161 var i = d3_interpolateNumber(startMargin, endMargin);
108163 var dx = lastMargin - Math.round(i(t));
108164 lastMargin = lastMargin - dx;
108165 context.ui().onResize(moveMap ? undefined : [dx * scaleX, 0]);
108167 }).on('end', function () {
108169 // hide the sidebar's content after it transitions offscreen
108170 selection.classed('collapsed', isCollapsing);
108171 } // switch back from px to %
108175 var containerWidth = container.node().getBoundingClientRect().width;
108176 var widthPct = sidebarWidth / containerWidth * 100;
108177 selection.style(xMarginProperty, null).style('width', widthPct + '%');
108180 }; // toggle the sidebar collapse when double-clicking the resizer
108183 resizer.on('dblclick', function (d3_event) {
108184 d3_event.preventDefault();
108186 if (d3_event.sourceEvent) {
108187 d3_event.sourceEvent.preventDefault();
108191 }); // ensure hover sidebar is closed when zooming out beyond editable zoom
108193 context.map().on('crossEditableZoom.sidebar', function (within) {
108194 if (!within && !selection.select('.inspector-hover').empty()) {
108200 sidebar.showPresetList = function () {};
108202 sidebar.hover = function () {};
108204 sidebar.hover.cancel = function () {};
108206 sidebar.intersects = function () {};
108208 sidebar.select = function () {};
108210 sidebar.show = function () {};
108212 sidebar.hide = function () {};
108214 sidebar.expand = function () {};
108216 sidebar.collapse = function () {};
108218 sidebar.toggle = function () {};
108223 function modeDrawArea(context, wayID, startGraph, button) {
108228 var behavior = behaviorDrawWay(context, wayID, mode, startGraph).on('rejectedSelfIntersection.modeDrawArea', function () {
108229 context.ui().flash.iconName('#iD-icon-no').label(_t.html('self_intersection.error.areas'))();
108233 mode.enter = function () {
108234 context.install(behavior);
108237 mode.exit = function () {
108238 context.uninstall(behavior);
108241 mode.selectedIDs = function () {
108245 mode.activeID = function () {
108246 return behavior && behavior.activeID() || [];
108252 function modeAddArea(context, mode) {
108254 var behavior = behaviorAddWay(context).on('start', start).on('startFromWay', startFromWay).on('startFromNode', startFromNode);
108258 if (mode.preset) defaultTags = mode.preset.setTags(defaultTags, 'area');
108260 function actionClose(wayId) {
108261 return function (graph) {
108262 return graph.replace(graph.entity(wayId).close());
108267 var startGraph = context.graph();
108274 context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id), actionClose(way.id));
108275 context.enter(modeDrawArea(context, way.id, startGraph, mode.button));
108278 function startFromWay(loc, edge) {
108279 var startGraph = context.graph();
108286 context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id), actionClose(way.id), actionAddMidpoint({
108290 context.enter(modeDrawArea(context, way.id, startGraph, mode.button));
108293 function startFromNode(node) {
108294 var startGraph = context.graph();
108298 context.perform(actionAddEntity(way), actionAddVertex(way.id, node.id), actionClose(way.id));
108299 context.enter(modeDrawArea(context, way.id, startGraph, mode.button));
108302 mode.enter = function () {
108303 context.install(behavior);
108306 mode.exit = function () {
108307 context.uninstall(behavior);
108313 function modeAddLine(context, mode) {
108315 var behavior = behaviorAddWay(context).on('start', start).on('startFromWay', startFromWay).on('startFromNode', startFromNode);
108317 if (mode.preset) defaultTags = mode.preset.setTags(defaultTags, 'line');
108320 var startGraph = context.graph();
108327 context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id));
108328 context.enter(modeDrawLine(context, way.id, startGraph, mode.button));
108331 function startFromWay(loc, edge) {
108332 var startGraph = context.graph();
108339 context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id), actionAddMidpoint({
108343 context.enter(modeDrawLine(context, way.id, startGraph, mode.button));
108346 function startFromNode(node) {
108347 var startGraph = context.graph();
108351 context.perform(actionAddEntity(way), actionAddVertex(way.id, node.id));
108352 context.enter(modeDrawLine(context, way.id, startGraph, mode.button));
108355 mode.enter = function () {
108356 context.install(behavior);
108359 mode.exit = function () {
108360 context.uninstall(behavior);
108366 function modeAddPoint(context, mode) {
108368 var behavior = behaviorDraw(context).on('click', add).on('clickWay', addWay).on('clickNode', addNode).on('cancel', cancel).on('finish', cancel);
108370 if (mode.preset) defaultTags = mode.preset.setTags(defaultTags, 'point');
108377 context.perform(actionAddEntity(node), _t('operations.add.annotation.point'));
108381 function addWay(loc, edge) {
108385 context.perform(actionAddMidpoint({
108388 }, node), _t('operations.add.annotation.vertex'));
108392 function enterSelectMode(node) {
108393 context.enter(modeSelect(context, [node.id]).newFeature(true));
108396 function addNode(node) {
108397 if (Object.keys(defaultTags).length === 0) {
108402 var tags = Object.assign({}, node.tags); // shallow copy
108404 for (var key in defaultTags) {
108405 tags[key] = defaultTags[key];
108408 context.perform(actionChangeTags(node.id, tags), _t('operations.add.annotation.point'));
108413 context.enter(modeBrowse(context));
108416 mode.enter = function () {
108417 context.install(behavior);
108420 mode.exit = function () {
108421 context.uninstall(behavior);
108427 function modeSelectNote(context, selectedNoteID) {
108433 var _keybinding = utilKeybinding('select-note');
108435 var _noteEditor = uiNoteEditor(context).on('change', function () {
108436 context.map().pan([0, 0]); // trigger a redraw
108438 var note = checkSelectedID();
108440 context.ui().sidebar.show(_noteEditor.note(note));
108443 var _behaviors = [behaviorBreathe(), behaviorHover(context), behaviorSelect(context), behaviorLasso(context), modeDragNode(context).behavior, modeDragNote(context).behavior];
108444 var _newFeature = false;
108446 function checkSelectedID() {
108447 if (!services.osm) return;
108448 var note = services.osm.getNote(selectedNoteID);
108451 context.enter(modeBrowse(context));
108455 } // class the note as selected, or return to browse mode if the note is gone
108458 function selectNote(d3_event, drawn) {
108459 if (!checkSelectedID()) return;
108460 var selection = context.surface().selectAll('.layer-notes .note-' + selectedNoteID);
108462 if (selection.empty()) {
108463 // Return to browse mode if selected DOM elements have
108464 // disappeared because the user moved them out of view..
108465 var source = d3_event && d3_event.type === 'zoom' && d3_event.sourceEvent;
108467 if (drawn && source && (source.type === 'pointermove' || source.type === 'mousemove' || source.type === 'touchmove')) {
108468 context.enter(modeBrowse(context));
108471 selection.classed('selected', true);
108472 context.selectedNoteID(selectedNoteID);
108477 if (context.container().select('.combobox').size()) return;
108478 context.enter(modeBrowse(context));
108481 mode.zoomToSelected = function () {
108482 if (!services.osm) return;
108483 var note = services.osm.getNote(selectedNoteID);
108486 context.map().centerZoomEase(note.loc, 20);
108490 mode.newFeature = function (val) {
108491 if (!arguments.length) return _newFeature;
108496 mode.enter = function () {
108497 var note = checkSelectedID();
108500 _behaviors.forEach(context.install);
108502 _keybinding.on(_t('inspector.zoom_to.key'), mode.zoomToSelected).on('⎋', esc, true);
108504 select(document).call(_keybinding);
108506 var sidebar = context.ui().sidebar;
108507 sidebar.show(_noteEditor.note(note).newNote(_newFeature)); // expand the sidebar, avoid obscuring the note if needed
108509 sidebar.expand(sidebar.intersects(note.extent()));
108510 context.map().on('drawn.select', selectNote);
108513 mode.exit = function () {
108514 _behaviors.forEach(context.uninstall);
108516 select(document).call(_keybinding.unbind);
108517 context.surface().selectAll('.layer-notes .selected').classed('selected hover', false);
108518 context.map().on('drawn.select', null);
108519 context.ui().sidebar.hide();
108520 context.selectedNoteID(null);
108526 function modeAddNote(context) {
108530 description: _t.html('modes.add_note.description'),
108531 key: _t('modes.add_note.key')
108533 var behavior = behaviorDraw(context).on('click', add).on('cancel', cancel).on('finish', cancel);
108536 var osm = services.osm;
108543 osm.replaceNote(note); // force a reraw (there is no history change that would otherwise do this)
108545 context.map().pan([0, 0]);
108546 context.selectedNoteID(note.id).enter(modeSelectNote(context, note.id).newFeature(true));
108550 context.enter(modeBrowse(context));
108553 mode.enter = function () {
108554 context.install(behavior);
108557 mode.exit = function () {
108558 context.uninstall(behavior);
108564 function modeSave(context) {
108568 var keybinding = utilKeybinding('modeSave');
108569 var commit = uiCommit(context).on('cancel', cancel);
108571 var _conflictsUi; // uiConflicts
108578 var uploader = context.uploader().on('saveStarted.modeSave', function () {
108580 }) // fire off some async work that we want to be ready later
108581 .on('willAttemptUpload.modeSave', prepareForSuccess).on('progressChanged.modeSave', showProgress).on('resultNoChanges.modeSave', function () {
108583 }).on('resultErrors.modeSave', showErrors).on('resultConflicts.modeSave', showConflicts).on('resultSuccess.modeSave', showSuccess);
108586 context.enter(modeBrowse(context));
108589 function showProgress(num, total) {
108590 var modal = context.container().select('.loading-modal .modal-section');
108591 var progress = modal.selectAll('.progress').data([0]); // enter/update
108593 progress.enter().append('div').attr('class', 'progress').merge(progress).text(_t('save.conflict_progress', {
108599 function showConflicts(changeset, conflicts, origChanges) {
108600 var selection = context.container().select('.sidebar').append('div').attr('class', 'sidebar-component');
108601 context.container().selectAll('.main-content').classed('active', true).classed('inactive', false);
108602 _conflictsUi = uiConflicts(context).conflictList(conflicts).origChanges(origChanges).on('cancel', function () {
108603 context.container().selectAll('.main-content').classed('active', false).classed('inactive', true);
108606 uploader.cancelConflictResolution();
108607 }).on('save', function () {
108608 context.container().selectAll('.main-content').classed('active', false).classed('inactive', true);
108610 uploader.processResolvedConflicts(changeset);
108612 selection.call(_conflictsUi);
108615 function showErrors(errors) {
108617 var selection = uiConfirm(context.container());
108618 selection.select('.modal-section.header').append('h3').text(_t('save.error'));
108619 addErrors(selection, errors);
108623 function addErrors(selection, data) {
108624 var message = selection.select('.modal-section.message-text');
108625 var items = message.selectAll('.error-container').data(data);
108626 var enter = items.enter().append('div').attr('class', 'error-container');
108627 enter.append('a').attr('class', 'error-description').attr('href', '#').classed('hide-toggle', true).text(function (d) {
108628 return d.msg || _t('save.unknown_error_details');
108629 }).on('click', function (d3_event) {
108630 d3_event.preventDefault();
108631 var error = select(this);
108632 var detail = select(this.nextElementSibling);
108633 var exp = error.classed('expanded');
108634 detail.style('display', exp ? 'none' : 'block');
108635 error.classed('expanded', !exp);
108637 var details = enter.append('div').attr('class', 'error-detail-container').style('display', 'none');
108638 details.append('ul').attr('class', 'error-detail-list').selectAll('li').data(function (d) {
108639 return d.details || [];
108640 }).enter().append('li').attr('class', 'error-detail-item').text(function (d) {
108646 function showSuccess(changeset) {
108649 var ui = _success.changeset(changeset).location(_location).on('cancel', function () {
108650 context.ui().sidebar.hide();
108653 context.enter(modeBrowse(context).sidebar(ui));
108656 function keybindingOn() {
108657 select(document).call(keybinding.on('⎋', cancel, true));
108660 function keybindingOff() {
108661 select(document).call(keybinding.unbind);
108662 } // Reverse geocode current map location so we can display a message on
108663 // the success screen like "Thank you for editing around place, region."
108666 function prepareForSuccess() {
108667 _success = uiSuccess(context);
108669 if (!services.geocoder) return;
108670 services.geocoder.reverse(context.map().center(), function (err, result) {
108671 if (err || !result || !result.address) return;
108672 var addr = result.address;
108673 var place = addr && (addr.town || addr.city || addr.county) || '';
108674 var region = addr && (addr.state || addr.country) || '';
108675 var separator = place && region ? _t('success.thank_you_where.separator') : '';
108676 _location = _t('success.thank_you_where.format', {
108684 mode.selectedIDs = function () {
108685 return _conflictsUi ? _conflictsUi.shownEntityIds() : [];
108688 mode.enter = function () {
108690 context.ui().sidebar.expand();
108693 context.ui().sidebar.show(commit);
108697 context.container().selectAll('.main-content').classed('active', false).classed('inactive', true);
108698 var osm = context.connection();
108705 if (osm.authenticated()) {
108708 osm.authenticate(function (err) {
108718 mode.exit = function () {
108720 context.container().selectAll('.main-content').classed('active', true).classed('inactive', false);
108721 context.ui().sidebar.hide();
108727 function modeSelectError(context, selectedErrorID, selectedErrorService) {
108732 var keybinding = utilKeybinding('select-error');
108733 var errorService = services[selectedErrorService];
108736 switch (selectedErrorService) {
108738 errorEditor = uiImproveOsmEditor(context).on('change', function () {
108739 context.map().pan([0, 0]); // trigger a redraw
108741 var error = checkSelectedID();
108743 context.ui().sidebar.show(errorEditor.error(error));
108748 errorEditor = uiKeepRightEditor(context).on('change', function () {
108749 context.map().pan([0, 0]); // trigger a redraw
108751 var error = checkSelectedID();
108753 context.ui().sidebar.show(errorEditor.error(error));
108758 errorEditor = uiOsmoseEditor(context).on('change', function () {
108759 context.map().pan([0, 0]); // trigger a redraw
108761 var error = checkSelectedID();
108763 context.ui().sidebar.show(errorEditor.error(error));
108768 var behaviors = [behaviorBreathe(), behaviorHover(context), behaviorSelect(context), behaviorLasso(context), modeDragNode(context).behavior, modeDragNote(context).behavior];
108770 function checkSelectedID() {
108771 if (!errorService) return;
108772 var error = errorService.getError(selectedErrorID);
108775 context.enter(modeBrowse(context));
108781 mode.zoomToSelected = function () {
108782 if (!errorService) return;
108783 var error = errorService.getError(selectedErrorID);
108786 context.map().centerZoomEase(error.loc, 20);
108790 mode.enter = function () {
108791 var error = checkSelectedID();
108793 behaviors.forEach(context.install);
108794 keybinding.on(_t('inspector.zoom_to.key'), mode.zoomToSelected).on('⎋', esc, true);
108795 select(document).call(keybinding);
108797 var sidebar = context.ui().sidebar;
108798 sidebar.show(errorEditor.error(error));
108799 context.map().on('drawn.select-error', selectError); // class the error as selected, or return to browse mode if the error is gone
108801 function selectError(d3_event, drawn) {
108802 if (!checkSelectedID()) return;
108803 var selection = context.surface().selectAll('.itemId-' + selectedErrorID + '.' + selectedErrorService);
108805 if (selection.empty()) {
108806 // Return to browse mode if selected DOM elements have
108807 // disappeared because the user moved them out of view..
108808 var source = d3_event && d3_event.type === 'zoom' && d3_event.sourceEvent;
108810 if (drawn && source && (source.type === 'pointermove' || source.type === 'mousemove' || source.type === 'touchmove')) {
108811 context.enter(modeBrowse(context));
108814 selection.classed('selected', true);
108815 context.selectedErrorID(selectedErrorID);
108820 if (context.container().select('.combobox').size()) return;
108821 context.enter(modeBrowse(context));
108825 mode.exit = function () {
108826 behaviors.forEach(context.uninstall);
108827 select(document).call(keybinding.unbind);
108828 context.surface().selectAll('.qaItem.selected').classed('selected hover', false);
108829 context.map().on('drawn.select-error', null);
108830 context.ui().sidebar.hide();
108831 context.selectedErrorID(null);
108832 context.features().forceVisible([]);
108838 function uiToolOldDrawModes(context) {
108841 label: _t.html('toolbar.add_feature')
108843 var modes = [modeAddPoint(context, {
108844 title: _t.html('modes.add_point.title'),
108846 description: _t.html('modes.add_point.description'),
108847 preset: _mainPresetIndex.item('point'),
108849 }), modeAddLine(context, {
108850 title: _t.html('modes.add_line.title'),
108852 description: _t.html('modes.add_line.description'),
108853 preset: _mainPresetIndex.item('line'),
108855 }), modeAddArea(context, {
108856 title: _t.html('modes.add_area.title'),
108858 description: _t.html('modes.add_area.description'),
108859 preset: _mainPresetIndex.item('area'),
108867 function osmEditable() {
108868 return context.editable();
108871 modes.forEach(function (mode) {
108872 context.keybinding().on(mode.key, function () {
108873 if (!enabled()) return;
108875 if (mode.id === context.mode().id) {
108876 context.enter(modeBrowse(context));
108883 tool.render = function (selection) {
108884 var wrap = selection.append('div').attr('class', 'joined').style('display', 'flex');
108886 var debouncedUpdate = debounce(update, 500, {
108891 context.map().on('move.modes', debouncedUpdate).on('drawn.modes', debouncedUpdate);
108892 context.on('enter.modes', update);
108896 var buttons = wrap.selectAll('button.add-button').data(modes, function (d) {
108900 buttons.exit().remove(); // enter
108902 var buttonsEnter = buttons.enter().append('button').attr('class', function (d) {
108903 return d.id + ' add-button bar-button';
108904 }).on('click.mode-buttons', function (d3_event, d) {
108905 if (!enabled()) return; // When drawing, ignore accidental clicks on mode buttons - #4042
108907 var currMode = context.mode().id;
108908 if (/^draw/.test(currMode)) return;
108910 if (d.id === currMode) {
108911 context.enter(modeBrowse(context));
108915 }).call(uiTooltip().placement('bottom').title(function (d) {
108919 }).scrollContainer(context.container().select('.top-toolbar')));
108920 buttonsEnter.each(function (d) {
108921 select(this).call(svgIcon('#iD-icon-' + d.button));
108923 buttonsEnter.append('span').attr('class', 'label').html(function (mode) {
108925 }); // if we are adding/removing the buttons, check if toolbar has overflowed
108927 if (buttons.enter().size() || buttons.exit().size()) {
108928 context.ui().checkOverflow('.top-toolbar', true);
108932 buttons = buttons.merge(buttonsEnter).attr('aria-disabled', function (d) {
108934 }).classed('disabled', function (d) {
108936 }).attr('aria-pressed', function (d) {
108937 return context.mode() && context.mode().button === d.button;
108938 }).classed('active', function (d) {
108939 return context.mode() && context.mode().button === d.button;
108947 function uiToolNotes(context) {
108950 label: _t.html('modes.add_note.label')
108952 var mode = modeAddNote(context);
108955 return notesEnabled() && notesEditable();
108958 function notesEnabled() {
108959 var noteLayer = context.layers().layer('notes');
108960 return noteLayer && noteLayer.enabled();
108963 function notesEditable() {
108964 var mode = context.mode();
108965 return context.map().notesEditable() && mode && mode.id !== 'save';
108968 context.keybinding().on(mode.key, function () {
108969 if (!enabled()) return;
108971 if (mode.id === context.mode().id) {
108972 context.enter(modeBrowse(context));
108978 tool.render = function (selection) {
108979 var debouncedUpdate = debounce(update, 500, {
108984 context.map().on('move.notes', debouncedUpdate).on('drawn.notes', debouncedUpdate);
108985 context.on('enter.notes', update);
108989 var showNotes = notesEnabled();
108990 var data = showNotes ? [mode] : [];
108991 var buttons = selection.selectAll('button.add-button').data(data, function (d) {
108995 buttons.exit().remove(); // enter
108997 var buttonsEnter = buttons.enter().append('button').attr('class', function (d) {
108998 return d.id + ' add-button bar-button';
108999 }).on('click.notes', function (d3_event, d) {
109000 if (!enabled()) return; // When drawing, ignore accidental clicks on mode buttons - #4042
109002 var currMode = context.mode().id;
109003 if (/^draw/.test(currMode)) return;
109005 if (d.id === currMode) {
109006 context.enter(modeBrowse(context));
109010 }).call(uiTooltip().placement('bottom').title(function (d) {
109014 }).scrollContainer(context.container().select('.top-toolbar')));
109015 buttonsEnter.each(function (d) {
109016 select(this).call(svgIcon(d.icon || '#iD-icon-' + d.button));
109017 }); // if we are adding/removing the buttons, check if toolbar has overflowed
109019 if (buttons.enter().size() || buttons.exit().size()) {
109020 context.ui().checkOverflow('.top-toolbar', true);
109024 buttons = buttons.merge(buttonsEnter).classed('disabled', function (d) {
109026 }).attr('aria-disabled', function (d) {
109028 }).classed('active', function (d) {
109029 return context.mode() && context.mode().button === d.button;
109030 }).attr('aria-pressed', function (d) {
109031 return context.mode() && context.mode().button === d.button;
109036 tool.uninstall = function () {
109037 context.on('enter.editor.notes', null).on('exit.editor.notes', null).on('enter.notes', null);
109038 context.map().on('move.notes', null).on('drawn.notes', null);
109044 function uiToolSave(context) {
109047 label: _t.html('save.title')
109050 var tooltipBehavior = null;
109051 var history = context.history();
109056 var mode = context.mode();
109057 return mode && mode.id === 'save';
109060 function isDisabled() {
109061 return _numChanges === 0 || isSaving();
109064 function save(d3_event) {
109065 d3_event.preventDefault();
109067 if (!context.inIntro() && !isSaving() && history.hasChanges()) {
109068 context.enter(modeSave(context));
109075 if (_numChanges === 0) {
109077 } else if (_numChanges <= 50) {
109078 step = _numChanges / 50;
109079 return d3_interpolateRgb('#fff', '#ff8')(step); // white -> yellow
109081 step = Math.min((_numChanges - 50) / 50, 1.0);
109082 return d3_interpolateRgb('#ff8', '#f88')(step); // yellow -> red
109086 function updateCount() {
109087 var val = history.difference().summary().length;
109088 if (val === _numChanges) return;
109092 tooltipBehavior.title(_t.html(_numChanges > 0 ? 'save.help' : 'save.no_changes')).keys([key]);
109096 button.classed('disabled', isDisabled()).style('background', bgColor());
109097 button.select('span.count').text(_numChanges);
109101 tool.render = function (selection) {
109102 tooltipBehavior = uiTooltip().placement('bottom').title(_t.html('save.no_changes')).keys([key]).scrollContainer(context.container().select('.top-toolbar'));
109104 button = selection.append('button').attr('class', 'save disabled bar-button').on('pointerup', function (d3_event) {
109105 lastPointerUpType = d3_event.pointerType;
109106 }).on('click', function (d3_event) {
109109 if (_numChanges === 0 && (lastPointerUpType === 'touch' || lastPointerUpType === 'pen')) {
109110 // there are no tooltips for touch interactions so flash feedback instead
109111 context.ui().flash.duration(2000).iconName('#iD-icon-save').iconClass('disabled').label(_t.html('save.no_changes'))();
109114 lastPointerUpType = null;
109115 }).call(tooltipBehavior);
109116 button.call(svgIcon('#iD-icon-save'));
109117 button.append('span').attr('class', 'count').attr('aria-hidden', 'true').text('0');
109119 context.keybinding().on(key, save, true);
109120 context.history().on('change.save', updateCount);
109121 context.on('enter.save', function () {
109123 button.classed('disabled', isDisabled());
109126 button.call(tooltipBehavior.hide);
109132 tool.uninstall = function () {
109133 context.keybinding().off(key, true);
109134 context.history().on('change.save', null);
109135 context.on('enter.save', null);
109137 tooltipBehavior = null;
109143 function uiToolSidebarToggle(context) {
109146 label: _t.html('toolbar.inspect')
109149 tool.render = function (selection) {
109150 selection.append('button').attr('class', 'bar-button').attr('aria-label', _t('sidebar.tooltip')).on('click', function () {
109151 context.ui().sidebar.toggle();
109152 }).call(uiTooltip().placement('bottom').title(_t.html('sidebar.tooltip')).keys([_t('sidebar.key')]).scrollContainer(context.container().select('.top-toolbar'))).call(svgIcon('#iD-icon-sidebar-' + (_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left')));
109158 function uiToolUndoRedo(context) {
109161 label: _t.html('toolbar.undo_redo')
109166 action: function action() {
109169 annotation: function annotation() {
109170 return context.history().undoAnnotation();
109172 icon: 'iD-icon-' + (_mainLocalizer.textDirection() === 'rtl' ? 'redo' : 'undo')
109176 action: function action() {
109179 annotation: function annotation() {
109180 return context.history().redoAnnotation();
109182 icon: 'iD-icon-' + (_mainLocalizer.textDirection() === 'rtl' ? 'undo' : 'redo')
109186 return context.mode() && context.mode().id !== 'save' && context.map().editableDataEnabled(true
109191 tool.render = function (selection) {
109192 var tooltipBehavior = uiTooltip().placement('bottom').title(function (d) {
109193 return d.annotation() ? _t.html(d.id + '.tooltip', {
109195 }) : _t.html(d.id + '.nothing');
109198 }).scrollContainer(context.container().select('.top-toolbar'));
109200 var buttons = selection.selectAll('button').data(commands).enter().append('button').attr('class', function (d) {
109201 return 'disabled ' + d.id + '-button bar-button';
109202 }).on('pointerup', function (d3_event) {
109203 // `pointerup` is always called before `click`
109204 lastPointerUpType = d3_event.pointerType;
109205 }).on('click', function (d3_event, d) {
109206 d3_event.preventDefault();
109207 var annotation = d.annotation();
109209 if (editable() && annotation) {
109213 if (editable() && (lastPointerUpType === 'touch' || lastPointerUpType === 'pen')) {
109214 // there are no tooltips for touch interactions so flash feedback instead
109215 var text = annotation ? _t.html(d.id + '.tooltip', {
109217 }) : _t.html(d.id + '.nothing');
109218 context.ui().flash.duration(2000).iconName('#' + d.icon).iconClass(annotation ? '' : 'disabled').label(text)();
109221 lastPointerUpType = null;
109222 }).call(tooltipBehavior);
109223 buttons.each(function (d) {
109224 select(this).call(svgIcon('#' + d.icon));
109226 context.keybinding().on(commands[0].cmd, function (d3_event) {
109227 d3_event.preventDefault();
109228 if (editable()) commands[0].action();
109229 }).on(commands[1].cmd, function (d3_event) {
109230 d3_event.preventDefault();
109231 if (editable()) commands[1].action();
109234 var debouncedUpdate = debounce(update, 500, {
109239 context.map().on('move.undo_redo', debouncedUpdate).on('drawn.undo_redo', debouncedUpdate);
109240 context.history().on('change.undo_redo', function (difference) {
109241 if (difference) update();
109243 context.on('enter.undo_redo', update);
109246 buttons.classed('disabled', function (d) {
109247 return !editable() || !d.annotation();
109249 var selection = select(this);
109251 if (!selection.select('.tooltip.in').empty()) {
109252 selection.call(tooltipBehavior.updateContent);
109258 tool.uninstall = function () {
109259 context.keybinding().off(commands[0].cmd).off(commands[1].cmd);
109260 context.map().on('move.undo_redo', null).on('drawn.undo_redo', null);
109261 context.history().on('change.undo_redo', null);
109262 context.on('enter.undo_redo', null);
109268 function uiTopToolbar(context) {
109269 var sidebarToggle = uiToolSidebarToggle(context),
109270 modes = uiToolOldDrawModes(context),
109271 notes = uiToolNotes(context),
109272 undoRedo = uiToolUndoRedo(context),
109273 save = uiToolSave(context);
109275 function notesEnabled() {
109276 var noteLayer = context.layers().layer('notes');
109277 return noteLayer && noteLayer.enabled();
109280 function topToolbar(bar) {
109281 bar.on('wheel.topToolbar', function (d3_event) {
109282 if (!d3_event.deltaX) {
109283 // translate vertical scrolling into horizontal scrolling in case
109284 // the user doesn't have an input device that can scroll horizontally
109285 bar.node().scrollLeft += d3_event.deltaY;
109289 var debouncedUpdate = debounce(update, 500, {
109294 context.layers().on('change.topToolbar', debouncedUpdate);
109298 var tools = [sidebarToggle, 'spacer', modes];
109302 tools = tools.concat([notes, 'spacer']);
109305 tools = tools.concat([undoRedo, save]);
109306 var toolbarItems = bar.selectAll('.toolbar-item').data(tools, function (d) {
109309 toolbarItems.exit().each(function (d) {
109314 var itemsEnter = toolbarItems.enter().append('div').attr('class', function (d) {
109315 var classes = 'toolbar-item ' + (d.id || d).replace('_', '-');
109316 if (d.klass) classes += ' ' + d.klass;
109319 var actionableItems = itemsEnter.filter(function (d) {
109322 actionableItems.append('div').attr('class', 'item-content').each(function (d) {
109323 select(this).call(d.render, bar);
109325 actionableItems.append('div').attr('class', 'item-label').html(function (d) {
109334 function uiZoomToSelection(context) {
109335 function isDisabled() {
109336 var mode = context.mode();
109337 return !mode || !mode.zoomToSelected;
109340 var _lastPointerUpType;
109342 function pointerup(d3_event) {
109343 _lastPointerUpType = d3_event.pointerType;
109346 function click(d3_event) {
109347 d3_event.preventDefault();
109350 if (_lastPointerUpType === 'touch' || _lastPointerUpType === 'pen') {
109351 context.ui().flash.duration(2000).iconName('#iD-icon-framed-dot').iconClass('disabled').label(_t.html('inspector.zoom_to.no_selection'))();
109354 var mode = context.mode();
109356 if (mode && mode.zoomToSelected) {
109361 _lastPointerUpType = null;
109364 return function (selection) {
109365 var tooltipBehavior = uiTooltip().placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left').title(function () {
109367 return _t.html('inspector.zoom_to.no_selection');
109370 return _t.html('inspector.zoom_to.title');
109371 }).keys([_t('inspector.zoom_to.key')]);
109372 var button = selection.append('button').on('pointerup', pointerup).on('click', click).call(svgIcon('#iD-icon-framed-dot', 'light')).call(tooltipBehavior);
109374 function setEnabledState() {
109375 button.classed('disabled', isDisabled());
109377 if (!button.select('.tooltip.in').empty()) {
109378 button.call(tooltipBehavior.updateContent);
109382 context.on('enter.uiZoomToSelection', setEnabledState);
109387 function uiPane(id, context) {
109394 var _sections; // array of uiSection objects
109397 var _paneSelection = select(null);
109405 pane.label = function (val) {
109406 if (!arguments.length) return _label;
109411 pane.key = function (val) {
109412 if (!arguments.length) return _key;
109417 pane.description = function (val) {
109418 if (!arguments.length) return _description;
109423 pane.iconName = function (val) {
109424 if (!arguments.length) return _iconName;
109429 pane.sections = function (val) {
109430 if (!arguments.length) return _sections;
109435 pane.selection = function () {
109440 context.ui().togglePanes();
109443 pane.togglePane = function (d3_event) {
109444 if (d3_event) d3_event.preventDefault();
109448 context.ui().togglePanes(!_paneSelection.classed('shown') ? _paneSelection : undefined);
109451 pane.renderToggleButton = function (selection) {
109453 _paneTooltip = uiTooltip().placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left').title(_description).keys([_key]);
109456 selection.append('button').on('click', pane.togglePane).call(svgIcon('#' + _iconName, 'light')).call(_paneTooltip);
109459 pane.renderContent = function (selection) {
109460 // override to fully customize content
109462 _sections.forEach(function (section) {
109463 selection.call(section.render);
109468 pane.renderPane = function (selection) {
109469 _paneSelection = selection.append('div').attr('class', 'fillL map-pane hide ' + id + '-pane').attr('pane', id);
109471 var heading = _paneSelection.append('div').attr('class', 'pane-heading');
109473 heading.append('h2').html(_label);
109474 heading.append('button').attr('title', _t('icons.close')).on('click', hidePane).call(svgIcon('#iD-icon-close'));
109476 _paneSelection.append('div').attr('class', 'pane-content').call(pane.renderContent);
109479 context.keybinding().on(_key, pane.togglePane);
109486 function uiSectionBackgroundDisplayOptions(context) {
109487 var section = uiSection('background-display-options', context).label(_t.html('background.display_options')).disclosureContent(renderDisclosureContent);
109489 var _detected = utilDetect();
109491 var _storedOpacity = corePreferences('background-opacity');
109495 var _maxVal = _detected.cssfilters ? 3 : 1;
109497 var _sliders = _detected.cssfilters ? ['brightness', 'contrast', 'saturation', 'sharpness'] : ['brightness'];
109500 brightness: _storedOpacity !== null ? +_storedOpacity : 1,
109506 function clamp(x, min, max) {
109507 return Math.max(min, Math.min(x, max));
109510 function updateValue(d, val) {
109511 val = clamp(val, _minVal, _maxVal);
109513 context.background()[d](val);
109515 if (d === 'brightness') {
109516 corePreferences('background-opacity', val);
109522 function renderDisclosureContent(selection) {
109523 var container = selection.selectAll('.display-options-container').data([0]);
109524 var containerEnter = container.enter().append('div').attr('class', 'display-options-container controls-list'); // add slider controls
109526 var slidersEnter = containerEnter.selectAll('.display-control').data(_sliders).enter().append('label').attr('class', function (d) {
109527 return 'display-control display-control-' + d;
109529 slidersEnter.html(function (d) {
109530 return _t.html('background.' + d);
109531 }).append('span').attr('class', function (d) {
109532 return 'display-option-value display-option-value-' + d;
109534 var sildersControlEnter = slidersEnter.append('div').attr('class', 'control-wrap');
109535 sildersControlEnter.append('input').attr('class', function (d) {
109536 return 'display-option-input display-option-input-' + d;
109537 }).attr('type', 'range').attr('min', _minVal).attr('max', _maxVal).attr('step', '0.05').on('input', function (d3_event, d) {
109538 var val = select(this).property('value');
109540 if (!val && d3_event && d3_event.target) {
109541 val = d3_event.target.value;
109546 sildersControlEnter.append('button').attr('title', function (d) {
109547 return "".concat(_t('background.reset'), " ").concat(_t('background.' + d));
109548 }).attr('class', function (d) {
109549 return 'display-option-reset display-option-reset-' + d;
109550 }).on('click', function (d3_event, d) {
109551 if (d3_event.button !== 0) return;
109553 }).call(svgIcon('#iD-icon-' + (_mainLocalizer.textDirection() === 'rtl' ? 'redo' : 'undo'))); // reset all button
109555 containerEnter.append('a').attr('class', 'display-option-resetlink').attr('role', 'button').attr('href', '#').call(_t.append('background.reset_all')).on('click', function (d3_event) {
109556 d3_event.preventDefault();
109558 for (var i = 0; i < _sliders.length; i++) {
109559 updateValue(_sliders[i], 1);
109563 container = containerEnter.merge(container);
109564 container.selectAll('.display-option-input').property('value', function (d) {
109567 container.selectAll('.display-option-value').text(function (d) {
109568 return Math.floor(_options[d] * 100) + '%';
109570 container.selectAll('.display-option-reset').classed('disabled', function (d) {
109571 return _options[d] === 1;
109572 }); // first time only, set brightness if needed
109574 if (containerEnter.size() && _options.brightness !== 1) {
109575 context.background().brightness(_options.brightness);
109582 function uiSettingsCustomBackground() {
109583 var dispatch = dispatch$8('change');
109585 function render(selection) {
109586 // keep separate copies of original and current settings
109588 template: corePreferences('background-custom-template')
109591 template: corePreferences('background-custom-template')
109593 var example = 'https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png';
109594 var modal = uiConfirm(selection).okButton();
109595 modal.classed('settings-modal settings-custom-background', true);
109596 modal.select('.modal-section.header').append('h3').call(_t.append('settings.custom_background.header'));
109597 var textSection = modal.select('.modal-section.message-text');
109598 var instructions = "".concat(_t.html('settings.custom_background.instructions.info'), "\n") + '\n' + "#### ".concat(_t.html('settings.custom_background.instructions.wms.tokens_label'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.wms.tokens.proj'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.wms.tokens.wkid'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.wms.tokens.dimensions'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.wms.tokens.bbox'), "\n") + '\n' + "#### ".concat(_t.html('settings.custom_background.instructions.tms.tokens_label'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.tms.tokens.xyz'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.tms.tokens.flipped_y'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.tms.tokens.switch'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.tms.tokens.quadtile'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.tms.tokens.scale_factor'), "\n") + '\n' + "#### ".concat(_t.html('settings.custom_background.instructions.example'), "\n") + "`".concat(example, "`");
109599 textSection.append('div').attr('class', 'instructions-template').html(marked_1(instructions));
109600 textSection.append('textarea').attr('class', 'field-template').attr('placeholder', _t('settings.custom_background.template.placeholder')).call(utilNoAuto).property('value', _currSettings.template); // insert a cancel button
109602 var buttonSection = modal.select('.modal-section.buttons');
109603 buttonSection.insert('button', '.ok-button').attr('class', 'button cancel-button secondary-action').call(_t.append('confirm.cancel'));
109604 buttonSection.select('.cancel-button').on('click.cancel', clickCancel);
109605 buttonSection.select('.ok-button').attr('disabled', isSaveDisabled).on('click.save', clickSave);
109607 function isSaveDisabled() {
109609 } // restore the original template
109612 function clickCancel() {
109613 textSection.select('.field-template').property('value', _origSettings.template);
109614 corePreferences('background-custom-template', _origSettings.template);
109617 } // accept the current template
109621 _currSettings.template = textSection.select('.field-template').property('value');
109622 corePreferences('background-custom-template', _currSettings.template);
109625 dispatch.call('change', this, _currSettings);
109629 return utilRebind(render, dispatch, 'on');
109632 function uiSectionBackgroundList(context) {
109633 var _backgroundList = select(null);
109635 var _customSource = context.background().findSource('custom');
109637 var _settingsCustomBackground = uiSettingsCustomBackground().on('change', customChanged);
109639 var section = uiSection('background-list', context).label(_t.html('background.backgrounds')).disclosureContent(renderDisclosureContent);
109641 function previousBackgroundID() {
109642 return corePreferences('background-last-used-toggle');
109645 function renderDisclosureContent(selection) {
109647 var container = selection.selectAll('.layer-background-list').data([0]);
109648 _backgroundList = container.enter().append('ul').attr('class', 'layer-list layer-background-list').attr('dir', 'auto').merge(container); // add minimap toggle below list
109650 var bgExtrasListEnter = selection.selectAll('.bg-extras-list').data([0]).enter().append('ul').attr('class', 'layer-list bg-extras-list');
109651 var minimapLabelEnter = bgExtrasListEnter.append('li').attr('class', 'minimap-toggle-item').append('label').call(uiTooltip().title(_t.html('background.minimap.tooltip')).keys([_t('background.minimap.key')]).placement('top'));
109652 minimapLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
109653 d3_event.preventDefault();
109656 minimapLabelEnter.append('span').call(_t.append('background.minimap.description'));
109657 var panelLabelEnter = bgExtrasListEnter.append('li').attr('class', 'background-panel-toggle-item').append('label').call(uiTooltip().title(_t.html('background.panel.tooltip')).keys([uiCmd('⌘⇧' + _t('info_panels.background.key'))]).placement('top'));
109658 panelLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
109659 d3_event.preventDefault();
109660 context.ui().info.toggle('background');
109662 panelLabelEnter.append('span').call(_t.append('background.panel.description'));
109663 var locPanelLabelEnter = bgExtrasListEnter.append('li').attr('class', 'location-panel-toggle-item').append('label').call(uiTooltip().title(_t.html('background.location_panel.tooltip')).keys([uiCmd('⌘⇧' + _t('info_panels.location.key'))]).placement('top'));
109664 locPanelLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
109665 d3_event.preventDefault();
109666 context.ui().info.toggle('location');
109668 locPanelLabelEnter.append('span').call(_t.append('background.location_panel.description')); // "Info / Report a Problem" link
109670 selection.selectAll('.imagery-faq').data([0]).enter().append('div').attr('class', 'imagery-faq').append('a').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).attr('href', 'https://github.com/openstreetmap/iD/blob/develop/FAQ.md#how-can-i-report-an-issue-with-background-imagery').append('span').call(_t.append('background.imagery_problem_faq'));
109672 _backgroundList.call(drawListItems, 'radio', function (d3_event, d) {
109675 return !d.isHidden() && !d.overlay;
109679 function setTooltips(selection) {
109680 selection.each(function (d, i, nodes) {
109681 var item = select(this).select('label');
109682 var span = item.select('span');
109683 var placement = i < nodes.length / 2 ? 'bottom' : 'top';
109684 var description = d.description();
109685 var isOverflowing = span.property('clientWidth') !== span.property('scrollWidth');
109686 item.call(uiTooltip().destroyAny);
109688 if (d.id === previousBackgroundID()) {
109689 item.call(uiTooltip().placement(placement).title('<div>' + _t.html('background.switch') + '</div>').keys([uiCmd('⌘' + _t('background.key'))]));
109690 } else if (description || isOverflowing) {
109691 item.call(uiTooltip().placement(placement).title(description || d.label()));
109696 function drawListItems(layerList, type, change, filter) {
109697 var sources = context.background().sources(context.map().extent(), context.map().zoom(), true).filter(filter).sort(function (a, b) {
109698 return a.best() && !b.best() ? -1 : b.best() && !a.best() ? 1 : d3_descending(a.area(), b.area()) || d3_ascending(a.name(), b.name()) || 0;
109700 var layerLinks = layerList.selectAll('li') // We have to be a bit inefficient about reordering the list since
109701 // arrow key navigation of radio values likes to work in the order
109702 // they were added, not the display document order.
109703 .data(sources, function (d, i) {
109704 return d.id + '---' + i;
109706 layerLinks.exit().remove();
109707 var enter = layerLinks.enter().append('li').classed('layer-custom', function (d) {
109708 return d.id === 'custom';
109709 }).classed('best', function (d) {
109712 var label = enter.append('label');
109713 label.append('input').attr('type', type).attr('name', 'background-layer').attr('value', function (d) {
109715 }).on('change', change);
109716 label.append('span').html(function (d) {
109719 enter.filter(function (d) {
109720 return d.id === 'custom';
109721 }).append('button').attr('class', 'layer-browse').call(uiTooltip().title(_t.html('settings.custom_background.tooltip')).placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left')).on('click', function (d3_event) {
109722 d3_event.preventDefault();
109724 }).call(svgIcon('#iD-icon-more'));
109725 enter.filter(function (d) {
109727 }).append('div').attr('class', 'best').call(uiTooltip().title(_t.html('background.best_imagery')).placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left')).append('span').html('★');
109728 layerList.call(updateLayerSelections);
109731 function updateLayerSelections(selection) {
109733 return context.background().showsLayer(d);
109736 selection.selectAll('li').classed('active', active).classed('switch', function (d) {
109737 return d.id === previousBackgroundID();
109738 }).call(setTooltips).selectAll('input').property('checked', active);
109741 function chooseBackground(d) {
109742 if (d.id === 'custom' && !d.template()) {
109746 var previousBackground = context.background().baseLayerSource();
109747 corePreferences('background-last-used-toggle', previousBackground.id);
109748 corePreferences('background-last-used', d.id);
109749 context.background().baseLayerSource(d);
109752 function customChanged(d) {
109754 _customSource.template(d.template);
109756 chooseBackground(_customSource);
109758 _customSource.template('');
109760 chooseBackground(context.background().findSource('none'));
109764 function editCustom() {
109765 context.container().call(_settingsCustomBackground);
109768 context.background().on('change.background_list', function () {
109769 _backgroundList.call(updateLayerSelections);
109771 context.map().on('move.background_list', debounce(function () {
109772 // layers in-view may have changed due to map move
109773 window.requestIdleCallback(section.reRender);
109778 function uiSectionBackgroundOffset(context) {
109779 var section = uiSection('background-offset', context).label(_t.html('background.fix_misalignment')).disclosureContent(renderDisclosureContent).expandedByDefault(false);
109781 var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
109783 var _directions = [['top', [0, -0.5]], ['left', [-0.5, 0]], ['right', [0.5, 0]], ['bottom', [0, 0.5]]];
109785 function updateValue() {
109786 var meters = geoOffsetToMeters(context.background().offset());
109787 var x = +meters[0].toFixed(2);
109788 var y = +meters[1].toFixed(2);
109789 context.container().selectAll('.nudge-inner-rect').select('input').classed('error', false).property('value', x + ', ' + y);
109790 context.container().selectAll('.nudge-reset').classed('disabled', function () {
109791 return x === 0 && y === 0;
109795 function resetOffset() {
109796 context.background().offset([0, 0]);
109801 context.background().nudge(d, context.map().zoom());
109805 function inputOffset() {
109806 var input = select(this);
109807 var d = input.node().value;
109808 if (d === '') return resetOffset();
109809 d = d.replace(/;/g, ',').split(',').map(function (n) {
109810 // if n is NaN, it will always get mapped to false.
109814 if (d.length !== 2 || !d[0] || !d[1]) {
109815 input.classed('error', true);
109819 context.background().offset(geoMetersToOffset(d));
109823 function dragOffset(d3_event) {
109824 if (d3_event.button !== 0) return;
109825 var origin = [d3_event.clientX, d3_event.clientY];
109826 var pointerId = d3_event.pointerId || 'mouse';
109827 context.container().append('div').attr('class', 'nudge-surface');
109828 select(window).on(_pointerPrefix + 'move.drag-bg-offset', pointermove).on(_pointerPrefix + 'up.drag-bg-offset', pointerup);
109830 if (_pointerPrefix === 'pointer') {
109831 select(window).on('pointercancel.drag-bg-offset', pointerup);
109834 function pointermove(d3_event) {
109835 if (pointerId !== (d3_event.pointerId || 'mouse')) return;
109836 var latest = [d3_event.clientX, d3_event.clientY];
109837 var d = [-(origin[0] - latest[0]) / 4, -(origin[1] - latest[1]) / 4];
109842 function pointerup(d3_event) {
109843 if (pointerId !== (d3_event.pointerId || 'mouse')) return;
109844 if (d3_event.button !== 0) return;
109845 context.container().selectAll('.nudge-surface').remove();
109846 select(window).on('.drag-bg-offset', null);
109850 function renderDisclosureContent(selection) {
109851 var container = selection.selectAll('.nudge-container').data([0]);
109852 var containerEnter = container.enter().append('div').attr('class', 'nudge-container');
109853 containerEnter.append('div').attr('class', 'nudge-instructions').call(_t.append('background.offset'));
109854 var nudgeWrapEnter = containerEnter.append('div').attr('class', 'nudge-controls-wrap');
109855 var nudgeEnter = nudgeWrapEnter.append('div').attr('class', 'nudge-outer-rect').on(_pointerPrefix + 'down', dragOffset);
109856 nudgeEnter.append('div').attr('class', 'nudge-inner-rect').append('input').attr('type', 'text').attr('aria-label', _t('background.offset_label')).on('change', inputOffset);
109857 nudgeWrapEnter.append('div').selectAll('button').data(_directions).enter().append('button').attr('title', function (d) {
109858 return _t("background.nudge.".concat(d[0]));
109859 }).attr('class', function (d) {
109860 return d[0] + ' nudge';
109861 }).on('click', function (d3_event, d) {
109864 nudgeWrapEnter.append('button').attr('title', _t('background.reset')).attr('class', 'nudge-reset disabled').on('click', function (d3_event) {
109865 d3_event.preventDefault();
109867 }).call(svgIcon('#iD-icon-' + (_mainLocalizer.textDirection() === 'rtl' ? 'redo' : 'undo')));
109871 context.background().on('change.backgroundOffset-update', updateValue);
109875 function uiSectionOverlayList(context) {
109876 var section = uiSection('overlay-list', context).label(_t.html('background.overlays')).disclosureContent(renderDisclosureContent);
109878 var _overlayList = select(null);
109880 function setTooltips(selection) {
109881 selection.each(function (d, i, nodes) {
109882 var item = select(this).select('label');
109883 var span = item.select('span');
109884 var placement = i < nodes.length / 2 ? 'bottom' : 'top';
109885 var description = d.description();
109886 var isOverflowing = span.property('clientWidth') !== span.property('scrollWidth');
109887 item.call(uiTooltip().destroyAny);
109889 if (description || isOverflowing) {
109890 item.call(uiTooltip().placement(placement).title(description || d.name()));
109895 function updateLayerSelections(selection) {
109897 return context.background().showsLayer(d);
109900 selection.selectAll('li').classed('active', active).call(setTooltips).selectAll('input').property('checked', active);
109903 function chooseOverlay(d3_event, d) {
109904 d3_event.preventDefault();
109905 context.background().toggleOverlayLayer(d);
109907 _overlayList.call(updateLayerSelections);
109909 document.activeElement.blur();
109912 function drawListItems(layerList, type, change, filter) {
109913 var sources = context.background().sources(context.map().extent(), context.map().zoom(), true).filter(filter);
109914 var layerLinks = layerList.selectAll('li').data(sources, function (d) {
109917 layerLinks.exit().remove();
109918 var enter = layerLinks.enter().append('li');
109919 var label = enter.append('label');
109920 label.append('input').attr('type', type).attr('name', 'layers').on('change', change);
109921 label.append('span').html(function (d) {
109924 layerList.selectAll('li').sort(sortSources);
109925 layerList.call(updateLayerSelections);
109927 function sortSources(a, b) {
109928 return a.best() && !b.best() ? -1 : b.best() && !a.best() ? 1 : d3_descending(a.area(), b.area()) || d3_ascending(a.name(), b.name()) || 0;
109932 function renderDisclosureContent(selection) {
109933 var container = selection.selectAll('.layer-overlay-list').data([0]);
109934 _overlayList = container.enter().append('ul').attr('class', 'layer-list layer-overlay-list').attr('dir', 'auto').merge(container);
109936 _overlayList.call(drawListItems, 'checkbox', chooseOverlay, function (d) {
109937 return !d.isHidden() && d.overlay;
109941 context.map().on('move.overlay_list', debounce(function () {
109942 // layers in-view may have changed due to map move
109943 window.requestIdleCallback(section.reRender);
109948 function uiPaneBackground(context) {
109949 var backgroundPane = uiPane('background', context).key(_t('background.key')).label(_t.html('background.title')).description(_t.html('background.description')).iconName('iD-icon-layers').sections([uiSectionBackgroundList(context), uiSectionOverlayList(context), uiSectionBackgroundDisplayOptions(context), uiSectionBackgroundOffset(context)]);
109953 function uiPaneHelp(context) {
109954 var docKeys = [['help', ['welcome', 'open_data_h', 'open_data', 'before_start_h', 'before_start', 'open_source_h', 'open_source', 'open_source_help']], ['overview', ['navigation_h', 'navigation_drag', 'navigation_zoom', 'features_h', 'features', 'nodes_ways']], ['editing', ['select_h', 'select_left_click', 'select_right_click', 'select_space', 'multiselect_h', 'multiselect', 'multiselect_shift_click', 'multiselect_lasso', 'undo_redo_h', 'undo_redo', 'save_h', 'save', 'save_validation', 'upload_h', 'upload', 'backups_h', 'backups', 'keyboard_h', 'keyboard']], ['feature_editor', ['intro', 'definitions', 'type_h', 'type', 'type_picker', 'fields_h', 'fields_all_fields', 'fields_example', 'fields_add_field', 'tags_h', 'tags_all_tags', 'tags_resources']], ['points', ['intro', 'add_point_h', 'add_point', 'add_point_finish', 'move_point_h', 'move_point', 'delete_point_h', 'delete_point', 'delete_point_command']], ['lines', ['intro', 'add_line_h', 'add_line', 'add_line_draw', 'add_line_continue', 'add_line_finish', 'modify_line_h', 'modify_line_dragnode', 'modify_line_addnode', 'connect_line_h', 'connect_line', 'connect_line_display', 'connect_line_drag', 'connect_line_tag', 'disconnect_line_h', 'disconnect_line_command', 'move_line_h', 'move_line_command', 'move_line_connected', 'delete_line_h', 'delete_line', 'delete_line_command']], ['areas', ['intro', 'point_or_area_h', 'point_or_area', 'add_area_h', 'add_area_command', 'add_area_draw', 'add_area_continue', 'add_area_finish', 'square_area_h', 'square_area_command', 'modify_area_h', 'modify_area_dragnode', 'modify_area_addnode', 'delete_area_h', 'delete_area', 'delete_area_command']], ['relations', ['intro', 'edit_relation_h', 'edit_relation', 'edit_relation_add', 'edit_relation_delete', 'maintain_relation_h', 'maintain_relation', 'relation_types_h', 'multipolygon_h', 'multipolygon', 'multipolygon_create', 'multipolygon_merge', 'turn_restriction_h', 'turn_restriction', 'turn_restriction_field', 'turn_restriction_editing', 'route_h', 'route', 'route_add', 'boundary_h', 'boundary', 'boundary_add']], ['operations', ['intro', 'intro_2', 'straighten', 'orthogonalize', 'circularize', 'move', 'rotate', 'reflect', 'continue', 'reverse', 'disconnect', 'split', 'extract', 'merge', 'delete', 'downgrade', 'copy_paste']], ['notes', ['intro', 'add_note_h', 'add_note', 'place_note', 'move_note', 'update_note_h', 'update_note', 'save_note_h', 'save_note']], ['imagery', ['intro', 'sources_h', 'choosing', 'sources', 'offsets_h', 'offset', 'offset_change']], ['streetlevel', ['intro', 'using_h', 'using', 'photos', 'viewer']], ['gps', ['intro', 'survey', 'using_h', 'using', 'tracing', 'upload']], ['qa', ['intro', 'tools_h', 'tools', 'issues_h', 'issues']]];
109956 'help.help.open_data_h': 3,
109957 'help.help.before_start_h': 3,
109958 'help.help.open_source_h': 3,
109959 'help.overview.navigation_h': 3,
109960 'help.overview.features_h': 3,
109961 'help.editing.select_h': 3,
109962 'help.editing.multiselect_h': 3,
109963 'help.editing.undo_redo_h': 3,
109964 'help.editing.save_h': 3,
109965 'help.editing.upload_h': 3,
109966 'help.editing.backups_h': 3,
109967 'help.editing.keyboard_h': 3,
109968 'help.feature_editor.type_h': 3,
109969 'help.feature_editor.fields_h': 3,
109970 'help.feature_editor.tags_h': 3,
109971 'help.points.add_point_h': 3,
109972 'help.points.move_point_h': 3,
109973 'help.points.delete_point_h': 3,
109974 'help.lines.add_line_h': 3,
109975 'help.lines.modify_line_h': 3,
109976 'help.lines.connect_line_h': 3,
109977 'help.lines.disconnect_line_h': 3,
109978 'help.lines.move_line_h': 3,
109979 'help.lines.delete_line_h': 3,
109980 'help.areas.point_or_area_h': 3,
109981 'help.areas.add_area_h': 3,
109982 'help.areas.square_area_h': 3,
109983 'help.areas.modify_area_h': 3,
109984 'help.areas.delete_area_h': 3,
109985 'help.relations.edit_relation_h': 3,
109986 'help.relations.maintain_relation_h': 3,
109987 'help.relations.relation_types_h': 2,
109988 'help.relations.multipolygon_h': 3,
109989 'help.relations.turn_restriction_h': 3,
109990 'help.relations.route_h': 3,
109991 'help.relations.boundary_h': 3,
109992 'help.notes.add_note_h': 3,
109993 'help.notes.update_note_h': 3,
109994 'help.notes.save_note_h': 3,
109995 'help.imagery.sources_h': 3,
109996 'help.imagery.offsets_h': 3,
109997 'help.streetlevel.using_h': 3,
110001 }; // For each section, squash all the texts into a single markdown document
110003 var docs = docKeys.map(function (key) {
110004 var helpkey = 'help.' + key[0];
110005 var helpPaneReplacements = {
110006 version: context.version
110008 var text = key[1].reduce(function (all, part) {
110009 var subkey = helpkey + '.' + part;
110010 var depth = headings[subkey]; // is this subkey a heading?
110012 var hhh = depth ? Array(depth + 1).join('#') + ' ' : ''; // if so, prepend with some ##'s
110014 return all + hhh + helpHtml(subkey, helpPaneReplacements) + '\n\n';
110017 title: _t.html(helpkey + '.title'),
110018 content: marked_1(text.trim()) // use keyboard key styling for shortcuts
110019 .replace(/<code>/g, '<kbd>').replace(/<\/code>/g, '<\/kbd>')
110022 var helpPane = uiPane('help', context).key(_t('help.key')).label(_t.html('help.title')).description(_t.html('help.title')).iconName('iD-icon-help');
110024 helpPane.renderContent = function (content) {
110025 function clickHelp(d, i) {
110026 var rtl = _mainLocalizer.textDirection() === 'rtl';
110027 content.property('scrollTop', 0);
110028 helpPane.selection().select('.pane-heading h2').html(d.title);
110030 body.selectAll('a').attr('target', '_blank');
110031 menuItems.classed('selected', function (m) {
110032 return m.title === d.title;
110037 nav.call(drawNext).call(drawPrevious);
110039 nav.call(drawPrevious).call(drawNext);
110042 function drawNext(selection) {
110043 if (i < docs.length - 1) {
110044 var nextLink = selection.append('a').attr('href', '#').attr('class', 'next').on('click', function (d3_event) {
110045 d3_event.preventDefault();
110046 clickHelp(docs[i + 1], i + 1);
110048 nextLink.append('span').html(docs[i + 1].title).call(svgIcon(rtl ? '#iD-icon-backward' : '#iD-icon-forward', 'inline'));
110052 function drawPrevious(selection) {
110054 var prevLink = selection.append('a').attr('href', '#').attr('class', 'previous').on('click', function (d3_event) {
110055 d3_event.preventDefault();
110056 clickHelp(docs[i - 1], i - 1);
110058 prevLink.call(svgIcon(rtl ? '#iD-icon-forward' : '#iD-icon-backward', 'inline')).append('span').html(docs[i - 1].title);
110063 function clickWalkthrough(d3_event) {
110064 d3_event.preventDefault();
110065 if (context.inIntro()) return;
110066 context.container().call(uiIntro(context));
110067 context.ui().togglePanes();
110070 function clickShortcuts(d3_event) {
110071 d3_event.preventDefault();
110072 context.container().call(context.ui().shortcuts, true);
110075 var toc = content.append('ul').attr('class', 'toc');
110076 var menuItems = toc.selectAll('li').data(docs).enter().append('li').append('a').attr('role', 'button').attr('href', '#').html(function (d) {
110078 }).on('click', function (d3_event, d) {
110079 d3_event.preventDefault();
110080 clickHelp(d, docs.indexOf(d));
110082 var shortcuts = toc.append('li').attr('class', 'shortcuts').call(uiTooltip().title(_t.html('shortcuts.tooltip')).keys(['?']).placement('top')).append('a').attr('href', '#').on('click', clickShortcuts);
110083 shortcuts.append('div').call(_t.append('shortcuts.title'));
110084 var walkthrough = toc.append('li').attr('class', 'walkthrough').append('a').attr('href', '#').on('click', clickWalkthrough);
110085 walkthrough.append('svg').attr('class', 'logo logo-walkthrough').append('use').attr('xlink:href', '#iD-logo-walkthrough');
110086 walkthrough.append('div').call(_t.append('splash.walkthrough'));
110087 var helpContent = content.append('div').attr('class', 'left-content');
110088 var body = helpContent.append('div').attr('class', 'body');
110089 var nav = helpContent.append('div').attr('class', 'nav');
110096 function uiSectionValidationIssues(id, severity, context) {
110098 var section = uiSection(id, context).label(function () {
110099 if (!_issues) return '';
110100 var issueCountText = _issues.length > 1000 ? '1000+' : String(_issues.length);
110101 return _t.html('inspector.title_count', {
110103 html: _t.html('issues.' + severity + 's.list_title')
110107 }).disclosureContent(renderDisclosureContent).shouldDisplay(function () {
110108 return _issues && _issues.length;
110111 function getOptions() {
110113 what: corePreferences('validate-what') || 'edited',
110114 where: corePreferences('validate-where') || 'all'
110116 } // get and cache the issues to display, unordered
110119 function reloadIssues() {
110120 _issues = context.validator().getIssuesBySeverity(getOptions())[severity];
110123 function renderDisclosureContent(selection) {
110124 var center = context.map().center();
110125 var graph = context.graph(); // sort issues by distance away from the center of the map
110127 var issues = _issues.map(function withDistance(issue) {
110128 var extent = issue.extent(graph);
110129 var dist = extent ? geoSphericalDistance(center, extent.center()) : 0;
110130 return Object.assign(issue, {
110133 }).sort(function byDistance(a, b) {
110134 return a.dist - b.dist;
110138 issues = issues.slice(0, 1000); //renderIgnoredIssuesReset(_warningsSelection);
110140 selection.call(drawIssuesList, issues);
110143 function drawIssuesList(selection, issues) {
110144 var list = selection.selectAll('.issues-list').data([0]);
110145 list = list.enter().append('ul').attr('class', 'layer-list issues-list ' + severity + 's-list').merge(list);
110146 var items = list.selectAll('li').data(issues, function (d) {
110150 items.exit().remove(); // Enter
110152 var itemsEnter = items.enter().append('li').attr('class', function (d) {
110153 return 'issue severity-' + d.severity;
110155 var labelsEnter = itemsEnter.append('button').attr('class', 'issue-label').on('click', function (d3_event, d) {
110156 context.validator().focusIssue(d);
110157 }).on('mouseover', function (d3_event, d) {
110158 utilHighlightEntities(d.entityIds, true, context);
110159 }).on('mouseout', function (d3_event, d) {
110160 utilHighlightEntities(d.entityIds, false, context);
110162 var textEnter = labelsEnter.append('span').attr('class', 'issue-text');
110163 textEnter.append('span').attr('class', 'issue-icon').each(function (d) {
110164 var iconName = '#iD-icon-' + (d.severity === 'warning' ? 'alert' : 'error');
110165 select(this).call(svgIcon(iconName));
110167 textEnter.append('span').attr('class', 'issue-message');
110171 .attr('class', 'issue-autofix')
110173 if (!d.autoFix) return;
110176 .attr('title', t('issues.fix_one.title'))
110177 .datum(d.autoFix) // set button datum to the autofix
110178 .attr('class', 'autofix action')
110179 .on('click', function(d3_event, d) {
110180 d3_event.preventDefault();
110181 d3_event.stopPropagation();
110182 var issuesEntityIDs = d.issue.entityIds;
110183 utilHighlightEntities(issuesEntityIDs.concat(d.entityIds), false, context);
110184 context.perform.apply(context, d.autoArgs);
110185 context.validator().validate();
110187 .call(svgIcon('#iD-icon-wrench'));
110192 items = items.merge(itemsEnter).order();
110193 items.selectAll('.issue-message').html(function (d) {
110194 return d.message(context);
110198 var canAutoFix = issues.filter(function(issue) { return issue.autoFix; });
110199 var autoFixAll = selection.selectAll('.autofix-all')
110200 .data(canAutoFix.length ? [0] : []);
110205 var autoFixAllEnter = autoFixAll.enter()
110206 .insert('div', '.issues-list')
110207 .attr('class', 'autofix-all');
110208 var linkEnter = autoFixAllEnter
110210 .attr('class', 'autofix-all-link')
110214 .attr('class', 'autofix-all-link-text')
110215 .call(t.append('issues.fix_all.title'));
110218 .attr('class', 'autofix-all-link-icon')
110219 .call(svgIcon('#iD-icon-wrench'));
110220 if (severity === 'warning') {
110221 renderIgnoredIssuesReset(selection);
110224 autoFixAll = autoFixAll
110225 .merge(autoFixAllEnter);
110226 autoFixAll.selectAll('.autofix-all-link')
110227 .on('click', function() {
110228 context.pauseChangeDispatch();
110229 context.perform(actionNoop());
110230 canAutoFix.forEach(function(issue) {
110231 var args = issue.autoFix.autoArgs.slice(); // copy
110232 if (typeof args[args.length - 1] !== 'function') {
110235 args.push(t('issues.fix_all.annotation'));
110236 context.replace.apply(context, args);
110238 context.resumeChangeDispatch();
110239 context.validator().validate();
110244 context.validator().on('validated.uiSectionValidationIssues' + id, function () {
110245 window.requestIdleCallback(function () {
110250 context.map().on('move.uiSectionValidationIssues' + id, debounce(function () {
110251 window.requestIdleCallback(function () {
110252 if (getOptions().where === 'visible') {
110253 // must refetch issues if they are viewport-dependent
110255 } // always reload list to re-sort-by-distance
110264 function uiSectionValidationOptions(context) {
110265 var section = uiSection('issues-options', context).content(renderContent);
110267 function renderContent(selection) {
110268 var container = selection.selectAll('.issues-options-container').data([0]);
110269 container = container.enter().append('div').attr('class', 'issues-options-container').merge(container);
110272 values: ['edited', 'all']
110275 values: ['visible', 'all']
110277 var options = container.selectAll('.issues-option').data(data, function (d) {
110280 var optionsEnter = options.enter().append('div').attr('class', function (d) {
110281 return 'issues-option issues-option-' + d.key;
110283 optionsEnter.append('div').attr('class', 'issues-option-title').html(function (d) {
110284 return _t.html('issues.options.' + d.key + '.title');
110286 var valuesEnter = optionsEnter.selectAll('label').data(function (d) {
110287 return d.values.map(function (val) {
110293 }).enter().append('label');
110294 valuesEnter.append('input').attr('type', 'radio').attr('name', function (d) {
110295 return 'issues-option-' + d.key;
110296 }).attr('value', function (d) {
110298 }).property('checked', function (d) {
110299 return getOptions()[d.key] === d.value;
110300 }).on('change', function (d3_event, d) {
110301 updateOptionValue(d3_event, d.key, d.value);
110303 valuesEnter.append('span').html(function (d) {
110304 return _t.html('issues.options.' + d.key + '.' + d.value);
110308 function getOptions() {
110310 what: corePreferences('validate-what') || 'edited',
110312 where: corePreferences('validate-where') || 'all' // 'all', 'visible'
110317 function updateOptionValue(d3_event, d, val) {
110318 if (!val && d3_event && d3_event.target) {
110319 val = d3_event.target.value;
110322 corePreferences('validate-' + d, val);
110323 context.validator().validate();
110329 function uiSectionValidationRules(context) {
110332 var DEFAULTSQUARE = 5; // see also unsquare_way.js
110334 var section = uiSection('issues-rules', context).disclosureContent(renderDisclosureContent).label(_t.html('issues.rules.title'));
110336 var _ruleKeys = context.validator().getRuleKeys().filter(function (key) {
110337 return key !== 'maprules';
110338 }).sort(function (key1, key2) {
110339 // alphabetize by localized title
110340 return _t('issues.' + key1 + '.title') < _t('issues.' + key2 + '.title') ? -1 : 1;
110343 function renderDisclosureContent(selection) {
110344 var container = selection.selectAll('.issues-rulelist-container').data([0]);
110345 var containerEnter = container.enter().append('div').attr('class', 'issues-rulelist-container');
110346 containerEnter.append('ul').attr('class', 'layer-list issue-rules-list');
110347 var ruleLinks = containerEnter.append('div').attr('class', 'issue-rules-links section-footer');
110348 ruleLinks.append('a').attr('class', 'issue-rules-link').attr('role', 'button').attr('href', '#').call(_t.append('issues.disable_all')).on('click', function (d3_event) {
110349 d3_event.preventDefault();
110350 context.validator().disableRules(_ruleKeys);
110352 ruleLinks.append('a').attr('class', 'issue-rules-link').attr('role', 'button').attr('href', '#').call(_t.append('issues.enable_all')).on('click', function (d3_event) {
110353 d3_event.preventDefault();
110354 context.validator().disableRules([]);
110357 container = container.merge(containerEnter);
110358 container.selectAll('.issue-rules-list').call(drawListItems, _ruleKeys, 'checkbox', 'rule', toggleRule, isRuleEnabled);
110361 function drawListItems(selection, data, type, name, change, active) {
110362 var items = selection.selectAll('li').data(data); // Exit
110364 items.exit().remove(); // Enter
110366 var enter = items.enter().append('li');
110369 enter.call(uiTooltip().title(function (d) {
110370 return _t.html('issues.' + d + '.tip');
110374 var label = enter.append('label');
110375 label.append('input').attr('type', type).attr('name', name).on('change', change);
110376 label.append('span').html(function (d) {
110379 if (d === 'unsquare_way') {
110381 html: '<span class="square-degrees"></span>'
110385 return _t.html('issues.' + d + '.title', params);
110388 items = items.merge(enter);
110389 items.classed('active', active).selectAll('input').property('checked', active).property('indeterminate', false); // user-configurable square threshold
110391 var degStr = corePreferences('validate-square-degrees');
110394 degStr = DEFAULTSQUARE.toString();
110397 var span = items.selectAll('.square-degrees');
110398 var input = span.selectAll('.square-degrees-input').data([0]); // enter / update
110400 input.enter().append('input').attr('type', 'number').attr('min', MINSQUARE.toString()).attr('max', MAXSQUARE.toString()).attr('step', '0.5').attr('class', 'square-degrees-input').call(utilNoAuto).on('click', function (d3_event) {
110401 d3_event.preventDefault();
110402 d3_event.stopPropagation();
110404 }).on('keyup', function (d3_event) {
110405 if (d3_event.keyCode === 13) {
110410 }).on('blur', changeSquare).merge(input).property('value', degStr);
110413 function changeSquare() {
110414 var input = select(this);
110415 var degStr = utilGetSetValue(input).trim();
110416 var degNum = parseFloat(degStr, 10);
110418 if (!isFinite(degNum)) {
110419 degNum = DEFAULTSQUARE;
110420 } else if (degNum > MAXSQUARE) {
110422 } else if (degNum < MINSQUARE) {
110426 degNum = Math.round(degNum * 10) / 10; // round to 1 decimal
110428 degStr = degNum.toString();
110429 input.property('value', degStr);
110430 corePreferences('validate-square-degrees', degStr);
110431 context.validator().revalidateUnsquare();
110434 function isRuleEnabled(d) {
110435 return context.validator().isRuleEnabled(d);
110438 function toggleRule(d3_event, d) {
110439 context.validator().toggleRule(d);
110442 context.validator().on('validated.uiSectionValidationRules', function () {
110443 window.requestIdleCallback(section.reRender);
110448 function uiSectionValidationStatus(context) {
110449 var section = uiSection('issues-status', context).content(renderContent).shouldDisplay(function () {
110450 var issues = context.validator().getIssues(getOptions());
110451 return issues.length === 0;
110454 function getOptions() {
110456 what: corePreferences('validate-what') || 'edited',
110457 where: corePreferences('validate-where') || 'all'
110461 function renderContent(selection) {
110462 var box = selection.selectAll('.box').data([0]);
110463 var boxEnter = box.enter().append('div').attr('class', 'box');
110464 boxEnter.append('div').call(svgIcon('#iD-icon-apply', 'pre-text'));
110465 var noIssuesMessage = boxEnter.append('span');
110466 noIssuesMessage.append('strong').attr('class', 'message');
110467 noIssuesMessage.append('br');
110468 noIssuesMessage.append('span').attr('class', 'details');
110469 renderIgnoredIssuesReset(selection);
110470 setNoIssuesText(selection);
110473 function renderIgnoredIssuesReset(selection) {
110474 var ignoredIssues = context.validator().getIssues({
110477 includeDisabledRules: true,
110480 var resetIgnored = selection.selectAll('.reset-ignored').data(ignoredIssues.length ? [0] : []); // exit
110482 resetIgnored.exit().remove(); // enter
110484 var resetIgnoredEnter = resetIgnored.enter().append('div').attr('class', 'reset-ignored section-footer');
110485 resetIgnoredEnter.append('a').attr('href', '#'); // update
110487 resetIgnored = resetIgnored.merge(resetIgnoredEnter);
110488 resetIgnored.select('a').html(_t.html('inspector.title_count', {
110490 html: _t.html('issues.reset_ignored')
110492 count: ignoredIssues.length
110494 resetIgnored.on('click', function (d3_event) {
110495 d3_event.preventDefault();
110496 context.validator().resetIgnoredIssues();
110500 function setNoIssuesText(selection) {
110501 var opts = getOptions();
110503 function checkForHiddenIssues(cases) {
110504 for (var type in cases) {
110505 var hiddenOpts = cases[type];
110506 var hiddenIssues = context.validator().getIssues(hiddenOpts);
110508 if (hiddenIssues.length) {
110509 selection.select('.box .details').html('').call(_t.append('issues.no_issues.hidden_issues.' + type, {
110510 count: hiddenIssues.length.toString()
110516 selection.select('.box .details').html('').call(_t.append('issues.no_issues.hidden_issues.none'));
110521 if (opts.what === 'edited' && opts.where === 'visible') {
110522 messageType = 'edits_in_view';
110535 includeDisabledRules: 'only'
110537 everything_else_elsewhere: {
110541 disabled_rules_elsewhere: {
110544 includeDisabledRules: 'only'
110551 ignored_issues_elsewhere: {
110557 } else if (opts.what === 'edited' && opts.where === 'all') {
110567 includeDisabledRules: 'only'
110575 } else if (opts.what === 'all' && opts.where === 'visible') {
110576 messageType = 'everything_in_view';
110585 includeDisabledRules: 'only'
110587 disabled_rules_elsewhere: {
110590 includeDisabledRules: 'only'
110597 ignored_issues_elsewhere: {
110603 } else if (opts.what === 'all' && opts.where === 'all') {
110604 messageType = 'everything';
110609 includeDisabledRules: 'only'
110619 if (opts.what === 'edited' && context.history().difference().summary().length === 0) {
110620 messageType = 'no_edits';
110623 selection.select('.box .message').html('').call(_t.append('issues.no_issues.message.' + messageType));
110626 context.validator().on('validated.uiSectionValidationStatus', function () {
110627 window.requestIdleCallback(section.reRender);
110629 context.map().on('move.uiSectionValidationStatus', debounce(function () {
110630 window.requestIdleCallback(section.reRender);
110635 function uiPaneIssues(context) {
110636 var issuesPane = uiPane('issues', context).key(_t('issues.key')).label(_t.html('issues.title')).description(_t.html('issues.title')).iconName('iD-icon-alert').sections([uiSectionValidationOptions(context), uiSectionValidationStatus(context), uiSectionValidationIssues('issues-errors', 'error', context), uiSectionValidationIssues('issues-warnings', 'warning', context), uiSectionValidationRules(context)]);
110640 function uiSettingsCustomData(context) {
110641 var dispatch = dispatch$8('change');
110643 function render(selection) {
110644 var dataLayer = context.layers().layer('data'); // keep separate copies of original and current settings
110647 fileList: dataLayer && dataLayer.fileList() || null,
110648 url: corePreferences('settings-custom-data-url')
110651 fileList: dataLayer && dataLayer.fileList() || null,
110652 url: corePreferences('settings-custom-data-url')
110653 }; // var example = 'https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png';
110655 var modal = uiConfirm(selection).okButton();
110656 modal.classed('settings-modal settings-custom-data', true);
110657 modal.select('.modal-section.header').append('h3').call(_t.append('settings.custom_data.header'));
110658 var textSection = modal.select('.modal-section.message-text');
110659 textSection.append('pre').attr('class', 'instructions-file').call(_t.append('settings.custom_data.file.instructions'));
110660 textSection.append('input').attr('class', 'field-file').attr('type', 'file').attr('accept', '.gpx,.kml,.geojson,.json,application/gpx+xml,application/vnd.google-earth.kml+xml,application/geo+json,application/json').property('files', _currSettings.fileList) // works for all except IE11
110661 .on('change', function (d3_event) {
110662 var files = d3_event.target.files;
110664 if (files && files.length) {
110665 _currSettings.url = '';
110666 textSection.select('.field-url').property('value', '');
110667 _currSettings.fileList = files;
110669 _currSettings.fileList = null;
110672 textSection.append('h4').call(_t.append('settings.custom_data.or'));
110673 textSection.append('pre').attr('class', 'instructions-url').call(_t.append('settings.custom_data.url.instructions'));
110674 textSection.append('textarea').attr('class', 'field-url').attr('placeholder', _t('settings.custom_data.url.placeholder')).call(utilNoAuto).property('value', _currSettings.url); // insert a cancel button
110676 var buttonSection = modal.select('.modal-section.buttons');
110677 buttonSection.insert('button', '.ok-button').attr('class', 'button cancel-button secondary-action').call(_t.append('confirm.cancel'));
110678 buttonSection.select('.cancel-button').on('click.cancel', clickCancel);
110679 buttonSection.select('.ok-button').attr('disabled', isSaveDisabled).on('click.save', clickSave);
110681 function isSaveDisabled() {
110683 } // restore the original url
110686 function clickCancel() {
110687 textSection.select('.field-url').property('value', _origSettings.url);
110688 corePreferences('settings-custom-data-url', _origSettings.url);
110691 } // accept the current url
110695 _currSettings.url = textSection.select('.field-url').property('value').trim(); // one or the other but not both
110697 if (_currSettings.url) {
110698 _currSettings.fileList = null;
110701 if (_currSettings.fileList) {
110702 _currSettings.url = '';
110705 corePreferences('settings-custom-data-url', _currSettings.url);
110708 dispatch.call('change', this, _currSettings);
110712 return utilRebind(render, dispatch, 'on');
110715 function uiSectionDataLayers(context) {
110716 var settingsCustomData = uiSettingsCustomData(context).on('change', customChanged);
110717 var layers = context.layers();
110718 var section = uiSection('data-layers', context).label(_t.html('map_data.data_layers')).disclosureContent(renderDisclosureContent);
110720 function renderDisclosureContent(selection) {
110721 var container = selection.selectAll('.data-layer-container').data([0]);
110722 container.enter().append('div').attr('class', 'data-layer-container').merge(container).call(drawOsmItems).call(drawQAItems).call(drawCustomDataItems).call(drawVectorItems) // Beta - Detroit mapping challenge
110726 function showsLayer(which) {
110727 var layer = layers.layer(which);
110730 return layer.enabled();
110736 function setLayer(which, enabled) {
110737 // Don't allow layer changes while drawing - #6584
110738 var mode = context.mode();
110739 if (mode && /^draw/.test(mode.id)) return;
110740 var layer = layers.layer(which);
110743 layer.enabled(enabled);
110745 if (!enabled && (which === 'osm' || which === 'notes')) {
110746 context.enter(modeBrowse(context));
110751 function toggleLayer(which) {
110752 setLayer(which, !showsLayer(which));
110755 function drawOsmItems(selection) {
110756 var osmKeys = ['osm', 'notes'];
110757 var osmLayers = layers.all().filter(function (obj) {
110758 return osmKeys.indexOf(obj.id) !== -1;
110760 var ul = selection.selectAll('.layer-list-osm').data([0]);
110761 ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-osm').merge(ul);
110762 var li = ul.selectAll('.list-item').data(osmLayers);
110764 var liEnter = li.enter().append('li').attr('class', function (d) {
110765 return 'list-item list-item-' + d.id;
110767 var labelEnter = liEnter.append('label').each(function (d) {
110769 select(this).call(uiTooltip().title(_t.html('map_data.layers.' + d.id + '.tooltip')).keys([uiCmd('⌥' + _t('area_fill.wireframe.key'))]).placement('bottom'));
110771 select(this).call(uiTooltip().title(_t.html('map_data.layers.' + d.id + '.tooltip')).placement('bottom'));
110774 labelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
110777 labelEnter.append('span').html(function (d) {
110778 return _t.html('map_data.layers.' + d.id + '.title');
110781 li.merge(liEnter).classed('active', function (d) {
110782 return d.layer.enabled();
110783 }).selectAll('input').property('checked', function (d) {
110784 return d.layer.enabled();
110788 function drawQAItems(selection) {
110789 var qaKeys = ['keepRight', 'improveOSM', 'osmose'];
110790 var qaLayers = layers.all().filter(function (obj) {
110791 return qaKeys.indexOf(obj.id) !== -1;
110793 var ul = selection.selectAll('.layer-list-qa').data([0]);
110794 ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-qa').merge(ul);
110795 var li = ul.selectAll('.list-item').data(qaLayers);
110797 var liEnter = li.enter().append('li').attr('class', function (d) {
110798 return 'list-item list-item-' + d.id;
110800 var labelEnter = liEnter.append('label').each(function (d) {
110801 select(this).call(uiTooltip().title(_t.html('map_data.layers.' + d.id + '.tooltip')).placement('bottom'));
110803 labelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
110806 labelEnter.append('span').html(function (d) {
110807 return _t.html('map_data.layers.' + d.id + '.title');
110810 li.merge(liEnter).classed('active', function (d) {
110811 return d.layer.enabled();
110812 }).selectAll('input').property('checked', function (d) {
110813 return d.layer.enabled();
110815 } // Beta feature - sample vector layers to support Detroit Mapping Challenge
110816 // https://github.com/osmus/detroit-mapping-challenge
110819 function drawVectorItems(selection) {
110820 var dataLayer = layers.layer('data');
110822 name: 'Detroit Neighborhoods/Parks',
110823 src: 'neighborhoods-parks',
110824 tooltip: 'Neighborhood boundaries and parks as compiled by City of Detroit in concert with community groups.',
110825 template: 'https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmur6x34562qp9iv1u3ksf-54hev,jonahadkins.cjksmqxdx33jj2wp90xd9x2md-4e5y2/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA'
110827 name: 'Detroit Composite POIs',
110829 tooltip: 'Fire Inspections, Business Licenses, and other public location data collated from the City of Detroit.',
110830 template: 'https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmm6a02sli31myxhsr7zf3-2sw8h/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA'
110832 name: 'Detroit All-The-Places POIs',
110833 src: 'alltheplaces-poi',
110834 tooltip: 'Public domain business location data created by web scrapers.',
110835 template: 'https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmswgk340g2vo06p1w9w0j-8fjjc/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA'
110836 }]; // Only show this if the map is around Detroit..
110838 var detroit = geoExtent([-83.5, 42.1], [-82.8, 42.5]);
110839 var showVectorItems = context.map().zoom() > 9 && detroit.contains(context.map().center());
110840 var container = selection.selectAll('.vectortile-container').data(showVectorItems ? [0] : []);
110841 container.exit().remove();
110842 var containerEnter = container.enter().append('div').attr('class', 'vectortile-container');
110843 containerEnter.append('h4').attr('class', 'vectortile-header').text('Detroit Vector Tiles (Beta)');
110844 containerEnter.append('ul').attr('class', 'layer-list layer-list-vectortile');
110845 containerEnter.append('div').attr('class', 'vectortile-footer').append('a').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).attr('href', 'https://github.com/osmus/detroit-mapping-challenge').append('span').text('About these layers');
110846 container = container.merge(containerEnter);
110847 var ul = container.selectAll('.layer-list-vectortile');
110848 var li = ul.selectAll('.list-item').data(vtData);
110850 var liEnter = li.enter().append('li').attr('class', function (d) {
110851 return 'list-item list-item-' + d.src;
110853 var labelEnter = liEnter.append('label').each(function (d) {
110854 select(this).call(uiTooltip().title(d.tooltip).placement('top'));
110856 labelEnter.append('input').attr('type', 'radio').attr('name', 'vectortile').on('change', selectVTLayer);
110857 labelEnter.append('span').text(function (d) {
110861 li.merge(liEnter).classed('active', isVTLayerSelected).selectAll('input').property('checked', isVTLayerSelected);
110863 function isVTLayerSelected(d) {
110864 return dataLayer && dataLayer.template() === d.template;
110867 function selectVTLayer(d3_event, d) {
110868 corePreferences('settings-custom-data-url', d.template);
110871 dataLayer.template(d.template, d.src);
110872 dataLayer.enabled(true);
110877 function drawCustomDataItems(selection) {
110878 var dataLayer = layers.layer('data');
110879 var hasData = dataLayer && dataLayer.hasData();
110880 var showsData = hasData && dataLayer.enabled();
110881 var ul = selection.selectAll('.layer-list-data').data(dataLayer ? [0] : []); // Exit
110883 ul.exit().remove(); // Enter
110885 var ulEnter = ul.enter().append('ul').attr('class', 'layer-list layer-list-data');
110886 var liEnter = ulEnter.append('li').attr('class', 'list-item-data');
110887 var labelEnter = liEnter.append('label').call(uiTooltip().title(_t.html('map_data.layers.custom.tooltip')).placement('top'));
110888 labelEnter.append('input').attr('type', 'checkbox').on('change', function () {
110891 labelEnter.append('span').call(_t.append('map_data.layers.custom.title'));
110892 liEnter.append('button').attr('class', 'open-data-options').call(uiTooltip().title(_t.html('settings.custom_data.tooltip')).placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left')).on('click', function (d3_event) {
110893 d3_event.preventDefault();
110895 }).call(svgIcon('#iD-icon-more'));
110896 liEnter.append('button').attr('class', 'zoom-to-data').call(uiTooltip().title(_t.html('map_data.layers.custom.zoom')).placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left')).on('click', function (d3_event) {
110897 if (select(this).classed('disabled')) return;
110898 d3_event.preventDefault();
110899 d3_event.stopPropagation();
110901 }).call(svgIcon('#iD-icon-framed-dot', 'monochrome')); // Update
110903 ul = ul.merge(ulEnter);
110904 ul.selectAll('.list-item-data').classed('active', showsData).selectAll('label').classed('deemphasize', !hasData).selectAll('input').property('disabled', !hasData).property('checked', showsData);
110905 ul.selectAll('button.zoom-to-data').classed('disabled', !hasData);
110908 function editCustom() {
110909 context.container().call(settingsCustomData);
110912 function customChanged(d) {
110913 var dataLayer = layers.layer('data');
110917 } else if (d && d.fileList) {
110918 dataLayer.fileList(d.fileList);
110922 function drawPanelItems(selection) {
110923 var panelsListEnter = selection.selectAll('.md-extras-list').data([0]).enter().append('ul').attr('class', 'layer-list md-extras-list');
110924 var historyPanelLabelEnter = panelsListEnter.append('li').attr('class', 'history-panel-toggle-item').append('label').call(uiTooltip().title(_t.html('map_data.history_panel.tooltip')).keys([uiCmd('⌘⇧' + _t('info_panels.history.key'))]).placement('top'));
110925 historyPanelLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
110926 d3_event.preventDefault();
110927 context.ui().info.toggle('history');
110929 historyPanelLabelEnter.append('span').call(_t.append('map_data.history_panel.title'));
110930 var measurementPanelLabelEnter = panelsListEnter.append('li').attr('class', 'measurement-panel-toggle-item').append('label').call(uiTooltip().title(_t.html('map_data.measurement_panel.tooltip')).keys([uiCmd('⌘⇧' + _t('info_panels.measurement.key'))]).placement('top'));
110931 measurementPanelLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
110932 d3_event.preventDefault();
110933 context.ui().info.toggle('measurement');
110935 measurementPanelLabelEnter.append('span').call(_t.append('map_data.measurement_panel.title'));
110938 context.layers().on('change.uiSectionDataLayers', section.reRender);
110939 context.map().on('move.uiSectionDataLayers', debounce(function () {
110940 // Detroit layers may have moved in or out of view
110941 window.requestIdleCallback(section.reRender);
110946 function uiSectionMapFeatures(context) {
110947 var _features = context.features().keys();
110949 var section = uiSection('map-features', context).label(_t.html('map_data.map_features')).disclosureContent(renderDisclosureContent).expandedByDefault(false);
110951 function renderDisclosureContent(selection) {
110952 var container = selection.selectAll('.layer-feature-list-container').data([0]);
110953 var containerEnter = container.enter().append('div').attr('class', 'layer-feature-list-container');
110954 containerEnter.append('ul').attr('class', 'layer-list layer-feature-list');
110955 var footer = containerEnter.append('div').attr('class', 'feature-list-links section-footer');
110956 footer.append('a').attr('class', 'feature-list-link').attr('role', 'button').attr('href', '#').call(_t.append('issues.disable_all')).on('click', function (d3_event) {
110957 d3_event.preventDefault();
110958 context.features().disableAll();
110960 footer.append('a').attr('class', 'feature-list-link').attr('role', 'button').attr('href', '#').call(_t.append('issues.enable_all')).on('click', function (d3_event) {
110961 d3_event.preventDefault();
110962 context.features().enableAll();
110965 container = container.merge(containerEnter);
110966 container.selectAll('.layer-feature-list').call(drawListItems, _features, 'checkbox', 'feature', clickFeature, showsFeature);
110969 function drawListItems(selection, data, type, name, change, active) {
110970 var items = selection.selectAll('li').data(data); // Exit
110972 items.exit().remove(); // Enter
110974 var enter = items.enter().append('li').call(uiTooltip().title(function (d) {
110975 var tip = _t.html(name + '.' + d + '.tooltip');
110977 if (autoHiddenFeature(d)) {
110978 var msg = showsLayer('osm') ? _t.html('map_data.autohidden') : _t.html('map_data.osmhidden');
110979 tip += '<div>' + msg + '</div>';
110984 var label = enter.append('label');
110985 label.append('input').attr('type', type).attr('name', name).on('change', change);
110986 label.append('span').html(function (d) {
110987 return _t.html(name + '.' + d + '.description');
110990 items = items.merge(enter);
110991 items.classed('active', active).selectAll('input').property('checked', active).property('indeterminate', autoHiddenFeature);
110994 function autoHiddenFeature(d) {
110995 return context.features().autoHidden(d);
110998 function showsFeature(d) {
110999 return context.features().enabled(d);
111002 function clickFeature(d3_event, d) {
111003 context.features().toggle(d);
111006 function showsLayer(id) {
111007 var layer = context.layers().layer(id);
111008 return layer && layer.enabled();
111012 context.features().on('change.map_features', section.reRender);
111016 function uiSectionMapStyleOptions(context) {
111017 var section = uiSection('fill-area', context).label(_t.html('map_data.style_options')).disclosureContent(renderDisclosureContent).expandedByDefault(false);
111019 function renderDisclosureContent(selection) {
111020 var container = selection.selectAll('.layer-fill-list').data([0]);
111021 container.enter().append('ul').attr('class', 'layer-list layer-fill-list').merge(container).call(drawListItems, context.map().areaFillOptions, 'radio', 'area_fill', setFill, isActiveFill);
111022 var container2 = selection.selectAll('.layer-visual-diff-list').data([0]);
111023 container2.enter().append('ul').attr('class', 'layer-list layer-visual-diff-list').merge(container2).call(drawListItems, ['highlight_edits'], 'checkbox', 'visual_diff', toggleHighlightEdited, function () {
111024 return context.surface().classed('highlight-edited');
111028 function drawListItems(selection, data, type, name, change, active) {
111029 var items = selection.selectAll('li').data(data); // Exit
111031 items.exit().remove(); // Enter
111033 var enter = items.enter().append('li').call(uiTooltip().title(function (d) {
111034 return _t.html(name + '.' + d + '.tooltip');
111036 var key = d === 'wireframe' ? _t('area_fill.wireframe.key') : null;
111037 if (d === 'highlight_edits') key = _t('map_data.highlight_edits.key');
111038 return key ? [key] : null;
111040 var label = enter.append('label');
111041 label.append('input').attr('type', type).attr('name', name).on('change', change);
111042 label.append('span').html(function (d) {
111043 return _t.html(name + '.' + d + '.description');
111046 items = items.merge(enter);
111047 items.classed('active', active).selectAll('input').property('checked', active).property('indeterminate', false);
111050 function isActiveFill(d) {
111051 return context.map().activeAreaFill() === d;
111054 function toggleHighlightEdited(d3_event) {
111055 d3_event.preventDefault();
111056 context.map().toggleHighlightEdited();
111059 function setFill(d3_event, d) {
111060 context.map().activeAreaFill(d);
111063 context.map().on('changeHighlighting.ui_style, changeAreaFill.ui_style', section.reRender);
111067 function uiSectionPhotoOverlays(context) {
111068 var layers = context.layers();
111069 var section = uiSection('photo-overlays', context).label(_t.html('photo_overlays.title')).disclosureContent(renderDisclosureContent).expandedByDefault(false);
111071 function renderDisclosureContent(selection) {
111072 var container = selection.selectAll('.photo-overlay-container').data([0]);
111073 container.enter().append('div').attr('class', 'photo-overlay-container').merge(container).call(drawPhotoItems).call(drawPhotoTypeItems).call(drawDateFilter).call(drawUsernameFilter);
111076 function drawPhotoItems(selection) {
111077 var photoKeys = context.photos().overlayLayerIDs();
111078 var photoLayers = layers.all().filter(function (obj) {
111079 return photoKeys.indexOf(obj.id) !== -1;
111081 var data = photoLayers.filter(function (obj) {
111082 return obj.layer.supported();
111085 function layerSupported(d) {
111086 return d.layer && d.layer.supported();
111089 function layerEnabled(d) {
111090 return layerSupported(d) && d.layer.enabled();
111093 var ul = selection.selectAll('.layer-list-photos').data([0]);
111094 ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-photos').merge(ul);
111095 var li = ul.selectAll('.list-item-photos').data(data);
111097 var liEnter = li.enter().append('li').attr('class', function (d) {
111098 var classes = 'list-item-photos list-item-' + d.id;
111100 if (d.id === 'mapillary-signs' || d.id === 'mapillary-map-features') {
111101 classes += ' indented';
111106 var labelEnter = liEnter.append('label').each(function (d) {
111108 if (d.id === 'mapillary-signs') titleID = 'mapillary.signs.tooltip';else if (d.id === 'mapillary') titleID = 'mapillary_images.tooltip';else if (d.id === 'kartaview') titleID = 'kartaview_images.tooltip';else titleID = d.id.replace(/-/g, '_') + '.tooltip';
111109 select(this).call(uiTooltip().title(_t.html(titleID)).placement('top'));
111111 labelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
111114 labelEnter.append('span').html(function (d) {
111116 if (id === 'mapillary-signs') id = 'photo_overlays.traffic_signs';
111117 return _t.html(id.replace(/-/g, '_') + '.title');
111120 li.merge(liEnter).classed('active', layerEnabled).selectAll('input').property('checked', layerEnabled);
111123 function drawPhotoTypeItems(selection) {
111124 var data = context.photos().allPhotoTypes();
111126 function typeEnabled(d) {
111127 return context.photos().showsPhotoType(d);
111130 var ul = selection.selectAll('.layer-list-photo-types').data([0]);
111132 ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-photo-types').merge(ul);
111133 var li = ul.selectAll('.list-item-photo-types').data(context.photos().shouldFilterByPhotoType() ? data : []);
111135 var liEnter = li.enter().append('li').attr('class', function (d) {
111136 return 'list-item-photo-types list-item-' + d;
111138 var labelEnter = liEnter.append('label').each(function (d) {
111139 select(this).call(uiTooltip().title(_t.html('photo_overlays.photo_type.' + d + '.tooltip')).placement('top'));
111141 labelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
111142 context.photos().togglePhotoType(d);
111144 labelEnter.append('span').html(function (d) {
111145 return _t.html('photo_overlays.photo_type.' + d + '.title');
111148 li.merge(liEnter).classed('active', typeEnabled).selectAll('input').property('checked', typeEnabled);
111151 function drawDateFilter(selection) {
111152 var data = context.photos().dateFilters();
111154 function filterEnabled(d) {
111155 return context.photos().dateFilterValue(d);
111158 var ul = selection.selectAll('.layer-list-date-filter').data([0]);
111160 ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-date-filter').merge(ul);
111161 var li = ul.selectAll('.list-item-date-filter').data(context.photos().shouldFilterByDate() ? data : []);
111163 var liEnter = li.enter().append('li').attr('class', 'list-item-date-filter');
111164 var labelEnter = liEnter.append('label').each(function (d) {
111165 select(this).call(uiTooltip().title(_t.html('photo_overlays.date_filter.' + d + '.tooltip')).placement('top'));
111167 labelEnter.append('span').html(function (d) {
111168 return _t.html('photo_overlays.date_filter.' + d + '.title');
111170 labelEnter.append('input').attr('type', 'date').attr('class', 'list-item-input').attr('placeholder', _t('units.year_month_day')).call(utilNoAuto).each(function (d) {
111171 utilGetSetValue(select(this), context.photos().dateFilterValue(d) || '');
111172 }).on('change', function (d3_event, d) {
111173 var value = utilGetSetValue(select(this)).trim();
111174 context.photos().setDateFilter(d, value, true); // reload the displayed dates
111176 li.selectAll('input').each(function (d) {
111177 utilGetSetValue(select(this), context.photos().dateFilterValue(d) || '');
111180 li = li.merge(liEnter).classed('active', filterEnabled);
111183 function drawUsernameFilter(selection) {
111184 function filterEnabled() {
111185 return context.photos().usernames();
111188 var ul = selection.selectAll('.layer-list-username-filter').data([0]);
111190 ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-username-filter').merge(ul);
111191 var li = ul.selectAll('.list-item-username-filter').data(context.photos().shouldFilterByUsername() ? ['username-filter'] : []);
111193 var liEnter = li.enter().append('li').attr('class', 'list-item-username-filter');
111194 var labelEnter = liEnter.append('label').each(function () {
111195 select(this).call(uiTooltip().title(_t.html('photo_overlays.username_filter.tooltip')).placement('top'));
111197 labelEnter.append('span').call(_t.append('photo_overlays.username_filter.title'));
111198 labelEnter.append('input').attr('type', 'text').attr('class', 'list-item-input').call(utilNoAuto).property('value', usernameValue).on('change', function () {
111199 var value = select(this).property('value');
111200 context.photos().setUsernameFilter(value, true);
111201 select(this).property('value', usernameValue);
111203 li.merge(liEnter).classed('active', filterEnabled);
111205 function usernameValue() {
111206 var usernames = context.photos().usernames();
111207 if (usernames) return usernames.join('; ');
111212 function toggleLayer(which) {
111213 setLayer(which, !showsLayer(which));
111216 function showsLayer(which) {
111217 var layer = layers.layer(which);
111220 return layer.enabled();
111226 function setLayer(which, enabled) {
111227 var layer = layers.layer(which);
111230 layer.enabled(enabled);
111234 context.layers().on('change.uiSectionPhotoOverlays', section.reRender);
111235 context.photos().on('change.uiSectionPhotoOverlays', section.reRender);
111239 function uiPaneMapData(context) {
111240 var mapDataPane = uiPane('map-data', context).key(_t('map_data.key')).label(_t.html('map_data.title')).description(_t.html('map_data.description')).iconName('iD-icon-data').sections([uiSectionDataLayers(context), uiSectionPhotoOverlays(context), uiSectionMapStyleOptions(context), uiSectionMapFeatures(context)]);
111244 function uiPanePreferences(context) {
111245 var preferencesPane = uiPane('preferences', context).key(_t('preferences.key')).label(_t.html('preferences.title')).description(_t.html('preferences.description')).iconName('fas-user-cog').sections([uiSectionPrivacy(context)]);
111246 return preferencesPane;
111249 function uiInit(context) {
111255 function render(container) {
111256 container.on('click.ui', function (d3_event) {
111257 // we're only concerned with the primary mouse button
111258 if (d3_event.button !== 0) return;
111259 if (!d3_event.composedPath) return; // some targets have default click events we don't want to override
111261 var isOkayTarget = d3_event.composedPath().some(function (node) {
111262 // we only care about element nodes
111263 return node.nodeType === 1 && ( // clicking <input> focuses it and/or changes a value
111264 node.nodeName === 'INPUT' || // clicking <label> affects its <input> by default
111265 node.nodeName === 'LABEL' || // clicking <a> opens a hyperlink by default
111266 node.nodeName === 'A');
111268 if (isOkayTarget) return; // disable double-tap-to-zoom on touchscreens
111270 d3_event.preventDefault();
111272 var detected = utilDetect(); // only WebKit supports gesture events
111274 if ('GestureEvent' in window && // Listening for gesture events on iOS 13.4+ breaks double-tapping,
111275 // but we only need to do this on desktop Safari anyway. – #7694
111276 !detected.isMobileWebKit) {
111277 // On iOS we disable pinch-to-zoom of the UI via the `touch-action`
111278 // CSS property, but on desktop Safari we need to manually cancel the
111279 // default gesture events.
111280 container.on('gesturestart.ui gesturechange.ui gestureend.ui', function (d3_event) {
111281 // disable pinch-to-zoom of the UI via multitouch trackpads on macOS Safari
111282 d3_event.preventDefault();
111286 if ('PointerEvent' in window) {
111287 select(window).on('pointerdown.ui pointerup.ui', function (d3_event) {
111288 var pointerType = d3_event.pointerType || 'mouse';
111290 if (_lastPointerType !== pointerType) {
111291 _lastPointerType = pointerType;
111292 container.attr('pointer', pointerType);
111296 _lastPointerType = 'mouse';
111297 container.attr('pointer', 'mouse');
111300 container.attr('lang', _mainLocalizer.localeCode()).attr('dir', _mainLocalizer.textDirection()); // setup fullscreen keybindings (no button shown at this time)
111302 container.call(uiFullScreen(context));
111303 var map = context.map();
111304 map.redrawEnable(false); // don't draw until we've set zoom/lat/long
111306 map.on('hitMinZoom.ui', function () {
111307 ui.flash.iconName('#iD-icon-no').label(_t.html('cannot_zoom'))();
111309 container.append('svg').attr('id', 'ideditor-defs').call(ui.svgDefs);
111310 container.append('div').attr('class', 'sidebar').call(ui.sidebar);
111311 var content = container.append('div').attr('class', 'main-content active'); // Top toolbar
111313 content.append('div').attr('class', 'top-toolbar-wrap').append('div').attr('class', 'top-toolbar fillD').call(uiTopToolbar(context));
111314 content.append('div').attr('class', 'main-map').attr('dir', 'ltr').call(map);
111315 var overMap = content.append('div').attr('class', 'over-map'); // HACK: Mobile Safari 14 likes to select anything selectable when long-
111316 // pressing, even if it's not targeted. This conflicts with long-pressing
111317 // to show the edit menu. We add a selectable offscreen element as the first
111318 // child to trick Safari into not showing the selection UI.
111320 overMap.append('div').attr('class', 'select-trap').text('t');
111321 overMap.call(uiMapInMap(context)).call(uiNotice(context));
111322 overMap.append('div').attr('class', 'spinner').call(uiSpinner(context)); // Map controls
111324 var controlsWrap = overMap.append('div').attr('class', 'map-controls-wrap');
111325 var controls = controlsWrap.append('div').attr('class', 'map-controls');
111326 controls.append('div').attr('class', 'map-control zoombuttons').call(uiZoom(context));
111327 controls.append('div').attr('class', 'map-control zoom-to-selection-control').call(uiZoomToSelection(context));
111328 controls.append('div').attr('class', 'map-control geolocate-control').call(uiGeolocate(context));
111329 controlsWrap.on('wheel.mapControls', function (d3_event) {
111330 if (!d3_event.deltaX) {
111331 controlsWrap.node().scrollTop += d3_event.deltaY;
111334 // This should happen after map is initialized, as some require surface()
111336 var panes = overMap.append('div').attr('class', 'map-panes');
111337 var uiPanes = [uiPaneBackground(context), uiPaneMapData(context), uiPaneIssues(context), uiPanePreferences(context), uiPaneHelp(context)];
111338 uiPanes.forEach(function (pane) {
111339 controls.append('div').attr('class', 'map-control map-pane-control ' + pane.id + '-control').call(pane.renderToggleButton);
111340 panes.call(pane.renderPane);
111342 ui.info = uiInfo(context);
111344 overMap.append('div').attr('class', 'photoviewer').classed('al', true) // 'al'=left, 'ar'=right
111345 .classed('hide', true).call(ui.photoviewer);
111346 overMap.append('div').attr('class', 'attribution-wrap').attr('dir', 'ltr').call(uiAttribution(context)); // Add footer
111348 var about = content.append('div').attr('class', 'map-footer');
111349 about.append('div').attr('class', 'api-status').call(uiStatus(context));
111350 var footer = about.append('div').attr('class', 'map-footer-bar fillD');
111351 footer.append('div').attr('class', 'flash-wrap footer-hide');
111352 var footerWrap = footer.append('div').attr('class', 'main-footer-wrap footer-show');
111353 footerWrap.append('div').attr('class', 'scale-block').call(uiScale(context));
111354 var aboutList = footerWrap.append('div').attr('class', 'info-block').append('ul').attr('class', 'map-footer-list');
111355 aboutList.append('li').attr('class', 'user-list').call(uiContributors(context));
111356 var apiConnections = context.apiConnections();
111358 if (apiConnections && apiConnections.length > 1) {
111359 aboutList.append('li').attr('class', 'source-switch').call(uiSourceSwitch(context).keys(apiConnections));
111362 aboutList.append('li').attr('class', 'issues-info').call(uiIssuesInfo(context));
111363 aboutList.append('li').attr('class', 'feature-warning').call(uiFeatureInfo(context));
111364 var issueLinks = aboutList.append('li');
111365 issueLinks.append('a').attr('target', '_blank').attr('href', 'https://github.com/openstreetmap/iD/issues').attr('aria-label', _t('report_a_bug')).call(svgIcon('#iD-icon-bug', 'light')).call(uiTooltip().title(_t.html('report_a_bug')).placement('top'));
111366 issueLinks.append('a').attr('target', '_blank').attr('href', 'https://github.com/openstreetmap/iD/blob/develop/CONTRIBUTING.md#translating').attr('aria-label', _t('help_translate')).call(svgIcon('#iD-icon-translate', 'light')).call(uiTooltip().title(_t.html('help_translate')).placement('top'));
111367 aboutList.append('li').attr('class', 'version').call(uiVersion(context));
111369 if (!context.embed()) {
111370 aboutList.call(uiAccount(context));
111371 } // Setup map dimensions and move map to initial center/zoom.
111372 // This should happen after .main-content and toolbars exist.
111376 map.redrawEnable(true);
111377 ui.hash = behaviorHash(context);
111380 if (!ui.hash.hadHash) {
111381 map.centerZoom([0, 0], 2);
111385 window.onbeforeunload = function () {
111389 window.onunload = function () {
111390 context.history().unlock();
111393 select(window).on('resize.editor', function () {
111397 context.keybinding().on('⌫', function (d3_event) {
111398 d3_event.preventDefault();
111399 }).on([_t('sidebar.key'), '`', '²', '@'], ui.sidebar.toggle) // #5663, #6864 - common QWERTY, AZERTY
111400 .on('←', pan([panPixels, 0])).on('↑', pan([0, panPixels])).on('→', pan([-panPixels, 0])).on('↓', pan([0, -panPixels])).on(uiCmd('⌥←'), pan([map.dimensions()[0], 0])).on(uiCmd('⌥↑'), pan([0, map.dimensions()[1]])).on(uiCmd('⌥→'), pan([-map.dimensions()[0], 0])).on(uiCmd('⌥↓'), pan([0, -map.dimensions()[1]])).on(uiCmd('⌘' + _t('background.key')), function quickSwitch(d3_event) {
111402 d3_event.stopImmediatePropagation();
111403 d3_event.preventDefault();
111406 var previousBackground = context.background().findSource(corePreferences('background-last-used-toggle'));
111408 if (previousBackground) {
111409 var currentBackground = context.background().baseLayerSource();
111410 corePreferences('background-last-used-toggle', currentBackground.id);
111411 corePreferences('background-last-used', previousBackground.id);
111412 context.background().baseLayerSource(previousBackground);
111414 }).on(_t('area_fill.wireframe.key'), function toggleWireframe(d3_event) {
111415 d3_event.preventDefault();
111416 d3_event.stopPropagation();
111417 context.map().toggleWireframe();
111418 }).on(uiCmd('⌥' + _t('area_fill.wireframe.key')), function toggleOsmData(d3_event) {
111419 d3_event.preventDefault();
111420 d3_event.stopPropagation(); // Don't allow layer changes while drawing - #6584
111422 var mode = context.mode();
111423 if (mode && /^draw/.test(mode.id)) return;
111424 var layer = context.layers().layer('osm');
111427 layer.enabled(!layer.enabled());
111429 if (!layer.enabled()) {
111430 context.enter(modeBrowse(context));
111433 }).on(_t('map_data.highlight_edits.key'), function toggleHighlightEdited(d3_event) {
111434 d3_event.preventDefault();
111435 context.map().toggleHighlightEdited();
111437 context.on('enter.editor', function (entered) {
111438 container.classed('mode-' + entered.id, true);
111439 }).on('exit.editor', function (exited) {
111440 container.classed('mode-' + exited.id, false);
111442 context.enter(modeBrowse(context));
111445 if (!ui.hash.startWalkthrough) {
111446 context.container().call(uiSplash(context)).call(uiRestore(context));
111449 context.container().call(ui.shortcuts);
111452 var osm = context.connection();
111453 var auth = uiLoading(context).message(_t.html('loading_auth')).blocking(true);
111456 osm.on('authLoading.ui', function () {
111457 context.container().call(auth);
111458 }).on('authDone.ui', function () {
111465 if (ui.hash.startWalkthrough) {
111466 ui.hash.startWalkthrough = false;
111467 context.container().call(uiIntro(context));
111471 return function (d3_event) {
111472 if (d3_event.shiftKey) return;
111473 if (context.container().select('.combobox').size()) return;
111474 d3_event.preventDefault();
111475 context.map().pan(d, 100);
111482 var _loadPromise; // renders the iD interface into the container node
111485 ui.ensureLoaded = function () {
111486 if (_loadPromise) return _loadPromise;
111487 return _loadPromise = Promise.all([// must have strings and presets before loading the UI
111488 _mainLocalizer.ensureLoaded(), _mainPresetIndex.ensureLoaded()]).then(function () {
111489 if (!context.container().empty()) render(context.container());
111490 })["catch"](function (err) {
111491 return console.error(err);
111492 }); // eslint-disable-line
111493 }; // `ui.restart()` will destroy and rebuild the entire iD interface,
111494 // for example to switch the locale while iD is running.
111497 ui.restart = function () {
111498 context.keybinding().clear();
111500 context.container().selectAll('*').remove();
111504 ui.lastPointerType = function () {
111505 return _lastPointerType;
111508 ui.svgDefs = svgDefs(context);
111509 ui.flash = uiFlash(context);
111510 ui.sidebar = uiSidebar(context);
111511 ui.photoviewer = uiPhotoviewer(context);
111512 ui.shortcuts = uiShortcuts(context);
111514 ui.onResize = function (withPan) {
111515 var map = context.map(); // Recalc dimensions of map and sidebar.. (`true` = force recalc)
111516 // This will call `getBoundingClientRect` and trigger reflow,
111517 // but the values will be cached for later use.
111519 var mapDimensions = utilGetDimensions(context.container().select('.main-content'), true);
111520 utilGetDimensions(context.container().select('.sidebar'), true);
111522 if (withPan !== undefined) {
111523 map.redrawEnable(false);
111525 map.redrawEnable(true);
111528 map.dimensions(mapDimensions);
111529 ui.photoviewer.onMapResize(); // check if header or footer have overflowed
111531 ui.checkOverflow('.top-toolbar');
111532 ui.checkOverflow('.map-footer-bar'); // Use outdated code so it works on Explorer
111534 var resizeWindowEvent = document.createEvent('Event');
111535 resizeWindowEvent.initEvent('resizeWindow', true, true);
111536 document.dispatchEvent(resizeWindowEvent);
111537 }; // Call checkOverflow when resizing or whenever the contents change.
111540 ui.checkOverflow = function (selector, reset) {
111542 delete _needWidth[selector];
111545 var selection = context.container().select(selector);
111546 if (selection.empty()) return;
111547 var scrollWidth = selection.property('scrollWidth');
111548 var clientWidth = selection.property('clientWidth');
111549 var needed = _needWidth[selector] || scrollWidth;
111551 if (scrollWidth > clientWidth) {
111553 selection.classed('narrow', true);
111555 if (!_needWidth[selector]) {
111556 _needWidth[selector] = scrollWidth;
111558 } else if (scrollWidth >= needed) {
111559 selection.classed('narrow', false);
111563 ui.togglePanes = function (showPane) {
111564 var hidePanes = context.container().selectAll('.map-pane.shown');
111565 var side = _mainLocalizer.textDirection() === 'ltr' ? 'right' : 'left';
111566 hidePanes.classed('shown', false).classed('hide', true);
111567 context.container().selectAll('.map-pane-control button').classed('active', false);
111570 hidePanes.classed('shown', false).classed('hide', true).style(side, '-500px');
111571 context.container().selectAll('.' + showPane.attr('pane') + '-control button').classed('active', true);
111572 showPane.classed('shown', true).classed('hide', false);
111574 if (hidePanes.empty()) {
111575 showPane.style(side, '-500px').transition().duration(200).style(side, '0px');
111577 showPane.style(side, '0px');
111580 hidePanes.classed('shown', true).classed('hide', false).style(side, '0px').transition().duration(200).style(side, '-500px').on('end', function () {
111581 select(this).classed('shown', false).classed('hide', true);
111586 var _editMenu = uiEditMenu(context);
111588 ui.editMenu = function () {
111592 ui.showEditMenu = function (anchorPoint, triggerType, operations) {
111593 // remove any displayed menu
111595 if (!operations && context.mode().operations) operations = context.mode().operations();
111596 if (!operations || !operations.length) return; // disable menu if in wide selection, for example
111598 if (!context.map().editableDataEnabled()) return;
111599 var surfaceNode = context.surface().node();
111601 if (surfaceNode.focus) {
111602 // FF doesn't support it
111603 // focus the surface or else clicking off the menu may not trigger modeBrowse
111607 operations.forEach(function (operation) {
111608 if (operation.point) operation.point(anchorPoint);
111611 _editMenu.anchorLoc(anchorPoint).triggerType(triggerType).operations(operations); // render the menu
111614 context.map().supersurface.call(_editMenu);
111617 ui.closeEditMenu = function () {
111618 // remove any existing menu no matter how it was added
111619 context.map().supersurface.select('.edit-menu').remove();
111622 var _saveLoading = select(null);
111624 context.uploader().on('saveStarted.ui', function () {
111625 _saveLoading = uiLoading(context).message(_t.html('save.uploading')).blocking(true);
111626 context.container().call(_saveLoading); // block input during upload
111627 }).on('saveEnded.ui', function () {
111630 _saveLoading = select(null);
111635 function coreContext() {
111638 var dispatch = dispatch$8('enter', 'exit', 'change');
111639 var context = utilRebind({}, dispatch, 'on');
111641 var _deferred = new Set();
111643 context.version = '2.20.4';
111644 context.privacyVersion = '20201202'; // iD will alter the hash so cache the parameters intended to setup the session
111646 context.initialHashParams = window.location.hash ? utilStringQs(window.location.hash) : {};
111648 // An osmChangeset object. Not loaded until needed.
111650 context.changeset = null;
111651 var _defaultChangesetComment = context.initialHashParams.comment;
111652 var _defaultChangesetSource = context.initialHashParams.source;
111653 var _defaultChangesetHashtags = context.initialHashParams.hashtags;
111655 context.defaultChangesetComment = function (val) {
111656 if (!arguments.length) return _defaultChangesetComment;
111657 _defaultChangesetComment = val;
111661 context.defaultChangesetSource = function (val) {
111662 if (!arguments.length) return _defaultChangesetSource;
111663 _defaultChangesetSource = val;
111667 context.defaultChangesetHashtags = function (val) {
111668 if (!arguments.length) return _defaultChangesetHashtags;
111669 _defaultChangesetHashtags = val;
111674 /* (typically shown as the label for the browser window/tab) */
111675 // If true, iD will update the title based on what the user is doing
111678 var _setsDocumentTitle = true;
111680 context.setsDocumentTitle = function (val) {
111681 if (!arguments.length) return _setsDocumentTitle;
111682 _setsDocumentTitle = val;
111684 }; // The part of the title that is always the same
111687 var _documentTitleBase = document.title;
111689 context.documentTitleBase = function (val) {
111690 if (!arguments.length) return _documentTitleBase;
111691 _documentTitleBase = val;
111694 /* User interface and keybinding */
111699 context.ui = function () {
111703 context.lastPointerType = function () {
111704 return _ui.lastPointerType();
111707 var _keybinding = utilKeybinding('context');
111709 context.keybinding = function () {
111713 select(document).call(_keybinding);
111714 /* Straight accessors. Avoid using these if you can. */
111715 // Instantiate the connection here because it doesn't require passing in
111716 // `context` and it's needed for pre-init calls like `preauth`
111718 var _connection = services.osm;
111726 context.connection = function () {
111730 context.history = function () {
111734 context.validator = function () {
111738 context.uploader = function () {
111744 context.preauth = function (options) {
111746 _connection["switch"](options);
111751 /* connection options for source switcher (optional) */
111756 context.apiConnections = function (val) {
111757 if (!arguments.length) return _apiConnections;
111760 }; // A string or array or locale codes to prefer over the browser's settings
111763 context.locale = function (locale) {
111764 if (!arguments.length) return _mainLocalizer.localeCode();
111765 _mainLocalizer.preferredLocaleCodes(locale);
111769 function afterLoad(cid, callback) {
111770 return function (err, result) {
111772 // 400 Bad Request, 401 Unauthorized, 403 Forbidden..
111773 if (err.status === 400 || err.status === 401 || err.status === 403) {
111779 if (typeof callback === 'function') {
111784 } else if (_connection && _connection.getConnectionId() !== cid) {
111785 if (typeof callback === 'function') {
111787 message: 'Connection Switched',
111794 _history.merge(result.data, result.extent);
111796 if (typeof callback === 'function') {
111805 context.loadTiles = function (projection, callback) {
111806 var handle = window.requestIdleCallback(function () {
111807 _deferred["delete"](handle);
111809 if (_connection && context.editableDataEnabled()) {
111810 var cid = _connection.getConnectionId();
111812 _connection.loadTiles(projection, afterLoad(cid, callback));
111819 context.loadTileAtLoc = function (loc, callback) {
111820 var handle = window.requestIdleCallback(function () {
111821 _deferred["delete"](handle);
111823 if (_connection && context.editableDataEnabled()) {
111824 var cid = _connection.getConnectionId();
111826 _connection.loadTileAtLoc(loc, afterLoad(cid, callback));
111831 }; // Download the full entity and its parent relations. The callback may be called multiple times.
111834 context.loadEntity = function (entityID, callback) {
111836 var cid = _connection.getConnectionId();
111838 _connection.loadEntity(entityID, afterLoad(cid, callback)); // We need to fetch the parent relations separately.
111841 _connection.loadEntityRelations(entityID, afterLoad(cid, callback));
111845 context.zoomToEntity = function (entityID, zoomTo) {
111846 // be sure to load the entity even if we're not going to zoom to it
111847 context.loadEntity(entityID, function (err, result) {
111850 if (zoomTo !== false) {
111851 var entity = result.data.find(function (e) {
111852 return e.id === entityID;
111861 _map.on('drawn.zoomToEntity', function () {
111862 if (!context.hasEntity(entityID)) return;
111864 _map.on('drawn.zoomToEntity', null);
111866 context.on('enter.zoomToEntity', null);
111867 context.enter(modeSelect(context, [entityID]));
111870 context.on('enter.zoomToEntity', function () {
111871 if (_mode.id !== 'browse') {
111872 _map.on('drawn.zoomToEntity', null);
111874 context.on('enter.zoomToEntity', null);
111879 var _minEditableZoom = 16;
111881 context.minEditableZoom = function (val) {
111882 if (!arguments.length) return _minEditableZoom;
111883 _minEditableZoom = val;
111886 _connection.tileZoom(val);
111890 }; // String length limits in Unicode characters, not JavaScript UTF-16 code units
111893 context.maxCharsForTagKey = function () {
111897 context.maxCharsForTagValue = function () {
111901 context.maxCharsForRelationRole = function () {
111905 function cleanOsmString(val, maxChars) {
111906 // be lenient with input
111907 if (val === undefined || val === null) {
111914 val = val.trim(); // use the canonical form of the string
111916 if (val.normalize) val = val.normalize('NFC'); // trim to the number of allowed characters
111918 return utilUnicodeCharsTruncated(val, maxChars);
111921 context.cleanTagKey = function (val) {
111922 return cleanOsmString(val, context.maxCharsForTagKey());
111925 context.cleanTagValue = function (val) {
111926 return cleanOsmString(val, context.maxCharsForTagValue());
111929 context.cleanRelationRole = function (val) {
111930 return cleanOsmString(val, context.maxCharsForRelationRole());
111937 context.inIntro = function (val) {
111938 if (!arguments.length) return _inIntro;
111941 }; // Immediately save the user's history to localstorage, if possible
111942 // This is called someteimes, but also on the `window.onbeforeunload` handler
111945 context.save = function () {
111946 // no history save, no message onbeforeunload
111947 if (_inIntro || context.container().select('.modal').size()) return;
111950 if (_mode && _mode.id === 'save') {
111951 canSave = false; // Attempt to prevent user from creating duplicate changes - see #5200
111953 if (services.osm && services.osm.isChangesetInflight()) {
111959 canSave = context.selectedIDs().every(function (id) {
111960 var entity = context.hasEntity(id);
111961 return entity && !entity.isDegenerate();
111969 if (_history.hasChanges()) {
111970 return _t('save.unsaved_changes');
111972 }; // Debounce save, since it's a synchronous localStorage write,
111973 // and history changes can happen frequently (e.g. when dragging).
111976 context.debouncedSave = debounce(context.save, 350);
111978 function withDebouncedSave(fn) {
111980 var result = fn.apply(_history, arguments);
111981 context.debouncedSave();
111988 context.hasEntity = function (id) {
111989 return _history.graph().hasEntity(id);
111992 context.entity = function (id) {
111993 return _history.graph().entity(id);
112000 context.mode = function () {
112004 context.enter = function (newMode) {
112008 dispatch.call('exit', _this, _mode);
112015 dispatch.call('enter', _this, _mode);
112018 context.selectedIDs = function () {
112019 return _mode && _mode.selectedIDs && _mode.selectedIDs() || [];
112022 context.activeID = function () {
112023 return _mode && _mode.activeID && _mode.activeID();
112028 context.selectedNoteID = function (noteID) {
112029 if (!arguments.length) return _selectedNoteID;
112030 _selectedNoteID = noteID;
112032 }; // NOTE: Don't change the name of this until UI v3 is merged
112037 context.selectedErrorID = function (errorID) {
112038 if (!arguments.length) return _selectedErrorID;
112039 _selectedErrorID = errorID;
112045 context.install = function (behavior) {
112046 return context.surface().call(behavior);
112049 context.uninstall = function (behavior) {
112050 return context.surface().call(behavior.off);
112057 context.copyGraph = function () {
112063 context.copyIDs = function (val) {
112064 if (!arguments.length) return _copyIDs;
112066 _copyGraph = _history.graph();
112072 context.copyLonLat = function (val) {
112073 if (!arguments.length) return _copyLonLat;
112082 context.background = function () {
112090 context.features = function () {
112094 context.hasHiddenConnections = function (id) {
112095 var graph = _history.graph();
112097 var entity = graph.entity(id);
112098 return _features.hasHiddenConnections(entity, graph);
112105 context.photos = function () {
112113 context.map = function () {
112117 context.layers = function () {
112121 context.surface = function () {
112125 context.editableDataEnabled = function () {
112126 return _map.editableDataEnabled();
112129 context.surfaceRect = function () {
112130 return _map.surface.node().getBoundingClientRect();
112133 context.editable = function () {
112134 // don't allow editing during save
112135 var mode = context.mode();
112136 if (!mode || mode.id === 'save') return false;
112137 return _map.editableDataEnabled();
112146 // label collision bounding boxes
112148 // imagery bounding polygons
112151 downloaded: false // downloaded data from osm
112155 context.debugFlags = function () {
112159 context.getDebug = function (flag) {
112160 return flag && _debugFlags[flag];
112163 context.setDebug = function (flag, val) {
112164 if (arguments.length === 1) val = true;
112165 _debugFlags[flag] = val;
112166 dispatch.call('change');
112172 var _container = select(null);
112174 context.container = function (val) {
112175 if (!arguments.length) return _container;
112178 _container.classed('ideditor', true);
112183 context.containerNode = function (val) {
112184 if (!arguments.length) return context.container().node();
112185 context.container(select(val));
112191 context.embed = function (val) {
112192 if (!arguments.length) return _embed;
112201 context.assetPath = function (val) {
112202 if (!arguments.length) return _assetPath;
112204 _mainFileFetcher.assetPath(val);
112210 context.assetMap = function (val) {
112211 if (!arguments.length) return _assetMap;
112213 _mainFileFetcher.assetMap(val);
112217 context.asset = function (val) {
112218 if (/^http(s)?:\/\//i.test(val)) return val;
112219 var filename = _assetPath + val;
112220 return _assetMap[filename] || filename;
112223 context.imagePath = function (val) {
112224 return context.asset("img/".concat(val));
112226 /* reset (aka flush) */
112229 context.reset = context.flush = function () {
112230 context.debouncedSave.cancel();
112231 Array.from(_deferred).forEach(function (handle) {
112232 window.cancelIdleCallback(handle);
112234 _deferred["delete"](handle);
112236 Object.values(services).forEach(function (service) {
112237 if (service && typeof service.reset === 'function') {
112238 service.reset(context);
112241 context.changeset = null;
112249 _uploader.reset(); // don't leave stale state in the inspector
112252 context.container().select('.inspector-wrap *').remove();
112258 context.projection = geoRawMercator();
112259 context.curtainProjection = geoRawMercator();
112262 context.init = function () {
112264 initializeDependents();
112265 return context; // Load variables and properties. No property of `context` should be accessed
112266 // until this is complete since load statuses are indeterminate. The order
112267 // of instantiation shouldn't matter.
112269 function instantiateInternal() {
112270 _history = coreHistory(context);
112271 context.graph = _history.graph;
112272 context.pauseChangeDispatch = _history.pauseChangeDispatch;
112273 context.resumeChangeDispatch = _history.resumeChangeDispatch;
112274 context.perform = withDebouncedSave(_history.perform);
112275 context.replace = withDebouncedSave(_history.replace);
112276 context.pop = withDebouncedSave(_history.pop);
112277 context.overwrite = withDebouncedSave(_history.overwrite);
112278 context.undo = withDebouncedSave(_history.undo);
112279 context.redo = withDebouncedSave(_history.redo);
112280 _validator = coreValidator(context);
112281 _uploader = coreUploader(context);
112282 _background = rendererBackground(context);
112283 _features = rendererFeatures(context);
112284 _map = rendererMap(context);
112285 _photos = rendererPhotos(context);
112287 } // Set up objects that might need to access properties of `context`. The order
112288 // might matter if dependents make calls to each other. Be wary of async calls.
112291 function initializeDependents() {
112292 if (context.initialHashParams.presets) {
112293 _mainPresetIndex.addablePresetIDs(new Set(context.initialHashParams.presets.split(',')));
112296 if (context.initialHashParams.locale) {
112297 _mainLocalizer.preferredLocaleCodes(context.initialHashParams.locale);
112298 } // kick off some async work
112301 _mainLocalizer.ensureLoaded();
112303 _background.ensureLoaded();
112305 _mainPresetIndex.ensureLoaded();
112306 Object.values(services).forEach(function (service) {
112307 if (service && typeof service.init === 'function') {
112318 if (services.maprules && context.initialHashParams.maprules) {
112319 d3_json(context.initialHashParams.maprules).then(function (mapcss) {
112320 services.maprules.init();
112321 mapcss.forEach(function (mapcssSelector) {
112322 return services.maprules.addRule(mapcssSelector);
112324 })["catch"](function () {
112327 } // if the container isn't available, e.g. when testing, don't load the UI
112330 if (!context.container().empty()) {
112331 _ui.ensureLoaded().then(function () {
112341 // NSI contains the most correct tagging for many commonly mapped features.
112342 // See https://github.com/osmlab/name-suggestion-index and https://nsi.guide
112345 var _nsiStatus = 'loading'; // 'loading', 'ok', 'failed'
112347 var _nsi = {}; // Sometimes we can upgrade a feature tagged like `building=yes` to a better tag.
112350 'building/commercial': true,
112351 'building/government': true,
112352 'building/hotel': true,
112353 'building/retail': true,
112354 'building/office': true,
112355 'building/supermarket': true,
112357 }; // Exceptions to the namelike regexes.
112358 // Usually a tag suffix contains a language code like `name:en`, `name:ru`
112359 // but we want to exclude things like `operator:type`, `name:etymology`, etc..
112361 var notNames = /:(colou?r|type|forward|backward|left|right|etymology|pronunciation|wikipedia)$/i; // Exceptions to the branchlike regexes
112363 var notBranches = /(coop|express|wireless|factory|outlet)/i; // PRIVATE FUNCTIONS
112365 // Adds the sources to iD's filemap so we can start downloading data.
112368 function setNsiSources() {
112369 var nsiVersion = packageJSON.devDependencies['name-suggestion-index'];
112370 var v = parseVersion(nsiVersion);
112371 var vMinor = "".concat(v.major, ".").concat(v.minor);
112373 'nsi_data': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/nsi.min.json"),
112374 'nsi_dissolved': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/dissolved.min.json"),
112375 'nsi_features': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/featureCollection.min.json"),
112376 'nsi_generics': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/genericWords.min.json"),
112377 'nsi_presets': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/presets/nsi-id-presets.min.json"),
112378 'nsi_replacements': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/replacements.min.json"),
112379 'nsi_trees': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/trees.min.json")
112381 var fileMap = _mainFileFetcher.fileMap();
112383 for (var k in sources) {
112384 if (!fileMap[k]) fileMap[k] = sources[k];
112386 } // `loadNsiPresets()`
112387 // Returns a Promise fulfilled when the presets have been downloaded and merged into iD.
112391 function loadNsiPresets() {
112392 return Promise.all([_mainFileFetcher.get('nsi_presets'), _mainFileFetcher.get('nsi_features')]).then(function (vals) {
112393 // Add `suggestion=true` to all the nsi presets
112394 // The preset json schema doesn't include it, but the iD code still uses it
112395 Object.values(vals[0].presets).forEach(function (preset) {
112396 return preset.suggestion = true;
112398 _mainPresetIndex.merge({
112399 presets: vals[0].presets,
112400 featureCollection: vals[1]
112404 // Returns a Promise fulfilled when the other data have been downloaded and processed
112408 function loadNsiData() {
112409 return Promise.all([_mainFileFetcher.get('nsi_data'), _mainFileFetcher.get('nsi_dissolved'), _mainFileFetcher.get('nsi_replacements'), _mainFileFetcher.get('nsi_trees')]).then(function (vals) {
112412 // the raw name-suggestion-index data
112413 dissolved: vals[1].dissolved,
112414 // list of dissolved items
112415 replacements: vals[2].replacements,
112416 // trivial old->new qid replacements
112418 // metadata about trees, main tags
112420 // Map (k -> Map (v -> t) )
112422 // Map (wd/wp tag values -> qids)
112423 ids: new Map() // Map (id -> NSI item)
112426 _nsi.matcher = new Matcher();
112428 _nsi.matcher.buildMatchIndex(_nsi.data);
112430 _nsi.matcher.buildLocationIndex(_nsi.data, _mainLocations.loco());
112432 Object.keys(_nsi.data).forEach(function (tkv) {
112433 var category = _nsi.data[tkv];
112434 var parts = tkv.split('/', 3); // tkv = "tree/key/value"
112438 var v = parts[2]; // Build a reverse index of keys -> values -> trees present in the name-suggestion-index
112439 // Collect primary keys (e.g. "amenity", "craft", "shop", "man_made", "route", etc)
112441 // "restaurant": "brands"
112444 var vmap = _nsi.kvt.get(k);
112453 var tree = _nsi.trees[t]; // e.g. "brands", "operators"
112455 var mainTag = tree.mainTag; // e.g. "brand:wikidata", "operator:wikidata", etc
112457 var items = category.items || [];
112458 items.forEach(function (item) {
112459 // Remember some useful things for later, cache NSI id -> item
112461 item.mainTag = mainTag;
112463 _nsi.ids.set(item.id, item); // Cache Wikidata/Wikipedia values -> qid, for #6416
112466 var wd = item.tags[mainTag];
112467 var wp = item.tags[mainTag.replace('wikidata', 'wikipedia')];
112468 if (wd) _nsi.qids.set(wd, wd);
112469 if (wp && wd) _nsi.qids.set(wp, wd);
112474 // Gather all the k/v pairs that we will run through the NSI matcher.
112475 // An OSM tags object can contain anything, but only a few tags will be interesting to NSI.
112477 // This function will return the interesting tag pairs like:
112478 // "amenity/restaurant", "man_made/flagpole"
112481 // excluding things like
112482 // "tiger:reviewed", "surface", "ref", etc.
112485 // `tags`: `Object` containing the feature's OSM tags
112487 // `Object` containing kv pairs to test:
112495 function gatherKVs(tags) {
112496 var primary = new Set();
112497 var alternate = new Set();
112498 Object.keys(tags).forEach(function (osmkey) {
112499 var osmvalue = tags[osmkey];
112500 if (!osmvalue) return; // Match a 'route_master' as if it were a 'route' - name-suggestion-index#5184
112502 if (osmkey === 'route_master') osmkey = 'route';
112504 var vmap = _nsi.kvt.get(osmkey);
112506 if (!vmap) return; // not an interesting key
112508 if (vmap.get(osmvalue)) {
112509 // Matched a category in NSI
112510 primary.add("".concat(osmkey, "/").concat(osmvalue)); // interesting key/value
112511 } else if (osmvalue === 'yes') {
112512 alternate.add("".concat(osmkey, "/").concat(osmvalue)); // fallback key/yes
112514 }); // Can we try a generic building fallback match? - See #6122, #7197
112515 // Only try this if we do a preset match and find nothing else remarkable about that building.
112516 // For example, a way with `building=yes` + `name=Westfield` may be a Westfield department store.
112517 // But a way with `building=yes` + `name=Westfield` + `public_transport=station` is a train station for a town named "Westfield"
112519 var preset = _mainPresetIndex.matchTags(tags, 'area');
112521 if (buildingPreset[preset.id]) {
112522 alternate.add('building/yes');
112530 // NSI has a concept of trees: "brands", "operators", "flags", "transit".
112531 // The tree determines things like which tags are namelike, and which tags hold important wikidata.
112532 // This takes an Object of tags and tries to identify what tree to use.
112535 // `tags`: `Object` containing the feature's OSM tags
112537 // `string` the name of the tree if known
112538 // or 'unknown' if it could match several trees (e.g. amenity/yes)
112543 function identifyTree(tags) {
112545 var t; // Check all tags
112547 Object.keys(tags).forEach(function (osmkey) {
112548 if (t) return; // found already
112550 var osmvalue = tags[osmkey];
112551 if (!osmvalue) return; // Match a 'route_master' as if it were a 'route' - name-suggestion-index#5184
112553 if (osmkey === 'route_master') osmkey = 'route';
112555 var vmap = _nsi.kvt.get(osmkey);
112557 if (!vmap) return; // this key is not in nsi
112559 if (osmvalue === 'yes') {
112562 t = vmap.get(osmvalue);
112565 return t || unknown || null;
112567 // Gather all the namelike values that we will run through the NSI matcher.
112568 // It will gather values primarily from tags `name`, `name:ru`, `flag:name`
112569 // and fallback to alternate tags like `brand`, `brand:ru`, `alt_name`
112572 // `tags`: `Object` containing the feature's OSM tags
112574 // `Object` containing namelike values to test:
112582 function gatherNames(tags) {
112587 var primary = new Set();
112588 var alternate = new Set();
112590 var testNameFragments = false;
112591 var patterns; // Patterns for matching OSM keys that might contain namelike values.
112592 // These roughly correspond to the "trees" concept in name-suggestion-index,
112594 var t = identifyTree(tags);
112600 alternate: /^(operator|operator:\w+|network:\w+|\w+_name|\w+_name:\w+)$/i
112602 } else if (t === 'flags') {
112604 primary: /^(flag:name|flag:name:\w+)$/i,
112605 alternate: /^(flag|flag:\w+|subject|subject:\w+)$/i // note: no `country`, we special-case it below
112608 } else if (t === 'brands') {
112609 testNameFragments = true;
112611 primary: /^(name|name:\w+)$/i,
112612 alternate: /^(brand|brand:\w+|operator|operator:\w+|\w+_name|\w+_name:\w+)/i
112614 } else if (t === 'operators') {
112615 testNameFragments = true;
112617 primary: /^(name|name:\w+|operator|operator:\w+)$/i,
112618 alternate: /^(brand|brand:\w+|\w+_name|\w+_name:\w+)/i
112622 testNameFragments = true;
112624 primary: /^(name|name:\w+)$/i,
112625 alternate: /^(brand|brand:\w+|network|network:\w+|operator|operator:\w+|\w+_name|\w+_name:\w+)/i
112627 } // Test `name` fragments, longest to shortest, to fit them into a "Name Branch" pattern.
112628 // e.g. "TUI ReiseCenter - Neuss Innenstadt" -> ["TUI", "ReiseCenter", "Neuss", "Innenstadt"]
112631 if (tags.name && testNameFragments) {
112632 var nameParts = tags.name.split(/[\s\-\/,.]/);
112634 for (var split = nameParts.length; split > 0; split--) {
112635 var name = nameParts.slice(0, split).join(' '); // e.g. "TUI ReiseCenter"
112642 Object.keys(tags).forEach(function (osmkey) {
112643 var osmvalue = tags[osmkey];
112646 if (isNamelike(osmkey, 'primary')) {
112647 if (/;/.test(osmvalue)) {
112651 alternate["delete"](osmvalue);
112653 } else if (!primary.has(osmvalue) && isNamelike(osmkey, 'alternate')) {
112654 if (/;/.test(osmvalue)) {
112657 alternate.add(osmvalue);
112660 }); // For flags only, fallback to `country` tag only if no other namelike values were found.
112661 // See https://github.com/openstreetmap/iD/pull/8305#issuecomment-769174070
112663 if (tags.man_made === 'flagpole' && !primary.size && !alternate.size && !!tags.country) {
112664 var osmvalue = tags.country;
112666 if (/;/.test(osmvalue)) {
112669 alternate.add(osmvalue);
112671 } // If any namelike value contained a semicolon, return empty set and don't try matching anything.
112683 function isNamelike(osmkey, which) {
112684 if (osmkey === 'old_name') return false;
112685 return patterns[which].test(osmkey) && !notNames.test(osmkey);
112688 // Generate all combinations of [key,value,name] that we want to test.
112689 // This prioritizes them so that the primary name and k/v pairs go first
112692 // `tryKVs`: `Object` containing primary and alternate k/v pairs to test
112693 // `tryNames`: `Object` containing primary and alternate names to test
112695 // `Array`: tuple objects ordered by priority
112699 function gatherTuples(tryKVs, tryNames) {
112701 ['primary', 'alternate'].forEach(function (whichName) {
112702 // test names longest to shortest
112703 var arr = Array.from(tryNames[whichName]).sort(function (a, b) {
112704 return b.length - a.length;
112706 arr.forEach(function (n) {
112707 ['primary', 'alternate'].forEach(function (whichKV) {
112708 tryKVs[whichKV].forEach(function (kv) {
112709 var parts = kv.split('/', 2);
112723 // Try to match a feature to a canonical record in name-suggestion-index
112724 // and upgrade the tags to match.
112727 // `tags`: `Object` containing the feature's OSM tags
112728 // `loc`: Location where this feature exists, as a [lon, lat]
112730 // `Object` containing the result, or `null` if no changes needed:
112732 // 'newTags': `Object` - The tags the the feature should have
112733 // 'matched': `Object` - The matched item
112738 function _upgradeTags(tags, loc) {
112739 var newTags = Object.assign({}, tags); // shallow copy
112741 var changed = false; // Before anything, perform trivial Wikipedia/Wikidata replacements
112743 Object.keys(newTags).forEach(function (osmkey) {
112744 var matchTag = osmkey.match(/^(\w+:)?wikidata$/);
112747 // Look at '*:wikidata' tags
112748 var prefix = matchTag[1] || '';
112749 var wd = newTags[osmkey];
112750 var replace = _nsi.replacements[wd]; // If it matches a QID in the replacement list...
112752 if (replace && replace.wikidata !== undefined) {
112753 // replace or delete `*:wikidata` tag
112756 if (replace.wikidata) {
112757 newTags[osmkey] = replace.wikidata;
112759 delete newTags[osmkey];
112763 if (replace && replace.wikipedia !== undefined) {
112764 // replace or delete `*:wikipedia` tag
112766 var wpkey = "".concat(prefix, "wikipedia");
112768 if (replace.wikipedia) {
112769 newTags[wpkey] = replace.wikipedia;
112775 }); // Match a 'route_master' as if it were a 'route' - name-suggestion-index#5184
112777 var isRouteMaster = tags.type === 'route_master'; // Gather key/value tag pairs to try to match
112779 var tryKVs = gatherKVs(tags);
112781 if (!tryKVs.primary.size && !tryKVs.alternate.size) {
112786 } // Gather namelike tag values to try to match
112789 var tryNames = gatherNames(tags); // Do `wikidata=*` or `wikipedia=*` tags identify this entity as a chain? - See #6416
112790 // If so, these tags can be swapped to e.g. `brand:wikidata`/`brand:wikipedia`.
112792 var foundQID = _nsi.qids.get(tags.wikidata) || _nsi.qids.get(tags.wikipedia);
112794 if (foundQID) tryNames.primary.add(foundQID); // matcher will recognize the Wikidata QID as name too
112796 if (!tryNames.primary.size && !tryNames.alternate.size) {
112801 } // Order the [key,value,name] tuples - test primary names before alternate names
112804 var tuples = gatherTuples(tryKVs, tryNames);
112805 var foundPrimary = false;
112806 var bestItem; // Test [key,value,name] tuples against the NSI matcher until we get a primary match or exhaust all options.
112808 for (var i = 0; i < tuples.length && !foundPrimary; i++) {
112811 var hits = _nsi.matcher.match(tuple.k, tuple.v, tuple.n, loc); // Attempt to match an item in NSI
112814 if (!hits || !hits.length) continue; // no match, try next tuple
112816 if (hits[0].match !== 'primary' && hits[0].match !== 'alternate') break; // a generic match, stop looking
112817 // A match may contain multiple results, the first one is likely the best one for this location
112818 // e.g. `['pfk-a54c14', 'kfc-1ff19c', 'kfc-658eea']`
112820 for (var j = 0; j < hits.length; j++) {
112822 var isPrimary = hits[j].match === 'primary';
112823 var itemID = hit.itemID;
112824 if (_nsi.dissolved[itemID]) continue; // Don't upgrade to a dissolved item
112826 var item = _nsi.ids.get(itemID);
112829 var mainTag = item.mainTag; // e.g. `brand:wikidata`
112831 var itemQID = item.tags[mainTag]; // e.g. `brand:wikidata` qid
112833 var notQID = newTags["not:".concat(mainTag)]; // e.g. `not:brand:wikidata` qid
112835 if ( // Exceptions, skip this hit
112836 !itemQID || itemQID === notQID || // No `*:wikidata` or matched a `not:*:wikidata`
112837 newTags.office && !item.tags.office // feature may be a corporate office for a brand? - #6416
112839 continue; // continue looking
112840 } // If we get here, the hit is good..
112843 if (!bestItem || isPrimary) {
112850 break; // can ignore the rest of the hits from this match
112853 } // At this point we have matched a canonical item and can suggest tag upgrades..
112857 var _ret = function () {
112858 var itemID = bestItem.id;
112859 var item = JSON.parse(JSON.stringify(bestItem)); // deep copy
112862 var parts = tkv.split('/', 3); // tkv = "tree/key/value"
112866 var category = _nsi.data[tkv];
112867 var properties = category.properties || {}; // Preserve some tags that we specifically don't want NSI to overwrite. ('^name', sometimes)
112869 var preserveTags = item.preserveTags || properties.preserveTags || []; // These tags can be toplevel tags -or- attributes - so we generally want to preserve existing values - #8615
112870 // We'll only _replace_ the tag value if this tag is the toplevel/defining tag for the matched item (`k`)
112872 ['building', 'emergency', 'internet_access', 'takeaway'].forEach(function (osmkey) {
112873 if (k !== osmkey) preserveTags.push("^".concat(osmkey, "$"));
112875 var regexes = preserveTags.map(function (s) {
112876 return new RegExp(s, 'i');
112879 Object.keys(newTags).forEach(function (osmkey) {
112880 if (regexes.some(function (regex) {
112881 return regex.test(osmkey);
112883 keepTags[osmkey] = newTags[osmkey];
112885 }); // Remove any primary tags ("amenity", "craft", "shop", "man_made", "route", etc) that have a
112886 // value like `amenity=yes` or `shop=yes` (exceptions have already been added to `keepTags` above)
112888 _nsi.kvt.forEach(function (vmap, k) {
112889 if (newTags[k] === 'yes') delete newTags[k];
112890 }); // Replace mistagged `wikidata`/`wikipedia` with e.g. `brand:wikidata`/`brand:wikipedia`
112894 delete newTags.wikipedia;
112895 delete newTags.wikidata;
112896 } // Do the tag upgrade
112899 Object.assign(newTags, item.tags, keepTags); // Swap `route` back to `route_master` - name-suggestion-index#5184
112902 newTags.route_master = newTags.route;
112904 } // Special `branch` splitting rules - IF..
112905 // - NSI is suggesting to replace `name`, AND
112906 // - `branch` doesn't already contain something, AND
112907 // - original name has not moved to an alternate name (e.g. "Dunkin' Donuts" -> "Dunkin'"), AND
112908 // - original name is "some name" + "some stuff", THEN
112909 // consider splitting `name` into `name`/`branch`..
112912 var origName = tags.name;
112913 var newName = newTags.name;
112915 if (newName && origName && newName !== origName && !newTags.branch) {
112916 var newNames = gatherNames(newTags);
112917 var newSet = new Set([].concat(_toConsumableArray(newNames.primary), _toConsumableArray(newNames.alternate)));
112918 var isMoved = newSet.has(origName); // another tag holds the original name now
112921 // Test name fragments, longest to shortest, to fit them into a "Name Branch" pattern.
112922 // e.g. "TUI ReiseCenter - Neuss Innenstadt" -> ["TUI", "ReiseCenter", "Neuss", "Innenstadt"]
112923 var nameParts = origName.split(/[\s\-\/,.]/);
112925 for (var split = nameParts.length; split > 0; split--) {
112926 var name = nameParts.slice(0, split).join(' '); // e.g. "TUI ReiseCenter"
112928 var branch = nameParts.slice(split).join(' '); // e.g. "Neuss Innenstadt"
112930 var nameHits = _nsi.matcher.match(k, v, name, loc);
112932 if (!nameHits || !nameHits.length) continue; // no match, try next name fragment
112934 if (nameHits.some(function (hit) {
112935 return hit.itemID === itemID;
112937 // matched the name fragment to the same itemID above
112939 if (notBranches.test(branch)) {
112940 // "branch" was detected but is noise ("factory outlet", etc)
112941 newTags.name = origName; // Leave `name` alone, this part of the name may be significant..
112943 var branchHits = _nsi.matcher.match(k, v, branch, loc);
112945 if (branchHits && branchHits.length) {
112946 // if "branch" matched something else in NSI..
112947 if (branchHits[0].match === 'primary' || branchHits[0].match === 'alternate') {
112948 // if another brand! (e.g. "KFC - Taco Bell"?)
112951 }; // bail out - can't suggest tags in this case
112952 } // else a generic (e.g. "gas", "cafe") - ignore
112955 // "branch" is not noise and not something in NSI
112956 newTags.branch = branch; // Stick it in the `branch` tag..
112975 if (_typeof(_ret) === "object") return _ret.v;
112982 } // `_isGenericName()`
112983 // Is the `name` tag generic?
112986 // `tags`: `Object` containing the feature's OSM tags
112988 // `true` if it is generic, `false` if not
112992 function _isGenericName(tags) {
112994 if (!n) return false; // tryNames just contains the `name` tag value and nothing else
112999 }; // Gather key/value tag pairs to try to match
113001 var tryKVs = gatherKVs(tags);
113002 if (!tryKVs.primary.size && !tryKVs.alternate.size) return false; // Order the [key,value,name] tuples - test primary before alternate
113004 var tuples = gatherTuples(tryKVs, tryNames);
113006 for (var i = 0; i < tuples.length; i++) {
113009 var hits = _nsi.matcher.match(tuple.k, tuple.v, tuple.n); // Attempt to match an item in NSI
113010 // If we get a `excludeGeneric` hit, this is a generic name.
113013 if (hits && hits.length && hits[0].match === 'excludeGeneric') return true;
113022 // On init, start preparing the name-suggestion-index
113024 init: function init() {
113025 // Note: service.init is called immediately after the presetManager has started loading its data.
113026 // We expect to chain onto an unfulfilled promise here.
113028 _mainPresetIndex.ensureLoaded().then(function () {
113029 return loadNsiPresets();
113032 }) // wait briefly for locationSets to enter the locationManager queue
113034 return _mainLocations.mergeLocationSets([]);
113035 }) // wait for locationSets to resolve
113039 return _nsiStatus = 'ok';
113040 })["catch"](function () {
113041 return _nsiStatus = 'failed';
113045 return new Promise(function (resolve) {
113046 window.setTimeout(resolve, msec);
113051 // Reset is called when user saves data to OSM (does nothing here)
113053 reset: function reset() {},
113055 // To let other code know how it's going...
113058 // `String`: 'loading', 'ok', 'failed'
113060 status: function status() {
113064 // Is the `name` tag generic?
113067 // `tags`: `Object` containing the feature's OSM tags
113069 // `true` if it is generic, `false` if not
113071 isGenericName: function isGenericName(tags) {
113072 return _isGenericName(tags);
113075 // Suggest tag upgrades.
113076 // This function will not modify the input tags, it makes a copy.
113079 // `tags`: `Object` containing the feature's OSM tags
113080 // `loc`: Location where this feature exists, as a [lon, lat]
113082 // `Object` containing the result, or `null` if no changes needed:
113084 // 'newTags': `Object` - The tags the the feature should have
113085 // 'matched': `Object` - The matched item
113088 upgradeTags: function upgradeTags(tags, loc) {
113089 return _upgradeTags(tags, loc);
113092 // Direct access to the NSI cache, useful for testing or breaking things
113095 // `Object`: the internal NSI cache
113097 cache: function cache() {
113102 var apibase$1 = 'https://kartaview.org';
113103 var maxResults$1 = 1000;
113105 var tiler$3 = utilTiler().zoomExtent([tileZoom$1, tileZoom$1]).skipNullIsland(true);
113106 var dispatch$3 = dispatch$8('loadedImages');
113107 var imgZoom = d3_zoom().extent([[0, 0], [320, 240]]).translateExtent([[0, 0], [320, 240]]).scaleExtent([1, 15]);
113113 var _loadViewerPromise$1;
113115 function abortRequest$3(controller) {
113119 function maxPageAtZoom(z) {
113121 if (z === 15) return 5;
113122 if (z === 16) return 10;
113123 if (z === 17) return 20;
113124 if (z === 18) return 40;
113128 function loadTiles$1(which, url, projection) {
113129 var currZoom = Math.floor(geoScaleToZoom(projection.scale()));
113130 var tiles = tiler$3.getTiles(projection); // abort inflight requests that are no longer needed
113132 var cache = _oscCache[which];
113133 Object.keys(cache.inflight).forEach(function (k) {
113134 var wanted = tiles.find(function (tile) {
113135 return k.indexOf(tile.id + ',') === 0;
113139 abortRequest$3(cache.inflight[k]);
113140 delete cache.inflight[k];
113143 tiles.forEach(function (tile) {
113144 loadNextTilePage$1(which, currZoom, url, tile);
113148 function loadNextTilePage$1(which, currZoom, url, tile) {
113149 var cache = _oscCache[which];
113150 var bbox = tile.extent.bbox();
113151 var maxPages = maxPageAtZoom(currZoom);
113152 var nextPage = cache.nextPage[tile.id] || 1;
113153 var params = utilQsString({
113156 // client_id: clientId,
113157 bbTopLeft: [bbox.maxY, bbox.minX].join(','),
113158 bbBottomRight: [bbox.minY, bbox.maxX].join(',')
113160 if (nextPage > maxPages) return;
113161 var id = tile.id + ',' + String(nextPage);
113162 if (cache.loaded[id] || cache.inflight[id]) return;
113163 var controller = new AbortController();
113164 cache.inflight[id] = controller;
113167 signal: controller.signal,
113170 'Content-Type': 'application/x-www-form-urlencoded'
113173 d3_json(url, options).then(function (data) {
113174 cache.loaded[id] = true;
113175 delete cache.inflight[id];
113177 if (!data || !data.currentPageItems || !data.currentPageItems.length) {
113178 throw new Error('No Data');
113181 var features = data.currentPageItems.map(function (item) {
113182 var loc = [+item.lng, +item.lat];
113185 if (which === 'images') {
113190 captured_at: item.shot_date || item.date_added,
113191 captured_by: item.username,
113192 imagePath: item.lth_name,
113193 sequence_id: item.sequence_id,
113194 sequence_index: +item.sequence_index
113195 }; // cache sequence info
113197 var seq = _oscCache.sequences[d.sequence_id];
113204 _oscCache.sequences[d.sequence_id] = seq;
113207 seq.images[d.sequence_index] = d;
113208 _oscCache.images.forImageKey[d.key] = d; // cache imageKey -> image
113219 cache.rtree.load(features);
113221 if (data.currentPageItems.length === maxResults$1) {
113223 cache.nextPage[tile.id] = nextPage + 1;
113224 loadNextTilePage$1(which, currZoom, url, tile);
113226 cache.nextPage[tile.id] = Infinity; // no more pages to load
113229 if (which === 'images') {
113230 dispatch$3.call('loadedImages');
113232 })["catch"](function () {
113233 cache.loaded[id] = true;
113234 delete cache.inflight[id];
113236 } // partition viewport into higher zoom tiles
113239 function partitionViewport$1(projection) {
113240 var z = geoScaleToZoom(projection.scale());
113241 var z2 = Math.ceil(z * 2) / 2 + 2.5; // round to next 0.5 and add 2.5
113243 var tiler = utilTiler().zoomExtent([z2, z2]);
113244 return tiler.getTiles(projection).map(function (tile) {
113247 } // no more than `limit` results per partition.
113250 function searchLimited$1(limit, projection, rtree) {
113252 return partitionViewport$1(projection).reduce(function (result, extent) {
113253 var found = rtree.search(extent.bbox()).slice(0, limit).map(function (d) {
113256 return found.length ? result.concat(found) : result;
113260 var serviceKartaview = {
113261 init: function init() {
113266 this.event = utilRebind(this, dispatch$3, 'on');
113268 reset: function reset() {
113270 Object.values(_oscCache.images.inflight).forEach(abortRequest$3);
113283 _oscSelectedImage = null;
113285 images: function images(projection) {
113287 return searchLimited$1(limit, projection, _oscCache.images.rtree);
113289 sequences: function sequences(projection) {
113290 var viewport = projection.clipExtent();
113291 var min = [viewport[0][0], viewport[1][1]];
113292 var max = [viewport[1][0], viewport[0][1]];
113293 var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
113294 var sequenceKeys = {}; // all sequences for images in viewport
113296 _oscCache.images.rtree.search(bbox).forEach(function (d) {
113297 sequenceKeys[d.data.sequence_id] = true;
113298 }); // make linestrings from those sequences
113302 Object.keys(sequenceKeys).forEach(function (sequenceKey) {
113303 var seq = _oscCache.sequences[sequenceKey];
113304 var images = seq && seq.images;
113309 coordinates: images.map(function (d) {
113313 captured_at: images[0] ? images[0].captured_at : null,
113314 captured_by: images[0] ? images[0].captured_by : null,
113322 cachedImage: function cachedImage(imageKey) {
113323 return _oscCache.images.forImageKey[imageKey];
113325 loadImages: function loadImages(projection) {
113326 var url = apibase$1 + '/1.0/list/nearby-photos/';
113327 loadTiles$1('images', url, projection);
113329 ensureViewerLoaded: function ensureViewerLoaded(context) {
113330 if (_loadViewerPromise$1) return _loadViewerPromise$1; // add kartaview-wrapper
113332 var wrap = context.container().select('.photoviewer').selectAll('.kartaview-wrapper').data([0]);
113334 var wrapEnter = wrap.enter().append('div').attr('class', 'photo-wrapper kartaview-wrapper').classed('hide', true).call(imgZoom.on('zoom', zoomPan)).on('dblclick.zoom', null);
113335 wrapEnter.append('div').attr('class', 'photo-attribution fillD');
113336 var controlsEnter = wrapEnter.append('div').attr('class', 'photo-controls-wrap').append('div').attr('class', 'photo-controls');
113337 controlsEnter.append('button').on('click.back', step(-1)).text('◄');
113338 controlsEnter.append('button').on('click.rotate-ccw', rotate(-90)).text('⤿');
113339 controlsEnter.append('button').on('click.rotate-cw', rotate(90)).text('⤾');
113340 controlsEnter.append('button').on('click.forward', step(1)).text('►');
113341 wrapEnter.append('div').attr('class', 'kartaview-image-wrap'); // Register viewer resize handler
113343 context.ui().photoviewer.on('resize.kartaview', function (dimensions) {
113344 imgZoom = d3_zoom().extent([[0, 0], dimensions]).translateExtent([[0, 0], dimensions]).scaleExtent([1, 15]).on('zoom', zoomPan);
113347 function zoomPan(d3_event) {
113348 var t = d3_event.transform;
113349 context.container().select('.photoviewer .kartaview-image-wrap').call(utilSetTransform, t.x, t.y, t.k);
113354 if (!_oscSelectedImage) return;
113355 var sequenceKey = _oscSelectedImage.sequence_id;
113356 var sequence = _oscCache.sequences[sequenceKey];
113358 var r = sequence.rotation || 0;
113361 if (r < -180) r += 360;
113363 var wrap = context.container().select('.photoviewer .kartaview-wrapper');
113364 wrap.transition().duration(100).call(imgZoom.transform, identity$2);
113365 wrap.selectAll('.kartaview-image').transition().duration(100).style('transform', 'rotate(' + r + 'deg)');
113369 function step(stepBy) {
113371 if (!_oscSelectedImage) return;
113372 var sequenceKey = _oscSelectedImage.sequence_id;
113373 var sequence = _oscCache.sequences[sequenceKey];
113375 var nextIndex = _oscSelectedImage.sequence_index + stepBy;
113376 var nextImage = sequence.images[nextIndex];
113377 if (!nextImage) return;
113378 context.map().centerEase(nextImage.loc);
113379 that.selectImage(context, nextImage.key);
113381 } // don't need any async loading so resolve immediately
113384 _loadViewerPromise$1 = Promise.resolve();
113385 return _loadViewerPromise$1;
113387 showViewer: function showViewer(context) {
113388 var viewer = context.container().select('.photoviewer').classed('hide', false);
113389 var isHidden = viewer.selectAll('.photo-wrapper.kartaview-wrapper.hide').size();
113392 viewer.selectAll('.photo-wrapper:not(.kartaview-wrapper)').classed('hide', true);
113393 viewer.selectAll('.photo-wrapper.kartaview-wrapper').classed('hide', false);
113398 hideViewer: function hideViewer(context) {
113399 _oscSelectedImage = null;
113400 this.updateUrlImage(null);
113401 var viewer = context.container().select('.photoviewer');
113402 if (!viewer.empty()) viewer.datum(null);
113403 viewer.classed('hide', true).selectAll('.photo-wrapper').classed('hide', true);
113404 context.container().selectAll('.viewfield-group, .sequence, .icon-sign').classed('currentView', false);
113405 return this.setStyles(context, null, true);
113407 selectImage: function selectImage(context, imageKey) {
113408 var d = this.cachedImage(imageKey);
113410 this.updateUrlImage(imageKey);
113411 var viewer = context.container().select('.photoviewer');
113412 if (!viewer.empty()) viewer.datum(d);
113413 this.setStyles(context, null, true);
113414 context.container().selectAll('.icon-sign').classed('currentView', false);
113416 var wrap = context.container().select('.photoviewer .kartaview-wrapper');
113417 var imageWrap = wrap.selectAll('.kartaview-image-wrap');
113418 var attribution = wrap.selectAll('.photo-attribution').text('');
113419 wrap.transition().duration(100).call(imgZoom.transform, identity$2);
113420 imageWrap.selectAll('.kartaview-image').remove();
113423 var sequence = _oscCache.sequences[d.sequence_id];
113424 var r = sequence && sequence.rotation || 0;
113425 imageWrap.append('img').attr('class', 'kartaview-image').attr('src', apibase$1 + '/' + d.imagePath).style('transform', 'rotate(' + r + 'deg)');
113428 attribution.append('a').attr('class', 'captured_by').attr('target', '_blank').attr('href', 'https://kartaview.org/user/' + encodeURIComponent(d.captured_by)).text('@' + d.captured_by);
113429 attribution.append('span').text('|');
113433 attribution.append('span').attr('class', 'captured_at').text(localeDateString(d.captured_at));
113434 attribution.append('span').text('|');
113437 attribution.append('a').attr('class', 'image-link').attr('target', '_blank').attr('href', 'https://kartaview.org/details/' + d.sequence_id + '/' + d.sequence_index).text('kartaview.org');
113442 function localeDateString(s) {
113450 if (isNaN(d.getTime())) return null;
113451 return d.toLocaleDateString(_mainLocalizer.localeCode(), options);
113454 getSelectedImage: function getSelectedImage() {
113455 return _oscSelectedImage;
113457 getSequenceKeyForImage: function getSequenceKeyForImage(d) {
113458 return d && d.sequence_id;
113460 // Updates the currently highlighted sequence and selected bubble.
113461 // Reset is only necessary when interacting with the viewport because
113462 // this implicitly changes the currently selected bubble/sequence
113463 setStyles: function setStyles(context, hovered, reset) {
113466 context.container().selectAll('.viewfield-group').classed('highlighted', false).classed('hovered', false).classed('currentView', false);
113467 context.container().selectAll('.sequence').classed('highlighted', false).classed('currentView', false);
113470 var hoveredImageKey = hovered && hovered.key;
113471 var hoveredSequenceKey = this.getSequenceKeyForImage(hovered);
113472 var hoveredSequence = hoveredSequenceKey && _oscCache.sequences[hoveredSequenceKey];
113473 var hoveredImageKeys = hoveredSequence && hoveredSequence.images.map(function (d) {
113476 var viewer = context.container().select('.photoviewer');
113477 var selected = viewer.empty() ? undefined : viewer.datum();
113478 var selectedImageKey = selected && selected.key;
113479 var selectedSequenceKey = this.getSequenceKeyForImage(selected);
113480 var selectedSequence = selectedSequenceKey && _oscCache.sequences[selectedSequenceKey];
113481 var selectedImageKeys = selectedSequence && selectedSequence.images.map(function (d) {
113483 }) || []; // highlight sibling viewfields on either the selected or the hovered sequences
113485 var highlightedImageKeys = utilArrayUnion(hoveredImageKeys, selectedImageKeys);
113486 context.container().selectAll('.layer-kartaview .viewfield-group').classed('highlighted', function (d) {
113487 return highlightedImageKeys.indexOf(d.key) !== -1;
113488 }).classed('hovered', function (d) {
113489 return d.key === hoveredImageKey;
113490 }).classed('currentView', function (d) {
113491 return d.key === selectedImageKey;
113493 context.container().selectAll('.layer-kartaview .sequence').classed('highlighted', function (d) {
113494 return d.properties.key === hoveredSequenceKey;
113495 }).classed('currentView', function (d) {
113496 return d.properties.key === selectedSequenceKey;
113497 }); // update viewfields if needed
113499 context.container().selectAll('.layer-kartaview .viewfield-group .viewfield').attr('d', viewfieldPath);
113501 function viewfieldPath() {
113502 var d = this.parentNode.__data__;
113504 if (d.pano && d.key !== selectedImageKey) {
113505 return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
113507 return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
113513 updateUrlImage: function updateUrlImage(imageKey) {
113515 var hash = utilStringQs(window.location.hash);
113518 hash.photo = 'kartaview/' + imageKey;
113523 window.location.replace('#' + utilQsString(hash, true));
113526 cache: function cache() {
113531 var hashes$1 = {exports: {}};
113533 (function (module, exports) {
113537 function utf8Encode(str) {
113544 if (str && str.length) {
113548 /* Decode utf-16 surrogate pairs */
113550 y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
113552 if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
113553 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
113556 /* Encode output as utf-8 */
113560 output += String.fromCharCode(x);
113561 } else if (x <= 0x7FF) {
113562 output += String.fromCharCode(0xC0 | x >>> 6 & 0x1F, 0x80 | x & 0x3F);
113563 } else if (x <= 0xFFFF) {
113564 output += String.fromCharCode(0xE0 | x >>> 12 & 0x0F, 0x80 | x >>> 6 & 0x3F, 0x80 | x & 0x3F);
113565 } else if (x <= 0x1FFFFF) {
113566 output += String.fromCharCode(0xF0 | x >>> 18 & 0x07, 0x80 | x >>> 12 & 0x3F, 0x80 | x >>> 6 & 0x3F, 0x80 | x & 0x3F);
113574 function utf8Decode(str) {
113582 i = ac = c1 = c2 = c3 = 0;
113584 if (str && str.length) {
113589 c1 = str.charCodeAt(i);
113593 arr[ac] = String.fromCharCode(c1);
113595 } else if (c1 > 191 && c1 < 224) {
113596 c2 = str.charCodeAt(i + 1);
113597 arr[ac] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
113600 c2 = str.charCodeAt(i + 1);
113601 c3 = str.charCodeAt(i + 2);
113602 arr[ac] = String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
113611 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
113612 * to work around bugs in some JS interpreters.
113616 function safe_add(x, y) {
113617 var lsw = (x & 0xFFFF) + (y & 0xFFFF),
113618 msw = (x >> 16) + (y >> 16) + (lsw >> 16);
113619 return msw << 16 | lsw & 0xFFFF;
113622 * Bitwise rotate a 32-bit number to the left.
113626 function bit_rol(num, cnt) {
113627 return num << cnt | num >>> 32 - cnt;
113630 * Convert a raw string to a hex string
113634 function rstr2hex(input, hexcase) {
113635 var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
113641 for (; i < l; i += 1) {
113642 x = input.charCodeAt(i);
113643 output += hex_tab.charAt(x >>> 4 & 0x0F) + hex_tab.charAt(x & 0x0F);
113649 * Convert an array of big-endian words to a string
113653 function binb2rstr(input) {
113658 for (i = 0; i < l; i += 8) {
113659 output += String.fromCharCode(input[i >> 5] >>> 24 - i % 32 & 0xFF);
113665 * Convert an array of little-endian words to a string
113669 function binl2rstr(input) {
113674 for (i = 0; i < l; i += 8) {
113675 output += String.fromCharCode(input[i >> 5] >>> i % 32 & 0xFF);
113681 * Convert a raw string to an array of little-endian words
113682 * Characters >255 have their high-byte silently ignored.
113686 function rstr2binl(input) {
113689 output = Array(input.length >> 2),
113692 for (i = 0; i < lo; i += 1) {
113696 for (i = 0; i < l; i += 8) {
113697 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << i % 32;
113703 * Convert a raw string to an array of big-endian words
113704 * Characters >255 have their high-byte silently ignored.
113708 function rstr2binb(input) {
113711 output = Array(input.length >> 2),
113714 for (i = 0; i < lo; i += 1) {
113718 for (i = 0; i < l; i += 8) {
113719 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << 24 - i % 32;
113725 * Convert a raw string to an arbitrary string encoding
113729 function rstr2any(input, encoding) {
113730 var divisor = encoding.length,
113740 /* Convert to an array of 16-bit big-endian values, forming the dividend */
113742 dividend = Array(Math.ceil(input.length / 2));
113745 for (i = 0; i < ld; i += 1) {
113746 dividend[i] = input.charCodeAt(i * 2) << 8 | input.charCodeAt(i * 2 + 1);
113749 * Repeatedly perform a long division. The binary array forms the dividend,
113750 * the length of the encoding is the divisor. Once computed, the quotient
113751 * forms the dividend for the next step. We stop when the dividend is zerHashes.
113752 * All remainders are stored for later use.
113756 while (dividend.length > 0) {
113760 for (i = 0; i < dividend.length; i += 1) {
113761 x = (x << 16) + dividend[i];
113762 q = Math.floor(x / divisor);
113765 if (quotient.length > 0 || q > 0) {
113766 quotient[quotient.length] = q;
113770 remainders[remainders.length] = x;
113773 /* Convert the remainders to the output string */
113778 for (i = remainders.length - 1; i >= 0; i--) {
113779 output += encoding.charAt(remainders[i]);
113781 /* Append leading zero equivalents */
113784 full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
113786 for (i = output.length; i < full_length; i += 1) {
113787 output = encoding[0] + output;
113793 * Convert a raw string to a base-64 string
113797 function rstr2b64(input, b64pad) {
113798 var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
113804 b64pad = b64pad || '=';
113806 for (i = 0; i < len; i += 3) {
113807 triplet = input.charCodeAt(i) << 16 | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
113809 for (j = 0; j < 4; j += 1) {
113810 if (i * 8 + j * 6 > input.length * 8) {
113813 output += tab.charAt(triplet >>> 6 * (3 - j) & 0x3F);
113823 * @property {String} version
113833 Base64: function Base64() {
113835 var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
113837 // URL encoding support @todo
113838 utf8 = true; // by default enable UTF-8 support encoding
113839 // public method for encoding
113841 this.encode = function (input) {
113848 input = utf8 ? utf8Encode(input) : input;
113850 for (i = 0; i < len; i += 3) {
113851 triplet = input.charCodeAt(i) << 16 | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
113853 for (j = 0; j < 4; j += 1) {
113854 if (i * 8 + j * 6 > len * 8) {
113857 output += tab.charAt(triplet >>> 6 * (3 - j) & 0x3F);
113863 }; // public method for decoding
113866 this.decode = function (input) {
113867 // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
113886 input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '='
113890 // unpack four hexets into three octets using index points in b64
113891 h1 = tab.indexOf(input.charAt(i += 1));
113892 h2 = tab.indexOf(input.charAt(i += 1));
113893 h3 = tab.indexOf(input.charAt(i += 1));
113894 h4 = tab.indexOf(input.charAt(i += 1));
113895 bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
113896 o1 = bits >> 16 & 0xff;
113902 arr[ac] = String.fromCharCode(o1);
113903 } else if (h4 === 64) {
113904 arr[ac] = String.fromCharCode(o1, o2);
113906 arr[ac] = String.fromCharCode(o1, o2, o3);
113908 } while (i < input.length);
113911 dec = utf8 ? utf8Decode(dec) : dec;
113913 }; // set custom pad string
113916 this.setPad = function (str) {
113919 }; // set custom tab string characters
113922 this.setTab = function (str) {
113927 this.setUTF8 = function (bool) {
113928 if (typeof bool === 'boolean') {
113941 * @param {String} str Input String
113944 CRC32: function CRC32(str) {
113952 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 ', '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ', 'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ', '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ', 'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ', '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ', 'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ', '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ', 'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ', '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ', 'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ', '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ', '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 ', '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 ', 'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ', '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ', 'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ', '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ', 'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'].join('');
113955 for (i = 0, iTop = str.length; i < iTop; i += 1) {
113956 y = (crc ^ str.charCodeAt(i)) & 0xFF;
113957 x = '0x' + table.substr(y * 9, 8);
113959 } // always return a positive number (that's what >>> 0 does)
113962 return (crc ^ -1) >>> 0;
113969 * @param {Object} [config]
113971 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
113972 * Digest Algorithm, as defined in RFC 1321.
113973 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
113974 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
113975 * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
113977 MD5: function MD5(options) {
113979 * Private config properties. You may need to tweak these to be compatible with
113980 * the server-side, but the defaults work in most cases.
113981 * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
113983 var hexcase = options && typeof options.uppercase === 'boolean' ? options.uppercase : false,
113984 // hexadecimal output case format. false - lowercase; true - uppercase
113985 b64pad = options && typeof options.pad === 'string' ? options.pad : '=',
113986 // base-64 pad character. Defaults to '=' for strict RFC compliance
113987 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true; // enable/disable utf8 encoding
113988 // privileged (public) methods
113990 this.hex = function (s) {
113991 return rstr2hex(rstr(s), hexcase);
113994 this.b64 = function (s) {
113995 return rstr2b64(rstr(s), b64pad);
113998 this.any = function (s, e) {
113999 return rstr2any(rstr(s), e);
114002 this.raw = function (s) {
114006 this.hex_hmac = function (k, d) {
114007 return rstr2hex(rstr_hmac(k, d), hexcase);
114010 this.b64_hmac = function (k, d) {
114011 return rstr2b64(rstr_hmac(k, d), b64pad);
114014 this.any_hmac = function (k, d, e) {
114015 return rstr2any(rstr_hmac(k, d), e);
114018 * Perform a simple self-test to see if the VM is working
114019 * @return {String} Hexadecimal hash sample
114023 this.vm_test = function () {
114024 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
114027 * Enable/disable uppercase hexadecimal returned string
114029 * @return {Object} this
114033 this.setUpperCase = function (a) {
114034 if (typeof a === 'boolean') {
114041 * Defines a base64 pad string
114043 * @return {Object} this
114047 this.setPad = function (a) {
114052 * Defines a base64 pad string
114054 * @return {Object} [this]
114058 this.setUTF8 = function (a) {
114059 if (typeof a === 'boolean') {
114067 * Calculate the MD5 of a raw string
114072 s = utf8 ? utf8Encode(s) : s;
114073 return binl2rstr(binl(rstr2binl(s), s.length * 8));
114076 * Calculate the HMAC-MD5, of a key and some data (raw strings)
114080 function rstr_hmac(key, data) {
114081 var bkey, ipad, opad, hash, i;
114082 key = utf8 ? utf8Encode(key) : key;
114083 data = utf8 ? utf8Encode(data) : data;
114086 if (bkey.length > 16) {
114087 bkey = binl(bkey, key.length * 8);
114090 ipad = Array(16), opad = Array(16);
114092 for (i = 0; i < 16; i += 1) {
114093 ipad[i] = bkey[i] ^ 0x36363636;
114094 opad[i] = bkey[i] ^ 0x5C5C5C5C;
114097 hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
114098 return binl2rstr(binl(opad.concat(hash), 512 + 128));
114101 * Calculate the MD5 of an array of little-endian words, and a bit length.
114105 function binl(x, len) {
114117 x[len >> 5] |= 0x80 << len % 32;
114118 x[(len + 64 >>> 9 << 4) + 14] = len;
114120 for (i = 0; i < x.length; i += 16) {
114125 a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
114126 d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
114127 c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
114128 b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
114129 a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
114130 d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
114131 c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
114132 b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
114133 a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
114134 d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
114135 c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
114136 b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
114137 a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
114138 d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
114139 c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
114140 b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
114141 a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
114142 d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
114143 c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
114144 b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
114145 a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
114146 d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
114147 c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
114148 b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
114149 a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
114150 d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
114151 c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
114152 b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
114153 a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
114154 d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
114155 c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
114156 b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
114157 a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
114158 d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
114159 c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
114160 b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
114161 a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
114162 d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
114163 c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
114164 b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
114165 a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
114166 d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
114167 c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
114168 b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
114169 a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
114170 d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
114171 c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
114172 b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
114173 a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
114174 d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
114175 c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
114176 b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
114177 a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
114178 d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
114179 c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
114180 b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
114181 a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
114182 d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
114183 c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
114184 b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
114185 a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
114186 d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
114187 c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
114188 b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
114195 return Array(a, b, c, d);
114198 * These functions implement the four basic operations the algorithm uses.
114202 function md5_cmn(q, a, b, x, s, t) {
114203 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
114206 function md5_ff(a, b, c, d, x, s, t) {
114207 return md5_cmn(b & c | ~b & d, a, b, x, s, t);
114210 function md5_gg(a, b, c, d, x, s, t) {
114211 return md5_cmn(b & d | c & ~d, a, b, x, s, t);
114214 function md5_hh(a, b, c, d, x, s, t) {
114215 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
114218 function md5_ii(a, b, c, d, x, s, t) {
114219 return md5_cmn(c ^ (b | ~d), a, b, x, s, t);
114226 * @param {Object} [config]
114229 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
114230 * Version 2.2 Copyright Paul Johnston 2000 - 2009.
114231 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
114232 * See http://pajhome.org.uk/crypt/md5 for details.
114234 SHA1: function SHA1(options) {
114236 * Private config properties. You may need to tweak these to be compatible with
114237 * the server-side, but the defaults work in most cases.
114238 * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
114240 var hexcase = options && typeof options.uppercase === 'boolean' ? options.uppercase : false,
114241 // hexadecimal output case format. false - lowercase; true - uppercase
114242 b64pad = options && typeof options.pad === 'string' ? options.pad : '=',
114243 // base-64 pad character. Defaults to '=' for strict RFC compliance
114244 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true; // enable/disable utf8 encoding
114247 this.hex = function (s) {
114248 return rstr2hex(rstr(s), hexcase);
114251 this.b64 = function (s) {
114252 return rstr2b64(rstr(s), b64pad);
114255 this.any = function (s, e) {
114256 return rstr2any(rstr(s), e);
114259 this.raw = function (s) {
114263 this.hex_hmac = function (k, d) {
114264 return rstr2hex(rstr_hmac(k, d));
114267 this.b64_hmac = function (k, d) {
114268 return rstr2b64(rstr_hmac(k, d), b64pad);
114271 this.any_hmac = function (k, d, e) {
114272 return rstr2any(rstr_hmac(k, d), e);
114275 * Perform a simple self-test to see if the VM is working
114276 * @return {String} Hexadecimal hash sample
114281 this.vm_test = function () {
114282 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
114285 * @description Enable/disable uppercase hexadecimal returned string
114287 * @return {Object} this
114292 this.setUpperCase = function (a) {
114293 if (typeof a === 'boolean') {
114300 * @description Defines a base64 pad string
114302 * @return {Object} this
114307 this.setPad = function (a) {
114312 * @description Defines a base64 pad string
114314 * @return {Object} this
114319 this.setUTF8 = function (a) {
114320 if (typeof a === 'boolean') {
114328 * Calculate the SHA-512 of a raw string
114333 s = utf8 ? utf8Encode(s) : s;
114334 return binb2rstr(binb(rstr2binb(s), s.length * 8));
114337 * Calculate the HMAC-SHA1 of a key and some data (raw strings)
114341 function rstr_hmac(key, data) {
114342 var bkey, ipad, opad, i, hash;
114343 key = utf8 ? utf8Encode(key) : key;
114344 data = utf8 ? utf8Encode(data) : data;
114347 if (bkey.length > 16) {
114348 bkey = binb(bkey, key.length * 8);
114351 ipad = Array(16), opad = Array(16);
114353 for (i = 0; i < 16; i += 1) {
114354 ipad[i] = bkey[i] ^ 0x36363636;
114355 opad[i] = bkey[i] ^ 0x5C5C5C5C;
114358 hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
114359 return binb2rstr(binb(opad.concat(hash), 512 + 160));
114362 * Calculate the SHA-1 of an array of big-endian words, and a bit length
114366 function binb(x, len) {
114383 x[len >> 5] |= 0x80 << 24 - len % 32;
114384 x[(len + 64 >> 9 << 4) + 15] = len;
114386 for (i = 0; i < x.length; i += 16) {
114393 for (j = 0; j < 80; j += 1) {
114397 w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
114400 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)));
114415 return Array(a, b, c, d, e);
114418 * Perform the appropriate triplet combination function for the current
114423 function sha1_ft(t, b, c, d) {
114433 return b & c | b & d | c & d;
114439 * Determine the appropriate additive constant for the current iteration
114444 return t < 20 ? 1518500249 : t < 40 ? 1859775393 : t < 60 ? -1894007588 : -899497514;
114452 * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
114453 * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
114454 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
114455 * See http://pajhome.org.uk/crypt/md5 for details.
114456 * Also http://anmar.eu.org/projects/jssha2/
114458 SHA256: function SHA256(options) {
114460 * Private properties configuration variables. You may need to tweak these to be compatible with
114461 * the server-side, but the defaults work in most cases.
114462 * @see this.setUpperCase() method
114463 * @see this.setPad() method
114465 options && typeof options.uppercase === 'boolean' ? options.uppercase : false;
114466 var // hexadecimal output case format. false - lowercase; true - uppercase */
114467 b64pad = options && typeof options.pad === 'string' ? options.pad : '=',
114469 /* base-64 pad character. Default '=' for strict RFC compliance */
114470 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true,
114472 /* enable/disable utf8 encoding */
114474 /* privileged (public) methods */
114476 this.hex = function (s) {
114477 return rstr2hex(rstr(s, utf8));
114480 this.b64 = function (s) {
114481 return rstr2b64(rstr(s, utf8), b64pad);
114484 this.any = function (s, e) {
114485 return rstr2any(rstr(s, utf8), e);
114488 this.raw = function (s) {
114492 this.hex_hmac = function (k, d) {
114493 return rstr2hex(rstr_hmac(k, d));
114496 this.b64_hmac = function (k, d) {
114497 return rstr2b64(rstr_hmac(k, d), b64pad);
114500 this.any_hmac = function (k, d, e) {
114501 return rstr2any(rstr_hmac(k, d), e);
114504 * Perform a simple self-test to see if the VM is working
114505 * @return {String} Hexadecimal hash sample
114510 this.vm_test = function () {
114511 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
114514 * Enable/disable uppercase hexadecimal returned string
114516 * @return {Object} this
114521 this.setUpperCase = function (a) {
114526 * @description Defines a base64 pad string
114528 * @return {Object} this
114533 this.setPad = function (a) {
114538 * Defines a base64 pad string
114540 * @return {Object} this
114545 this.setUTF8 = function (a) {
114546 if (typeof a === 'boolean') {
114554 * Calculate the SHA-512 of a raw string
114558 function rstr(s, utf8) {
114559 s = utf8 ? utf8Encode(s) : s;
114560 return binb2rstr(binb(rstr2binb(s), s.length * 8));
114563 * Calculate the HMAC-sha256 of a key and some data (raw strings)
114567 function rstr_hmac(key, data) {
114568 key = utf8 ? utf8Encode(key) : key;
114569 data = utf8 ? utf8Encode(data) : data;
114576 if (bkey.length > 16) {
114577 bkey = binb(bkey, key.length * 8);
114580 for (; i < 16; i += 1) {
114581 ipad[i] = bkey[i] ^ 0x36363636;
114582 opad[i] = bkey[i] ^ 0x5C5C5C5C;
114585 hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
114586 return binb2rstr(binb(opad.concat(hash), 512 + 256));
114589 * Main sha256 function, with its support functions
114593 function sha256_S(X, n) {
114594 return X >>> n | X << 32 - n;
114597 function sha256_R(X, n) {
114601 function sha256_Ch(x, y, z) {
114605 function sha256_Maj(x, y, z) {
114606 return x & y ^ x & z ^ y & z;
114609 function sha256_Sigma0256(x) {
114610 return sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22);
114613 function sha256_Sigma1256(x) {
114614 return sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25);
114617 function sha256_Gamma0256(x) {
114618 return sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3);
114621 function sha256_Gamma1256(x) {
114622 return sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10);
114625 sha256_K = [1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998];
114628 var HASH = [1779033703, -1150833019, 1013904242, -1521486534, 1359893119, -1694144372, 528734635, 1541459225];
114630 var a, b, c, d, e, f, g, h;
114634 m[l >> 5] |= 0x80 << 24 - l % 32;
114635 m[(l + 64 >> 9 << 4) + 15] = l;
114637 for (i = 0; i < m.length; i += 16) {
114647 for (j = 0; j < 64; j += 1) {
114651 W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]), sha256_Gamma0256(W[j - 15])), W[j - 16]);
114654 T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)), sha256_K[j]), W[j]);
114655 T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
114666 HASH[0] = safe_add(a, HASH[0]);
114667 HASH[1] = safe_add(b, HASH[1]);
114668 HASH[2] = safe_add(c, HASH[2]);
114669 HASH[3] = safe_add(d, HASH[3]);
114670 HASH[4] = safe_add(e, HASH[4]);
114671 HASH[5] = safe_add(f, HASH[5]);
114672 HASH[6] = safe_add(g, HASH[6]);
114673 HASH[7] = safe_add(h, HASH[7]);
114684 * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
114685 * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
114686 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
114687 * See http://pajhome.org.uk/crypt/md5 for details.
114689 SHA512: function SHA512(options) {
114691 * Private properties configuration variables. You may need to tweak these to be compatible with
114692 * the server-side, but the defaults work in most cases.
114693 * @see this.setUpperCase() method
114694 * @see this.setPad() method
114696 options && typeof options.uppercase === 'boolean' ? options.uppercase : false;
114698 var /* hexadecimal output case format. false - lowercase; true - uppercase */
114699 b64pad = options && typeof options.pad === 'string' ? options.pad : '=',
114701 /* base-64 pad character. Default '=' for strict RFC compliance */
114702 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true,
114704 /* enable/disable utf8 encoding */
114706 /* privileged (public) methods */
114708 this.hex = function (s) {
114709 return rstr2hex(rstr(s));
114712 this.b64 = function (s) {
114713 return rstr2b64(rstr(s), b64pad);
114716 this.any = function (s, e) {
114717 return rstr2any(rstr(s), e);
114720 this.raw = function (s) {
114724 this.hex_hmac = function (k, d) {
114725 return rstr2hex(rstr_hmac(k, d));
114728 this.b64_hmac = function (k, d) {
114729 return rstr2b64(rstr_hmac(k, d), b64pad);
114732 this.any_hmac = function (k, d, e) {
114733 return rstr2any(rstr_hmac(k, d), e);
114736 * Perform a simple self-test to see if the VM is working
114737 * @return {String} Hexadecimal hash sample
114742 this.vm_test = function () {
114743 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
114746 * @description Enable/disable uppercase hexadecimal returned string
114748 * @return {Object} this
114753 this.setUpperCase = function (a) {
114758 * @description Defines a base64 pad string
114760 * @return {Object} this
114765 this.setPad = function (a) {
114770 * @description Defines a base64 pad string
114772 * @return {Object} this
114777 this.setUTF8 = function (a) {
114778 if (typeof a === 'boolean') {
114787 * Calculate the SHA-512 of a raw string
114792 s = utf8 ? utf8Encode(s) : s;
114793 return binb2rstr(binb(rstr2binb(s), s.length * 8));
114796 * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
114800 function rstr_hmac(key, data) {
114801 key = utf8 ? utf8Encode(key) : key;
114802 data = utf8 ? utf8Encode(data) : data;
114809 if (bkey.length > 32) {
114810 bkey = binb(bkey, key.length * 8);
114813 for (; i < 32; i += 1) {
114814 ipad[i] = bkey[i] ^ 0x36363636;
114815 opad[i] = bkey[i] ^ 0x5C5C5C5C;
114818 hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
114819 return binb2rstr(binb(opad.concat(hash), 1024 + 512));
114822 * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
114826 function binb(x, len) {
114833 H = [new int64(0x6a09e667, -205731576), new int64(-1150833019, -2067093701), new int64(0x3c6ef372, -23791573), new int64(-1521486534, 0x5f1d36f1), new int64(0x510e527f, -1377402159), new int64(-1694144372, 0x2b3e6c1f), new int64(0x1f83d9ab, -79577749), new int64(0x5be0cd19, 0x137e2179)],
114844 //Temporary variables not specified by the document
114853 if (sha512_k === undefined) {
114855 sha512_k = [new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd), new int64(-1245643825, -330482897), new int64(-373957723, -2121671748), new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031), new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736), new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe), new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302), new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1), new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428), new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3), new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65), new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483), new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459), new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210), new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340), new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395), new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70), new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926), new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473), new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8), new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b), new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023), new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30), new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910), new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8), new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53), new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016), new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893), new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397), new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60), new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec), new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047), new int64(-1090935817, -1295615723), new int64(-965641998, -479046869), new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207), new int64(-354779690, -840897762), new int64(-176337025, -294727304), new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026), new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b), new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493), new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620), new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430), new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)];
114858 for (i = 0; i < 80; i += 1) {
114859 W[i] = new int64(0, 0);
114860 } // append padding to the source string. The format is described in the FIPS.
114863 x[len >> 5] |= 0x80 << 24 - (len & 0x1f);
114864 x[(len + 128 >> 10 << 5) + 31] = len;
114867 for (i = 0; i < l; i += 32) {
114868 //32 dwords is the block size
114878 for (j = 0; j < 16; j += 1) {
114880 W[j].l = x[i + 2 * j + 1];
114883 for (j = 16; j < 80; j += 1) {
114885 int64rrot(r1, W[j - 2], 19);
114886 int64revrrot(r2, W[j - 2], 29);
114887 int64shr(r3, W[j - 2], 6);
114888 s1.l = r1.l ^ r2.l ^ r3.l;
114889 s1.h = r1.h ^ r2.h ^ r3.h; //sigma0
114891 int64rrot(r1, W[j - 15], 1);
114892 int64rrot(r2, W[j - 15], 8);
114893 int64shr(r3, W[j - 15], 7);
114894 s0.l = r1.l ^ r2.l ^ r3.l;
114895 s0.h = r1.h ^ r2.h ^ r3.h;
114896 int64add4(W[j], s1, W[j - 7], s0, W[j - 16]);
114899 for (j = 0; j < 80; j += 1) {
114901 Ch.l = e.l & f.l ^ ~e.l & g.l;
114902 Ch.h = e.h & f.h ^ ~e.h & g.h; //Sigma1
114906 int64revrrot(r3, e, 9);
114907 s1.l = r1.l ^ r2.l ^ r3.l;
114908 s1.h = r1.h ^ r2.h ^ r3.h; //Sigma0
114911 int64revrrot(r2, a, 2);
114912 int64revrrot(r3, a, 7);
114913 s0.l = r1.l ^ r2.l ^ r3.l;
114914 s0.h = r1.h ^ r2.h ^ r3.h; //Maj
114916 Maj.l = a.l & b.l ^ a.l & c.l ^ b.l & c.l;
114917 Maj.h = a.h & b.h ^ a.h & c.h ^ b.h & c.h;
114918 int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
114930 int64add(H[0], H[0], a);
114931 int64add(H[1], H[1], b);
114932 int64add(H[2], H[2], c);
114933 int64add(H[3], H[3], d);
114934 int64add(H[4], H[4], e);
114935 int64add(H[5], H[5], f);
114936 int64add(H[6], H[6], g);
114937 int64add(H[7], H[7], h);
114938 } //represent the hash as an array of 32-bit dwords
114941 for (i = 0; i < 8; i += 1) {
114943 hash[2 * i + 1] = H[i].l;
114947 } //A constructor for 64-bit numbers
114952 this.l = l; //this.toString = int64toString;
114953 } //Copies src into dst, assuming both are 64-bit numbers
114956 function int64copy(dst, src) {
114959 } //Right-rotates a 64-bit number by shift
114960 //Won't handle cases of shift>=32
114961 //The function revrrot() is for that
114964 function int64rrot(dst, x, shift) {
114965 dst.l = x.l >>> shift | x.h << 32 - shift;
114966 dst.h = x.h >>> shift | x.l << 32 - shift;
114967 } //Reverses the dwords of the source and then rotates right by shift.
114968 //This is equivalent to rotation by 32+shift
114971 function int64revrrot(dst, x, shift) {
114972 dst.l = x.h >>> shift | x.l << 32 - shift;
114973 dst.h = x.l >>> shift | x.h << 32 - shift;
114974 } //Bitwise-shifts right a 64-bit number by shift
114975 //Won't handle shift>=32, but it's never needed in SHA512
114978 function int64shr(dst, x, shift) {
114979 dst.l = x.l >>> shift | x.h << 32 - shift;
114981 } //Adds two 64-bit numbers
114982 //Like the original implementation, does not rely on 32-bit operations
114985 function int64add(dst, x, y) {
114986 var w0 = (x.l & 0xffff) + (y.l & 0xffff);
114987 var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
114988 var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
114989 var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
114990 dst.l = w0 & 0xffff | w1 << 16;
114991 dst.h = w2 & 0xffff | w3 << 16;
114992 } //Same, except with 4 addends. Works faster than adding them one by one.
114995 function int64add4(dst, a, b, c, d) {
114996 var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
114997 var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
114998 var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
114999 var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
115000 dst.l = w0 & 0xffff | w1 << 16;
115001 dst.h = w2 & 0xffff | w3 << 16;
115002 } //Same, except with 5 addends
115005 function int64add5(dst, a, b, c, d, e) {
115006 var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
115007 w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
115008 w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
115009 w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
115010 dst.l = w0 & 0xffff | w1 << 16;
115011 dst.h = w2 & 0xffff | w3 << 16;
115018 * @param {Object} [config]
115020 * A JavaScript implementation of the RIPEMD-160 Algorithm
115021 * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
115022 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
115023 * See http://pajhome.org.uk/crypt/md5 for details.
115024 * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
115026 RMD160: function RMD160(options) {
115028 * Private properties configuration variables. You may need to tweak these to be compatible with
115029 * the server-side, but the defaults work in most cases.
115030 * @see this.setUpperCase() method
115031 * @see this.setPad() method
115033 options && typeof options.uppercase === 'boolean' ? options.uppercase : false;
115035 var /* hexadecimal output case format. false - lowercase; true - uppercase */
115036 b64pad = options && typeof options.pad === 'string' ? options.pa : '=',
115038 /* base-64 pad character. Default '=' for strict RFC compliance */
115039 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true,
115041 /* enable/disable utf8 encoding */
115042 rmd160_r1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13],
115043 rmd160_r2 = [5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11],
115044 rmd160_s1 = [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6],
115045 rmd160_s2 = [8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11];
115046 /* privileged (public) methods */
115048 this.hex = function (s) {
115049 return rstr2hex(rstr(s));
115052 this.b64 = function (s) {
115053 return rstr2b64(rstr(s), b64pad);
115056 this.any = function (s, e) {
115057 return rstr2any(rstr(s), e);
115060 this.raw = function (s) {
115064 this.hex_hmac = function (k, d) {
115065 return rstr2hex(rstr_hmac(k, d));
115068 this.b64_hmac = function (k, d) {
115069 return rstr2b64(rstr_hmac(k, d), b64pad);
115072 this.any_hmac = function (k, d, e) {
115073 return rstr2any(rstr_hmac(k, d), e);
115076 * Perform a simple self-test to see if the VM is working
115077 * @return {String} Hexadecimal hash sample
115082 this.vm_test = function () {
115083 return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
115086 * @description Enable/disable uppercase hexadecimal returned string
115088 * @return {Object} this
115093 this.setUpperCase = function (a) {
115098 * @description Defines a base64 pad string
115100 * @return {Object} this
115105 this.setPad = function (a) {
115106 if (typeof a !== 'undefined') {
115113 * @description Defines a base64 pad string
115115 * @return {Object} this
115120 this.setUTF8 = function (a) {
115121 if (typeof a === 'boolean') {
115130 * Calculate the rmd160 of a raw string
115135 s = utf8 ? utf8Encode(s) : s;
115136 return binl2rstr(binl(rstr2binl(s), s.length * 8));
115139 * Calculate the HMAC-rmd160 of a key and some data (raw strings)
115143 function rstr_hmac(key, data) {
115144 key = utf8 ? utf8Encode(key) : key;
115145 data = utf8 ? utf8Encode(data) : data;
115152 if (bkey.length > 16) {
115153 bkey = binl(bkey, key.length * 8);
115156 for (i = 0; i < 16; i += 1) {
115157 ipad[i] = bkey[i] ^ 0x36363636;
115158 opad[i] = bkey[i] ^ 0x5C5C5C5C;
115161 hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
115162 return binl2rstr(binl(opad.concat(hash), 512 + 160));
115165 * Convert an array of little-endian words to a string
115169 function binl2rstr(input) {
115174 for (i = 0; i < l; i += 8) {
115175 output += String.fromCharCode(input[i >> 5] >>> i % 32 & 0xFF);
115181 * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
115185 function binl(x, len) {
115207 x[len >> 5] |= 0x80 << len % 32;
115208 x[(len + 64 >>> 9 << 4) + 14] = len;
115211 for (i = 0; i < l; i += 16) {
115218 for (j = 0; j <= 79; j += 1) {
115219 T = safe_add(A1, rmd160_f(j, B1, C1, D1));
115220 T = safe_add(T, x[i + rmd160_r1[j]]);
115221 T = safe_add(T, rmd160_K1(j));
115222 T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
115228 T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
115229 T = safe_add(T, x[i + rmd160_r2[j]]);
115230 T = safe_add(T, rmd160_K2(j));
115231 T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
115239 T = safe_add(h1, safe_add(C1, D2));
115240 h1 = safe_add(h2, safe_add(D1, E2));
115241 h2 = safe_add(h3, safe_add(E1, A2));
115242 h3 = safe_add(h4, safe_add(A1, B2));
115243 h4 = safe_add(h0, safe_add(B1, C2));
115247 return [h0, h1, h2, h3, h4];
115248 } // specific algorithm methods
115251 function rmd160_f(j, x, y, z) {
115252 return 0 <= j && j <= 15 ? x ^ y ^ z : 16 <= j && j <= 31 ? x & y | ~x & z : 32 <= j && j <= 47 ? (x | ~y) ^ z : 48 <= j && j <= 63 ? x & z | y & ~z : 64 <= j && j <= 79 ? x ^ (y | ~z) : 'rmd160_f: j out of range';
115255 function rmd160_K1(j) {
115256 return 0 <= j && j <= 15 ? 0x00000000 : 16 <= j && j <= 31 ? 0x5a827999 : 32 <= j && j <= 47 ? 0x6ed9eba1 : 48 <= j && j <= 63 ? 0x8f1bbcdc : 64 <= j && j <= 79 ? 0xa953fd4e : 'rmd160_K1: j out of range';
115259 function rmd160_K2(j) {
115260 return 0 <= j && j <= 15 ? 0x50a28be6 : 16 <= j && j <= 31 ? 0x5c4dd124 : 32 <= j && j <= 47 ? 0x6d703ef3 : 48 <= j && j <= 63 ? 0x7a6d76e9 : 64 <= j && j <= 79 ? 0x00000000 : 'rmd160_K2: j out of range';
115265 (function (window, undefined$1) {
115266 var freeExports = false;
115271 if (exports && _typeof(commonjsGlobal) === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) {
115272 window = commonjsGlobal;
115276 if (typeof undefined$1 === 'function' && _typeof(undefined$1.amd) === 'object' && undefined$1.amd) {
115277 // define as an anonymous module, so, through path mapping, it can be aliased
115278 undefined$1(function () {
115281 } else if (freeExports) {
115282 // in Node.js or RingoJS v0.8.0+
115283 if (module && module.exports === freeExports) {
115284 module.exports = Hashes;
115285 } // in Narwhal or RingoJS v0.7.0-
115287 freeExports.Hashes = Hashes;
115290 // in a browser or Rhino
115291 window.Hashes = Hashes;
115296 })(hashes$1, hashes$1.exports);
115298 var hashes = hashes$1.exports,
115299 sha1 = new hashes.SHA1(); // # xtend
115301 var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
115306 for (var i = 0; i < arguments.length; i++) {
115307 var source = arguments[i];
115309 for (var key in source) {
115310 if (hasOwnProperty$1.call(source, key)) {
115311 target[key] = source[key];
115321 ohauth$1.qsString = function (obj) {
115322 return Object.keys(obj).sort().map(function (key) {
115323 return ohauth$1.percentEncode(key) + '=' + ohauth$1.percentEncode(obj[key]);
115327 ohauth$1.stringQs = function (str) {
115328 return str.split('&').filter(function (pair) {
115330 }).reduce(function (obj, pair) {
115331 var parts = pair.split('=');
115332 obj[decodeURIComponent(parts[0])] = null === parts[1] ? '' : decodeURIComponent(parts[1]);
115337 ohauth$1.rawxhr = function (method, url, data, headers, callback) {
115338 var xhr = new XMLHttpRequest(),
115341 xhr.onreadystatechange = function () {
115342 if (4 === xhr.readyState && 0 !== xhr.status) {
115343 if (twoHundred.test(xhr.status)) callback(null, xhr);else return callback(xhr, null);
115347 xhr.onerror = function (e) {
115348 return callback(e, null);
115351 xhr.open(method, url, true);
115353 for (var h in headers) {
115354 xhr.setRequestHeader(h, headers[h]);
115361 ohauth$1.xhr = function (method, url, auth, data, options, callback) {
115362 var headers = options && options.header || {
115363 'Content-Type': 'application/x-www-form-urlencoded'
115365 headers.Authorization = 'OAuth ' + ohauth$1.authHeader(auth);
115366 return ohauth$1.rawxhr(method, url, data, headers, callback);
115369 ohauth$1.nonce = function () {
115370 for (var o = ''; o.length < 6;) {
115371 o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
115377 ohauth$1.authHeader = function (obj) {
115378 return Object.keys(obj).sort().map(function (key) {
115379 return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
115383 ohauth$1.timestamp = function () {
115384 return ~~(+new Date() / 1000);
115387 ohauth$1.percentEncode = function (s) {
115388 return encodeURIComponent(s).replace(/\!/g, '%21').replace(/\'/g, '%27').replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
115391 ohauth$1.baseString = function (method, url, params) {
115392 if (params.oauth_signature) delete params.oauth_signature;
115393 return [method, ohauth$1.percentEncode(url), ohauth$1.percentEncode(ohauth$1.qsString(params))].join('&');
115396 ohauth$1.signature = function (oauth_secret, token_secret, baseString) {
115397 return sha1.b64_hmac(ohauth$1.percentEncode(oauth_secret) + '&' + ohauth$1.percentEncode(token_secret), baseString);
115400 * Takes an options object for configuration (consumer_key,
115401 * consumer_secret, version, signature_method, token, token_secret)
115402 * and returns a function that generates the Authorization header
115405 * The returned function takes these parameters:
115406 * - method: GET/POST/...
115407 * - uri: full URI with protocol, port, path and query string
115408 * - extra_params: any extra parameters (that are passed in the POST data),
115409 * can be an object or a from-urlencoded string.
115411 * Returned function returns full OAuth header with "OAuth" string in it.
115415 ohauth$1.headerGenerator = function (options) {
115416 options = options || {};
115417 var consumer_key = options.consumer_key || '',
115418 consumer_secret = options.consumer_secret || '',
115419 signature_method = options.signature_method || 'HMAC-SHA1',
115420 version = options.version || '1.0',
115421 token = options.token || '',
115422 token_secret = options.token_secret || '';
115423 return function (method, uri, extra_params) {
115424 method = method.toUpperCase();
115426 if (typeof extra_params === 'string' && extra_params.length > 0) {
115427 extra_params = ohauth$1.stringQs(extra_params);
115430 var uri_parts = uri.split('?', 2),
115431 base_uri = uri_parts[0];
115432 var query_params = uri_parts.length === 2 ? ohauth$1.stringQs(uri_parts[1]) : {};
115434 oauth_consumer_key: consumer_key,
115435 oauth_signature_method: signature_method,
115436 oauth_version: version,
115437 oauth_timestamp: ohauth$1.timestamp(),
115438 oauth_nonce: ohauth$1.nonce()
115440 if (token) oauth_params.oauth_token = token;
115441 var all_params = xtend$1({}, oauth_params, query_params, extra_params),
115442 base_str = ohauth$1.baseString(method, base_uri, all_params);
115443 oauth_params.oauth_signature = ohauth$1.signature(consumer_secret, token_secret, base_str);
115444 return 'OAuth ' + ohauth$1.authHeader(oauth_params);
115448 var ohauth_1 = ohauth$1;
115450 var resolveUrl$1 = {exports: {}};
115452 (function (module, exports) {
115453 // Copyright 2014 Simon Lydell
115454 // X11 (“MIT”) Licensed. (See LICENSE.)
115455 void function (root, factory) {
115457 module.exports = factory();
115459 }(commonjsGlobal, function () {
115463 var numUrls = arguments.length;
115466 throw new Error("resolveUrl requires at least one argument; got none.");
115469 var base = document.createElement("base");
115470 base.href = arguments[0];
115476 var head = document.getElementsByTagName("head")[0];
115477 head.insertBefore(base, head.firstChild);
115478 var a = document.createElement("a");
115481 for (var index = 1; index < numUrls; index++) {
115482 a.href = arguments[index];
115487 head.removeChild(base);
115495 var assign = make_assign();
115496 var create$1 = make_create();
115497 var trim$1 = make_trim();
115498 var Global$5 = typeof window !== 'undefined' ? window : commonjsGlobal;
115509 isFunction: isFunction$1,
115514 function make_assign() {
115518 return function shimAssign(obj, props1, props2, etc) {
115519 for (var i = 1; i < arguments.length; i++) {
115520 each$7(Object(arguments[i]), function (val, key) {
115530 function make_create() {
115532 return function create(obj, assignProps1, assignProps2, etc) {
115533 var assignArgsList = slice$1(arguments, 1);
115534 return assign.apply(this, [Object.create(obj)].concat(assignArgsList));
115537 var F = function F() {}; // eslint-disable-line no-inner-declarations
115540 return function create(obj, assignProps1, assignProps2, etc) {
115541 var assignArgsList = slice$1(arguments, 1);
115543 return assign.apply(this, [new F()].concat(assignArgsList));
115549 if (String.prototype.trim) {
115550 return function trim(str) {
115551 return String.prototype.trim.call(str);
115554 return function trim(str) {
115555 return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
115560 function bind$1(obj, fn) {
115562 return fn.apply(obj, Array.prototype.slice.call(arguments, 0));
115566 function slice$1(arr, index) {
115567 return Array.prototype.slice.call(arr, index || 0);
115570 function each$7(obj, fn) {
115571 pluck$1(obj, function (val, key) {
115577 function map(obj, fn) {
115578 var res = isList$1(obj) ? [] : {};
115579 pluck$1(obj, function (v, k) {
115586 function pluck$1(obj, fn) {
115588 for (var i = 0; i < obj.length; i++) {
115595 if (obj.hasOwnProperty(key)) {
115596 if (fn(obj[key], key)) {
115604 function isList$1(val) {
115605 return val != null && typeof val != 'function' && typeof val.length == 'number';
115608 function isFunction$1(val) {
115609 return val && {}.toString.call(val) === '[object Function]';
115612 function isObject$1(val) {
115613 return val && {}.toString.call(val) === '[object Object]';
115617 var slice = util$5.slice;
115618 var pluck = util$5.pluck;
115619 var each$6 = util$5.each;
115620 var bind = util$5.bind;
115621 var create = util$5.create;
115622 var isList = util$5.isList;
115623 var isFunction = util$5.isFunction;
115624 var isObject = util$5.isObject;
115626 createStore: _createStore
115631 // get returns the value of the given key. If that value
115632 // is undefined, it returns optionalDefaultValue instead.
115633 get: function get(key, optionalDefaultValue) {
115634 var data = this.storage.read(this._namespacePrefix + key);
115635 return this._deserialize(data, optionalDefaultValue);
115637 // set will store the given value at key and returns value.
115638 // Calling set with value === undefined is equivalent to calling remove.
115639 set: function set(key, value) {
115640 if (value === undefined) {
115641 return this.remove(key);
115644 this.storage.write(this._namespacePrefix + key, this._serialize(value));
115647 // remove deletes the key and value stored at the given key.
115648 remove: function remove(key) {
115649 this.storage.remove(this._namespacePrefix + key);
115651 // each will call the given callback once for each key-value pair
115653 each: function each(callback) {
115655 this.storage.each(function (val, namespacedKey) {
115656 callback.call(self, self._deserialize(val), (namespacedKey || '').replace(self._namespaceRegexp, ''));
115659 // clearAll will remove all the stored key-value pairs in this store.
115660 clearAll: function clearAll() {
115661 this.storage.clearAll();
115663 // additional functionality that can't live in plugins
115664 // ---------------------------------------------------
115665 // hasNamespace returns true if this store instance has the given namespace.
115666 hasNamespace: function hasNamespace(namespace) {
115667 return this._namespacePrefix == '__storejs_' + namespace + '_';
115669 // createStore creates a store.js instance with the first
115670 // functioning storage in the list of storage candidates,
115671 // and applies the the given mixins to the instance.
115672 createStore: function createStore() {
115673 return _createStore.apply(this, arguments);
115675 addPlugin: function addPlugin(plugin) {
115676 this._addPlugin(plugin);
115678 namespace: function namespace(_namespace) {
115679 return _createStore(this.storage, this.plugins, _namespace);
115684 var _console = typeof console == 'undefined' ? null : console;
115690 var fn = _console.warn ? _console.warn : _console.log;
115691 fn.apply(_console, arguments);
115694 function _createStore(storages, plugins, namespace) {
115699 if (storages && !isList(storages)) {
115703 if (plugins && !isList(plugins)) {
115707 var namespacePrefix = namespace ? '__storejs_' + namespace + '_' : '';
115708 var namespaceRegexp = namespace ? new RegExp('^' + namespacePrefix) : null;
115709 var legalNamespaces = /^[a-zA-Z0-9_\-]*$/; // alpha-numeric + underscore and dash
115711 if (!legalNamespaces.test(namespace)) {
115712 throw new Error('store.js namespaces can only have alphanumerics + underscores and dashes');
115715 var _privateStoreProps = {
115716 _namespacePrefix: namespacePrefix,
115717 _namespaceRegexp: namespaceRegexp,
115718 _testStorage: function _testStorage(storage) {
115720 var testStr = '__storejs__test__';
115721 storage.write(testStr, testStr);
115722 var ok = storage.read(testStr) === testStr;
115723 storage.remove(testStr);
115729 _assignPluginFnProp: function _assignPluginFnProp(pluginFnProp, propName) {
115730 var oldFn = this[propName];
115732 this[propName] = function pluginFn() {
115733 var args = slice(arguments, 0);
115734 var self = this; // super_fn calls the old function which was overwritten by
115742 each$6(arguments, function (arg, i) {
115745 return oldFn.apply(self, args);
115746 } // Give mixing function access to super_fn by prefixing all mixin function
115747 // arguments with super_fn.
115750 var newFnArgs = [super_fn].concat(args);
115751 return pluginFnProp.apply(self, newFnArgs);
115754 _serialize: function _serialize(obj) {
115755 return JSON.stringify(obj);
115757 _deserialize: function _deserialize(strVal, defaultVal) {
115760 } // It is possible that a raw string value has been previously stored
115761 // in a storage without using store.js, meaning it will be a raw
115762 // string value instead of a JSON serialized string. By defaulting
115763 // to the raw string value in case of a JSON parse error, we allow
115764 // for past stored values to be forwards-compatible with store.js
115770 val = JSON.parse(strVal);
115775 return val !== undefined ? val : defaultVal;
115777 _addStorage: function _addStorage(storage) {
115782 if (this._testStorage(storage)) {
115783 this.storage = storage;
115787 _addPlugin: function _addPlugin(plugin) {
115788 var self = this; // If the plugin is an array, then add all plugins in the array.
115789 // This allows for a plugin to depend on other plugins.
115792 each$6(plugin, function (plugin) {
115793 self._addPlugin(plugin);
115796 } // Keep track of all plugins we've seen so far, so that we
115797 // don't add any of them twice.
115800 var seenPlugin = pluck(this.plugins, function (seenPlugin) {
115801 return plugin === seenPlugin;
115808 this.plugins.push(plugin); // Check that the plugin is properly formed
115810 if (!isFunction(plugin)) {
115811 throw new Error('Plugins must be function values that return objects');
115814 var pluginProperties = plugin.call(this);
115816 if (!isObject(pluginProperties)) {
115817 throw new Error('Plugins must return an object of function properties');
115818 } // Add the plugin function properties to this store instance.
115821 each$6(pluginProperties, function (pluginFnProp, propName) {
115822 if (!isFunction(pluginFnProp)) {
115823 throw new Error('Bad plugin property: ' + propName + ' from plugin ' + plugin.name + '. Plugins should only return functions.');
115826 self._assignPluginFnProp(pluginFnProp, propName);
115829 // Put deprecated properties in the private API, so as to not expose it to accidential
115830 // discovery through inspection of the store object.
115831 // Deprecated: addStorage
115832 addStorage: function addStorage(storage) {
115833 _warn('store.addStorage(storage) is deprecated. Use createStore([storages])');
115835 this._addStorage(storage);
115838 var store = create(_privateStoreProps, storeAPI, {
115842 each$6(store, function (prop, propName) {
115843 if (isFunction(prop)) {
115844 store.raw[propName] = bind(store, prop);
115847 each$6(storages, function (storage) {
115848 store._addStorage(storage);
115850 each$6(plugins, function (plugin) {
115851 store._addPlugin(plugin);
115857 var Global$4 = util$4.Global;
115867 function localStorage$1() {
115868 return Global$4.localStorage;
115872 return localStorage$1().getItem(key);
115875 function write$5(key, data) {
115876 return localStorage$1().setItem(key, data);
115880 for (var i = localStorage$1().length - 1; i >= 0; i--) {
115881 var key = localStorage$1().key(i);
115886 function remove$5(key) {
115887 return localStorage$1().removeItem(key);
115890 function clearAll$5() {
115891 return localStorage$1().clear();
115894 // versions 6 and 7, where no localStorage, etc
115898 var Global$3 = util$3.Global;
115899 var oldFFGlobalStorage = {
115900 name: 'oldFF-globalStorage',
115907 var globalStorage = Global$3.globalStorage;
115910 return globalStorage[key];
115913 function write$4(key, data) {
115914 globalStorage[key] = data;
115918 for (var i = globalStorage.length - 1; i >= 0; i--) {
115919 var key = globalStorage.key(i);
115920 fn(globalStorage[key], key);
115924 function remove$4(key) {
115925 return globalStorage.removeItem(key);
115928 function clearAll$4() {
115929 each$4(function (key, _) {
115930 delete globalStorage[key];
115934 // versions 6 and 7, where no localStorage, sessionStorage, etc
115938 var Global$2 = util$2.Global;
115939 var oldIEUserDataStorage = {
115940 name: 'oldIE-userDataStorage',
115947 var storageName = 'storejs';
115948 var doc$1 = Global$2.document;
115950 var _withStorageEl = _makeIEStorageElFunction();
115952 var disable = (Global$2.navigator ? Global$2.navigator.userAgent : '').match(/ (MSIE 8|MSIE 9|MSIE 10)\./); // MSIE 9.x, MSIE 10.x
115954 function write$3(unfixedKey, data) {
115959 var fixedKey = fixKey(unfixedKey);
115961 _withStorageEl(function (storageEl) {
115962 storageEl.setAttribute(fixedKey, data);
115963 storageEl.save(storageName);
115967 function read$3(unfixedKey) {
115972 var fixedKey = fixKey(unfixedKey);
115975 _withStorageEl(function (storageEl) {
115976 res = storageEl.getAttribute(fixedKey);
115982 function each$3(callback) {
115983 _withStorageEl(function (storageEl) {
115984 var attributes = storageEl.XMLDocument.documentElement.attributes;
115986 for (var i = attributes.length - 1; i >= 0; i--) {
115987 var attr = attributes[i];
115988 callback(storageEl.getAttribute(attr.name), attr.name);
115993 function remove$3(unfixedKey) {
115994 var fixedKey = fixKey(unfixedKey);
115996 _withStorageEl(function (storageEl) {
115997 storageEl.removeAttribute(fixedKey);
115998 storageEl.save(storageName);
116002 function clearAll$3() {
116003 _withStorageEl(function (storageEl) {
116004 var attributes = storageEl.XMLDocument.documentElement.attributes;
116005 storageEl.load(storageName);
116007 for (var i = attributes.length - 1; i >= 0; i--) {
116008 storageEl.removeAttribute(attributes[i].name);
116011 storageEl.save(storageName);
116015 // In IE7, keys cannot start with a digit or contain certain chars.
116016 // See https://github.com/marcuswestin/store.js/issues/40
116017 // See https://github.com/marcuswestin/store.js/issues/83
116020 var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
116023 return key.replace(/^\d/, '___$&').replace(forbiddenCharsRegex, '___');
116026 function _makeIEStorageElFunction() {
116027 if (!doc$1 || !doc$1.documentElement || !doc$1.documentElement.addBehavior) {
116031 var scriptTag = 'script',
116034 storageEl; // Since #userData storage applies only to specific paths, we need to
116035 // somehow link our data to a specific path. We choose /favicon.ico
116036 // as a pretty safe option, since all browsers already make a request to
116037 // this URL anyway and being a 404 will not hurt us here. We wrap an
116038 // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
116039 // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
116040 // since the iframe access rules appear to allow direct access and
116041 // manipulation of the document element, even for a 404 page. This
116042 // document can be used instead of the current document (which would
116043 // have been limited to the current path) to perform #userData storage.
116046 /* global ActiveXObject */
116047 storageContainer = new ActiveXObject('htmlfile');
116048 storageContainer.open();
116049 storageContainer.write('<' + scriptTag + '>document.w=window</' + scriptTag + '><iframe src="/favicon.ico"></iframe>');
116050 storageContainer.close();
116051 storageOwner = storageContainer.w.frames[0].document;
116052 storageEl = storageOwner.createElement('div');
116054 // somehow ActiveXObject instantiation failed (perhaps some special
116055 // security settings or otherwse), fall back to per-path storage
116056 storageEl = doc$1.createElement('div');
116057 storageOwner = doc$1.body;
116060 return function (storeFunction) {
116061 var args = [].slice.call(arguments, 0);
116062 args.unshift(storageEl); // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
116063 // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
116065 storageOwner.appendChild(storageEl);
116066 storageEl.addBehavior('#default#userData');
116067 storageEl.load(storageName);
116068 storeFunction.apply(this, args);
116069 storageOwner.removeChild(storageEl);
116074 // doesn't work but cookies do. This implementation is adopted from
116075 // https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage
116078 var Global$1 = util$1.Global;
116079 var trim = util$1.trim;
116088 var doc = Global$1.document;
116091 if (!key || !_has(key)) {
116095 var regexpStr = "(?:^|.*;\\s*)" + escape(key).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*";
116096 return unescape(doc.cookie.replace(new RegExp(regexpStr), "$1"));
116099 function each$2(callback) {
116100 var cookies = doc.cookie.split(/; ?/g);
116102 for (var i = cookies.length - 1; i >= 0; i--) {
116103 if (!trim(cookies[i])) {
116107 var kvp = cookies[i].split('=');
116108 var key = unescape(kvp[0]);
116109 var val = unescape(kvp[1]);
116114 function write$2(key, data) {
116119 doc.cookie = escape(key) + "=" + escape(data) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/";
116122 function remove$2(key) {
116123 if (!key || !_has(key)) {
116127 doc.cookie = escape(key) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
116130 function clearAll$2() {
116131 each$2(function (_, key) {
116137 return new RegExp("(?:^|;\\s*)" + escape(key).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=").test(doc.cookie);
116141 var Global = util.Global;
116142 var sessionStorage_1 = {
116143 name: 'sessionStorage',
116151 function sessionStorage() {
116152 return Global.sessionStorage;
116156 return sessionStorage().getItem(key);
116159 function write$1(key, data) {
116160 return sessionStorage().setItem(key, data);
116164 for (var i = sessionStorage().length - 1; i >= 0; i--) {
116165 var key = sessionStorage().key(i);
116170 function remove$1(key) {
116171 return sessionStorage().removeItem(key);
116174 function clearAll$1() {
116175 return sessionStorage().clear();
116178 // is functions (meaning store.get(), store.set(), etc will all function).
116179 // However, stored values will not persist when the browser navigates to
116180 // a new page or reloads the current page.
116182 var memoryStorage_1 = {
116190 var memoryStorage = {};
116193 return memoryStorage[key];
116196 function write(key, data) {
116197 memoryStorage[key] = data;
116200 function each(callback) {
116201 for (var key in memoryStorage) {
116202 if (memoryStorage.hasOwnProperty(key)) {
116203 callback(memoryStorage[key], key);
116209 delete memoryStorage[key];
116212 function clearAll(key) {
116216 var all = [// Listed in order of usage preference
116217 localStorage_1, oldFFGlobalStorage, oldIEUserDataStorage, cookieStorage, sessionStorage_1, memoryStorage_1];
116223 // NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
116224 // See http://www.JSON.org/js.html
116225 // This code should be minified before deployment.
116226 // See http://javascript.crockford.com/jsmin.html
116227 // USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
116229 // This file creates a global JSON object containing two methods: stringify
116230 // and parse. This file provides the ES5 JSON capability to ES3 systems.
116231 // If a project might run on IE8 or earlier, then this file should be included.
116232 // This file does nothing on ES5 systems.
116233 // JSON.stringify(value, replacer, space)
116234 // value any JavaScript value, usually an object or array.
116235 // replacer an optional parameter that determines how object
116236 // values are stringified for objects. It can be a
116237 // function or an array of strings.
116238 // space an optional parameter that specifies the indentation
116239 // of nested structures. If it is omitted, the text will
116240 // be packed without extra whitespace. If it is a number,
116241 // it will specify the number of spaces to indent at each
116242 // level. If it is a string (such as "\t" or " "),
116243 // it contains the characters used to indent at each level.
116244 // This method produces a JSON text from a JavaScript value.
116245 // When an object value is found, if the object contains a toJSON
116246 // method, its toJSON method will be called and the result will be
116247 // stringified. A toJSON method does not serialize: it returns the
116248 // value represented by the name/value pair that should be serialized,
116249 // or undefined if nothing should be serialized. The toJSON method
116250 // will be passed the key associated with the value, and this will be
116252 // For example, this would serialize Dates as ISO strings.
116253 // Date.prototype.toJSON = function (key) {
116255 // // Format integers to have at least two digits.
116260 // return this.getUTCFullYear() + "-" +
116261 // f(this.getUTCMonth() + 1) + "-" +
116262 // f(this.getUTCDate()) + "T" +
116263 // f(this.getUTCHours()) + ":" +
116264 // f(this.getUTCMinutes()) + ":" +
116265 // f(this.getUTCSeconds()) + "Z";
116267 // You can provide an optional replacer method. It will be passed the
116268 // key and value of each member, with this bound to the containing
116269 // object. The value that is returned from your method will be
116270 // serialized. If your method returns undefined, then the member will
116271 // be excluded from the serialization.
116272 // If the replacer parameter is an array of strings, then it will be
116273 // used to select the members to be serialized. It filters the results
116274 // such that only members with keys listed in the replacer array are
116276 // Values that do not have JSON representations, such as undefined or
116277 // functions, will not be serialized. Such values in objects will be
116278 // dropped; in arrays they will be replaced with null. You can use
116279 // a replacer function to replace those with JSON values.
116280 // JSON.stringify(undefined) returns undefined.
116281 // The optional space parameter produces a stringification of the
116282 // value that is filled with line breaks and indentation to make it
116284 // If the space parameter is a non-empty string, then that string will
116285 // be used for indentation. If the space parameter is a number, then
116286 // the indentation will be that many spaces.
116288 // text = JSON.stringify(["e", {pluribus: "unum"}]);
116289 // // text is '["e",{"pluribus":"unum"}]'
116290 // text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t");
116291 // // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
116292 // text = JSON.stringify([new Date()], function (key, value) {
116293 // return this[key] instanceof Date
116294 // ? "Date(" + this[key] + ")"
116297 // // text is '["Date(---current time---)"]'
116298 // JSON.parse(text, reviver)
116299 // This method parses a JSON text to produce an object or array.
116300 // It can throw a SyntaxError exception.
116301 // The optional reviver parameter is a function that can filter and
116302 // transform the results. It receives each of the keys and values,
116303 // and its return value is used instead of the original value.
116304 // If it returns what it received, then the structure is not modified.
116305 // If it returns undefined then the member is deleted.
116307 // // Parse the text. Values that look like ISO date strings will
116308 // // be converted to Date objects.
116309 // myData = JSON.parse(text, function (key, value) {
116311 // if (typeof value === "string") {
116313 // /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
116315 // return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
116321 // myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
116323 // if (typeof value === "string" &&
116324 // value.slice(0, 5) === "Date(" &&
116325 // value.slice(-1) === ")") {
116326 // d = new Date(value.slice(5, -1));
116333 // This is a reference implementation. You are free to copy, modify, or
116341 JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
116342 getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
116343 lastIndex, length, parse, prototype, push, replace, slice, stringify,
116344 test, toJSON, toString, valueOf
116346 // Create a JSON object only if one does not already exist. We create the
116347 // methods in a closure to avoid creating global variables.
116348 if ((typeof JSON === "undefined" ? "undefined" : _typeof(JSON)) !== "object") {
116354 var rx_one = /^[\],:{}\s]*$/;
116355 var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
116356 var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
116357 var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
116358 var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
116359 var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
116362 // Format integers to have at least two digits.
116363 return n < 10 ? "0" + n : n;
116366 function this_value() {
116370 if (typeof Date.prototype.toJSON !== "function") {
116371 Date.prototype.toJSON = function () {
116372 return isFinite(this.valueOf()) ? this.getUTCFullYear() + "-" + f(this.getUTCMonth() + 1) + "-" + f(this.getUTCDate()) + "T" + f(this.getUTCHours()) + ":" + f(this.getUTCMinutes()) + ":" + f(this.getUTCSeconds()) + "Z" : null;
116375 Boolean.prototype.toJSON = this_value;
116376 Number.prototype.toJSON = this_value;
116377 String.prototype.toJSON = this_value;
116385 function quote(string) {
116386 // If the string contains no control characters, no quote characters, and no
116387 // backslash characters, then we can safely slap some quotes around it.
116388 // Otherwise we must also replace the offending characters with safe escape
116390 rx_escapable.lastIndex = 0;
116391 return rx_escapable.test(string) ? "\"" + string.replace(rx_escapable, function (a) {
116393 return typeof c === "string" ? c : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
116394 }) + "\"" : "\"" + string + "\"";
116397 function str(key, holder) {
116398 // Produce a string from holder[key].
116399 var i; // The loop counter.
116401 var k; // The member key.
116403 var v; // The member value.
116408 var value = holder[key]; // If the value has a toJSON method, call it to obtain a replacement value.
116410 if (value && _typeof(value) === "object" && typeof value.toJSON === "function") {
116411 value = value.toJSON(key);
116412 } // If we were called with a replacer function, then call the replacer to
116413 // obtain a replacement value.
116416 if (typeof rep === "function") {
116417 value = rep.call(holder, key, value);
116418 } // What happens next depends on the value's type.
116421 switch (_typeof(value)) {
116426 // JSON numbers must be finite. Encode non-finite numbers as null.
116427 return isFinite(value) ? String(value) : "null";
116431 // If the value is a boolean or null, convert it to a string. Note:
116432 // typeof null does not produce "null". The case is included here in
116433 // the remote chance that this gets fixed someday.
116435 // If the type is "object", we might be dealing with an object or an array or
116439 // Due to a specification blunder in ECMAScript, typeof null is "object",
116440 // so watch out for that case.
116443 } // Make an array to hold the partial results of stringifying this object value.
116447 partial = []; // Is the value an array?
116449 if (Object.prototype.toString.apply(value) === "[object Array]") {
116450 // The value is an array. Stringify every element. Use null as a placeholder
116451 // for non-JSON values.
116454 for (i = 0; i < length; i += 1) {
116455 partial[i] = str(i, value) || "null";
116456 } // Join all of the elements together, separated with commas, and wrap them in
116460 v = partial.length === 0 ? "[]" : gap ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]" : "[" + partial.join(",") + "]";
116463 } // If the replacer is an array, use it to select the members to be stringified.
116466 if (rep && _typeof(rep) === "object") {
116469 for (i = 0; i < length; i += 1) {
116470 if (typeof rep[i] === "string") {
116475 partial.push(quote(k) + (gap ? ": " : ":") + v);
116480 // Otherwise, iterate through all of the keys in the object.
116482 if (Object.prototype.hasOwnProperty.call(value, k)) {
116486 partial.push(quote(k) + (gap ? ": " : ":") + v);
116490 } // Join all of the member texts together, separated with commas,
116491 // and wrap them in braces.
116494 v = partial.length === 0 ? "{}" : gap ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" : "{" + partial.join(",") + "}";
116498 } // If the JSON object does not yet have a stringify method, give it one.
116501 if (typeof JSON.stringify !== "function") {
116503 // table of character substitutions
116513 JSON.stringify = function (value, replacer, space) {
116514 // The stringify method takes a value and an optional replacer, and an optional
116515 // space parameter, and returns a JSON text. The replacer can be a function
116516 // that can replace values, or an array of strings that will select the keys.
116517 // A default replacer method can be provided. Use of the space parameter can
116518 // produce text that is more easily readable.
116521 indent = ""; // If the space parameter is a number, make an indent string containing that
116524 if (typeof space === "number") {
116525 for (i = 0; i < space; i += 1) {
116527 } // If the space parameter is a string, it will be used as the indent string.
116529 } else if (typeof space === "string") {
116531 } // If there is a replacer, it must be a function or an array.
116532 // Otherwise, throw an error.
116537 if (replacer && typeof replacer !== "function" && (_typeof(replacer) !== "object" || typeof replacer.length !== "number")) {
116538 throw new Error("JSON.stringify");
116539 } // Make a fake root object containing our value under the key of "".
116540 // Return the result of stringifying the value.
116547 } // If the JSON object does not yet have a parse method, give it one.
116550 if (typeof JSON.parse !== "function") {
116551 JSON.parse = function (text, reviver) {
116552 // The parse method takes a text and an optional reviver function, and returns
116553 // a JavaScript value if the text is a valid JSON text.
116556 function walk(holder, key) {
116557 // The walk method is used to recursively walk the resulting structure so
116558 // that modifications can be made.
116561 var value = holder[key];
116563 if (value && _typeof(value) === "object") {
116565 if (Object.prototype.hasOwnProperty.call(value, k)) {
116577 return reviver.call(holder, key, value);
116578 } // Parsing happens in four stages. In the first stage, we replace certain
116579 // Unicode characters with escape sequences. JavaScript handles many characters
116580 // incorrectly, either silently deleting them, or treating them as line endings.
116584 rx_dangerous.lastIndex = 0;
116586 if (rx_dangerous.test(text)) {
116587 text = text.replace(rx_dangerous, function (a) {
116588 return "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
116590 } // In the second stage, we run the text against regular expressions that look
116591 // for non-JSON patterns. We are especially concerned with "()" and "new"
116592 // because they can cause invocation, and "=" because it can cause mutation.
116593 // But just to be safe, we want to reject all unexpected forms.
116594 // We split the second stage into 4 regexp operations in order to work around
116595 // crippling inefficiencies in IE's and Safari's regexp engines. First we
116596 // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
116597 // replace all simple value tokens with "]" characters. Third, we delete all
116598 // open brackets that follow a colon or comma or that begin the text. Finally,
116599 // we look to see that the remaining characters are only whitespace or "]" or
116600 // "," or ":" or "{" or "}". If that is so, then the text is safe for eval.
116603 if (rx_one.test(text.replace(rx_two, "@").replace(rx_three, "]").replace(rx_four, ""))) {
116604 // In the third stage we use the eval function to compile the text into a
116605 // JavaScript structure. The "{" operator is subject to a syntactic ambiguity
116606 // in JavaScript: it can begin a block or an object literal. We wrap the text
116607 // in parens to eliminate the ambiguity.
116608 j = eval("(" + text + ")"); // In the optional fourth stage, we recursively walk the new structure, passing
116609 // each name/value pair to a reviver function for possible transformation.
116611 return typeof reviver === "function" ? walk({
116614 } // If the text is not JSON parseable, then a SyntaxError is thrown.
116617 throw new SyntaxError("JSON.parse");
116622 var json2 = json2Plugin;
116624 function json2Plugin() {
116628 var engine = storeEngine;
116631 var store_legacy = engine.createStore(storages, plugins);
116633 var immutable = extend;
116634 var hasOwnProperty = Object.prototype.hasOwnProperty;
116639 for (var i = 0; i < arguments.length; i++) {
116640 var source = arguments[i];
116642 for (var key in source) {
116643 if (hasOwnProperty.call(source, key)) {
116644 target[key] = source[key];
116653 var resolveUrl = resolveUrl$1.exports;
116654 var store = store_legacy;
116655 var xtend = immutable; // # osm-auth
116657 // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
116658 // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
116659 // does not support custom headers, which this uses everywhere.
116661 var osmAuth = function osmAuth(o) {
116662 var oauth = {}; // authenticated users will also have a request token secret, but it's
116663 // not used in transactions with the server
116665 oauth.authenticated = function () {
116666 return !!(token('oauth_token') && token('oauth_token_secret'));
116669 oauth.logout = function () {
116670 token('oauth_token', '');
116671 token('oauth_token_secret', '');
116672 token('oauth_request_token_secret', '');
116674 }; // TODO: detect lack of click event
116677 oauth.authenticate = function (callback) {
116678 if (oauth.authenticated()) return callback();
116679 oauth.logout(); // ## Getting a request token
116681 var params = timenonce(getAuth(o)),
116682 url = o.url + '/oauth/request_token';
116683 params.oauth_signature = ohauth.signature(o.oauth_secret, '', ohauth.baseString('POST', url, params));
116686 // Create a 600x550 popup window in the center of the screen
116689 settings = [['width', w], ['height', h], ['left', screen.width / 2 - w / 2], ['top', screen.height / 2 - h / 2]].map(function (x) {
116692 popup = window.open('about:blank', 'oauth_window', settings);
116693 oauth.popupWindow = popup;
116696 var error = new Error('Popup was blocked');
116697 error.status = 'popup-blocked';
116700 } // Request a request token. When this is complete, the popup
116701 // window is redirected to OSM's authorization page.
116704 ohauth.xhr('POST', url, params, null, {}, reqTokenDone);
116707 function reqTokenDone(err, xhr) {
116709 if (err) return callback(err);
116710 var resp = ohauth.stringQs(xhr.response);
116711 token('oauth_request_token_secret', resp.oauth_token_secret);
116712 var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
116713 oauth_token: resp.oauth_token,
116714 oauth_callback: resolveUrl(o.landing)
116718 location.href = authorize_url;
116720 popup.location = authorize_url;
116722 } // Called by a function in a landing page, in the popup window. The
116723 // window closes itself.
116726 window.authComplete = function (token) {
116727 var oauth_token = ohauth.stringQs(token.split('?')[1]);
116728 get_access_token(oauth_token.oauth_token);
116729 delete window.authComplete;
116730 }; // ## Getting an request token
116732 // At this point we have an `oauth_token`, brought in from a function
116733 // call on a landing page popup.
116736 function get_access_token(oauth_token) {
116737 var url = o.url + '/oauth/access_token',
116738 params = timenonce(getAuth(o)),
116739 request_token_secret = token('oauth_request_token_secret');
116740 params.oauth_token = oauth_token;
116741 params.oauth_signature = ohauth.signature(o.oauth_secret, request_token_secret, ohauth.baseString('POST', url, params)); // ## Getting an access token
116743 // The final token required for authentication. At this point
116744 // we have a `request token secret`
116746 ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
116750 function accessTokenDone(err, xhr) {
116752 if (err) return callback(err);
116753 var access_token = ohauth.stringQs(xhr.response);
116754 token('oauth_token', access_token.oauth_token);
116755 token('oauth_token_secret', access_token.oauth_token_secret);
116760 oauth.bringPopupWindowToFront = function () {
116761 var brougtPopupToFront = false;
116764 // This may cause a cross-origin error:
116765 // `DOMException: Blocked a frame with origin "..." from accessing a cross-origin frame.`
116766 if (oauth.popupWindow && !oauth.popupWindow.closed) {
116767 oauth.popupWindow.focus();
116768 brougtPopupToFront = true;
116770 } catch (err) {// Bringing popup window to front failed (probably because of the cross-origin error mentioned above)
116773 return brougtPopupToFront;
116776 oauth.bootstrapToken = function (oauth_token, callback) {
116777 // ## Getting an request token
116778 // At this point we have an `oauth_token`, brought in from a function
116779 // call on a landing page popup.
116780 function get_access_token(oauth_token) {
116781 var url = o.url + '/oauth/access_token',
116782 params = timenonce(getAuth(o)),
116783 request_token_secret = token('oauth_request_token_secret');
116784 params.oauth_token = oauth_token;
116785 params.oauth_signature = ohauth.signature(o.oauth_secret, request_token_secret, ohauth.baseString('POST', url, params)); // ## Getting an access token
116786 // The final token required for authentication. At this point
116787 // we have a `request token secret`
116789 ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
116793 function accessTokenDone(err, xhr) {
116795 if (err) return callback(err);
116796 var access_token = ohauth.stringQs(xhr.response);
116797 token('oauth_token', access_token.oauth_token);
116798 token('oauth_token_secret', access_token.oauth_token_secret);
116802 get_access_token(oauth_token);
116805 // A single XMLHttpRequest wrapper that does authenticated calls if the
116809 oauth.xhr = function (options, callback) {
116810 if (!oauth.authenticated()) {
116812 return oauth.authenticate(run);
116814 callback('not authenticated', null);
116822 var params = timenonce(getAuth(o)),
116823 oauth_token_secret = token('oauth_token_secret'),
116824 url = options.prefix !== false ? o.url + options.path : options.path,
116825 url_parts = url.replace(/#.*$/, '').split('?', 2),
116826 base_url = url_parts[0],
116827 query = url_parts.length === 2 ? url_parts[1] : ''; // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
116829 if ((!options.options || !options.options.header || options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') && options.content) {
116830 params = xtend(params, ohauth.stringQs(options.content));
116833 params.oauth_token = token('oauth_token');
116834 params.oauth_signature = ohauth.signature(o.oauth_secret, oauth_token_secret, ohauth.baseString(options.method, base_url, xtend(params, ohauth.stringQs(query))));
116835 return ohauth.xhr(options.method, url, params, options.content, options.options, done);
116838 function done(err, xhr) {
116839 if (err) return callback(err);else if (xhr.responseXML) return callback(err, xhr.responseXML);else return callback(err, xhr.response);
116841 }; // pre-authorize this object, if we can just get a token and token_secret
116845 oauth.preauth = function (c) {
116847 if (c.oauth_token) token('oauth_token', c.oauth_token);
116848 if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
116852 oauth.options = function (_) {
116853 if (!arguments.length) return o;
116855 o.url = o.url || 'https://www.openstreetmap.org';
116856 o.landing = o.landing || 'land.html';
116857 o.singlepage = o.singlepage || false; // Optional loading and loading-done functions for nice UI feedback.
116860 o.loading = o.loading || function () {};
116862 o.done = o.done || function () {};
116864 return oauth.preauth(o);
116865 }; // 'stamp' an authentication object from `getAuth()`
116866 // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
116870 function timenonce(o) {
116871 o.oauth_timestamp = ohauth.timestamp();
116872 o.oauth_nonce = ohauth.nonce();
116874 } // get/set tokens. These are prefixed with the base URL so that `osm-auth`
116875 // can be used with multiple APIs and the keys in `localStorage`
116882 token = function token(x, y) {
116883 if (arguments.length === 1) return store.get(o.url + x);else if (arguments.length === 2) return store.set(o.url + x, y);
116888 token = function token(x, y) {
116889 if (arguments.length === 1) return storage[o.url + x];else if (arguments.length === 2) return storage[o.url + x] = y;
116891 } // Get an authentication object. If you just add and remove properties
116892 // from a single object, you'll need to use `delete` to make sure that
116893 // it doesn't contain undesired properties for authentication
116898 oauth_consumer_key: o.oauth_consumer_key,
116899 oauth_signature_method: 'HMAC-SHA1'
116901 } // potentially pre-authorize
116908 var tiler$2 = utilTiler();
116909 var dispatch$2 = dispatch$8('apiStatusChange', 'authLoading', 'authDone', 'change', 'loading', 'loaded', 'loadedNotes');
116910 var urlroot = 'https://www.openstreetmap.org';
116913 oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
116914 oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
116917 }); // hardcode default block of Google Maps
116919 var _imageryBlocklists = [/.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/];
116945 var _deferred = new Set();
116957 var _off; // set a default but also load this from the API status
116960 var _maxWayNodes = 2000;
116962 function authLoading() {
116963 dispatch$2.call('authLoading');
116967 dispatch$2.call('authDone');
116970 function abortRequest$2(controllerOrXHR) {
116972 controllerOrXHR.abort();
116976 function hasInflightRequests(cache) {
116977 return Object.keys(cache.inflight).length;
116980 function abortUnwantedRequests(cache, visibleTiles) {
116981 Object.keys(cache.inflight).forEach(function (k) {
116982 if (cache.toLoad[k]) return;
116983 if (visibleTiles.find(function (tile) {
116986 abortRequest$2(cache.inflight[k]);
116987 delete cache.inflight[k];
116991 function getLoc(attrs) {
116992 var lon = attrs.lon && attrs.lon.value;
116993 var lat = attrs.lat && attrs.lat.value;
116994 return [parseFloat(lon), parseFloat(lat)];
116997 function getNodes(obj) {
116998 var elems = obj.getElementsByTagName('nd');
116999 var nodes = new Array(elems.length);
117001 for (var i = 0, l = elems.length; i < l; i++) {
117002 nodes[i] = 'n' + elems[i].attributes.ref.value;
117008 function getNodesJSON(obj) {
117010 var nodes = new Array(elems.length);
117012 for (var i = 0, l = elems.length; i < l; i++) {
117013 nodes[i] = 'n' + elems[i];
117019 function getTags(obj) {
117020 var elems = obj.getElementsByTagName('tag');
117023 for (var i = 0, l = elems.length; i < l; i++) {
117024 var attrs = elems[i].attributes;
117025 tags[attrs.k.value] = attrs.v.value;
117031 function getMembers(obj) {
117032 var elems = obj.getElementsByTagName('member');
117033 var members = new Array(elems.length);
117035 for (var i = 0, l = elems.length; i < l; i++) {
117036 var attrs = elems[i].attributes;
117038 id: attrs.type.value[0] + attrs.ref.value,
117039 type: attrs.type.value,
117047 function getMembersJSON(obj) {
117048 var elems = obj.members;
117049 var members = new Array(elems.length);
117051 for (var i = 0, l = elems.length; i < l; i++) {
117054 id: attrs.type[0] + attrs.ref,
117063 function getVisible(attrs) {
117064 return !attrs.visible || attrs.visible.value !== 'false';
117067 function parseComments(comments) {
117068 var parsedComments = []; // for each comment
117070 for (var i = 0; i < comments.length; i++) {
117071 var comment = comments[i];
117073 if (comment.nodeName === 'comment') {
117074 var childNodes = comment.childNodes;
117075 var parsedComment = {};
117077 for (var j = 0; j < childNodes.length; j++) {
117078 var node = childNodes[j];
117079 var nodeName = node.nodeName;
117080 if (nodeName === '#text') continue;
117081 parsedComment[nodeName] = node.textContent;
117083 if (nodeName === 'uid') {
117084 var uid = node.textContent;
117086 if (uid && !_userCache.user[uid]) {
117087 _userCache.toLoad[uid] = true;
117093 parsedComments.push(parsedComment);
117101 function encodeNoteRtree(note) {
117112 node: function nodeData(obj, uid) {
117115 visible: typeof obj.visible === 'boolean' ? obj.visible : true,
117116 version: obj.version && obj.version.toString(),
117117 changeset: obj.changeset && obj.changeset.toString(),
117118 timestamp: obj.timestamp,
117120 uid: obj.uid && obj.uid.toString(),
117121 loc: [parseFloat(obj.lon), parseFloat(obj.lat)],
117125 way: function wayData(obj, uid) {
117128 visible: typeof obj.visible === 'boolean' ? obj.visible : true,
117129 version: obj.version && obj.version.toString(),
117130 changeset: obj.changeset && obj.changeset.toString(),
117131 timestamp: obj.timestamp,
117133 uid: obj.uid && obj.uid.toString(),
117135 nodes: getNodesJSON(obj)
117138 relation: function relationData(obj, uid) {
117139 return new osmRelation({
117141 visible: typeof obj.visible === 'boolean' ? obj.visible : true,
117142 version: obj.version && obj.version.toString(),
117143 changeset: obj.changeset && obj.changeset.toString(),
117144 timestamp: obj.timestamp,
117146 uid: obj.uid && obj.uid.toString(),
117148 members: getMembersJSON(obj)
117151 user: function parseUser(obj, uid) {
117154 display_name: obj.display_name,
117155 account_created: obj.account_created,
117156 image_url: obj.img && obj.img.href,
117157 changesets_count: obj.changesets && obj.changesets.count && obj.changesets.count.toString() || '0',
117158 active_blocks: obj.blocks && obj.blocks.received && obj.blocks.received.active && obj.blocks.received.active.toString() || '0'
117163 function parseJSON(payload, callback, options) {
117164 options = Object.assign({
117176 if (_typeof(json) !== 'object') json = JSON.parse(payload);
117177 if (!json.elements) return callback({
117181 var children = json.elements;
117182 var handle = window.requestIdleCallback(function () {
117183 _deferred["delete"](handle);
117188 for (var i = 0; i < children.length; i++) {
117189 result = parseChild(children[i]);
117190 if (result) results.push(result);
117193 callback(null, results);
117198 function parseChild(child) {
117199 var parser = jsonparsers[child.type];
117200 if (!parser) return null;
117202 uid = osmEntity.id.fromOSM(child.type, child.id);
117204 if (options.skipSeen) {
117205 if (_tileCache.seen[uid]) return null; // avoid reparsing a "seen" entity
117207 _tileCache.seen[uid] = true;
117210 return parser(child, uid);
117214 function parseUserJSON(payload, callback, options) {
117215 options = Object.assign({
117227 if (_typeof(json) !== 'object') json = JSON.parse(payload);
117228 if (!json.users && !json.user) return callback({
117232 var objs = json.users || [json];
117233 var handle = window.requestIdleCallback(function () {
117234 _deferred["delete"](handle);
117239 for (var i = 0; i < objs.length; i++) {
117240 result = parseObj(objs[i]);
117241 if (result) results.push(result);
117244 callback(null, results);
117249 function parseObj(obj) {
117250 var uid = obj.user.id && obj.user.id.toString();
117252 if (options.skipSeen && _userCache.user[uid]) {
117253 delete _userCache.toLoad[uid];
117257 var user = jsonparsers.user(obj.user, uid);
117258 _userCache.user[uid] = user;
117259 delete _userCache.toLoad[uid];
117265 node: function nodeData(obj, uid) {
117266 var attrs = obj.attributes;
117269 visible: getVisible(attrs),
117270 version: attrs.version.value,
117271 changeset: attrs.changeset && attrs.changeset.value,
117272 timestamp: attrs.timestamp && attrs.timestamp.value,
117273 user: attrs.user && attrs.user.value,
117274 uid: attrs.uid && attrs.uid.value,
117279 way: function wayData(obj, uid) {
117280 var attrs = obj.attributes;
117283 visible: getVisible(attrs),
117284 version: attrs.version.value,
117285 changeset: attrs.changeset && attrs.changeset.value,
117286 timestamp: attrs.timestamp && attrs.timestamp.value,
117287 user: attrs.user && attrs.user.value,
117288 uid: attrs.uid && attrs.uid.value,
117293 relation: function relationData(obj, uid) {
117294 var attrs = obj.attributes;
117295 return new osmRelation({
117297 visible: getVisible(attrs),
117298 version: attrs.version.value,
117299 changeset: attrs.changeset && attrs.changeset.value,
117300 timestamp: attrs.timestamp && attrs.timestamp.value,
117301 user: attrs.user && attrs.user.value,
117302 uid: attrs.uid && attrs.uid.value,
117304 members: getMembers(obj)
117307 note: function parseNote(obj, uid) {
117308 var attrs = obj.attributes;
117309 var childNodes = obj.childNodes;
117312 props.loc = getLoc(attrs); // if notes are coincident, move them apart slightly
117314 var coincident = false;
117319 props.loc = geoVecAdd(props.loc, [epsilon, epsilon]);
117322 var bbox = geoExtent(props.loc).bbox();
117323 coincident = _noteCache.rtree.search(bbox).length;
117324 } while (coincident); // parse note contents
117327 for (var i = 0; i < childNodes.length; i++) {
117328 var node = childNodes[i];
117329 var nodeName = node.nodeName;
117330 if (nodeName === '#text') continue; // if the element is comments, parse the comments
117332 if (nodeName === 'comments') {
117333 props[nodeName] = parseComments(node.childNodes);
117335 props[nodeName] = node.textContent;
117339 var note = new osmNote(props);
117340 var item = encodeNoteRtree(note);
117341 _noteCache.note[note.id] = note;
117343 _noteCache.rtree.insert(item);
117347 user: function parseUser(obj, uid) {
117348 var attrs = obj.attributes;
117351 display_name: attrs.display_name && attrs.display_name.value,
117352 account_created: attrs.account_created && attrs.account_created.value,
117356 var img = obj.getElementsByTagName('img');
117358 if (img && img[0] && img[0].getAttribute('href')) {
117359 user.image_url = img[0].getAttribute('href');
117362 var changesets = obj.getElementsByTagName('changesets');
117364 if (changesets && changesets[0] && changesets[0].getAttribute('count')) {
117365 user.changesets_count = changesets[0].getAttribute('count');
117368 var blocks = obj.getElementsByTagName('blocks');
117370 if (blocks && blocks[0]) {
117371 var received = blocks[0].getElementsByTagName('received');
117373 if (received && received[0] && received[0].getAttribute('active')) {
117374 user.active_blocks = received[0].getAttribute('active');
117378 _userCache.user[uid] = user;
117379 delete _userCache.toLoad[uid];
117384 function parseXML(xml, callback, options) {
117385 options = Object.assign({
117389 if (!xml || !xml.childNodes) {
117396 var root = xml.childNodes[0];
117397 var children = root.childNodes;
117398 var handle = window.requestIdleCallback(function () {
117399 _deferred["delete"](handle);
117404 for (var i = 0; i < children.length; i++) {
117405 result = parseChild(children[i]);
117406 if (result) results.push(result);
117409 callback(null, results);
117414 function parseChild(child) {
117415 var parser = parsers[child.nodeName];
117416 if (!parser) return null;
117419 if (child.nodeName === 'user') {
117420 uid = child.attributes.id.value;
117422 if (options.skipSeen && _userCache.user[uid]) {
117423 delete _userCache.toLoad[uid];
117426 } else if (child.nodeName === 'note') {
117427 uid = child.getElementsByTagName('id')[0].textContent;
117429 uid = osmEntity.id.fromOSM(child.nodeName, child.attributes.id.value);
117431 if (options.skipSeen) {
117432 if (_tileCache.seen[uid]) return null; // avoid reparsing a "seen" entity
117434 _tileCache.seen[uid] = true;
117438 return parser(child, uid);
117440 } // replace or remove note from rtree
117443 function updateRtree(item, replace) {
117444 _noteCache.rtree.remove(item, function isEql(a, b) {
117445 return a.data.id === b.data.id;
117449 _noteCache.rtree.insert(item);
117453 function wrapcb(thisArg, callback, cid) {
117454 return function (err, result) {
117456 // 400 Bad Request, 401 Unauthorized, 403 Forbidden..
117457 if (err.status === 400 || err.status === 401 || err.status === 403) {
117461 return callback.call(thisArg, err);
117462 } else if (thisArg.getConnectionId() !== cid) {
117463 return callback.call(thisArg, {
117464 message: 'Connection Switched',
117468 return callback.call(thisArg, err, result);
117474 init: function init() {
117475 utilRebind(this, dispatch$2, 'on');
117477 reset: function reset() {
117478 Array.from(_deferred).forEach(function (handle) {
117479 window.cancelIdleCallback(handle);
117481 _deferred["delete"](handle);
117484 _userChangesets = undefined;
117485 _userDetails = undefined;
117486 _rateLimitError = undefined;
117487 Object.values(_tileCache.inflight).forEach(abortRequest$2);
117488 Object.values(_noteCache.inflight).forEach(abortRequest$2);
117489 Object.values(_noteCache.inflightPost).forEach(abortRequest$2);
117490 if (_changeset.inflight) abortRequest$2(_changeset.inflight);
117511 _cachedApiStatus = undefined;
117515 getConnectionId: function getConnectionId() {
117518 changesetURL: function changesetURL(changesetID) {
117519 return urlroot + '/changeset/' + changesetID;
117521 changesetsURL: function changesetsURL(center, zoom) {
117522 var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
117523 return urlroot + '/history#map=' + Math.floor(zoom) + '/' + center[1].toFixed(precision) + '/' + center[0].toFixed(precision);
117525 entityURL: function entityURL(entity) {
117526 return urlroot + '/' + entity.type + '/' + entity.osmId();
117528 historyURL: function historyURL(entity) {
117529 return urlroot + '/' + entity.type + '/' + entity.osmId() + '/history';
117531 userURL: function userURL(username) {
117532 return urlroot + '/user/' + encodeURIComponent(username);
117534 noteURL: function noteURL(note) {
117535 return urlroot + '/note/' + note.id;
117537 noteReportURL: function noteReportURL(note) {
117538 return urlroot + '/reports/new?reportable_type=Note&reportable_id=' + note.id;
117540 // Generic method to load data from the OSM API
117541 // Can handle either auth or unauth calls.
117542 loadFromAPI: function loadFromAPI(path, callback, options) {
117543 options = Object.assign({
117547 var cid = _connectionID;
117549 function done(err, payload) {
117550 if (that.getConnectionId() !== cid) {
117551 if (callback) callback({
117552 message: 'Connection Switched',
117558 var isAuthenticated = that.authenticated(); // 400 Bad Request, 401 Unauthorized, 403 Forbidden
117559 // Logout and retry the request..
117561 if (isAuthenticated && err && err.status && (err.status === 400 || err.status === 401 || err.status === 403)) {
117563 that.loadFromAPI(path, callback, options); // else, no retry..
117565 // 509 Bandwidth Limit Exceeded, 429 Too Many Requests
117566 // Set the rateLimitError flag and trigger a warning..
117567 if (!isAuthenticated && !_rateLimitError && err && err.status && (err.status === 509 || err.status === 429)) {
117569 dispatch$2.call('change');
117570 that.reloadApiStatus();
117571 } else if (err && _cachedApiStatus === 'online' || !err && _cachedApiStatus !== 'online') {
117572 // If the response's error state doesn't match the status,
117573 // it's likely we lost or gained the connection so reload the status
117574 that.reloadApiStatus();
117581 if (path.indexOf('.json') !== -1) {
117582 return parseJSON(payload, callback, options);
117584 return parseXML(payload, callback, options);
117591 if (this.authenticated()) {
117597 var url = urlroot + path;
117598 var controller = new AbortController();
117601 if (path.indexOf('.json') !== -1) {
117608 signal: controller.signal
117609 }).then(function (data) {
117611 })["catch"](function (err) {
117612 if (err.name === 'AbortError') return; // d3-fetch includes status in the error message,
117613 // but we can't access the response itself
117614 // https://github.com/d3/d3-fetch/issues/27
117616 var match = err.message.match(/^\d{3}/);
117621 statusText: err.message
117630 // Load a single entity by id (ways and relations use the `/full` call to include
117631 // nodes and members). Parent relations are not included, see `loadEntityRelations`.
117632 // GET /api/0.6/node/#id
117633 // GET /api/0.6/[way|relation]/#id/full
117634 loadEntity: function loadEntity(id, callback) {
117635 var type = osmEntity.id.type(id);
117636 var osmID = osmEntity.id.toOSM(id);
117640 this.loadFromAPI('/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : '') + '.json', function (err, entities) {
117641 if (callback) callback(err, {
117646 // Load a single entity with a specific version
117647 // GET /api/0.6/[node|way|relation]/#id/#version
117648 loadEntityVersion: function loadEntityVersion(id, version, callback) {
117649 var type = osmEntity.id.type(id);
117650 var osmID = osmEntity.id.toOSM(id);
117654 this.loadFromAPI('/api/0.6/' + type + '/' + osmID + '/' + version + '.json', function (err, entities) {
117655 if (callback) callback(err, {
117660 // Load the relations of a single entity with the given.
117661 // GET /api/0.6/[node|way|relation]/#id/relations
117662 loadEntityRelations: function loadEntityRelations(id, callback) {
117663 var type = osmEntity.id.type(id);
117664 var osmID = osmEntity.id.toOSM(id);
117668 this.loadFromAPI('/api/0.6/' + type + '/' + osmID + '/relations.json', function (err, entities) {
117669 if (callback) callback(err, {
117674 // Load multiple entities in chunks
117675 // (note: callback may be called multiple times)
117676 // Unlike `loadEntity`, child nodes and members are not fetched
117677 // GET /api/0.6/[nodes|ways|relations]?#parameters
117678 loadMultiple: function loadMultiple(ids, callback) {
117680 var groups = utilArrayGroupBy(utilArrayUniq(ids), osmEntity.id.type);
117681 Object.keys(groups).forEach(function (k) {
117682 var type = k + 's'; // nodes, ways, relations
117684 var osmIDs = groups[k].map(function (id) {
117685 return osmEntity.id.toOSM(id);
117690 utilArrayChunk(osmIDs, 150).forEach(function (arr) {
117691 that.loadFromAPI('/api/0.6/' + type + '.json?' + type + '=' + arr.join(), function (err, entities) {
117692 if (callback) callback(err, {
117699 // Create, upload, and close a changeset
117700 // PUT /api/0.6/changeset/create
117701 // POST /api/0.6/changeset/#id/upload
117702 // PUT /api/0.6/changeset/#id/close
117703 putChangeset: function putChangeset(changeset, changes, callback) {
117704 var cid = _connectionID;
117706 if (_changeset.inflight) {
117708 message: 'Changeset already inflight',
117711 } else if (_changeset.open) {
117712 // reuse existing open changeset..
117713 return createdChangeset.call(this, null, _changeset.open);
117715 // Open a new changeset..
117718 path: '/api/0.6/changeset/create',
117721 'Content-Type': 'text/xml'
117724 content: JXON.stringify(changeset.asJXON())
117726 _changeset.inflight = oauth.xhr(options, wrapcb(this, createdChangeset, cid));
117729 function createdChangeset(err, changesetID) {
117730 _changeset.inflight = null;
117733 return callback(err, changeset);
117736 _changeset.open = changesetID;
117737 changeset = changeset.update({
117739 }); // Upload the changeset..
117743 path: '/api/0.6/changeset/' + changesetID + '/upload',
117746 'Content-Type': 'text/xml'
117749 content: JXON.stringify(changeset.osmChangeJXON(changes))
117751 _changeset.inflight = oauth.xhr(options, wrapcb(this, uploadedChangeset, cid));
117754 function uploadedChangeset(err) {
117755 _changeset.inflight = null;
117756 if (err) return callback(err, changeset); // Upload was successful, safe to call the callback.
117757 // Add delay to allow for postgres replication #1646 #2678
117759 window.setTimeout(function () {
117760 callback(null, changeset);
117762 _changeset.open = null; // At this point, we don't really care if the connection was switched..
117763 // Only try to close the changeset if we're still talking to the same server.
117765 if (this.getConnectionId() === cid) {
117766 // Still attempt to close changeset, but ignore response because #2667
117769 path: '/api/0.6/changeset/' + changeset.id + '/close',
117772 'Content-Type': 'text/xml'
117781 // Load multiple users in chunks
117782 // (note: callback may be called multiple times)
117783 // GET /api/0.6/users?users=#id1,#id2,...,#idn
117784 loadUsers: function loadUsers(uids, callback) {
117787 utilArrayUniq(uids).forEach(function (uid) {
117788 if (_userCache.user[uid]) {
117789 delete _userCache.toLoad[uid];
117790 cached.push(_userCache.user[uid]);
117796 if (cached.length || !this.authenticated()) {
117797 callback(undefined, cached);
117798 if (!this.authenticated()) return; // require auth
117801 utilArrayChunk(toLoad, 150).forEach(function (arr) {
117804 path: '/api/0.6/users.json?users=' + arr.join()
117805 }, wrapcb(this, done, _connectionID));
117808 function done(err, payload) {
117809 if (err) return callback(err);
117813 return parseUserJSON(payload, function (err, results) {
117814 if (err) return callback(err);
117815 return callback(undefined, results);
117819 // Load a given user by id
117820 // GET /api/0.6/user/#id
117821 loadUser: function loadUser(uid, callback) {
117822 if (_userCache.user[uid] || !this.authenticated()) {
117824 delete _userCache.toLoad[uid];
117825 return callback(undefined, _userCache.user[uid]);
117830 path: '/api/0.6/user/' + uid + '.json'
117831 }, wrapcb(this, done, _connectionID));
117833 function done(err, payload) {
117834 if (err) return callback(err);
117838 return parseUserJSON(payload, function (err, results) {
117839 if (err) return callback(err);
117840 return callback(undefined, results[0]);
117844 // Load the details of the logged-in user
117845 // GET /api/0.6/user/details
117846 userDetails: function userDetails(callback) {
117849 return callback(undefined, _userDetails);
117854 path: '/api/0.6/user/details.json'
117855 }, wrapcb(this, done, _connectionID));
117857 function done(err, payload) {
117858 if (err) return callback(err);
117862 return parseUserJSON(payload, function (err, results) {
117863 if (err) return callback(err);
117864 _userDetails = results[0];
117865 return callback(undefined, _userDetails);
117869 // Load previous changesets for the logged in user
117870 // GET /api/0.6/changesets?user=#id
117871 userChangesets: function userChangesets(callback) {
117874 return callback(undefined, _userChangesets);
117877 this.userDetails(wrapcb(this, gotDetails, _connectionID));
117879 function gotDetails(err, user) {
117886 path: '/api/0.6/changesets?user=' + user.id
117887 }, wrapcb(this, done, _connectionID));
117890 function done(err, xml) {
117895 _userChangesets = Array.prototype.map.call(xml.getElementsByTagName('changeset'), function (changeset) {
117897 tags: getTags(changeset)
117899 }).filter(function (changeset) {
117900 var comment = changeset.tags.comment;
117901 return comment && comment !== '';
117903 return callback(undefined, _userChangesets);
117906 // Fetch the status of the OSM API
117907 // GET /api/capabilities
117908 status: function status(callback) {
117909 var url = urlroot + '/api/capabilities';
117910 var errback = wrapcb(this, done, _connectionID);
117911 d3_xml(url).then(function (data) {
117913 })["catch"](function (err) {
117917 function done(err, xml) {
117919 // the status is null if no response could be retrieved
117920 return callback(err, null);
117924 var elements = xml.getElementsByTagName('blacklist');
117927 for (var i = 0; i < elements.length; i++) {
117928 var regexString = elements[i].getAttribute('regex'); // needs unencode?
117932 var regex = new RegExp(regexString);
117941 _imageryBlocklists = regexes;
117945 return callback(_rateLimitError, 'rateLimited');
117947 var waynodes = xml.getElementsByTagName('waynodes');
117948 var maxWayNodes = waynodes.length && parseInt(waynodes[0].getAttribute('maximum'), 10);
117949 if (maxWayNodes && isFinite(maxWayNodes)) _maxWayNodes = maxWayNodes;
117950 var apiStatus = xml.getElementsByTagName('status');
117951 var val = apiStatus[0].getAttribute('api');
117952 return callback(undefined, val);
117956 // Calls `status` and dispatches an `apiStatusChange` event if the returned
117957 // status differs from the cached status.
117958 reloadApiStatus: function reloadApiStatus() {
117959 // throttle to avoid unnecessary API calls
117960 if (!this.throttledReloadApiStatus) {
117962 this.throttledReloadApiStatus = throttle(function () {
117963 that.status(function (err, status) {
117964 if (status !== _cachedApiStatus) {
117965 _cachedApiStatus = status;
117966 dispatch$2.call('apiStatusChange', that, err, status);
117972 this.throttledReloadApiStatus();
117974 // Returns the maximum number of nodes a single way can have
117975 maxWayNodes: function maxWayNodes() {
117978 // Load data (entities) from the API in tiles
117979 // GET /api/0.6/map?bbox=
117980 loadTiles: function loadTiles(projection, callback) {
117981 if (_off) return; // determine the needed tiles to cover the view
117983 var tiles = tiler$2.zoomExtent([_tileZoom, _tileZoom]).getTiles(projection); // abort inflight requests that are no longer needed
117985 var hadRequests = hasInflightRequests(_tileCache);
117986 abortUnwantedRequests(_tileCache, tiles);
117988 if (hadRequests && !hasInflightRequests(_tileCache)) {
117989 dispatch$2.call('loaded'); // stop the spinner
117990 } // issue new requests..
117993 tiles.forEach(function (tile) {
117994 this.loadTile(tile, callback);
117997 // Load a single data tile
117998 // GET /api/0.6/map?bbox=
117999 loadTile: function loadTile(tile, callback) {
118001 if (_tileCache.loaded[tile.id] || _tileCache.inflight[tile.id]) return;
118003 if (!hasInflightRequests(_tileCache)) {
118004 dispatch$2.call('loading'); // start the spinner
118007 var path = '/api/0.6/map.json?bbox=';
118011 _tileCache.inflight[tile.id] = this.loadFromAPI(path + tile.extent.toParam(), tileCallback, options);
118013 function tileCallback(err, parsed) {
118014 delete _tileCache.inflight[tile.id];
118017 delete _tileCache.toLoad[tile.id];
118018 _tileCache.loaded[tile.id] = true;
118019 var bbox = tile.extent.bbox();
118022 _tileCache.rtree.insert(bbox);
118026 callback(err, Object.assign({
118031 if (!hasInflightRequests(_tileCache)) {
118032 dispatch$2.call('loaded'); // stop the spinner
118036 isDataLoaded: function isDataLoaded(loc) {
118043 return _tileCache.rtree.collides(bbox);
118045 // load the tile that covers the given `loc`
118046 loadTileAtLoc: function loadTileAtLoc(loc, callback) {
118047 // Back off if the toLoad queue is filling up.. re #6417
118048 // (Currently `loadTileAtLoc` requests are considered low priority - used by operations to
118049 // let users safely edit geometries which extend to unloaded tiles. We can drop some.)
118050 if (Object.keys(_tileCache.toLoad).length > 50) return;
118051 var k = geoZoomToScale(_tileZoom + 1);
118052 var offset = geoRawMercator().scale(k)(loc);
118053 var projection = geoRawMercator().transform({
118058 var tiles = tiler$2.zoomExtent([_tileZoom, _tileZoom]).getTiles(projection);
118059 tiles.forEach(function (tile) {
118060 if (_tileCache.toLoad[tile.id] || _tileCache.loaded[tile.id] || _tileCache.inflight[tile.id]) return;
118061 _tileCache.toLoad[tile.id] = true;
118062 this.loadTile(tile, callback);
118065 // Load notes from the API in tiles
118066 // GET /api/0.6/notes?bbox=
118067 loadNotes: function loadNotes(projection, noteOptions) {
118068 noteOptions = Object.assign({
118074 var path = '/api/0.6/notes?limit=' + noteOptions.limit + '&closed=' + noteOptions.closed + '&bbox=';
118076 var throttleLoadUsers = throttle(function () {
118077 var uids = Object.keys(_userCache.toLoad);
118078 if (!uids.length) return;
118079 that.loadUsers(uids, function () {}); // eagerly load user details
118080 }, 750); // determine the needed tiles to cover the view
118083 var tiles = tiler$2.zoomExtent([_noteZoom, _noteZoom]).getTiles(projection); // abort inflight requests that are no longer needed
118085 abortUnwantedRequests(_noteCache, tiles); // issue new requests..
118087 tiles.forEach(function (tile) {
118088 if (_noteCache.loaded[tile.id] || _noteCache.inflight[tile.id]) return;
118092 _noteCache.inflight[tile.id] = that.loadFromAPI(path + tile.extent.toParam(), function (err) {
118093 delete _noteCache.inflight[tile.id];
118096 _noteCache.loaded[tile.id] = true;
118100 dispatch$2.call('loadedNotes');
118105 // POST /api/0.6/notes?params
118106 postNoteCreate: function postNoteCreate(note, callback) {
118107 if (!this.authenticated()) {
118109 message: 'Not Authenticated',
118114 if (_noteCache.inflightPost[note.id]) {
118116 message: 'Note update already inflight',
118121 if (!note.loc[0] || !note.loc[1] || !note.newComment) return; // location & description required
118123 var comment = note.newComment;
118125 if (note.newCategory && note.newCategory !== 'None') {
118126 comment += ' #' + note.newCategory;
118129 var path = '/api/0.6/notes?' + utilQsString({
118134 _noteCache.inflightPost[note.id] = oauth.xhr({
118137 }, wrapcb(this, done, _connectionID));
118139 function done(err, xml) {
118140 delete _noteCache.inflightPost[note.id];
118144 } // we get the updated note back, remove from caches and reparse..
118151 return parseXML(xml, function (err, results) {
118155 return callback(undefined, results[0]);
118161 // POST /api/0.6/notes/#id/comment?text=comment
118162 // POST /api/0.6/notes/#id/close?text=comment
118163 // POST /api/0.6/notes/#id/reopen?text=comment
118164 postNoteUpdate: function postNoteUpdate(note, newStatus, callback) {
118165 if (!this.authenticated()) {
118167 message: 'Not Authenticated',
118172 if (_noteCache.inflightPost[note.id]) {
118174 message: 'Note update already inflight',
118181 if (note.status !== 'closed' && newStatus === 'closed') {
118183 } else if (note.status !== 'open' && newStatus === 'open') {
118187 if (!note.newComment) return; // when commenting, comment required
118190 var path = '/api/0.6/notes/' + note.id + '/' + action;
118193 path += '?' + utilQsString({
118198 _noteCache.inflightPost[note.id] = oauth.xhr({
118201 }, wrapcb(this, done, _connectionID));
118203 function done(err, xml) {
118204 delete _noteCache.inflightPost[note.id];
118208 } // we get the updated note back, remove from caches and reparse..
118211 this.removeNote(note); // update closed note cache - used to populate `closed:note` changeset tag
118213 if (action === 'close') {
118214 _noteCache.closed[note.id] = true;
118215 } else if (action === 'reopen') {
118216 delete _noteCache.closed[note.id];
118222 return parseXML(xml, function (err, results) {
118226 return callback(undefined, results[0]);
118231 "switch": function _switch(options) {
118232 urlroot = options.urlroot;
118233 oauth.options(Object.assign({
118239 this.userChangesets(function () {}); // eagerly load user details/changesets
118241 dispatch$2.call('change');
118244 toggle: function toggle(val) {
118248 isChangesetInflight: function isChangesetInflight() {
118249 return !!_changeset.inflight;
118252 // This is used to save/restore the state when entering/exiting the walkthrough
118253 // Also used for testing purposes.
118254 caches: function caches(obj) {
118255 function cloneCache(source) {
118257 Object.keys(source).forEach(function (k) {
118259 target.rtree = new RBush().fromJSON(source.rtree.toJSON()); // clone rbush
118260 } else if (k === 'note') {
118262 Object.keys(source.note).forEach(function (id) {
118263 target.note[id] = osmNote(source.note[id]); // copy notes
118266 target[k] = JSON.parse(JSON.stringify(source[k])); // clone deep
118272 if (!arguments.length) {
118274 tile: cloneCache(_tileCache),
118275 note: cloneCache(_noteCache),
118276 user: cloneCache(_userCache)
118278 } // access caches directly for testing (e.g., loading notes rtree)
118291 _tileCache.inflight = {};
118296 _noteCache.inflight = {};
118297 _noteCache.inflightPost = {};
118306 logout: function logout() {
118307 _userChangesets = undefined;
118308 _userDetails = undefined;
118310 dispatch$2.call('change');
118313 authenticated: function authenticated() {
118314 return oauth.authenticated();
118316 authenticate: function authenticate(callback) {
118318 var cid = _connectionID;
118319 _userChangesets = undefined;
118320 _userDetails = undefined;
118322 function done(err, res) {
118324 if (callback) callback(err);
118328 if (that.getConnectionId() !== cid) {
118329 if (callback) callback({
118330 message: 'Connection Switched',
118336 _rateLimitError = undefined;
118337 dispatch$2.call('change');
118338 if (callback) callback(err, res);
118339 that.userChangesets(function () {}); // eagerly load user details/changesets
118342 return oauth.authenticate(done);
118344 imageryBlocklists: function imageryBlocklists() {
118345 return _imageryBlocklists;
118347 tileZoom: function tileZoom(val) {
118348 if (!arguments.length) return _tileZoom;
118352 // get all cached notes covering the viewport
118353 notes: function notes(projection) {
118354 var viewport = projection.clipExtent();
118355 var min = [viewport[0][0], viewport[1][1]];
118356 var max = [viewport[1][0], viewport[0][1]];
118357 var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
118358 return _noteCache.rtree.search(bbox).map(function (d) {
118362 // get a single note from the cache
118363 getNote: function getNote(id) {
118364 return _noteCache.note[id];
118366 // remove a single note from the cache
118367 removeNote: function removeNote(note) {
118368 if (!(note instanceof osmNote) || !note.id) return;
118369 delete _noteCache.note[note.id];
118370 updateRtree(encodeNoteRtree(note), false); // false = remove
118372 // replace a single note in the cache
118373 replaceNote: function replaceNote(note) {
118374 if (!(note instanceof osmNote) || !note.id) return;
118375 _noteCache.note[note.id] = note;
118376 updateRtree(encodeNoteRtree(note), true); // true = replace
118380 // Get an array of note IDs closed during this session.
118381 // Used to populate `closed:note` changeset tag
118382 getClosedIDs: function getClosedIDs() {
118383 return Object.keys(_noteCache.closed).sort();
118387 var _apibase$1 = 'https://wiki.openstreetmap.org/w/api.php';
118389 var _wikibaseCache = {};
118394 var debouncedRequest$1 = debounce(request$1, 500, {
118398 function request$1(url, callback) {
118399 if (_inflight$1[url]) return;
118400 var controller = new AbortController();
118401 _inflight$1[url] = controller;
118403 signal: controller.signal
118404 }).then(function (result) {
118405 delete _inflight$1[url];
118406 if (callback) callback(null, result);
118407 })["catch"](function (err) {
118408 delete _inflight$1[url];
118409 if (err.name === 'AbortError') return;
118410 if (callback) callback(err.message);
118414 var serviceOsmWikibase = {
118415 init: function init() {
118420 reset: function reset() {
118421 Object.values(_inflight$1).forEach(function (controller) {
118428 * Get the best value for the property, or undefined if not found
118429 * @param entity object from wikibase
118430 * @param property string e.g. 'P4' for image
118431 * @param langCode string e.g. 'fr' for French
118433 claimToValue: function claimToValue(entity, property, langCode) {
118434 if (!entity.claims[property]) return undefined;
118435 var locale = _localeIDs[langCode];
118436 var preferredPick, localePick;
118437 entity.claims[property].forEach(function (stmt) {
118438 // If exists, use value limited to the needed language (has a qualifier P26 = locale)
118439 // Or if not found, use the first value with the "preferred" rank
118440 if (!preferredPick && stmt.rank === 'preferred') {
118444 if (locale && stmt.qualifiers && stmt.qualifiers.P26 && stmt.qualifiers.P26[0].datavalue.value.id === locale) {
118448 var result = localePick || preferredPick;
118451 var datavalue = result.mainsnak.datavalue;
118452 return datavalue.type === 'wikibase-entityid' ? datavalue.value.id : datavalue.value;
118459 * Convert monolingual property into a key-value object (language -> value)
118460 * @param entity object from wikibase
118461 * @param property string e.g. 'P31' for monolingual wiki page title
118463 monolingualClaimToValueObj: function monolingualClaimToValueObj(entity, property) {
118464 if (!entity || !entity.claims[property]) return undefined;
118465 return entity.claims[property].reduce(function (acc, obj) {
118466 var value = obj.mainsnak.datavalue.value;
118467 acc[value.language] = value.text;
118471 toSitelink: function toSitelink(key, value) {
118472 var result = value ? 'Tag:' + key + '=' + value : 'Key:' + key;
118473 return result.replace(/_/g, ' ').trim();
118476 // Pass params object of the form:
118483 getEntity: function getEntity(params, callback) {
118484 var doRequest = params.debounce ? debouncedRequest$1 : request$1;
118488 var rtypeSitelink = params.key === 'type' && params.value ? ('Relation:' + params.value).replace(/_/g, ' ').trim() : false;
118489 var keySitelink = params.key ? this.toSitelink(params.key) : false;
118490 var tagSitelink = params.key && params.value ? this.toSitelink(params.key, params.value) : false;
118493 if (params.langCodes) {
118494 params.langCodes.forEach(function (langCode) {
118495 if (_localeIDs[langCode] === undefined) {
118496 // If this is the first time we are asking about this locale,
118497 // fetch corresponding entity (if it exists), and cache it.
118498 // If there is no such entry, cache `false` value to avoid re-requesting it.
118499 localeSitelink = ('Locale:' + langCode).replace(/_/g, ' ').trim();
118500 titles.push(localeSitelink);
118506 if (_wikibaseCache[rtypeSitelink]) {
118507 result.rtype = _wikibaseCache[rtypeSitelink];
118509 titles.push(rtypeSitelink);
118514 if (_wikibaseCache[keySitelink]) {
118515 result.key = _wikibaseCache[keySitelink];
118517 titles.push(keySitelink);
118522 if (_wikibaseCache[tagSitelink]) {
118523 result.tag = _wikibaseCache[tagSitelink];
118525 titles.push(tagSitelink);
118530 // Nothing to do, we already had everything in the cache
118531 return callback(null, result);
118532 } // Requesting just the user language code
118533 // If backend recognizes the code, it will perform proper fallbacks,
118534 // and the result will contain the requested code. If not, all values are returned:
118535 // {"zh-tw":{"value":"...","language":"zh-tw","source-language":"zh-hant"}
118536 // {"pt-br":{"value":"...","language":"pt","for-language":"pt-br"}}
118540 action: 'wbgetentities',
118542 titles: titles.join('|'),
118543 languages: params.langCodes.join('|'),
118546 format: 'json' // There is an MW Wikibase API bug https://phabricator.wikimedia.org/T212069
118547 // We shouldn't use v1 until it gets fixed, but should switch to it afterwards
118551 var url = _apibase$1 + '?' + utilQsString(obj);
118552 doRequest(url, function (err, d) {
118555 } else if (!d.success || d.error) {
118556 callback(d.error.messages.map(function (v) {
118561 Object.values(d.entities).forEach(function (res) {
118562 if (res.missing !== '') {
118563 var title = res.sitelinks.wiki.title;
118565 if (title === rtypeSitelink) {
118566 _wikibaseCache[rtypeSitelink] = res;
118568 } else if (title === keySitelink) {
118569 _wikibaseCache[keySitelink] = res;
118571 } else if (title === tagSitelink) {
118572 _wikibaseCache[tagSitelink] = res;
118574 } else if (title === localeSitelink) {
118577 console.log('Unexpected title ' + title); // eslint-disable-line no-console
118583 // If locale ID is not found, store false to prevent repeated queries
118584 that.addLocale(params.langCodes[0], localeID);
118587 callback(null, result);
118592 // Pass params object of the form:
118594 // key: 'string', // required
118595 // value: 'string' // optional
118598 // Get an result object used to display tag documentation
118601 // description: 'string',
118604 // wiki: { title: 'string', text: 'string', url: 'string' }
118607 getDocs: function getDocs(params, callback) {
118609 var langCodes = _mainLocalizer.localeCodes().map(function (code) {
118610 return code.toLowerCase();
118612 params.langCodes = langCodes;
118613 this.getEntity(params, function (err, data) {
118619 var entity = data.rtype || data.tag || data.key;
118630 var _code = langCodes[i];
118632 if (entity.descriptions[_code] && entity.descriptions[_code].language === _code) {
118633 description = entity.descriptions[_code];
118638 if (!description && Object.values(entity.descriptions).length) description = Object.values(entity.descriptions)[0]; // prepare result
118642 description: description ? description.value : '',
118643 descriptionLocaleCode: description ? description.language : '',
118644 editURL: 'https://wiki.openstreetmap.org/wiki/' + entity.title
118649 var image = that.claimToValue(entity, 'P4', langCodes[0]);
118652 imageroot = 'https://commons.wikimedia.org/w/index.php';
118654 image = that.claimToValue(entity, 'P28', langCodes[0]);
118657 imageroot = 'https://wiki.openstreetmap.org/w/index.php';
118661 if (imageroot && image) {
118662 result.imageURL = imageroot + '?' + utilQsString({
118663 title: 'Special:Redirect/file/' + image,
118667 } // Try to get a wiki page from tag data item first, followed by the corresponding key data item.
118668 // If neither tag nor key data item contain a wiki page in the needed language nor English,
118669 // get the first found wiki page from either the tag or the key item.
118672 var rtypeWiki = that.monolingualClaimToValueObj(data.rtype, 'P31');
118673 var tagWiki = that.monolingualClaimToValueObj(data.tag, 'P31');
118674 var keyWiki = that.monolingualClaimToValueObj(data.key, 'P31');
118675 var wikis = [rtypeWiki, tagWiki, keyWiki];
118680 for (var j in langCodes) {
118681 var code = langCodes[j];
118682 var referenceId = langCodes[0].split('-')[0] !== 'en' && code.split('-')[0] === 'en' ? 'inspector.wiki_en_reference' : 'inspector.wiki_reference';
118683 var info = getWikiInfo(wiki, code, referenceId);
118691 if (result.wiki) break;
118694 callback(null, result); // Helper method to get wiki info if a given language exists
118696 function getWikiInfo(wiki, langCode, tKey) {
118697 if (wiki && wiki[langCode]) {
118701 url: 'https://wiki.openstreetmap.org/wiki/' + wiki[langCode]
118707 addLocale: function addLocale(langCode, qid) {
118708 // Makes it easier to unit test
118709 _localeIDs[langCode] = qid;
118711 apibase: function apibase(val) {
118712 if (!arguments.length) return _apibase$1;
118719 window.jsonpCache = jsonpCache;
118720 function jsonpRequest(url, callback) {
118722 abort: function abort() {}
118725 if (window.JSONP_FIX) {
118726 if (window.JSONP_DELAY === 0) {
118727 callback(window.JSONP_FIX);
118729 var t = window.setTimeout(function () {
118730 callback(window.JSONP_FIX);
118731 }, window.JSONP_DELAY || 0);
118733 request.abort = function () {
118734 window.clearTimeout(t);
118742 var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
118747 c += chars.charAt(Math.floor(Math.random() * 52));
118754 var e = url.match(/callback=(\w+)/);
118755 var c = e ? e[1] : rand();
118757 jsonpCache[c] = function (data) {
118770 request.abort = finalize;
118771 return 'jsonpCache.' + c;
118775 var script = select('head').append('script').attr('type', 'text/javascript').attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
118779 var bubbleApi = 'https://dev.virtualearth.net/mapcontrol/HumanScaleServices/GetBubbles.ashx?';
118780 var streetsideImagesApi = 'https://t.ssl.ak.tiles.virtualearth.net/tiles/';
118781 var bubbleAppKey = 'AuftgJsO0Xs8Ts4M1xZUQJQXJNsvmh3IV8DkNieCiy3tCwCUMq76-WpkrBtNAuEm';
118782 var pannellumViewerCSS = 'pannellum-streetside/pannellum.css';
118783 var pannellumViewerJS = 'pannellum-streetside/pannellum.js';
118786 var tiler$1 = utilTiler().zoomExtent([tileZoom, tileZoom]).skipNullIsland(true);
118787 var dispatch$1 = dispatch$8('loadedImages', 'viewerChanged');
118788 var minHfov = 10; // zoom in degrees: 20, 10, 5
118790 var maxHfov = 90; // zoom out degrees
118794 var _resolution = 512; // higher numbers are slower - 512, 1024, 2048, 4096
118803 showFullscreenCtrl: false,
118814 var _loadViewerPromise;
118820 function abortRequest$1(i) {
118828 function localeTimestamp(s) {
118836 if (isNaN(d.getTime())) return null;
118837 return d.toLocaleString(_mainLocalizer.localeCode(), options);
118840 * loadTiles() wraps the process of generating tiles and then fetching image points for each tile.
118844 function loadTiles(which, url, projection, margin) {
118845 var tiles = tiler$1.margin(margin).getTiles(projection); // abort inflight requests that are no longer needed
118847 var cache = _ssCache[which];
118848 Object.keys(cache.inflight).forEach(function (k) {
118849 var wanted = tiles.find(function (tile) {
118850 return k.indexOf(tile.id + ',') === 0;
118854 abortRequest$1(cache.inflight[k]);
118855 delete cache.inflight[k];
118858 tiles.forEach(function (tile) {
118859 return loadNextTilePage(which, url, tile);
118863 * loadNextTilePage() load data for the next tile page in line.
118867 function loadNextTilePage(which, url, tile) {
118868 var cache = _ssCache[which];
118869 var nextPage = cache.nextPage[tile.id] || 0;
118870 var id = tile.id + ',' + String(nextPage);
118871 if (cache.loaded[id] || cache.inflight[id]) return;
118872 cache.inflight[id] = getBubbles(url, tile, function (bubbles) {
118873 cache.loaded[id] = true;
118874 delete cache.inflight[id];
118875 if (!bubbles) return; // [].shift() removes the first element, some statistics info, not a bubble point
118878 var features = bubbles.map(function (bubble) {
118879 if (cache.points[bubble.id]) return null; // skip duplicates
118881 var loc = [bubble.lo, bubble.la];
118886 captured_at: bubble.cd,
118887 captured_by: 'microsoft',
118899 cache.points[bubble.id] = d; // a sequence starts here
118901 if (bubble.pr === undefined) {
118902 cache.leaders.push(bubble.id);
118913 cache.rtree.load(features);
118916 if (which === 'bubbles') {
118917 dispatch$1.call('loadedImages');
118920 } // call this sometimes to connect the bubbles into sequences
118923 function connectSequences() {
118924 var cache = _ssCache.bubbles;
118927 for (var i = 0; i < cache.leaders.length; i++) {
118928 var bubble = cache.points[cache.leaders[i]];
118929 var seen = {}; // try to make a sequence.. use the key of the leader bubble.
118938 sequence.bubbles.push(bubble);
118939 seen[bubble.key] = true;
118941 if (bubble.ne === undefined) {
118944 bubble = cache.points[bubble.ne]; // advance to next
118946 } while (bubble && !seen[bubble.key] && !complete);
118949 _ssCache.sequences[sequence.key] = sequence; // assign bubbles to the sequence
118951 for (var j = 0; j < sequence.bubbles.length; j++) {
118952 sequence.bubbles[j].sequenceKey = sequence.key;
118953 } // create a GeoJSON LineString
118959 captured_at: sequence.bubbles[0] ? sequence.bubbles[0].captured_at : null,
118960 captured_by: sequence.bubbles[0] ? sequence.bubbles[0].captured_by : null,
118963 coordinates: sequence.bubbles.map(function (d) {
118968 keepLeaders.push(cache.leaders[i]);
118970 } // couldn't complete these, save for later
118973 cache.leaders = keepLeaders;
118976 * getBubbles() handles the request to the server for a tile extent of 'bubbles' (streetside image locations).
118980 function getBubbles(url, tile, callback) {
118981 var rect = tile.extent.rectangle();
118982 var urlForRequest = url + utilQsString({
118989 jsCallback: '{callback}'
118991 return jsonpRequest(urlForRequest, function (data) {
118992 if (!data || data.error) {
118998 } // partition viewport into higher zoom tiles
119001 function partitionViewport(projection) {
119002 var z = geoScaleToZoom(projection.scale());
119003 var z2 = Math.ceil(z * 2) / 2 + 2.5; // round to next 0.5 and add 2.5
119005 var tiler = utilTiler().zoomExtent([z2, z2]);
119006 return tiler.getTiles(projection).map(function (tile) {
119009 } // no more than `limit` results per partition.
119012 function searchLimited(limit, projection, rtree) {
119014 return partitionViewport(projection).reduce(function (result, extent) {
119015 var found = rtree.search(extent.bbox()).slice(0, limit).map(function (d) {
119018 return found.length ? result.concat(found) : result;
119026 function loadImage(imgInfo) {
119027 return new Promise(function (resolve) {
119030 img.onload = function () {
119031 var canvas = document.getElementById('ideditor-canvas' + imgInfo.face);
119032 var ctx = canvas.getContext('2d');
119033 ctx.drawImage(img, imgInfo.x, imgInfo.y);
119040 img.onerror = function () {
119047 img.setAttribute('crossorigin', '');
119056 function loadCanvas(imageGroup) {
119057 return Promise.all(imageGroup.map(loadImage)).then(function (data) {
119058 var canvas = document.getElementById('ideditor-canvas' + data[0].imgInfo.face);
119067 var face = data[0].imgInfo.face;
119068 _sceneOptions.cubeMap[which[face]] = canvas.toDataURL('image/jpeg', 1.0);
119070 status: 'loadCanvas for face ' + data[0].imgInfo.face + 'ok'
119079 function loadFaces(faceGroup) {
119080 return Promise.all(faceGroup.map(loadCanvas)).then(function () {
119082 status: 'loadFaces done'
119087 function setupCanvas(selection, reset) {
119089 selection.selectAll('#ideditor-stitcher-canvases').remove();
119090 } // Add the Streetside working canvases. These are used for 'stitching', or combining,
119091 // multiple images for each of the six faces, before passing to the Pannellum control as DataUrls
119094 selection.selectAll('#ideditor-stitcher-canvases').data([0]).enter().append('div').attr('id', 'ideditor-stitcher-canvases').attr('display', 'none').selectAll('canvas').data(['canvas01', 'canvas02', 'canvas03', 'canvas10', 'canvas11', 'canvas12']).enter().append('canvas').attr('id', function (d) {
119095 return 'ideditor-' + d;
119096 }).attr('width', _resolution).attr('height', _resolution);
119104 for (var i = qk.length; i > 0; i--) {
119106 x += +(key === '1' || key === '3') * scale;
119107 y += +(key === '2' || key === '3') * scale;
119114 function getQuadKeys() {
119115 var dim = _resolution / 256;
119119 quadKeys = ['0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111', '0002', '0003', '0012', '0013', '0102', '0103', '0112', '0113', '1002', '1003', '1012', '1013', '1102', '1103', '1112', '1113', '0020', '0021', '0030', '0031', '0120', '0121', '0130', '0131', '1020', '1021', '1030', '1031', '1120', '1121', '1130', '1131', '0022', '0023', '0032', '0033', '0122', '0123', '0132', '0133', '1022', '1023', '1032', '1033', '1122', '1123', '1132', '1133', '0200', '0201', '0210', '0211', '0300', '0301', '0310', '0311', '1200', '1201', '1210', '1211', '1300', '1301', '1310', '1311', '0202', '0203', '0212', '0213', '0302', '0303', '0312', '0313', '1202', '1203', '1212', '1213', '1302', '1303', '1312', '1313', '0220', '0221', '0230', '0231', '0320', '0321', '0330', '0331', '1220', '1221', '1230', '1231', '1320', '1321', '1330', '1331', '0222', '0223', '0232', '0233', '0322', '0323', '0332', '0333', '1222', '1223', '1232', '1233', '1322', '1323', '1332', '1333', '2000', '2001', '2010', '2011', '2100', '2101', '2110', '2111', '3000', '3001', '3010', '3011', '3100', '3101', '3110', '3111', '2002', '2003', '2012', '2013', '2102', '2103', '2112', '2113', '3002', '3003', '3012', '3013', '3102', '3103', '3112', '3113', '2020', '2021', '2030', '2031', '2120', '2121', '2130', '2131', '3020', '3021', '3030', '3031', '3120', '3121', '3130', '3131', '2022', '2023', '2032', '2033', '2122', '2123', '2132', '2133', '3022', '3023', '3032', '3033', '3122', '3123', '3132', '3133', '2200', '2201', '2210', '2211', '2300', '2301', '2310', '2311', '3200', '3201', '3210', '3211', '3300', '3301', '3310', '3311', '2202', '2203', '2212', '2213', '2302', '2303', '2312', '2313', '3202', '3203', '3212', '3213', '3302', '3303', '3312', '3313', '2220', '2221', '2230', '2231', '2320', '2321', '2330', '2331', '3220', '3221', '3230', '3231', '3320', '3321', '3330', '3331', '2222', '2223', '2232', '2233', '2322', '2323', '2332', '2333', '3222', '3223', '3232', '3233', '3322', '3323', '3332', '3333'];
119120 } else if (dim === 8) {
119121 quadKeys = ['000', '001', '010', '011', '100', '101', '110', '111', '002', '003', '012', '013', '102', '103', '112', '113', '020', '021', '030', '031', '120', '121', '130', '131', '022', '023', '032', '033', '122', '123', '132', '133', '200', '201', '210', '211', '300', '301', '310', '311', '202', '203', '212', '213', '302', '303', '312', '313', '220', '221', '230', '231', '320', '321', '330', '331', '222', '223', '232', '233', '322', '323', '332', '333'];
119122 } else if (dim === 4) {
119123 quadKeys = ['00', '01', '10', '11', '02', '03', '12', '13', '20', '21', '30', '31', '22', '23', '32', '33'];
119126 quadKeys = ['0', '1', '2', '3'];
119132 var serviceStreetside = {
119134 * init() initialize streetside.
119136 init: function init() {
119141 this.event = utilRebind(this, dispatch$1, 'on');
119145 * reset() reset the cache.
119147 reset: function reset() {
119149 Object.values(_ssCache.bubbles.inflight).forEach(abortRequest$1);
119168 bubbles: function bubbles(projection) {
119170 return searchLimited(limit, projection, _ssCache.bubbles.rtree);
119172 cachedImage: function cachedImage(imageKey) {
119173 return _ssCache.bubbles.points[imageKey];
119175 sequences: function sequences(projection) {
119176 var viewport = projection.clipExtent();
119177 var min = [viewport[0][0], viewport[1][1]];
119178 var max = [viewport[1][0], viewport[0][1]];
119179 var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
119181 var results = []; // all sequences for bubbles in viewport
119183 _ssCache.bubbles.rtree.search(bbox).forEach(function (d) {
119184 var key = d.data.sequenceKey;
119186 if (key && !seen[key]) {
119188 results.push(_ssCache.sequences[key].geojson);
119198 loadBubbles: function loadBubbles(projection, margin) {
119199 // by default: request 2 nearby tiles so we can connect sequences.
119200 if (margin === undefined) margin = 2;
119201 loadTiles('bubbles', bubbleApi, projection, margin);
119203 viewer: function viewer() {
119204 return _pannellumViewer;
119206 initViewer: function initViewer() {
119207 if (!window.pannellum) return;
119208 if (_pannellumViewer) return;
119211 var sceneID = _currScene.toString();
119219 options.scenes[sceneID] = _sceneOptions;
119220 _pannellumViewer = window.pannellum.viewer('ideditor-viewer-streetside', options);
119222 ensureViewerLoaded: function ensureViewerLoaded(context) {
119223 if (_loadViewerPromise) return _loadViewerPromise; // create ms-wrapper, a photo wrapper class
119225 var wrap = context.container().select('.photoviewer').selectAll('.ms-wrapper').data([0]); // inject ms-wrapper into the photoviewer div
119226 // (used by all to house each custom photo viewer)
119228 var wrapEnter = wrap.enter().append('div').attr('class', 'photo-wrapper ms-wrapper').classed('hide', true);
119230 var pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse'; // inject div to support streetside viewer (pannellum) and attribution line
119232 wrapEnter.append('div').attr('id', 'ideditor-viewer-streetside').on(pointerPrefix + 'down.streetside', function () {
119233 select(window).on(pointerPrefix + 'move.streetside', function () {
119234 dispatch$1.call('viewerChanged');
119236 }).on(pointerPrefix + 'up.streetside pointercancel.streetside', function () {
119237 select(window).on(pointerPrefix + 'move.streetside', null); // continue dispatching events for a few seconds, in case viewer has inertia.
119239 var t = timer(function (elapsed) {
119240 dispatch$1.call('viewerChanged');
119246 }).append('div').attr('class', 'photo-attribution fillD');
119247 var controlsEnter = wrapEnter.append('div').attr('class', 'photo-controls-wrap').append('div').attr('class', 'photo-controls');
119248 controlsEnter.append('button').on('click.back', step(-1)).text('◄');
119249 controlsEnter.append('button').on('click.forward', step(1)).text('►'); // create working canvas for stitching together images
119251 wrap = wrap.merge(wrapEnter).call(setupCanvas, true); // Register viewer resize handler
119253 context.ui().photoviewer.on('resize.streetside', function () {
119254 if (_pannellumViewer) {
119255 _pannellumViewer.resize();
119258 _loadViewerPromise = new Promise(function (resolve, reject) {
119262 loadedCount += 1; // wait until both files are loaded
119264 if (loadedCount === 2) resolve();
119267 var head = select('head'); // load streetside pannellum viewer css
119269 head.selectAll('#ideditor-streetside-viewercss').data([0]).enter().append('link').attr('id', 'ideditor-streetside-viewercss').attr('rel', 'stylesheet').attr('crossorigin', 'anonymous').attr('href', context.asset(pannellumViewerCSS)).on('load.serviceStreetside', loaded).on('error.serviceStreetside', function () {
119271 }); // load streetside pannellum viewer js
119273 head.selectAll('#ideditor-streetside-viewerjs').data([0]).enter().append('script').attr('id', 'ideditor-streetside-viewerjs').attr('crossorigin', 'anonymous').attr('src', context.asset(pannellumViewerJS)).on('load.serviceStreetside', loaded).on('error.serviceStreetside', function () {
119276 })["catch"](function () {
119277 _loadViewerPromise = null;
119279 return _loadViewerPromise;
119281 function step(stepBy) {
119283 var viewer = context.container().select('.photoviewer');
119284 var selected = viewer.empty() ? undefined : viewer.datum();
119286 var nextID = stepBy === 1 ? selected.ne : selected.pr;
119288 var yaw = _pannellumViewer.getYaw();
119290 var ca = selected.ca + yaw;
119291 var origin = selected.loc; // construct a search trapezoid pointing out from current bubble
119294 var p1 = [origin[0] + geoMetersToLon(meters / 5, origin[1]), origin[1]];
119295 var p2 = [origin[0] + geoMetersToLon(meters / 2, origin[1]), origin[1] + geoMetersToLat(meters)];
119296 var p3 = [origin[0] - geoMetersToLon(meters / 2, origin[1]), origin[1] + geoMetersToLat(meters)];
119297 var p4 = [origin[0] - geoMetersToLon(meters / 5, origin[1]), origin[1]];
119298 var poly = [p1, p2, p3, p4, p1]; // rotate it to face forward/backward
119300 var angle = (stepBy === 1 ? ca : ca + 180) * (Math.PI / 180);
119301 poly = geoRotate(poly, -angle, origin);
119302 var extent = poly.reduce(function (extent, point) {
119303 return extent.extend(geoExtent(point));
119304 }, geoExtent()); // find nearest other bubble in the search polygon
119306 var minDist = Infinity;
119308 _ssCache.bubbles.rtree.search(extent.bbox()).forEach(function (d) {
119309 if (d.data.key === selected.key) return;
119310 if (!geoPointInPolygon(d.data.loc, poly)) return;
119311 var dist = geoVecLength(d.data.loc, selected.loc);
119312 var theta = selected.ca - d.data.ca;
119313 var minTheta = Math.min(Math.abs(theta), 360 - Math.abs(theta));
119316 dist += 5; // penalize distance if camera angles don't match
119325 var nextBubble = nextID && that.cachedImage(nextID);
119326 if (!nextBubble) return;
119327 context.map().centerEase(nextBubble.loc);
119328 that.selectImage(context, nextBubble.key).yaw(yaw).showViewer(context);
119332 yaw: function yaw(_yaw) {
119333 if (typeof _yaw !== 'number') return _yaw;
119334 _sceneOptions.yaw = _yaw;
119341 showViewer: function showViewer(context) {
119342 var wrap = context.container().select('.photoviewer').classed('hide', false);
119343 var isHidden = wrap.selectAll('.photo-wrapper.ms-wrapper.hide').size();
119346 wrap.selectAll('.photo-wrapper:not(.ms-wrapper)').classed('hide', true);
119347 wrap.selectAll('.photo-wrapper.ms-wrapper').classed('hide', false);
119356 hideViewer: function hideViewer(context) {
119357 var viewer = context.container().select('.photoviewer');
119358 if (!viewer.empty()) viewer.datum(null);
119359 viewer.classed('hide', true).selectAll('.photo-wrapper').classed('hide', true);
119360 context.container().selectAll('.viewfield-group, .sequence, .icon-sign').classed('currentView', false);
119361 this.updateUrlImage(null);
119362 return this.setStyles(context, null, true);
119368 selectImage: function selectImage(context, key) {
119370 var d = this.cachedImage(key);
119371 var viewer = context.container().select('.photoviewer');
119372 if (!viewer.empty()) viewer.datum(d);
119373 this.setStyles(context, null, true);
119374 var wrap = context.container().select('.photoviewer .ms-wrapper');
119375 var attribution = wrap.selectAll('.photo-attribution').html('');
119376 wrap.selectAll('.pnlm-load-box') // display "loading.."
119377 .style('display', 'block');
119379 this.updateUrlImage(key);
119380 _sceneOptions.northOffset = d.ca;
119381 var line1 = attribution.append('div').attr('class', 'attribution-row');
119382 var hiresDomId = utilUniqueDomId('streetside-hires'); // Add hires checkbox
119384 var label = line1.append('label').attr('for', hiresDomId).attr('class', 'streetside-hires');
119385 label.append('input').attr('type', 'checkbox').attr('id', hiresDomId).property('checked', _hires).on('click', function (d3_event) {
119386 d3_event.stopPropagation();
119388 _resolution = _hires ? 1024 : 512;
119389 wrap.call(setupCanvas, true);
119391 yaw: _pannellumViewer.getYaw(),
119392 pitch: _pannellumViewer.getPitch(),
119393 hfov: _pannellumViewer.getHfov()
119395 _sceneOptions = Object.assign(_sceneOptions, viewstate);
119396 that.selectImage(context, d.key).showViewer(context);
119398 label.append('span').call(_t.append('streetside.hires'));
119399 var captureInfo = line1.append('div').attr('class', 'attribution-capture-info'); // Add capture date
119402 var yyyy = new Date().getFullYear();
119403 captureInfo.append('a').attr('class', 'captured_by').attr('target', '_blank').attr('href', 'https://www.microsoft.com/en-us/maps/streetside').text('©' + yyyy + ' Microsoft');
119404 captureInfo.append('span').text('|');
119408 captureInfo.append('span').attr('class', 'captured_at').text(localeTimestamp(d.captured_at));
119412 var line2 = attribution.append('div').attr('class', 'attribution-row');
119413 line2.append('a').attr('class', 'image-view-link').attr('target', '_blank').attr('href', 'https://www.bing.com/maps?cp=' + d.loc[1] + '~' + d.loc[0] + '&lvl=17&dir=' + d.ca + '&style=x&v=2&sV=1').call(_t.append('streetside.view_on_bing'));
119414 line2.append('a').attr('class', 'image-report-link').attr('target', '_blank').attr('href', 'https://www.bing.com/maps/privacyreport/streetsideprivacyreport?bubbleid=' + encodeURIComponent(d.key) + '&focus=photo&lat=' + d.loc[1] + '&lng=' + d.loc[0] + '&z=17').call(_t.append('streetside.report'));
119415 var bubbleIdQuadKey = d.key.toString(4);
119416 var paddingNeeded = 16 - bubbleIdQuadKey.length;
119418 for (var i = 0; i < paddingNeeded; i++) {
119419 bubbleIdQuadKey = '0' + bubbleIdQuadKey;
119422 var imgUrlPrefix = streetsideImagesApi + 'hs' + bubbleIdQuadKey;
119423 var imgUrlSuffix = '.jpg?g=6338&n=z'; // Cubemap face code order matters here: front=01, right=02, back=03, left=10, up=11, down=12
119425 var faceKeys = ['01', '02', '03', '10', '11', '12']; // Map images to cube faces
119427 var quadKeys = getQuadKeys();
119428 var faces = faceKeys.map(function (faceKey) {
119429 return quadKeys.map(function (quadKey) {
119430 var xy = qkToXY(quadKey);
119433 url: imgUrlPrefix + faceKey + quadKey + imgUrlSuffix,
119439 loadFaces(faces).then(function () {
119440 if (!_pannellumViewer) {
119446 var sceneID = _currScene.toString();
119448 _pannellumViewer.addScene(sceneID, _sceneOptions).loadScene(sceneID); // remove previous scene
119452 sceneID = (_currScene - 1).toString();
119454 _pannellumViewer.removeScene(sceneID);
119460 getSequenceKeyForBubble: function getSequenceKeyForBubble(d) {
119461 return d && d.sequenceKey;
119463 // Updates the currently highlighted sequence and selected bubble.
119464 // Reset is only necessary when interacting with the viewport because
119465 // this implicitly changes the currently selected bubble/sequence
119466 setStyles: function setStyles(context, hovered, reset) {
119469 context.container().selectAll('.viewfield-group').classed('highlighted', false).classed('hovered', false).classed('currentView', false);
119470 context.container().selectAll('.sequence').classed('highlighted', false).classed('currentView', false);
119473 var hoveredBubbleKey = hovered && hovered.key;
119474 var hoveredSequenceKey = this.getSequenceKeyForBubble(hovered);
119475 var hoveredSequence = hoveredSequenceKey && _ssCache.sequences[hoveredSequenceKey];
119476 var hoveredBubbleKeys = hoveredSequence && hoveredSequence.bubbles.map(function (d) {
119479 var viewer = context.container().select('.photoviewer');
119480 var selected = viewer.empty() ? undefined : viewer.datum();
119481 var selectedBubbleKey = selected && selected.key;
119482 var selectedSequenceKey = this.getSequenceKeyForBubble(selected);
119483 var selectedSequence = selectedSequenceKey && _ssCache.sequences[selectedSequenceKey];
119484 var selectedBubbleKeys = selectedSequence && selectedSequence.bubbles.map(function (d) {
119486 }) || []; // highlight sibling viewfields on either the selected or the hovered sequences
119488 var highlightedBubbleKeys = utilArrayUnion(hoveredBubbleKeys, selectedBubbleKeys);
119489 context.container().selectAll('.layer-streetside-images .viewfield-group').classed('highlighted', function (d) {
119490 return highlightedBubbleKeys.indexOf(d.key) !== -1;
119491 }).classed('hovered', function (d) {
119492 return d.key === hoveredBubbleKey;
119493 }).classed('currentView', function (d) {
119494 return d.key === selectedBubbleKey;
119496 context.container().selectAll('.layer-streetside-images .sequence').classed('highlighted', function (d) {
119497 return d.properties.key === hoveredSequenceKey;
119498 }).classed('currentView', function (d) {
119499 return d.properties.key === selectedSequenceKey;
119500 }); // update viewfields if needed
119502 context.container().selectAll('.layer-streetside-images .viewfield-group .viewfield').attr('d', viewfieldPath);
119504 function viewfieldPath() {
119505 var d = this.parentNode.__data__;
119507 if (d.pano && d.key !== selectedBubbleKey) {
119508 return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
119510 return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
119516 updateUrlImage: function updateUrlImage(imageKey) {
119518 var hash = utilStringQs(window.location.hash);
119521 hash.photo = 'streetside/' + imageKey;
119526 window.location.replace('#' + utilQsString(hash, true));
119533 cache: function cache() {
119538 var _apibase = 'https://taginfo.openstreetmap.org/api/4/';
119541 var _taginfoCache = {};
119548 var tag_sort_members = {
119549 point: 'count_node_members',
119550 vertex: 'count_node_members',
119551 area: 'count_way_members',
119552 line: 'count_way_members',
119553 relation: 'count_relation_members'
119561 var tag_members_fractions = {
119562 point: 'count_node_members_fraction',
119563 vertex: 'count_node_members_fraction',
119564 area: 'count_way_members_fraction',
119565 line: 'count_way_members_fraction',
119566 relation: 'count_relation_members_fraction'
119569 function sets(params, n, o) {
119570 if (params.geometry && o[params.geometry]) {
119571 params[n] = o[params.geometry];
119577 function setFilter(params) {
119578 return sets(params, 'filter', tag_filters);
119581 function setSort(params) {
119582 return sets(params, 'sortname', tag_sorts);
119585 function setSortMembers(params) {
119586 return sets(params, 'sortname', tag_sort_members);
119589 function clean(params) {
119590 return utilObjectOmit(params, ['geometry', 'debounce']);
119593 function filterKeys(type) {
119594 var count_type = type ? 'count_' + type : 'count_all';
119596 return parseFloat(d[count_type]) > 2500 || d.in_wiki;
119600 function filterMultikeys(prefix) {
119602 // d.key begins with prefix, and d.key contains no additional ':'s
119603 var re = new RegExp('^' + prefix + '(.*)$');
119604 var matches = d.key.match(re) || [];
119605 return matches.length === 2 && matches[1].indexOf(':') === -1;
119609 function filterValues(allowUpperCase) {
119611 if (d.value.match(/[;,]/) !== null) return false; // exclude some punctuation
119613 if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false; // exclude uppercase letters
119615 return parseFloat(d.fraction) > 0.0;
119619 function filterRoles(geometry) {
119621 if (d.role === '') return false; // exclude empty role
119623 if (d.role.match(/[A-Z*;,]/) !== null) return false; // exclude uppercase letters and some punctuation
119625 return parseFloat(d[tag_members_fractions[geometry]]) > 0.0;
119636 function valKeyDescription(d) {
119639 title: d.description || d.value
119654 } // sort keys with ':' lower than keys without ':'
119657 function sortKeys(a, b) {
119658 return a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1 ? -1 : a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1 ? 1 : 0;
119661 var debouncedRequest = debounce(request, 300, {
119665 function request(url, params, exactMatch, callback, loaded) {
119666 if (_inflight[url]) return;
119667 if (checkCache(url, params, exactMatch, callback)) return;
119668 var controller = new AbortController();
119669 _inflight[url] = controller;
119671 signal: controller.signal
119672 }).then(function (result) {
119674 if (loaded) loaded(null, result);
119675 })["catch"](function (err) {
119677 if (err.name === 'AbortError') return;
119678 if (loaded) loaded(err.message);
119682 function checkCache(url, params, exactMatch, callback) {
119683 var rp = params.rp || 25;
119684 var testQuery = params.query || '';
119688 var hit = _taginfoCache[testUrl]; // exact match, or shorter match yielding fewer than max results (rp)
119690 if (hit && (url === testUrl || hit.length < rp)) {
119693 } // don't try to shorten the query
119696 if (exactMatch || !testQuery.length) return false; // do shorten the query to see if we already have a cached result
119697 // that has returned fewer than max results (rp)
119699 testQuery = testQuery.slice(0, -1);
119700 testUrl = url.replace(/&query=(.*?)&/, '&query=' + testQuery + '&');
119701 } while (testQuery.length >= 0);
119707 init: function init() {
119711 // manually exclude some keys – #5377, #7485
119722 }; // Fetch popular keys. We'll exclude these from `values`
119723 // lookups because they stress taginfo, and they aren't likely
119724 // to yield meaningful autocomplete results.. see #3955
119728 sortname: 'values_all',
119732 lang: _mainLocalizer.languageCode()
119734 this.keys(params, function (err, data) {
119736 data.forEach(function (d) {
119737 if (d.value === 'opening_hours') return; // exception
119739 _popularKeys[d.value] = true;
119743 reset: function reset() {
119744 Object.values(_inflight).forEach(function (controller) {
119749 keys: function keys(params, callback) {
119750 var doRequest = params.debounce ? debouncedRequest : request;
119751 params = clean(setSort(params));
119752 params = Object.assign({
119757 lang: _mainLocalizer.languageCode()
119759 var url = _apibase + 'keys/all?' + utilQsString(params);
119760 doRequest(url, params, false, callback, function (err, d) {
119764 var f = filterKeys(params.filter);
119765 var result = d.data.filter(f).sort(sortKeys).map(valKey);
119766 _taginfoCache[url] = result;
119767 callback(null, result);
119771 multikeys: function multikeys(params, callback) {
119772 var doRequest = params.debounce ? debouncedRequest : request;
119773 params = clean(setSort(params));
119774 params = Object.assign({
119779 lang: _mainLocalizer.languageCode()
119781 var prefix = params.query;
119782 var url = _apibase + 'keys/all?' + utilQsString(params);
119783 doRequest(url, params, true, callback, function (err, d) {
119787 var f = filterMultikeys(prefix);
119788 var result = d.data.filter(f).map(valKey);
119789 _taginfoCache[url] = result;
119790 callback(null, result);
119794 values: function values(params, callback) {
119795 // Exclude popular keys from values lookups.. see #3955
119798 if (key && _popularKeys[key]) {
119803 var doRequest = params.debounce ? debouncedRequest : request;
119804 params = clean(setSort(setFilter(params)));
119805 params = Object.assign({
119810 lang: _mainLocalizer.languageCode()
119812 var url = _apibase + 'key/values?' + utilQsString(params);
119813 doRequest(url, params, false, callback, function (err, d) {
119817 // In most cases we prefer taginfo value results with lowercase letters.
119818 // A few OSM keys expect values to contain uppercase values (see #3377).
119819 // This is not an exhaustive list (e.g. `name` also has uppercase values)
119820 // but these are the fields where taginfo value lookup is most useful.
119821 var re = /network|taxon|genus|species|brand|grape_variety|royal_cypher|listed_status|booth|rating|stars|:output|_hours|_times|_ref|manufacturer|country|target|brewery|cai_scale/;
119822 var allowUpperCase = re.test(params.key);
119823 var f = filterValues(allowUpperCase);
119824 var result = d.data.filter(f).map(valKeyDescription);
119825 _taginfoCache[url] = result;
119826 callback(null, result);
119830 roles: function roles(params, callback) {
119831 var doRequest = params.debounce ? debouncedRequest : request;
119832 var geometry = params.geometry;
119833 params = clean(setSortMembers(params));
119834 params = Object.assign({
119836 sortname: 'count_all_members',
119839 lang: _mainLocalizer.languageCode()
119841 var url = _apibase + 'relation/roles?' + utilQsString(params);
119842 doRequest(url, params, true, callback, function (err, d) {
119846 var f = filterRoles(geometry);
119847 var result = d.data.filter(f).map(roleKey);
119848 _taginfoCache[url] = result;
119849 callback(null, result);
119853 docs: function docs(params, callback) {
119854 var doRequest = params.debounce ? debouncedRequest : request;
119855 params = clean(setSort(params));
119856 var path = 'key/wiki_pages?';
119859 path = 'tag/wiki_pages?';
119860 } else if (params.rtype) {
119861 path = 'relation/wiki_pages?';
119864 var url = _apibase + path + utilQsString(params);
119865 doRequest(url, params, true, callback, function (err, d) {
119869 _taginfoCache[url] = d.data;
119870 callback(null, d.data);
119874 apibase: function apibase(_) {
119875 if (!arguments.length) return _apibase;
119882 * Wraps a GeoJSON {@link Geometry} in a GeoJSON {@link Feature}.
119885 * @param {Geometry} geometry input geometry
119886 * @param {Object} [properties={}] an Object of key-value pairs to add as properties
119887 * @param {Object} [options={}] Optional Parameters
119888 * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
119889 * @param {string|number} [options.id] Identifier associated with the Feature
119890 * @returns {Feature} a GeoJSON Feature
119894 * "coordinates": [110, 50]
119897 * var feature = turf.feature(geometry);
119902 function feature(geom, properties, options) {
119903 if (options === void 0) {
119911 if (options.id === 0 || options.id) {
119916 feat.bbox = options.bbox;
119919 feat.properties = properties || {};
119924 * Creates a {@link Polygon} {@link Feature} from an Array of LinearRings.
119927 * @param {Array<Array<Array<number>>>} coordinates an array of LinearRings
119928 * @param {Object} [properties={}] an Object of key-value pairs to add as properties
119929 * @param {Object} [options={}] Optional Parameters
119930 * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
119931 * @param {string|number} [options.id] Identifier associated with the Feature
119932 * @returns {Feature<Polygon>} Polygon Feature
119934 * var polygon = turf.polygon([[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]], { name: 'poly1' });
119939 function polygon(coordinates, properties, options) {
119940 if (options === void 0) {
119944 for (var _i = 0, coordinates_1 = coordinates; _i < coordinates_1.length; _i++) {
119945 var ring = coordinates_1[_i];
119948 throw new Error("Each LinearRing of a Polygon must have 4 or more Positions.");
119951 for (var j = 0; j < ring[ring.length - 1].length; j++) {
119952 // Check if first point of Polygon contains two numbers
119953 if (ring[ring.length - 1][j] !== ring[0][j]) {
119954 throw new Error("First and last Position are not equivalent.");
119961 coordinates: coordinates
119963 return feature(geom, properties, options);
119966 * Creates a {@link LineString} {@link Feature} from an Array of Positions.
119969 * @param {Array<Array<number>>} coordinates an array of Positions
119970 * @param {Object} [properties={}] an Object of key-value pairs to add as properties
119971 * @param {Object} [options={}] Optional Parameters
119972 * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
119973 * @param {string|number} [options.id] Identifier associated with the Feature
119974 * @returns {Feature<LineString>} LineString Feature
119976 * var linestring1 = turf.lineString([[-24, 63], [-23, 60], [-25, 65], [-20, 69]], {name: 'line 1'});
119977 * var linestring2 = turf.lineString([[-14, 43], [-13, 40], [-15, 45], [-10, 49]], {name: 'line 2'});
119983 function lineString(coordinates, properties, options) {
119984 if (options === void 0) {
119988 if (coordinates.length < 2) {
119989 throw new Error("coordinates must be an array of two or more positions");
119994 coordinates: coordinates
119996 return feature(geom, properties, options);
119999 * Creates a {@link Feature<MultiLineString>} based on a
120000 * coordinate array. Properties can be added optionally.
120002 * @name multiLineString
120003 * @param {Array<Array<Array<number>>>} coordinates an array of LineStrings
120004 * @param {Object} [properties={}] an Object of key-value pairs to add as properties
120005 * @param {Object} [options={}] Optional Parameters
120006 * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
120007 * @param {string|number} [options.id] Identifier associated with the Feature
120008 * @returns {Feature<MultiLineString>} a MultiLineString feature
120009 * @throws {Error} if no coordinates are passed
120011 * var multiLine = turf.multiLineString([[[0,0],[10,10]]]);
120016 function multiLineString(coordinates, properties, options) {
120017 if (options === void 0) {
120022 type: "MultiLineString",
120023 coordinates: coordinates
120025 return feature(geom, properties, options);
120028 * Creates a {@link Feature<MultiPolygon>} based on a
120029 * coordinate array. Properties can be added optionally.
120032 * @param {Array<Array<Array<Array<number>>>>} coordinates an array of Polygons
120033 * @param {Object} [properties={}] an Object of key-value pairs to add as properties
120034 * @param {Object} [options={}] Optional Parameters
120035 * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
120036 * @param {string|number} [options.id] Identifier associated with the Feature
120037 * @returns {Feature<MultiPolygon>} a multipolygon feature
120038 * @throws {Error} if no coordinates are passed
120040 * var multiPoly = turf.multiPolygon([[[[0,0],[0,10],[10,10],[10,0],[0,0]]]]);
120046 function multiPolygon(coordinates, properties, options) {
120047 if (options === void 0) {
120053 coordinates: coordinates
120055 return feature(geom, properties, options);
120059 * Get Geometry from Feature or Geometry Object
120061 * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object
120062 * @returns {Geometry|null} GeoJSON Geometry Object
120063 * @throws {Error} if geojson is not a Feature or Geometry Object
120070 * "coordinates": [110, 40]
120073 * var geom = turf.getGeom(point)
120074 * //={"type": "Point", "coordinates": [110, 40]}
120077 function getGeom(geojson) {
120078 if (geojson.type === "Feature") {
120079 return geojson.geometry;
120085 // Cohen-Sutherland line clipping algorithm, adapted to efficiently
120086 // handle polylines rather than just segments
120087 function lineclip(points, bbox, result) {
120088 var len = points.length,
120089 codeA = bitCode(points[0], bbox),
120096 if (!result) result = [];
120098 for (i = 1; i < len; i++) {
120101 codeB = lastCode = bitCode(b, bbox);
120104 if (!(codeA | codeB)) {
120108 if (codeB !== lastCode) {
120109 // segment went outside
120117 } else if (i === len - 1) {
120122 } else if (codeA & codeB) {
120126 // a outside, intersect with clip edge
120127 a = intersect(a, b, codeA, bbox);
120128 codeA = bitCode(a, bbox);
120131 b = intersect(a, b, codeB, bbox);
120132 codeB = bitCode(b, bbox);
120139 if (part.length) result.push(part);
120141 } // Sutherland-Hodgeman polygon clipping algorithm
120143 function polygonclip(points, bbox) {
120144 var result, edge, prev, prevInside, i, p, inside; // clip against each side of the clip rectangle
120146 for (edge = 1; edge <= 8; edge *= 2) {
120148 prev = points[points.length - 1];
120149 prevInside = !(bitCode(prev, bbox) & edge);
120151 for (i = 0; i < points.length; i++) {
120153 inside = !(bitCode(p, bbox) & edge); // if segment goes through the clip window, add an intersection
120155 if (inside !== prevInside) result.push(intersect(prev, p, edge, bbox));
120156 if (inside) result.push(p); // add a point if it's inside
120163 if (!points.length) break;
120167 } // intersect a segment against one of the 4 lines that make up the bbox
120169 function intersect(a, b, edge, bbox) {
120170 return edge & 8 ? [a[0] + (b[0] - a[0]) * (bbox[3] - a[1]) / (b[1] - a[1]), bbox[3]] // top
120171 : edge & 4 ? [a[0] + (b[0] - a[0]) * (bbox[1] - a[1]) / (b[1] - a[1]), bbox[1]] // bottom
120172 : edge & 2 ? [bbox[2], a[1] + (b[1] - a[1]) * (bbox[2] - a[0]) / (b[0] - a[0])] // right
120173 : edge & 1 ? [bbox[0], a[1] + (b[1] - a[1]) * (bbox[0] - a[0]) / (b[0] - a[0])] // left
120175 } // bit code reflects the point position relative to the bbox:
120179 // bottom 0101 0100 0110
120182 function bitCode(p, bbox) {
120184 if (p[0] < bbox[0]) code |= 1; // left
120185 else if (p[0] > bbox[2]) code |= 2; // right
120187 if (p[1] < bbox[1]) code |= 4; // bottom
120188 else if (p[1] > bbox[3]) code |= 8; // top
120194 * Takes a {@link Feature} and a bbox and clips the feature to the bbox using
120195 * [lineclip](https://github.com/mapbox/lineclip).
120196 * May result in degenerate edges when clipping Polygons.
120199 * @param {Feature<LineString|MultiLineString|Polygon|MultiPolygon>} feature feature to clip to the bbox
120200 * @param {BBox} bbox extent in [minX, minY, maxX, maxY] order
120201 * @returns {Feature<LineString|MultiLineString|Polygon|MultiPolygon>} clipped Feature
120203 * var bbox = [0, 0, 10, 10];
120204 * var poly = turf.polygon([[[2, 2], [8, 4], [12, 8], [3, 7], [2, 2]]]);
120206 * var clipped = turf.bboxClip(poly, bbox);
120209 * var addToMap = [bbox, poly, clipped]
120212 function bboxClip(feature, bbox) {
120213 var geom = getGeom(feature);
120215 var properties = feature.type === "Feature" ? feature.properties : {};
120216 var coords = geom.coordinates;
120220 case "MultiLineString":
120224 if (type === "LineString") {
120228 coords.forEach(function (line) {
120229 lineclip(line, bbox, lines_1);
120232 if (lines_1.length === 1) {
120233 return lineString(lines_1[0], properties);
120236 return multiLineString(lines_1, properties);
120240 return polygon(clipPolygon(coords, bbox), properties);
120243 return multiPolygon(coords.map(function (poly) {
120244 return clipPolygon(poly, bbox);
120248 throw new Error("geometry " + type + " not supported");
120252 function clipPolygon(rings, bbox) {
120255 for (var _i = 0, rings_1 = rings; _i < rings_1.length; _i++) {
120256 var ring = rings_1[_i];
120257 var clipped = polygonclip(ring, bbox);
120259 if (clipped.length > 0) {
120260 if (clipped[0][0] !== clipped[clipped.length - 1][0] || clipped[0][1] !== clipped[clipped.length - 1][1]) {
120261 clipped.push(clipped[0]);
120264 if (clipped.length >= 4) {
120265 outRings.push(clipped);
120273 var tiler = utilTiler().tileSize(512).margin(1);
120274 var dispatch = dispatch$8('loadedData');
120278 function abortRequest(controller) {
120282 function vtToGeoJSON(data, tile, mergeCache) {
120283 var vectorTile$1 = new vectorTile.VectorTile(new pbf(data));
120284 var layers = Object.keys(vectorTile$1.layers);
120286 if (!Array.isArray(layers)) {
120291 layers.forEach(function (layerID) {
120292 var layer = vectorTile$1.layers[layerID];
120295 for (var i = 0; i < layer.length; i++) {
120296 var feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
120297 var geometry = feature.geometry; // Treat all Polygons as MultiPolygons
120299 if (geometry.type === 'Polygon') {
120300 geometry.type = 'MultiPolygon';
120301 geometry.coordinates = [geometry.coordinates];
120304 var isClipped = false; // Clip to tile bounds
120306 if (geometry.type === 'MultiPolygon') {
120307 var featureClip = bboxClip(feature, tile.extent.rectangle());
120309 if (!fastDeepEqual(feature.geometry, featureClip.geometry)) {
120310 // feature = featureClip;
120314 if (!feature.geometry.coordinates.length) continue; // not actually on this tile
120316 if (!feature.geometry.coordinates[0].length) continue; // not actually on this tile
120317 } // Generate some unique IDs and add some metadata
120320 var featurehash = utilHashcode(fastJsonStableStringify(feature));
120321 var propertyhash = utilHashcode(fastJsonStableStringify(feature.properties || {}));
120322 feature.__layerID__ = layerID.replace(/[^_a-zA-Z0-9\-]/g, '_');
120323 feature.__featurehash__ = featurehash;
120324 feature.__propertyhash__ = propertyhash;
120325 features.push(feature); // Clipped Polygons at same zoom with identical properties can get merged
120327 if (isClipped && geometry.type === 'MultiPolygon') {
120328 var merged = mergeCache[propertyhash];
120330 if (merged && merged.length) {
120332 var coords = index.union(feature.geometry.coordinates, other.geometry.coordinates);
120334 if (!coords || !coords.length) {
120335 continue; // something failed in polygon union
120340 for (var j = 0; j < merged.length; j++) {
120341 // all these features get...
120342 merged[j].geometry.coordinates = coords; // same coords
120344 merged[j].__featurehash__ = featurehash; // same hash, so deduplication works
120347 mergeCache[propertyhash] = [feature];
120356 function loadTile(source, tile) {
120357 if (source.loaded[tile.id] || source.inflight[tile.id]) return;
120358 var url = source.template.replace('{x}', tile.xyz[0]).replace('{y}', tile.xyz[1]) // TMS-flipped y coordinate
120359 .replace(/\{[t-]y\}/, Math.pow(2, tile.xyz[2]) - tile.xyz[1] - 1).replace(/\{z(oom)?\}/, tile.xyz[2]).replace(/\{switch:([^}]+)\}/, function (s, r) {
120360 var subdomains = r.split(',');
120361 return subdomains[(tile.xyz[0] + tile.xyz[1]) % subdomains.length];
120363 var controller = new AbortController();
120364 source.inflight[tile.id] = controller;
120366 signal: controller.signal
120367 }).then(function (response) {
120369 throw new Error(response.status + ' ' + response.statusText);
120372 source.loaded[tile.id] = [];
120373 delete source.inflight[tile.id];
120374 return response.arrayBuffer();
120375 }).then(function (data) {
120377 throw new Error('No Data');
120382 if (!source.canMerge[z]) {
120383 source.canMerge[z] = {}; // initialize mergeCache
120386 source.loaded[tile.id] = vtToGeoJSON(data, tile, source.canMerge[z]);
120387 dispatch.call('loadedData');
120388 })["catch"](function () {
120389 source.loaded[tile.id] = [];
120390 delete source.inflight[tile.id];
120394 var serviceVectorTile = {
120395 init: function init() {
120400 this.event = utilRebind(this, dispatch, 'on');
120402 reset: function reset() {
120403 for (var sourceID in _vtCache) {
120404 var source = _vtCache[sourceID];
120406 if (source && source.inflight) {
120407 Object.values(source.inflight).forEach(abortRequest);
120413 addSource: function addSource(sourceID, template) {
120420 return _vtCache[sourceID];
120422 data: function data(sourceID, projection) {
120423 var source = _vtCache[sourceID];
120424 if (!source) return [];
120425 var tiles = tiler.getTiles(projection);
120429 for (var i = 0; i < tiles.length; i++) {
120430 var features = source.loaded[tiles[i].id];
120431 if (!features || !features.length) continue;
120433 for (var j = 0; j < features.length; j++) {
120434 var feature = features[j];
120435 var hash = feature.__featurehash__;
120436 if (seen[hash]) continue;
120437 seen[hash] = true; // return a shallow copy, because the hash may change
120438 // later if this feature gets merged with another
120440 results.push(Object.assign({}, feature)); // shallow copy
120446 loadTiles: function loadTiles(sourceID, template, projection) {
120447 var source = _vtCache[sourceID];
120450 source = this.addSource(sourceID, template);
120453 var tiles = tiler.getTiles(projection); // abort inflight requests that are no longer needed
120455 Object.keys(source.inflight).forEach(function (k) {
120456 var wanted = tiles.find(function (tile) {
120461 abortRequest(source.inflight[k]);
120462 delete source.inflight[k];
120465 tiles.forEach(function (tile) {
120466 loadTile(source, tile);
120469 cache: function cache() {
120474 var apibase = 'https://www.wikidata.org/w/api.php?';
120475 var _wikidataCache = {};
120476 var serviceWikidata = {
120477 init: function init() {},
120478 reset: function reset() {
120481 // Search for Wikidata items matching the query
120482 itemsForSearchQuery: function itemsForSearchQuery(query, callback) {
120484 if (callback) callback('No query', {});
120488 var lang = this.languagesToQuery()[0];
120489 var url = apibase + utilQsString({
120490 action: 'wbsearchentities',
120495 // the language to search
120497 // the language for the label and description in the result
120502 d3_json(url).then(function (result) {
120503 if (result && result.error) {
120504 throw new Error(result.error);
120507 if (callback) callback(null, result.search || {});
120508 })["catch"](function (err) {
120509 if (callback) callback(err.message, {});
120512 // Given a Wikipedia language and article title,
120513 // return an array of corresponding Wikidata entities.
120514 itemsByTitle: function itemsByTitle(lang, title, callback) {
120516 if (callback) callback('No title', {});
120521 var url = apibase + utilQsString({
120522 action: 'wbgetentities',
120525 sites: lang.replace(/-/g, '_') + 'wiki',
120528 // shrink response by filtering to one language
120531 d3_json(url).then(function (result) {
120532 if (result && result.error) {
120533 throw new Error(result.error);
120536 if (callback) callback(null, result.entities || {});
120537 })["catch"](function (err) {
120538 if (callback) callback(err.message, {});
120541 languagesToQuery: function languagesToQuery() {
120542 return _mainLocalizer.localeCodes().map(function (code) {
120543 return code.toLowerCase();
120544 }).filter(function (code) {
120545 // HACK: en-us isn't a wikidata language. We should really be filtering by
120546 // the languages known to be supported by wikidata.
120547 return code !== 'en-us';
120550 entityByQID: function entityByQID(qid, callback) {
120552 callback('No qid', {});
120556 if (_wikidataCache[qid]) {
120557 if (callback) callback(null, _wikidataCache[qid]);
120561 var langs = this.languagesToQuery();
120562 var url = apibase + utilQsString({
120563 action: 'wbgetentities',
120567 props: 'labels|descriptions|claims|sitelinks',
120568 sitefilter: langs.map(function (d) {
120571 languages: langs.join('|'),
120575 d3_json(url).then(function (result) {
120576 if (result && result.error) {
120577 throw new Error(result.error);
120580 if (callback) callback(null, result.entities[qid] || {});
120581 })["catch"](function (err) {
120582 if (callback) callback(err.message, {});
120585 // Pass `params` object of the form:
120587 // qid: 'string' // brand wikidata (e.g. 'Q37158')
120590 // Get an result object used to display tag documentation
120593 // description: 'string',
120596 // wiki: { title: 'string', text: 'string', url: 'string' }
120599 getDocs: function getDocs(params, callback) {
120600 var langs = this.languagesToQuery();
120601 this.entityByQID(params.qid, function (err, entity) {
120603 callback(err || 'No entity');
120613 if (entity.descriptions[code] && entity.descriptions[code].language === code) {
120614 description = entity.descriptions[code];
120619 if (!description && Object.values(entity.descriptions).length) description = Object.values(entity.descriptions)[0]; // prepare result
120623 description: description ? description.value : '',
120624 descriptionLocaleCode: description ? description.language : '',
120625 editURL: 'https://www.wikidata.org/wiki/' + entity.id
120629 var imageroot = 'https://commons.wikimedia.org/w/index.php';
120630 var props = ['P154', 'P18']; // logo image, image
120634 for (i = 0; i < props.length; i++) {
120635 prop = entity.claims[props[i]];
120637 if (prop && Object.keys(prop).length > 0) {
120638 image = prop[Object.keys(prop)[0]].mainsnak.datavalue.value;
120641 result.imageURL = imageroot + '?' + utilQsString({
120642 title: 'Special:Redirect/file/' + image,
120651 if (entity.sitelinks) {
120652 var englishLocale = _mainLocalizer.languageCode().toLowerCase() === 'en'; // must be one of these that we requested..
120654 for (i = 0; i < langs.length; i++) {
120655 // check each, in order of preference
120656 var w = langs[i] + 'wiki';
120658 if (entity.sitelinks[w]) {
120659 var title = entity.sitelinks[w].title;
120660 var tKey = 'inspector.wiki_reference';
120662 if (!englishLocale && langs[i] === 'en') {
120663 // user's locale isn't English but
120664 tKey = 'inspector.wiki_en_reference'; // we are sending them to enwiki anyway..
120670 url: 'https://' + langs[i] + '.wikipedia.org/wiki/' + title.replace(/ /g, '_')
120677 callback(null, result);
120682 var endpoint = 'https://en.wikipedia.org/w/api.php?';
120683 var serviceWikipedia = {
120684 init: function init() {},
120685 reset: function reset() {},
120686 search: function search(lang, query, callback) {
120688 if (callback) callback('No Query', []);
120693 var url = endpoint.replace('en', lang) + utilQsString({
120702 d3_json(url).then(function (result) {
120703 if (result && result.error) {
120704 throw new Error(result.error);
120705 } else if (!result || !result.query || !result.query.search) {
120706 throw new Error('No Results');
120710 var titles = result.query.search.map(function (d) {
120713 callback(null, titles);
120715 })["catch"](function (err) {
120716 if (callback) callback(err, []);
120719 suggestions: function suggestions(lang, query, callback) {
120721 if (callback) callback('', []);
120726 var url = endpoint.replace('en', lang) + utilQsString({
120734 d3_json(url).then(function (result) {
120735 if (result && result.error) {
120736 throw new Error(result.error);
120737 } else if (!result || result.length < 2) {
120738 throw new Error('No Results');
120741 if (callback) callback(null, result[1] || []);
120742 })["catch"](function (err) {
120743 if (callback) callback(err.message, []);
120746 translations: function translations(lang, title, callback) {
120748 if (callback) callback('No Title');
120752 var url = endpoint.replace('en', lang) + utilQsString({
120760 d3_json(url).then(function (result) {
120761 if (result && result.error) {
120762 throw new Error(result.error);
120763 } else if (!result || !result.query || !result.query.pages) {
120764 throw new Error('No Results');
120768 var list = result.query.pages[Object.keys(result.query.pages)[0]];
120771 if (list && list.langlinks) {
120772 list.langlinks.forEach(function (d) {
120773 translations[d.lang] = d['*'];
120777 callback(null, translations);
120779 })["catch"](function (err) {
120780 if (callback) callback(err.message);
120786 geocoder: serviceNominatim,
120787 keepRight: serviceKeepRight,
120788 improveOSM: serviceImproveOSM,
120790 mapillary: serviceMapillary,
120792 kartaview: serviceKartaview,
120794 osmWikibase: serviceOsmWikibase,
120795 maprules: serviceMapRules,
120796 streetside: serviceStreetside,
120797 taginfo: serviceTaginfo,
120798 vectorTile: serviceVectorTile,
120799 wikidata: serviceWikidata,
120800 wikipedia: serviceWikipedia
120803 function modeDragNote(context) {
120808 var edit = behaviorEdit(context);
120814 var _note; // most current note.. dragged note may have stale datum.
120817 function startNudge(d3_event, nudge) {
120818 if (_nudgeInterval) window.clearInterval(_nudgeInterval);
120819 _nudgeInterval = window.setInterval(function () {
120820 context.map().pan(nudge);
120821 doMove(d3_event, nudge);
120827 window.clearInterval(_nudgeInterval);
120832 function origin(note) {
120833 return context.projection(note.loc);
120836 function start(d3_event, note) {
120838 var osm = services.osm;
120841 // Get latest note from cache.. The marker may have a stale datum bound to it
120842 // and dragging it around can sometimes delete the users note comment.
120843 _note = osm.getNote(_note.id);
120846 context.surface().selectAll('.note-' + _note.id).classed('active', true);
120847 context.perform(actionNoop());
120849 context.selectedNoteID(_note.id);
120852 function move(d3_event, entity, point) {
120853 d3_event.stopPropagation();
120854 _lastLoc = context.projection.invert(point);
120856 var nudge = geoViewportEdge(point, context.map().dimensions());
120859 startNudge(d3_event, nudge);
120865 function doMove(d3_event, nudge) {
120866 nudge = nudge || [0, 0];
120867 var currPoint = d3_event && d3_event.point || context.projection(_lastLoc);
120868 var currMouse = geoVecSubtract(currPoint, nudge);
120869 var loc = context.projection.invert(currMouse);
120870 _note = _note.move(loc);
120871 var osm = services.osm;
120874 osm.replaceNote(_note); // update note cache
120877 context.replace(actionNoop()); // trigger redraw
120881 context.replace(actionNoop()); // trigger redraw
120883 context.selectedNoteID(_note.id).enter(modeSelectNote(context, _note.id));
120886 var drag = behaviorDrag().selector('.layer-touch.markers .target.note.new').surface(context.container().select('.main-map').node()).origin(origin).on('start', start).on('move', move).on('end', end);
120888 mode.enter = function () {
120892 mode.exit = function () {
120893 context.ui().sidebar.hover.cancel();
120894 context.uninstall(edit);
120895 context.surface().selectAll('.active').classed('active', false);
120903 function modeSelectData(context, selectedDatum) {
120908 var keybinding = utilKeybinding('select-data');
120909 var dataEditor = uiDataEditor(context);
120910 var behaviors = [behaviorBreathe(), behaviorHover(context), behaviorSelect(context), behaviorLasso(context), modeDragNode(context).behavior, modeDragNote(context).behavior]; // class the data as selected, or return to browse mode if the data is gone
120912 function selectData(d3_event, drawn) {
120913 var selection = context.surface().selectAll('.layer-mapdata .data' + selectedDatum.__featurehash__);
120915 if (selection.empty()) {
120916 // Return to browse mode if selected DOM elements have
120917 // disappeared because the user moved them out of view..
120918 var source = d3_event && d3_event.type === 'zoom' && d3_event.sourceEvent;
120920 if (drawn && source && (source.type === 'pointermove' || source.type === 'mousemove' || source.type === 'touchmove')) {
120921 context.enter(modeBrowse(context));
120924 selection.classed('selected', true);
120929 if (context.container().select('.combobox').size()) return;
120930 context.enter(modeBrowse(context));
120933 mode.zoomToSelected = function () {
120934 var extent = geoExtent(d3_geoBounds(selectedDatum));
120935 context.map().centerZoomEase(extent.center(), context.map().trimmedExtentZoom(extent));
120938 mode.enter = function () {
120939 behaviors.forEach(context.install);
120940 keybinding.on(_t('inspector.zoom_to.key'), mode.zoomToSelected).on('⎋', esc, true);
120941 select(document).call(keybinding);
120943 var sidebar = context.ui().sidebar;
120944 sidebar.show(dataEditor.datum(selectedDatum)); // expand the sidebar, avoid obscuring the data if needed
120946 var extent = geoExtent(d3_geoBounds(selectedDatum));
120947 sidebar.expand(sidebar.intersects(extent));
120948 context.map().on('drawn.select-data', selectData);
120951 mode.exit = function () {
120952 behaviors.forEach(context.uninstall);
120953 select(document).call(keybinding.unbind);
120954 context.surface().selectAll('.layer-mapdata .selected').classed('selected hover', false);
120955 context.map().on('drawn.select-data', null);
120956 context.ui().sidebar.hide();
120962 function behaviorSelect(context) {
120963 var _tolerancePx = 4; // see also behaviorDrag
120965 var _lastMouseEvent = null;
120967 var _downPointers = {};
120968 var _longPressTimeout = null;
120969 var _lastInteractionType = null; // the id of the down pointer that's enabling multiselection while down
120971 var _multiselectionPointerId = null; // use pointer events on supported platforms; fallback to mouse events
120973 var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
120975 function keydown(d3_event) {
120976 if (d3_event.keyCode === 32) {
120977 // don't react to spacebar events during text input
120978 var activeNode = document.activeElement;
120979 if (activeNode && new Set(['INPUT', 'TEXTAREA']).has(activeNode.nodeName)) return;
120982 if (d3_event.keyCode === 93 || // context menu key
120983 d3_event.keyCode === 32) {
120985 d3_event.preventDefault();
120988 if (d3_event.repeat) return; // ignore repeated events for held keys
120989 // if any key is pressed the user is probably doing something other than long-pressing
120993 if (d3_event.shiftKey) {
120994 context.surface().classed('behavior-multiselect', true);
120997 if (d3_event.keyCode === 32) {
120999 if (!_downPointers.spacebar && _lastMouseEvent) {
121001 _longPressTimeout = window.setTimeout(didLongPress, 500, 'spacebar', 'spacebar');
121002 _downPointers.spacebar = {
121003 firstEvent: _lastMouseEvent,
121004 lastEvent: _lastMouseEvent
121010 function keyup(d3_event) {
121013 if (!d3_event.shiftKey) {
121014 context.surface().classed('behavior-multiselect', false);
121017 if (d3_event.keyCode === 93) {
121019 d3_event.preventDefault();
121020 _lastInteractionType = 'menukey';
121022 } else if (d3_event.keyCode === 32) {
121024 var pointer = _downPointers.spacebar;
121027 delete _downPointers.spacebar;
121028 if (pointer.done) return;
121029 d3_event.preventDefault();
121030 _lastInteractionType = 'spacebar';
121031 click(pointer.firstEvent, pointer.lastEvent, 'spacebar');
121036 function pointerdown(d3_event) {
121037 var id = (d3_event.pointerId || 'mouse').toString();
121039 if (d3_event.buttons && d3_event.buttons !== 1) return;
121040 context.ui().closeEditMenu();
121041 _longPressTimeout = window.setTimeout(didLongPress, 500, id, 'longdown-' + (d3_event.pointerType || 'mouse'));
121048 function didLongPress(id, interactionType) {
121049 var pointer = _downPointers[id];
121052 for (var i in _downPointers) {
121053 // don't allow this or any currently down pointer to trigger another click
121054 _downPointers[i].done = true;
121055 } // treat long presses like right-clicks
121058 _longPressTimeout = null;
121059 _lastInteractionType = interactionType;
121061 click(pointer.firstEvent, pointer.lastEvent, id);
121064 function pointermove(d3_event) {
121065 var id = (d3_event.pointerId || 'mouse').toString();
121067 if (_downPointers[id]) {
121068 _downPointers[id].lastEvent = d3_event;
121071 if (!d3_event.pointerType || d3_event.pointerType === 'mouse') {
121072 _lastMouseEvent = d3_event;
121074 if (_downPointers.spacebar) {
121075 _downPointers.spacebar.lastEvent = d3_event;
121080 function pointerup(d3_event) {
121081 var id = (d3_event.pointerId || 'mouse').toString();
121082 var pointer = _downPointers[id];
121084 delete _downPointers[id];
121086 if (_multiselectionPointerId === id) {
121087 _multiselectionPointerId = null;
121090 if (pointer.done) return;
121091 click(pointer.firstEvent, d3_event, id);
121094 function pointercancel(d3_event) {
121095 var id = (d3_event.pointerId || 'mouse').toString();
121096 if (!_downPointers[id]) return;
121097 delete _downPointers[id];
121099 if (_multiselectionPointerId === id) {
121100 _multiselectionPointerId = null;
121104 function contextmenu(d3_event) {
121105 d3_event.preventDefault();
121107 if (!+d3_event.clientX && !+d3_event.clientY) {
121109 d3_event.sourceEvent = _lastMouseEvent;
121114 _lastMouseEvent = d3_event;
121115 _lastInteractionType = 'rightclick';
121119 click(d3_event, d3_event);
121122 function click(firstEvent, lastEvent, pointerId) {
121124 var mapNode = context.container().select('.main-map').node(); // Use the `main-map` coordinate system since the surface and supersurface
121125 // are transformed when drag-panning.
121127 var pointGetter = utilFastMouse(mapNode);
121128 var p1 = pointGetter(firstEvent);
121129 var p2 = pointGetter(lastEvent);
121130 var dist = geoVecLength(p1, p2);
121132 if (dist > _tolerancePx || !mapContains(lastEvent)) {
121137 var targetDatum = lastEvent.target.__data__;
121138 var multiselectEntityId;
121140 if (!_multiselectionPointerId) {
121141 // If a different pointer than the one triggering this click is down on a
121142 // feature, treat this and all future clicks as multiselection until that
121144 var selectPointerInfo = pointerDownOnSelection(pointerId);
121146 if (selectPointerInfo) {
121147 _multiselectionPointerId = selectPointerInfo.pointerId; // if the other feature isn't selected yet, make sure we select it
121149 multiselectEntityId = !selectPointerInfo.selected && selectPointerInfo.entityId;
121150 _downPointers[selectPointerInfo.pointerId].done = true;
121152 } // support multiselect if data is already selected
121155 var isMultiselect = context.mode().id === 'select' && ( // and shift key is down
121156 lastEvent && lastEvent.shiftKey || // or we're lasso-selecting
121157 context.surface().select('.lasso').node() || // or a pointer is down over a selected feature
121158 _multiselectionPointerId && !multiselectEntityId);
121160 processClick(targetDatum, isMultiselect, p2, multiselectEntityId);
121162 function mapContains(event) {
121163 var rect = mapNode.getBoundingClientRect();
121164 return event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom;
121167 function pointerDownOnSelection(skipPointerId) {
121168 var mode = context.mode();
121169 var selectedIDs = mode.id === 'select' ? mode.selectedIDs() : [];
121171 for (var pointerId in _downPointers) {
121172 if (pointerId === 'spacebar' || pointerId === skipPointerId) continue;
121173 var pointerInfo = _downPointers[pointerId];
121174 var p1 = pointGetter(pointerInfo.firstEvent);
121175 var p2 = pointGetter(pointerInfo.lastEvent);
121176 if (geoVecLength(p1, p2) > _tolerancePx) continue;
121177 var datum = pointerInfo.firstEvent.target.__data__;
121178 var entity = datum && datum.properties && datum.properties.entity || datum;
121180 if (context.graph().hasEntity(entity.id)) {
121184 selected: selectedIDs.indexOf(entity.id) !== -1
121193 function processClick(datum, isMultiselect, point, alsoSelectId) {
121194 var mode = context.mode();
121195 var showMenu = _showMenu;
121196 var interactionType = _lastInteractionType;
121197 var entity = datum && datum.properties && datum.properties.entity;
121198 if (entity) datum = entity;
121200 if (datum && datum.type === 'midpoint') {
121201 // treat targeting midpoints as if targeting the parent way
121202 datum = datum.parents[0];
121207 if (datum instanceof osmEntity) {
121209 var selectedIDs = context.selectedIDs();
121210 context.selectedNoteID(null);
121211 context.selectedErrorID(null);
121214 // don't change the selection if we're toggling the menu atop a multiselection
121215 if (!showMenu || selectedIDs.length <= 1 || selectedIDs.indexOf(datum.id) === -1) {
121216 if (alsoSelectId === datum.id) alsoSelectId = null;
121217 selectedIDs = (alsoSelectId ? [alsoSelectId] : []).concat([datum.id]); // always enter modeSelect even if the entity is already
121218 // selected since listeners may expect `context.enter` events,
121219 // e.g. in the walkthrough
121221 newMode = mode.id === 'select' ? mode.selectedIDs(selectedIDs) : modeSelect(context, selectedIDs).selectBehavior(behavior);
121222 context.enter(newMode);
121225 if (selectedIDs.indexOf(datum.id) !== -1) {
121226 // clicked entity is already in the selectedIDs list..
121228 // deselect clicked entity, then reenter select mode or return to browse mode..
121229 selectedIDs = selectedIDs.filter(function (id) {
121230 return id !== datum.id;
121232 newMode = selectedIDs.length ? mode.selectedIDs(selectedIDs) : modeBrowse(context).selectBehavior(behavior);
121233 context.enter(newMode);
121236 // clicked entity is not in the selected list, add it..
121237 selectedIDs = selectedIDs.concat([datum.id]);
121238 newMode = mode.selectedIDs(selectedIDs);
121239 context.enter(newMode);
121242 } else if (datum && datum.__featurehash__ && !isMultiselect) {
121243 // targeting custom data
121244 context.selectedNoteID(null).enter(modeSelectData(context, datum));
121245 } else if (datum instanceof osmNote && !isMultiselect) {
121247 context.selectedNoteID(datum.id).enter(modeSelectNote(context, datum.id));
121248 } else if (datum instanceof QAItem & !isMultiselect) {
121249 // targeting an external QA issue
121250 context.selectedErrorID(datum.id).enter(modeSelectError(context, datum.id, datum.service));
121253 context.selectedNoteID(null);
121254 context.selectedErrorID(null);
121256 if (!isMultiselect && mode.id !== 'browse') {
121257 context.enter(modeBrowse(context));
121261 context.ui().closeEditMenu(); // always request to show the edit menu in case the mode needs it
121263 if (showMenu) context.ui().showEditMenu(point, interactionType);
121267 function cancelLongPress() {
121268 if (_longPressTimeout) window.clearTimeout(_longPressTimeout);
121269 _longPressTimeout = null;
121272 function resetProperties() {
121275 _lastInteractionType = null; // don't reset _lastMouseEvent since it might still be useful
121278 function behavior(selection) {
121280 _lastMouseEvent = context.map().lastPointerEvent();
121281 select(window).on('keydown.select', keydown).on('keyup.select', keyup).on(_pointerPrefix + 'move.select', pointermove, true).on(_pointerPrefix + 'up.select', pointerup, true).on('pointercancel.select', pointercancel, true).on('contextmenu.select-window', function (d3_event) {
121282 // Edge and IE really like to show the contextmenu on the
121283 // menubar when user presses a keyboard menu button
121284 // even after we've already preventdefaulted the key event.
121287 if (+e.clientX === 0 && +e.clientY === 0) {
121288 d3_event.preventDefault();
121291 selection.on(_pointerPrefix + 'down.select', pointerdown).on('contextmenu.select', contextmenu);
121292 /*if (d3_event && d3_event.shiftKey) {
121294 .classed('behavior-multiselect', true);
121298 behavior.off = function (selection) {
121300 select(window).on('keydown.select', null).on('keyup.select', null).on('contextmenu.select-window', null).on(_pointerPrefix + 'move.select', null, true).on(_pointerPrefix + 'up.select', null, true).on('pointercancel.select', null, true);
121301 selection.on(_pointerPrefix + 'down.select', null).on('contextmenu.select', null);
121302 context.surface().classed('behavior-multiselect', false);
121308 function operationContinue(context, selectedIDs) {
121309 var _entities = selectedIDs.map(function (id) {
121310 return context.graph().entity(id);
121313 var _geometries = Object.assign({
121316 }, utilArrayGroupBy(_entities, function (entity) {
121317 return entity.geometry(context.graph());
121320 var _vertex = _geometries.vertex.length && _geometries.vertex[0];
121322 function candidateWays() {
121323 return _vertex ? context.graph().parentWays(_vertex).filter(function (parent) {
121324 return parent.geometry(context.graph()) === 'line' && !parent.isClosed() && parent.affix(_vertex.id) && (_geometries.line.length === 0 || _geometries.line[0] === parent);
121328 var _candidates = candidateWays();
121330 var operation = function operation() {
121331 var candidate = _candidates[0];
121332 context.enter(modeDrawLine(context, candidate.id, context.graph(), 'line', candidate.affix(_vertex.id), true));
121335 operation.relatedEntityIds = function () {
121336 return _candidates.length ? [_candidates[0].id] : [];
121339 operation.available = function () {
121340 return _geometries.vertex.length === 1 && _geometries.line.length <= 1 && !context.features().hasHiddenConnections(_vertex, context.graph());
121343 operation.disabled = function () {
121344 if (_candidates.length === 0) {
121346 } else if (_candidates.length > 1) {
121353 operation.tooltip = function () {
121354 var disable = operation.disabled();
121355 return disable ? _t('operations.continue.' + disable) : _t('operations.continue.description');
121358 operation.annotation = function () {
121359 return _t('operations.continue.annotation.line');
121362 operation.id = 'continue';
121363 operation.keys = [_t('operations.continue.key')];
121364 operation.title = _t('operations.continue.title');
121365 operation.behavior = behaviorOperation(context).which(operation);
121369 function operationCopy(context, selectedIDs) {
121370 function getFilteredIdsToCopy() {
121371 return selectedIDs.filter(function (selectedID) {
121372 var entity = context.graph().hasEntity(selectedID); // don't copy untagged vertices separately from ways
121374 return entity.hasInterestingTags() || entity.geometry(context.graph()) !== 'vertex';
121378 var operation = function operation() {
121379 var graph = context.graph();
121380 var selected = groupEntities(getFilteredIdsToCopy(), graph);
121386 for (i = 0; i < selected.relation.length; i++) {
121387 entity = selected.relation[i];
121389 if (!skip[entity.id] && entity.isComplete(graph)) {
121390 canCopy.push(entity.id);
121391 skip = getDescendants(entity.id, graph, skip);
121395 for (i = 0; i < selected.way.length; i++) {
121396 entity = selected.way[i];
121398 if (!skip[entity.id]) {
121399 canCopy.push(entity.id);
121400 skip = getDescendants(entity.id, graph, skip);
121404 for (i = 0; i < selected.node.length; i++) {
121405 entity = selected.node[i];
121407 if (!skip[entity.id]) {
121408 canCopy.push(entity.id);
121412 context.copyIDs(canCopy);
121414 if (_point && (canCopy.length !== 1 || graph.entity(canCopy[0]).type !== 'node')) {
121415 // store the anchor coordinates if copying more than a single node
121416 context.copyLonLat(context.projection.invert(_point));
121418 context.copyLonLat(null);
121422 function groupEntities(ids, graph) {
121423 var entities = ids.map(function (id) {
121424 return graph.entity(id);
121430 }, utilArrayGroupBy(entities, 'type'));
121433 function getDescendants(id, graph, descendants) {
121434 var entity = graph.entity(id);
121436 descendants = descendants || {};
121438 if (entity.type === 'relation') {
121439 children = entity.members.map(function (m) {
121442 } else if (entity.type === 'way') {
121443 children = entity.nodes;
121448 for (var i = 0; i < children.length; i++) {
121449 if (!descendants[children[i]]) {
121450 descendants[children[i]] = true;
121451 descendants = getDescendants(children[i], graph, descendants);
121458 operation.available = function () {
121459 return getFilteredIdsToCopy().length > 0;
121462 operation.disabled = function () {
121463 var extent = utilTotalExtent(getFilteredIdsToCopy(), context.graph());
121465 if (extent.percentContainedIn(context.map().extent()) < 0.8) {
121472 operation.availableForKeypress = function () {
121473 var selection = window.getSelection && window.getSelection(); // if the user has text selected then let them copy that, not the selected feature
121475 return !selection || !selection.toString();
121478 operation.tooltip = function () {
121479 var disable = operation.disabled();
121480 return disable ? _t('operations.copy.' + disable, {
121482 }) : _t('operations.copy.description', {
121487 operation.annotation = function () {
121488 return _t('operations.copy.annotation', {
121495 operation.point = function (val) {
121501 operation.keys = [uiCmd('⌘C')];
121502 operation.title = _t('operations.copy.title');
121503 operation.behavior = behaviorOperation(context).which(operation);
121507 function operationDisconnect(context, selectedIDs) {
121512 selectedIDs.forEach(function (id) {
121513 var entity = context.entity(id);
121515 if (entity.type === 'way') {
121517 } else if (entity.geometry(context.graph()) === 'vertex') {
121526 _annotationID = 'features';
121528 var _disconnectingVertexIds = [];
121529 var _disconnectingWayIds = [];
121531 if (_vertexIDs.length > 0) {
121532 // At the selected vertices, disconnect the selected ways, if any, else
121533 // disconnect all connected ways
121534 _disconnectingVertexIds = _vertexIDs;
121536 _vertexIDs.forEach(function (vertexID) {
121537 var action = actionDisconnect(vertexID);
121539 if (_wayIDs.length > 0) {
121540 var waysIDsForVertex = _wayIDs.filter(function (wayID) {
121541 var way = context.entity(wayID);
121542 return way.nodes.indexOf(vertexID) !== -1;
121545 action.limitWays(waysIDsForVertex);
121550 _disconnectingWayIds = _disconnectingWayIds.concat(context.graph().parentWays(context.graph().entity(vertexID)).map(function (d) {
121555 _disconnectingWayIds = utilArrayUniq(_disconnectingWayIds).filter(function (id) {
121556 return _wayIDs.indexOf(id) === -1;
121558 _descriptionID += _actions.length === 1 ? 'single_point.' : 'multiple_points.';
121560 if (_wayIDs.length === 1) {
121561 _descriptionID += 'single_way.' + context.graph().geometry(_wayIDs[0]);
121563 _descriptionID += _wayIDs.length === 0 ? 'no_ways' : 'multiple_ways';
121565 } else if (_wayIDs.length > 0) {
121566 // Disconnect the selected ways from each other, if they're connected,
121567 // else disconnect them from all connected ways
121568 var ways = _wayIDs.map(function (id) {
121569 return context.entity(id);
121572 var nodes = utilGetAllNodes(_wayIDs, context.graph());
121573 _coords = nodes.map(function (n) {
121575 }); // actions for connected nodes shared by at least two selected ways
121577 var sharedActions = [];
121578 var sharedNodes = []; // actions for connected nodes
121580 var unsharedActions = [];
121581 var unsharedNodes = [];
121582 nodes.forEach(function (node) {
121583 var action = actionDisconnect(node.id).limitWays(_wayIDs);
121585 if (action.disabled(context.graph()) !== 'not_connected') {
121591 if (way.nodes.indexOf(node.id) !== -1) {
121599 sharedActions.push(action);
121600 sharedNodes.push(node);
121602 unsharedActions.push(action);
121603 unsharedNodes.push(node);
121607 _descriptionID += 'no_points.';
121608 _descriptionID += _wayIDs.length === 1 ? 'single_way.' : 'multiple_ways.';
121610 if (sharedActions.length) {
121611 // if any nodes are shared, only disconnect the selected ways from each other
121612 _actions = sharedActions;
121613 _disconnectingVertexIds = sharedNodes.map(function (node) {
121616 _descriptionID += 'conjoined';
121617 _annotationID = 'from_each_other';
121619 // if no nodes are shared, disconnect the selected ways from all connected ways
121620 _actions = unsharedActions;
121621 _disconnectingVertexIds = unsharedNodes.map(function (node) {
121625 if (_wayIDs.length === 1) {
121626 _descriptionID += context.graph().geometry(_wayIDs[0]);
121628 _descriptionID += 'separate';
121633 var _extent = utilTotalExtent(_disconnectingVertexIds, context.graph());
121635 var operation = function operation() {
121636 context.perform(function (graph) {
121637 return _actions.reduce(function (graph, action) {
121640 }, operation.annotation());
121641 context.validator().validate();
121644 operation.relatedEntityIds = function () {
121645 if (_vertexIDs.length) {
121646 return _disconnectingWayIds;
121649 return _disconnectingVertexIds;
121652 operation.available = function () {
121653 if (_actions.length === 0) return false;
121654 if (_otherIDs.length !== 0) return false;
121655 if (_vertexIDs.length !== 0 && _wayIDs.length !== 0 && !_wayIDs.every(function (wayID) {
121656 return _vertexIDs.some(function (vertexID) {
121657 var way = context.entity(wayID);
121658 return way.nodes.indexOf(vertexID) !== -1;
121664 operation.disabled = function () {
121667 for (var actionIndex in _actions) {
121668 reason = _actions[actionIndex].disabled(context.graph());
121669 if (reason) return reason;
121672 if (_extent && _extent.percentContainedIn(context.map().extent()) < 0.8) {
121673 return 'too_large.' + ((_vertexIDs.length ? _vertexIDs : _wayIDs).length === 1 ? 'single' : 'multiple');
121674 } else if (_coords && someMissing()) {
121675 return 'not_downloaded';
121676 } else if (selectedIDs.some(context.hasHiddenConnections)) {
121677 return 'connected_to_hidden';
121682 function someMissing() {
121683 if (context.inIntro()) return false;
121684 var osm = context.connection();
121687 var missing = _coords.filter(function (loc) {
121688 return !osm.isDataLoaded(loc);
121692 missing.forEach(function (loc) {
121693 context.loadTileAtLoc(loc);
121703 operation.tooltip = function () {
121704 var disable = operation.disabled();
121707 return _t('operations.disconnect.' + disable);
121710 return _t('operations.disconnect.description.' + _descriptionID);
121713 operation.annotation = function () {
121714 return _t('operations.disconnect.annotation.' + _annotationID);
121717 operation.id = 'disconnect';
121718 operation.keys = [_t('operations.disconnect.key')];
121719 operation.title = _t('operations.disconnect.title');
121720 operation.behavior = behaviorOperation(context).which(operation);
121724 function operationDowngrade(context, selectedIDs) {
121725 var _affectedFeatureCount = 0;
121727 var _downgradeType = downgradeTypeForEntityIDs(selectedIDs);
121729 var _multi = _affectedFeatureCount === 1 ? 'single' : 'multiple';
121731 function downgradeTypeForEntityIDs(entityIds) {
121733 _affectedFeatureCount = 0;
121735 for (var i in entityIds) {
121736 var entityID = entityIds[i];
121737 var type = downgradeTypeForEntityID(entityID);
121740 _affectedFeatureCount += 1;
121742 if (downgradeType && type !== downgradeType) {
121743 if (downgradeType !== 'generic' && type !== 'generic') {
121744 downgradeType = 'building_address';
121746 downgradeType = 'generic';
121757 function downgradeTypeForEntityID(entityID) {
121758 var graph = context.graph();
121759 var entity = graph.entity(entityID);
121760 var preset = _mainPresetIndex.match(entity, graph);
121761 if (!preset || preset.isFallback()) return null;
121763 if (entity.type === 'node' && preset.id !== 'address' && Object.keys(entity.tags).some(function (key) {
121764 return key.match(/^addr:.{1,}/);
121769 var geometry = entity.geometry(graph);
121771 if (geometry === 'area' && entity.tags.building && !preset.tags.building) {
121775 if (geometry === 'vertex' && Object.keys(entity.tags).length) {
121782 var buildingKeysToKeep = ['architect', 'building', 'height', 'layer', 'source', 'type', 'wheelchair'];
121783 var addressKeysToKeep = ['source'];
121785 var operation = function operation() {
121786 context.perform(function (graph) {
121787 for (var i in selectedIDs) {
121788 var entityID = selectedIDs[i];
121789 var type = downgradeTypeForEntityID(entityID);
121791 var tags = Object.assign({}, graph.entity(entityID).tags); // shallow copy
121793 for (var key in tags) {
121794 if (type === 'address' && addressKeysToKeep.indexOf(key) !== -1) continue;
121796 if (type === 'building') {
121797 if (buildingKeysToKeep.indexOf(key) !== -1 || key.match(/^building:.{1,}/) || key.match(/^roof:.{1,}/)) continue;
121800 if (type !== 'generic') {
121801 if (key.match(/^addr:.{1,}/) || key.match(/^source:.{1,}/)) continue;
121807 graph = actionChangeTags(entityID, tags)(graph);
121811 }, operation.annotation());
121812 context.validator().validate(); // refresh the select mode to enable the delete operation
121814 context.enter(modeSelect(context, selectedIDs));
121817 operation.available = function () {
121821 operation.disabled = function () {
121822 if (selectedIDs.some(hasWikidataTag)) {
121823 return 'has_wikidata_tag';
121828 function hasWikidataTag(id) {
121829 var entity = context.entity(id);
121830 return entity.tags.wikidata && entity.tags.wikidata.trim().length > 0;
121834 operation.tooltip = function () {
121835 var disable = operation.disabled();
121836 return disable ? _t('operations.downgrade.' + disable + '.' + _multi) : _t('operations.downgrade.description.' + _downgradeType);
121839 operation.annotation = function () {
121842 if (_downgradeType === 'building_address') {
121845 suffix = _downgradeType;
121848 return _t('operations.downgrade.annotation.' + suffix, {
121849 n: _affectedFeatureCount
121853 operation.id = 'downgrade';
121854 operation.keys = [uiCmd('⌫')];
121855 operation.title = _t('operations.downgrade.title');
121856 operation.behavior = behaviorOperation(context).which(operation);
121860 function operationExtract(context, selectedIDs) {
121861 var _amount = selectedIDs.length === 1 ? 'single' : 'multiple';
121863 var _geometries = utilArrayUniq(selectedIDs.map(function (entityID) {
121864 return context.graph().hasEntity(entityID) && context.graph().geometry(entityID);
121867 var _geometryID = _geometries.length === 1 ? _geometries[0] : 'feature';
121871 var _actions = selectedIDs.map(function (entityID) {
121872 var graph = context.graph();
121873 var entity = graph.hasEntity(entityID);
121874 if (!entity || !entity.hasInterestingTags()) return null;
121875 if (entity.type === 'node' && graph.parentWays(entity).length === 0) return null;
121877 if (entity.type !== 'node') {
121878 var preset = _mainPresetIndex.match(entity, graph); // only allow extraction from ways/relations if the preset supports points
121880 if (preset.geometry.indexOf('point') === -1) return null;
121883 _extent = _extent ? _extent.extend(entity.extent(graph)) : entity.extent(graph);
121884 return actionExtract(entityID, context.projection);
121887 var operation = function operation() {
121888 var combinedAction = function combinedAction(graph) {
121889 _actions.forEach(function (action) {
121896 context.perform(combinedAction, operation.annotation()); // do the extract
121898 var extractedNodeIDs = _actions.map(function (action) {
121899 return action.getExtractedNodeID();
121902 context.enter(modeSelect(context, extractedNodeIDs));
121905 operation.available = function () {
121906 return _actions.length && selectedIDs.length === _actions.length;
121909 operation.disabled = function () {
121910 if (_extent && _extent.percentContainedIn(context.map().extent()) < 0.8) {
121912 } else if (selectedIDs.some(function (entityID) {
121913 return context.graph().geometry(entityID) === 'vertex' && context.hasHiddenConnections(entityID);
121915 return 'connected_to_hidden';
121921 operation.tooltip = function () {
121922 var disableReason = operation.disabled();
121925 return _t('operations.extract.' + disableReason + '.' + _amount);
121927 return _t('operations.extract.description.' + _geometryID + '.' + _amount);
121931 operation.annotation = function () {
121932 return _t('operations.extract.annotation', {
121937 operation.id = 'extract';
121938 operation.keys = [_t('operations.extract.key')];
121939 operation.title = _t('operations.extract.title');
121940 operation.behavior = behaviorOperation(context).which(operation);
121944 function operationMerge(context, selectedIDs) {
121945 var _action = getAction();
121948 // prefer a non-disabled action first
121949 var join = actionJoin(selectedIDs);
121950 if (!join.disabled(context.graph())) return join;
121951 var merge = actionMerge(selectedIDs);
121952 if (!merge.disabled(context.graph())) return merge;
121953 var mergePolygon = actionMergePolygon(selectedIDs);
121954 if (!mergePolygon.disabled(context.graph())) return mergePolygon;
121955 var mergeNodes = actionMergeNodes(selectedIDs);
121956 if (!mergeNodes.disabled(context.graph())) return mergeNodes; // otherwise prefer an action with an interesting disabled reason
121958 if (join.disabled(context.graph()) !== 'not_eligible') return join;
121959 if (merge.disabled(context.graph()) !== 'not_eligible') return merge;
121960 if (mergePolygon.disabled(context.graph()) !== 'not_eligible') return mergePolygon;
121964 var operation = function operation() {
121965 if (operation.disabled()) return;
121966 context.perform(_action, operation.annotation());
121967 context.validator().validate();
121968 var resultIDs = selectedIDs.filter(context.hasEntity);
121970 if (resultIDs.length > 1) {
121971 var interestingIDs = resultIDs.filter(function (id) {
121972 return context.entity(id).hasInterestingTags();
121974 if (interestingIDs.length) resultIDs = interestingIDs;
121977 context.enter(modeSelect(context, resultIDs));
121980 operation.available = function () {
121981 return selectedIDs.length >= 2;
121984 operation.disabled = function () {
121985 var actionDisabled = _action.disabled(context.graph());
121987 if (actionDisabled) return actionDisabled;
121988 var osm = context.connection();
121990 if (osm && _action.resultingWayNodesLength && _action.resultingWayNodesLength(context.graph()) > osm.maxWayNodes()) {
121991 return 'too_many_vertices';
121997 operation.tooltip = function () {
121998 var disabled = operation.disabled();
122001 if (disabled === 'conflicting_relations') {
122002 return _t('operations.merge.conflicting_relations');
122005 if (disabled === 'restriction' || disabled === 'connectivity') {
122006 return _t('operations.merge.damage_relation', {
122007 relation: _mainPresetIndex.item('type/' + disabled).name()
122011 return _t('operations.merge.' + disabled);
122014 return _t('operations.merge.description');
122017 operation.annotation = function () {
122018 return _t('operations.merge.annotation', {
122023 operation.id = 'merge';
122024 operation.keys = [_t('operations.merge.key')];
122025 operation.title = _t('operations.merge.title');
122026 operation.behavior = behaviorOperation(context).which(operation);
122030 function operationPaste(context) {
122033 var operation = function operation() {
122034 if (!_pastePoint) return;
122035 var oldIDs = context.copyIDs();
122036 if (!oldIDs.length) return;
122037 var projection = context.projection;
122038 var extent = geoExtent();
122039 var oldGraph = context.copyGraph();
122041 var action = actionCopyEntities(oldIDs, oldGraph);
122042 context.perform(action);
122043 var copies = action.copies();
122044 var originals = new Set();
122045 Object.values(copies).forEach(function (entity) {
122046 originals.add(entity.id);
122049 for (var id in copies) {
122050 var oldEntity = oldGraph.entity(id);
122051 var newEntity = copies[id];
122053 extent._extend(oldEntity.extent(oldGraph)); // Exclude child nodes from newIDs if their parent way was also copied.
122056 var parents = context.graph().parentWays(newEntity);
122057 var parentCopied = parents.some(function (parent) {
122058 return originals.has(parent.id);
122062 newIDs.push(newEntity.id);
122064 } // Use the location of the copy operation to offset the paste location,
122065 // or else use the center of the pasted extent
122068 var copyPoint = context.copyLonLat() && projection(context.copyLonLat()) || projection(extent.center());
122069 var delta = geoVecSubtract(_pastePoint, copyPoint); // Move the pasted objects to be anchored at the paste location
122071 context.replace(actionMove(newIDs, delta, projection), operation.annotation());
122072 context.enter(modeSelect(context, newIDs));
122075 operation.point = function (val) {
122080 operation.available = function () {
122081 return context.mode().id === 'browse';
122084 operation.disabled = function () {
122085 return !context.copyIDs().length;
122088 operation.tooltip = function () {
122089 var oldGraph = context.copyGraph();
122090 var ids = context.copyIDs();
122093 return _t('operations.paste.nothing_copied');
122096 return _t('operations.paste.description', {
122097 feature: utilDisplayLabel(oldGraph.entity(ids[0]), oldGraph),
122102 operation.annotation = function () {
122103 var ids = context.copyIDs();
122104 return _t('operations.paste.annotation', {
122109 operation.id = 'paste';
122110 operation.keys = [uiCmd('⌘V')];
122111 operation.title = _t('operations.paste.title');
122115 function operationReverse(context, selectedIDs) {
122116 var operation = function operation() {
122117 context.perform(function combinedReverseAction(graph) {
122118 actions().forEach(function (action) {
122122 }, operation.annotation());
122123 context.validator().validate();
122126 function actions(situation) {
122127 return selectedIDs.map(function (entityID) {
122128 var entity = context.hasEntity(entityID);
122129 if (!entity) return null;
122131 if (situation === 'toolbar') {
122132 if (entity.type === 'way' && !entity.isOneWay() && !entity.isSided()) return null;
122135 var geometry = entity.geometry(context.graph());
122136 if (entity.type !== 'node' && geometry !== 'line') return null;
122137 var action = actionReverse(entityID);
122138 if (action.disabled(context.graph())) return null;
122143 function reverseTypeID() {
122145 var nodeActionCount = acts.filter(function (act) {
122146 var entity = context.hasEntity(act.entityID());
122147 return entity && entity.type === 'node';
122149 if (nodeActionCount === 0) return 'line';
122150 if (nodeActionCount === acts.length) return 'point';
122154 operation.available = function (situation) {
122155 return actions(situation).length > 0;
122158 operation.disabled = function () {
122162 operation.tooltip = function () {
122163 return _t('operations.reverse.description.' + reverseTypeID());
122166 operation.annotation = function () {
122168 return _t('operations.reverse.annotation.' + reverseTypeID(), {
122173 operation.id = 'reverse';
122174 operation.keys = [_t('operations.reverse.key')];
122175 operation.title = _t('operations.reverse.title');
122176 operation.behavior = behaviorOperation(context).which(operation);
122180 function operationSplit(context, selectedIDs) {
122181 var _vertexIds = selectedIDs.filter(function (id) {
122182 return context.graph().geometry(id) === 'vertex';
122185 var _selectedWayIds = selectedIDs.filter(function (id) {
122186 var entity = context.graph().hasEntity(id);
122187 return entity && entity.type === 'way';
122190 var _isAvailable = _vertexIds.length > 0 && _vertexIds.length + _selectedWayIds.length === selectedIDs.length;
122192 var _action = actionSplit(_vertexIds);
122195 var _geometry = 'feature';
122196 var _waysAmount = 'single';
122198 var _nodesAmount = _vertexIds.length === 1 ? 'single' : 'multiple';
122201 if (_selectedWayIds.length) _action.limitWays(_selectedWayIds);
122202 _ways = _action.ways(context.graph());
122205 _ways.forEach(function (way) {
122206 geometries[way.geometry(context.graph())] = true;
122209 if (Object.keys(geometries).length === 1) {
122210 _geometry = Object.keys(geometries)[0];
122213 _waysAmount = _ways.length === 1 ? 'single' : 'multiple';
122216 var operation = function operation() {
122217 var difference = context.perform(_action, operation.annotation()); // select both the nodes and the ways so the mapper can immediately disconnect them if desired
122219 var idsToSelect = _vertexIds.concat(difference.extantIDs().filter(function (id) {
122220 // filter out relations that may have had member additions
122221 return context.entity(id).type === 'way';
122224 context.enter(modeSelect(context, idsToSelect));
122227 operation.relatedEntityIds = function () {
122228 return _selectedWayIds.length ? [] : _ways.map(function (way) {
122233 operation.available = function () {
122237 operation.disabled = function () {
122238 var reason = _action.disabled(context.graph());
122242 } else if (selectedIDs.some(context.hasHiddenConnections)) {
122243 return 'connected_to_hidden';
122249 operation.tooltip = function () {
122250 var disable = operation.disabled();
122251 if (disable) return _t('operations.split.' + disable);
122252 return _t('operations.split.description.' + _geometry + '.' + _waysAmount + '.' + _nodesAmount + '_node');
122255 operation.annotation = function () {
122256 return _t('operations.split.annotation.' + _geometry, {
122261 operation.icon = function () {
122262 if (_waysAmount === 'multiple') {
122263 return '#iD-operation-split-multiple';
122265 return '#iD-operation-split';
122269 operation.id = 'split';
122270 operation.keys = [_t('operations.split.key')];
122271 operation.title = _t('operations.split.title');
122272 operation.behavior = behaviorOperation(context).which(operation);
122276 function operationStraighten(context, selectedIDs) {
122277 var _wayIDs = selectedIDs.filter(function (id) {
122278 return id.charAt(0) === 'w';
122281 var _nodeIDs = selectedIDs.filter(function (id) {
122282 return id.charAt(0) === 'n';
122285 var _amount = (_wayIDs.length ? _wayIDs : _nodeIDs).length === 1 ? 'single' : 'multiple';
122287 var _nodes = utilGetAllNodes(selectedIDs, context.graph());
122289 var _coords = _nodes.map(function (n) {
122293 var _extent = utilTotalExtent(selectedIDs, context.graph());
122295 var _action = chooseAction();
122299 function chooseAction() {
122300 // straighten selected nodes
122301 if (_wayIDs.length === 0 && _nodeIDs.length > 2) {
122303 return actionStraightenNodes(_nodeIDs, context.projection); // straighten selected ways (possibly between range of 2 selected nodes)
122304 } else if (_wayIDs.length > 0 && (_nodeIDs.length === 0 || _nodeIDs.length === 2)) {
122308 for (var i = 0; i < selectedIDs.length; i++) {
122309 var entity = context.entity(selectedIDs[i]);
122311 if (entity.type === 'node') {
122313 } else if (entity.type !== 'way' || entity.isClosed()) {
122314 return null; // exit early, can't straighten these
122317 startNodeIDs.push(entity.first());
122318 endNodeIDs.push(entity.last());
122319 } // Remove duplicate end/startNodeIDs (duplicate nodes cannot be at the line end)
122322 startNodeIDs = startNodeIDs.filter(function (n) {
122323 return startNodeIDs.indexOf(n) === startNodeIDs.lastIndexOf(n);
122325 endNodeIDs = endNodeIDs.filter(function (n) {
122326 return endNodeIDs.indexOf(n) === endNodeIDs.lastIndexOf(n);
122327 }); // Ensure all ways are connected (i.e. only 2 unique endpoints/startpoints)
122329 if (utilArrayDifference(startNodeIDs, endNodeIDs).length + utilArrayDifference(endNodeIDs, startNodeIDs).length !== 2) return null; // Ensure path contains at least 3 unique nodes
122331 var wayNodeIDs = utilGetAllNodes(_wayIDs, context.graph()).map(function (node) {
122334 if (wayNodeIDs.length <= 2) return null; // If range of 2 selected nodes is supplied, ensure nodes lie on the selected path
122336 if (_nodeIDs.length === 2 && (wayNodeIDs.indexOf(_nodeIDs[0]) === -1 || wayNodeIDs.indexOf(_nodeIDs[1]) === -1)) return null;
122339 // If we're only straightenting between two points, we only need that extent visible
122340 _extent = utilTotalExtent(_nodeIDs, context.graph());
122344 return actionStraightenWay(selectedIDs, context.projection);
122352 context.perform(_action, operation.annotation());
122353 window.setTimeout(function () {
122354 context.validator().validate();
122355 }, 300); // after any transition
122358 operation.available = function () {
122359 return Boolean(_action);
122362 operation.disabled = function () {
122363 var reason = _action.disabled(context.graph());
122367 } else if (_extent.percentContainedIn(context.map().extent()) < 0.8) {
122369 } else if (someMissing()) {
122370 return 'not_downloaded';
122371 } else if (selectedIDs.some(context.hasHiddenConnections)) {
122372 return 'connected_to_hidden';
122377 function someMissing() {
122378 if (context.inIntro()) return false;
122379 var osm = context.connection();
122382 var missing = _coords.filter(function (loc) {
122383 return !osm.isDataLoaded(loc);
122387 missing.forEach(function (loc) {
122388 context.loadTileAtLoc(loc);
122398 operation.tooltip = function () {
122399 var disable = operation.disabled();
122400 return disable ? _t('operations.straighten.' + disable + '.' + _amount) : _t('operations.straighten.description.' + _geometry + (_wayIDs.length === 1 ? '' : 's'));
122403 operation.annotation = function () {
122404 return _t('operations.straighten.annotation.' + _geometry, {
122405 n: _wayIDs.length ? _wayIDs.length : _nodeIDs.length
122409 operation.id = 'straighten';
122410 operation.keys = [_t('operations.straighten.key')];
122411 operation.title = _t('operations.straighten.title');
122412 operation.behavior = behaviorOperation(context).which(operation);
122416 var Operations = /*#__PURE__*/Object.freeze({
122418 operationCircularize: operationCircularize,
122419 operationContinue: operationContinue,
122420 operationCopy: operationCopy,
122421 operationDelete: operationDelete,
122422 operationDisconnect: operationDisconnect,
122423 operationDowngrade: operationDowngrade,
122424 operationExtract: operationExtract,
122425 operationMerge: operationMerge,
122426 operationMove: operationMove,
122427 operationOrthogonalize: operationOrthogonalize,
122428 operationPaste: operationPaste,
122429 operationReflectShort: operationReflectShort,
122430 operationReflectLong: operationReflectLong,
122431 operationReverse: operationReverse,
122432 operationRotate: operationRotate,
122433 operationSplit: operationSplit,
122434 operationStraighten: operationStraighten
122437 function modeSelect(context, selectedIDs) {
122442 var keybinding = utilKeybinding('select');
122444 var _breatheBehavior = behaviorBreathe();
122446 var _modeDragNode = modeDragNode(context);
122452 var _newFeature = false;
122453 var _follow = false; // `_focusedParentWayId` is used when we visit a vertex with multiple
122454 // parents, and we want to remember which parent line we started on.
122456 var _focusedParentWayId;
122461 if (selectedIDs && selectedIDs.length === 1) {
122462 return context.hasEntity(selectedIDs[0]);
122466 function selectedEntities() {
122467 return selectedIDs.map(function (id) {
122468 return context.hasEntity(id);
122472 function checkSelectedIDs() {
122475 if (Array.isArray(selectedIDs)) {
122476 ids = selectedIDs.filter(function (id) {
122477 return context.hasEntity(id);
122482 context.enter(modeBrowse(context));
122484 } else if (selectedIDs.length > 1 && ids.length === 1 || selectedIDs.length === 1 && ids.length > 1) {
122485 // switch between single- and multi-select UI
122486 context.enter(modeSelect(context, ids));
122492 } // find the parent ways for nextVertex, previousVertex, and selectParent
122495 function parentWaysIdsOfSelection(onlyCommonParents) {
122496 var graph = context.graph();
122499 for (var i = 0; i < selectedIDs.length; i++) {
122500 var entity = context.hasEntity(selectedIDs[i]);
122502 if (!entity || entity.geometry(graph) !== 'vertex') {
122503 return []; // selection includes some non-vertices
122506 var currParents = graph.parentWays(entity).map(function (w) {
122515 parents = (onlyCommonParents ? utilArrayIntersection : utilArrayUnion)(parents, currParents);
122523 } // find the child nodes for selected ways
122526 function childNodeIdsOfSelection(onlyCommon) {
122527 var graph = context.graph();
122530 for (var i = 0; i < selectedIDs.length; i++) {
122531 var entity = context.hasEntity(selectedIDs[i]);
122533 if (!entity || !['area', 'line'].includes(entity.geometry(graph))) {
122534 return []; // selection includes non-area/non-line
122537 var currChilds = graph.childNodes(entity).map(function (node) {
122546 childs = (onlyCommon ? utilArrayIntersection : utilArrayUnion)(childs, currChilds);
122556 function checkFocusedParent() {
122557 if (_focusedParentWayId) {
122558 var parents = parentWaysIdsOfSelection(true);
122559 if (parents.indexOf(_focusedParentWayId) === -1) _focusedParentWayId = null;
122563 function parentWayIdForVertexNavigation() {
122564 var parentIds = parentWaysIdsOfSelection(true);
122566 if (_focusedParentWayId && parentIds.indexOf(_focusedParentWayId) !== -1) {
122567 // prefer the previously seen parent
122568 return _focusedParentWayId;
122571 return parentIds.length ? parentIds[0] : null;
122574 mode.selectedIDs = function (val) {
122575 if (!arguments.length) return selectedIDs;
122580 mode.zoomToSelected = function () {
122581 context.map().zoomToEase(selectedEntities());
122584 mode.newFeature = function (val) {
122585 if (!arguments.length) return _newFeature;
122590 mode.selectBehavior = function (val) {
122591 if (!arguments.length) return _selectBehavior;
122596 mode.follow = function (val) {
122597 if (!arguments.length) return _follow;
122602 function loadOperations() {
122603 _operations.forEach(function (operation) {
122604 if (operation.behavior) {
122605 context.uninstall(operation.behavior);
122609 _operations = Object.values(Operations).map(function (o) {
122610 return o(context, selectedIDs);
122611 }).filter(function (o) {
122612 return o.id !== 'delete' && o.id !== 'downgrade' && o.id !== 'copy';
122613 }).concat([// group copy/downgrade/delete operation together at the end of the list
122614 operationCopy(context, selectedIDs), operationDowngrade(context, selectedIDs), operationDelete(context, selectedIDs)]).filter(function (operation) {
122615 return operation.available();
122618 _operations.forEach(function (operation) {
122619 if (operation.behavior) {
122620 context.install(operation.behavior);
122622 }); // remove any displayed menu
122625 context.ui().closeEditMenu();
122628 mode.operations = function () {
122632 mode.enter = function () {
122633 if (!checkSelectedIDs()) return;
122634 context.features().forceVisible(selectedIDs);
122636 _modeDragNode.restoreSelectedIDs(selectedIDs);
122640 if (!_behaviors.length) {
122641 if (!_selectBehavior) _selectBehavior = behaviorSelect(context);
122642 _behaviors = [behaviorPaste(context), _breatheBehavior, behaviorHover(context).on('hover', context.ui().sidebar.hoverModeSelect), _selectBehavior, behaviorLasso(context), _modeDragNode.behavior, modeDragNote(context).behavior];
122645 _behaviors.forEach(context.install);
122647 keybinding.on(_t('inspector.zoom_to.key'), mode.zoomToSelected).on(['[', 'pgup'], previousVertex).on([']', 'pgdown'], nextVertex).on(['{', uiCmd('⌘['), 'home'], firstVertex).on(['}', uiCmd('⌘]'), 'end'], lastVertex).on(uiCmd('⇧←'), nudgeSelection([-10, 0])).on(uiCmd('⇧↑'), nudgeSelection([0, -10])).on(uiCmd('⇧→'), nudgeSelection([10, 0])).on(uiCmd('⇧↓'), nudgeSelection([0, 10])).on(uiCmd('⇧⌥←'), nudgeSelection([-100, 0])).on(uiCmd('⇧⌥↑'), nudgeSelection([0, -100])).on(uiCmd('⇧⌥→'), nudgeSelection([100, 0])).on(uiCmd('⇧⌥↓'), nudgeSelection([0, 100])).on(utilKeybinding.plusKeys.map(function (key) {
122648 return uiCmd('⇧' + key);
122649 }), scaleSelection(1.05)).on(utilKeybinding.plusKeys.map(function (key) {
122650 return uiCmd('⇧⌥' + key);
122651 }), scaleSelection(Math.pow(1.05, 5))).on(utilKeybinding.minusKeys.map(function (key) {
122652 return uiCmd('⇧' + key);
122653 }), scaleSelection(1 / 1.05)).on(utilKeybinding.minusKeys.map(function (key) {
122654 return uiCmd('⇧⌥' + key);
122655 }), scaleSelection(1 / Math.pow(1.05, 5))).on(['\\', 'pause'], focusNextParent).on(uiCmd('⌘↑'), selectParent).on(uiCmd('⌘↓'), selectChild).on('⎋', esc, true);
122656 select(document).call(keybinding);
122657 context.ui().sidebar.select(selectedIDs, _newFeature);
122658 context.history().on('change.select', function () {
122659 loadOperations(); // reselect after change in case relation members were removed or added
122662 }).on('undone.select', checkSelectedIDs).on('redone.select', checkSelectedIDs);
122663 context.map().on('drawn.select', selectElements).on('crossEditableZoom.select', function () {
122666 _breatheBehavior.restartIfNeeded(context.surface());
122668 context.map().doubleUpHandler().on('doubleUp.modeSelect', didDoubleUp);
122672 var extent = geoExtent();
122673 var graph = context.graph();
122674 selectedIDs.forEach(function (id) {
122675 var entity = context.entity(id);
122677 extent._extend(entity.extent(graph));
122679 var loc = extent.center();
122680 context.map().centerEase(loc); // we could enter the mode multiple times, so reset follow for next time
122685 function nudgeSelection(delta) {
122687 // prevent nudging during low zoom selection
122688 if (!context.map().withinEditableZoom()) return;
122689 var moveOp = operationMove(context, selectedIDs);
122691 if (moveOp.disabled()) {
122692 context.ui().flash.duration(4000).iconName('#iD-operation-' + moveOp.id).iconClass('operation disabled').label(moveOp.tooltip)();
122694 context.perform(actionMove(selectedIDs, delta, context.projection), moveOp.annotation());
122695 context.validator().validate();
122700 function scaleSelection(factor) {
122702 // prevent scaling during low zoom selection
122703 if (!context.map().withinEditableZoom()) return;
122704 var nodes = utilGetAllNodes(selectedIDs, context.graph());
122705 var isUp = factor > 1; // can only scale if multiple nodes are selected
122707 if (nodes.length <= 1) return;
122708 var extent = utilTotalExtent(selectedIDs, context.graph()); // These disabled checks would normally be handled by an operation
122709 // object, but we don't want an actual scale operation at this point.
122711 function scalingDisabled() {
122714 } else if (extent.percentContainedIn(context.map().extent()) < 0.8) {
122716 } else if (someMissing() || selectedIDs.some(incompleteRelation)) {
122717 return 'not_downloaded';
122718 } else if (selectedIDs.some(context.hasHiddenConnections)) {
122719 return 'connected_to_hidden';
122725 if (isUp) return false;
122726 var dLon = Math.abs(extent[1][0] - extent[0][0]);
122727 var dLat = Math.abs(extent[1][1] - extent[0][1]);
122728 return dLon < geoMetersToLon(1, extent[1][1]) && dLat < geoMetersToLat(1);
122731 function someMissing() {
122732 if (context.inIntro()) return false;
122733 var osm = context.connection();
122736 var missing = nodes.filter(function (n) {
122737 return !osm.isDataLoaded(n.loc);
122741 missing.forEach(function (loc) {
122742 context.loadTileAtLoc(loc);
122751 function incompleteRelation(id) {
122752 var entity = context.entity(id);
122753 return entity.type === 'relation' && !entity.isComplete(context.graph());
122757 var disabled = scalingDisabled();
122760 var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
122761 context.ui().flash.duration(4000).iconName('#iD-icon-no').iconClass('operation disabled').label(_t.html('operations.scale.' + disabled + '.' + multi))();
122763 var pivot = context.projection(extent.center());
122764 var annotation = _t('operations.scale.annotation.' + (isUp ? 'up' : 'down') + '.feature', {
122767 context.perform(actionScale(selectedIDs, pivot, factor, context.projection), annotation);
122768 context.validator().validate();
122773 function didDoubleUp(d3_event, loc) {
122774 if (!context.map().withinEditableZoom()) return;
122775 var target = select(d3_event.target);
122776 var datum = target.datum();
122777 var entity = datum && datum.properties && datum.properties.entity;
122780 if (entity instanceof osmWay && target.classed('target')) {
122781 var choice = geoChooseEdge(context.graph().childNodes(entity), loc, context.projection);
122782 var prev = entity.nodes[choice.index - 1];
122783 var next = entity.nodes[choice.index];
122784 context.perform(actionAddMidpoint({
122787 }, osmNode()), _t('operations.add.annotation.vertex'));
122788 context.validator().validate();
122789 } else if (entity.type === 'midpoint') {
122790 context.perform(actionAddMidpoint({
122793 }, osmNode()), _t('operations.add.annotation.vertex'));
122794 context.validator().validate();
122798 function selectElements() {
122799 if (!checkSelectedIDs()) return;
122800 var surface = context.surface();
122801 surface.selectAll('.selected-member').classed('selected-member', false);
122802 surface.selectAll('.selected').classed('selected', false);
122803 surface.selectAll('.related').classed('related', false); // reload `_focusedParentWayId` based on the current selection
122807 if (_focusedParentWayId) {
122808 surface.selectAll(utilEntitySelector([_focusedParentWayId])).classed('related', true);
122811 if (context.map().withinEditableZoom()) {
122812 // Apply selection styling if not in wide selection
122813 surface.selectAll(utilDeepMemberSelector(selectedIDs, context.graph(), true
122814 /* skipMultipolgonMembers */
122815 )).classed('selected-member', true);
122816 surface.selectAll(utilEntityOrDeepMemberSelector(selectedIDs, context.graph())).classed('selected', true);
122821 if (context.container().select('.combobox').size()) return;
122822 context.enter(modeBrowse(context));
122825 function firstVertex(d3_event) {
122826 d3_event.preventDefault();
122827 var entity = singular();
122828 var parentId = parentWayIdForVertexNavigation();
122831 if (entity && entity.type === 'way') {
122834 way = context.entity(parentId);
122837 _focusedParentWayId = way && way.id;
122840 context.enter(mode.selectedIDs([way.first()]).follow(true));
122844 function lastVertex(d3_event) {
122845 d3_event.preventDefault();
122846 var entity = singular();
122847 var parentId = parentWayIdForVertexNavigation();
122850 if (entity && entity.type === 'way') {
122853 way = context.entity(parentId);
122856 _focusedParentWayId = way && way.id;
122859 context.enter(mode.selectedIDs([way.last()]).follow(true));
122863 function previousVertex(d3_event) {
122864 d3_event.preventDefault();
122865 var parentId = parentWayIdForVertexNavigation();
122866 _focusedParentWayId = parentId;
122868 var way = context.entity(parentId);
122869 var length = way.nodes.length;
122870 var curr = way.nodes.indexOf(selectedIDs[0]);
122875 } else if (way.isClosed()) {
122880 context.enter(mode.selectedIDs([way.nodes[index]]).follow(true));
122884 function nextVertex(d3_event) {
122885 d3_event.preventDefault();
122886 var parentId = parentWayIdForVertexNavigation();
122887 _focusedParentWayId = parentId;
122889 var way = context.entity(parentId);
122890 var length = way.nodes.length;
122891 var curr = way.nodes.indexOf(selectedIDs[0]);
122894 if (curr < length - 1) {
122896 } else if (way.isClosed()) {
122901 context.enter(mode.selectedIDs([way.nodes[index]]).follow(true));
122905 function focusNextParent(d3_event) {
122906 d3_event.preventDefault();
122907 var parents = parentWaysIdsOfSelection(true);
122908 if (!parents || parents.length < 2) return;
122909 var index = parents.indexOf(_focusedParentWayId);
122911 if (index < 0 || index > parents.length - 2) {
122912 _focusedParentWayId = parents[0];
122914 _focusedParentWayId = parents[index + 1];
122917 var surface = context.surface();
122918 surface.selectAll('.related').classed('related', false);
122920 if (_focusedParentWayId) {
122921 surface.selectAll(utilEntitySelector([_focusedParentWayId])).classed('related', true);
122925 function selectParent(d3_event) {
122926 d3_event.preventDefault();
122927 var currentSelectedIds = mode.selectedIDs();
122928 var parentIds = _focusedParentWayId ? [_focusedParentWayId] : parentWaysIdsOfSelection(false);
122929 if (!parentIds.length) return;
122930 context.enter(mode.selectedIDs(parentIds)); // set this after re-entering the selection since we normally want it cleared on exit
122932 _focusedVertexIds = currentSelectedIds;
122935 function selectChild(d3_event) {
122936 d3_event.preventDefault();
122937 var currentSelectedIds = mode.selectedIDs();
122938 var childIds = _focusedVertexIds ? _focusedVertexIds.filter(function (id) {
122939 return context.hasEntity(id);
122940 }) : childNodeIdsOfSelection(true);
122941 if (!childIds || !childIds.length) return;
122942 if (currentSelectedIds.length === 1) _focusedParentWayId = currentSelectedIds[0];
122943 context.enter(mode.selectedIDs(childIds));
122947 mode.exit = function () {
122948 // we could enter the mode multiple times but it's only new the first time
122950 _focusedVertexIds = null;
122952 _operations.forEach(function (operation) {
122953 if (operation.behavior) {
122954 context.uninstall(operation.behavior);
122960 _behaviors.forEach(context.uninstall);
122962 select(document).call(keybinding.unbind);
122963 context.ui().closeEditMenu();
122964 context.history().on('change.select', null).on('undone.select', null).on('redone.select', null);
122965 var surface = context.surface();
122966 surface.selectAll('.selected-member').classed('selected-member', false);
122967 surface.selectAll('.selected').classed('selected', false);
122968 surface.selectAll('.highlighted').classed('highlighted', false);
122969 surface.selectAll('.related').classed('related', false);
122970 context.map().on('drawn.select', null);
122971 context.ui().sidebar.hide();
122972 context.features().forceVisible([]);
122973 var entity = singular();
122975 if (_newFeature && entity && entity.type === 'relation' && // no tags
122976 Object.keys(entity.tags).length === 0 && // no parent relations
122977 context.graph().parentRelations(entity).length === 0 && ( // no members or one member with no role
122978 entity.members.length === 0 || entity.members.length === 1 && !entity.members[0].role)) {
122979 // the user added this relation but didn't edit it at all, so just delete it
122980 var deleteAction = actionDeleteRelation(entity.id, true
122981 /* don't delete untagged members */
122983 context.perform(deleteAction, _t('operations.delete.annotation.relation'));
122984 context.validator().validate();
122991 function behaviorLasso(context) {
122992 // use pointer events on supported platforms; fallback to mouse events
122993 var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
122995 var behavior = function behavior(selection) {
122998 function pointerdown(d3_event) {
122999 var button = 0; // left
123001 if (d3_event.button === button && d3_event.shiftKey === true) {
123003 select(window).on(_pointerPrefix + 'move.lasso', pointermove).on(_pointerPrefix + 'up.lasso', pointerup);
123004 d3_event.stopPropagation();
123008 function pointermove() {
123010 lasso = uiLasso(context);
123011 context.surface().call(lasso);
123014 lasso.p(context.map().mouse());
123017 function normalize(a, b) {
123018 return [[Math.min(a[0], b[0]), Math.min(a[1], b[1])], [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
123023 var graph = context.graph();
123026 if (context.map().editableDataEnabled(true
123028 ) && context.map().isInWideSelection()) {
123029 // only select from the visible nodes
123030 limitToNodes = new Set(utilGetAllNodes(context.selectedIDs(), graph));
123031 } else if (!context.map().editableDataEnabled()) {
123035 var bounds = lasso.extent().map(context.projection.invert);
123036 var extent = geoExtent(normalize(bounds[0], bounds[1]));
123037 var intersects = context.history().intersects(extent).filter(function (entity) {
123038 return entity.type === 'node' && (!limitToNodes || limitToNodes.has(entity)) && geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) && !context.features().isHidden(entity, graph, entity.geometry(graph));
123039 }); // sort the lassoed nodes as best we can
123041 intersects.sort(function (node1, node2) {
123042 var parents1 = graph.parentWays(node1);
123043 var parents2 = graph.parentWays(node2);
123045 if (parents1.length && parents2.length) {
123046 // both nodes are vertices
123047 var sharedParents = utilArrayIntersection(parents1, parents2);
123049 if (sharedParents.length) {
123050 var sharedParentNodes = sharedParents[0].nodes; // vertices are members of the same way; sort them in their listed order
123052 return sharedParentNodes.indexOf(node1.id) - sharedParentNodes.indexOf(node2.id);
123054 // vertices do not share a way; group them by their respective parent ways
123055 return parseFloat(parents1[0].id.slice(1)) - parseFloat(parents2[0].id.slice(1));
123057 } else if (parents1.length || parents2.length) {
123058 // only one node is a vertex; sort standalone points before vertices
123059 return parents1.length - parents2.length;
123060 } // both nodes are standalone points; sort left to right
123063 return node1.loc[0] - node2.loc[0];
123065 return intersects.map(function (entity) {
123071 select(window).on(_pointerPrefix + 'move.lasso', null).on(_pointerPrefix + 'up.lasso', null);
123077 context.enter(modeSelect(context, ids));
123081 selection.on(_pointerPrefix + 'down.lasso', pointerdown);
123084 behavior.off = function (selection) {
123085 selection.on(_pointerPrefix + 'down.lasso', null);
123091 function modeBrowse(context) {
123095 title: _t('modes.browse.title'),
123096 description: _t('modes.browse.description')
123104 mode.selectBehavior = function (val) {
123105 if (!arguments.length) return _selectBehavior;
123110 mode.enter = function () {
123111 if (!_behaviors.length) {
123112 if (!_selectBehavior) _selectBehavior = behaviorSelect(context);
123113 _behaviors = [behaviorPaste(context), behaviorHover(context).on('hover', context.ui().sidebar.hover), _selectBehavior, behaviorLasso(context), modeDragNode(context).behavior, modeDragNote(context).behavior];
123116 _behaviors.forEach(context.install); // Get focus on the body.
123119 if (document.activeElement && document.activeElement.blur) {
123120 document.activeElement.blur();
123124 context.ui().sidebar.show(sidebar);
123126 context.ui().sidebar.select(null);
123130 mode.exit = function () {
123131 context.ui().sidebar.hover.cancel();
123133 _behaviors.forEach(context.uninstall);
123136 context.ui().sidebar.hide();
123140 mode.sidebar = function (_) {
123141 if (!arguments.length) return sidebar;
123146 mode.operations = function () {
123147 return [operationPaste(context)];
123153 function behaviorAddWay(context) {
123154 var dispatch = dispatch$8('start', 'startFromWay', 'startFromNode');
123155 var draw = behaviorDraw(context);
123157 function behavior(surface) {
123158 draw.on('click', function () {
123159 dispatch.apply('start', this, arguments);
123160 }).on('clickWay', function () {
123161 dispatch.apply('startFromWay', this, arguments);
123162 }).on('clickNode', function () {
123163 dispatch.apply('startFromNode', this, arguments);
123164 }).on('cancel', behavior.cancel).on('finish', behavior.cancel);
123165 context.map().dblclickZoomEnable(false);
123169 behavior.off = function (surface) {
123170 surface.call(draw.off);
123173 behavior.cancel = function () {
123174 window.setTimeout(function () {
123175 context.map().dblclickZoomEnable(true);
123177 context.enter(modeBrowse(context));
123180 return utilRebind(behavior, dispatch, 'on');
123183 function behaviorHash(context) {
123184 // cached window.location.hash
123185 var _cachedHash = null; // allowable latitude range
123187 var _latitudeLimit = 90 - 1e-8;
123189 function computedHashParameters() {
123190 var map = context.map();
123191 var center = map.center();
123193 var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
123194 var oldParams = utilObjectOmit(utilStringQs(window.location.hash), ['comment', 'source', 'hashtags', 'walkthrough']);
123197 var selected = context.selectedIDs().filter(function (id) {
123198 return context.hasEntity(id);
123202 newParams.id = selected.join(',');
123205 newParams.map = zoom.toFixed(2) + '/' + center[1].toFixed(precision) + '/' + center[0].toFixed(precision);
123206 return Object.assign(oldParams, newParams);
123209 function computedHash() {
123210 return '#' + utilQsString(computedHashParameters(), true);
123213 function computedTitle(includeChangeCount) {
123214 var baseTitle = context.documentTitleBase() || 'iD';
123218 var selected = context.selectedIDs().filter(function (id) {
123219 return context.hasEntity(id);
123223 var firstLabel = utilDisplayLabel(context.entity(selected[0]), context.graph());
123225 if (selected.length > 1) {
123226 contextual = _t('title.labeled_and_more', {
123228 count: selected.length - 1
123231 contextual = firstLabel;
123237 if (includeChangeCount) {
123238 changeCount = context.history().difference().summary().length;
123241 titleID = contextual ? 'changes_context' : 'changes';
123246 return _t('title.format.' + titleID, {
123256 function updateTitle(includeChangeCount) {
123257 if (!context.setsDocumentTitle()) return;
123258 var newTitle = computedTitle(includeChangeCount);
123260 if (document.title !== newTitle) {
123261 document.title = newTitle;
123265 function updateHashIfNeeded() {
123266 if (context.inIntro()) return;
123267 var latestHash = computedHash();
123269 if (_cachedHash !== latestHash) {
123270 _cachedHash = latestHash; // Update the URL hash without affecting the browser navigation stack,
123271 // though unavoidably creating a browser history entry
123273 window.history.replaceState(null, computedTitle(false
123274 /* includeChangeCount */
123275 ), latestHash); // set the title we want displayed for the browser tab/window
123278 /* includeChangeCount */
123283 var _throttledUpdate = throttle(updateHashIfNeeded, 500);
123285 var _throttledUpdateTitle = throttle(function () {
123287 /* includeChangeCount */
123291 function hashchange() {
123292 // ignore spurious hashchange events
123293 if (window.location.hash === _cachedHash) return;
123294 _cachedHash = window.location.hash;
123295 var q = utilStringQs(_cachedHash);
123296 var mapArgs = (q.map || '').split('/').map(Number);
123298 if (mapArgs.length < 3 || mapArgs.some(isNaN)) {
123302 // don't update if the new hash already reflects the state of iD
123303 if (_cachedHash === computedHash()) return;
123304 var mode = context.mode();
123305 context.map().centerZoom([mapArgs[2], Math.min(_latitudeLimit, Math.max(-_latitudeLimit, mapArgs[1]))], mapArgs[0]);
123308 var ids = q.id.split(',').filter(function (id) {
123309 return context.hasEntity(id);
123312 if (ids.length && (mode.id === 'browse' || mode.id === 'select' && !utilArrayIdentical(mode.selectedIDs(), ids))) {
123313 context.enter(modeSelect(context, ids));
123318 var center = context.map().center();
123319 var dist = geoSphericalDistance(center, [mapArgs[2], mapArgs[1]]);
123320 var maxdist = 500; // Don't allow the hash location to change too much while drawing
123321 // This can happen if the user accidentally hit the back button. #3996
123323 if (mode && mode.id.match(/^draw/) !== null && dist > maxdist) {
123324 context.enter(modeBrowse(context));
123331 context.map().on('move.behaviorHash', _throttledUpdate);
123332 context.history().on('change.behaviorHash', _throttledUpdateTitle);
123333 context.on('enter.behaviorHash', _throttledUpdate);
123334 select(window).on('hashchange.behaviorHash', hashchange);
123336 if (window.location.hash) {
123337 var q = utilStringQs(window.location.hash);
123340 //if (!context.history().hasRestorableChanges()) {
123341 // targeting specific features: download, select, and zoom to them
123342 context.zoomToEntity(q.id.split(',')[0], !q.map); //}
123345 if (q.walkthrough === 'true') {
123346 behavior.startWalkthrough = true;
123350 behavior.hadHash = true;
123358 behavior.off = function () {
123359 _throttledUpdate.cancel();
123361 _throttledUpdateTitle.cancel();
123363 context.map().on('move.behaviorHash', null);
123364 context.on('enter.behaviorHash', null);
123365 select(window).on('hashchange.behaviorHash', null);
123366 window.location.hash = '';
123372 // This is only done in testing because of the performance penalty.
123374 var debug = false; // Reexport just what our tests use, see #4379
123378 geoProjection: projection,
123379 polygonArea: d3_polygonArea,
123380 polygonCentroid: d3_polygonCentroid,
123386 var iD = /*#__PURE__*/Object.freeze({
123390 actionAddEntity: actionAddEntity,
123391 actionAddMember: actionAddMember,
123392 actionAddMidpoint: actionAddMidpoint,
123393 actionAddVertex: actionAddVertex,
123394 actionChangeMember: actionChangeMember,
123395 actionChangePreset: actionChangePreset,
123396 actionChangeTags: actionChangeTags,
123397 actionCircularize: actionCircularize,
123398 actionConnect: actionConnect,
123399 actionCopyEntities: actionCopyEntities,
123400 actionDeleteMember: actionDeleteMember,
123401 actionDeleteMultiple: actionDeleteMultiple,
123402 actionDeleteNode: actionDeleteNode,
123403 actionDeleteRelation: actionDeleteRelation,
123404 actionDeleteWay: actionDeleteWay,
123405 actionDiscardTags: actionDiscardTags,
123406 actionDisconnect: actionDisconnect,
123407 actionExtract: actionExtract,
123408 actionJoin: actionJoin,
123409 actionMerge: actionMerge,
123410 actionMergeNodes: actionMergeNodes,
123411 actionMergePolygon: actionMergePolygon,
123412 actionMergeRemoteChanges: actionMergeRemoteChanges,
123413 actionMove: actionMove,
123414 actionMoveMember: actionMoveMember,
123415 actionMoveNode: actionMoveNode,
123416 actionNoop: actionNoop,
123417 actionOrthogonalize: actionOrthogonalize,
123418 actionRestrictTurn: actionRestrictTurn,
123419 actionReverse: actionReverse,
123420 actionRevert: actionRevert,
123421 actionRotate: actionRotate,
123422 actionScale: actionScale,
123423 actionSplit: actionSplit,
123424 actionStraightenNodes: actionStraightenNodes,
123425 actionStraightenWay: actionStraightenWay,
123426 actionUnrestrictTurn: actionUnrestrictTurn,
123427 actionReflect: actionReflect,
123428 actionUpgradeTags: actionUpgradeTags,
123429 behaviorAddWay: behaviorAddWay,
123430 behaviorBreathe: behaviorBreathe,
123431 behaviorDrag: behaviorDrag,
123432 behaviorDrawWay: behaviorDrawWay,
123433 behaviorDraw: behaviorDraw,
123434 behaviorEdit: behaviorEdit,
123435 behaviorHash: behaviorHash,
123436 behaviorHover: behaviorHover,
123437 behaviorLasso: behaviorLasso,
123438 behaviorOperation: behaviorOperation,
123439 behaviorPaste: behaviorPaste,
123440 behaviorSelect: behaviorSelect,
123441 coreContext: coreContext,
123442 coreFileFetcher: coreFileFetcher,
123443 fileFetcher: _mainFileFetcher,
123444 coreDifference: coreDifference,
123446 coreHistory: coreHistory,
123447 coreLocalizer: coreLocalizer,
123449 localizer: _mainLocalizer,
123450 coreLocations: coreLocations,
123451 locationManager: _mainLocations,
123452 prefs: corePreferences,
123454 coreUploader: coreUploader,
123455 coreValidator: coreValidator,
123457 geoLatToMeters: geoLatToMeters,
123458 geoLonToMeters: geoLonToMeters,
123459 geoMetersToLat: geoMetersToLat,
123460 geoMetersToLon: geoMetersToLon,
123461 geoMetersToOffset: geoMetersToOffset,
123462 geoOffsetToMeters: geoOffsetToMeters,
123463 geoScaleToZoom: geoScaleToZoom,
123464 geoSphericalClosestNode: geoSphericalClosestNode,
123465 geoSphericalDistance: geoSphericalDistance,
123466 geoZoomToScale: geoZoomToScale,
123468 geoChooseEdge: geoChooseEdge,
123469 geoEdgeEqual: geoEdgeEqual,
123470 geoGetSmallestSurroundingRectangle: geoGetSmallestSurroundingRectangle,
123471 geoHasLineIntersections: geoHasLineIntersections,
123472 geoHasSelfIntersections: geoHasSelfIntersections,
123474 geoLineIntersection: geoLineIntersection,
123475 geoPathHasIntersections: geoPathHasIntersections,
123476 geoPathIntersections: geoPathIntersections,
123477 geoPathLength: geoPathLength,
123478 geoPointInPolygon: geoPointInPolygon,
123479 geoPolygonContainsPolygon: geoPolygonContainsPolygon,
123480 geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon,
123481 geoViewportEdge: geoViewportEdge,
123482 geoRawMercator: geoRawMercator,
123484 geoVecAngle: geoVecAngle,
123485 geoVecCross: geoVecCross,
123487 geoVecEqual: geoVecEqual,
123488 geoVecFloor: geoVecFloor,
123489 geoVecInterp: geoVecInterp,
123490 geoVecLength: geoVecLength,
123491 geoVecLengthSquare: geoVecLengthSquare,
123492 geoVecNormalize: geoVecNormalize,
123493 geoVecNormalizedDot: geoVecNormalizedDot,
123494 geoVecProject: geoVecProject,
123495 geoVecSubtract: geoVecSubtract,
123496 geoVecScale: geoVecScale,
123497 geoOrthoNormalizedDotProduct: geoOrthoNormalizedDotProduct,
123498 geoOrthoCalcScore: geoOrthoCalcScore,
123499 geoOrthoMaxOffsetAngle: geoOrthoMaxOffsetAngle,
123500 geoOrthoCanOrthogonalize: geoOrthoCanOrthogonalize,
123501 modeAddArea: modeAddArea,
123502 modeAddLine: modeAddLine,
123503 modeAddPoint: modeAddPoint,
123504 modeAddNote: modeAddNote,
123505 modeBrowse: modeBrowse,
123506 modeDragNode: modeDragNode,
123507 modeDragNote: modeDragNote,
123508 modeDrawArea: modeDrawArea,
123509 modeDrawLine: modeDrawLine,
123511 modeRotate: modeRotate,
123513 modeSelect: modeSelect,
123514 modeSelectData: modeSelectData,
123515 modeSelectError: modeSelectError,
123516 modeSelectNote: modeSelectNote,
123517 operationCircularize: operationCircularize,
123518 operationContinue: operationContinue,
123519 operationCopy: operationCopy,
123520 operationDelete: operationDelete,
123521 operationDisconnect: operationDisconnect,
123522 operationDowngrade: operationDowngrade,
123523 operationExtract: operationExtract,
123524 operationMerge: operationMerge,
123525 operationMove: operationMove,
123526 operationOrthogonalize: operationOrthogonalize,
123527 operationPaste: operationPaste,
123528 operationReflectShort: operationReflectShort,
123529 operationReflectLong: operationReflectLong,
123530 operationReverse: operationReverse,
123531 operationRotate: operationRotate,
123532 operationSplit: operationSplit,
123533 operationStraighten: operationStraighten,
123534 osmChangeset: osmChangeset,
123538 osmRelation: osmRelation,
123541 osmIntersection: osmIntersection,
123543 osmInferRestriction: osmInferRestriction,
123545 osmOldMultipolygonOuterMemberOfRelation: osmOldMultipolygonOuterMemberOfRelation,
123546 osmIsOldMultipolygonOuterMember: osmIsOldMultipolygonOuterMember,
123547 osmOldMultipolygonOuterMember: osmOldMultipolygonOuterMember,
123548 osmJoinWays: osmJoinWays,
123549 get osmAreaKeys () { return osmAreaKeys; },
123550 osmSetAreaKeys: osmSetAreaKeys,
123551 osmTagSuggestingArea: osmTagSuggestingArea,
123552 get osmPointTags () { return osmPointTags; },
123553 osmSetPointTags: osmSetPointTags,
123554 get osmVertexTags () { return osmVertexTags; },
123555 osmSetVertexTags: osmSetVertexTags,
123556 osmNodeGeometriesForTags: osmNodeGeometriesForTags,
123557 osmOneWayTags: osmOneWayTags,
123558 osmPavedTags: osmPavedTags,
123559 osmIsInterestingTag: osmIsInterestingTag,
123560 osmRoutableHighwayTagValues: osmRoutableHighwayTagValues,
123561 osmFlowingWaterwayTagValues: osmFlowingWaterwayTagValues,
123562 osmRailwayTrackTagValues: osmRailwayTrackTagValues,
123563 presetCategory: presetCategory,
123564 presetCollection: presetCollection,
123565 presetField: presetField,
123566 presetPreset: presetPreset,
123567 presetManager: _mainPresetIndex,
123568 presetIndex: presetIndex,
123569 rendererBackgroundSource: rendererBackgroundSource,
123570 rendererBackground: rendererBackground,
123571 rendererFeatures: rendererFeatures,
123572 rendererMap: rendererMap,
123573 rendererPhotos: rendererPhotos,
123574 rendererTileLayer: rendererTileLayer,
123576 serviceKeepRight: serviceKeepRight,
123577 serviceImproveOSM: serviceImproveOSM,
123578 serviceOsmose: serviceOsmose,
123579 serviceMapillary: serviceMapillary,
123580 serviceMapRules: serviceMapRules,
123581 serviceNominatim: serviceNominatim,
123582 serviceNsi: serviceNsi,
123583 serviceKartaview: serviceKartaview,
123584 serviceOsm: serviceOsm,
123585 serviceOsmWikibase: serviceOsmWikibase,
123586 serviceStreetside: serviceStreetside,
123587 serviceTaginfo: serviceTaginfo,
123588 serviceVectorTile: serviceVectorTile,
123589 serviceWikidata: serviceWikidata,
123590 serviceWikipedia: serviceWikipedia,
123595 svgKeepRight: svgKeepRight,
123597 svgGeolocate: svgGeolocate,
123601 svgMapillaryImages: svgMapillaryImages,
123602 svgMapillarySigns: svgMapillarySigns,
123603 svgMidpoints: svgMidpoints,
123605 svgMarkerSegments: svgMarkerSegments,
123606 svgKartaviewImages: svgKartaviewImages,
123608 svgPassiveVertex: svgPassiveVertex,
123610 svgPointTransform: svgPointTransform,
123612 svgRelationMemberTags: svgRelationMemberTags,
123613 svgSegmentWay: svgSegmentWay,
123614 svgStreetside: svgStreetside,
123615 svgTagClasses: svgTagClasses,
123616 svgTagPattern: svgTagPattern,
123619 svgVertices: svgVertices,
123620 uiFieldDefaultCheck: uiFieldCheck,
123621 uiFieldOnewayCheck: uiFieldCheck,
123622 uiFieldCheck: uiFieldCheck,
123623 uiFieldManyCombo: uiFieldCombo,
123624 uiFieldMultiCombo: uiFieldCombo,
123625 uiFieldNetworkCombo: uiFieldCombo,
123626 uiFieldSemiCombo: uiFieldCombo,
123627 uiFieldTypeCombo: uiFieldCombo,
123628 uiFieldCombo: uiFieldCombo,
123629 uiFieldUrl: uiFieldText,
123630 uiFieldIdentifier: uiFieldText,
123631 uiFieldNumber: uiFieldText,
123632 uiFieldTel: uiFieldText,
123633 uiFieldEmail: uiFieldText,
123634 uiFieldText: uiFieldText,
123635 uiFieldAccess: uiFieldAccess,
123636 uiFieldAddress: uiFieldAddress,
123637 uiFieldCycleway: uiFieldCycleway,
123638 uiFieldLanes: uiFieldLanes,
123639 uiFieldLocalized: uiFieldLocalized,
123640 uiFieldRoadheight: uiFieldRoadheight,
123641 uiFieldRoadspeed: uiFieldRoadspeed,
123642 uiFieldStructureRadio: uiFieldRadio,
123643 uiFieldRadio: uiFieldRadio,
123644 uiFieldRestrictions: uiFieldRestrictions,
123645 uiFieldTextarea: uiFieldTextarea,
123646 uiFieldWikidata: uiFieldWikidata,
123647 uiFieldWikipedia: uiFieldWikipedia,
123650 uiPanelBackground: uiPanelBackground,
123651 uiPanelHistory: uiPanelHistory,
123652 uiPanelLocation: uiPanelLocation,
123653 uiPanelMeasurement: uiPanelMeasurement,
123654 uiInfoPanels: uiInfoPanels,
123655 uiPaneBackground: uiPaneBackground,
123656 uiPaneHelp: uiPaneHelp,
123657 uiPaneIssues: uiPaneIssues,
123658 uiPaneMapData: uiPaneMapData,
123659 uiPanePreferences: uiPanePreferences,
123660 uiSectionBackgroundDisplayOptions: uiSectionBackgroundDisplayOptions,
123661 uiSectionBackgroundList: uiSectionBackgroundList,
123662 uiSectionBackgroundOffset: uiSectionBackgroundOffset,
123663 uiSectionChanges: uiSectionChanges,
123664 uiSectionDataLayers: uiSectionDataLayers,
123665 uiSectionEntityIssues: uiSectionEntityIssues,
123666 uiSectionFeatureType: uiSectionFeatureType,
123667 uiSectionMapFeatures: uiSectionMapFeatures,
123668 uiSectionMapStyleOptions: uiSectionMapStyleOptions,
123669 uiSectionOverlayList: uiSectionOverlayList,
123670 uiSectionPhotoOverlays: uiSectionPhotoOverlays,
123671 uiSectionPresetFields: uiSectionPresetFields,
123672 uiSectionPrivacy: uiSectionPrivacy,
123673 uiSectionRawMemberEditor: uiSectionRawMemberEditor,
123674 uiSectionRawMembershipEditor: uiSectionRawMembershipEditor,
123675 uiSectionRawTagEditor: uiSectionRawTagEditor,
123676 uiSectionSelectionList: uiSectionSelectionList,
123677 uiSectionValidationIssues: uiSectionValidationIssues,
123678 uiSectionValidationOptions: uiSectionValidationOptions,
123679 uiSectionValidationRules: uiSectionValidationRules,
123680 uiSectionValidationStatus: uiSectionValidationStatus,
123681 uiSettingsCustomBackground: uiSettingsCustomBackground,
123682 uiSettingsCustomData: uiSettingsCustomData,
123685 uiAttribution: uiAttribution,
123686 uiChangesetEditor: uiChangesetEditor,
123688 uiCombobox: uiCombobox,
123690 uiCommitWarnings: uiCommitWarnings,
123692 uiConflicts: uiConflicts,
123693 uiContributors: uiContributors,
123695 uiDataEditor: uiDataEditor,
123696 uiDataHeader: uiDataHeader,
123697 uiDisclosure: uiDisclosure,
123698 uiEditMenu: uiEditMenu,
123699 uiEntityEditor: uiEntityEditor,
123700 uiFeatureInfo: uiFeatureInfo,
123701 uiFeatureList: uiFeatureList,
123703 uiFieldHelp: uiFieldHelp,
123705 uiFormFields: uiFormFields,
123706 uiFullScreen: uiFullScreen,
123707 uiGeolocate: uiGeolocate,
123708 uiImproveOsmComments: uiImproveOsmComments,
123709 uiImproveOsmDetails: uiImproveOsmDetails,
123710 uiImproveOsmEditor: uiImproveOsmEditor,
123711 uiImproveOsmHeader: uiImproveOsmHeader,
123713 uiInspector: uiInspector,
123714 uiIssuesInfo: uiIssuesInfo,
123715 uiKeepRightDetails: uiKeepRightDetails,
123716 uiKeepRightEditor: uiKeepRightEditor,
123717 uiKeepRightHeader: uiKeepRightHeader,
123720 uiMapInMap: uiMapInMap,
123723 uiNoteComments: uiNoteComments,
123724 uiNoteEditor: uiNoteEditor,
123725 uiNoteHeader: uiNoteHeader,
123726 uiNoteReport: uiNoteReport,
123728 uiPresetIcon: uiPresetIcon,
123729 uiPresetList: uiPresetList,
123733 uiSourceSwitch: uiSourceSwitch,
123738 uiTagReference: uiTagReference,
123742 uiViewOnOSM: uiViewOnOSM,
123743 uiViewOnKeepRight: uiViewOnKeepRight,
123745 utilAesEncrypt: utilAesEncrypt,
123746 utilAesDecrypt: utilAesDecrypt,
123747 utilArrayChunk: utilArrayChunk,
123748 utilArrayDifference: utilArrayDifference,
123749 utilArrayFlatten: utilArrayFlatten,
123750 utilArrayGroupBy: utilArrayGroupBy,
123751 utilArrayIdentical: utilArrayIdentical,
123752 utilArrayIntersection: utilArrayIntersection,
123753 utilArrayUnion: utilArrayUnion,
123754 utilArrayUniq: utilArrayUniq,
123755 utilArrayUniqBy: utilArrayUniqBy,
123756 utilAsyncMap: utilAsyncMap,
123757 utilCleanTags: utilCleanTags,
123758 utilCombinedTags: utilCombinedTags,
123759 utilDeepMemberSelector: utilDeepMemberSelector,
123760 utilDetect: utilDetect,
123761 utilDisplayName: utilDisplayName,
123762 utilDisplayNameForPath: utilDisplayNameForPath,
123763 utilDisplayType: utilDisplayType,
123764 utilDisplayLabel: utilDisplayLabel,
123765 utilEntityRoot: utilEntityRoot,
123766 utilEditDistance: utilEditDistance,
123767 utilEntityAndDeepMemberIDs: utilEntityAndDeepMemberIDs,
123768 utilEntityOrMemberSelector: utilEntityOrMemberSelector,
123769 utilEntityOrDeepMemberSelector: utilEntityOrDeepMemberSelector,
123770 utilEntitySelector: utilEntitySelector,
123771 utilFastMouse: utilFastMouse,
123772 utilFunctor: utilFunctor,
123773 utilGetAllNodes: utilGetAllNodes,
123774 utilGetSetValue: utilGetSetValue,
123775 utilHashcode: utilHashcode,
123776 utilHighlightEntities: utilHighlightEntities,
123777 utilKeybinding: utilKeybinding,
123778 utilNoAuto: utilNoAuto,
123779 utilObjectOmit: utilObjectOmit,
123780 utilCompareIDs: utilCompareIDs,
123781 utilOldestID: utilOldestID,
123782 utilPrefixCSSProperty: utilPrefixCSSProperty,
123783 utilPrefixDOMProperty: utilPrefixDOMProperty,
123784 utilQsString: utilQsString,
123785 utilRebind: utilRebind,
123786 utilSafeClassName: utilSafeClassName,
123787 utilSetTransform: utilSetTransform,
123788 utilSessionMutex: utilSessionMutex,
123789 utilStringQs: utilStringQs,
123790 utilTagDiff: utilTagDiff,
123791 utilTagText: utilTagText,
123793 utilTotalExtent: utilTotalExtent,
123794 utilTriggerEvent: utilTriggerEvent,
123795 utilUnicodeCharsCount: utilUnicodeCharsCount,
123796 utilUnicodeCharsTruncated: utilUnicodeCharsTruncated,
123797 utilUniqueDomId: utilUniqueDomId,
123799 validationAlmostJunction: validationAlmostJunction,
123800 validationCloseNodes: validationCloseNodes,
123801 validationCrossingWays: validationCrossingWays,
123802 validationDisconnectedWay: validationDisconnectedWay,
123803 validationFormatting: validationFormatting,
123804 validationHelpRequest: validationHelpRequest,
123805 validationImpossibleOneway: validationImpossibleOneway,
123806 validationIncompatibleSource: validationIncompatibleSource,
123807 validationMaprules: validationMaprules,
123808 validationMismatchedGeometry: validationMismatchedGeometry,
123809 validationMissingRole: validationMissingRole,
123810 validationMissingTag: validationMissingTag,
123811 validationOutdatedTags: validationOutdatedTags,
123812 validationPrivateData: validationPrivateData,
123813 validationSuspiciousName: validationSuspiciousName,
123814 validationUnsquareWay: validationUnsquareWay
123817 window.requestIdleCallback = window.requestIdleCallback || function (cb) {
123818 var start = Date.now();
123819 return window.requestAnimationFrame(function () {
123822 timeRemaining: function timeRemaining() {
123823 return Math.max(0, 50 - (Date.now() - start));
123829 window.cancelIdleCallback = window.cancelIdleCallback || function (id) {
123830 window.cancelAnimationFrame(id);