UNPKG

1.72 MBJavaScriptView Raw
1/**
2 * vis-network - network
3 * http://visjs.org/
4 *
5 * A dynamic, browser-based visualization library.
6 *
7 * @version 6.3.2
8 * @date 2019-11-08T19:06:45Z
9 *
10 * @copyright (c) 2011-2017 Almende B.V, http://almende.com
11 * @copyright (c) 2018-2019 visjs contributors, https://github.com/visjs
12 *
13 * @license
14 * vis.js is dual licensed under both
15 *
16 * 1. The Apache 2.0 License
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * and
20 *
21 * 2. The MIT License
22 * http://opensource.org/licenses/MIT
23 *
24 * vis.js may be distributed under either license.
25 */
26var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
27
28function commonjsRequire () {
29 throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
30}
31
32function unwrapExports (x) {
33 return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
34}
35
36function createCommonjsModule(fn, module) {
37 return module = { exports: {} }, fn(module, module.exports), module.exports;
38}
39
40function getCjsExportFromNamespace (n) {
41 return n && n['default'] || n;
42}
43
44var check = function (it) {
45 return it && it.Math == Math && it;
46}; // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
47
48
49var global_1 = // eslint-disable-next-line no-undef
50check(typeof globalThis == 'object' && globalThis) || check(typeof window == 'object' && window) || check(typeof self == 'object' && self) || check(typeof commonjsGlobal == 'object' && commonjsGlobal) || // eslint-disable-next-line no-new-func
51Function('return this')();
52
53var fails = function (exec) {
54 try {
55 return !!exec();
56 } catch (error) {
57 return true;
58 }
59};
60
61var descriptors = !fails(function () {
62 return Object.defineProperty({}, 'a', {
63 get: function () {
64 return 7;
65 }
66 }).a != 7;
67});
68
69var nativePropertyIsEnumerable = {}.propertyIsEnumerable;
70var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; // Nashorn ~ JDK8 bug
71
72var NASHORN_BUG = getOwnPropertyDescriptor && !nativePropertyIsEnumerable.call({
73 1: 2
74}, 1); // `Object.prototype.propertyIsEnumerable` method implementation
75// https://tc39.github.io/ecma262/#sec-object.prototype.propertyisenumerable
76
77var f = NASHORN_BUG ? function propertyIsEnumerable(V) {
78 var descriptor = getOwnPropertyDescriptor(this, V);
79 return !!descriptor && descriptor.enumerable;
80} : nativePropertyIsEnumerable;
81var objectPropertyIsEnumerable = {
82 f: f
83};
84
85var createPropertyDescriptor = function (bitmap, value) {
86 return {
87 enumerable: !(bitmap & 1),
88 configurable: !(bitmap & 2),
89 writable: !(bitmap & 4),
90 value: value
91 };
92};
93
94var toString = {}.toString;
95
96var classofRaw = function (it) {
97 return toString.call(it).slice(8, -1);
98};
99
100var split = ''.split; // fallback for non-array-like ES3 and non-enumerable old V8 strings
101
102var indexedObject = fails(function () {
103 // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
104 // eslint-disable-next-line no-prototype-builtins
105 return !Object('z').propertyIsEnumerable(0);
106}) ? function (it) {
107 return classofRaw(it) == 'String' ? split.call(it, '') : Object(it);
108} : Object;
109
110// `RequireObjectCoercible` abstract operation
111// https://tc39.github.io/ecma262/#sec-requireobjectcoercible
112var requireObjectCoercible = function (it) {
113 if (it == undefined) throw TypeError("Can't call method on " + it);
114 return it;
115};
116
117var toIndexedObject = function (it) {
118 return indexedObject(requireObjectCoercible(it));
119};
120
121var isObject = function (it) {
122 return typeof it === 'object' ? it !== null : typeof it === 'function';
123};
124
125// https://tc39.github.io/ecma262/#sec-toprimitive
126// instead of the ES6 spec version, we didn't implement @@toPrimitive case
127// and the second argument - flag - preferred type is a string
128
129var toPrimitive = function (input, PREFERRED_STRING) {
130 if (!isObject(input)) return input;
131 var fn, val;
132 if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
133 if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val;
134 if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
135 throw TypeError("Can't convert object to primitive value");
136};
137
138var hasOwnProperty = {}.hasOwnProperty;
139
140var has = function (it, key) {
141 return hasOwnProperty.call(it, key);
142};
143
144var document$1 = global_1.document; // typeof document.createElement is 'object' in old IE
145
146var EXISTS = isObject(document$1) && isObject(document$1.createElement);
147
148var documentCreateElement = function (it) {
149 return EXISTS ? document$1.createElement(it) : {};
150};
151
152var ie8DomDefine = !descriptors && !fails(function () {
153 return Object.defineProperty(documentCreateElement('div'), 'a', {
154 get: function () {
155 return 7;
156 }
157 }).a != 7;
158});
159
160var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; // `Object.getOwnPropertyDescriptor` method
161// https://tc39.github.io/ecma262/#sec-object.getownpropertydescriptor
162
163var f$1 = descriptors ? nativeGetOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) {
164 O = toIndexedObject(O);
165 P = toPrimitive(P, true);
166 if (ie8DomDefine) try {
167 return nativeGetOwnPropertyDescriptor(O, P);
168 } catch (error) {
169 /* empty */
170 }
171 if (has(O, P)) return createPropertyDescriptor(!objectPropertyIsEnumerable.f.call(O, P), O[P]);
172};
173var objectGetOwnPropertyDescriptor = {
174 f: f$1
175};
176
177var anObject = function (it) {
178 if (!isObject(it)) {
179 throw TypeError(String(it) + ' is not an object');
180 }
181
182 return it;
183};
184
185var nativeDefineProperty = Object.defineProperty; // `Object.defineProperty` method
186// https://tc39.github.io/ecma262/#sec-object.defineproperty
187
188var f$2 = descriptors ? nativeDefineProperty : function defineProperty(O, P, Attributes) {
189 anObject(O);
190 P = toPrimitive(P, true);
191 anObject(Attributes);
192 if (ie8DomDefine) try {
193 return nativeDefineProperty(O, P, Attributes);
194 } catch (error) {
195 /* empty */
196 }
197 if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported');
198 if ('value' in Attributes) O[P] = Attributes.value;
199 return O;
200};
201var objectDefineProperty = {
202 f: f$2
203};
204
205var createNonEnumerableProperty = descriptors ? function (object, key, value) {
206 return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value));
207} : function (object, key, value) {
208 object[key] = value;
209 return object;
210};
211
212var setGlobal = function (key, value) {
213 try {
214 createNonEnumerableProperty(global_1, key, value);
215 } catch (error) {
216 global_1[key] = value;
217 }
218
219 return value;
220};
221
222var SHARED = '__core-js_shared__';
223var store = global_1[SHARED] || setGlobal(SHARED, {});
224var sharedStore = store;
225
226var shared = createCommonjsModule(function (module) {
227 (module.exports = function (key, value) {
228 return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
229 })('versions', []).push({
230 version: '3.3.4',
231 mode: 'global',
232 copyright: '© 2019 Denis Pushkarev (zloirock.ru)'
233 });
234});
235
236var functionToString = shared('native-function-to-string', Function.toString);
237
238var WeakMap = global_1.WeakMap;
239var nativeWeakMap = typeof WeakMap === 'function' && /native code/.test(functionToString.call(WeakMap));
240
241var id = 0;
242var postfix = Math.random();
243
244var uid = function (key) {
245 return 'Symbol(' + String(key === undefined ? '' : key) + ')_' + (++id + postfix).toString(36);
246};
247
248var keys = shared('keys');
249
250var sharedKey = function (key) {
251 return keys[key] || (keys[key] = uid(key));
252};
253
254var hiddenKeys = {};
255
256var WeakMap$1 = global_1.WeakMap;
257var set, get, has$1;
258
259var enforce = function (it) {
260 return has$1(it) ? get(it) : set(it, {});
261};
262
263var getterFor = function (TYPE) {
264 return function (it) {
265 var state;
266
267 if (!isObject(it) || (state = get(it)).type !== TYPE) {
268 throw TypeError('Incompatible receiver, ' + TYPE + ' required');
269 }
270
271 return state;
272 };
273};
274
275if (nativeWeakMap) {
276 var store$1 = new WeakMap$1();
277 var wmget = store$1.get;
278 var wmhas = store$1.has;
279 var wmset = store$1.set;
280
281 set = function (it, metadata) {
282 wmset.call(store$1, it, metadata);
283 return metadata;
284 };
285
286 get = function (it) {
287 return wmget.call(store$1, it) || {};
288 };
289
290 has$1 = function (it) {
291 return wmhas.call(store$1, it);
292 };
293} else {
294 var STATE = sharedKey('state');
295 hiddenKeys[STATE] = true;
296
297 set = function (it, metadata) {
298 createNonEnumerableProperty(it, STATE, metadata);
299 return metadata;
300 };
301
302 get = function (it) {
303 return has(it, STATE) ? it[STATE] : {};
304 };
305
306 has$1 = function (it) {
307 return has(it, STATE);
308 };
309}
310
311var internalState = {
312 set: set,
313 get: get,
314 has: has$1,
315 enforce: enforce,
316 getterFor: getterFor
317};
318
319var redefine = createCommonjsModule(function (module) {
320 var getInternalState = internalState.get;
321 var enforceInternalState = internalState.enforce;
322 var TEMPLATE = String(functionToString).split('toString');
323 shared('inspectSource', function (it) {
324 return functionToString.call(it);
325 });
326 (module.exports = function (O, key, value, options) {
327 var unsafe = options ? !!options.unsafe : false;
328 var simple = options ? !!options.enumerable : false;
329 var noTargetGet = options ? !!options.noTargetGet : false;
330
331 if (typeof value == 'function') {
332 if (typeof key == 'string' && !has(value, 'name')) createNonEnumerableProperty(value, 'name', key);
333 enforceInternalState(value).source = TEMPLATE.join(typeof key == 'string' ? key : '');
334 }
335
336 if (O === global_1) {
337 if (simple) O[key] = value;else setGlobal(key, value);
338 return;
339 } else if (!unsafe) {
340 delete O[key];
341 } else if (!noTargetGet && O[key]) {
342 simple = true;
343 }
344
345 if (simple) O[key] = value;else createNonEnumerableProperty(O, key, value); // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
346 })(Function.prototype, 'toString', function toString() {
347 return typeof this == 'function' && getInternalState(this).source || functionToString.call(this);
348 });
349});
350
351var path = global_1;
352
353var aFunction = function (variable) {
354 return typeof variable == 'function' ? variable : undefined;
355};
356
357var getBuiltIn = function (namespace, method) {
358 return arguments.length < 2 ? aFunction(path[namespace]) || aFunction(global_1[namespace]) : path[namespace] && path[namespace][method] || global_1[namespace] && global_1[namespace][method];
359};
360
361var ceil = Math.ceil;
362var floor = Math.floor; // `ToInteger` abstract operation
363// https://tc39.github.io/ecma262/#sec-tointeger
364
365var toInteger = function (argument) {
366 return isNaN(argument = +argument) ? 0 : (argument > 0 ? floor : ceil)(argument);
367};
368
369var min = Math.min; // `ToLength` abstract operation
370// https://tc39.github.io/ecma262/#sec-tolength
371
372var toLength = function (argument) {
373 return argument > 0 ? min(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
374};
375
376var max = Math.max;
377var min$1 = Math.min; // Helper for a popular repeating case of the spec:
378// Let integer be ? ToInteger(index).
379// If integer < 0, let result be max((length + integer), 0); else let result be min(length, length).
380
381var toAbsoluteIndex = function (index, length) {
382 var integer = toInteger(index);
383 return integer < 0 ? max(integer + length, 0) : min$1(integer, length);
384};
385
386var createMethod = function (IS_INCLUDES) {
387 return function ($this, el, fromIndex) {
388 var O = toIndexedObject($this);
389 var length = toLength(O.length);
390 var index = toAbsoluteIndex(fromIndex, length);
391 var value; // Array#includes uses SameValueZero equality algorithm
392 // eslint-disable-next-line no-self-compare
393
394 if (IS_INCLUDES && el != el) while (length > index) {
395 value = O[index++]; // eslint-disable-next-line no-self-compare
396
397 if (value != value) return true; // Array#indexOf ignores holes, Array#includes - not
398 } else for (; length > index; index++) {
399 if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
400 }
401 return !IS_INCLUDES && -1;
402 };
403};
404
405var arrayIncludes = {
406 // `Array.prototype.includes` method
407 // https://tc39.github.io/ecma262/#sec-array.prototype.includes
408 includes: createMethod(true),
409 // `Array.prototype.indexOf` method
410 // https://tc39.github.io/ecma262/#sec-array.prototype.indexof
411 indexOf: createMethod(false)
412};
413
414var indexOf = arrayIncludes.indexOf;
415
416var objectKeysInternal = function (object, names) {
417 var O = toIndexedObject(object);
418 var i = 0;
419 var result = [];
420 var key;
421
422 for (key in O) !has(hiddenKeys, key) && has(O, key) && result.push(key); // Don't enum bug & hidden keys
423
424
425 while (names.length > i) if (has(O, key = names[i++])) {
426 ~indexOf(result, key) || result.push(key);
427 }
428
429 return result;
430};
431
432// IE8- don't enum bug keys
433var enumBugKeys = ['constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf'];
434
435var hiddenKeys$1 = enumBugKeys.concat('length', 'prototype'); // `Object.getOwnPropertyNames` method
436// https://tc39.github.io/ecma262/#sec-object.getownpropertynames
437
438var f$3 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
439 return objectKeysInternal(O, hiddenKeys$1);
440};
441
442var objectGetOwnPropertyNames = {
443 f: f$3
444};
445
446var f$4 = Object.getOwnPropertySymbols;
447var objectGetOwnPropertySymbols = {
448 f: f$4
449};
450
451var ownKeys = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) {
452 var keys = objectGetOwnPropertyNames.f(anObject(it));
453 var getOwnPropertySymbols = objectGetOwnPropertySymbols.f;
454 return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys;
455};
456
457var copyConstructorProperties = function (target, source) {
458 var keys = ownKeys(source);
459 var defineProperty = objectDefineProperty.f;
460 var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
461
462 for (var i = 0; i < keys.length; i++) {
463 var key = keys[i];
464 if (!has(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key));
465 }
466};
467
468var replacement = /#|\.prototype\./;
469
470var isForced = function (feature, detection) {
471 var value = data[normalize(feature)];
472 return value == POLYFILL ? true : value == NATIVE ? false : typeof detection == 'function' ? fails(detection) : !!detection;
473};
474
475var normalize = isForced.normalize = function (string) {
476 return String(string).replace(replacement, '.').toLowerCase();
477};
478
479var data = isForced.data = {};
480var NATIVE = isForced.NATIVE = 'N';
481var POLYFILL = isForced.POLYFILL = 'P';
482var isForced_1 = isForced;
483
484var getOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f;
485/*
486 options.target - name of the target object
487 options.global - target is the global object
488 options.stat - export as static methods of target
489 options.proto - export as prototype methods of target
490 options.real - real prototype method for the `pure` version
491 options.forced - export even if the native feature is available
492 options.bind - bind methods to the target, required for the `pure` version
493 options.wrap - wrap constructors to preventing global pollution, required for the `pure` version
494 options.unsafe - use the simple assignment of property instead of delete + defineProperty
495 options.sham - add a flag to not completely full polyfills
496 options.enumerable - export as enumerable property
497 options.noTargetGet - prevent calling a getter on target
498*/
499
500var _export = function (options, source) {
501 var TARGET = options.target;
502 var GLOBAL = options.global;
503 var STATIC = options.stat;
504 var FORCED, target, key, targetProperty, sourceProperty, descriptor;
505
506 if (GLOBAL) {
507 target = global_1;
508 } else if (STATIC) {
509 target = global_1[TARGET] || setGlobal(TARGET, {});
510 } else {
511 target = (global_1[TARGET] || {}).prototype;
512 }
513
514 if (target) for (key in source) {
515 sourceProperty = source[key];
516
517 if (options.noTargetGet) {
518 descriptor = getOwnPropertyDescriptor$1(target, key);
519 targetProperty = descriptor && descriptor.value;
520 } else targetProperty = target[key];
521
522 FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced); // contained in target
523
524 if (!FORCED && targetProperty !== undefined) {
525 if (typeof sourceProperty === typeof targetProperty) continue;
526 copyConstructorProperties(sourceProperty, targetProperty);
527 } // add a flag to not completely full polyfills
528
529
530 if (options.sham || targetProperty && targetProperty.sham) {
531 createNonEnumerableProperty(sourceProperty, 'sham', true);
532 } // extend global
533
534
535 redefine(target, key, sourceProperty, options);
536 }
537};
538
539var nativeSymbol = !!Object.getOwnPropertySymbols && !fails(function () {
540 // Chrome 38 Symbol has incorrect toString conversion
541 // eslint-disable-next-line no-undef
542 return !String(Symbol());
543});
544
545var Symbol$1 = global_1.Symbol;
546var store$2 = shared('wks');
547
548var wellKnownSymbol = function (name) {
549 return store$2[name] || (store$2[name] = nativeSymbol && Symbol$1[name] || (nativeSymbol ? Symbol$1 : uid)('Symbol.' + name));
550};
551
552var TO_STRING_TAG = wellKnownSymbol('toStringTag'); // ES3 wrong here
553
554var CORRECT_ARGUMENTS = classofRaw(function () {
555 return arguments;
556}()) == 'Arguments'; // fallback for IE11 Script Access Denied error
557
558var tryGet = function (it, key) {
559 try {
560 return it[key];
561 } catch (error) {
562 /* empty */
563 }
564}; // getting tag from ES6+ `Object.prototype.toString`
565
566
567var classof = function (it) {
568 var O, tag, result;
569 return it === undefined ? 'Undefined' : it === null ? 'Null' // @@toStringTag case
570 : typeof (tag = tryGet(O = Object(it), TO_STRING_TAG)) == 'string' ? tag // builtinTag case
571 : CORRECT_ARGUMENTS ? classofRaw(O) // ES3 arguments fallback
572 : (result = classofRaw(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : result;
573};
574
575// https://tc39.github.io/ecma262/#sec-toobject
576
577var toObject = function (argument) {
578 return Object(requireObjectCoercible(argument));
579};
580
581var correctPrototypeGetter = !fails(function () {
582 function F() {
583 /* empty */
584 }
585
586 F.prototype.constructor = null;
587 return Object.getPrototypeOf(new F()) !== F.prototype;
588});
589
590var IE_PROTO = sharedKey('IE_PROTO');
591var ObjectPrototype = Object.prototype; // `Object.getPrototypeOf` method
592// https://tc39.github.io/ecma262/#sec-object.getprototypeof
593
594var objectGetPrototypeOf = correctPrototypeGetter ? Object.getPrototypeOf : function (O) {
595 O = toObject(O);
596 if (has(O, IE_PROTO)) return O[IE_PROTO];
597
598 if (typeof O.constructor == 'function' && O instanceof O.constructor) {
599 return O.constructor.prototype;
600 }
601
602 return O instanceof Object ? ObjectPrototype : null;
603};
604
605var aPossiblePrototype = function (it) {
606 if (!isObject(it) && it !== null) {
607 throw TypeError("Can't set " + String(it) + ' as a prototype');
608 }
609
610 return it;
611};
612
613// https://tc39.github.io/ecma262/#sec-object.setprototypeof
614// Works with __proto__ only. Old v8 can't work with null proto objects.
615
616/* eslint-disable no-proto */
617
618var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () {
619 var CORRECT_SETTER = false;
620 var test = {};
621 var setter;
622
623 try {
624 setter = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set;
625 setter.call(test, []);
626 CORRECT_SETTER = test instanceof Array;
627 } catch (error) {
628 /* empty */
629 }
630
631 return function setPrototypeOf(O, proto) {
632 anObject(O);
633 aPossiblePrototype(proto);
634 if (CORRECT_SETTER) setter.call(O, proto);else O.__proto__ = proto;
635 return O;
636 };
637}() : undefined);
638
639var defineProperty = objectDefineProperty.f;
640var DataView = global_1.DataView;
641var DataViewPrototype = DataView && DataView.prototype;
642var Int8Array = global_1.Int8Array;
643var Int8ArrayPrototype = Int8Array && Int8Array.prototype;
644var Uint8ClampedArray = global_1.Uint8ClampedArray;
645var Uint8ClampedArrayPrototype = Uint8ClampedArray && Uint8ClampedArray.prototype;
646var TypedArray = Int8Array && objectGetPrototypeOf(Int8Array);
647var TypedArrayPrototype = Int8ArrayPrototype && objectGetPrototypeOf(Int8ArrayPrototype);
648var ObjectPrototype$1 = Object.prototype;
649var isPrototypeOf = ObjectPrototype$1.isPrototypeOf;
650var TO_STRING_TAG$1 = wellKnownSymbol('toStringTag');
651var TYPED_ARRAY_TAG = uid('TYPED_ARRAY_TAG');
652var NATIVE_ARRAY_BUFFER = !!(global_1.ArrayBuffer && DataView); // Fixing native typed arrays in Opera Presto crashes the browser, see #595
653
654var NATIVE_ARRAY_BUFFER_VIEWS = NATIVE_ARRAY_BUFFER && !!objectSetPrototypeOf && classof(global_1.opera) !== 'Opera';
655var TYPED_ARRAY_TAG_REQIRED = false;
656var NAME;
657var TypedArrayConstructorsList = {
658 Int8Array: 1,
659 Uint8Array: 1,
660 Uint8ClampedArray: 1,
661 Int16Array: 2,
662 Uint16Array: 2,
663 Int32Array: 4,
664 Uint32Array: 4,
665 Float32Array: 4,
666 Float64Array: 8
667};
668
669var isView = function isView(it) {
670 var klass = classof(it);
671 return klass === 'DataView' || has(TypedArrayConstructorsList, klass);
672};
673
674var isTypedArray = function (it) {
675 return isObject(it) && has(TypedArrayConstructorsList, classof(it));
676};
677
678var aTypedArray = function (it) {
679 if (isTypedArray(it)) return it;
680 throw TypeError('Target is not a typed array');
681};
682
683var aTypedArrayConstructor = function (C) {
684 if (objectSetPrototypeOf) {
685 if (isPrototypeOf.call(TypedArray, C)) return C;
686 } else for (var ARRAY in TypedArrayConstructorsList) if (has(TypedArrayConstructorsList, NAME)) {
687 var TypedArrayConstructor = global_1[ARRAY];
688
689 if (TypedArrayConstructor && (C === TypedArrayConstructor || isPrototypeOf.call(TypedArrayConstructor, C))) {
690 return C;
691 }
692 }
693
694 throw TypeError('Target is not a typed array constructor');
695};
696
697var exportProto = function (KEY, property, forced) {
698 if (!descriptors) return;
699 if (forced) for (var ARRAY in TypedArrayConstructorsList) {
700 var TypedArrayConstructor = global_1[ARRAY];
701
702 if (TypedArrayConstructor && has(TypedArrayConstructor.prototype, KEY)) {
703 delete TypedArrayConstructor.prototype[KEY];
704 }
705 }
706
707 if (!TypedArrayPrototype[KEY] || forced) {
708 redefine(TypedArrayPrototype, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && Int8ArrayPrototype[KEY] || property);
709 }
710};
711
712var exportStatic = function (KEY, property, forced) {
713 var ARRAY, TypedArrayConstructor;
714 if (!descriptors) return;
715
716 if (objectSetPrototypeOf) {
717 if (forced) for (ARRAY in TypedArrayConstructorsList) {
718 TypedArrayConstructor = global_1[ARRAY];
719
720 if (TypedArrayConstructor && has(TypedArrayConstructor, KEY)) {
721 delete TypedArrayConstructor[KEY];
722 }
723 }
724
725 if (!TypedArray[KEY] || forced) {
726 // V8 ~ Chrome 49-50 `%TypedArray%` methods are non-writable non-configurable
727 try {
728 return redefine(TypedArray, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && Int8Array[KEY] || property);
729 } catch (error) {
730 /* empty */
731 }
732 } else return;
733 }
734
735 for (ARRAY in TypedArrayConstructorsList) {
736 TypedArrayConstructor = global_1[ARRAY];
737
738 if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) {
739 redefine(TypedArrayConstructor, KEY, property);
740 }
741 }
742};
743
744for (NAME in TypedArrayConstructorsList) {
745 if (!global_1[NAME]) NATIVE_ARRAY_BUFFER_VIEWS = false;
746} // WebKit bug - typed arrays constructors prototype is Object.prototype
747
748
749if (!NATIVE_ARRAY_BUFFER_VIEWS || typeof TypedArray != 'function' || TypedArray === Function.prototype) {
750 // eslint-disable-next-line no-shadow
751 TypedArray = function TypedArray() {
752 throw TypeError('Incorrect invocation');
753 };
754
755 if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) {
756 if (global_1[NAME]) objectSetPrototypeOf(global_1[NAME], TypedArray);
757 }
758}
759
760if (!NATIVE_ARRAY_BUFFER_VIEWS || !TypedArrayPrototype || TypedArrayPrototype === ObjectPrototype$1) {
761 TypedArrayPrototype = TypedArray.prototype;
762 if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) {
763 if (global_1[NAME]) objectSetPrototypeOf(global_1[NAME].prototype, TypedArrayPrototype);
764 }
765} // WebKit bug - one more object in Uint8ClampedArray prototype chain
766
767
768if (NATIVE_ARRAY_BUFFER_VIEWS && objectGetPrototypeOf(Uint8ClampedArrayPrototype) !== TypedArrayPrototype) {
769 objectSetPrototypeOf(Uint8ClampedArrayPrototype, TypedArrayPrototype);
770}
771
772if (descriptors && !has(TypedArrayPrototype, TO_STRING_TAG$1)) {
773 TYPED_ARRAY_TAG_REQIRED = true;
774 defineProperty(TypedArrayPrototype, TO_STRING_TAG$1, {
775 get: function () {
776 return isObject(this) ? this[TYPED_ARRAY_TAG] : undefined;
777 }
778 });
779
780 for (NAME in TypedArrayConstructorsList) if (global_1[NAME]) {
781 createNonEnumerableProperty(global_1[NAME], TYPED_ARRAY_TAG, NAME);
782 }
783} // WebKit bug - the same parent prototype for typed arrays and data view
784
785
786if (NATIVE_ARRAY_BUFFER && objectSetPrototypeOf && objectGetPrototypeOf(DataViewPrototype) !== ObjectPrototype$1) {
787 objectSetPrototypeOf(DataViewPrototype, ObjectPrototype$1);
788}
789
790var arrayBufferViewCore = {
791 NATIVE_ARRAY_BUFFER: NATIVE_ARRAY_BUFFER,
792 NATIVE_ARRAY_BUFFER_VIEWS: NATIVE_ARRAY_BUFFER_VIEWS,
793 TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQIRED && TYPED_ARRAY_TAG,
794 aTypedArray: aTypedArray,
795 aTypedArrayConstructor: aTypedArrayConstructor,
796 exportProto: exportProto,
797 exportStatic: exportStatic,
798 isView: isView,
799 isTypedArray: isTypedArray,
800 TypedArray: TypedArray,
801 TypedArrayPrototype: TypedArrayPrototype
802};
803
804var redefineAll = function (target, src, options) {
805 for (var key in src) redefine(target, key, src[key], options);
806
807 return target;
808};
809
810var anInstance = function (it, Constructor, name) {
811 if (!(it instanceof Constructor)) {
812 throw TypeError('Incorrect ' + (name ? name + ' ' : '') + 'invocation');
813 }
814
815 return it;
816};
817
818// https://tc39.github.io/ecma262/#sec-toindex
819
820var toIndex = function (it) {
821 if (it === undefined) return 0;
822 var number = toInteger(it);
823 var length = toLength(number);
824 if (number !== length) throw RangeError('Wrong length or index');
825 return length;
826};
827
828// https://tc39.github.io/ecma262/#sec-array.prototype.fill
829
830
831var arrayFill = function fill(value
832/* , start = 0, end = @length */
833) {
834 var O = toObject(this);
835 var length = toLength(O.length);
836 var argumentsLength = arguments.length;
837 var index = toAbsoluteIndex(argumentsLength > 1 ? arguments[1] : undefined, length);
838 var end = argumentsLength > 2 ? arguments[2] : undefined;
839 var endPos = end === undefined ? length : toAbsoluteIndex(end, length);
840
841 while (endPos > index) O[index++] = value;
842
843 return O;
844};
845
846var defineProperty$1 = objectDefineProperty.f;
847var TO_STRING_TAG$2 = wellKnownSymbol('toStringTag');
848
849var setToStringTag = function (it, TAG, STATIC) {
850 if (it && !has(it = STATIC ? it : it.prototype, TO_STRING_TAG$2)) {
851 defineProperty$1(it, TO_STRING_TAG$2, {
852 configurable: true,
853 value: TAG
854 });
855 }
856};
857
858var NATIVE_ARRAY_BUFFER$1 = arrayBufferViewCore.NATIVE_ARRAY_BUFFER;
859var getOwnPropertyNames = objectGetOwnPropertyNames.f;
860var defineProperty$2 = objectDefineProperty.f;
861var getInternalState = internalState.get;
862var setInternalState = internalState.set;
863var ARRAY_BUFFER = 'ArrayBuffer';
864var DATA_VIEW = 'DataView';
865var PROTOTYPE = 'prototype';
866var WRONG_LENGTH = 'Wrong length';
867var WRONG_INDEX = 'Wrong index';
868var NativeArrayBuffer = global_1[ARRAY_BUFFER];
869var $ArrayBuffer = NativeArrayBuffer;
870var $DataView = global_1[DATA_VIEW];
871var Math$1 = global_1.Math;
872var RangeError$1 = global_1.RangeError; // eslint-disable-next-line no-shadow-restricted-names
873
874var Infinity$1 = 1 / 0;
875var abs = Math$1.abs;
876var pow = Math$1.pow;
877var floor$1 = Math$1.floor;
878var log = Math$1.log;
879var LN2 = Math$1.LN2; // IEEE754 conversions based on https://github.com/feross/ieee754
880
881var packIEEE754 = function (number, mantissaLength, bytes) {
882 var buffer = new Array(bytes);
883 var exponentLength = bytes * 8 - mantissaLength - 1;
884 var eMax = (1 << exponentLength) - 1;
885 var eBias = eMax >> 1;
886 var rt = mantissaLength === 23 ? pow(2, -24) - pow(2, -77) : 0;
887 var sign = number < 0 || number === 0 && 1 / number < 0 ? 1 : 0;
888 var index = 0;
889 var exponent, mantissa, c;
890 number = abs(number); // eslint-disable-next-line no-self-compare
891
892 if (number != number || number === Infinity$1) {
893 // eslint-disable-next-line no-self-compare
894 mantissa = number != number ? 1 : 0;
895 exponent = eMax;
896 } else {
897 exponent = floor$1(log(number) / LN2);
898
899 if (number * (c = pow(2, -exponent)) < 1) {
900 exponent--;
901 c *= 2;
902 }
903
904 if (exponent + eBias >= 1) {
905 number += rt / c;
906 } else {
907 number += rt * pow(2, 1 - eBias);
908 }
909
910 if (number * c >= 2) {
911 exponent++;
912 c /= 2;
913 }
914
915 if (exponent + eBias >= eMax) {
916 mantissa = 0;
917 exponent = eMax;
918 } else if (exponent + eBias >= 1) {
919 mantissa = (number * c - 1) * pow(2, mantissaLength);
920 exponent = exponent + eBias;
921 } else {
922 mantissa = number * pow(2, eBias - 1) * pow(2, mantissaLength);
923 exponent = 0;
924 }
925 }
926
927 for (; mantissaLength >= 8; buffer[index++] = mantissa & 255, mantissa /= 256, mantissaLength -= 8);
928
929 exponent = exponent << mantissaLength | mantissa;
930 exponentLength += mantissaLength;
931
932 for (; exponentLength > 0; buffer[index++] = exponent & 255, exponent /= 256, exponentLength -= 8);
933
934 buffer[--index] |= sign * 128;
935 return buffer;
936};
937
938var unpackIEEE754 = function (buffer, mantissaLength) {
939 var bytes = buffer.length;
940 var exponentLength = bytes * 8 - mantissaLength - 1;
941 var eMax = (1 << exponentLength) - 1;
942 var eBias = eMax >> 1;
943 var nBits = exponentLength - 7;
944 var index = bytes - 1;
945 var sign = buffer[index--];
946 var exponent = sign & 127;
947 var mantissa;
948 sign >>= 7;
949
950 for (; nBits > 0; exponent = exponent * 256 + buffer[index], index--, nBits -= 8);
951
952 mantissa = exponent & (1 << -nBits) - 1;
953 exponent >>= -nBits;
954 nBits += mantissaLength;
955
956 for (; nBits > 0; mantissa = mantissa * 256 + buffer[index], index--, nBits -= 8);
957
958 if (exponent === 0) {
959 exponent = 1 - eBias;
960 } else if (exponent === eMax) {
961 return mantissa ? NaN : sign ? -Infinity$1 : Infinity$1;
962 } else {
963 mantissa = mantissa + pow(2, mantissaLength);
964 exponent = exponent - eBias;
965 }
966
967 return (sign ? -1 : 1) * mantissa * pow(2, exponent - mantissaLength);
968};
969
970var unpackInt32 = function (buffer) {
971 return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
972};
973
974var packInt8 = function (number) {
975 return [number & 0xFF];
976};
977
978var packInt16 = function (number) {
979 return [number & 0xFF, number >> 8 & 0xFF];
980};
981
982var packInt32 = function (number) {
983 return [number & 0xFF, number >> 8 & 0xFF, number >> 16 & 0xFF, number >> 24 & 0xFF];
984};
985
986var packFloat32 = function (number) {
987 return packIEEE754(number, 23, 4);
988};
989
990var packFloat64 = function (number) {
991 return packIEEE754(number, 52, 8);
992};
993
994var addGetter = function (Constructor, key) {
995 defineProperty$2(Constructor[PROTOTYPE], key, {
996 get: function () {
997 return getInternalState(this)[key];
998 }
999 });
1000};
1001
1002var get$1 = function (view, count, index, isLittleEndian) {
1003 var numIndex = +index;
1004 var intIndex = toIndex(numIndex);
1005 var store = getInternalState(view);
1006 if (intIndex + count > store.byteLength) throw RangeError$1(WRONG_INDEX);
1007 var bytes = getInternalState(store.buffer).bytes;
1008 var start = intIndex + store.byteOffset;
1009 var pack = bytes.slice(start, start + count);
1010 return isLittleEndian ? pack : pack.reverse();
1011};
1012
1013var set$1 = function (view, count, index, conversion, value, isLittleEndian) {
1014 var numIndex = +index;
1015 var intIndex = toIndex(numIndex);
1016 var store = getInternalState(view);
1017 if (intIndex + count > store.byteLength) throw RangeError$1(WRONG_INDEX);
1018 var bytes = getInternalState(store.buffer).bytes;
1019 var start = intIndex + store.byteOffset;
1020 var pack = conversion(+value);
1021
1022 for (var i = 0; i < count; i++) bytes[start + i] = pack[isLittleEndian ? i : count - i - 1];
1023};
1024
1025if (!NATIVE_ARRAY_BUFFER$1) {
1026 $ArrayBuffer = function ArrayBuffer(length) {
1027 anInstance(this, $ArrayBuffer, ARRAY_BUFFER);
1028 var byteLength = toIndex(length);
1029 setInternalState(this, {
1030 bytes: arrayFill.call(new Array(byteLength), 0),
1031 byteLength: byteLength
1032 });
1033 if (!descriptors) this.byteLength = byteLength;
1034 };
1035
1036 $DataView = function DataView(buffer, byteOffset, byteLength) {
1037 anInstance(this, $DataView, DATA_VIEW);
1038 anInstance(buffer, $ArrayBuffer, DATA_VIEW);
1039 var bufferLength = getInternalState(buffer).byteLength;
1040 var offset = toInteger(byteOffset);
1041 if (offset < 0 || offset > bufferLength) throw RangeError$1('Wrong offset');
1042 byteLength = byteLength === undefined ? bufferLength - offset : toLength(byteLength);
1043 if (offset + byteLength > bufferLength) throw RangeError$1(WRONG_LENGTH);
1044 setInternalState(this, {
1045 buffer: buffer,
1046 byteLength: byteLength,
1047 byteOffset: offset
1048 });
1049
1050 if (!descriptors) {
1051 this.buffer = buffer;
1052 this.byteLength = byteLength;
1053 this.byteOffset = offset;
1054 }
1055 };
1056
1057 if (descriptors) {
1058 addGetter($ArrayBuffer, 'byteLength');
1059 addGetter($DataView, 'buffer');
1060 addGetter($DataView, 'byteLength');
1061 addGetter($DataView, 'byteOffset');
1062 }
1063
1064 redefineAll($DataView[PROTOTYPE], {
1065 getInt8: function getInt8(byteOffset) {
1066 return get$1(this, 1, byteOffset)[0] << 24 >> 24;
1067 },
1068 getUint8: function getUint8(byteOffset) {
1069 return get$1(this, 1, byteOffset)[0];
1070 },
1071 getInt16: function getInt16(byteOffset
1072 /* , littleEndian */
1073 ) {
1074 var bytes = get$1(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : undefined);
1075 return (bytes[1] << 8 | bytes[0]) << 16 >> 16;
1076 },
1077 getUint16: function getUint16(byteOffset
1078 /* , littleEndian */
1079 ) {
1080 var bytes = get$1(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : undefined);
1081 return bytes[1] << 8 | bytes[0];
1082 },
1083 getInt32: function getInt32(byteOffset
1084 /* , littleEndian */
1085 ) {
1086 return unpackInt32(get$1(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined));
1087 },
1088 getUint32: function getUint32(byteOffset
1089 /* , littleEndian */
1090 ) {
1091 return unpackInt32(get$1(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined)) >>> 0;
1092 },
1093 getFloat32: function getFloat32(byteOffset
1094 /* , littleEndian */
1095 ) {
1096 return unpackIEEE754(get$1(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined), 23);
1097 },
1098 getFloat64: function getFloat64(byteOffset
1099 /* , littleEndian */
1100 ) {
1101 return unpackIEEE754(get$1(this, 8, byteOffset, arguments.length > 1 ? arguments[1] : undefined), 52);
1102 },
1103 setInt8: function setInt8(byteOffset, value) {
1104 set$1(this, 1, byteOffset, packInt8, value);
1105 },
1106 setUint8: function setUint8(byteOffset, value) {
1107 set$1(this, 1, byteOffset, packInt8, value);
1108 },
1109 setInt16: function setInt16(byteOffset, value
1110 /* , littleEndian */
1111 ) {
1112 set$1(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : undefined);
1113 },
1114 setUint16: function setUint16(byteOffset, value
1115 /* , littleEndian */
1116 ) {
1117 set$1(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : undefined);
1118 },
1119 setInt32: function setInt32(byteOffset, value
1120 /* , littleEndian */
1121 ) {
1122 set$1(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : undefined);
1123 },
1124 setUint32: function setUint32(byteOffset, value
1125 /* , littleEndian */
1126 ) {
1127 set$1(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : undefined);
1128 },
1129 setFloat32: function setFloat32(byteOffset, value
1130 /* , littleEndian */
1131 ) {
1132 set$1(this, 4, byteOffset, packFloat32, value, arguments.length > 2 ? arguments[2] : undefined);
1133 },
1134 setFloat64: function setFloat64(byteOffset, value
1135 /* , littleEndian */
1136 ) {
1137 set$1(this, 8, byteOffset, packFloat64, value, arguments.length > 2 ? arguments[2] : undefined);
1138 }
1139 });
1140} else {
1141 if (!fails(function () {
1142 NativeArrayBuffer(1);
1143 }) || !fails(function () {
1144 new NativeArrayBuffer(-1); // eslint-disable-line no-new
1145 }) || fails(function () {
1146 new NativeArrayBuffer(); // eslint-disable-line no-new
1147
1148 new NativeArrayBuffer(1.5); // eslint-disable-line no-new
1149
1150 new NativeArrayBuffer(NaN); // eslint-disable-line no-new
1151
1152 return NativeArrayBuffer.name != ARRAY_BUFFER;
1153 })) {
1154 $ArrayBuffer = function ArrayBuffer(length) {
1155 anInstance(this, $ArrayBuffer);
1156 return new NativeArrayBuffer(toIndex(length));
1157 };
1158
1159 var ArrayBufferPrototype = $ArrayBuffer[PROTOTYPE] = NativeArrayBuffer[PROTOTYPE];
1160
1161 for (var keys$1 = getOwnPropertyNames(NativeArrayBuffer), j = 0, key; keys$1.length > j;) {
1162 if (!((key = keys$1[j++]) in $ArrayBuffer)) {
1163 createNonEnumerableProperty($ArrayBuffer, key, NativeArrayBuffer[key]);
1164 }
1165 }
1166
1167 ArrayBufferPrototype.constructor = $ArrayBuffer;
1168 } // iOS Safari 7.x bug
1169
1170
1171 var testView = new $DataView(new $ArrayBuffer(2));
1172 var nativeSetInt8 = $DataView[PROTOTYPE].setInt8;
1173 testView.setInt8(0, 2147483648);
1174 testView.setInt8(1, 2147483649);
1175 if (testView.getInt8(0) || !testView.getInt8(1)) redefineAll($DataView[PROTOTYPE], {
1176 setInt8: function setInt8(byteOffset, value) {
1177 nativeSetInt8.call(this, byteOffset, value << 24 >> 24);
1178 },
1179 setUint8: function setUint8(byteOffset, value) {
1180 nativeSetInt8.call(this, byteOffset, value << 24 >> 24);
1181 }
1182 }, {
1183 unsafe: true
1184 });
1185}
1186
1187setToStringTag($ArrayBuffer, ARRAY_BUFFER);
1188setToStringTag($DataView, DATA_VIEW);
1189var arrayBuffer = {
1190 ArrayBuffer: $ArrayBuffer,
1191 DataView: $DataView
1192};
1193
1194var aFunction$1 = function (it) {
1195 if (typeof it != 'function') {
1196 throw TypeError(String(it) + ' is not a function');
1197 }
1198
1199 return it;
1200};
1201
1202var SPECIES = wellKnownSymbol('species'); // `SpeciesConstructor` abstract operation
1203// https://tc39.github.io/ecma262/#sec-speciesconstructor
1204
1205var speciesConstructor = function (O, defaultConstructor) {
1206 var C = anObject(O).constructor;
1207 var S;
1208 return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? defaultConstructor : aFunction$1(S);
1209};
1210
1211var ArrayBuffer = arrayBuffer.ArrayBuffer;
1212var DataView$1 = arrayBuffer.DataView;
1213var nativeArrayBufferSlice = ArrayBuffer.prototype.slice;
1214var INCORRECT_SLICE = fails(function () {
1215 return !new ArrayBuffer(2).slice(1, undefined).byteLength;
1216}); // `ArrayBuffer.prototype.slice` method
1217// https://tc39.github.io/ecma262/#sec-arraybuffer.prototype.slice
1218
1219_export({
1220 target: 'ArrayBuffer',
1221 proto: true,
1222 unsafe: true,
1223 forced: INCORRECT_SLICE
1224}, {
1225 slice: function slice(start, end) {
1226 if (nativeArrayBufferSlice !== undefined && end === undefined) {
1227 return nativeArrayBufferSlice.call(anObject(this), start); // FF fix
1228 }
1229
1230 var length = anObject(this).byteLength;
1231 var first = toAbsoluteIndex(start, length);
1232 var fin = toAbsoluteIndex(end === undefined ? length : end, length);
1233 var result = new (speciesConstructor(this, ArrayBuffer))(toLength(fin - first));
1234 var viewSource = new DataView$1(this);
1235 var viewTarget = new DataView$1(result);
1236 var index = 0;
1237
1238 while (first < fin) {
1239 viewTarget.setUint8(index++, viewSource.getUint8(first++));
1240 }
1241
1242 return result;
1243 }
1244});
1245
1246var NATIVE_ARRAY_BUFFER$2 = arrayBufferViewCore.NATIVE_ARRAY_BUFFER; // `DataView` constructor
1247// https://tc39.github.io/ecma262/#sec-dataview-constructor
1248
1249_export({
1250 global: true,
1251 forced: !NATIVE_ARRAY_BUFFER$2
1252}, {
1253 DataView: arrayBuffer.DataView
1254});
1255
1256var TO_STRING_TAG$3 = wellKnownSymbol('toStringTag');
1257var test = {};
1258test[TO_STRING_TAG$3] = 'z'; // `Object.prototype.toString` method implementation
1259// https://tc39.github.io/ecma262/#sec-object.prototype.tostring
1260
1261var objectToString = String(test) !== '[object z]' ? function toString() {
1262 return '[object ' + classof(this) + ']';
1263} : test.toString;
1264
1265var ObjectPrototype$2 = Object.prototype; // `Object.prototype.toString` method
1266// https://tc39.github.io/ecma262/#sec-object.prototype.tostring
1267
1268if (objectToString !== ObjectPrototype$2.toString) {
1269 redefine(ObjectPrototype$2, 'toString', objectToString, {
1270 unsafe: true
1271 });
1272}
1273
1274/*
1275 * Canvas shapes used by Network
1276 */
1277
1278if (typeof CanvasRenderingContext2D !== "undefined") {
1279 CanvasRenderingContext2D.prototype.circle = function (x, y, r) {
1280 this.beginPath();
1281 this.arc(x, y, r, 0, 2 * Math.PI, false);
1282 this.closePath();
1283 };
1284
1285 CanvasRenderingContext2D.prototype.square = function (x, y, r) {
1286 this.beginPath();
1287 this.rect(x - r, y - r, r * 2, r * 2);
1288 this.closePath();
1289 };
1290
1291 CanvasRenderingContext2D.prototype.triangle = function (x, y, r) {
1292 this.beginPath(); // the change in radius and the offset is here to center the shape
1293
1294 r *= 1.15;
1295 y += 0.275 * r;
1296 var s = r * 2;
1297 var s2 = s / 2;
1298 var ir = Math.sqrt(3) / 6 * s; // radius of inner circle
1299
1300 var h = Math.sqrt(s * s - s2 * s2); // height
1301
1302 this.moveTo(x, y - (h - ir));
1303 this.lineTo(x + s2, y + ir);
1304 this.lineTo(x - s2, y + ir);
1305 this.lineTo(x, y - (h - ir));
1306 this.closePath();
1307 };
1308
1309 CanvasRenderingContext2D.prototype.triangleDown = function (x, y, r) {
1310 this.beginPath(); // the change in radius and the offset is here to center the shape
1311
1312 r *= 1.15;
1313 y -= 0.275 * r;
1314 var s = r * 2;
1315 var s2 = s / 2;
1316 var ir = Math.sqrt(3) / 6 * s; // radius of inner circle
1317
1318 var h = Math.sqrt(s * s - s2 * s2); // height
1319
1320 this.moveTo(x, y + (h - ir));
1321 this.lineTo(x + s2, y - ir);
1322 this.lineTo(x - s2, y - ir);
1323 this.lineTo(x, y + (h - ir));
1324 this.closePath();
1325 };
1326
1327 CanvasRenderingContext2D.prototype.star = function (x, y, r) {
1328 // http://www.html5canvastutorials.com/labs/html5-canvas-star-spinner/
1329 this.beginPath(); // the change in radius and the offset is here to center the shape
1330
1331 r *= 0.82;
1332 y += 0.1 * r;
1333
1334 for (var n = 0; n < 10; n++) {
1335 var radius = n % 2 === 0 ? r * 1.3 : r * 0.5;
1336 this.lineTo(x + radius * Math.sin(n * 2 * Math.PI / 10), y - radius * Math.cos(n * 2 * Math.PI / 10));
1337 }
1338
1339 this.closePath();
1340 };
1341
1342 CanvasRenderingContext2D.prototype.diamond = function (x, y, r) {
1343 this.beginPath();
1344 this.lineTo(x, y + r);
1345 this.lineTo(x + r, y);
1346 this.lineTo(x, y - r);
1347 this.lineTo(x - r, y);
1348 this.closePath();
1349 };
1350
1351 CanvasRenderingContext2D.prototype.roundRect = function (x, y, w, h, r) {
1352 var r2d = Math.PI / 180;
1353
1354 if (w - 2 * r < 0) {
1355 r = w / 2;
1356 } //ensure that the radius isn't too large for x
1357
1358
1359 if (h - 2 * r < 0) {
1360 r = h / 2;
1361 } //ensure that the radius isn't too large for y
1362
1363
1364 this.beginPath();
1365 this.moveTo(x + r, y);
1366 this.lineTo(x + w - r, y);
1367 this.arc(x + w - r, y + r, r, r2d * 270, r2d * 360, false);
1368 this.lineTo(x + w, y + h - r);
1369 this.arc(x + w - r, y + h - r, r, 0, r2d * 90, false);
1370 this.lineTo(x + r, y + h);
1371 this.arc(x + r, y + h - r, r, r2d * 90, r2d * 180, false);
1372 this.lineTo(x, y + r);
1373 this.arc(x + r, y + r, r, r2d * 180, r2d * 270, false);
1374 this.closePath();
1375 };
1376
1377 CanvasRenderingContext2D.prototype.ellipse_vis = function (x, y, w, h) {
1378 var kappa = 0.5522848,
1379 ox = w / 2 * kappa,
1380 // control point offset horizontal
1381 oy = h / 2 * kappa,
1382 // control point offset vertical
1383 xe = x + w,
1384 // x-end
1385 ye = y + h,
1386 // y-end
1387 xm = x + w / 2,
1388 // x-middle
1389 ym = y + h / 2; // y-middle
1390
1391 this.beginPath();
1392 this.moveTo(x, ym);
1393 this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
1394 this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
1395 this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
1396 this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
1397 this.closePath();
1398 };
1399
1400 CanvasRenderingContext2D.prototype.database = function (x, y, w, h) {
1401 var f = 1 / 3;
1402 var wEllipse = w;
1403 var hEllipse = h * f;
1404 var kappa = 0.5522848,
1405 ox = wEllipse / 2 * kappa,
1406 // control point offset horizontal
1407 oy = hEllipse / 2 * kappa,
1408 // control point offset vertical
1409 xe = x + wEllipse,
1410 // x-end
1411 ye = y + hEllipse,
1412 // y-end
1413 xm = x + wEllipse / 2,
1414 // x-middle
1415 ym = y + hEllipse / 2,
1416 // y-middle
1417 ymb = y + (h - hEllipse / 2),
1418 // y-midlle, bottom ellipse
1419 yeb = y + h; // y-end, bottom ellipse
1420
1421 this.beginPath();
1422 this.moveTo(xe, ym);
1423 this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
1424 this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
1425 this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
1426 this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
1427 this.lineTo(xe, ymb);
1428 this.bezierCurveTo(xe, ymb + oy, xm + ox, yeb, xm, yeb);
1429 this.bezierCurveTo(xm - ox, yeb, x, ymb + oy, x, ymb);
1430 this.lineTo(x, ym);
1431 };
1432
1433 CanvasRenderingContext2D.prototype.dashedLine = function (x, y, x2, y2, pattern) {
1434 this.beginPath();
1435 this.moveTo(x, y);
1436 var patternLength = pattern.length;
1437 var dx = x2 - x;
1438 var dy = y2 - y;
1439 var slope = dy / dx;
1440 var distRemaining = Math.sqrt(dx * dx + dy * dy);
1441 var patternIndex = 0;
1442 var draw = true;
1443 var xStep = 0;
1444 var dashLength = +pattern[0];
1445
1446 while (distRemaining >= 0.1) {
1447 dashLength = +pattern[patternIndex++ % patternLength];
1448
1449 if (dashLength > distRemaining) {
1450 dashLength = distRemaining;
1451 }
1452
1453 xStep = Math.sqrt(dashLength * dashLength / (1 + slope * slope));
1454 xStep = dx < 0 ? -xStep : xStep;
1455 x += xStep;
1456 y += slope * xStep;
1457
1458 if (draw === true) {
1459 this.lineTo(x, y);
1460 } else {
1461 this.moveTo(x, y);
1462 }
1463
1464 distRemaining -= dashLength;
1465 draw = !draw;
1466 }
1467 };
1468
1469 CanvasRenderingContext2D.prototype.hexagon = function (x, y, r) {
1470 this.beginPath();
1471 var sides = 6;
1472 var a = Math.PI * 2 / sides;
1473 this.moveTo(x + r, y);
1474
1475 for (var i = 1; i < sides; i++) {
1476 this.lineTo(x + r * Math.cos(a * i), y + r * Math.sin(a * i));
1477 }
1478
1479 this.closePath();
1480 };
1481}
1482
1483var componentEmitter = createCommonjsModule(function (module) {
1484 /**
1485 * Expose `Emitter`.
1486 */
1487 {
1488 module.exports = Emitter;
1489 }
1490 /**
1491 * Initialize a new `Emitter`.
1492 *
1493 * @api public
1494 */
1495
1496
1497 function Emitter(obj) {
1498 if (obj) return mixin(obj);
1499 }
1500 /**
1501 * Mixin the emitter properties.
1502 *
1503 * @param {Object} obj
1504 * @return {Object}
1505 * @api private
1506 */
1507
1508 function mixin(obj) {
1509 for (var key in Emitter.prototype) {
1510 obj[key] = Emitter.prototype[key];
1511 }
1512
1513 return obj;
1514 }
1515 /**
1516 * Listen on the given `event` with `fn`.
1517 *
1518 * @param {String} event
1519 * @param {Function} fn
1520 * @return {Emitter}
1521 * @api public
1522 */
1523
1524
1525 Emitter.prototype.on = Emitter.prototype.addEventListener = function (event, fn) {
1526 this._callbacks = this._callbacks || {};
1527 (this._callbacks['$' + event] = this._callbacks['$' + event] || []).push(fn);
1528 return this;
1529 };
1530 /**
1531 * Adds an `event` listener that will be invoked a single
1532 * time then automatically removed.
1533 *
1534 * @param {String} event
1535 * @param {Function} fn
1536 * @return {Emitter}
1537 * @api public
1538 */
1539
1540
1541 Emitter.prototype.once = function (event, fn) {
1542 function on() {
1543 this.off(event, on);
1544 fn.apply(this, arguments);
1545 }
1546
1547 on.fn = fn;
1548 this.on(event, on);
1549 return this;
1550 };
1551 /**
1552 * Remove the given callback for `event` or all
1553 * registered callbacks.
1554 *
1555 * @param {String} event
1556 * @param {Function} fn
1557 * @return {Emitter}
1558 * @api public
1559 */
1560
1561
1562 Emitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function (event, fn) {
1563 this._callbacks = this._callbacks || {}; // all
1564
1565 if (0 == arguments.length) {
1566 this._callbacks = {};
1567 return this;
1568 } // specific event
1569
1570
1571 var callbacks = this._callbacks['$' + event];
1572 if (!callbacks) return this; // remove all handlers
1573
1574 if (1 == arguments.length) {
1575 delete this._callbacks['$' + event];
1576 return this;
1577 } // remove specific handler
1578
1579
1580 var cb;
1581
1582 for (var i = 0; i < callbacks.length; i++) {
1583 cb = callbacks[i];
1584
1585 if (cb === fn || cb.fn === fn) {
1586 callbacks.splice(i, 1);
1587 break;
1588 }
1589 } // Remove event specific arrays for event types that no
1590 // one is subscribed for to avoid memory leak.
1591
1592
1593 if (callbacks.length === 0) {
1594 delete this._callbacks['$' + event];
1595 }
1596
1597 return this;
1598 };
1599 /**
1600 * Emit `event` with the given args.
1601 *
1602 * @param {String} event
1603 * @param {Mixed} ...
1604 * @return {Emitter}
1605 */
1606
1607
1608 Emitter.prototype.emit = function (event) {
1609 this._callbacks = this._callbacks || {};
1610 var args = new Array(arguments.length - 1),
1611 callbacks = this._callbacks['$' + event];
1612
1613 for (var i = 1; i < arguments.length; i++) {
1614 args[i - 1] = arguments[i];
1615 }
1616
1617 if (callbacks) {
1618 callbacks = callbacks.slice(0);
1619
1620 for (var i = 0, len = callbacks.length; i < len; ++i) {
1621 callbacks[i].apply(this, args);
1622 }
1623 }
1624
1625 return this;
1626 };
1627 /**
1628 * Return array of callbacks for `event`.
1629 *
1630 * @param {String} event
1631 * @return {Array}
1632 * @api public
1633 */
1634
1635
1636 Emitter.prototype.listeners = function (event) {
1637 this._callbacks = this._callbacks || {};
1638 return this._callbacks['$' + event] || [];
1639 };
1640 /**
1641 * Check if this emitter has `event` handlers.
1642 *
1643 * @param {String} event
1644 * @return {Boolean}
1645 * @api public
1646 */
1647
1648
1649 Emitter.prototype.hasListeners = function (event) {
1650 return !!this.listeners(event).length;
1651 };
1652});
1653
1654var commonjsGlobal$1 = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
1655
1656function commonjsRequire$1() {
1657 throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
1658}
1659
1660function createCommonjsModule$1(fn, module) {
1661 return module = {
1662 exports: {}
1663 }, fn(module, module.exports), module.exports;
1664}
1665
1666var _global = createCommonjsModule$1(function (module) {
1667 // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
1668 var global = module.exports = typeof window != 'undefined' && window.Math == Math ? window : typeof self != 'undefined' && self.Math == Math ? self // eslint-disable-next-line no-new-func
1669 : Function('return this')();
1670 if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef
1671});
1672
1673var _core = createCommonjsModule$1(function (module) {
1674 var core = module.exports = {
1675 version: '2.6.9'
1676 };
1677 if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef
1678});
1679
1680var _core_1 = _core.version;
1681var _library = false;
1682
1683var _shared = createCommonjsModule$1(function (module) {
1684 var SHARED = '__core-js_shared__';
1685 var store = _global[SHARED] || (_global[SHARED] = {});
1686 (module.exports = function (key, value) {
1687 return store[key] || (store[key] = value !== undefined ? value : {});
1688 })('versions', []).push({
1689 version: _core.version,
1690 mode: 'global',
1691 copyright: '© 2019 Denis Pushkarev (zloirock.ru)'
1692 });
1693});
1694
1695var id$1 = 0;
1696var px = Math.random();
1697
1698var _uid = function (key) {
1699 return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id$1 + px).toString(36));
1700};
1701
1702var _wks = createCommonjsModule$1(function (module) {
1703 var store = _shared('wks');
1704
1705 var Symbol = _global.Symbol;
1706 var USE_SYMBOL = typeof Symbol == 'function';
1707
1708 var $exports = module.exports = function (name) {
1709 return store[name] || (store[name] = USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : _uid)('Symbol.' + name));
1710 };
1711
1712 $exports.store = store;
1713});
1714
1715var f$5 = _wks;
1716var _wksExt = {
1717 f: f$5
1718};
1719
1720var _isObject = function (it) {
1721 return typeof it === 'object' ? it !== null : typeof it === 'function';
1722};
1723
1724var _anObject = function (it) {
1725 if (!_isObject(it)) throw TypeError(it + ' is not an object!');
1726 return it;
1727};
1728
1729var _fails = function (exec) {
1730 try {
1731 return !!exec();
1732 } catch (e) {
1733 return true;
1734 }
1735};
1736
1737var _descriptors = !_fails(function () {
1738 return Object.defineProperty({}, 'a', {
1739 get: function () {
1740 return 7;
1741 }
1742 }).a != 7;
1743});
1744
1745var document$1$1 = _global.document; // typeof document.createElement is 'object' in old IE
1746
1747var is = _isObject(document$1$1) && _isObject(document$1$1.createElement);
1748
1749var _domCreate = function (it) {
1750 return is ? document$1$1.createElement(it) : {};
1751};
1752
1753var _ie8DomDefine = !_descriptors && !_fails(function () {
1754 return Object.defineProperty(_domCreate('div'), 'a', {
1755 get: function () {
1756 return 7;
1757 }
1758 }).a != 7;
1759}); // instead of the ES6 spec version, we didn't implement @@toPrimitive case
1760// and the second argument - flag - preferred type is a string
1761
1762
1763var _toPrimitive = function (it, S) {
1764 if (!_isObject(it)) return it;
1765 var fn, val;
1766 if (S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) return val;
1767 if (typeof (fn = it.valueOf) == 'function' && !_isObject(val = fn.call(it))) return val;
1768 if (!S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) return val;
1769 throw TypeError("Can't convert object to primitive value");
1770};
1771
1772var dP = Object.defineProperty;
1773var f$1$1 = _descriptors ? Object.defineProperty : function defineProperty(O, P, Attributes) {
1774 _anObject(O);
1775
1776 P = _toPrimitive(P, true);
1777
1778 _anObject(Attributes);
1779
1780 if (_ie8DomDefine) try {
1781 return dP(O, P, Attributes);
1782 } catch (e) {
1783 /* empty */
1784 }
1785 if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');
1786 if ('value' in Attributes) O[P] = Attributes.value;
1787 return O;
1788};
1789var _objectDp = {
1790 f: f$1$1
1791};
1792var defineProperty$3 = _objectDp.f;
1793
1794var _wksDefine = function (name) {
1795 var $Symbol = _core.Symbol || (_core.Symbol = _global.Symbol || {});
1796 if (name.charAt(0) != '_' && !(name in $Symbol)) defineProperty$3($Symbol, name, {
1797 value: _wksExt.f(name)
1798 });
1799};
1800
1801_wksDefine('asyncIterator');
1802
1803var hasOwnProperty$1 = {}.hasOwnProperty;
1804
1805var _has = function (it, key) {
1806 return hasOwnProperty$1.call(it, key);
1807};
1808
1809var _propertyDesc = function (bitmap, value) {
1810 return {
1811 enumerable: !(bitmap & 1),
1812 configurable: !(bitmap & 2),
1813 writable: !(bitmap & 4),
1814 value: value
1815 };
1816};
1817
1818var _hide = _descriptors ? function (object, key, value) {
1819 return _objectDp.f(object, key, _propertyDesc(1, value));
1820} : function (object, key, value) {
1821 object[key] = value;
1822 return object;
1823};
1824
1825var _functionToString = _shared('native-function-to-string', Function.toString);
1826
1827var _redefine = createCommonjsModule$1(function (module) {
1828 var SRC = _uid('src');
1829
1830 var TO_STRING = 'toString';
1831
1832 var TPL = ('' + _functionToString).split(TO_STRING);
1833
1834 _core.inspectSource = function (it) {
1835 return _functionToString.call(it);
1836 };
1837
1838 (module.exports = function (O, key, val, safe) {
1839 var isFunction = typeof val == 'function';
1840 if (isFunction) _has(val, 'name') || _hide(val, 'name', key);
1841 if (O[key] === val) return;
1842 if (isFunction) _has(val, SRC) || _hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));
1843
1844 if (O === _global) {
1845 O[key] = val;
1846 } else if (!safe) {
1847 delete O[key];
1848
1849 _hide(O, key, val);
1850 } else if (O[key]) {
1851 O[key] = val;
1852 } else {
1853 _hide(O, key, val);
1854 } // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
1855
1856 })(Function.prototype, TO_STRING, function toString() {
1857 return typeof this == 'function' && this[SRC] || _functionToString.call(this);
1858 });
1859});
1860
1861var _aFunction = function (it) {
1862 if (typeof it != 'function') throw TypeError(it + ' is not a function!');
1863 return it;
1864};
1865
1866var _ctx = function (fn, that, length) {
1867 _aFunction(fn);
1868
1869 if (that === undefined) return fn;
1870
1871 switch (length) {
1872 case 1:
1873 return function (a) {
1874 return fn.call(that, a);
1875 };
1876
1877 case 2:
1878 return function (a, b) {
1879 return fn.call(that, a, b);
1880 };
1881
1882 case 3:
1883 return function (a, b, c) {
1884 return fn.call(that, a, b, c);
1885 };
1886 }
1887
1888 return function ()
1889 /* ...args */
1890 {
1891 return fn.apply(that, arguments);
1892 };
1893};
1894
1895var PROTOTYPE$1 = 'prototype';
1896
1897var $export = function (type, name, source) {
1898 var IS_FORCED = type & $export.F;
1899 var IS_GLOBAL = type & $export.G;
1900 var IS_STATIC = type & $export.S;
1901 var IS_PROTO = type & $export.P;
1902 var IS_BIND = type & $export.B;
1903 var target = IS_GLOBAL ? _global : IS_STATIC ? _global[name] || (_global[name] = {}) : (_global[name] || {})[PROTOTYPE$1];
1904 var exports = IS_GLOBAL ? _core : _core[name] || (_core[name] = {});
1905 var expProto = exports[PROTOTYPE$1] || (exports[PROTOTYPE$1] = {});
1906 var key, own, out, exp;
1907 if (IS_GLOBAL) source = name;
1908
1909 for (key in source) {
1910 // contains in native
1911 own = !IS_FORCED && target && target[key] !== undefined; // export native or passed
1912
1913 out = (own ? target : source)[key]; // bind timers to global for call from export context
1914
1915 exp = IS_BIND && own ? _ctx(out, _global) : IS_PROTO && typeof out == 'function' ? _ctx(Function.call, out) : out; // extend global
1916
1917 if (target) _redefine(target, key, out, type & $export.U); // export
1918
1919 if (exports[key] != out) _hide(exports, key, exp);
1920 if (IS_PROTO && expProto[key] != out) expProto[key] = out;
1921 }
1922};
1923
1924_global.core = _core; // type bitmap
1925
1926$export.F = 1; // forced
1927
1928$export.G = 2; // global
1929
1930$export.S = 4; // static
1931
1932$export.P = 8; // proto
1933
1934$export.B = 16; // bind
1935
1936$export.W = 32; // wrap
1937
1938$export.U = 64; // safe
1939
1940$export.R = 128; // real proto method for `library`
1941
1942var _export$1 = $export;
1943
1944var _meta = createCommonjsModule$1(function (module) {
1945 var META = _uid('meta');
1946
1947 var setDesc = _objectDp.f;
1948 var id = 0;
1949
1950 var isExtensible = Object.isExtensible || function () {
1951 return true;
1952 };
1953
1954 var FREEZE = !_fails(function () {
1955 return isExtensible(Object.preventExtensions({}));
1956 });
1957
1958 var setMeta = function (it) {
1959 setDesc(it, META, {
1960 value: {
1961 i: 'O' + ++id,
1962 // object ID
1963 w: {} // weak collections IDs
1964
1965 }
1966 });
1967 };
1968
1969 var fastKey = function (it, create) {
1970 // return primitive with prefix
1971 if (!_isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
1972
1973 if (!_has(it, META)) {
1974 // can't set metadata to uncaught frozen object
1975 if (!isExtensible(it)) return 'F'; // not necessary to add metadata
1976
1977 if (!create) return 'E'; // add missing metadata
1978
1979 setMeta(it); // return object ID
1980 }
1981
1982 return it[META].i;
1983 };
1984
1985 var getWeak = function (it, create) {
1986 if (!_has(it, META)) {
1987 // can't set metadata to uncaught frozen object
1988 if (!isExtensible(it)) return true; // not necessary to add metadata
1989
1990 if (!create) return false; // add missing metadata
1991
1992 setMeta(it); // return hash weak collections IDs
1993 }
1994
1995 return it[META].w;
1996 }; // add metadata on freeze-family methods calling
1997
1998
1999 var onFreeze = function (it) {
2000 if (FREEZE && meta.NEED && isExtensible(it) && !_has(it, META)) setMeta(it);
2001 return it;
2002 };
2003
2004 var meta = module.exports = {
2005 KEY: META,
2006 NEED: false,
2007 fastKey: fastKey,
2008 getWeak: getWeak,
2009 onFreeze: onFreeze
2010 };
2011});
2012
2013var _meta_1 = _meta.KEY;
2014var _meta_2 = _meta.NEED;
2015var _meta_3 = _meta.fastKey;
2016var _meta_4 = _meta.getWeak;
2017var _meta_5 = _meta.onFreeze;
2018var def = _objectDp.f;
2019
2020var TAG = _wks('toStringTag');
2021
2022var _setToStringTag = function (it, tag, stat) {
2023 if (it && !_has(it = stat ? it : it.prototype, TAG)) def(it, TAG, {
2024 configurable: true,
2025 value: tag
2026 });
2027};
2028
2029var toString$1 = {}.toString;
2030
2031var _cof = function (it) {
2032 return toString$1.call(it).slice(8, -1);
2033}; // eslint-disable-next-line no-prototype-builtins
2034
2035
2036var _iobject = Object('z').propertyIsEnumerable(0) ? Object : function (it) {
2037 return _cof(it) == 'String' ? it.split('') : Object(it);
2038}; // 7.2.1 RequireObjectCoercible(argument)
2039
2040
2041var _defined = function (it) {
2042 if (it == undefined) throw TypeError("Can't call method on " + it);
2043 return it;
2044};
2045
2046var _toIobject = function (it) {
2047 return _iobject(_defined(it));
2048}; // 7.1.4 ToInteger
2049
2050
2051var ceil$1 = Math.ceil;
2052var floor$2 = Math.floor;
2053
2054var _toInteger = function (it) {
2055 return isNaN(it = +it) ? 0 : (it > 0 ? floor$2 : ceil$1)(it);
2056};
2057
2058var min$2 = Math.min;
2059
2060var _toLength = function (it) {
2061 return it > 0 ? min$2(_toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991
2062};
2063
2064var max$1 = Math.max;
2065var min$1$1 = Math.min;
2066
2067var _toAbsoluteIndex = function (index, length) {
2068 index = _toInteger(index);
2069 return index < 0 ? max$1(index + length, 0) : min$1$1(index, length);
2070}; // true -> Array#includes
2071
2072
2073var _arrayIncludes = function (IS_INCLUDES) {
2074 return function ($this, el, fromIndex) {
2075 var O = _toIobject($this);
2076
2077 var length = _toLength(O.length);
2078
2079 var index = _toAbsoluteIndex(fromIndex, length);
2080
2081 var value; // Array#includes uses SameValueZero equality algorithm
2082 // eslint-disable-next-line no-self-compare
2083
2084 if (IS_INCLUDES && el != el) while (length > index) {
2085 value = O[index++]; // eslint-disable-next-line no-self-compare
2086
2087 if (value != value) return true; // Array#indexOf ignores holes, Array#includes - not
2088 } else for (; length > index; index++) if (IS_INCLUDES || index in O) {
2089 if (O[index] === el) return IS_INCLUDES || index || 0;
2090 }
2091 return !IS_INCLUDES && -1;
2092 };
2093};
2094
2095var shared$1 = _shared('keys');
2096
2097var _sharedKey = function (key) {
2098 return shared$1[key] || (shared$1[key] = _uid(key));
2099};
2100
2101var arrayIndexOf = _arrayIncludes(false);
2102
2103var IE_PROTO$1 = _sharedKey('IE_PROTO');
2104
2105var _objectKeysInternal = function (object, names) {
2106 var O = _toIobject(object);
2107
2108 var i = 0;
2109 var result = [];
2110 var key;
2111
2112 for (key in O) if (key != IE_PROTO$1) _has(O, key) && result.push(key); // Don't enum bug & hidden keys
2113
2114
2115 while (names.length > i) if (_has(O, key = names[i++])) {
2116 ~arrayIndexOf(result, key) || result.push(key);
2117 }
2118
2119 return result;
2120}; // IE 8- don't enum bug keys
2121
2122
2123var _enumBugKeys = 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'.split(',');
2124
2125var _objectKeys = Object.keys || function keys(O) {
2126 return _objectKeysInternal(O, _enumBugKeys);
2127};
2128
2129var f$2$1 = Object.getOwnPropertySymbols;
2130var _objectGops = {
2131 f: f$2$1
2132};
2133var f$3$1 = {}.propertyIsEnumerable;
2134var _objectPie = {
2135 f: f$3$1
2136};
2137
2138var _enumKeys = function (it) {
2139 var result = _objectKeys(it);
2140
2141 var getSymbols = _objectGops.f;
2142
2143 if (getSymbols) {
2144 var symbols = getSymbols(it);
2145 var isEnum = _objectPie.f;
2146 var i = 0;
2147 var key;
2148
2149 while (symbols.length > i) if (isEnum.call(it, key = symbols[i++])) result.push(key);
2150 }
2151
2152 return result;
2153};
2154
2155var _isArray = Array.isArray || function isArray(arg) {
2156 return _cof(arg) == 'Array';
2157};
2158
2159var _toObject = function (it) {
2160 return Object(_defined(it));
2161};
2162
2163var _objectDps = _descriptors ? Object.defineProperties : function defineProperties(O, Properties) {
2164 _anObject(O);
2165
2166 var keys = _objectKeys(Properties);
2167
2168 var length = keys.length;
2169 var i = 0;
2170 var P;
2171
2172 while (length > i) _objectDp.f(O, P = keys[i++], Properties[P]);
2173
2174 return O;
2175};
2176
2177var document$2 = _global.document;
2178
2179var _html = document$2 && document$2.documentElement;
2180
2181var IE_PROTO$1$1 = _sharedKey('IE_PROTO');
2182
2183var Empty = function () {
2184 /* empty */
2185};
2186
2187var PROTOTYPE$1$1 = 'prototype'; // Create object with fake `null` prototype: use iframe Object with cleared prototype
2188
2189var createDict = function () {
2190 // Thrash, waste and sodomy: IE GC bug
2191 var iframe = _domCreate('iframe');
2192
2193 var i = _enumBugKeys.length;
2194 var lt = '<';
2195 var gt = '>';
2196 var iframeDocument;
2197 iframe.style.display = 'none';
2198
2199 _html.appendChild(iframe);
2200
2201 iframe.src = 'javascript:'; // eslint-disable-line no-script-url
2202 // createDict = iframe.contentWindow.Object;
2203 // html.removeChild(iframe);
2204
2205 iframeDocument = iframe.contentWindow.document;
2206 iframeDocument.open();
2207 iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);
2208 iframeDocument.close();
2209 createDict = iframeDocument.F;
2210
2211 while (i--) delete createDict[PROTOTYPE$1$1][_enumBugKeys[i]];
2212
2213 return createDict();
2214};
2215
2216var _objectCreate = Object.create || function create(O, Properties) {
2217 var result;
2218
2219 if (O !== null) {
2220 Empty[PROTOTYPE$1$1] = _anObject(O);
2221 result = new Empty();
2222 Empty[PROTOTYPE$1$1] = null; // add "__proto__" for Object.getPrototypeOf polyfill
2223
2224 result[IE_PROTO$1$1] = O;
2225 } else result = createDict();
2226
2227 return Properties === undefined ? result : _objectDps(result, Properties);
2228};
2229
2230var hiddenKeys$2 = _enumBugKeys.concat('length', 'prototype');
2231
2232var f$4$1 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
2233 return _objectKeysInternal(O, hiddenKeys$2);
2234};
2235
2236var _objectGopn = {
2237 f: f$4$1
2238};
2239var gOPN = _objectGopn.f;
2240var toString$1$1 = {}.toString;
2241var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames ? Object.getOwnPropertyNames(window) : [];
2242
2243var getWindowNames = function (it) {
2244 try {
2245 return gOPN(it);
2246 } catch (e) {
2247 return windowNames.slice();
2248 }
2249};
2250
2251var f$5$1 = function getOwnPropertyNames(it) {
2252 return windowNames && toString$1$1.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(_toIobject(it));
2253};
2254
2255var _objectGopnExt = {
2256 f: f$5$1
2257};
2258var gOPD = Object.getOwnPropertyDescriptor;
2259var f$6 = _descriptors ? gOPD : function getOwnPropertyDescriptor(O, P) {
2260 O = _toIobject(O);
2261 P = _toPrimitive(P, true);
2262 if (_ie8DomDefine) try {
2263 return gOPD(O, P);
2264 } catch (e) {
2265 /* empty */
2266 }
2267 if (_has(O, P)) return _propertyDesc(!_objectPie.f.call(O, P), O[P]);
2268};
2269var _objectGopd = {
2270 f: f$6
2271};
2272var META = _meta.KEY;
2273var gOPD$1 = _objectGopd.f;
2274var dP$1 = _objectDp.f;
2275var gOPN$1 = _objectGopnExt.f;
2276var $Symbol = _global.Symbol;
2277var $JSON = _global.JSON;
2278
2279var _stringify = $JSON && $JSON.stringify;
2280
2281var PROTOTYPE$2 = 'prototype';
2282
2283var HIDDEN = _wks('_hidden');
2284
2285var TO_PRIMITIVE = _wks('toPrimitive');
2286
2287var isEnum = {}.propertyIsEnumerable;
2288
2289var SymbolRegistry = _shared('symbol-registry');
2290
2291var AllSymbols = _shared('symbols');
2292
2293var OPSymbols = _shared('op-symbols');
2294
2295var ObjectProto = Object[PROTOTYPE$2];
2296var USE_NATIVE = typeof $Symbol == 'function' && !!_objectGops.f;
2297var QObject = _global.QObject; // Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173
2298
2299var setter = !QObject || !QObject[PROTOTYPE$2] || !QObject[PROTOTYPE$2].findChild; // fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687
2300
2301var setSymbolDesc = _descriptors && _fails(function () {
2302 return _objectCreate(dP$1({}, 'a', {
2303 get: function () {
2304 return dP$1(this, 'a', {
2305 value: 7
2306 }).a;
2307 }
2308 })).a != 7;
2309}) ? function (it, key, D) {
2310 var protoDesc = gOPD$1(ObjectProto, key);
2311 if (protoDesc) delete ObjectProto[key];
2312 dP$1(it, key, D);
2313 if (protoDesc && it !== ObjectProto) dP$1(ObjectProto, key, protoDesc);
2314} : dP$1;
2315
2316var wrap = function (tag) {
2317 var sym = AllSymbols[tag] = _objectCreate($Symbol[PROTOTYPE$2]);
2318
2319 sym._k = tag;
2320 return sym;
2321};
2322
2323var isSymbol = USE_NATIVE && typeof $Symbol.iterator == 'symbol' ? function (it) {
2324 return typeof it == 'symbol';
2325} : function (it) {
2326 return it instanceof $Symbol;
2327};
2328
2329var $defineProperty = function defineProperty(it, key, D) {
2330 if (it === ObjectProto) $defineProperty(OPSymbols, key, D);
2331
2332 _anObject(it);
2333
2334 key = _toPrimitive(key, true);
2335
2336 _anObject(D);
2337
2338 if (_has(AllSymbols, key)) {
2339 if (!D.enumerable) {
2340 if (!_has(it, HIDDEN)) dP$1(it, HIDDEN, _propertyDesc(1, {}));
2341 it[HIDDEN][key] = true;
2342 } else {
2343 if (_has(it, HIDDEN) && it[HIDDEN][key]) it[HIDDEN][key] = false;
2344 D = _objectCreate(D, {
2345 enumerable: _propertyDesc(0, false)
2346 });
2347 }
2348
2349 return setSymbolDesc(it, key, D);
2350 }
2351
2352 return dP$1(it, key, D);
2353};
2354
2355var $defineProperties = function defineProperties(it, P) {
2356 _anObject(it);
2357
2358 var keys = _enumKeys(P = _toIobject(P));
2359
2360 var i = 0;
2361 var l = keys.length;
2362 var key;
2363
2364 while (l > i) $defineProperty(it, key = keys[i++], P[key]);
2365
2366 return it;
2367};
2368
2369var $create = function create(it, P) {
2370 return P === undefined ? _objectCreate(it) : $defineProperties(_objectCreate(it), P);
2371};
2372
2373var $propertyIsEnumerable = function propertyIsEnumerable(key) {
2374 var E = isEnum.call(this, key = _toPrimitive(key, true));
2375 if (this === ObjectProto && _has(AllSymbols, key) && !_has(OPSymbols, key)) return false;
2376 return E || !_has(this, key) || !_has(AllSymbols, key) || _has(this, HIDDEN) && this[HIDDEN][key] ? E : true;
2377};
2378
2379var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key) {
2380 it = _toIobject(it);
2381 key = _toPrimitive(key, true);
2382 if (it === ObjectProto && _has(AllSymbols, key) && !_has(OPSymbols, key)) return;
2383 var D = gOPD$1(it, key);
2384 if (D && _has(AllSymbols, key) && !(_has(it, HIDDEN) && it[HIDDEN][key])) D.enumerable = true;
2385 return D;
2386};
2387
2388var $getOwnPropertyNames = function getOwnPropertyNames(it) {
2389 var names = gOPN$1(_toIobject(it));
2390 var result = [];
2391 var i = 0;
2392 var key;
2393
2394 while (names.length > i) {
2395 if (!_has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META) result.push(key);
2396 }
2397
2398 return result;
2399};
2400
2401var $getOwnPropertySymbols = function getOwnPropertySymbols(it) {
2402 var IS_OP = it === ObjectProto;
2403 var names = gOPN$1(IS_OP ? OPSymbols : _toIobject(it));
2404 var result = [];
2405 var i = 0;
2406 var key;
2407
2408 while (names.length > i) {
2409 if (_has(AllSymbols, key = names[i++]) && (IS_OP ? _has(ObjectProto, key) : true)) result.push(AllSymbols[key]);
2410 }
2411
2412 return result;
2413}; // 19.4.1.1 Symbol([description])
2414
2415
2416if (!USE_NATIVE) {
2417 $Symbol = function Symbol() {
2418 if (this instanceof $Symbol) throw TypeError('Symbol is not a constructor!');
2419
2420 var tag = _uid(arguments.length > 0 ? arguments[0] : undefined);
2421
2422 var $set = function (value) {
2423 if (this === ObjectProto) $set.call(OPSymbols, value);
2424 if (_has(this, HIDDEN) && _has(this[HIDDEN], tag)) this[HIDDEN][tag] = false;
2425 setSymbolDesc(this, tag, _propertyDesc(1, value));
2426 };
2427
2428 if (_descriptors && setter) setSymbolDesc(ObjectProto, tag, {
2429 configurable: true,
2430 set: $set
2431 });
2432 return wrap(tag);
2433 };
2434
2435 _redefine($Symbol[PROTOTYPE$2], 'toString', function toString() {
2436 return this._k;
2437 });
2438
2439 _objectGopd.f = $getOwnPropertyDescriptor;
2440 _objectDp.f = $defineProperty;
2441 _objectGopn.f = _objectGopnExt.f = $getOwnPropertyNames;
2442 _objectPie.f = $propertyIsEnumerable;
2443 _objectGops.f = $getOwnPropertySymbols;
2444
2445 if (_descriptors && !_library) {
2446 _redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true);
2447 }
2448
2449 _wksExt.f = function (name) {
2450 return wrap(_wks(name));
2451 };
2452}
2453
2454_export$1(_export$1.G + _export$1.W + _export$1.F * !USE_NATIVE, {
2455 Symbol: $Symbol
2456});
2457
2458for (var es6Symbols = // 19.4.2.2, 19.4.2.3, 19.4.2.4, 19.4.2.6, 19.4.2.8, 19.4.2.9, 19.4.2.10, 19.4.2.11, 19.4.2.12, 19.4.2.13, 19.4.2.14
2459'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables'.split(','), j$1 = 0; es6Symbols.length > j$1;) _wks(es6Symbols[j$1++]);
2460
2461for (var wellKnownSymbols = _objectKeys(_wks.store), k = 0; wellKnownSymbols.length > k;) _wksDefine(wellKnownSymbols[k++]);
2462
2463_export$1(_export$1.S + _export$1.F * !USE_NATIVE, 'Symbol', {
2464 // 19.4.2.1 Symbol.for(key)
2465 'for': function (key) {
2466 return _has(SymbolRegistry, key += '') ? SymbolRegistry[key] : SymbolRegistry[key] = $Symbol(key);
2467 },
2468 // 19.4.2.5 Symbol.keyFor(sym)
2469 keyFor: function keyFor(sym) {
2470 if (!isSymbol(sym)) throw TypeError(sym + ' is not a symbol!');
2471
2472 for (var key in SymbolRegistry) if (SymbolRegistry[key] === sym) return key;
2473 },
2474 useSetter: function () {
2475 setter = true;
2476 },
2477 useSimple: function () {
2478 setter = false;
2479 }
2480});
2481
2482_export$1(_export$1.S + _export$1.F * !USE_NATIVE, 'Object', {
2483 // 19.1.2.2 Object.create(O [, Properties])
2484 create: $create,
2485 // 19.1.2.4 Object.defineProperty(O, P, Attributes)
2486 defineProperty: $defineProperty,
2487 // 19.1.2.3 Object.defineProperties(O, Properties)
2488 defineProperties: $defineProperties,
2489 // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)
2490 getOwnPropertyDescriptor: $getOwnPropertyDescriptor,
2491 // 19.1.2.7 Object.getOwnPropertyNames(O)
2492 getOwnPropertyNames: $getOwnPropertyNames,
2493 // 19.1.2.8 Object.getOwnPropertySymbols(O)
2494 getOwnPropertySymbols: $getOwnPropertySymbols
2495}); // Chrome 38 and 39 `Object.getOwnPropertySymbols` fails on primitives
2496// https://bugs.chromium.org/p/v8/issues/detail?id=3443
2497
2498
2499var FAILS_ON_PRIMITIVES = _fails(function () {
2500 _objectGops.f(1);
2501});
2502
2503_export$1(_export$1.S + _export$1.F * FAILS_ON_PRIMITIVES, 'Object', {
2504 getOwnPropertySymbols: function getOwnPropertySymbols(it) {
2505 return _objectGops.f(_toObject(it));
2506 }
2507}); // 24.3.2 JSON.stringify(value [, replacer [, space]])
2508
2509
2510$JSON && _export$1(_export$1.S + _export$1.F * (!USE_NATIVE || _fails(function () {
2511 var S = $Symbol(); // MS Edge converts symbol values to JSON as {}
2512 // WebKit converts symbol values to JSON as null
2513 // V8 throws on boxed symbols
2514
2515 return _stringify([S]) != '[null]' || _stringify({
2516 a: S
2517 }) != '{}' || _stringify(Object(S)) != '{}';
2518})), 'JSON', {
2519 stringify: function stringify(it) {
2520 var args = [it];
2521 var i = 1;
2522 var replacer, $replacer;
2523
2524 while (arguments.length > i) args.push(arguments[i++]);
2525
2526 $replacer = replacer = args[1];
2527 if (!_isObject(replacer) && it === undefined || isSymbol(it)) return; // IE8 returns string on undefined
2528
2529 if (!_isArray(replacer)) replacer = function (key, value) {
2530 if (typeof $replacer == 'function') value = $replacer.call(this, key, value);
2531 if (!isSymbol(value)) return value;
2532 };
2533 args[1] = replacer;
2534 return _stringify.apply($JSON, args);
2535 }
2536}); // 19.4.3.4 Symbol.prototype[@@toPrimitive](hint)
2537
2538$Symbol[PROTOTYPE$2][TO_PRIMITIVE] || _hide($Symbol[PROTOTYPE$2], TO_PRIMITIVE, $Symbol[PROTOTYPE$2].valueOf); // 19.4.3.5 Symbol.prototype[@@toStringTag]
2539
2540_setToStringTag($Symbol, 'Symbol'); // 20.2.1.9 Math[@@toStringTag]
2541
2542
2543_setToStringTag(Math, 'Math', true); // 24.3.3 JSON[@@toStringTag]
2544
2545
2546_setToStringTag(_global.JSON, 'JSON', true);
2547
2548function _typeof(obj) {
2549 if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
2550 _typeof = function (obj) {
2551 return typeof obj;
2552 };
2553 } else {
2554 _typeof = function (obj) {
2555 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
2556 };
2557 }
2558
2559 return _typeof(obj);
2560}
2561
2562function _defineProperty(obj, key, value) {
2563 if (key in obj) {
2564 Object.defineProperty(obj, key, {
2565 value: value,
2566 enumerable: true,
2567 configurable: true,
2568 writable: true
2569 });
2570 } else {
2571 obj[key] = value;
2572 }
2573
2574 return obj;
2575}
2576
2577function ownKeys$1(object, enumerableOnly) {
2578 var keys = Object.keys(object);
2579
2580 if (Object.getOwnPropertySymbols) {
2581 var symbols = Object.getOwnPropertySymbols(object);
2582 if (enumerableOnly) symbols = symbols.filter(function (sym) {
2583 return Object.getOwnPropertyDescriptor(object, sym).enumerable;
2584 });
2585 keys.push.apply(keys, symbols);
2586 }
2587
2588 return keys;
2589}
2590
2591function _objectSpread2(target) {
2592 for (var i = 1; i < arguments.length; i++) {
2593 var source = arguments[i] != null ? arguments[i] : {};
2594
2595 if (i % 2) {
2596 ownKeys$1(source, true).forEach(function (key) {
2597 _defineProperty(target, key, source[key]);
2598 });
2599 } else if (Object.getOwnPropertyDescriptors) {
2600 Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
2601 } else {
2602 ownKeys$1(source).forEach(function (key) {
2603 Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
2604 });
2605 }
2606 }
2607
2608 return target;
2609}
2610
2611function _toConsumableArray(arr) {
2612 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
2613}
2614
2615function _arrayWithoutHoles(arr) {
2616 if (Array.isArray(arr)) {
2617 for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
2618
2619 return arr2;
2620 }
2621}
2622
2623function _iterableToArray(iter) {
2624 if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
2625}
2626
2627function _nonIterableSpread() {
2628 throw new TypeError("Invalid attempt to spread non-iterable instance");
2629}
2630
2631var _objectSap = function (KEY, exec) {
2632 var fn = (_core.Object || {})[KEY] || Object[KEY];
2633 var exp = {};
2634 exp[KEY] = exec(fn);
2635
2636 _export$1(_export$1.S + _export$1.F * _fails(function () {
2637 fn(1);
2638 }), 'Object', exp);
2639};
2640
2641_objectSap('keys', function () {
2642 return function keys(it) {
2643 return _objectKeys(_toObject(it));
2644 };
2645});
2646
2647var _flags = function () {
2648 var that = _anObject(this);
2649
2650 var result = '';
2651 if (that.global) result += 'g';
2652 if (that.ignoreCase) result += 'i';
2653 if (that.multiline) result += 'm';
2654 if (that.unicode) result += 'u';
2655 if (that.sticky) result += 'y';
2656 return result;
2657};
2658
2659if (_descriptors && /./g.flags != 'g') _objectDp.f(RegExp.prototype, 'flags', {
2660 configurable: true,
2661 get: _flags
2662});
2663var TO_STRING = 'toString';
2664var $toString = /./[TO_STRING];
2665
2666var define = function (fn) {
2667 _redefine(RegExp.prototype, TO_STRING, fn, true);
2668}; // 21.2.5.14 RegExp.prototype.toString()
2669
2670
2671if (_fails(function () {
2672 return $toString.call({
2673 source: 'a',
2674 flags: 'b'
2675 }) != '/a/b';
2676})) {
2677 define(function toString() {
2678 var R = _anObject(this);
2679
2680 return '/'.concat(R.source, '/', 'flags' in R ? R.flags : !_descriptors && R instanceof RegExp ? _flags.call(R) : undefined);
2681 }); // FF44- RegExp#toString has a wrong name
2682} else if ($toString.name != TO_STRING) {
2683 define(function toString() {
2684 return $toString.call(this);
2685 });
2686} // false -> String#codePointAt
2687
2688
2689var _stringAt = function (TO_STRING) {
2690 return function (that, pos) {
2691 var s = String(_defined(that));
2692
2693 var i = _toInteger(pos);
2694
2695 var l = s.length;
2696 var a, b;
2697 if (i < 0 || i >= l) return TO_STRING ? '' : undefined;
2698 a = s.charCodeAt(i);
2699 return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff ? TO_STRING ? s.charAt(i) : a : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;
2700 };
2701};
2702
2703var at = _stringAt(true); // `AdvanceStringIndex` abstract operation
2704// https://tc39.github.io/ecma262/#sec-advancestringindex
2705
2706
2707var _advanceStringIndex = function (S, index, unicode) {
2708 return index + (unicode ? at(S, index).length : 1);
2709};
2710
2711var TAG$1 = _wks('toStringTag'); // ES3 wrong here
2712
2713
2714var ARG = _cof(function () {
2715 return arguments;
2716}()) == 'Arguments'; // fallback for IE11 Script Access Denied error
2717
2718var tryGet$1 = function (it, key) {
2719 try {
2720 return it[key];
2721 } catch (e) {
2722 /* empty */
2723 }
2724};
2725
2726var _classof = function (it) {
2727 var O, T, B;
2728 return it === undefined ? 'Undefined' : it === null ? 'Null' // @@toStringTag case
2729 : typeof (T = tryGet$1(O = Object(it), TAG$1)) == 'string' ? T // builtinTag case
2730 : ARG ? _cof(O) // ES3 arguments fallback
2731 : (B = _cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;
2732};
2733
2734var builtinExec = RegExp.prototype.exec; // `RegExpExec` abstract operation
2735// https://tc39.github.io/ecma262/#sec-regexpexec
2736
2737var _regexpExecAbstract = function (R, S) {
2738 var exec = R.exec;
2739
2740 if (typeof exec === 'function') {
2741 var result = exec.call(R, S);
2742
2743 if (typeof result !== 'object') {
2744 throw new TypeError('RegExp exec method returned something other than an Object or null');
2745 }
2746
2747 return result;
2748 }
2749
2750 if (_classof(R) !== 'RegExp') {
2751 throw new TypeError('RegExp#exec called on incompatible receiver');
2752 }
2753
2754 return builtinExec.call(R, S);
2755};
2756
2757var nativeExec = RegExp.prototype.exec; // This always refers to the native implementation, because the
2758// String#replace polyfill uses ./fix-regexp-well-known-symbol-logic.js,
2759// which loads this file before patching the method.
2760
2761var nativeReplace = String.prototype.replace;
2762var patchedExec = nativeExec;
2763var LAST_INDEX = 'lastIndex';
2764
2765var UPDATES_LAST_INDEX_WRONG = function () {
2766 var re1 = /a/,
2767 re2 = /b*/g;
2768 nativeExec.call(re1, 'a');
2769 nativeExec.call(re2, 'a');
2770 return re1[LAST_INDEX] !== 0 || re2[LAST_INDEX] !== 0;
2771}(); // nonparticipating capturing group, copied from es5-shim's String#split patch.
2772
2773
2774var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;
2775var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED;
2776
2777if (PATCH) {
2778 patchedExec = function exec(str) {
2779 var re = this;
2780 var lastIndex, reCopy, match, i;
2781
2782 if (NPCG_INCLUDED) {
2783 reCopy = new RegExp('^' + re.source + '$(?!\\s)', _flags.call(re));
2784 }
2785
2786 if (UPDATES_LAST_INDEX_WRONG) lastIndex = re[LAST_INDEX];
2787 match = nativeExec.call(re, str);
2788
2789 if (UPDATES_LAST_INDEX_WRONG && match) {
2790 re[LAST_INDEX] = re.global ? match.index + match[0].length : lastIndex;
2791 }
2792
2793 if (NPCG_INCLUDED && match && match.length > 1) {
2794 // Fix browsers whose `exec` methods don't consistently return `undefined`
2795 // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/
2796 // eslint-disable-next-line no-loop-func
2797 nativeReplace.call(match[0], reCopy, function () {
2798 for (i = 1; i < arguments.length - 2; i++) {
2799 if (arguments[i] === undefined) match[i] = undefined;
2800 }
2801 });
2802 }
2803
2804 return match;
2805 };
2806}
2807
2808var _regexpExec = patchedExec;
2809
2810_export$1({
2811 target: 'RegExp',
2812 proto: true,
2813 forced: _regexpExec !== /./.exec
2814}, {
2815 exec: _regexpExec
2816});
2817
2818var SPECIES$1 = _wks('species');
2819
2820var REPLACE_SUPPORTS_NAMED_GROUPS = !_fails(function () {
2821 // #replace needs built-in support for named groups.
2822 // #match works fine because it just return the exec results, even if it has
2823 // a "grops" property.
2824 var re = /./;
2825
2826 re.exec = function () {
2827 var result = [];
2828 result.groups = {
2829 a: '7'
2830 };
2831 return result;
2832 };
2833
2834 return ''.replace(re, '$<a>') !== '7';
2835});
2836
2837var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = function () {
2838 // Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec
2839 var re = /(?:)/;
2840 var originalExec = re.exec;
2841
2842 re.exec = function () {
2843 return originalExec.apply(this, arguments);
2844 };
2845
2846 var result = 'ab'.split(re);
2847 return result.length === 2 && result[0] === 'a' && result[1] === 'b';
2848}();
2849
2850var _fixReWks = function (KEY, length, exec) {
2851 var SYMBOL = _wks(KEY);
2852
2853 var DELEGATES_TO_SYMBOL = !_fails(function () {
2854 // String methods call symbol-named RegEp methods
2855 var O = {};
2856
2857 O[SYMBOL] = function () {
2858 return 7;
2859 };
2860
2861 return ''[KEY](O) != 7;
2862 });
2863 var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL ? !_fails(function () {
2864 // Symbol-named RegExp methods call .exec
2865 var execCalled = false;
2866 var re = /a/;
2867
2868 re.exec = function () {
2869 execCalled = true;
2870 return null;
2871 };
2872
2873 if (KEY === 'split') {
2874 // RegExp[@@split] doesn't call the regex's exec method, but first creates
2875 // a new one. We need to return the patched regex when creating the new one.
2876 re.constructor = {};
2877
2878 re.constructor[SPECIES$1] = function () {
2879 return re;
2880 };
2881 }
2882
2883 re[SYMBOL]('');
2884 return !execCalled;
2885 }) : undefined;
2886
2887 if (!DELEGATES_TO_SYMBOL || !DELEGATES_TO_EXEC || KEY === 'replace' && !REPLACE_SUPPORTS_NAMED_GROUPS || KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC) {
2888 var nativeRegExpMethod = /./[SYMBOL];
2889 var fns = exec(_defined, SYMBOL, ''[KEY], function maybeCallNative(nativeMethod, regexp, str, arg2, forceStringMethod) {
2890 if (regexp.exec === _regexpExec) {
2891 if (DELEGATES_TO_SYMBOL && !forceStringMethod) {
2892 // The native String method already delegates to @@method (this
2893 // polyfilled function), leasing to infinite recursion.
2894 // We avoid it by directly calling the native @@method method.
2895 return {
2896 done: true,
2897 value: nativeRegExpMethod.call(regexp, str, arg2)
2898 };
2899 }
2900
2901 return {
2902 done: true,
2903 value: nativeMethod.call(str, regexp, arg2)
2904 };
2905 }
2906
2907 return {
2908 done: false
2909 };
2910 });
2911 var strfn = fns[0];
2912 var rxfn = fns[1];
2913
2914 _redefine(String.prototype, KEY, strfn);
2915
2916 _hide(RegExp.prototype, SYMBOL, length == 2 // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)
2917 // 21.2.5.11 RegExp.prototype[@@split](string, limit)
2918 ? function (string, arg) {
2919 return rxfn.call(string, this, arg);
2920 } // 21.2.5.6 RegExp.prototype[@@match](string)
2921 // 21.2.5.9 RegExp.prototype[@@search](string)
2922 : function (string) {
2923 return rxfn.call(string, this);
2924 });
2925 }
2926};
2927
2928var max$1$1 = Math.max;
2929var min$2$1 = Math.min;
2930var floor$1$1 = Math.floor;
2931var SUBSTITUTION_SYMBOLS = /\$([$&`']|\d\d?|<[^>]*>)/g;
2932var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&`']|\d\d?)/g;
2933
2934var maybeToString = function (it) {
2935 return it === undefined ? it : String(it);
2936}; // @@replace logic
2937
2938
2939_fixReWks('replace', 2, function (defined, REPLACE, $replace, maybeCallNative) {
2940 return [// `String.prototype.replace` method
2941 // https://tc39.github.io/ecma262/#sec-string.prototype.replace
2942 function replace(searchValue, replaceValue) {
2943 var O = defined(this);
2944 var fn = searchValue == undefined ? undefined : searchValue[REPLACE];
2945 return fn !== undefined ? fn.call(searchValue, O, replaceValue) : $replace.call(String(O), searchValue, replaceValue);
2946 }, // `RegExp.prototype[@@replace]` method
2947 // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@replace
2948 function (regexp, replaceValue) {
2949 var res = maybeCallNative($replace, regexp, this, replaceValue);
2950 if (res.done) return res.value;
2951
2952 var rx = _anObject(regexp);
2953
2954 var S = String(this);
2955 var functionalReplace = typeof replaceValue === 'function';
2956 if (!functionalReplace) replaceValue = String(replaceValue);
2957 var global = rx.global;
2958
2959 if (global) {
2960 var fullUnicode = rx.unicode;
2961 rx.lastIndex = 0;
2962 }
2963
2964 var results = [];
2965
2966 while (true) {
2967 var result = _regexpExecAbstract(rx, S);
2968
2969 if (result === null) break;
2970 results.push(result);
2971 if (!global) break;
2972 var matchStr = String(result[0]);
2973 if (matchStr === '') rx.lastIndex = _advanceStringIndex(S, _toLength(rx.lastIndex), fullUnicode);
2974 }
2975
2976 var accumulatedResult = '';
2977 var nextSourcePosition = 0;
2978
2979 for (var i = 0; i < results.length; i++) {
2980 result = results[i];
2981 var matched = String(result[0]);
2982 var position = max$1$1(min$2$1(_toInteger(result.index), S.length), 0);
2983 var captures = []; // NOTE: This is equivalent to
2984 // captures = result.slice(1).map(maybeToString)
2985 // but for some reason `nativeSlice.call(result, 1, result.length)` (called in
2986 // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and
2987 // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it.
2988
2989 for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j]));
2990
2991 var namedCaptures = result.groups;
2992
2993 if (functionalReplace) {
2994 var replacerArgs = [matched].concat(captures, position, S);
2995 if (namedCaptures !== undefined) replacerArgs.push(namedCaptures);
2996 var replacement = String(replaceValue.apply(undefined, replacerArgs));
2997 } else {
2998 replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue);
2999 }
3000
3001 if (position >= nextSourcePosition) {
3002 accumulatedResult += S.slice(nextSourcePosition, position) + replacement;
3003 nextSourcePosition = position + matched.length;
3004 }
3005 }
3006
3007 return accumulatedResult + S.slice(nextSourcePosition);
3008 }]; // https://tc39.github.io/ecma262/#sec-getsubstitution
3009
3010 function getSubstitution(matched, str, position, captures, namedCaptures, replacement) {
3011 var tailPos = position + matched.length;
3012 var m = captures.length;
3013 var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;
3014
3015 if (namedCaptures !== undefined) {
3016 namedCaptures = _toObject(namedCaptures);
3017 symbols = SUBSTITUTION_SYMBOLS;
3018 }
3019
3020 return $replace.call(replacement, symbols, function (match, ch) {
3021 var capture;
3022
3023 switch (ch.charAt(0)) {
3024 case '$':
3025 return '$';
3026
3027 case '&':
3028 return matched;
3029
3030 case '`':
3031 return str.slice(0, position);
3032
3033 case "'":
3034 return str.slice(tailPos);
3035
3036 case '<':
3037 capture = namedCaptures[ch.slice(1, -1)];
3038 break;
3039
3040 default:
3041 // \d\d?
3042 var n = +ch;
3043 if (n === 0) return match;
3044
3045 if (n > m) {
3046 var f = floor$1$1(n / 10);
3047 if (f === 0) return match;
3048 if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1);
3049 return match;
3050 }
3051
3052 capture = captures[n - 1];
3053 }
3054
3055 return capture === undefined ? '' : capture;
3056 });
3057 }
3058});
3059
3060var UNSCOPABLES = _wks('unscopables');
3061
3062var ArrayProto = Array.prototype;
3063if (ArrayProto[UNSCOPABLES] == undefined) _hide(ArrayProto, UNSCOPABLES, {});
3064
3065var _addToUnscopables = function (key) {
3066 ArrayProto[UNSCOPABLES][key] = true;
3067};
3068
3069var _iterStep = function (done, value) {
3070 return {
3071 value: value,
3072 done: !!done
3073 };
3074};
3075
3076var _iterators = {};
3077var IteratorPrototype = {}; // 25.1.2.1.1 %IteratorPrototype%[@@iterator]()
3078
3079_hide(IteratorPrototype, _wks('iterator'), function () {
3080 return this;
3081});
3082
3083var _iterCreate = function (Constructor, NAME, next) {
3084 Constructor.prototype = _objectCreate(IteratorPrototype, {
3085 next: _propertyDesc(1, next)
3086 });
3087
3088 _setToStringTag(Constructor, NAME + ' Iterator');
3089};
3090
3091var IE_PROTO$2 = _sharedKey('IE_PROTO');
3092
3093var ObjectProto$1 = Object.prototype;
3094
3095var _objectGpo = Object.getPrototypeOf || function (O) {
3096 O = _toObject(O);
3097 if (_has(O, IE_PROTO$2)) return O[IE_PROTO$2];
3098
3099 if (typeof O.constructor == 'function' && O instanceof O.constructor) {
3100 return O.constructor.prototype;
3101 }
3102
3103 return O instanceof Object ? ObjectProto$1 : null;
3104};
3105
3106var ITERATOR = _wks('iterator');
3107
3108var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next`
3109
3110var FF_ITERATOR = '@@iterator';
3111var KEYS = 'keys';
3112var VALUES = 'values';
3113
3114var returnThis = function () {
3115 return this;
3116};
3117
3118var _iterDefine = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {
3119 _iterCreate(Constructor, NAME, next);
3120
3121 var getMethod = function (kind) {
3122 if (!BUGGY && kind in proto) return proto[kind];
3123
3124 switch (kind) {
3125 case KEYS:
3126 return function keys() {
3127 return new Constructor(this, kind);
3128 };
3129
3130 case VALUES:
3131 return function values() {
3132 return new Constructor(this, kind);
3133 };
3134 }
3135
3136 return function entries() {
3137 return new Constructor(this, kind);
3138 };
3139 };
3140
3141 var TAG = NAME + ' Iterator';
3142 var DEF_VALUES = DEFAULT == VALUES;
3143 var VALUES_BUG = false;
3144 var proto = Base.prototype;
3145 var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];
3146 var $default = $native || getMethod(DEFAULT);
3147 var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;
3148 var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;
3149 var methods, key, IteratorPrototype; // Fix native
3150
3151 if ($anyNative) {
3152 IteratorPrototype = _objectGpo($anyNative.call(new Base()));
3153
3154 if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {
3155 // Set @@toStringTag to native iterators
3156 _setToStringTag(IteratorPrototype, TAG, true); // fix for some old engines
3157
3158
3159 if (typeof IteratorPrototype[ITERATOR] != 'function') _hide(IteratorPrototype, ITERATOR, returnThis);
3160 }
3161 } // fix Array#{values, @@iterator}.name in V8 / FF
3162
3163
3164 if (DEF_VALUES && $native && $native.name !== VALUES) {
3165 VALUES_BUG = true;
3166
3167 $default = function values() {
3168 return $native.call(this);
3169 };
3170 } // Define iterator
3171
3172
3173 if (BUGGY || VALUES_BUG || !proto[ITERATOR]) {
3174 _hide(proto, ITERATOR, $default);
3175 } // Plug for library
3176
3177
3178 _iterators[NAME] = $default;
3179 _iterators[TAG] = returnThis;
3180
3181 if (DEFAULT) {
3182 methods = {
3183 values: DEF_VALUES ? $default : getMethod(VALUES),
3184 keys: IS_SET ? $default : getMethod(KEYS),
3185 entries: $entries
3186 };
3187 if (FORCED) for (key in methods) {
3188 if (!(key in proto)) _redefine(proto, key, methods[key]);
3189 } else _export$1(_export$1.P + _export$1.F * (BUGGY || VALUES_BUG), NAME, methods);
3190 }
3191
3192 return methods;
3193}; // 22.1.3.13 Array.prototype.keys()
3194// 22.1.3.29 Array.prototype.values()
3195// 22.1.3.30 Array.prototype[@@iterator]()
3196
3197
3198var es6_array_iterator = _iterDefine(Array, 'Array', function (iterated, kind) {
3199 this._t = _toIobject(iterated); // target
3200
3201 this._i = 0; // next index
3202
3203 this._k = kind; // kind
3204 // 22.1.5.2.1 %ArrayIteratorPrototype%.next()
3205}, function () {
3206 var O = this._t;
3207 var kind = this._k;
3208 var index = this._i++;
3209
3210 if (!O || index >= O.length) {
3211 this._t = undefined;
3212 return _iterStep(1);
3213 }
3214
3215 if (kind == 'keys') return _iterStep(0, index);
3216 if (kind == 'values') return _iterStep(0, O[index]);
3217 return _iterStep(0, [index, O[index]]);
3218}, 'values'); // argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7)
3219
3220
3221_iterators.Arguments = _iterators.Array;
3222
3223_addToUnscopables('keys');
3224
3225_addToUnscopables('values');
3226
3227_addToUnscopables('entries');
3228
3229var ITERATOR$1 = _wks('iterator');
3230
3231var TO_STRING_TAG$4 = _wks('toStringTag');
3232
3233var ArrayValues = _iterators.Array;
3234var DOMIterables = {
3235 CSSRuleList: true,
3236 // TODO: Not spec compliant, should be false.
3237 CSSStyleDeclaration: false,
3238 CSSValueList: false,
3239 ClientRectList: false,
3240 DOMRectList: false,
3241 DOMStringList: false,
3242 DOMTokenList: true,
3243 DataTransferItemList: false,
3244 FileList: false,
3245 HTMLAllCollection: false,
3246 HTMLCollection: false,
3247 HTMLFormElement: false,
3248 HTMLSelectElement: false,
3249 MediaList: true,
3250 // TODO: Not spec compliant, should be false.
3251 MimeTypeArray: false,
3252 NamedNodeMap: false,
3253 NodeList: true,
3254 PaintRequestList: false,
3255 Plugin: false,
3256 PluginArray: false,
3257 SVGLengthList: false,
3258 SVGNumberList: false,
3259 SVGPathSegList: false,
3260 SVGPointList: false,
3261 SVGStringList: false,
3262 SVGTransformList: false,
3263 SourceBufferList: false,
3264 StyleSheetList: true,
3265 // TODO: Not spec compliant, should be false.
3266 TextTrackCueList: false,
3267 TextTrackList: false,
3268 TouchList: false
3269};
3270
3271for (var collections = _objectKeys(DOMIterables), i = 0; i < collections.length; i++) {
3272 var NAME$1 = collections[i];
3273 var explicit = DOMIterables[NAME$1];
3274 var Collection = _global[NAME$1];
3275 var proto = Collection && Collection.prototype;
3276 var key$1;
3277
3278 if (proto) {
3279 if (!proto[ITERATOR$1]) _hide(proto, ITERATOR$1, ArrayValues);
3280 if (!proto[TO_STRING_TAG$4]) _hide(proto, TO_STRING_TAG$4, NAME$1);
3281 _iterators[NAME$1] = ArrayValues;
3282 if (explicit) for (key$1 in es6_array_iterator) if (!proto[key$1]) _redefine(proto, key$1, es6_array_iterator[key$1], true);
3283 }
3284}
3285
3286var test$1 = {};
3287test$1[_wks('toStringTag')] = 'z';
3288
3289if (test$1 + '' != '[object z]') {
3290 _redefine(Object.prototype, 'toString', function toString() {
3291 return '[object ' + _classof(this) + ']';
3292 }, true);
3293}
3294
3295var isEnum$1 = _objectPie.f;
3296
3297var _objectToArray = function (isEntries) {
3298 return function (it) {
3299 var O = _toIobject(it);
3300
3301 var keys = _objectKeys(O);
3302
3303 var length = keys.length;
3304 var i = 0;
3305 var result = [];
3306 var key;
3307
3308 while (length > i) {
3309 key = keys[i++];
3310
3311 if (!_descriptors || isEnum$1.call(O, key)) {
3312 result.push(isEntries ? [key, O[key]] : O[key]);
3313 }
3314 }
3315
3316 return result;
3317 };
3318};
3319
3320var $values = _objectToArray(false);
3321
3322_export$1(_export$1.S, 'Object', {
3323 values: function values(it) {
3324 return $values(it);
3325 }
3326});
3327
3328var MATCH = _wks('match');
3329
3330var _isRegexp = function (it) {
3331 var isRegExp;
3332 return _isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : _cof(it) == 'RegExp');
3333};
3334
3335var SPECIES$1$1 = _wks('species');
3336
3337var _speciesConstructor = function (O, D) {
3338 var C = _anObject(O).constructor;
3339
3340 var S;
3341 return C === undefined || (S = _anObject(C)[SPECIES$1$1]) == undefined ? D : _aFunction(S);
3342};
3343
3344var $min = Math.min;
3345var $push = [].push;
3346var $SPLIT = 'split';
3347var LENGTH = 'length';
3348var LAST_INDEX$1 = 'lastIndex';
3349var MAX_UINT32 = 0xffffffff; // babel-minify transpiles RegExp('x', 'y') -> /x/y and it causes SyntaxError
3350
3351var SUPPORTS_Y = !_fails(function () {
3352 RegExp(MAX_UINT32, 'y');
3353}); // @@split logic
3354
3355_fixReWks('split', 2, function (defined, SPLIT, $split, maybeCallNative) {
3356 var internalSplit;
3357
3358 if ('abbc'[$SPLIT](/(b)*/)[1] == 'c' || 'test'[$SPLIT](/(?:)/, -1)[LENGTH] != 4 || 'ab'[$SPLIT](/(?:ab)*/)[LENGTH] != 2 || '.'[$SPLIT](/(.?)(.?)/)[LENGTH] != 4 || '.'[$SPLIT](/()()/)[LENGTH] > 1 || ''[$SPLIT](/.?/)[LENGTH]) {
3359 // based on es5-shim implementation, need to rework it
3360 internalSplit = function (separator, limit) {
3361 var string = String(this);
3362 if (separator === undefined && limit === 0) return []; // If `separator` is not a regex, use native split
3363
3364 if (!_isRegexp(separator)) return $split.call(string, separator, limit);
3365 var output = [];
3366 var flags = (separator.ignoreCase ? 'i' : '') + (separator.multiline ? 'm' : '') + (separator.unicode ? 'u' : '') + (separator.sticky ? 'y' : '');
3367 var lastLastIndex = 0;
3368 var splitLimit = limit === undefined ? MAX_UINT32 : limit >>> 0; // Make `global` and avoid `lastIndex` issues by working with a copy
3369
3370 var separatorCopy = new RegExp(separator.source, flags + 'g');
3371 var match, lastIndex, lastLength;
3372
3373 while (match = _regexpExec.call(separatorCopy, string)) {
3374 lastIndex = separatorCopy[LAST_INDEX$1];
3375
3376 if (lastIndex > lastLastIndex) {
3377 output.push(string.slice(lastLastIndex, match.index));
3378 if (match[LENGTH] > 1 && match.index < string[LENGTH]) $push.apply(output, match.slice(1));
3379 lastLength = match[0][LENGTH];
3380 lastLastIndex = lastIndex;
3381 if (output[LENGTH] >= splitLimit) break;
3382 }
3383
3384 if (separatorCopy[LAST_INDEX$1] === match.index) separatorCopy[LAST_INDEX$1]++; // Avoid an infinite loop
3385 }
3386
3387 if (lastLastIndex === string[LENGTH]) {
3388 if (lastLength || !separatorCopy.test('')) output.push('');
3389 } else output.push(string.slice(lastLastIndex));
3390
3391 return output[LENGTH] > splitLimit ? output.slice(0, splitLimit) : output;
3392 }; // Chakra, V8
3393
3394 } else if ('0'[$SPLIT](undefined, 0)[LENGTH]) {
3395 internalSplit = function (separator, limit) {
3396 return separator === undefined && limit === 0 ? [] : $split.call(this, separator, limit);
3397 };
3398 } else {
3399 internalSplit = $split;
3400 }
3401
3402 return [// `String.prototype.split` method
3403 // https://tc39.github.io/ecma262/#sec-string.prototype.split
3404 function split(separator, limit) {
3405 var O = defined(this);
3406 var splitter = separator == undefined ? undefined : separator[SPLIT];
3407 return splitter !== undefined ? splitter.call(separator, O, limit) : internalSplit.call(String(O), separator, limit);
3408 }, // `RegExp.prototype[@@split]` method
3409 // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@split
3410 //
3411 // NOTE: This cannot be properly polyfilled in engines that don't support
3412 // the 'y' flag.
3413 function (regexp, limit) {
3414 var res = maybeCallNative(internalSplit, regexp, this, limit, internalSplit !== $split);
3415 if (res.done) return res.value;
3416
3417 var rx = _anObject(regexp);
3418
3419 var S = String(this);
3420
3421 var C = _speciesConstructor(rx, RegExp);
3422
3423 var unicodeMatching = rx.unicode;
3424 var flags = (rx.ignoreCase ? 'i' : '') + (rx.multiline ? 'm' : '') + (rx.unicode ? 'u' : '') + (SUPPORTS_Y ? 'y' : 'g'); // ^(? + rx + ) is needed, in combination with some S slicing, to
3425 // simulate the 'y' flag.
3426
3427 var splitter = new C(SUPPORTS_Y ? rx : '^(?:' + rx.source + ')', flags);
3428 var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
3429 if (lim === 0) return [];
3430 if (S.length === 0) return _regexpExecAbstract(splitter, S) === null ? [S] : [];
3431 var p = 0;
3432 var q = 0;
3433 var A = [];
3434
3435 while (q < S.length) {
3436 splitter.lastIndex = SUPPORTS_Y ? q : 0;
3437
3438 var z = _regexpExecAbstract(splitter, SUPPORTS_Y ? S : S.slice(q));
3439
3440 var e;
3441
3442 if (z === null || (e = $min(_toLength(splitter.lastIndex + (SUPPORTS_Y ? 0 : q)), S.length)) === p) {
3443 q = _advanceStringIndex(S, q, unicodeMatching);
3444 } else {
3445 A.push(S.slice(p, q));
3446 if (A.length === lim) return A;
3447
3448 for (var i = 1; i <= z.length - 1; i++) {
3449 A.push(z[i]);
3450 if (A.length === lim) return A;
3451 }
3452
3453 q = p = e;
3454 }
3455 }
3456
3457 A.push(S.slice(p));
3458 return A;
3459 }];
3460});
3461
3462var $assign = Object.assign; // should work with symbols and should have deterministic property order (V8 bug)
3463
3464var _objectAssign = !$assign || _fails(function () {
3465 var A = {};
3466 var B = {}; // eslint-disable-next-line no-undef
3467
3468 var S = Symbol();
3469 var K = 'abcdefghijklmnopqrst';
3470 A[S] = 7;
3471 K.split('').forEach(function (k) {
3472 B[k] = k;
3473 });
3474 return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;
3475}) ? function assign(target, source) {
3476 // eslint-disable-line no-unused-vars
3477 var T = _toObject(target);
3478
3479 var aLen = arguments.length;
3480 var index = 1;
3481 var getSymbols = _objectGops.f;
3482 var isEnum = _objectPie.f;
3483
3484 while (aLen > index) {
3485 var S = _iobject(arguments[index++]);
3486
3487 var keys = getSymbols ? _objectKeys(S).concat(getSymbols(S)) : _objectKeys(S);
3488 var length = keys.length;
3489 var j = 0;
3490 var key;
3491
3492 while (length > j) {
3493 key = keys[j++];
3494 if (!_descriptors || isEnum.call(S, key)) T[key] = S[key];
3495 }
3496 }
3497
3498 return T;
3499} : $assign;
3500
3501_export$1(_export$1.S + _export$1.F, 'Object', {
3502 assign: _objectAssign
3503});
3504/* eslint-disable no-proto */
3505
3506
3507var check$1 = function (O, proto) {
3508 _anObject(O);
3509
3510 if (!_isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!");
3511};
3512
3513var _setProto = {
3514 set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line
3515 function (test, buggy, set) {
3516 try {
3517 set = _ctx(Function.call, _objectGopd.f(Object.prototype, '__proto__').set, 2);
3518 set(test, []);
3519 buggy = !(test instanceof Array);
3520 } catch (e) {
3521 buggy = true;
3522 }
3523
3524 return function setPrototypeOf(O, proto) {
3525 check$1(O, proto);
3526 if (buggy) O.__proto__ = proto;else set(O, proto);
3527 return O;
3528 };
3529 }({}, false) : undefined),
3530 check: check$1
3531};
3532var setPrototypeOf = _setProto.set;
3533
3534var _inheritIfRequired = function (that, target, C) {
3535 var S = target.constructor;
3536 var P;
3537
3538 if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && _isObject(P) && setPrototypeOf) {
3539 setPrototypeOf(that, P);
3540 }
3541
3542 return that;
3543};
3544
3545var _stringWs = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' + '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF';
3546
3547var space = '[' + _stringWs + ']';
3548var non = '\u200b\u0085';
3549var ltrim = RegExp('^' + space + space + '*');
3550var rtrim = RegExp(space + space + '*$');
3551
3552var exporter = function (KEY, exec, ALIAS) {
3553 var exp = {};
3554
3555 var FORCE = _fails(function () {
3556 return !!_stringWs[KEY]() || non[KEY]() != non;
3557 });
3558
3559 var fn = exp[KEY] = FORCE ? exec(trim) : _stringWs[KEY];
3560 if (ALIAS) exp[ALIAS] = fn;
3561
3562 _export$1(_export$1.P + _export$1.F * FORCE, 'String', exp);
3563}; // 1 -> String#trimLeft
3564// 2 -> String#trimRight
3565// 3 -> String#trim
3566
3567
3568var trim = exporter.trim = function (string, TYPE) {
3569 string = String(_defined(string));
3570 if (TYPE & 1) string = string.replace(ltrim, '');
3571 if (TYPE & 2) string = string.replace(rtrim, '');
3572 return string;
3573};
3574
3575var _stringTrim = exporter;
3576var gOPN$2 = _objectGopn.f;
3577var gOPD$2 = _objectGopd.f;
3578var dP$2 = _objectDp.f;
3579var $trim = _stringTrim.trim;
3580var NUMBER = 'Number';
3581var $Number = _global[NUMBER];
3582var Base = $Number;
3583var proto$1 = $Number.prototype; // Opera ~12 has broken Object#toString
3584
3585var BROKEN_COF = _cof(_objectCreate(proto$1)) == NUMBER;
3586var TRIM = 'trim' in String.prototype; // 7.1.3 ToNumber(argument)
3587
3588var toNumber = function (argument) {
3589 var it = _toPrimitive(argument, false);
3590
3591 if (typeof it == 'string' && it.length > 2) {
3592 it = TRIM ? it.trim() : $trim(it, 3);
3593 var first = it.charCodeAt(0);
3594 var third, radix, maxCode;
3595
3596 if (first === 43 || first === 45) {
3597 third = it.charCodeAt(2);
3598 if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix
3599 } else if (first === 48) {
3600 switch (it.charCodeAt(1)) {
3601 case 66:
3602 case 98:
3603 radix = 2;
3604 maxCode = 49;
3605 break;
3606 // fast equal /^0b[01]+$/i
3607
3608 case 79:
3609 case 111:
3610 radix = 8;
3611 maxCode = 55;
3612 break;
3613 // fast equal /^0o[0-7]+$/i
3614
3615 default:
3616 return +it;
3617 }
3618
3619 for (var digits = it.slice(2), i = 0, l = digits.length, code; i < l; i++) {
3620 code = digits.charCodeAt(i); // parseInt parses a string to a first unavailable symbol
3621 // but ToNumber should return NaN if a string contains unavailable symbols
3622
3623 if (code < 48 || code > maxCode) return NaN;
3624 }
3625
3626 return parseInt(digits, radix);
3627 }
3628 }
3629
3630 return +it;
3631};
3632
3633if (!$Number(' 0o1') || !$Number('0b1') || $Number('+0x1')) {
3634 $Number = function Number(value) {
3635 var it = arguments.length < 1 ? 0 : value;
3636 var that = this;
3637 return that instanceof $Number // check on 1..constructor(foo) case
3638 && (BROKEN_COF ? _fails(function () {
3639 proto$1.valueOf.call(that);
3640 }) : _cof(that) != NUMBER) ? _inheritIfRequired(new Base(toNumber(it)), that, $Number) : toNumber(it);
3641 };
3642
3643 for (var keys$2 = _descriptors ? gOPN$2(Base) : ( // ES3:
3644 'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' + // ES6 (in case, if modules with ES6 Number statics required before):
3645 'EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,' + 'MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger').split(','), j$1$1 = 0, key$1$1; keys$2.length > j$1$1; j$1$1++) {
3646 if (_has(Base, key$1$1 = keys$2[j$1$1]) && !_has($Number, key$1$1)) {
3647 dP$2($Number, key$1$1, gOPD$2(Base, key$1$1));
3648 }
3649 }
3650
3651 $Number.prototype = proto$1;
3652 proto$1.constructor = $Number;
3653
3654 _redefine(_global, NUMBER, $Number);
3655}
3656
3657var moment = createCommonjsModule$1(function (module, exports) {
3658 (function (global, factory) {
3659 module.exports = factory();
3660 })(commonjsGlobal$1, function () {
3661 var hookCallback;
3662
3663 function hooks() {
3664 return hookCallback.apply(null, arguments);
3665 } // This is done to register the method called with moment()
3666 // without creating circular dependencies.
3667
3668
3669 function setHookCallback(callback) {
3670 hookCallback = callback;
3671 }
3672
3673 function isArray(input) {
3674 return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
3675 }
3676
3677 function isObject(input) {
3678 // IE8 will treat undefined and null as object if it wasn't for
3679 // input != null
3680 return input != null && Object.prototype.toString.call(input) === '[object Object]';
3681 }
3682
3683 function isObjectEmpty(obj) {
3684 if (Object.getOwnPropertyNames) {
3685 return Object.getOwnPropertyNames(obj).length === 0;
3686 } else {
3687 var k;
3688
3689 for (k in obj) {
3690 if (obj.hasOwnProperty(k)) {
3691 return false;
3692 }
3693 }
3694
3695 return true;
3696 }
3697 }
3698
3699 function isUndefined(input) {
3700 return input === void 0;
3701 }
3702
3703 function isNumber(input) {
3704 return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
3705 }
3706
3707 function isDate(input) {
3708 return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
3709 }
3710
3711 function map(arr, fn) {
3712 var res = [],
3713 i;
3714
3715 for (i = 0; i < arr.length; ++i) {
3716 res.push(fn(arr[i], i));
3717 }
3718
3719 return res;
3720 }
3721
3722 function hasOwnProp(a, b) {
3723 return Object.prototype.hasOwnProperty.call(a, b);
3724 }
3725
3726 function extend(a, b) {
3727 for (var i in b) {
3728 if (hasOwnProp(b, i)) {
3729 a[i] = b[i];
3730 }
3731 }
3732
3733 if (hasOwnProp(b, 'toString')) {
3734 a.toString = b.toString;
3735 }
3736
3737 if (hasOwnProp(b, 'valueOf')) {
3738 a.valueOf = b.valueOf;
3739 }
3740
3741 return a;
3742 }
3743
3744 function createUTC(input, format, locale, strict) {
3745 return createLocalOrUTC(input, format, locale, strict, true).utc();
3746 }
3747
3748 function defaultParsingFlags() {
3749 // We need to deep clone this object.
3750 return {
3751 empty: false,
3752 unusedTokens: [],
3753 unusedInput: [],
3754 overflow: -2,
3755 charsLeftOver: 0,
3756 nullInput: false,
3757 invalidMonth: null,
3758 invalidFormat: false,
3759 userInvalidated: false,
3760 iso: false,
3761 parsedDateParts: [],
3762 meridiem: null,
3763 rfc2822: false,
3764 weekdayMismatch: false
3765 };
3766 }
3767
3768 function getParsingFlags(m) {
3769 if (m._pf == null) {
3770 m._pf = defaultParsingFlags();
3771 }
3772
3773 return m._pf;
3774 }
3775
3776 var some;
3777
3778 if (Array.prototype.some) {
3779 some = Array.prototype.some;
3780 } else {
3781 some = function (fun) {
3782 var t = Object(this);
3783 var len = t.length >>> 0;
3784
3785 for (var i = 0; i < len; i++) {
3786 if (i in t && fun.call(this, t[i], i, t)) {
3787 return true;
3788 }
3789 }
3790
3791 return false;
3792 };
3793 }
3794
3795 function isValid(m) {
3796 if (m._isValid == null) {
3797 var flags = getParsingFlags(m);
3798 var parsedParts = some.call(flags.parsedDateParts, function (i) {
3799 return i != null;
3800 });
3801 var isNowValid = !isNaN(m._d.getTime()) && flags.overflow < 0 && !flags.empty && !flags.invalidMonth && !flags.invalidWeekday && !flags.weekdayMismatch && !flags.nullInput && !flags.invalidFormat && !flags.userInvalidated && (!flags.meridiem || flags.meridiem && parsedParts);
3802
3803 if (m._strict) {
3804 isNowValid = isNowValid && flags.charsLeftOver === 0 && flags.unusedTokens.length === 0 && flags.bigHour === undefined;
3805 }
3806
3807 if (Object.isFrozen == null || !Object.isFrozen(m)) {
3808 m._isValid = isNowValid;
3809 } else {
3810 return isNowValid;
3811 }
3812 }
3813
3814 return m._isValid;
3815 }
3816
3817 function createInvalid(flags) {
3818 var m = createUTC(NaN);
3819
3820 if (flags != null) {
3821 extend(getParsingFlags(m), flags);
3822 } else {
3823 getParsingFlags(m).userInvalidated = true;
3824 }
3825
3826 return m;
3827 } // Plugins that add properties should also add the key here (null value),
3828 // so we can properly clone ourselves.
3829
3830
3831 var momentProperties = hooks.momentProperties = [];
3832
3833 function copyConfig(to, from) {
3834 var i, prop, val;
3835
3836 if (!isUndefined(from._isAMomentObject)) {
3837 to._isAMomentObject = from._isAMomentObject;
3838 }
3839
3840 if (!isUndefined(from._i)) {
3841 to._i = from._i;
3842 }
3843
3844 if (!isUndefined(from._f)) {
3845 to._f = from._f;
3846 }
3847
3848 if (!isUndefined(from._l)) {
3849 to._l = from._l;
3850 }
3851
3852 if (!isUndefined(from._strict)) {
3853 to._strict = from._strict;
3854 }
3855
3856 if (!isUndefined(from._tzm)) {
3857 to._tzm = from._tzm;
3858 }
3859
3860 if (!isUndefined(from._isUTC)) {
3861 to._isUTC = from._isUTC;
3862 }
3863
3864 if (!isUndefined(from._offset)) {
3865 to._offset = from._offset;
3866 }
3867
3868 if (!isUndefined(from._pf)) {
3869 to._pf = getParsingFlags(from);
3870 }
3871
3872 if (!isUndefined(from._locale)) {
3873 to._locale = from._locale;
3874 }
3875
3876 if (momentProperties.length > 0) {
3877 for (i = 0; i < momentProperties.length; i++) {
3878 prop = momentProperties[i];
3879 val = from[prop];
3880
3881 if (!isUndefined(val)) {
3882 to[prop] = val;
3883 }
3884 }
3885 }
3886
3887 return to;
3888 }
3889
3890 var updateInProgress = false; // Moment prototype object
3891
3892 function Moment(config) {
3893 copyConfig(this, config);
3894 this._d = new Date(config._d != null ? config._d.getTime() : NaN);
3895
3896 if (!this.isValid()) {
3897 this._d = new Date(NaN);
3898 } // Prevent infinite loop in case updateOffset creates new moment
3899 // objects.
3900
3901
3902 if (updateInProgress === false) {
3903 updateInProgress = true;
3904 hooks.updateOffset(this);
3905 updateInProgress = false;
3906 }
3907 }
3908
3909 function isMoment(obj) {
3910 return obj instanceof Moment || obj != null && obj._isAMomentObject != null;
3911 }
3912
3913 function absFloor(number) {
3914 if (number < 0) {
3915 // -0 -> 0
3916 return Math.ceil(number) || 0;
3917 } else {
3918 return Math.floor(number);
3919 }
3920 }
3921
3922 function toInt(argumentForCoercion) {
3923 var coercedNumber = +argumentForCoercion,
3924 value = 0;
3925
3926 if (coercedNumber !== 0 && isFinite(coercedNumber)) {
3927 value = absFloor(coercedNumber);
3928 }
3929
3930 return value;
3931 } // compare two arrays, return the number of differences
3932
3933
3934 function compareArrays(array1, array2, dontConvert) {
3935 var len = Math.min(array1.length, array2.length),
3936 lengthDiff = Math.abs(array1.length - array2.length),
3937 diffs = 0,
3938 i;
3939
3940 for (i = 0; i < len; i++) {
3941 if (dontConvert && array1[i] !== array2[i] || !dontConvert && toInt(array1[i]) !== toInt(array2[i])) {
3942 diffs++;
3943 }
3944 }
3945
3946 return diffs + lengthDiff;
3947 }
3948
3949 function warn(msg) {
3950 if (hooks.suppressDeprecationWarnings === false && typeof console !== 'undefined' && console.warn) {
3951 console.warn('Deprecation warning: ' + msg);
3952 }
3953 }
3954
3955 function deprecate(msg, fn) {
3956 var firstTime = true;
3957 return extend(function () {
3958 if (hooks.deprecationHandler != null) {
3959 hooks.deprecationHandler(null, msg);
3960 }
3961
3962 if (firstTime) {
3963 var args = [];
3964 var arg;
3965
3966 for (var i = 0; i < arguments.length; i++) {
3967 arg = '';
3968
3969 if (typeof arguments[i] === 'object') {
3970 arg += '\n[' + i + '] ';
3971
3972 for (var key in arguments[0]) {
3973 arg += key + ': ' + arguments[0][key] + ', ';
3974 }
3975
3976 arg = arg.slice(0, -2); // Remove trailing comma and space
3977 } else {
3978 arg = arguments[i];
3979 }
3980
3981 args.push(arg);
3982 }
3983
3984 warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + new Error().stack);
3985 firstTime = false;
3986 }
3987
3988 return fn.apply(this, arguments);
3989 }, fn);
3990 }
3991
3992 var deprecations = {};
3993
3994 function deprecateSimple(name, msg) {
3995 if (hooks.deprecationHandler != null) {
3996 hooks.deprecationHandler(name, msg);
3997 }
3998
3999 if (!deprecations[name]) {
4000 warn(msg);
4001 deprecations[name] = true;
4002 }
4003 }
4004
4005 hooks.suppressDeprecationWarnings = false;
4006 hooks.deprecationHandler = null;
4007
4008 function isFunction(input) {
4009 return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
4010 }
4011
4012 function set(config) {
4013 var prop, i;
4014
4015 for (i in config) {
4016 prop = config[i];
4017
4018 if (isFunction(prop)) {
4019 this[i] = prop;
4020 } else {
4021 this['_' + i] = prop;
4022 }
4023 }
4024
4025 this._config = config; // Lenient ordinal parsing accepts just a number in addition to
4026 // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
4027 // TODO: Remove "ordinalParse" fallback in next major release.
4028
4029 this._dayOfMonthOrdinalParseLenient = new RegExp((this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) + '|' + /\d{1,2}/.source);
4030 }
4031
4032 function mergeConfigs(parentConfig, childConfig) {
4033 var res = extend({}, parentConfig),
4034 prop;
4035
4036 for (prop in childConfig) {
4037 if (hasOwnProp(childConfig, prop)) {
4038 if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
4039 res[prop] = {};
4040 extend(res[prop], parentConfig[prop]);
4041 extend(res[prop], childConfig[prop]);
4042 } else if (childConfig[prop] != null) {
4043 res[prop] = childConfig[prop];
4044 } else {
4045 delete res[prop];
4046 }
4047 }
4048 }
4049
4050 for (prop in parentConfig) {
4051 if (hasOwnProp(parentConfig, prop) && !hasOwnProp(childConfig, prop) && isObject(parentConfig[prop])) {
4052 // make sure changes to properties don't modify parent config
4053 res[prop] = extend({}, res[prop]);
4054 }
4055 }
4056
4057 return res;
4058 }
4059
4060 function Locale(config) {
4061 if (config != null) {
4062 this.set(config);
4063 }
4064 }
4065
4066 var keys;
4067
4068 if (Object.keys) {
4069 keys = Object.keys;
4070 } else {
4071 keys = function (obj) {
4072 var i,
4073 res = [];
4074
4075 for (i in obj) {
4076 if (hasOwnProp(obj, i)) {
4077 res.push(i);
4078 }
4079 }
4080
4081 return res;
4082 };
4083 }
4084
4085 var defaultCalendar = {
4086 sameDay: '[Today at] LT',
4087 nextDay: '[Tomorrow at] LT',
4088 nextWeek: 'dddd [at] LT',
4089 lastDay: '[Yesterday at] LT',
4090 lastWeek: '[Last] dddd [at] LT',
4091 sameElse: 'L'
4092 };
4093
4094 function calendar(key, mom, now) {
4095 var output = this._calendar[key] || this._calendar['sameElse'];
4096 return isFunction(output) ? output.call(mom, now) : output;
4097 }
4098
4099 var defaultLongDateFormat = {
4100 LTS: 'h:mm:ss A',
4101 LT: 'h:mm A',
4102 L: 'MM/DD/YYYY',
4103 LL: 'MMMM D, YYYY',
4104 LLL: 'MMMM D, YYYY h:mm A',
4105 LLLL: 'dddd, MMMM D, YYYY h:mm A'
4106 };
4107
4108 function longDateFormat(key) {
4109 var format = this._longDateFormat[key],
4110 formatUpper = this._longDateFormat[key.toUpperCase()];
4111
4112 if (format || !formatUpper) {
4113 return format;
4114 }
4115
4116 this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
4117 return val.slice(1);
4118 });
4119 return this._longDateFormat[key];
4120 }
4121
4122 var defaultInvalidDate = 'Invalid date';
4123
4124 function invalidDate() {
4125 return this._invalidDate;
4126 }
4127
4128 var defaultOrdinal = '%d';
4129 var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
4130
4131 function ordinal(number) {
4132 return this._ordinal.replace('%d', number);
4133 }
4134
4135 var defaultRelativeTime = {
4136 future: 'in %s',
4137 past: '%s ago',
4138 s: 'a few seconds',
4139 ss: '%d seconds',
4140 m: 'a minute',
4141 mm: '%d minutes',
4142 h: 'an hour',
4143 hh: '%d hours',
4144 d: 'a day',
4145 dd: '%d days',
4146 M: 'a month',
4147 MM: '%d months',
4148 y: 'a year',
4149 yy: '%d years'
4150 };
4151
4152 function relativeTime(number, withoutSuffix, string, isFuture) {
4153 var output = this._relativeTime[string];
4154 return isFunction(output) ? output(number, withoutSuffix, string, isFuture) : output.replace(/%d/i, number);
4155 }
4156
4157 function pastFuture(diff, output) {
4158 var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
4159 return isFunction(format) ? format(output) : format.replace(/%s/i, output);
4160 }
4161
4162 var aliases = {};
4163
4164 function addUnitAlias(unit, shorthand) {
4165 var lowerCase = unit.toLowerCase();
4166 aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
4167 }
4168
4169 function normalizeUnits(units) {
4170 return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
4171 }
4172
4173 function normalizeObjectUnits(inputObject) {
4174 var normalizedInput = {},
4175 normalizedProp,
4176 prop;
4177
4178 for (prop in inputObject) {
4179 if (hasOwnProp(inputObject, prop)) {
4180 normalizedProp = normalizeUnits(prop);
4181
4182 if (normalizedProp) {
4183 normalizedInput[normalizedProp] = inputObject[prop];
4184 }
4185 }
4186 }
4187
4188 return normalizedInput;
4189 }
4190
4191 var priorities = {};
4192
4193 function addUnitPriority(unit, priority) {
4194 priorities[unit] = priority;
4195 }
4196
4197 function getPrioritizedUnits(unitsObj) {
4198 var units = [];
4199
4200 for (var u in unitsObj) {
4201 units.push({
4202 unit: u,
4203 priority: priorities[u]
4204 });
4205 }
4206
4207 units.sort(function (a, b) {
4208 return a.priority - b.priority;
4209 });
4210 return units;
4211 }
4212
4213 function zeroFill(number, targetLength, forceSign) {
4214 var absNumber = '' + Math.abs(number),
4215 zerosToFill = targetLength - absNumber.length,
4216 sign = number >= 0;
4217 return (sign ? forceSign ? '+' : '' : '-') + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
4218 }
4219
4220 var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
4221 var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
4222 var formatFunctions = {};
4223 var formatTokenFunctions = {}; // token: 'M'
4224 // padded: ['MM', 2]
4225 // ordinal: 'Mo'
4226 // callback: function () { this.month() + 1 }
4227
4228 function addFormatToken(token, padded, ordinal, callback) {
4229 var func = callback;
4230
4231 if (typeof callback === 'string') {
4232 func = function () {
4233 return this[callback]();
4234 };
4235 }
4236
4237 if (token) {
4238 formatTokenFunctions[token] = func;
4239 }
4240
4241 if (padded) {
4242 formatTokenFunctions[padded[0]] = function () {
4243 return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
4244 };
4245 }
4246
4247 if (ordinal) {
4248 formatTokenFunctions[ordinal] = function () {
4249 return this.localeData().ordinal(func.apply(this, arguments), token);
4250 };
4251 }
4252 }
4253
4254 function removeFormattingTokens(input) {
4255 if (input.match(/\[[\s\S]/)) {
4256 return input.replace(/^\[|\]$/g, '');
4257 }
4258
4259 return input.replace(/\\/g, '');
4260 }
4261
4262 function makeFormatFunction(format) {
4263 var array = format.match(formattingTokens),
4264 i,
4265 length;
4266
4267 for (i = 0, length = array.length; i < length; i++) {
4268 if (formatTokenFunctions[array[i]]) {
4269 array[i] = formatTokenFunctions[array[i]];
4270 } else {
4271 array[i] = removeFormattingTokens(array[i]);
4272 }
4273 }
4274
4275 return function (mom) {
4276 var output = '',
4277 i;
4278
4279 for (i = 0; i < length; i++) {
4280 output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
4281 }
4282
4283 return output;
4284 };
4285 } // format date using native date object
4286
4287
4288 function formatMoment(m, format) {
4289 if (!m.isValid()) {
4290 return m.localeData().invalidDate();
4291 }
4292
4293 format = expandFormat(format, m.localeData());
4294 formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
4295 return formatFunctions[format](m);
4296 }
4297
4298 function expandFormat(format, locale) {
4299 var i = 5;
4300
4301 function replaceLongDateFormatTokens(input) {
4302 return locale.longDateFormat(input) || input;
4303 }
4304
4305 localFormattingTokens.lastIndex = 0;
4306
4307 while (i >= 0 && localFormattingTokens.test(format)) {
4308 format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
4309 localFormattingTokens.lastIndex = 0;
4310 i -= 1;
4311 }
4312
4313 return format;
4314 }
4315
4316 var match1 = /\d/; // 0 - 9
4317
4318 var match2 = /\d\d/; // 00 - 99
4319
4320 var match3 = /\d{3}/; // 000 - 999
4321
4322 var match4 = /\d{4}/; // 0000 - 9999
4323
4324 var match6 = /[+-]?\d{6}/; // -999999 - 999999
4325
4326 var match1to2 = /\d\d?/; // 0 - 99
4327
4328 var match3to4 = /\d\d\d\d?/; // 999 - 9999
4329
4330 var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999
4331
4332 var match1to3 = /\d{1,3}/; // 0 - 999
4333
4334 var match1to4 = /\d{1,4}/; // 0 - 9999
4335
4336 var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
4337
4338 var matchUnsigned = /\d+/; // 0 - inf
4339
4340 var matchSigned = /[+-]?\d+/; // -inf - inf
4341
4342 var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
4343
4344 var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
4345
4346 var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
4347 // any word (or two) characters or numbers including two/three word month in arabic.
4348 // includes scottish gaelic two word and hyphenated months
4349
4350 var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
4351 var regexes = {};
4352
4353 function addRegexToken(token, regex, strictRegex) {
4354 regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
4355 return isStrict && strictRegex ? strictRegex : regex;
4356 };
4357 }
4358
4359 function getParseRegexForToken(token, config) {
4360 if (!hasOwnProp(regexes, token)) {
4361 return new RegExp(unescapeFormat(token));
4362 }
4363
4364 return regexes[token](config._strict, config._locale);
4365 } // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
4366
4367
4368 function unescapeFormat(s) {
4369 return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
4370 return p1 || p2 || p3 || p4;
4371 }));
4372 }
4373
4374 function regexEscape(s) {
4375 return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
4376 }
4377
4378 var tokens = {};
4379
4380 function addParseToken(token, callback) {
4381 var i,
4382 func = callback;
4383
4384 if (typeof token === 'string') {
4385 token = [token];
4386 }
4387
4388 if (isNumber(callback)) {
4389 func = function (input, array) {
4390 array[callback] = toInt(input);
4391 };
4392 }
4393
4394 for (i = 0; i < token.length; i++) {
4395 tokens[token[i]] = func;
4396 }
4397 }
4398
4399 function addWeekParseToken(token, callback) {
4400 addParseToken(token, function (input, array, config, token) {
4401 config._w = config._w || {};
4402 callback(input, config._w, config, token);
4403 });
4404 }
4405
4406 function addTimeToArrayFromToken(token, input, config) {
4407 if (input != null && hasOwnProp(tokens, token)) {
4408 tokens[token](input, config._a, config, token);
4409 }
4410 }
4411
4412 var YEAR = 0;
4413 var MONTH = 1;
4414 var DATE = 2;
4415 var HOUR = 3;
4416 var MINUTE = 4;
4417 var SECOND = 5;
4418 var MILLISECOND = 6;
4419 var WEEK = 7;
4420 var WEEKDAY = 8; // FORMATTING
4421
4422 addFormatToken('Y', 0, 0, function () {
4423 var y = this.year();
4424 return y <= 9999 ? '' + y : '+' + y;
4425 });
4426 addFormatToken(0, ['YY', 2], 0, function () {
4427 return this.year() % 100;
4428 });
4429 addFormatToken(0, ['YYYY', 4], 0, 'year');
4430 addFormatToken(0, ['YYYYY', 5], 0, 'year');
4431 addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); // ALIASES
4432
4433 addUnitAlias('year', 'y'); // PRIORITIES
4434
4435 addUnitPriority('year', 1); // PARSING
4436
4437 addRegexToken('Y', matchSigned);
4438 addRegexToken('YY', match1to2, match2);
4439 addRegexToken('YYYY', match1to4, match4);
4440 addRegexToken('YYYYY', match1to6, match6);
4441 addRegexToken('YYYYYY', match1to6, match6);
4442 addParseToken(['YYYYY', 'YYYYYY'], YEAR);
4443 addParseToken('YYYY', function (input, array) {
4444 array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
4445 });
4446 addParseToken('YY', function (input, array) {
4447 array[YEAR] = hooks.parseTwoDigitYear(input);
4448 });
4449 addParseToken('Y', function (input, array) {
4450 array[YEAR] = parseInt(input, 10);
4451 }); // HELPERS
4452
4453 function daysInYear(year) {
4454 return isLeapYear(year) ? 366 : 365;
4455 }
4456
4457 function isLeapYear(year) {
4458 return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
4459 } // HOOKS
4460
4461
4462 hooks.parseTwoDigitYear = function (input) {
4463 return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
4464 }; // MOMENTS
4465
4466
4467 var getSetYear = makeGetSet('FullYear', true);
4468
4469 function getIsLeapYear() {
4470 return isLeapYear(this.year());
4471 }
4472
4473 function makeGetSet(unit, keepTime) {
4474 return function (value) {
4475 if (value != null) {
4476 set$1(this, unit, value);
4477 hooks.updateOffset(this, keepTime);
4478 return this;
4479 } else {
4480 return get(this, unit);
4481 }
4482 };
4483 }
4484
4485 function get(mom, unit) {
4486 return mom.isValid() ? mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
4487 }
4488
4489 function set$1(mom, unit, value) {
4490 if (mom.isValid() && !isNaN(value)) {
4491 if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
4492 mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
4493 } else {
4494 mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
4495 }
4496 }
4497 } // MOMENTS
4498
4499
4500 function stringGet(units) {
4501 units = normalizeUnits(units);
4502
4503 if (isFunction(this[units])) {
4504 return this[units]();
4505 }
4506
4507 return this;
4508 }
4509
4510 function stringSet(units, value) {
4511 if (typeof units === 'object') {
4512 units = normalizeObjectUnits(units);
4513 var prioritized = getPrioritizedUnits(units);
4514
4515 for (var i = 0; i < prioritized.length; i++) {
4516 this[prioritized[i].unit](units[prioritized[i].unit]);
4517 }
4518 } else {
4519 units = normalizeUnits(units);
4520
4521 if (isFunction(this[units])) {
4522 return this[units](value);
4523 }
4524 }
4525
4526 return this;
4527 }
4528
4529 function mod(n, x) {
4530 return (n % x + x) % x;
4531 }
4532
4533 var indexOf;
4534
4535 if (Array.prototype.indexOf) {
4536 indexOf = Array.prototype.indexOf;
4537 } else {
4538 indexOf = function (o) {
4539 // I know
4540 var i;
4541
4542 for (i = 0; i < this.length; ++i) {
4543 if (this[i] === o) {
4544 return i;
4545 }
4546 }
4547
4548 return -1;
4549 };
4550 }
4551
4552 function daysInMonth(year, month) {
4553 if (isNaN(year) || isNaN(month)) {
4554 return NaN;
4555 }
4556
4557 var modMonth = mod(month, 12);
4558 year += (month - modMonth) / 12;
4559 return modMonth === 1 ? isLeapYear(year) ? 29 : 28 : 31 - modMonth % 7 % 2;
4560 } // FORMATTING
4561
4562
4563 addFormatToken('M', ['MM', 2], 'Mo', function () {
4564 return this.month() + 1;
4565 });
4566 addFormatToken('MMM', 0, 0, function (format) {
4567 return this.localeData().monthsShort(this, format);
4568 });
4569 addFormatToken('MMMM', 0, 0, function (format) {
4570 return this.localeData().months(this, format);
4571 }); // ALIASES
4572
4573 addUnitAlias('month', 'M'); // PRIORITY
4574
4575 addUnitPriority('month', 8); // PARSING
4576
4577 addRegexToken('M', match1to2);
4578 addRegexToken('MM', match1to2, match2);
4579 addRegexToken('MMM', function (isStrict, locale) {
4580 return locale.monthsShortRegex(isStrict);
4581 });
4582 addRegexToken('MMMM', function (isStrict, locale) {
4583 return locale.monthsRegex(isStrict);
4584 });
4585 addParseToken(['M', 'MM'], function (input, array) {
4586 array[MONTH] = toInt(input) - 1;
4587 });
4588 addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
4589 var month = config._locale.monthsParse(input, token, config._strict); // if we didn't find a month name, mark the date as invalid.
4590
4591
4592 if (month != null) {
4593 array[MONTH] = month;
4594 } else {
4595 getParsingFlags(config).invalidMonth = input;
4596 }
4597 }); // LOCALES
4598
4599 var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
4600 var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
4601
4602 function localeMonths(m, format) {
4603 if (!m) {
4604 return isArray(this._months) ? this._months : this._months['standalone'];
4605 }
4606
4607 return isArray(this._months) ? this._months[m.month()] : this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
4608 }
4609
4610 var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
4611
4612 function localeMonthsShort(m, format) {
4613 if (!m) {
4614 return isArray(this._monthsShort) ? this._monthsShort : this._monthsShort['standalone'];
4615 }
4616
4617 return isArray(this._monthsShort) ? this._monthsShort[m.month()] : this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
4618 }
4619
4620 function handleStrictParse(monthName, format, strict) {
4621 var i,
4622 ii,
4623 mom,
4624 llc = monthName.toLocaleLowerCase();
4625
4626 if (!this._monthsParse) {
4627 // this is not used
4628 this._monthsParse = [];
4629 this._longMonthsParse = [];
4630 this._shortMonthsParse = [];
4631
4632 for (i = 0; i < 12; ++i) {
4633 mom = createUTC([2000, i]);
4634 this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
4635 this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
4636 }
4637 }
4638
4639 if (strict) {
4640 if (format === 'MMM') {
4641 ii = indexOf.call(this._shortMonthsParse, llc);
4642 return ii !== -1 ? ii : null;
4643 } else {
4644 ii = indexOf.call(this._longMonthsParse, llc);
4645 return ii !== -1 ? ii : null;
4646 }
4647 } else {
4648 if (format === 'MMM') {
4649 ii = indexOf.call(this._shortMonthsParse, llc);
4650
4651 if (ii !== -1) {
4652 return ii;
4653 }
4654
4655 ii = indexOf.call(this._longMonthsParse, llc);
4656 return ii !== -1 ? ii : null;
4657 } else {
4658 ii = indexOf.call(this._longMonthsParse, llc);
4659
4660 if (ii !== -1) {
4661 return ii;
4662 }
4663
4664 ii = indexOf.call(this._shortMonthsParse, llc);
4665 return ii !== -1 ? ii : null;
4666 }
4667 }
4668 }
4669
4670 function localeMonthsParse(monthName, format, strict) {
4671 var i, mom, regex;
4672
4673 if (this._monthsParseExact) {
4674 return handleStrictParse.call(this, monthName, format, strict);
4675 }
4676
4677 if (!this._monthsParse) {
4678 this._monthsParse = [];
4679 this._longMonthsParse = [];
4680 this._shortMonthsParse = [];
4681 } // TODO: add sorting
4682 // Sorting makes sure if one month (or abbr) is a prefix of another
4683 // see sorting in computeMonthsParse
4684
4685
4686 for (i = 0; i < 12; i++) {
4687 // make the regex if we don't have it already
4688 mom = createUTC([2000, i]);
4689
4690 if (strict && !this._longMonthsParse[i]) {
4691 this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
4692 this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
4693 }
4694
4695 if (!strict && !this._monthsParse[i]) {
4696 regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
4697 this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
4698 } // test the regex
4699
4700
4701 if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
4702 return i;
4703 } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
4704 return i;
4705 } else if (!strict && this._monthsParse[i].test(monthName)) {
4706 return i;
4707 }
4708 }
4709 } // MOMENTS
4710
4711
4712 function setMonth(mom, value) {
4713 var dayOfMonth;
4714
4715 if (!mom.isValid()) {
4716 // No op
4717 return mom;
4718 }
4719
4720 if (typeof value === 'string') {
4721 if (/^\d+$/.test(value)) {
4722 value = toInt(value);
4723 } else {
4724 value = mom.localeData().monthsParse(value); // TODO: Another silent failure?
4725
4726 if (!isNumber(value)) {
4727 return mom;
4728 }
4729 }
4730 }
4731
4732 dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
4733
4734 mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
4735
4736 return mom;
4737 }
4738
4739 function getSetMonth(value) {
4740 if (value != null) {
4741 setMonth(this, value);
4742 hooks.updateOffset(this, true);
4743 return this;
4744 } else {
4745 return get(this, 'Month');
4746 }
4747 }
4748
4749 function getDaysInMonth() {
4750 return daysInMonth(this.year(), this.month());
4751 }
4752
4753 var defaultMonthsShortRegex = matchWord;
4754
4755 function monthsShortRegex(isStrict) {
4756 if (this._monthsParseExact) {
4757 if (!hasOwnProp(this, '_monthsRegex')) {
4758 computeMonthsParse.call(this);
4759 }
4760
4761 if (isStrict) {
4762 return this._monthsShortStrictRegex;
4763 } else {
4764 return this._monthsShortRegex;
4765 }
4766 } else {
4767 if (!hasOwnProp(this, '_monthsShortRegex')) {
4768 this._monthsShortRegex = defaultMonthsShortRegex;
4769 }
4770
4771 return this._monthsShortStrictRegex && isStrict ? this._monthsShortStrictRegex : this._monthsShortRegex;
4772 }
4773 }
4774
4775 var defaultMonthsRegex = matchWord;
4776
4777 function monthsRegex(isStrict) {
4778 if (this._monthsParseExact) {
4779 if (!hasOwnProp(this, '_monthsRegex')) {
4780 computeMonthsParse.call(this);
4781 }
4782
4783 if (isStrict) {
4784 return this._monthsStrictRegex;
4785 } else {
4786 return this._monthsRegex;
4787 }
4788 } else {
4789 if (!hasOwnProp(this, '_monthsRegex')) {
4790 this._monthsRegex = defaultMonthsRegex;
4791 }
4792
4793 return this._monthsStrictRegex && isStrict ? this._monthsStrictRegex : this._monthsRegex;
4794 }
4795 }
4796
4797 function computeMonthsParse() {
4798 function cmpLenRev(a, b) {
4799 return b.length - a.length;
4800 }
4801
4802 var shortPieces = [],
4803 longPieces = [],
4804 mixedPieces = [],
4805 i,
4806 mom;
4807
4808 for (i = 0; i < 12; i++) {
4809 // make the regex if we don't have it already
4810 mom = createUTC([2000, i]);
4811 shortPieces.push(this.monthsShort(mom, ''));
4812 longPieces.push(this.months(mom, ''));
4813 mixedPieces.push(this.months(mom, ''));
4814 mixedPieces.push(this.monthsShort(mom, ''));
4815 } // Sorting makes sure if one month (or abbr) is a prefix of another it
4816 // will match the longer piece.
4817
4818
4819 shortPieces.sort(cmpLenRev);
4820 longPieces.sort(cmpLenRev);
4821 mixedPieces.sort(cmpLenRev);
4822
4823 for (i = 0; i < 12; i++) {
4824 shortPieces[i] = regexEscape(shortPieces[i]);
4825 longPieces[i] = regexEscape(longPieces[i]);
4826 }
4827
4828 for (i = 0; i < 24; i++) {
4829 mixedPieces[i] = regexEscape(mixedPieces[i]);
4830 }
4831
4832 this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
4833 this._monthsShortRegex = this._monthsRegex;
4834 this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
4835 this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
4836 }
4837
4838 function createDate(y, m, d, h, M, s, ms) {
4839 // can't just apply() to create a date:
4840 // https://stackoverflow.com/q/181348
4841 var date; // the date constructor remaps years 0-99 to 1900-1999
4842
4843 if (y < 100 && y >= 0) {
4844 // preserve leap years using a full 400 year cycle, then reset
4845 date = new Date(y + 400, m, d, h, M, s, ms);
4846
4847 if (isFinite(date.getFullYear())) {
4848 date.setFullYear(y);
4849 }
4850 } else {
4851 date = new Date(y, m, d, h, M, s, ms);
4852 }
4853
4854 return date;
4855 }
4856
4857 function createUTCDate(y) {
4858 var date; // the Date.UTC function remaps years 0-99 to 1900-1999
4859
4860 if (y < 100 && y >= 0) {
4861 var args = Array.prototype.slice.call(arguments); // preserve leap years using a full 400 year cycle, then reset
4862
4863 args[0] = y + 400;
4864 date = new Date(Date.UTC.apply(null, args));
4865
4866 if (isFinite(date.getUTCFullYear())) {
4867 date.setUTCFullYear(y);
4868 }
4869 } else {
4870 date = new Date(Date.UTC.apply(null, arguments));
4871 }
4872
4873 return date;
4874 } // start-of-first-week - start-of-year
4875
4876
4877 function firstWeekOffset(year, dow, doy) {
4878 var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
4879 fwd = 7 + dow - doy,
4880 // first-week day local weekday -- which local weekday is fwd
4881 fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
4882 return -fwdlw + fwd - 1;
4883 } // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
4884
4885
4886 function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
4887 var localWeekday = (7 + weekday - dow) % 7,
4888 weekOffset = firstWeekOffset(year, dow, doy),
4889 dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
4890 resYear,
4891 resDayOfYear;
4892
4893 if (dayOfYear <= 0) {
4894 resYear = year - 1;
4895 resDayOfYear = daysInYear(resYear) + dayOfYear;
4896 } else if (dayOfYear > daysInYear(year)) {
4897 resYear = year + 1;
4898 resDayOfYear = dayOfYear - daysInYear(year);
4899 } else {
4900 resYear = year;
4901 resDayOfYear = dayOfYear;
4902 }
4903
4904 return {
4905 year: resYear,
4906 dayOfYear: resDayOfYear
4907 };
4908 }
4909
4910 function weekOfYear(mom, dow, doy) {
4911 var weekOffset = firstWeekOffset(mom.year(), dow, doy),
4912 week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
4913 resWeek,
4914 resYear;
4915
4916 if (week < 1) {
4917 resYear = mom.year() - 1;
4918 resWeek = week + weeksInYear(resYear, dow, doy);
4919 } else if (week > weeksInYear(mom.year(), dow, doy)) {
4920 resWeek = week - weeksInYear(mom.year(), dow, doy);
4921 resYear = mom.year() + 1;
4922 } else {
4923 resYear = mom.year();
4924 resWeek = week;
4925 }
4926
4927 return {
4928 week: resWeek,
4929 year: resYear
4930 };
4931 }
4932
4933 function weeksInYear(year, dow, doy) {
4934 var weekOffset = firstWeekOffset(year, dow, doy),
4935 weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
4936 return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
4937 } // FORMATTING
4938
4939
4940 addFormatToken('w', ['ww', 2], 'wo', 'week');
4941 addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); // ALIASES
4942
4943 addUnitAlias('week', 'w');
4944 addUnitAlias('isoWeek', 'W'); // PRIORITIES
4945
4946 addUnitPriority('week', 5);
4947 addUnitPriority('isoWeek', 5); // PARSING
4948
4949 addRegexToken('w', match1to2);
4950 addRegexToken('ww', match1to2, match2);
4951 addRegexToken('W', match1to2);
4952 addRegexToken('WW', match1to2, match2);
4953 addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
4954 week[token.substr(0, 1)] = toInt(input);
4955 }); // HELPERS
4956 // LOCALES
4957
4958 function localeWeek(mom) {
4959 return weekOfYear(mom, this._week.dow, this._week.doy).week;
4960 }
4961
4962 var defaultLocaleWeek = {
4963 dow: 0,
4964 // Sunday is the first day of the week.
4965 doy: 6 // The week that contains Jan 6th is the first week of the year.
4966
4967 };
4968
4969 function localeFirstDayOfWeek() {
4970 return this._week.dow;
4971 }
4972
4973 function localeFirstDayOfYear() {
4974 return this._week.doy;
4975 } // MOMENTS
4976
4977
4978 function getSetWeek(input) {
4979 var week = this.localeData().week(this);
4980 return input == null ? week : this.add((input - week) * 7, 'd');
4981 }
4982
4983 function getSetISOWeek(input) {
4984 var week = weekOfYear(this, 1, 4).week;
4985 return input == null ? week : this.add((input - week) * 7, 'd');
4986 } // FORMATTING
4987
4988
4989 addFormatToken('d', 0, 'do', 'day');
4990 addFormatToken('dd', 0, 0, function (format) {
4991 return this.localeData().weekdaysMin(this, format);
4992 });
4993 addFormatToken('ddd', 0, 0, function (format) {
4994 return this.localeData().weekdaysShort(this, format);
4995 });
4996 addFormatToken('dddd', 0, 0, function (format) {
4997 return this.localeData().weekdays(this, format);
4998 });
4999 addFormatToken('e', 0, 0, 'weekday');
5000 addFormatToken('E', 0, 0, 'isoWeekday'); // ALIASES
5001
5002 addUnitAlias('day', 'd');
5003 addUnitAlias('weekday', 'e');
5004 addUnitAlias('isoWeekday', 'E'); // PRIORITY
5005
5006 addUnitPriority('day', 11);
5007 addUnitPriority('weekday', 11);
5008 addUnitPriority('isoWeekday', 11); // PARSING
5009
5010 addRegexToken('d', match1to2);
5011 addRegexToken('e', match1to2);
5012 addRegexToken('E', match1to2);
5013 addRegexToken('dd', function (isStrict, locale) {
5014 return locale.weekdaysMinRegex(isStrict);
5015 });
5016 addRegexToken('ddd', function (isStrict, locale) {
5017 return locale.weekdaysShortRegex(isStrict);
5018 });
5019 addRegexToken('dddd', function (isStrict, locale) {
5020 return locale.weekdaysRegex(isStrict);
5021 });
5022 addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
5023 var weekday = config._locale.weekdaysParse(input, token, config._strict); // if we didn't get a weekday name, mark the date as invalid
5024
5025
5026 if (weekday != null) {
5027 week.d = weekday;
5028 } else {
5029 getParsingFlags(config).invalidWeekday = input;
5030 }
5031 });
5032 addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
5033 week[token] = toInt(input);
5034 }); // HELPERS
5035
5036 function parseWeekday(input, locale) {
5037 if (typeof input !== 'string') {
5038 return input;
5039 }
5040
5041 if (!isNaN(input)) {
5042 return parseInt(input, 10);
5043 }
5044
5045 input = locale.weekdaysParse(input);
5046
5047 if (typeof input === 'number') {
5048 return input;
5049 }
5050
5051 return null;
5052 }
5053
5054 function parseIsoWeekday(input, locale) {
5055 if (typeof input === 'string') {
5056 return locale.weekdaysParse(input) % 7 || 7;
5057 }
5058
5059 return isNaN(input) ? null : input;
5060 } // LOCALES
5061
5062
5063 function shiftWeekdays(ws, n) {
5064 return ws.slice(n, 7).concat(ws.slice(0, n));
5065 }
5066
5067 var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
5068
5069 function localeWeekdays(m, format) {
5070 var weekdays = isArray(this._weekdays) ? this._weekdays : this._weekdays[m && m !== true && this._weekdays.isFormat.test(format) ? 'format' : 'standalone'];
5071 return m === true ? shiftWeekdays(weekdays, this._week.dow) : m ? weekdays[m.day()] : weekdays;
5072 }
5073
5074 var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
5075
5076 function localeWeekdaysShort(m) {
5077 return m === true ? shiftWeekdays(this._weekdaysShort, this._week.dow) : m ? this._weekdaysShort[m.day()] : this._weekdaysShort;
5078 }
5079
5080 var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
5081
5082 function localeWeekdaysMin(m) {
5083 return m === true ? shiftWeekdays(this._weekdaysMin, this._week.dow) : m ? this._weekdaysMin[m.day()] : this._weekdaysMin;
5084 }
5085
5086 function handleStrictParse$1(weekdayName, format, strict) {
5087 var i,
5088 ii,
5089 mom,
5090 llc = weekdayName.toLocaleLowerCase();
5091
5092 if (!this._weekdaysParse) {
5093 this._weekdaysParse = [];
5094 this._shortWeekdaysParse = [];
5095 this._minWeekdaysParse = [];
5096
5097 for (i = 0; i < 7; ++i) {
5098 mom = createUTC([2000, 1]).day(i);
5099 this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
5100 this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
5101 this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
5102 }
5103 }
5104
5105 if (strict) {
5106 if (format === 'dddd') {
5107 ii = indexOf.call(this._weekdaysParse, llc);
5108 return ii !== -1 ? ii : null;
5109 } else if (format === 'ddd') {
5110 ii = indexOf.call(this._shortWeekdaysParse, llc);
5111 return ii !== -1 ? ii : null;
5112 } else {
5113 ii = indexOf.call(this._minWeekdaysParse, llc);
5114 return ii !== -1 ? ii : null;
5115 }
5116 } else {
5117 if (format === 'dddd') {
5118 ii = indexOf.call(this._weekdaysParse, llc);
5119
5120 if (ii !== -1) {
5121 return ii;
5122 }
5123
5124 ii = indexOf.call(this._shortWeekdaysParse, llc);
5125
5126 if (ii !== -1) {
5127 return ii;
5128 }
5129
5130 ii = indexOf.call(this._minWeekdaysParse, llc);
5131 return ii !== -1 ? ii : null;
5132 } else if (format === 'ddd') {
5133 ii = indexOf.call(this._shortWeekdaysParse, llc);
5134
5135 if (ii !== -1) {
5136 return ii;
5137 }
5138
5139 ii = indexOf.call(this._weekdaysParse, llc);
5140
5141 if (ii !== -1) {
5142 return ii;
5143 }
5144
5145 ii = indexOf.call(this._minWeekdaysParse, llc);
5146 return ii !== -1 ? ii : null;
5147 } else {
5148 ii = indexOf.call(this._minWeekdaysParse, llc);
5149
5150 if (ii !== -1) {
5151 return ii;
5152 }
5153
5154 ii = indexOf.call(this._weekdaysParse, llc);
5155
5156 if (ii !== -1) {
5157 return ii;
5158 }
5159
5160 ii = indexOf.call(this._shortWeekdaysParse, llc);
5161 return ii !== -1 ? ii : null;
5162 }
5163 }
5164 }
5165
5166 function localeWeekdaysParse(weekdayName, format, strict) {
5167 var i, mom, regex;
5168
5169 if (this._weekdaysParseExact) {
5170 return handleStrictParse$1.call(this, weekdayName, format, strict);
5171 }
5172
5173 if (!this._weekdaysParse) {
5174 this._weekdaysParse = [];
5175 this._minWeekdaysParse = [];
5176 this._shortWeekdaysParse = [];
5177 this._fullWeekdaysParse = [];
5178 }
5179
5180 for (i = 0; i < 7; i++) {
5181 // make the regex if we don't have it already
5182 mom = createUTC([2000, 1]).day(i);
5183
5184 if (strict && !this._fullWeekdaysParse[i]) {
5185 this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i');
5186 this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i');
5187 this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i');
5188 }
5189
5190 if (!this._weekdaysParse[i]) {
5191 regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
5192 this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
5193 } // test the regex
5194
5195
5196 if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
5197 return i;
5198 } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
5199 return i;
5200 } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
5201 return i;
5202 } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
5203 return i;
5204 }
5205 }
5206 } // MOMENTS
5207
5208
5209 function getSetDayOfWeek(input) {
5210 if (!this.isValid()) {
5211 return input != null ? this : NaN;
5212 }
5213
5214 var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
5215
5216 if (input != null) {
5217 input = parseWeekday(input, this.localeData());
5218 return this.add(input - day, 'd');
5219 } else {
5220 return day;
5221 }
5222 }
5223
5224 function getSetLocaleDayOfWeek(input) {
5225 if (!this.isValid()) {
5226 return input != null ? this : NaN;
5227 }
5228
5229 var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
5230 return input == null ? weekday : this.add(input - weekday, 'd');
5231 }
5232
5233 function getSetISODayOfWeek(input) {
5234 if (!this.isValid()) {
5235 return input != null ? this : NaN;
5236 } // behaves the same as moment#day except
5237 // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
5238 // as a setter, sunday should belong to the previous week.
5239
5240
5241 if (input != null) {
5242 var weekday = parseIsoWeekday(input, this.localeData());
5243 return this.day(this.day() % 7 ? weekday : weekday - 7);
5244 } else {
5245 return this.day() || 7;
5246 }
5247 }
5248
5249 var defaultWeekdaysRegex = matchWord;
5250
5251 function weekdaysRegex(isStrict) {
5252 if (this._weekdaysParseExact) {
5253 if (!hasOwnProp(this, '_weekdaysRegex')) {
5254 computeWeekdaysParse.call(this);
5255 }
5256
5257 if (isStrict) {
5258 return this._weekdaysStrictRegex;
5259 } else {
5260 return this._weekdaysRegex;
5261 }
5262 } else {
5263 if (!hasOwnProp(this, '_weekdaysRegex')) {
5264 this._weekdaysRegex = defaultWeekdaysRegex;
5265 }
5266
5267 return this._weekdaysStrictRegex && isStrict ? this._weekdaysStrictRegex : this._weekdaysRegex;
5268 }
5269 }
5270
5271 var defaultWeekdaysShortRegex = matchWord;
5272
5273 function weekdaysShortRegex(isStrict) {
5274 if (this._weekdaysParseExact) {
5275 if (!hasOwnProp(this, '_weekdaysRegex')) {
5276 computeWeekdaysParse.call(this);
5277 }
5278
5279 if (isStrict) {
5280 return this._weekdaysShortStrictRegex;
5281 } else {
5282 return this._weekdaysShortRegex;
5283 }
5284 } else {
5285 if (!hasOwnProp(this, '_weekdaysShortRegex')) {
5286 this._weekdaysShortRegex = defaultWeekdaysShortRegex;
5287 }
5288
5289 return this._weekdaysShortStrictRegex && isStrict ? this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
5290 }
5291 }
5292
5293 var defaultWeekdaysMinRegex = matchWord;
5294
5295 function weekdaysMinRegex(isStrict) {
5296 if (this._weekdaysParseExact) {
5297 if (!hasOwnProp(this, '_weekdaysRegex')) {
5298 computeWeekdaysParse.call(this);
5299 }
5300
5301 if (isStrict) {
5302 return this._weekdaysMinStrictRegex;
5303 } else {
5304 return this._weekdaysMinRegex;
5305 }
5306 } else {
5307 if (!hasOwnProp(this, '_weekdaysMinRegex')) {
5308 this._weekdaysMinRegex = defaultWeekdaysMinRegex;
5309 }
5310
5311 return this._weekdaysMinStrictRegex && isStrict ? this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
5312 }
5313 }
5314
5315 function computeWeekdaysParse() {
5316 function cmpLenRev(a, b) {
5317 return b.length - a.length;
5318 }
5319
5320 var minPieces = [],
5321 shortPieces = [],
5322 longPieces = [],
5323 mixedPieces = [],
5324 i,
5325 mom,
5326 minp,
5327 shortp,
5328 longp;
5329
5330 for (i = 0; i < 7; i++) {
5331 // make the regex if we don't have it already
5332 mom = createUTC([2000, 1]).day(i);
5333 minp = this.weekdaysMin(mom, '');
5334 shortp = this.weekdaysShort(mom, '');
5335 longp = this.weekdays(mom, '');
5336 minPieces.push(minp);
5337 shortPieces.push(shortp);
5338 longPieces.push(longp);
5339 mixedPieces.push(minp);
5340 mixedPieces.push(shortp);
5341 mixedPieces.push(longp);
5342 } // Sorting makes sure if one weekday (or abbr) is a prefix of another it
5343 // will match the longer piece.
5344
5345
5346 minPieces.sort(cmpLenRev);
5347 shortPieces.sort(cmpLenRev);
5348 longPieces.sort(cmpLenRev);
5349 mixedPieces.sort(cmpLenRev);
5350
5351 for (i = 0; i < 7; i++) {
5352 shortPieces[i] = regexEscape(shortPieces[i]);
5353 longPieces[i] = regexEscape(longPieces[i]);
5354 mixedPieces[i] = regexEscape(mixedPieces[i]);
5355 }
5356
5357 this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
5358 this._weekdaysShortRegex = this._weekdaysRegex;
5359 this._weekdaysMinRegex = this._weekdaysRegex;
5360 this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
5361 this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
5362 this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
5363 } // FORMATTING
5364
5365
5366 function hFormat() {
5367 return this.hours() % 12 || 12;
5368 }
5369
5370 function kFormat() {
5371 return this.hours() || 24;
5372 }
5373
5374 addFormatToken('H', ['HH', 2], 0, 'hour');
5375 addFormatToken('h', ['hh', 2], 0, hFormat);
5376 addFormatToken('k', ['kk', 2], 0, kFormat);
5377 addFormatToken('hmm', 0, 0, function () {
5378 return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
5379 });
5380 addFormatToken('hmmss', 0, 0, function () {
5381 return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + zeroFill(this.seconds(), 2);
5382 });
5383 addFormatToken('Hmm', 0, 0, function () {
5384 return '' + this.hours() + zeroFill(this.minutes(), 2);
5385 });
5386 addFormatToken('Hmmss', 0, 0, function () {
5387 return '' + this.hours() + zeroFill(this.minutes(), 2) + zeroFill(this.seconds(), 2);
5388 });
5389
5390 function meridiem(token, lowercase) {
5391 addFormatToken(token, 0, 0, function () {
5392 return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
5393 });
5394 }
5395
5396 meridiem('a', true);
5397 meridiem('A', false); // ALIASES
5398
5399 addUnitAlias('hour', 'h'); // PRIORITY
5400
5401 addUnitPriority('hour', 13); // PARSING
5402
5403 function matchMeridiem(isStrict, locale) {
5404 return locale._meridiemParse;
5405 }
5406
5407 addRegexToken('a', matchMeridiem);
5408 addRegexToken('A', matchMeridiem);
5409 addRegexToken('H', match1to2);
5410 addRegexToken('h', match1to2);
5411 addRegexToken('k', match1to2);
5412 addRegexToken('HH', match1to2, match2);
5413 addRegexToken('hh', match1to2, match2);
5414 addRegexToken('kk', match1to2, match2);
5415 addRegexToken('hmm', match3to4);
5416 addRegexToken('hmmss', match5to6);
5417 addRegexToken('Hmm', match3to4);
5418 addRegexToken('Hmmss', match5to6);
5419 addParseToken(['H', 'HH'], HOUR);
5420 addParseToken(['k', 'kk'], function (input, array, config) {
5421 var kInput = toInt(input);
5422 array[HOUR] = kInput === 24 ? 0 : kInput;
5423 });
5424 addParseToken(['a', 'A'], function (input, array, config) {
5425 config._isPm = config._locale.isPM(input);
5426 config._meridiem = input;
5427 });
5428 addParseToken(['h', 'hh'], function (input, array, config) {
5429 array[HOUR] = toInt(input);
5430 getParsingFlags(config).bigHour = true;
5431 });
5432 addParseToken('hmm', function (input, array, config) {
5433 var pos = input.length - 2;
5434 array[HOUR] = toInt(input.substr(0, pos));
5435 array[MINUTE] = toInt(input.substr(pos));
5436 getParsingFlags(config).bigHour = true;
5437 });
5438 addParseToken('hmmss', function (input, array, config) {
5439 var pos1 = input.length - 4;
5440 var pos2 = input.length - 2;
5441 array[HOUR] = toInt(input.substr(0, pos1));
5442 array[MINUTE] = toInt(input.substr(pos1, 2));
5443 array[SECOND] = toInt(input.substr(pos2));
5444 getParsingFlags(config).bigHour = true;
5445 });
5446 addParseToken('Hmm', function (input, array, config) {
5447 var pos = input.length - 2;
5448 array[HOUR] = toInt(input.substr(0, pos));
5449 array[MINUTE] = toInt(input.substr(pos));
5450 });
5451 addParseToken('Hmmss', function (input, array, config) {
5452 var pos1 = input.length - 4;
5453 var pos2 = input.length - 2;
5454 array[HOUR] = toInt(input.substr(0, pos1));
5455 array[MINUTE] = toInt(input.substr(pos1, 2));
5456 array[SECOND] = toInt(input.substr(pos2));
5457 }); // LOCALES
5458
5459 function localeIsPM(input) {
5460 // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
5461 // Using charAt should be more compatible.
5462 return (input + '').toLowerCase().charAt(0) === 'p';
5463 }
5464
5465 var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
5466
5467 function localeMeridiem(hours, minutes, isLower) {
5468 if (hours > 11) {
5469 return isLower ? 'pm' : 'PM';
5470 } else {
5471 return isLower ? 'am' : 'AM';
5472 }
5473 } // MOMENTS
5474 // Setting the hour should keep the time, because the user explicitly
5475 // specified which hour they want. So trying to maintain the same hour (in
5476 // a new timezone) makes sense. Adding/subtracting hours does not follow
5477 // this rule.
5478
5479
5480 var getSetHour = makeGetSet('Hours', true);
5481 var baseConfig = {
5482 calendar: defaultCalendar,
5483 longDateFormat: defaultLongDateFormat,
5484 invalidDate: defaultInvalidDate,
5485 ordinal: defaultOrdinal,
5486 dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
5487 relativeTime: defaultRelativeTime,
5488 months: defaultLocaleMonths,
5489 monthsShort: defaultLocaleMonthsShort,
5490 week: defaultLocaleWeek,
5491 weekdays: defaultLocaleWeekdays,
5492 weekdaysMin: defaultLocaleWeekdaysMin,
5493 weekdaysShort: defaultLocaleWeekdaysShort,
5494 meridiemParse: defaultLocaleMeridiemParse
5495 }; // internal storage for locale config files
5496
5497 var locales = {};
5498 var localeFamilies = {};
5499 var globalLocale;
5500
5501 function normalizeLocale(key) {
5502 return key ? key.toLowerCase().replace('_', '-') : key;
5503 } // pick the locale from the array
5504 // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
5505 // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
5506
5507
5508 function chooseLocale(names) {
5509 var i = 0,
5510 j,
5511 next,
5512 locale,
5513 split;
5514
5515 while (i < names.length) {
5516 split = normalizeLocale(names[i]).split('-');
5517 j = split.length;
5518 next = normalizeLocale(names[i + 1]);
5519 next = next ? next.split('-') : null;
5520
5521 while (j > 0) {
5522 locale = loadLocale(split.slice(0, j).join('-'));
5523
5524 if (locale) {
5525 return locale;
5526 }
5527
5528 if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
5529 //the next array item is better than a shallower substring of this one
5530 break;
5531 }
5532
5533 j--;
5534 }
5535
5536 i++;
5537 }
5538
5539 return globalLocale;
5540 }
5541
5542 function loadLocale(name) {
5543 var oldLocale = null; // TODO: Find a better way to register and load all the locales in Node
5544
5545 if (!locales[name] && 'object' !== 'undefined' && module && module.exports) {
5546 try {
5547 oldLocale = globalLocale._abbr;
5548 var aliasedRequire = commonjsRequire$1;
5549 aliasedRequire('./locale/' + name);
5550 getSetGlobalLocale(oldLocale);
5551 } catch (e) {}
5552 }
5553
5554 return locales[name];
5555 } // This function will load locale and then set the global locale. If
5556 // no arguments are passed in, it will simply return the current global
5557 // locale key.
5558
5559
5560 function getSetGlobalLocale(key, values) {
5561 var data;
5562
5563 if (key) {
5564 if (isUndefined(values)) {
5565 data = getLocale(key);
5566 } else {
5567 data = defineLocale(key, values);
5568 }
5569
5570 if (data) {
5571 // moment.duration._locale = moment._locale = data;
5572 globalLocale = data;
5573 } else {
5574 if (typeof console !== 'undefined' && console.warn) {
5575 //warn user if arguments are passed but the locale could not be set
5576 console.warn('Locale ' + key + ' not found. Did you forget to load it?');
5577 }
5578 }
5579 }
5580
5581 return globalLocale._abbr;
5582 }
5583
5584 function defineLocale(name, config) {
5585 if (config !== null) {
5586 var locale,
5587 parentConfig = baseConfig;
5588 config.abbr = name;
5589
5590 if (locales[name] != null) {
5591 deprecateSimple('defineLocaleOverride', 'use moment.updateLocale(localeName, config) to change ' + 'an existing locale. moment.defineLocale(localeName, ' + 'config) should only be used for creating a new locale ' + 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
5592 parentConfig = locales[name]._config;
5593 } else if (config.parentLocale != null) {
5594 if (locales[config.parentLocale] != null) {
5595 parentConfig = locales[config.parentLocale]._config;
5596 } else {
5597 locale = loadLocale(config.parentLocale);
5598
5599 if (locale != null) {
5600 parentConfig = locale._config;
5601 } else {
5602 if (!localeFamilies[config.parentLocale]) {
5603 localeFamilies[config.parentLocale] = [];
5604 }
5605
5606 localeFamilies[config.parentLocale].push({
5607 name: name,
5608 config: config
5609 });
5610 return null;
5611 }
5612 }
5613 }
5614
5615 locales[name] = new Locale(mergeConfigs(parentConfig, config));
5616
5617 if (localeFamilies[name]) {
5618 localeFamilies[name].forEach(function (x) {
5619 defineLocale(x.name, x.config);
5620 });
5621 } // backwards compat for now: also set the locale
5622 // make sure we set the locale AFTER all child locales have been
5623 // created, so we won't end up with the child locale set.
5624
5625
5626 getSetGlobalLocale(name);
5627 return locales[name];
5628 } else {
5629 // useful for testing
5630 delete locales[name];
5631 return null;
5632 }
5633 }
5634
5635 function updateLocale(name, config) {
5636 if (config != null) {
5637 var locale,
5638 tmpLocale,
5639 parentConfig = baseConfig; // MERGE
5640
5641 tmpLocale = loadLocale(name);
5642
5643 if (tmpLocale != null) {
5644 parentConfig = tmpLocale._config;
5645 }
5646
5647 config = mergeConfigs(parentConfig, config);
5648 locale = new Locale(config);
5649 locale.parentLocale = locales[name];
5650 locales[name] = locale; // backwards compat for now: also set the locale
5651
5652 getSetGlobalLocale(name);
5653 } else {
5654 // pass null for config to unupdate, useful for tests
5655 if (locales[name] != null) {
5656 if (locales[name].parentLocale != null) {
5657 locales[name] = locales[name].parentLocale;
5658 } else if (locales[name] != null) {
5659 delete locales[name];
5660 }
5661 }
5662 }
5663
5664 return locales[name];
5665 } // returns locale data
5666
5667
5668 function getLocale(key) {
5669 var locale;
5670
5671 if (key && key._locale && key._locale._abbr) {
5672 key = key._locale._abbr;
5673 }
5674
5675 if (!key) {
5676 return globalLocale;
5677 }
5678
5679 if (!isArray(key)) {
5680 //short-circuit everything else
5681 locale = loadLocale(key);
5682
5683 if (locale) {
5684 return locale;
5685 }
5686
5687 key = [key];
5688 }
5689
5690 return chooseLocale(key);
5691 }
5692
5693 function listLocales() {
5694 return keys(locales);
5695 }
5696
5697 function checkOverflow(m) {
5698 var overflow;
5699 var a = m._a;
5700
5701 if (a && getParsingFlags(m).overflow === -2) {
5702 overflow = a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : a[HOUR] < 0 || a[HOUR] > 24 || a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0) ? HOUR : a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : -1;
5703
5704 if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
5705 overflow = DATE;
5706 }
5707
5708 if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
5709 overflow = WEEK;
5710 }
5711
5712 if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
5713 overflow = WEEKDAY;
5714 }
5715
5716 getParsingFlags(m).overflow = overflow;
5717 }
5718
5719 return m;
5720 } // Pick the first defined of two or three arguments.
5721
5722
5723 function defaults(a, b, c) {
5724 if (a != null) {
5725 return a;
5726 }
5727
5728 if (b != null) {
5729 return b;
5730 }
5731
5732 return c;
5733 }
5734
5735 function currentDateArray(config) {
5736 // hooks is actually the exported moment object
5737 var nowValue = new Date(hooks.now());
5738
5739 if (config._useUTC) {
5740 return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
5741 }
5742
5743 return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
5744 } // convert an array to a date.
5745 // the array should mirror the parameters below
5746 // note: all values past the year are optional and will default to the lowest possible value.
5747 // [year, month, day , hour, minute, second, millisecond]
5748
5749
5750 function configFromArray(config) {
5751 var i,
5752 date,
5753 input = [],
5754 currentDate,
5755 expectedWeekday,
5756 yearToUse;
5757
5758 if (config._d) {
5759 return;
5760 }
5761
5762 currentDate = currentDateArray(config); //compute day of the year from weeks and weekdays
5763
5764 if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
5765 dayOfYearFromWeekInfo(config);
5766 } //if the day of the year is set, figure out what it is
5767
5768
5769 if (config._dayOfYear != null) {
5770 yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
5771
5772 if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
5773 getParsingFlags(config)._overflowDayOfYear = true;
5774 }
5775
5776 date = createUTCDate(yearToUse, 0, config._dayOfYear);
5777 config._a[MONTH] = date.getUTCMonth();
5778 config._a[DATE] = date.getUTCDate();
5779 } // Default to current date.
5780 // * if no year, month, day of month are given, default to today
5781 // * if day of month is given, default month and year
5782 // * if month is given, default only year
5783 // * if year is given, don't default anything
5784
5785
5786 for (i = 0; i < 3 && config._a[i] == null; ++i) {
5787 config._a[i] = input[i] = currentDate[i];
5788 } // Zero out whatever was not defaulted, including time
5789
5790
5791 for (; i < 7; i++) {
5792 config._a[i] = input[i] = config._a[i] == null ? i === 2 ? 1 : 0 : config._a[i];
5793 } // Check for 24:00:00.000
5794
5795
5796 if (config._a[HOUR] === 24 && config._a[MINUTE] === 0 && config._a[SECOND] === 0 && config._a[MILLISECOND] === 0) {
5797 config._nextDay = true;
5798 config._a[HOUR] = 0;
5799 }
5800
5801 config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
5802 expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay(); // Apply timezone offset from input. The actual utcOffset can be changed
5803 // with parseZone.
5804
5805 if (config._tzm != null) {
5806 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
5807 }
5808
5809 if (config._nextDay) {
5810 config._a[HOUR] = 24;
5811 } // check for mismatching day of week
5812
5813
5814 if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) {
5815 getParsingFlags(config).weekdayMismatch = true;
5816 }
5817 }
5818
5819 function dayOfYearFromWeekInfo(config) {
5820 var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
5821 w = config._w;
5822
5823 if (w.GG != null || w.W != null || w.E != null) {
5824 dow = 1;
5825 doy = 4; // TODO: We need to take the current isoWeekYear, but that depends on
5826 // how we interpret now (local, utc, fixed offset). So create
5827 // a now version of current config (take local/utc/offset flags, and
5828 // create now).
5829
5830 weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
5831 week = defaults(w.W, 1);
5832 weekday = defaults(w.E, 1);
5833
5834 if (weekday < 1 || weekday > 7) {
5835 weekdayOverflow = true;
5836 }
5837 } else {
5838 dow = config._locale._week.dow;
5839 doy = config._locale._week.doy;
5840 var curWeek = weekOfYear(createLocal(), dow, doy);
5841 weekYear = defaults(w.gg, config._a[YEAR], curWeek.year); // Default to current week.
5842
5843 week = defaults(w.w, curWeek.week);
5844
5845 if (w.d != null) {
5846 // weekday -- low day numbers are considered next week
5847 weekday = w.d;
5848
5849 if (weekday < 0 || weekday > 6) {
5850 weekdayOverflow = true;
5851 }
5852 } else if (w.e != null) {
5853 // local weekday -- counting starts from beginning of week
5854 weekday = w.e + dow;
5855
5856 if (w.e < 0 || w.e > 6) {
5857 weekdayOverflow = true;
5858 }
5859 } else {
5860 // default to beginning of week
5861 weekday = dow;
5862 }
5863 }
5864
5865 if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
5866 getParsingFlags(config)._overflowWeeks = true;
5867 } else if (weekdayOverflow != null) {
5868 getParsingFlags(config)._overflowWeekday = true;
5869 } else {
5870 temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
5871 config._a[YEAR] = temp.year;
5872 config._dayOfYear = temp.dayOfYear;
5873 }
5874 } // iso 8601 regex
5875 // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
5876
5877
5878 var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
5879 var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
5880 var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
5881 var isoDates = [['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], ['GGGG-[W]WW', /\d{4}-W\d\d/, false], ['YYYY-DDD', /\d{4}-\d{3}/], ['YYYY-MM', /\d{4}-\d\d/, false], ['YYYYYYMMDD', /[+-]\d{10}/], ['YYYYMMDD', /\d{8}/], // YYYYMM is NOT allowed by the standard
5882 ['GGGG[W]WWE', /\d{4}W\d{3}/], ['GGGG[W]WW', /\d{4}W\d{2}/, false], ['YYYYDDD', /\d{7}/]]; // iso time formats and regexes
5883
5884 var isoTimes = [['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], ['HH:mm:ss', /\d\d:\d\d:\d\d/], ['HH:mm', /\d\d:\d\d/], ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], ['HHmmss', /\d\d\d\d\d\d/], ['HHmm', /\d\d\d\d/], ['HH', /\d\d/]];
5885 var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; // date from iso format
5886
5887 function configFromISO(config) {
5888 var i,
5889 l,
5890 string = config._i,
5891 match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
5892 allowTime,
5893 dateFormat,
5894 timeFormat,
5895 tzFormat;
5896
5897 if (match) {
5898 getParsingFlags(config).iso = true;
5899
5900 for (i = 0, l = isoDates.length; i < l; i++) {
5901 if (isoDates[i][1].exec(match[1])) {
5902 dateFormat = isoDates[i][0];
5903 allowTime = isoDates[i][2] !== false;
5904 break;
5905 }
5906 }
5907
5908 if (dateFormat == null) {
5909 config._isValid = false;
5910 return;
5911 }
5912
5913 if (match[3]) {
5914 for (i = 0, l = isoTimes.length; i < l; i++) {
5915 if (isoTimes[i][1].exec(match[3])) {
5916 // match[2] should be 'T' or space
5917 timeFormat = (match[2] || ' ') + isoTimes[i][0];
5918 break;
5919 }
5920 }
5921
5922 if (timeFormat == null) {
5923 config._isValid = false;
5924 return;
5925 }
5926 }
5927
5928 if (!allowTime && timeFormat != null) {
5929 config._isValid = false;
5930 return;
5931 }
5932
5933 if (match[4]) {
5934 if (tzRegex.exec(match[4])) {
5935 tzFormat = 'Z';
5936 } else {
5937 config._isValid = false;
5938 return;
5939 }
5940 }
5941
5942 config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
5943 configFromStringAndFormat(config);
5944 } else {
5945 config._isValid = false;
5946 }
5947 } // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
5948
5949
5950 var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
5951
5952 function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
5953 var result = [untruncateYear(yearStr), defaultLocaleMonthsShort.indexOf(monthStr), parseInt(dayStr, 10), parseInt(hourStr, 10), parseInt(minuteStr, 10)];
5954
5955 if (secondStr) {
5956 result.push(parseInt(secondStr, 10));
5957 }
5958
5959 return result;
5960 }
5961
5962 function untruncateYear(yearStr) {
5963 var year = parseInt(yearStr, 10);
5964
5965 if (year <= 49) {
5966 return 2000 + year;
5967 } else if (year <= 999) {
5968 return 1900 + year;
5969 }
5970
5971 return year;
5972 }
5973
5974 function preprocessRFC2822(s) {
5975 // Remove comments and folding whitespace and replace multiple-spaces with a single space
5976 return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
5977 }
5978
5979 function checkWeekday(weekdayStr, parsedInput, config) {
5980 if (weekdayStr) {
5981 // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
5982 var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
5983 weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
5984
5985 if (weekdayProvided !== weekdayActual) {
5986 getParsingFlags(config).weekdayMismatch = true;
5987 config._isValid = false;
5988 return false;
5989 }
5990 }
5991
5992 return true;
5993 }
5994
5995 var obsOffsets = {
5996 UT: 0,
5997 GMT: 0,
5998 EDT: -4 * 60,
5999 EST: -5 * 60,
6000 CDT: -5 * 60,
6001 CST: -6 * 60,
6002 MDT: -6 * 60,
6003 MST: -7 * 60,
6004 PDT: -7 * 60,
6005 PST: -8 * 60
6006 };
6007
6008 function calculateOffset(obsOffset, militaryOffset, numOffset) {
6009 if (obsOffset) {
6010 return obsOffsets[obsOffset];
6011 } else if (militaryOffset) {
6012 // the only allowed military tz is Z
6013 return 0;
6014 } else {
6015 var hm = parseInt(numOffset, 10);
6016 var m = hm % 100,
6017 h = (hm - m) / 100;
6018 return h * 60 + m;
6019 }
6020 } // date and time from ref 2822 format
6021
6022
6023 function configFromRFC2822(config) {
6024 var match = rfc2822.exec(preprocessRFC2822(config._i));
6025
6026 if (match) {
6027 var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
6028
6029 if (!checkWeekday(match[1], parsedArray, config)) {
6030 return;
6031 }
6032
6033 config._a = parsedArray;
6034 config._tzm = calculateOffset(match[8], match[9], match[10]);
6035 config._d = createUTCDate.apply(null, config._a);
6036
6037 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
6038
6039 getParsingFlags(config).rfc2822 = true;
6040 } else {
6041 config._isValid = false;
6042 }
6043 } // date from iso format or fallback
6044
6045
6046 function configFromString(config) {
6047 var matched = aspNetJsonRegex.exec(config._i);
6048
6049 if (matched !== null) {
6050 config._d = new Date(+matched[1]);
6051 return;
6052 }
6053
6054 configFromISO(config);
6055
6056 if (config._isValid === false) {
6057 delete config._isValid;
6058 } else {
6059 return;
6060 }
6061
6062 configFromRFC2822(config);
6063
6064 if (config._isValid === false) {
6065 delete config._isValid;
6066 } else {
6067 return;
6068 } // Final attempt, use Input Fallback
6069
6070
6071 hooks.createFromInputFallback(config);
6072 }
6073
6074 hooks.createFromInputFallback = deprecate('value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' + 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' + 'discouraged and will be removed in an upcoming major release. Please refer to ' + 'http://momentjs.com/guides/#/warnings/js-date/ for more info.', function (config) {
6075 config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
6076 }); // constant that refers to the ISO standard
6077
6078 hooks.ISO_8601 = function () {}; // constant that refers to the RFC 2822 form
6079
6080
6081 hooks.RFC_2822 = function () {}; // date from string and format string
6082
6083
6084 function configFromStringAndFormat(config) {
6085 // TODO: Move this to another part of the creation flow to prevent circular deps
6086 if (config._f === hooks.ISO_8601) {
6087 configFromISO(config);
6088 return;
6089 }
6090
6091 if (config._f === hooks.RFC_2822) {
6092 configFromRFC2822(config);
6093 return;
6094 }
6095
6096 config._a = [];
6097 getParsingFlags(config).empty = true; // This array is used to make a Date, either with `new Date` or `Date.UTC`
6098
6099 var string = '' + config._i,
6100 i,
6101 parsedInput,
6102 tokens,
6103 token,
6104 skipped,
6105 stringLength = string.length,
6106 totalParsedInputLength = 0;
6107 tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
6108
6109 for (i = 0; i < tokens.length; i++) {
6110 token = tokens[i];
6111 parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; // console.log('token', token, 'parsedInput', parsedInput,
6112 // 'regex', getParseRegexForToken(token, config));
6113
6114 if (parsedInput) {
6115 skipped = string.substr(0, string.indexOf(parsedInput));
6116
6117 if (skipped.length > 0) {
6118 getParsingFlags(config).unusedInput.push(skipped);
6119 }
6120
6121 string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
6122 totalParsedInputLength += parsedInput.length;
6123 } // don't parse if it's not a known token
6124
6125
6126 if (formatTokenFunctions[token]) {
6127 if (parsedInput) {
6128 getParsingFlags(config).empty = false;
6129 } else {
6130 getParsingFlags(config).unusedTokens.push(token);
6131 }
6132
6133 addTimeToArrayFromToken(token, parsedInput, config);
6134 } else if (config._strict && !parsedInput) {
6135 getParsingFlags(config).unusedTokens.push(token);
6136 }
6137 } // add remaining unparsed input length to the string
6138
6139
6140 getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
6141
6142 if (string.length > 0) {
6143 getParsingFlags(config).unusedInput.push(string);
6144 } // clear _12h flag if hour is <= 12
6145
6146
6147 if (config._a[HOUR] <= 12 && getParsingFlags(config).bigHour === true && config._a[HOUR] > 0) {
6148 getParsingFlags(config).bigHour = undefined;
6149 }
6150
6151 getParsingFlags(config).parsedDateParts = config._a.slice(0);
6152 getParsingFlags(config).meridiem = config._meridiem; // handle meridiem
6153
6154 config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
6155 configFromArray(config);
6156 checkOverflow(config);
6157 }
6158
6159 function meridiemFixWrap(locale, hour, meridiem) {
6160 var isPm;
6161
6162 if (meridiem == null) {
6163 // nothing to do
6164 return hour;
6165 }
6166
6167 if (locale.meridiemHour != null) {
6168 return locale.meridiemHour(hour, meridiem);
6169 } else if (locale.isPM != null) {
6170 // Fallback
6171 isPm = locale.isPM(meridiem);
6172
6173 if (isPm && hour < 12) {
6174 hour += 12;
6175 }
6176
6177 if (!isPm && hour === 12) {
6178 hour = 0;
6179 }
6180
6181 return hour;
6182 } else {
6183 // this is not supposed to happen
6184 return hour;
6185 }
6186 } // date from string and array of format strings
6187
6188
6189 function configFromStringAndArray(config) {
6190 var tempConfig, bestMoment, scoreToBeat, i, currentScore;
6191
6192 if (config._f.length === 0) {
6193 getParsingFlags(config).invalidFormat = true;
6194 config._d = new Date(NaN);
6195 return;
6196 }
6197
6198 for (i = 0; i < config._f.length; i++) {
6199 currentScore = 0;
6200 tempConfig = copyConfig({}, config);
6201
6202 if (config._useUTC != null) {
6203 tempConfig._useUTC = config._useUTC;
6204 }
6205
6206 tempConfig._f = config._f[i];
6207 configFromStringAndFormat(tempConfig);
6208
6209 if (!isValid(tempConfig)) {
6210 continue;
6211 } // if there is any input that was not parsed add a penalty for that format
6212
6213
6214 currentScore += getParsingFlags(tempConfig).charsLeftOver; //or tokens
6215
6216 currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
6217 getParsingFlags(tempConfig).score = currentScore;
6218
6219 if (scoreToBeat == null || currentScore < scoreToBeat) {
6220 scoreToBeat = currentScore;
6221 bestMoment = tempConfig;
6222 }
6223 }
6224
6225 extend(config, bestMoment || tempConfig);
6226 }
6227
6228 function configFromObject(config) {
6229 if (config._d) {
6230 return;
6231 }
6232
6233 var i = normalizeObjectUnits(config._i);
6234 config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
6235 return obj && parseInt(obj, 10);
6236 });
6237 configFromArray(config);
6238 }
6239
6240 function createFromConfig(config) {
6241 var res = new Moment(checkOverflow(prepareConfig(config)));
6242
6243 if (res._nextDay) {
6244 // Adding is smart enough around DST
6245 res.add(1, 'd');
6246 res._nextDay = undefined;
6247 }
6248
6249 return res;
6250 }
6251
6252 function prepareConfig(config) {
6253 var input = config._i,
6254 format = config._f;
6255 config._locale = config._locale || getLocale(config._l);
6256
6257 if (input === null || format === undefined && input === '') {
6258 return createInvalid({
6259 nullInput: true
6260 });
6261 }
6262
6263 if (typeof input === 'string') {
6264 config._i = input = config._locale.preparse(input);
6265 }
6266
6267 if (isMoment(input)) {
6268 return new Moment(checkOverflow(input));
6269 } else if (isDate(input)) {
6270 config._d = input;
6271 } else if (isArray(format)) {
6272 configFromStringAndArray(config);
6273 } else if (format) {
6274 configFromStringAndFormat(config);
6275 } else {
6276 configFromInput(config);
6277 }
6278
6279 if (!isValid(config)) {
6280 config._d = null;
6281 }
6282
6283 return config;
6284 }
6285
6286 function configFromInput(config) {
6287 var input = config._i;
6288
6289 if (isUndefined(input)) {
6290 config._d = new Date(hooks.now());
6291 } else if (isDate(input)) {
6292 config._d = new Date(input.valueOf());
6293 } else if (typeof input === 'string') {
6294 configFromString(config);
6295 } else if (isArray(input)) {
6296 config._a = map(input.slice(0), function (obj) {
6297 return parseInt(obj, 10);
6298 });
6299 configFromArray(config);
6300 } else if (isObject(input)) {
6301 configFromObject(config);
6302 } else if (isNumber(input)) {
6303 // from milliseconds
6304 config._d = new Date(input);
6305 } else {
6306 hooks.createFromInputFallback(config);
6307 }
6308 }
6309
6310 function createLocalOrUTC(input, format, locale, strict, isUTC) {
6311 var c = {};
6312
6313 if (locale === true || locale === false) {
6314 strict = locale;
6315 locale = undefined;
6316 }
6317
6318 if (isObject(input) && isObjectEmpty(input) || isArray(input) && input.length === 0) {
6319 input = undefined;
6320 } // object construction must be done this way.
6321 // https://github.com/moment/moment/issues/1423
6322
6323
6324 c._isAMomentObject = true;
6325 c._useUTC = c._isUTC = isUTC;
6326 c._l = locale;
6327 c._i = input;
6328 c._f = format;
6329 c._strict = strict;
6330 return createFromConfig(c);
6331 }
6332
6333 function createLocal(input, format, locale, strict) {
6334 return createLocalOrUTC(input, format, locale, strict, false);
6335 }
6336
6337 var prototypeMin = deprecate('moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', function () {
6338 var other = createLocal.apply(null, arguments);
6339
6340 if (this.isValid() && other.isValid()) {
6341 return other < this ? this : other;
6342 } else {
6343 return createInvalid();
6344 }
6345 });
6346 var prototypeMax = deprecate('moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', function () {
6347 var other = createLocal.apply(null, arguments);
6348
6349 if (this.isValid() && other.isValid()) {
6350 return other > this ? this : other;
6351 } else {
6352 return createInvalid();
6353 }
6354 }); // Pick a moment m from moments so that m[fn](other) is true for all
6355 // other. This relies on the function fn to be transitive.
6356 //
6357 // moments should either be an array of moment objects or an array, whose
6358 // first element is an array of moment objects.
6359
6360 function pickBy(fn, moments) {
6361 var res, i;
6362
6363 if (moments.length === 1 && isArray(moments[0])) {
6364 moments = moments[0];
6365 }
6366
6367 if (!moments.length) {
6368 return createLocal();
6369 }
6370
6371 res = moments[0];
6372
6373 for (i = 1; i < moments.length; ++i) {
6374 if (!moments[i].isValid() || moments[i][fn](res)) {
6375 res = moments[i];
6376 }
6377 }
6378
6379 return res;
6380 } // TODO: Use [].sort instead?
6381
6382
6383 function min() {
6384 var args = [].slice.call(arguments, 0);
6385 return pickBy('isBefore', args);
6386 }
6387
6388 function max() {
6389 var args = [].slice.call(arguments, 0);
6390 return pickBy('isAfter', args);
6391 }
6392
6393 var now = function () {
6394 return Date.now ? Date.now() : +new Date();
6395 };
6396
6397 var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
6398
6399 function isDurationValid(m) {
6400 for (var key in m) {
6401 if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
6402 return false;
6403 }
6404 }
6405
6406 var unitHasDecimal = false;
6407
6408 for (var i = 0; i < ordering.length; ++i) {
6409 if (m[ordering[i]]) {
6410 if (unitHasDecimal) {
6411 return false; // only allow non-integers for smallest unit
6412 }
6413
6414 if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
6415 unitHasDecimal = true;
6416 }
6417 }
6418 }
6419
6420 return true;
6421 }
6422
6423 function isValid$1() {
6424 return this._isValid;
6425 }
6426
6427 function createInvalid$1() {
6428 return createDuration(NaN);
6429 }
6430
6431 function Duration(duration) {
6432 var normalizedInput = normalizeObjectUnits(duration),
6433 years = normalizedInput.year || 0,
6434 quarters = normalizedInput.quarter || 0,
6435 months = normalizedInput.month || 0,
6436 weeks = normalizedInput.week || normalizedInput.isoWeek || 0,
6437 days = normalizedInput.day || 0,
6438 hours = normalizedInput.hour || 0,
6439 minutes = normalizedInput.minute || 0,
6440 seconds = normalizedInput.second || 0,
6441 milliseconds = normalizedInput.millisecond || 0;
6442 this._isValid = isDurationValid(normalizedInput); // representation for dateAddRemove
6443
6444 this._milliseconds = +milliseconds + seconds * 1e3 + // 1000
6445 minutes * 6e4 + // 1000 * 60
6446 hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
6447 // Because of dateAddRemove treats 24 hours as different from a
6448 // day when working around DST, we need to store them separately
6449
6450 this._days = +days + weeks * 7; // It is impossible to translate months into days without knowing
6451 // which months you are are talking about, so we have to store
6452 // it separately.
6453
6454 this._months = +months + quarters * 3 + years * 12;
6455 this._data = {};
6456 this._locale = getLocale();
6457
6458 this._bubble();
6459 }
6460
6461 function isDuration(obj) {
6462 return obj instanceof Duration;
6463 }
6464
6465 function absRound(number) {
6466 if (number < 0) {
6467 return Math.round(-1 * number) * -1;
6468 } else {
6469 return Math.round(number);
6470 }
6471 } // FORMATTING
6472
6473
6474 function offset(token, separator) {
6475 addFormatToken(token, 0, 0, function () {
6476 var offset = this.utcOffset();
6477 var sign = '+';
6478
6479 if (offset < 0) {
6480 offset = -offset;
6481 sign = '-';
6482 }
6483
6484 return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~offset % 60, 2);
6485 });
6486 }
6487
6488 offset('Z', ':');
6489 offset('ZZ', ''); // PARSING
6490
6491 addRegexToken('Z', matchShortOffset);
6492 addRegexToken('ZZ', matchShortOffset);
6493 addParseToken(['Z', 'ZZ'], function (input, array, config) {
6494 config._useUTC = true;
6495 config._tzm = offsetFromString(matchShortOffset, input);
6496 }); // HELPERS
6497 // timezone chunker
6498 // '+10:00' > ['10', '00']
6499 // '-1530' > ['-15', '30']
6500
6501 var chunkOffset = /([\+\-]|\d\d)/gi;
6502
6503 function offsetFromString(matcher, string) {
6504 var matches = (string || '').match(matcher);
6505
6506 if (matches === null) {
6507 return null;
6508 }
6509
6510 var chunk = matches[matches.length - 1] || [];
6511 var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
6512 var minutes = +(parts[1] * 60) + toInt(parts[2]);
6513 return minutes === 0 ? 0 : parts[0] === '+' ? minutes : -minutes;
6514 } // Return a moment from input, that is local/utc/zone equivalent to model.
6515
6516
6517 function cloneWithOffset(input, model) {
6518 var res, diff;
6519
6520 if (model._isUTC) {
6521 res = model.clone();
6522 diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf(); // Use low-level api, because this fn is low-level api.
6523
6524 res._d.setTime(res._d.valueOf() + diff);
6525
6526 hooks.updateOffset(res, false);
6527 return res;
6528 } else {
6529 return createLocal(input).local();
6530 }
6531 }
6532
6533 function getDateOffset(m) {
6534 // On Firefox.24 Date#getTimezoneOffset returns a floating point.
6535 // https://github.com/moment/moment/pull/1871
6536 return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
6537 } // HOOKS
6538 // This function will be called whenever a moment is mutated.
6539 // It is intended to keep the offset in sync with the timezone.
6540
6541
6542 hooks.updateOffset = function () {}; // MOMENTS
6543 // keepLocalTime = true means only change the timezone, without
6544 // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
6545 // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
6546 // +0200, so we adjust the time as needed, to be valid.
6547 //
6548 // Keeping the time actually adds/subtracts (one hour)
6549 // from the actual represented time. That is why we call updateOffset
6550 // a second time. In case it wants us to change the offset again
6551 // _changeInProgress == true case, then we have to adjust, because
6552 // there is no such time in the given timezone.
6553
6554
6555 function getSetOffset(input, keepLocalTime, keepMinutes) {
6556 var offset = this._offset || 0,
6557 localAdjust;
6558
6559 if (!this.isValid()) {
6560 return input != null ? this : NaN;
6561 }
6562
6563 if (input != null) {
6564 if (typeof input === 'string') {
6565 input = offsetFromString(matchShortOffset, input);
6566
6567 if (input === null) {
6568 return this;
6569 }
6570 } else if (Math.abs(input) < 16 && !keepMinutes) {
6571 input = input * 60;
6572 }
6573
6574 if (!this._isUTC && keepLocalTime) {
6575 localAdjust = getDateOffset(this);
6576 }
6577
6578 this._offset = input;
6579 this._isUTC = true;
6580
6581 if (localAdjust != null) {
6582 this.add(localAdjust, 'm');
6583 }
6584
6585 if (offset !== input) {
6586 if (!keepLocalTime || this._changeInProgress) {
6587 addSubtract(this, createDuration(input - offset, 'm'), 1, false);
6588 } else if (!this._changeInProgress) {
6589 this._changeInProgress = true;
6590 hooks.updateOffset(this, true);
6591 this._changeInProgress = null;
6592 }
6593 }
6594
6595 return this;
6596 } else {
6597 return this._isUTC ? offset : getDateOffset(this);
6598 }
6599 }
6600
6601 function getSetZone(input, keepLocalTime) {
6602 if (input != null) {
6603 if (typeof input !== 'string') {
6604 input = -input;
6605 }
6606
6607 this.utcOffset(input, keepLocalTime);
6608 return this;
6609 } else {
6610 return -this.utcOffset();
6611 }
6612 }
6613
6614 function setOffsetToUTC(keepLocalTime) {
6615 return this.utcOffset(0, keepLocalTime);
6616 }
6617
6618 function setOffsetToLocal(keepLocalTime) {
6619 if (this._isUTC) {
6620 this.utcOffset(0, keepLocalTime);
6621 this._isUTC = false;
6622
6623 if (keepLocalTime) {
6624 this.subtract(getDateOffset(this), 'm');
6625 }
6626 }
6627
6628 return this;
6629 }
6630
6631 function setOffsetToParsedOffset() {
6632 if (this._tzm != null) {
6633 this.utcOffset(this._tzm, false, true);
6634 } else if (typeof this._i === 'string') {
6635 var tZone = offsetFromString(matchOffset, this._i);
6636
6637 if (tZone != null) {
6638 this.utcOffset(tZone);
6639 } else {
6640 this.utcOffset(0, true);
6641 }
6642 }
6643
6644 return this;
6645 }
6646
6647 function hasAlignedHourOffset(input) {
6648 if (!this.isValid()) {
6649 return false;
6650 }
6651
6652 input = input ? createLocal(input).utcOffset() : 0;
6653 return (this.utcOffset() - input) % 60 === 0;
6654 }
6655
6656 function isDaylightSavingTime() {
6657 return this.utcOffset() > this.clone().month(0).utcOffset() || this.utcOffset() > this.clone().month(5).utcOffset();
6658 }
6659
6660 function isDaylightSavingTimeShifted() {
6661 if (!isUndefined(this._isDSTShifted)) {
6662 return this._isDSTShifted;
6663 }
6664
6665 var c = {};
6666 copyConfig(c, this);
6667 c = prepareConfig(c);
6668
6669 if (c._a) {
6670 var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
6671 this._isDSTShifted = this.isValid() && compareArrays(c._a, other.toArray()) > 0;
6672 } else {
6673 this._isDSTShifted = false;
6674 }
6675
6676 return this._isDSTShifted;
6677 }
6678
6679 function isLocal() {
6680 return this.isValid() ? !this._isUTC : false;
6681 }
6682
6683 function isUtcOffset() {
6684 return this.isValid() ? this._isUTC : false;
6685 }
6686
6687 function isUtc() {
6688 return this.isValid() ? this._isUTC && this._offset === 0 : false;
6689 } // ASP.NET json date format regex
6690
6691
6692 var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/; // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
6693 // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
6694 // and further modified to allow for strings containing both week and day
6695
6696 var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
6697
6698 function createDuration(input, key) {
6699 var duration = input,
6700 // matching against regexp is expensive, do it on demand
6701 match = null,
6702 sign,
6703 ret,
6704 diffRes;
6705
6706 if (isDuration(input)) {
6707 duration = {
6708 ms: input._milliseconds,
6709 d: input._days,
6710 M: input._months
6711 };
6712 } else if (isNumber(input)) {
6713 duration = {};
6714
6715 if (key) {
6716 duration[key] = input;
6717 } else {
6718 duration.milliseconds = input;
6719 }
6720 } else if (!!(match = aspNetRegex.exec(input))) {
6721 sign = match[1] === '-' ? -1 : 1;
6722 duration = {
6723 y: 0,
6724 d: toInt(match[DATE]) * sign,
6725 h: toInt(match[HOUR]) * sign,
6726 m: toInt(match[MINUTE]) * sign,
6727 s: toInt(match[SECOND]) * sign,
6728 ms: toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
6729
6730 };
6731 } else if (!!(match = isoRegex.exec(input))) {
6732 sign = match[1] === '-' ? -1 : 1;
6733 duration = {
6734 y: parseIso(match[2], sign),
6735 M: parseIso(match[3], sign),
6736 w: parseIso(match[4], sign),
6737 d: parseIso(match[5], sign),
6738 h: parseIso(match[6], sign),
6739 m: parseIso(match[7], sign),
6740 s: parseIso(match[8], sign)
6741 };
6742 } else if (duration == null) {
6743 // checks for null or undefined
6744 duration = {};
6745 } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
6746 diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
6747 duration = {};
6748 duration.ms = diffRes.milliseconds;
6749 duration.M = diffRes.months;
6750 }
6751
6752 ret = new Duration(duration);
6753
6754 if (isDuration(input) && hasOwnProp(input, '_locale')) {
6755 ret._locale = input._locale;
6756 }
6757
6758 return ret;
6759 }
6760
6761 createDuration.fn = Duration.prototype;
6762 createDuration.invalid = createInvalid$1;
6763
6764 function parseIso(inp, sign) {
6765 // We'd normally use ~~inp for this, but unfortunately it also
6766 // converts floats to ints.
6767 // inp may be undefined, so careful calling replace on it.
6768 var res = inp && parseFloat(inp.replace(',', '.')); // apply sign while we're at it
6769
6770 return (isNaN(res) ? 0 : res) * sign;
6771 }
6772
6773 function positiveMomentsDifference(base, other) {
6774 var res = {};
6775 res.months = other.month() - base.month() + (other.year() - base.year()) * 12;
6776
6777 if (base.clone().add(res.months, 'M').isAfter(other)) {
6778 --res.months;
6779 }
6780
6781 res.milliseconds = +other - +base.clone().add(res.months, 'M');
6782 return res;
6783 }
6784
6785 function momentsDifference(base, other) {
6786 var res;
6787
6788 if (!(base.isValid() && other.isValid())) {
6789 return {
6790 milliseconds: 0,
6791 months: 0
6792 };
6793 }
6794
6795 other = cloneWithOffset(other, base);
6796
6797 if (base.isBefore(other)) {
6798 res = positiveMomentsDifference(base, other);
6799 } else {
6800 res = positiveMomentsDifference(other, base);
6801 res.milliseconds = -res.milliseconds;
6802 res.months = -res.months;
6803 }
6804
6805 return res;
6806 } // TODO: remove 'name' arg after deprecation is removed
6807
6808
6809 function createAdder(direction, name) {
6810 return function (val, period) {
6811 var dur, tmp; //invert the arguments, but complain about it
6812
6813 if (period !== null && !isNaN(+period)) {
6814 deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' + 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
6815 tmp = val;
6816 val = period;
6817 period = tmp;
6818 }
6819
6820 val = typeof val === 'string' ? +val : val;
6821 dur = createDuration(val, period);
6822 addSubtract(this, dur, direction);
6823 return this;
6824 };
6825 }
6826
6827 function addSubtract(mom, duration, isAdding, updateOffset) {
6828 var milliseconds = duration._milliseconds,
6829 days = absRound(duration._days),
6830 months = absRound(duration._months);
6831
6832 if (!mom.isValid()) {
6833 // No op
6834 return;
6835 }
6836
6837 updateOffset = updateOffset == null ? true : updateOffset;
6838
6839 if (months) {
6840 setMonth(mom, get(mom, 'Month') + months * isAdding);
6841 }
6842
6843 if (days) {
6844 set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
6845 }
6846
6847 if (milliseconds) {
6848 mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
6849 }
6850
6851 if (updateOffset) {
6852 hooks.updateOffset(mom, days || months);
6853 }
6854 }
6855
6856 var add = createAdder(1, 'add');
6857 var subtract = createAdder(-1, 'subtract');
6858
6859 function getCalendarFormat(myMoment, now) {
6860 var diff = myMoment.diff(now, 'days', true);
6861 return diff < -6 ? 'sameElse' : diff < -1 ? 'lastWeek' : diff < 0 ? 'lastDay' : diff < 1 ? 'sameDay' : diff < 2 ? 'nextDay' : diff < 7 ? 'nextWeek' : 'sameElse';
6862 }
6863
6864 function calendar$1(time, formats) {
6865 // We want to compare the start of today, vs this.
6866 // Getting start-of-today depends on whether we're local/utc/offset or not.
6867 var now = time || createLocal(),
6868 sod = cloneWithOffset(now, this).startOf('day'),
6869 format = hooks.calendarFormat(this, sod) || 'sameElse';
6870 var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
6871 return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
6872 }
6873
6874 function clone() {
6875 return new Moment(this);
6876 }
6877
6878 function isAfter(input, units) {
6879 var localInput = isMoment(input) ? input : createLocal(input);
6880
6881 if (!(this.isValid() && localInput.isValid())) {
6882 return false;
6883 }
6884
6885 units = normalizeUnits(units) || 'millisecond';
6886
6887 if (units === 'millisecond') {
6888 return this.valueOf() > localInput.valueOf();
6889 } else {
6890 return localInput.valueOf() < this.clone().startOf(units).valueOf();
6891 }
6892 }
6893
6894 function isBefore(input, units) {
6895 var localInput = isMoment(input) ? input : createLocal(input);
6896
6897 if (!(this.isValid() && localInput.isValid())) {
6898 return false;
6899 }
6900
6901 units = normalizeUnits(units) || 'millisecond';
6902
6903 if (units === 'millisecond') {
6904 return this.valueOf() < localInput.valueOf();
6905 } else {
6906 return this.clone().endOf(units).valueOf() < localInput.valueOf();
6907 }
6908 }
6909
6910 function isBetween(from, to, units, inclusivity) {
6911 var localFrom = isMoment(from) ? from : createLocal(from),
6912 localTo = isMoment(to) ? to : createLocal(to);
6913
6914 if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
6915 return false;
6916 }
6917
6918 inclusivity = inclusivity || '()';
6919 return (inclusivity[0] === '(' ? this.isAfter(localFrom, units) : !this.isBefore(localFrom, units)) && (inclusivity[1] === ')' ? this.isBefore(localTo, units) : !this.isAfter(localTo, units));
6920 }
6921
6922 function isSame(input, units) {
6923 var localInput = isMoment(input) ? input : createLocal(input),
6924 inputMs;
6925
6926 if (!(this.isValid() && localInput.isValid())) {
6927 return false;
6928 }
6929
6930 units = normalizeUnits(units) || 'millisecond';
6931
6932 if (units === 'millisecond') {
6933 return this.valueOf() === localInput.valueOf();
6934 } else {
6935 inputMs = localInput.valueOf();
6936 return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
6937 }
6938 }
6939
6940 function isSameOrAfter(input, units) {
6941 return this.isSame(input, units) || this.isAfter(input, units);
6942 }
6943
6944 function isSameOrBefore(input, units) {
6945 return this.isSame(input, units) || this.isBefore(input, units);
6946 }
6947
6948 function diff(input, units, asFloat) {
6949 var that, zoneDelta, output;
6950
6951 if (!this.isValid()) {
6952 return NaN;
6953 }
6954
6955 that = cloneWithOffset(input, this);
6956
6957 if (!that.isValid()) {
6958 return NaN;
6959 }
6960
6961 zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
6962 units = normalizeUnits(units);
6963
6964 switch (units) {
6965 case 'year':
6966 output = monthDiff(this, that) / 12;
6967 break;
6968
6969 case 'month':
6970 output = monthDiff(this, that);
6971 break;
6972
6973 case 'quarter':
6974 output = monthDiff(this, that) / 3;
6975 break;
6976
6977 case 'second':
6978 output = (this - that) / 1e3;
6979 break;
6980 // 1000
6981
6982 case 'minute':
6983 output = (this - that) / 6e4;
6984 break;
6985 // 1000 * 60
6986
6987 case 'hour':
6988 output = (this - that) / 36e5;
6989 break;
6990 // 1000 * 60 * 60
6991
6992 case 'day':
6993 output = (this - that - zoneDelta) / 864e5;
6994 break;
6995 // 1000 * 60 * 60 * 24, negate dst
6996
6997 case 'week':
6998 output = (this - that - zoneDelta) / 6048e5;
6999 break;
7000 // 1000 * 60 * 60 * 24 * 7, negate dst
7001
7002 default:
7003 output = this - that;
7004 }
7005
7006 return asFloat ? output : absFloor(output);
7007 }
7008
7009 function monthDiff(a, b) {
7010 // difference in months
7011 var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()),
7012 // b is in (anchor - 1 month, anchor + 1 month)
7013 anchor = a.clone().add(wholeMonthDiff, 'months'),
7014 anchor2,
7015 adjust;
7016
7017 if (b - anchor < 0) {
7018 anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); // linear across the month
7019
7020 adjust = (b - anchor) / (anchor - anchor2);
7021 } else {
7022 anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); // linear across the month
7023
7024 adjust = (b - anchor) / (anchor2 - anchor);
7025 } //check for negative zero, return zero if negative zero
7026
7027
7028 return -(wholeMonthDiff + adjust) || 0;
7029 }
7030
7031 hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
7032 hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
7033
7034 function toString() {
7035 return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
7036 }
7037
7038 function toISOString(keepOffset) {
7039 if (!this.isValid()) {
7040 return null;
7041 }
7042
7043 var utc = keepOffset !== true;
7044 var m = utc ? this.clone().utc() : this;
7045
7046 if (m.year() < 0 || m.year() > 9999) {
7047 return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ');
7048 }
7049
7050 if (isFunction(Date.prototype.toISOString)) {
7051 // native implementation is ~50x faster, use it when we can
7052 if (utc) {
7053 return this.toDate().toISOString();
7054 } else {
7055 return new Date(this.valueOf() + this.utcOffset() * 60 * 1000).toISOString().replace('Z', formatMoment(m, 'Z'));
7056 }
7057 }
7058
7059 return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
7060 }
7061 /**
7062 * Return a human readable representation of a moment that can
7063 * also be evaluated to get a new moment which is the same
7064 *
7065 * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
7066 */
7067
7068
7069 function inspect() {
7070 if (!this.isValid()) {
7071 return 'moment.invalid(/* ' + this._i + ' */)';
7072 }
7073
7074 var func = 'moment';
7075 var zone = '';
7076
7077 if (!this.isLocal()) {
7078 func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
7079 zone = 'Z';
7080 }
7081
7082 var prefix = '[' + func + '("]';
7083 var year = 0 <= this.year() && this.year() <= 9999 ? 'YYYY' : 'YYYYYY';
7084 var datetime = '-MM-DD[T]HH:mm:ss.SSS';
7085 var suffix = zone + '[")]';
7086 return this.format(prefix + year + datetime + suffix);
7087 }
7088
7089 function format(inputString) {
7090 if (!inputString) {
7091 inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
7092 }
7093
7094 var output = formatMoment(this, inputString);
7095 return this.localeData().postformat(output);
7096 }
7097
7098 function from(time, withoutSuffix) {
7099 if (this.isValid() && (isMoment(time) && time.isValid() || createLocal(time).isValid())) {
7100 return createDuration({
7101 to: this,
7102 from: time
7103 }).locale(this.locale()).humanize(!withoutSuffix);
7104 } else {
7105 return this.localeData().invalidDate();
7106 }
7107 }
7108
7109 function fromNow(withoutSuffix) {
7110 return this.from(createLocal(), withoutSuffix);
7111 }
7112
7113 function to(time, withoutSuffix) {
7114 if (this.isValid() && (isMoment(time) && time.isValid() || createLocal(time).isValid())) {
7115 return createDuration({
7116 from: this,
7117 to: time
7118 }).locale(this.locale()).humanize(!withoutSuffix);
7119 } else {
7120 return this.localeData().invalidDate();
7121 }
7122 }
7123
7124 function toNow(withoutSuffix) {
7125 return this.to(createLocal(), withoutSuffix);
7126 } // If passed a locale key, it will set the locale for this
7127 // instance. Otherwise, it will return the locale configuration
7128 // variables for this instance.
7129
7130
7131 function locale(key) {
7132 var newLocaleData;
7133
7134 if (key === undefined) {
7135 return this._locale._abbr;
7136 } else {
7137 newLocaleData = getLocale(key);
7138
7139 if (newLocaleData != null) {
7140 this._locale = newLocaleData;
7141 }
7142
7143 return this;
7144 }
7145 }
7146
7147 var lang = deprecate('moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', function (key) {
7148 if (key === undefined) {
7149 return this.localeData();
7150 } else {
7151 return this.locale(key);
7152 }
7153 });
7154
7155 function localeData() {
7156 return this._locale;
7157 }
7158
7159 var MS_PER_SECOND = 1000;
7160 var MS_PER_MINUTE = 60 * MS_PER_SECOND;
7161 var MS_PER_HOUR = 60 * MS_PER_MINUTE;
7162 var MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR; // actual modulo - handles negative numbers (for dates before 1970):
7163
7164 function mod$1(dividend, divisor) {
7165 return (dividend % divisor + divisor) % divisor;
7166 }
7167
7168 function localStartOfDate(y, m, d) {
7169 // the date constructor remaps years 0-99 to 1900-1999
7170 if (y < 100 && y >= 0) {
7171 // preserve leap years using a full 400 year cycle, then reset
7172 return new Date(y + 400, m, d) - MS_PER_400_YEARS;
7173 } else {
7174 return new Date(y, m, d).valueOf();
7175 }
7176 }
7177
7178 function utcStartOfDate(y, m, d) {
7179 // Date.UTC remaps years 0-99 to 1900-1999
7180 if (y < 100 && y >= 0) {
7181 // preserve leap years using a full 400 year cycle, then reset
7182 return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
7183 } else {
7184 return Date.UTC(y, m, d);
7185 }
7186 }
7187
7188 function startOf(units) {
7189 var time;
7190 units = normalizeUnits(units);
7191
7192 if (units === undefined || units === 'millisecond' || !this.isValid()) {
7193 return this;
7194 }
7195
7196 var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
7197
7198 switch (units) {
7199 case 'year':
7200 time = startOfDate(this.year(), 0, 1);
7201 break;
7202
7203 case 'quarter':
7204 time = startOfDate(this.year(), this.month() - this.month() % 3, 1);
7205 break;
7206
7207 case 'month':
7208 time = startOfDate(this.year(), this.month(), 1);
7209 break;
7210
7211 case 'week':
7212 time = startOfDate(this.year(), this.month(), this.date() - this.weekday());
7213 break;
7214
7215 case 'isoWeek':
7216 time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1));
7217 break;
7218
7219 case 'day':
7220 case 'date':
7221 time = startOfDate(this.year(), this.month(), this.date());
7222 break;
7223
7224 case 'hour':
7225 time = this._d.valueOf();
7226 time -= mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR);
7227 break;
7228
7229 case 'minute':
7230 time = this._d.valueOf();
7231 time -= mod$1(time, MS_PER_MINUTE);
7232 break;
7233
7234 case 'second':
7235 time = this._d.valueOf();
7236 time -= mod$1(time, MS_PER_SECOND);
7237 break;
7238 }
7239
7240 this._d.setTime(time);
7241
7242 hooks.updateOffset(this, true);
7243 return this;
7244 }
7245
7246 function endOf(units) {
7247 var time;
7248 units = normalizeUnits(units);
7249
7250 if (units === undefined || units === 'millisecond' || !this.isValid()) {
7251 return this;
7252 }
7253
7254 var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
7255
7256 switch (units) {
7257 case 'year':
7258 time = startOfDate(this.year() + 1, 0, 1) - 1;
7259 break;
7260
7261 case 'quarter':
7262 time = startOfDate(this.year(), this.month() - this.month() % 3 + 3, 1) - 1;
7263 break;
7264
7265 case 'month':
7266 time = startOfDate(this.year(), this.month() + 1, 1) - 1;
7267 break;
7268
7269 case 'week':
7270 time = startOfDate(this.year(), this.month(), this.date() - this.weekday() + 7) - 1;
7271 break;
7272
7273 case 'isoWeek':
7274 time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1) + 7) - 1;
7275 break;
7276
7277 case 'day':
7278 case 'date':
7279 time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
7280 break;
7281
7282 case 'hour':
7283 time = this._d.valueOf();
7284 time += MS_PER_HOUR - mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR) - 1;
7285 break;
7286
7287 case 'minute':
7288 time = this._d.valueOf();
7289 time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
7290 break;
7291
7292 case 'second':
7293 time = this._d.valueOf();
7294 time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
7295 break;
7296 }
7297
7298 this._d.setTime(time);
7299
7300 hooks.updateOffset(this, true);
7301 return this;
7302 }
7303
7304 function valueOf() {
7305 return this._d.valueOf() - (this._offset || 0) * 60000;
7306 }
7307
7308 function unix() {
7309 return Math.floor(this.valueOf() / 1000);
7310 }
7311
7312 function toDate() {
7313 return new Date(this.valueOf());
7314 }
7315
7316 function toArray() {
7317 var m = this;
7318 return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
7319 }
7320
7321 function toObject() {
7322 var m = this;
7323 return {
7324 years: m.year(),
7325 months: m.month(),
7326 date: m.date(),
7327 hours: m.hours(),
7328 minutes: m.minutes(),
7329 seconds: m.seconds(),
7330 milliseconds: m.milliseconds()
7331 };
7332 }
7333
7334 function toJSON() {
7335 // new Date(NaN).toJSON() === null
7336 return this.isValid() ? this.toISOString() : null;
7337 }
7338
7339 function isValid$2() {
7340 return isValid(this);
7341 }
7342
7343 function parsingFlags() {
7344 return extend({}, getParsingFlags(this));
7345 }
7346
7347 function invalidAt() {
7348 return getParsingFlags(this).overflow;
7349 }
7350
7351 function creationData() {
7352 return {
7353 input: this._i,
7354 format: this._f,
7355 locale: this._locale,
7356 isUTC: this._isUTC,
7357 strict: this._strict
7358 };
7359 } // FORMATTING
7360
7361
7362 addFormatToken(0, ['gg', 2], 0, function () {
7363 return this.weekYear() % 100;
7364 });
7365 addFormatToken(0, ['GG', 2], 0, function () {
7366 return this.isoWeekYear() % 100;
7367 });
7368
7369 function addWeekYearFormatToken(token, getter) {
7370 addFormatToken(0, [token, token.length], 0, getter);
7371 }
7372
7373 addWeekYearFormatToken('gggg', 'weekYear');
7374 addWeekYearFormatToken('ggggg', 'weekYear');
7375 addWeekYearFormatToken('GGGG', 'isoWeekYear');
7376 addWeekYearFormatToken('GGGGG', 'isoWeekYear'); // ALIASES
7377
7378 addUnitAlias('weekYear', 'gg');
7379 addUnitAlias('isoWeekYear', 'GG'); // PRIORITY
7380
7381 addUnitPriority('weekYear', 1);
7382 addUnitPriority('isoWeekYear', 1); // PARSING
7383
7384 addRegexToken('G', matchSigned);
7385 addRegexToken('g', matchSigned);
7386 addRegexToken('GG', match1to2, match2);
7387 addRegexToken('gg', match1to2, match2);
7388 addRegexToken('GGGG', match1to4, match4);
7389 addRegexToken('gggg', match1to4, match4);
7390 addRegexToken('GGGGG', match1to6, match6);
7391 addRegexToken('ggggg', match1to6, match6);
7392 addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
7393 week[token.substr(0, 2)] = toInt(input);
7394 });
7395 addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
7396 week[token] = hooks.parseTwoDigitYear(input);
7397 }); // MOMENTS
7398
7399 function getSetWeekYear(input) {
7400 return getSetWeekYearHelper.call(this, input, this.week(), this.weekday(), this.localeData()._week.dow, this.localeData()._week.doy);
7401 }
7402
7403 function getSetISOWeekYear(input) {
7404 return getSetWeekYearHelper.call(this, input, this.isoWeek(), this.isoWeekday(), 1, 4);
7405 }
7406
7407 function getISOWeeksInYear() {
7408 return weeksInYear(this.year(), 1, 4);
7409 }
7410
7411 function getWeeksInYear() {
7412 var weekInfo = this.localeData()._week;
7413
7414 return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
7415 }
7416
7417 function getSetWeekYearHelper(input, week, weekday, dow, doy) {
7418 var weeksTarget;
7419
7420 if (input == null) {
7421 return weekOfYear(this, dow, doy).year;
7422 } else {
7423 weeksTarget = weeksInYear(input, dow, doy);
7424
7425 if (week > weeksTarget) {
7426 week = weeksTarget;
7427 }
7428
7429 return setWeekAll.call(this, input, week, weekday, dow, doy);
7430 }
7431 }
7432
7433 function setWeekAll(weekYear, week, weekday, dow, doy) {
7434 var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
7435 date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
7436 this.year(date.getUTCFullYear());
7437 this.month(date.getUTCMonth());
7438 this.date(date.getUTCDate());
7439 return this;
7440 } // FORMATTING
7441
7442
7443 addFormatToken('Q', 0, 'Qo', 'quarter'); // ALIASES
7444
7445 addUnitAlias('quarter', 'Q'); // PRIORITY
7446
7447 addUnitPriority('quarter', 7); // PARSING
7448
7449 addRegexToken('Q', match1);
7450 addParseToken('Q', function (input, array) {
7451 array[MONTH] = (toInt(input) - 1) * 3;
7452 }); // MOMENTS
7453
7454 function getSetQuarter(input) {
7455 return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
7456 } // FORMATTING
7457
7458
7459 addFormatToken('D', ['DD', 2], 'Do', 'date'); // ALIASES
7460
7461 addUnitAlias('date', 'D'); // PRIORITY
7462
7463 addUnitPriority('date', 9); // PARSING
7464
7465 addRegexToken('D', match1to2);
7466 addRegexToken('DD', match1to2, match2);
7467 addRegexToken('Do', function (isStrict, locale) {
7468 // TODO: Remove "ordinalParse" fallback in next major release.
7469 return isStrict ? locale._dayOfMonthOrdinalParse || locale._ordinalParse : locale._dayOfMonthOrdinalParseLenient;
7470 });
7471 addParseToken(['D', 'DD'], DATE);
7472 addParseToken('Do', function (input, array) {
7473 array[DATE] = toInt(input.match(match1to2)[0]);
7474 }); // MOMENTS
7475
7476 var getSetDayOfMonth = makeGetSet('Date', true); // FORMATTING
7477
7478 addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); // ALIASES
7479
7480 addUnitAlias('dayOfYear', 'DDD'); // PRIORITY
7481
7482 addUnitPriority('dayOfYear', 4); // PARSING
7483
7484 addRegexToken('DDD', match1to3);
7485 addRegexToken('DDDD', match3);
7486 addParseToken(['DDD', 'DDDD'], function (input, array, config) {
7487 config._dayOfYear = toInt(input);
7488 }); // HELPERS
7489 // MOMENTS
7490
7491 function getSetDayOfYear(input) {
7492 var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
7493 return input == null ? dayOfYear : this.add(input - dayOfYear, 'd');
7494 } // FORMATTING
7495
7496
7497 addFormatToken('m', ['mm', 2], 0, 'minute'); // ALIASES
7498
7499 addUnitAlias('minute', 'm'); // PRIORITY
7500
7501 addUnitPriority('minute', 14); // PARSING
7502
7503 addRegexToken('m', match1to2);
7504 addRegexToken('mm', match1to2, match2);
7505 addParseToken(['m', 'mm'], MINUTE); // MOMENTS
7506
7507 var getSetMinute = makeGetSet('Minutes', false); // FORMATTING
7508
7509 addFormatToken('s', ['ss', 2], 0, 'second'); // ALIASES
7510
7511 addUnitAlias('second', 's'); // PRIORITY
7512
7513 addUnitPriority('second', 15); // PARSING
7514
7515 addRegexToken('s', match1to2);
7516 addRegexToken('ss', match1to2, match2);
7517 addParseToken(['s', 'ss'], SECOND); // MOMENTS
7518
7519 var getSetSecond = makeGetSet('Seconds', false); // FORMATTING
7520
7521 addFormatToken('S', 0, 0, function () {
7522 return ~~(this.millisecond() / 100);
7523 });
7524 addFormatToken(0, ['SS', 2], 0, function () {
7525 return ~~(this.millisecond() / 10);
7526 });
7527 addFormatToken(0, ['SSS', 3], 0, 'millisecond');
7528 addFormatToken(0, ['SSSS', 4], 0, function () {
7529 return this.millisecond() * 10;
7530 });
7531 addFormatToken(0, ['SSSSS', 5], 0, function () {
7532 return this.millisecond() * 100;
7533 });
7534 addFormatToken(0, ['SSSSSS', 6], 0, function () {
7535 return this.millisecond() * 1000;
7536 });
7537 addFormatToken(0, ['SSSSSSS', 7], 0, function () {
7538 return this.millisecond() * 10000;
7539 });
7540 addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
7541 return this.millisecond() * 100000;
7542 });
7543 addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
7544 return this.millisecond() * 1000000;
7545 }); // ALIASES
7546
7547 addUnitAlias('millisecond', 'ms'); // PRIORITY
7548
7549 addUnitPriority('millisecond', 16); // PARSING
7550
7551 addRegexToken('S', match1to3, match1);
7552 addRegexToken('SS', match1to3, match2);
7553 addRegexToken('SSS', match1to3, match3);
7554 var token;
7555
7556 for (token = 'SSSS'; token.length <= 9; token += 'S') {
7557 addRegexToken(token, matchUnsigned);
7558 }
7559
7560 function parseMs(input, array) {
7561 array[MILLISECOND] = toInt(('0.' + input) * 1000);
7562 }
7563
7564 for (token = 'S'; token.length <= 9; token += 'S') {
7565 addParseToken(token, parseMs);
7566 } // MOMENTS
7567
7568
7569 var getSetMillisecond = makeGetSet('Milliseconds', false); // FORMATTING
7570
7571 addFormatToken('z', 0, 0, 'zoneAbbr');
7572 addFormatToken('zz', 0, 0, 'zoneName'); // MOMENTS
7573
7574 function getZoneAbbr() {
7575 return this._isUTC ? 'UTC' : '';
7576 }
7577
7578 function getZoneName() {
7579 return this._isUTC ? 'Coordinated Universal Time' : '';
7580 }
7581
7582 var proto = Moment.prototype;
7583 proto.add = add;
7584 proto.calendar = calendar$1;
7585 proto.clone = clone;
7586 proto.diff = diff;
7587 proto.endOf = endOf;
7588 proto.format = format;
7589 proto.from = from;
7590 proto.fromNow = fromNow;
7591 proto.to = to;
7592 proto.toNow = toNow;
7593 proto.get = stringGet;
7594 proto.invalidAt = invalidAt;
7595 proto.isAfter = isAfter;
7596 proto.isBefore = isBefore;
7597 proto.isBetween = isBetween;
7598 proto.isSame = isSame;
7599 proto.isSameOrAfter = isSameOrAfter;
7600 proto.isSameOrBefore = isSameOrBefore;
7601 proto.isValid = isValid$2;
7602 proto.lang = lang;
7603 proto.locale = locale;
7604 proto.localeData = localeData;
7605 proto.max = prototypeMax;
7606 proto.min = prototypeMin;
7607 proto.parsingFlags = parsingFlags;
7608 proto.set = stringSet;
7609 proto.startOf = startOf;
7610 proto.subtract = subtract;
7611 proto.toArray = toArray;
7612 proto.toObject = toObject;
7613 proto.toDate = toDate;
7614 proto.toISOString = toISOString;
7615 proto.inspect = inspect;
7616 proto.toJSON = toJSON;
7617 proto.toString = toString;
7618 proto.unix = unix;
7619 proto.valueOf = valueOf;
7620 proto.creationData = creationData;
7621 proto.year = getSetYear;
7622 proto.isLeapYear = getIsLeapYear;
7623 proto.weekYear = getSetWeekYear;
7624 proto.isoWeekYear = getSetISOWeekYear;
7625 proto.quarter = proto.quarters = getSetQuarter;
7626 proto.month = getSetMonth;
7627 proto.daysInMonth = getDaysInMonth;
7628 proto.week = proto.weeks = getSetWeek;
7629 proto.isoWeek = proto.isoWeeks = getSetISOWeek;
7630 proto.weeksInYear = getWeeksInYear;
7631 proto.isoWeeksInYear = getISOWeeksInYear;
7632 proto.date = getSetDayOfMonth;
7633 proto.day = proto.days = getSetDayOfWeek;
7634 proto.weekday = getSetLocaleDayOfWeek;
7635 proto.isoWeekday = getSetISODayOfWeek;
7636 proto.dayOfYear = getSetDayOfYear;
7637 proto.hour = proto.hours = getSetHour;
7638 proto.minute = proto.minutes = getSetMinute;
7639 proto.second = proto.seconds = getSetSecond;
7640 proto.millisecond = proto.milliseconds = getSetMillisecond;
7641 proto.utcOffset = getSetOffset;
7642 proto.utc = setOffsetToUTC;
7643 proto.local = setOffsetToLocal;
7644 proto.parseZone = setOffsetToParsedOffset;
7645 proto.hasAlignedHourOffset = hasAlignedHourOffset;
7646 proto.isDST = isDaylightSavingTime;
7647 proto.isLocal = isLocal;
7648 proto.isUtcOffset = isUtcOffset;
7649 proto.isUtc = isUtc;
7650 proto.isUTC = isUtc;
7651 proto.zoneAbbr = getZoneAbbr;
7652 proto.zoneName = getZoneName;
7653 proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
7654 proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
7655 proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);
7656 proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
7657 proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
7658
7659 function createUnix(input) {
7660 return createLocal(input * 1000);
7661 }
7662
7663 function createInZone() {
7664 return createLocal.apply(null, arguments).parseZone();
7665 }
7666
7667 function preParsePostFormat(string) {
7668 return string;
7669 }
7670
7671 var proto$1 = Locale.prototype;
7672 proto$1.calendar = calendar;
7673 proto$1.longDateFormat = longDateFormat;
7674 proto$1.invalidDate = invalidDate;
7675 proto$1.ordinal = ordinal;
7676 proto$1.preparse = preParsePostFormat;
7677 proto$1.postformat = preParsePostFormat;
7678 proto$1.relativeTime = relativeTime;
7679 proto$1.pastFuture = pastFuture;
7680 proto$1.set = set;
7681 proto$1.months = localeMonths;
7682 proto$1.monthsShort = localeMonthsShort;
7683 proto$1.monthsParse = localeMonthsParse;
7684 proto$1.monthsRegex = monthsRegex;
7685 proto$1.monthsShortRegex = monthsShortRegex;
7686 proto$1.week = localeWeek;
7687 proto$1.firstDayOfYear = localeFirstDayOfYear;
7688 proto$1.firstDayOfWeek = localeFirstDayOfWeek;
7689 proto$1.weekdays = localeWeekdays;
7690 proto$1.weekdaysMin = localeWeekdaysMin;
7691 proto$1.weekdaysShort = localeWeekdaysShort;
7692 proto$1.weekdaysParse = localeWeekdaysParse;
7693 proto$1.weekdaysRegex = weekdaysRegex;
7694 proto$1.weekdaysShortRegex = weekdaysShortRegex;
7695 proto$1.weekdaysMinRegex = weekdaysMinRegex;
7696 proto$1.isPM = localeIsPM;
7697 proto$1.meridiem = localeMeridiem;
7698
7699 function get$1(format, index, field, setter) {
7700 var locale = getLocale();
7701 var utc = createUTC().set(setter, index);
7702 return locale[field](utc, format);
7703 }
7704
7705 function listMonthsImpl(format, index, field) {
7706 if (isNumber(format)) {
7707 index = format;
7708 format = undefined;
7709 }
7710
7711 format = format || '';
7712
7713 if (index != null) {
7714 return get$1(format, index, field, 'month');
7715 }
7716
7717 var i;
7718 var out = [];
7719
7720 for (i = 0; i < 12; i++) {
7721 out[i] = get$1(format, i, field, 'month');
7722 }
7723
7724 return out;
7725 } // ()
7726 // (5)
7727 // (fmt, 5)
7728 // (fmt)
7729 // (true)
7730 // (true, 5)
7731 // (true, fmt, 5)
7732 // (true, fmt)
7733
7734
7735 function listWeekdaysImpl(localeSorted, format, index, field) {
7736 if (typeof localeSorted === 'boolean') {
7737 if (isNumber(format)) {
7738 index = format;
7739 format = undefined;
7740 }
7741
7742 format = format || '';
7743 } else {
7744 format = localeSorted;
7745 index = format;
7746 localeSorted = false;
7747
7748 if (isNumber(format)) {
7749 index = format;
7750 format = undefined;
7751 }
7752
7753 format = format || '';
7754 }
7755
7756 var locale = getLocale(),
7757 shift = localeSorted ? locale._week.dow : 0;
7758
7759 if (index != null) {
7760 return get$1(format, (index + shift) % 7, field, 'day');
7761 }
7762
7763 var i;
7764 var out = [];
7765
7766 for (i = 0; i < 7; i++) {
7767 out[i] = get$1(format, (i + shift) % 7, field, 'day');
7768 }
7769
7770 return out;
7771 }
7772
7773 function listMonths(format, index) {
7774 return listMonthsImpl(format, index, 'months');
7775 }
7776
7777 function listMonthsShort(format, index) {
7778 return listMonthsImpl(format, index, 'monthsShort');
7779 }
7780
7781 function listWeekdays(localeSorted, format, index) {
7782 return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
7783 }
7784
7785 function listWeekdaysShort(localeSorted, format, index) {
7786 return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
7787 }
7788
7789 function listWeekdaysMin(localeSorted, format, index) {
7790 return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
7791 }
7792
7793 getSetGlobalLocale('en', {
7794 dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
7795 ordinal: function (number) {
7796 var b = number % 10,
7797 output = toInt(number % 100 / 10) === 1 ? 'th' : b === 1 ? 'st' : b === 2 ? 'nd' : b === 3 ? 'rd' : 'th';
7798 return number + output;
7799 }
7800 }); // Side effect imports
7801
7802 hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
7803 hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
7804 var mathAbs = Math.abs;
7805
7806 function abs() {
7807 var data = this._data;
7808 this._milliseconds = mathAbs(this._milliseconds);
7809 this._days = mathAbs(this._days);
7810 this._months = mathAbs(this._months);
7811 data.milliseconds = mathAbs(data.milliseconds);
7812 data.seconds = mathAbs(data.seconds);
7813 data.minutes = mathAbs(data.minutes);
7814 data.hours = mathAbs(data.hours);
7815 data.months = mathAbs(data.months);
7816 data.years = mathAbs(data.years);
7817 return this;
7818 }
7819
7820 function addSubtract$1(duration, input, value, direction) {
7821 var other = createDuration(input, value);
7822 duration._milliseconds += direction * other._milliseconds;
7823 duration._days += direction * other._days;
7824 duration._months += direction * other._months;
7825 return duration._bubble();
7826 } // supports only 2.0-style add(1, 's') or add(duration)
7827
7828
7829 function add$1(input, value) {
7830 return addSubtract$1(this, input, value, 1);
7831 } // supports only 2.0-style subtract(1, 's') or subtract(duration)
7832
7833
7834 function subtract$1(input, value) {
7835 return addSubtract$1(this, input, value, -1);
7836 }
7837
7838 function absCeil(number) {
7839 if (number < 0) {
7840 return Math.floor(number);
7841 } else {
7842 return Math.ceil(number);
7843 }
7844 }
7845
7846 function bubble() {
7847 var milliseconds = this._milliseconds;
7848 var days = this._days;
7849 var months = this._months;
7850 var data = this._data;
7851 var seconds, minutes, hours, years, monthsFromDays; // if we have a mix of positive and negative values, bubble down first
7852 // check: https://github.com/moment/moment/issues/2166
7853
7854 if (!(milliseconds >= 0 && days >= 0 && months >= 0 || milliseconds <= 0 && days <= 0 && months <= 0)) {
7855 milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
7856 days = 0;
7857 months = 0;
7858 } // The following code bubbles up values, see the tests for
7859 // examples of what that means.
7860
7861
7862 data.milliseconds = milliseconds % 1000;
7863 seconds = absFloor(milliseconds / 1000);
7864 data.seconds = seconds % 60;
7865 minutes = absFloor(seconds / 60);
7866 data.minutes = minutes % 60;
7867 hours = absFloor(minutes / 60);
7868 data.hours = hours % 24;
7869 days += absFloor(hours / 24); // convert days to months
7870
7871 monthsFromDays = absFloor(daysToMonths(days));
7872 months += monthsFromDays;
7873 days -= absCeil(monthsToDays(monthsFromDays)); // 12 months -> 1 year
7874
7875 years = absFloor(months / 12);
7876 months %= 12;
7877 data.days = days;
7878 data.months = months;
7879 data.years = years;
7880 return this;
7881 }
7882
7883 function daysToMonths(days) {
7884 // 400 years have 146097 days (taking into account leap year rules)
7885 // 400 years have 12 months === 4800
7886 return days * 4800 / 146097;
7887 }
7888
7889 function monthsToDays(months) {
7890 // the reverse of daysToMonths
7891 return months * 146097 / 4800;
7892 }
7893
7894 function as(units) {
7895 if (!this.isValid()) {
7896 return NaN;
7897 }
7898
7899 var days;
7900 var months;
7901 var milliseconds = this._milliseconds;
7902 units = normalizeUnits(units);
7903
7904 if (units === 'month' || units === 'quarter' || units === 'year') {
7905 days = this._days + milliseconds / 864e5;
7906 months = this._months + daysToMonths(days);
7907
7908 switch (units) {
7909 case 'month':
7910 return months;
7911
7912 case 'quarter':
7913 return months / 3;
7914
7915 case 'year':
7916 return months / 12;
7917 }
7918 } else {
7919 // handle milliseconds separately because of floating point math errors (issue #1867)
7920 days = this._days + Math.round(monthsToDays(this._months));
7921
7922 switch (units) {
7923 case 'week':
7924 return days / 7 + milliseconds / 6048e5;
7925
7926 case 'day':
7927 return days + milliseconds / 864e5;
7928
7929 case 'hour':
7930 return days * 24 + milliseconds / 36e5;
7931
7932 case 'minute':
7933 return days * 1440 + milliseconds / 6e4;
7934
7935 case 'second':
7936 return days * 86400 + milliseconds / 1000;
7937 // Math.floor prevents floating point math errors here
7938
7939 case 'millisecond':
7940 return Math.floor(days * 864e5) + milliseconds;
7941
7942 default:
7943 throw new Error('Unknown unit ' + units);
7944 }
7945 }
7946 } // TODO: Use this.as('ms')?
7947
7948
7949 function valueOf$1() {
7950 if (!this.isValid()) {
7951 return NaN;
7952 }
7953
7954 return this._milliseconds + this._days * 864e5 + this._months % 12 * 2592e6 + toInt(this._months / 12) * 31536e6;
7955 }
7956
7957 function makeAs(alias) {
7958 return function () {
7959 return this.as(alias);
7960 };
7961 }
7962
7963 var asMilliseconds = makeAs('ms');
7964 var asSeconds = makeAs('s');
7965 var asMinutes = makeAs('m');
7966 var asHours = makeAs('h');
7967 var asDays = makeAs('d');
7968 var asWeeks = makeAs('w');
7969 var asMonths = makeAs('M');
7970 var asQuarters = makeAs('Q');
7971 var asYears = makeAs('y');
7972
7973 function clone$1() {
7974 return createDuration(this);
7975 }
7976
7977 function get$2(units) {
7978 units = normalizeUnits(units);
7979 return this.isValid() ? this[units + 's']() : NaN;
7980 }
7981
7982 function makeGetter(name) {
7983 return function () {
7984 return this.isValid() ? this._data[name] : NaN;
7985 };
7986 }
7987
7988 var milliseconds = makeGetter('milliseconds');
7989 var seconds = makeGetter('seconds');
7990 var minutes = makeGetter('minutes');
7991 var hours = makeGetter('hours');
7992 var days = makeGetter('days');
7993 var months = makeGetter('months');
7994 var years = makeGetter('years');
7995
7996 function weeks() {
7997 return absFloor(this.days() / 7);
7998 }
7999
8000 var round = Math.round;
8001 var thresholds = {
8002 ss: 44,
8003 // a few seconds to seconds
8004 s: 45,
8005 // seconds to minute
8006 m: 45,
8007 // minutes to hour
8008 h: 22,
8009 // hours to day
8010 d: 26,
8011 // days to month
8012 M: 11 // months to year
8013
8014 }; // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
8015
8016 function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
8017 return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
8018 }
8019
8020 function relativeTime$1(posNegDuration, withoutSuffix, locale) {
8021 var duration = createDuration(posNegDuration).abs();
8022 var seconds = round(duration.as('s'));
8023 var minutes = round(duration.as('m'));
8024 var hours = round(duration.as('h'));
8025 var days = round(duration.as('d'));
8026 var months = round(duration.as('M'));
8027 var years = round(duration.as('y'));
8028 var a = seconds <= thresholds.ss && ['s', seconds] || seconds < thresholds.s && ['ss', seconds] || minutes <= 1 && ['m'] || minutes < thresholds.m && ['mm', minutes] || hours <= 1 && ['h'] || hours < thresholds.h && ['hh', hours] || days <= 1 && ['d'] || days < thresholds.d && ['dd', days] || months <= 1 && ['M'] || months < thresholds.M && ['MM', months] || years <= 1 && ['y'] || ['yy', years];
8029 a[2] = withoutSuffix;
8030 a[3] = +posNegDuration > 0;
8031 a[4] = locale;
8032 return substituteTimeAgo.apply(null, a);
8033 } // This function allows you to set the rounding function for relative time strings
8034
8035
8036 function getSetRelativeTimeRounding(roundingFunction) {
8037 if (roundingFunction === undefined) {
8038 return round;
8039 }
8040
8041 if (typeof roundingFunction === 'function') {
8042 round = roundingFunction;
8043 return true;
8044 }
8045
8046 return false;
8047 } // This function allows you to set a threshold for relative time strings
8048
8049
8050 function getSetRelativeTimeThreshold(threshold, limit) {
8051 if (thresholds[threshold] === undefined) {
8052 return false;
8053 }
8054
8055 if (limit === undefined) {
8056 return thresholds[threshold];
8057 }
8058
8059 thresholds[threshold] = limit;
8060
8061 if (threshold === 's') {
8062 thresholds.ss = limit - 1;
8063 }
8064
8065 return true;
8066 }
8067
8068 function humanize(withSuffix) {
8069 if (!this.isValid()) {
8070 return this.localeData().invalidDate();
8071 }
8072
8073 var locale = this.localeData();
8074 var output = relativeTime$1(this, !withSuffix, locale);
8075
8076 if (withSuffix) {
8077 output = locale.pastFuture(+this, output);
8078 }
8079
8080 return locale.postformat(output);
8081 }
8082
8083 var abs$1 = Math.abs;
8084
8085 function sign(x) {
8086 return (x > 0) - (x < 0) || +x;
8087 }
8088
8089 function toISOString$1() {
8090 // for ISO strings we do not use the normal bubbling rules:
8091 // * milliseconds bubble up until they become hours
8092 // * days do not bubble at all
8093 // * months bubble up until they become years
8094 // This is because there is no context-free conversion between hours and days
8095 // (think of clock changes)
8096 // and also not between days and months (28-31 days per month)
8097 if (!this.isValid()) {
8098 return this.localeData().invalidDate();
8099 }
8100
8101 var seconds = abs$1(this._milliseconds) / 1000;
8102 var days = abs$1(this._days);
8103 var months = abs$1(this._months);
8104 var minutes, hours, years; // 3600 seconds -> 60 minutes -> 1 hour
8105
8106 minutes = absFloor(seconds / 60);
8107 hours = absFloor(minutes / 60);
8108 seconds %= 60;
8109 minutes %= 60; // 12 months -> 1 year
8110
8111 years = absFloor(months / 12);
8112 months %= 12; // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
8113
8114 var Y = years;
8115 var M = months;
8116 var D = days;
8117 var h = hours;
8118 var m = minutes;
8119 var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
8120 var total = this.asSeconds();
8121
8122 if (!total) {
8123 // this is the same as C#'s (Noda) and python (isodate)...
8124 // but not other JS (goog.date)
8125 return 'P0D';
8126 }
8127
8128 var totalSign = total < 0 ? '-' : '';
8129 var ymSign = sign(this._months) !== sign(total) ? '-' : '';
8130 var daysSign = sign(this._days) !== sign(total) ? '-' : '';
8131 var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
8132 return totalSign + 'P' + (Y ? ymSign + Y + 'Y' : '') + (M ? ymSign + M + 'M' : '') + (D ? daysSign + D + 'D' : '') + (h || m || s ? 'T' : '') + (h ? hmsSign + h + 'H' : '') + (m ? hmsSign + m + 'M' : '') + (s ? hmsSign + s + 'S' : '');
8133 }
8134
8135 var proto$2 = Duration.prototype;
8136 proto$2.isValid = isValid$1;
8137 proto$2.abs = abs;
8138 proto$2.add = add$1;
8139 proto$2.subtract = subtract$1;
8140 proto$2.as = as;
8141 proto$2.asMilliseconds = asMilliseconds;
8142 proto$2.asSeconds = asSeconds;
8143 proto$2.asMinutes = asMinutes;
8144 proto$2.asHours = asHours;
8145 proto$2.asDays = asDays;
8146 proto$2.asWeeks = asWeeks;
8147 proto$2.asMonths = asMonths;
8148 proto$2.asQuarters = asQuarters;
8149 proto$2.asYears = asYears;
8150 proto$2.valueOf = valueOf$1;
8151 proto$2._bubble = bubble;
8152 proto$2.clone = clone$1;
8153 proto$2.get = get$2;
8154 proto$2.milliseconds = milliseconds;
8155 proto$2.seconds = seconds;
8156 proto$2.minutes = minutes;
8157 proto$2.hours = hours;
8158 proto$2.days = days;
8159 proto$2.weeks = weeks;
8160 proto$2.months = months;
8161 proto$2.years = years;
8162 proto$2.humanize = humanize;
8163 proto$2.toISOString = toISOString$1;
8164 proto$2.toString = toISOString$1;
8165 proto$2.toJSON = toISOString$1;
8166 proto$2.locale = locale;
8167 proto$2.localeData = localeData;
8168 proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
8169 proto$2.lang = lang; // Side effect imports
8170 // FORMATTING
8171
8172 addFormatToken('X', 0, 0, 'unix');
8173 addFormatToken('x', 0, 0, 'valueOf'); // PARSING
8174
8175 addRegexToken('x', matchSigned);
8176 addRegexToken('X', matchTimestamp);
8177 addParseToken('X', function (input, array, config) {
8178 config._d = new Date(parseFloat(input, 10) * 1000);
8179 });
8180 addParseToken('x', function (input, array, config) {
8181 config._d = new Date(toInt(input));
8182 }); // Side effect imports
8183
8184 hooks.version = '2.24.0';
8185 setHookCallback(createLocal);
8186 hooks.fn = proto;
8187 hooks.min = min;
8188 hooks.max = max;
8189 hooks.now = now;
8190 hooks.utc = createUTC;
8191 hooks.unix = createUnix;
8192 hooks.months = listMonths;
8193 hooks.isDate = isDate;
8194 hooks.locale = getSetGlobalLocale;
8195 hooks.invalid = createInvalid;
8196 hooks.duration = createDuration;
8197 hooks.isMoment = isMoment;
8198 hooks.weekdays = listWeekdays;
8199 hooks.parseZone = createInZone;
8200 hooks.localeData = getLocale;
8201 hooks.isDuration = isDuration;
8202 hooks.monthsShort = listMonthsShort;
8203 hooks.weekdaysMin = listWeekdaysMin;
8204 hooks.defineLocale = defineLocale;
8205 hooks.updateLocale = updateLocale;
8206 hooks.locales = listLocales;
8207 hooks.weekdaysShort = listWeekdaysShort;
8208 hooks.normalizeUnits = normalizeUnits;
8209 hooks.relativeTimeRounding = getSetRelativeTimeRounding;
8210 hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
8211 hooks.calendarFormat = getCalendarFormat;
8212 hooks.prototype = proto; // currently HTML5 input type only supports 24-hour formats
8213
8214 hooks.HTML5_FMT = {
8215 DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm',
8216 // <input type="datetime-local" />
8217 DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss',
8218 // <input type="datetime-local" step="1" />
8219 DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS',
8220 // <input type="datetime-local" step="0.001" />
8221 DATE: 'YYYY-MM-DD',
8222 // <input type="date" />
8223 TIME: 'HH:mm',
8224 // <input type="time" />
8225 TIME_SECONDS: 'HH:mm:ss',
8226 // <input type="time" step="1" />
8227 TIME_MS: 'HH:mm:ss.SSS',
8228 // <input type="time" step="0.001" />
8229 WEEK: 'GGGG-[W]WW',
8230 // <input type="week" />
8231 MONTH: 'YYYY-MM' // <input type="month" />
8232
8233 };
8234 return hooks;
8235 });
8236}); // Maps for number <-> hex string conversion
8237
8238var byteToHex = [];
8239
8240for (var i$1 = 0; i$1 < 256; i$1++) {
8241 byteToHex[i$1] = (i$1 + 0x100).toString(16).substr(1);
8242}
8243/**
8244 * Represent binary UUID into it's string representation.
8245 *
8246 * @param buf - Buffer containing UUID bytes.
8247 * @param offset - Offset from the start of the buffer where the UUID is saved (not needed if the buffer starts with the UUID).
8248 *
8249 * @returns String representation of the UUID.
8250 */
8251
8252
8253function stringifyUUID(buf, offset) {
8254 var i = offset || 0;
8255 var bth = byteToHex;
8256 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]];
8257}
8258/**
8259 * Generate 16 random bytes to be used as a base for UUID.
8260 *
8261 * @ignore
8262 */
8263
8264
8265var random = function () {
8266 if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
8267 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
8268 // Moderately fast, high quality
8269 var _rnds8 = new Uint8Array(16);
8270
8271 return function whatwgRNG() {
8272 crypto.getRandomValues(_rnds8);
8273 return _rnds8;
8274 };
8275 } // Math.random()-based (RNG)
8276 //
8277 // If all else fails, use Math.random().
8278 // It's fast, but is of unspecified quality.
8279
8280
8281 var _rnds = new Array(16);
8282
8283 return function () {
8284 for (var i = 0, r; i < 16; i++) {
8285 if ((i & 0x03) === 0) {
8286 r = Math.random() * 0x100000000;
8287 }
8288
8289 _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
8290 }
8291
8292 return _rnds;
8293 }; // uuid.js
8294 //
8295 // Copyright (c) 2010-2012 Robert Kieffer
8296 // MIT License - http://opensource.org/licenses/mit-license.php
8297 // Unique ID creation requires a high quality random # generator. We feature
8298 // detect to determine the best RNG source, normalizing to a function that
8299 // returns 128-bits of randomness, since that's what's usually required
8300 // return require('./rng');
8301}();
8302
8303var byteToHex$1 = [];
8304
8305for (var i$1$1 = 0; i$1$1 < 256; i$1$1++) {
8306 byteToHex$1[i$1$1] = (i$1$1 + 0x100).toString(16).substr(1);
8307} // **`v1()` - Generate time-based UUID**
8308//
8309// Inspired by https://github.com/LiosK/UUID.js
8310// and http://docs.python.org/library/uuid.html
8311// random #'s we need to init node and clockseq
8312
8313
8314var seedBytes = random(); // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
8315
8316var defaultNodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; // Per 4.2.2, randomize (14 bit) clockseq
8317
8318var defaultClockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; // Previous uuid creation time
8319
8320/**
8321 * UUIDv4 options.
8322 */
8323
8324/**
8325 * Generate UUIDv4
8326 *
8327 * @param options - Options to be used instead of default generated values.
8328 * String 'binary' is a shorthand for uuid4({}, new Array(16)).
8329 * @param buf - If present the buffer will be filled with the generated UUID.
8330 * @param offset - Offset of the UUID from the start of the buffer.
8331 *
8332 * @returns UUIDv4
8333 */
8334
8335function uuid4() {
8336 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
8337 var buf = arguments.length > 1 ? arguments[1] : undefined;
8338 var offset = arguments.length > 2 ? arguments[2] : undefined; // Deprecated - 'format' argument, as supported in v1.2
8339
8340 var i = buf && offset || 0;
8341
8342 if (typeof options === 'string') {
8343 buf = options === 'binary' ? new Array(16) : undefined;
8344 options = {};
8345 }
8346
8347 var rnds = options.random || (options.rng || random)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
8348
8349 rnds[6] = rnds[6] & 0x0f | 0x40;
8350 rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
8351
8352 if (buf) {
8353 for (var ii = 0; ii < 16; ii++) {
8354 buf[i + ii] = rnds[ii];
8355 }
8356 }
8357
8358 return buf || stringifyUUID(rnds);
8359} // Rollup will complain about mixing default and named exports in UMD build,
8360// for example '/Date(1198908717056)/' or '/Date(1198908717056-0700)/'
8361// code from http://momentjs.com/
8362
8363
8364var ASPDateRegex = /^\/?Date\((-?\d+)/i; // Color REs
8365
8366var fullHexRE = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
8367var shortHexRE = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
8368var rgbRE = /^rgb\( *(1?\d{1,2}|2[0-4]\d|25[0-5]) *, *(1?\d{1,2}|2[0-4]\d|25[0-5]) *, *(1?\d{1,2}|2[0-4]\d|25[0-5]) *\)$/i;
8369var rgbaRE = /^rgba\( *(1?\d{1,2}|2[0-4]\d|25[0-5]) *, *(1?\d{1,2}|2[0-4]\d|25[0-5]) *, *(1?\d{1,2}|2[0-4]\d|25[0-5]) *, *([01]|0?\.\d+) *\)$/i;
8370/**
8371 * Hue, Saturation, Value.
8372 */
8373
8374/**
8375 * Test whether given object is a number
8376 *
8377 * @param value - Input value of unknown type.
8378 *
8379 * @returns True if number, false otherwise.
8380 */
8381
8382function isNumber(value) {
8383 return value instanceof Number || typeof value === "number";
8384}
8385/**
8386 * Remove everything in the DOM object
8387 *
8388 * @param DOMobject - Node whose child nodes will be recursively deleted.
8389 */
8390
8391
8392function recursiveDOMDelete(DOMobject) {
8393 if (DOMobject) {
8394 while (DOMobject.hasChildNodes() === true) {
8395 var child = DOMobject.firstChild;
8396
8397 if (child) {
8398 recursiveDOMDelete(child);
8399 DOMobject.removeChild(child);
8400 }
8401 }
8402 }
8403}
8404/**
8405 * Test whether given object is a string
8406 *
8407 * @param value - Input value of unknown type.
8408 *
8409 * @returns True if string, false otherwise.
8410 */
8411
8412
8413function isString(value) {
8414 return value instanceof String || typeof value === "string";
8415}
8416/**
8417 * Test whether given object is a object (not primitive or null).
8418 *
8419 * @param value - Input value of unknown type.
8420 *
8421 * @returns True if not null object, false otherwise.
8422 */
8423
8424
8425function isObject$1(value) {
8426 return _typeof(value) === "object" && value !== null;
8427}
8428/**
8429 * Test whether given object is a Date, or a String containing a Date
8430 *
8431 * @param value - Input value of unknown type.
8432 *
8433 * @returns True if Date instance or string date representation, false otherwise.
8434 */
8435
8436
8437function isDate(value) {
8438 if (value instanceof Date) {
8439 return true;
8440 } else if (isString(value)) {
8441 // test whether this string contains a date
8442 var match = ASPDateRegex.exec(value);
8443
8444 if (match) {
8445 return true;
8446 } else if (!isNaN(Date.parse(value))) {
8447 return true;
8448 }
8449 }
8450
8451 return false;
8452}
8453/**
8454 * Test whether given object is a Moment date.
8455 * @TODO: This is basically a workaround, if Moment was imported property it wouldn't necessary as moment.isMoment is a TS type guard.
8456 *
8457 * @param value - Input value of unknown type.
8458 *
8459 * @returns True if Moment instance, false otherwise.
8460 */
8461
8462
8463function isMoment(value) {
8464 return moment.isMoment(value);
8465}
8466/**
8467 * Copy property from b to a if property present in a.
8468 * If property in b explicitly set to null, delete it if `allowDeletion` set.
8469 *
8470 * Internal helper routine, should not be exported. Not added to `exports` for that reason.
8471 *
8472 * @param a - Target object.
8473 * @param b - Source object.
8474 * @param prop - Name of property to copy from b to a.
8475 * @param allowDeletion if true, delete property in a if explicitly set to null in b
8476 */
8477
8478
8479function copyOrDelete(a, b, prop, allowDeletion) {
8480 var doDeletion = false;
8481
8482 if (allowDeletion === true) {
8483 doDeletion = b[prop] === null && a[prop] !== undefined;
8484 }
8485
8486 if (doDeletion) {
8487 delete a[prop];
8488 } else {
8489 a[prop] = b[prop]; // Remember, this is a reference copy!
8490 }
8491}
8492/**
8493 * Fill an object with a possibly partially defined other object.
8494 *
8495 * Only copies values for the properties already present in a.
8496 * That means an object is not created on a property if only the b object has it.
8497 *
8498 * @param a - The object that will have it's properties updated.
8499 * @param b - The object with property updates.
8500 * @param allowDeletion - if true, delete properties in a that are explicitly set to null in b
8501 */
8502
8503
8504function fillIfDefined(a, b) {
8505 var allowDeletion = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; // NOTE: iteration of properties of a
8506 // NOTE: prototype properties iterated over as well
8507
8508 for (var prop in a) {
8509 if (b[prop] !== undefined) {
8510 if (b[prop] === null || _typeof(b[prop]) !== "object") {
8511 // Note: typeof null === 'object'
8512 copyOrDelete(a, b, prop, allowDeletion);
8513 } else {
8514 var aProp = a[prop];
8515 var bProp = b[prop];
8516
8517 if (isObject$1(aProp) && isObject$1(bProp)) {
8518 fillIfDefined(aProp, bProp, allowDeletion);
8519 }
8520 }
8521 }
8522 }
8523}
8524/**
8525 * Copy the values of all of the enumerable own properties from one or more source objects to a
8526 * target object. Returns the target object.
8527 *
8528 * @param target - The target object to copy to.
8529 * @param source - The source object from which to copy properties.
8530 *
8531 * @return The target object.
8532 */
8533
8534
8535var extend = Object.assign;
8536/**
8537 * Extend object a with selected properties of object b or a series of objects
8538 * Only properties with defined values are copied
8539 *
8540 * @param props - Properties to be copied to a.
8541 * @param a - The target.
8542 * @param others - The sources.
8543 *
8544 * @returns Argument a.
8545 */
8546
8547function selectiveExtend(props, a) {
8548 if (!Array.isArray(props)) {
8549 throw new Error("Array with property names expected as first argument");
8550 }
8551
8552 for (var _len = arguments.length, others = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
8553 others[_key - 2] = arguments[_key];
8554 }
8555
8556 for (var _i = 0, _others = others; _i < _others.length; _i++) {
8557 var other = _others[_i];
8558
8559 for (var p = 0; p < props.length; p++) {
8560 var prop = props[p];
8561
8562 if (other && Object.prototype.hasOwnProperty.call(other, prop)) {
8563 a[prop] = other[prop];
8564 }
8565 }
8566 }
8567
8568 return a;
8569}
8570/**
8571 * Extend object a with selected properties of object b.
8572 * Only properties with defined values are copied.
8573 *
8574 * **Note:** Previous version of this routine implied that multiple source objects
8575 * could be used; however, the implementation was **wrong**.
8576 * Since multiple (>1) sources weren't used anywhere in the `vis.js` code,
8577 * this has been removed
8578 *
8579 * @param props - Names of first-level properties to copy over.
8580 * @param a - Target object.
8581 * @param b - Source object.
8582 * @param allowDeletion - If true, delete property in a if explicitly set to null in b.
8583 *
8584 * @returns Argument a.
8585 */
8586
8587
8588function selectiveDeepExtend(props, a, b) {
8589 var allowDeletion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; // TODO: add support for Arrays to deepExtend
8590
8591 if (Array.isArray(b)) {
8592 throw new TypeError("Arrays are not supported by deepExtend");
8593 }
8594
8595 for (var p = 0; p < props.length; p++) {
8596 var prop = props[p];
8597
8598 if (Object.prototype.hasOwnProperty.call(b, prop)) {
8599 if (b[prop] && b[prop].constructor === Object) {
8600 if (a[prop] === undefined) {
8601 a[prop] = {};
8602 }
8603
8604 if (a[prop].constructor === Object) {
8605 deepExtend(a[prop], b[prop], false, allowDeletion);
8606 } else {
8607 copyOrDelete(a, b, prop, allowDeletion);
8608 }
8609 } else if (Array.isArray(b[prop])) {
8610 throw new TypeError("Arrays are not supported by deepExtend");
8611 } else {
8612 copyOrDelete(a, b, prop, allowDeletion);
8613 }
8614 }
8615 }
8616
8617 return a;
8618}
8619/**
8620 * Extend object `a` with properties of object `b`, ignoring properties which are explicitly
8621 * specified to be excluded.
8622 *
8623 * The properties of `b` are considered for copying.
8624 * Properties which are themselves objects are are also extended.
8625 * Only properties with defined values are copied
8626 *
8627 * @param propsToExclude - Names of properties which should *not* be copied.
8628 * @param a - Object to extend.
8629 * @param b - Object to take properties from for extension.
8630 * @param allowDeletion - If true, delete properties in a that are explicitly set to null in b.
8631 *
8632 * @returns Argument a.
8633 */
8634
8635
8636function selectiveNotDeepExtend(propsToExclude, a, b) {
8637 var allowDeletion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; // TODO: add support for Arrays to deepExtend
8638 // NOTE: array properties have an else-below; apparently, there is a problem here.
8639
8640 if (Array.isArray(b)) {
8641 throw new TypeError("Arrays are not supported by deepExtend");
8642 }
8643
8644 for (var prop in b) {
8645 if (!Object.prototype.hasOwnProperty.call(b, prop)) {
8646 continue;
8647 } // Handle local properties only
8648
8649
8650 if (propsToExclude.indexOf(prop) !== -1) {
8651 continue;
8652 } // In exclusion list, skip
8653
8654
8655 if (b[prop] && b[prop].constructor === Object) {
8656 if (a[prop] === undefined) {
8657 a[prop] = {};
8658 }
8659
8660 if (a[prop].constructor === Object) {
8661 deepExtend(a[prop], b[prop]); // NOTE: allowDeletion not propagated!
8662 } else {
8663 copyOrDelete(a, b, prop, allowDeletion);
8664 }
8665 } else if (Array.isArray(b[prop])) {
8666 a[prop] = [];
8667
8668 for (var i = 0; i < b[prop].length; i++) {
8669 a[prop].push(b[prop][i]);
8670 }
8671 } else {
8672 copyOrDelete(a, b, prop, allowDeletion);
8673 }
8674 }
8675
8676 return a;
8677}
8678/**
8679 * Deep extend an object a with the properties of object b
8680 *
8681 * @param a - Target object.
8682 * @param b - Source object.
8683 * @param protoExtend - If true, the prototype values will also be extended
8684 * (ie. the options objects that inherit from others will also get the inherited options).
8685 * @param allowDeletion - If true, the values of fields that are null will be deleted.
8686 *
8687 * @returns Argument a.
8688 */
8689
8690
8691function deepExtend(a, b) {
8692 var protoExtend = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
8693 var allowDeletion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
8694
8695 for (var prop in b) {
8696 if (Object.prototype.hasOwnProperty.call(b, prop) || protoExtend === true) {
8697 if (_typeof(b[prop]) === "object" && b[prop] !== null && Object.getPrototypeOf(b[prop]) === Object.prototype) {
8698 if (a[prop] === undefined) {
8699 a[prop] = deepExtend({}, b[prop], protoExtend); // NOTE: allowDeletion not propagated!
8700 } else if (_typeof(a[prop]) === "object" && a[prop] !== null && Object.getPrototypeOf(a[prop]) === Object.prototype) {
8701 deepExtend(a[prop], b[prop], protoExtend); // NOTE: allowDeletion not propagated!
8702 } else {
8703 copyOrDelete(a, b, prop, allowDeletion);
8704 }
8705 } else if (Array.isArray(b[prop])) {
8706 a[prop] = b[prop].slice();
8707 } else {
8708 copyOrDelete(a, b, prop, allowDeletion);
8709 }
8710 }
8711 }
8712
8713 return a;
8714}
8715/**
8716 * Test whether all elements in two arrays are equal.
8717 *
8718 * @param a - First array.
8719 * @param b - Second array.
8720 *
8721 * @returns True if both arrays have the same length and same elements (1 = '1').
8722 */
8723
8724
8725function equalArray(a, b) {
8726 if (a.length !== b.length) {
8727 return false;
8728 }
8729
8730 for (var i = 0, len = a.length; i < len; i++) {
8731 if (a[i] != b[i]) {
8732 return false;
8733 }
8734 }
8735
8736 return true;
8737}
8738/**
8739 * Convert an object into another type
8740 *
8741 * @param object - Value of unknown type.
8742 * @param type - Name of the desired type.
8743 *
8744 * @returns Object in the desired type.
8745 * @throws Error
8746 */
8747
8748
8749function convert(object, type) {
8750 var match;
8751
8752 if (object === undefined) {
8753 return undefined;
8754 }
8755
8756 if (object === null) {
8757 return null;
8758 }
8759
8760 if (!type) {
8761 return object;
8762 }
8763
8764 if (!(typeof type === "string") && !(type instanceof String)) {
8765 throw new Error("Type must be a string");
8766 } //noinspection FallthroughInSwitchStatementJS
8767
8768
8769 switch (type) {
8770 case "boolean":
8771 case "Boolean":
8772 return Boolean(object);
8773
8774 case "number":
8775 case "Number":
8776 if (isString(object) && !isNaN(Date.parse(object))) {
8777 return moment(object).valueOf();
8778 } else {
8779 // @TODO: I don't think that Number and String constructors are a good idea.
8780 // This could also fail if the object doesn't have valueOf method or if it's redefined.
8781 // For example: Object.create(null) or { valueOf: 7 }.
8782 return Number(object.valueOf());
8783 }
8784
8785 case "string":
8786 case "String":
8787 return String(object);
8788
8789 case "Date":
8790 if (isNumber(object)) {
8791 return new Date(object);
8792 }
8793
8794 if (object instanceof Date) {
8795 return new Date(object.valueOf());
8796 } else if (isMoment(object)) {
8797 return new Date(object.valueOf());
8798 }
8799
8800 if (isString(object)) {
8801 match = ASPDateRegex.exec(object);
8802
8803 if (match) {
8804 // object is an ASP date
8805 return new Date(Number(match[1])); // parse number
8806 } else {
8807 return moment(new Date(object)).toDate(); // parse string
8808 }
8809 } else {
8810 throw new Error("Cannot convert object of type " + getType(object) + " to type Date");
8811 }
8812
8813 case "Moment":
8814 if (isNumber(object)) {
8815 return moment(object);
8816 }
8817
8818 if (object instanceof Date) {
8819 return moment(object.valueOf());
8820 } else if (isMoment(object)) {
8821 return moment(object);
8822 }
8823
8824 if (isString(object)) {
8825 match = ASPDateRegex.exec(object);
8826
8827 if (match) {
8828 // object is an ASP date
8829 return moment(Number(match[1])); // parse number
8830 } else {
8831 return moment(object); // parse string
8832 }
8833 } else {
8834 throw new Error("Cannot convert object of type " + getType(object) + " to type Date");
8835 }
8836
8837 case "ISODate":
8838 if (isNumber(object)) {
8839 return new Date(object);
8840 } else if (object instanceof Date) {
8841 return object.toISOString();
8842 } else if (isMoment(object)) {
8843 return object.toDate().toISOString();
8844 } else if (isString(object)) {
8845 match = ASPDateRegex.exec(object);
8846
8847 if (match) {
8848 // object is an ASP date
8849 return new Date(Number(match[1])).toISOString(); // parse number
8850 } else {
8851 return moment(object).format(); // ISO 8601
8852 }
8853 } else {
8854 throw new Error("Cannot convert object of type " + getType(object) + " to type ISODate");
8855 }
8856
8857 case "ASPDate":
8858 if (isNumber(object)) {
8859 return "/Date(" + object + ")/";
8860 } else if (object instanceof Date || isMoment(object)) {
8861 return "/Date(" + object.valueOf() + ")/";
8862 } else if (isString(object)) {
8863 match = ASPDateRegex.exec(object);
8864
8865 var _value;
8866
8867 if (match) {
8868 // object is an ASP date
8869 _value = new Date(Number(match[1])).valueOf(); // parse number
8870 } else {
8871 _value = new Date(object).valueOf(); // parse string
8872 }
8873
8874 return "/Date(" + _value + ")/";
8875 } else {
8876 throw new Error("Cannot convert object of type " + getType(object) + " to type ASPDate");
8877 }
8878
8879 default:
8880 var never = type;
8881 throw new Error("Unknown type ".concat(never));
8882 }
8883}
8884/**
8885 * Get the type of an object, for example exports.getType([]) returns 'Array'
8886 *
8887 * @param object - Input value of unknown type.
8888 *
8889 * @returns Detected type.
8890 */
8891
8892
8893function getType(object) {
8894 var type = _typeof(object);
8895
8896 if (type === "object") {
8897 if (object === null) {
8898 return "null";
8899 }
8900
8901 if (object instanceof Boolean) {
8902 return "Boolean";
8903 }
8904
8905 if (object instanceof Number) {
8906 return "Number";
8907 }
8908
8909 if (object instanceof String) {
8910 return "String";
8911 }
8912
8913 if (Array.isArray(object)) {
8914 return "Array";
8915 }
8916
8917 if (object instanceof Date) {
8918 return "Date";
8919 }
8920
8921 return "Object";
8922 }
8923
8924 if (type === "number") {
8925 return "Number";
8926 }
8927
8928 if (type === "boolean") {
8929 return "Boolean";
8930 }
8931
8932 if (type === "string") {
8933 return "String";
8934 }
8935
8936 if (type === undefined) {
8937 return "undefined";
8938 }
8939
8940 return type;
8941}
8942/**
8943 * Used to extend an array and copy it. This is used to propagate paths recursively.
8944 *
8945 * @param arr - First part.
8946 * @param newValue - The value to be aadded into the array.
8947 *
8948 * @returns A new array with all items from arr and newValue (which is last).
8949 */
8950
8951
8952function copyAndExtendArray(arr, newValue) {
8953 return [].concat(_toConsumableArray(arr), [newValue]);
8954}
8955/**
8956 * Used to extend an array and copy it. This is used to propagate paths recursively.
8957 *
8958 * @param arr - The array to be copied.
8959 *
8960 * @returns Shallow copy of arr.
8961 */
8962
8963
8964function copyArray(arr) {
8965 return arr.slice();
8966}
8967/**
8968 * Retrieve the absolute left value of a DOM element
8969 *
8970 * @param elem - A dom element, for example a div.
8971 *
8972 * @returns The absolute left position of this element in the browser page.
8973 */
8974
8975
8976function getAbsoluteLeft(elem) {
8977 return elem.getBoundingClientRect().left;
8978}
8979/**
8980 * Retrieve the absolute right value of a DOM element
8981 *
8982 * @param elem - A dom element, for example a div.
8983 *
8984 * @returns The absolute right position of this element in the browser page.
8985 */
8986
8987
8988function getAbsoluteRight(elem) {
8989 return elem.getBoundingClientRect().right;
8990}
8991/**
8992 * Retrieve the absolute top value of a DOM element
8993 *
8994 * @param elem - A dom element, for example a div.
8995 *
8996 * @returns The absolute top position of this element in the browser page.
8997 */
8998
8999
9000function getAbsoluteTop(elem) {
9001 return elem.getBoundingClientRect().top;
9002}
9003/**
9004 * Add a className to the given elements style.
9005 *
9006 * @param elem - The element to which the classes will be added.
9007 * @param classNames - Space separated list of classes.
9008 */
9009
9010
9011function addClassName(elem, classNames) {
9012 var classes = elem.className.split(" ");
9013 var newClasses = classNames.split(" ");
9014 classes = classes.concat(newClasses.filter(function (className) {
9015 return classes.indexOf(className) < 0;
9016 }));
9017 elem.className = classes.join(" ");
9018}
9019/**
9020 * Remove a className from the given elements style.
9021 *
9022 * @param elem - The element from which the classes will be removed.
9023 * @param classNames - Space separated list of classes.
9024 */
9025
9026
9027function removeClassName(elem, classNames) {
9028 var classes = elem.className.split(" ");
9029 var oldClasses = classNames.split(" ");
9030 classes = classes.filter(function (className) {
9031 return oldClasses.indexOf(className) < 0;
9032 });
9033 elem.className = classes.join(" ");
9034}
9035/**
9036 * For each method for both arrays and objects.
9037 * In case of an array, the built-in Array.forEach() is applied (**No, it's not!**).
9038 * In case of an Object, the method loops over all properties of the object.
9039 *
9040 * @param object - An Object or Array to be iterated over.
9041 * @param callback - Array.forEach-like callback.
9042 */
9043
9044
9045function forEach(object, callback) {
9046 if (Array.isArray(object)) {
9047 // array
9048 var len = object.length;
9049
9050 for (var i = 0; i < len; i++) {
9051 callback(object[i], i, object);
9052 }
9053 } else {
9054 // object
9055 for (var _key2 in object) {
9056 if (Object.prototype.hasOwnProperty.call(object, _key2)) {
9057 callback(object[_key2], _key2, object);
9058 }
9059 }
9060 }
9061}
9062/**
9063 * Convert an object into an array: all objects properties are put into the array. The resulting array is unordered.
9064 *
9065 * @param o - Object that contains the properties and methods.
9066 *
9067 * @returns An array of unordered values.
9068 */
9069
9070
9071var toArray = Object.values;
9072/**
9073 * Update a property in an object
9074 *
9075 * @param object - The object whose property will be updated.
9076 * @param key - Name of the property to be updated.
9077 * @param value - The new value to be assigned.
9078 *
9079 * @returns Whether the value was updated (true) or already strictly the same in the original object (false).
9080 */
9081
9082function updateProperty(object, key, value) {
9083 if (object[key] !== value) {
9084 object[key] = value;
9085 return true;
9086 } else {
9087 return false;
9088 }
9089}
9090/**
9091 * Throttle the given function to be only executed once per animation frame.
9092 *
9093 * @param fn - The original function.
9094 *
9095 * @returns The throttled function.
9096 */
9097
9098
9099function throttle(fn) {
9100 var scheduled = false;
9101 return function () {
9102 if (!scheduled) {
9103 scheduled = true;
9104 requestAnimationFrame(function () {
9105 scheduled = false;
9106 fn();
9107 });
9108 }
9109 };
9110}
9111/**
9112 * Add and event listener. Works for all browsers.
9113 *
9114 * @param element - The element to bind the event listener to.
9115 * @param action - Same as Element.addEventListener(action, —, —).
9116 * @param listener - Same as Element.addEventListener(—, listener, —).
9117 * @param useCapture - Same as Element.addEventListener(—, —, useCapture).
9118 */
9119
9120
9121function addEventListener(element, action, listener, useCapture) {
9122 if (element.addEventListener) {
9123 if (useCapture === undefined) {
9124 useCapture = false;
9125 }
9126
9127 if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) {
9128 action = "DOMMouseScroll"; // For Firefox
9129 }
9130
9131 element.addEventListener(action, listener, useCapture);
9132 } else {
9133 // @TODO: IE types? Does anyone care?
9134 element.attachEvent("on" + action, listener); // IE browsers
9135 }
9136}
9137/**
9138 * Remove an event listener from an element
9139 *
9140 * @param element - The element to bind the event listener to.
9141 * @param action - Same as Element.removeEventListener(action, —, —).
9142 * @param listener - Same as Element.removeEventListener(—, listener, —).
9143 * @param useCapture - Same as Element.removeEventListener(—, —, useCapture).
9144 */
9145
9146
9147function removeEventListener(element, action, listener, useCapture) {
9148 if (element.removeEventListener) {
9149 // non-IE browsers
9150 if (useCapture === undefined) {
9151 useCapture = false;
9152 }
9153
9154 if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) {
9155 action = "DOMMouseScroll"; // For Firefox
9156 }
9157
9158 element.removeEventListener(action, listener, useCapture);
9159 } else {
9160 // @TODO: IE types? Does anyone care?
9161 element.detachEvent("on" + action, listener); // IE browsers
9162 }
9163}
9164/**
9165 * Cancels the event's default action if it is cancelable, without stopping further propagation of the event.
9166 *
9167 * @param event - The event whose default action should be prevented.
9168 */
9169
9170
9171function preventDefault(event) {
9172 if (!event) {
9173 event = window.event;
9174 }
9175
9176 if (!event) ;else if (event.preventDefault) {
9177 event.preventDefault(); // non-IE browsers
9178 } else {
9179 // @TODO: IE types? Does anyone care?
9180 event.returnValue = false; // IE browsers
9181 }
9182}
9183/**
9184 * Get HTML element which is the target of the event.
9185 *
9186 * @param event - The event.
9187 *
9188 * @returns The element or null if not obtainable.
9189 */
9190
9191
9192function getTarget() {
9193 var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.event; // code from http://www.quirksmode.org/js/events_properties.html
9194 // @TODO: EventTarget can be almost anything, is it okay to return only Elements?
9195
9196 var target = null;
9197 if (!event) ;else if (event.target) {
9198 target = event.target;
9199 } else if (event.srcElement) {
9200 target = event.srcElement;
9201 }
9202
9203 if (!(target instanceof Element)) {
9204 return null;
9205 }
9206
9207 if (target.nodeType != null && target.nodeType == 3) {
9208 // defeat Safari bug
9209 target = target.parentNode;
9210
9211 if (!(target instanceof Element)) {
9212 return null;
9213 }
9214 }
9215
9216 return target;
9217}
9218/**
9219 * Check if given element contains given parent somewhere in the DOM tree
9220 *
9221 * @param element - The element to be tested.
9222 * @param parent - The ancestor (not necessarily parent) of the element.
9223 *
9224 * @returns True if parent is an ancestor of the element, false otherwise.
9225 */
9226
9227
9228function hasParent(element, parent) {
9229 var elem = element;
9230
9231 while (elem) {
9232 if (elem === parent) {
9233 return true;
9234 } else if (elem.parentNode) {
9235 elem = elem.parentNode;
9236 } else {
9237 return false;
9238 }
9239 }
9240
9241 return false;
9242}
9243
9244var option = {
9245 /**
9246 * Convert a value into a boolean.
9247 *
9248 * @param value - Value to be converted intoboolean, a function will be executed as (() => unknown).
9249 * @param defaultValue - If the value or the return value of the function == null then this will be returned.
9250 *
9251 * @returns Corresponding boolean value, if none then the default value, if none then null.
9252 */
9253 asBoolean: function asBoolean(value, defaultValue) {
9254 if (typeof value == "function") {
9255 value = value();
9256 }
9257
9258 if (value != null) {
9259 return value != false;
9260 }
9261
9262 return defaultValue || null;
9263 },
9264
9265 /**
9266 * Convert a value into a number.
9267 *
9268 * @param value - Value to be converted intonumber, a function will be executed as (() => unknown).
9269 * @param defaultValue - If the value or the return value of the function == null then this will be returned.
9270 *
9271 * @returns Corresponding **boxed** number value, if none then the default value, if none then null.
9272 */
9273 asNumber: function asNumber(value, defaultValue) {
9274 if (typeof value == "function") {
9275 value = value();
9276 }
9277
9278 if (value != null) {
9279 return Number(value) || defaultValue || null;
9280 }
9281
9282 return defaultValue || null;
9283 },
9284
9285 /**
9286 * Convert a value into a string.
9287 *
9288 * @param value - Value to be converted intostring, a function will be executed as (() => unknown).
9289 * @param defaultValue - If the value or the return value of the function == null then this will be returned.
9290 *
9291 * @returns Corresponding **boxed** string value, if none then the default value, if none then null.
9292 */
9293 asString: function asString(value, defaultValue) {
9294 if (typeof value == "function") {
9295 value = value();
9296 }
9297
9298 if (value != null) {
9299 return String(value);
9300 }
9301
9302 return defaultValue || null;
9303 },
9304
9305 /**
9306 * Convert a value into a size.
9307 *
9308 * @param value - Value to be converted intosize, a function will be executed as (() => unknown).
9309 * @param defaultValue - If the value or the return value of the function == null then this will be returned.
9310 *
9311 * @returns Corresponding string value (number + 'px'), if none then the default value, if none then null.
9312 */
9313 asSize: function asSize(value, defaultValue) {
9314 if (typeof value == "function") {
9315 value = value();
9316 }
9317
9318 if (isString(value)) {
9319 return value;
9320 } else if (isNumber(value)) {
9321 return value + "px";
9322 } else {
9323 return defaultValue || null;
9324 }
9325 },
9326
9327 /**
9328 * Convert a value into a DOM Element.
9329 *
9330 * @param value - Value to be converted into DOM Element, a function will be executed as (() => unknown).
9331 * @param defaultValue - If the value or the return value of the function == null then this will be returned.
9332 *
9333 * @returns The DOM Element, if none then the default value, if none then null.
9334 */
9335 asElement: function asElement(value, defaultValue) {
9336 if (typeof value == "function") {
9337 value = value();
9338 }
9339
9340 return value || defaultValue || null;
9341 }
9342};
9343/**
9344 * Convert hex color string into RGB color object.
9345 * http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
9346 *
9347 * @param hex - Hex color string (3 or 6 digits, with or without #).
9348 *
9349 * @returns RGB color object.
9350 */
9351
9352function hexToRGB(hex) {
9353 var result;
9354
9355 switch (hex.length) {
9356 case 3:
9357 case 4:
9358 result = shortHexRE.exec(hex);
9359 return result ? {
9360 r: parseInt(result[1] + result[1], 16),
9361 g: parseInt(result[2] + result[2], 16),
9362 b: parseInt(result[3] + result[3], 16)
9363 } : null;
9364
9365 case 6:
9366 case 7:
9367 result = fullHexRE.exec(hex);
9368 return result ? {
9369 r: parseInt(result[1], 16),
9370 g: parseInt(result[2], 16),
9371 b: parseInt(result[3], 16)
9372 } : null;
9373
9374 default:
9375 return null;
9376 }
9377}
9378/**
9379 * This function takes string color in hex or RGB format and adds the opacity, RGBA is passed through unchanged.
9380 *
9381 * @param color - The color string (hex, RGB, RGBA).
9382 * @param opacity - The new opacity.
9383 *
9384 * @returns RGBA string, for example 'rgba(255, 0, 127, 0.3)'.
9385 */
9386
9387
9388function overrideOpacity(color, opacity) {
9389 if (color.indexOf("rgba") !== -1) {
9390 return color;
9391 } else if (color.indexOf("rgb") !== -1) {
9392 var rgb = color.substr(color.indexOf("(") + 1).replace(")", "").split(",");
9393 return "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + opacity + ")";
9394 } else {
9395 var _rgb = hexToRGB(color);
9396
9397 if (_rgb == null) {
9398 return color;
9399 } else {
9400 return "rgba(" + _rgb.r + "," + _rgb.g + "," + _rgb.b + "," + opacity + ")";
9401 }
9402 }
9403}
9404/**
9405 * Convert RGB <0, 255> into hex color string.
9406 *
9407 * @param red - Red channel.
9408 * @param green - Green channel.
9409 * @param blue - Blue channel.
9410 *
9411 * @returns Hex color string (for example: '#0acdc0').
9412 */
9413
9414
9415function RGBToHex(red, green, blue) {
9416 return "#" + ((1 << 24) + (red << 16) + (green << 8) + blue).toString(16).slice(1);
9417}
9418/**
9419 * Parse a color property into an object with border, background, and highlight colors
9420 *
9421 * @param inputColor - Shorthand color string or input color object.
9422 * @param defaultColor - Full color object to fill in missing values in inputColor.
9423 *
9424 * @returns Color object.
9425 */
9426
9427
9428function parseColor(inputColor, defaultColor) {
9429 if (isString(inputColor)) {
9430 var colorStr = inputColor;
9431
9432 if (isValidRGB(colorStr)) {
9433 var rgb = colorStr.substr(4).substr(0, colorStr.length - 5).split(",").map(function (value) {
9434 return parseInt(value);
9435 });
9436 colorStr = RGBToHex(rgb[0], rgb[1], rgb[2]);
9437 }
9438
9439 if (isValidHex(colorStr) === true) {
9440 var hsv = hexToHSV(colorStr);
9441 var lighterColorHSV = {
9442 h: hsv.h,
9443 s: hsv.s * 0.8,
9444 v: Math.min(1, hsv.v * 1.02)
9445 };
9446 var darkerColorHSV = {
9447 h: hsv.h,
9448 s: Math.min(1, hsv.s * 1.25),
9449 v: hsv.v * 0.8
9450 };
9451 var darkerColorHex = HSVToHex(darkerColorHSV.h, darkerColorHSV.s, darkerColorHSV.v);
9452 var lighterColorHex = HSVToHex(lighterColorHSV.h, lighterColorHSV.s, lighterColorHSV.v);
9453 return {
9454 background: colorStr,
9455 border: darkerColorHex,
9456 highlight: {
9457 background: lighterColorHex,
9458 border: darkerColorHex
9459 },
9460 hover: {
9461 background: lighterColorHex,
9462 border: darkerColorHex
9463 }
9464 };
9465 } else {
9466 return {
9467 background: colorStr,
9468 border: colorStr,
9469 highlight: {
9470 background: colorStr,
9471 border: colorStr
9472 },
9473 hover: {
9474 background: colorStr,
9475 border: colorStr
9476 }
9477 };
9478 }
9479 } else {
9480 if (defaultColor) {
9481 var color = {
9482 background: inputColor.background || defaultColor.background,
9483 border: inputColor.border || defaultColor.border,
9484 highlight: isString(inputColor.highlight) ? {
9485 border: inputColor.highlight,
9486 background: inputColor.highlight
9487 } : {
9488 background: inputColor.highlight && inputColor.highlight.background || defaultColor.highlight.background,
9489 border: inputColor.highlight && inputColor.highlight.border || defaultColor.highlight.border
9490 },
9491 hover: isString(inputColor.hover) ? {
9492 border: inputColor.hover,
9493 background: inputColor.hover
9494 } : {
9495 border: inputColor.hover && inputColor.hover.border || defaultColor.hover.border,
9496 background: inputColor.hover && inputColor.hover.background || defaultColor.hover.background
9497 }
9498 };
9499 return color;
9500 } else {
9501 var _color = {
9502 background: inputColor.background || undefined,
9503 border: inputColor.border || undefined,
9504 highlight: isString(inputColor.highlight) ? {
9505 border: inputColor.highlight,
9506 background: inputColor.highlight
9507 } : {
9508 background: inputColor.highlight && inputColor.highlight.background || undefined,
9509 border: inputColor.highlight && inputColor.highlight.border || undefined
9510 },
9511 hover: isString(inputColor.hover) ? {
9512 border: inputColor.hover,
9513 background: inputColor.hover
9514 } : {
9515 border: inputColor.hover && inputColor.hover.border || undefined,
9516 background: inputColor.hover && inputColor.hover.background || undefined
9517 }
9518 };
9519 return _color;
9520 }
9521 }
9522}
9523/**
9524 * Convert RGB <0, 255> into HSV object.
9525 * http://www.javascripter.net/faq/rgb2hsv.htm
9526 *
9527 * @param red - Red channel.
9528 * @param green - Green channel.
9529 * @param blue - Blue channel.
9530 *
9531 * @returns HSV color object.
9532 */
9533
9534
9535function RGBToHSV(red, green, blue) {
9536 red = red / 255;
9537 green = green / 255;
9538 blue = blue / 255;
9539 var minRGB = Math.min(red, Math.min(green, blue));
9540 var maxRGB = Math.max(red, Math.max(green, blue)); // Black-gray-white
9541
9542 if (minRGB === maxRGB) {
9543 return {
9544 h: 0,
9545 s: 0,
9546 v: minRGB
9547 };
9548 } // Colors other than black-gray-white:
9549
9550
9551 var d = red === minRGB ? green - blue : blue === minRGB ? red - green : blue - red;
9552 var h = red === minRGB ? 3 : blue === minRGB ? 1 : 5;
9553 var hue = 60 * (h - d / (maxRGB - minRGB)) / 360;
9554 var saturation = (maxRGB - minRGB) / maxRGB;
9555 var value = maxRGB;
9556 return {
9557 h: hue,
9558 s: saturation,
9559 v: value
9560 };
9561}
9562
9563var cssUtil = {
9564 // split a string with css styles into an object with key/values
9565 split: function split(cssText) {
9566 var styles = {};
9567 cssText.split(";").forEach(function (style) {
9568 if (style.trim() != "") {
9569 var parts = style.split(":");
9570
9571 var _key3 = parts[0].trim();
9572
9573 var _value2 = parts[1].trim();
9574
9575 styles[_key3] = _value2;
9576 }
9577 });
9578 return styles;
9579 },
9580 // build a css text string from an object with key/values
9581 join: function join(styles) {
9582 return Object.keys(styles).map(function (key) {
9583 return key + ": " + styles[key];
9584 }).join("; ");
9585 }
9586};
9587/**
9588 * Append a string with css styles to an element
9589 *
9590 * @param element - The element that will receive new styles.
9591 * @param cssText - The styles to be appended.
9592 */
9593
9594function addCssText(element, cssText) {
9595 var currentStyles = cssUtil.split(element.style.cssText);
9596 var newStyles = cssUtil.split(cssText);
9597
9598 var styles = _objectSpread2({}, currentStyles, {}, newStyles);
9599
9600 element.style.cssText = cssUtil.join(styles);
9601}
9602/**
9603 * Remove a string with css styles from an element
9604 *
9605 * @param element - The element from which styles should be removed.
9606 * @param cssText - The styles to be removed.
9607 */
9608
9609
9610function removeCssText(element, cssText) {
9611 var styles = cssUtil.split(element.style.cssText);
9612 var removeStyles = cssUtil.split(cssText);
9613
9614 for (var _key4 in removeStyles) {
9615 if (Object.prototype.hasOwnProperty.call(removeStyles, _key4)) {
9616 delete styles[_key4];
9617 }
9618 }
9619
9620 element.style.cssText = cssUtil.join(styles);
9621}
9622/**
9623 * Convert HSV <0, 1> into RGB color object.
9624 * https://gist.github.com/mjijackson/5311256
9625 *
9626 * @param h - Hue
9627 * @param s - Saturation
9628 * @param v - Value
9629 *
9630 * @returns RGB color object.
9631 */
9632
9633
9634function HSVToRGB(h, s, v) {
9635 var r;
9636 var g;
9637 var b;
9638 var i = Math.floor(h * 6);
9639 var f = h * 6 - i;
9640 var p = v * (1 - s);
9641 var q = v * (1 - f * s);
9642 var t = v * (1 - (1 - f) * s);
9643
9644 switch (i % 6) {
9645 case 0:
9646 r = v, g = t, b = p;
9647 break;
9648
9649 case 1:
9650 r = q, g = v, b = p;
9651 break;
9652
9653 case 2:
9654 r = p, g = v, b = t;
9655 break;
9656
9657 case 3:
9658 r = p, g = q, b = v;
9659 break;
9660
9661 case 4:
9662 r = t, g = p, b = v;
9663 break;
9664
9665 case 5:
9666 r = v, g = p, b = q;
9667 break;
9668 }
9669
9670 return {
9671 r: Math.floor(r * 255),
9672 g: Math.floor(g * 255),
9673 b: Math.floor(b * 255)
9674 };
9675}
9676/**
9677 * Convert HSV <0, 1> into hex color string.
9678 *
9679 * @param h - Hue
9680 * @param s - Saturation
9681 * @param v - Value
9682 *
9683 * @returns Hex color string.
9684 */
9685
9686
9687function HSVToHex(h, s, v) {
9688 var rgb = HSVToRGB(h, s, v);
9689 return RGBToHex(rgb.r, rgb.g, rgb.b);
9690}
9691/**
9692 * Convert hex color string into HSV <0, 1>.
9693 *
9694 * @param hex - Hex color string.
9695 *
9696 * @returns HSV color object.
9697 */
9698
9699
9700function hexToHSV(hex) {
9701 var rgb = hexToRGB(hex);
9702
9703 if (!rgb) {
9704 throw new TypeError("'".concat(hex, "' is not a valid color."));
9705 }
9706
9707 return RGBToHSV(rgb.r, rgb.g, rgb.b);
9708}
9709/**
9710 * Validate hex color string.
9711 *
9712 * @param hex - Unknown string that may contain a color.
9713 *
9714 * @returns True if the string is valid, false otherwise.
9715 */
9716
9717
9718function isValidHex(hex) {
9719 var isOk = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(hex);
9720 return isOk;
9721}
9722/**
9723 * Validate RGB color string.
9724 *
9725 * @param rgb - Unknown string that may contain a color.
9726 *
9727 * @returns True if the string is valid, false otherwise.
9728 */
9729
9730
9731function isValidRGB(rgb) {
9732 return rgbRE.test(rgb);
9733}
9734/**
9735 * Validate RGBA color string.
9736 *
9737 * @param rgba - Unknown string that may contain a color.
9738 *
9739 * @returns True if the string is valid, false otherwise.
9740 */
9741
9742
9743function isValidRGBA(rgba) {
9744 return rgbaRE.test(rgba);
9745}
9746/**
9747 * This recursively redirects the prototype of JSON objects to the referenceObject.
9748 * This is used for default options.
9749 *
9750 * @param fields - Names of properties to be bridged.
9751 * @param referenceObject - The original object.
9752 *
9753 * @returns A new object inheriting from the referenceObject.
9754 */
9755
9756
9757function selectiveBridgeObject(fields, referenceObject) {
9758 if (referenceObject !== null && _typeof(referenceObject) === "object") {
9759 // !!! typeof null === 'object'
9760 var objectTo = Object.create(referenceObject);
9761
9762 for (var i = 0; i < fields.length; i++) {
9763 if (Object.prototype.hasOwnProperty.call(referenceObject, fields[i])) {
9764 if (_typeof(referenceObject[fields[i]]) == "object") {
9765 objectTo[fields[i]] = bridgeObject(referenceObject[fields[i]]);
9766 }
9767 }
9768 }
9769
9770 return objectTo;
9771 } else {
9772 return null;
9773 }
9774}
9775/**
9776 * This recursively redirects the prototype of JSON objects to the referenceObject.
9777 * This is used for default options.
9778 *
9779 * @param referenceObject - The original object.
9780 *
9781 * @returns The Element if the referenceObject is an Element, or a new object inheriting from the referenceObject.
9782 */
9783
9784
9785function bridgeObject(referenceObject) {
9786 if (referenceObject === null || _typeof(referenceObject) !== "object") {
9787 return null;
9788 }
9789
9790 if (referenceObject instanceof Element) {
9791 // Avoid bridging DOM objects
9792 return referenceObject;
9793 }
9794
9795 var objectTo = Object.create(referenceObject);
9796
9797 for (var i in referenceObject) {
9798 if (Object.prototype.hasOwnProperty.call(referenceObject, i)) {
9799 if (_typeof(referenceObject[i]) == "object") {
9800 objectTo[i] = bridgeObject(referenceObject[i]);
9801 }
9802 }
9803 }
9804
9805 return objectTo;
9806}
9807/**
9808 * This method provides a stable sort implementation, very fast for presorted data.
9809 *
9810 * @param a - The array to be sorted (in-place).
9811 * @param compare - An order comparator.
9812 *
9813 * @returns The argument a.
9814 */
9815
9816
9817function insertSort(a, compare) {
9818 for (var i = 0; i < a.length; i++) {
9819 var k = a[i];
9820 var j = void 0;
9821
9822 for (j = i; j > 0 && compare(k, a[j - 1]) < 0; j--) {
9823 a[j] = a[j - 1];
9824 }
9825
9826 a[j] = k;
9827 }
9828
9829 return a;
9830}
9831/**
9832 * This is used to set the options of subobjects in the options object.
9833 *
9834 * A requirement of these subobjects is that they have an 'enabled' element
9835 * which is optional for the user but mandatory for the program.
9836 *
9837 * The added value here of the merge is that option 'enabled' is set as required.
9838 *
9839 * @param mergeTarget - Either this.options or the options used for the groups.
9840 * @param options - Options.
9841 * @param option - Option key in the options argument.
9842 * @param globalOptions - Global options, passed in to determine value of option 'enabled'.
9843 */
9844
9845
9846function mergeOptions(mergeTarget, options, option) {
9847 var globalOptions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; // Local helpers
9848
9849 var isPresent = function isPresent(obj) {
9850 return obj !== null && obj !== undefined;
9851 };
9852
9853 var isObject = function isObject(obj) {
9854 return obj !== null && _typeof(obj) === "object";
9855 }; // https://stackoverflow.com/a/34491287/1223531
9856
9857
9858 var isEmpty = function isEmpty(obj) {
9859 for (var x in obj) {
9860 if (Object.prototype.hasOwnProperty.call(obj, x)) {
9861 return false;
9862 }
9863 }
9864
9865 return true;
9866 }; // Guards
9867
9868
9869 if (!isObject(mergeTarget)) {
9870 throw new Error("Parameter mergeTarget must be an object");
9871 }
9872
9873 if (!isObject(options)) {
9874 throw new Error("Parameter options must be an object");
9875 }
9876
9877 if (!isPresent(option)) {
9878 throw new Error("Parameter option must have a value");
9879 }
9880
9881 if (!isObject(globalOptions)) {
9882 throw new Error("Parameter globalOptions must be an object");
9883 } //
9884 // Actual merge routine, separated from main logic
9885 // Only a single level of options is merged. Deeper levels are ref'd. This may actually be an issue.
9886 //
9887
9888
9889 var doMerge = function doMerge(target, options, option) {
9890 if (!isObject(target[option])) {
9891 target[option] = {};
9892 }
9893
9894 var src = options[option];
9895 var dst = target[option];
9896
9897 for (var prop in src) {
9898 if (Object.prototype.hasOwnProperty.call(src, prop)) {
9899 dst[prop] = src[prop];
9900 }
9901 }
9902 }; // Local initialization
9903
9904
9905 var srcOption = options[option];
9906 var globalPassed = isObject(globalOptions) && !isEmpty(globalOptions);
9907 var globalOption = globalPassed ? globalOptions[option] : undefined;
9908 var globalEnabled = globalOption ? globalOption.enabled : undefined; /////////////////////////////////////////
9909 // Main routine
9910 /////////////////////////////////////////
9911
9912 if (srcOption === undefined) {
9913 return; // Nothing to do
9914 }
9915
9916 if (typeof srcOption === "boolean") {
9917 if (!isObject(mergeTarget[option])) {
9918 mergeTarget[option] = {};
9919 }
9920
9921 mergeTarget[option].enabled = srcOption;
9922 return;
9923 }
9924
9925 if (srcOption === null && !isObject(mergeTarget[option])) {
9926 // If possible, explicit copy from globals
9927 if (isPresent(globalOption)) {
9928 mergeTarget[option] = Object.create(globalOption);
9929 } else {
9930 return; // Nothing to do
9931 }
9932 }
9933
9934 if (!isObject(srcOption)) {
9935 return;
9936 } //
9937 // Ensure that 'enabled' is properly set. It is required internally
9938 // Note that the value from options will always overwrite the existing value
9939 //
9940
9941
9942 var enabled = true; // default value
9943
9944 if (srcOption.enabled !== undefined) {
9945 enabled = srcOption.enabled;
9946 } else {
9947 // Take from globals, if present
9948 if (globalEnabled !== undefined) {
9949 enabled = globalOption.enabled;
9950 }
9951 }
9952
9953 doMerge(mergeTarget, options, option);
9954 mergeTarget[option].enabled = enabled;
9955}
9956/**
9957 * This function does a binary search for a visible item in a sorted list. If we find a visible item, the code that uses
9958 * this function will then iterate in both directions over this sorted list to find all visible items.
9959 *
9960 * @param orderedItems - Items ordered by start
9961 * @param comparator - -1 is lower, 0 is equal, 1 is higher
9962 * @param field - Property name on an item (i.e. item[field]).
9963 * @param field2 - Second property name on an item (i.e. item[field][field2]).
9964 *
9965 * @returns Index of the found item or -1 if nothing was found.
9966 */
9967
9968
9969function binarySearchCustom(orderedItems, comparator, field, field2) {
9970 var maxIterations = 10000;
9971 var iteration = 0;
9972 var low = 0;
9973 var high = orderedItems.length - 1;
9974
9975 while (low <= high && iteration < maxIterations) {
9976 var middle = Math.floor((low + high) / 2);
9977 var item = orderedItems[middle];
9978
9979 var _value3 = field2 === undefined ? item[field] : item[field][field2];
9980
9981 var searchResult = comparator(_value3);
9982
9983 if (searchResult == 0) {
9984 // jihaa, found a visible item!
9985 return middle;
9986 } else if (searchResult == -1) {
9987 // it is too small --> increase low
9988 low = middle + 1;
9989 } else {
9990 // it is too big --> decrease high
9991 high = middle - 1;
9992 }
9993
9994 iteration++;
9995 }
9996
9997 return -1;
9998}
9999/**
10000 * This function does a binary search for a specific value in a sorted array. If it does not exist but is in between of
10001 * two values, we return either the one before or the one after, depending on user input
10002 * If it is found, we return the index, else -1.
10003 *
10004 * @param orderedItems - Sorted array.
10005 * @param target - The searched value.
10006 * @param field - Name of the property in items to be searched.
10007 * @param sidePreference - If the target is between two values, should the index of the before or the after be returned?
10008 * @param comparator - An optional comparator, returning -1, 0, 1 for <, ===, >.
10009 *
10010 * @returns The index of found value or -1 if nothing was found.
10011 */
10012
10013
10014function binarySearchValue(orderedItems, target, field, sidePreference, comparator) {
10015 var maxIterations = 10000;
10016 var iteration = 0;
10017 var low = 0;
10018 var high = orderedItems.length - 1;
10019 var prevValue;
10020 var value;
10021 var nextValue;
10022 var middle;
10023 comparator = comparator != undefined ? comparator : function (a, b) {
10024 return a == b ? 0 : a < b ? -1 : 1;
10025 };
10026
10027 while (low <= high && iteration < maxIterations) {
10028 // get a new guess
10029 middle = Math.floor(0.5 * (high + low));
10030 prevValue = orderedItems[Math.max(0, middle - 1)][field];
10031 value = orderedItems[middle][field];
10032 nextValue = orderedItems[Math.min(orderedItems.length - 1, middle + 1)][field];
10033
10034 if (comparator(value, target) == 0) {
10035 // we found the target
10036 return middle;
10037 } else if (comparator(prevValue, target) < 0 && comparator(value, target) > 0) {
10038 // target is in between of the previous and the current
10039 return sidePreference == "before" ? Math.max(0, middle - 1) : middle;
10040 } else if (comparator(value, target) < 0 && comparator(nextValue, target) > 0) {
10041 // target is in between of the current and the next
10042 return sidePreference == "before" ? middle : Math.min(orderedItems.length - 1, middle + 1);
10043 } else {
10044 // didnt find the target, we need to change our boundaries.
10045 if (comparator(value, target) < 0) {
10046 // it is too small --> increase low
10047 low = middle + 1;
10048 } else {
10049 // it is too big --> decrease high
10050 high = middle - 1;
10051 }
10052 }
10053
10054 iteration++;
10055 } // didnt find anything. Return -1.
10056
10057
10058 return -1;
10059}
10060/*
10061 * Easing Functions.
10062 * Only considering the t value for the range [0, 1] => [0, 1].
10063 *
10064 * Inspiration: from http://gizma.com/easing/
10065 * https://gist.github.com/gre/1650294
10066 */
10067
10068
10069var easingFunctions = {
10070 /**
10071 * no easing, no acceleration
10072 *
10073 * @param t - Time.
10074 *
10075 * @returns Value at time t.
10076 */
10077 linear: function linear(t) {
10078 return t;
10079 },
10080
10081 /**
10082 * accelerating from zero velocity
10083 *
10084 * @param t - Time.
10085 *
10086 * @returns Value at time t.
10087 */
10088 easeInQuad: function easeInQuad(t) {
10089 return t * t;
10090 },
10091
10092 /**
10093 * decelerating to zero velocity
10094 *
10095 * @param t - Time.
10096 *
10097 * @returns Value at time t.
10098 */
10099 easeOutQuad: function easeOutQuad(t) {
10100 return t * (2 - t);
10101 },
10102
10103 /**
10104 * acceleration until halfway, then deceleration
10105 *
10106 * @param t - Time.
10107 *
10108 * @returns Value at time t.
10109 */
10110 easeInOutQuad: function easeInOutQuad(t) {
10111 return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
10112 },
10113
10114 /**
10115 * accelerating from zero velocity
10116 *
10117 * @param t - Time.
10118 *
10119 * @returns Value at time t.
10120 */
10121 easeInCubic: function easeInCubic(t) {
10122 return t * t * t;
10123 },
10124
10125 /**
10126 * decelerating to zero velocity
10127 *
10128 * @param t - Time.
10129 *
10130 * @returns Value at time t.
10131 */
10132 easeOutCubic: function easeOutCubic(t) {
10133 return --t * t * t + 1;
10134 },
10135
10136 /**
10137 * acceleration until halfway, then deceleration
10138 *
10139 * @param t - Time.
10140 *
10141 * @returns Value at time t.
10142 */
10143 easeInOutCubic: function easeInOutCubic(t) {
10144 return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
10145 },
10146
10147 /**
10148 * accelerating from zero velocity
10149 *
10150 * @param t - Time.
10151 *
10152 * @returns Value at time t.
10153 */
10154 easeInQuart: function easeInQuart(t) {
10155 return t * t * t * t;
10156 },
10157
10158 /**
10159 * decelerating to zero velocity
10160 *
10161 * @param t - Time.
10162 *
10163 * @returns Value at time t.
10164 */
10165 easeOutQuart: function easeOutQuart(t) {
10166 return 1 - --t * t * t * t;
10167 },
10168
10169 /**
10170 * acceleration until halfway, then deceleration
10171 *
10172 * @param t - Time.
10173 *
10174 * @returns Value at time t.
10175 */
10176 easeInOutQuart: function easeInOutQuart(t) {
10177 return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
10178 },
10179
10180 /**
10181 * accelerating from zero velocity
10182 *
10183 * @param t - Time.
10184 *
10185 * @returns Value at time t.
10186 */
10187 easeInQuint: function easeInQuint(t) {
10188 return t * t * t * t * t;
10189 },
10190
10191 /**
10192 * decelerating to zero velocity
10193 *
10194 * @param t - Time.
10195 *
10196 * @returns Value at time t.
10197 */
10198 easeOutQuint: function easeOutQuint(t) {
10199 return 1 + --t * t * t * t * t;
10200 },
10201
10202 /**
10203 * acceleration until halfway, then deceleration
10204 *
10205 * @param t - Time.
10206 *
10207 * @returns Value at time t.
10208 */
10209 easeInOutQuint: function easeInOutQuint(t) {
10210 return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
10211 }
10212};
10213/**
10214 * Experimentaly compute the width of the scrollbar for this browser.
10215 *
10216 * @returns The width in pixels.
10217 */
10218
10219function getScrollBarWidth() {
10220 var inner = document.createElement("p");
10221 inner.style.width = "100%";
10222 inner.style.height = "200px";
10223 var outer = document.createElement("div");
10224 outer.style.position = "absolute";
10225 outer.style.top = "0px";
10226 outer.style.left = "0px";
10227 outer.style.visibility = "hidden";
10228 outer.style.width = "200px";
10229 outer.style.height = "150px";
10230 outer.style.overflow = "hidden";
10231 outer.appendChild(inner);
10232 document.body.appendChild(outer);
10233 var w1 = inner.offsetWidth;
10234 outer.style.overflow = "scroll";
10235 var w2 = inner.offsetWidth;
10236
10237 if (w1 == w2) {
10238 w2 = outer.clientWidth;
10239 }
10240
10241 document.body.removeChild(outer);
10242 return w1 - w2;
10243} // @TODO: This doesn't work properly.
10244// It works only for single property objects,
10245// otherwise it combines all of the types in a union.
10246// export function topMost<K1 extends string, V1> (
10247// pile: Record<K1, undefined | V1>[],
10248// accessors: K1 | [K1]
10249// ): undefined | V1
10250// export function topMost<K1 extends string, K2 extends string, V1, V2> (
10251// pile: Record<K1, undefined | V1 | Record<K2, undefined | V2>>[],
10252// accessors: [K1, K2]
10253// ): undefined | V1 | V2
10254// export function topMost<K1 extends string, K2 extends string, K3 extends string, V1, V2, V3> (
10255// pile: Record<K1, undefined | V1 | Record<K2, undefined | V2 | Record<K3, undefined | V3>>>[],
10256// accessors: [K1, K2, K3]
10257// ): undefined | V1 | V2 | V3
10258
10259/**
10260 * Get the top most property value from a pile of objects.
10261 *
10262 * @param pile - Array of objects, no required format.
10263 * @param accessors - Array of property names (e.g. object['foo']['bar'] → ['foo', 'bar']).
10264 *
10265 * @returns Value of the property with given accessors path from the first pile item where it's not undefined.
10266 */
10267
10268
10269function topMost(pile, accessors) {
10270 var candidate;
10271
10272 if (!Array.isArray(accessors)) {
10273 accessors = [accessors];
10274 }
10275
10276 var _iteratorNormalCompletion = true;
10277 var _didIteratorError = false;
10278 var _iteratorError = undefined;
10279
10280 try {
10281 for (var _iterator = pile[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
10282 var member = _step.value;
10283
10284 if (member) {
10285 candidate = member[accessors[0]];
10286
10287 for (var i = 1; i < accessors.length; i++) {
10288 if (candidate) {
10289 candidate = candidate[accessors[i]];
10290 }
10291 }
10292
10293 if (typeof candidate !== "undefined") {
10294 break;
10295 }
10296 }
10297 }
10298 } catch (err) {
10299 _didIteratorError = true;
10300 _iteratorError = err;
10301 } finally {
10302 try {
10303 if (!_iteratorNormalCompletion && _iterator.return != null) {
10304 _iterator.return();
10305 }
10306 } finally {
10307 if (_didIteratorError) {
10308 throw _iteratorError;
10309 }
10310 }
10311 }
10312
10313 return candidate;
10314}
10315
10316var util =
10317/*#__PURE__*/
10318Object.freeze({
10319 isNumber: isNumber,
10320 recursiveDOMDelete: recursiveDOMDelete,
10321 isString: isString,
10322 isObject: isObject$1,
10323 isDate: isDate,
10324 isMoment: isMoment,
10325 fillIfDefined: fillIfDefined,
10326 extend: extend,
10327 selectiveExtend: selectiveExtend,
10328 selectiveDeepExtend: selectiveDeepExtend,
10329 selectiveNotDeepExtend: selectiveNotDeepExtend,
10330 deepExtend: deepExtend,
10331 equalArray: equalArray,
10332 convert: convert,
10333 getType: getType,
10334 copyAndExtendArray: copyAndExtendArray,
10335 copyArray: copyArray,
10336 getAbsoluteLeft: getAbsoluteLeft,
10337 getAbsoluteRight: getAbsoluteRight,
10338 getAbsoluteTop: getAbsoluteTop,
10339 addClassName: addClassName,
10340 removeClassName: removeClassName,
10341 forEach: forEach,
10342 toArray: toArray,
10343 updateProperty: updateProperty,
10344 throttle: throttle,
10345 addEventListener: addEventListener,
10346 removeEventListener: removeEventListener,
10347 preventDefault: preventDefault,
10348 getTarget: getTarget,
10349 hasParent: hasParent,
10350 option: option,
10351 hexToRGB: hexToRGB,
10352 overrideOpacity: overrideOpacity,
10353 RGBToHex: RGBToHex,
10354 parseColor: parseColor,
10355 RGBToHSV: RGBToHSV,
10356 addCssText: addCssText,
10357 removeCssText: removeCssText,
10358 HSVToRGB: HSVToRGB,
10359 HSVToHex: HSVToHex,
10360 hexToHSV: hexToHSV,
10361 isValidHex: isValidHex,
10362 isValidRGB: isValidRGB,
10363 isValidRGBA: isValidRGBA,
10364 selectiveBridgeObject: selectiveBridgeObject,
10365 bridgeObject: bridgeObject,
10366 insertSort: insertSort,
10367 mergeOptions: mergeOptions,
10368 binarySearchCustom: binarySearchCustom,
10369 binarySearchValue: binarySearchValue,
10370 easingFunctions: easingFunctions,
10371 getScrollBarWidth: getScrollBarWidth,
10372 topMost: topMost,
10373 randomUUID: uuid4
10374}); // New API (tree shakeable).
10375
10376var esm = /*#__PURE__*/Object.freeze({
10377 __proto__: null,
10378 'default': util,
10379 HSVToHex: HSVToHex,
10380 HSVToRGB: HSVToRGB,
10381 RGBToHSV: RGBToHSV,
10382 RGBToHex: RGBToHex,
10383 addClassName: addClassName,
10384 addCssText: addCssText,
10385 addEventListener: addEventListener,
10386 binarySearchCustom: binarySearchCustom,
10387 binarySearchValue: binarySearchValue,
10388 bridgeObject: bridgeObject,
10389 convert: convert,
10390 copyAndExtendArray: copyAndExtendArray,
10391 copyArray: copyArray,
10392 deepExtend: deepExtend,
10393 easingFunctions: easingFunctions,
10394 equalArray: equalArray,
10395 extend: extend,
10396 fillIfDefined: fillIfDefined,
10397 forEach: forEach,
10398 getAbsoluteLeft: getAbsoluteLeft,
10399 getAbsoluteRight: getAbsoluteRight,
10400 getAbsoluteTop: getAbsoluteTop,
10401 getScrollBarWidth: getScrollBarWidth,
10402 getTarget: getTarget,
10403 getType: getType,
10404 hasParent: hasParent,
10405 hexToHSV: hexToHSV,
10406 hexToRGB: hexToRGB,
10407 insertSort: insertSort,
10408 isDate: isDate,
10409 isMoment: isMoment,
10410 isNumber: isNumber,
10411 isObject: isObject$1,
10412 isString: isString,
10413 isValidHex: isValidHex,
10414 isValidRGB: isValidRGB,
10415 isValidRGBA: isValidRGBA,
10416 mergeOptions: mergeOptions,
10417 option: option,
10418 overrideOpacity: overrideOpacity,
10419 parseColor: parseColor,
10420 preventDefault: preventDefault,
10421 randomUUID: uuid4,
10422 recursiveDOMDelete: recursiveDOMDelete,
10423 removeClassName: removeClassName,
10424 removeCssText: removeCssText,
10425 removeEventListener: removeEventListener,
10426 selectiveBridgeObject: selectiveBridgeObject,
10427 selectiveDeepExtend: selectiveDeepExtend,
10428 selectiveExtend: selectiveExtend,
10429 selectiveNotDeepExtend: selectiveNotDeepExtend,
10430 throttle: throttle,
10431 toArray: toArray,
10432 topMost: topMost,
10433 updateProperty: updateProperty
10434});
10435
10436var bindContext = function (fn, that, length) {
10437 aFunction$1(fn);
10438 if (that === undefined) return fn;
10439
10440 switch (length) {
10441 case 0:
10442 return function () {
10443 return fn.call(that);
10444 };
10445
10446 case 1:
10447 return function (a) {
10448 return fn.call(that, a);
10449 };
10450
10451 case 2:
10452 return function (a, b) {
10453 return fn.call(that, a, b);
10454 };
10455
10456 case 3:
10457 return function (a, b, c) {
10458 return fn.call(that, a, b, c);
10459 };
10460 }
10461
10462 return function ()
10463 /* ...args */
10464 {
10465 return fn.apply(that, arguments);
10466 };
10467};
10468
10469// https://tc39.github.io/ecma262/#sec-isarray
10470
10471var isArray = Array.isArray || function isArray(arg) {
10472 return classofRaw(arg) == 'Array';
10473};
10474
10475var SPECIES$2 = wellKnownSymbol('species'); // `ArraySpeciesCreate` abstract operation
10476// https://tc39.github.io/ecma262/#sec-arrayspeciescreate
10477
10478var arraySpeciesCreate = function (originalArray, length) {
10479 var C;
10480
10481 if (isArray(originalArray)) {
10482 C = originalArray.constructor; // cross-realm fallback
10483
10484 if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;else if (isObject(C)) {
10485 C = C[SPECIES$2];
10486 if (C === null) C = undefined;
10487 }
10488 }
10489
10490 return new (C === undefined ? Array : C)(length === 0 ? 0 : length);
10491};
10492
10493var push = [].push; // `Array.prototype.{ forEach, map, filter, some, every, find, findIndex }` methods implementation
10494
10495var createMethod$1 = function (TYPE) {
10496 var IS_MAP = TYPE == 1;
10497 var IS_FILTER = TYPE == 2;
10498 var IS_SOME = TYPE == 3;
10499 var IS_EVERY = TYPE == 4;
10500 var IS_FIND_INDEX = TYPE == 6;
10501 var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
10502 return function ($this, callbackfn, that, specificCreate) {
10503 var O = toObject($this);
10504 var self = indexedObject(O);
10505 var boundFunction = bindContext(callbackfn, that, 3);
10506 var length = toLength(self.length);
10507 var index = 0;
10508 var create = specificCreate || arraySpeciesCreate;
10509 var target = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;
10510 var value, result;
10511
10512 for (; length > index; index++) if (NO_HOLES || index in self) {
10513 value = self[index];
10514 result = boundFunction(value, index, O);
10515
10516 if (TYPE) {
10517 if (IS_MAP) target[index] = result; // map
10518 else if (result) switch (TYPE) {
10519 case 3:
10520 return true;
10521 // some
10522
10523 case 5:
10524 return value;
10525 // find
10526
10527 case 6:
10528 return index;
10529 // findIndex
10530
10531 case 2:
10532 push.call(target, value);
10533 // filter
10534 } else if (IS_EVERY) return false; // every
10535 }
10536 }
10537
10538 return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target;
10539 };
10540};
10541
10542var arrayIteration = {
10543 // `Array.prototype.forEach` method
10544 // https://tc39.github.io/ecma262/#sec-array.prototype.foreach
10545 forEach: createMethod$1(0),
10546 // `Array.prototype.map` method
10547 // https://tc39.github.io/ecma262/#sec-array.prototype.map
10548 map: createMethod$1(1),
10549 // `Array.prototype.filter` method
10550 // https://tc39.github.io/ecma262/#sec-array.prototype.filter
10551 filter: createMethod$1(2),
10552 // `Array.prototype.some` method
10553 // https://tc39.github.io/ecma262/#sec-array.prototype.some
10554 some: createMethod$1(3),
10555 // `Array.prototype.every` method
10556 // https://tc39.github.io/ecma262/#sec-array.prototype.every
10557 every: createMethod$1(4),
10558 // `Array.prototype.find` method
10559 // https://tc39.github.io/ecma262/#sec-array.prototype.find
10560 find: createMethod$1(5),
10561 // `Array.prototype.findIndex` method
10562 // https://tc39.github.io/ecma262/#sec-array.prototype.findIndex
10563 findIndex: createMethod$1(6)
10564};
10565
10566var sloppyArrayMethod = function (METHOD_NAME, argument) {
10567 var method = [][METHOD_NAME];
10568 return !method || !fails(function () {
10569 // eslint-disable-next-line no-useless-call,no-throw-literal
10570 method.call(null, argument || function () {
10571 throw 1;
10572 }, 1);
10573 });
10574};
10575
10576var $forEach = arrayIteration.forEach; // `Array.prototype.forEach` method implementation
10577// https://tc39.github.io/ecma262/#sec-array.prototype.foreach
10578
10579var arrayForEach = sloppyArrayMethod('forEach') ? function forEach(callbackfn
10580/* , thisArg */
10581) {
10582 return $forEach(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
10583} : [].forEach;
10584
10585// https://tc39.github.io/ecma262/#sec-array.prototype.foreach
10586
10587
10588_export({
10589 target: 'Array',
10590 proto: true,
10591 forced: [].forEach != arrayForEach
10592}, {
10593 forEach: arrayForEach
10594});
10595
10596// https://tc39.github.io/ecma262/#sec-object.keys
10597
10598var objectKeys = Object.keys || function keys(O) {
10599 return objectKeysInternal(O, enumBugKeys);
10600};
10601
10602// https://tc39.github.io/ecma262/#sec-object.defineproperties
10603
10604var objectDefineProperties = descriptors ? Object.defineProperties : function defineProperties(O, Properties) {
10605 anObject(O);
10606 var keys = objectKeys(Properties);
10607 var length = keys.length;
10608 var index = 0;
10609 var key;
10610
10611 while (length > index) objectDefineProperty.f(O, key = keys[index++], Properties[key]);
10612
10613 return O;
10614};
10615
10616var html = getBuiltIn('document', 'documentElement');
10617
10618var IE_PROTO$3 = sharedKey('IE_PROTO');
10619var PROTOTYPE$3 = 'prototype';
10620
10621var Empty$1 = function () {
10622 /* empty */
10623}; // Create object with fake `null` prototype: use iframe Object with cleared prototype
10624
10625
10626var createDict$1 = function () {
10627 // Thrash, waste and sodomy: IE GC bug
10628 var iframe = documentCreateElement('iframe');
10629 var length = enumBugKeys.length;
10630 var lt = '<';
10631 var script = 'script';
10632 var gt = '>';
10633 var js = 'java' + script + ':';
10634 var iframeDocument;
10635 iframe.style.display = 'none';
10636 html.appendChild(iframe);
10637 iframe.src = String(js);
10638 iframeDocument = iframe.contentWindow.document;
10639 iframeDocument.open();
10640 iframeDocument.write(lt + script + gt + 'document.F=Object' + lt + '/' + script + gt);
10641 iframeDocument.close();
10642 createDict$1 = iframeDocument.F;
10643
10644 while (length--) delete createDict$1[PROTOTYPE$3][enumBugKeys[length]];
10645
10646 return createDict$1();
10647}; // `Object.create` method
10648// https://tc39.github.io/ecma262/#sec-object.create
10649
10650
10651var objectCreate = Object.create || function create(O, Properties) {
10652 var result;
10653
10654 if (O !== null) {
10655 Empty$1[PROTOTYPE$3] = anObject(O);
10656 result = new Empty$1();
10657 Empty$1[PROTOTYPE$3] = null; // add "__proto__" for Object.getPrototypeOf polyfill
10658
10659 result[IE_PROTO$3] = O;
10660 } else result = createDict$1();
10661
10662 return Properties === undefined ? result : objectDefineProperties(result, Properties);
10663};
10664
10665hiddenKeys[IE_PROTO$3] = true;
10666
10667var UNSCOPABLES$1 = wellKnownSymbol('unscopables');
10668var ArrayPrototype = Array.prototype; // Array.prototype[@@unscopables]
10669// https://tc39.github.io/ecma262/#sec-array.prototype-@@unscopables
10670
10671if (ArrayPrototype[UNSCOPABLES$1] == undefined) {
10672 createNonEnumerableProperty(ArrayPrototype, UNSCOPABLES$1, objectCreate(null));
10673} // add a key to Array.prototype[@@unscopables]
10674
10675
10676var addToUnscopables = function (key) {
10677 ArrayPrototype[UNSCOPABLES$1][key] = true;
10678};
10679
10680var $includes = arrayIncludes.includes; // `Array.prototype.includes` method
10681// https://tc39.github.io/ecma262/#sec-array.prototype.includes
10682
10683_export({
10684 target: 'Array',
10685 proto: true
10686}, {
10687 includes: function includes(el
10688 /* , fromIndex = 0 */
10689 ) {
10690 return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
10691 }
10692}); // https://tc39.github.io/ecma262/#sec-array.prototype-@@unscopables
10693
10694addToUnscopables('includes');
10695
10696var $indexOf = arrayIncludes.indexOf;
10697var nativeIndexOf = [].indexOf;
10698var NEGATIVE_ZERO = !!nativeIndexOf && 1 / [1].indexOf(1, -0) < 0;
10699var SLOPPY_METHOD = sloppyArrayMethod('indexOf'); // `Array.prototype.indexOf` method
10700// https://tc39.github.io/ecma262/#sec-array.prototype.indexof
10701
10702_export({
10703 target: 'Array',
10704 proto: true,
10705 forced: NEGATIVE_ZERO || SLOPPY_METHOD
10706}, {
10707 indexOf: function indexOf(searchElement
10708 /* , fromIndex = 0 */
10709 ) {
10710 return NEGATIVE_ZERO // convert -0 to +0
10711 ? nativeIndexOf.apply(this, arguments) || 0 : $indexOf(this, searchElement, arguments.length > 1 ? arguments[1] : undefined);
10712 }
10713});
10714
10715var createProperty = function (object, key, value) {
10716 var propertyKey = toPrimitive(key);
10717 if (propertyKey in object) objectDefineProperty.f(object, propertyKey, createPropertyDescriptor(0, value));else object[propertyKey] = value;
10718};
10719
10720var userAgent = getBuiltIn('navigator', 'userAgent') || '';
10721
10722var process = global_1.process;
10723var versions = process && process.versions;
10724var v8 = versions && versions.v8;
10725var match, version;
10726
10727if (v8) {
10728 match = v8.split('.');
10729 version = match[0] + match[1];
10730} else if (userAgent) {
10731 match = userAgent.match(/Chrome\/(\d+)/);
10732 if (match) version = match[1];
10733}
10734
10735var v8Version = version && +version;
10736
10737var SPECIES$3 = wellKnownSymbol('species');
10738
10739var arrayMethodHasSpeciesSupport = function (METHOD_NAME) {
10740 // We can't use this feature detection in V8 since it causes
10741 // deoptimization and serious performance degradation
10742 // https://github.com/zloirock/core-js/issues/677
10743 return v8Version >= 51 || !fails(function () {
10744 var array = [];
10745 var constructor = array.constructor = {};
10746
10747 constructor[SPECIES$3] = function () {
10748 return {
10749 foo: 1
10750 };
10751 };
10752
10753 return array[METHOD_NAME](Boolean).foo !== 1;
10754 });
10755};
10756
10757var max$2 = Math.max;
10758var min$3 = Math.min;
10759var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF;
10760var MAXIMUM_ALLOWED_LENGTH_EXCEEDED = 'Maximum allowed length exceeded'; // `Array.prototype.splice` method
10761// https://tc39.github.io/ecma262/#sec-array.prototype.splice
10762// with adding support of @@species
10763
10764_export({
10765 target: 'Array',
10766 proto: true,
10767 forced: !arrayMethodHasSpeciesSupport('splice')
10768}, {
10769 splice: function splice(start, deleteCount
10770 /* , ...items */
10771 ) {
10772 var O = toObject(this);
10773 var len = toLength(O.length);
10774 var actualStart = toAbsoluteIndex(start, len);
10775 var argumentsLength = arguments.length;
10776 var insertCount, actualDeleteCount, A, k, from, to;
10777
10778 if (argumentsLength === 0) {
10779 insertCount = actualDeleteCount = 0;
10780 } else if (argumentsLength === 1) {
10781 insertCount = 0;
10782 actualDeleteCount = len - actualStart;
10783 } else {
10784 insertCount = argumentsLength - 2;
10785 actualDeleteCount = min$3(max$2(toInteger(deleteCount), 0), len - actualStart);
10786 }
10787
10788 if (len + insertCount - actualDeleteCount > MAX_SAFE_INTEGER) {
10789 throw TypeError(MAXIMUM_ALLOWED_LENGTH_EXCEEDED);
10790 }
10791
10792 A = arraySpeciesCreate(O, actualDeleteCount);
10793
10794 for (k = 0; k < actualDeleteCount; k++) {
10795 from = actualStart + k;
10796 if (from in O) createProperty(A, k, O[from]);
10797 }
10798
10799 A.length = actualDeleteCount;
10800
10801 if (insertCount < actualDeleteCount) {
10802 for (k = actualStart; k < len - actualDeleteCount; k++) {
10803 from = k + actualDeleteCount;
10804 to = k + insertCount;
10805 if (from in O) O[to] = O[from];else delete O[to];
10806 }
10807
10808 for (k = len; k > len - actualDeleteCount + insertCount; k--) delete O[k - 1];
10809 } else if (insertCount > actualDeleteCount) {
10810 for (k = len - actualDeleteCount; k > actualStart; k--) {
10811 from = k + actualDeleteCount - 1;
10812 to = k + insertCount - 1;
10813 if (from in O) O[to] = O[from];else delete O[to];
10814 }
10815 }
10816
10817 for (k = 0; k < insertCount; k++) {
10818 O[k + actualStart] = arguments[k + 2];
10819 }
10820
10821 O.length = len - actualDeleteCount + insertCount;
10822 return A;
10823 }
10824});
10825
10826var defineProperty$4 = objectDefineProperty.f;
10827var FunctionPrototype = Function.prototype;
10828var FunctionPrototypeToString = FunctionPrototype.toString;
10829var nameRE = /^\s*function ([^ (]*)/;
10830var NAME$2 = 'name'; // Function instances `.name` property
10831// https://tc39.github.io/ecma262/#sec-function-instances-name
10832
10833if (descriptors && !(NAME$2 in FunctionPrototype)) {
10834 defineProperty$4(FunctionPrototype, NAME$2, {
10835 configurable: true,
10836 get: function () {
10837 try {
10838 return FunctionPrototypeToString.call(this).match(nameRE)[1];
10839 } catch (error) {
10840 return '';
10841 }
10842 }
10843 });
10844}
10845
10846var inheritIfRequired = function ($this, dummy, Wrapper) {
10847 var NewTarget, NewTargetPrototype;
10848 if ( // it can work only with native `setPrototypeOf`
10849 objectSetPrototypeOf && // we haven't completely correct pre-ES6 way for getting `new.target`, so use this
10850 typeof (NewTarget = dummy.constructor) == 'function' && NewTarget !== Wrapper && isObject(NewTargetPrototype = NewTarget.prototype) && NewTargetPrototype !== Wrapper.prototype) objectSetPrototypeOf($this, NewTargetPrototype);
10851 return $this;
10852};
10853
10854// a string of all valid unicode whitespaces
10855// eslint-disable-next-line max-len
10856var whitespaces = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF';
10857
10858var whitespace = '[' + whitespaces + ']';
10859var ltrim$1 = RegExp('^' + whitespace + whitespace + '*');
10860var rtrim$1 = RegExp(whitespace + whitespace + '*$'); // `String.prototype.{ trim, trimStart, trimEnd, trimLeft, trimRight }` methods implementation
10861
10862var createMethod$2 = function (TYPE) {
10863 return function ($this) {
10864 var string = String(requireObjectCoercible($this));
10865 if (TYPE & 1) string = string.replace(ltrim$1, '');
10866 if (TYPE & 2) string = string.replace(rtrim$1, '');
10867 return string;
10868 };
10869};
10870
10871var stringTrim = {
10872 // `String.prototype.{ trimLeft, trimStart }` methods
10873 // https://tc39.github.io/ecma262/#sec-string.prototype.trimstart
10874 start: createMethod$2(1),
10875 // `String.prototype.{ trimRight, trimEnd }` methods
10876 // https://tc39.github.io/ecma262/#sec-string.prototype.trimend
10877 end: createMethod$2(2),
10878 // `String.prototype.trim` method
10879 // https://tc39.github.io/ecma262/#sec-string.prototype.trim
10880 trim: createMethod$2(3)
10881};
10882
10883var getOwnPropertyNames$1 = objectGetOwnPropertyNames.f;
10884var getOwnPropertyDescriptor$2 = objectGetOwnPropertyDescriptor.f;
10885var defineProperty$5 = objectDefineProperty.f;
10886var trim$1 = stringTrim.trim;
10887var NUMBER$1 = 'Number';
10888var NativeNumber = global_1[NUMBER$1];
10889var NumberPrototype = NativeNumber.prototype; // Opera ~12 has broken Object#toString
10890
10891var BROKEN_CLASSOF = classofRaw(objectCreate(NumberPrototype)) == NUMBER$1; // `ToNumber` abstract operation
10892// https://tc39.github.io/ecma262/#sec-tonumber
10893
10894var toNumber$1 = function (argument) {
10895 var it = toPrimitive(argument, false);
10896 var first, third, radix, maxCode, digits, length, index, code;
10897
10898 if (typeof it == 'string' && it.length > 2) {
10899 it = trim$1(it);
10900 first = it.charCodeAt(0);
10901
10902 if (first === 43 || first === 45) {
10903 third = it.charCodeAt(2);
10904 if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix
10905 } else if (first === 48) {
10906 switch (it.charCodeAt(1)) {
10907 case 66:
10908 case 98:
10909 radix = 2;
10910 maxCode = 49;
10911 break;
10912 // fast equal of /^0b[01]+$/i
10913
10914 case 79:
10915 case 111:
10916 radix = 8;
10917 maxCode = 55;
10918 break;
10919 // fast equal of /^0o[0-7]+$/i
10920
10921 default:
10922 return +it;
10923 }
10924
10925 digits = it.slice(2);
10926 length = digits.length;
10927
10928 for (index = 0; index < length; index++) {
10929 code = digits.charCodeAt(index); // parseInt parses a string to a first unavailable symbol
10930 // but ToNumber should return NaN if a string contains unavailable symbols
10931
10932 if (code < 48 || code > maxCode) return NaN;
10933 }
10934
10935 return parseInt(digits, radix);
10936 }
10937 }
10938
10939 return +it;
10940}; // `Number` constructor
10941// https://tc39.github.io/ecma262/#sec-number-constructor
10942
10943
10944if (isForced_1(NUMBER$1, !NativeNumber(' 0o1') || !NativeNumber('0b1') || NativeNumber('+0x1'))) {
10945 var NumberWrapper = function Number(value) {
10946 var it = arguments.length < 1 ? 0 : value;
10947 var dummy = this;
10948 return dummy instanceof NumberWrapper // check on 1..constructor(foo) case
10949 && (BROKEN_CLASSOF ? fails(function () {
10950 NumberPrototype.valueOf.call(dummy);
10951 }) : classofRaw(dummy) != NUMBER$1) ? inheritIfRequired(new NativeNumber(toNumber$1(it)), dummy, NumberWrapper) : toNumber$1(it);
10952 };
10953
10954 for (var keys$3 = descriptors ? getOwnPropertyNames$1(NativeNumber) : ( // ES3:
10955 'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' + // ES2015 (in case, if modules with ES2015 Number statics required before):
10956 'EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,' + 'MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger').split(','), j$2 = 0, key$2; keys$3.length > j$2; j$2++) {
10957 if (has(NativeNumber, key$2 = keys$3[j$2]) && !has(NumberWrapper, key$2)) {
10958 defineProperty$5(NumberWrapper, key$2, getOwnPropertyDescriptor$2(NativeNumber, key$2));
10959 }
10960 }
10961
10962 NumberWrapper.prototype = NumberPrototype;
10963 NumberPrototype.constructor = NumberWrapper;
10964 redefine(global_1, NUMBER$1, NumberWrapper);
10965}
10966
10967// https://tc39.github.io/ecma262/#sec-get-regexp.prototype.flags
10968
10969
10970var regexpFlags = function () {
10971 var that = anObject(this);
10972 var result = '';
10973 if (that.global) result += 'g';
10974 if (that.ignoreCase) result += 'i';
10975 if (that.multiline) result += 'm';
10976 if (that.dotAll) result += 's';
10977 if (that.unicode) result += 'u';
10978 if (that.sticky) result += 'y';
10979 return result;
10980};
10981
10982var nativeExec$1 = RegExp.prototype.exec; // This always refers to the native implementation, because the
10983// String#replace polyfill uses ./fix-regexp-well-known-symbol-logic.js,
10984// which loads this file before patching the method.
10985
10986var nativeReplace$1 = String.prototype.replace;
10987var patchedExec$1 = nativeExec$1;
10988
10989var UPDATES_LAST_INDEX_WRONG$1 = function () {
10990 var re1 = /a/;
10991 var re2 = /b*/g;
10992 nativeExec$1.call(re1, 'a');
10993 nativeExec$1.call(re2, 'a');
10994 return re1.lastIndex !== 0 || re2.lastIndex !== 0;
10995}(); // nonparticipating capturing group, copied from es5-shim's String#split patch.
10996
10997
10998var NPCG_INCLUDED$1 = /()??/.exec('')[1] !== undefined;
10999var PATCH$1 = UPDATES_LAST_INDEX_WRONG$1 || NPCG_INCLUDED$1;
11000
11001if (PATCH$1) {
11002 patchedExec$1 = function exec(str) {
11003 var re = this;
11004 var lastIndex, reCopy, match, i;
11005
11006 if (NPCG_INCLUDED$1) {
11007 reCopy = new RegExp('^' + re.source + '$(?!\\s)', regexpFlags.call(re));
11008 }
11009
11010 if (UPDATES_LAST_INDEX_WRONG$1) lastIndex = re.lastIndex;
11011 match = nativeExec$1.call(re, str);
11012
11013 if (UPDATES_LAST_INDEX_WRONG$1 && match) {
11014 re.lastIndex = re.global ? match.index + match[0].length : lastIndex;
11015 }
11016
11017 if (NPCG_INCLUDED$1 && match && match.length > 1) {
11018 // Fix browsers whose `exec` methods don't consistently return `undefined`
11019 // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/
11020 nativeReplace$1.call(match[0], reCopy, function () {
11021 for (i = 1; i < arguments.length - 2; i++) {
11022 if (arguments[i] === undefined) match[i] = undefined;
11023 }
11024 });
11025 }
11026
11027 return match;
11028 };
11029}
11030
11031var regexpExec = patchedExec$1;
11032
11033_export({
11034 target: 'RegExp',
11035 proto: true,
11036 forced: /./.exec !== regexpExec
11037}, {
11038 exec: regexpExec
11039});
11040
11041var MATCH$1 = wellKnownSymbol('match'); // `IsRegExp` abstract operation
11042// https://tc39.github.io/ecma262/#sec-isregexp
11043
11044var isRegexp = function (it) {
11045 var isRegExp;
11046 return isObject(it) && ((isRegExp = it[MATCH$1]) !== undefined ? !!isRegExp : classofRaw(it) == 'RegExp');
11047};
11048
11049var notARegexp = function (it) {
11050 if (isRegexp(it)) {
11051 throw TypeError("The method doesn't accept regular expressions");
11052 }
11053
11054 return it;
11055};
11056
11057var MATCH$2 = wellKnownSymbol('match');
11058
11059var correctIsRegexpLogic = function (METHOD_NAME) {
11060 var regexp = /./;
11061
11062 try {
11063 '/./'[METHOD_NAME](regexp);
11064 } catch (e) {
11065 try {
11066 regexp[MATCH$2] = false;
11067 return '/./'[METHOD_NAME](regexp);
11068 } catch (f) {
11069 /* empty */
11070 }
11071 }
11072
11073 return false;
11074};
11075
11076// https://tc39.github.io/ecma262/#sec-string.prototype.includes
11077
11078
11079_export({
11080 target: 'String',
11081 proto: true,
11082 forced: !correctIsRegexpLogic('includes')
11083}, {
11084 includes: function includes(searchString
11085 /* , position = 0 */
11086 ) {
11087 return !!~String(requireObjectCoercible(this)).indexOf(notARegexp(searchString), arguments.length > 1 ? arguments[1] : undefined);
11088 }
11089});
11090
11091var SPECIES$4 = wellKnownSymbol('species');
11092var REPLACE_SUPPORTS_NAMED_GROUPS$1 = !fails(function () {
11093 // #replace needs built-in support for named groups.
11094 // #match works fine because it just return the exec results, even if it has
11095 // a "grops" property.
11096 var re = /./;
11097
11098 re.exec = function () {
11099 var result = [];
11100 result.groups = {
11101 a: '7'
11102 };
11103 return result;
11104 };
11105
11106 return ''.replace(re, '$<a>') !== '7';
11107}); // Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec
11108// Weex JS has frozen built-in prototypes, so use try / catch wrapper
11109
11110var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC$1 = !fails(function () {
11111 var re = /(?:)/;
11112 var originalExec = re.exec;
11113
11114 re.exec = function () {
11115 return originalExec.apply(this, arguments);
11116 };
11117
11118 var result = 'ab'.split(re);
11119 return result.length !== 2 || result[0] !== 'a' || result[1] !== 'b';
11120});
11121
11122var fixRegexpWellKnownSymbolLogic = function (KEY, length, exec, sham) {
11123 var SYMBOL = wellKnownSymbol(KEY);
11124 var DELEGATES_TO_SYMBOL = !fails(function () {
11125 // String methods call symbol-named RegEp methods
11126 var O = {};
11127
11128 O[SYMBOL] = function () {
11129 return 7;
11130 };
11131
11132 return ''[KEY](O) != 7;
11133 });
11134 var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails(function () {
11135 // Symbol-named RegExp methods call .exec
11136 var execCalled = false;
11137 var re = /a/;
11138
11139 if (KEY === 'split') {
11140 // We can't use real regex here since it causes deoptimization
11141 // and serious performance degradation in V8
11142 // https://github.com/zloirock/core-js/issues/306
11143 re = {}; // RegExp[@@split] doesn't call the regex's exec method, but first creates
11144 // a new one. We need to return the patched regex when creating the new one.
11145
11146 re.constructor = {};
11147
11148 re.constructor[SPECIES$4] = function () {
11149 return re;
11150 };
11151
11152 re.flags = '';
11153 re[SYMBOL] = /./[SYMBOL];
11154 }
11155
11156 re.exec = function () {
11157 execCalled = true;
11158 return null;
11159 };
11160
11161 re[SYMBOL]('');
11162 return !execCalled;
11163 });
11164
11165 if (!DELEGATES_TO_SYMBOL || !DELEGATES_TO_EXEC || KEY === 'replace' && !REPLACE_SUPPORTS_NAMED_GROUPS$1 || KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC$1) {
11166 var nativeRegExpMethod = /./[SYMBOL];
11167 var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) {
11168 if (regexp.exec === regexpExec) {
11169 if (DELEGATES_TO_SYMBOL && !forceStringMethod) {
11170 // The native String method already delegates to @@method (this
11171 // polyfilled function), leasing to infinite recursion.
11172 // We avoid it by directly calling the native @@method method.
11173 return {
11174 done: true,
11175 value: nativeRegExpMethod.call(regexp, str, arg2)
11176 };
11177 }
11178
11179 return {
11180 done: true,
11181 value: nativeMethod.call(str, regexp, arg2)
11182 };
11183 }
11184
11185 return {
11186 done: false
11187 };
11188 });
11189 var stringMethod = methods[0];
11190 var regexMethod = methods[1];
11191 redefine(String.prototype, KEY, stringMethod);
11192 redefine(RegExp.prototype, SYMBOL, length == 2 // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)
11193 // 21.2.5.11 RegExp.prototype[@@split](string, limit)
11194 ? function (string, arg) {
11195 return regexMethod.call(string, this, arg);
11196 } // 21.2.5.6 RegExp.prototype[@@match](string)
11197 // 21.2.5.9 RegExp.prototype[@@search](string)
11198 : function (string) {
11199 return regexMethod.call(string, this);
11200 });
11201 if (sham) createNonEnumerableProperty(RegExp.prototype[SYMBOL], 'sham', true);
11202 }
11203};
11204
11205var createMethod$3 = function (CONVERT_TO_STRING) {
11206 return function ($this, pos) {
11207 var S = String(requireObjectCoercible($this));
11208 var position = toInteger(pos);
11209 var size = S.length;
11210 var first, second;
11211 if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
11212 first = S.charCodeAt(position);
11213 return first < 0xD800 || first > 0xDBFF || position + 1 === size || (second = S.charCodeAt(position + 1)) < 0xDC00 || second > 0xDFFF ? CONVERT_TO_STRING ? S.charAt(position) : first : CONVERT_TO_STRING ? S.slice(position, position + 2) : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
11214 };
11215};
11216
11217var stringMultibyte = {
11218 // `String.prototype.codePointAt` method
11219 // https://tc39.github.io/ecma262/#sec-string.prototype.codepointat
11220 codeAt: createMethod$3(false),
11221 // `String.prototype.at` method
11222 // https://github.com/mathiasbynens/String.prototype.at
11223 charAt: createMethod$3(true)
11224};
11225
11226var charAt = stringMultibyte.charAt; // `AdvanceStringIndex` abstract operation
11227// https://tc39.github.io/ecma262/#sec-advancestringindex
11228
11229var advanceStringIndex = function (S, index, unicode) {
11230 return index + (unicode ? charAt(S, index).length : 1);
11231};
11232
11233// https://tc39.github.io/ecma262/#sec-regexpexec
11234
11235var regexpExecAbstract = function (R, S) {
11236 var exec = R.exec;
11237
11238 if (typeof exec === 'function') {
11239 var result = exec.call(R, S);
11240
11241 if (typeof result !== 'object') {
11242 throw TypeError('RegExp exec method returned something other than an Object or null');
11243 }
11244
11245 return result;
11246 }
11247
11248 if (classofRaw(R) !== 'RegExp') {
11249 throw TypeError('RegExp#exec called on incompatible receiver');
11250 }
11251
11252 return regexpExec.call(R, S);
11253};
11254
11255var arrayPush = [].push;
11256var min$4 = Math.min;
11257var MAX_UINT32$1 = 0xFFFFFFFF; // babel-minify transpiles RegExp('x', 'y') -> /x/y and it causes SyntaxError
11258
11259var SUPPORTS_Y$1 = !fails(function () {
11260 return !RegExp(MAX_UINT32$1, 'y');
11261}); // @@split logic
11262
11263fixRegexpWellKnownSymbolLogic('split', 2, function (SPLIT, nativeSplit, maybeCallNative) {
11264 var internalSplit;
11265
11266 if ('abbc'.split(/(b)*/)[1] == 'c' || 'test'.split(/(?:)/, -1).length != 4 || 'ab'.split(/(?:ab)*/).length != 2 || '.'.split(/(.?)(.?)/).length != 4 || '.'.split(/()()/).length > 1 || ''.split(/.?/).length) {
11267 // based on es5-shim implementation, need to rework it
11268 internalSplit = function (separator, limit) {
11269 var string = String(requireObjectCoercible(this));
11270 var lim = limit === undefined ? MAX_UINT32$1 : limit >>> 0;
11271 if (lim === 0) return [];
11272 if (separator === undefined) return [string]; // If `separator` is not a regex, use native split
11273
11274 if (!isRegexp(separator)) {
11275 return nativeSplit.call(string, separator, lim);
11276 }
11277
11278 var output = [];
11279 var flags = (separator.ignoreCase ? 'i' : '') + (separator.multiline ? 'm' : '') + (separator.unicode ? 'u' : '') + (separator.sticky ? 'y' : '');
11280 var lastLastIndex = 0; // Make `global` and avoid `lastIndex` issues by working with a copy
11281
11282 var separatorCopy = new RegExp(separator.source, flags + 'g');
11283 var match, lastIndex, lastLength;
11284
11285 while (match = regexpExec.call(separatorCopy, string)) {
11286 lastIndex = separatorCopy.lastIndex;
11287
11288 if (lastIndex > lastLastIndex) {
11289 output.push(string.slice(lastLastIndex, match.index));
11290 if (match.length > 1 && match.index < string.length) arrayPush.apply(output, match.slice(1));
11291 lastLength = match[0].length;
11292 lastLastIndex = lastIndex;
11293 if (output.length >= lim) break;
11294 }
11295
11296 if (separatorCopy.lastIndex === match.index) separatorCopy.lastIndex++; // Avoid an infinite loop
11297 }
11298
11299 if (lastLastIndex === string.length) {
11300 if (lastLength || !separatorCopy.test('')) output.push('');
11301 } else output.push(string.slice(lastLastIndex));
11302
11303 return output.length > lim ? output.slice(0, lim) : output;
11304 }; // Chakra, V8
11305
11306 } else if ('0'.split(undefined, 0).length) {
11307 internalSplit = function (separator, limit) {
11308 return separator === undefined && limit === 0 ? [] : nativeSplit.call(this, separator, limit);
11309 };
11310 } else internalSplit = nativeSplit;
11311
11312 return [// `String.prototype.split` method
11313 // https://tc39.github.io/ecma262/#sec-string.prototype.split
11314 function split(separator, limit) {
11315 var O = requireObjectCoercible(this);
11316 var splitter = separator == undefined ? undefined : separator[SPLIT];
11317 return splitter !== undefined ? splitter.call(separator, O, limit) : internalSplit.call(String(O), separator, limit);
11318 }, // `RegExp.prototype[@@split]` method
11319 // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@split
11320 //
11321 // NOTE: This cannot be properly polyfilled in engines that don't support
11322 // the 'y' flag.
11323 function (regexp, limit) {
11324 var res = maybeCallNative(internalSplit, regexp, this, limit, internalSplit !== nativeSplit);
11325 if (res.done) return res.value;
11326 var rx = anObject(regexp);
11327 var S = String(this);
11328 var C = speciesConstructor(rx, RegExp);
11329 var unicodeMatching = rx.unicode;
11330 var flags = (rx.ignoreCase ? 'i' : '') + (rx.multiline ? 'm' : '') + (rx.unicode ? 'u' : '') + (SUPPORTS_Y$1 ? 'y' : 'g'); // ^(? + rx + ) is needed, in combination with some S slicing, to
11331 // simulate the 'y' flag.
11332
11333 var splitter = new C(SUPPORTS_Y$1 ? rx : '^(?:' + rx.source + ')', flags);
11334 var lim = limit === undefined ? MAX_UINT32$1 : limit >>> 0;
11335 if (lim === 0) return [];
11336 if (S.length === 0) return regexpExecAbstract(splitter, S) === null ? [S] : [];
11337 var p = 0;
11338 var q = 0;
11339 var A = [];
11340
11341 while (q < S.length) {
11342 splitter.lastIndex = SUPPORTS_Y$1 ? q : 0;
11343 var z = regexpExecAbstract(splitter, SUPPORTS_Y$1 ? S : S.slice(q));
11344 var e;
11345
11346 if (z === null || (e = min$4(toLength(splitter.lastIndex + (SUPPORTS_Y$1 ? 0 : q)), S.length)) === p) {
11347 q = advanceStringIndex(S, q, unicodeMatching);
11348 } else {
11349 A.push(S.slice(p, q));
11350 if (A.length === lim) return A;
11351
11352 for (var i = 1; i <= z.length - 1; i++) {
11353 A.push(z[i]);
11354 if (A.length === lim) return A;
11355 }
11356
11357 q = p = e;
11358 }
11359 }
11360
11361 A.push(S.slice(p));
11362 return A;
11363 }];
11364}, !SUPPORTS_Y$1);
11365
11366// iterable DOM collections
11367// flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods
11368var domIterables = {
11369 CSSRuleList: 0,
11370 CSSStyleDeclaration: 0,
11371 CSSValueList: 0,
11372 ClientRectList: 0,
11373 DOMRectList: 0,
11374 DOMStringList: 0,
11375 DOMTokenList: 1,
11376 DataTransferItemList: 0,
11377 FileList: 0,
11378 HTMLAllCollection: 0,
11379 HTMLCollection: 0,
11380 HTMLFormElement: 0,
11381 HTMLSelectElement: 0,
11382 MediaList: 0,
11383 MimeTypeArray: 0,
11384 NamedNodeMap: 0,
11385 NodeList: 1,
11386 PaintRequestList: 0,
11387 Plugin: 0,
11388 PluginArray: 0,
11389 SVGLengthList: 0,
11390 SVGNumberList: 0,
11391 SVGPathSegList: 0,
11392 SVGPointList: 0,
11393 SVGStringList: 0,
11394 SVGTransformList: 0,
11395 SourceBufferList: 0,
11396 StyleSheetList: 0,
11397 TextTrackCueList: 0,
11398 TextTrackList: 0,
11399 TouchList: 0
11400};
11401
11402for (var COLLECTION_NAME in domIterables) {
11403 var Collection$1 = global_1[COLLECTION_NAME];
11404 var CollectionPrototype = Collection$1 && Collection$1.prototype; // some Chrome versions have non-configurable methods on DOMTokenList
11405
11406 if (CollectionPrototype && CollectionPrototype.forEach !== arrayForEach) try {
11407 createNonEnumerableProperty(CollectionPrototype, 'forEach', arrayForEach);
11408 } catch (error) {
11409 CollectionPrototype.forEach = arrayForEach;
11410 }
11411}
11412
11413/**
11414 * Parse a text source containing data in DOT language into a JSON object.
11415 * The object contains two lists: one with nodes and one with edges.
11416 *
11417 * DOT language reference: http://www.graphviz.org/doc/info/lang.html
11418 *
11419 * DOT language attributes: http://graphviz.org/content/attrs
11420 *
11421 * @param {string} data Text containing a graph in DOT-notation
11422 * @return {Object} graph An object containing two parameters:
11423 * {Object[]} nodes
11424 * {Object[]} edges
11425 *
11426 * -------------------------------------------
11427 * TODO
11428 * ====
11429 *
11430 * For label handling, this is an incomplete implementation. From docs (quote #3015):
11431 *
11432 * > the escape sequences "\n", "\l" and "\r" divide the label into lines, centered,
11433 * > left-justified, and right-justified, respectively.
11434 *
11435 * Source: http://www.graphviz.org/content/attrs#kescString
11436 *
11437 * > As another aid for readability, dot allows double-quoted strings to span multiple physical
11438 * > lines using the standard C convention of a backslash immediately preceding a newline
11439 * > character
11440 * > In addition, double-quoted strings can be concatenated using a '+' operator.
11441 * > As HTML strings can contain newline characters, which are used solely for formatting,
11442 * > the language does not allow escaped newlines or concatenation operators to be used
11443 * > within them.
11444 *
11445 * - Currently, only '\\n' is handled
11446 * - Note that text explicitly says 'labels'; the dot parser currently handles escape
11447 * sequences in **all** strings.
11448 */
11449function parseDOT(data) {
11450 dot = data;
11451 return parseGraph();
11452} // mapping of attributes from DOT (the keys) to vis.js (the values)
11453
11454
11455var NODE_ATTR_MAPPING = {
11456 'fontsize': 'font.size',
11457 'fontcolor': 'font.color',
11458 'labelfontcolor': 'font.color',
11459 'fontname': 'font.face',
11460 'color': ['color.border', 'color.background'],
11461 'fillcolor': 'color.background',
11462 'tooltip': 'title',
11463 'labeltooltip': 'title'
11464};
11465var EDGE_ATTR_MAPPING = Object.create(NODE_ATTR_MAPPING);
11466EDGE_ATTR_MAPPING.color = 'color.color';
11467EDGE_ATTR_MAPPING.style = 'dashes'; // token types enumeration
11468
11469var TOKENTYPE = {
11470 NULL: 0,
11471 DELIMITER: 1,
11472 IDENTIFIER: 2,
11473 UNKNOWN: 3
11474}; // map with all delimiters
11475
11476var DELIMITERS = {
11477 '{': true,
11478 '}': true,
11479 '[': true,
11480 ']': true,
11481 ';': true,
11482 '=': true,
11483 ',': true,
11484 '->': true,
11485 '--': true
11486};
11487var dot = ''; // current dot file
11488
11489var index = 0; // current index in dot file
11490
11491var c = ''; // current token character in expr
11492
11493var token = ''; // current token
11494
11495var tokenType = TOKENTYPE.NULL; // type of the token
11496
11497/**
11498 * Get the first character from the dot file.
11499 * The character is stored into the char c. If the end of the dot file is
11500 * reached, the function puts an empty string in c.
11501 */
11502
11503function first() {
11504 index = 0;
11505 c = dot.charAt(0);
11506}
11507/**
11508 * Get the next character from the dot file.
11509 * The character is stored into the char c. If the end of the dot file is
11510 * reached, the function puts an empty string in c.
11511 */
11512
11513
11514function next() {
11515 index++;
11516 c = dot.charAt(index);
11517}
11518/**
11519 * Preview the next character from the dot file.
11520 * @return {string} cNext
11521 */
11522
11523
11524function nextPreview() {
11525 return dot.charAt(index + 1);
11526}
11527
11528var regexAlphaNumeric = /[a-zA-Z_0-9.:#]/;
11529/**
11530 * Test whether given character is alphabetic or numeric
11531 * @param {string} c
11532 * @return {Boolean} isAlphaNumeric
11533 */
11534
11535function isAlphaNumeric(c) {
11536 return regexAlphaNumeric.test(c);
11537}
11538/**
11539 * Merge all options of object b into object b
11540 * @param {Object} a
11541 * @param {Object} b
11542 * @return {Object} a
11543 */
11544
11545
11546function merge(a, b) {
11547 if (!a) {
11548 a = {};
11549 }
11550
11551 if (b) {
11552 for (var name in b) {
11553 if (b.hasOwnProperty(name)) {
11554 a[name] = b[name];
11555 }
11556 }
11557 }
11558
11559 return a;
11560}
11561/**
11562 * Set a value in an object, where the provided parameter name can be a
11563 * path with nested parameters. For example:
11564 *
11565 * var obj = {a: 2};
11566 * setValue(obj, 'b.c', 3); // obj = {a: 2, b: {c: 3}}
11567 *
11568 * @param {Object} obj
11569 * @param {string} path A parameter name or dot-separated parameter path,
11570 * like "color.highlight.border".
11571 * @param {*} value
11572 */
11573
11574
11575function setValue(obj, path, value) {
11576 var keys = path.split('.');
11577 var o = obj;
11578
11579 while (keys.length) {
11580 var key = keys.shift();
11581
11582 if (keys.length) {
11583 // this isn't the end point
11584 if (!o[key]) {
11585 o[key] = {};
11586 }
11587
11588 o = o[key];
11589 } else {
11590 // this is the end point
11591 o[key] = value;
11592 }
11593 }
11594}
11595/**
11596 * Add a node to a graph object. If there is already a node with
11597 * the same id, their attributes will be merged.
11598 * @param {Object} graph
11599 * @param {Object} node
11600 */
11601
11602
11603function addNode(graph, node) {
11604 var i, len;
11605 var current = null; // find root graph (in case of subgraph)
11606
11607 var graphs = [graph]; // list with all graphs from current graph to root graph
11608
11609 var root = graph;
11610
11611 while (root.parent) {
11612 graphs.push(root.parent);
11613 root = root.parent;
11614 } // find existing node (at root level) by its id
11615
11616
11617 if (root.nodes) {
11618 for (i = 0, len = root.nodes.length; i < len; i++) {
11619 if (node.id === root.nodes[i].id) {
11620 current = root.nodes[i];
11621 break;
11622 }
11623 }
11624 }
11625
11626 if (!current) {
11627 // this is a new node
11628 current = {
11629 id: node.id
11630 };
11631
11632 if (graph.node) {
11633 // clone default attributes
11634 current.attr = merge(current.attr, graph.node);
11635 }
11636 } // add node to this (sub)graph and all its parent graphs
11637
11638
11639 for (i = graphs.length - 1; i >= 0; i--) {
11640 var g = graphs[i];
11641
11642 if (!g.nodes) {
11643 g.nodes = [];
11644 }
11645
11646 if (g.nodes.indexOf(current) === -1) {
11647 g.nodes.push(current);
11648 }
11649 } // merge attributes
11650
11651
11652 if (node.attr) {
11653 current.attr = merge(current.attr, node.attr);
11654 }
11655}
11656/**
11657 * Add an edge to a graph object
11658 * @param {Object} graph
11659 * @param {Object} edge
11660 */
11661
11662
11663function addEdge(graph, edge) {
11664 if (!graph.edges) {
11665 graph.edges = [];
11666 }
11667
11668 graph.edges.push(edge);
11669
11670 if (graph.edge) {
11671 var attr = merge({}, graph.edge); // clone default attributes
11672
11673 edge.attr = merge(attr, edge.attr); // merge attributes
11674 }
11675}
11676/**
11677 * Create an edge to a graph object
11678 * @param {Object} graph
11679 * @param {string | number | Object} from
11680 * @param {string | number | Object} to
11681 * @param {string} type
11682 * @param {Object | null} attr
11683 * @return {Object} edge
11684 */
11685
11686
11687function createEdge(graph, from, to, type, attr) {
11688 var edge = {
11689 from: from,
11690 to: to,
11691 type: type
11692 };
11693
11694 if (graph.edge) {
11695 edge.attr = merge({}, graph.edge); // clone default attributes
11696 }
11697
11698 edge.attr = merge(edge.attr || {}, attr); // merge attributes
11699 // Move arrows attribute from attr to edge temporally created in
11700 // parseAttributeList().
11701
11702 if (attr != null) {
11703 if (attr.hasOwnProperty('arrows') && attr['arrows'] != null) {
11704 edge['arrows'] = {
11705 to: {
11706 enabled: true,
11707 type: attr.arrows.type
11708 }
11709 };
11710 attr['arrows'] = null;
11711 }
11712 }
11713
11714 return edge;
11715}
11716/**
11717 * Get next token in the current dot file.
11718 * The token and token type are available as token and tokenType
11719 */
11720
11721
11722function getToken() {
11723 tokenType = TOKENTYPE.NULL;
11724 token = ''; // skip over whitespaces
11725
11726 while (c === ' ' || c === '\t' || c === '\n' || c === '\r') {
11727 // space, tab, enter
11728 next();
11729 }
11730
11731 do {
11732 var isComment = false; // skip comment
11733
11734 if (c === '#') {
11735 // find the previous non-space character
11736 var i = index - 1;
11737
11738 while (dot.charAt(i) === ' ' || dot.charAt(i) === '\t') {
11739 i--;
11740 }
11741
11742 if (dot.charAt(i) === '\n' || dot.charAt(i) === '') {
11743 // the # is at the start of a line, this is indeed a line comment
11744 while (c != '' && c != '\n') {
11745 next();
11746 }
11747
11748 isComment = true;
11749 }
11750 }
11751
11752 if (c === '/' && nextPreview() === '/') {
11753 // skip line comment
11754 while (c != '' && c != '\n') {
11755 next();
11756 }
11757
11758 isComment = true;
11759 }
11760
11761 if (c === '/' && nextPreview() === '*') {
11762 // skip block comment
11763 while (c != '') {
11764 if (c === '*' && nextPreview() === '/') {
11765 // end of block comment found. skip these last two characters
11766 next();
11767 next();
11768 break;
11769 } else {
11770 next();
11771 }
11772 }
11773
11774 isComment = true;
11775 } // skip over whitespaces
11776
11777
11778 while (c === ' ' || c === '\t' || c === '\n' || c === '\r') {
11779 // space, tab, enter
11780 next();
11781 }
11782 } while (isComment); // check for end of dot file
11783
11784
11785 if (c === '') {
11786 // token is still empty
11787 tokenType = TOKENTYPE.DELIMITER;
11788 return;
11789 } // check for delimiters consisting of 2 characters
11790
11791
11792 var c2 = c + nextPreview();
11793
11794 if (DELIMITERS[c2]) {
11795 tokenType = TOKENTYPE.DELIMITER;
11796 token = c2;
11797 next();
11798 next();
11799 return;
11800 } // check for delimiters consisting of 1 character
11801
11802
11803 if (DELIMITERS[c]) {
11804 tokenType = TOKENTYPE.DELIMITER;
11805 token = c;
11806 next();
11807 return;
11808 } // check for an identifier (number or string)
11809 // TODO: more precise parsing of numbers/strings (and the port separator ':')
11810
11811
11812 if (isAlphaNumeric(c) || c === '-') {
11813 token += c;
11814 next();
11815
11816 while (isAlphaNumeric(c)) {
11817 token += c;
11818 next();
11819 }
11820
11821 if (token === 'false') {
11822 token = false; // convert to boolean
11823 } else if (token === 'true') {
11824 token = true; // convert to boolean
11825 } else if (!isNaN(Number(token))) {
11826 token = Number(token); // convert to number
11827 }
11828
11829 tokenType = TOKENTYPE.IDENTIFIER;
11830 return;
11831 } // check for a string enclosed by double quotes
11832
11833
11834 if (c === '"') {
11835 next();
11836
11837 while (c != '' && (c != '"' || c === '"' && nextPreview() === '"')) {
11838 if (c === '"') {
11839 // skip the escape character
11840 token += c;
11841 next();
11842 } else if (c === '\\' && nextPreview() === 'n') {
11843 // Honor a newline escape sequence
11844 token += '\n';
11845 next();
11846 } else {
11847 token += c;
11848 }
11849
11850 next();
11851 }
11852
11853 if (c != '"') {
11854 throw newSyntaxError('End of string " expected');
11855 }
11856
11857 next();
11858 tokenType = TOKENTYPE.IDENTIFIER;
11859 return;
11860 } // something unknown is found, wrong characters, a syntax error
11861
11862
11863 tokenType = TOKENTYPE.UNKNOWN;
11864
11865 while (c != '') {
11866 token += c;
11867 next();
11868 }
11869
11870 throw new SyntaxError('Syntax error in part "' + chop(token, 30) + '"');
11871}
11872/**
11873 * Parse a graph.
11874 * @returns {Object} graph
11875 */
11876
11877
11878function parseGraph() {
11879 var graph = {};
11880 first();
11881 getToken(); // optional strict keyword
11882
11883 if (token === 'strict') {
11884 graph.strict = true;
11885 getToken();
11886 } // graph or digraph keyword
11887
11888
11889 if (token === 'graph' || token === 'digraph') {
11890 graph.type = token;
11891 getToken();
11892 } // optional graph id
11893
11894
11895 if (tokenType === TOKENTYPE.IDENTIFIER) {
11896 graph.id = token;
11897 getToken();
11898 } // open angle bracket
11899
11900
11901 if (token != '{') {
11902 throw newSyntaxError('Angle bracket { expected');
11903 }
11904
11905 getToken(); // statements
11906
11907 parseStatements(graph); // close angle bracket
11908
11909 if (token != '}') {
11910 throw newSyntaxError('Angle bracket } expected');
11911 }
11912
11913 getToken(); // end of file
11914
11915 if (token !== '') {
11916 throw newSyntaxError('End of file expected');
11917 }
11918
11919 getToken(); // remove temporary default options
11920
11921 delete graph.node;
11922 delete graph.edge;
11923 delete graph.graph;
11924 return graph;
11925}
11926/**
11927 * Parse a list with statements.
11928 * @param {Object} graph
11929 */
11930
11931
11932function parseStatements(graph) {
11933 while (token !== '' && token != '}') {
11934 parseStatement(graph);
11935
11936 if (token === ';') {
11937 getToken();
11938 }
11939 }
11940}
11941/**
11942 * Parse a single statement. Can be a an attribute statement, node
11943 * statement, a series of node statements and edge statements, or a
11944 * parameter.
11945 * @param {Object} graph
11946 */
11947
11948
11949function parseStatement(graph) {
11950 // parse subgraph
11951 var subgraph = parseSubgraph(graph);
11952
11953 if (subgraph) {
11954 // edge statements
11955 parseEdge(graph, subgraph);
11956 return;
11957 } // parse an attribute statement
11958
11959
11960 var attr = parseAttributeStatement(graph);
11961
11962 if (attr) {
11963 return;
11964 } // parse node
11965
11966
11967 if (tokenType != TOKENTYPE.IDENTIFIER) {
11968 throw newSyntaxError('Identifier expected');
11969 }
11970
11971 var id = token; // id can be a string or a number
11972
11973 getToken();
11974
11975 if (token === '=') {
11976 // id statement
11977 getToken();
11978
11979 if (tokenType != TOKENTYPE.IDENTIFIER) {
11980 throw newSyntaxError('Identifier expected');
11981 }
11982
11983 graph[id] = token;
11984 getToken(); // TODO: implement comma separated list with "a_list: ID=ID [','] [a_list] "
11985 } else {
11986 parseNodeStatement(graph, id);
11987 }
11988}
11989/**
11990 * Parse a subgraph
11991 * @param {Object} graph parent graph object
11992 * @return {Object | null} subgraph
11993 */
11994
11995
11996function parseSubgraph(graph) {
11997 var subgraph = null; // optional subgraph keyword
11998
11999 if (token === 'subgraph') {
12000 subgraph = {};
12001 subgraph.type = 'subgraph';
12002 getToken(); // optional graph id
12003
12004 if (tokenType === TOKENTYPE.IDENTIFIER) {
12005 subgraph.id = token;
12006 getToken();
12007 }
12008 } // open angle bracket
12009
12010
12011 if (token === '{') {
12012 getToken();
12013
12014 if (!subgraph) {
12015 subgraph = {};
12016 }
12017
12018 subgraph.parent = graph;
12019 subgraph.node = graph.node;
12020 subgraph.edge = graph.edge;
12021 subgraph.graph = graph.graph; // statements
12022
12023 parseStatements(subgraph); // close angle bracket
12024
12025 if (token != '}') {
12026 throw newSyntaxError('Angle bracket } expected');
12027 }
12028
12029 getToken(); // remove temporary default options
12030
12031 delete subgraph.node;
12032 delete subgraph.edge;
12033 delete subgraph.graph;
12034 delete subgraph.parent; // register at the parent graph
12035
12036 if (!graph.subgraphs) {
12037 graph.subgraphs = [];
12038 }
12039
12040 graph.subgraphs.push(subgraph);
12041 }
12042
12043 return subgraph;
12044}
12045/**
12046 * parse an attribute statement like "node [shape=circle fontSize=16]".
12047 * Available keywords are 'node', 'edge', 'graph'.
12048 * The previous list with default attributes will be replaced
12049 * @param {Object} graph
12050 * @returns {String | null} keyword Returns the name of the parsed attribute
12051 * (node, edge, graph), or null if nothing
12052 * is parsed.
12053 */
12054
12055
12056function parseAttributeStatement(graph) {
12057 // attribute statements
12058 if (token === 'node') {
12059 getToken(); // node attributes
12060
12061 graph.node = parseAttributeList();
12062 return 'node';
12063 } else if (token === 'edge') {
12064 getToken(); // edge attributes
12065
12066 graph.edge = parseAttributeList();
12067 return 'edge';
12068 } else if (token === 'graph') {
12069 getToken(); // graph attributes
12070
12071 graph.graph = parseAttributeList();
12072 return 'graph';
12073 }
12074
12075 return null;
12076}
12077/**
12078 * parse a node statement
12079 * @param {Object} graph
12080 * @param {string | number} id
12081 */
12082
12083
12084function parseNodeStatement(graph, id) {
12085 // node statement
12086 var node = {
12087 id: id
12088 };
12089 var attr = parseAttributeList();
12090
12091 if (attr) {
12092 node.attr = attr;
12093 }
12094
12095 addNode(graph, node); // edge statements
12096
12097 parseEdge(graph, id);
12098}
12099/**
12100 * Parse an edge or a series of edges
12101 * @param {Object} graph
12102 * @param {string | number} from Id of the from node
12103 */
12104
12105
12106function parseEdge(graph, from) {
12107 while (token === '->' || token === '--') {
12108 var to;
12109 var type = token;
12110 getToken();
12111 var subgraph = parseSubgraph(graph);
12112
12113 if (subgraph) {
12114 to = subgraph;
12115 } else {
12116 if (tokenType != TOKENTYPE.IDENTIFIER) {
12117 throw newSyntaxError('Identifier or subgraph expected');
12118 }
12119
12120 to = token;
12121 addNode(graph, {
12122 id: to
12123 });
12124 getToken();
12125 } // parse edge attributes
12126
12127
12128 var attr = parseAttributeList(); // create edge
12129
12130 var edge = createEdge(graph, from, to, type, attr);
12131 addEdge(graph, edge);
12132 from = to;
12133 }
12134}
12135/**
12136 * Parse a set with attributes,
12137 * for example [label="1.000", shape=solid]
12138 * @return {Object | null} attr
12139 */
12140
12141
12142function parseAttributeList() {
12143 var i;
12144 var attr = null; // edge styles of dot and vis
12145
12146 var edgeStyles = {
12147 'dashed': true,
12148 'solid': false,
12149 'dotted': [1, 5]
12150 };
12151 /**
12152 * Define arrow types.
12153 * vis currently supports types defined in 'arrowTypes'.
12154 * Details of arrow shapes are described in
12155 * http://www.graphviz.org/content/arrow-shapes
12156 */
12157
12158 var arrowTypes = {
12159 dot: 'circle',
12160 box: 'box',
12161 crow: 'crow',
12162 curve: 'curve',
12163 icurve: 'inv_curve',
12164 normal: 'triangle',
12165 inv: 'inv_triangle',
12166 diamond: 'diamond',
12167 tee: 'bar',
12168 vee: 'vee'
12169 };
12170 /**
12171 * 'attr_list' contains attributes for checking if some of them are affected
12172 * later. For instance, both of 'arrowhead' and 'dir' (edge style defined
12173 * in DOT) make changes to 'arrows' attribute in vis.
12174 */
12175
12176 var attr_list = new Array();
12177 var attr_names = new Array(); // used for checking the case.
12178 // parse attributes
12179
12180 while (token === '[') {
12181 getToken();
12182 attr = {};
12183
12184 while (token !== '' && token != ']') {
12185 if (tokenType != TOKENTYPE.IDENTIFIER) {
12186 throw newSyntaxError('Attribute name expected');
12187 }
12188
12189 var name = token;
12190 getToken();
12191
12192 if (token != '=') {
12193 throw newSyntaxError('Equal sign = expected');
12194 }
12195
12196 getToken();
12197
12198 if (tokenType != TOKENTYPE.IDENTIFIER) {
12199 throw newSyntaxError('Attribute value expected');
12200 }
12201
12202 var value = token; // convert from dot style to vis
12203
12204 if (name === 'style') {
12205 value = edgeStyles[value];
12206 }
12207
12208 var arrowType;
12209
12210 if (name === 'arrowhead') {
12211 arrowType = arrowTypes[value];
12212 name = 'arrows';
12213 value = {
12214 'to': {
12215 'enabled': true,
12216 'type': arrowType
12217 }
12218 };
12219 }
12220
12221 if (name === 'arrowtail') {
12222 arrowType = arrowTypes[value];
12223 name = 'arrows';
12224 value = {
12225 'from': {
12226 'enabled': true,
12227 'type': arrowType
12228 }
12229 };
12230 }
12231
12232 attr_list.push({
12233 'attr': attr,
12234 'name': name,
12235 'value': value
12236 });
12237 attr_names.push(name);
12238 getToken();
12239
12240 if (token == ',') {
12241 getToken();
12242 }
12243 }
12244
12245 if (token != ']') {
12246 throw newSyntaxError('Bracket ] expected');
12247 }
12248
12249 getToken();
12250 }
12251 /**
12252 * As explained in [1], graphviz has limitations for combination of
12253 * arrow[head|tail] and dir. If attribute list includes 'dir',
12254 * following cases just be supported.
12255 * 1. both or none + arrowhead, arrowtail
12256 * 2. forward + arrowhead (arrowtail is not affedted)
12257 * 3. back + arrowtail (arrowhead is not affected)
12258 * [1] https://www.graphviz.org/doc/info/attrs.html#h:undir_note
12259 */
12260
12261
12262 if (attr_names.includes('dir')) {
12263 var idx = {}; // get index of 'arrows' and 'dir'
12264
12265 idx.arrows = {};
12266
12267 for (i = 0; i < attr_list.length; i++) {
12268 if (attr_list[i].name === 'arrows') {
12269 if (attr_list[i].value.to != null) {
12270 idx.arrows.to = i;
12271 } else if (attr_list[i].value.from != null) {
12272 idx.arrows.from = i;
12273 } else {
12274 throw newSyntaxError('Invalid value of arrows');
12275 }
12276 } else if (attr_list[i].name === 'dir') {
12277 idx.dir = i;
12278 }
12279 } // first, add default arrow shape if it is not assigned to avoid error
12280
12281
12282 var dir_type = attr_list[idx.dir].value;
12283
12284 if (!attr_names.includes('arrows')) {
12285 if (dir_type === 'both') {
12286 attr_list.push({
12287 'attr': attr_list[idx.dir].attr,
12288 'name': 'arrows',
12289 'value': {
12290 to: {
12291 enabled: true
12292 }
12293 }
12294 });
12295 idx.arrows.to = attr_list.length - 1;
12296 attr_list.push({
12297 'attr': attr_list[idx.dir].attr,
12298 'name': 'arrows',
12299 'value': {
12300 from: {
12301 enabled: true
12302 }
12303 }
12304 });
12305 idx.arrows.from = attr_list.length - 1;
12306 } else if (dir_type === 'forward') {
12307 attr_list.push({
12308 'attr': attr_list[idx.dir].attr,
12309 'name': 'arrows',
12310 'value': {
12311 to: {
12312 enabled: true
12313 }
12314 }
12315 });
12316 idx.arrows.to = attr_list.length - 1;
12317 } else if (dir_type === 'back') {
12318 attr_list.push({
12319 'attr': attr_list[idx.dir].attr,
12320 'name': 'arrows',
12321 'value': {
12322 from: {
12323 enabled: true
12324 }
12325 }
12326 });
12327 idx.arrows.from = attr_list.length - 1;
12328 } else if (dir_type === 'none') {
12329 attr_list.push({
12330 'attr': attr_list[idx.dir].attr,
12331 'name': 'arrows',
12332 'value': ''
12333 });
12334 idx.arrows.to = attr_list.length - 1;
12335 } else {
12336 throw newSyntaxError('Invalid dir type "' + dir_type + '"');
12337 }
12338 }
12339
12340 var from_type;
12341 var to_type; // update 'arrows' attribute from 'dir'.
12342
12343 if (dir_type === 'both') {
12344 // both of shapes of 'from' and 'to' are given
12345 if (idx.arrows.to && idx.arrows.from) {
12346 to_type = attr_list[idx.arrows.to].value.to.type;
12347 from_type = attr_list[idx.arrows.from].value.from.type;
12348 attr_list[idx.arrows.to] = {
12349 'attr': attr_list[idx.arrows.to].attr,
12350 'name': attr_list[idx.arrows.to].name,
12351 'value': {
12352 to: {
12353 enabled: true,
12354 type: to_type
12355 },
12356 from: {
12357 enabled: true,
12358 type: from_type
12359 }
12360 }
12361 };
12362 attr_list.splice(idx.arrows.from, 1); // shape of 'to' is assigned and use default to 'from'
12363 } else if (idx.arrows.to) {
12364 to_type = attr_list[idx.arrows.to].value.to.type;
12365 from_type = 'arrow';
12366 attr_list[idx.arrows.to] = {
12367 'attr': attr_list[idx.arrows.to].attr,
12368 'name': attr_list[idx.arrows.to].name,
12369 'value': {
12370 to: {
12371 enabled: true,
12372 type: to_type
12373 },
12374 from: {
12375 enabled: true,
12376 type: from_type
12377 }
12378 }
12379 }; // only shape of 'from' is assigned and use default for 'to'
12380 } else if (idx.arrows.from) {
12381 to_type = 'arrow';
12382 from_type = attr_list[idx.arrows.from].value.from.type;
12383 attr_list[idx.arrows.from] = {
12384 'attr': attr_list[idx.arrows.from].attr,
12385 'name': attr_list[idx.arrows.from].name,
12386 'value': {
12387 to: {
12388 enabled: true,
12389 type: to_type
12390 },
12391 from: {
12392 enabled: true,
12393 type: from_type
12394 }
12395 }
12396 };
12397 }
12398 } else if (dir_type === 'back') {
12399 // given both of shapes, but use only 'from'
12400 if (idx.arrows.to && idx.arrows.from) {
12401 to_type = '';
12402 from_type = attr_list[idx.arrows.from].value.from.type;
12403 attr_list[idx.arrows.from] = {
12404 'attr': attr_list[idx.arrows.from].attr,
12405 'name': attr_list[idx.arrows.from].name,
12406 'value': {
12407 to: {
12408 enabled: true,
12409 type: to_type
12410 },
12411 from: {
12412 enabled: true,
12413 type: from_type
12414 }
12415 }
12416 }; // given shape of 'to', but does not use it
12417 } else if (idx.arrows.to) {
12418 to_type = '';
12419 from_type = 'arrow';
12420 idx.arrows.from = idx.arrows.to;
12421 attr_list[idx.arrows.from] = {
12422 'attr': attr_list[idx.arrows.from].attr,
12423 'name': attr_list[idx.arrows.from].name,
12424 'value': {
12425 to: {
12426 enabled: true,
12427 type: to_type
12428 },
12429 from: {
12430 enabled: true,
12431 type: from_type
12432 }
12433 }
12434 }; // assign given 'from' shape
12435 } else if (idx.arrows.from) {
12436 to_type = '';
12437 from_type = attr_list[idx.arrows.from].value.from.type;
12438 attr_list[idx.arrows.to] = {
12439 'attr': attr_list[idx.arrows.from].attr,
12440 'name': attr_list[idx.arrows.from].name,
12441 'value': {
12442 to: {
12443 enabled: true,
12444 type: to_type
12445 },
12446 from: {
12447 enabled: true,
12448 type: from_type
12449 }
12450 }
12451 };
12452 }
12453
12454 attr_list[idx.arrows.from] = {
12455 'attr': attr_list[idx.arrows.from].attr,
12456 'name': attr_list[idx.arrows.from].name,
12457 'value': {
12458 from: {
12459 enabled: true,
12460 type: attr_list[idx.arrows.from].value.from.type
12461 }
12462 }
12463 };
12464 } else if (dir_type === 'none') {
12465 var idx_arrow;
12466
12467 if (idx.arrows.to) {
12468 idx_arrow = idx.arrows.to;
12469 } else {
12470 idx_arrow = idx.arrows.from;
12471 }
12472
12473 attr_list[idx_arrow] = {
12474 'attr': attr_list[idx_arrow].attr,
12475 'name': attr_list[idx_arrow].name,
12476 'value': ''
12477 };
12478 } else if (dir_type === 'forward') {
12479 // given both of shapes, but use only 'to'
12480 if (idx.arrows.to && idx.arrows.from) {
12481 to_type = attr_list[idx.arrows.to].value.to.type;
12482 from_type = '';
12483 attr_list[idx.arrows.to] = {
12484 'attr': attr_list[idx.arrows.to].attr,
12485 'name': attr_list[idx.arrows.to].name,
12486 'value': {
12487 to: {
12488 enabled: true,
12489 type: to_type
12490 },
12491 from: {
12492 enabled: true,
12493 type: from_type
12494 }
12495 }
12496 }; // assign given 'to' shape
12497 } else if (idx.arrows.to) {
12498 to_type = attr_list[idx.arrows.to].value.to.type;
12499 from_type = '';
12500 attr_list[idx.arrows.to] = {
12501 'attr': attr_list[idx.arrows.to].attr,
12502 'name': attr_list[idx.arrows.to].name,
12503 'value': {
12504 to: {
12505 enabled: true,
12506 type: to_type
12507 },
12508 from: {
12509 enabled: true,
12510 type: from_type
12511 }
12512 }
12513 }; // given shape of 'from', but does not use it
12514 } else if (idx.arrows.from) {
12515 to_type = 'arrow';
12516 from_type = '';
12517 idx.arrows.to = idx.arrows.from;
12518 attr_list[idx.arrows.to] = {
12519 'attr': attr_list[idx.arrows.to].attr,
12520 'name': attr_list[idx.arrows.to].name,
12521 'value': {
12522 to: {
12523 enabled: true,
12524 type: to_type
12525 },
12526 from: {
12527 enabled: true,
12528 type: from_type
12529 }
12530 }
12531 };
12532 }
12533
12534 attr_list[idx.arrows.to] = {
12535 'attr': attr_list[idx.arrows.to].attr,
12536 'name': attr_list[idx.arrows.to].name,
12537 'value': {
12538 to: {
12539 enabled: true,
12540 type: attr_list[idx.arrows.to].value.to.type
12541 }
12542 }
12543 };
12544 } else {
12545 throw newSyntaxError('Invalid dir type "' + dir_type + '"');
12546 } // remove 'dir' attribute no need anymore
12547
12548
12549 attr_list.splice(idx.dir, 1);
12550 } // parse 'penwidth'
12551
12552
12553 var nof_attr_list;
12554
12555 if (attr_names.includes('penwidth')) {
12556 var tmp_attr_list = [];
12557 nof_attr_list = attr_list.length;
12558
12559 for (i = 0; i < nof_attr_list; i++) {
12560 // exclude 'width' from attr_list if 'penwidth' exists
12561 if (attr_list[i].name !== 'width') {
12562 if (attr_list[i].name === 'penwidth') {
12563 attr_list[i].name = 'width';
12564 }
12565
12566 tmp_attr_list.push(attr_list[i]);
12567 }
12568 }
12569
12570 attr_list = tmp_attr_list;
12571 }
12572
12573 nof_attr_list = attr_list.length;
12574
12575 for (i = 0; i < nof_attr_list; i++) {
12576 setValue(attr_list[i].attr, attr_list[i].name, attr_list[i].value);
12577 }
12578
12579 return attr;
12580}
12581/**
12582 * Create a syntax error with extra information on current token and index.
12583 * @param {string} message
12584 * @returns {SyntaxError} err
12585 */
12586
12587
12588function newSyntaxError(message) {
12589 return new SyntaxError(message + ', got "' + chop(token, 30) + '" (char ' + index + ')');
12590}
12591/**
12592 * Chop off text after a maximum length
12593 * @param {string} text
12594 * @param {number} maxLength
12595 * @returns {String}
12596 */
12597
12598
12599function chop(text, maxLength) {
12600 return text.length <= maxLength ? text : text.substr(0, 27) + '...';
12601}
12602/**
12603 * Execute a function fn for each pair of elements in two arrays
12604 * @param {Array | *} array1
12605 * @param {Array | *} array2
12606 * @param {function} fn
12607 */
12608
12609
12610function forEach2(array1, array2, fn) {
12611 if (Array.isArray(array1)) {
12612 array1.forEach(function (elem1) {
12613 if (Array.isArray(array2)) {
12614 array2.forEach(function (elem2) {
12615 fn(elem1, elem2);
12616 });
12617 } else {
12618 fn(elem1, array2);
12619 }
12620 });
12621 } else {
12622 if (Array.isArray(array2)) {
12623 array2.forEach(function (elem2) {
12624 fn(array1, elem2);
12625 });
12626 } else {
12627 fn(array1, array2);
12628 }
12629 }
12630}
12631/**
12632 * Set a nested property on an object
12633 * When nested objects are missing, they will be created.
12634 * For example setProp({}, 'font.color', 'red') will return {font: {color: 'red'}}
12635 * @param {Object} object
12636 * @param {string} path A dot separated string like 'font.color'
12637 * @param {*} value Value for the property
12638 * @return {Object} Returns the original object, allows for chaining.
12639 */
12640
12641
12642function setProp(object, path, value) {
12643 var names = path.split('.');
12644 var prop = names.pop(); // traverse over the nested objects
12645
12646 var obj = object;
12647
12648 for (var i = 0; i < names.length; i++) {
12649 var name = names[i];
12650
12651 if (!(name in obj)) {
12652 obj[name] = {};
12653 }
12654
12655 obj = obj[name];
12656 } // set the property value
12657
12658
12659 obj[prop] = value;
12660 return object;
12661}
12662/**
12663 * Convert an object with DOT attributes to their vis.js equivalents.
12664 * @param {Object} attr Object with DOT attributes
12665 * @param {Object} mapping
12666 * @return {Object} Returns an object with vis.js attributes
12667 */
12668
12669
12670function convertAttr(attr, mapping) {
12671 var converted = {};
12672
12673 for (var prop in attr) {
12674 if (attr.hasOwnProperty(prop)) {
12675 var visProp = mapping[prop];
12676
12677 if (Array.isArray(visProp)) {
12678 visProp.forEach(function (visPropI) {
12679 setProp(converted, visPropI, attr[prop]);
12680 });
12681 } else if (typeof visProp === 'string') {
12682 setProp(converted, visProp, attr[prop]);
12683 } else {
12684 setProp(converted, prop, attr[prop]);
12685 }
12686 }
12687 }
12688
12689 return converted;
12690}
12691/**
12692 * Convert a string containing a graph in DOT language into a map containing
12693 * with nodes and edges in the format of graph.
12694 * @param {string} data Text containing a graph in DOT-notation
12695 * @return {Object} graphData
12696 */
12697
12698
12699function DOTToGraph(data) {
12700 // parse the DOT file
12701 var dotData = parseDOT(data);
12702 var graphData = {
12703 nodes: [],
12704 edges: [],
12705 options: {}
12706 }; // copy the nodes
12707
12708 if (dotData.nodes) {
12709 dotData.nodes.forEach(function (dotNode) {
12710 var graphNode = {
12711 id: dotNode.id,
12712 label: String(dotNode.label || dotNode.id)
12713 };
12714 merge(graphNode, convertAttr(dotNode.attr, NODE_ATTR_MAPPING));
12715
12716 if (graphNode.image) {
12717 graphNode.shape = 'image';
12718 }
12719
12720 graphData.nodes.push(graphNode);
12721 });
12722 } // copy the edges
12723
12724
12725 if (dotData.edges) {
12726 /**
12727 * Convert an edge in DOT format to an edge with VisGraph format
12728 * @param {Object} dotEdge
12729 * @returns {Object} graphEdge
12730 */
12731 var convertEdge = function convertEdge(dotEdge) {
12732 var graphEdge = {
12733 from: dotEdge.from,
12734 to: dotEdge.to
12735 };
12736 merge(graphEdge, convertAttr(dotEdge.attr, EDGE_ATTR_MAPPING)); // Add arrows attribute to default styled arrow.
12737 // The reason why default style is not added in parseAttributeList() is
12738 // because only default is cleared before here.
12739
12740 if (graphEdge.arrows == null && dotEdge.type === '->') {
12741 graphEdge.arrows = 'to';
12742 }
12743
12744 return graphEdge;
12745 };
12746
12747 dotData.edges.forEach(function (dotEdge) {
12748 var from, to;
12749
12750 if (dotEdge.from instanceof Object) {
12751 from = dotEdge.from.nodes;
12752 } else {
12753 from = {
12754 id: dotEdge.from
12755 };
12756 }
12757
12758 if (dotEdge.to instanceof Object) {
12759 to = dotEdge.to.nodes;
12760 } else {
12761 to = {
12762 id: dotEdge.to
12763 };
12764 }
12765
12766 if (dotEdge.from instanceof Object && dotEdge.from.edges) {
12767 dotEdge.from.edges.forEach(function (subEdge) {
12768 var graphEdge = convertEdge(subEdge);
12769 graphData.edges.push(graphEdge);
12770 });
12771 }
12772
12773 forEach2(from, to, function (from, to) {
12774 var subEdge = createEdge(graphData, from.id, to.id, dotEdge.type, dotEdge.attr);
12775 var graphEdge = convertEdge(subEdge);
12776 graphData.edges.push(graphEdge);
12777 });
12778
12779 if (dotEdge.to instanceof Object && dotEdge.to.edges) {
12780 dotEdge.to.edges.forEach(function (subEdge) {
12781 var graphEdge = convertEdge(subEdge);
12782 graphData.edges.push(graphEdge);
12783 });
12784 }
12785 });
12786 } // copy the options
12787
12788
12789 if (dotData.attr) {
12790 graphData.options = dotData.attr;
12791 }
12792
12793 return graphData;
12794} // exports
12795
12796
12797var parseDOT_1 = parseDOT;
12798var DOTToGraph_1 = DOTToGraph;
12799var dotparser = {
12800 parseDOT: parseDOT_1,
12801 DOTToGraph: DOTToGraph_1
12802};
12803
12804var dotparser$1 = /*#__PURE__*/Object.freeze({
12805 __proto__: null,
12806 'default': dotparser,
12807 __moduleExports: dotparser,
12808 parseDOT: parseDOT_1,
12809 DOTToGraph: DOTToGraph_1
12810});
12811
12812var $map = arrayIteration.map; // `Array.prototype.map` method
12813// https://tc39.github.io/ecma262/#sec-array.prototype.map
12814// with adding support of @@species
12815
12816_export({
12817 target: 'Array',
12818 proto: true,
12819 forced: !arrayMethodHasSpeciesSupport('map')
12820}, {
12821 map: function map(callbackfn
12822 /* , thisArg */
12823 ) {
12824 return $map(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
12825 }
12826});
12827
12828var quot = /"/g; // B.2.3.2.1 CreateHTML(string, tag, attribute, value)
12829// https://tc39.github.io/ecma262/#sec-createhtml
12830
12831var createHtml = function (string, tag, attribute, value) {
12832 var S = String(requireObjectCoercible(string));
12833 var p1 = '<' + tag;
12834 if (attribute !== '') p1 += ' ' + attribute + '="' + String(value).replace(quot, '&quot;') + '"';
12835 return p1 + '>' + S + '</' + tag + '>';
12836};
12837
12838// of a tag and escaping quotes in arguments
12839
12840var forcedStringHtmlMethod = function (METHOD_NAME) {
12841 return fails(function () {
12842 var test = ''[METHOD_NAME]('"');
12843 return test !== test.toLowerCase() || test.split('"').length > 3;
12844 });
12845};
12846
12847// https://tc39.github.io/ecma262/#sec-string.prototype.fixed
12848
12849
12850_export({
12851 target: 'String',
12852 proto: true,
12853 forced: forcedStringHtmlMethod('fixed')
12854}, {
12855 fixed: function fixed() {
12856 return createHtml(this, 'tt', '', '');
12857 }
12858});
12859
12860/**
12861 * Convert Gephi to Vis.
12862 *
12863 * @param gephiJSON - The parsed JSON data in Gephi format.
12864 * @param optionsObj - Additional options.
12865 *
12866 * @returns The converted data ready to be used in Vis.
12867 */
12868function parseGephi(gephiJSON, optionsObj) {
12869 var options = {
12870 edges: {
12871 inheritColor: false
12872 },
12873 nodes: {
12874 fixed: false,
12875 parseColor: false
12876 }
12877 };
12878
12879 if (optionsObj != null) {
12880 if (optionsObj.fixed != null) {
12881 options.nodes.fixed = optionsObj.fixed;
12882 }
12883
12884 if (optionsObj.parseColor != null) {
12885 options.nodes.parseColor = optionsObj.parseColor;
12886 }
12887
12888 if (optionsObj.inheritColor != null) {
12889 options.edges.inheritColor = optionsObj.inheritColor;
12890 }
12891 }
12892
12893 var gEdges = gephiJSON.edges;
12894 var vEdges = gEdges.map(function (gEdge) {
12895 var vEdge = {
12896 from: gEdge.source,
12897 id: gEdge.id,
12898 to: gEdge.target
12899 };
12900
12901 if (gEdge.attributes != null) {
12902 vEdge.attributes = gEdge.attributes;
12903 }
12904
12905 if (gEdge.label != null) {
12906 vEdge.label = gEdge.label;
12907 }
12908
12909 if (gEdge.attributes != null && gEdge.attributes.title != null) {
12910 vEdge.title = gEdge.attributes.title;
12911 }
12912
12913 if (gEdge.type === 'Directed') {
12914 vEdge.arrows = 'to';
12915 } // edge['value'] = gEdge.attributes != null ? gEdge.attributes.Weight : undefined;
12916 // edge['width'] = edge['value'] != null ? undefined : edgegEdge.size;
12917
12918
12919 if (gEdge.color && options.edges.inheritColor === false) {
12920 vEdge.color = gEdge.color;
12921 }
12922
12923 return vEdge;
12924 });
12925 var vNodes = gephiJSON.nodes.map(function (gNode) {
12926 var vNode = {
12927 id: gNode.id,
12928 fixed: options.nodes.fixed && gNode.x != null && gNode.y != null
12929 };
12930
12931 if (gNode.attributes != null) {
12932 vNode.attributes = gNode.attributes;
12933 }
12934
12935 if (gNode.label != null) {
12936 vNode.label = gNode.label;
12937 }
12938
12939 if (gNode.size != null) {
12940 vNode.size = gNode.size;
12941 }
12942
12943 if (gNode.attributes != null && gNode.attributes.title != null) {
12944 vNode.title = gNode.attributes.title;
12945 }
12946
12947 if (gNode.title != null) {
12948 vNode.title = gNode.title;
12949 }
12950
12951 if (gNode.x != null) {
12952 vNode.x = gNode.x;
12953 }
12954
12955 if (gNode.y != null) {
12956 vNode.y = gNode.y;
12957 }
12958
12959 if (gNode.color != null) {
12960 if (options.nodes.parseColor === true) {
12961 vNode.color = gNode.color;
12962 } else {
12963 vNode.color = {
12964 background: gNode.color,
12965 border: gNode.color,
12966 highlight: {
12967 background: gNode.color,
12968 border: gNode.color
12969 },
12970 hover: {
12971 background: gNode.color,
12972 border: gNode.color
12973 }
12974 };
12975 }
12976 }
12977
12978 return vNode;
12979 });
12980 return {
12981 nodes: vNodes,
12982 edges: vEdges
12983 };
12984}
12985
12986var gephiParser = /*#__PURE__*/Object.freeze({
12987 __proto__: null,
12988 parseGephi: parseGephi
12989});
12990
12991
12992
12993var Activator = /*#__PURE__*/Object.freeze({
12994 __proto__: null
12995});
12996
12997var keycharm = createCommonjsModule(function (module, exports) {
12998 /**
12999 * Created by Alex on 11/6/2014.
13000 */
13001 // https://github.com/umdjs/umd/blob/master/returnExports.js#L40-L60
13002 // if the module has no dependencies, the above pattern can be simplified to
13003
13004 (function (root, factory) {
13005 {
13006 // Node. Does not work with strict CommonJS, but
13007 // only CommonJS-like environments that support module.exports,
13008 // like Node.
13009 module.exports = factory();
13010 }
13011 })(commonjsGlobal, function () {
13012 function keycharm(options) {
13013 var preventDefault = options && options.preventDefault || false;
13014 var container = options && options.container || window;
13015 var _exportFunctions = {};
13016 var _bound = {
13017 keydown: {},
13018 keyup: {}
13019 };
13020 var _keys = {};
13021 var i; // a - z
13022
13023 for (i = 97; i <= 122; i++) {
13024 _keys[String.fromCharCode(i)] = {
13025 code: 65 + (i - 97),
13026 shift: false
13027 };
13028 } // A - Z
13029
13030
13031 for (i = 65; i <= 90; i++) {
13032 _keys[String.fromCharCode(i)] = {
13033 code: i,
13034 shift: true
13035 };
13036 } // 0 - 9
13037
13038
13039 for (i = 0; i <= 9; i++) {
13040 _keys['' + i] = {
13041 code: 48 + i,
13042 shift: false
13043 };
13044 } // F1 - F12
13045
13046
13047 for (i = 1; i <= 12; i++) {
13048 _keys['F' + i] = {
13049 code: 111 + i,
13050 shift: false
13051 };
13052 } // num0 - num9
13053
13054
13055 for (i = 0; i <= 9; i++) {
13056 _keys['num' + i] = {
13057 code: 96 + i,
13058 shift: false
13059 };
13060 } // numpad misc
13061
13062
13063 _keys['num*'] = {
13064 code: 106,
13065 shift: false
13066 };
13067 _keys['num+'] = {
13068 code: 107,
13069 shift: false
13070 };
13071 _keys['num-'] = {
13072 code: 109,
13073 shift: false
13074 };
13075 _keys['num/'] = {
13076 code: 111,
13077 shift: false
13078 };
13079 _keys['num.'] = {
13080 code: 110,
13081 shift: false
13082 }; // arrows
13083
13084 _keys['left'] = {
13085 code: 37,
13086 shift: false
13087 };
13088 _keys['up'] = {
13089 code: 38,
13090 shift: false
13091 };
13092 _keys['right'] = {
13093 code: 39,
13094 shift: false
13095 };
13096 _keys['down'] = {
13097 code: 40,
13098 shift: false
13099 }; // extra keys
13100
13101 _keys['space'] = {
13102 code: 32,
13103 shift: false
13104 };
13105 _keys['enter'] = {
13106 code: 13,
13107 shift: false
13108 };
13109 _keys['shift'] = {
13110 code: 16,
13111 shift: undefined
13112 };
13113 _keys['esc'] = {
13114 code: 27,
13115 shift: false
13116 };
13117 _keys['backspace'] = {
13118 code: 8,
13119 shift: false
13120 };
13121 _keys['tab'] = {
13122 code: 9,
13123 shift: false
13124 };
13125 _keys['ctrl'] = {
13126 code: 17,
13127 shift: false
13128 };
13129 _keys['alt'] = {
13130 code: 18,
13131 shift: false
13132 };
13133 _keys['delete'] = {
13134 code: 46,
13135 shift: false
13136 };
13137 _keys['pageup'] = {
13138 code: 33,
13139 shift: false
13140 };
13141 _keys['pagedown'] = {
13142 code: 34,
13143 shift: false
13144 }; // symbols
13145
13146 _keys['='] = {
13147 code: 187,
13148 shift: false
13149 };
13150 _keys['-'] = {
13151 code: 189,
13152 shift: false
13153 };
13154 _keys[']'] = {
13155 code: 221,
13156 shift: false
13157 };
13158 _keys['['] = {
13159 code: 219,
13160 shift: false
13161 };
13162
13163 var down = function (event) {
13164 handleEvent(event, 'keydown');
13165 };
13166
13167 var up = function (event) {
13168 handleEvent(event, 'keyup');
13169 }; // handle the actualy bound key with the event
13170
13171
13172 var handleEvent = function (event, type) {
13173 if (_bound[type][event.keyCode] !== undefined) {
13174 var bound = _bound[type][event.keyCode];
13175
13176 for (var i = 0; i < bound.length; i++) {
13177 if (bound[i].shift === undefined) {
13178 bound[i].fn(event);
13179 } else if (bound[i].shift == true && event.shiftKey == true) {
13180 bound[i].fn(event);
13181 } else if (bound[i].shift == false && event.shiftKey == false) {
13182 bound[i].fn(event);
13183 }
13184 }
13185
13186 if (preventDefault == true) {
13187 event.preventDefault();
13188 }
13189 }
13190 }; // bind a key to a callback
13191
13192
13193 _exportFunctions.bind = function (key, callback, type) {
13194 if (type === undefined) {
13195 type = 'keydown';
13196 }
13197
13198 if (_keys[key] === undefined) {
13199 throw new Error("unsupported key: " + key);
13200 }
13201
13202 if (_bound[type][_keys[key].code] === undefined) {
13203 _bound[type][_keys[key].code] = [];
13204 }
13205
13206 _bound[type][_keys[key].code].push({
13207 fn: callback,
13208 shift: _keys[key].shift
13209 });
13210 }; // bind all keys to a call back (demo purposes)
13211
13212
13213 _exportFunctions.bindAll = function (callback, type) {
13214 if (type === undefined) {
13215 type = 'keydown';
13216 }
13217
13218 for (var key in _keys) {
13219 if (_keys.hasOwnProperty(key)) {
13220 _exportFunctions.bind(key, callback, type);
13221 }
13222 }
13223 }; // get the key label from an event
13224
13225
13226 _exportFunctions.getKey = function (event) {
13227 for (var key in _keys) {
13228 if (_keys.hasOwnProperty(key)) {
13229 if (event.shiftKey == true && _keys[key].shift == true && event.keyCode == _keys[key].code) {
13230 return key;
13231 } else if (event.shiftKey == false && _keys[key].shift == false && event.keyCode == _keys[key].code) {
13232 return key;
13233 } else if (event.keyCode == _keys[key].code && key == 'shift') {
13234 return key;
13235 }
13236 }
13237 }
13238
13239 return "unknown key, currently not supported";
13240 }; // unbind either a specific callback from a key or all of them (by leaving callback undefined)
13241
13242
13243 _exportFunctions.unbind = function (key, callback, type) {
13244 if (type === undefined) {
13245 type = 'keydown';
13246 }
13247
13248 if (_keys[key] === undefined) {
13249 throw new Error("unsupported key: " + key);
13250 }
13251
13252 if (callback !== undefined) {
13253 var newBindings = [];
13254 var bound = _bound[type][_keys[key].code];
13255
13256 if (bound !== undefined) {
13257 for (var i = 0; i < bound.length; i++) {
13258 if (!(bound[i].fn == callback && bound[i].shift == _keys[key].shift)) {
13259 newBindings.push(_bound[type][_keys[key].code][i]);
13260 }
13261 }
13262 }
13263
13264 _bound[type][_keys[key].code] = newBindings;
13265 } else {
13266 _bound[type][_keys[key].code] = [];
13267 }
13268 }; // reset all bound variables.
13269
13270
13271 _exportFunctions.reset = function () {
13272 _bound = {
13273 keydown: {},
13274 keyup: {}
13275 };
13276 }; // unbind all listeners and reset all variables.
13277
13278
13279 _exportFunctions.destroy = function () {
13280 _bound = {
13281 keydown: {},
13282 keyup: {}
13283 };
13284 container.removeEventListener('keydown', down, true);
13285 container.removeEventListener('keyup', up, true);
13286 }; // create listeners.
13287
13288
13289 container.addEventListener('keydown', down, true);
13290 container.addEventListener('keyup', up, true); // return the public functions.
13291
13292 return _exportFunctions;
13293 }
13294
13295 return keycharm;
13296 });
13297});
13298
13299var keycharm$1 = /*#__PURE__*/Object.freeze({
13300 __proto__: null,
13301 'default': keycharm,
13302 __moduleExports: keycharm
13303});
13304
13305/*! Hammer.JS - v2.0.15 - 2019-04-04
13306 * http://naver.github.io/egjs
13307 *
13308 * Forked By Naver egjs
13309 * Copyright (c) hammerjs
13310 * Licensed under the MIT license */
13311function _extends() {
13312 _extends = Object.assign || function (target) {
13313 for (var i = 1; i < arguments.length; i++) {
13314 var source = arguments[i];
13315
13316 for (var key in source) {
13317 if (Object.prototype.hasOwnProperty.call(source, key)) {
13318 target[key] = source[key];
13319 }
13320 }
13321 }
13322
13323 return target;
13324 };
13325
13326 return _extends.apply(this, arguments);
13327}
13328
13329function _inheritsLoose(subClass, superClass) {
13330 subClass.prototype = Object.create(superClass.prototype);
13331 subClass.prototype.constructor = subClass;
13332 subClass.__proto__ = superClass;
13333}
13334
13335function _assertThisInitialized(self) {
13336 if (self === void 0) {
13337 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
13338 }
13339
13340 return self;
13341}
13342/**
13343 * @private
13344 * extend object.
13345 * means that properties in dest will be overwritten by the ones in src.
13346 * @param {Object} target
13347 * @param {...Object} objects_to_assign
13348 * @returns {Object} target
13349 */
13350
13351
13352var assign;
13353
13354if (typeof Object.assign !== 'function') {
13355 assign = function assign(target) {
13356 if (target === undefined || target === null) {
13357 throw new TypeError('Cannot convert undefined or null to object');
13358 }
13359
13360 var output = Object(target);
13361
13362 for (var index = 1; index < arguments.length; index++) {
13363 var source = arguments[index];
13364
13365 if (source !== undefined && source !== null) {
13366 for (var nextKey in source) {
13367 if (source.hasOwnProperty(nextKey)) {
13368 output[nextKey] = source[nextKey];
13369 }
13370 }
13371 }
13372 }
13373
13374 return output;
13375 };
13376} else {
13377 assign = Object.assign;
13378}
13379
13380var assign$1 = assign;
13381var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
13382var TEST_ELEMENT = typeof document === "undefined" ? {
13383 style: {}
13384} : document.createElement('div');
13385var TYPE_FUNCTION = 'function';
13386var round = Math.round,
13387 abs$1 = Math.abs;
13388var now = Date.now;
13389/**
13390 * @private
13391 * get the prefixed property
13392 * @param {Object} obj
13393 * @param {String} property
13394 * @returns {String|Undefined} prefixed
13395 */
13396
13397function prefixed(obj, property) {
13398 var prefix;
13399 var prop;
13400 var camelProp = property[0].toUpperCase() + property.slice(1);
13401 var i = 0;
13402
13403 while (i < VENDOR_PREFIXES.length) {
13404 prefix = VENDOR_PREFIXES[i];
13405 prop = prefix ? prefix + camelProp : property;
13406
13407 if (prop in obj) {
13408 return prop;
13409 }
13410
13411 i++;
13412 }
13413
13414 return undefined;
13415}
13416/* eslint-disable no-new-func, no-nested-ternary */
13417
13418
13419var win;
13420
13421if (typeof window === "undefined") {
13422 // window is undefined in node.js
13423 win = {};
13424} else {
13425 win = window;
13426}
13427
13428var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
13429var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
13430
13431function getTouchActionProps() {
13432 if (!NATIVE_TOUCH_ACTION) {
13433 return false;
13434 }
13435
13436 var touchMap = {};
13437 var cssSupports = win.CSS && win.CSS.supports;
13438 ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function (val) {
13439 // If css.supports is not supported but there is native touch-action assume it supports
13440 // all values. This is the case for IE 10 and 11.
13441 return touchMap[val] = cssSupports ? win.CSS.supports('touch-action', val) : true;
13442 });
13443 return touchMap;
13444}
13445
13446var TOUCH_ACTION_COMPUTE = 'compute';
13447var TOUCH_ACTION_AUTO = 'auto';
13448var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented
13449
13450var TOUCH_ACTION_NONE = 'none';
13451var TOUCH_ACTION_PAN_X = 'pan-x';
13452var TOUCH_ACTION_PAN_Y = 'pan-y';
13453var TOUCH_ACTION_MAP = getTouchActionProps();
13454var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
13455var SUPPORT_TOUCH = 'ontouchstart' in win;
13456var SUPPORT_POINTER_EVENTS = prefixed(win, 'PointerEvent') !== undefined;
13457var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
13458var INPUT_TYPE_TOUCH = 'touch';
13459var INPUT_TYPE_PEN = 'pen';
13460var INPUT_TYPE_MOUSE = 'mouse';
13461var INPUT_TYPE_KINECT = 'kinect';
13462var COMPUTE_INTERVAL = 25;
13463var INPUT_START = 1;
13464var INPUT_MOVE = 2;
13465var INPUT_END = 4;
13466var INPUT_CANCEL = 8;
13467var DIRECTION_NONE = 1;
13468var DIRECTION_LEFT = 2;
13469var DIRECTION_RIGHT = 4;
13470var DIRECTION_UP = 8;
13471var DIRECTION_DOWN = 16;
13472var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
13473var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
13474var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
13475var PROPS_XY = ['x', 'y'];
13476var PROPS_CLIENT_XY = ['clientX', 'clientY'];
13477/**
13478 * @private
13479 * walk objects and arrays
13480 * @param {Object} obj
13481 * @param {Function} iterator
13482 * @param {Object} context
13483 */
13484
13485function each(obj, iterator, context) {
13486 var i;
13487
13488 if (!obj) {
13489 return;
13490 }
13491
13492 if (obj.forEach) {
13493 obj.forEach(iterator, context);
13494 } else if (obj.length !== undefined) {
13495 i = 0;
13496
13497 while (i < obj.length) {
13498 iterator.call(context, obj[i], i, obj);
13499 i++;
13500 }
13501 } else {
13502 for (i in obj) {
13503 obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
13504 }
13505 }
13506}
13507/**
13508 * @private
13509 * let a boolean value also be a function that must return a boolean
13510 * this first item in args will be used as the context
13511 * @param {Boolean|Function} val
13512 * @param {Array} [args]
13513 * @returns {Boolean}
13514 */
13515
13516
13517function boolOrFn(val, args) {
13518 if (typeof val === TYPE_FUNCTION) {
13519 return val.apply(args ? args[0] || undefined : undefined, args);
13520 }
13521
13522 return val;
13523}
13524/**
13525 * @private
13526 * small indexOf wrapper
13527 * @param {String} str
13528 * @param {String} find
13529 * @returns {Boolean} found
13530 */
13531
13532
13533function inStr(str, find) {
13534 return str.indexOf(find) > -1;
13535}
13536/**
13537 * @private
13538 * when the touchActions are collected they are not a valid value, so we need to clean things up. *
13539 * @param {String} actions
13540 * @returns {*}
13541 */
13542
13543
13544function cleanTouchActions(actions) {
13545 // none
13546 if (inStr(actions, TOUCH_ACTION_NONE)) {
13547 return TOUCH_ACTION_NONE;
13548 }
13549
13550 var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
13551 var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); // if both pan-x and pan-y are set (different recognizers
13552 // for different directions, e.g. horizontal pan but vertical swipe?)
13553 // we need none (as otherwise with pan-x pan-y combined none of these
13554 // recognizers will work, since the browser would handle all panning
13555
13556 if (hasPanX && hasPanY) {
13557 return TOUCH_ACTION_NONE;
13558 } // pan-x OR pan-y
13559
13560
13561 if (hasPanX || hasPanY) {
13562 return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
13563 } // manipulation
13564
13565
13566 if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
13567 return TOUCH_ACTION_MANIPULATION;
13568 }
13569
13570 return TOUCH_ACTION_AUTO;
13571}
13572/**
13573 * @private
13574 * Touch Action
13575 * sets the touchAction property or uses the js alternative
13576 * @param {Manager} manager
13577 * @param {String} value
13578 * @constructor
13579 */
13580
13581
13582var TouchAction =
13583/*#__PURE__*/
13584function () {
13585 function TouchAction(manager, value) {
13586 this.manager = manager;
13587 this.set(value);
13588 }
13589 /**
13590 * @private
13591 * set the touchAction value on the element or enable the polyfill
13592 * @param {String} value
13593 */
13594
13595
13596 var _proto = TouchAction.prototype;
13597
13598 _proto.set = function set(value) {
13599 // find out the touch-action by the event handlers
13600 if (value === TOUCH_ACTION_COMPUTE) {
13601 value = this.compute();
13602 }
13603
13604 if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {
13605 this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
13606 }
13607
13608 this.actions = value.toLowerCase().trim();
13609 };
13610 /**
13611 * @private
13612 * just re-set the touchAction value
13613 */
13614
13615
13616 _proto.update = function update() {
13617 this.set(this.manager.options.touchAction);
13618 };
13619 /**
13620 * @private
13621 * compute the value for the touchAction property based on the recognizer's settings
13622 * @returns {String} value
13623 */
13624
13625
13626 _proto.compute = function compute() {
13627 var actions = [];
13628 each(this.manager.recognizers, function (recognizer) {
13629 if (boolOrFn(recognizer.options.enable, [recognizer])) {
13630 actions = actions.concat(recognizer.getTouchAction());
13631 }
13632 });
13633 return cleanTouchActions(actions.join(' '));
13634 };
13635 /**
13636 * @private
13637 * this method is called on each input cycle and provides the preventing of the browser behavior
13638 * @param {Object} input
13639 */
13640
13641
13642 _proto.preventDefaults = function preventDefaults(input) {
13643 var srcEvent = input.srcEvent;
13644 var direction = input.offsetDirection; // if the touch action did prevented once this session
13645
13646 if (this.manager.session.prevented) {
13647 srcEvent.preventDefault();
13648 return;
13649 }
13650
13651 var actions = this.actions;
13652 var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];
13653 var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];
13654 var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];
13655
13656 if (hasNone) {
13657 // do not prevent defaults if this is a tap gesture
13658 var isTapPointer = input.pointers.length === 1;
13659 var isTapMovement = input.distance < 2;
13660 var isTapTouchTime = input.deltaTime < 250;
13661
13662 if (isTapPointer && isTapMovement && isTapTouchTime) {
13663 return;
13664 }
13665 }
13666
13667 if (hasPanX && hasPanY) {
13668 // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
13669 return;
13670 }
13671
13672 if (hasNone || hasPanY && direction & DIRECTION_HORIZONTAL || hasPanX && direction & DIRECTION_VERTICAL) {
13673 return this.preventSrc(srcEvent);
13674 }
13675 };
13676 /**
13677 * @private
13678 * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
13679 * @param {Object} srcEvent
13680 */
13681
13682
13683 _proto.preventSrc = function preventSrc(srcEvent) {
13684 this.manager.session.prevented = true;
13685 srcEvent.preventDefault();
13686 };
13687
13688 return TouchAction;
13689}();
13690/**
13691 * @private
13692 * find if a node is in the given parent
13693 * @method hasParent
13694 * @param {HTMLElement} node
13695 * @param {HTMLElement} parent
13696 * @return {Boolean} found
13697 */
13698
13699
13700function hasParent$1(node, parent) {
13701 while (node) {
13702 if (node === parent) {
13703 return true;
13704 }
13705
13706 node = node.parentNode;
13707 }
13708
13709 return false;
13710}
13711/**
13712 * @private
13713 * get the center of all the pointers
13714 * @param {Array} pointers
13715 * @return {Object} center contains `x` and `y` properties
13716 */
13717
13718
13719function getCenter(pointers) {
13720 var pointersLength = pointers.length; // no need to loop when only one touch
13721
13722 if (pointersLength === 1) {
13723 return {
13724 x: round(pointers[0].clientX),
13725 y: round(pointers[0].clientY)
13726 };
13727 }
13728
13729 var x = 0;
13730 var y = 0;
13731 var i = 0;
13732
13733 while (i < pointersLength) {
13734 x += pointers[i].clientX;
13735 y += pointers[i].clientY;
13736 i++;
13737 }
13738
13739 return {
13740 x: round(x / pointersLength),
13741 y: round(y / pointersLength)
13742 };
13743}
13744/**
13745 * @private
13746 * create a simple clone from the input used for storage of firstInput and firstMultiple
13747 * @param {Object} input
13748 * @returns {Object} clonedInputData
13749 */
13750
13751
13752function simpleCloneInputData(input) {
13753 // make a simple copy of the pointers because we will get a reference if we don't
13754 // we only need clientXY for the calculations
13755 var pointers = [];
13756 var i = 0;
13757
13758 while (i < input.pointers.length) {
13759 pointers[i] = {
13760 clientX: round(input.pointers[i].clientX),
13761 clientY: round(input.pointers[i].clientY)
13762 };
13763 i++;
13764 }
13765
13766 return {
13767 timeStamp: now(),
13768 pointers: pointers,
13769 center: getCenter(pointers),
13770 deltaX: input.deltaX,
13771 deltaY: input.deltaY
13772 };
13773}
13774/**
13775 * @private
13776 * calculate the absolute distance between two points
13777 * @param {Object} p1 {x, y}
13778 * @param {Object} p2 {x, y}
13779 * @param {Array} [props] containing x and y keys
13780 * @return {Number} distance
13781 */
13782
13783
13784function getDistance(p1, p2, props) {
13785 if (!props) {
13786 props = PROPS_XY;
13787 }
13788
13789 var x = p2[props[0]] - p1[props[0]];
13790 var y = p2[props[1]] - p1[props[1]];
13791 return Math.sqrt(x * x + y * y);
13792}
13793/**
13794 * @private
13795 * calculate the angle between two coordinates
13796 * @param {Object} p1
13797 * @param {Object} p2
13798 * @param {Array} [props] containing x and y keys
13799 * @return {Number} angle
13800 */
13801
13802
13803function getAngle(p1, p2, props) {
13804 if (!props) {
13805 props = PROPS_XY;
13806 }
13807
13808 var x = p2[props[0]] - p1[props[0]];
13809 var y = p2[props[1]] - p1[props[1]];
13810 return Math.atan2(y, x) * 180 / Math.PI;
13811}
13812/**
13813 * @private
13814 * get the direction between two points
13815 * @param {Number} x
13816 * @param {Number} y
13817 * @return {Number} direction
13818 */
13819
13820
13821function getDirection(x, y) {
13822 if (x === y) {
13823 return DIRECTION_NONE;
13824 }
13825
13826 if (abs$1(x) >= abs$1(y)) {
13827 return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
13828 }
13829
13830 return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
13831}
13832
13833function computeDeltaXY(session, input) {
13834 var center = input.center; // let { offsetDelta:offset = {}, prevDelta = {}, prevInput = {} } = session;
13835 // jscs throwing error on defalut destructured values and without defaults tests fail
13836
13837 var offset = session.offsetDelta || {};
13838 var prevDelta = session.prevDelta || {};
13839 var prevInput = session.prevInput || {};
13840
13841 if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
13842 prevDelta = session.prevDelta = {
13843 x: prevInput.deltaX || 0,
13844 y: prevInput.deltaY || 0
13845 };
13846 offset = session.offsetDelta = {
13847 x: center.x,
13848 y: center.y
13849 };
13850 }
13851
13852 input.deltaX = prevDelta.x + (center.x - offset.x);
13853 input.deltaY = prevDelta.y + (center.y - offset.y);
13854}
13855/**
13856 * @private
13857 * calculate the velocity between two points. unit is in px per ms.
13858 * @param {Number} deltaTime
13859 * @param {Number} x
13860 * @param {Number} y
13861 * @return {Object} velocity `x` and `y`
13862 */
13863
13864
13865function getVelocity(deltaTime, x, y) {
13866 return {
13867 x: x / deltaTime || 0,
13868 y: y / deltaTime || 0
13869 };
13870}
13871/**
13872 * @private
13873 * calculate the scale factor between two pointersets
13874 * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
13875 * @param {Array} start array of pointers
13876 * @param {Array} end array of pointers
13877 * @return {Number} scale
13878 */
13879
13880
13881function getScale(start, end) {
13882 return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
13883}
13884/**
13885 * @private
13886 * calculate the rotation degrees between two pointersets
13887 * @param {Array} start array of pointers
13888 * @param {Array} end array of pointers
13889 * @return {Number} rotation
13890 */
13891
13892
13893function getRotation(start, end) {
13894 return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);
13895}
13896/**
13897 * @private
13898 * velocity is calculated every x ms
13899 * @param {Object} session
13900 * @param {Object} input
13901 */
13902
13903
13904function computeIntervalInputData(session, input) {
13905 var last = session.lastInterval || input;
13906 var deltaTime = input.timeStamp - last.timeStamp;
13907 var velocity;
13908 var velocityX;
13909 var velocityY;
13910 var direction;
13911
13912 if (input.eventType !== INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
13913 var deltaX = input.deltaX - last.deltaX;
13914 var deltaY = input.deltaY - last.deltaY;
13915 var v = getVelocity(deltaTime, deltaX, deltaY);
13916 velocityX = v.x;
13917 velocityY = v.y;
13918 velocity = abs$1(v.x) > abs$1(v.y) ? v.x : v.y;
13919 direction = getDirection(deltaX, deltaY);
13920 session.lastInterval = input;
13921 } else {
13922 // use latest velocity info if it doesn't overtake a minimum period
13923 velocity = last.velocity;
13924 velocityX = last.velocityX;
13925 velocityY = last.velocityY;
13926 direction = last.direction;
13927 }
13928
13929 input.velocity = velocity;
13930 input.velocityX = velocityX;
13931 input.velocityY = velocityY;
13932 input.direction = direction;
13933}
13934/**
13935* @private
13936 * extend the data with some usable properties like scale, rotate, velocity etc
13937 * @param {Object} manager
13938 * @param {Object} input
13939 */
13940
13941
13942function computeInputData(manager, input) {
13943 var session = manager.session;
13944 var pointers = input.pointers;
13945 var pointersLength = pointers.length; // store the first input to calculate the distance and direction
13946
13947 if (!session.firstInput) {
13948 session.firstInput = simpleCloneInputData(input);
13949 } // to compute scale and rotation we need to store the multiple touches
13950
13951
13952 if (pointersLength > 1 && !session.firstMultiple) {
13953 session.firstMultiple = simpleCloneInputData(input);
13954 } else if (pointersLength === 1) {
13955 session.firstMultiple = false;
13956 }
13957
13958 var firstInput = session.firstInput,
13959 firstMultiple = session.firstMultiple;
13960 var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
13961 var center = input.center = getCenter(pointers);
13962 input.timeStamp = now();
13963 input.deltaTime = input.timeStamp - firstInput.timeStamp;
13964 input.angle = getAngle(offsetCenter, center);
13965 input.distance = getDistance(offsetCenter, center);
13966 computeDeltaXY(session, input);
13967 input.offsetDirection = getDirection(input.deltaX, input.deltaY);
13968 var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);
13969 input.overallVelocityX = overallVelocity.x;
13970 input.overallVelocityY = overallVelocity.y;
13971 input.overallVelocity = abs$1(overallVelocity.x) > abs$1(overallVelocity.y) ? overallVelocity.x : overallVelocity.y;
13972 input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
13973 input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
13974 input.maxPointers = !session.prevInput ? input.pointers.length : input.pointers.length > session.prevInput.maxPointers ? input.pointers.length : session.prevInput.maxPointers;
13975 computeIntervalInputData(session, input); // find the correct target
13976
13977 var target = manager.element;
13978
13979 if (hasParent$1(input.srcEvent.target, target)) {
13980 target = input.srcEvent.target;
13981 }
13982
13983 input.target = target;
13984}
13985/**
13986 * @private
13987 * handle input events
13988 * @param {Manager} manager
13989 * @param {String} eventType
13990 * @param {Object} input
13991 */
13992
13993
13994function inputHandler(manager, eventType, input) {
13995 var pointersLen = input.pointers.length;
13996 var changedPointersLen = input.changedPointers.length;
13997 var isFirst = eventType & INPUT_START && pointersLen - changedPointersLen === 0;
13998 var isFinal = eventType & (INPUT_END | INPUT_CANCEL) && pointersLen - changedPointersLen === 0;
13999 input.isFirst = !!isFirst;
14000 input.isFinal = !!isFinal;
14001
14002 if (isFirst) {
14003 manager.session = {};
14004 } // source event is the normalized value of the domEvents
14005 // like 'touchstart, mouseup, pointerdown'
14006
14007
14008 input.eventType = eventType; // compute scale, rotation etc
14009
14010 computeInputData(manager, input); // emit secret event
14011
14012 manager.emit('hammer.input', input);
14013 manager.recognize(input);
14014 manager.session.prevInput = input;
14015}
14016/**
14017 * @private
14018 * split string on whitespace
14019 * @param {String} str
14020 * @returns {Array} words
14021 */
14022
14023
14024function splitStr(str) {
14025 return str.trim().split(/\s+/g);
14026}
14027/**
14028 * @private
14029 * addEventListener with multiple events at once
14030 * @param {EventTarget} target
14031 * @param {String} types
14032 * @param {Function} handler
14033 */
14034
14035
14036function addEventListeners(target, types, handler) {
14037 each(splitStr(types), function (type) {
14038 target.addEventListener(type, handler, false);
14039 });
14040}
14041/**
14042 * @private
14043 * removeEventListener with multiple events at once
14044 * @param {EventTarget} target
14045 * @param {String} types
14046 * @param {Function} handler
14047 */
14048
14049
14050function removeEventListeners(target, types, handler) {
14051 each(splitStr(types), function (type) {
14052 target.removeEventListener(type, handler, false);
14053 });
14054}
14055/**
14056 * @private
14057 * get the window object of an element
14058 * @param {HTMLElement} element
14059 * @returns {DocumentView|Window}
14060 */
14061
14062
14063function getWindowForElement(element) {
14064 var doc = element.ownerDocument || element;
14065 return doc.defaultView || doc.parentWindow || window;
14066}
14067/**
14068 * @private
14069 * create new input type manager
14070 * @param {Manager} manager
14071 * @param {Function} callback
14072 * @returns {Input}
14073 * @constructor
14074 */
14075
14076
14077var Input =
14078/*#__PURE__*/
14079function () {
14080 function Input(manager, callback) {
14081 var self = this;
14082 this.manager = manager;
14083 this.callback = callback;
14084 this.element = manager.element;
14085 this.target = manager.options.inputTarget; // smaller wrapper around the handler, for the scope and the enabled state of the manager,
14086 // so when disabled the input events are completely bypassed.
14087
14088 this.domHandler = function (ev) {
14089 if (boolOrFn(manager.options.enable, [manager])) {
14090 self.handler(ev);
14091 }
14092 };
14093
14094 this.init();
14095 }
14096 /**
14097 * @private
14098 * should handle the inputEvent data and trigger the callback
14099 * @virtual
14100 */
14101
14102
14103 var _proto = Input.prototype;
14104
14105 _proto.handler = function handler() {};
14106 /**
14107 * @private
14108 * bind the events
14109 */
14110
14111
14112 _proto.init = function init() {
14113 this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
14114 this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
14115 this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
14116 };
14117 /**
14118 * @private
14119 * unbind the events
14120 */
14121
14122
14123 _proto.destroy = function destroy() {
14124 this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
14125 this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
14126 this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
14127 };
14128
14129 return Input;
14130}();
14131/**
14132 * @private
14133 * find if a array contains the object using indexOf or a simple polyFill
14134 * @param {Array} src
14135 * @param {String} find
14136 * @param {String} [findByKey]
14137 * @return {Boolean|Number} false when not found, or the index
14138 */
14139
14140
14141function inArray(src, find, findByKey) {
14142 if (src.indexOf && !findByKey) {
14143 return src.indexOf(find);
14144 } else {
14145 var i = 0;
14146
14147 while (i < src.length) {
14148 if (findByKey && src[i][findByKey] == find || !findByKey && src[i] === find) {
14149 // do not use === here, test fails
14150 return i;
14151 }
14152
14153 i++;
14154 }
14155
14156 return -1;
14157 }
14158}
14159
14160var POINTER_INPUT_MAP = {
14161 pointerdown: INPUT_START,
14162 pointermove: INPUT_MOVE,
14163 pointerup: INPUT_END,
14164 pointercancel: INPUT_CANCEL,
14165 pointerout: INPUT_CANCEL
14166}; // in IE10 the pointer types is defined as an enum
14167
14168var IE10_POINTER_TYPE_ENUM = {
14169 2: INPUT_TYPE_TOUCH,
14170 3: INPUT_TYPE_PEN,
14171 4: INPUT_TYPE_MOUSE,
14172 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816
14173
14174};
14175var POINTER_ELEMENT_EVENTS = 'pointerdown';
14176var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; // IE10 has prefixed support, and case-sensitive
14177
14178if (win.MSPointerEvent && !win.PointerEvent) {
14179 POINTER_ELEMENT_EVENTS = 'MSPointerDown';
14180 POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
14181}
14182/**
14183 * @private
14184 * Pointer events input
14185 * @constructor
14186 * @extends Input
14187 */
14188
14189
14190var PointerEventInput =
14191/*#__PURE__*/
14192function (_Input) {
14193 _inheritsLoose(PointerEventInput, _Input);
14194
14195 function PointerEventInput() {
14196 var _this;
14197
14198 var proto = PointerEventInput.prototype;
14199 proto.evEl = POINTER_ELEMENT_EVENTS;
14200 proto.evWin = POINTER_WINDOW_EVENTS;
14201 _this = _Input.apply(this, arguments) || this;
14202 _this.store = _this.manager.session.pointerEvents = [];
14203 return _this;
14204 }
14205 /**
14206 * @private
14207 * handle mouse events
14208 * @param {Object} ev
14209 */
14210
14211
14212 var _proto = PointerEventInput.prototype;
14213
14214 _proto.handler = function handler(ev) {
14215 var store = this.store;
14216 var removePointer = false;
14217 var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
14218 var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
14219 var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
14220 var isTouch = pointerType === INPUT_TYPE_TOUCH; // get index of the event in the store
14221
14222 var storeIndex = inArray(store, ev.pointerId, 'pointerId'); // start and mouse must be down
14223
14224 if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
14225 if (storeIndex < 0) {
14226 store.push(ev);
14227 storeIndex = store.length - 1;
14228 }
14229 } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
14230 removePointer = true;
14231 } // it not found, so the pointer hasn't been down (so it's probably a hover)
14232
14233
14234 if (storeIndex < 0) {
14235 return;
14236 } // update the event in the store
14237
14238
14239 store[storeIndex] = ev;
14240 this.callback(this.manager, eventType, {
14241 pointers: store,
14242 changedPointers: [ev],
14243 pointerType: pointerType,
14244 srcEvent: ev
14245 });
14246
14247 if (removePointer) {
14248 // remove from the store
14249 store.splice(storeIndex, 1);
14250 }
14251 };
14252
14253 return PointerEventInput;
14254}(Input);
14255/**
14256 * @private
14257 * convert array-like objects to real arrays
14258 * @param {Object} obj
14259 * @returns {Array}
14260 */
14261
14262
14263function toArray$1(obj) {
14264 return Array.prototype.slice.call(obj, 0);
14265}
14266/**
14267 * @private
14268 * unique array with objects based on a key (like 'id') or just by the array's value
14269 * @param {Array} src [{id:1},{id:2},{id:1}]
14270 * @param {String} [key]
14271 * @param {Boolean} [sort=False]
14272 * @returns {Array} [{id:1},{id:2}]
14273 */
14274
14275
14276function uniqueArray(src, key, sort) {
14277 var results = [];
14278 var values = [];
14279 var i = 0;
14280
14281 while (i < src.length) {
14282 var val = key ? src[i][key] : src[i];
14283
14284 if (inArray(values, val) < 0) {
14285 results.push(src[i]);
14286 }
14287
14288 values[i] = val;
14289 i++;
14290 }
14291
14292 if (sort) {
14293 if (!key) {
14294 results = results.sort();
14295 } else {
14296 results = results.sort(function (a, b) {
14297 return a[key] > b[key];
14298 });
14299 }
14300 }
14301
14302 return results;
14303}
14304
14305var TOUCH_INPUT_MAP = {
14306 touchstart: INPUT_START,
14307 touchmove: INPUT_MOVE,
14308 touchend: INPUT_END,
14309 touchcancel: INPUT_CANCEL
14310};
14311var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
14312/**
14313 * @private
14314 * Multi-user touch events input
14315 * @constructor
14316 * @extends Input
14317 */
14318
14319var TouchInput =
14320/*#__PURE__*/
14321function (_Input) {
14322 _inheritsLoose(TouchInput, _Input);
14323
14324 function TouchInput() {
14325 var _this;
14326
14327 TouchInput.prototype.evTarget = TOUCH_TARGET_EVENTS;
14328 _this = _Input.apply(this, arguments) || this;
14329 _this.targetIds = {}; // this.evTarget = TOUCH_TARGET_EVENTS;
14330
14331 return _this;
14332 }
14333
14334 var _proto = TouchInput.prototype;
14335
14336 _proto.handler = function handler(ev) {
14337 var type = TOUCH_INPUT_MAP[ev.type];
14338 var touches = getTouches.call(this, ev, type);
14339
14340 if (!touches) {
14341 return;
14342 }
14343
14344 this.callback(this.manager, type, {
14345 pointers: touches[0],
14346 changedPointers: touches[1],
14347 pointerType: INPUT_TYPE_TOUCH,
14348 srcEvent: ev
14349 });
14350 };
14351
14352 return TouchInput;
14353}(Input);
14354
14355function getTouches(ev, type) {
14356 var allTouches = toArray$1(ev.touches);
14357 var targetIds = this.targetIds; // when there is only one touch, the process can be simplified
14358
14359 if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
14360 targetIds[allTouches[0].identifier] = true;
14361 return [allTouches, allTouches];
14362 }
14363
14364 var i;
14365 var targetTouches;
14366 var changedTouches = toArray$1(ev.changedTouches);
14367 var changedTargetTouches = [];
14368 var target = this.target; // get target touches from touches
14369
14370 targetTouches = allTouches.filter(function (touch) {
14371 return hasParent$1(touch.target, target);
14372 }); // collect touches
14373
14374 if (type === INPUT_START) {
14375 i = 0;
14376
14377 while (i < targetTouches.length) {
14378 targetIds[targetTouches[i].identifier] = true;
14379 i++;
14380 }
14381 } // filter changed touches to only contain touches that exist in the collected target ids
14382
14383
14384 i = 0;
14385
14386 while (i < changedTouches.length) {
14387 if (targetIds[changedTouches[i].identifier]) {
14388 changedTargetTouches.push(changedTouches[i]);
14389 } // cleanup removed touches
14390
14391
14392 if (type & (INPUT_END | INPUT_CANCEL)) {
14393 delete targetIds[changedTouches[i].identifier];
14394 }
14395
14396 i++;
14397 }
14398
14399 if (!changedTargetTouches.length) {
14400 return;
14401 }
14402
14403 return [// merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
14404 uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), changedTargetTouches];
14405}
14406
14407var MOUSE_INPUT_MAP = {
14408 mousedown: INPUT_START,
14409 mousemove: INPUT_MOVE,
14410 mouseup: INPUT_END
14411};
14412var MOUSE_ELEMENT_EVENTS = 'mousedown';
14413var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
14414/**
14415 * @private
14416 * Mouse events input
14417 * @constructor
14418 * @extends Input
14419 */
14420
14421var MouseInput =
14422/*#__PURE__*/
14423function (_Input) {
14424 _inheritsLoose(MouseInput, _Input);
14425
14426 function MouseInput() {
14427 var _this;
14428
14429 var proto = MouseInput.prototype;
14430 proto.evEl = MOUSE_ELEMENT_EVENTS;
14431 proto.evWin = MOUSE_WINDOW_EVENTS;
14432 _this = _Input.apply(this, arguments) || this;
14433 _this.pressed = false; // mousedown state
14434
14435 return _this;
14436 }
14437 /**
14438 * @private
14439 * handle mouse events
14440 * @param {Object} ev
14441 */
14442
14443
14444 var _proto = MouseInput.prototype;
14445
14446 _proto.handler = function handler(ev) {
14447 var eventType = MOUSE_INPUT_MAP[ev.type]; // on start we want to have the left mouse button down
14448
14449 if (eventType & INPUT_START && ev.button === 0) {
14450 this.pressed = true;
14451 }
14452
14453 if (eventType & INPUT_MOVE && ev.which !== 1) {
14454 eventType = INPUT_END;
14455 } // mouse must be down
14456
14457
14458 if (!this.pressed) {
14459 return;
14460 }
14461
14462 if (eventType & INPUT_END) {
14463 this.pressed = false;
14464 }
14465
14466 this.callback(this.manager, eventType, {
14467 pointers: [ev],
14468 changedPointers: [ev],
14469 pointerType: INPUT_TYPE_MOUSE,
14470 srcEvent: ev
14471 });
14472 };
14473
14474 return MouseInput;
14475}(Input);
14476/**
14477 * @private
14478 * Combined touch and mouse input
14479 *
14480 * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
14481 * This because touch devices also emit mouse events while doing a touch.
14482 *
14483 * @constructor
14484 * @extends Input
14485 */
14486
14487
14488var DEDUP_TIMEOUT = 2500;
14489var DEDUP_DISTANCE = 25;
14490
14491function setLastTouch(eventData) {
14492 var _eventData$changedPoi = eventData.changedPointers,
14493 touch = _eventData$changedPoi[0];
14494
14495 if (touch.identifier === this.primaryTouch) {
14496 var lastTouch = {
14497 x: touch.clientX,
14498 y: touch.clientY
14499 };
14500 var lts = this.lastTouches;
14501 this.lastTouches.push(lastTouch);
14502
14503 var removeLastTouch = function removeLastTouch() {
14504 var i = lts.indexOf(lastTouch);
14505
14506 if (i > -1) {
14507 lts.splice(i, 1);
14508 }
14509 };
14510
14511 setTimeout(removeLastTouch, DEDUP_TIMEOUT);
14512 }
14513}
14514
14515function recordTouches(eventType, eventData) {
14516 if (eventType & INPUT_START) {
14517 this.primaryTouch = eventData.changedPointers[0].identifier;
14518 setLastTouch.call(this, eventData);
14519 } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
14520 setLastTouch.call(this, eventData);
14521 }
14522}
14523
14524function isSyntheticEvent(eventData) {
14525 var x = eventData.srcEvent.clientX;
14526 var y = eventData.srcEvent.clientY;
14527
14528 for (var i = 0; i < this.lastTouches.length; i++) {
14529 var t = this.lastTouches[i];
14530 var dx = Math.abs(x - t.x);
14531 var dy = Math.abs(y - t.y);
14532
14533 if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {
14534 return true;
14535 }
14536 }
14537
14538 return false;
14539}
14540
14541var TouchMouseInput =
14542/*#__PURE__*/
14543function () {
14544 var TouchMouseInput =
14545 /*#__PURE__*/
14546 function (_Input) {
14547 _inheritsLoose(TouchMouseInput, _Input);
14548
14549 function TouchMouseInput(_manager, callback) {
14550 var _this;
14551
14552 _this = _Input.call(this, _manager, callback) || this;
14553
14554 _this.handler = function (manager, inputEvent, inputData) {
14555 var isTouch = inputData.pointerType === INPUT_TYPE_TOUCH;
14556 var isMouse = inputData.pointerType === INPUT_TYPE_MOUSE;
14557
14558 if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {
14559 return;
14560 } // when we're in a touch event, record touches to de-dupe synthetic mouse event
14561
14562
14563 if (isTouch) {
14564 recordTouches.call(_assertThisInitialized(_assertThisInitialized(_this)), inputEvent, inputData);
14565 } else if (isMouse && isSyntheticEvent.call(_assertThisInitialized(_assertThisInitialized(_this)), inputData)) {
14566 return;
14567 }
14568
14569 _this.callback(manager, inputEvent, inputData);
14570 };
14571
14572 _this.touch = new TouchInput(_this.manager, _this.handler);
14573 _this.mouse = new MouseInput(_this.manager, _this.handler);
14574 _this.primaryTouch = null;
14575 _this.lastTouches = [];
14576 return _this;
14577 }
14578 /**
14579 * @private
14580 * handle mouse and touch events
14581 * @param {Hammer} manager
14582 * @param {String} inputEvent
14583 * @param {Object} inputData
14584 */
14585
14586
14587 var _proto = TouchMouseInput.prototype;
14588 /**
14589 * @private
14590 * remove the event listeners
14591 */
14592
14593 _proto.destroy = function destroy() {
14594 this.touch.destroy();
14595 this.mouse.destroy();
14596 };
14597
14598 return TouchMouseInput;
14599 }(Input);
14600
14601 return TouchMouseInput;
14602}();
14603/**
14604 * @private
14605 * create new input type manager
14606 * called by the Manager constructor
14607 * @param {Hammer} manager
14608 * @returns {Input}
14609 */
14610
14611
14612function createInputInstance(manager) {
14613 var Type; // let inputClass = manager.options.inputClass;
14614
14615 var inputClass = manager.options.inputClass;
14616
14617 if (inputClass) {
14618 Type = inputClass;
14619 } else if (SUPPORT_POINTER_EVENTS) {
14620 Type = PointerEventInput;
14621 } else if (SUPPORT_ONLY_TOUCH) {
14622 Type = TouchInput;
14623 } else if (!SUPPORT_TOUCH) {
14624 Type = MouseInput;
14625 } else {
14626 Type = TouchMouseInput;
14627 }
14628
14629 return new Type(manager, inputHandler);
14630}
14631/**
14632 * @private
14633 * if the argument is an array, we want to execute the fn on each entry
14634 * if it aint an array we don't want to do a thing.
14635 * this is used by all the methods that accept a single and array argument.
14636 * @param {*|Array} arg
14637 * @param {String} fn
14638 * @param {Object} [context]
14639 * @returns {Boolean}
14640 */
14641
14642
14643function invokeArrayArg(arg, fn, context) {
14644 if (Array.isArray(arg)) {
14645 each(arg, context[fn], context);
14646 return true;
14647 }
14648
14649 return false;
14650}
14651
14652var STATE_POSSIBLE = 1;
14653var STATE_BEGAN = 2;
14654var STATE_CHANGED = 4;
14655var STATE_ENDED = 8;
14656var STATE_RECOGNIZED = STATE_ENDED;
14657var STATE_CANCELLED = 16;
14658var STATE_FAILED = 32;
14659/**
14660 * @private
14661 * get a unique id
14662 * @returns {number} uniqueId
14663 */
14664
14665var _uniqueId = 1;
14666
14667function uniqueId() {
14668 return _uniqueId++;
14669}
14670/**
14671 * @private
14672 * get a recognizer by name if it is bound to a manager
14673 * @param {Recognizer|String} otherRecognizer
14674 * @param {Recognizer} recognizer
14675 * @returns {Recognizer}
14676 */
14677
14678
14679function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
14680 var manager = recognizer.manager;
14681
14682 if (manager) {
14683 return manager.get(otherRecognizer);
14684 }
14685
14686 return otherRecognizer;
14687}
14688/**
14689 * @private
14690 * get a usable string, used as event postfix
14691 * @param {constant} state
14692 * @returns {String} state
14693 */
14694
14695
14696function stateStr(state) {
14697 if (state & STATE_CANCELLED) {
14698 return 'cancel';
14699 } else if (state & STATE_ENDED) {
14700 return 'end';
14701 } else if (state & STATE_CHANGED) {
14702 return 'move';
14703 } else if (state & STATE_BEGAN) {
14704 return 'start';
14705 }
14706
14707 return '';
14708}
14709/**
14710 * @private
14711 * Recognizer flow explained; *
14712 * All recognizers have the initial state of POSSIBLE when a input session starts.
14713 * The definition of a input session is from the first input until the last input, with all it's movement in it. *
14714 * Example session for mouse-input: mousedown -> mousemove -> mouseup
14715 *
14716 * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
14717 * which determines with state it should be.
14718 *
14719 * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
14720 * POSSIBLE to give it another change on the next cycle.
14721 *
14722 * Possible
14723 * |
14724 * +-----+---------------+
14725 * | |
14726 * +-----+-----+ |
14727 * | | |
14728 * Failed Cancelled |
14729 * +-------+------+
14730 * | |
14731 * Recognized Began
14732 * |
14733 * Changed
14734 * |
14735 * Ended/Recognized
14736 */
14737
14738/**
14739 * @private
14740 * Recognizer
14741 * Every recognizer needs to extend from this class.
14742 * @constructor
14743 * @param {Object} options
14744 */
14745
14746
14747var Recognizer =
14748/*#__PURE__*/
14749function () {
14750 function Recognizer(options) {
14751 if (options === void 0) {
14752 options = {};
14753 }
14754
14755 this.options = _extends({
14756 enable: true
14757 }, options);
14758 this.id = uniqueId();
14759 this.manager = null; // default is enable true
14760
14761 this.state = STATE_POSSIBLE;
14762 this.simultaneous = {};
14763 this.requireFail = [];
14764 }
14765 /**
14766 * @private
14767 * set options
14768 * @param {Object} options
14769 * @return {Recognizer}
14770 */
14771
14772
14773 var _proto = Recognizer.prototype;
14774
14775 _proto.set = function set(options) {
14776 assign$1(this.options, options); // also update the touchAction, in case something changed about the directions/enabled state
14777
14778 this.manager && this.manager.touchAction.update();
14779 return this;
14780 };
14781 /**
14782 * @private
14783 * recognize simultaneous with an other recognizer.
14784 * @param {Recognizer} otherRecognizer
14785 * @returns {Recognizer} this
14786 */
14787
14788
14789 _proto.recognizeWith = function recognizeWith(otherRecognizer) {
14790 if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
14791 return this;
14792 }
14793
14794 var simultaneous = this.simultaneous;
14795 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
14796
14797 if (!simultaneous[otherRecognizer.id]) {
14798 simultaneous[otherRecognizer.id] = otherRecognizer;
14799 otherRecognizer.recognizeWith(this);
14800 }
14801
14802 return this;
14803 };
14804 /**
14805 * @private
14806 * drop the simultaneous link. it doesnt remove the link on the other recognizer.
14807 * @param {Recognizer} otherRecognizer
14808 * @returns {Recognizer} this
14809 */
14810
14811
14812 _proto.dropRecognizeWith = function dropRecognizeWith(otherRecognizer) {
14813 if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
14814 return this;
14815 }
14816
14817 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
14818 delete this.simultaneous[otherRecognizer.id];
14819 return this;
14820 };
14821 /**
14822 * @private
14823 * recognizer can only run when an other is failing
14824 * @param {Recognizer} otherRecognizer
14825 * @returns {Recognizer} this
14826 */
14827
14828
14829 _proto.requireFailure = function requireFailure(otherRecognizer) {
14830 if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
14831 return this;
14832 }
14833
14834 var requireFail = this.requireFail;
14835 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
14836
14837 if (inArray(requireFail, otherRecognizer) === -1) {
14838 requireFail.push(otherRecognizer);
14839 otherRecognizer.requireFailure(this);
14840 }
14841
14842 return this;
14843 };
14844 /**
14845 * @private
14846 * drop the requireFailure link. it does not remove the link on the other recognizer.
14847 * @param {Recognizer} otherRecognizer
14848 * @returns {Recognizer} this
14849 */
14850
14851
14852 _proto.dropRequireFailure = function dropRequireFailure(otherRecognizer) {
14853 if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
14854 return this;
14855 }
14856
14857 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
14858 var index = inArray(this.requireFail, otherRecognizer);
14859
14860 if (index > -1) {
14861 this.requireFail.splice(index, 1);
14862 }
14863
14864 return this;
14865 };
14866 /**
14867 * @private
14868 * has require failures boolean
14869 * @returns {boolean}
14870 */
14871
14872
14873 _proto.hasRequireFailures = function hasRequireFailures() {
14874 return this.requireFail.length > 0;
14875 };
14876 /**
14877 * @private
14878 * if the recognizer can recognize simultaneous with an other recognizer
14879 * @param {Recognizer} otherRecognizer
14880 * @returns {Boolean}
14881 */
14882
14883
14884 _proto.canRecognizeWith = function canRecognizeWith(otherRecognizer) {
14885 return !!this.simultaneous[otherRecognizer.id];
14886 };
14887 /**
14888 * @private
14889 * You should use `tryEmit` instead of `emit` directly to check
14890 * that all the needed recognizers has failed before emitting.
14891 * @param {Object} input
14892 */
14893
14894
14895 _proto.emit = function emit(input) {
14896 var self = this;
14897 var state = this.state;
14898
14899 function emit(event) {
14900 self.manager.emit(event, input);
14901 } // 'panstart' and 'panmove'
14902
14903
14904 if (state < STATE_ENDED) {
14905 emit(self.options.event + stateStr(state));
14906 }
14907
14908 emit(self.options.event); // simple 'eventName' events
14909
14910 if (input.additionalEvent) {
14911 // additional event(panleft, panright, pinchin, pinchout...)
14912 emit(input.additionalEvent);
14913 } // panend and pancancel
14914
14915
14916 if (state >= STATE_ENDED) {
14917 emit(self.options.event + stateStr(state));
14918 }
14919 };
14920 /**
14921 * @private
14922 * Check that all the require failure recognizers has failed,
14923 * if true, it emits a gesture event,
14924 * otherwise, setup the state to FAILED.
14925 * @param {Object} input
14926 */
14927
14928
14929 _proto.tryEmit = function tryEmit(input) {
14930 if (this.canEmit()) {
14931 return this.emit(input);
14932 } // it's failing anyway
14933
14934
14935 this.state = STATE_FAILED;
14936 };
14937 /**
14938 * @private
14939 * can we emit?
14940 * @returns {boolean}
14941 */
14942
14943
14944 _proto.canEmit = function canEmit() {
14945 var i = 0;
14946
14947 while (i < this.requireFail.length) {
14948 if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
14949 return false;
14950 }
14951
14952 i++;
14953 }
14954
14955 return true;
14956 };
14957 /**
14958 * @private
14959 * update the recognizer
14960 * @param {Object} inputData
14961 */
14962
14963
14964 _proto.recognize = function recognize(inputData) {
14965 // make a new copy of the inputData
14966 // so we can change the inputData without messing up the other recognizers
14967 var inputDataClone = assign$1({}, inputData); // is is enabled and allow recognizing?
14968
14969 if (!boolOrFn(this.options.enable, [this, inputDataClone])) {
14970 this.reset();
14971 this.state = STATE_FAILED;
14972 return;
14973 } // reset when we've reached the end
14974
14975
14976 if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {
14977 this.state = STATE_POSSIBLE;
14978 }
14979
14980 this.state = this.process(inputDataClone); // the recognizer has recognized a gesture
14981 // so trigger an event
14982
14983 if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {
14984 this.tryEmit(inputDataClone);
14985 }
14986 };
14987 /**
14988 * @private
14989 * return the state of the recognizer
14990 * the actual recognizing happens in this method
14991 * @virtual
14992 * @param {Object} inputData
14993 * @returns {constant} STATE
14994 */
14995
14996 /* jshint ignore:start */
14997
14998
14999 _proto.process = function process(inputData) {};
15000 /* jshint ignore:end */
15001
15002 /**
15003 * @private
15004 * return the preferred touch-action
15005 * @virtual
15006 * @returns {Array}
15007 */
15008
15009
15010 _proto.getTouchAction = function getTouchAction() {};
15011 /**
15012 * @private
15013 * called when the gesture isn't allowed to recognize
15014 * like when another is being recognized or it is disabled
15015 * @virtual
15016 */
15017
15018
15019 _proto.reset = function reset() {};
15020
15021 return Recognizer;
15022}();
15023
15024var defaults = {
15025 /**
15026 * @private
15027 * set if DOM events are being triggered.
15028 * But this is slower and unused by simple implementations, so disabled by default.
15029 * @type {Boolean}
15030 * @default false
15031 */
15032 domEvents: false,
15033
15034 /**
15035 * @private
15036 * The value for the touchAction property/fallback.
15037 * When set to `compute` it will magically set the correct value based on the added recognizers.
15038 * @type {String}
15039 * @default compute
15040 */
15041 touchAction: TOUCH_ACTION_COMPUTE,
15042
15043 /**
15044 * @private
15045 * @type {Boolean}
15046 * @default true
15047 */
15048 enable: true,
15049
15050 /**
15051 * @private
15052 * EXPERIMENTAL FEATURE -- can be removed/changed
15053 * Change the parent input target element.
15054 * If Null, then it is being set the to main element.
15055 * @type {Null|EventTarget}
15056 * @default null
15057 */
15058 inputTarget: null,
15059
15060 /**
15061 * @private
15062 * force an input class
15063 * @type {Null|Function}
15064 * @default null
15065 */
15066 inputClass: null,
15067
15068 /**
15069 * @private
15070 * Default recognizer setup when calling `Hammer()`
15071 * When creating a new Manager these will be skipped.
15072 * @type {Array}
15073 */
15074 preset: [],
15075
15076 /**
15077 * @private
15078 * Some CSS properties can be used to improve the working of Hammer.
15079 * Add them to this method and they will be set when creating a new Manager.
15080 * @namespace
15081 */
15082 cssProps: {
15083 /**
15084 * @private
15085 * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
15086 * @type {String}
15087 * @default 'none'
15088 */
15089 userSelect: "none",
15090
15091 /**
15092 * @private
15093 * Disable the Windows Phone grippers when pressing an element.
15094 * @type {String}
15095 * @default 'none'
15096 */
15097 touchSelect: "none",
15098
15099 /**
15100 * @private
15101 * Disables the default callout shown when you touch and hold a touch target.
15102 * On iOS, when you touch and hold a touch target such as a link, Safari displays
15103 * a callout containing information about the link. This property allows you to disable that callout.
15104 * @type {String}
15105 * @default 'none'
15106 */
15107 touchCallout: "none",
15108
15109 /**
15110 * @private
15111 * Specifies whether zooming is enabled. Used by IE10>
15112 * @type {String}
15113 * @default 'none'
15114 */
15115 contentZooming: "none",
15116
15117 /**
15118 * @private
15119 * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
15120 * @type {String}
15121 * @default 'none'
15122 */
15123 userDrag: "none",
15124
15125 /**
15126 * @private
15127 * Overrides the highlight color shown when the user taps a link or a JavaScript
15128 * clickable element in iOS. This property obeys the alpha value, if specified.
15129 * @type {String}
15130 * @default 'rgba(0,0,0,0)'
15131 */
15132 tapHighlightColor: "rgba(0,0,0,0)"
15133 }
15134};
15135var STOP = 1;
15136var FORCED_STOP = 2;
15137/**
15138 * @private
15139 * add/remove the css properties as defined in manager.options.cssProps
15140 * @param {Manager} manager
15141 * @param {Boolean} add
15142 */
15143
15144function toggleCssProps(manager, add) {
15145 var element = manager.element;
15146
15147 if (!element.style) {
15148 return;
15149 }
15150
15151 var prop;
15152 each(manager.options.cssProps, function (value, name) {
15153 prop = prefixed(element.style, name);
15154
15155 if (add) {
15156 manager.oldCssProps[prop] = element.style[prop];
15157 element.style[prop] = value;
15158 } else {
15159 element.style[prop] = manager.oldCssProps[prop] || "";
15160 }
15161 });
15162
15163 if (!add) {
15164 manager.oldCssProps = {};
15165 }
15166}
15167/**
15168 * @private
15169 * trigger dom event
15170 * @param {String} event
15171 * @param {Object} data
15172 */
15173
15174
15175function triggerDomEvent(event, data) {
15176 var gestureEvent = document.createEvent("Event");
15177 gestureEvent.initEvent(event, true, true);
15178 gestureEvent.gesture = data;
15179 data.target.dispatchEvent(gestureEvent);
15180}
15181/**
15182* @private
15183 * Manager
15184 * @param {HTMLElement} element
15185 * @param {Object} [options]
15186 * @constructor
15187 */
15188
15189
15190var Manager =
15191/*#__PURE__*/
15192function () {
15193 function Manager(element, options) {
15194 var _this = this;
15195
15196 this.options = assign$1({}, defaults, options || {});
15197 this.options.inputTarget = this.options.inputTarget || element;
15198 this.handlers = {};
15199 this.session = {};
15200 this.recognizers = [];
15201 this.oldCssProps = {};
15202 this.element = element;
15203 this.input = createInputInstance(this);
15204 this.touchAction = new TouchAction(this, this.options.touchAction);
15205 toggleCssProps(this, true);
15206 each(this.options.recognizers, function (item) {
15207 var recognizer = _this.add(new item[0](item[1]));
15208
15209 item[2] && recognizer.recognizeWith(item[2]);
15210 item[3] && recognizer.requireFailure(item[3]);
15211 }, this);
15212 }
15213 /**
15214 * @private
15215 * set options
15216 * @param {Object} options
15217 * @returns {Manager}
15218 */
15219
15220
15221 var _proto = Manager.prototype;
15222
15223 _proto.set = function set(options) {
15224 assign$1(this.options, options); // Options that need a little more setup
15225
15226 if (options.touchAction) {
15227 this.touchAction.update();
15228 }
15229
15230 if (options.inputTarget) {
15231 // Clean up existing event listeners and reinitialize
15232 this.input.destroy();
15233 this.input.target = options.inputTarget;
15234 this.input.init();
15235 }
15236
15237 return this;
15238 };
15239 /**
15240 * @private
15241 * stop recognizing for this session.
15242 * This session will be discarded, when a new [input]start event is fired.
15243 * When forced, the recognizer cycle is stopped immediately.
15244 * @param {Boolean} [force]
15245 */
15246
15247
15248 _proto.stop = function stop(force) {
15249 this.session.stopped = force ? FORCED_STOP : STOP;
15250 };
15251 /**
15252 * @private
15253 * run the recognizers!
15254 * called by the inputHandler function on every movement of the pointers (touches)
15255 * it walks through all the recognizers and tries to detect the gesture that is being made
15256 * @param {Object} inputData
15257 */
15258
15259
15260 _proto.recognize = function recognize(inputData) {
15261 var session = this.session;
15262
15263 if (session.stopped) {
15264 return;
15265 } // run the touch-action polyfill
15266
15267
15268 this.touchAction.preventDefaults(inputData);
15269 var recognizer;
15270 var recognizers = this.recognizers; // this holds the recognizer that is being recognized.
15271 // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
15272 // if no recognizer is detecting a thing, it is set to `null`
15273
15274 var curRecognizer = session.curRecognizer; // reset when the last recognizer is recognized
15275 // or when we're in a new session
15276
15277 if (!curRecognizer || curRecognizer && curRecognizer.state & STATE_RECOGNIZED) {
15278 session.curRecognizer = null;
15279 curRecognizer = null;
15280 }
15281
15282 var i = 0;
15283
15284 while (i < recognizers.length) {
15285 recognizer = recognizers[i]; // find out if we are allowed try to recognize the input for this one.
15286 // 1. allow if the session is NOT forced stopped (see the .stop() method)
15287 // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
15288 // that is being recognized.
15289 // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
15290 // this can be setup with the `recognizeWith()` method on the recognizer.
15291
15292 if (session.stopped !== FORCED_STOP && ( // 1
15293 !curRecognizer || recognizer === curRecognizer || // 2
15294 recognizer.canRecognizeWith(curRecognizer))) {
15295 // 3
15296 recognizer.recognize(inputData);
15297 } else {
15298 recognizer.reset();
15299 } // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
15300 // current active recognizer. but only if we don't already have an active recognizer
15301
15302
15303 if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
15304 session.curRecognizer = recognizer;
15305 curRecognizer = recognizer;
15306 }
15307
15308 i++;
15309 }
15310 };
15311 /**
15312 * @private
15313 * get a recognizer by its event name.
15314 * @param {Recognizer|String} recognizer
15315 * @returns {Recognizer|Null}
15316 */
15317
15318
15319 _proto.get = function get(recognizer) {
15320 if (recognizer instanceof Recognizer) {
15321 return recognizer;
15322 }
15323
15324 var recognizers = this.recognizers;
15325
15326 for (var i = 0; i < recognizers.length; i++) {
15327 if (recognizers[i].options.event === recognizer) {
15328 return recognizers[i];
15329 }
15330 }
15331
15332 return null;
15333 };
15334 /**
15335 * @private add a recognizer to the manager
15336 * existing recognizers with the same event name will be removed
15337 * @param {Recognizer} recognizer
15338 * @returns {Recognizer|Manager}
15339 */
15340
15341
15342 _proto.add = function add(recognizer) {
15343 if (invokeArrayArg(recognizer, "add", this)) {
15344 return this;
15345 } // remove existing
15346
15347
15348 var existing = this.get(recognizer.options.event);
15349
15350 if (existing) {
15351 this.remove(existing);
15352 }
15353
15354 this.recognizers.push(recognizer);
15355 recognizer.manager = this;
15356 this.touchAction.update();
15357 return recognizer;
15358 };
15359 /**
15360 * @private
15361 * remove a recognizer by name or instance
15362 * @param {Recognizer|String} recognizer
15363 * @returns {Manager}
15364 */
15365
15366
15367 _proto.remove = function remove(recognizer) {
15368 if (invokeArrayArg(recognizer, "remove", this)) {
15369 return this;
15370 }
15371
15372 var targetRecognizer = this.get(recognizer); // let's make sure this recognizer exists
15373
15374 if (recognizer) {
15375 var recognizers = this.recognizers;
15376 var index = inArray(recognizers, targetRecognizer);
15377
15378 if (index !== -1) {
15379 recognizers.splice(index, 1);
15380 this.touchAction.update();
15381 }
15382 }
15383
15384 return this;
15385 };
15386 /**
15387 * @private
15388 * bind event
15389 * @param {String} events
15390 * @param {Function} handler
15391 * @returns {EventEmitter} this
15392 */
15393
15394
15395 _proto.on = function on(events, handler) {
15396 if (events === undefined || handler === undefined) {
15397 return this;
15398 }
15399
15400 var handlers = this.handlers;
15401 each(splitStr(events), function (event) {
15402 handlers[event] = handlers[event] || [];
15403 handlers[event].push(handler);
15404 });
15405 return this;
15406 };
15407 /**
15408 * @private unbind event, leave emit blank to remove all handlers
15409 * @param {String} events
15410 * @param {Function} [handler]
15411 * @returns {EventEmitter} this
15412 */
15413
15414
15415 _proto.off = function off(events, handler) {
15416 if (events === undefined) {
15417 return this;
15418 }
15419
15420 var handlers = this.handlers;
15421 each(splitStr(events), function (event) {
15422 if (!handler) {
15423 delete handlers[event];
15424 } else {
15425 handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);
15426 }
15427 });
15428 return this;
15429 };
15430 /**
15431 * @private emit event to the listeners
15432 * @param {String} event
15433 * @param {Object} data
15434 */
15435
15436
15437 _proto.emit = function emit(event, data) {
15438 // we also want to trigger dom events
15439 if (this.options.domEvents) {
15440 triggerDomEvent(event, data);
15441 } // no handlers, so skip it all
15442
15443
15444 var handlers = this.handlers[event] && this.handlers[event].slice();
15445
15446 if (!handlers || !handlers.length) {
15447 return;
15448 }
15449
15450 data.type = event;
15451
15452 data.preventDefault = function () {
15453 data.srcEvent.preventDefault();
15454 };
15455
15456 var i = 0;
15457
15458 while (i < handlers.length) {
15459 handlers[i](data);
15460 i++;
15461 }
15462 };
15463 /**
15464 * @private
15465 * destroy the manager and unbinds all events
15466 * it doesn't unbind dom events, that is the user own responsibility
15467 */
15468
15469
15470 _proto.destroy = function destroy() {
15471 this.element && toggleCssProps(this, false);
15472 this.handlers = {};
15473 this.session = {};
15474 this.input.destroy();
15475 this.element = null;
15476 };
15477
15478 return Manager;
15479}();
15480
15481var SINGLE_TOUCH_INPUT_MAP = {
15482 touchstart: INPUT_START,
15483 touchmove: INPUT_MOVE,
15484 touchend: INPUT_END,
15485 touchcancel: INPUT_CANCEL
15486};
15487var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';
15488var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';
15489/**
15490 * @private
15491 * Touch events input
15492 * @constructor
15493 * @extends Input
15494 */
15495
15496var SingleTouchInput =
15497/*#__PURE__*/
15498function (_Input) {
15499 _inheritsLoose(SingleTouchInput, _Input);
15500
15501 function SingleTouchInput() {
15502 var _this;
15503
15504 var proto = SingleTouchInput.prototype;
15505 proto.evTarget = SINGLE_TOUCH_TARGET_EVENTS;
15506 proto.evWin = SINGLE_TOUCH_WINDOW_EVENTS;
15507 _this = _Input.apply(this, arguments) || this;
15508 _this.started = false;
15509 return _this;
15510 }
15511
15512 var _proto = SingleTouchInput.prototype;
15513
15514 _proto.handler = function handler(ev) {
15515 var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; // should we handle the touch events?
15516
15517 if (type === INPUT_START) {
15518 this.started = true;
15519 }
15520
15521 if (!this.started) {
15522 return;
15523 }
15524
15525 var touches = normalizeSingleTouches.call(this, ev, type); // when done, reset the started state
15526
15527 if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {
15528 this.started = false;
15529 }
15530
15531 this.callback(this.manager, type, {
15532 pointers: touches[0],
15533 changedPointers: touches[1],
15534 pointerType: INPUT_TYPE_TOUCH,
15535 srcEvent: ev
15536 });
15537 };
15538
15539 return SingleTouchInput;
15540}(Input);
15541
15542function normalizeSingleTouches(ev, type) {
15543 var all = toArray$1(ev.touches);
15544 var changed = toArray$1(ev.changedTouches);
15545
15546 if (type & (INPUT_END | INPUT_CANCEL)) {
15547 all = uniqueArray(all.concat(changed), 'identifier', true);
15548 }
15549
15550 return [all, changed];
15551}
15552/**
15553 * @private
15554 * This recognizer is just used as a base for the simple attribute recognizers.
15555 * @constructor
15556 * @extends Recognizer
15557 */
15558
15559
15560var AttrRecognizer =
15561/*#__PURE__*/
15562function (_Recognizer) {
15563 _inheritsLoose(AttrRecognizer, _Recognizer);
15564
15565 function AttrRecognizer(options) {
15566 if (options === void 0) {
15567 options = {};
15568 }
15569
15570 return _Recognizer.call(this, _extends({
15571 pointers: 1
15572 }, options)) || this;
15573 }
15574 /**
15575 * @private
15576 * Used to check if it the recognizer receives valid input, like input.distance > 10.
15577 * @memberof AttrRecognizer
15578 * @param {Object} input
15579 * @returns {Boolean} recognized
15580 */
15581
15582
15583 var _proto = AttrRecognizer.prototype;
15584
15585 _proto.attrTest = function attrTest(input) {
15586 var optionPointers = this.options.pointers;
15587 return optionPointers === 0 || input.pointers.length === optionPointers;
15588 };
15589 /**
15590 * @private
15591 * Process the input and return the state for the recognizer
15592 * @memberof AttrRecognizer
15593 * @param {Object} input
15594 * @returns {*} State
15595 */
15596
15597
15598 _proto.process = function process(input) {
15599 var state = this.state;
15600 var eventType = input.eventType;
15601 var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);
15602 var isValid = this.attrTest(input); // on cancel input and we've recognized before, return STATE_CANCELLED
15603
15604 if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {
15605 return state | STATE_CANCELLED;
15606 } else if (isRecognized || isValid) {
15607 if (eventType & INPUT_END) {
15608 return state | STATE_ENDED;
15609 } else if (!(state & STATE_BEGAN)) {
15610 return STATE_BEGAN;
15611 }
15612
15613 return state | STATE_CHANGED;
15614 }
15615
15616 return STATE_FAILED;
15617 };
15618
15619 return AttrRecognizer;
15620}(Recognizer);
15621/**
15622 * @private
15623 * A tap is recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur
15624 * between the given interval and position. The delay option can be used to recognize multi-taps without firing
15625 * a single tap.
15626 *
15627 * The eventData from the emitted event contains the property `tapCount`, which contains the amount of
15628 * multi-taps being recognized.
15629 * @constructor
15630 * @extends Recognizer
15631 */
15632
15633
15634var TapRecognizer =
15635/*#__PURE__*/
15636function (_Recognizer) {
15637 _inheritsLoose(TapRecognizer, _Recognizer);
15638
15639 function TapRecognizer(options) {
15640 var _this;
15641
15642 if (options === void 0) {
15643 options = {};
15644 }
15645
15646 _this = _Recognizer.call(this, _extends({
15647 event: 'tap',
15648 pointers: 1,
15649 taps: 1,
15650 interval: 300,
15651 // max time between the multi-tap taps
15652 time: 250,
15653 // max time of the pointer to be down (like finger on the screen)
15654 threshold: 9,
15655 // a minimal movement is ok, but keep it low
15656 posThreshold: 10
15657 }, options)) || this; // previous time and center,
15658 // used for tap counting
15659
15660 _this.pTime = false;
15661 _this.pCenter = false;
15662 _this._timer = null;
15663 _this._input = null;
15664 _this.count = 0;
15665 return _this;
15666 }
15667
15668 var _proto = TapRecognizer.prototype;
15669
15670 _proto.getTouchAction = function getTouchAction() {
15671 return [TOUCH_ACTION_MANIPULATION];
15672 };
15673
15674 _proto.process = function process(input) {
15675 var _this2 = this;
15676
15677 var options = this.options;
15678 var validPointers = input.pointers.length === options.pointers;
15679 var validMovement = input.distance < options.threshold;
15680 var validTouchTime = input.deltaTime < options.time;
15681 this.reset();
15682
15683 if (input.eventType & INPUT_START && this.count === 0) {
15684 return this.failTimeout();
15685 } // we only allow little movement
15686 // and we've reached an end event, so a tap is possible
15687
15688
15689 if (validMovement && validTouchTime && validPointers) {
15690 if (input.eventType !== INPUT_END) {
15691 return this.failTimeout();
15692 }
15693
15694 var validInterval = this.pTime ? input.timeStamp - this.pTime < options.interval : true;
15695 var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;
15696 this.pTime = input.timeStamp;
15697 this.pCenter = input.center;
15698
15699 if (!validMultiTap || !validInterval) {
15700 this.count = 1;
15701 } else {
15702 this.count += 1;
15703 }
15704
15705 this._input = input; // if tap count matches we have recognized it,
15706 // else it has began recognizing...
15707
15708 var tapCount = this.count % options.taps;
15709
15710 if (tapCount === 0) {
15711 // no failing requirements, immediately trigger the tap event
15712 // or wait as long as the multitap interval to trigger
15713 if (!this.hasRequireFailures()) {
15714 return STATE_RECOGNIZED;
15715 } else {
15716 this._timer = setTimeout(function () {
15717 _this2.state = STATE_RECOGNIZED;
15718
15719 _this2.tryEmit();
15720 }, options.interval);
15721 return STATE_BEGAN;
15722 }
15723 }
15724 }
15725
15726 return STATE_FAILED;
15727 };
15728
15729 _proto.failTimeout = function failTimeout() {
15730 var _this3 = this;
15731
15732 this._timer = setTimeout(function () {
15733 _this3.state = STATE_FAILED;
15734 }, this.options.interval);
15735 return STATE_FAILED;
15736 };
15737
15738 _proto.reset = function reset() {
15739 clearTimeout(this._timer);
15740 };
15741
15742 _proto.emit = function emit() {
15743 if (this.state === STATE_RECOGNIZED) {
15744 this._input.tapCount = this.count;
15745 this.manager.emit(this.options.event, this._input);
15746 }
15747 };
15748
15749 return TapRecognizer;
15750}(Recognizer);
15751/**
15752 * @private
15753 * direction cons to string
15754 * @param {constant} direction
15755 * @returns {String}
15756 */
15757
15758
15759function directionStr(direction) {
15760 if (direction === DIRECTION_DOWN) {
15761 return 'down';
15762 } else if (direction === DIRECTION_UP) {
15763 return 'up';
15764 } else if (direction === DIRECTION_LEFT) {
15765 return 'left';
15766 } else if (direction === DIRECTION_RIGHT) {
15767 return 'right';
15768 }
15769
15770 return '';
15771}
15772/**
15773 * @private
15774 * Pan
15775 * Recognized when the pointer is down and moved in the allowed direction.
15776 * @constructor
15777 * @extends AttrRecognizer
15778 */
15779
15780
15781var PanRecognizer =
15782/*#__PURE__*/
15783function (_AttrRecognizer) {
15784 _inheritsLoose(PanRecognizer, _AttrRecognizer);
15785
15786 function PanRecognizer(options) {
15787 var _this;
15788
15789 if (options === void 0) {
15790 options = {};
15791 }
15792
15793 _this = _AttrRecognizer.call(this, _extends({
15794 event: 'pan',
15795 threshold: 10,
15796 pointers: 1,
15797 direction: DIRECTION_ALL
15798 }, options)) || this;
15799 _this.pX = null;
15800 _this.pY = null;
15801 return _this;
15802 }
15803
15804 var _proto = PanRecognizer.prototype;
15805
15806 _proto.getTouchAction = function getTouchAction() {
15807 var direction = this.options.direction;
15808 var actions = [];
15809
15810 if (direction & DIRECTION_HORIZONTAL) {
15811 actions.push(TOUCH_ACTION_PAN_Y);
15812 }
15813
15814 if (direction & DIRECTION_VERTICAL) {
15815 actions.push(TOUCH_ACTION_PAN_X);
15816 }
15817
15818 return actions;
15819 };
15820
15821 _proto.directionTest = function directionTest(input) {
15822 var options = this.options;
15823 var hasMoved = true;
15824 var distance = input.distance;
15825 var direction = input.direction;
15826 var x = input.deltaX;
15827 var y = input.deltaY; // lock to axis?
15828
15829 if (!(direction & options.direction)) {
15830 if (options.direction & DIRECTION_HORIZONTAL) {
15831 direction = x === 0 ? DIRECTION_NONE : x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
15832 hasMoved = x !== this.pX;
15833 distance = Math.abs(input.deltaX);
15834 } else {
15835 direction = y === 0 ? DIRECTION_NONE : y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
15836 hasMoved = y !== this.pY;
15837 distance = Math.abs(input.deltaY);
15838 }
15839 }
15840
15841 input.direction = direction;
15842 return hasMoved && distance > options.threshold && direction & options.direction;
15843 };
15844
15845 _proto.attrTest = function attrTest(input) {
15846 return AttrRecognizer.prototype.attrTest.call(this, input) && ( // replace with a super call
15847 this.state & STATE_BEGAN || !(this.state & STATE_BEGAN) && this.directionTest(input));
15848 };
15849
15850 _proto.emit = function emit(input) {
15851 this.pX = input.deltaX;
15852 this.pY = input.deltaY;
15853 var direction = directionStr(input.direction);
15854
15855 if (direction) {
15856 input.additionalEvent = this.options.event + direction;
15857 }
15858
15859 _AttrRecognizer.prototype.emit.call(this, input);
15860 };
15861
15862 return PanRecognizer;
15863}(AttrRecognizer);
15864/**
15865 * @private
15866 * Swipe
15867 * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
15868 * @constructor
15869 * @extends AttrRecognizer
15870 */
15871
15872
15873var SwipeRecognizer =
15874/*#__PURE__*/
15875function (_AttrRecognizer) {
15876 _inheritsLoose(SwipeRecognizer, _AttrRecognizer);
15877
15878 function SwipeRecognizer(options) {
15879 if (options === void 0) {
15880 options = {};
15881 }
15882
15883 return _AttrRecognizer.call(this, _extends({
15884 event: 'swipe',
15885 threshold: 10,
15886 velocity: 0.3,
15887 direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,
15888 pointers: 1
15889 }, options)) || this;
15890 }
15891
15892 var _proto = SwipeRecognizer.prototype;
15893
15894 _proto.getTouchAction = function getTouchAction() {
15895 return PanRecognizer.prototype.getTouchAction.call(this);
15896 };
15897
15898 _proto.attrTest = function attrTest(input) {
15899 var direction = this.options.direction;
15900 var velocity;
15901
15902 if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {
15903 velocity = input.overallVelocity;
15904 } else if (direction & DIRECTION_HORIZONTAL) {
15905 velocity = input.overallVelocityX;
15906 } else if (direction & DIRECTION_VERTICAL) {
15907 velocity = input.overallVelocityY;
15908 }
15909
15910 return _AttrRecognizer.prototype.attrTest.call(this, input) && direction & input.offsetDirection && input.distance > this.options.threshold && input.maxPointers === this.options.pointers && abs$1(velocity) > this.options.velocity && input.eventType & INPUT_END;
15911 };
15912
15913 _proto.emit = function emit(input) {
15914 var direction = directionStr(input.offsetDirection);
15915
15916 if (direction) {
15917 this.manager.emit(this.options.event + direction, input);
15918 }
15919
15920 this.manager.emit(this.options.event, input);
15921 };
15922
15923 return SwipeRecognizer;
15924}(AttrRecognizer);
15925/**
15926 * @private
15927 * Pinch
15928 * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
15929 * @constructor
15930 * @extends AttrRecognizer
15931 */
15932
15933
15934var PinchRecognizer =
15935/*#__PURE__*/
15936function (_AttrRecognizer) {
15937 _inheritsLoose(PinchRecognizer, _AttrRecognizer);
15938
15939 function PinchRecognizer(options) {
15940 if (options === void 0) {
15941 options = {};
15942 }
15943
15944 return _AttrRecognizer.call(this, _extends({
15945 event: 'pinch',
15946 threshold: 0,
15947 pointers: 2
15948 }, options)) || this;
15949 }
15950
15951 var _proto = PinchRecognizer.prototype;
15952
15953 _proto.getTouchAction = function getTouchAction() {
15954 return [TOUCH_ACTION_NONE];
15955 };
15956
15957 _proto.attrTest = function attrTest(input) {
15958 return _AttrRecognizer.prototype.attrTest.call(this, input) && (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);
15959 };
15960
15961 _proto.emit = function emit(input) {
15962 if (input.scale !== 1) {
15963 var inOut = input.scale < 1 ? 'in' : 'out';
15964 input.additionalEvent = this.options.event + inOut;
15965 }
15966
15967 _AttrRecognizer.prototype.emit.call(this, input);
15968 };
15969
15970 return PinchRecognizer;
15971}(AttrRecognizer);
15972/**
15973 * @private
15974 * Rotate
15975 * Recognized when two or more pointer are moving in a circular motion.
15976 * @constructor
15977 * @extends AttrRecognizer
15978 */
15979
15980
15981var RotateRecognizer =
15982/*#__PURE__*/
15983function (_AttrRecognizer) {
15984 _inheritsLoose(RotateRecognizer, _AttrRecognizer);
15985
15986 function RotateRecognizer(options) {
15987 if (options === void 0) {
15988 options = {};
15989 }
15990
15991 return _AttrRecognizer.call(this, _extends({
15992 event: 'rotate',
15993 threshold: 0,
15994 pointers: 2
15995 }, options)) || this;
15996 }
15997
15998 var _proto = RotateRecognizer.prototype;
15999
16000 _proto.getTouchAction = function getTouchAction() {
16001 return [TOUCH_ACTION_NONE];
16002 };
16003
16004 _proto.attrTest = function attrTest(input) {
16005 return _AttrRecognizer.prototype.attrTest.call(this, input) && (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);
16006 };
16007
16008 return RotateRecognizer;
16009}(AttrRecognizer);
16010/**
16011 * @private
16012 * Press
16013 * Recognized when the pointer is down for x ms without any movement.
16014 * @constructor
16015 * @extends Recognizer
16016 */
16017
16018
16019var PressRecognizer =
16020/*#__PURE__*/
16021function (_Recognizer) {
16022 _inheritsLoose(PressRecognizer, _Recognizer);
16023
16024 function PressRecognizer(options) {
16025 var _this;
16026
16027 if (options === void 0) {
16028 options = {};
16029 }
16030
16031 _this = _Recognizer.call(this, _extends({
16032 event: 'press',
16033 pointers: 1,
16034 time: 251,
16035 // minimal time of the pointer to be pressed
16036 threshold: 9
16037 }, options)) || this;
16038 _this._timer = null;
16039 _this._input = null;
16040 return _this;
16041 }
16042
16043 var _proto = PressRecognizer.prototype;
16044
16045 _proto.getTouchAction = function getTouchAction() {
16046 return [TOUCH_ACTION_AUTO];
16047 };
16048
16049 _proto.process = function process(input) {
16050 var _this2 = this;
16051
16052 var options = this.options;
16053 var validPointers = input.pointers.length === options.pointers;
16054 var validMovement = input.distance < options.threshold;
16055 var validTime = input.deltaTime > options.time;
16056 this._input = input; // we only allow little movement
16057 // and we've reached an end event, so a tap is possible
16058
16059 if (!validMovement || !validPointers || input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime) {
16060 this.reset();
16061 } else if (input.eventType & INPUT_START) {
16062 this.reset();
16063 this._timer = setTimeout(function () {
16064 _this2.state = STATE_RECOGNIZED;
16065
16066 _this2.tryEmit();
16067 }, options.time);
16068 } else if (input.eventType & INPUT_END) {
16069 return STATE_RECOGNIZED;
16070 }
16071
16072 return STATE_FAILED;
16073 };
16074
16075 _proto.reset = function reset() {
16076 clearTimeout(this._timer);
16077 };
16078
16079 _proto.emit = function emit(input) {
16080 if (this.state !== STATE_RECOGNIZED) {
16081 return;
16082 }
16083
16084 if (input && input.eventType & INPUT_END) {
16085 this.manager.emit(this.options.event + "up", input);
16086 } else {
16087 this._input.timeStamp = now();
16088 this.manager.emit(this.options.event, this._input);
16089 }
16090 };
16091
16092 return PressRecognizer;
16093}(Recognizer);
16094/**
16095 * @private
16096 * wrap a method with a deprecation warning and stack trace
16097 * @param {Function} method
16098 * @param {String} name
16099 * @param {String} message
16100 * @returns {Function} A new function wrapping the supplied method.
16101 */
16102
16103
16104function deprecate(method, name, message) {
16105 var deprecationMessage = "DEPRECATED METHOD: " + name + "\n" + message + " AT \n";
16106 return function () {
16107 var e = new Error('get-stack-trace');
16108 var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '').replace(/^\s+at\s+/gm, '').replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';
16109 var log = window.console && (window.console.warn || window.console.log);
16110
16111 if (log) {
16112 log.call(window.console, deprecationMessage, stack);
16113 }
16114
16115 return method.apply(this, arguments);
16116 };
16117}
16118/**
16119 * @private
16120 * extend object.
16121 * means that properties in dest will be overwritten by the ones in src.
16122 * @param {Object} dest
16123 * @param {Object} src
16124 * @param {Boolean} [merge=false]
16125 * @returns {Object} dest
16126 */
16127
16128
16129var extend$1 = deprecate(function (dest, src, merge) {
16130 var keys = Object.keys(src);
16131 var i = 0;
16132
16133 while (i < keys.length) {
16134 if (!merge || merge && dest[keys[i]] === undefined) {
16135 dest[keys[i]] = src[keys[i]];
16136 }
16137
16138 i++;
16139 }
16140
16141 return dest;
16142}, 'extend', 'Use `assign`.');
16143/**
16144 * @private
16145 * merge the values from src in the dest.
16146 * means that properties that exist in dest will not be overwritten by src
16147 * @param {Object} dest
16148 * @param {Object} src
16149 * @returns {Object} dest
16150 */
16151
16152var merge$1 = deprecate(function (dest, src) {
16153 return extend$1(dest, src, true);
16154}, 'merge', 'Use `assign`.');
16155/**
16156 * @private
16157 * simple class inheritance
16158 * @param {Function} child
16159 * @param {Function} base
16160 * @param {Object} [properties]
16161 */
16162
16163function inherit(child, base, properties) {
16164 var baseP = base.prototype;
16165 var childP;
16166 childP = child.prototype = Object.create(baseP);
16167 childP.constructor = child;
16168 childP._super = baseP;
16169
16170 if (properties) {
16171 assign$1(childP, properties);
16172 }
16173}
16174/**
16175 * @private
16176 * simple function bind
16177 * @param {Function} fn
16178 * @param {Object} context
16179 * @returns {Function}
16180 */
16181
16182
16183function bindFn(fn, context) {
16184 return function boundFn() {
16185 return fn.apply(context, arguments);
16186 };
16187}
16188/**
16189 * @private
16190 * Simple way to create a manager with a default set of recognizers.
16191 * @param {HTMLElement} element
16192 * @param {Object} [options]
16193 * @constructor
16194 */
16195
16196
16197var Hammer =
16198/*#__PURE__*/
16199function () {
16200 var Hammer =
16201 /**
16202 * @private
16203 * @const {string}
16204 */
16205 function Hammer(element, options) {
16206 if (options === void 0) {
16207 options = {};
16208 }
16209
16210 return new Manager(element, _extends({
16211 recognizers: [// RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]
16212 [RotateRecognizer, {
16213 enable: false
16214 }], [PinchRecognizer, {
16215 enable: false
16216 }, ['rotate']], [SwipeRecognizer, {
16217 direction: DIRECTION_HORIZONTAL
16218 }], [PanRecognizer, {
16219 direction: DIRECTION_HORIZONTAL
16220 }, ['swipe']], [TapRecognizer], [TapRecognizer, {
16221 event: 'doubletap',
16222 taps: 2
16223 }, ['tap']], [PressRecognizer]]
16224 }, options));
16225 };
16226
16227 Hammer.VERSION = "2.0.15";
16228 Hammer.DIRECTION_ALL = DIRECTION_ALL;
16229 Hammer.DIRECTION_DOWN = DIRECTION_DOWN;
16230 Hammer.DIRECTION_LEFT = DIRECTION_LEFT;
16231 Hammer.DIRECTION_RIGHT = DIRECTION_RIGHT;
16232 Hammer.DIRECTION_UP = DIRECTION_UP;
16233 Hammer.DIRECTION_HORIZONTAL = DIRECTION_HORIZONTAL;
16234 Hammer.DIRECTION_VERTICAL = DIRECTION_VERTICAL;
16235 Hammer.DIRECTION_NONE = DIRECTION_NONE;
16236 Hammer.DIRECTION_DOWN = DIRECTION_DOWN;
16237 Hammer.INPUT_START = INPUT_START;
16238 Hammer.INPUT_MOVE = INPUT_MOVE;
16239 Hammer.INPUT_END = INPUT_END;
16240 Hammer.INPUT_CANCEL = INPUT_CANCEL;
16241 Hammer.STATE_POSSIBLE = STATE_POSSIBLE;
16242 Hammer.STATE_BEGAN = STATE_BEGAN;
16243 Hammer.STATE_CHANGED = STATE_CHANGED;
16244 Hammer.STATE_ENDED = STATE_ENDED;
16245 Hammer.STATE_RECOGNIZED = STATE_RECOGNIZED;
16246 Hammer.STATE_CANCELLED = STATE_CANCELLED;
16247 Hammer.STATE_FAILED = STATE_FAILED;
16248 Hammer.Manager = Manager;
16249 Hammer.Input = Input;
16250 Hammer.TouchAction = TouchAction;
16251 Hammer.TouchInput = TouchInput;
16252 Hammer.MouseInput = MouseInput;
16253 Hammer.PointerEventInput = PointerEventInput;
16254 Hammer.TouchMouseInput = TouchMouseInput;
16255 Hammer.SingleTouchInput = SingleTouchInput;
16256 Hammer.Recognizer = Recognizer;
16257 Hammer.AttrRecognizer = AttrRecognizer;
16258 Hammer.Tap = TapRecognizer;
16259 Hammer.Pan = PanRecognizer;
16260 Hammer.Swipe = SwipeRecognizer;
16261 Hammer.Pinch = PinchRecognizer;
16262 Hammer.Rotate = RotateRecognizer;
16263 Hammer.Press = PressRecognizer;
16264 Hammer.on = addEventListeners;
16265 Hammer.off = removeEventListeners;
16266 Hammer.each = each;
16267 Hammer.merge = merge$1;
16268 Hammer.extend = extend$1;
16269 Hammer.bindFn = bindFn;
16270 Hammer.assign = assign$1;
16271 Hammer.inherit = inherit;
16272 Hammer.bindFn = bindFn;
16273 Hammer.prefixed = prefixed;
16274 Hammer.toArray = toArray$1;
16275 Hammer.inArray = inArray;
16276 Hammer.uniqueArray = uniqueArray;
16277 Hammer.splitStr = splitStr;
16278 Hammer.boolOrFn = boolOrFn;
16279 Hammer.hasParent = hasParent$1;
16280 Hammer.addEventListeners = addEventListeners;
16281 Hammer.removeEventListeners = removeEventListeners;
16282 Hammer.defaults = defaults;
16283 return Hammer;
16284}();
16285
16286var hammer = createCommonjsModule(function (module) {
16287 /**
16288 * Setup a mock hammer.js object, for unit testing.
16289 *
16290 * Inspiration: https://github.com/uber/deck.gl/pull/658
16291 *
16292 * @returns {{on: noop, off: noop, destroy: noop, emit: noop, get: get}}
16293 */
16294 function hammerMock() {
16295 var noop = function noop() {};
16296
16297 return {
16298 on: noop,
16299 off: noop,
16300 destroy: noop,
16301 emit: noop,
16302 get: function get(m) {
16303 //eslint-disable-line no-unused-vars
16304 return {
16305 set: noop
16306 };
16307 }
16308 };
16309 }
16310
16311 if (typeof window !== 'undefined') {
16312 var Hammer$1 = window['Hammer'] || Hammer;
16313 module.exports = Hammer$1;
16314 } else {
16315 module.exports = function () {
16316 // hammer.js is only available in a browser, not in node.js. Replacing it with a mock object.
16317 return hammerMock();
16318 };
16319 }
16320});
16321
16322var hammer$1 = /*#__PURE__*/Object.freeze({
16323 __proto__: null,
16324 'default': hammer,
16325 __moduleExports: hammer
16326});
16327
16328getCjsExportFromNamespace(Activator);
16329
16330/**
16331 * Turn an element into an clickToUse element.
16332 * When not active, the element has a transparent overlay. When the overlay is
16333 * clicked, the mode is changed to active.
16334 * When active, the element is displayed with a blue border around it, and
16335 * the interactive contents of the element can be used. When clicked outside
16336 * the element, the elements mode is changed to inactive.
16337 * @param {Element} container
16338 * @constructor Activator
16339 */
16340
16341function Activator$1(container) {
16342 var _this = this;
16343
16344 this.active = false;
16345 this.dom = {
16346 container: container
16347 };
16348 this.dom.overlay = document.createElement('div');
16349 this.dom.overlay.className = 'vis-overlay';
16350 this.dom.container.appendChild(this.dom.overlay);
16351 this.hammer = hammer(this.dom.overlay);
16352 this.hammer.on('tap', this._onTapOverlay.bind(this)); // block all touch events (except tap)
16353
16354 var events = ['tap', 'doubletap', 'press', 'pinch', 'pan', 'panstart', 'panmove', 'panend'];
16355 events.forEach(function (event) {
16356 _this.hammer.on(event, function (event) {
16357 event.srcEvent.stopPropagation();
16358 });
16359 }); // attach a click event to the window, in order to deactivate when clicking outside the timeline
16360
16361 if (document && document.body) {
16362 this.onClick = function (event) {
16363 if (!_hasParent(event.target, container)) {
16364 _this.deactivate();
16365 }
16366 };
16367
16368 document.body.addEventListener('click', this.onClick);
16369 }
16370
16371 if (this.keycharm !== undefined) {
16372 this.keycharm.destroy();
16373 }
16374
16375 this.keycharm = keycharm(); // keycharm listener only bounded when active)
16376
16377 this.escListener = this.deactivate.bind(this);
16378} // turn into an event emitter
16379
16380
16381componentEmitter(Activator$1.prototype); // The currently active activator
16382
16383Activator$1.current = null;
16384/**
16385 * Destroy the activator. Cleans up all created DOM and event listeners
16386 */
16387
16388Activator$1.prototype.destroy = function () {
16389 this.deactivate(); // remove dom
16390
16391 this.dom.overlay.parentNode.removeChild(this.dom.overlay); // remove global event listener
16392
16393 if (this.onClick) {
16394 document.body.removeEventListener('click', this.onClick);
16395 } // remove keycharm
16396
16397
16398 if (this.keycharm !== undefined) {
16399 this.keycharm.destroy();
16400 }
16401
16402 this.keycharm = null; // cleanup hammer instances
16403
16404 this.hammer.destroy();
16405 this.hammer = null; // FIXME: cleaning up hammer instances doesn't work (Timeline not removed from memory)
16406};
16407/**
16408 * Activate the element
16409 * Overlay is hidden, element is decorated with a blue shadow border
16410 */
16411
16412
16413Activator$1.prototype.activate = function () {
16414 // we allow only one active activator at a time
16415 if (Activator$1.current) {
16416 Activator$1.current.deactivate();
16417 }
16418
16419 Activator$1.current = this;
16420 this.active = true;
16421 this.dom.overlay.style.display = 'none';
16422 util.addClassName(this.dom.container, 'vis-active');
16423 this.emit('change');
16424 this.emit('activate'); // ugly hack: bind ESC after emitting the events, as the Network rebinds all
16425 // keyboard events on a 'change' event
16426
16427 this.keycharm.bind('esc', this.escListener);
16428};
16429/**
16430 * Deactivate the element
16431 * Overlay is displayed on top of the element
16432 */
16433
16434
16435Activator$1.prototype.deactivate = function () {
16436 this.active = false;
16437 this.dom.overlay.style.display = 'block';
16438 util.removeClassName(this.dom.container, 'vis-active');
16439 this.keycharm.unbind('esc', this.escListener);
16440 this.emit('change');
16441 this.emit('deactivate');
16442};
16443/**
16444 * Handle a tap event: activate the container
16445 * @param {Event} event The event
16446 * @private
16447 */
16448
16449
16450Activator$1.prototype._onTapOverlay = function (event) {
16451 // activate the container
16452 this.activate();
16453 event.srcEvent.stopPropagation();
16454};
16455/**
16456 * Test whether the element has the requested parent element somewhere in
16457 * its chain of parent nodes.
16458 * @param {HTMLElement} element
16459 * @param {HTMLElement} parent
16460 * @returns {boolean} Returns true when the parent is found somewhere in the
16461 * chain of parent nodes.
16462 * @private
16463 */
16464
16465
16466function _hasParent(element, parent) {
16467 while (element) {
16468 if (element === parent) {
16469 return true;
16470 }
16471
16472 element = element.parentNode;
16473 }
16474
16475 return false;
16476}
16477
16478var Activator_1 = Activator$1;
16479
16480var locales = createCommonjsModule(function (module, exports) {
16481 // English
16482 exports['en'] = {
16483 edit: 'Edit',
16484 del: 'Delete selected',
16485 back: 'Back',
16486 addNode: 'Add Node',
16487 addEdge: 'Add Edge',
16488 editNode: 'Edit Node',
16489 editEdge: 'Edit Edge',
16490 addDescription: 'Click in an empty space to place a new node.',
16491 edgeDescription: 'Click on a node and drag the edge to another node to connect them.',
16492 editEdgeDescription: 'Click on the control points and drag them to a node to connect to it.',
16493 createEdgeError: 'Cannot link edges to a cluster.',
16494 deleteClusterError: 'Clusters cannot be deleted.',
16495 editClusterError: 'Clusters cannot be edited.'
16496 };
16497 exports['en_EN'] = exports['en'];
16498 exports['en_US'] = exports['en']; // German
16499
16500 exports['de'] = {
16501 edit: 'Editieren',
16502 del: "L\xF6sche Auswahl",
16503 back: "Zur\xFCck",
16504 addNode: "Knoten hinzuf\xFCgen",
16505 addEdge: "Kante hinzuf\xFCgen",
16506 editNode: 'Knoten editieren',
16507 editEdge: 'Kante editieren',
16508 addDescription: 'Klicke auf eine freie Stelle, um einen neuen Knoten zu plazieren.',
16509 edgeDescription: 'Klicke auf einen Knoten und ziehe die Kante zu einem anderen Knoten, um diese zu verbinden.',
16510 editEdgeDescription: 'Klicke auf die Verbindungspunkte und ziehe diese auf einen Knoten, um sie zu verbinden.',
16511 createEdgeError: "Es ist nicht m\xF6glich, Kanten mit Clustern zu verbinden.",
16512 deleteClusterError: "Cluster k\xF6nnen nicht gel\xF6scht werden.",
16513 editClusterError: "Cluster k\xF6nnen nicht editiert werden."
16514 };
16515 exports['de_DE'] = exports['de']; // Spanish
16516
16517 exports['es'] = {
16518 edit: 'Editar',
16519 del: "Eliminar selecci\xF3n",
16520 back: "Atr\xE1s",
16521 addNode: "A\xF1adir nodo",
16522 addEdge: "A\xF1adir arista",
16523 editNode: 'Editar nodo',
16524 editEdge: 'Editar arista',
16525 addDescription: "Haga clic en un lugar vac\xEDo para colocar un nuevo nodo.",
16526 edgeDescription: 'Haga clic en un nodo y arrastre la arista hacia otro nodo para conectarlos.',
16527 editEdgeDescription: 'Haga clic en un punto de control y arrastrelo a un nodo para conectarlo.',
16528 createEdgeError: 'No se puede conectar una arista a un grupo.',
16529 deleteClusterError: 'No es posible eliminar grupos.',
16530 editClusterError: 'No es posible editar grupos.'
16531 };
16532 exports['es_ES'] = exports['es']; //Italiano
16533
16534 exports['it'] = {
16535 edit: 'Modifica',
16536 del: 'Cancella la selezione',
16537 back: 'Indietro',
16538 addNode: 'Aggiungi un nodo',
16539 addEdge: 'Aggiungi un vertice',
16540 editNode: 'Modifica il nodo',
16541 editEdge: 'Modifica il vertice',
16542 addDescription: 'Clicca per aggiungere un nuovo nodo',
16543 edgeDescription: 'Clicca su un nodo e trascinalo ad un altro nodo per connetterli.',
16544 editEdgeDescription: 'Clicca sui Punti di controllo e trascinali ad un nodo per connetterli.',
16545 createEdgeError: 'Non si possono collegare vertici ad un cluster',
16546 deleteClusterError: 'I cluster non possono essere cancellati',
16547 editClusterError: 'I clusters non possono essere modificati.'
16548 };
16549 exports['it_IT'] = exports['it']; // Dutch
16550
16551 exports['nl'] = {
16552 edit: 'Wijzigen',
16553 del: 'Selectie verwijderen',
16554 back: 'Terug',
16555 addNode: 'Node toevoegen',
16556 addEdge: 'Link toevoegen',
16557 editNode: 'Node wijzigen',
16558 editEdge: 'Link wijzigen',
16559 addDescription: 'Klik op een leeg gebied om een nieuwe node te maken.',
16560 edgeDescription: 'Klik op een node en sleep de link naar een andere node om ze te verbinden.',
16561 editEdgeDescription: 'Klik op de verbindingspunten en sleep ze naar een node om daarmee te verbinden.',
16562 createEdgeError: 'Kan geen link maken naar een cluster.',
16563 deleteClusterError: 'Clusters kunnen niet worden verwijderd.',
16564 editClusterError: 'Clusters kunnen niet worden aangepast.'
16565 };
16566 exports['nl_NL'] = exports['nl'];
16567 exports['nl_BE'] = exports['nl']; // Portuguese Brazil
16568
16569 exports['pt-br'] = {
16570 edit: 'Editar',
16571 del: 'Remover selecionado',
16572 back: 'Voltar',
16573 addNode: 'Adicionar nó',
16574 addEdge: 'Adicionar aresta',
16575 editNode: 'Editar nó',
16576 editEdge: 'Editar aresta',
16577 addDescription: 'Clique em um espaço em branco para adicionar um novo nó',
16578 edgeDescription: 'Clique em um nó e arraste a aresta até outro nó para conectá-los',
16579 editEdgeDescription: 'Clique nos pontos de controle e os arraste para um nó para conectá-los',
16580 createEdgeError: 'Não foi possível linkar arestas a um cluster.',
16581 deleteClusterError: 'Clusters não puderam ser removidos.',
16582 editClusterError: 'Clusters não puderam ser editados.'
16583 };
16584 exports['pt-BR'] = exports['pt-br'];
16585 exports['pt_BR'] = exports['pt-br'];
16586 exports['pt_br'] = exports['pt-br']; // Russian
16587
16588 exports['ru'] = {
16589 edit: 'Редактировать',
16590 del: 'Удалить выбранное',
16591 back: 'Назад',
16592 addNode: 'Добавить узел',
16593 addEdge: 'Добавить ребро',
16594 editNode: 'Редактировать узел',
16595 editEdge: 'Редактировать ребро',
16596 addDescription: 'Кликните в свободное место, чтобы добавить новый узел.',
16597 edgeDescription: 'Кликните на узел и протяните ребро к другому узлу, чтобы соединить их.',
16598 editEdgeDescription: 'Кликните на контрольные точки и перетащите их в узел, чтобы подключиться к нему.',
16599 createEdgeError: 'Невозможно соединить ребра в кластер.',
16600 deleteClusterError: 'Кластеры не могут быть удалены',
16601 editClusterError: 'Кластеры недоступны для редактирования.'
16602 };
16603 exports['ru_RU'] = exports['ru']; // Chinese
16604
16605 exports['cn'] = {
16606 edit: '编辑',
16607 del: '删除选定',
16608 back: '返回',
16609 addNode: '添加节点',
16610 addEdge: '添加连接线',
16611 editNode: '编辑节点',
16612 editEdge: '编辑连接线',
16613 addDescription: '单击空白处放置新节点。',
16614 edgeDescription: '单击某个节点并将该连接线拖动到另一个节点以连接它们。',
16615 editEdgeDescription: '单击控制节点并将它们拖到节点上连接。',
16616 createEdgeError: '无法将连接线连接到群集。',
16617 deleteClusterError: '无法删除群集。',
16618 editClusterError: '无法编辑群集。'
16619 };
16620 exports['zh_CN'] = exports['cn']; // Ukrainian
16621
16622 exports['uk'] = {
16623 edit: 'Редагувати',
16624 del: 'Видалити обране',
16625 back: 'Назад',
16626 addNode: 'Додати вузол',
16627 addEdge: 'Додати край',
16628 editNode: 'Редагувати вузол',
16629 editEdge: 'Редагувати край',
16630 addDescription: 'Kлікніть на вільне місце, щоб додати новий вузол.',
16631 edgeDescription: 'Клікніть на вузол і перетягніть край до іншого вузла, щоб їх з\'єднати.',
16632 editEdgeDescription: 'Клікніть на контрольні точки і перетягніть їх у вузол, щоб підключитися до нього.',
16633 createEdgeError: 'Не можливо об\'єднати краї в групу.',
16634 deleteClusterError: 'Групи не можуть бути видалені.',
16635 editClusterError: 'Групи недоступні для редагування.'
16636 };
16637 exports['uk_UA'] = exports['uk']; // French
16638
16639 exports['fr'] = {
16640 edit: 'Editer',
16641 del: 'Effacer la selection',
16642 back: 'Retour',
16643 addNode: 'Ajouter un noeud',
16644 addEdge: 'Ajouter un lien',
16645 editNode: 'Editer le noeud',
16646 editEdge: 'Editer le lien',
16647 addDescription: 'Cliquez dans un endroit vide pour placer un noeud.',
16648 edgeDescription: 'Cliquez sur un noeud et glissez le lien vers un autre noeud pour les connecter.',
16649 editEdgeDescription: 'Cliquez sur les points de contrôle et glissez-les pour connecter un noeud.',
16650 createEdgeError: 'Impossible de créer un lien vers un cluster.',
16651 deleteClusterError: 'Les clusters ne peuvent pas être éffacés.',
16652 editClusterError: 'Les clusters ne peuvent pas être édites.'
16653 };
16654 exports['fr_FR'] = exports['fr']; // Czech
16655
16656 exports['cs'] = {
16657 edit: 'Upravit',
16658 del: 'Smazat výběr',
16659 back: 'Zpět',
16660 addNode: 'Přidat vrchol',
16661 addEdge: 'Přidat hranu',
16662 editNode: 'Upravit vrchol',
16663 editEdge: 'Upravit hranu',
16664 addDescription: 'Kluknutím do prázdného prostoru můžete přidat nový vrchol.',
16665 edgeDescription: 'Přetažením z jednoho vrcholu do druhého můžete spojit tyto vrcholy novou hranou.',
16666 editEdgeDescription: 'Přetažením kontrolního vrcholu hrany ji můžete připojit k jinému vrcholu.',
16667 createEdgeError: 'Nelze připojit hranu ke shluku.',
16668 deleteClusterError: 'Nelze mazat shluky.',
16669 editClusterError: 'Nelze upravovat shluky.'
16670 };
16671 exports['cs_CZ'] = exports['cs'];
16672});
16673
16674function _typeof$1(obj) {
16675 if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
16676 _typeof$1 = function (obj) {
16677 return typeof obj;
16678 };
16679 } else {
16680 _typeof$1 = function (obj) {
16681 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
16682 };
16683 }
16684
16685 return _typeof$1(obj);
16686}
16687
16688function _classCallCheck(instance, Constructor) {
16689 if (!(instance instanceof Constructor)) {
16690 throw new TypeError("Cannot call a class as a function");
16691 }
16692}
16693
16694function _defineProperties(target, props) {
16695 for (var i = 0; i < props.length; i++) {
16696 var descriptor = props[i];
16697 descriptor.enumerable = descriptor.enumerable || false;
16698 descriptor.configurable = true;
16699 if ("value" in descriptor) descriptor.writable = true;
16700 Object.defineProperty(target, descriptor.key, descriptor);
16701 }
16702}
16703
16704function _createClass(Constructor, protoProps, staticProps) {
16705 if (protoProps) _defineProperties(Constructor.prototype, protoProps);
16706 if (staticProps) _defineProperties(Constructor, staticProps);
16707 return Constructor;
16708}
16709
16710function _defineProperty$1(obj, key, value) {
16711 if (key in obj) {
16712 Object.defineProperty(obj, key, {
16713 value: value,
16714 enumerable: true,
16715 configurable: true,
16716 writable: true
16717 });
16718 } else {
16719 obj[key] = value;
16720 }
16721
16722 return obj;
16723}
16724
16725function ownKeys$2(object, enumerableOnly) {
16726 var keys = Object.keys(object);
16727
16728 if (Object.getOwnPropertySymbols) {
16729 var symbols = Object.getOwnPropertySymbols(object);
16730 if (enumerableOnly) symbols = symbols.filter(function (sym) {
16731 return Object.getOwnPropertyDescriptor(object, sym).enumerable;
16732 });
16733 keys.push.apply(keys, symbols);
16734 }
16735
16736 return keys;
16737}
16738
16739function _objectSpread2$1(target) {
16740 for (var i = 1; i < arguments.length; i++) {
16741 var source = arguments[i] != null ? arguments[i] : {};
16742
16743 if (i % 2) {
16744 ownKeys$2(source, true).forEach(function (key) {
16745 _defineProperty$1(target, key, source[key]);
16746 });
16747 } else if (Object.getOwnPropertyDescriptors) {
16748 Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
16749 } else {
16750 ownKeys$2(source).forEach(function (key) {
16751 Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
16752 });
16753 }
16754 }
16755
16756 return target;
16757}
16758
16759function _inherits(subClass, superClass) {
16760 if (typeof superClass !== "function" && superClass !== null) {
16761 throw new TypeError("Super expression must either be null or a function");
16762 }
16763
16764 subClass.prototype = Object.create(superClass && superClass.prototype, {
16765 constructor: {
16766 value: subClass,
16767 writable: true,
16768 configurable: true
16769 }
16770 });
16771 if (superClass) _setPrototypeOf(subClass, superClass);
16772}
16773
16774function _getPrototypeOf(o) {
16775 _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
16776 return o.__proto__ || Object.getPrototypeOf(o);
16777 };
16778 return _getPrototypeOf(o);
16779}
16780
16781function _setPrototypeOf(o, p) {
16782 _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
16783 o.__proto__ = p;
16784 return o;
16785 };
16786
16787 return _setPrototypeOf(o, p);
16788}
16789
16790function _assertThisInitialized$1(self) {
16791 if (self === void 0) {
16792 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
16793 }
16794
16795 return self;
16796}
16797
16798function _possibleConstructorReturn(self, call) {
16799 if (call && (typeof call === "object" || typeof call === "function")) {
16800 return call;
16801 }
16802
16803 return _assertThisInitialized$1(self);
16804}
16805
16806function _superPropBase(object, property) {
16807 while (!Object.prototype.hasOwnProperty.call(object, property)) {
16808 object = _getPrototypeOf(object);
16809 if (object === null) break;
16810 }
16811
16812 return object;
16813}
16814
16815function _get(target, property, receiver) {
16816 if (typeof Reflect !== "undefined" && Reflect.get) {
16817 _get = Reflect.get;
16818 } else {
16819 _get = function _get(target, property, receiver) {
16820 var base = _superPropBase(target, property);
16821
16822 if (!base) return;
16823 var desc = Object.getOwnPropertyDescriptor(base, property);
16824
16825 if (desc.get) {
16826 return desc.get.call(receiver);
16827 }
16828
16829 return desc.value;
16830 };
16831 }
16832
16833 return _get(target, property, receiver || target);
16834}
16835
16836function _readOnlyError(name) {
16837 throw new Error("\"" + name + "\" is read-only");
16838}
16839
16840function _slicedToArray(arr, i) {
16841 return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
16842}
16843
16844function _arrayWithHoles(arr) {
16845 if (Array.isArray(arr)) return arr;
16846}
16847
16848function _iterableToArrayLimit(arr, i) {
16849 if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) {
16850 return;
16851 }
16852
16853 var _arr = [];
16854 var _n = true;
16855 var _d = false;
16856 var _e = undefined;
16857
16858 try {
16859 for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
16860 _arr.push(_s.value);
16861
16862 if (i && _arr.length === i) break;
16863 }
16864 } catch (err) {
16865 _d = true;
16866 _e = err;
16867 } finally {
16868 try {
16869 if (!_n && _i["return"] != null) _i["return"]();
16870 } finally {
16871 if (_d) throw _e;
16872 }
16873 }
16874
16875 return _arr;
16876}
16877
16878function _nonIterableRest() {
16879 throw new TypeError("Invalid attempt to destructure non-iterable instance");
16880}
16881
16882/**
16883 * Associates a canvas to a given image, containing a number of renderings
16884 * of the image at various sizes.
16885 *
16886 * This technique is known as 'mipmapping'.
16887 *
16888 * NOTE: Images can also be of type 'data:svg+xml`. This code also works
16889 * for svg, but the mipmapping may not be necessary.
16890 *
16891 * @param {Image} image
16892 */
16893var CachedImage =
16894/*#__PURE__*/
16895function () {
16896 /**
16897 * @ignore
16898 */
16899 function CachedImage() {
16900 _classCallCheck(this, CachedImage);
16901
16902 // eslint-disable-line no-unused-vars
16903 this.NUM_ITERATIONS = 4; // Number of items in the coordinates array
16904
16905 this.image = new Image();
16906 this.canvas = document.createElement('canvas');
16907 }
16908 /**
16909 * Called when the image has been successfully loaded.
16910 */
16911
16912
16913 _createClass(CachedImage, [{
16914 key: "init",
16915 value: function init() {
16916 if (this.initialized()) return;
16917 this.src = this.image.src; // For same interface with Image
16918
16919 var w = this.image.width;
16920 var h = this.image.height; // Ease external access
16921
16922 this.width = w;
16923 this.height = h;
16924 var h2 = Math.floor(h / 2);
16925 var h4 = Math.floor(h / 4);
16926 var h8 = Math.floor(h / 8);
16927 var h16 = Math.floor(h / 16);
16928 var w2 = Math.floor(w / 2);
16929 var w4 = Math.floor(w / 4);
16930 var w8 = Math.floor(w / 8);
16931 var w16 = Math.floor(w / 16); // Make canvas as small as possible
16932
16933 this.canvas.width = 3 * w4;
16934 this.canvas.height = h2; // Coordinates and sizes of images contained in the canvas
16935 // Values per row: [top x, left y, width, height]
16936
16937 this.coordinates = [[0, 0, w2, h2], [w2, 0, w4, h4], [w2, h4, w8, h8], [5 * w8, h4, w16, h16]];
16938
16939 this._fillMipMap();
16940 }
16941 /**
16942 * @return {Boolean} true if init() has been called, false otherwise.
16943 */
16944
16945 }, {
16946 key: "initialized",
16947 value: function initialized() {
16948 return this.coordinates !== undefined;
16949 }
16950 /**
16951 * Redraw main image in various sizes to the context.
16952 *
16953 * The rationale behind this is to reduce artefacts due to interpolation
16954 * at differing zoom levels.
16955 *
16956 * Source: http://stackoverflow.com/q/18761404/1223531
16957 *
16958 * This methods takes the resizing out of the drawing loop, in order to
16959 * reduce performance overhead.
16960 *
16961 * TODO: The code assumes that a 2D context can always be gotten. This is
16962 * not necessarily true! OTOH, if not true then usage of this class
16963 * is senseless.
16964 *
16965 * @private
16966 */
16967
16968 }, {
16969 key: "_fillMipMap",
16970 value: function _fillMipMap() {
16971 var ctx = this.canvas.getContext('2d'); // First zoom-level comes from the image
16972
16973 var to = this.coordinates[0];
16974 ctx.drawImage(this.image, to[0], to[1], to[2], to[3]); // The rest are copy actions internal to the canvas/context
16975
16976 for (var iterations = 1; iterations < this.NUM_ITERATIONS; iterations++) {
16977 var from = this.coordinates[iterations - 1];
16978 var _to = this.coordinates[iterations];
16979 ctx.drawImage(this.canvas, from[0], from[1], from[2], from[3], _to[0], _to[1], _to[2], _to[3]);
16980 }
16981 }
16982 /**
16983 * Draw the image, using the mipmap if necessary.
16984 *
16985 * MipMap is only used if param factor > 2; otherwise, original bitmap
16986 * is resized. This is also used to skip mipmap usage, e.g. by setting factor = 1
16987 *
16988 * Credits to 'Alex de Mulder' for original implementation.
16989 *
16990 * @param {CanvasRenderingContext2D} ctx context on which to draw zoomed image
16991 * @param {Float} factor scale factor at which to draw
16992 * @param {number} left
16993 * @param {number} top
16994 * @param {number} width
16995 * @param {number} height
16996 */
16997
16998 }, {
16999 key: "drawImageAtPosition",
17000 value: function drawImageAtPosition(ctx, factor, left, top, width, height) {
17001 if (!this.initialized()) return; //can't draw image yet not intialized
17002
17003 if (factor > 2) {
17004 // Determine which zoomed image to use
17005 factor *= 0.5;
17006 var iterations = 0;
17007
17008 while (factor > 2 && iterations < this.NUM_ITERATIONS) {
17009 factor *= 0.5;
17010 iterations += 1;
17011 }
17012
17013 if (iterations >= this.NUM_ITERATIONS) {
17014 iterations = this.NUM_ITERATIONS - 1;
17015 } //console.log("iterations: " + iterations);
17016
17017
17018 var from = this.coordinates[iterations];
17019 ctx.drawImage(this.canvas, from[0], from[1], from[2], from[3], left, top, width, height);
17020 } else {
17021 // Draw image directly
17022 ctx.drawImage(this.image, left, top, width, height);
17023 }
17024 }
17025 }]);
17026
17027 return CachedImage;
17028}();
17029
17030/**
17031 * This callback is a callback that accepts an Image.
17032 * @callback ImageCallback
17033 * @param {Image} image
17034 */
17035
17036/**
17037 * This class loads images and keeps them stored.
17038 *
17039 * @param {ImageCallback} callback
17040 */
17041
17042var Images =
17043/*#__PURE__*/
17044function () {
17045 /**
17046 * @param {ImageCallback} callback
17047 */
17048 function Images(callback) {
17049 _classCallCheck(this, Images);
17050
17051 this.images = {};
17052 this.imageBroken = {};
17053 this.callback = callback;
17054 }
17055 /**
17056 * @param {string} url The original Url that failed to load, if the broken image is successfully loaded it will be added to the cache using this Url as the key so that subsequent requests for this Url will return the broken image
17057 * @param {string} brokenUrl Url the broken image to try and load
17058 * @param {Image} imageToLoadBrokenUrlOn The image object
17059 */
17060
17061
17062 _createClass(Images, [{
17063 key: "_tryloadBrokenUrl",
17064 value: function _tryloadBrokenUrl(url, brokenUrl, imageToLoadBrokenUrlOn) {
17065 //If these parameters aren't specified then exit the function because nothing constructive can be done
17066 if (url === undefined || imageToLoadBrokenUrlOn === undefined) return;
17067
17068 if (brokenUrl === undefined) {
17069 console.warn("No broken url image defined");
17070 return;
17071 } //Clear the old subscription to the error event and put a new in place that only handle errors in loading the brokenImageUrl
17072
17073
17074 imageToLoadBrokenUrlOn.image.onerror = function () {
17075 console.error("Could not load brokenImage:", brokenUrl); // cache item will contain empty image, this should be OK for default
17076 }; //Set the source of the image to the brokenUrl, this is actually what kicks off the loading of the broken image
17077
17078
17079 imageToLoadBrokenUrlOn.image.src = brokenUrl;
17080 }
17081 /**
17082 *
17083 * @param {vis.Image} imageToRedrawWith
17084 * @private
17085 */
17086
17087 }, {
17088 key: "_redrawWithImage",
17089 value: function _redrawWithImage(imageToRedrawWith) {
17090 if (this.callback) {
17091 this.callback(imageToRedrawWith);
17092 }
17093 }
17094 /**
17095 * @param {string} url Url of the image
17096 * @param {string} brokenUrl Url of an image to use if the url image is not found
17097 * @return {Image} img The image object
17098 */
17099
17100 }, {
17101 key: "load",
17102 value: function load(url, brokenUrl) {
17103 var _this = this;
17104
17105 //Try and get the image from the cache, if successful then return the cached image
17106 var cachedImage = this.images[url];
17107 if (cachedImage) return cachedImage; //Create a new image
17108
17109 var img = new CachedImage(); // Need to add to cache here, otherwise final return will spawn different copies of the same image,
17110 // Also, there will be multiple loads of the same image.
17111
17112 this.images[url] = img; //Subscribe to the event that is raised if the image loads successfully
17113
17114 img.image.onload = function () {
17115 // Properly init the cached item and then request a redraw
17116 _this._fixImageCoordinates(img.image);
17117
17118 img.init();
17119
17120 _this._redrawWithImage(img);
17121 }; //Subscribe to the event that is raised if the image fails to load
17122
17123
17124 img.image.onerror = function () {
17125 console.error("Could not load image:", url); //Try and load the image specified by the brokenUrl using
17126
17127 _this._tryloadBrokenUrl(url, brokenUrl, img);
17128 }; //Set the source of the image to the url, this is what actually kicks off the loading of the image
17129
17130
17131 img.image.src = url; //Return the new image
17132
17133 return img;
17134 }
17135 /**
17136 * IE11 fix -- thanks dponch!
17137 *
17138 * Local helper function
17139 * @param {vis.Image} imageToCache
17140 * @private
17141 */
17142
17143 }, {
17144 key: "_fixImageCoordinates",
17145 value: function _fixImageCoordinates(imageToCache) {
17146 if (imageToCache.width === 0) {
17147 document.body.appendChild(imageToCache);
17148 imageToCache.width = imageToCache.offsetWidth;
17149 imageToCache.height = imageToCache.offsetHeight;
17150 document.body.removeChild(imageToCache);
17151 }
17152 }
17153 }]);
17154
17155 return Images;
17156}();
17157
17158/**
17159 * This class can store groups and options specific for groups.
17160 */
17161
17162var Groups =
17163/*#__PURE__*/
17164function () {
17165 /**
17166 * @ignore
17167 */
17168 function Groups() {
17169 _classCallCheck(this, Groups);
17170
17171 this.clear();
17172 this.defaultIndex = 0;
17173 this.groupsArray = [];
17174 this.groupIndex = 0;
17175 this.defaultGroups = [{
17176 border: "#2B7CE9",
17177 background: "#97C2FC",
17178 highlight: {
17179 border: "#2B7CE9",
17180 background: "#D2E5FF"
17181 },
17182 hover: {
17183 border: "#2B7CE9",
17184 background: "#D2E5FF"
17185 }
17186 }, // 0: blue
17187 {
17188 border: "#FFA500",
17189 background: "#FFFF00",
17190 highlight: {
17191 border: "#FFA500",
17192 background: "#FFFFA3"
17193 },
17194 hover: {
17195 border: "#FFA500",
17196 background: "#FFFFA3"
17197 }
17198 }, // 1: yellow
17199 {
17200 border: "#FA0A10",
17201 background: "#FB7E81",
17202 highlight: {
17203 border: "#FA0A10",
17204 background: "#FFAFB1"
17205 },
17206 hover: {
17207 border: "#FA0A10",
17208 background: "#FFAFB1"
17209 }
17210 }, // 2: red
17211 {
17212 border: "#41A906",
17213 background: "#7BE141",
17214 highlight: {
17215 border: "#41A906",
17216 background: "#A1EC76"
17217 },
17218 hover: {
17219 border: "#41A906",
17220 background: "#A1EC76"
17221 }
17222 }, // 3: green
17223 {
17224 border: "#E129F0",
17225 background: "#EB7DF4",
17226 highlight: {
17227 border: "#E129F0",
17228 background: "#F0B3F5"
17229 },
17230 hover: {
17231 border: "#E129F0",
17232 background: "#F0B3F5"
17233 }
17234 }, // 4: magenta
17235 {
17236 border: "#7C29F0",
17237 background: "#AD85E4",
17238 highlight: {
17239 border: "#7C29F0",
17240 background: "#D3BDF0"
17241 },
17242 hover: {
17243 border: "#7C29F0",
17244 background: "#D3BDF0"
17245 }
17246 }, // 5: purple
17247 {
17248 border: "#C37F00",
17249 background: "#FFA807",
17250 highlight: {
17251 border: "#C37F00",
17252 background: "#FFCA66"
17253 },
17254 hover: {
17255 border: "#C37F00",
17256 background: "#FFCA66"
17257 }
17258 }, // 6: orange
17259 {
17260 border: "#4220FB",
17261 background: "#6E6EFD",
17262 highlight: {
17263 border: "#4220FB",
17264 background: "#9B9BFD"
17265 },
17266 hover: {
17267 border: "#4220FB",
17268 background: "#9B9BFD"
17269 }
17270 }, // 7: darkblue
17271 {
17272 border: "#FD5A77",
17273 background: "#FFC0CB",
17274 highlight: {
17275 border: "#FD5A77",
17276 background: "#FFD1D9"
17277 },
17278 hover: {
17279 border: "#FD5A77",
17280 background: "#FFD1D9"
17281 }
17282 }, // 8: pink
17283 {
17284 border: "#4AD63A",
17285 background: "#C2FABC",
17286 highlight: {
17287 border: "#4AD63A",
17288 background: "#E6FFE3"
17289 },
17290 hover: {
17291 border: "#4AD63A",
17292 background: "#E6FFE3"
17293 }
17294 }, // 9: mint
17295 {
17296 border: "#990000",
17297 background: "#EE0000",
17298 highlight: {
17299 border: "#BB0000",
17300 background: "#FF3333"
17301 },
17302 hover: {
17303 border: "#BB0000",
17304 background: "#FF3333"
17305 }
17306 }, // 10:bright red
17307 {
17308 border: "#FF6000",
17309 background: "#FF6000",
17310 highlight: {
17311 border: "#FF6000",
17312 background: "#FF6000"
17313 },
17314 hover: {
17315 border: "#FF6000",
17316 background: "#FF6000"
17317 }
17318 }, // 12: real orange
17319 {
17320 border: "#97C2FC",
17321 background: "#2B7CE9",
17322 highlight: {
17323 border: "#D2E5FF",
17324 background: "#2B7CE9"
17325 },
17326 hover: {
17327 border: "#D2E5FF",
17328 background: "#2B7CE9"
17329 }
17330 }, // 13: blue
17331 {
17332 border: "#399605",
17333 background: "#255C03",
17334 highlight: {
17335 border: "#399605",
17336 background: "#255C03"
17337 },
17338 hover: {
17339 border: "#399605",
17340 background: "#255C03"
17341 }
17342 }, // 14: green
17343 {
17344 border: "#B70054",
17345 background: "#FF007E",
17346 highlight: {
17347 border: "#B70054",
17348 background: "#FF007E"
17349 },
17350 hover: {
17351 border: "#B70054",
17352 background: "#FF007E"
17353 }
17354 }, // 15: magenta
17355 {
17356 border: "#AD85E4",
17357 background: "#7C29F0",
17358 highlight: {
17359 border: "#D3BDF0",
17360 background: "#7C29F0"
17361 },
17362 hover: {
17363 border: "#D3BDF0",
17364 background: "#7C29F0"
17365 }
17366 }, // 16: purple
17367 {
17368 border: "#4557FA",
17369 background: "#000EA1",
17370 highlight: {
17371 border: "#6E6EFD",
17372 background: "#000EA1"
17373 },
17374 hover: {
17375 border: "#6E6EFD",
17376 background: "#000EA1"
17377 }
17378 }, // 17: darkblue
17379 {
17380 border: "#FFC0CB",
17381 background: "#FD5A77",
17382 highlight: {
17383 border: "#FFD1D9",
17384 background: "#FD5A77"
17385 },
17386 hover: {
17387 border: "#FFD1D9",
17388 background: "#FD5A77"
17389 }
17390 }, // 18: pink
17391 {
17392 border: "#C2FABC",
17393 background: "#74D66A",
17394 highlight: {
17395 border: "#E6FFE3",
17396 background: "#74D66A"
17397 },
17398 hover: {
17399 border: "#E6FFE3",
17400 background: "#74D66A"
17401 }
17402 }, // 19: mint
17403 {
17404 border: "#EE0000",
17405 background: "#990000",
17406 highlight: {
17407 border: "#FF3333",
17408 background: "#BB0000"
17409 },
17410 hover: {
17411 border: "#FF3333",
17412 background: "#BB0000"
17413 }
17414 } // 20:bright red
17415 ];
17416 this.options = {};
17417 this.defaultOptions = {
17418 useDefaultGroups: true
17419 };
17420 extend(this.options, this.defaultOptions);
17421 }
17422 /**
17423 *
17424 * @param {Object} options
17425 */
17426
17427
17428 _createClass(Groups, [{
17429 key: "setOptions",
17430 value: function setOptions(options) {
17431 var optionFields = ['useDefaultGroups'];
17432
17433 if (options !== undefined) {
17434 for (var groupName in options) {
17435 if (options.hasOwnProperty(groupName)) {
17436 if (optionFields.indexOf(groupName) === -1) {
17437 var group = options[groupName];
17438 this.add(groupName, group);
17439 }
17440 }
17441 }
17442 }
17443 }
17444 /**
17445 * Clear all groups
17446 */
17447
17448 }, {
17449 key: "clear",
17450 value: function clear() {
17451 this.groups = {};
17452 this.groupsArray = [];
17453 }
17454 /**
17455 * Get group options of a groupname.
17456 * If groupname is not found, a new group may be created.
17457 *
17458 * @param {*} groupname Can be a number, string, Date, etc.
17459 * @param {boolean} [shouldCreate=true] If true, create a new group
17460 * @return {Object} The found or created group
17461 */
17462
17463 }, {
17464 key: "get",
17465 value: function get(groupname) {
17466 var shouldCreate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
17467 var group = this.groups[groupname];
17468
17469 if (group === undefined && shouldCreate) {
17470 if (this.options.useDefaultGroups === false && this.groupsArray.length > 0) {
17471 // create new group
17472 var index = this.groupIndex % this.groupsArray.length;
17473 this.groupIndex++;
17474 group = {};
17475 group.color = this.groups[this.groupsArray[index]];
17476 this.groups[groupname] = group;
17477 } else {
17478 // create new group
17479 var _index = this.defaultIndex % this.defaultGroups.length;
17480
17481 this.defaultIndex++;
17482 group = {};
17483 group.color = this.defaultGroups[_index];
17484 this.groups[groupname] = group;
17485 }
17486 }
17487
17488 return group;
17489 }
17490 /**
17491 * Add a custom group style
17492 * @param {string} groupName
17493 * @param {Object} style An object containing borderColor,
17494 * backgroundColor, etc.
17495 * @return {Object} group The created group object
17496 */
17497
17498 }, {
17499 key: "add",
17500 value: function add(groupName, style) {
17501 this.groups[groupName] = style;
17502 this.groupsArray.push(groupName);
17503 return style;
17504 }
17505 }]);
17506
17507 return Groups;
17508}();
17509
17510var $some = arrayIteration.some; // `Array.prototype.some` method
17511// https://tc39.github.io/ecma262/#sec-array.prototype.some
17512
17513_export({
17514 target: 'Array',
17515 proto: true,
17516 forced: sloppyArrayMethod('some')
17517}, {
17518 some: function some(callbackfn
17519 /* , thisArg */
17520 ) {
17521 return $some(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
17522 }
17523});
17524
17525/**
17526 * vis-data - data
17527 * http://visjs.org/
17528 *
17529 * Manage unstructured data using DataSet. Add, update, and remove data, and listen for changes in the data.
17530 *
17531 * @version 6.2.1
17532 * @date 2019-09-13T21:24:53Z
17533 *
17534 * @copyright (c) 2011-2017 Almende B.V, http://almende.com
17535 * @copyright (c) 2018-2019 visjs contributors, https://github.com/visjs
17536 *
17537 * @license
17538 * vis.js is dual licensed under both
17539 *
17540 * 1. The Apache 2.0 License
17541 * http://www.apache.org/licenses/LICENSE-2.0
17542 *
17543 * and
17544 *
17545 * 2. The MIT License
17546 * http://opensource.org/licenses/MIT
17547 *
17548 * vis.js may be distributed under either license.
17549 */
17550function createCommonjsModule$2(fn, module) {
17551 return module = {
17552 exports: {}
17553 }, fn(module, module.exports), module.exports;
17554}
17555
17556var runtime_1 = createCommonjsModule$2(function (module) {
17557 /**
17558 * Copyright (c) 2014-present, Facebook, Inc.
17559 *
17560 * This source code is licensed under the MIT license found in the
17561 * LICENSE file in the root directory of this source tree.
17562 */
17563 var runtime = function (exports) {
17564 var Op = Object.prototype;
17565 var hasOwn = Op.hasOwnProperty;
17566 var undefined$1; // More compressible than void 0.
17567
17568 var $Symbol = typeof Symbol === "function" ? Symbol : {};
17569 var iteratorSymbol = $Symbol.iterator || "@@iterator";
17570 var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
17571 var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
17572
17573 function wrap(innerFn, outerFn, self, tryLocsList) {
17574 // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.
17575 var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
17576 var generator = Object.create(protoGenerator.prototype);
17577 var context = new Context(tryLocsList || []); // The ._invoke method unifies the implementations of the .next,
17578 // .throw, and .return methods.
17579
17580 generator._invoke = makeInvokeMethod(innerFn, self, context);
17581 return generator;
17582 }
17583
17584 exports.wrap = wrap; // Try/catch helper to minimize deoptimizations. Returns a completion
17585 // record like context.tryEntries[i].completion. This interface could
17586 // have been (and was previously) designed to take a closure to be
17587 // invoked without arguments, but in all the cases we care about we
17588 // already have an existing method we want to call, so there's no need
17589 // to create a new function object. We can even get away with assuming
17590 // the method takes exactly one argument, since that happens to be true
17591 // in every case, so we don't have to touch the arguments object. The
17592 // only additional allocation required is the completion record, which
17593 // has a stable shape and so hopefully should be cheap to allocate.
17594
17595 function tryCatch(fn, obj, arg) {
17596 try {
17597 return {
17598 type: "normal",
17599 arg: fn.call(obj, arg)
17600 };
17601 } catch (err) {
17602 return {
17603 type: "throw",
17604 arg: err
17605 };
17606 }
17607 }
17608
17609 var GenStateSuspendedStart = "suspendedStart";
17610 var GenStateSuspendedYield = "suspendedYield";
17611 var GenStateExecuting = "executing";
17612 var GenStateCompleted = "completed"; // Returning this object from the innerFn has the same effect as
17613 // breaking out of the dispatch switch statement.
17614
17615 var ContinueSentinel = {}; // Dummy constructor functions that we use as the .constructor and
17616 // .constructor.prototype properties for functions that return Generator
17617 // objects. For full spec compliance, you may wish to configure your
17618 // minifier not to mangle the names of these two functions.
17619
17620 function Generator() {}
17621
17622 function GeneratorFunction() {}
17623
17624 function GeneratorFunctionPrototype() {} // This is a polyfill for %IteratorPrototype% for environments that
17625 // don't natively support it.
17626
17627
17628 var IteratorPrototype = {};
17629
17630 IteratorPrototype[iteratorSymbol] = function () {
17631 return this;
17632 };
17633
17634 var getProto = Object.getPrototypeOf;
17635 var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
17636
17637 if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
17638 // This environment has a native %IteratorPrototype%; use it instead
17639 // of the polyfill.
17640 IteratorPrototype = NativeIteratorPrototype;
17641 }
17642
17643 var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
17644 GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
17645 GeneratorFunctionPrototype.constructor = GeneratorFunction;
17646 GeneratorFunctionPrototype[toStringTagSymbol] = GeneratorFunction.displayName = "GeneratorFunction"; // Helper for defining the .next, .throw, and .return methods of the
17647 // Iterator interface in terms of a single ._invoke method.
17648
17649 function defineIteratorMethods(prototype) {
17650 ["next", "throw", "return"].forEach(function (method) {
17651 prototype[method] = function (arg) {
17652 return this._invoke(method, arg);
17653 };
17654 });
17655 }
17656
17657 exports.isGeneratorFunction = function (genFun) {
17658 var ctor = typeof genFun === "function" && genFun.constructor;
17659 return ctor ? ctor === GeneratorFunction || // For the native GeneratorFunction constructor, the best we can
17660 // do is to check its .name property.
17661 (ctor.displayName || ctor.name) === "GeneratorFunction" : false;
17662 };
17663
17664 exports.mark = function (genFun) {
17665 if (Object.setPrototypeOf) {
17666 Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
17667 } else {
17668 genFun.__proto__ = GeneratorFunctionPrototype;
17669
17670 if (!(toStringTagSymbol in genFun)) {
17671 genFun[toStringTagSymbol] = "GeneratorFunction";
17672 }
17673 }
17674
17675 genFun.prototype = Object.create(Gp);
17676 return genFun;
17677 }; // Within the body of any async function, `await x` is transformed to
17678 // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
17679 // `hasOwn.call(value, "__await")` to determine if the yielded value is
17680 // meant to be awaited.
17681
17682
17683 exports.awrap = function (arg) {
17684 return {
17685 __await: arg
17686 };
17687 };
17688
17689 function AsyncIterator(generator) {
17690 function invoke(method, arg, resolve, reject) {
17691 var record = tryCatch(generator[method], generator, arg);
17692
17693 if (record.type === "throw") {
17694 reject(record.arg);
17695 } else {
17696 var result = record.arg;
17697 var value = result.value;
17698
17699 if (value && typeof value === "object" && hasOwn.call(value, "__await")) {
17700 return Promise.resolve(value.__await).then(function (value) {
17701 invoke("next", value, resolve, reject);
17702 }, function (err) {
17703 invoke("throw", err, resolve, reject);
17704 });
17705 }
17706
17707 return Promise.resolve(value).then(function (unwrapped) {
17708 // When a yielded Promise is resolved, its final value becomes
17709 // the .value of the Promise<{value,done}> result for the
17710 // current iteration.
17711 result.value = unwrapped;
17712 resolve(result);
17713 }, function (error) {
17714 // If a rejected Promise was yielded, throw the rejection back
17715 // into the async generator function so it can be handled there.
17716 return invoke("throw", error, resolve, reject);
17717 });
17718 }
17719 }
17720
17721 var previousPromise;
17722
17723 function enqueue(method, arg) {
17724 function callInvokeWithMethodAndArg() {
17725 return new Promise(function (resolve, reject) {
17726 invoke(method, arg, resolve, reject);
17727 });
17728 }
17729
17730 return previousPromise = // If enqueue has been called before, then we want to wait until
17731 // all previous Promises have been resolved before calling invoke,
17732 // so that results are always delivered in the correct order. If
17733 // enqueue has not been called before, then it is important to
17734 // call invoke immediately, without waiting on a callback to fire,
17735 // so that the async generator function has the opportunity to do
17736 // any necessary setup in a predictable way. This predictability
17737 // is why the Promise constructor synchronously invokes its
17738 // executor callback, and why async functions synchronously
17739 // execute code before the first await. Since we implement simple
17740 // async functions in terms of async generators, it is especially
17741 // important to get this right, even though it requires care.
17742 previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, // Avoid propagating failures to Promises returned by later
17743 // invocations of the iterator.
17744 callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
17745 } // Define the unified helper method that is used to implement .next,
17746 // .throw, and .return (see defineIteratorMethods).
17747
17748
17749 this._invoke = enqueue;
17750 }
17751
17752 defineIteratorMethods(AsyncIterator.prototype);
17753
17754 AsyncIterator.prototype[asyncIteratorSymbol] = function () {
17755 return this;
17756 };
17757
17758 exports.AsyncIterator = AsyncIterator; // Note that simple async functions are implemented on top of
17759 // AsyncIterator objects; they just return a Promise for the value of
17760 // the final result produced by the iterator.
17761
17762 exports.async = function (innerFn, outerFn, self, tryLocsList) {
17763 var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList));
17764 return exports.isGeneratorFunction(outerFn) ? iter // If outerFn is a generator, return the full iterator.
17765 : iter.next().then(function (result) {
17766 return result.done ? result.value : iter.next();
17767 });
17768 };
17769
17770 function makeInvokeMethod(innerFn, self, context) {
17771 var state = GenStateSuspendedStart;
17772 return function invoke(method, arg) {
17773 if (state === GenStateExecuting) {
17774 throw new Error("Generator is already running");
17775 }
17776
17777 if (state === GenStateCompleted) {
17778 if (method === "throw") {
17779 throw arg;
17780 } // Be forgiving, per 25.3.3.3.3 of the spec:
17781 // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
17782
17783
17784 return doneResult();
17785 }
17786
17787 context.method = method;
17788 context.arg = arg;
17789
17790 while (true) {
17791 var delegate = context.delegate;
17792
17793 if (delegate) {
17794 var delegateResult = maybeInvokeDelegate(delegate, context);
17795
17796 if (delegateResult) {
17797 if (delegateResult === ContinueSentinel) continue;
17798 return delegateResult;
17799 }
17800 }
17801
17802 if (context.method === "next") {
17803 // Setting context._sent for legacy support of Babel's
17804 // function.sent implementation.
17805 context.sent = context._sent = context.arg;
17806 } else if (context.method === "throw") {
17807 if (state === GenStateSuspendedStart) {
17808 state = GenStateCompleted;
17809 throw context.arg;
17810 }
17811
17812 context.dispatchException(context.arg);
17813 } else if (context.method === "return") {
17814 context.abrupt("return", context.arg);
17815 }
17816
17817 state = GenStateExecuting;
17818 var record = tryCatch(innerFn, self, context);
17819
17820 if (record.type === "normal") {
17821 // If an exception is thrown from innerFn, we leave state ===
17822 // GenStateExecuting and loop back for another invocation.
17823 state = context.done ? GenStateCompleted : GenStateSuspendedYield;
17824
17825 if (record.arg === ContinueSentinel) {
17826 continue;
17827 }
17828
17829 return {
17830 value: record.arg,
17831 done: context.done
17832 };
17833 } else if (record.type === "throw") {
17834 state = GenStateCompleted; // Dispatch the exception by looping back around to the
17835 // context.dispatchException(context.arg) call above.
17836
17837 context.method = "throw";
17838 context.arg = record.arg;
17839 }
17840 }
17841 };
17842 } // Call delegate.iterator[context.method](context.arg) and handle the
17843 // result, either by returning a { value, done } result from the
17844 // delegate iterator, or by modifying context.method and context.arg,
17845 // setting context.delegate to null, and returning the ContinueSentinel.
17846
17847
17848 function maybeInvokeDelegate(delegate, context) {
17849 var method = delegate.iterator[context.method];
17850
17851 if (method === undefined$1) {
17852 // A .throw or .return when the delegate iterator has no .throw
17853 // method always terminates the yield* loop.
17854 context.delegate = null;
17855
17856 if (context.method === "throw") {
17857 // Note: ["return"] must be used for ES3 parsing compatibility.
17858 if (delegate.iterator["return"]) {
17859 // If the delegate iterator has a return method, give it a
17860 // chance to clean up.
17861 context.method = "return";
17862 context.arg = undefined$1;
17863 maybeInvokeDelegate(delegate, context);
17864
17865 if (context.method === "throw") {
17866 // If maybeInvokeDelegate(context) changed context.method from
17867 // "return" to "throw", let that override the TypeError below.
17868 return ContinueSentinel;
17869 }
17870 }
17871
17872 context.method = "throw";
17873 context.arg = new TypeError("The iterator does not provide a 'throw' method");
17874 }
17875
17876 return ContinueSentinel;
17877 }
17878
17879 var record = tryCatch(method, delegate.iterator, context.arg);
17880
17881 if (record.type === "throw") {
17882 context.method = "throw";
17883 context.arg = record.arg;
17884 context.delegate = null;
17885 return ContinueSentinel;
17886 }
17887
17888 var info = record.arg;
17889
17890 if (!info) {
17891 context.method = "throw";
17892 context.arg = new TypeError("iterator result is not an object");
17893 context.delegate = null;
17894 return ContinueSentinel;
17895 }
17896
17897 if (info.done) {
17898 // Assign the result of the finished delegate to the temporary
17899 // variable specified by delegate.resultName (see delegateYield).
17900 context[delegate.resultName] = info.value; // Resume execution at the desired location (see delegateYield).
17901
17902 context.next = delegate.nextLoc; // If context.method was "throw" but the delegate handled the
17903 // exception, let the outer generator proceed normally. If
17904 // context.method was "next", forget context.arg since it has been
17905 // "consumed" by the delegate iterator. If context.method was
17906 // "return", allow the original .return call to continue in the
17907 // outer generator.
17908
17909 if (context.method !== "return") {
17910 context.method = "next";
17911 context.arg = undefined$1;
17912 }
17913 } else {
17914 // Re-yield the result returned by the delegate method.
17915 return info;
17916 } // The delegate iterator is finished, so forget it and continue with
17917 // the outer generator.
17918
17919
17920 context.delegate = null;
17921 return ContinueSentinel;
17922 } // Define Generator.prototype.{next,throw,return} in terms of the
17923 // unified ._invoke helper method.
17924
17925
17926 defineIteratorMethods(Gp);
17927 Gp[toStringTagSymbol] = "Generator"; // A Generator should always return itself as the iterator object when the
17928 // @@iterator function is called on it. Some browsers' implementations of the
17929 // iterator prototype chain incorrectly implement this, causing the Generator
17930 // object to not be returned from this call. This ensures that doesn't happen.
17931 // See https://github.com/facebook/regenerator/issues/274 for more details.
17932
17933 Gp[iteratorSymbol] = function () {
17934 return this;
17935 };
17936
17937 Gp.toString = function () {
17938 return "[object Generator]";
17939 };
17940
17941 function pushTryEntry(locs) {
17942 var entry = {
17943 tryLoc: locs[0]
17944 };
17945
17946 if (1 in locs) {
17947 entry.catchLoc = locs[1];
17948 }
17949
17950 if (2 in locs) {
17951 entry.finallyLoc = locs[2];
17952 entry.afterLoc = locs[3];
17953 }
17954
17955 this.tryEntries.push(entry);
17956 }
17957
17958 function resetTryEntry(entry) {
17959 var record = entry.completion || {};
17960 record.type = "normal";
17961 delete record.arg;
17962 entry.completion = record;
17963 }
17964
17965 function Context(tryLocsList) {
17966 // The root entry object (effectively a try statement without a catch
17967 // or a finally block) gives us a place to store values thrown from
17968 // locations where there is no enclosing try statement.
17969 this.tryEntries = [{
17970 tryLoc: "root"
17971 }];
17972 tryLocsList.forEach(pushTryEntry, this);
17973 this.reset(true);
17974 }
17975
17976 exports.keys = function (object) {
17977 var keys = [];
17978
17979 for (var key in object) {
17980 keys.push(key);
17981 }
17982
17983 keys.reverse(); // Rather than returning an object with a next method, we keep
17984 // things simple and return the next function itself.
17985
17986 return function next() {
17987 while (keys.length) {
17988 var key = keys.pop();
17989
17990 if (key in object) {
17991 next.value = key;
17992 next.done = false;
17993 return next;
17994 }
17995 } // To avoid creating an additional object, we just hang the .value
17996 // and .done properties off the next function object itself. This
17997 // also ensures that the minifier will not anonymize the function.
17998
17999
18000 next.done = true;
18001 return next;
18002 };
18003 };
18004
18005 function values(iterable) {
18006 if (iterable) {
18007 var iteratorMethod = iterable[iteratorSymbol];
18008
18009 if (iteratorMethod) {
18010 return iteratorMethod.call(iterable);
18011 }
18012
18013 if (typeof iterable.next === "function") {
18014 return iterable;
18015 }
18016
18017 if (!isNaN(iterable.length)) {
18018 var i = -1,
18019 next = function next() {
18020 while (++i < iterable.length) {
18021 if (hasOwn.call(iterable, i)) {
18022 next.value = iterable[i];
18023 next.done = false;
18024 return next;
18025 }
18026 }
18027
18028 next.value = undefined$1;
18029 next.done = true;
18030 return next;
18031 };
18032
18033 return next.next = next;
18034 }
18035 } // Return an iterator with no values.
18036
18037
18038 return {
18039 next: doneResult
18040 };
18041 }
18042
18043 exports.values = values;
18044
18045 function doneResult() {
18046 return {
18047 value: undefined$1,
18048 done: true
18049 };
18050 }
18051
18052 Context.prototype = {
18053 constructor: Context,
18054 reset: function (skipTempReset) {
18055 this.prev = 0;
18056 this.next = 0; // Resetting context._sent for legacy support of Babel's
18057 // function.sent implementation.
18058
18059 this.sent = this._sent = undefined$1;
18060 this.done = false;
18061 this.delegate = null;
18062 this.method = "next";
18063 this.arg = undefined$1;
18064 this.tryEntries.forEach(resetTryEntry);
18065
18066 if (!skipTempReset) {
18067 for (var name in this) {
18068 // Not sure about the optimal order of these conditions:
18069 if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) {
18070 this[name] = undefined$1;
18071 }
18072 }
18073 }
18074 },
18075 stop: function () {
18076 this.done = true;
18077 var rootEntry = this.tryEntries[0];
18078 var rootRecord = rootEntry.completion;
18079
18080 if (rootRecord.type === "throw") {
18081 throw rootRecord.arg;
18082 }
18083
18084 return this.rval;
18085 },
18086 dispatchException: function (exception) {
18087 if (this.done) {
18088 throw exception;
18089 }
18090
18091 var context = this;
18092
18093 function handle(loc, caught) {
18094 record.type = "throw";
18095 record.arg = exception;
18096 context.next = loc;
18097
18098 if (caught) {
18099 // If the dispatched exception was caught by a catch block,
18100 // then let that catch block handle the exception normally.
18101 context.method = "next";
18102 context.arg = undefined$1;
18103 }
18104
18105 return !!caught;
18106 }
18107
18108 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
18109 var entry = this.tryEntries[i];
18110 var record = entry.completion;
18111
18112 if (entry.tryLoc === "root") {
18113 // Exception thrown outside of any try block that could handle
18114 // it, so set the completion value of the entire function to
18115 // throw the exception.
18116 return handle("end");
18117 }
18118
18119 if (entry.tryLoc <= this.prev) {
18120 var hasCatch = hasOwn.call(entry, "catchLoc");
18121 var hasFinally = hasOwn.call(entry, "finallyLoc");
18122
18123 if (hasCatch && hasFinally) {
18124 if (this.prev < entry.catchLoc) {
18125 return handle(entry.catchLoc, true);
18126 } else if (this.prev < entry.finallyLoc) {
18127 return handle(entry.finallyLoc);
18128 }
18129 } else if (hasCatch) {
18130 if (this.prev < entry.catchLoc) {
18131 return handle(entry.catchLoc, true);
18132 }
18133 } else if (hasFinally) {
18134 if (this.prev < entry.finallyLoc) {
18135 return handle(entry.finallyLoc);
18136 }
18137 } else {
18138 throw new Error("try statement without catch or finally");
18139 }
18140 }
18141 }
18142 },
18143 abrupt: function (type, arg) {
18144 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
18145 var entry = this.tryEntries[i];
18146
18147 if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
18148 var finallyEntry = entry;
18149 break;
18150 }
18151 }
18152
18153 if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) {
18154 // Ignore the finally entry if control is not jumping to a
18155 // location outside the try/catch block.
18156 finallyEntry = null;
18157 }
18158
18159 var record = finallyEntry ? finallyEntry.completion : {};
18160 record.type = type;
18161 record.arg = arg;
18162
18163 if (finallyEntry) {
18164 this.method = "next";
18165 this.next = finallyEntry.finallyLoc;
18166 return ContinueSentinel;
18167 }
18168
18169 return this.complete(record);
18170 },
18171 complete: function (record, afterLoc) {
18172 if (record.type === "throw") {
18173 throw record.arg;
18174 }
18175
18176 if (record.type === "break" || record.type === "continue") {
18177 this.next = record.arg;
18178 } else if (record.type === "return") {
18179 this.rval = this.arg = record.arg;
18180 this.method = "return";
18181 this.next = "end";
18182 } else if (record.type === "normal" && afterLoc) {
18183 this.next = afterLoc;
18184 }
18185
18186 return ContinueSentinel;
18187 },
18188 finish: function (finallyLoc) {
18189 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
18190 var entry = this.tryEntries[i];
18191
18192 if (entry.finallyLoc === finallyLoc) {
18193 this.complete(entry.completion, entry.afterLoc);
18194 resetTryEntry(entry);
18195 return ContinueSentinel;
18196 }
18197 }
18198 },
18199 "catch": function (tryLoc) {
18200 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
18201 var entry = this.tryEntries[i];
18202
18203 if (entry.tryLoc === tryLoc) {
18204 var record = entry.completion;
18205
18206 if (record.type === "throw") {
18207 var thrown = record.arg;
18208 resetTryEntry(entry);
18209 }
18210
18211 return thrown;
18212 }
18213 } // The context.catch method must only be called with a location
18214 // argument that corresponds to a known catch block.
18215
18216
18217 throw new Error("illegal catch attempt");
18218 },
18219 delegateYield: function (iterable, resultName, nextLoc) {
18220 this.delegate = {
18221 iterator: values(iterable),
18222 resultName: resultName,
18223 nextLoc: nextLoc
18224 };
18225
18226 if (this.method === "next") {
18227 // Deliberately forget the last sent value so that we don't
18228 // accidentally pass it on to the delegate.
18229 this.arg = undefined$1;
18230 }
18231
18232 return ContinueSentinel;
18233 }
18234 }; // Regardless of whether this script is executing as a CommonJS module
18235 // or not, return the runtime object so that we can declare the variable
18236 // regeneratorRuntime in the outer scope, which allows this module to be
18237 // injected easily by `bin/regenerator --include-runtime script.js`.
18238
18239 return exports;
18240 }( // If this script is executing as a CommonJS module, use module.exports
18241 // as the regeneratorRuntime namespace. Otherwise create a new empty
18242 // object. Either way, the resulting object will be used to initialize
18243 // the regeneratorRuntime variable at the top of this file.
18244 module.exports);
18245
18246 try {
18247 regeneratorRuntime = runtime;
18248 } catch (accidentalStrictMode) {
18249 // This module should not be running in strict mode, so the above
18250 // assignment should always work unless something is misconfigured. Just
18251 // in case runtime.js accidentally runs in strict mode, we can escape
18252 // strict mode using a global Function call. This could conceivably fail
18253 // if a Content Security Policy forbids using Function, but in that case
18254 // the proper solution is to fix the accidental strict mode problem. If
18255 // you've misconfigured your bundler to force strict mode and applied a
18256 // CSP to forbid Function, and you're not willing to fix either of those
18257 // problems, please detail your unique predicament in a GitHub issue.
18258 Function("r", "regeneratorRuntime = r")(runtime);
18259 }
18260});
18261var regenerator = runtime_1;
18262
18263function _defineProperty$2(obj, key, value) {
18264 if (key in obj) {
18265 Object.defineProperty(obj, key, {
18266 value: value,
18267 enumerable: true,
18268 configurable: true,
18269 writable: true
18270 });
18271 } else {
18272 obj[key] = value;
18273 }
18274
18275 return obj;
18276}
18277
18278var defineProperty$6 = _defineProperty$2;
18279
18280function _arrayWithoutHoles$1(arr) {
18281 if (Array.isArray(arr)) {
18282 for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {
18283 arr2[i] = arr[i];
18284 }
18285
18286 return arr2;
18287 }
18288}
18289
18290var arrayWithoutHoles = _arrayWithoutHoles$1;
18291
18292function _iterableToArray$1(iter) {
18293 if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
18294}
18295
18296var iterableToArray = _iterableToArray$1;
18297
18298function _nonIterableSpread$1() {
18299 throw new TypeError("Invalid attempt to spread non-iterable instance");
18300}
18301
18302var nonIterableSpread = _nonIterableSpread$1;
18303
18304function _toConsumableArray$1(arr) {
18305 return arrayWithoutHoles(arr) || iterableToArray(arr) || nonIterableSpread();
18306}
18307
18308var toConsumableArray = _toConsumableArray$1;
18309
18310var _typeof_1 = createCommonjsModule$2(function (module) {
18311 function _typeof2(obj) {
18312 if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
18313 _typeof2 = function _typeof2(obj) {
18314 return typeof obj;
18315 };
18316 } else {
18317 _typeof2 = function _typeof2(obj) {
18318 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
18319 };
18320 }
18321
18322 return _typeof2(obj);
18323 }
18324
18325 function _typeof(obj) {
18326 if (typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol") {
18327 module.exports = _typeof = function _typeof(obj) {
18328 return _typeof2(obj);
18329 };
18330 } else {
18331 module.exports = _typeof = function _typeof(obj) {
18332 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : _typeof2(obj);
18333 };
18334 }
18335
18336 return _typeof(obj);
18337 }
18338
18339 module.exports = _typeof;
18340});
18341
18342function _classCallCheck$1(instance, Constructor) {
18343 if (!(instance instanceof Constructor)) {
18344 throw new TypeError("Cannot call a class as a function");
18345 }
18346}
18347
18348var classCallCheck = _classCallCheck$1;
18349
18350function _defineProperties$1(target, props) {
18351 for (var i = 0; i < props.length; i++) {
18352 var descriptor = props[i];
18353 descriptor.enumerable = descriptor.enumerable || false;
18354 descriptor.configurable = true;
18355 if ("value" in descriptor) descriptor.writable = true;
18356 Object.defineProperty(target, descriptor.key, descriptor);
18357 }
18358}
18359
18360function _createClass$1(Constructor, protoProps, staticProps) {
18361 if (protoProps) _defineProperties$1(Constructor.prototype, protoProps);
18362 if (staticProps) _defineProperties$1(Constructor, staticProps);
18363 return Constructor;
18364}
18365
18366var createClass = _createClass$1;
18367
18368function _assertThisInitialized$2(self) {
18369 if (self === void 0) {
18370 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
18371 }
18372
18373 return self;
18374}
18375
18376var assertThisInitialized = _assertThisInitialized$2;
18377
18378function _possibleConstructorReturn$1(self, call) {
18379 if (call && (_typeof_1(call) === "object" || typeof call === "function")) {
18380 return call;
18381 }
18382
18383 return assertThisInitialized(self);
18384}
18385
18386var possibleConstructorReturn = _possibleConstructorReturn$1;
18387var getPrototypeOf = createCommonjsModule$2(function (module) {
18388 function _getPrototypeOf(o) {
18389 module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
18390 return o.__proto__ || Object.getPrototypeOf(o);
18391 };
18392 return _getPrototypeOf(o);
18393 }
18394
18395 module.exports = _getPrototypeOf;
18396});
18397var setPrototypeOf$1 = createCommonjsModule$2(function (module) {
18398 function _setPrototypeOf(o, p) {
18399 module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
18400 o.__proto__ = p;
18401 return o;
18402 };
18403
18404 return _setPrototypeOf(o, p);
18405 }
18406
18407 module.exports = _setPrototypeOf;
18408});
18409
18410function _inherits$1(subClass, superClass) {
18411 if (typeof superClass !== "function" && superClass !== null) {
18412 throw new TypeError("Super expression must either be null or a function");
18413 }
18414
18415 subClass.prototype = Object.create(superClass && superClass.prototype, {
18416 constructor: {
18417 value: subClass,
18418 writable: true,
18419 configurable: true
18420 }
18421 });
18422 if (superClass) setPrototypeOf$1(subClass, superClass);
18423}
18424
18425var inherits = _inherits$1; // Maps for number <-> hex string conversion
18426
18427var byteToHex$2 = [];
18428
18429for (var i$2 = 0; i$2 < 256; i$2++) {
18430 byteToHex$2[i$2] = (i$2 + 0x100).toString(16).substr(1);
18431}
18432/**
18433 * Represent binary UUID into it's string representation.
18434 *
18435 * @param buf - Buffer containing UUID bytes.
18436 * @param offset - Offset from the start of the buffer where the UUID is saved (not needed if the buffer starts with the UUID).
18437 *
18438 * @returns String representation of the UUID.
18439 */
18440
18441
18442function stringifyUUID$1(buf, offset) {
18443 var i = offset || 0;
18444 var bth = byteToHex$2;
18445 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]];
18446}
18447/**
18448 * Generate 16 random bytes to be used as a base for UUID.
18449 *
18450 * @ignore
18451 */
18452
18453
18454var random$1 = function () {
18455 if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
18456 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
18457 // Moderately fast, high quality
18458 var _rnds8 = new Uint8Array(16);
18459
18460 return function whatwgRNG() {
18461 crypto.getRandomValues(_rnds8);
18462 return _rnds8;
18463 };
18464 } // Math.random()-based (RNG)
18465 //
18466 // If all else fails, use Math.random().
18467 // It's fast, but is of unspecified quality.
18468
18469
18470 var _rnds = new Array(16);
18471
18472 return function () {
18473 for (var i = 0, r; i < 16; i++) {
18474 if ((i & 0x03) === 0) {
18475 r = Math.random() * 0x100000000;
18476 }
18477
18478 _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
18479 }
18480
18481 return _rnds;
18482 }; // uuid.js
18483 //
18484 // Copyright (c) 2010-2012 Robert Kieffer
18485 // MIT License - http://opensource.org/licenses/mit-license.php
18486 // Unique ID creation requires a high quality random # generator. We feature
18487 // detect to determine the best RNG source, normalizing to a function that
18488 // returns 128-bits of randomness, since that's what's usually required
18489 // return require('./rng');
18490}();
18491
18492var byteToHex$1$1 = [];
18493
18494for (var i$1$2 = 0; i$1$2 < 256; i$1$2++) {
18495 byteToHex$1$1[i$1$2] = (i$1$2 + 0x100).toString(16).substr(1);
18496} // **`v1()` - Generate time-based UUID**
18497//
18498// Inspired by https://github.com/LiosK/UUID.js
18499// and http://docs.python.org/library/uuid.html
18500// random #'s we need to init node and clockseq
18501
18502
18503var seedBytes$1 = random$1(); // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
18504
18505var defaultNodeId$1 = [seedBytes$1[0] | 0x01, seedBytes$1[1], seedBytes$1[2], seedBytes$1[3], seedBytes$1[4], seedBytes$1[5]]; // Per 4.2.2, randomize (14 bit) clockseq
18506
18507var defaultClockseq$1 = (seedBytes$1[6] << 8 | seedBytes$1[7]) & 0x3fff; // Previous uuid creation time
18508
18509/**
18510 * UUIDv4 options.
18511 */
18512
18513/**
18514 * Generate UUIDv4
18515 *
18516 * @param options - Options to be used instead of default generated values.
18517 * String 'binary' is a shorthand for uuid4({}, new Array(16)).
18518 * @param buf - If present the buffer will be filled with the generated UUID.
18519 * @param offset - Offset of the UUID from the start of the buffer.
18520 *
18521 * @returns UUIDv4
18522 */
18523
18524function uuid4$1() {
18525 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
18526 var buf = arguments.length > 1 ? arguments[1] : undefined;
18527 var offset = arguments.length > 2 ? arguments[2] : undefined; // Deprecated - 'format' argument, as supported in v1.2
18528
18529 var i = buf && offset || 0;
18530
18531 if (typeof options === 'string') {
18532 buf = options === 'binary' ? new Array(16) : undefined;
18533 options = {};
18534 }
18535
18536 var rnds = options.random || (options.rng || random$1)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
18537
18538 rnds[6] = rnds[6] & 0x0f | 0x40;
18539 rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
18540
18541 if (buf) {
18542 for (var ii = 0; ii < 16; ii++) {
18543 buf[i + ii] = rnds[ii];
18544 }
18545 }
18546
18547 return buf || stringifyUUID$1(rnds);
18548} // Rollup will complain about mixing default and named exports in UMD build,
18549
18550
18551function _typeof$2(obj) {
18552 if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
18553 _typeof$2 = function (obj) {
18554 return typeof obj;
18555 };
18556 } else {
18557 _typeof$2 = function (obj) {
18558 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
18559 };
18560 }
18561
18562 return _typeof$2(obj);
18563}
18564
18565var commonjsGlobal$2 = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
18566
18567function commonjsRequire$2() {
18568 throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
18569}
18570
18571function createCommonjsModule$1$1(fn, module) {
18572 return module = {
18573 exports: {}
18574 }, fn(module, module.exports), module.exports;
18575}
18576
18577var moment$1 = createCommonjsModule$1$1(function (module, exports) {
18578 (function (global, factory) {
18579 module.exports = factory();
18580 })(commonjsGlobal$2, function () {
18581 var hookCallback;
18582
18583 function hooks() {
18584 return hookCallback.apply(null, arguments);
18585 } // This is done to register the method called with moment()
18586 // without creating circular dependencies.
18587
18588
18589 function setHookCallback(callback) {
18590 hookCallback = callback;
18591 }
18592
18593 function isArray(input) {
18594 return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
18595 }
18596
18597 function isObject(input) {
18598 // IE8 will treat undefined and null as object if it wasn't for
18599 // input != null
18600 return input != null && Object.prototype.toString.call(input) === '[object Object]';
18601 }
18602
18603 function isObjectEmpty(obj) {
18604 if (Object.getOwnPropertyNames) {
18605 return Object.getOwnPropertyNames(obj).length === 0;
18606 } else {
18607 var k;
18608
18609 for (k in obj) {
18610 if (obj.hasOwnProperty(k)) {
18611 return false;
18612 }
18613 }
18614
18615 return true;
18616 }
18617 }
18618
18619 function isUndefined(input) {
18620 return input === void 0;
18621 }
18622
18623 function isNumber(input) {
18624 return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
18625 }
18626
18627 function isDate(input) {
18628 return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
18629 }
18630
18631 function map(arr, fn) {
18632 var res = [],
18633 i;
18634
18635 for (i = 0; i < arr.length; ++i) {
18636 res.push(fn(arr[i], i));
18637 }
18638
18639 return res;
18640 }
18641
18642 function hasOwnProp(a, b) {
18643 return Object.prototype.hasOwnProperty.call(a, b);
18644 }
18645
18646 function extend(a, b) {
18647 for (var i in b) {
18648 if (hasOwnProp(b, i)) {
18649 a[i] = b[i];
18650 }
18651 }
18652
18653 if (hasOwnProp(b, 'toString')) {
18654 a.toString = b.toString;
18655 }
18656
18657 if (hasOwnProp(b, 'valueOf')) {
18658 a.valueOf = b.valueOf;
18659 }
18660
18661 return a;
18662 }
18663
18664 function createUTC(input, format, locale, strict) {
18665 return createLocalOrUTC(input, format, locale, strict, true).utc();
18666 }
18667
18668 function defaultParsingFlags() {
18669 // We need to deep clone this object.
18670 return {
18671 empty: false,
18672 unusedTokens: [],
18673 unusedInput: [],
18674 overflow: -2,
18675 charsLeftOver: 0,
18676 nullInput: false,
18677 invalidMonth: null,
18678 invalidFormat: false,
18679 userInvalidated: false,
18680 iso: false,
18681 parsedDateParts: [],
18682 meridiem: null,
18683 rfc2822: false,
18684 weekdayMismatch: false
18685 };
18686 }
18687
18688 function getParsingFlags(m) {
18689 if (m._pf == null) {
18690 m._pf = defaultParsingFlags();
18691 }
18692
18693 return m._pf;
18694 }
18695
18696 var some;
18697
18698 if (Array.prototype.some) {
18699 some = Array.prototype.some;
18700 } else {
18701 some = function (fun) {
18702 var t = Object(this);
18703 var len = t.length >>> 0;
18704
18705 for (var i = 0; i < len; i++) {
18706 if (i in t && fun.call(this, t[i], i, t)) {
18707 return true;
18708 }
18709 }
18710
18711 return false;
18712 };
18713 }
18714
18715 function isValid(m) {
18716 if (m._isValid == null) {
18717 var flags = getParsingFlags(m);
18718 var parsedParts = some.call(flags.parsedDateParts, function (i) {
18719 return i != null;
18720 });
18721 var isNowValid = !isNaN(m._d.getTime()) && flags.overflow < 0 && !flags.empty && !flags.invalidMonth && !flags.invalidWeekday && !flags.weekdayMismatch && !flags.nullInput && !flags.invalidFormat && !flags.userInvalidated && (!flags.meridiem || flags.meridiem && parsedParts);
18722
18723 if (m._strict) {
18724 isNowValid = isNowValid && flags.charsLeftOver === 0 && flags.unusedTokens.length === 0 && flags.bigHour === undefined;
18725 }
18726
18727 if (Object.isFrozen == null || !Object.isFrozen(m)) {
18728 m._isValid = isNowValid;
18729 } else {
18730 return isNowValid;
18731 }
18732 }
18733
18734 return m._isValid;
18735 }
18736
18737 function createInvalid(flags) {
18738 var m = createUTC(NaN);
18739
18740 if (flags != null) {
18741 extend(getParsingFlags(m), flags);
18742 } else {
18743 getParsingFlags(m).userInvalidated = true;
18744 }
18745
18746 return m;
18747 } // Plugins that add properties should also add the key here (null value),
18748 // so we can properly clone ourselves.
18749
18750
18751 var momentProperties = hooks.momentProperties = [];
18752
18753 function copyConfig(to, from) {
18754 var i, prop, val;
18755
18756 if (!isUndefined(from._isAMomentObject)) {
18757 to._isAMomentObject = from._isAMomentObject;
18758 }
18759
18760 if (!isUndefined(from._i)) {
18761 to._i = from._i;
18762 }
18763
18764 if (!isUndefined(from._f)) {
18765 to._f = from._f;
18766 }
18767
18768 if (!isUndefined(from._l)) {
18769 to._l = from._l;
18770 }
18771
18772 if (!isUndefined(from._strict)) {
18773 to._strict = from._strict;
18774 }
18775
18776 if (!isUndefined(from._tzm)) {
18777 to._tzm = from._tzm;
18778 }
18779
18780 if (!isUndefined(from._isUTC)) {
18781 to._isUTC = from._isUTC;
18782 }
18783
18784 if (!isUndefined(from._offset)) {
18785 to._offset = from._offset;
18786 }
18787
18788 if (!isUndefined(from._pf)) {
18789 to._pf = getParsingFlags(from);
18790 }
18791
18792 if (!isUndefined(from._locale)) {
18793 to._locale = from._locale;
18794 }
18795
18796 if (momentProperties.length > 0) {
18797 for (i = 0; i < momentProperties.length; i++) {
18798 prop = momentProperties[i];
18799 val = from[prop];
18800
18801 if (!isUndefined(val)) {
18802 to[prop] = val;
18803 }
18804 }
18805 }
18806
18807 return to;
18808 }
18809
18810 var updateInProgress = false; // Moment prototype object
18811
18812 function Moment(config) {
18813 copyConfig(this, config);
18814 this._d = new Date(config._d != null ? config._d.getTime() : NaN);
18815
18816 if (!this.isValid()) {
18817 this._d = new Date(NaN);
18818 } // Prevent infinite loop in case updateOffset creates new moment
18819 // objects.
18820
18821
18822 if (updateInProgress === false) {
18823 updateInProgress = true;
18824 hooks.updateOffset(this);
18825 updateInProgress = false;
18826 }
18827 }
18828
18829 function isMoment(obj) {
18830 return obj instanceof Moment || obj != null && obj._isAMomentObject != null;
18831 }
18832
18833 function absFloor(number) {
18834 if (number < 0) {
18835 // -0 -> 0
18836 return Math.ceil(number) || 0;
18837 } else {
18838 return Math.floor(number);
18839 }
18840 }
18841
18842 function toInt(argumentForCoercion) {
18843 var coercedNumber = +argumentForCoercion,
18844 value = 0;
18845
18846 if (coercedNumber !== 0 && isFinite(coercedNumber)) {
18847 value = absFloor(coercedNumber);
18848 }
18849
18850 return value;
18851 } // compare two arrays, return the number of differences
18852
18853
18854 function compareArrays(array1, array2, dontConvert) {
18855 var len = Math.min(array1.length, array2.length),
18856 lengthDiff = Math.abs(array1.length - array2.length),
18857 diffs = 0,
18858 i;
18859
18860 for (i = 0; i < len; i++) {
18861 if (dontConvert && array1[i] !== array2[i] || !dontConvert && toInt(array1[i]) !== toInt(array2[i])) {
18862 diffs++;
18863 }
18864 }
18865
18866 return diffs + lengthDiff;
18867 }
18868
18869 function warn(msg) {
18870 if (hooks.suppressDeprecationWarnings === false && typeof console !== 'undefined' && console.warn) {
18871 console.warn('Deprecation warning: ' + msg);
18872 }
18873 }
18874
18875 function deprecate(msg, fn) {
18876 var firstTime = true;
18877 return extend(function () {
18878 if (hooks.deprecationHandler != null) {
18879 hooks.deprecationHandler(null, msg);
18880 }
18881
18882 if (firstTime) {
18883 var args = [];
18884 var arg;
18885
18886 for (var i = 0; i < arguments.length; i++) {
18887 arg = '';
18888
18889 if (typeof arguments[i] === 'object') {
18890 arg += '\n[' + i + '] ';
18891
18892 for (var key in arguments[0]) {
18893 arg += key + ': ' + arguments[0][key] + ', ';
18894 }
18895
18896 arg = arg.slice(0, -2); // Remove trailing comma and space
18897 } else {
18898 arg = arguments[i];
18899 }
18900
18901 args.push(arg);
18902 }
18903
18904 warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + new Error().stack);
18905 firstTime = false;
18906 }
18907
18908 return fn.apply(this, arguments);
18909 }, fn);
18910 }
18911
18912 var deprecations = {};
18913
18914 function deprecateSimple(name, msg) {
18915 if (hooks.deprecationHandler != null) {
18916 hooks.deprecationHandler(name, msg);
18917 }
18918
18919 if (!deprecations[name]) {
18920 warn(msg);
18921 deprecations[name] = true;
18922 }
18923 }
18924
18925 hooks.suppressDeprecationWarnings = false;
18926 hooks.deprecationHandler = null;
18927
18928 function isFunction(input) {
18929 return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
18930 }
18931
18932 function set(config) {
18933 var prop, i;
18934
18935 for (i in config) {
18936 prop = config[i];
18937
18938 if (isFunction(prop)) {
18939 this[i] = prop;
18940 } else {
18941 this['_' + i] = prop;
18942 }
18943 }
18944
18945 this._config = config; // Lenient ordinal parsing accepts just a number in addition to
18946 // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
18947 // TODO: Remove "ordinalParse" fallback in next major release.
18948
18949 this._dayOfMonthOrdinalParseLenient = new RegExp((this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) + '|' + /\d{1,2}/.source);
18950 }
18951
18952 function mergeConfigs(parentConfig, childConfig) {
18953 var res = extend({}, parentConfig),
18954 prop;
18955
18956 for (prop in childConfig) {
18957 if (hasOwnProp(childConfig, prop)) {
18958 if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
18959 res[prop] = {};
18960 extend(res[prop], parentConfig[prop]);
18961 extend(res[prop], childConfig[prop]);
18962 } else if (childConfig[prop] != null) {
18963 res[prop] = childConfig[prop];
18964 } else {
18965 delete res[prop];
18966 }
18967 }
18968 }
18969
18970 for (prop in parentConfig) {
18971 if (hasOwnProp(parentConfig, prop) && !hasOwnProp(childConfig, prop) && isObject(parentConfig[prop])) {
18972 // make sure changes to properties don't modify parent config
18973 res[prop] = extend({}, res[prop]);
18974 }
18975 }
18976
18977 return res;
18978 }
18979
18980 function Locale(config) {
18981 if (config != null) {
18982 this.set(config);
18983 }
18984 }
18985
18986 var keys;
18987
18988 if (Object.keys) {
18989 keys = Object.keys;
18990 } else {
18991 keys = function (obj) {
18992 var i,
18993 res = [];
18994
18995 for (i in obj) {
18996 if (hasOwnProp(obj, i)) {
18997 res.push(i);
18998 }
18999 }
19000
19001 return res;
19002 };
19003 }
19004
19005 var defaultCalendar = {
19006 sameDay: '[Today at] LT',
19007 nextDay: '[Tomorrow at] LT',
19008 nextWeek: 'dddd [at] LT',
19009 lastDay: '[Yesterday at] LT',
19010 lastWeek: '[Last] dddd [at] LT',
19011 sameElse: 'L'
19012 };
19013
19014 function calendar(key, mom, now) {
19015 var output = this._calendar[key] || this._calendar['sameElse'];
19016 return isFunction(output) ? output.call(mom, now) : output;
19017 }
19018
19019 var defaultLongDateFormat = {
19020 LTS: 'h:mm:ss A',
19021 LT: 'h:mm A',
19022 L: 'MM/DD/YYYY',
19023 LL: 'MMMM D, YYYY',
19024 LLL: 'MMMM D, YYYY h:mm A',
19025 LLLL: 'dddd, MMMM D, YYYY h:mm A'
19026 };
19027
19028 function longDateFormat(key) {
19029 var format = this._longDateFormat[key],
19030 formatUpper = this._longDateFormat[key.toUpperCase()];
19031
19032 if (format || !formatUpper) {
19033 return format;
19034 }
19035
19036 this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
19037 return val.slice(1);
19038 });
19039 return this._longDateFormat[key];
19040 }
19041
19042 var defaultInvalidDate = 'Invalid date';
19043
19044 function invalidDate() {
19045 return this._invalidDate;
19046 }
19047
19048 var defaultOrdinal = '%d';
19049 var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
19050
19051 function ordinal(number) {
19052 return this._ordinal.replace('%d', number);
19053 }
19054
19055 var defaultRelativeTime = {
19056 future: 'in %s',
19057 past: '%s ago',
19058 s: 'a few seconds',
19059 ss: '%d seconds',
19060 m: 'a minute',
19061 mm: '%d minutes',
19062 h: 'an hour',
19063 hh: '%d hours',
19064 d: 'a day',
19065 dd: '%d days',
19066 M: 'a month',
19067 MM: '%d months',
19068 y: 'a year',
19069 yy: '%d years'
19070 };
19071
19072 function relativeTime(number, withoutSuffix, string, isFuture) {
19073 var output = this._relativeTime[string];
19074 return isFunction(output) ? output(number, withoutSuffix, string, isFuture) : output.replace(/%d/i, number);
19075 }
19076
19077 function pastFuture(diff, output) {
19078 var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
19079 return isFunction(format) ? format(output) : format.replace(/%s/i, output);
19080 }
19081
19082 var aliases = {};
19083
19084 function addUnitAlias(unit, shorthand) {
19085 var lowerCase = unit.toLowerCase();
19086 aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
19087 }
19088
19089 function normalizeUnits(units) {
19090 return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
19091 }
19092
19093 function normalizeObjectUnits(inputObject) {
19094 var normalizedInput = {},
19095 normalizedProp,
19096 prop;
19097
19098 for (prop in inputObject) {
19099 if (hasOwnProp(inputObject, prop)) {
19100 normalizedProp = normalizeUnits(prop);
19101
19102 if (normalizedProp) {
19103 normalizedInput[normalizedProp] = inputObject[prop];
19104 }
19105 }
19106 }
19107
19108 return normalizedInput;
19109 }
19110
19111 var priorities = {};
19112
19113 function addUnitPriority(unit, priority) {
19114 priorities[unit] = priority;
19115 }
19116
19117 function getPrioritizedUnits(unitsObj) {
19118 var units = [];
19119
19120 for (var u in unitsObj) {
19121 units.push({
19122 unit: u,
19123 priority: priorities[u]
19124 });
19125 }
19126
19127 units.sort(function (a, b) {
19128 return a.priority - b.priority;
19129 });
19130 return units;
19131 }
19132
19133 function zeroFill(number, targetLength, forceSign) {
19134 var absNumber = '' + Math.abs(number),
19135 zerosToFill = targetLength - absNumber.length,
19136 sign = number >= 0;
19137 return (sign ? forceSign ? '+' : '' : '-') + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
19138 }
19139
19140 var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
19141 var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
19142 var formatFunctions = {};
19143 var formatTokenFunctions = {}; // token: 'M'
19144 // padded: ['MM', 2]
19145 // ordinal: 'Mo'
19146 // callback: function () { this.month() + 1 }
19147
19148 function addFormatToken(token, padded, ordinal, callback) {
19149 var func = callback;
19150
19151 if (typeof callback === 'string') {
19152 func = function () {
19153 return this[callback]();
19154 };
19155 }
19156
19157 if (token) {
19158 formatTokenFunctions[token] = func;
19159 }
19160
19161 if (padded) {
19162 formatTokenFunctions[padded[0]] = function () {
19163 return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
19164 };
19165 }
19166
19167 if (ordinal) {
19168 formatTokenFunctions[ordinal] = function () {
19169 return this.localeData().ordinal(func.apply(this, arguments), token);
19170 };
19171 }
19172 }
19173
19174 function removeFormattingTokens(input) {
19175 if (input.match(/\[[\s\S]/)) {
19176 return input.replace(/^\[|\]$/g, '');
19177 }
19178
19179 return input.replace(/\\/g, '');
19180 }
19181
19182 function makeFormatFunction(format) {
19183 var array = format.match(formattingTokens),
19184 i,
19185 length;
19186
19187 for (i = 0, length = array.length; i < length; i++) {
19188 if (formatTokenFunctions[array[i]]) {
19189 array[i] = formatTokenFunctions[array[i]];
19190 } else {
19191 array[i] = removeFormattingTokens(array[i]);
19192 }
19193 }
19194
19195 return function (mom) {
19196 var output = '',
19197 i;
19198
19199 for (i = 0; i < length; i++) {
19200 output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
19201 }
19202
19203 return output;
19204 };
19205 } // format date using native date object
19206
19207
19208 function formatMoment(m, format) {
19209 if (!m.isValid()) {
19210 return m.localeData().invalidDate();
19211 }
19212
19213 format = expandFormat(format, m.localeData());
19214 formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
19215 return formatFunctions[format](m);
19216 }
19217
19218 function expandFormat(format, locale) {
19219 var i = 5;
19220
19221 function replaceLongDateFormatTokens(input) {
19222 return locale.longDateFormat(input) || input;
19223 }
19224
19225 localFormattingTokens.lastIndex = 0;
19226
19227 while (i >= 0 && localFormattingTokens.test(format)) {
19228 format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
19229 localFormattingTokens.lastIndex = 0;
19230 i -= 1;
19231 }
19232
19233 return format;
19234 }
19235
19236 var match1 = /\d/; // 0 - 9
19237
19238 var match2 = /\d\d/; // 00 - 99
19239
19240 var match3 = /\d{3}/; // 000 - 999
19241
19242 var match4 = /\d{4}/; // 0000 - 9999
19243
19244 var match6 = /[+-]?\d{6}/; // -999999 - 999999
19245
19246 var match1to2 = /\d\d?/; // 0 - 99
19247
19248 var match3to4 = /\d\d\d\d?/; // 999 - 9999
19249
19250 var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999
19251
19252 var match1to3 = /\d{1,3}/; // 0 - 999
19253
19254 var match1to4 = /\d{1,4}/; // 0 - 9999
19255
19256 var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
19257
19258 var matchUnsigned = /\d+/; // 0 - inf
19259
19260 var matchSigned = /[+-]?\d+/; // -inf - inf
19261
19262 var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
19263
19264 var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
19265
19266 var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
19267 // any word (or two) characters or numbers including two/three word month in arabic.
19268 // includes scottish gaelic two word and hyphenated months
19269
19270 var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
19271 var regexes = {};
19272
19273 function addRegexToken(token, regex, strictRegex) {
19274 regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
19275 return isStrict && strictRegex ? strictRegex : regex;
19276 };
19277 }
19278
19279 function getParseRegexForToken(token, config) {
19280 if (!hasOwnProp(regexes, token)) {
19281 return new RegExp(unescapeFormat(token));
19282 }
19283
19284 return regexes[token](config._strict, config._locale);
19285 } // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
19286
19287
19288 function unescapeFormat(s) {
19289 return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
19290 return p1 || p2 || p3 || p4;
19291 }));
19292 }
19293
19294 function regexEscape(s) {
19295 return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
19296 }
19297
19298 var tokens = {};
19299
19300 function addParseToken(token, callback) {
19301 var i,
19302 func = callback;
19303
19304 if (typeof token === 'string') {
19305 token = [token];
19306 }
19307
19308 if (isNumber(callback)) {
19309 func = function (input, array) {
19310 array[callback] = toInt(input);
19311 };
19312 }
19313
19314 for (i = 0; i < token.length; i++) {
19315 tokens[token[i]] = func;
19316 }
19317 }
19318
19319 function addWeekParseToken(token, callback) {
19320 addParseToken(token, function (input, array, config, token) {
19321 config._w = config._w || {};
19322 callback(input, config._w, config, token);
19323 });
19324 }
19325
19326 function addTimeToArrayFromToken(token, input, config) {
19327 if (input != null && hasOwnProp(tokens, token)) {
19328 tokens[token](input, config._a, config, token);
19329 }
19330 }
19331
19332 var YEAR = 0;
19333 var MONTH = 1;
19334 var DATE = 2;
19335 var HOUR = 3;
19336 var MINUTE = 4;
19337 var SECOND = 5;
19338 var MILLISECOND = 6;
19339 var WEEK = 7;
19340 var WEEKDAY = 8; // FORMATTING
19341
19342 addFormatToken('Y', 0, 0, function () {
19343 var y = this.year();
19344 return y <= 9999 ? '' + y : '+' + y;
19345 });
19346 addFormatToken(0, ['YY', 2], 0, function () {
19347 return this.year() % 100;
19348 });
19349 addFormatToken(0, ['YYYY', 4], 0, 'year');
19350 addFormatToken(0, ['YYYYY', 5], 0, 'year');
19351 addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); // ALIASES
19352
19353 addUnitAlias('year', 'y'); // PRIORITIES
19354
19355 addUnitPriority('year', 1); // PARSING
19356
19357 addRegexToken('Y', matchSigned);
19358 addRegexToken('YY', match1to2, match2);
19359 addRegexToken('YYYY', match1to4, match4);
19360 addRegexToken('YYYYY', match1to6, match6);
19361 addRegexToken('YYYYYY', match1to6, match6);
19362 addParseToken(['YYYYY', 'YYYYYY'], YEAR);
19363 addParseToken('YYYY', function (input, array) {
19364 array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
19365 });
19366 addParseToken('YY', function (input, array) {
19367 array[YEAR] = hooks.parseTwoDigitYear(input);
19368 });
19369 addParseToken('Y', function (input, array) {
19370 array[YEAR] = parseInt(input, 10);
19371 }); // HELPERS
19372
19373 function daysInYear(year) {
19374 return isLeapYear(year) ? 366 : 365;
19375 }
19376
19377 function isLeapYear(year) {
19378 return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
19379 } // HOOKS
19380
19381
19382 hooks.parseTwoDigitYear = function (input) {
19383 return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
19384 }; // MOMENTS
19385
19386
19387 var getSetYear = makeGetSet('FullYear', true);
19388
19389 function getIsLeapYear() {
19390 return isLeapYear(this.year());
19391 }
19392
19393 function makeGetSet(unit, keepTime) {
19394 return function (value) {
19395 if (value != null) {
19396 set$1(this, unit, value);
19397 hooks.updateOffset(this, keepTime);
19398 return this;
19399 } else {
19400 return get(this, unit);
19401 }
19402 };
19403 }
19404
19405 function get(mom, unit) {
19406 return mom.isValid() ? mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
19407 }
19408
19409 function set$1(mom, unit, value) {
19410 if (mom.isValid() && !isNaN(value)) {
19411 if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
19412 mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
19413 } else {
19414 mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
19415 }
19416 }
19417 } // MOMENTS
19418
19419
19420 function stringGet(units) {
19421 units = normalizeUnits(units);
19422
19423 if (isFunction(this[units])) {
19424 return this[units]();
19425 }
19426
19427 return this;
19428 }
19429
19430 function stringSet(units, value) {
19431 if (typeof units === 'object') {
19432 units = normalizeObjectUnits(units);
19433 var prioritized = getPrioritizedUnits(units);
19434
19435 for (var i = 0; i < prioritized.length; i++) {
19436 this[prioritized[i].unit](units[prioritized[i].unit]);
19437 }
19438 } else {
19439 units = normalizeUnits(units);
19440
19441 if (isFunction(this[units])) {
19442 return this[units](value);
19443 }
19444 }
19445
19446 return this;
19447 }
19448
19449 function mod(n, x) {
19450 return (n % x + x) % x;
19451 }
19452
19453 var indexOf;
19454
19455 if (Array.prototype.indexOf) {
19456 indexOf = Array.prototype.indexOf;
19457 } else {
19458 indexOf = function (o) {
19459 // I know
19460 var i;
19461
19462 for (i = 0; i < this.length; ++i) {
19463 if (this[i] === o) {
19464 return i;
19465 }
19466 }
19467
19468 return -1;
19469 };
19470 }
19471
19472 function daysInMonth(year, month) {
19473 if (isNaN(year) || isNaN(month)) {
19474 return NaN;
19475 }
19476
19477 var modMonth = mod(month, 12);
19478 year += (month - modMonth) / 12;
19479 return modMonth === 1 ? isLeapYear(year) ? 29 : 28 : 31 - modMonth % 7 % 2;
19480 } // FORMATTING
19481
19482
19483 addFormatToken('M', ['MM', 2], 'Mo', function () {
19484 return this.month() + 1;
19485 });
19486 addFormatToken('MMM', 0, 0, function (format) {
19487 return this.localeData().monthsShort(this, format);
19488 });
19489 addFormatToken('MMMM', 0, 0, function (format) {
19490 return this.localeData().months(this, format);
19491 }); // ALIASES
19492
19493 addUnitAlias('month', 'M'); // PRIORITY
19494
19495 addUnitPriority('month', 8); // PARSING
19496
19497 addRegexToken('M', match1to2);
19498 addRegexToken('MM', match1to2, match2);
19499 addRegexToken('MMM', function (isStrict, locale) {
19500 return locale.monthsShortRegex(isStrict);
19501 });
19502 addRegexToken('MMMM', function (isStrict, locale) {
19503 return locale.monthsRegex(isStrict);
19504 });
19505 addParseToken(['M', 'MM'], function (input, array) {
19506 array[MONTH] = toInt(input) - 1;
19507 });
19508 addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
19509 var month = config._locale.monthsParse(input, token, config._strict); // if we didn't find a month name, mark the date as invalid.
19510
19511
19512 if (month != null) {
19513 array[MONTH] = month;
19514 } else {
19515 getParsingFlags(config).invalidMonth = input;
19516 }
19517 }); // LOCALES
19518
19519 var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
19520 var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
19521
19522 function localeMonths(m, format) {
19523 if (!m) {
19524 return isArray(this._months) ? this._months : this._months['standalone'];
19525 }
19526
19527 return isArray(this._months) ? this._months[m.month()] : this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
19528 }
19529
19530 var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
19531
19532 function localeMonthsShort(m, format) {
19533 if (!m) {
19534 return isArray(this._monthsShort) ? this._monthsShort : this._monthsShort['standalone'];
19535 }
19536
19537 return isArray(this._monthsShort) ? this._monthsShort[m.month()] : this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
19538 }
19539
19540 function handleStrictParse(monthName, format, strict) {
19541 var i,
19542 ii,
19543 mom,
19544 llc = monthName.toLocaleLowerCase();
19545
19546 if (!this._monthsParse) {
19547 // this is not used
19548 this._monthsParse = [];
19549 this._longMonthsParse = [];
19550 this._shortMonthsParse = [];
19551
19552 for (i = 0; i < 12; ++i) {
19553 mom = createUTC([2000, i]);
19554 this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
19555 this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
19556 }
19557 }
19558
19559 if (strict) {
19560 if (format === 'MMM') {
19561 ii = indexOf.call(this._shortMonthsParse, llc);
19562 return ii !== -1 ? ii : null;
19563 } else {
19564 ii = indexOf.call(this._longMonthsParse, llc);
19565 return ii !== -1 ? ii : null;
19566 }
19567 } else {
19568 if (format === 'MMM') {
19569 ii = indexOf.call(this._shortMonthsParse, llc);
19570
19571 if (ii !== -1) {
19572 return ii;
19573 }
19574
19575 ii = indexOf.call(this._longMonthsParse, llc);
19576 return ii !== -1 ? ii : null;
19577 } else {
19578 ii = indexOf.call(this._longMonthsParse, llc);
19579
19580 if (ii !== -1) {
19581 return ii;
19582 }
19583
19584 ii = indexOf.call(this._shortMonthsParse, llc);
19585 return ii !== -1 ? ii : null;
19586 }
19587 }
19588 }
19589
19590 function localeMonthsParse(monthName, format, strict) {
19591 var i, mom, regex;
19592
19593 if (this._monthsParseExact) {
19594 return handleStrictParse.call(this, monthName, format, strict);
19595 }
19596
19597 if (!this._monthsParse) {
19598 this._monthsParse = [];
19599 this._longMonthsParse = [];
19600 this._shortMonthsParse = [];
19601 } // TODO: add sorting
19602 // Sorting makes sure if one month (or abbr) is a prefix of another
19603 // see sorting in computeMonthsParse
19604
19605
19606 for (i = 0; i < 12; i++) {
19607 // make the regex if we don't have it already
19608 mom = createUTC([2000, i]);
19609
19610 if (strict && !this._longMonthsParse[i]) {
19611 this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
19612 this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
19613 }
19614
19615 if (!strict && !this._monthsParse[i]) {
19616 regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
19617 this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
19618 } // test the regex
19619
19620
19621 if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
19622 return i;
19623 } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
19624 return i;
19625 } else if (!strict && this._monthsParse[i].test(monthName)) {
19626 return i;
19627 }
19628 }
19629 } // MOMENTS
19630
19631
19632 function setMonth(mom, value) {
19633 var dayOfMonth;
19634
19635 if (!mom.isValid()) {
19636 // No op
19637 return mom;
19638 }
19639
19640 if (typeof value === 'string') {
19641 if (/^\d+$/.test(value)) {
19642 value = toInt(value);
19643 } else {
19644 value = mom.localeData().monthsParse(value); // TODO: Another silent failure?
19645
19646 if (!isNumber(value)) {
19647 return mom;
19648 }
19649 }
19650 }
19651
19652 dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
19653
19654 mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
19655
19656 return mom;
19657 }
19658
19659 function getSetMonth(value) {
19660 if (value != null) {
19661 setMonth(this, value);
19662 hooks.updateOffset(this, true);
19663 return this;
19664 } else {
19665 return get(this, 'Month');
19666 }
19667 }
19668
19669 function getDaysInMonth() {
19670 return daysInMonth(this.year(), this.month());
19671 }
19672
19673 var defaultMonthsShortRegex = matchWord;
19674
19675 function monthsShortRegex(isStrict) {
19676 if (this._monthsParseExact) {
19677 if (!hasOwnProp(this, '_monthsRegex')) {
19678 computeMonthsParse.call(this);
19679 }
19680
19681 if (isStrict) {
19682 return this._monthsShortStrictRegex;
19683 } else {
19684 return this._monthsShortRegex;
19685 }
19686 } else {
19687 if (!hasOwnProp(this, '_monthsShortRegex')) {
19688 this._monthsShortRegex = defaultMonthsShortRegex;
19689 }
19690
19691 return this._monthsShortStrictRegex && isStrict ? this._monthsShortStrictRegex : this._monthsShortRegex;
19692 }
19693 }
19694
19695 var defaultMonthsRegex = matchWord;
19696
19697 function monthsRegex(isStrict) {
19698 if (this._monthsParseExact) {
19699 if (!hasOwnProp(this, '_monthsRegex')) {
19700 computeMonthsParse.call(this);
19701 }
19702
19703 if (isStrict) {
19704 return this._monthsStrictRegex;
19705 } else {
19706 return this._monthsRegex;
19707 }
19708 } else {
19709 if (!hasOwnProp(this, '_monthsRegex')) {
19710 this._monthsRegex = defaultMonthsRegex;
19711 }
19712
19713 return this._monthsStrictRegex && isStrict ? this._monthsStrictRegex : this._monthsRegex;
19714 }
19715 }
19716
19717 function computeMonthsParse() {
19718 function cmpLenRev(a, b) {
19719 return b.length - a.length;
19720 }
19721
19722 var shortPieces = [],
19723 longPieces = [],
19724 mixedPieces = [],
19725 i,
19726 mom;
19727
19728 for (i = 0; i < 12; i++) {
19729 // make the regex if we don't have it already
19730 mom = createUTC([2000, i]);
19731 shortPieces.push(this.monthsShort(mom, ''));
19732 longPieces.push(this.months(mom, ''));
19733 mixedPieces.push(this.months(mom, ''));
19734 mixedPieces.push(this.monthsShort(mom, ''));
19735 } // Sorting makes sure if one month (or abbr) is a prefix of another it
19736 // will match the longer piece.
19737
19738
19739 shortPieces.sort(cmpLenRev);
19740 longPieces.sort(cmpLenRev);
19741 mixedPieces.sort(cmpLenRev);
19742
19743 for (i = 0; i < 12; i++) {
19744 shortPieces[i] = regexEscape(shortPieces[i]);
19745 longPieces[i] = regexEscape(longPieces[i]);
19746 }
19747
19748 for (i = 0; i < 24; i++) {
19749 mixedPieces[i] = regexEscape(mixedPieces[i]);
19750 }
19751
19752 this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
19753 this._monthsShortRegex = this._monthsRegex;
19754 this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
19755 this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
19756 }
19757
19758 function createDate(y, m, d, h, M, s, ms) {
19759 // can't just apply() to create a date:
19760 // https://stackoverflow.com/q/181348
19761 var date; // the date constructor remaps years 0-99 to 1900-1999
19762
19763 if (y < 100 && y >= 0) {
19764 // preserve leap years using a full 400 year cycle, then reset
19765 date = new Date(y + 400, m, d, h, M, s, ms);
19766
19767 if (isFinite(date.getFullYear())) {
19768 date.setFullYear(y);
19769 }
19770 } else {
19771 date = new Date(y, m, d, h, M, s, ms);
19772 }
19773
19774 return date;
19775 }
19776
19777 function createUTCDate(y) {
19778 var date; // the Date.UTC function remaps years 0-99 to 1900-1999
19779
19780 if (y < 100 && y >= 0) {
19781 var args = Array.prototype.slice.call(arguments); // preserve leap years using a full 400 year cycle, then reset
19782
19783 args[0] = y + 400;
19784 date = new Date(Date.UTC.apply(null, args));
19785
19786 if (isFinite(date.getUTCFullYear())) {
19787 date.setUTCFullYear(y);
19788 }
19789 } else {
19790 date = new Date(Date.UTC.apply(null, arguments));
19791 }
19792
19793 return date;
19794 } // start-of-first-week - start-of-year
19795
19796
19797 function firstWeekOffset(year, dow, doy) {
19798 var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
19799 fwd = 7 + dow - doy,
19800 // first-week day local weekday -- which local weekday is fwd
19801 fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
19802 return -fwdlw + fwd - 1;
19803 } // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
19804
19805
19806 function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
19807 var localWeekday = (7 + weekday - dow) % 7,
19808 weekOffset = firstWeekOffset(year, dow, doy),
19809 dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
19810 resYear,
19811 resDayOfYear;
19812
19813 if (dayOfYear <= 0) {
19814 resYear = year - 1;
19815 resDayOfYear = daysInYear(resYear) + dayOfYear;
19816 } else if (dayOfYear > daysInYear(year)) {
19817 resYear = year + 1;
19818 resDayOfYear = dayOfYear - daysInYear(year);
19819 } else {
19820 resYear = year;
19821 resDayOfYear = dayOfYear;
19822 }
19823
19824 return {
19825 year: resYear,
19826 dayOfYear: resDayOfYear
19827 };
19828 }
19829
19830 function weekOfYear(mom, dow, doy) {
19831 var weekOffset = firstWeekOffset(mom.year(), dow, doy),
19832 week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
19833 resWeek,
19834 resYear;
19835
19836 if (week < 1) {
19837 resYear = mom.year() - 1;
19838 resWeek = week + weeksInYear(resYear, dow, doy);
19839 } else if (week > weeksInYear(mom.year(), dow, doy)) {
19840 resWeek = week - weeksInYear(mom.year(), dow, doy);
19841 resYear = mom.year() + 1;
19842 } else {
19843 resYear = mom.year();
19844 resWeek = week;
19845 }
19846
19847 return {
19848 week: resWeek,
19849 year: resYear
19850 };
19851 }
19852
19853 function weeksInYear(year, dow, doy) {
19854 var weekOffset = firstWeekOffset(year, dow, doy),
19855 weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
19856 return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
19857 } // FORMATTING
19858
19859
19860 addFormatToken('w', ['ww', 2], 'wo', 'week');
19861 addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); // ALIASES
19862
19863 addUnitAlias('week', 'w');
19864 addUnitAlias('isoWeek', 'W'); // PRIORITIES
19865
19866 addUnitPriority('week', 5);
19867 addUnitPriority('isoWeek', 5); // PARSING
19868
19869 addRegexToken('w', match1to2);
19870 addRegexToken('ww', match1to2, match2);
19871 addRegexToken('W', match1to2);
19872 addRegexToken('WW', match1to2, match2);
19873 addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
19874 week[token.substr(0, 1)] = toInt(input);
19875 }); // HELPERS
19876 // LOCALES
19877
19878 function localeWeek(mom) {
19879 return weekOfYear(mom, this._week.dow, this._week.doy).week;
19880 }
19881
19882 var defaultLocaleWeek = {
19883 dow: 0,
19884 // Sunday is the first day of the week.
19885 doy: 6 // The week that contains Jan 6th is the first week of the year.
19886
19887 };
19888
19889 function localeFirstDayOfWeek() {
19890 return this._week.dow;
19891 }
19892
19893 function localeFirstDayOfYear() {
19894 return this._week.doy;
19895 } // MOMENTS
19896
19897
19898 function getSetWeek(input) {
19899 var week = this.localeData().week(this);
19900 return input == null ? week : this.add((input - week) * 7, 'd');
19901 }
19902
19903 function getSetISOWeek(input) {
19904 var week = weekOfYear(this, 1, 4).week;
19905 return input == null ? week : this.add((input - week) * 7, 'd');
19906 } // FORMATTING
19907
19908
19909 addFormatToken('d', 0, 'do', 'day');
19910 addFormatToken('dd', 0, 0, function (format) {
19911 return this.localeData().weekdaysMin(this, format);
19912 });
19913 addFormatToken('ddd', 0, 0, function (format) {
19914 return this.localeData().weekdaysShort(this, format);
19915 });
19916 addFormatToken('dddd', 0, 0, function (format) {
19917 return this.localeData().weekdays(this, format);
19918 });
19919 addFormatToken('e', 0, 0, 'weekday');
19920 addFormatToken('E', 0, 0, 'isoWeekday'); // ALIASES
19921
19922 addUnitAlias('day', 'd');
19923 addUnitAlias('weekday', 'e');
19924 addUnitAlias('isoWeekday', 'E'); // PRIORITY
19925
19926 addUnitPriority('day', 11);
19927 addUnitPriority('weekday', 11);
19928 addUnitPriority('isoWeekday', 11); // PARSING
19929
19930 addRegexToken('d', match1to2);
19931 addRegexToken('e', match1to2);
19932 addRegexToken('E', match1to2);
19933 addRegexToken('dd', function (isStrict, locale) {
19934 return locale.weekdaysMinRegex(isStrict);
19935 });
19936 addRegexToken('ddd', function (isStrict, locale) {
19937 return locale.weekdaysShortRegex(isStrict);
19938 });
19939 addRegexToken('dddd', function (isStrict, locale) {
19940 return locale.weekdaysRegex(isStrict);
19941 });
19942 addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
19943 var weekday = config._locale.weekdaysParse(input, token, config._strict); // if we didn't get a weekday name, mark the date as invalid
19944
19945
19946 if (weekday != null) {
19947 week.d = weekday;
19948 } else {
19949 getParsingFlags(config).invalidWeekday = input;
19950 }
19951 });
19952 addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
19953 week[token] = toInt(input);
19954 }); // HELPERS
19955
19956 function parseWeekday(input, locale) {
19957 if (typeof input !== 'string') {
19958 return input;
19959 }
19960
19961 if (!isNaN(input)) {
19962 return parseInt(input, 10);
19963 }
19964
19965 input = locale.weekdaysParse(input);
19966
19967 if (typeof input === 'number') {
19968 return input;
19969 }
19970
19971 return null;
19972 }
19973
19974 function parseIsoWeekday(input, locale) {
19975 if (typeof input === 'string') {
19976 return locale.weekdaysParse(input) % 7 || 7;
19977 }
19978
19979 return isNaN(input) ? null : input;
19980 } // LOCALES
19981
19982
19983 function shiftWeekdays(ws, n) {
19984 return ws.slice(n, 7).concat(ws.slice(0, n));
19985 }
19986
19987 var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
19988
19989 function localeWeekdays(m, format) {
19990 var weekdays = isArray(this._weekdays) ? this._weekdays : this._weekdays[m && m !== true && this._weekdays.isFormat.test(format) ? 'format' : 'standalone'];
19991 return m === true ? shiftWeekdays(weekdays, this._week.dow) : m ? weekdays[m.day()] : weekdays;
19992 }
19993
19994 var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
19995
19996 function localeWeekdaysShort(m) {
19997 return m === true ? shiftWeekdays(this._weekdaysShort, this._week.dow) : m ? this._weekdaysShort[m.day()] : this._weekdaysShort;
19998 }
19999
20000 var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
20001
20002 function localeWeekdaysMin(m) {
20003 return m === true ? shiftWeekdays(this._weekdaysMin, this._week.dow) : m ? this._weekdaysMin[m.day()] : this._weekdaysMin;
20004 }
20005
20006 function handleStrictParse$1(weekdayName, format, strict) {
20007 var i,
20008 ii,
20009 mom,
20010 llc = weekdayName.toLocaleLowerCase();
20011
20012 if (!this._weekdaysParse) {
20013 this._weekdaysParse = [];
20014 this._shortWeekdaysParse = [];
20015 this._minWeekdaysParse = [];
20016
20017 for (i = 0; i < 7; ++i) {
20018 mom = createUTC([2000, 1]).day(i);
20019 this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
20020 this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
20021 this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
20022 }
20023 }
20024
20025 if (strict) {
20026 if (format === 'dddd') {
20027 ii = indexOf.call(this._weekdaysParse, llc);
20028 return ii !== -1 ? ii : null;
20029 } else if (format === 'ddd') {
20030 ii = indexOf.call(this._shortWeekdaysParse, llc);
20031 return ii !== -1 ? ii : null;
20032 } else {
20033 ii = indexOf.call(this._minWeekdaysParse, llc);
20034 return ii !== -1 ? ii : null;
20035 }
20036 } else {
20037 if (format === 'dddd') {
20038 ii = indexOf.call(this._weekdaysParse, llc);
20039
20040 if (ii !== -1) {
20041 return ii;
20042 }
20043
20044 ii = indexOf.call(this._shortWeekdaysParse, llc);
20045
20046 if (ii !== -1) {
20047 return ii;
20048 }
20049
20050 ii = indexOf.call(this._minWeekdaysParse, llc);
20051 return ii !== -1 ? ii : null;
20052 } else if (format === 'ddd') {
20053 ii = indexOf.call(this._shortWeekdaysParse, llc);
20054
20055 if (ii !== -1) {
20056 return ii;
20057 }
20058
20059 ii = indexOf.call(this._weekdaysParse, llc);
20060
20061 if (ii !== -1) {
20062 return ii;
20063 }
20064
20065 ii = indexOf.call(this._minWeekdaysParse, llc);
20066 return ii !== -1 ? ii : null;
20067 } else {
20068 ii = indexOf.call(this._minWeekdaysParse, llc);
20069
20070 if (ii !== -1) {
20071 return ii;
20072 }
20073
20074 ii = indexOf.call(this._weekdaysParse, llc);
20075
20076 if (ii !== -1) {
20077 return ii;
20078 }
20079
20080 ii = indexOf.call(this._shortWeekdaysParse, llc);
20081 return ii !== -1 ? ii : null;
20082 }
20083 }
20084 }
20085
20086 function localeWeekdaysParse(weekdayName, format, strict) {
20087 var i, mom, regex;
20088
20089 if (this._weekdaysParseExact) {
20090 return handleStrictParse$1.call(this, weekdayName, format, strict);
20091 }
20092
20093 if (!this._weekdaysParse) {
20094 this._weekdaysParse = [];
20095 this._minWeekdaysParse = [];
20096 this._shortWeekdaysParse = [];
20097 this._fullWeekdaysParse = [];
20098 }
20099
20100 for (i = 0; i < 7; i++) {
20101 // make the regex if we don't have it already
20102 mom = createUTC([2000, 1]).day(i);
20103
20104 if (strict && !this._fullWeekdaysParse[i]) {
20105 this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i');
20106 this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i');
20107 this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i');
20108 }
20109
20110 if (!this._weekdaysParse[i]) {
20111 regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
20112 this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
20113 } // test the regex
20114
20115
20116 if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
20117 return i;
20118 } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
20119 return i;
20120 } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
20121 return i;
20122 } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
20123 return i;
20124 }
20125 }
20126 } // MOMENTS
20127
20128
20129 function getSetDayOfWeek(input) {
20130 if (!this.isValid()) {
20131 return input != null ? this : NaN;
20132 }
20133
20134 var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
20135
20136 if (input != null) {
20137 input = parseWeekday(input, this.localeData());
20138 return this.add(input - day, 'd');
20139 } else {
20140 return day;
20141 }
20142 }
20143
20144 function getSetLocaleDayOfWeek(input) {
20145 if (!this.isValid()) {
20146 return input != null ? this : NaN;
20147 }
20148
20149 var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
20150 return input == null ? weekday : this.add(input - weekday, 'd');
20151 }
20152
20153 function getSetISODayOfWeek(input) {
20154 if (!this.isValid()) {
20155 return input != null ? this : NaN;
20156 } // behaves the same as moment#day except
20157 // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
20158 // as a setter, sunday should belong to the previous week.
20159
20160
20161 if (input != null) {
20162 var weekday = parseIsoWeekday(input, this.localeData());
20163 return this.day(this.day() % 7 ? weekday : weekday - 7);
20164 } else {
20165 return this.day() || 7;
20166 }
20167 }
20168
20169 var defaultWeekdaysRegex = matchWord;
20170
20171 function weekdaysRegex(isStrict) {
20172 if (this._weekdaysParseExact) {
20173 if (!hasOwnProp(this, '_weekdaysRegex')) {
20174 computeWeekdaysParse.call(this);
20175 }
20176
20177 if (isStrict) {
20178 return this._weekdaysStrictRegex;
20179 } else {
20180 return this._weekdaysRegex;
20181 }
20182 } else {
20183 if (!hasOwnProp(this, '_weekdaysRegex')) {
20184 this._weekdaysRegex = defaultWeekdaysRegex;
20185 }
20186
20187 return this._weekdaysStrictRegex && isStrict ? this._weekdaysStrictRegex : this._weekdaysRegex;
20188 }
20189 }
20190
20191 var defaultWeekdaysShortRegex = matchWord;
20192
20193 function weekdaysShortRegex(isStrict) {
20194 if (this._weekdaysParseExact) {
20195 if (!hasOwnProp(this, '_weekdaysRegex')) {
20196 computeWeekdaysParse.call(this);
20197 }
20198
20199 if (isStrict) {
20200 return this._weekdaysShortStrictRegex;
20201 } else {
20202 return this._weekdaysShortRegex;
20203 }
20204 } else {
20205 if (!hasOwnProp(this, '_weekdaysShortRegex')) {
20206 this._weekdaysShortRegex = defaultWeekdaysShortRegex;
20207 }
20208
20209 return this._weekdaysShortStrictRegex && isStrict ? this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
20210 }
20211 }
20212
20213 var defaultWeekdaysMinRegex = matchWord;
20214
20215 function weekdaysMinRegex(isStrict) {
20216 if (this._weekdaysParseExact) {
20217 if (!hasOwnProp(this, '_weekdaysRegex')) {
20218 computeWeekdaysParse.call(this);
20219 }
20220
20221 if (isStrict) {
20222 return this._weekdaysMinStrictRegex;
20223 } else {
20224 return this._weekdaysMinRegex;
20225 }
20226 } else {
20227 if (!hasOwnProp(this, '_weekdaysMinRegex')) {
20228 this._weekdaysMinRegex = defaultWeekdaysMinRegex;
20229 }
20230
20231 return this._weekdaysMinStrictRegex && isStrict ? this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
20232 }
20233 }
20234
20235 function computeWeekdaysParse() {
20236 function cmpLenRev(a, b) {
20237 return b.length - a.length;
20238 }
20239
20240 var minPieces = [],
20241 shortPieces = [],
20242 longPieces = [],
20243 mixedPieces = [],
20244 i,
20245 mom,
20246 minp,
20247 shortp,
20248 longp;
20249
20250 for (i = 0; i < 7; i++) {
20251 // make the regex if we don't have it already
20252 mom = createUTC([2000, 1]).day(i);
20253 minp = this.weekdaysMin(mom, '');
20254 shortp = this.weekdaysShort(mom, '');
20255 longp = this.weekdays(mom, '');
20256 minPieces.push(minp);
20257 shortPieces.push(shortp);
20258 longPieces.push(longp);
20259 mixedPieces.push(minp);
20260 mixedPieces.push(shortp);
20261 mixedPieces.push(longp);
20262 } // Sorting makes sure if one weekday (or abbr) is a prefix of another it
20263 // will match the longer piece.
20264
20265
20266 minPieces.sort(cmpLenRev);
20267 shortPieces.sort(cmpLenRev);
20268 longPieces.sort(cmpLenRev);
20269 mixedPieces.sort(cmpLenRev);
20270
20271 for (i = 0; i < 7; i++) {
20272 shortPieces[i] = regexEscape(shortPieces[i]);
20273 longPieces[i] = regexEscape(longPieces[i]);
20274 mixedPieces[i] = regexEscape(mixedPieces[i]);
20275 }
20276
20277 this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
20278 this._weekdaysShortRegex = this._weekdaysRegex;
20279 this._weekdaysMinRegex = this._weekdaysRegex;
20280 this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
20281 this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
20282 this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
20283 } // FORMATTING
20284
20285
20286 function hFormat() {
20287 return this.hours() % 12 || 12;
20288 }
20289
20290 function kFormat() {
20291 return this.hours() || 24;
20292 }
20293
20294 addFormatToken('H', ['HH', 2], 0, 'hour');
20295 addFormatToken('h', ['hh', 2], 0, hFormat);
20296 addFormatToken('k', ['kk', 2], 0, kFormat);
20297 addFormatToken('hmm', 0, 0, function () {
20298 return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
20299 });
20300 addFormatToken('hmmss', 0, 0, function () {
20301 return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + zeroFill(this.seconds(), 2);
20302 });
20303 addFormatToken('Hmm', 0, 0, function () {
20304 return '' + this.hours() + zeroFill(this.minutes(), 2);
20305 });
20306 addFormatToken('Hmmss', 0, 0, function () {
20307 return '' + this.hours() + zeroFill(this.minutes(), 2) + zeroFill(this.seconds(), 2);
20308 });
20309
20310 function meridiem(token, lowercase) {
20311 addFormatToken(token, 0, 0, function () {
20312 return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
20313 });
20314 }
20315
20316 meridiem('a', true);
20317 meridiem('A', false); // ALIASES
20318
20319 addUnitAlias('hour', 'h'); // PRIORITY
20320
20321 addUnitPriority('hour', 13); // PARSING
20322
20323 function matchMeridiem(isStrict, locale) {
20324 return locale._meridiemParse;
20325 }
20326
20327 addRegexToken('a', matchMeridiem);
20328 addRegexToken('A', matchMeridiem);
20329 addRegexToken('H', match1to2);
20330 addRegexToken('h', match1to2);
20331 addRegexToken('k', match1to2);
20332 addRegexToken('HH', match1to2, match2);
20333 addRegexToken('hh', match1to2, match2);
20334 addRegexToken('kk', match1to2, match2);
20335 addRegexToken('hmm', match3to4);
20336 addRegexToken('hmmss', match5to6);
20337 addRegexToken('Hmm', match3to4);
20338 addRegexToken('Hmmss', match5to6);
20339 addParseToken(['H', 'HH'], HOUR);
20340 addParseToken(['k', 'kk'], function (input, array, config) {
20341 var kInput = toInt(input);
20342 array[HOUR] = kInput === 24 ? 0 : kInput;
20343 });
20344 addParseToken(['a', 'A'], function (input, array, config) {
20345 config._isPm = config._locale.isPM(input);
20346 config._meridiem = input;
20347 });
20348 addParseToken(['h', 'hh'], function (input, array, config) {
20349 array[HOUR] = toInt(input);
20350 getParsingFlags(config).bigHour = true;
20351 });
20352 addParseToken('hmm', function (input, array, config) {
20353 var pos = input.length - 2;
20354 array[HOUR] = toInt(input.substr(0, pos));
20355 array[MINUTE] = toInt(input.substr(pos));
20356 getParsingFlags(config).bigHour = true;
20357 });
20358 addParseToken('hmmss', function (input, array, config) {
20359 var pos1 = input.length - 4;
20360 var pos2 = input.length - 2;
20361 array[HOUR] = toInt(input.substr(0, pos1));
20362 array[MINUTE] = toInt(input.substr(pos1, 2));
20363 array[SECOND] = toInt(input.substr(pos2));
20364 getParsingFlags(config).bigHour = true;
20365 });
20366 addParseToken('Hmm', function (input, array, config) {
20367 var pos = input.length - 2;
20368 array[HOUR] = toInt(input.substr(0, pos));
20369 array[MINUTE] = toInt(input.substr(pos));
20370 });
20371 addParseToken('Hmmss', function (input, array, config) {
20372 var pos1 = input.length - 4;
20373 var pos2 = input.length - 2;
20374 array[HOUR] = toInt(input.substr(0, pos1));
20375 array[MINUTE] = toInt(input.substr(pos1, 2));
20376 array[SECOND] = toInt(input.substr(pos2));
20377 }); // LOCALES
20378
20379 function localeIsPM(input) {
20380 // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
20381 // Using charAt should be more compatible.
20382 return (input + '').toLowerCase().charAt(0) === 'p';
20383 }
20384
20385 var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
20386
20387 function localeMeridiem(hours, minutes, isLower) {
20388 if (hours > 11) {
20389 return isLower ? 'pm' : 'PM';
20390 } else {
20391 return isLower ? 'am' : 'AM';
20392 }
20393 } // MOMENTS
20394 // Setting the hour should keep the time, because the user explicitly
20395 // specified which hour they want. So trying to maintain the same hour (in
20396 // a new timezone) makes sense. Adding/subtracting hours does not follow
20397 // this rule.
20398
20399
20400 var getSetHour = makeGetSet('Hours', true);
20401 var baseConfig = {
20402 calendar: defaultCalendar,
20403 longDateFormat: defaultLongDateFormat,
20404 invalidDate: defaultInvalidDate,
20405 ordinal: defaultOrdinal,
20406 dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
20407 relativeTime: defaultRelativeTime,
20408 months: defaultLocaleMonths,
20409 monthsShort: defaultLocaleMonthsShort,
20410 week: defaultLocaleWeek,
20411 weekdays: defaultLocaleWeekdays,
20412 weekdaysMin: defaultLocaleWeekdaysMin,
20413 weekdaysShort: defaultLocaleWeekdaysShort,
20414 meridiemParse: defaultLocaleMeridiemParse
20415 }; // internal storage for locale config files
20416
20417 var locales = {};
20418 var localeFamilies = {};
20419 var globalLocale;
20420
20421 function normalizeLocale(key) {
20422 return key ? key.toLowerCase().replace('_', '-') : key;
20423 } // pick the locale from the array
20424 // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
20425 // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
20426
20427
20428 function chooseLocale(names) {
20429 var i = 0,
20430 j,
20431 next,
20432 locale,
20433 split;
20434
20435 while (i < names.length) {
20436 split = normalizeLocale(names[i]).split('-');
20437 j = split.length;
20438 next = normalizeLocale(names[i + 1]);
20439 next = next ? next.split('-') : null;
20440
20441 while (j > 0) {
20442 locale = loadLocale(split.slice(0, j).join('-'));
20443
20444 if (locale) {
20445 return locale;
20446 }
20447
20448 if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
20449 //the next array item is better than a shallower substring of this one
20450 break;
20451 }
20452
20453 j--;
20454 }
20455
20456 i++;
20457 }
20458
20459 return globalLocale;
20460 }
20461
20462 function loadLocale(name) {
20463 var oldLocale = null; // TODO: Find a better way to register and load all the locales in Node
20464
20465 if (!locales[name] && 'object' !== 'undefined' && module && module.exports) {
20466 try {
20467 oldLocale = globalLocale._abbr;
20468 var aliasedRequire = commonjsRequire$2;
20469 aliasedRequire('./locale/' + name);
20470 getSetGlobalLocale(oldLocale);
20471 } catch (e) {}
20472 }
20473
20474 return locales[name];
20475 } // This function will load locale and then set the global locale. If
20476 // no arguments are passed in, it will simply return the current global
20477 // locale key.
20478
20479
20480 function getSetGlobalLocale(key, values) {
20481 var data;
20482
20483 if (key) {
20484 if (isUndefined(values)) {
20485 data = getLocale(key);
20486 } else {
20487 data = defineLocale(key, values);
20488 }
20489
20490 if (data) {
20491 // moment.duration._locale = moment._locale = data;
20492 globalLocale = data;
20493 } else {
20494 if (typeof console !== 'undefined' && console.warn) {
20495 //warn user if arguments are passed but the locale could not be set
20496 console.warn('Locale ' + key + ' not found. Did you forget to load it?');
20497 }
20498 }
20499 }
20500
20501 return globalLocale._abbr;
20502 }
20503
20504 function defineLocale(name, config) {
20505 if (config !== null) {
20506 var locale,
20507 parentConfig = baseConfig;
20508 config.abbr = name;
20509
20510 if (locales[name] != null) {
20511 deprecateSimple('defineLocaleOverride', 'use moment.updateLocale(localeName, config) to change ' + 'an existing locale. moment.defineLocale(localeName, ' + 'config) should only be used for creating a new locale ' + 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
20512 parentConfig = locales[name]._config;
20513 } else if (config.parentLocale != null) {
20514 if (locales[config.parentLocale] != null) {
20515 parentConfig = locales[config.parentLocale]._config;
20516 } else {
20517 locale = loadLocale(config.parentLocale);
20518
20519 if (locale != null) {
20520 parentConfig = locale._config;
20521 } else {
20522 if (!localeFamilies[config.parentLocale]) {
20523 localeFamilies[config.parentLocale] = [];
20524 }
20525
20526 localeFamilies[config.parentLocale].push({
20527 name: name,
20528 config: config
20529 });
20530 return null;
20531 }
20532 }
20533 }
20534
20535 locales[name] = new Locale(mergeConfigs(parentConfig, config));
20536
20537 if (localeFamilies[name]) {
20538 localeFamilies[name].forEach(function (x) {
20539 defineLocale(x.name, x.config);
20540 });
20541 } // backwards compat for now: also set the locale
20542 // make sure we set the locale AFTER all child locales have been
20543 // created, so we won't end up with the child locale set.
20544
20545
20546 getSetGlobalLocale(name);
20547 return locales[name];
20548 } else {
20549 // useful for testing
20550 delete locales[name];
20551 return null;
20552 }
20553 }
20554
20555 function updateLocale(name, config) {
20556 if (config != null) {
20557 var locale,
20558 tmpLocale,
20559 parentConfig = baseConfig; // MERGE
20560
20561 tmpLocale = loadLocale(name);
20562
20563 if (tmpLocale != null) {
20564 parentConfig = tmpLocale._config;
20565 }
20566
20567 config = mergeConfigs(parentConfig, config);
20568 locale = new Locale(config);
20569 locale.parentLocale = locales[name];
20570 locales[name] = locale; // backwards compat for now: also set the locale
20571
20572 getSetGlobalLocale(name);
20573 } else {
20574 // pass null for config to unupdate, useful for tests
20575 if (locales[name] != null) {
20576 if (locales[name].parentLocale != null) {
20577 locales[name] = locales[name].parentLocale;
20578 } else if (locales[name] != null) {
20579 delete locales[name];
20580 }
20581 }
20582 }
20583
20584 return locales[name];
20585 } // returns locale data
20586
20587
20588 function getLocale(key) {
20589 var locale;
20590
20591 if (key && key._locale && key._locale._abbr) {
20592 key = key._locale._abbr;
20593 }
20594
20595 if (!key) {
20596 return globalLocale;
20597 }
20598
20599 if (!isArray(key)) {
20600 //short-circuit everything else
20601 locale = loadLocale(key);
20602
20603 if (locale) {
20604 return locale;
20605 }
20606
20607 key = [key];
20608 }
20609
20610 return chooseLocale(key);
20611 }
20612
20613 function listLocales() {
20614 return keys(locales);
20615 }
20616
20617 function checkOverflow(m) {
20618 var overflow;
20619 var a = m._a;
20620
20621 if (a && getParsingFlags(m).overflow === -2) {
20622 overflow = a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : a[HOUR] < 0 || a[HOUR] > 24 || a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0) ? HOUR : a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : -1;
20623
20624 if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
20625 overflow = DATE;
20626 }
20627
20628 if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
20629 overflow = WEEK;
20630 }
20631
20632 if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
20633 overflow = WEEKDAY;
20634 }
20635
20636 getParsingFlags(m).overflow = overflow;
20637 }
20638
20639 return m;
20640 } // Pick the first defined of two or three arguments.
20641
20642
20643 function defaults(a, b, c) {
20644 if (a != null) {
20645 return a;
20646 }
20647
20648 if (b != null) {
20649 return b;
20650 }
20651
20652 return c;
20653 }
20654
20655 function currentDateArray(config) {
20656 // hooks is actually the exported moment object
20657 var nowValue = new Date(hooks.now());
20658
20659 if (config._useUTC) {
20660 return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
20661 }
20662
20663 return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
20664 } // convert an array to a date.
20665 // the array should mirror the parameters below
20666 // note: all values past the year are optional and will default to the lowest possible value.
20667 // [year, month, day , hour, minute, second, millisecond]
20668
20669
20670 function configFromArray(config) {
20671 var i,
20672 date,
20673 input = [],
20674 currentDate,
20675 expectedWeekday,
20676 yearToUse;
20677
20678 if (config._d) {
20679 return;
20680 }
20681
20682 currentDate = currentDateArray(config); //compute day of the year from weeks and weekdays
20683
20684 if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
20685 dayOfYearFromWeekInfo(config);
20686 } //if the day of the year is set, figure out what it is
20687
20688
20689 if (config._dayOfYear != null) {
20690 yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
20691
20692 if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
20693 getParsingFlags(config)._overflowDayOfYear = true;
20694 }
20695
20696 date = createUTCDate(yearToUse, 0, config._dayOfYear);
20697 config._a[MONTH] = date.getUTCMonth();
20698 config._a[DATE] = date.getUTCDate();
20699 } // Default to current date.
20700 // * if no year, month, day of month are given, default to today
20701 // * if day of month is given, default month and year
20702 // * if month is given, default only year
20703 // * if year is given, don't default anything
20704
20705
20706 for (i = 0; i < 3 && config._a[i] == null; ++i) {
20707 config._a[i] = input[i] = currentDate[i];
20708 } // Zero out whatever was not defaulted, including time
20709
20710
20711 for (; i < 7; i++) {
20712 config._a[i] = input[i] = config._a[i] == null ? i === 2 ? 1 : 0 : config._a[i];
20713 } // Check for 24:00:00.000
20714
20715
20716 if (config._a[HOUR] === 24 && config._a[MINUTE] === 0 && config._a[SECOND] === 0 && config._a[MILLISECOND] === 0) {
20717 config._nextDay = true;
20718 config._a[HOUR] = 0;
20719 }
20720
20721 config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
20722 expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay(); // Apply timezone offset from input. The actual utcOffset can be changed
20723 // with parseZone.
20724
20725 if (config._tzm != null) {
20726 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
20727 }
20728
20729 if (config._nextDay) {
20730 config._a[HOUR] = 24;
20731 } // check for mismatching day of week
20732
20733
20734 if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) {
20735 getParsingFlags(config).weekdayMismatch = true;
20736 }
20737 }
20738
20739 function dayOfYearFromWeekInfo(config) {
20740 var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
20741 w = config._w;
20742
20743 if (w.GG != null || w.W != null || w.E != null) {
20744 dow = 1;
20745 doy = 4; // TODO: We need to take the current isoWeekYear, but that depends on
20746 // how we interpret now (local, utc, fixed offset). So create
20747 // a now version of current config (take local/utc/offset flags, and
20748 // create now).
20749
20750 weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
20751 week = defaults(w.W, 1);
20752 weekday = defaults(w.E, 1);
20753
20754 if (weekday < 1 || weekday > 7) {
20755 weekdayOverflow = true;
20756 }
20757 } else {
20758 dow = config._locale._week.dow;
20759 doy = config._locale._week.doy;
20760 var curWeek = weekOfYear(createLocal(), dow, doy);
20761 weekYear = defaults(w.gg, config._a[YEAR], curWeek.year); // Default to current week.
20762
20763 week = defaults(w.w, curWeek.week);
20764
20765 if (w.d != null) {
20766 // weekday -- low day numbers are considered next week
20767 weekday = w.d;
20768
20769 if (weekday < 0 || weekday > 6) {
20770 weekdayOverflow = true;
20771 }
20772 } else if (w.e != null) {
20773 // local weekday -- counting starts from beginning of week
20774 weekday = w.e + dow;
20775
20776 if (w.e < 0 || w.e > 6) {
20777 weekdayOverflow = true;
20778 }
20779 } else {
20780 // default to beginning of week
20781 weekday = dow;
20782 }
20783 }
20784
20785 if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
20786 getParsingFlags(config)._overflowWeeks = true;
20787 } else if (weekdayOverflow != null) {
20788 getParsingFlags(config)._overflowWeekday = true;
20789 } else {
20790 temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
20791 config._a[YEAR] = temp.year;
20792 config._dayOfYear = temp.dayOfYear;
20793 }
20794 } // iso 8601 regex
20795 // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
20796
20797
20798 var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
20799 var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
20800 var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
20801 var isoDates = [['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], ['GGGG-[W]WW', /\d{4}-W\d\d/, false], ['YYYY-DDD', /\d{4}-\d{3}/], ['YYYY-MM', /\d{4}-\d\d/, false], ['YYYYYYMMDD', /[+-]\d{10}/], ['YYYYMMDD', /\d{8}/], // YYYYMM is NOT allowed by the standard
20802 ['GGGG[W]WWE', /\d{4}W\d{3}/], ['GGGG[W]WW', /\d{4}W\d{2}/, false], ['YYYYDDD', /\d{7}/]]; // iso time formats and regexes
20803
20804 var isoTimes = [['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], ['HH:mm:ss', /\d\d:\d\d:\d\d/], ['HH:mm', /\d\d:\d\d/], ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], ['HHmmss', /\d\d\d\d\d\d/], ['HHmm', /\d\d\d\d/], ['HH', /\d\d/]];
20805 var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; // date from iso format
20806
20807 function configFromISO(config) {
20808 var i,
20809 l,
20810 string = config._i,
20811 match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
20812 allowTime,
20813 dateFormat,
20814 timeFormat,
20815 tzFormat;
20816
20817 if (match) {
20818 getParsingFlags(config).iso = true;
20819
20820 for (i = 0, l = isoDates.length; i < l; i++) {
20821 if (isoDates[i][1].exec(match[1])) {
20822 dateFormat = isoDates[i][0];
20823 allowTime = isoDates[i][2] !== false;
20824 break;
20825 }
20826 }
20827
20828 if (dateFormat == null) {
20829 config._isValid = false;
20830 return;
20831 }
20832
20833 if (match[3]) {
20834 for (i = 0, l = isoTimes.length; i < l; i++) {
20835 if (isoTimes[i][1].exec(match[3])) {
20836 // match[2] should be 'T' or space
20837 timeFormat = (match[2] || ' ') + isoTimes[i][0];
20838 break;
20839 }
20840 }
20841
20842 if (timeFormat == null) {
20843 config._isValid = false;
20844 return;
20845 }
20846 }
20847
20848 if (!allowTime && timeFormat != null) {
20849 config._isValid = false;
20850 return;
20851 }
20852
20853 if (match[4]) {
20854 if (tzRegex.exec(match[4])) {
20855 tzFormat = 'Z';
20856 } else {
20857 config._isValid = false;
20858 return;
20859 }
20860 }
20861
20862 config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
20863 configFromStringAndFormat(config);
20864 } else {
20865 config._isValid = false;
20866 }
20867 } // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
20868
20869
20870 var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
20871
20872 function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
20873 var result = [untruncateYear(yearStr), defaultLocaleMonthsShort.indexOf(monthStr), parseInt(dayStr, 10), parseInt(hourStr, 10), parseInt(minuteStr, 10)];
20874
20875 if (secondStr) {
20876 result.push(parseInt(secondStr, 10));
20877 }
20878
20879 return result;
20880 }
20881
20882 function untruncateYear(yearStr) {
20883 var year = parseInt(yearStr, 10);
20884
20885 if (year <= 49) {
20886 return 2000 + year;
20887 } else if (year <= 999) {
20888 return 1900 + year;
20889 }
20890
20891 return year;
20892 }
20893
20894 function preprocessRFC2822(s) {
20895 // Remove comments and folding whitespace and replace multiple-spaces with a single space
20896 return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
20897 }
20898
20899 function checkWeekday(weekdayStr, parsedInput, config) {
20900 if (weekdayStr) {
20901 // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
20902 var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
20903 weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
20904
20905 if (weekdayProvided !== weekdayActual) {
20906 getParsingFlags(config).weekdayMismatch = true;
20907 config._isValid = false;
20908 return false;
20909 }
20910 }
20911
20912 return true;
20913 }
20914
20915 var obsOffsets = {
20916 UT: 0,
20917 GMT: 0,
20918 EDT: -4 * 60,
20919 EST: -5 * 60,
20920 CDT: -5 * 60,
20921 CST: -6 * 60,
20922 MDT: -6 * 60,
20923 MST: -7 * 60,
20924 PDT: -7 * 60,
20925 PST: -8 * 60
20926 };
20927
20928 function calculateOffset(obsOffset, militaryOffset, numOffset) {
20929 if (obsOffset) {
20930 return obsOffsets[obsOffset];
20931 } else if (militaryOffset) {
20932 // the only allowed military tz is Z
20933 return 0;
20934 } else {
20935 var hm = parseInt(numOffset, 10);
20936 var m = hm % 100,
20937 h = (hm - m) / 100;
20938 return h * 60 + m;
20939 }
20940 } // date and time from ref 2822 format
20941
20942
20943 function configFromRFC2822(config) {
20944 var match = rfc2822.exec(preprocessRFC2822(config._i));
20945
20946 if (match) {
20947 var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
20948
20949 if (!checkWeekday(match[1], parsedArray, config)) {
20950 return;
20951 }
20952
20953 config._a = parsedArray;
20954 config._tzm = calculateOffset(match[8], match[9], match[10]);
20955 config._d = createUTCDate.apply(null, config._a);
20956
20957 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
20958
20959 getParsingFlags(config).rfc2822 = true;
20960 } else {
20961 config._isValid = false;
20962 }
20963 } // date from iso format or fallback
20964
20965
20966 function configFromString(config) {
20967 var matched = aspNetJsonRegex.exec(config._i);
20968
20969 if (matched !== null) {
20970 config._d = new Date(+matched[1]);
20971 return;
20972 }
20973
20974 configFromISO(config);
20975
20976 if (config._isValid === false) {
20977 delete config._isValid;
20978 } else {
20979 return;
20980 }
20981
20982 configFromRFC2822(config);
20983
20984 if (config._isValid === false) {
20985 delete config._isValid;
20986 } else {
20987 return;
20988 } // Final attempt, use Input Fallback
20989
20990
20991 hooks.createFromInputFallback(config);
20992 }
20993
20994 hooks.createFromInputFallback = deprecate('value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' + 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' + 'discouraged and will be removed in an upcoming major release. Please refer to ' + 'http://momentjs.com/guides/#/warnings/js-date/ for more info.', function (config) {
20995 config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
20996 }); // constant that refers to the ISO standard
20997
20998 hooks.ISO_8601 = function () {}; // constant that refers to the RFC 2822 form
20999
21000
21001 hooks.RFC_2822 = function () {}; // date from string and format string
21002
21003
21004 function configFromStringAndFormat(config) {
21005 // TODO: Move this to another part of the creation flow to prevent circular deps
21006 if (config._f === hooks.ISO_8601) {
21007 configFromISO(config);
21008 return;
21009 }
21010
21011 if (config._f === hooks.RFC_2822) {
21012 configFromRFC2822(config);
21013 return;
21014 }
21015
21016 config._a = [];
21017 getParsingFlags(config).empty = true; // This array is used to make a Date, either with `new Date` or `Date.UTC`
21018
21019 var string = '' + config._i,
21020 i,
21021 parsedInput,
21022 tokens,
21023 token,
21024 skipped,
21025 stringLength = string.length,
21026 totalParsedInputLength = 0;
21027 tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
21028
21029 for (i = 0; i < tokens.length; i++) {
21030 token = tokens[i];
21031 parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; // console.log('token', token, 'parsedInput', parsedInput,
21032 // 'regex', getParseRegexForToken(token, config));
21033
21034 if (parsedInput) {
21035 skipped = string.substr(0, string.indexOf(parsedInput));
21036
21037 if (skipped.length > 0) {
21038 getParsingFlags(config).unusedInput.push(skipped);
21039 }
21040
21041 string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
21042 totalParsedInputLength += parsedInput.length;
21043 } // don't parse if it's not a known token
21044
21045
21046 if (formatTokenFunctions[token]) {
21047 if (parsedInput) {
21048 getParsingFlags(config).empty = false;
21049 } else {
21050 getParsingFlags(config).unusedTokens.push(token);
21051 }
21052
21053 addTimeToArrayFromToken(token, parsedInput, config);
21054 } else if (config._strict && !parsedInput) {
21055 getParsingFlags(config).unusedTokens.push(token);
21056 }
21057 } // add remaining unparsed input length to the string
21058
21059
21060 getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
21061
21062 if (string.length > 0) {
21063 getParsingFlags(config).unusedInput.push(string);
21064 } // clear _12h flag if hour is <= 12
21065
21066
21067 if (config._a[HOUR] <= 12 && getParsingFlags(config).bigHour === true && config._a[HOUR] > 0) {
21068 getParsingFlags(config).bigHour = undefined;
21069 }
21070
21071 getParsingFlags(config).parsedDateParts = config._a.slice(0);
21072 getParsingFlags(config).meridiem = config._meridiem; // handle meridiem
21073
21074 config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
21075 configFromArray(config);
21076 checkOverflow(config);
21077 }
21078
21079 function meridiemFixWrap(locale, hour, meridiem) {
21080 var isPm;
21081
21082 if (meridiem == null) {
21083 // nothing to do
21084 return hour;
21085 }
21086
21087 if (locale.meridiemHour != null) {
21088 return locale.meridiemHour(hour, meridiem);
21089 } else if (locale.isPM != null) {
21090 // Fallback
21091 isPm = locale.isPM(meridiem);
21092
21093 if (isPm && hour < 12) {
21094 hour += 12;
21095 }
21096
21097 if (!isPm && hour === 12) {
21098 hour = 0;
21099 }
21100
21101 return hour;
21102 } else {
21103 // this is not supposed to happen
21104 return hour;
21105 }
21106 } // date from string and array of format strings
21107
21108
21109 function configFromStringAndArray(config) {
21110 var tempConfig, bestMoment, scoreToBeat, i, currentScore;
21111
21112 if (config._f.length === 0) {
21113 getParsingFlags(config).invalidFormat = true;
21114 config._d = new Date(NaN);
21115 return;
21116 }
21117
21118 for (i = 0; i < config._f.length; i++) {
21119 currentScore = 0;
21120 tempConfig = copyConfig({}, config);
21121
21122 if (config._useUTC != null) {
21123 tempConfig._useUTC = config._useUTC;
21124 }
21125
21126 tempConfig._f = config._f[i];
21127 configFromStringAndFormat(tempConfig);
21128
21129 if (!isValid(tempConfig)) {
21130 continue;
21131 } // if there is any input that was not parsed add a penalty for that format
21132
21133
21134 currentScore += getParsingFlags(tempConfig).charsLeftOver; //or tokens
21135
21136 currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
21137 getParsingFlags(tempConfig).score = currentScore;
21138
21139 if (scoreToBeat == null || currentScore < scoreToBeat) {
21140 scoreToBeat = currentScore;
21141 bestMoment = tempConfig;
21142 }
21143 }
21144
21145 extend(config, bestMoment || tempConfig);
21146 }
21147
21148 function configFromObject(config) {
21149 if (config._d) {
21150 return;
21151 }
21152
21153 var i = normalizeObjectUnits(config._i);
21154 config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
21155 return obj && parseInt(obj, 10);
21156 });
21157 configFromArray(config);
21158 }
21159
21160 function createFromConfig(config) {
21161 var res = new Moment(checkOverflow(prepareConfig(config)));
21162
21163 if (res._nextDay) {
21164 // Adding is smart enough around DST
21165 res.add(1, 'd');
21166 res._nextDay = undefined;
21167 }
21168
21169 return res;
21170 }
21171
21172 function prepareConfig(config) {
21173 var input = config._i,
21174 format = config._f;
21175 config._locale = config._locale || getLocale(config._l);
21176
21177 if (input === null || format === undefined && input === '') {
21178 return createInvalid({
21179 nullInput: true
21180 });
21181 }
21182
21183 if (typeof input === 'string') {
21184 config._i = input = config._locale.preparse(input);
21185 }
21186
21187 if (isMoment(input)) {
21188 return new Moment(checkOverflow(input));
21189 } else if (isDate(input)) {
21190 config._d = input;
21191 } else if (isArray(format)) {
21192 configFromStringAndArray(config);
21193 } else if (format) {
21194 configFromStringAndFormat(config);
21195 } else {
21196 configFromInput(config);
21197 }
21198
21199 if (!isValid(config)) {
21200 config._d = null;
21201 }
21202
21203 return config;
21204 }
21205
21206 function configFromInput(config) {
21207 var input = config._i;
21208
21209 if (isUndefined(input)) {
21210 config._d = new Date(hooks.now());
21211 } else if (isDate(input)) {
21212 config._d = new Date(input.valueOf());
21213 } else if (typeof input === 'string') {
21214 configFromString(config);
21215 } else if (isArray(input)) {
21216 config._a = map(input.slice(0), function (obj) {
21217 return parseInt(obj, 10);
21218 });
21219 configFromArray(config);
21220 } else if (isObject(input)) {
21221 configFromObject(config);
21222 } else if (isNumber(input)) {
21223 // from milliseconds
21224 config._d = new Date(input);
21225 } else {
21226 hooks.createFromInputFallback(config);
21227 }
21228 }
21229
21230 function createLocalOrUTC(input, format, locale, strict, isUTC) {
21231 var c = {};
21232
21233 if (locale === true || locale === false) {
21234 strict = locale;
21235 locale = undefined;
21236 }
21237
21238 if (isObject(input) && isObjectEmpty(input) || isArray(input) && input.length === 0) {
21239 input = undefined;
21240 } // object construction must be done this way.
21241 // https://github.com/moment/moment/issues/1423
21242
21243
21244 c._isAMomentObject = true;
21245 c._useUTC = c._isUTC = isUTC;
21246 c._l = locale;
21247 c._i = input;
21248 c._f = format;
21249 c._strict = strict;
21250 return createFromConfig(c);
21251 }
21252
21253 function createLocal(input, format, locale, strict) {
21254 return createLocalOrUTC(input, format, locale, strict, false);
21255 }
21256
21257 var prototypeMin = deprecate('moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', function () {
21258 var other = createLocal.apply(null, arguments);
21259
21260 if (this.isValid() && other.isValid()) {
21261 return other < this ? this : other;
21262 } else {
21263 return createInvalid();
21264 }
21265 });
21266 var prototypeMax = deprecate('moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', function () {
21267 var other = createLocal.apply(null, arguments);
21268
21269 if (this.isValid() && other.isValid()) {
21270 return other > this ? this : other;
21271 } else {
21272 return createInvalid();
21273 }
21274 }); // Pick a moment m from moments so that m[fn](other) is true for all
21275 // other. This relies on the function fn to be transitive.
21276 //
21277 // moments should either be an array of moment objects or an array, whose
21278 // first element is an array of moment objects.
21279
21280 function pickBy(fn, moments) {
21281 var res, i;
21282
21283 if (moments.length === 1 && isArray(moments[0])) {
21284 moments = moments[0];
21285 }
21286
21287 if (!moments.length) {
21288 return createLocal();
21289 }
21290
21291 res = moments[0];
21292
21293 for (i = 1; i < moments.length; ++i) {
21294 if (!moments[i].isValid() || moments[i][fn](res)) {
21295 res = moments[i];
21296 }
21297 }
21298
21299 return res;
21300 } // TODO: Use [].sort instead?
21301
21302
21303 function min() {
21304 var args = [].slice.call(arguments, 0);
21305 return pickBy('isBefore', args);
21306 }
21307
21308 function max() {
21309 var args = [].slice.call(arguments, 0);
21310 return pickBy('isAfter', args);
21311 }
21312
21313 var now = function () {
21314 return Date.now ? Date.now() : +new Date();
21315 };
21316
21317 var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
21318
21319 function isDurationValid(m) {
21320 for (var key in m) {
21321 if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
21322 return false;
21323 }
21324 }
21325
21326 var unitHasDecimal = false;
21327
21328 for (var i = 0; i < ordering.length; ++i) {
21329 if (m[ordering[i]]) {
21330 if (unitHasDecimal) {
21331 return false; // only allow non-integers for smallest unit
21332 }
21333
21334 if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
21335 unitHasDecimal = true;
21336 }
21337 }
21338 }
21339
21340 return true;
21341 }
21342
21343 function isValid$1() {
21344 return this._isValid;
21345 }
21346
21347 function createInvalid$1() {
21348 return createDuration(NaN);
21349 }
21350
21351 function Duration(duration) {
21352 var normalizedInput = normalizeObjectUnits(duration),
21353 years = normalizedInput.year || 0,
21354 quarters = normalizedInput.quarter || 0,
21355 months = normalizedInput.month || 0,
21356 weeks = normalizedInput.week || normalizedInput.isoWeek || 0,
21357 days = normalizedInput.day || 0,
21358 hours = normalizedInput.hour || 0,
21359 minutes = normalizedInput.minute || 0,
21360 seconds = normalizedInput.second || 0,
21361 milliseconds = normalizedInput.millisecond || 0;
21362 this._isValid = isDurationValid(normalizedInput); // representation for dateAddRemove
21363
21364 this._milliseconds = +milliseconds + seconds * 1e3 + // 1000
21365 minutes * 6e4 + // 1000 * 60
21366 hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
21367 // Because of dateAddRemove treats 24 hours as different from a
21368 // day when working around DST, we need to store them separately
21369
21370 this._days = +days + weeks * 7; // It is impossible to translate months into days without knowing
21371 // which months you are are talking about, so we have to store
21372 // it separately.
21373
21374 this._months = +months + quarters * 3 + years * 12;
21375 this._data = {};
21376 this._locale = getLocale();
21377
21378 this._bubble();
21379 }
21380
21381 function isDuration(obj) {
21382 return obj instanceof Duration;
21383 }
21384
21385 function absRound(number) {
21386 if (number < 0) {
21387 return Math.round(-1 * number) * -1;
21388 } else {
21389 return Math.round(number);
21390 }
21391 } // FORMATTING
21392
21393
21394 function offset(token, separator) {
21395 addFormatToken(token, 0, 0, function () {
21396 var offset = this.utcOffset();
21397 var sign = '+';
21398
21399 if (offset < 0) {
21400 offset = -offset;
21401 sign = '-';
21402 }
21403
21404 return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~offset % 60, 2);
21405 });
21406 }
21407
21408 offset('Z', ':');
21409 offset('ZZ', ''); // PARSING
21410
21411 addRegexToken('Z', matchShortOffset);
21412 addRegexToken('ZZ', matchShortOffset);
21413 addParseToken(['Z', 'ZZ'], function (input, array, config) {
21414 config._useUTC = true;
21415 config._tzm = offsetFromString(matchShortOffset, input);
21416 }); // HELPERS
21417 // timezone chunker
21418 // '+10:00' > ['10', '00']
21419 // '-1530' > ['-15', '30']
21420
21421 var chunkOffset = /([\+\-]|\d\d)/gi;
21422
21423 function offsetFromString(matcher, string) {
21424 var matches = (string || '').match(matcher);
21425
21426 if (matches === null) {
21427 return null;
21428 }
21429
21430 var chunk = matches[matches.length - 1] || [];
21431 var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
21432 var minutes = +(parts[1] * 60) + toInt(parts[2]);
21433 return minutes === 0 ? 0 : parts[0] === '+' ? minutes : -minutes;
21434 } // Return a moment from input, that is local/utc/zone equivalent to model.
21435
21436
21437 function cloneWithOffset(input, model) {
21438 var res, diff;
21439
21440 if (model._isUTC) {
21441 res = model.clone();
21442 diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf(); // Use low-level api, because this fn is low-level api.
21443
21444 res._d.setTime(res._d.valueOf() + diff);
21445
21446 hooks.updateOffset(res, false);
21447 return res;
21448 } else {
21449 return createLocal(input).local();
21450 }
21451 }
21452
21453 function getDateOffset(m) {
21454 // On Firefox.24 Date#getTimezoneOffset returns a floating point.
21455 // https://github.com/moment/moment/pull/1871
21456 return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
21457 } // HOOKS
21458 // This function will be called whenever a moment is mutated.
21459 // It is intended to keep the offset in sync with the timezone.
21460
21461
21462 hooks.updateOffset = function () {}; // MOMENTS
21463 // keepLocalTime = true means only change the timezone, without
21464 // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
21465 // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
21466 // +0200, so we adjust the time as needed, to be valid.
21467 //
21468 // Keeping the time actually adds/subtracts (one hour)
21469 // from the actual represented time. That is why we call updateOffset
21470 // a second time. In case it wants us to change the offset again
21471 // _changeInProgress == true case, then we have to adjust, because
21472 // there is no such time in the given timezone.
21473
21474
21475 function getSetOffset(input, keepLocalTime, keepMinutes) {
21476 var offset = this._offset || 0,
21477 localAdjust;
21478
21479 if (!this.isValid()) {
21480 return input != null ? this : NaN;
21481 }
21482
21483 if (input != null) {
21484 if (typeof input === 'string') {
21485 input = offsetFromString(matchShortOffset, input);
21486
21487 if (input === null) {
21488 return this;
21489 }
21490 } else if (Math.abs(input) < 16 && !keepMinutes) {
21491 input = input * 60;
21492 }
21493
21494 if (!this._isUTC && keepLocalTime) {
21495 localAdjust = getDateOffset(this);
21496 }
21497
21498 this._offset = input;
21499 this._isUTC = true;
21500
21501 if (localAdjust != null) {
21502 this.add(localAdjust, 'm');
21503 }
21504
21505 if (offset !== input) {
21506 if (!keepLocalTime || this._changeInProgress) {
21507 addSubtract(this, createDuration(input - offset, 'm'), 1, false);
21508 } else if (!this._changeInProgress) {
21509 this._changeInProgress = true;
21510 hooks.updateOffset(this, true);
21511 this._changeInProgress = null;
21512 }
21513 }
21514
21515 return this;
21516 } else {
21517 return this._isUTC ? offset : getDateOffset(this);
21518 }
21519 }
21520
21521 function getSetZone(input, keepLocalTime) {
21522 if (input != null) {
21523 if (typeof input !== 'string') {
21524 input = -input;
21525 }
21526
21527 this.utcOffset(input, keepLocalTime);
21528 return this;
21529 } else {
21530 return -this.utcOffset();
21531 }
21532 }
21533
21534 function setOffsetToUTC(keepLocalTime) {
21535 return this.utcOffset(0, keepLocalTime);
21536 }
21537
21538 function setOffsetToLocal(keepLocalTime) {
21539 if (this._isUTC) {
21540 this.utcOffset(0, keepLocalTime);
21541 this._isUTC = false;
21542
21543 if (keepLocalTime) {
21544 this.subtract(getDateOffset(this), 'm');
21545 }
21546 }
21547
21548 return this;
21549 }
21550
21551 function setOffsetToParsedOffset() {
21552 if (this._tzm != null) {
21553 this.utcOffset(this._tzm, false, true);
21554 } else if (typeof this._i === 'string') {
21555 var tZone = offsetFromString(matchOffset, this._i);
21556
21557 if (tZone != null) {
21558 this.utcOffset(tZone);
21559 } else {
21560 this.utcOffset(0, true);
21561 }
21562 }
21563
21564 return this;
21565 }
21566
21567 function hasAlignedHourOffset(input) {
21568 if (!this.isValid()) {
21569 return false;
21570 }
21571
21572 input = input ? createLocal(input).utcOffset() : 0;
21573 return (this.utcOffset() - input) % 60 === 0;
21574 }
21575
21576 function isDaylightSavingTime() {
21577 return this.utcOffset() > this.clone().month(0).utcOffset() || this.utcOffset() > this.clone().month(5).utcOffset();
21578 }
21579
21580 function isDaylightSavingTimeShifted() {
21581 if (!isUndefined(this._isDSTShifted)) {
21582 return this._isDSTShifted;
21583 }
21584
21585 var c = {};
21586 copyConfig(c, this);
21587 c = prepareConfig(c);
21588
21589 if (c._a) {
21590 var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
21591 this._isDSTShifted = this.isValid() && compareArrays(c._a, other.toArray()) > 0;
21592 } else {
21593 this._isDSTShifted = false;
21594 }
21595
21596 return this._isDSTShifted;
21597 }
21598
21599 function isLocal() {
21600 return this.isValid() ? !this._isUTC : false;
21601 }
21602
21603 function isUtcOffset() {
21604 return this.isValid() ? this._isUTC : false;
21605 }
21606
21607 function isUtc() {
21608 return this.isValid() ? this._isUTC && this._offset === 0 : false;
21609 } // ASP.NET json date format regex
21610
21611
21612 var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/; // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
21613 // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
21614 // and further modified to allow for strings containing both week and day
21615
21616 var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
21617
21618 function createDuration(input, key) {
21619 var duration = input,
21620 // matching against regexp is expensive, do it on demand
21621 match = null,
21622 sign,
21623 ret,
21624 diffRes;
21625
21626 if (isDuration(input)) {
21627 duration = {
21628 ms: input._milliseconds,
21629 d: input._days,
21630 M: input._months
21631 };
21632 } else if (isNumber(input)) {
21633 duration = {};
21634
21635 if (key) {
21636 duration[key] = input;
21637 } else {
21638 duration.milliseconds = input;
21639 }
21640 } else if (!!(match = aspNetRegex.exec(input))) {
21641 sign = match[1] === '-' ? -1 : 1;
21642 duration = {
21643 y: 0,
21644 d: toInt(match[DATE]) * sign,
21645 h: toInt(match[HOUR]) * sign,
21646 m: toInt(match[MINUTE]) * sign,
21647 s: toInt(match[SECOND]) * sign,
21648 ms: toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
21649
21650 };
21651 } else if (!!(match = isoRegex.exec(input))) {
21652 sign = match[1] === '-' ? -1 : 1;
21653 duration = {
21654 y: parseIso(match[2], sign),
21655 M: parseIso(match[3], sign),
21656 w: parseIso(match[4], sign),
21657 d: parseIso(match[5], sign),
21658 h: parseIso(match[6], sign),
21659 m: parseIso(match[7], sign),
21660 s: parseIso(match[8], sign)
21661 };
21662 } else if (duration == null) {
21663 // checks for null or undefined
21664 duration = {};
21665 } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
21666 diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
21667 duration = {};
21668 duration.ms = diffRes.milliseconds;
21669 duration.M = diffRes.months;
21670 }
21671
21672 ret = new Duration(duration);
21673
21674 if (isDuration(input) && hasOwnProp(input, '_locale')) {
21675 ret._locale = input._locale;
21676 }
21677
21678 return ret;
21679 }
21680
21681 createDuration.fn = Duration.prototype;
21682 createDuration.invalid = createInvalid$1;
21683
21684 function parseIso(inp, sign) {
21685 // We'd normally use ~~inp for this, but unfortunately it also
21686 // converts floats to ints.
21687 // inp may be undefined, so careful calling replace on it.
21688 var res = inp && parseFloat(inp.replace(',', '.')); // apply sign while we're at it
21689
21690 return (isNaN(res) ? 0 : res) * sign;
21691 }
21692
21693 function positiveMomentsDifference(base, other) {
21694 var res = {};
21695 res.months = other.month() - base.month() + (other.year() - base.year()) * 12;
21696
21697 if (base.clone().add(res.months, 'M').isAfter(other)) {
21698 --res.months;
21699 }
21700
21701 res.milliseconds = +other - +base.clone().add(res.months, 'M');
21702 return res;
21703 }
21704
21705 function momentsDifference(base, other) {
21706 var res;
21707
21708 if (!(base.isValid() && other.isValid())) {
21709 return {
21710 milliseconds: 0,
21711 months: 0
21712 };
21713 }
21714
21715 other = cloneWithOffset(other, base);
21716
21717 if (base.isBefore(other)) {
21718 res = positiveMomentsDifference(base, other);
21719 } else {
21720 res = positiveMomentsDifference(other, base);
21721 res.milliseconds = -res.milliseconds;
21722 res.months = -res.months;
21723 }
21724
21725 return res;
21726 } // TODO: remove 'name' arg after deprecation is removed
21727
21728
21729 function createAdder(direction, name) {
21730 return function (val, period) {
21731 var dur, tmp; //invert the arguments, but complain about it
21732
21733 if (period !== null && !isNaN(+period)) {
21734 deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' + 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
21735 tmp = val;
21736 val = period;
21737 period = tmp;
21738 }
21739
21740 val = typeof val === 'string' ? +val : val;
21741 dur = createDuration(val, period);
21742 addSubtract(this, dur, direction);
21743 return this;
21744 };
21745 }
21746
21747 function addSubtract(mom, duration, isAdding, updateOffset) {
21748 var milliseconds = duration._milliseconds,
21749 days = absRound(duration._days),
21750 months = absRound(duration._months);
21751
21752 if (!mom.isValid()) {
21753 // No op
21754 return;
21755 }
21756
21757 updateOffset = updateOffset == null ? true : updateOffset;
21758
21759 if (months) {
21760 setMonth(mom, get(mom, 'Month') + months * isAdding);
21761 }
21762
21763 if (days) {
21764 set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
21765 }
21766
21767 if (milliseconds) {
21768 mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
21769 }
21770
21771 if (updateOffset) {
21772 hooks.updateOffset(mom, days || months);
21773 }
21774 }
21775
21776 var add = createAdder(1, 'add');
21777 var subtract = createAdder(-1, 'subtract');
21778
21779 function getCalendarFormat(myMoment, now) {
21780 var diff = myMoment.diff(now, 'days', true);
21781 return diff < -6 ? 'sameElse' : diff < -1 ? 'lastWeek' : diff < 0 ? 'lastDay' : diff < 1 ? 'sameDay' : diff < 2 ? 'nextDay' : diff < 7 ? 'nextWeek' : 'sameElse';
21782 }
21783
21784 function calendar$1(time, formats) {
21785 // We want to compare the start of today, vs this.
21786 // Getting start-of-today depends on whether we're local/utc/offset or not.
21787 var now = time || createLocal(),
21788 sod = cloneWithOffset(now, this).startOf('day'),
21789 format = hooks.calendarFormat(this, sod) || 'sameElse';
21790 var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
21791 return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
21792 }
21793
21794 function clone() {
21795 return new Moment(this);
21796 }
21797
21798 function isAfter(input, units) {
21799 var localInput = isMoment(input) ? input : createLocal(input);
21800
21801 if (!(this.isValid() && localInput.isValid())) {
21802 return false;
21803 }
21804
21805 units = normalizeUnits(units) || 'millisecond';
21806
21807 if (units === 'millisecond') {
21808 return this.valueOf() > localInput.valueOf();
21809 } else {
21810 return localInput.valueOf() < this.clone().startOf(units).valueOf();
21811 }
21812 }
21813
21814 function isBefore(input, units) {
21815 var localInput = isMoment(input) ? input : createLocal(input);
21816
21817 if (!(this.isValid() && localInput.isValid())) {
21818 return false;
21819 }
21820
21821 units = normalizeUnits(units) || 'millisecond';
21822
21823 if (units === 'millisecond') {
21824 return this.valueOf() < localInput.valueOf();
21825 } else {
21826 return this.clone().endOf(units).valueOf() < localInput.valueOf();
21827 }
21828 }
21829
21830 function isBetween(from, to, units, inclusivity) {
21831 var localFrom = isMoment(from) ? from : createLocal(from),
21832 localTo = isMoment(to) ? to : createLocal(to);
21833
21834 if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
21835 return false;
21836 }
21837
21838 inclusivity = inclusivity || '()';
21839 return (inclusivity[0] === '(' ? this.isAfter(localFrom, units) : !this.isBefore(localFrom, units)) && (inclusivity[1] === ')' ? this.isBefore(localTo, units) : !this.isAfter(localTo, units));
21840 }
21841
21842 function isSame(input, units) {
21843 var localInput = isMoment(input) ? input : createLocal(input),
21844 inputMs;
21845
21846 if (!(this.isValid() && localInput.isValid())) {
21847 return false;
21848 }
21849
21850 units = normalizeUnits(units) || 'millisecond';
21851
21852 if (units === 'millisecond') {
21853 return this.valueOf() === localInput.valueOf();
21854 } else {
21855 inputMs = localInput.valueOf();
21856 return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
21857 }
21858 }
21859
21860 function isSameOrAfter(input, units) {
21861 return this.isSame(input, units) || this.isAfter(input, units);
21862 }
21863
21864 function isSameOrBefore(input, units) {
21865 return this.isSame(input, units) || this.isBefore(input, units);
21866 }
21867
21868 function diff(input, units, asFloat) {
21869 var that, zoneDelta, output;
21870
21871 if (!this.isValid()) {
21872 return NaN;
21873 }
21874
21875 that = cloneWithOffset(input, this);
21876
21877 if (!that.isValid()) {
21878 return NaN;
21879 }
21880
21881 zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
21882 units = normalizeUnits(units);
21883
21884 switch (units) {
21885 case 'year':
21886 output = monthDiff(this, that) / 12;
21887 break;
21888
21889 case 'month':
21890 output = monthDiff(this, that);
21891 break;
21892
21893 case 'quarter':
21894 output = monthDiff(this, that) / 3;
21895 break;
21896
21897 case 'second':
21898 output = (this - that) / 1e3;
21899 break;
21900 // 1000
21901
21902 case 'minute':
21903 output = (this - that) / 6e4;
21904 break;
21905 // 1000 * 60
21906
21907 case 'hour':
21908 output = (this - that) / 36e5;
21909 break;
21910 // 1000 * 60 * 60
21911
21912 case 'day':
21913 output = (this - that - zoneDelta) / 864e5;
21914 break;
21915 // 1000 * 60 * 60 * 24, negate dst
21916
21917 case 'week':
21918 output = (this - that - zoneDelta) / 6048e5;
21919 break;
21920 // 1000 * 60 * 60 * 24 * 7, negate dst
21921
21922 default:
21923 output = this - that;
21924 }
21925
21926 return asFloat ? output : absFloor(output);
21927 }
21928
21929 function monthDiff(a, b) {
21930 // difference in months
21931 var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()),
21932 // b is in (anchor - 1 month, anchor + 1 month)
21933 anchor = a.clone().add(wholeMonthDiff, 'months'),
21934 anchor2,
21935 adjust;
21936
21937 if (b - anchor < 0) {
21938 anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); // linear across the month
21939
21940 adjust = (b - anchor) / (anchor - anchor2);
21941 } else {
21942 anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); // linear across the month
21943
21944 adjust = (b - anchor) / (anchor2 - anchor);
21945 } //check for negative zero, return zero if negative zero
21946
21947
21948 return -(wholeMonthDiff + adjust) || 0;
21949 }
21950
21951 hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
21952 hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
21953
21954 function toString() {
21955 return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
21956 }
21957
21958 function toISOString(keepOffset) {
21959 if (!this.isValid()) {
21960 return null;
21961 }
21962
21963 var utc = keepOffset !== true;
21964 var m = utc ? this.clone().utc() : this;
21965
21966 if (m.year() < 0 || m.year() > 9999) {
21967 return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ');
21968 }
21969
21970 if (isFunction(Date.prototype.toISOString)) {
21971 // native implementation is ~50x faster, use it when we can
21972 if (utc) {
21973 return this.toDate().toISOString();
21974 } else {
21975 return new Date(this.valueOf() + this.utcOffset() * 60 * 1000).toISOString().replace('Z', formatMoment(m, 'Z'));
21976 }
21977 }
21978
21979 return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
21980 }
21981 /**
21982 * Return a human readable representation of a moment that can
21983 * also be evaluated to get a new moment which is the same
21984 *
21985 * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
21986 */
21987
21988
21989 function inspect() {
21990 if (!this.isValid()) {
21991 return 'moment.invalid(/* ' + this._i + ' */)';
21992 }
21993
21994 var func = 'moment';
21995 var zone = '';
21996
21997 if (!this.isLocal()) {
21998 func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
21999 zone = 'Z';
22000 }
22001
22002 var prefix = '[' + func + '("]';
22003 var year = 0 <= this.year() && this.year() <= 9999 ? 'YYYY' : 'YYYYYY';
22004 var datetime = '-MM-DD[T]HH:mm:ss.SSS';
22005 var suffix = zone + '[")]';
22006 return this.format(prefix + year + datetime + suffix);
22007 }
22008
22009 function format(inputString) {
22010 if (!inputString) {
22011 inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
22012 }
22013
22014 var output = formatMoment(this, inputString);
22015 return this.localeData().postformat(output);
22016 }
22017
22018 function from(time, withoutSuffix) {
22019 if (this.isValid() && (isMoment(time) && time.isValid() || createLocal(time).isValid())) {
22020 return createDuration({
22021 to: this,
22022 from: time
22023 }).locale(this.locale()).humanize(!withoutSuffix);
22024 } else {
22025 return this.localeData().invalidDate();
22026 }
22027 }
22028
22029 function fromNow(withoutSuffix) {
22030 return this.from(createLocal(), withoutSuffix);
22031 }
22032
22033 function to(time, withoutSuffix) {
22034 if (this.isValid() && (isMoment(time) && time.isValid() || createLocal(time).isValid())) {
22035 return createDuration({
22036 from: this,
22037 to: time
22038 }).locale(this.locale()).humanize(!withoutSuffix);
22039 } else {
22040 return this.localeData().invalidDate();
22041 }
22042 }
22043
22044 function toNow(withoutSuffix) {
22045 return this.to(createLocal(), withoutSuffix);
22046 } // If passed a locale key, it will set the locale for this
22047 // instance. Otherwise, it will return the locale configuration
22048 // variables for this instance.
22049
22050
22051 function locale(key) {
22052 var newLocaleData;
22053
22054 if (key === undefined) {
22055 return this._locale._abbr;
22056 } else {
22057 newLocaleData = getLocale(key);
22058
22059 if (newLocaleData != null) {
22060 this._locale = newLocaleData;
22061 }
22062
22063 return this;
22064 }
22065 }
22066
22067 var lang = deprecate('moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', function (key) {
22068 if (key === undefined) {
22069 return this.localeData();
22070 } else {
22071 return this.locale(key);
22072 }
22073 });
22074
22075 function localeData() {
22076 return this._locale;
22077 }
22078
22079 var MS_PER_SECOND = 1000;
22080 var MS_PER_MINUTE = 60 * MS_PER_SECOND;
22081 var MS_PER_HOUR = 60 * MS_PER_MINUTE;
22082 var MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR; // actual modulo - handles negative numbers (for dates before 1970):
22083
22084 function mod$1(dividend, divisor) {
22085 return (dividend % divisor + divisor) % divisor;
22086 }
22087
22088 function localStartOfDate(y, m, d) {
22089 // the date constructor remaps years 0-99 to 1900-1999
22090 if (y < 100 && y >= 0) {
22091 // preserve leap years using a full 400 year cycle, then reset
22092 return new Date(y + 400, m, d) - MS_PER_400_YEARS;
22093 } else {
22094 return new Date(y, m, d).valueOf();
22095 }
22096 }
22097
22098 function utcStartOfDate(y, m, d) {
22099 // Date.UTC remaps years 0-99 to 1900-1999
22100 if (y < 100 && y >= 0) {
22101 // preserve leap years using a full 400 year cycle, then reset
22102 return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
22103 } else {
22104 return Date.UTC(y, m, d);
22105 }
22106 }
22107
22108 function startOf(units) {
22109 var time;
22110 units = normalizeUnits(units);
22111
22112 if (units === undefined || units === 'millisecond' || !this.isValid()) {
22113 return this;
22114 }
22115
22116 var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
22117
22118 switch (units) {
22119 case 'year':
22120 time = startOfDate(this.year(), 0, 1);
22121 break;
22122
22123 case 'quarter':
22124 time = startOfDate(this.year(), this.month() - this.month() % 3, 1);
22125 break;
22126
22127 case 'month':
22128 time = startOfDate(this.year(), this.month(), 1);
22129 break;
22130
22131 case 'week':
22132 time = startOfDate(this.year(), this.month(), this.date() - this.weekday());
22133 break;
22134
22135 case 'isoWeek':
22136 time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1));
22137 break;
22138
22139 case 'day':
22140 case 'date':
22141 time = startOfDate(this.year(), this.month(), this.date());
22142 break;
22143
22144 case 'hour':
22145 time = this._d.valueOf();
22146 time -= mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR);
22147 break;
22148
22149 case 'minute':
22150 time = this._d.valueOf();
22151 time -= mod$1(time, MS_PER_MINUTE);
22152 break;
22153
22154 case 'second':
22155 time = this._d.valueOf();
22156 time -= mod$1(time, MS_PER_SECOND);
22157 break;
22158 }
22159
22160 this._d.setTime(time);
22161
22162 hooks.updateOffset(this, true);
22163 return this;
22164 }
22165
22166 function endOf(units) {
22167 var time;
22168 units = normalizeUnits(units);
22169
22170 if (units === undefined || units === 'millisecond' || !this.isValid()) {
22171 return this;
22172 }
22173
22174 var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
22175
22176 switch (units) {
22177 case 'year':
22178 time = startOfDate(this.year() + 1, 0, 1) - 1;
22179 break;
22180
22181 case 'quarter':
22182 time = startOfDate(this.year(), this.month() - this.month() % 3 + 3, 1) - 1;
22183 break;
22184
22185 case 'month':
22186 time = startOfDate(this.year(), this.month() + 1, 1) - 1;
22187 break;
22188
22189 case 'week':
22190 time = startOfDate(this.year(), this.month(), this.date() - this.weekday() + 7) - 1;
22191 break;
22192
22193 case 'isoWeek':
22194 time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1) + 7) - 1;
22195 break;
22196
22197 case 'day':
22198 case 'date':
22199 time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
22200 break;
22201
22202 case 'hour':
22203 time = this._d.valueOf();
22204 time += MS_PER_HOUR - mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR) - 1;
22205 break;
22206
22207 case 'minute':
22208 time = this._d.valueOf();
22209 time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
22210 break;
22211
22212 case 'second':
22213 time = this._d.valueOf();
22214 time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
22215 break;
22216 }
22217
22218 this._d.setTime(time);
22219
22220 hooks.updateOffset(this, true);
22221 return this;
22222 }
22223
22224 function valueOf() {
22225 return this._d.valueOf() - (this._offset || 0) * 60000;
22226 }
22227
22228 function unix() {
22229 return Math.floor(this.valueOf() / 1000);
22230 }
22231
22232 function toDate() {
22233 return new Date(this.valueOf());
22234 }
22235
22236 function toArray() {
22237 var m = this;
22238 return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
22239 }
22240
22241 function toObject() {
22242 var m = this;
22243 return {
22244 years: m.year(),
22245 months: m.month(),
22246 date: m.date(),
22247 hours: m.hours(),
22248 minutes: m.minutes(),
22249 seconds: m.seconds(),
22250 milliseconds: m.milliseconds()
22251 };
22252 }
22253
22254 function toJSON() {
22255 // new Date(NaN).toJSON() === null
22256 return this.isValid() ? this.toISOString() : null;
22257 }
22258
22259 function isValid$2() {
22260 return isValid(this);
22261 }
22262
22263 function parsingFlags() {
22264 return extend({}, getParsingFlags(this));
22265 }
22266
22267 function invalidAt() {
22268 return getParsingFlags(this).overflow;
22269 }
22270
22271 function creationData() {
22272 return {
22273 input: this._i,
22274 format: this._f,
22275 locale: this._locale,
22276 isUTC: this._isUTC,
22277 strict: this._strict
22278 };
22279 } // FORMATTING
22280
22281
22282 addFormatToken(0, ['gg', 2], 0, function () {
22283 return this.weekYear() % 100;
22284 });
22285 addFormatToken(0, ['GG', 2], 0, function () {
22286 return this.isoWeekYear() % 100;
22287 });
22288
22289 function addWeekYearFormatToken(token, getter) {
22290 addFormatToken(0, [token, token.length], 0, getter);
22291 }
22292
22293 addWeekYearFormatToken('gggg', 'weekYear');
22294 addWeekYearFormatToken('ggggg', 'weekYear');
22295 addWeekYearFormatToken('GGGG', 'isoWeekYear');
22296 addWeekYearFormatToken('GGGGG', 'isoWeekYear'); // ALIASES
22297
22298 addUnitAlias('weekYear', 'gg');
22299 addUnitAlias('isoWeekYear', 'GG'); // PRIORITY
22300
22301 addUnitPriority('weekYear', 1);
22302 addUnitPriority('isoWeekYear', 1); // PARSING
22303
22304 addRegexToken('G', matchSigned);
22305 addRegexToken('g', matchSigned);
22306 addRegexToken('GG', match1to2, match2);
22307 addRegexToken('gg', match1to2, match2);
22308 addRegexToken('GGGG', match1to4, match4);
22309 addRegexToken('gggg', match1to4, match4);
22310 addRegexToken('GGGGG', match1to6, match6);
22311 addRegexToken('ggggg', match1to6, match6);
22312 addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
22313 week[token.substr(0, 2)] = toInt(input);
22314 });
22315 addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
22316 week[token] = hooks.parseTwoDigitYear(input);
22317 }); // MOMENTS
22318
22319 function getSetWeekYear(input) {
22320 return getSetWeekYearHelper.call(this, input, this.week(), this.weekday(), this.localeData()._week.dow, this.localeData()._week.doy);
22321 }
22322
22323 function getSetISOWeekYear(input) {
22324 return getSetWeekYearHelper.call(this, input, this.isoWeek(), this.isoWeekday(), 1, 4);
22325 }
22326
22327 function getISOWeeksInYear() {
22328 return weeksInYear(this.year(), 1, 4);
22329 }
22330
22331 function getWeeksInYear() {
22332 var weekInfo = this.localeData()._week;
22333
22334 return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
22335 }
22336
22337 function getSetWeekYearHelper(input, week, weekday, dow, doy) {
22338 var weeksTarget;
22339
22340 if (input == null) {
22341 return weekOfYear(this, dow, doy).year;
22342 } else {
22343 weeksTarget = weeksInYear(input, dow, doy);
22344
22345 if (week > weeksTarget) {
22346 week = weeksTarget;
22347 }
22348
22349 return setWeekAll.call(this, input, week, weekday, dow, doy);
22350 }
22351 }
22352
22353 function setWeekAll(weekYear, week, weekday, dow, doy) {
22354 var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
22355 date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
22356 this.year(date.getUTCFullYear());
22357 this.month(date.getUTCMonth());
22358 this.date(date.getUTCDate());
22359 return this;
22360 } // FORMATTING
22361
22362
22363 addFormatToken('Q', 0, 'Qo', 'quarter'); // ALIASES
22364
22365 addUnitAlias('quarter', 'Q'); // PRIORITY
22366
22367 addUnitPriority('quarter', 7); // PARSING
22368
22369 addRegexToken('Q', match1);
22370 addParseToken('Q', function (input, array) {
22371 array[MONTH] = (toInt(input) - 1) * 3;
22372 }); // MOMENTS
22373
22374 function getSetQuarter(input) {
22375 return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
22376 } // FORMATTING
22377
22378
22379 addFormatToken('D', ['DD', 2], 'Do', 'date'); // ALIASES
22380
22381 addUnitAlias('date', 'D'); // PRIORITY
22382
22383 addUnitPriority('date', 9); // PARSING
22384
22385 addRegexToken('D', match1to2);
22386 addRegexToken('DD', match1to2, match2);
22387 addRegexToken('Do', function (isStrict, locale) {
22388 // TODO: Remove "ordinalParse" fallback in next major release.
22389 return isStrict ? locale._dayOfMonthOrdinalParse || locale._ordinalParse : locale._dayOfMonthOrdinalParseLenient;
22390 });
22391 addParseToken(['D', 'DD'], DATE);
22392 addParseToken('Do', function (input, array) {
22393 array[DATE] = toInt(input.match(match1to2)[0]);
22394 }); // MOMENTS
22395
22396 var getSetDayOfMonth = makeGetSet('Date', true); // FORMATTING
22397
22398 addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); // ALIASES
22399
22400 addUnitAlias('dayOfYear', 'DDD'); // PRIORITY
22401
22402 addUnitPriority('dayOfYear', 4); // PARSING
22403
22404 addRegexToken('DDD', match1to3);
22405 addRegexToken('DDDD', match3);
22406 addParseToken(['DDD', 'DDDD'], function (input, array, config) {
22407 config._dayOfYear = toInt(input);
22408 }); // HELPERS
22409 // MOMENTS
22410
22411 function getSetDayOfYear(input) {
22412 var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
22413 return input == null ? dayOfYear : this.add(input - dayOfYear, 'd');
22414 } // FORMATTING
22415
22416
22417 addFormatToken('m', ['mm', 2], 0, 'minute'); // ALIASES
22418
22419 addUnitAlias('minute', 'm'); // PRIORITY
22420
22421 addUnitPriority('minute', 14); // PARSING
22422
22423 addRegexToken('m', match1to2);
22424 addRegexToken('mm', match1to2, match2);
22425 addParseToken(['m', 'mm'], MINUTE); // MOMENTS
22426
22427 var getSetMinute = makeGetSet('Minutes', false); // FORMATTING
22428
22429 addFormatToken('s', ['ss', 2], 0, 'second'); // ALIASES
22430
22431 addUnitAlias('second', 's'); // PRIORITY
22432
22433 addUnitPriority('second', 15); // PARSING
22434
22435 addRegexToken('s', match1to2);
22436 addRegexToken('ss', match1to2, match2);
22437 addParseToken(['s', 'ss'], SECOND); // MOMENTS
22438
22439 var getSetSecond = makeGetSet('Seconds', false); // FORMATTING
22440
22441 addFormatToken('S', 0, 0, function () {
22442 return ~~(this.millisecond() / 100);
22443 });
22444 addFormatToken(0, ['SS', 2], 0, function () {
22445 return ~~(this.millisecond() / 10);
22446 });
22447 addFormatToken(0, ['SSS', 3], 0, 'millisecond');
22448 addFormatToken(0, ['SSSS', 4], 0, function () {
22449 return this.millisecond() * 10;
22450 });
22451 addFormatToken(0, ['SSSSS', 5], 0, function () {
22452 return this.millisecond() * 100;
22453 });
22454 addFormatToken(0, ['SSSSSS', 6], 0, function () {
22455 return this.millisecond() * 1000;
22456 });
22457 addFormatToken(0, ['SSSSSSS', 7], 0, function () {
22458 return this.millisecond() * 10000;
22459 });
22460 addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
22461 return this.millisecond() * 100000;
22462 });
22463 addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
22464 return this.millisecond() * 1000000;
22465 }); // ALIASES
22466
22467 addUnitAlias('millisecond', 'ms'); // PRIORITY
22468
22469 addUnitPriority('millisecond', 16); // PARSING
22470
22471 addRegexToken('S', match1to3, match1);
22472 addRegexToken('SS', match1to3, match2);
22473 addRegexToken('SSS', match1to3, match3);
22474 var token;
22475
22476 for (token = 'SSSS'; token.length <= 9; token += 'S') {
22477 addRegexToken(token, matchUnsigned);
22478 }
22479
22480 function parseMs(input, array) {
22481 array[MILLISECOND] = toInt(('0.' + input) * 1000);
22482 }
22483
22484 for (token = 'S'; token.length <= 9; token += 'S') {
22485 addParseToken(token, parseMs);
22486 } // MOMENTS
22487
22488
22489 var getSetMillisecond = makeGetSet('Milliseconds', false); // FORMATTING
22490
22491 addFormatToken('z', 0, 0, 'zoneAbbr');
22492 addFormatToken('zz', 0, 0, 'zoneName'); // MOMENTS
22493
22494 function getZoneAbbr() {
22495 return this._isUTC ? 'UTC' : '';
22496 }
22497
22498 function getZoneName() {
22499 return this._isUTC ? 'Coordinated Universal Time' : '';
22500 }
22501
22502 var proto = Moment.prototype;
22503 proto.add = add;
22504 proto.calendar = calendar$1;
22505 proto.clone = clone;
22506 proto.diff = diff;
22507 proto.endOf = endOf;
22508 proto.format = format;
22509 proto.from = from;
22510 proto.fromNow = fromNow;
22511 proto.to = to;
22512 proto.toNow = toNow;
22513 proto.get = stringGet;
22514 proto.invalidAt = invalidAt;
22515 proto.isAfter = isAfter;
22516 proto.isBefore = isBefore;
22517 proto.isBetween = isBetween;
22518 proto.isSame = isSame;
22519 proto.isSameOrAfter = isSameOrAfter;
22520 proto.isSameOrBefore = isSameOrBefore;
22521 proto.isValid = isValid$2;
22522 proto.lang = lang;
22523 proto.locale = locale;
22524 proto.localeData = localeData;
22525 proto.max = prototypeMax;
22526 proto.min = prototypeMin;
22527 proto.parsingFlags = parsingFlags;
22528 proto.set = stringSet;
22529 proto.startOf = startOf;
22530 proto.subtract = subtract;
22531 proto.toArray = toArray;
22532 proto.toObject = toObject;
22533 proto.toDate = toDate;
22534 proto.toISOString = toISOString;
22535 proto.inspect = inspect;
22536 proto.toJSON = toJSON;
22537 proto.toString = toString;
22538 proto.unix = unix;
22539 proto.valueOf = valueOf;
22540 proto.creationData = creationData;
22541 proto.year = getSetYear;
22542 proto.isLeapYear = getIsLeapYear;
22543 proto.weekYear = getSetWeekYear;
22544 proto.isoWeekYear = getSetISOWeekYear;
22545 proto.quarter = proto.quarters = getSetQuarter;
22546 proto.month = getSetMonth;
22547 proto.daysInMonth = getDaysInMonth;
22548 proto.week = proto.weeks = getSetWeek;
22549 proto.isoWeek = proto.isoWeeks = getSetISOWeek;
22550 proto.weeksInYear = getWeeksInYear;
22551 proto.isoWeeksInYear = getISOWeeksInYear;
22552 proto.date = getSetDayOfMonth;
22553 proto.day = proto.days = getSetDayOfWeek;
22554 proto.weekday = getSetLocaleDayOfWeek;
22555 proto.isoWeekday = getSetISODayOfWeek;
22556 proto.dayOfYear = getSetDayOfYear;
22557 proto.hour = proto.hours = getSetHour;
22558 proto.minute = proto.minutes = getSetMinute;
22559 proto.second = proto.seconds = getSetSecond;
22560 proto.millisecond = proto.milliseconds = getSetMillisecond;
22561 proto.utcOffset = getSetOffset;
22562 proto.utc = setOffsetToUTC;
22563 proto.local = setOffsetToLocal;
22564 proto.parseZone = setOffsetToParsedOffset;
22565 proto.hasAlignedHourOffset = hasAlignedHourOffset;
22566 proto.isDST = isDaylightSavingTime;
22567 proto.isLocal = isLocal;
22568 proto.isUtcOffset = isUtcOffset;
22569 proto.isUtc = isUtc;
22570 proto.isUTC = isUtc;
22571 proto.zoneAbbr = getZoneAbbr;
22572 proto.zoneName = getZoneName;
22573 proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
22574 proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
22575 proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);
22576 proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
22577 proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
22578
22579 function createUnix(input) {
22580 return createLocal(input * 1000);
22581 }
22582
22583 function createInZone() {
22584 return createLocal.apply(null, arguments).parseZone();
22585 }
22586
22587 function preParsePostFormat(string) {
22588 return string;
22589 }
22590
22591 var proto$1 = Locale.prototype;
22592 proto$1.calendar = calendar;
22593 proto$1.longDateFormat = longDateFormat;
22594 proto$1.invalidDate = invalidDate;
22595 proto$1.ordinal = ordinal;
22596 proto$1.preparse = preParsePostFormat;
22597 proto$1.postformat = preParsePostFormat;
22598 proto$1.relativeTime = relativeTime;
22599 proto$1.pastFuture = pastFuture;
22600 proto$1.set = set;
22601 proto$1.months = localeMonths;
22602 proto$1.monthsShort = localeMonthsShort;
22603 proto$1.monthsParse = localeMonthsParse;
22604 proto$1.monthsRegex = monthsRegex;
22605 proto$1.monthsShortRegex = monthsShortRegex;
22606 proto$1.week = localeWeek;
22607 proto$1.firstDayOfYear = localeFirstDayOfYear;
22608 proto$1.firstDayOfWeek = localeFirstDayOfWeek;
22609 proto$1.weekdays = localeWeekdays;
22610 proto$1.weekdaysMin = localeWeekdaysMin;
22611 proto$1.weekdaysShort = localeWeekdaysShort;
22612 proto$1.weekdaysParse = localeWeekdaysParse;
22613 proto$1.weekdaysRegex = weekdaysRegex;
22614 proto$1.weekdaysShortRegex = weekdaysShortRegex;
22615 proto$1.weekdaysMinRegex = weekdaysMinRegex;
22616 proto$1.isPM = localeIsPM;
22617 proto$1.meridiem = localeMeridiem;
22618
22619 function get$1(format, index, field, setter) {
22620 var locale = getLocale();
22621 var utc = createUTC().set(setter, index);
22622 return locale[field](utc, format);
22623 }
22624
22625 function listMonthsImpl(format, index, field) {
22626 if (isNumber(format)) {
22627 index = format;
22628 format = undefined;
22629 }
22630
22631 format = format || '';
22632
22633 if (index != null) {
22634 return get$1(format, index, field, 'month');
22635 }
22636
22637 var i;
22638 var out = [];
22639
22640 for (i = 0; i < 12; i++) {
22641 out[i] = get$1(format, i, field, 'month');
22642 }
22643
22644 return out;
22645 } // ()
22646 // (5)
22647 // (fmt, 5)
22648 // (fmt)
22649 // (true)
22650 // (true, 5)
22651 // (true, fmt, 5)
22652 // (true, fmt)
22653
22654
22655 function listWeekdaysImpl(localeSorted, format, index, field) {
22656 if (typeof localeSorted === 'boolean') {
22657 if (isNumber(format)) {
22658 index = format;
22659 format = undefined;
22660 }
22661
22662 format = format || '';
22663 } else {
22664 format = localeSorted;
22665 index = format;
22666 localeSorted = false;
22667
22668 if (isNumber(format)) {
22669 index = format;
22670 format = undefined;
22671 }
22672
22673 format = format || '';
22674 }
22675
22676 var locale = getLocale(),
22677 shift = localeSorted ? locale._week.dow : 0;
22678
22679 if (index != null) {
22680 return get$1(format, (index + shift) % 7, field, 'day');
22681 }
22682
22683 var i;
22684 var out = [];
22685
22686 for (i = 0; i < 7; i++) {
22687 out[i] = get$1(format, (i + shift) % 7, field, 'day');
22688 }
22689
22690 return out;
22691 }
22692
22693 function listMonths(format, index) {
22694 return listMonthsImpl(format, index, 'months');
22695 }
22696
22697 function listMonthsShort(format, index) {
22698 return listMonthsImpl(format, index, 'monthsShort');
22699 }
22700
22701 function listWeekdays(localeSorted, format, index) {
22702 return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
22703 }
22704
22705 function listWeekdaysShort(localeSorted, format, index) {
22706 return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
22707 }
22708
22709 function listWeekdaysMin(localeSorted, format, index) {
22710 return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
22711 }
22712
22713 getSetGlobalLocale('en', {
22714 dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
22715 ordinal: function (number) {
22716 var b = number % 10,
22717 output = toInt(number % 100 / 10) === 1 ? 'th' : b === 1 ? 'st' : b === 2 ? 'nd' : b === 3 ? 'rd' : 'th';
22718 return number + output;
22719 }
22720 }); // Side effect imports
22721
22722 hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
22723 hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
22724 var mathAbs = Math.abs;
22725
22726 function abs() {
22727 var data = this._data;
22728 this._milliseconds = mathAbs(this._milliseconds);
22729 this._days = mathAbs(this._days);
22730 this._months = mathAbs(this._months);
22731 data.milliseconds = mathAbs(data.milliseconds);
22732 data.seconds = mathAbs(data.seconds);
22733 data.minutes = mathAbs(data.minutes);
22734 data.hours = mathAbs(data.hours);
22735 data.months = mathAbs(data.months);
22736 data.years = mathAbs(data.years);
22737 return this;
22738 }
22739
22740 function addSubtract$1(duration, input, value, direction) {
22741 var other = createDuration(input, value);
22742 duration._milliseconds += direction * other._milliseconds;
22743 duration._days += direction * other._days;
22744 duration._months += direction * other._months;
22745 return duration._bubble();
22746 } // supports only 2.0-style add(1, 's') or add(duration)
22747
22748
22749 function add$1(input, value) {
22750 return addSubtract$1(this, input, value, 1);
22751 } // supports only 2.0-style subtract(1, 's') or subtract(duration)
22752
22753
22754 function subtract$1(input, value) {
22755 return addSubtract$1(this, input, value, -1);
22756 }
22757
22758 function absCeil(number) {
22759 if (number < 0) {
22760 return Math.floor(number);
22761 } else {
22762 return Math.ceil(number);
22763 }
22764 }
22765
22766 function bubble() {
22767 var milliseconds = this._milliseconds;
22768 var days = this._days;
22769 var months = this._months;
22770 var data = this._data;
22771 var seconds, minutes, hours, years, monthsFromDays; // if we have a mix of positive and negative values, bubble down first
22772 // check: https://github.com/moment/moment/issues/2166
22773
22774 if (!(milliseconds >= 0 && days >= 0 && months >= 0 || milliseconds <= 0 && days <= 0 && months <= 0)) {
22775 milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
22776 days = 0;
22777 months = 0;
22778 } // The following code bubbles up values, see the tests for
22779 // examples of what that means.
22780
22781
22782 data.milliseconds = milliseconds % 1000;
22783 seconds = absFloor(milliseconds / 1000);
22784 data.seconds = seconds % 60;
22785 minutes = absFloor(seconds / 60);
22786 data.minutes = minutes % 60;
22787 hours = absFloor(minutes / 60);
22788 data.hours = hours % 24;
22789 days += absFloor(hours / 24); // convert days to months
22790
22791 monthsFromDays = absFloor(daysToMonths(days));
22792 months += monthsFromDays;
22793 days -= absCeil(monthsToDays(monthsFromDays)); // 12 months -> 1 year
22794
22795 years = absFloor(months / 12);
22796 months %= 12;
22797 data.days = days;
22798 data.months = months;
22799 data.years = years;
22800 return this;
22801 }
22802
22803 function daysToMonths(days) {
22804 // 400 years have 146097 days (taking into account leap year rules)
22805 // 400 years have 12 months === 4800
22806 return days * 4800 / 146097;
22807 }
22808
22809 function monthsToDays(months) {
22810 // the reverse of daysToMonths
22811 return months * 146097 / 4800;
22812 }
22813
22814 function as(units) {
22815 if (!this.isValid()) {
22816 return NaN;
22817 }
22818
22819 var days;
22820 var months;
22821 var milliseconds = this._milliseconds;
22822 units = normalizeUnits(units);
22823
22824 if (units === 'month' || units === 'quarter' || units === 'year') {
22825 days = this._days + milliseconds / 864e5;
22826 months = this._months + daysToMonths(days);
22827
22828 switch (units) {
22829 case 'month':
22830 return months;
22831
22832 case 'quarter':
22833 return months / 3;
22834
22835 case 'year':
22836 return months / 12;
22837 }
22838 } else {
22839 // handle milliseconds separately because of floating point math errors (issue #1867)
22840 days = this._days + Math.round(monthsToDays(this._months));
22841
22842 switch (units) {
22843 case 'week':
22844 return days / 7 + milliseconds / 6048e5;
22845
22846 case 'day':
22847 return days + milliseconds / 864e5;
22848
22849 case 'hour':
22850 return days * 24 + milliseconds / 36e5;
22851
22852 case 'minute':
22853 return days * 1440 + milliseconds / 6e4;
22854
22855 case 'second':
22856 return days * 86400 + milliseconds / 1000;
22857 // Math.floor prevents floating point math errors here
22858
22859 case 'millisecond':
22860 return Math.floor(days * 864e5) + milliseconds;
22861
22862 default:
22863 throw new Error('Unknown unit ' + units);
22864 }
22865 }
22866 } // TODO: Use this.as('ms')?
22867
22868
22869 function valueOf$1() {
22870 if (!this.isValid()) {
22871 return NaN;
22872 }
22873
22874 return this._milliseconds + this._days * 864e5 + this._months % 12 * 2592e6 + toInt(this._months / 12) * 31536e6;
22875 }
22876
22877 function makeAs(alias) {
22878 return function () {
22879 return this.as(alias);
22880 };
22881 }
22882
22883 var asMilliseconds = makeAs('ms');
22884 var asSeconds = makeAs('s');
22885 var asMinutes = makeAs('m');
22886 var asHours = makeAs('h');
22887 var asDays = makeAs('d');
22888 var asWeeks = makeAs('w');
22889 var asMonths = makeAs('M');
22890 var asQuarters = makeAs('Q');
22891 var asYears = makeAs('y');
22892
22893 function clone$1() {
22894 return createDuration(this);
22895 }
22896
22897 function get$2(units) {
22898 units = normalizeUnits(units);
22899 return this.isValid() ? this[units + 's']() : NaN;
22900 }
22901
22902 function makeGetter(name) {
22903 return function () {
22904 return this.isValid() ? this._data[name] : NaN;
22905 };
22906 }
22907
22908 var milliseconds = makeGetter('milliseconds');
22909 var seconds = makeGetter('seconds');
22910 var minutes = makeGetter('minutes');
22911 var hours = makeGetter('hours');
22912 var days = makeGetter('days');
22913 var months = makeGetter('months');
22914 var years = makeGetter('years');
22915
22916 function weeks() {
22917 return absFloor(this.days() / 7);
22918 }
22919
22920 var round = Math.round;
22921 var thresholds = {
22922 ss: 44,
22923 // a few seconds to seconds
22924 s: 45,
22925 // seconds to minute
22926 m: 45,
22927 // minutes to hour
22928 h: 22,
22929 // hours to day
22930 d: 26,
22931 // days to month
22932 M: 11 // months to year
22933
22934 }; // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
22935
22936 function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
22937 return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
22938 }
22939
22940 function relativeTime$1(posNegDuration, withoutSuffix, locale) {
22941 var duration = createDuration(posNegDuration).abs();
22942 var seconds = round(duration.as('s'));
22943 var minutes = round(duration.as('m'));
22944 var hours = round(duration.as('h'));
22945 var days = round(duration.as('d'));
22946 var months = round(duration.as('M'));
22947 var years = round(duration.as('y'));
22948 var a = seconds <= thresholds.ss && ['s', seconds] || seconds < thresholds.s && ['ss', seconds] || minutes <= 1 && ['m'] || minutes < thresholds.m && ['mm', minutes] || hours <= 1 && ['h'] || hours < thresholds.h && ['hh', hours] || days <= 1 && ['d'] || days < thresholds.d && ['dd', days] || months <= 1 && ['M'] || months < thresholds.M && ['MM', months] || years <= 1 && ['y'] || ['yy', years];
22949 a[2] = withoutSuffix;
22950 a[3] = +posNegDuration > 0;
22951 a[4] = locale;
22952 return substituteTimeAgo.apply(null, a);
22953 } // This function allows you to set the rounding function for relative time strings
22954
22955
22956 function getSetRelativeTimeRounding(roundingFunction) {
22957 if (roundingFunction === undefined) {
22958 return round;
22959 }
22960
22961 if (typeof roundingFunction === 'function') {
22962 round = roundingFunction;
22963 return true;
22964 }
22965
22966 return false;
22967 } // This function allows you to set a threshold for relative time strings
22968
22969
22970 function getSetRelativeTimeThreshold(threshold, limit) {
22971 if (thresholds[threshold] === undefined) {
22972 return false;
22973 }
22974
22975 if (limit === undefined) {
22976 return thresholds[threshold];
22977 }
22978
22979 thresholds[threshold] = limit;
22980
22981 if (threshold === 's') {
22982 thresholds.ss = limit - 1;
22983 }
22984
22985 return true;
22986 }
22987
22988 function humanize(withSuffix) {
22989 if (!this.isValid()) {
22990 return this.localeData().invalidDate();
22991 }
22992
22993 var locale = this.localeData();
22994 var output = relativeTime$1(this, !withSuffix, locale);
22995
22996 if (withSuffix) {
22997 output = locale.pastFuture(+this, output);
22998 }
22999
23000 return locale.postformat(output);
23001 }
23002
23003 var abs$1 = Math.abs;
23004
23005 function sign(x) {
23006 return (x > 0) - (x < 0) || +x;
23007 }
23008
23009 function toISOString$1() {
23010 // for ISO strings we do not use the normal bubbling rules:
23011 // * milliseconds bubble up until they become hours
23012 // * days do not bubble at all
23013 // * months bubble up until they become years
23014 // This is because there is no context-free conversion between hours and days
23015 // (think of clock changes)
23016 // and also not between days and months (28-31 days per month)
23017 if (!this.isValid()) {
23018 return this.localeData().invalidDate();
23019 }
23020
23021 var seconds = abs$1(this._milliseconds) / 1000;
23022 var days = abs$1(this._days);
23023 var months = abs$1(this._months);
23024 var minutes, hours, years; // 3600 seconds -> 60 minutes -> 1 hour
23025
23026 minutes = absFloor(seconds / 60);
23027 hours = absFloor(minutes / 60);
23028 seconds %= 60;
23029 minutes %= 60; // 12 months -> 1 year
23030
23031 years = absFloor(months / 12);
23032 months %= 12; // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
23033
23034 var Y = years;
23035 var M = months;
23036 var D = days;
23037 var h = hours;
23038 var m = minutes;
23039 var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
23040 var total = this.asSeconds();
23041
23042 if (!total) {
23043 // this is the same as C#'s (Noda) and python (isodate)...
23044 // but not other JS (goog.date)
23045 return 'P0D';
23046 }
23047
23048 var totalSign = total < 0 ? '-' : '';
23049 var ymSign = sign(this._months) !== sign(total) ? '-' : '';
23050 var daysSign = sign(this._days) !== sign(total) ? '-' : '';
23051 var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
23052 return totalSign + 'P' + (Y ? ymSign + Y + 'Y' : '') + (M ? ymSign + M + 'M' : '') + (D ? daysSign + D + 'D' : '') + (h || m || s ? 'T' : '') + (h ? hmsSign + h + 'H' : '') + (m ? hmsSign + m + 'M' : '') + (s ? hmsSign + s + 'S' : '');
23053 }
23054
23055 var proto$2 = Duration.prototype;
23056 proto$2.isValid = isValid$1;
23057 proto$2.abs = abs;
23058 proto$2.add = add$1;
23059 proto$2.subtract = subtract$1;
23060 proto$2.as = as;
23061 proto$2.asMilliseconds = asMilliseconds;
23062 proto$2.asSeconds = asSeconds;
23063 proto$2.asMinutes = asMinutes;
23064 proto$2.asHours = asHours;
23065 proto$2.asDays = asDays;
23066 proto$2.asWeeks = asWeeks;
23067 proto$2.asMonths = asMonths;
23068 proto$2.asQuarters = asQuarters;
23069 proto$2.asYears = asYears;
23070 proto$2.valueOf = valueOf$1;
23071 proto$2._bubble = bubble;
23072 proto$2.clone = clone$1;
23073 proto$2.get = get$2;
23074 proto$2.milliseconds = milliseconds;
23075 proto$2.seconds = seconds;
23076 proto$2.minutes = minutes;
23077 proto$2.hours = hours;
23078 proto$2.days = days;
23079 proto$2.weeks = weeks;
23080 proto$2.months = months;
23081 proto$2.years = years;
23082 proto$2.humanize = humanize;
23083 proto$2.toISOString = toISOString$1;
23084 proto$2.toString = toISOString$1;
23085 proto$2.toJSON = toISOString$1;
23086 proto$2.locale = locale;
23087 proto$2.localeData = localeData;
23088 proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
23089 proto$2.lang = lang; // Side effect imports
23090 // FORMATTING
23091
23092 addFormatToken('X', 0, 0, 'unix');
23093 addFormatToken('x', 0, 0, 'valueOf'); // PARSING
23094
23095 addRegexToken('x', matchSigned);
23096 addRegexToken('X', matchTimestamp);
23097 addParseToken('X', function (input, array, config) {
23098 config._d = new Date(parseFloat(input, 10) * 1000);
23099 });
23100 addParseToken('x', function (input, array, config) {
23101 config._d = new Date(toInt(input));
23102 }); // Side effect imports
23103
23104 hooks.version = '2.24.0';
23105 setHookCallback(createLocal);
23106 hooks.fn = proto;
23107 hooks.min = min;
23108 hooks.max = max;
23109 hooks.now = now;
23110 hooks.utc = createUTC;
23111 hooks.unix = createUnix;
23112 hooks.months = listMonths;
23113 hooks.isDate = isDate;
23114 hooks.locale = getSetGlobalLocale;
23115 hooks.invalid = createInvalid;
23116 hooks.duration = createDuration;
23117 hooks.isMoment = isMoment;
23118 hooks.weekdays = listWeekdays;
23119 hooks.parseZone = createInZone;
23120 hooks.localeData = getLocale;
23121 hooks.isDuration = isDuration;
23122 hooks.monthsShort = listMonthsShort;
23123 hooks.weekdaysMin = listWeekdaysMin;
23124 hooks.defineLocale = defineLocale;
23125 hooks.updateLocale = updateLocale;
23126 hooks.locales = listLocales;
23127 hooks.weekdaysShort = listWeekdaysShort;
23128 hooks.normalizeUnits = normalizeUnits;
23129 hooks.relativeTimeRounding = getSetRelativeTimeRounding;
23130 hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
23131 hooks.calendarFormat = getCalendarFormat;
23132 hooks.prototype = proto; // currently HTML5 input type only supports 24-hour formats
23133
23134 hooks.HTML5_FMT = {
23135 DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm',
23136 // <input type="datetime-local" />
23137 DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss',
23138 // <input type="datetime-local" step="1" />
23139 DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS',
23140 // <input type="datetime-local" step="0.001" />
23141 DATE: 'YYYY-MM-DD',
23142 // <input type="date" />
23143 TIME: 'HH:mm',
23144 // <input type="time" />
23145 TIME_SECONDS: 'HH:mm:ss',
23146 // <input type="time" step="1" />
23147 TIME_MS: 'HH:mm:ss.SSS',
23148 // <input type="time" step="0.001" />
23149 WEEK: 'GGGG-[W]WW',
23150 // <input type="week" />
23151 MONTH: 'YYYY-MM' // <input type="month" />
23152
23153 };
23154 return hooks;
23155 });
23156}); // Maps for number <-> hex string conversion
23157
23158var byteToHex$2$1 = [];
23159
23160for (var i$2$1 = 0; i$2$1 < 256; i$2$1++) {
23161 byteToHex$2$1[i$2$1] = (i$2$1 + 0x100).toString(16).substr(1);
23162}
23163/**
23164 * Generate 16 random bytes to be used as a base for UUID.
23165 *
23166 * @ignore
23167 */
23168
23169
23170var random$1$1 = function () {
23171 if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
23172 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
23173 // Moderately fast, high quality
23174 var _rnds8 = new Uint8Array(16);
23175
23176 return function whatwgRNG() {
23177 crypto.getRandomValues(_rnds8);
23178 return _rnds8;
23179 };
23180 } // Math.random()-based (RNG)
23181 //
23182 // If all else fails, use Math.random().
23183 // It's fast, but is of unspecified quality.
23184
23185
23186 var _rnds = new Array(16);
23187
23188 return function () {
23189 for (var i = 0, r; i < 16; i++) {
23190 if ((i & 0x03) === 0) {
23191 r = Math.random() * 0x100000000;
23192 }
23193
23194 _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
23195 }
23196
23197 return _rnds;
23198 }; // uuid.js
23199 //
23200 // Copyright (c) 2010-2012 Robert Kieffer
23201 // MIT License - http://opensource.org/licenses/mit-license.php
23202 // Unique ID creation requires a high quality random # generator. We feature
23203 // detect to determine the best RNG source, normalizing to a function that
23204 // returns 128-bits of randomness, since that's what's usually required
23205 // return require('./rng');
23206}();
23207
23208var byteToHex$1$1$1 = [];
23209
23210for (var i$1$1$1 = 0; i$1$1$1 < 256; i$1$1$1++) {
23211 byteToHex$1$1$1[i$1$1$1] = (i$1$1$1 + 0x100).toString(16).substr(1);
23212} // **`v1()` - Generate time-based UUID**
23213//
23214// Inspired by https://github.com/LiosK/UUID.js
23215// and http://docs.python.org/library/uuid.html
23216// random #'s we need to init node and clockseq
23217
23218
23219var seedBytes$1$1 = random$1$1(); // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
23220
23221var defaultNodeId$1$1 = [seedBytes$1$1[0] | 0x01, seedBytes$1$1[1], seedBytes$1$1[2], seedBytes$1$1[3], seedBytes$1$1[4], seedBytes$1$1[5]]; // Per 4.2.2, randomize (14 bit) clockseq
23222
23223var defaultClockseq$1$1 = (seedBytes$1$1[6] << 8 | seedBytes$1$1[7]) & 0x3fff; // Previous uuid creation time
23224// for example '/Date(1198908717056)/' or '/Date(1198908717056-0700)/'
23225// code from http://momentjs.com/
23226
23227var ASPDateRegex$1 = /^\/?Date\((-?\d+)/i; // Hex color
23228
23229/**
23230 * Hue, Saturation, Value.
23231 */
23232
23233/**
23234 * Test whether given object is a number
23235 *
23236 * @param value - Input value of unknown type.
23237 *
23238 * @returns True if number, false otherwise.
23239 */
23240
23241function isNumber$1(value) {
23242 return value instanceof Number || typeof value === 'number';
23243}
23244/**
23245 * Test whether given object is a string
23246 *
23247 * @param value - Input value of unknown type.
23248 *
23249 * @returns True if string, false otherwise.
23250 */
23251
23252
23253function isString$1(value) {
23254 return value instanceof String || typeof value === 'string';
23255}
23256/**
23257 * Test whether given object is a Moment date.
23258 * @TODO: This is basically a workaround, if Moment was imported property it wouldn't necessary as moment.isMoment is a TS type guard.
23259 *
23260 * @param value - Input value of unknown type.
23261 *
23262 * @returns True if Moment instance, false otherwise.
23263 */
23264
23265
23266function isMoment$1(value) {
23267 return moment$1.isMoment(value);
23268}
23269/**
23270 * Copy property from b to a if property present in a.
23271 * If property in b explicitly set to null, delete it if `allowDeletion` set.
23272 *
23273 * Internal helper routine, should not be exported. Not added to `exports` for that reason.
23274 *
23275 * @param a - Target object.
23276 * @param b - Source object.
23277 * @param prop - Name of property to copy from b to a.
23278 * @param allowDeletion if true, delete property in a if explicitly set to null in b
23279 */
23280
23281
23282function copyOrDelete$1(a, b, prop, allowDeletion) {
23283 var doDeletion = false;
23284
23285 if (allowDeletion === true) {
23286 doDeletion = b[prop] === null && a[prop] !== undefined;
23287 }
23288
23289 if (doDeletion) {
23290 delete a[prop];
23291 } else {
23292 a[prop] = b[prop]; // Remember, this is a reference copy!
23293 }
23294}
23295/**
23296 * Deep extend an object a with the properties of object b
23297 *
23298 * @param a - Target object.
23299 * @param b - Source object.
23300 * @param protoExtend - If true, the prototype values will also be extended
23301 * (ie. the options objects that inherit from others will also get the inherited options).
23302 * @param allowDeletion - If true, the values of fields that are null will be deleted.
23303 *
23304 * @returns Argument a.
23305 */
23306
23307
23308function deepExtend$1(a, b) {
23309 var protoExtend = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
23310 var allowDeletion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
23311
23312 for (var prop in b) {
23313 if (Object.prototype.hasOwnProperty.call(b, prop) || protoExtend === true) {
23314 if (b[prop] && b[prop].constructor === Object) {
23315 if (a[prop] === undefined) {
23316 a[prop] = {};
23317 }
23318
23319 if (a[prop].constructor === Object) {
23320 deepExtend$1(a[prop], b[prop], protoExtend); // NOTE: allowDeletion not propagated!
23321 } else {
23322 copyOrDelete$1(a, b, prop, allowDeletion);
23323 }
23324 } else if (Array.isArray(b[prop])) {
23325 a[prop] = [];
23326
23327 for (var i = 0; i < b[prop].length; i++) {
23328 a[prop].push(b[prop][i]);
23329 }
23330 } else {
23331 copyOrDelete$1(a, b, prop, allowDeletion);
23332 }
23333 }
23334 }
23335
23336 return a;
23337}
23338/**
23339 * Convert an object into another type
23340 *
23341 * @param object - Value of unknown type.
23342 * @param type - Name of the desired type.
23343 *
23344 * @returns Object in the desired type.
23345 * @throws Error
23346 */
23347
23348
23349function convert$1(object, type) {
23350 var match;
23351
23352 if (object === undefined) {
23353 return undefined;
23354 }
23355
23356 if (object === null) {
23357 return null;
23358 }
23359
23360 if (!type) {
23361 return object;
23362 }
23363
23364 if (!(typeof type === 'string') && !(type instanceof String)) {
23365 throw new Error('Type must be a string');
23366 } //noinspection FallthroughInSwitchStatementJS
23367
23368
23369 switch (type) {
23370 case 'boolean':
23371 case 'Boolean':
23372 return Boolean(object);
23373
23374 case 'number':
23375 case 'Number':
23376 if (isString$1(object) && !isNaN(Date.parse(object))) {
23377 return moment$1(object).valueOf();
23378 } else {
23379 // @TODO: I don't think that Number and String constructors are a good idea.
23380 // This could also fail if the object doesn't have valueOf method or if it's redefined.
23381 // For example: Object.create(null) or { valueOf: 7 }.
23382 return Number(object.valueOf());
23383 }
23384
23385 case 'string':
23386 case 'String':
23387 return String(object);
23388
23389 case 'Date':
23390 if (isNumber$1(object)) {
23391 return new Date(object);
23392 }
23393
23394 if (object instanceof Date) {
23395 return new Date(object.valueOf());
23396 } else if (isMoment$1(object)) {
23397 return new Date(object.valueOf());
23398 }
23399
23400 if (isString$1(object)) {
23401 match = ASPDateRegex$1.exec(object);
23402
23403 if (match) {
23404 // object is an ASP date
23405 return new Date(Number(match[1])); // parse number
23406 } else {
23407 return moment$1(new Date(object)).toDate(); // parse string
23408 }
23409 } else {
23410 throw new Error('Cannot convert object of type ' + getType$1(object) + ' to type Date');
23411 }
23412
23413 case 'Moment':
23414 if (isNumber$1(object)) {
23415 return moment$1(object);
23416 }
23417
23418 if (object instanceof Date) {
23419 return moment$1(object.valueOf());
23420 } else if (isMoment$1(object)) {
23421 return moment$1(object);
23422 }
23423
23424 if (isString$1(object)) {
23425 match = ASPDateRegex$1.exec(object);
23426
23427 if (match) {
23428 // object is an ASP date
23429 return moment$1(Number(match[1])); // parse number
23430 } else {
23431 return moment$1(object); // parse string
23432 }
23433 } else {
23434 throw new Error('Cannot convert object of type ' + getType$1(object) + ' to type Date');
23435 }
23436
23437 case 'ISODate':
23438 if (isNumber$1(object)) {
23439 return new Date(object);
23440 } else if (object instanceof Date) {
23441 return object.toISOString();
23442 } else if (isMoment$1(object)) {
23443 return object.toDate().toISOString();
23444 } else if (isString$1(object)) {
23445 match = ASPDateRegex$1.exec(object);
23446
23447 if (match) {
23448 // object is an ASP date
23449 return new Date(Number(match[1])).toISOString(); // parse number
23450 } else {
23451 return moment$1(object).format(); // ISO 8601
23452 }
23453 } else {
23454 throw new Error('Cannot convert object of type ' + getType$1(object) + ' to type ISODate');
23455 }
23456
23457 case 'ASPDate':
23458 if (isNumber$1(object)) {
23459 return '/Date(' + object + ')/';
23460 } else if (object instanceof Date) {
23461 return '/Date(' + object.valueOf() + ')/';
23462 } else if (isString$1(object)) {
23463 match = ASPDateRegex$1.exec(object);
23464
23465 var _value;
23466
23467 if (match) {
23468 // object is an ASP date
23469 _value = new Date(Number(match[1])).valueOf(); // parse number
23470 } else {
23471 _value = new Date(object).valueOf(); // parse string
23472 }
23473
23474 return '/Date(' + _value + ')/';
23475 } else {
23476 throw new Error('Cannot convert object of type ' + getType$1(object) + ' to type ASPDate');
23477 }
23478
23479 default:
23480 var never = type;
23481 throw new Error("Unknown type ".concat(never));
23482 }
23483}
23484/**
23485 * Get the type of an object, for example exports.getType([]) returns 'Array'
23486 *
23487 * @param object - Input value of unknown type.
23488 *
23489 * @returns Detected type.
23490 */
23491
23492
23493function getType$1(object) {
23494 var type = _typeof$2(object);
23495
23496 if (type === 'object') {
23497 if (object === null) {
23498 return 'null';
23499 }
23500
23501 if (object instanceof Boolean) {
23502 return 'Boolean';
23503 }
23504
23505 if (object instanceof Number) {
23506 return 'Number';
23507 }
23508
23509 if (object instanceof String) {
23510 return 'String';
23511 }
23512
23513 if (Array.isArray(object)) {
23514 return 'Array';
23515 }
23516
23517 if (object instanceof Date) {
23518 return 'Date';
23519 }
23520
23521 return 'Object';
23522 }
23523
23524 if (type === 'number') {
23525 return 'Number';
23526 }
23527
23528 if (type === 'boolean') {
23529 return 'Boolean';
23530 }
23531
23532 if (type === 'string') {
23533 return 'String';
23534 }
23535
23536 if (type === undefined) {
23537 return 'undefined';
23538 }
23539
23540 return type;
23541}
23542/**
23543 * Determine whether a value can be used as an id.
23544 *
23545 * @param value - Input value of unknown type.
23546 *
23547 * @returns True if the value is valid id, false otherwise.
23548 */
23549
23550
23551function isId(value) {
23552 return typeof value === "string" || typeof value === "number";
23553}
23554/* eslint @typescript-eslint/member-ordering: ["error", { "classes": ["field", "constructor", "method"] }] */
23555
23556/**
23557 * A queue.
23558 *
23559 * @typeParam T - The type of method names to be replaced by queued versions.
23560 */
23561
23562
23563var Queue =
23564/*#__PURE__*/
23565function () {
23566 /**
23567 * Construct a new Queue.
23568 *
23569 * @param options - Queue configuration.
23570 */
23571 function Queue(options) {
23572 classCallCheck(this, Queue);
23573 this._queue = [];
23574 this._timeout = null;
23575 this._extended = null; // options
23576
23577 this.delay = null;
23578 this.max = Infinity;
23579 this.setOptions(options);
23580 }
23581 /**
23582 * Update the configuration of the queue.
23583 *
23584 * @param options - Queue configuration.
23585 */
23586
23587
23588 createClass(Queue, [{
23589 key: "setOptions",
23590 value: function setOptions(options) {
23591 if (options && typeof options.delay !== "undefined") {
23592 this.delay = options.delay;
23593 }
23594
23595 if (options && typeof options.max !== "undefined") {
23596 this.max = options.max;
23597 }
23598
23599 this._flushIfNeeded();
23600 }
23601 /**
23602 * Extend an object with queuing functionality.
23603 * The object will be extended with a function flush, and the methods provided in options.replace will be replaced with queued ones.
23604 *
23605 * @param object - The object to be extended.
23606 * @param options - Additional options.
23607 *
23608 * @returns The created queue.
23609 */
23610
23611 }, {
23612 key: "destroy",
23613
23614 /**
23615 * Destroy the queue. The queue will first flush all queued actions, and in case it has extended an object, will restore the original object.
23616 */
23617 value: function destroy() {
23618 this.flush();
23619
23620 if (this._extended) {
23621 var object = this._extended.object;
23622 var methods = this._extended.methods;
23623
23624 for (var i = 0; i < methods.length; i++) {
23625 var method = methods[i];
23626
23627 if (method.original) {
23628 // @TODO: better solution?
23629 object[method.name] = method.original;
23630 } else {
23631 // @TODO: better solution?
23632 delete object[method.name];
23633 }
23634 }
23635
23636 this._extended = null;
23637 }
23638 }
23639 /**
23640 * Replace a method on an object with a queued version.
23641 *
23642 * @param object - Object having the method.
23643 * @param method - The method name.
23644 */
23645
23646 }, {
23647 key: "replace",
23648 value: function replace(object, method) {
23649 /* eslint-disable-next-line @typescript-eslint/no-this-alias */
23650 var me = this;
23651 var original = object[method];
23652
23653 if (!original) {
23654 throw new Error("Method " + method + " undefined");
23655 }
23656
23657 object[method] = function () {
23658 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
23659 args[_key] = arguments[_key];
23660 } // add this call to the queue
23661
23662
23663 me.queue({
23664 args: args,
23665 fn: original,
23666 context: this
23667 });
23668 };
23669 }
23670 /**
23671 * Queue a call.
23672 *
23673 * @param entry - The function or entry to be queued.
23674 */
23675
23676 }, {
23677 key: "queue",
23678 value: function queue(entry) {
23679 if (typeof entry === "function") {
23680 this._queue.push({
23681 fn: entry
23682 });
23683 } else {
23684 this._queue.push(entry);
23685 }
23686
23687 this._flushIfNeeded();
23688 }
23689 /**
23690 * Check whether the queue needs to be flushed.
23691 */
23692
23693 }, {
23694 key: "_flushIfNeeded",
23695 value: function _flushIfNeeded() {
23696 var _this = this; // flush when the maximum is exceeded.
23697
23698
23699 if (this._queue.length > this.max) {
23700 this.flush();
23701 } // flush after a period of inactivity when a delay is configured
23702
23703
23704 if (this._timeout != null) {
23705 clearTimeout(this._timeout);
23706 this._timeout = null;
23707 }
23708
23709 if (this.queue.length > 0 && typeof this.delay === "number") {
23710 this._timeout = setTimeout(function () {
23711 _this.flush();
23712 }, this.delay);
23713 }
23714 }
23715 /**
23716 * Flush all queued calls
23717 */
23718
23719 }, {
23720 key: "flush",
23721 value: function flush() {
23722 this._queue.splice(0).forEach(function (entry) {
23723 entry.fn.apply(entry.context || entry.fn, entry.args || []);
23724 });
23725 }
23726 }], [{
23727 key: "extend",
23728 value: function extend(object, options) {
23729 var queue = new Queue(options);
23730
23731 if (object.flush !== undefined) {
23732 throw new Error("Target object already has a property flush");
23733 }
23734
23735 object.flush = function () {
23736 queue.flush();
23737 };
23738
23739 var methods = [{
23740 name: "flush",
23741 original: undefined
23742 }];
23743
23744 if (options && options.replace) {
23745 for (var i = 0; i < options.replace.length; i++) {
23746 var name = options.replace[i];
23747 methods.push({
23748 name: name,
23749 // @TODO: better solution?
23750 original: object[name]
23751 }); // @TODO: better solution?
23752
23753 queue.replace(object, name);
23754 }
23755 }
23756
23757 queue._extended = {
23758 object: object,
23759 methods: methods
23760 };
23761 return queue;
23762 }
23763 }]);
23764 return Queue;
23765}();
23766/* eslint-disable @typescript-eslint/member-ordering */
23767
23768/**
23769 * [[DataSet]] code that can be reused in [[DataView]] or other similar implementations of [[DataInterface]].
23770 *
23771 * @typeParam Item - Item type that may or may not have an id.
23772 * @typeParam IdProp - Name of the property that contains the id.
23773 */
23774
23775
23776var DataSetPart =
23777/*#__PURE__*/
23778function () {
23779 function DataSetPart() {
23780 classCallCheck(this, DataSetPart);
23781 this._subscribers = {
23782 "*": [],
23783 add: [],
23784 remove: [],
23785 update: []
23786 };
23787 /**
23788 * @deprecated Use on instead (PS: DataView.subscribe === DataView.on).
23789 */
23790
23791 this.subscribe = DataSetPart.prototype.on;
23792 /**
23793 * @deprecated Use off instead (PS: DataView.unsubscribe === DataView.off).
23794 */
23795
23796 this.unsubscribe = DataSetPart.prototype.off;
23797 }
23798 /**
23799 * Trigger an event
23800 *
23801 * @param event - Event name.
23802 * @param payload - Event payload.
23803 * @param senderId - Id of the sender.
23804 */
23805
23806
23807 createClass(DataSetPart, [{
23808 key: "_trigger",
23809 value: function _trigger(event, payload, senderId) {
23810 if (event === "*") {
23811 throw new Error("Cannot trigger event *");
23812 }
23813
23814 [].concat(toConsumableArray(this._subscribers[event]), toConsumableArray(this._subscribers["*"])).forEach(function (subscriber) {
23815 subscriber(event, payload, senderId != null ? senderId : null);
23816 });
23817 }
23818 /**
23819 * Subscribe to an event, add an event listener.
23820 *
23821 * @remarks Non-function callbacks are ignored.
23822 *
23823 * @param event - Event name.
23824 * @param callback - Callback method.
23825 */
23826
23827 }, {
23828 key: "on",
23829 value: function on(event, callback) {
23830 if (typeof callback === "function") {
23831 this._subscribers[event].push(callback);
23832 } // @TODO: Maybe throw for invalid callbacks?
23833
23834 }
23835 /**
23836 * Unsubscribe from an event, remove an event listener.
23837 *
23838 * @remarks If the same callback was subscribed more than once **all** occurences will be removed.
23839 *
23840 * @param event - Event name.
23841 * @param callback - Callback method.
23842 */
23843
23844 }, {
23845 key: "off",
23846 value: function off(event, callback) {
23847 this._subscribers[event] = this._subscribers[event].filter(function (subscriber) {
23848 return subscriber !== callback;
23849 });
23850 }
23851 }]);
23852 return DataSetPart;
23853}();
23854
23855function _arrayWithHoles$1(arr) {
23856 if (Array.isArray(arr)) return arr;
23857}
23858
23859var arrayWithHoles = _arrayWithHoles$1;
23860
23861function _iterableToArrayLimit$1(arr, i) {
23862 var _arr = [];
23863 var _n = true;
23864 var _d = false;
23865 var _e = undefined;
23866
23867 try {
23868 for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
23869 _arr.push(_s.value);
23870
23871 if (i && _arr.length === i) break;
23872 }
23873 } catch (err) {
23874 _d = true;
23875 _e = err;
23876 } finally {
23877 try {
23878 if (!_n && _i["return"] != null) _i["return"]();
23879 } finally {
23880 if (_d) throw _e;
23881 }
23882 }
23883
23884 return _arr;
23885}
23886
23887var iterableToArrayLimit = _iterableToArrayLimit$1;
23888
23889function _nonIterableRest$1() {
23890 throw new TypeError("Invalid attempt to destructure non-iterable instance");
23891}
23892
23893var nonIterableRest = _nonIterableRest$1;
23894
23895function _slicedToArray$1(arr, i) {
23896 return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || nonIterableRest();
23897}
23898
23899var slicedToArray = _slicedToArray$1;
23900/**
23901 * Data stream
23902 *
23903 * @remarks
23904 * [[DataStream]] offers an always up to date stream of items from a [[DataSet]] or [[DataView]].
23905 * That means that the stream is evaluated at the time of iteration, conversion to another data type or when [[cache]] is called, not when the [[DataStream]] was created.
23906 * Multiple invocations of for example [[toItemArray]] may yield different results (if the data source like for example [[DataSet]] gets modified).
23907 *
23908 * @typeparam Item - The item type this stream is going to work with.
23909 */
23910
23911var DataStream =
23912/*#__PURE__*/
23913function () {
23914 /**
23915 * Create a new data stream.
23916 *
23917 * @param _pairs - The id, item pairs.
23918 */
23919 function DataStream(_pairs) {
23920 classCallCheck(this, DataStream);
23921 this._pairs = _pairs;
23922 }
23923 /**
23924 * Return an iterable of key, value pairs for every entry in the stream.
23925 */
23926
23927
23928 createClass(DataStream, [{
23929 key: Symbol.iterator,
23930 value:
23931 /*#__PURE__*/
23932 regenerator.mark(function value() {
23933 var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step$value, id, item;
23934
23935 return regenerator.wrap(function value$(_context) {
23936 while (1) {
23937 switch (_context.prev = _context.next) {
23938 case 0:
23939 _iteratorNormalCompletion = true;
23940 _didIteratorError = false;
23941 _iteratorError = undefined;
23942 _context.prev = 3;
23943 _iterator = this._pairs[Symbol.iterator]();
23944
23945 case 5:
23946 if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
23947 _context.next = 12;
23948 break;
23949 }
23950
23951 _step$value = slicedToArray(_step.value, 2), id = _step$value[0], item = _step$value[1];
23952 _context.next = 9;
23953 return [id, item];
23954
23955 case 9:
23956 _iteratorNormalCompletion = true;
23957 _context.next = 5;
23958 break;
23959
23960 case 12:
23961 _context.next = 18;
23962 break;
23963
23964 case 14:
23965 _context.prev = 14;
23966 _context.t0 = _context["catch"](3);
23967 _didIteratorError = true;
23968 _iteratorError = _context.t0;
23969
23970 case 18:
23971 _context.prev = 18;
23972 _context.prev = 19;
23973
23974 if (!_iteratorNormalCompletion && _iterator.return != null) {
23975 _iterator.return();
23976 }
23977
23978 case 21:
23979 _context.prev = 21;
23980
23981 if (!_didIteratorError) {
23982 _context.next = 24;
23983 break;
23984 }
23985
23986 throw _iteratorError;
23987
23988 case 24:
23989 return _context.finish(21);
23990
23991 case 25:
23992 return _context.finish(18);
23993
23994 case 26:
23995 case "end":
23996 return _context.stop();
23997 }
23998 }
23999 }, value, this, [[3, 14, 18, 26], [19,, 21, 25]]);
24000 })
24001 /**
24002 * Return an iterable of key, value pairs for every entry in the stream.
24003 */
24004
24005 }, {
24006 key: "entries",
24007 value:
24008 /*#__PURE__*/
24009 regenerator.mark(function entries() {
24010 var _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, _step2$value, id, item;
24011
24012 return regenerator.wrap(function entries$(_context2) {
24013 while (1) {
24014 switch (_context2.prev = _context2.next) {
24015 case 0:
24016 _iteratorNormalCompletion2 = true;
24017 _didIteratorError2 = false;
24018 _iteratorError2 = undefined;
24019 _context2.prev = 3;
24020 _iterator2 = this._pairs[Symbol.iterator]();
24021
24022 case 5:
24023 if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
24024 _context2.next = 12;
24025 break;
24026 }
24027
24028 _step2$value = slicedToArray(_step2.value, 2), id = _step2$value[0], item = _step2$value[1];
24029 _context2.next = 9;
24030 return [id, item];
24031
24032 case 9:
24033 _iteratorNormalCompletion2 = true;
24034 _context2.next = 5;
24035 break;
24036
24037 case 12:
24038 _context2.next = 18;
24039 break;
24040
24041 case 14:
24042 _context2.prev = 14;
24043 _context2.t0 = _context2["catch"](3);
24044 _didIteratorError2 = true;
24045 _iteratorError2 = _context2.t0;
24046
24047 case 18:
24048 _context2.prev = 18;
24049 _context2.prev = 19;
24050
24051 if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
24052 _iterator2.return();
24053 }
24054
24055 case 21:
24056 _context2.prev = 21;
24057
24058 if (!_didIteratorError2) {
24059 _context2.next = 24;
24060 break;
24061 }
24062
24063 throw _iteratorError2;
24064
24065 case 24:
24066 return _context2.finish(21);
24067
24068 case 25:
24069 return _context2.finish(18);
24070
24071 case 26:
24072 case "end":
24073 return _context2.stop();
24074 }
24075 }
24076 }, entries, this, [[3, 14, 18, 26], [19,, 21, 25]]);
24077 })
24078 /**
24079 * Return an iterable of keys in the stream.
24080 */
24081
24082 }, {
24083 key: "keys",
24084 value:
24085 /*#__PURE__*/
24086 regenerator.mark(function keys() {
24087 var _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, _step3$value, id;
24088
24089 return regenerator.wrap(function keys$(_context3) {
24090 while (1) {
24091 switch (_context3.prev = _context3.next) {
24092 case 0:
24093 _iteratorNormalCompletion3 = true;
24094 _didIteratorError3 = false;
24095 _iteratorError3 = undefined;
24096 _context3.prev = 3;
24097 _iterator3 = this._pairs[Symbol.iterator]();
24098
24099 case 5:
24100 if (_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done) {
24101 _context3.next = 12;
24102 break;
24103 }
24104
24105 _step3$value = slicedToArray(_step3.value, 1), id = _step3$value[0];
24106 _context3.next = 9;
24107 return id;
24108
24109 case 9:
24110 _iteratorNormalCompletion3 = true;
24111 _context3.next = 5;
24112 break;
24113
24114 case 12:
24115 _context3.next = 18;
24116 break;
24117
24118 case 14:
24119 _context3.prev = 14;
24120 _context3.t0 = _context3["catch"](3);
24121 _didIteratorError3 = true;
24122 _iteratorError3 = _context3.t0;
24123
24124 case 18:
24125 _context3.prev = 18;
24126 _context3.prev = 19;
24127
24128 if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
24129 _iterator3.return();
24130 }
24131
24132 case 21:
24133 _context3.prev = 21;
24134
24135 if (!_didIteratorError3) {
24136 _context3.next = 24;
24137 break;
24138 }
24139
24140 throw _iteratorError3;
24141
24142 case 24:
24143 return _context3.finish(21);
24144
24145 case 25:
24146 return _context3.finish(18);
24147
24148 case 26:
24149 case "end":
24150 return _context3.stop();
24151 }
24152 }
24153 }, keys, this, [[3, 14, 18, 26], [19,, 21, 25]]);
24154 })
24155 /**
24156 * Return an iterable of values in the stream.
24157 */
24158
24159 }, {
24160 key: "values",
24161 value:
24162 /*#__PURE__*/
24163 regenerator.mark(function values() {
24164 var _iteratorNormalCompletion4, _didIteratorError4, _iteratorError4, _iterator4, _step4, _step4$value, item;
24165
24166 return regenerator.wrap(function values$(_context4) {
24167 while (1) {
24168 switch (_context4.prev = _context4.next) {
24169 case 0:
24170 _iteratorNormalCompletion4 = true;
24171 _didIteratorError4 = false;
24172 _iteratorError4 = undefined;
24173 _context4.prev = 3;
24174 _iterator4 = this._pairs[Symbol.iterator]();
24175
24176 case 5:
24177 if (_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done) {
24178 _context4.next = 12;
24179 break;
24180 }
24181
24182 _step4$value = slicedToArray(_step4.value, 2), item = _step4$value[1];
24183 _context4.next = 9;
24184 return item;
24185
24186 case 9:
24187 _iteratorNormalCompletion4 = true;
24188 _context4.next = 5;
24189 break;
24190
24191 case 12:
24192 _context4.next = 18;
24193 break;
24194
24195 case 14:
24196 _context4.prev = 14;
24197 _context4.t0 = _context4["catch"](3);
24198 _didIteratorError4 = true;
24199 _iteratorError4 = _context4.t0;
24200
24201 case 18:
24202 _context4.prev = 18;
24203 _context4.prev = 19;
24204
24205 if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
24206 _iterator4.return();
24207 }
24208
24209 case 21:
24210 _context4.prev = 21;
24211
24212 if (!_didIteratorError4) {
24213 _context4.next = 24;
24214 break;
24215 }
24216
24217 throw _iteratorError4;
24218
24219 case 24:
24220 return _context4.finish(21);
24221
24222 case 25:
24223 return _context4.finish(18);
24224
24225 case 26:
24226 case "end":
24227 return _context4.stop();
24228 }
24229 }
24230 }, values, this, [[3, 14, 18, 26], [19,, 21, 25]]);
24231 })
24232 /**
24233 * Return an array containing all the ids in this stream.
24234 *
24235 * @remarks
24236 * The array may contain duplicities.
24237 *
24238 * @returns The array with all ids from this stream.
24239 */
24240
24241 }, {
24242 key: "toIdArray",
24243 value: function toIdArray() {
24244 return toConsumableArray(this._pairs).map(function (pair) {
24245 return pair[0];
24246 });
24247 }
24248 /**
24249 * Return an array containing all the items in this stream.
24250 *
24251 * @remarks
24252 * The array may contain duplicities.
24253 *
24254 * @returns The array with all items from this stream.
24255 */
24256
24257 }, {
24258 key: "toItemArray",
24259 value: function toItemArray() {
24260 return toConsumableArray(this._pairs).map(function (pair) {
24261 return pair[1];
24262 });
24263 }
24264 /**
24265 * Return an array containing all the entries in this stream.
24266 *
24267 * @remarks
24268 * The array may contain duplicities.
24269 *
24270 * @returns The array with all entries from this stream.
24271 */
24272
24273 }, {
24274 key: "toEntryArray",
24275 value: function toEntryArray() {
24276 return toConsumableArray(this._pairs);
24277 }
24278 /**
24279 * Return an object map containing all the items in this stream accessible by ids.
24280 *
24281 * @remarks
24282 * In case of duplicate ids (coerced to string so `7 == '7'`) the last encoutered appears in the returned object.
24283 *
24284 * @returns The object map of all id → item pairs from this stream.
24285 */
24286
24287 }, {
24288 key: "toObjectMap",
24289 value: function toObjectMap() {
24290 var map = Object.create(null);
24291 var _iteratorNormalCompletion5 = true;
24292 var _didIteratorError5 = false;
24293 var _iteratorError5 = undefined;
24294
24295 try {
24296 for (var _iterator5 = this._pairs[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
24297 var _step5$value = slicedToArray(_step5.value, 2),
24298 id = _step5$value[0],
24299 item = _step5$value[1];
24300
24301 map[id] = item;
24302 }
24303 } catch (err) {
24304 _didIteratorError5 = true;
24305 _iteratorError5 = err;
24306 } finally {
24307 try {
24308 if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
24309 _iterator5.return();
24310 }
24311 } finally {
24312 if (_didIteratorError5) {
24313 throw _iteratorError5;
24314 }
24315 }
24316 }
24317
24318 return map;
24319 }
24320 /**
24321 * Return a map containing all the items in this stream accessible by ids.
24322 *
24323 * @returns The map of all id → item pairs from this stream.
24324 */
24325
24326 }, {
24327 key: "toMap",
24328 value: function toMap() {
24329 return new Map(this._pairs);
24330 }
24331 /**
24332 * Return a set containing all the (unique) ids in this stream.
24333 *
24334 * @returns The set of all ids from this stream.
24335 */
24336
24337 }, {
24338 key: "toIdSet",
24339 value: function toIdSet() {
24340 return new Set(this.toIdArray());
24341 }
24342 /**
24343 * Return a set containing all the (unique) items in this stream.
24344 *
24345 * @returns The set of all items from this stream.
24346 */
24347
24348 }, {
24349 key: "toItemSet",
24350 value: function toItemSet() {
24351 return new Set(this.toItemArray());
24352 }
24353 /**
24354 * Cache the items from this stream.
24355 *
24356 * @remarks
24357 * This method allows for items to be fetched immediatelly and used (possibly multiple times) later.
24358 * It can also be used to optimize performance as [[DataStream]] would otherwise reevaluate everything upon each iteration.
24359 *
24360 * ## Example
24361 * ```javascript
24362 * const ds = new DataSet([…])
24363 *
24364 * const cachedStream = ds.stream()
24365 * .filter(…)
24366 * .sort(…)
24367 * .map(…)
24368 * .cached(…) // Data are fetched, processed and cached here.
24369 *
24370 * ds.clear()
24371 * chachedStream // Still has all the items.
24372 * ```
24373 *
24374 * @returns A new [[DataStream]] with cached items (detached from the original [[DataSet]]).
24375 */
24376
24377 }, {
24378 key: "cache",
24379 value: function cache() {
24380 return new DataStream(toConsumableArray(this._pairs));
24381 }
24382 /**
24383 * Get the distinct values of given property.
24384 *
24385 * @param callback - The function that picks and possibly converts the property.
24386 *
24387 * @typeparam T - The type of the distinct value.
24388 *
24389 * @returns A set of all distinct properties.
24390 */
24391
24392 }, {
24393 key: "distinct",
24394 value: function distinct(callback) {
24395 var set = new Set();
24396 var _iteratorNormalCompletion6 = true;
24397 var _didIteratorError6 = false;
24398 var _iteratorError6 = undefined;
24399
24400 try {
24401 for (var _iterator6 = this._pairs[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
24402 var _step6$value = slicedToArray(_step6.value, 2),
24403 id = _step6$value[0],
24404 item = _step6$value[1];
24405
24406 set.add(callback(item, id));
24407 }
24408 } catch (err) {
24409 _didIteratorError6 = true;
24410 _iteratorError6 = err;
24411 } finally {
24412 try {
24413 if (!_iteratorNormalCompletion6 && _iterator6.return != null) {
24414 _iterator6.return();
24415 }
24416 } finally {
24417 if (_didIteratorError6) {
24418 throw _iteratorError6;
24419 }
24420 }
24421 }
24422
24423 return set;
24424 }
24425 /**
24426 * Filter the items of the stream.
24427 *
24428 * @param callback - The function that decides whether an item will be included.
24429 *
24430 * @returns A new data stream with the filtered items.
24431 */
24432
24433 }, {
24434 key: "filter",
24435 value: function filter(callback) {
24436 var pairs = this._pairs;
24437 return new DataStream(defineProperty$6({}, Symbol.iterator,
24438 /*#__PURE__*/
24439 regenerator.mark(function _callee() {
24440 var _iteratorNormalCompletion7, _didIteratorError7, _iteratorError7, _iterator7, _step7, _step7$value, id, item;
24441
24442 return regenerator.wrap(function _callee$(_context5) {
24443 while (1) {
24444 switch (_context5.prev = _context5.next) {
24445 case 0:
24446 _iteratorNormalCompletion7 = true;
24447 _didIteratorError7 = false;
24448 _iteratorError7 = undefined;
24449 _context5.prev = 3;
24450 _iterator7 = pairs[Symbol.iterator]();
24451
24452 case 5:
24453 if (_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done) {
24454 _context5.next = 13;
24455 break;
24456 }
24457
24458 _step7$value = slicedToArray(_step7.value, 2), id = _step7$value[0], item = _step7$value[1];
24459
24460 if (!callback(item, id)) {
24461 _context5.next = 10;
24462 break;
24463 }
24464
24465 _context5.next = 10;
24466 return [id, item];
24467
24468 case 10:
24469 _iteratorNormalCompletion7 = true;
24470 _context5.next = 5;
24471 break;
24472
24473 case 13:
24474 _context5.next = 19;
24475 break;
24476
24477 case 15:
24478 _context5.prev = 15;
24479 _context5.t0 = _context5["catch"](3);
24480 _didIteratorError7 = true;
24481 _iteratorError7 = _context5.t0;
24482
24483 case 19:
24484 _context5.prev = 19;
24485 _context5.prev = 20;
24486
24487 if (!_iteratorNormalCompletion7 && _iterator7.return != null) {
24488 _iterator7.return();
24489 }
24490
24491 case 22:
24492 _context5.prev = 22;
24493
24494 if (!_didIteratorError7) {
24495 _context5.next = 25;
24496 break;
24497 }
24498
24499 throw _iteratorError7;
24500
24501 case 25:
24502 return _context5.finish(22);
24503
24504 case 26:
24505 return _context5.finish(19);
24506
24507 case 27:
24508 case "end":
24509 return _context5.stop();
24510 }
24511 }
24512 }, _callee, null, [[3, 15, 19, 27], [20,, 22, 26]]);
24513 })));
24514 }
24515 /**
24516 * Execute a callback for each item of the stream.
24517 *
24518 * @param callback - The function that will be invoked for each item.
24519 */
24520
24521 }, {
24522 key: "forEach",
24523 value: function forEach(callback) {
24524 var _iteratorNormalCompletion8 = true;
24525 var _didIteratorError8 = false;
24526 var _iteratorError8 = undefined;
24527
24528 try {
24529 for (var _iterator8 = this._pairs[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
24530 var _step8$value = slicedToArray(_step8.value, 2),
24531 id = _step8$value[0],
24532 item = _step8$value[1];
24533
24534 callback(item, id);
24535 }
24536 } catch (err) {
24537 _didIteratorError8 = true;
24538 _iteratorError8 = err;
24539 } finally {
24540 try {
24541 if (!_iteratorNormalCompletion8 && _iterator8.return != null) {
24542 _iterator8.return();
24543 }
24544 } finally {
24545 if (_didIteratorError8) {
24546 throw _iteratorError8;
24547 }
24548 }
24549 }
24550 }
24551 /**
24552 * Map the items into a different type.
24553 *
24554 * @param callback - The function that does the conversion.
24555 *
24556 * @typeparam Mapped - The type of the item after mapping.
24557 *
24558 * @returns A new data stream with the mapped items.
24559 */
24560
24561 }, {
24562 key: "map",
24563 value: function map(callback) {
24564 var pairs = this._pairs;
24565 return new DataStream(defineProperty$6({}, Symbol.iterator,
24566 /*#__PURE__*/
24567 regenerator.mark(function _callee2() {
24568 var _iteratorNormalCompletion9, _didIteratorError9, _iteratorError9, _iterator9, _step9, _step9$value, id, item;
24569
24570 return regenerator.wrap(function _callee2$(_context6) {
24571 while (1) {
24572 switch (_context6.prev = _context6.next) {
24573 case 0:
24574 _iteratorNormalCompletion9 = true;
24575 _didIteratorError9 = false;
24576 _iteratorError9 = undefined;
24577 _context6.prev = 3;
24578 _iterator9 = pairs[Symbol.iterator]();
24579
24580 case 5:
24581 if (_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done) {
24582 _context6.next = 12;
24583 break;
24584 }
24585
24586 _step9$value = slicedToArray(_step9.value, 2), id = _step9$value[0], item = _step9$value[1];
24587 _context6.next = 9;
24588 return [id, callback(item, id)];
24589
24590 case 9:
24591 _iteratorNormalCompletion9 = true;
24592 _context6.next = 5;
24593 break;
24594
24595 case 12:
24596 _context6.next = 18;
24597 break;
24598
24599 case 14:
24600 _context6.prev = 14;
24601 _context6.t0 = _context6["catch"](3);
24602 _didIteratorError9 = true;
24603 _iteratorError9 = _context6.t0;
24604
24605 case 18:
24606 _context6.prev = 18;
24607 _context6.prev = 19;
24608
24609 if (!_iteratorNormalCompletion9 && _iterator9.return != null) {
24610 _iterator9.return();
24611 }
24612
24613 case 21:
24614 _context6.prev = 21;
24615
24616 if (!_didIteratorError9) {
24617 _context6.next = 24;
24618 break;
24619 }
24620
24621 throw _iteratorError9;
24622
24623 case 24:
24624 return _context6.finish(21);
24625
24626 case 25:
24627 return _context6.finish(18);
24628
24629 case 26:
24630 case "end":
24631 return _context6.stop();
24632 }
24633 }
24634 }, _callee2, null, [[3, 14, 18, 26], [19,, 21, 25]]);
24635 })));
24636 }
24637 /**
24638 * Get the item with the maximum value of given property.
24639 *
24640 * @param callback - The function that picks and possibly converts the property.
24641 *
24642 * @returns The item with the maximum if found otherwise null.
24643 */
24644
24645 }, {
24646 key: "max",
24647 value: function max(callback) {
24648 var iter = this._pairs[Symbol.iterator]();
24649
24650 var curr = iter.next();
24651
24652 if (curr.done) {
24653 return null;
24654 }
24655
24656 var maxItem = curr.value[1];
24657 var maxValue = callback(curr.value[1], curr.value[0]);
24658
24659 while (!(curr = iter.next()).done) {
24660 var _curr$value = slicedToArray(curr.value, 2),
24661 id = _curr$value[0],
24662 item = _curr$value[1];
24663
24664 var _value = callback(item, id);
24665
24666 if (_value > maxValue) {
24667 maxValue = _value;
24668 maxItem = item;
24669 }
24670 }
24671
24672 return maxItem;
24673 }
24674 /**
24675 * Get the item with the minimum value of given property.
24676 *
24677 * @param callback - The function that picks and possibly converts the property.
24678 *
24679 * @returns The item with the minimum if found otherwise null.
24680 */
24681
24682 }, {
24683 key: "min",
24684 value: function min(callback) {
24685 var iter = this._pairs[Symbol.iterator]();
24686
24687 var curr = iter.next();
24688
24689 if (curr.done) {
24690 return null;
24691 }
24692
24693 var minItem = curr.value[1];
24694 var minValue = callback(curr.value[1], curr.value[0]);
24695
24696 while (!(curr = iter.next()).done) {
24697 var _curr$value2 = slicedToArray(curr.value, 2),
24698 id = _curr$value2[0],
24699 item = _curr$value2[1];
24700
24701 var _value2 = callback(item, id);
24702
24703 if (_value2 < minValue) {
24704 minValue = _value2;
24705 minItem = item;
24706 }
24707 }
24708
24709 return minItem;
24710 }
24711 /**
24712 * Reduce the items into a single value.
24713 *
24714 * @param callback - The function that does the reduction.
24715 * @param accumulator - The initial value of the accumulator.
24716 *
24717 * @typeparam T - The type of the accumulated value.
24718 *
24719 * @returns The reduced value.
24720 */
24721
24722 }, {
24723 key: "reduce",
24724 value: function reduce(callback, accumulator) {
24725 var _iteratorNormalCompletion10 = true;
24726 var _didIteratorError10 = false;
24727 var _iteratorError10 = undefined;
24728
24729 try {
24730 for (var _iterator10 = this._pairs[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
24731 var _step10$value = slicedToArray(_step10.value, 2),
24732 id = _step10$value[0],
24733 item = _step10$value[1];
24734
24735 accumulator = callback(accumulator, item, id);
24736 }
24737 } catch (err) {
24738 _didIteratorError10 = true;
24739 _iteratorError10 = err;
24740 } finally {
24741 try {
24742 if (!_iteratorNormalCompletion10 && _iterator10.return != null) {
24743 _iterator10.return();
24744 }
24745 } finally {
24746 if (_didIteratorError10) {
24747 throw _iteratorError10;
24748 }
24749 }
24750 }
24751
24752 return accumulator;
24753 }
24754 /**
24755 * Sort the items.
24756 *
24757 * @param callback - Item comparator.
24758 *
24759 * @returns A new stream with sorted items.
24760 */
24761
24762 }, {
24763 key: "sort",
24764 value: function sort(callback) {
24765 var _this = this;
24766
24767 return new DataStream(defineProperty$6({}, Symbol.iterator, function () {
24768 return toConsumableArray(_this._pairs).sort(function (_ref3, _ref4) {
24769 var _ref5 = slicedToArray(_ref3, 2),
24770 idA = _ref5[0],
24771 itemA = _ref5[1];
24772
24773 var _ref6 = slicedToArray(_ref4, 2),
24774 idB = _ref6[0],
24775 itemB = _ref6[1];
24776
24777 return callback(itemA, itemB, idA, idB);
24778 })[Symbol.iterator]();
24779 }));
24780 }
24781 }]);
24782 return DataStream;
24783}();
24784
24785function ownKeys$3(object, enumerableOnly) {
24786 var keys = Object.keys(object);
24787
24788 if (Object.getOwnPropertySymbols) {
24789 keys.push.apply(keys, Object.getOwnPropertySymbols(object));
24790 }
24791
24792 if (enumerableOnly) keys = keys.filter(function (sym) {
24793 return Object.getOwnPropertyDescriptor(object, sym).enumerable;
24794 });
24795 return keys;
24796}
24797
24798function _objectSpread(target) {
24799 for (var i = 1; i < arguments.length; i++) {
24800 var source = arguments[i] != null ? arguments[i] : {};
24801
24802 if (i % 2) {
24803 ownKeys$3(source, true).forEach(function (key) {
24804 defineProperty$6(target, key, source[key]);
24805 });
24806 } else if (Object.getOwnPropertyDescriptors) {
24807 Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
24808 } else {
24809 ownKeys$3(source).forEach(function (key) {
24810 Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
24811 });
24812 }
24813 }
24814
24815 return target;
24816}
24817/**
24818 * # DataSet
24819 *
24820 * Vis.js comes with a flexible DataSet, which can be used to hold and manipulate unstructured data and listen for changes in the data. The DataSet is key/value based. Data items can be added, updated and removed from the DataSet, and one can subscribe to changes in the DataSet. The data in the DataSet can be filtered and ordered, and fields (like dates) can be converted to a specific type. Data can be normalized when appending it to the DataSet as well.
24821 *
24822 * ## Example
24823 *
24824 * The following example shows how to use a DataSet.
24825 *
24826 * ```javascript
24827 * // create a DataSet
24828 * var options = {};
24829 * var data = new vis.DataSet(options);
24830 *
24831 * // add items
24832 * // note that the data items can contain different properties and data formats
24833 * data.add([
24834 * {id: 1, text: 'item 1', date: new Date(2013, 6, 20), group: 1, first: true},
24835 * {id: 2, text: 'item 2', date: '2013-06-23', group: 2},
24836 * {id: 3, text: 'item 3', date: '2013-06-25', group: 2},
24837 * {id: 4, text: 'item 4'}
24838 * ]);
24839 *
24840 * // subscribe to any change in the DataSet
24841 * data.on('*', function (event, properties, senderId) {
24842 * console.log('event', event, properties);
24843 * });
24844 *
24845 * // update an existing item
24846 * data.update({id: 2, group: 1});
24847 *
24848 * // remove an item
24849 * data.remove(4);
24850 *
24851 * // get all ids
24852 * var ids = data.getIds();
24853 * console.log('ids', ids);
24854 *
24855 * // get a specific item
24856 * var item1 = data.get(1);
24857 * console.log('item1', item1);
24858 *
24859 * // retrieve a filtered subset of the data
24860 * var items = data.get({
24861 * filter: function (item) {
24862 * return item.group == 1;
24863 * }
24864 * });
24865 * console.log('filtered items', items);
24866 *
24867 * // retrieve formatted items
24868 * var items = data.get({
24869 * fields: ['id', 'date'],
24870 * type: {
24871 * date: 'ISODate'
24872 * }
24873 * });
24874 * console.log('formatted items', items);
24875 * ```
24876 *
24877 * @typeParam Item - Item type that may or may not have an id.
24878 * @typeParam IdProp - Name of the property that contains the id.
24879 */
24880
24881
24882var DataSet =
24883/*#__PURE__*/
24884function (_DataSetPart) {
24885 inherits(DataSet, _DataSetPart);
24886 /**
24887 * Construct a new DataSet.
24888 *
24889 * @param data - Initial data or options.
24890 * @param options - Options (type error if data is also options).
24891 */
24892
24893 function DataSet(data, options) {
24894 var _this;
24895
24896 classCallCheck(this, DataSet);
24897 _this = possibleConstructorReturn(this, getPrototypeOf(DataSet).call(this)); // correctly read optional arguments
24898
24899 if (data && !Array.isArray(data)) {
24900 options = data;
24901 data = [];
24902 }
24903
24904 _this._options = options || {};
24905 _this._data = new Map(); // map with data indexed by id
24906
24907 _this.length = 0; // number of items in the DataSet
24908
24909 _this._idProp = _this._options.fieldId || "id"; // name of the field containing id
24910
24911 _this._type = {}; // internal field types (NOTE: this can differ from this._options.type)
24912 // all variants of a Date are internally stored as Date, so we can convert
24913 // from everything to everything (also from ISODate to Number for example)
24914
24915 if (_this._options.type) {
24916 var fields = Object.keys(_this._options.type);
24917
24918 for (var i = 0, len = fields.length; i < len; i++) {
24919 var field = fields[i];
24920 var value = _this._options.type[field];
24921
24922 if (value == "Date" || value == "ISODate" || value == "ASPDate") {
24923 _this._type[field] = "Date";
24924 } else {
24925 _this._type[field] = value;
24926 }
24927 }
24928 } // add initial data when provided
24929
24930
24931 if (data && data.length) {
24932 _this.add(data);
24933 }
24934
24935 _this.setOptions(options);
24936
24937 return _this;
24938 }
24939 /**
24940 * Set new options.
24941 *
24942 * @param options - The new options.
24943 */
24944
24945
24946 createClass(DataSet, [{
24947 key: "setOptions",
24948 value: function setOptions(options) {
24949 if (options && options.queue !== undefined) {
24950 if (options.queue === false) {
24951 // delete queue if loaded
24952 if (this._queue) {
24953 this._queue.destroy();
24954
24955 delete this._queue;
24956 }
24957 } else {
24958 // create queue and update its options
24959 if (!this._queue) {
24960 this._queue = Queue.extend(this, {
24961 replace: ["add", "update", "remove"]
24962 });
24963 }
24964
24965 if (options.queue && _typeof_1(options.queue) === "object") {
24966 this._queue.setOptions(options.queue);
24967 }
24968 }
24969 }
24970 }
24971 /**
24972 * Add a data item or an array with items.
24973 *
24974 * After the items are added to the DataSet, the DataSet will trigger an event `add`. When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
24975 *
24976 * ## Example
24977 *
24978 * ```javascript
24979 * // create a DataSet
24980 * const data = new vis.DataSet()
24981 *
24982 * // add items
24983 * const ids = data.add([
24984 * { id: 1, text: 'item 1' },
24985 * { id: 2, text: 'item 2' },
24986 * { text: 'item without an id' }
24987 * ])
24988 *
24989 * console.log(ids) // [1, 2, '<UUIDv4>']
24990 * ```
24991 *
24992 * @param data - Items to be added (ids will be generated if missing).
24993 * @param senderId - Sender id.
24994 *
24995 * @returns addedIds - Array with the ids (generated if not present) of the added items.
24996 *
24997 * @throws When an item with the same id as any of the added items already exists.
24998 */
24999
25000 }, {
25001 key: "add",
25002 value: function add(data, senderId) {
25003 var _this2 = this;
25004
25005 var addedIds = [];
25006 var id;
25007
25008 if (Array.isArray(data)) {
25009 // Array
25010 var idsToAdd = data.map(function (d) {
25011 return d[_this2._idProp];
25012 });
25013
25014 if (idsToAdd.some(function (id) {
25015 return _this2._data.has(id);
25016 })) {
25017 throw new Error("A duplicate id was found in the parameter array.");
25018 }
25019
25020 for (var i = 0, len = data.length; i < len; i++) {
25021 id = this._addItem(data[i]);
25022 addedIds.push(id);
25023 }
25024 } else if (data && _typeof_1(data) === "object") {
25025 // Single item
25026 id = this._addItem(data);
25027 addedIds.push(id);
25028 } else {
25029 throw new Error("Unknown dataType");
25030 }
25031
25032 if (addedIds.length) {
25033 this._trigger("add", {
25034 items: addedIds
25035 }, senderId);
25036 }
25037
25038 return addedIds;
25039 }
25040 /**
25041 * Update existing items. When an item does not exist, it will be created.
25042 *
25043 * @remarks
25044 * The provided properties will be merged in the existing item. When an item does not exist, it will be created.
25045 *
25046 * After the items are updated, the DataSet will trigger an event `add` for the added items, and an event `update`. When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
25047 *
25048 * ## Example
25049 *
25050 * ```javascript
25051 * // create a DataSet
25052 * const data = new vis.DataSet([
25053 * { id: 1, text: 'item 1' },
25054 * { id: 2, text: 'item 2' },
25055 * { id: 3, text: 'item 3' }
25056 * ])
25057 *
25058 * // update items
25059 * const ids = data.update([
25060 * { id: 2, text: 'item 2 (updated)' },
25061 * { id: 4, text: 'item 4 (new)' }
25062 * ])
25063 *
25064 * console.log(ids) // [2, 4]
25065 * ```
25066 *
25067 * ## Warning for TypeScript users
25068 * This method may introduce partial items into the data set. Use add or updateOnly instead for better type safety.
25069 *
25070 * @param data - Items to be updated (if the id is already present) or added (if the id is missing).
25071 * @param senderId - Sender id.
25072 *
25073 * @returns updatedIds - The ids of the added (these may be newly generated if there was no id in the item from the data) or updated items.
25074 *
25075 * @throws When the supplied data is neither an item nor an array of items.
25076 */
25077
25078 }, {
25079 key: "update",
25080 value: function update(data, senderId) {
25081 var _this3 = this;
25082
25083 var addedIds = [];
25084 var updatedIds = [];
25085 var oldData = [];
25086 var updatedData = [];
25087 var idProp = this._idProp;
25088
25089 var addOrUpdate = function addOrUpdate(item) {
25090 var origId = item[idProp];
25091
25092 if (origId != null && _this3._data.has(origId)) {
25093 var fullItem = item; // it has an id, therefore it is a fullitem
25094
25095 var oldItem = Object.assign({}, _this3._data.get(origId)); // update item
25096
25097 var id = _this3._updateItem(fullItem);
25098
25099 updatedIds.push(id);
25100 updatedData.push(fullItem);
25101 oldData.push(oldItem);
25102 } else {
25103 // add new item
25104 var _id = _this3._addItem(item);
25105
25106 addedIds.push(_id);
25107 }
25108 };
25109
25110 if (Array.isArray(data)) {
25111 // Array
25112 for (var i = 0, len = data.length; i < len; i++) {
25113 if (data[i] && _typeof_1(data[i]) === "object") {
25114 addOrUpdate(data[i]);
25115 } else {
25116 console.warn("Ignoring input item, which is not an object at index " + i);
25117 }
25118 }
25119 } else if (data && _typeof_1(data) === "object") {
25120 // Single item
25121 addOrUpdate(data);
25122 } else {
25123 throw new Error("Unknown dataType");
25124 }
25125
25126 if (addedIds.length) {
25127 this._trigger("add", {
25128 items: addedIds
25129 }, senderId);
25130 }
25131
25132 if (updatedIds.length) {
25133 var props = {
25134 items: updatedIds,
25135 oldData: oldData,
25136 data: updatedData
25137 }; // TODO: remove deprecated property 'data' some day
25138 //Object.defineProperty(props, 'data', {
25139 // 'get': (function() {
25140 // console.warn('Property data is deprecated. Use DataSet.get(ids) to retrieve the new data, use the oldData property on this object to get the old data');
25141 // return updatedData;
25142 // }).bind(this)
25143 //});
25144
25145 this._trigger("update", props, senderId);
25146 }
25147
25148 return addedIds.concat(updatedIds);
25149 }
25150 /**
25151 * Update existing items. When an item does not exist, an error will be thrown.
25152 *
25153 * @remarks
25154 * The provided properties will be deeply merged into the existing item.
25155 * When an item does not exist (id not present in the data set or absent), an error will be thrown and nothing will be changed.
25156 *
25157 * After the items are updated, the DataSet will trigger an event `update`.
25158 * When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
25159 *
25160 * ## Example
25161 *
25162 * ```javascript
25163 * // create a DataSet
25164 * const data = new vis.DataSet([
25165 * { id: 1, text: 'item 1' },
25166 * { id: 2, text: 'item 2' },
25167 * { id: 3, text: 'item 3' },
25168 * ])
25169 *
25170 * // update items
25171 * const ids = data.update([
25172 * { id: 2, text: 'item 2 (updated)' }, // works
25173 * // { id: 4, text: 'item 4 (new)' }, // would throw
25174 * // { text: 'item 4 (new)' }, // would also throw
25175 * ])
25176 *
25177 * console.log(ids) // [2]
25178 * ```
25179 *
25180 * @param data - Updates (the id and optionally other props) to the items in this data set.
25181 * @param senderId - Sender id.
25182 *
25183 * @returns updatedIds - The ids of the updated items.
25184 *
25185 * @throws When the supplied data is neither an item nor an array of items, when the ids are missing.
25186 */
25187
25188 }, {
25189 key: "updateOnly",
25190 value: function updateOnly(data, senderId) {
25191 var _this4 = this;
25192
25193 if (!Array.isArray(data)) {
25194 data = [data];
25195 }
25196
25197 var updateEventData = data.map(function (update) {
25198 var oldData = _this4._data.get(update[_this4._idProp]);
25199
25200 if (oldData == null) {
25201 throw new Error("Updating non-existent items is not allowed.");
25202 }
25203
25204 return {
25205 oldData: oldData,
25206 update: update
25207 };
25208 }).map(function (_ref) {
25209 var oldData = _ref.oldData,
25210 update = _ref.update;
25211 var id = oldData[_this4._idProp];
25212 var updatedData = deepExtend$1(deepExtend$1({}, oldData), update);
25213
25214 _this4._data.set(id, updatedData);
25215
25216 return {
25217 id: id,
25218 oldData: oldData,
25219 updatedData: updatedData
25220 };
25221 });
25222
25223 if (updateEventData.length) {
25224 var props = {
25225 items: updateEventData.map(function (value) {
25226 return value.id;
25227 }),
25228 oldData: updateEventData.map(function (value) {
25229 return value.oldData;
25230 }),
25231 data: updateEventData.map(function (value) {
25232 return value.updatedData;
25233 })
25234 }; // TODO: remove deprecated property 'data' some day
25235 //Object.defineProperty(props, 'data', {
25236 // 'get': (function() {
25237 // console.warn('Property data is deprecated. Use DataSet.get(ids) to retrieve the new data, use the oldData property on this object to get the old data');
25238 // return updatedData;
25239 // }).bind(this)
25240 //});
25241
25242 this._trigger("update", props, senderId);
25243
25244 return props.items;
25245 } else {
25246 return [];
25247 }
25248 }
25249 /** @inheritdoc */
25250
25251 }, {
25252 key: "get",
25253 value: function get(first, second) {
25254 // @TODO: Woudn't it be better to split this into multiple methods?
25255 // parse the arguments
25256 var id = undefined;
25257 var ids = undefined;
25258 var options = undefined;
25259
25260 if (isId(first)) {
25261 // get(id [, options])
25262 id = first;
25263 options = second;
25264 } else if (Array.isArray(first)) {
25265 // get(ids [, options])
25266 ids = first;
25267 options = second;
25268 } else {
25269 // get([, options])
25270 options = first;
25271 } // determine the return type
25272
25273
25274 var returnType = options && options.returnType === "Object" ? "Object" : "Array"; // @TODO: WTF is this? Or am I missing something?
25275 // var returnType
25276 // if (options && options.returnType) {
25277 // var allowedValues = ['Array', 'Object']
25278 // returnType =
25279 // allowedValues.indexOf(options.returnType) == -1
25280 // ? 'Array'
25281 // : options.returnType
25282 // } else {
25283 // returnType = 'Array'
25284 // }
25285 // build options
25286
25287 var type = options && options.type || this._options.type;
25288 var filter = options && options.filter;
25289 var items = [];
25290 var item = null;
25291 var itemIds = null;
25292 var itemId = null; // convert items
25293
25294 if (id != null) {
25295 // return a single item
25296 item = this._getItem(id, type);
25297
25298 if (item && filter && !filter(item)) {
25299 item = null;
25300 }
25301 } else if (ids != null) {
25302 // return a subset of items
25303 for (var i = 0, len = ids.length; i < len; i++) {
25304 item = this._getItem(ids[i], type);
25305
25306 if (item != null && (!filter || filter(item))) {
25307 items.push(item);
25308 }
25309 }
25310 } else {
25311 // return all items
25312 itemIds = toConsumableArray(this._data.keys());
25313
25314 for (var _i = 0, _len = itemIds.length; _i < _len; _i++) {
25315 itemId = itemIds[_i];
25316 item = this._getItem(itemId, type);
25317
25318 if (item != null && (!filter || filter(item))) {
25319 items.push(item);
25320 }
25321 }
25322 } // order the results
25323
25324
25325 if (options && options.order && id == undefined) {
25326 this._sort(items, options.order);
25327 } // filter fields of the items
25328
25329
25330 if (options && options.fields) {
25331 var fields = options.fields;
25332
25333 if (id != undefined && item != null) {
25334 item = this._filterFields(item, fields);
25335 } else {
25336 for (var _i2 = 0, _len2 = items.length; _i2 < _len2; _i2++) {
25337 items[_i2] = this._filterFields(items[_i2], fields);
25338 }
25339 }
25340 } // return the results
25341
25342
25343 if (returnType == "Object") {
25344 var result = {};
25345
25346 for (var _i3 = 0, _len3 = items.length; _i3 < _len3; _i3++) {
25347 var resultant = items[_i3]; // @TODO: Shoudn't this be this._fieldId?
25348 // result[resultant.id] = resultant
25349
25350 var _id2 = resultant[this._idProp];
25351 result[_id2] = resultant;
25352 }
25353
25354 return result;
25355 } else {
25356 if (id != null) {
25357 // a single item
25358 return item;
25359 } else {
25360 // just return our array
25361 return items;
25362 }
25363 }
25364 }
25365 /** @inheritdoc */
25366
25367 }, {
25368 key: "getIds",
25369 value: function getIds(options) {
25370 var data = this._data;
25371 var filter = options && options.filter;
25372 var order = options && options.order;
25373 var type = options && options.type || this._options.type;
25374 var itemIds = toConsumableArray(data.keys());
25375 var ids = [];
25376 var item;
25377 var items;
25378
25379 if (filter) {
25380 // get filtered items
25381 if (order) {
25382 // create ordered list
25383 items = [];
25384
25385 for (var i = 0, len = itemIds.length; i < len; i++) {
25386 var id = itemIds[i];
25387 item = this._getItem(id, type);
25388
25389 if (filter(item)) {
25390 items.push(item);
25391 }
25392 }
25393
25394 this._sort(items, order);
25395
25396 for (var _i4 = 0, _len4 = items.length; _i4 < _len4; _i4++) {
25397 ids.push(items[_i4][this._idProp]);
25398 }
25399 } else {
25400 // create unordered list
25401 for (var _i5 = 0, _len5 = itemIds.length; _i5 < _len5; _i5++) {
25402 var _id3 = itemIds[_i5];
25403 item = this._getItem(_id3, type);
25404
25405 if (filter(item)) {
25406 ids.push(item[this._idProp]);
25407 }
25408 }
25409 }
25410 } else {
25411 // get all items
25412 if (order) {
25413 // create an ordered list
25414 items = [];
25415
25416 for (var _i6 = 0, _len6 = itemIds.length; _i6 < _len6; _i6++) {
25417 var _id4 = itemIds[_i6];
25418 items.push(data.get(_id4));
25419 }
25420
25421 this._sort(items, order);
25422
25423 for (var _i7 = 0, _len7 = items.length; _i7 < _len7; _i7++) {
25424 ids.push(items[_i7][this._idProp]);
25425 }
25426 } else {
25427 // create unordered list
25428 for (var _i8 = 0, _len8 = itemIds.length; _i8 < _len8; _i8++) {
25429 var _id5 = itemIds[_i8];
25430 item = data.get(_id5);
25431 ids.push(item[this._idProp]);
25432 }
25433 }
25434 }
25435
25436 return ids;
25437 }
25438 /** @inheritdoc */
25439
25440 }, {
25441 key: "getDataSet",
25442 value: function getDataSet() {
25443 return this;
25444 }
25445 /** @inheritdoc */
25446
25447 }, {
25448 key: "forEach",
25449 value: function forEach(callback, options) {
25450 var filter = options && options.filter;
25451 var type = options && options.type || this._options.type;
25452 var data = this._data;
25453 var itemIds = toConsumableArray(data.keys());
25454
25455 if (options && options.order) {
25456 // execute forEach on ordered list
25457 var items = this.get(options);
25458
25459 for (var i = 0, len = items.length; i < len; i++) {
25460 var item = items[i];
25461 var id = item[this._idProp];
25462 callback(item, id);
25463 }
25464 } else {
25465 // unordered
25466 for (var _i9 = 0, _len9 = itemIds.length; _i9 < _len9; _i9++) {
25467 var _id6 = itemIds[_i9];
25468
25469 var _item = this._getItem(_id6, type);
25470
25471 if (!filter || filter(_item)) {
25472 callback(_item, _id6);
25473 }
25474 }
25475 }
25476 }
25477 /** @inheritdoc */
25478
25479 }, {
25480 key: "map",
25481 value: function map(callback, options) {
25482 var filter = options && options.filter;
25483 var type = options && options.type || this._options.type;
25484 var mappedItems = [];
25485 var data = this._data;
25486 var itemIds = toConsumableArray(data.keys()); // convert and filter items
25487
25488 for (var i = 0, len = itemIds.length; i < len; i++) {
25489 var id = itemIds[i];
25490
25491 var item = this._getItem(id, type);
25492
25493 if (!filter || filter(item)) {
25494 mappedItems.push(callback(item, id));
25495 }
25496 } // order items
25497
25498
25499 if (options && options.order) {
25500 this._sort(mappedItems, options.order);
25501 }
25502
25503 return mappedItems;
25504 }
25505 /**
25506 * Filter the fields of an item.
25507 *
25508 * @param item - The item whose fields should be filtered.
25509 * @param fields - The names of the fields that will be kept.
25510 *
25511 * @typeParam K - Field name type.
25512 *
25513 * @returns The item without any additional fields.
25514 */
25515
25516 }, {
25517 key: "_filterFields",
25518 value: function _filterFields(item, fields) {
25519 if (!item) {
25520 // item is null
25521 return item;
25522 }
25523
25524 return (Array.isArray(fields) ? // Use the supplied array
25525 fields : // Use the keys of the supplied object
25526 Object.keys(fields)).reduce(function (filteredItem, field) {
25527 filteredItem[field] = item[field];
25528 return filteredItem;
25529 }, {});
25530 }
25531 /**
25532 * Sort the provided array with items.
25533 *
25534 * @param items - Items to be sorted in place.
25535 * @param order - A field name or custom sort function.
25536 *
25537 * @typeParam T - The type of the items in the items array.
25538 */
25539
25540 }, {
25541 key: "_sort",
25542 value: function _sort(items, order) {
25543 if (typeof order === "string") {
25544 // order by provided field name
25545 var name = order; // field name
25546
25547 items.sort(function (a, b) {
25548 // @TODO: How to treat missing properties?
25549 var av = a[name];
25550 var bv = b[name];
25551 return av > bv ? 1 : av < bv ? -1 : 0;
25552 });
25553 } else if (typeof order === "function") {
25554 // order by sort function
25555 items.sort(order);
25556 } else {
25557 // TODO: extend order by an Object {field:string, direction:string}
25558 // where direction can be 'asc' or 'desc'
25559 throw new TypeError("Order must be a function or a string");
25560 }
25561 }
25562 /**
25563 * Remove an item or multiple items by “reference” (only the id is used) or by id.
25564 *
25565 * The method ignores removal of non-existing items, and returns an array containing the ids of the items which are actually removed from the DataSet.
25566 *
25567 * After the items are removed, the DataSet will trigger an event `remove` for the removed items. When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
25568 *
25569 * ## Example
25570 * ```javascript
25571 * // create a DataSet
25572 * const data = new vis.DataSet([
25573 * { id: 1, text: 'item 1' },
25574 * { id: 2, text: 'item 2' },
25575 * { id: 3, text: 'item 3' }
25576 * ])
25577 *
25578 * // remove items
25579 * const ids = data.remove([2, { id: 3 }, 4])
25580 *
25581 * console.log(ids) // [2, 3]
25582 * ```
25583 *
25584 * @param id - One or more items or ids of items to be removed.
25585 * @param senderId - Sender id.
25586 *
25587 * @returns The ids of the removed items.
25588 */
25589
25590 }, {
25591 key: "remove",
25592 value: function remove(id, senderId) {
25593 var removedIds = [];
25594 var removedItems = []; // force everything to be an array for simplicity
25595
25596 var ids = Array.isArray(id) ? id : [id];
25597
25598 for (var i = 0, len = ids.length; i < len; i++) {
25599 var item = this._remove(ids[i]);
25600
25601 if (item) {
25602 var itemId = item[this._idProp];
25603
25604 if (itemId != null) {
25605 removedIds.push(itemId);
25606 removedItems.push(item);
25607 }
25608 }
25609 }
25610
25611 if (removedIds.length) {
25612 this._trigger("remove", {
25613 items: removedIds,
25614 oldData: removedItems
25615 }, senderId);
25616 }
25617
25618 return removedIds;
25619 }
25620 /**
25621 * Remove an item by its id or reference.
25622 *
25623 * @param id - Id of an item or the item itself.
25624 *
25625 * @returns The removed item if removed, null otherwise.
25626 */
25627
25628 }, {
25629 key: "_remove",
25630 value: function _remove(id) {
25631 // @TODO: It origianlly returned the item although the docs say id.
25632 // The code expects the item, so probably an error in the docs.
25633 var ident; // confirm the id to use based on the args type
25634
25635 if (isId(id)) {
25636 ident = id;
25637 } else if (id && _typeof_1(id) === "object") {
25638 ident = id[this._idProp]; // look for the identifier field using ._idProp
25639 } // do the removing if the item is found
25640
25641
25642 if (ident != null && this._data.has(ident)) {
25643 var item = this._data.get(ident) || null;
25644
25645 this._data.delete(ident);
25646
25647 --this.length;
25648 return item;
25649 }
25650
25651 return null;
25652 }
25653 /**
25654 * Clear the entire data set.
25655 *
25656 * After the items are removed, the [[DataSet]] will trigger an event `remove` for all removed items. When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
25657 *
25658 * @param senderId - Sender id.
25659 *
25660 * @returns removedIds - The ids of all removed items.
25661 */
25662
25663 }, {
25664 key: "clear",
25665 value: function clear(senderId) {
25666 var ids = toConsumableArray(this._data.keys());
25667 var items = [];
25668
25669 for (var i = 0, len = ids.length; i < len; i++) {
25670 items.push(this._data.get(ids[i]));
25671 }
25672
25673 this._data.clear();
25674
25675 this.length = 0;
25676
25677 this._trigger("remove", {
25678 items: ids,
25679 oldData: items
25680 }, senderId);
25681
25682 return ids;
25683 }
25684 /**
25685 * Find the item with maximum value of a specified field.
25686 *
25687 * @param field - Name of the property that should be searched for max value.
25688 *
25689 * @returns Item containing max value, or null if no items.
25690 */
25691
25692 }, {
25693 key: "max",
25694 value: function max(field) {
25695 var max = null;
25696 var maxField = null;
25697 var _iteratorNormalCompletion = true;
25698 var _didIteratorError = false;
25699 var _iteratorError = undefined;
25700
25701 try {
25702 for (var _iterator = this._data.values()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
25703 var item = _step.value;
25704 var itemField = item[field];
25705
25706 if (typeof itemField === "number" && (maxField == null || itemField > maxField)) {
25707 max = item;
25708 maxField = itemField;
25709 }
25710 }
25711 } catch (err) {
25712 _didIteratorError = true;
25713 _iteratorError = err;
25714 } finally {
25715 try {
25716 if (!_iteratorNormalCompletion && _iterator.return != null) {
25717 _iterator.return();
25718 }
25719 } finally {
25720 if (_didIteratorError) {
25721 throw _iteratorError;
25722 }
25723 }
25724 }
25725
25726 return max || null;
25727 }
25728 /**
25729 * Find the item with minimum value of a specified field.
25730 *
25731 * @param field - Name of the property that should be searched for min value.
25732 *
25733 * @returns Item containing min value, or null if no items.
25734 */
25735
25736 }, {
25737 key: "min",
25738 value: function min(field) {
25739 var min = null;
25740 var minField = null;
25741 var _iteratorNormalCompletion2 = true;
25742 var _didIteratorError2 = false;
25743 var _iteratorError2 = undefined;
25744
25745 try {
25746 for (var _iterator2 = this._data.values()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
25747 var item = _step2.value;
25748 var itemField = item[field];
25749
25750 if (typeof itemField === "number" && (minField == null || itemField < minField)) {
25751 min = item;
25752 minField = itemField;
25753 }
25754 }
25755 } catch (err) {
25756 _didIteratorError2 = true;
25757 _iteratorError2 = err;
25758 } finally {
25759 try {
25760 if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
25761 _iterator2.return();
25762 }
25763 } finally {
25764 if (_didIteratorError2) {
25765 throw _iteratorError2;
25766 }
25767 }
25768 }
25769
25770 return min || null;
25771 }
25772 /**
25773 * Find all distinct values of a specified field
25774 *
25775 * @param prop - The property name whose distinct values should be returned.
25776 *
25777 * @returns Unordered array containing all distinct values. Items without specified property are ignored.
25778 */
25779
25780 }, {
25781 key: "distinct",
25782 value: function distinct(prop) {
25783 var data = this._data;
25784 var itemIds = toConsumableArray(data.keys());
25785 var values = [];
25786 var fieldType = this._options.type && this._options.type[prop] || null;
25787 var count = 0;
25788
25789 for (var i = 0, len = itemIds.length; i < len; i++) {
25790 var id = itemIds[i];
25791 var item = data.get(id);
25792 var value = item[prop];
25793 var exists = false;
25794
25795 for (var j = 0; j < count; j++) {
25796 if (values[j] == value) {
25797 exists = true;
25798 break;
25799 }
25800 }
25801
25802 if (!exists && value !== undefined) {
25803 values[count] = value;
25804 count++;
25805 }
25806 }
25807
25808 if (fieldType) {
25809 for (var _i10 = 0, _len10 = values.length; _i10 < _len10; _i10++) {
25810 values[_i10] = convert$1(values[_i10], fieldType);
25811 }
25812 }
25813
25814 return values;
25815 }
25816 /**
25817 * Add a single item. Will fail when an item with the same id already exists.
25818 *
25819 * @param item - A new item to be added.
25820 *
25821 * @returns Added item's id. An id is generated when it is not present in the item.
25822 */
25823
25824 }, {
25825 key: "_addItem",
25826 value: function _addItem(item) {
25827 var id = item[this._idProp];
25828
25829 if (id != null) {
25830 // check whether this id is already taken
25831 if (this._data.has(id)) {
25832 // item already exists
25833 throw new Error("Cannot add item: item with id " + id + " already exists");
25834 }
25835 } else {
25836 // generate an id
25837 id = uuid4$1();
25838 item[this._idProp] = id;
25839 }
25840
25841 var d = {};
25842 var fields = Object.keys(item);
25843
25844 for (var i = 0, len = fields.length; i < len; i++) {
25845 var field = fields[i];
25846 var fieldType = this._type[field]; // type may be undefined
25847
25848 d[field] = convert$1(item[field], fieldType);
25849 }
25850
25851 this._data.set(id, d);
25852
25853 ++this.length;
25854 return id;
25855 }
25856 /**
25857 * Get an item. Fields can be converted to a specific type
25858 *
25859 * @param id - Id of the requested item.
25860 * @param types - Property name to type name object map of type converstions.
25861 *
25862 * @returns The item, optionally after type conversion.
25863 */
25864
25865 }, {
25866 key: "_getItem",
25867 value: function _getItem(id, types) {
25868 // @TODO: I have no idea how to type this.
25869 // get the item from the dataset
25870 var raw = this._data.get(id);
25871
25872 if (!raw) {
25873 return null;
25874 } // convert the items field types
25875
25876
25877 var converted;
25878 var fields = Object.keys(raw);
25879
25880 if (types) {
25881 converted = {};
25882
25883 for (var i = 0, len = fields.length; i < len; i++) {
25884 var field = fields[i];
25885 var value = raw[field];
25886 converted[field] = convert$1(value, types[field]);
25887 }
25888 } else {
25889 // no field types specified, no converting needed
25890 converted = _objectSpread({}, raw);
25891 }
25892
25893 if (converted[this._idProp] == null) {
25894 converted[this._idProp] = raw.id;
25895 }
25896
25897 return converted;
25898 }
25899 /**
25900 * Update a single item: merge with existing item.
25901 * Will fail when the item has no id, or when there does not exist an item with the same id.
25902 *
25903 * @param item - The new item
25904 *
25905 * @returns The id of the updated item.
25906 */
25907
25908 }, {
25909 key: "_updateItem",
25910 value: function _updateItem(item) {
25911 var id = item[this._idProp];
25912
25913 if (id == null) {
25914 throw new Error("Cannot update item: item has no id (item: " + JSON.stringify(item) + ")");
25915 }
25916
25917 var d = this._data.get(id);
25918
25919 if (!d) {
25920 // item doesn't exist
25921 throw new Error("Cannot update item: no item with id " + id + " found");
25922 } // merge with current item
25923
25924
25925 var fields = Object.keys(item);
25926
25927 for (var i = 0, len = fields.length; i < len; i++) {
25928 var field = fields[i];
25929 var fieldType = this._type[field]; // type may be undefined
25930
25931 d[field] = convert$1(item[field], fieldType);
25932 }
25933
25934 return id;
25935 }
25936 /** @inheritdoc */
25937
25938 }, {
25939 key: "stream",
25940 value: function stream(ids) {
25941 if (ids) {
25942 var data = this._data;
25943 return new DataStream(defineProperty$6({}, Symbol.iterator,
25944 /*#__PURE__*/
25945 regenerator.mark(function _callee() {
25946 var _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, id, item;
25947
25948 return regenerator.wrap(function _callee$(_context) {
25949 while (1) {
25950 switch (_context.prev = _context.next) {
25951 case 0:
25952 _iteratorNormalCompletion3 = true;
25953 _didIteratorError3 = false;
25954 _iteratorError3 = undefined;
25955 _context.prev = 3;
25956 _iterator3 = ids[Symbol.iterator]();
25957
25958 case 5:
25959 if (_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done) {
25960 _context.next = 14;
25961 break;
25962 }
25963
25964 id = _step3.value;
25965 item = data.get(id);
25966
25967 if (!(item != null)) {
25968 _context.next = 11;
25969 break;
25970 }
25971
25972 _context.next = 11;
25973 return [id, item];
25974
25975 case 11:
25976 _iteratorNormalCompletion3 = true;
25977 _context.next = 5;
25978 break;
25979
25980 case 14:
25981 _context.next = 20;
25982 break;
25983
25984 case 16:
25985 _context.prev = 16;
25986 _context.t0 = _context["catch"](3);
25987 _didIteratorError3 = true;
25988 _iteratorError3 = _context.t0;
25989
25990 case 20:
25991 _context.prev = 20;
25992 _context.prev = 21;
25993
25994 if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
25995 _iterator3.return();
25996 }
25997
25998 case 23:
25999 _context.prev = 23;
26000
26001 if (!_didIteratorError3) {
26002 _context.next = 26;
26003 break;
26004 }
26005
26006 throw _iteratorError3;
26007
26008 case 26:
26009 return _context.finish(23);
26010
26011 case 27:
26012 return _context.finish(20);
26013
26014 case 28:
26015 case "end":
26016 return _context.stop();
26017 }
26018 }
26019 }, _callee, null, [[3, 16, 20, 28], [21,, 23, 27]]);
26020 })));
26021 } else {
26022 return new DataStream(defineProperty$6({}, Symbol.iterator, this._data.entries.bind(this._data)));
26023 }
26024 }
26025 }]);
26026 return DataSet;
26027}(DataSetPart);
26028/**
26029 * DataView
26030 *
26031 * A DataView offers a filtered and/or formatted view on a DataSet. One can subscribe to changes in a DataView, and easily get filtered or formatted data without having to specify filters and field types all the time.
26032 *
26033 * ## Example
26034 * ```javascript
26035 * // create a DataSet
26036 * var data = new vis.DataSet();
26037 * data.add([
26038 * {id: 1, text: 'item 1', date: new Date(2013, 6, 20), group: 1, first: true},
26039 * {id: 2, text: 'item 2', date: '2013-06-23', group: 2},
26040 * {id: 3, text: 'item 3', date: '2013-06-25', group: 2},
26041 * {id: 4, text: 'item 4'}
26042 * ]);
26043 *
26044 * // create a DataView
26045 * // the view will only contain items having a property group with value 1,
26046 * // and will only output fields id, text, and date.
26047 * var view = new vis.DataView(data, {
26048 * filter: function (item) {
26049 * return (item.group == 1);
26050 * },
26051 * fields: ['id', 'text', 'date']
26052 * });
26053 *
26054 * // subscribe to any change in the DataView
26055 * view.on('*', function (event, properties, senderId) {
26056 * console.log('event', event, properties);
26057 * });
26058 *
26059 * // update an item in the data set
26060 * data.update({id: 2, group: 1});
26061 *
26062 * // get all ids in the view
26063 * var ids = view.getIds();
26064 * console.log('ids', ids); // will output [1, 2]
26065 *
26066 * // get all items in the view
26067 * var items = view.get();
26068 * ```
26069 *
26070 * @typeParam Item - Item type that may or may not have an id.
26071 * @typeParam IdProp - Name of the property that contains the id.
26072 */
26073
26074
26075var DataView$2 =
26076/*#__PURE__*/
26077function (_DataSetPart) {
26078 inherits(DataView, _DataSetPart);
26079 /**
26080 * Create a DataView.
26081 *
26082 * @param data - The instance containing data (directly or indirectly).
26083 * @param options - Options to configure this data view.
26084 */
26085
26086 function DataView(data, options) {
26087 var _this;
26088
26089 classCallCheck(this, DataView);
26090 _this = possibleConstructorReturn(this, getPrototypeOf(DataView).call(this));
26091 /** @inheritdoc */
26092
26093 _this.length = 0;
26094 _this._ids = new Set(); // ids of the items currently in memory (just contains a boolean true)
26095
26096 _this._options = options || {};
26097 _this._listener = _this._onEvent.bind(assertThisInitialized(_this));
26098
26099 _this.setData(data);
26100
26101 return _this;
26102 } // TODO: implement a function .config() to dynamically update things like configured filter
26103 // and trigger changes accordingly
26104
26105 /**
26106 * Set a data source for the view.
26107 *
26108 * @param data - The instance containing data (directly or indirectly).
26109 */
26110
26111
26112 createClass(DataView, [{
26113 key: "setData",
26114 value: function setData(data) {
26115 if (this._data) {
26116 // unsubscribe from current dataset
26117 if (this._data.off) {
26118 this._data.off("*", this._listener);
26119 } // trigger a remove of all items in memory
26120
26121
26122 var ids = this._data.getIds({
26123 filter: this._options.filter
26124 });
26125
26126 var items = this._data.get(ids);
26127
26128 this._ids.clear();
26129
26130 this.length = 0;
26131
26132 this._trigger("remove", {
26133 items: ids,
26134 oldData: items
26135 });
26136 }
26137
26138 if (data != null) {
26139 this._data = data; // trigger an add of all added items
26140
26141 var _ids = this._data.getIds({
26142 filter: this._options.filter
26143 });
26144
26145 for (var i = 0, len = _ids.length; i < len; i++) {
26146 var id = _ids[i];
26147
26148 this._ids.add(id);
26149 }
26150
26151 this.length = _ids.length;
26152
26153 this._trigger("add", {
26154 items: _ids
26155 });
26156 } else {
26157 this._data = new DataSet();
26158 } // subscribe to new dataset
26159
26160
26161 if (this._data.on) {
26162 this._data.on("*", this._listener);
26163 }
26164 }
26165 /**
26166 * Refresh the DataView.
26167 * Useful when the DataView has a filter function containing a variable parameter.
26168 */
26169
26170 }, {
26171 key: "refresh",
26172 value: function refresh() {
26173 var ids = this._data.getIds({
26174 filter: this._options.filter
26175 });
26176
26177 var oldIds = toConsumableArray(this._ids);
26178 var newIds = {};
26179 var addedIds = [];
26180 var removedIds = [];
26181 var removedItems = []; // check for additions
26182
26183 for (var i = 0, len = ids.length; i < len; i++) {
26184 var id = ids[i];
26185 newIds[id] = true;
26186
26187 if (!this._ids.has(id)) {
26188 addedIds.push(id);
26189
26190 this._ids.add(id);
26191 }
26192 } // check for removals
26193
26194
26195 for (var _i = 0, _len = oldIds.length; _i < _len; _i++) {
26196 var _id = oldIds[_i];
26197
26198 var item = this._data.get(_id);
26199
26200 if (item == null) {
26201 // @TODO: Investigate.
26202 // Doesn't happen during tests or examples.
26203 // Is it really impossible or could it eventually happen?
26204 // How to handle it if it does? The types guarantee non-nullable items.
26205 console.error("If you see this, report it please.");
26206 } else if (!newIds[_id]) {
26207 removedIds.push(_id);
26208 removedItems.push(item);
26209
26210 this._ids.delete(_id);
26211 }
26212 }
26213
26214 this.length += addedIds.length - removedIds.length; // trigger events
26215
26216 if (addedIds.length) {
26217 this._trigger("add", {
26218 items: addedIds
26219 });
26220 }
26221
26222 if (removedIds.length) {
26223 this._trigger("remove", {
26224 items: removedIds,
26225 oldData: removedItems
26226 });
26227 }
26228 }
26229 /** @inheritdoc */
26230
26231 }, {
26232 key: "get",
26233 value: function get(first, second) {
26234 if (this._data == null) {
26235 return null;
26236 } // parse the arguments
26237
26238
26239 var ids = null;
26240 var options;
26241
26242 if (isId(first) || Array.isArray(first)) {
26243 ids = first;
26244 options = second;
26245 } else {
26246 options = first;
26247 } // extend the options with the default options and provided options
26248
26249
26250 var viewOptions = Object.assign({}, this._options, options); // create a combined filter method when needed
26251
26252 var thisFilter = this._options.filter;
26253 var optionsFilter = options && options.filter;
26254
26255 if (thisFilter && optionsFilter) {
26256 viewOptions.filter = function (item) {
26257 return thisFilter(item) && optionsFilter(item);
26258 };
26259 }
26260
26261 if (ids == null) {
26262 return this._data.get(viewOptions);
26263 } else {
26264 return this._data.get(ids, viewOptions);
26265 }
26266 }
26267 /** @inheritdoc */
26268
26269 }, {
26270 key: "getIds",
26271 value: function getIds(options) {
26272 if (this._data.length) {
26273 var defaultFilter = this._options.filter;
26274 var optionsFilter = options != null ? options.filter : null;
26275 var filter;
26276
26277 if (optionsFilter) {
26278 if (defaultFilter) {
26279 filter = function filter(item) {
26280 return defaultFilter(item) && optionsFilter(item);
26281 };
26282 } else {
26283 filter = optionsFilter;
26284 }
26285 } else {
26286 filter = defaultFilter;
26287 }
26288
26289 return this._data.getIds({
26290 filter: filter,
26291 order: options && options.order
26292 });
26293 } else {
26294 return [];
26295 }
26296 }
26297 /** @inheritdoc */
26298
26299 }, {
26300 key: "forEach",
26301 value: function forEach(callback, options) {
26302 if (this._data) {
26303 var defaultFilter = this._options.filter;
26304 var optionsFilter = options && options.filter;
26305 var filter;
26306
26307 if (optionsFilter) {
26308 if (defaultFilter) {
26309 filter = function filter(item) {
26310 return defaultFilter(item) && optionsFilter(item);
26311 };
26312 } else {
26313 filter = optionsFilter;
26314 }
26315 } else {
26316 filter = defaultFilter;
26317 }
26318
26319 this._data.forEach(callback, {
26320 filter: filter,
26321 order: options && options.order
26322 });
26323 }
26324 }
26325 /** @inheritdoc */
26326
26327 }, {
26328 key: "map",
26329 value: function map(callback, options) {
26330 if (this._data) {
26331 var defaultFilter = this._options.filter;
26332 var optionsFilter = options && options.filter;
26333 var filter;
26334
26335 if (optionsFilter) {
26336 if (defaultFilter) {
26337 filter = function filter(item) {
26338 return defaultFilter(item) && optionsFilter(item);
26339 };
26340 } else {
26341 filter = optionsFilter;
26342 }
26343 } else {
26344 filter = defaultFilter;
26345 }
26346
26347 return this._data.map(callback, {
26348 filter: filter,
26349 order: options && options.order
26350 });
26351 } else {
26352 return [];
26353 }
26354 }
26355 /** @inheritdoc */
26356
26357 }, {
26358 key: "getDataSet",
26359 value: function getDataSet() {
26360 return this._data.getDataSet();
26361 }
26362 /** @inheritdoc */
26363
26364 }, {
26365 key: "stream",
26366 value: function stream(ids) {
26367 return this._data.stream(ids || defineProperty$6({}, Symbol.iterator, this._ids.keys.bind(this._ids)));
26368 }
26369 /**
26370 * Event listener. Will propagate all events from the connected data set to the subscribers of the DataView, but will filter the items and only trigger when there are changes in the filtered data set.
26371 *
26372 * @param event - The name of the event.
26373 * @param params - Parameters of the event.
26374 * @param senderId - Id supplied by the sender.
26375 */
26376
26377 }, {
26378 key: "_onEvent",
26379 value: function _onEvent(event, params, senderId) {
26380 if (!params || !params.items || !this._data) {
26381 return;
26382 }
26383
26384 var ids = params.items;
26385 var addedIds = [];
26386 var updatedIds = [];
26387 var removedIds = [];
26388 var oldItems = [];
26389 var updatedItems = [];
26390 var removedItems = [];
26391
26392 switch (event) {
26393 case "add":
26394 // filter the ids of the added items
26395 for (var i = 0, len = ids.length; i < len; i++) {
26396 var id = ids[i];
26397 var item = this.get(id);
26398
26399 if (item) {
26400 this._ids.add(id);
26401
26402 addedIds.push(id);
26403 }
26404 }
26405
26406 break;
26407
26408 case "update":
26409 // determine the event from the views viewpoint: an updated
26410 // item can be added, updated, or removed from this view.
26411 for (var _i2 = 0, _len2 = ids.length; _i2 < _len2; _i2++) {
26412 var _id2 = ids[_i2];
26413
26414 var _item = this.get(_id2);
26415
26416 if (_item) {
26417 if (this._ids.has(_id2)) {
26418 updatedIds.push(_id2);
26419 updatedItems.push(params.data[_i2]);
26420 oldItems.push(params.oldData[_i2]);
26421 } else {
26422 this._ids.add(_id2);
26423
26424 addedIds.push(_id2);
26425 }
26426 } else {
26427 if (this._ids.has(_id2)) {
26428 this._ids.delete(_id2);
26429
26430 removedIds.push(_id2);
26431 removedItems.push(params.oldData[_i2]);
26432 }
26433 }
26434 }
26435
26436 break;
26437
26438 case "remove":
26439 // filter the ids of the removed items
26440 for (var _i3 = 0, _len3 = ids.length; _i3 < _len3; _i3++) {
26441 var _id3 = ids[_i3];
26442
26443 if (this._ids.has(_id3)) {
26444 this._ids.delete(_id3);
26445
26446 removedIds.push(_id3);
26447 removedItems.push(params.oldData[_i3]);
26448 }
26449 }
26450
26451 break;
26452 }
26453
26454 this.length += addedIds.length - removedIds.length;
26455
26456 if (addedIds.length) {
26457 this._trigger("add", {
26458 items: addedIds
26459 }, senderId);
26460 }
26461
26462 if (updatedIds.length) {
26463 this._trigger("update", {
26464 items: updatedIds,
26465 oldData: oldItems,
26466 data: updatedItems
26467 }, senderId);
26468 }
26469
26470 if (removedIds.length) {
26471 this._trigger("remove", {
26472 items: removedIds,
26473 oldData: removedItems
26474 }, senderId);
26475 }
26476 }
26477 }]);
26478 return DataView;
26479}(DataSetPart);
26480
26481var index$1 = {
26482 DataSet: DataSet,
26483 DataView: DataView$2,
26484 Queue: Queue
26485};
26486
26487var esm$1 = /*#__PURE__*/Object.freeze({
26488 __proto__: null,
26489 'default': index$1,
26490 DataSet: DataSet,
26491 DataStream: DataStream,
26492 DataView: DataView$2,
26493 Queue: Queue
26494});
26495
26496var trim$2 = stringTrim.trim;
26497var nativeParseFloat = global_1.parseFloat;
26498var FORCED = 1 / nativeParseFloat(whitespaces + '-0') !== -Infinity; // `parseFloat` method
26499// https://tc39.github.io/ecma262/#sec-parsefloat-string
26500
26501var _parseFloat = FORCED ? function parseFloat(string) {
26502 var trimmedString = trim$2(String(string));
26503 var result = nativeParseFloat(trimmedString);
26504 return result === 0 && trimmedString.charAt(0) == '-' ? -0 : result;
26505} : nativeParseFloat;
26506
26507// https://tc39.github.io/ecma262/#sec-parsefloat-string
26508
26509_export({
26510 global: true,
26511 forced: parseFloat != _parseFloat
26512}, {
26513 parseFloat: _parseFloat
26514});
26515
26516var trim$3 = stringTrim.trim;
26517var nativeParseInt = global_1.parseInt;
26518var hex = /^[+-]?0[Xx]/;
26519var FORCED$1 = nativeParseInt(whitespaces + '08') !== 8 || nativeParseInt(whitespaces + '0x16') !== 22; // `parseInt` method
26520// https://tc39.github.io/ecma262/#sec-parseint-string-radix
26521
26522var _parseInt = FORCED$1 ? function parseInt(string, radix) {
26523 var S = trim$3(String(string));
26524 return nativeParseInt(S, radix >>> 0 || (hex.test(S) ? 16 : 10));
26525} : nativeParseInt;
26526
26527// https://tc39.github.io/ecma262/#sec-parseint-string-radix
26528
26529_export({
26530 global: true,
26531 forced: parseInt != _parseInt
26532}, {
26533 parseInt: _parseInt
26534});
26535
26536var max$3 = Math.max;
26537var min$5 = Math.min;
26538var floor$3 = Math.floor;
26539var SUBSTITUTION_SYMBOLS$1 = /\$([$&'`]|\d\d?|<[^>]*>)/g;
26540var SUBSTITUTION_SYMBOLS_NO_NAMED$1 = /\$([$&'`]|\d\d?)/g;
26541
26542var maybeToString$1 = function (it) {
26543 return it === undefined ? it : String(it);
26544}; // @@replace logic
26545
26546
26547fixRegexpWellKnownSymbolLogic('replace', 2, function (REPLACE, nativeReplace, maybeCallNative) {
26548 return [// `String.prototype.replace` method
26549 // https://tc39.github.io/ecma262/#sec-string.prototype.replace
26550 function replace(searchValue, replaceValue) {
26551 var O = requireObjectCoercible(this);
26552 var replacer = searchValue == undefined ? undefined : searchValue[REPLACE];
26553 return replacer !== undefined ? replacer.call(searchValue, O, replaceValue) : nativeReplace.call(String(O), searchValue, replaceValue);
26554 }, // `RegExp.prototype[@@replace]` method
26555 // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@replace
26556 function (regexp, replaceValue) {
26557 var res = maybeCallNative(nativeReplace, regexp, this, replaceValue);
26558 if (res.done) return res.value;
26559 var rx = anObject(regexp);
26560 var S = String(this);
26561 var functionalReplace = typeof replaceValue === 'function';
26562 if (!functionalReplace) replaceValue = String(replaceValue);
26563 var global = rx.global;
26564
26565 if (global) {
26566 var fullUnicode = rx.unicode;
26567 rx.lastIndex = 0;
26568 }
26569
26570 var results = [];
26571
26572 while (true) {
26573 var result = regexpExecAbstract(rx, S);
26574 if (result === null) break;
26575 results.push(result);
26576 if (!global) break;
26577 var matchStr = String(result[0]);
26578 if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode);
26579 }
26580
26581 var accumulatedResult = '';
26582 var nextSourcePosition = 0;
26583
26584 for (var i = 0; i < results.length; i++) {
26585 result = results[i];
26586 var matched = String(result[0]);
26587 var position = max$3(min$5(toInteger(result.index), S.length), 0);
26588 var captures = []; // NOTE: This is equivalent to
26589 // captures = result.slice(1).map(maybeToString)
26590 // but for some reason `nativeSlice.call(result, 1, result.length)` (called in
26591 // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and
26592 // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it.
26593
26594 for (var j = 1; j < result.length; j++) captures.push(maybeToString$1(result[j]));
26595
26596 var namedCaptures = result.groups;
26597
26598 if (functionalReplace) {
26599 var replacerArgs = [matched].concat(captures, position, S);
26600 if (namedCaptures !== undefined) replacerArgs.push(namedCaptures);
26601 var replacement = String(replaceValue.apply(undefined, replacerArgs));
26602 } else {
26603 replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue);
26604 }
26605
26606 if (position >= nextSourcePosition) {
26607 accumulatedResult += S.slice(nextSourcePosition, position) + replacement;
26608 nextSourcePosition = position + matched.length;
26609 }
26610 }
26611
26612 return accumulatedResult + S.slice(nextSourcePosition);
26613 }]; // https://tc39.github.io/ecma262/#sec-getsubstitution
26614
26615 function getSubstitution(matched, str, position, captures, namedCaptures, replacement) {
26616 var tailPos = position + matched.length;
26617 var m = captures.length;
26618 var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED$1;
26619
26620 if (namedCaptures !== undefined) {
26621 namedCaptures = toObject(namedCaptures);
26622 symbols = SUBSTITUTION_SYMBOLS$1;
26623 }
26624
26625 return nativeReplace.call(replacement, symbols, function (match, ch) {
26626 var capture;
26627
26628 switch (ch.charAt(0)) {
26629 case '$':
26630 return '$';
26631
26632 case '&':
26633 return matched;
26634
26635 case '`':
26636 return str.slice(0, position);
26637
26638 case "'":
26639 return str.slice(tailPos);
26640
26641 case '<':
26642 capture = namedCaptures[ch.slice(1, -1)];
26643 break;
26644
26645 default:
26646 // \d\d?
26647 var n = +ch;
26648 if (n === 0) return match;
26649
26650 if (n > m) {
26651 var f = floor$3(n / 10);
26652 if (f === 0) return match;
26653 if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1);
26654 return match;
26655 }
26656
26657 capture = captures[n - 1];
26658 }
26659
26660 return capture === undefined ? '' : capture;
26661 });
26662 }
26663});
26664
26665var nativeJoin = [].join;
26666var ES3_STRINGS = indexedObject != Object;
26667var SLOPPY_METHOD$1 = sloppyArrayMethod('join', ','); // `Array.prototype.join` method
26668// https://tc39.github.io/ecma262/#sec-array.prototype.join
26669
26670_export({
26671 target: 'Array',
26672 proto: true,
26673 forced: ES3_STRINGS || SLOPPY_METHOD$1
26674}, {
26675 join: function join(separator) {
26676 return nativeJoin.call(toIndexedObject(this), separator === undefined ? ',' : separator);
26677 }
26678});
26679
26680/**
26681 * Helper functions for components
26682 * @class
26683 */
26684
26685var ComponentUtil =
26686/*#__PURE__*/
26687function () {
26688 function ComponentUtil() {
26689 _classCallCheck(this, ComponentUtil);
26690 }
26691
26692 _createClass(ComponentUtil, null, [{
26693 key: "choosify",
26694
26695 /**
26696 * Determine values to use for (sub)options of 'chosen'.
26697 *
26698 * This option is either a boolean or an object whose values should be examined further.
26699 * The relevant structures are:
26700 *
26701 * - chosen: <boolean value>
26702 * - chosen: { subOption: <boolean or function> }
26703 *
26704 * Where subOption is 'node', 'edge' or 'label'.
26705 *
26706 * The intention of this method appears to be to set a specific priority to the options;
26707 * Since most properties are either bridged or merged into the local options objects, there
26708 * is not much point in handling them separately.
26709 * TODO: examine if 'most' in previous sentence can be replaced with 'all'. In that case, we
26710 * should be able to get rid of this method.
26711 *
26712 * @param {string} subOption option within object 'chosen' to consider; either 'node', 'edge' or 'label'
26713 * @param {Object} pile array of options objects to consider
26714 *
26715 * @return {boolean|function} value for passed subOption of 'chosen' to use
26716 */
26717 value: function choosify(subOption, pile) {
26718 // allowed values for subOption
26719 var allowed = ['node', 'edge', 'label'];
26720 var value = true;
26721 var chosen = topMost(pile, 'chosen');
26722
26723 if (typeof chosen === 'boolean') {
26724 value = chosen;
26725 } else if (_typeof$1(chosen) === 'object') {
26726 if (allowed.indexOf(subOption) === -1) {
26727 throw new Error('choosify: subOption \'' + subOption + '\' should be one of ' + "'" + allowed.join("', '") + "'");
26728 }
26729
26730 var chosenEdge = topMost(pile, ['chosen', subOption]);
26731
26732 if (typeof chosenEdge === 'boolean' || typeof chosenEdge === 'function') {
26733 value = chosenEdge;
26734 }
26735 }
26736
26737 return value;
26738 }
26739 /**
26740 * Check if the point falls within the given rectangle.
26741 *
26742 * @param {rect} rect
26743 * @param {point} point
26744 * @param {rotationPoint} [rotationPoint] if specified, the rotation that applies to the rectangle.
26745 * @returns {boolean} true if point within rectangle, false otherwise
26746 * @static
26747 */
26748
26749 }, {
26750 key: "pointInRect",
26751 value: function pointInRect(rect, point, rotationPoint) {
26752 if (rect.width <= 0 || rect.height <= 0) {
26753 return false; // early out
26754 }
26755
26756 if (rotationPoint !== undefined) {
26757 // Rotate the point the same amount as the rectangle
26758 var tmp = {
26759 x: point.x - rotationPoint.x,
26760 y: point.y - rotationPoint.y
26761 };
26762
26763 if (rotationPoint.angle !== 0) {
26764 // In order to get the coordinates the same, you need to
26765 // rotate in the reverse direction
26766 var angle = -rotationPoint.angle;
26767 var tmp2 = {
26768 x: Math.cos(angle) * tmp.x - Math.sin(angle) * tmp.y,
26769 y: Math.sin(angle) * tmp.x + Math.cos(angle) * tmp.y
26770 };
26771 point = tmp2;
26772 } else {
26773 point = tmp;
26774 } // Note that if a rotation is specified, the rectangle coordinates
26775 // are **not* the full canvas coordinates. They are relative to the
26776 // rotationPoint. Hence, the point coordinates need not be translated
26777 // back in this case.
26778
26779 }
26780
26781 var right = rect.x + rect.width;
26782 var bottom = rect.y + rect.width;
26783 return rect.left < point.x && right > point.x && rect.top < point.y && bottom > point.y;
26784 }
26785 /**
26786 * Check if given value is acceptable as a label text.
26787 *
26788 * @param {*} text value to check; can be anything at this point
26789 * @returns {boolean} true if valid label value, false otherwise
26790 */
26791
26792 }, {
26793 key: "isValidLabel",
26794 value: function isValidLabel(text) {
26795 // Note that this is quite strict: types that *might* be converted to string are disallowed
26796 return typeof text === 'string' && text !== '';
26797 }
26798 }]);
26799
26800 return ComponentUtil;
26801}();
26802
26803var SPECIES$5 = wellKnownSymbol('species');
26804var nativeSlice = [].slice;
26805var max$4 = Math.max; // `Array.prototype.slice` method
26806// https://tc39.github.io/ecma262/#sec-array.prototype.slice
26807// fallback for not array-like ES3 strings and DOM objects
26808
26809_export({
26810 target: 'Array',
26811 proto: true,
26812 forced: !arrayMethodHasSpeciesSupport('slice')
26813}, {
26814 slice: function slice(start, end) {
26815 var O = toIndexedObject(this);
26816 var length = toLength(O.length);
26817 var k = toAbsoluteIndex(start, length);
26818 var fin = toAbsoluteIndex(end === undefined ? length : end, length); // inline `ArraySpeciesCreate` for usage native `Array#slice` where it's possible
26819
26820 var Constructor, result, n;
26821
26822 if (isArray(O)) {
26823 Constructor = O.constructor; // cross-realm fallback
26824
26825 if (typeof Constructor == 'function' && (Constructor === Array || isArray(Constructor.prototype))) {
26826 Constructor = undefined;
26827 } else if (isObject(Constructor)) {
26828 Constructor = Constructor[SPECIES$5];
26829 if (Constructor === null) Constructor = undefined;
26830 }
26831
26832 if (Constructor === Array || Constructor === undefined) {
26833 return nativeSlice.call(O, k, fin);
26834 }
26835 }
26836
26837 result = new (Constructor === undefined ? Array : Constructor)(max$4(fin - k, 0));
26838
26839 for (n = 0; k < fin; k++, n++) if (k in O) createProperty(result, n, O[k]);
26840
26841 result.length = n;
26842 return result;
26843 }
26844});
26845
26846var SPECIES$6 = wellKnownSymbol('species');
26847
26848var setSpecies = function (CONSTRUCTOR_NAME) {
26849 var Constructor = getBuiltIn(CONSTRUCTOR_NAME);
26850 var defineProperty = objectDefineProperty.f;
26851
26852 if (descriptors && Constructor && !Constructor[SPECIES$6]) {
26853 defineProperty(Constructor, SPECIES$6, {
26854 configurable: true,
26855 get: function () {
26856 return this;
26857 }
26858 });
26859 }
26860};
26861
26862var defineProperty$7 = objectDefineProperty.f;
26863var getOwnPropertyNames$2 = objectGetOwnPropertyNames.f;
26864var MATCH$3 = wellKnownSymbol('match');
26865var NativeRegExp = global_1.RegExp;
26866var RegExpPrototype = NativeRegExp.prototype;
26867var re1 = /a/g;
26868var re2 = /a/g; // "new" should create a new object, old webkit bug
26869
26870var CORRECT_NEW = new NativeRegExp(re1) !== re1;
26871var FORCED$2 = descriptors && isForced_1('RegExp', !CORRECT_NEW || fails(function () {
26872 re2[MATCH$3] = false; // RegExp constructor can alter flags and IsRegExp works correct with @@match
26873
26874 return NativeRegExp(re1) != re1 || NativeRegExp(re2) == re2 || NativeRegExp(re1, 'i') != '/a/i';
26875})); // `RegExp` constructor
26876// https://tc39.github.io/ecma262/#sec-regexp-constructor
26877
26878if (FORCED$2) {
26879 var RegExpWrapper = function RegExp(pattern, flags) {
26880 var thisIsRegExp = this instanceof RegExpWrapper;
26881 var patternIsRegExp = isRegexp(pattern);
26882 var flagsAreUndefined = flags === undefined;
26883 return !thisIsRegExp && patternIsRegExp && pattern.constructor === RegExpWrapper && flagsAreUndefined ? pattern : inheritIfRequired(CORRECT_NEW ? new NativeRegExp(patternIsRegExp && !flagsAreUndefined ? pattern.source : pattern, flags) : NativeRegExp((patternIsRegExp = pattern instanceof RegExpWrapper) ? pattern.source : pattern, patternIsRegExp && flagsAreUndefined ? regexpFlags.call(pattern) : flags), thisIsRegExp ? this : RegExpPrototype, RegExpWrapper);
26884 };
26885
26886 var proxy = function (key) {
26887 key in RegExpWrapper || defineProperty$7(RegExpWrapper, key, {
26888 configurable: true,
26889 get: function () {
26890 return NativeRegExp[key];
26891 },
26892 set: function (it) {
26893 NativeRegExp[key] = it;
26894 }
26895 });
26896 };
26897
26898 var keys$4 = getOwnPropertyNames$2(NativeRegExp);
26899 var index$2 = 0;
26900
26901 while (keys$4.length > index$2) proxy(keys$4[index$2++]);
26902
26903 RegExpPrototype.constructor = RegExpWrapper;
26904 RegExpWrapper.prototype = RegExpPrototype;
26905 redefine(global_1, 'RegExp', RegExpWrapper);
26906} // https://tc39.github.io/ecma262/#sec-get-regexp-@@species
26907
26908
26909setSpecies('RegExp');
26910
26911var TO_STRING$1 = 'toString';
26912var RegExpPrototype$1 = RegExp.prototype;
26913var nativeToString = RegExpPrototype$1[TO_STRING$1];
26914var NOT_GENERIC = fails(function () {
26915 return nativeToString.call({
26916 source: 'a',
26917 flags: 'b'
26918 }) != '/a/b';
26919}); // FF44- RegExp#toString has a wrong name
26920
26921var INCORRECT_NAME = nativeToString.name != TO_STRING$1; // `RegExp.prototype.toString` method
26922// https://tc39.github.io/ecma262/#sec-regexp.prototype.tostring
26923
26924if (NOT_GENERIC || INCORRECT_NAME) {
26925 redefine(RegExp.prototype, TO_STRING$1, function toString() {
26926 var R = anObject(this);
26927 var p = String(R.source);
26928 var rf = R.flags;
26929 var f = String(rf === undefined && R instanceof RegExp && !('flags' in RegExpPrototype$1) ? regexpFlags.call(R) : rf);
26930 return '/' + p + '/' + f;
26931 }, {
26932 unsafe: true
26933 });
26934}
26935
26936fixRegexpWellKnownSymbolLogic('match', 1, function (MATCH, nativeMatch, maybeCallNative) {
26937 return [// `String.prototype.match` method
26938 // https://tc39.github.io/ecma262/#sec-string.prototype.match
26939 function match(regexp) {
26940 var O = requireObjectCoercible(this);
26941 var matcher = regexp == undefined ? undefined : regexp[MATCH];
26942 return matcher !== undefined ? matcher.call(regexp, O) : new RegExp(regexp)[MATCH](String(O));
26943 }, // `RegExp.prototype[@@match]` method
26944 // https://tc39.github.io/ecma262/#sec-regexp.prototype-@@match
26945 function (regexp) {
26946 var res = maybeCallNative(nativeMatch, regexp, this);
26947 if (res.done) return res.value;
26948 var rx = anObject(regexp);
26949 var S = String(this);
26950 if (!rx.global) return regexpExecAbstract(rx, S);
26951 var fullUnicode = rx.unicode;
26952 rx.lastIndex = 0;
26953 var A = [];
26954 var n = 0;
26955 var result;
26956
26957 while ((result = regexpExecAbstract(rx, S)) !== null) {
26958 var matchStr = String(result[0]);
26959 A[n] = matchStr;
26960 if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode);
26961 n++;
26962 }
26963
26964 return n === 0 ? null : A;
26965 }];
26966});
26967
26968// https://tc39.github.io/ecma262/#sec-string.prototype.bold
26969
26970
26971_export({
26972 target: 'String',
26973 proto: true,
26974 forced: forcedStringHtmlMethod('bold')
26975}, {
26976 bold: function bold() {
26977 return createHtml(this, 'b', '', '');
26978 }
26979});
26980
26981var iterators = {};
26982
26983var ITERATOR$2 = wellKnownSymbol('iterator');
26984var BUGGY_SAFARI_ITERATORS = false;
26985
26986var returnThis$1 = function () {
26987 return this;
26988}; // `%IteratorPrototype%` object
26989// https://tc39.github.io/ecma262/#sec-%iteratorprototype%-object
26990
26991
26992var IteratorPrototype$1, PrototypeOfArrayIteratorPrototype, arrayIterator;
26993
26994if ([].keys) {
26995 arrayIterator = [].keys(); // Safari 8 has buggy iterators w/o `next`
26996
26997 if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS = true;else {
26998 PrototypeOfArrayIteratorPrototype = objectGetPrototypeOf(objectGetPrototypeOf(arrayIterator));
26999 if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype$1 = PrototypeOfArrayIteratorPrototype;
27000 }
27001}
27002
27003if (IteratorPrototype$1 == undefined) IteratorPrototype$1 = {}; // 25.1.2.1.1 %IteratorPrototype%[@@iterator]()
27004
27005if ( !has(IteratorPrototype$1, ITERATOR$2)) {
27006 createNonEnumerableProperty(IteratorPrototype$1, ITERATOR$2, returnThis$1);
27007}
27008
27009var iteratorsCore = {
27010 IteratorPrototype: IteratorPrototype$1,
27011 BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS
27012};
27013
27014var IteratorPrototype$2 = iteratorsCore.IteratorPrototype;
27015
27016var returnThis$2 = function () {
27017 return this;
27018};
27019
27020var createIteratorConstructor = function (IteratorConstructor, NAME, next) {
27021 var TO_STRING_TAG = NAME + ' Iterator';
27022 IteratorConstructor.prototype = objectCreate(IteratorPrototype$2, {
27023 next: createPropertyDescriptor(1, next)
27024 });
27025 setToStringTag(IteratorConstructor, TO_STRING_TAG, false);
27026 iterators[TO_STRING_TAG] = returnThis$2;
27027 return IteratorConstructor;
27028};
27029
27030var IteratorPrototype$3 = iteratorsCore.IteratorPrototype;
27031var BUGGY_SAFARI_ITERATORS$1 = iteratorsCore.BUGGY_SAFARI_ITERATORS;
27032var ITERATOR$3 = wellKnownSymbol('iterator');
27033var KEYS$1 = 'keys';
27034var VALUES$1 = 'values';
27035var ENTRIES = 'entries';
27036
27037var returnThis$3 = function () {
27038 return this;
27039};
27040
27041var defineIterator = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {
27042 createIteratorConstructor(IteratorConstructor, NAME, next);
27043
27044 var getIterationMethod = function (KIND) {
27045 if (KIND === DEFAULT && defaultIterator) return defaultIterator;
27046 if (!BUGGY_SAFARI_ITERATORS$1 && KIND in IterablePrototype) return IterablePrototype[KIND];
27047
27048 switch (KIND) {
27049 case KEYS$1:
27050 return function keys() {
27051 return new IteratorConstructor(this, KIND);
27052 };
27053
27054 case VALUES$1:
27055 return function values() {
27056 return new IteratorConstructor(this, KIND);
27057 };
27058
27059 case ENTRIES:
27060 return function entries() {
27061 return new IteratorConstructor(this, KIND);
27062 };
27063 }
27064
27065 return function () {
27066 return new IteratorConstructor(this);
27067 };
27068 };
27069
27070 var TO_STRING_TAG = NAME + ' Iterator';
27071 var INCORRECT_VALUES_NAME = false;
27072 var IterablePrototype = Iterable.prototype;
27073 var nativeIterator = IterablePrototype[ITERATOR$3] || IterablePrototype['@@iterator'] || DEFAULT && IterablePrototype[DEFAULT];
27074 var defaultIterator = !BUGGY_SAFARI_ITERATORS$1 && nativeIterator || getIterationMethod(DEFAULT);
27075 var anyNativeIterator = NAME == 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
27076 var CurrentIteratorPrototype, methods, KEY; // fix native
27077
27078 if (anyNativeIterator) {
27079 CurrentIteratorPrototype = objectGetPrototypeOf(anyNativeIterator.call(new Iterable()));
27080
27081 if (IteratorPrototype$3 !== Object.prototype && CurrentIteratorPrototype.next) {
27082 if ( objectGetPrototypeOf(CurrentIteratorPrototype) !== IteratorPrototype$3) {
27083 if (objectSetPrototypeOf) {
27084 objectSetPrototypeOf(CurrentIteratorPrototype, IteratorPrototype$3);
27085 } else if (typeof CurrentIteratorPrototype[ITERATOR$3] != 'function') {
27086 createNonEnumerableProperty(CurrentIteratorPrototype, ITERATOR$3, returnThis$3);
27087 }
27088 } // Set @@toStringTag to native iterators
27089
27090
27091 setToStringTag(CurrentIteratorPrototype, TO_STRING_TAG, true);
27092 }
27093 } // fix Array#{values, @@iterator}.name in V8 / FF
27094
27095
27096 if (DEFAULT == VALUES$1 && nativeIterator && nativeIterator.name !== VALUES$1) {
27097 INCORRECT_VALUES_NAME = true;
27098
27099 defaultIterator = function values() {
27100 return nativeIterator.call(this);
27101 };
27102 } // define iterator
27103
27104
27105 if ( IterablePrototype[ITERATOR$3] !== defaultIterator) {
27106 createNonEnumerableProperty(IterablePrototype, ITERATOR$3, defaultIterator);
27107 }
27108
27109 iterators[NAME] = defaultIterator; // export additional methods
27110
27111 if (DEFAULT) {
27112 methods = {
27113 values: getIterationMethod(VALUES$1),
27114 keys: IS_SET ? defaultIterator : getIterationMethod(KEYS$1),
27115 entries: getIterationMethod(ENTRIES)
27116 };
27117 if (FORCED) for (KEY in methods) {
27118 if (BUGGY_SAFARI_ITERATORS$1 || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
27119 redefine(IterablePrototype, KEY, methods[KEY]);
27120 }
27121 } else _export({
27122 target: NAME,
27123 proto: true,
27124 forced: BUGGY_SAFARI_ITERATORS$1 || INCORRECT_VALUES_NAME
27125 }, methods);
27126 }
27127
27128 return methods;
27129};
27130
27131var ARRAY_ITERATOR = 'Array Iterator';
27132var setInternalState$1 = internalState.set;
27133var getInternalState$1 = internalState.getterFor(ARRAY_ITERATOR); // `Array.prototype.entries` method
27134// https://tc39.github.io/ecma262/#sec-array.prototype.entries
27135// `Array.prototype.keys` method
27136// https://tc39.github.io/ecma262/#sec-array.prototype.keys
27137// `Array.prototype.values` method
27138// https://tc39.github.io/ecma262/#sec-array.prototype.values
27139// `Array.prototype[@@iterator]` method
27140// https://tc39.github.io/ecma262/#sec-array.prototype-@@iterator
27141// `CreateArrayIterator` internal method
27142// https://tc39.github.io/ecma262/#sec-createarrayiterator
27143
27144var es_array_iterator = defineIterator(Array, 'Array', function (iterated, kind) {
27145 setInternalState$1(this, {
27146 type: ARRAY_ITERATOR,
27147 target: toIndexedObject(iterated),
27148 // target
27149 index: 0,
27150 // next index
27151 kind: kind // kind
27152
27153 }); // `%ArrayIteratorPrototype%.next` method
27154 // https://tc39.github.io/ecma262/#sec-%arrayiteratorprototype%.next
27155}, function () {
27156 var state = getInternalState$1(this);
27157 var target = state.target;
27158 var kind = state.kind;
27159 var index = state.index++;
27160
27161 if (!target || index >= target.length) {
27162 state.target = undefined;
27163 return {
27164 value: undefined,
27165 done: true
27166 };
27167 }
27168
27169 if (kind == 'keys') return {
27170 value: index,
27171 done: false
27172 };
27173 if (kind == 'values') return {
27174 value: target[index],
27175 done: false
27176 };
27177 return {
27178 value: [index, target[index]],
27179 done: false
27180 };
27181}, 'values'); // argumentsList[@@iterator] is %ArrayProto_values%
27182// https://tc39.github.io/ecma262/#sec-createunmappedargumentsobject
27183// https://tc39.github.io/ecma262/#sec-createmappedargumentsobject
27184
27185iterators.Arguments = iterators.Array; // https://tc39.github.io/ecma262/#sec-array.prototype-@@unscopables
27186
27187addToUnscopables('keys');
27188addToUnscopables('values');
27189addToUnscopables('entries');
27190
27191var nativeAssign = Object.assign; // `Object.assign` method
27192// https://tc39.github.io/ecma262/#sec-object.assign
27193// should work with symbols and should have deterministic property order (V8 bug)
27194
27195var objectAssign = !nativeAssign || fails(function () {
27196 var A = {};
27197 var B = {}; // eslint-disable-next-line no-undef
27198
27199 var symbol = Symbol();
27200 var alphabet = 'abcdefghijklmnopqrst';
27201 A[symbol] = 7;
27202 alphabet.split('').forEach(function (chr) {
27203 B[chr] = chr;
27204 });
27205 return nativeAssign({}, A)[symbol] != 7 || objectKeys(nativeAssign({}, B)).join('') != alphabet;
27206}) ? function assign(target, source) {
27207 // eslint-disable-line no-unused-vars
27208 var T = toObject(target);
27209 var argumentsLength = arguments.length;
27210 var index = 1;
27211 var getOwnPropertySymbols = objectGetOwnPropertySymbols.f;
27212 var propertyIsEnumerable = objectPropertyIsEnumerable.f;
27213
27214 while (argumentsLength > index) {
27215 var S = indexedObject(arguments[index++]);
27216 var keys = getOwnPropertySymbols ? objectKeys(S).concat(getOwnPropertySymbols(S)) : objectKeys(S);
27217 var length = keys.length;
27218 var j = 0;
27219 var key;
27220
27221 while (length > j) {
27222 key = keys[j++];
27223 if (!descriptors || propertyIsEnumerable.call(S, key)) T[key] = S[key];
27224 }
27225 }
27226
27227 return T;
27228} : nativeAssign;
27229
27230// https://tc39.github.io/ecma262/#sec-object.assign
27231
27232_export({
27233 target: 'Object',
27234 stat: true,
27235 forced: Object.assign !== objectAssign
27236}, {
27237 assign: objectAssign
27238});
27239
27240var ITERATOR$4 = wellKnownSymbol('iterator');
27241var TO_STRING_TAG$5 = wellKnownSymbol('toStringTag');
27242var ArrayValues$1 = es_array_iterator.values;
27243
27244for (var COLLECTION_NAME$1 in domIterables) {
27245 var Collection$2 = global_1[COLLECTION_NAME$1];
27246 var CollectionPrototype$1 = Collection$2 && Collection$2.prototype;
27247
27248 if (CollectionPrototype$1) {
27249 // some Chrome versions have non-configurable methods on DOMTokenList
27250 if (CollectionPrototype$1[ITERATOR$4] !== ArrayValues$1) try {
27251 createNonEnumerableProperty(CollectionPrototype$1, ITERATOR$4, ArrayValues$1);
27252 } catch (error) {
27253 CollectionPrototype$1[ITERATOR$4] = ArrayValues$1;
27254 }
27255
27256 if (!CollectionPrototype$1[TO_STRING_TAG$5]) {
27257 createNonEnumerableProperty(CollectionPrototype$1, TO_STRING_TAG$5, COLLECTION_NAME$1);
27258 }
27259
27260 if (domIterables[COLLECTION_NAME$1]) for (var METHOD_NAME in es_array_iterator) {
27261 // some Chrome versions have non-configurable methods on DOMTokenList
27262 if (CollectionPrototype$1[METHOD_NAME] !== es_array_iterator[METHOD_NAME]) try {
27263 createNonEnumerableProperty(CollectionPrototype$1, METHOD_NAME, es_array_iterator[METHOD_NAME]);
27264 } catch (error) {
27265 CollectionPrototype$1[METHOD_NAME] = es_array_iterator[METHOD_NAME];
27266 }
27267 }
27268 }
27269}
27270
27271/**
27272 * Callback to determine text dimensions, using the parent label settings.
27273 * @callback MeasureText
27274 * @param {text} text
27275 * @param {text} mod
27276 * @return {Object} { width, values} width in pixels and font attributes
27277 */
27278
27279/**
27280 * Helper class for Label which collects results of splitting labels into lines and blocks.
27281 *
27282 * @private
27283 */
27284var LabelAccumulator =
27285/*#__PURE__*/
27286function () {
27287 /**
27288 * @param {MeasureText} measureText
27289 */
27290 function LabelAccumulator(measureText) {
27291 _classCallCheck(this, LabelAccumulator);
27292
27293 this.measureText = measureText;
27294 this.current = 0;
27295 this.width = 0;
27296 this.height = 0;
27297 this.lines = [];
27298 }
27299 /**
27300 * Append given text to the given line.
27301 *
27302 * @param {number} l index of line to add to
27303 * @param {string} text string to append to line
27304 * @param {'bold'|'ital'|'boldital'|'mono'|'normal'} [mod='normal']
27305 * @private
27306 */
27307
27308
27309 _createClass(LabelAccumulator, [{
27310 key: "_add",
27311 value: function _add(l, text) {
27312 var mod = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'normal';
27313
27314 if (this.lines[l] === undefined) {
27315 this.lines[l] = {
27316 width: 0,
27317 height: 0,
27318 blocks: []
27319 };
27320 } // We still need to set a block for undefined and empty texts, hence return at this point
27321 // This is necessary because we don't know at this point if we're at the
27322 // start of an empty line or not.
27323 // To compensate, empty blocks are removed in `finalize()`.
27324 //
27325 // Empty strings should still have a height
27326
27327
27328 var tmpText = text;
27329 if (text === undefined || text === "") tmpText = " "; // Determine width and get the font properties
27330
27331 var result = this.measureText(tmpText, mod);
27332 var block = Object.assign({}, result.values);
27333 block.text = text;
27334 block.width = result.width;
27335 block.mod = mod;
27336
27337 if (text === undefined || text === "") {
27338 block.width = 0;
27339 }
27340
27341 this.lines[l].blocks.push(block); // Update the line width. We need this for determining if a string goes over max width
27342
27343 this.lines[l].width += block.width;
27344 }
27345 /**
27346 * Returns the width in pixels of the current line.
27347 *
27348 * @returns {number}
27349 */
27350
27351 }, {
27352 key: "curWidth",
27353 value: function curWidth() {
27354 var line = this.lines[this.current];
27355 if (line === undefined) return 0;
27356 return line.width;
27357 }
27358 /**
27359 * Add text in block to current line
27360 *
27361 * @param {string} text
27362 * @param {'bold'|'ital'|'boldital'|'mono'|'normal'} [mod='normal']
27363 */
27364
27365 }, {
27366 key: "append",
27367 value: function append(text) {
27368 var mod = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'normal';
27369
27370 this._add(this.current, text, mod);
27371 }
27372 /**
27373 * Add text in block to current line and start a new line
27374 *
27375 * @param {string} text
27376 * @param {'bold'|'ital'|'boldital'|'mono'|'normal'} [mod='normal']
27377 */
27378
27379 }, {
27380 key: "newLine",
27381 value: function newLine(text) {
27382 var mod = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'normal';
27383
27384 this._add(this.current, text, mod);
27385
27386 this.current++;
27387 }
27388 /**
27389 * Determine and set the heights of all the lines currently contained in this instance
27390 *
27391 * Note that width has already been set.
27392 *
27393 * @private
27394 */
27395
27396 }, {
27397 key: "determineLineHeights",
27398 value: function determineLineHeights() {
27399 for (var k = 0; k < this.lines.length; k++) {
27400 var line = this.lines[k]; // Looking for max height of blocks in line
27401
27402 var height = 0;
27403
27404 if (line.blocks !== undefined) {
27405 // Can happen if text contains e.g. '\n '
27406 for (var l = 0; l < line.blocks.length; l++) {
27407 var block = line.blocks[l];
27408
27409 if (height < block.height) {
27410 height = block.height;
27411 }
27412 }
27413 }
27414
27415 line.height = height;
27416 }
27417 }
27418 /**
27419 * Determine the full size of the label text, as determined by current lines and blocks
27420 *
27421 * @private
27422 */
27423
27424 }, {
27425 key: "determineLabelSize",
27426 value: function determineLabelSize() {
27427 var width = 0;
27428 var height = 0;
27429
27430 for (var k = 0; k < this.lines.length; k++) {
27431 var line = this.lines[k];
27432
27433 if (line.width > width) {
27434 width = line.width;
27435 }
27436
27437 height += line.height;
27438 }
27439
27440 this.width = width;
27441 this.height = height;
27442 }
27443 /**
27444 * Remove all empty blocks and empty lines we don't need
27445 *
27446 * This must be done after the width/height determination,
27447 * so that these are set properly for processing here.
27448 *
27449 * @returns {Array<Line>} Lines with empty blocks (and some empty lines) removed
27450 * @private
27451 */
27452
27453 }, {
27454 key: "removeEmptyBlocks",
27455 value: function removeEmptyBlocks() {
27456 var tmpLines = [];
27457
27458 for (var k = 0; k < this.lines.length; k++) {
27459 var line = this.lines[k]; // Note: an empty line in between text has width zero but is still relevant to layout.
27460 // So we can't use width for testing empty line here
27461
27462 if (line.blocks.length === 0) continue; // Discard final empty line always
27463
27464 if (k === this.lines.length - 1) {
27465 if (line.width === 0) continue;
27466 }
27467
27468 var tmpLine = {};
27469 Object.assign(tmpLine, line);
27470 tmpLine.blocks = [];
27471 var firstEmptyBlock = void 0;
27472 var tmpBlocks = [];
27473
27474 for (var l = 0; l < line.blocks.length; l++) {
27475 var block = line.blocks[l];
27476
27477 if (block.width !== 0) {
27478 tmpBlocks.push(block);
27479 } else {
27480 if (firstEmptyBlock === undefined) {
27481 firstEmptyBlock = block;
27482 }
27483 }
27484 } // Ensure that there is *some* text present
27485
27486
27487 if (tmpBlocks.length === 0 && firstEmptyBlock !== undefined) {
27488 tmpBlocks.push(firstEmptyBlock);
27489 }
27490
27491 tmpLine.blocks = tmpBlocks;
27492 tmpLines.push(tmpLine);
27493 }
27494
27495 return tmpLines;
27496 }
27497 /**
27498 * Set the sizes for all lines and the whole thing.
27499 *
27500 * @returns {{width: (number|*), height: (number|*), lines: Array}}
27501 */
27502
27503 }, {
27504 key: "finalize",
27505 value: function finalize() {
27506 //console.log(JSON.stringify(this.lines, null, 2));
27507 this.determineLineHeights();
27508 this.determineLabelSize();
27509 var tmpLines = this.removeEmptyBlocks(); // Return a simple hash object for further processing.
27510
27511 return {
27512 width: this.width,
27513 height: this.height,
27514 lines: tmpLines
27515 };
27516 }
27517 }]);
27518
27519 return LabelAccumulator;
27520}();
27521
27522var tagPattern = {
27523 // HTML
27524 '<b>': /<b>/,
27525 '<i>': /<i>/,
27526 '<code>': /<code>/,
27527 '</b>': /<\/b>/,
27528 '</i>': /<\/i>/,
27529 '</code>': /<\/code>/,
27530 // Markdown
27531 '*': /\*/,
27532 // bold
27533 '_': /\_/,
27534 // ital
27535 '`': /`/,
27536 // mono
27537 'afterBold': /[^\*]/,
27538 'afterItal': /[^_]/,
27539 'afterMono': /[^`]/
27540};
27541/**
27542 * Internal helper class for parsing the markup tags for HTML and Markdown.
27543 *
27544 * NOTE: Sequences of tabs and spaces are reduced to single space.
27545 * Scan usage of `this.spacing` within method
27546 */
27547
27548var MarkupAccumulator =
27549/*#__PURE__*/
27550function () {
27551 /**
27552 * Create an instance
27553 *
27554 * @param {string} text text to parse for markup
27555 */
27556 function MarkupAccumulator(text) {
27557 _classCallCheck(this, MarkupAccumulator);
27558
27559 this.text = text;
27560 this.bold = false;
27561 this.ital = false;
27562 this.mono = false;
27563 this.spacing = false;
27564 this.position = 0;
27565 this.buffer = "";
27566 this.modStack = [];
27567 this.blocks = [];
27568 }
27569 /**
27570 * Return the mod label currently on the top of the stack
27571 *
27572 * @returns {string} label of topmost mod
27573 * @private
27574 */
27575
27576
27577 _createClass(MarkupAccumulator, [{
27578 key: "mod",
27579 value: function mod() {
27580 return this.modStack.length === 0 ? 'normal' : this.modStack[0];
27581 }
27582 /**
27583 * Return the mod label currently active
27584 *
27585 * @returns {string} label of active mod
27586 * @private
27587 */
27588
27589 }, {
27590 key: "modName",
27591 value: function modName() {
27592 if (this.modStack.length === 0) return 'normal';else if (this.modStack[0] === 'mono') return 'mono';else {
27593 if (this.bold && this.ital) {
27594 return 'boldital';
27595 } else if (this.bold) {
27596 return 'bold';
27597 } else if (this.ital) {
27598 return 'ital';
27599 }
27600 }
27601 }
27602 /**
27603 * @private
27604 */
27605
27606 }, {
27607 key: "emitBlock",
27608 value: function emitBlock() {
27609 if (this.spacing) {
27610 this.add(" ");
27611 this.spacing = false;
27612 }
27613
27614 if (this.buffer.length > 0) {
27615 this.blocks.push({
27616 text: this.buffer,
27617 mod: this.modName()
27618 });
27619 this.buffer = "";
27620 }
27621 }
27622 /**
27623 * Output text to buffer
27624 *
27625 * @param {string} text text to add
27626 * @private
27627 */
27628
27629 }, {
27630 key: "add",
27631 value: function add(text) {
27632 if (text === " ") {
27633 this.spacing = true;
27634 }
27635
27636 if (this.spacing) {
27637 this.buffer += " ";
27638 this.spacing = false;
27639 }
27640
27641 if (text != " ") {
27642 this.buffer += text;
27643 }
27644 }
27645 /**
27646 * Handle parsing of whitespace
27647 *
27648 * @param {string} ch the character to check
27649 * @returns {boolean} true if the character was processed as whitespace, false otherwise
27650 */
27651
27652 }, {
27653 key: "parseWS",
27654 value: function parseWS(ch) {
27655 if (/[ \t]/.test(ch)) {
27656 if (!this.mono) {
27657 this.spacing = true;
27658 } else {
27659 this.add(ch);
27660 }
27661
27662 return true;
27663 }
27664
27665 return false;
27666 }
27667 /**
27668 * @param {string} tagName label for block type to set
27669 * @private
27670 */
27671
27672 }, {
27673 key: "setTag",
27674 value: function setTag(tagName) {
27675 this.emitBlock();
27676 this[tagName] = true;
27677 this.modStack.unshift(tagName);
27678 }
27679 /**
27680 * @param {string} tagName label for block type to unset
27681 * @private
27682 */
27683
27684 }, {
27685 key: "unsetTag",
27686 value: function unsetTag(tagName) {
27687 this.emitBlock();
27688 this[tagName] = false;
27689 this.modStack.shift();
27690 }
27691 /**
27692 * @param {string} tagName label for block type we are currently processing
27693 * @param {string|RegExp} tag string to match in text
27694 * @returns {boolean} true if the tag was processed, false otherwise
27695 */
27696
27697 }, {
27698 key: "parseStartTag",
27699 value: function parseStartTag(tagName, tag) {
27700 // Note: if 'mono' passed as tagName, there is a double check here. This is OK
27701 if (!this.mono && !this[tagName] && this.match(tag)) {
27702 this.setTag(tagName);
27703 return true;
27704 }
27705
27706 return false;
27707 }
27708 /**
27709 * @param {string|RegExp} tag
27710 * @param {number} [advance=true] if set, advance current position in text
27711 * @returns {boolean} true if match at given position, false otherwise
27712 * @private
27713 */
27714
27715 }, {
27716 key: "match",
27717 value: function match(tag) {
27718 var advance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
27719
27720 var _this$prepareRegExp = this.prepareRegExp(tag),
27721 _this$prepareRegExp2 = _slicedToArray(_this$prepareRegExp, 2),
27722 regExp = _this$prepareRegExp2[0],
27723 length = _this$prepareRegExp2[1];
27724
27725 var matched = regExp.test(this.text.substr(this.position, length));
27726
27727 if (matched && advance) {
27728 this.position += length - 1;
27729 }
27730
27731 return matched;
27732 }
27733 /**
27734 * @param {string} tagName label for block type we are currently processing
27735 * @param {string|RegExp} tag string to match in text
27736 * @param {RegExp} [nextTag] regular expression to match for characters *following* the current tag
27737 * @returns {boolean} true if the tag was processed, false otherwise
27738 */
27739
27740 }, {
27741 key: "parseEndTag",
27742 value: function parseEndTag(tagName, tag, nextTag) {
27743 var checkTag = this.mod() === tagName;
27744
27745 if (tagName === 'mono') {
27746 // special handling for 'mono'
27747 checkTag = checkTag && this.mono;
27748 } else {
27749 checkTag = checkTag && !this.mono;
27750 }
27751
27752 if (checkTag && this.match(tag)) {
27753 if (nextTag !== undefined) {
27754 // Purpose of the following match is to prevent a direct unset/set of a given tag
27755 // E.g. '*bold **still bold*' => '*bold still bold*'
27756 if (this.position === this.text.length - 1 || this.match(nextTag, false)) {
27757 this.unsetTag(tagName);
27758 }
27759 } else {
27760 this.unsetTag(tagName);
27761 }
27762
27763 return true;
27764 }
27765
27766 return false;
27767 }
27768 /**
27769 * @param {string|RegExp} tag string to match in text
27770 * @param {value} value string to replace tag with, if found at current position
27771 * @returns {boolean} true if the tag was processed, false otherwise
27772 */
27773
27774 }, {
27775 key: "replace",
27776 value: function replace(tag, value) {
27777 if (this.match(tag)) {
27778 this.add(value);
27779 this.position += length - 1;
27780 return true;
27781 }
27782
27783 return false;
27784 }
27785 /**
27786 * Create a regular expression for the tag if it isn't already one.
27787 *
27788 * The return value is an array `[RegExp, number]`, with exactly two value, where:
27789 * - RegExp is the regular expression to use
27790 * - number is the lenth of the input string to match
27791 *
27792 * @param {string|RegExp} tag string to match in text
27793 * @returns {Array} regular expression to use and length of input string to match
27794 * @private
27795 */
27796
27797 }, {
27798 key: "prepareRegExp",
27799 value: function prepareRegExp(tag) {
27800 var length;
27801 var regExp;
27802
27803 if (tag instanceof RegExp) {
27804 regExp = tag;
27805 length = 1; // ASSUMPTION: regexp only tests one character
27806 } else {
27807 // use prepared regexp if present
27808 var prepared = tagPattern[tag];
27809
27810 if (prepared !== undefined) {
27811 regExp = prepared;
27812 } else {
27813 regExp = new RegExp(tag);
27814 }
27815
27816 length = tag.length;
27817 }
27818
27819 return [regExp, length];
27820 }
27821 }]);
27822
27823 return MarkupAccumulator;
27824}();
27825/**
27826 * Helper class for Label which explodes the label text into lines and blocks within lines
27827 *
27828 * @private
27829 */
27830
27831
27832var LabelSplitter =
27833/*#__PURE__*/
27834function () {
27835 /**
27836 * @param {CanvasRenderingContext2D} ctx Canvas rendering context
27837 * @param {Label} parent reference to the Label instance using current instance
27838 * @param {boolean} selected
27839 * @param {boolean} hover
27840 */
27841 function LabelSplitter(ctx, parent, selected, hover) {
27842 var _this = this;
27843
27844 _classCallCheck(this, LabelSplitter);
27845
27846 this.ctx = ctx;
27847 this.parent = parent;
27848 this.selected = selected;
27849 this.hover = hover;
27850 /**
27851 * Callback to determine text width; passed to LabelAccumulator instance
27852 *
27853 * @param {String} text string to determine width of
27854 * @param {String} mod font type to use for this text
27855 * @return {Object} { width, values} width in pixels and font attributes
27856 */
27857
27858 var textWidth = function textWidth(text, mod) {
27859 if (text === undefined) return 0; // TODO: This can be done more efficiently with caching
27860 // This will set the ctx.font correctly, depending on selected/hover and mod - so that ctx.measureText() will be accurate.
27861
27862 var values = _this.parent.getFormattingValues(ctx, selected, hover, mod);
27863
27864 var width = 0;
27865
27866 if (text !== '') {
27867 var measure = _this.ctx.measureText(text);
27868
27869 width = measure.width;
27870 }
27871
27872 return {
27873 width: width,
27874 values: values
27875 };
27876 };
27877
27878 this.lines = new LabelAccumulator(textWidth);
27879 }
27880 /**
27881 * Split passed text of a label into lines and blocks.
27882 *
27883 * # NOTE
27884 *
27885 * The handling of spacing is option dependent:
27886 *
27887 * - if `font.multi : false`, all spaces are retained
27888 * - if `font.multi : true`, every sequence of spaces is compressed to a single space
27889 *
27890 * This might not be the best way to do it, but this is as it has been working till now.
27891 * In order not to break existing functionality, for the time being this behaviour will
27892 * be retained in any code changes.
27893 *
27894 * @param {string} text text to split
27895 * @returns {Array<line>}
27896 */
27897
27898
27899 _createClass(LabelSplitter, [{
27900 key: "process",
27901 value: function process(text) {
27902 if (!ComponentUtil.isValidLabel(text)) {
27903 return this.lines.finalize();
27904 }
27905
27906 var font = this.parent.fontOptions; // Normalize the end-of-line's to a single representation - order important
27907
27908 text = text.replace(/\r\n/g, '\n'); // Dos EOL's
27909
27910 text = text.replace(/\r/g, '\n'); // Mac EOL's
27911 // Note that at this point, there can be no \r's in the text.
27912 // This is used later on splitStringIntoLines() to split multifont texts.
27913
27914 var nlLines = String(text).split('\n');
27915 var lineCount = nlLines.length;
27916
27917 if (font.multi) {
27918 // Multi-font case: styling tags active
27919 for (var i = 0; i < lineCount; i++) {
27920 var blocks = this.splitBlocks(nlLines[i], font.multi); // Post: Sequences of tabs and spaces are reduced to single space
27921
27922 if (blocks === undefined) continue;
27923
27924 if (blocks.length === 0) {
27925 this.lines.newLine("");
27926 continue;
27927 }
27928
27929 if (font.maxWdt > 0) {
27930 // widthConstraint.maximum defined
27931 //console.log('Running widthConstraint multi, max: ' + this.fontOptions.maxWdt);
27932 for (var j = 0; j < blocks.length; j++) {
27933 var mod = blocks[j].mod;
27934 var _text = blocks[j].text;
27935 this.splitStringIntoLines(_text, mod, true);
27936 }
27937 } else {
27938 // widthConstraint.maximum NOT defined
27939 for (var _j = 0; _j < blocks.length; _j++) {
27940 var _mod = blocks[_j].mod;
27941 var _text2 = blocks[_j].text;
27942 this.lines.append(_text2, _mod);
27943 }
27944 }
27945
27946 this.lines.newLine();
27947 }
27948 } else {
27949 // Single-font case
27950 if (font.maxWdt > 0) {
27951 // widthConstraint.maximum defined
27952 // console.log('Running widthConstraint normal, max: ' + this.fontOptions.maxWdt);
27953 for (var _i = 0; _i < lineCount; _i++) {
27954 this.splitStringIntoLines(nlLines[_i]);
27955 }
27956 } else {
27957 // widthConstraint.maximum NOT defined
27958 for (var _i2 = 0; _i2 < lineCount; _i2++) {
27959 this.lines.newLine(nlLines[_i2]);
27960 }
27961 }
27962 }
27963
27964 return this.lines.finalize();
27965 }
27966 /**
27967 * normalize the markup system
27968 *
27969 * @param {boolean|'md'|'markdown'|'html'} markupSystem
27970 * @returns {string}
27971 */
27972
27973 }, {
27974 key: "decodeMarkupSystem",
27975 value: function decodeMarkupSystem(markupSystem) {
27976 var system = 'none';
27977
27978 if (markupSystem === 'markdown' || markupSystem === 'md') {
27979 system = 'markdown';
27980 } else if (markupSystem === true || markupSystem === 'html') {
27981 system = 'html';
27982 }
27983
27984 return system;
27985 }
27986 /**
27987 *
27988 * @param {string} text
27989 * @returns {Array}
27990 */
27991
27992 }, {
27993 key: "splitHtmlBlocks",
27994 value: function splitHtmlBlocks(text) {
27995 var s = new MarkupAccumulator(text);
27996
27997 var parseEntities = function parseEntities(ch) {
27998 if (/&/.test(ch)) {
27999 var parsed = s.replace(s.text, '&lt;', '<') || s.replace(s.text, '&amp;', '&');
28000
28001 if (!parsed) {
28002 s.add("&");
28003 }
28004
28005 return true;
28006 }
28007
28008 return false;
28009 };
28010
28011 while (s.position < s.text.length) {
28012 var ch = s.text.charAt(s.position);
28013 var parsed = s.parseWS(ch) || /</.test(ch) && (s.parseStartTag('bold', '<b>') || s.parseStartTag('ital', '<i>') || s.parseStartTag('mono', '<code>') || s.parseEndTag('bold', '</b>') || s.parseEndTag('ital', '</i>') || s.parseEndTag('mono', '</code>')) || parseEntities(ch);
28014
28015 if (!parsed) {
28016 s.add(ch);
28017 }
28018
28019 s.position++;
28020 }
28021
28022 s.emitBlock();
28023 return s.blocks;
28024 }
28025 /**
28026 *
28027 * @param {string} text
28028 * @returns {Array}
28029 */
28030
28031 }, {
28032 key: "splitMarkdownBlocks",
28033 value: function splitMarkdownBlocks(text) {
28034 var _this2 = this;
28035
28036 var s = new MarkupAccumulator(text);
28037 var beginable = true;
28038
28039 var parseOverride = function parseOverride(ch) {
28040 if (/\\/.test(ch)) {
28041 if (s.position < _this2.text.length + 1) {
28042 s.position++;
28043 ch = _this2.text.charAt(s.position);
28044
28045 if (/ \t/.test(ch)) {
28046 s.spacing = true;
28047 } else {
28048 s.add(ch);
28049 beginable = false;
28050 }
28051 }
28052
28053 return true;
28054 }
28055
28056 return false;
28057 };
28058
28059 while (s.position < s.text.length) {
28060 var ch = s.text.charAt(s.position);
28061 var parsed = s.parseWS(ch) || parseOverride(ch) || (beginable || s.spacing) && (s.parseStartTag('bold', '*') || s.parseStartTag('ital', '_') || s.parseStartTag('mono', '`')) || s.parseEndTag('bold', '*', 'afterBold') || s.parseEndTag('ital', '_', 'afterItal') || s.parseEndTag('mono', '`', 'afterMono');
28062
28063 if (!parsed) {
28064 s.add(ch);
28065 beginable = false;
28066 }
28067
28068 s.position++;
28069 }
28070
28071 s.emitBlock();
28072 return s.blocks;
28073 }
28074 /**
28075 * Explodes a piece of text into single-font blocks using a given markup
28076 *
28077 * @param {string} text
28078 * @param {boolean|'md'|'markdown'|'html'} markupSystem
28079 * @returns {Array.<{text: string, mod: string}>}
28080 * @private
28081 */
28082
28083 }, {
28084 key: "splitBlocks",
28085 value: function splitBlocks(text, markupSystem) {
28086 var system = this.decodeMarkupSystem(markupSystem);
28087
28088 if (system === 'none') {
28089 return [{
28090 text: text,
28091 mod: 'normal'
28092 }];
28093 } else if (system === 'markdown') {
28094 return this.splitMarkdownBlocks(text);
28095 } else if (system === 'html') {
28096 return this.splitHtmlBlocks(text);
28097 }
28098 }
28099 /**
28100 * @param {string} text
28101 * @returns {boolean} true if text length over the current max with
28102 * @private
28103 */
28104
28105 }, {
28106 key: "overMaxWidth",
28107 value: function overMaxWidth(text) {
28108 var width = this.ctx.measureText(text).width;
28109 return this.lines.curWidth() + width > this.parent.fontOptions.maxWdt;
28110 }
28111 /**
28112 * Determine the longest part of the sentence which still fits in the
28113 * current max width.
28114 *
28115 * @param {Array} words Array of strings signifying a text lines
28116 * @return {number} index of first item in string making string go over max
28117 * @private
28118 */
28119
28120 }, {
28121 key: "getLongestFit",
28122 value: function getLongestFit(words) {
28123 var text = '';
28124 var w = 0;
28125
28126 while (w < words.length) {
28127 var pre = text === '' ? '' : ' ';
28128 var newText = text + pre + words[w];
28129 if (this.overMaxWidth(newText)) break;
28130 text = newText;
28131 w++;
28132 }
28133
28134 return w;
28135 }
28136 /**
28137 * Determine the longest part of the string which still fits in the
28138 * current max width.
28139 *
28140 * @param {Array} words Array of strings signifying a text lines
28141 * @return {number} index of first item in string making string go over max
28142 */
28143
28144 }, {
28145 key: "getLongestFitWord",
28146 value: function getLongestFitWord(words) {
28147 var w = 0;
28148
28149 while (w < words.length) {
28150 if (this.overMaxWidth(words.slice(0, w))) break;
28151 w++;
28152 }
28153
28154 return w;
28155 }
28156 /**
28157 * Split the passed text into lines, according to width constraint (if any).
28158 *
28159 * The method assumes that the input string is a single line, i.e. without lines break.
28160 *
28161 * This method retains spaces, if still present (case `font.multi: false`).
28162 * A space which falls on an internal line break, will be replaced by a newline.
28163 * There is no special handling of tabs; these go along with the flow.
28164 *
28165 * @param {string} str
28166 * @param {string} [mod='normal']
28167 * @param {boolean} [appendLast=false]
28168 * @private
28169 */
28170
28171 }, {
28172 key: "splitStringIntoLines",
28173 value: function splitStringIntoLines(str) {
28174 var mod = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'normal';
28175 var appendLast = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
28176 // Set the canvas context font, based upon the current selected/hover state
28177 // and the provided mod, so the text measurement performed by getLongestFit
28178 // will be accurate - and not just use the font of whoever last used the canvas.
28179 this.parent.getFormattingValues(this.ctx, this.selected, this.hover, mod); // Still-present spaces are relevant, retain them
28180
28181 str = str.replace(/^( +)/g, '$1\r');
28182 str = str.replace(/([^\r][^ ]*)( +)/g, '$1\r$2\r');
28183 var words = str.split('\r');
28184
28185 while (words.length > 0) {
28186 var w = this.getLongestFit(words);
28187
28188 if (w === 0) {
28189 // Special case: the first word is already larger than the max width.
28190 var word = words[0]; // Break the word to the largest part that fits the line
28191
28192 var x = this.getLongestFitWord(word);
28193 this.lines.newLine(word.slice(0, x), mod); // Adjust the word, so that the rest will be done next iteration
28194
28195 words[0] = word.slice(x);
28196 } else {
28197 // skip any space that is replaced by a newline
28198 var newW = w;
28199
28200 if (words[w - 1] === ' ') {
28201 w--;
28202 } else if (words[newW] === ' ') {
28203 newW++;
28204 }
28205
28206 var text = words.slice(0, w).join("");
28207
28208 if (w == words.length && appendLast) {
28209 this.lines.append(text, mod);
28210 } else {
28211 this.lines.newLine(text, mod);
28212 } // Adjust the word, so that the rest will be done next iteration
28213
28214
28215 words = words.slice(newW);
28216 }
28217 }
28218 }
28219 }]);
28220
28221 return LabelSplitter;
28222}();
28223
28224/**
28225 * List of special styles for multi-fonts
28226 * @private
28227 */
28228
28229var multiFontStyle = ['bold', 'ital', 'boldital', 'mono'];
28230/**
28231 * A Label to be used for Nodes or Edges.
28232 */
28233
28234var Label =
28235/*#__PURE__*/
28236function () {
28237 /**
28238 * @param {Object} body
28239 * @param {Object} options
28240 * @param {boolean} [edgelabel=false]
28241 */
28242 function Label(body, options) {
28243 var edgelabel = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
28244
28245 _classCallCheck(this, Label);
28246
28247 this.body = body;
28248 this.pointToSelf = false;
28249 this.baseSize = undefined;
28250 this.fontOptions = {}; // instance variable containing the *instance-local* font options
28251
28252 this.setOptions(options);
28253 this.size = {
28254 top: 0,
28255 left: 0,
28256 width: 0,
28257 height: 0,
28258 yLine: 0
28259 };
28260 this.isEdgeLabel = edgelabel;
28261 }
28262 /**
28263 * @param {Object} options the options of the parent Node-instance
28264 */
28265
28266
28267 _createClass(Label, [{
28268 key: "setOptions",
28269 value: function setOptions(options) {
28270 this.elementOptions = options; // Reference to the options of the parent Node-instance
28271
28272 this.initFontOptions(options.font);
28273
28274 if (ComponentUtil.isValidLabel(options.label)) {
28275 this.labelDirty = true;
28276 } else {
28277 // Bad label! Change the option value to prevent bad stuff happening
28278 options.label = undefined;
28279 }
28280
28281 if (options.font !== undefined && options.font !== null) {
28282 // font options can be deleted at various levels
28283 if (typeof options.font === 'string') {
28284 this.baseSize = this.fontOptions.size;
28285 } else if (_typeof$1(options.font) === 'object') {
28286 var size = options.font.size;
28287
28288 if (size !== undefined) {
28289 this.baseSize = size;
28290 }
28291 }
28292 }
28293 }
28294 /**
28295 * Init the font Options structure.
28296 *
28297 * Member fontOptions serves as an accumulator for the current font options.
28298 * As such, it needs to be completely separated from the node options.
28299 *
28300 * @param {Object} newFontOptions the new font options to process
28301 * @private
28302 */
28303
28304 }, {
28305 key: "initFontOptions",
28306 value: function initFontOptions(newFontOptions) {
28307 var _this = this;
28308
28309 // Prepare the multi-font option objects.
28310 // These will be filled in propagateFonts(), if required
28311 forEach(multiFontStyle, function (style) {
28312 _this.fontOptions[style] = {};
28313 }); // Handle shorthand option, if present
28314
28315 if (Label.parseFontString(this.fontOptions, newFontOptions)) {
28316 this.fontOptions.vadjust = 0;
28317 return;
28318 } // Copy over the non-multifont options, if specified
28319
28320
28321 forEach(newFontOptions, function (prop, n) {
28322 if (prop !== undefined && prop !== null && _typeof$1(prop) !== 'object') {
28323 _this.fontOptions[n] = prop;
28324 }
28325 });
28326 }
28327 /**
28328 * If in-variable is a string, parse it as a font specifier.
28329 *
28330 * Note that following is not done here and have to be done after the call:
28331 * - Not all font options are set (vadjust, mod)
28332 *
28333 * @param {Object} outOptions out-parameter, object in which to store the parse results (if any)
28334 * @param {Object} inOptions font options to parse
28335 * @return {boolean} true if font parsed as string, false otherwise
28336 * @static
28337 */
28338
28339 }, {
28340 key: "constrain",
28341
28342 /**
28343 * Set the width and height constraints based on 'nearest' value
28344 *
28345 * @param {Array} pile array of option objects to consider
28346 * @returns {object} the actual constraint values to use
28347 * @private
28348 */
28349 value: function constrain(pile) {
28350 // NOTE: constrainWidth and constrainHeight never set!
28351 // NOTE: for edge labels, only 'maxWdt' set
28352 // Node labels can set all the fields
28353 var fontOptions = {
28354 constrainWidth: false,
28355 maxWdt: -1,
28356 minWdt: -1,
28357 constrainHeight: false,
28358 minHgt: -1,
28359 valign: 'middle'
28360 };
28361 var widthConstraint = topMost(pile, 'widthConstraint');
28362
28363 if (typeof widthConstraint === 'number') {
28364 fontOptions.maxWdt = Number(widthConstraint);
28365 fontOptions.minWdt = Number(widthConstraint);
28366 } else if (_typeof$1(widthConstraint) === 'object') {
28367 var widthConstraintMaximum = topMost(pile, ['widthConstraint', 'maximum']);
28368
28369 if (typeof widthConstraintMaximum === 'number') {
28370 fontOptions.maxWdt = Number(widthConstraintMaximum);
28371 }
28372
28373 var widthConstraintMinimum = topMost(pile, ['widthConstraint', 'minimum']);
28374
28375 if (typeof widthConstraintMinimum === 'number') {
28376 fontOptions.minWdt = Number(widthConstraintMinimum);
28377 }
28378 }
28379
28380 var heightConstraint = topMost(pile, 'heightConstraint');
28381
28382 if (typeof heightConstraint === 'number') {
28383 fontOptions.minHgt = Number(heightConstraint);
28384 } else if (_typeof$1(heightConstraint) === 'object') {
28385 var heightConstraintMinimum = topMost(pile, ['heightConstraint', 'minimum']);
28386
28387 if (typeof heightConstraintMinimum === 'number') {
28388 fontOptions.minHgt = Number(heightConstraintMinimum);
28389 }
28390
28391 var heightConstraintValign = topMost(pile, ['heightConstraint', 'valign']);
28392
28393 if (typeof heightConstraintValign === 'string') {
28394 if (heightConstraintValign === 'top' || heightConstraintValign === 'bottom') {
28395 fontOptions.valign = heightConstraintValign;
28396 }
28397 }
28398 }
28399
28400 return fontOptions;
28401 }
28402 /**
28403 * Set options and update internal state
28404 *
28405 * @param {Object} options options to set
28406 * @param {Array} pile array of option objects to consider for option 'chosen'
28407 */
28408
28409 }, {
28410 key: "update",
28411 value: function update(options, pile) {
28412 this.setOptions(options, true);
28413 this.propagateFonts(pile);
28414 deepExtend(this.fontOptions, this.constrain(pile));
28415 this.fontOptions.chooser = ComponentUtil.choosify('label', pile);
28416 }
28417 /**
28418 * When margins are set in an element, adjust sizes is called to remove them
28419 * from the width/height constraints. This must be done prior to label sizing.
28420 *
28421 * @param {{top: number, right: number, bottom: number, left: number}} margins
28422 */
28423
28424 }, {
28425 key: "adjustSizes",
28426 value: function adjustSizes(margins) {
28427 var widthBias = margins ? margins.right + margins.left : 0;
28428
28429 if (this.fontOptions.constrainWidth) {
28430 this.fontOptions.maxWdt -= widthBias;
28431 this.fontOptions.minWdt -= widthBias;
28432 }
28433
28434 var heightBias = margins ? margins.top + margins.bottom : 0;
28435
28436 if (this.fontOptions.constrainHeight) {
28437 this.fontOptions.minHgt -= heightBias;
28438 }
28439 } /////////////////////////////////////////////////////////
28440 // Methods for handling options piles
28441 // Eventually, these will be moved to a separate class
28442 /////////////////////////////////////////////////////////
28443
28444 /**
28445 * Add the font members of the passed list of option objects to the pile.
28446 *
28447 * @param {Pile} dstPile pile of option objects add to
28448 * @param {Pile} srcPile pile of option objects to take font options from
28449 * @private
28450 */
28451
28452 }, {
28453 key: "addFontOptionsToPile",
28454 value: function addFontOptionsToPile(dstPile, srcPile) {
28455 for (var i = 0; i < srcPile.length; ++i) {
28456 this.addFontToPile(dstPile, srcPile[i]);
28457 }
28458 }
28459 /**
28460 * Add given font option object to the list of objects (the 'pile') to consider for determining
28461 * multi-font option values.
28462 *
28463 * @param {Pile} pile pile of option objects to use
28464 * @param {object} options instance to add to pile
28465 * @private
28466 */
28467
28468 }, {
28469 key: "addFontToPile",
28470 value: function addFontToPile(pile, options) {
28471 if (options === undefined) return;
28472 if (options.font === undefined || options.font === null) return;
28473 var item = options.font;
28474 pile.push(item);
28475 }
28476 /**
28477 * Collect all own-property values from the font pile that aren't multi-font option objectss.
28478 *
28479 * @param {Pile} pile pile of option objects to use
28480 * @returns {object} object with all current own basic font properties
28481 * @private
28482 */
28483
28484 }, {
28485 key: "getBasicOptions",
28486 value: function getBasicOptions(pile) {
28487 var ret = {}; // Scans the whole pile to get all options present
28488
28489 for (var n = 0; n < pile.length; ++n) {
28490 var fontOptions = pile[n]; // Convert shorthand if necessary
28491
28492 var tmpShorthand = {};
28493
28494 if (Label.parseFontString(tmpShorthand, fontOptions)) {
28495 fontOptions = tmpShorthand;
28496 }
28497
28498 forEach(fontOptions, function (opt, name) {
28499 if (opt === undefined) return; // multi-font option need not be present
28500
28501 if (ret.hasOwnProperty(name)) return; // Keep first value we encounter
28502
28503 if (multiFontStyle.indexOf(name) !== -1) {
28504 // Skip multi-font properties but we do need the structure
28505 ret[name] = {};
28506 } else {
28507 ret[name] = opt;
28508 }
28509 });
28510 }
28511
28512 return ret;
28513 }
28514 /**
28515 * Return the value for given option for the given multi-font.
28516 *
28517 * All available option objects are trawled in the set order to construct the option values.
28518 *
28519 * ---------------------------------------------------------------------
28520 * ## Traversal of pile for multi-fonts
28521 *
28522 * The determination of multi-font option values is a special case, because any values not
28523 * present in the multi-font options should by definition be taken from the main font options,
28524 * i.e. from the current 'parent' object of the multi-font option.
28525 *
28526 * ### Search order for multi-fonts
28527 *
28528 * 'bold' used as example:
28529 *
28530 * - search in option group 'bold' in local properties
28531 * - search in main font option group in local properties
28532 *
28533 * ---------------------------------------------------------------------
28534 *
28535 * @param {Pile} pile pile of option objects to use
28536 * @param {MultiFontStyle} multiName sub path for the multi-font
28537 * @param {string} option the option to search for, for the given multi-font
28538 * @returns {string|number} the value for the given option
28539 * @private
28540 */
28541
28542 }, {
28543 key: "getFontOption",
28544 value: function getFontOption(pile, multiName, option) {
28545 var multiFont; // Search multi font in local properties
28546
28547 for (var n = 0; n < pile.length; ++n) {
28548 var fontOptions = pile[n];
28549
28550 if (fontOptions.hasOwnProperty(multiName)) {
28551 multiFont = fontOptions[multiName];
28552 if (multiFont === undefined || multiFont === null) continue; // Convert shorthand if necessary
28553 // TODO: inefficient to do this conversion every time; find a better way.
28554
28555 var tmpShorthand = {};
28556
28557 if (Label.parseFontString(tmpShorthand, multiFont)) {
28558 multiFont = tmpShorthand;
28559 }
28560
28561 if (multiFont.hasOwnProperty(option)) {
28562 return multiFont[option];
28563 }
28564 }
28565 } // Option is not mentioned in the multi font options; take it from the parent font options.
28566 // These have already been converted with getBasicOptions(), so use the converted values.
28567
28568
28569 if (this.fontOptions.hasOwnProperty(option)) {
28570 return this.fontOptions[option];
28571 } // A value **must** be found; you should never get here.
28572
28573
28574 throw new Error("Did not find value for multi-font for property: '" + option + "'");
28575 }
28576 /**
28577 * Return all options values for the given multi-font.
28578 *
28579 * All available option objects are trawled in the set order to construct the option values.
28580 *
28581 * @param {Pile} pile pile of option objects to use
28582 * @param {MultiFontStyle} multiName sub path for the mod-font
28583 * @returns {MultiFontOptions}
28584 * @private
28585 */
28586
28587 }, {
28588 key: "getFontOptions",
28589 value: function getFontOptions(pile, multiName) {
28590 var result = {};
28591 var optionNames = ['color', 'size', 'face', 'mod', 'vadjust']; // List of allowed options per multi-font
28592
28593 for (var i = 0; i < optionNames.length; ++i) {
28594 var mod = optionNames[i];
28595 result[mod] = this.getFontOption(pile, multiName, mod);
28596 }
28597
28598 return result;
28599 } /////////////////////////////////////////////////////////
28600 // End methods for handling options piles
28601 /////////////////////////////////////////////////////////
28602
28603 /**
28604 * Collapse the font options for the multi-font to single objects, from
28605 * the chain of option objects passed (the 'pile').
28606 *
28607 * @param {Pile} pile sequence of option objects to consider.
28608 * First item in list assumed to be the newly set options.
28609 */
28610
28611 }, {
28612 key: "propagateFonts",
28613 value: function propagateFonts(pile) {
28614 var _this2 = this;
28615
28616 var fontPile = []; // sequence of font objects to consider, order important
28617 // Note that this.elementOptions is not used here.
28618
28619 this.addFontOptionsToPile(fontPile, pile);
28620 this.fontOptions = this.getBasicOptions(fontPile); // We set multifont values even if multi === false, for consistency (things break otherwise)
28621
28622 var _loop = function _loop(i) {
28623 var mod = multiFontStyle[i];
28624 var modOptions = _this2.fontOptions[mod];
28625
28626 var tmpMultiFontOptions = _this2.getFontOptions(fontPile, mod); // Copy over found values
28627
28628
28629 forEach(tmpMultiFontOptions, function (option, n) {
28630 modOptions[n] = option;
28631 });
28632 modOptions.size = Number(modOptions.size);
28633 modOptions.vadjust = Number(modOptions.vadjust);
28634 };
28635
28636 for (var i = 0; i < multiFontStyle.length; ++i) {
28637 _loop(i);
28638 }
28639 }
28640 /**
28641 * Main function. This is called from anything that wants to draw a label.
28642 * @param {CanvasRenderingContext2D} ctx
28643 * @param {number} x
28644 * @param {number} y
28645 * @param {boolean} selected
28646 * @param {boolean} hover
28647 * @param {string} [baseline='middle']
28648 */
28649
28650 }, {
28651 key: "draw",
28652 value: function draw(ctx, x, y, selected, hover) {
28653 var baseline = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 'middle';
28654 // if no label, return
28655 if (this.elementOptions.label === undefined) return; // check if we have to render the label
28656
28657 var viewFontSize = this.fontOptions.size * this.body.view.scale;
28658 if (this.elementOptions.label && viewFontSize < this.elementOptions.scaling.label.drawThreshold - 1) return; // This ensures that there will not be HUGE letters on screen
28659 // by setting an upper limit on the visible text size (regardless of zoomLevel)
28660
28661 if (viewFontSize >= this.elementOptions.scaling.label.maxVisible) {
28662 viewFontSize = Number(this.elementOptions.scaling.label.maxVisible) / this.body.view.scale;
28663 } // update the size cache if required
28664
28665
28666 this.calculateLabelSize(ctx, selected, hover, x, y, baseline);
28667
28668 this._drawBackground(ctx);
28669
28670 this._drawText(ctx, x, this.size.yLine, baseline, viewFontSize);
28671 }
28672 /**
28673 * Draws the label background
28674 * @param {CanvasRenderingContext2D} ctx
28675 * @private
28676 */
28677
28678 }, {
28679 key: "_drawBackground",
28680 value: function _drawBackground(ctx) {
28681 if (this.fontOptions.background !== undefined && this.fontOptions.background !== "none") {
28682 ctx.fillStyle = this.fontOptions.background;
28683 var size = this.getSize();
28684 ctx.fillRect(size.left, size.top, size.width, size.height);
28685 }
28686 }
28687 /**
28688 *
28689 * @param {CanvasRenderingContext2D} ctx
28690 * @param {number} x
28691 * @param {number} y
28692 * @param {string} [baseline='middle']
28693 * @param {number} viewFontSize
28694 * @private
28695 */
28696
28697 }, {
28698 key: "_drawText",
28699 value: function _drawText(ctx, x, y) {
28700 var baseline = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'middle';
28701 var viewFontSize = arguments.length > 4 ? arguments[4] : undefined;
28702
28703 var _this$_setAlignment = this._setAlignment(ctx, x, y, baseline);
28704
28705 var _this$_setAlignment2 = _slicedToArray(_this$_setAlignment, 2);
28706
28707 x = _this$_setAlignment2[0];
28708 y = _this$_setAlignment2[1];
28709 ctx.textAlign = 'left';
28710 x = x - this.size.width / 2; // Shift label 1/2-distance to the left
28711
28712 if (this.fontOptions.valign && this.size.height > this.size.labelHeight) {
28713 if (this.fontOptions.valign === 'top') {
28714 y -= (this.size.height - this.size.labelHeight) / 2;
28715 }
28716
28717 if (this.fontOptions.valign === 'bottom') {
28718 y += (this.size.height - this.size.labelHeight) / 2;
28719 }
28720 } // draw the text
28721
28722
28723 for (var i = 0; i < this.lineCount; i++) {
28724 var line = this.lines[i];
28725
28726 if (line && line.blocks) {
28727 var width = 0;
28728
28729 if (this.isEdgeLabel || this.fontOptions.align === 'center') {
28730 width += (this.size.width - line.width) / 2;
28731 } else if (this.fontOptions.align === 'right') {
28732 width += this.size.width - line.width;
28733 }
28734
28735 for (var j = 0; j < line.blocks.length; j++) {
28736 var block = line.blocks[j];
28737 ctx.font = block.font;
28738
28739 var _this$_getColor = this._getColor(block.color, viewFontSize, block.strokeColor),
28740 _this$_getColor2 = _slicedToArray(_this$_getColor, 2),
28741 fontColor = _this$_getColor2[0],
28742 strokeColor = _this$_getColor2[1];
28743
28744 if (block.strokeWidth > 0) {
28745 ctx.lineWidth = block.strokeWidth;
28746 ctx.strokeStyle = strokeColor;
28747 ctx.lineJoin = 'round';
28748 }
28749
28750 ctx.fillStyle = fontColor;
28751
28752 if (block.strokeWidth > 0) {
28753 ctx.strokeText(block.text, x + width, y + block.vadjust);
28754 }
28755
28756 ctx.fillText(block.text, x + width, y + block.vadjust);
28757 width += block.width;
28758 }
28759
28760 y += line.height;
28761 }
28762 }
28763 }
28764 /**
28765 *
28766 * @param {CanvasRenderingContext2D} ctx
28767 * @param {number} x
28768 * @param {number} y
28769 * @param {string} baseline
28770 * @returns {Array.<number>}
28771 * @private
28772 */
28773
28774 }, {
28775 key: "_setAlignment",
28776 value: function _setAlignment(ctx, x, y, baseline) {
28777 // check for label alignment (for edges)
28778 // TODO: make alignment for nodes
28779 if (this.isEdgeLabel && this.fontOptions.align !== 'horizontal' && this.pointToSelf === false) {
28780 x = 0;
28781 y = 0;
28782 var lineMargin = 2;
28783
28784 if (this.fontOptions.align === 'top') {
28785 ctx.textBaseline = 'alphabetic';
28786 y -= 2 * lineMargin; // distance from edge, required because we use alphabetic. Alphabetic has less difference between browsers
28787 } else if (this.fontOptions.align === 'bottom') {
28788 ctx.textBaseline = 'hanging';
28789 y += 2 * lineMargin; // distance from edge, required because we use hanging. Hanging has less difference between browsers
28790 } else {
28791 ctx.textBaseline = 'middle';
28792 }
28793 } else {
28794 ctx.textBaseline = baseline;
28795 }
28796
28797 return [x, y];
28798 }
28799 /**
28800 * fade in when relative scale is between threshold and threshold - 1.
28801 * If the relative scale would be smaller than threshold -1 the draw function would have returned before coming here.
28802 *
28803 * @param {string} color The font color to use
28804 * @param {number} viewFontSize
28805 * @param {string} initialStrokeColor
28806 * @returns {Array.<string>} An array containing the font color and stroke color
28807 * @private
28808 */
28809
28810 }, {
28811 key: "_getColor",
28812 value: function _getColor(color, viewFontSize, initialStrokeColor) {
28813 var fontColor = color || '#000000';
28814 var strokeColor = initialStrokeColor || '#ffffff';
28815
28816 if (viewFontSize <= this.elementOptions.scaling.label.drawThreshold) {
28817 var opacity = Math.max(0, Math.min(1, 1 - (this.elementOptions.scaling.label.drawThreshold - viewFontSize)));
28818 fontColor = overrideOpacity(fontColor, opacity);
28819 strokeColor = overrideOpacity(strokeColor, opacity);
28820 }
28821
28822 return [fontColor, strokeColor];
28823 }
28824 /**
28825 *
28826 * @param {CanvasRenderingContext2D} ctx
28827 * @param {boolean} selected
28828 * @param {boolean} hover
28829 * @returns {{width: number, height: number}}
28830 */
28831
28832 }, {
28833 key: "getTextSize",
28834 value: function getTextSize(ctx) {
28835 var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
28836 var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
28837
28838 this._processLabel(ctx, selected, hover);
28839
28840 return {
28841 width: this.size.width,
28842 height: this.size.height,
28843 lineCount: this.lineCount
28844 };
28845 }
28846 /**
28847 * Get the current dimensions of the label
28848 *
28849 * @return {rect}
28850 */
28851
28852 }, {
28853 key: "getSize",
28854 value: function getSize() {
28855 var lineMargin = 2;
28856 var x = this.size.left; // default values which might be overridden below
28857
28858 var y = this.size.top - 0.5 * lineMargin; // idem
28859
28860 if (this.isEdgeLabel) {
28861 var x2 = -this.size.width * 0.5;
28862
28863 switch (this.fontOptions.align) {
28864 case 'middle':
28865 x = x2;
28866 y = -this.size.height * 0.5;
28867 break;
28868
28869 case 'top':
28870 x = x2;
28871 y = -(this.size.height + lineMargin);
28872 break;
28873
28874 case 'bottom':
28875 x = x2;
28876 y = lineMargin;
28877 break;
28878 }
28879 }
28880
28881 var ret = {
28882 left: x,
28883 top: y,
28884 width: this.size.width,
28885 height: this.size.height
28886 };
28887 return ret;
28888 }
28889 /**
28890 *
28891 * @param {CanvasRenderingContext2D} ctx
28892 * @param {boolean} selected
28893 * @param {boolean} hover
28894 * @param {number} [x=0]
28895 * @param {number} [y=0]
28896 * @param {'middle'|'hanging'} [baseline='middle']
28897 */
28898
28899 }, {
28900 key: "calculateLabelSize",
28901 value: function calculateLabelSize(ctx, selected, hover) {
28902 var x = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
28903 var y = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
28904 var baseline = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 'middle';
28905
28906 this._processLabel(ctx, selected, hover);
28907
28908 this.size.left = x - this.size.width * 0.5;
28909 this.size.top = y - this.size.height * 0.5;
28910 this.size.yLine = y + (1 - this.lineCount) * 0.5 * this.fontOptions.size;
28911
28912 if (baseline === "hanging") {
28913 this.size.top += 0.5 * this.fontOptions.size;
28914 this.size.top += 4; // distance from node, required because we use hanging. Hanging has less difference between browsers
28915
28916 this.size.yLine += 4; // distance from node
28917 }
28918 }
28919 /**
28920 *
28921 * @param {CanvasRenderingContext2D} ctx
28922 * @param {boolean} selected
28923 * @param {boolean} hover
28924 * @param {string} mod
28925 * @returns {{color, size, face, mod, vadjust, strokeWidth: *, strokeColor: (*|string|allOptions.edges.font.strokeColor|{string}|allOptions.nodes.font.strokeColor|Array)}}
28926 */
28927
28928 }, {
28929 key: "getFormattingValues",
28930 value: function getFormattingValues(ctx, selected, hover, mod) {
28931 var getValue = function getValue(fontOptions, mod, option) {
28932 if (mod === "normal") {
28933 if (option === 'mod') return "";
28934 return fontOptions[option];
28935 }
28936
28937 if (fontOptions[mod][option] !== undefined) {
28938 // Grumbl leaving out test on undefined equals false for ""
28939 return fontOptions[mod][option];
28940 } else {
28941 // Take from parent font option
28942 return fontOptions[option];
28943 }
28944 };
28945
28946 var values = {
28947 color: getValue(this.fontOptions, mod, 'color'),
28948 size: getValue(this.fontOptions, mod, 'size'),
28949 face: getValue(this.fontOptions, mod, 'face'),
28950 mod: getValue(this.fontOptions, mod, 'mod'),
28951 vadjust: getValue(this.fontOptions, mod, 'vadjust'),
28952 strokeWidth: this.fontOptions.strokeWidth,
28953 strokeColor: this.fontOptions.strokeColor
28954 };
28955
28956 if (selected || hover) {
28957 if (mod === "normal" && this.fontOptions.chooser === true && this.elementOptions.labelHighlightBold) {
28958 values.mod = 'bold';
28959 } else {
28960 if (typeof this.fontOptions.chooser === 'function') {
28961 this.fontOptions.chooser(values, this.elementOptions.id, selected, hover);
28962 }
28963 }
28964 }
28965
28966 var fontString = "";
28967
28968 if (values.mod !== undefined && values.mod !== "") {
28969 // safeguard for undefined - this happened
28970 fontString += values.mod + " ";
28971 }
28972
28973 fontString += values.size + "px " + values.face;
28974 ctx.font = fontString.replace(/"/g, "");
28975 values.font = ctx.font;
28976 values.height = values.size;
28977 return values;
28978 }
28979 /**
28980 *
28981 * @param {boolean} selected
28982 * @param {boolean} hover
28983 * @returns {boolean}
28984 */
28985
28986 }, {
28987 key: "differentState",
28988 value: function differentState(selected, hover) {
28989 return selected !== this.selectedState || hover !== this.hoverState;
28990 }
28991 /**
28992 * This explodes the passed text into lines and determines the width, height and number of lines.
28993 *
28994 * @param {CanvasRenderingContext2D} ctx
28995 * @param {boolean} selected
28996 * @param {boolean} hover
28997 * @param {string} inText the text to explode
28998 * @returns {{width, height, lines}|*}
28999 * @private
29000 */
29001
29002 }, {
29003 key: "_processLabelText",
29004 value: function _processLabelText(ctx, selected, hover, inText) {
29005 var splitter = new LabelSplitter(ctx, this, selected, hover);
29006 return splitter.process(inText);
29007 }
29008 /**
29009 * This explodes the label string into lines and sets the width, height and number of lines.
29010 * @param {CanvasRenderingContext2D} ctx
29011 * @param {boolean} selected
29012 * @param {boolean} hover
29013 * @private
29014 */
29015
29016 }, {
29017 key: "_processLabel",
29018 value: function _processLabel(ctx, selected, hover) {
29019 if (this.labelDirty === false && !this.differentState(selected, hover)) return;
29020
29021 var state = this._processLabelText(ctx, selected, hover, this.elementOptions.label);
29022
29023 if (this.fontOptions.minWdt > 0 && state.width < this.fontOptions.minWdt) {
29024 state.width = this.fontOptions.minWdt;
29025 }
29026
29027 this.size.labelHeight = state.height;
29028
29029 if (this.fontOptions.minHgt > 0 && state.height < this.fontOptions.minHgt) {
29030 state.height = this.fontOptions.minHgt;
29031 }
29032
29033 this.lines = state.lines;
29034 this.lineCount = state.lines.length;
29035 this.size.width = state.width;
29036 this.size.height = state.height;
29037 this.selectedState = selected;
29038 this.hoverState = hover;
29039 this.labelDirty = false;
29040 }
29041 /**
29042 * Check if this label is visible
29043 *
29044 * @return {boolean} true if this label will be show, false otherwise
29045 */
29046
29047 }, {
29048 key: "visible",
29049 value: function visible() {
29050 if (this.size.width === 0 || this.size.height === 0 || this.elementOptions.label === undefined) {
29051 return false; // nothing to display
29052 }
29053
29054 var viewFontSize = this.fontOptions.size * this.body.view.scale;
29055
29056 if (viewFontSize < this.elementOptions.scaling.label.drawThreshold - 1) {
29057 return false; // Too small or too far away to show
29058 }
29059
29060 return true;
29061 }
29062 }], [{
29063 key: "parseFontString",
29064 value: function parseFontString(outOptions, inOptions) {
29065 if (!inOptions || typeof inOptions !== 'string') return false;
29066 var newOptionsArray = inOptions.split(" ");
29067 outOptions.size = +newOptionsArray[0].replace("px", '');
29068 outOptions.face = newOptionsArray[1];
29069 outOptions.color = newOptionsArray[2];
29070 return true;
29071 }
29072 }]);
29073
29074 return Label;
29075}();
29076
29077// https://tc39.github.io/ecma262/#sec-array.prototype.fill
29078
29079_export({
29080 target: 'Array',
29081 proto: true
29082}, {
29083 fill: arrayFill
29084}); // https://tc39.github.io/ecma262/#sec-array.prototype-@@unscopables
29085
29086addToUnscopables('fill');
29087
29088/**
29089 * The Base class for all Nodes.
29090 */
29091var NodeBase =
29092/*#__PURE__*/
29093function () {
29094 /**
29095 * @param {Object} options
29096 * @param {Object} body
29097 * @param {Label} labelModule
29098 */
29099 function NodeBase(options, body, labelModule) {
29100 _classCallCheck(this, NodeBase);
29101
29102 this.body = body;
29103 this.labelModule = labelModule;
29104 this.setOptions(options);
29105 this.top = undefined;
29106 this.left = undefined;
29107 this.height = undefined;
29108 this.width = undefined;
29109 this.radius = undefined;
29110 this.margin = undefined;
29111 this.refreshNeeded = true;
29112 this.boundingBox = {
29113 top: 0,
29114 left: 0,
29115 right: 0,
29116 bottom: 0
29117 };
29118 }
29119 /**
29120 *
29121 * @param {Object} options
29122 */
29123
29124
29125 _createClass(NodeBase, [{
29126 key: "setOptions",
29127 value: function setOptions(options) {
29128 this.options = options;
29129 }
29130 /**
29131 *
29132 * @param {Label} labelModule
29133 * @private
29134 */
29135
29136 }, {
29137 key: "_setMargins",
29138 value: function _setMargins(labelModule) {
29139 this.margin = {};
29140
29141 if (this.options.margin) {
29142 if (_typeof$1(this.options.margin) == 'object') {
29143 this.margin.top = this.options.margin.top;
29144 this.margin.right = this.options.margin.right;
29145 this.margin.bottom = this.options.margin.bottom;
29146 this.margin.left = this.options.margin.left;
29147 } else {
29148 this.margin.top = this.options.margin;
29149 this.margin.right = this.options.margin;
29150 this.margin.bottom = this.options.margin;
29151 this.margin.left = this.options.margin;
29152 }
29153 }
29154
29155 labelModule.adjustSizes(this.margin);
29156 }
29157 /**
29158 *
29159 * @param {CanvasRenderingContext2D} ctx
29160 * @param {number} angle
29161 * @returns {number}
29162 * @private
29163 */
29164
29165 }, {
29166 key: "_distanceToBorder",
29167 value: function _distanceToBorder(ctx, angle) {
29168 var borderWidth = this.options.borderWidth;
29169 this.resize(ctx);
29170 return Math.min(Math.abs(this.width / 2 / Math.cos(angle)), Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth;
29171 }
29172 /**
29173 *
29174 * @param {CanvasRenderingContext2D} ctx
29175 * @param {ArrowOptions} values
29176 */
29177
29178 }, {
29179 key: "enableShadow",
29180 value: function enableShadow(ctx, values) {
29181 if (values.shadow) {
29182 ctx.shadowColor = values.shadowColor;
29183 ctx.shadowBlur = values.shadowSize;
29184 ctx.shadowOffsetX = values.shadowX;
29185 ctx.shadowOffsetY = values.shadowY;
29186 }
29187 }
29188 /**
29189 *
29190 * @param {CanvasRenderingContext2D} ctx
29191 * @param {ArrowOptions} values
29192 */
29193
29194 }, {
29195 key: "disableShadow",
29196 value: function disableShadow(ctx, values) {
29197 if (values.shadow) {
29198 ctx.shadowColor = 'rgba(0,0,0,0)';
29199 ctx.shadowBlur = 0;
29200 ctx.shadowOffsetX = 0;
29201 ctx.shadowOffsetY = 0;
29202 }
29203 }
29204 /**
29205 *
29206 * @param {CanvasRenderingContext2D} ctx
29207 * @param {ArrowOptions} values
29208 */
29209
29210 }, {
29211 key: "enableBorderDashes",
29212 value: function enableBorderDashes(ctx, values) {
29213 if (values.borderDashes !== false) {
29214 if (ctx.setLineDash !== undefined) {
29215 var dashes = values.borderDashes;
29216
29217 if (dashes === true) {
29218 dashes = [5, 15];
29219 }
29220
29221 ctx.setLineDash(dashes);
29222 } else {
29223 console.warn("setLineDash is not supported in this browser. The dashed borders cannot be used.");
29224 this.options.shapeProperties.borderDashes = false;
29225 values.borderDashes = false;
29226 }
29227 }
29228 }
29229 /**
29230 *
29231 * @param {CanvasRenderingContext2D} ctx
29232 * @param {ArrowOptions} values
29233 */
29234
29235 }, {
29236 key: "disableBorderDashes",
29237 value: function disableBorderDashes(ctx, values) {
29238 if (values.borderDashes !== false) {
29239 if (ctx.setLineDash !== undefined) {
29240 ctx.setLineDash([0]);
29241 } else {
29242 console.warn("setLineDash is not supported in this browser. The dashed borders cannot be used.");
29243 this.options.shapeProperties.borderDashes = false;
29244 values.borderDashes = false;
29245 }
29246 }
29247 }
29248 /**
29249 * Determine if the shape of a node needs to be recalculated.
29250 *
29251 * @param {boolean} selected
29252 * @param {boolean} hover
29253 * @returns {boolean}
29254 * @protected
29255 */
29256
29257 }, {
29258 key: "needsRefresh",
29259 value: function needsRefresh(selected, hover) {
29260 if (this.refreshNeeded === true) {
29261 // This is probably not the best location to reset this member.
29262 // However, in the current logic, it is the most convenient one.
29263 this.refreshNeeded = false;
29264 return true;
29265 }
29266
29267 return this.width === undefined || this.labelModule.differentState(selected, hover);
29268 }
29269 /**
29270 *
29271 * @param {CanvasRenderingContext2D} ctx
29272 * @param {ArrowOptions} values
29273 */
29274
29275 }, {
29276 key: "initContextForDraw",
29277 value: function initContextForDraw(ctx, values) {
29278 var borderWidth = values.borderWidth / this.body.view.scale;
29279 ctx.lineWidth = Math.min(this.width, borderWidth);
29280 ctx.strokeStyle = values.borderColor;
29281 ctx.fillStyle = values.color;
29282 }
29283 /**
29284 *
29285 * @param {CanvasRenderingContext2D} ctx
29286 * @param {ArrowOptions} values
29287 */
29288
29289 }, {
29290 key: "performStroke",
29291 value: function performStroke(ctx, values) {
29292 var borderWidth = values.borderWidth / this.body.view.scale; //draw dashed border if enabled, save and restore is required for firefox not to crash on unix.
29293
29294 ctx.save(); // if borders are zero width, they will be drawn with width 1 by default. This prevents that
29295
29296 if (borderWidth > 0) {
29297 this.enableBorderDashes(ctx, values); //draw the border
29298
29299 ctx.stroke(); //disable dashed border for other elements
29300
29301 this.disableBorderDashes(ctx, values);
29302 }
29303
29304 ctx.restore();
29305 }
29306 /**
29307 *
29308 * @param {CanvasRenderingContext2D} ctx
29309 * @param {ArrowOptions} values
29310 */
29311
29312 }, {
29313 key: "performFill",
29314 value: function performFill(ctx, values) {
29315 // draw shadow if enabled
29316 this.enableShadow(ctx, values); // draw the background
29317
29318 ctx.fill(); // disable shadows for other elements.
29319
29320 this.disableShadow(ctx, values);
29321 this.performStroke(ctx, values);
29322 }
29323 /**
29324 *
29325 * @param {number} margin
29326 * @private
29327 */
29328
29329 }, {
29330 key: "_addBoundingBoxMargin",
29331 value: function _addBoundingBoxMargin(margin) {
29332 this.boundingBox.left -= margin;
29333 this.boundingBox.top -= margin;
29334 this.boundingBox.bottom += margin;
29335 this.boundingBox.right += margin;
29336 }
29337 /**
29338 * Actual implementation of this method call.
29339 *
29340 * Doing it like this makes it easier to override
29341 * in the child classes.
29342 *
29343 * @param {number} x width
29344 * @param {number} y height
29345 * @param {CanvasRenderingContext2D} ctx
29346 * @param {boolean} selected
29347 * @param {boolean} hover
29348 * @private
29349 */
29350
29351 }, {
29352 key: "_updateBoundingBox",
29353 value: function _updateBoundingBox(x, y, ctx, selected, hover) {
29354 if (ctx !== undefined) {
29355 this.resize(ctx, selected, hover);
29356 }
29357
29358 this.left = x - this.width / 2;
29359 this.top = y - this.height / 2;
29360 this.boundingBox.left = this.left;
29361 this.boundingBox.top = this.top;
29362 this.boundingBox.bottom = this.top + this.height;
29363 this.boundingBox.right = this.left + this.width;
29364 }
29365 /**
29366 * Default implementation of this method call.
29367 * This acts as a stub which can be overridden.
29368 *
29369 * @param {number} x width
29370 * @param {number} y height
29371 * @param {CanvasRenderingContext2D} ctx
29372 * @param {boolean} selected
29373 * @param {boolean} hover
29374 */
29375
29376 }, {
29377 key: "updateBoundingBox",
29378 value: function updateBoundingBox(x, y, ctx, selected, hover) {
29379 this._updateBoundingBox(x, y, ctx, selected, hover);
29380 }
29381 /**
29382 * Determine the dimensions to use for nodes with an internal label
29383 *
29384 * Currently, these are: Circle, Ellipse, Database, Box
29385 * The other nodes have external labels, and will not call this method
29386 *
29387 * If there is no label, decent default values are supplied.
29388 *
29389 * @param {CanvasRenderingContext2D} ctx
29390 * @param {boolean} [selected]
29391 * @param {boolean} [hover]
29392 * @returns {{width:number, height:number}}
29393 */
29394
29395 }, {
29396 key: "getDimensionsFromLabel",
29397 value: function getDimensionsFromLabel(ctx, selected, hover) {
29398 // NOTE: previously 'textSize' was not put in 'this' for Ellipse
29399 // TODO: examine the consequences.
29400 this.textSize = this.labelModule.getTextSize(ctx, selected, hover);
29401 var width = this.textSize.width;
29402 var height = this.textSize.height;
29403 var DEFAULT_SIZE = 14;
29404
29405 if (width === 0) {
29406 // This happens when there is no label text set
29407 width = DEFAULT_SIZE; // use a decent default
29408
29409 height = DEFAULT_SIZE; // if width zero, then height also always zero
29410 }
29411
29412 return {
29413 width: width,
29414 height: height
29415 };
29416 }
29417 }]);
29418
29419 return NodeBase;
29420}();
29421
29422/**
29423 * A Box Node/Cluster shape.
29424 *
29425 * @extends NodeBase
29426 */
29427
29428var Box =
29429/*#__PURE__*/
29430function (_NodeBase) {
29431 _inherits(Box, _NodeBase);
29432
29433 /**
29434 * @param {Object} options
29435 * @param {Object} body
29436 * @param {Label} labelModule
29437 */
29438 function Box(options, body, labelModule) {
29439 var _this;
29440
29441 _classCallCheck(this, Box);
29442
29443 _this = _possibleConstructorReturn(this, _getPrototypeOf(Box).call(this, options, body, labelModule));
29444
29445 _this._setMargins(labelModule);
29446
29447 return _this;
29448 }
29449 /**
29450 *
29451 * @param {CanvasRenderingContext2D} ctx
29452 * @param {boolean} [selected]
29453 * @param {boolean} [hover]
29454 */
29455
29456
29457 _createClass(Box, [{
29458 key: "resize",
29459 value: function resize(ctx) {
29460 var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.selected;
29461 var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hover;
29462
29463 if (this.needsRefresh(selected, hover)) {
29464 var dimensions = this.getDimensionsFromLabel(ctx, selected, hover);
29465 this.width = dimensions.width + this.margin.right + this.margin.left;
29466 this.height = dimensions.height + this.margin.top + this.margin.bottom;
29467 this.radius = this.width / 2;
29468 }
29469 }
29470 /**
29471 *
29472 * @param {CanvasRenderingContext2D} ctx
29473 * @param {number} x width
29474 * @param {number} y height
29475 * @param {boolean} selected
29476 * @param {boolean} hover
29477 * @param {ArrowOptions} values
29478 */
29479
29480 }, {
29481 key: "draw",
29482 value: function draw(ctx, x, y, selected, hover, values) {
29483 this.resize(ctx, selected, hover);
29484 this.left = x - this.width / 2;
29485 this.top = y - this.height / 2;
29486 this.initContextForDraw(ctx, values);
29487 ctx.roundRect(this.left, this.top, this.width, this.height, values.borderRadius);
29488 this.performFill(ctx, values);
29489 this.updateBoundingBox(x, y, ctx, selected, hover);
29490 this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left, this.top + this.textSize.height / 2 + this.margin.top, selected, hover);
29491 }
29492 /**
29493 *
29494 * @param {number} x width
29495 * @param {number} y height
29496 * @param {CanvasRenderingContext2D} ctx
29497 * @param {boolean} selected
29498 * @param {boolean} hover
29499 */
29500
29501 }, {
29502 key: "updateBoundingBox",
29503 value: function updateBoundingBox(x, y, ctx, selected, hover) {
29504 this._updateBoundingBox(x, y, ctx, selected, hover);
29505
29506 var borderRadius = this.options.shapeProperties.borderRadius; // only effective for box
29507
29508 this._addBoundingBoxMargin(borderRadius);
29509 }
29510 /**
29511 *
29512 * @param {CanvasRenderingContext2D} ctx
29513 * @param {number} angle
29514 * @returns {number}
29515 */
29516
29517 }, {
29518 key: "distanceToBorder",
29519 value: function distanceToBorder(ctx, angle) {
29520 this.resize(ctx);
29521 var borderWidth = this.options.borderWidth;
29522 return Math.min(Math.abs(this.width / 2 / Math.cos(angle)), Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth;
29523 }
29524 }]);
29525
29526 return Box;
29527}(NodeBase);
29528
29529/**
29530 * NOTE: This is a bad base class
29531 *
29532 * Child classes are:
29533 *
29534 * Image - uses *only* image methods
29535 * Circle - uses *only* _drawRawCircle
29536 * CircleImage - uses all
29537 *
29538 * TODO: Refactor, move _drawRawCircle to different module, derive Circle from NodeBase
29539 * Rename this to ImageBase
29540 * Consolidate common code in Image and CircleImage to base class
29541 *
29542 * @extends NodeBase
29543 */
29544
29545var CircleImageBase =
29546/*#__PURE__*/
29547function (_NodeBase) {
29548 _inherits(CircleImageBase, _NodeBase);
29549
29550 /**
29551 * @param {Object} options
29552 * @param {Object} body
29553 * @param {Label} labelModule
29554 */
29555 function CircleImageBase(options, body, labelModule) {
29556 var _this;
29557
29558 _classCallCheck(this, CircleImageBase);
29559
29560 _this = _possibleConstructorReturn(this, _getPrototypeOf(CircleImageBase).call(this, options, body, labelModule));
29561 _this.labelOffset = 0;
29562 _this.selected = false;
29563 return _this;
29564 }
29565 /**
29566 *
29567 * @param {Object} options
29568 * @param {Object} [imageObj]
29569 * @param {Object} [imageObjAlt]
29570 */
29571
29572
29573 _createClass(CircleImageBase, [{
29574 key: "setOptions",
29575 value: function setOptions(options, imageObj, imageObjAlt) {
29576 this.options = options;
29577
29578 if (!(imageObj === undefined && imageObjAlt === undefined)) {
29579 this.setImages(imageObj, imageObjAlt);
29580 }
29581 }
29582 /**
29583 * Set the images for this node.
29584 *
29585 * The images can be updated after the initial setting of options;
29586 * therefore, this method needs to be reentrant.
29587 *
29588 * For correct working in error cases, it is necessary to properly set
29589 * field 'nodes.brokenImage' in the options.
29590 *
29591 * @param {Image} imageObj required; main image to show for this node
29592 * @param {Image|undefined} imageObjAlt optional; image to show when node is selected
29593 */
29594
29595 }, {
29596 key: "setImages",
29597 value: function setImages(imageObj, imageObjAlt) {
29598 if (imageObjAlt && this.selected) {
29599 this.imageObj = imageObjAlt;
29600 this.imageObjAlt = imageObj;
29601 } else {
29602 this.imageObj = imageObj;
29603 this.imageObjAlt = imageObjAlt;
29604 }
29605 }
29606 /**
29607 * Set selection and switch between the base and the selected image.
29608 *
29609 * Do the switch only if imageObjAlt exists.
29610 *
29611 * @param {boolean} selected value of new selected state for current node
29612 */
29613
29614 }, {
29615 key: "switchImages",
29616 value: function switchImages(selected) {
29617 var selection_changed = selected && !this.selected || !selected && this.selected;
29618 this.selected = selected; // Remember new selection
29619
29620 if (this.imageObjAlt !== undefined && selection_changed) {
29621 var imageTmp = this.imageObj;
29622 this.imageObj = this.imageObjAlt;
29623 this.imageObjAlt = imageTmp;
29624 }
29625 }
29626 /**
29627 * Returns Image Padding from node options
29628 *
29629 * @returns {{top: number,left: number,bottom: number,right: number}} image padding inside this shape
29630 * @private
29631 */
29632
29633 }, {
29634 key: "_getImagePadding",
29635 value: function _getImagePadding() {
29636 var imgPadding = {
29637 top: 0,
29638 right: 0,
29639 bottom: 0,
29640 left: 0
29641 };
29642
29643 if (this.options.imagePadding) {
29644 var optImgPadding = this.options.imagePadding;
29645
29646 if (_typeof$1(optImgPadding) == 'object') {
29647 imgPadding.top = optImgPadding.top;
29648 imgPadding.right = optImgPadding.right;
29649 imgPadding.bottom = optImgPadding.bottom;
29650 imgPadding.left = optImgPadding.left;
29651 } else {
29652 imgPadding.top = optImgPadding;
29653 imgPadding.right = optImgPadding;
29654 imgPadding.bottom = optImgPadding;
29655 imgPadding.left = optImgPadding;
29656 }
29657 }
29658
29659 return imgPadding;
29660 }
29661 /**
29662 * Adjust the node dimensions for a loaded image.
29663 *
29664 * Pre: this.imageObj is valid
29665 */
29666
29667 }, {
29668 key: "_resizeImage",
29669 value: function _resizeImage() {
29670 var width, height;
29671
29672 if (this.options.shapeProperties.useImageSize === false) {
29673 // Use the size property
29674 var ratio_width = 1;
29675 var ratio_height = 1; // Only calculate the proper ratio if both width and height not zero
29676
29677 if (this.imageObj.width && this.imageObj.height) {
29678 if (this.imageObj.width > this.imageObj.height) {
29679 ratio_width = this.imageObj.width / this.imageObj.height;
29680 } else {
29681 ratio_height = this.imageObj.height / this.imageObj.width;
29682 }
29683 }
29684
29685 width = this.options.size * 2 * ratio_width;
29686 height = this.options.size * 2 * ratio_height;
29687 } else {
29688 // Use the image size with image padding
29689 var imgPadding = this._getImagePadding();
29690
29691 width = this.imageObj.width + imgPadding.left + imgPadding.right;
29692 height = this.imageObj.height + imgPadding.top + imgPadding.bottom;
29693 }
29694
29695 this.width = width;
29696 this.height = height;
29697 this.radius = 0.5 * this.width;
29698 }
29699 /**
29700 *
29701 * @param {CanvasRenderingContext2D} ctx
29702 * @param {number} x width
29703 * @param {number} y height
29704 * @param {ArrowOptions} values
29705 * @private
29706 */
29707
29708 }, {
29709 key: "_drawRawCircle",
29710 value: function _drawRawCircle(ctx, x, y, values) {
29711 this.initContextForDraw(ctx, values);
29712 ctx.circle(x, y, values.size);
29713 this.performFill(ctx, values);
29714 }
29715 /**
29716 *
29717 * @param {CanvasRenderingContext2D} ctx
29718 * @param {ArrowOptions} values
29719 * @private
29720 */
29721
29722 }, {
29723 key: "_drawImageAtPosition",
29724 value: function _drawImageAtPosition(ctx, values) {
29725 if (this.imageObj.width != 0) {
29726 // draw the image
29727 ctx.globalAlpha = 1.0; // draw shadow if enabled
29728
29729 this.enableShadow(ctx, values);
29730 var factor = 1;
29731
29732 if (this.options.shapeProperties.interpolation === true) {
29733 factor = this.imageObj.width / this.width / this.body.view.scale;
29734 }
29735
29736 var imgPadding = this._getImagePadding();
29737
29738 var imgPosLeft = this.left + imgPadding.left;
29739 var imgPosTop = this.top + imgPadding.top;
29740 var imgWidth = this.width - imgPadding.left - imgPadding.right;
29741 var imgHeight = this.height - imgPadding.top - imgPadding.bottom;
29742 this.imageObj.drawImageAtPosition(ctx, factor, imgPosLeft, imgPosTop, imgWidth, imgHeight); // disable shadows for other elements.
29743
29744 this.disableShadow(ctx, values);
29745 }
29746 }
29747 /**
29748 *
29749 * @param {CanvasRenderingContext2D} ctx
29750 * @param {number} x width
29751 * @param {number} y height
29752 * @param {boolean} selected
29753 * @param {boolean} hover
29754 * @private
29755 */
29756
29757 }, {
29758 key: "_drawImageLabel",
29759 value: function _drawImageLabel(ctx, x, y, selected, hover) {
29760 var yLabel;
29761 var offset = 0;
29762
29763 if (this.height !== undefined) {
29764 offset = this.height * 0.5;
29765 var labelDimensions = this.labelModule.getTextSize(ctx, selected, hover);
29766
29767 if (labelDimensions.lineCount >= 1) {
29768 offset += labelDimensions.height / 2;
29769 }
29770 }
29771
29772 yLabel = y + offset;
29773
29774 if (this.options.label) {
29775 this.labelOffset = offset;
29776 }
29777
29778 this.labelModule.draw(ctx, x, yLabel, selected, hover, 'hanging');
29779 }
29780 }]);
29781
29782 return CircleImageBase;
29783}(NodeBase);
29784
29785/**
29786 * A Circle Node/Cluster shape.
29787 *
29788 * @extends CircleImageBase
29789 */
29790
29791var Circle =
29792/*#__PURE__*/
29793function (_CircleImageBase) {
29794 _inherits(Circle, _CircleImageBase);
29795
29796 /**
29797 * @param {Object} options
29798 * @param {Object} body
29799 * @param {Label} labelModule
29800 */
29801 function Circle(options, body, labelModule) {
29802 var _this;
29803
29804 _classCallCheck(this, Circle);
29805
29806 _this = _possibleConstructorReturn(this, _getPrototypeOf(Circle).call(this, options, body, labelModule));
29807
29808 _this._setMargins(labelModule);
29809
29810 return _this;
29811 }
29812 /**
29813 *
29814 * @param {CanvasRenderingContext2D} ctx
29815 * @param {boolean} [selected]
29816 * @param {boolean} [hover]
29817 */
29818
29819
29820 _createClass(Circle, [{
29821 key: "resize",
29822 value: function resize(ctx) {
29823 var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.selected;
29824 var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hover;
29825
29826 if (this.needsRefresh(selected, hover)) {
29827 var dimensions = this.getDimensionsFromLabel(ctx, selected, hover);
29828 var diameter = Math.max(dimensions.width + this.margin.right + this.margin.left, dimensions.height + this.margin.top + this.margin.bottom);
29829 this.options.size = diameter / 2; // NOTE: this size field only set here, not in Ellipse, Database, Box
29830
29831 this.width = diameter;
29832 this.height = diameter;
29833 this.radius = this.width / 2;
29834 }
29835 }
29836 /**
29837 *
29838 * @param {CanvasRenderingContext2D} ctx
29839 * @param {number} x width
29840 * @param {number} y height
29841 * @param {boolean} selected
29842 * @param {boolean} hover
29843 * @param {ArrowOptions} values
29844 */
29845
29846 }, {
29847 key: "draw",
29848 value: function draw(ctx, x, y, selected, hover, values) {
29849 this.resize(ctx, selected, hover);
29850 this.left = x - this.width / 2;
29851 this.top = y - this.height / 2;
29852
29853 this._drawRawCircle(ctx, x, y, values);
29854
29855 this.updateBoundingBox(x, y);
29856 this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left, y, selected, hover);
29857 }
29858 /**
29859 *
29860 * @param {number} x width
29861 * @param {number} y height
29862 */
29863
29864 }, {
29865 key: "updateBoundingBox",
29866 value: function updateBoundingBox(x, y) {
29867 this.boundingBox.top = y - this.options.size;
29868 this.boundingBox.left = x - this.options.size;
29869 this.boundingBox.right = x + this.options.size;
29870 this.boundingBox.bottom = y + this.options.size;
29871 }
29872 /**
29873 *
29874 * @param {CanvasRenderingContext2D} ctx
29875 * @param {number} angle - Unused
29876 * @returns {number}
29877 */
29878
29879 }, {
29880 key: "distanceToBorder",
29881 value: function distanceToBorder(ctx, angle) {
29882 // eslint-disable-line no-unused-vars
29883 this.resize(ctx);
29884 return this.width * 0.5;
29885 }
29886 }]);
29887
29888 return Circle;
29889}(CircleImageBase);
29890
29891/**
29892 * A CircularImage Node/Cluster shape.
29893 *
29894 * @extends CircleImageBase
29895 */
29896
29897var CircularImage =
29898/*#__PURE__*/
29899function (_CircleImageBase) {
29900 _inherits(CircularImage, _CircleImageBase);
29901
29902 /**
29903 * @param {Object} options
29904 * @param {Object} body
29905 * @param {Label} labelModule
29906 * @param {Image} imageObj
29907 * @param {Image} imageObjAlt
29908 */
29909 function CircularImage(options, body, labelModule, imageObj, imageObjAlt) {
29910 var _this;
29911
29912 _classCallCheck(this, CircularImage);
29913
29914 _this = _possibleConstructorReturn(this, _getPrototypeOf(CircularImage).call(this, options, body, labelModule));
29915
29916 _this.setImages(imageObj, imageObjAlt);
29917
29918 return _this;
29919 }
29920 /**
29921 *
29922 * @param {CanvasRenderingContext2D} ctx
29923 * @param {boolean} [selected]
29924 * @param {boolean} [hover]
29925 */
29926
29927
29928 _createClass(CircularImage, [{
29929 key: "resize",
29930 value: function resize(ctx) {
29931 var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.selected;
29932 var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hover;
29933 var imageAbsent = this.imageObj.src === undefined || this.imageObj.width === undefined || this.imageObj.height === undefined;
29934
29935 if (imageAbsent) {
29936 var diameter = this.options.size * 2;
29937 this.width = diameter;
29938 this.height = diameter;
29939 this.radius = 0.5 * this.width;
29940 return;
29941 } // At this point, an image is present, i.e. this.imageObj is valid.
29942
29943
29944 if (this.needsRefresh(selected, hover)) {
29945 this._resizeImage();
29946 }
29947 }
29948 /**
29949 *
29950 * @param {CanvasRenderingContext2D} ctx
29951 * @param {number} x width
29952 * @param {number} y height
29953 * @param {boolean} selected
29954 * @param {boolean} hover
29955 * @param {ArrowOptions} values
29956 */
29957
29958 }, {
29959 key: "draw",
29960 value: function draw(ctx, x, y, selected, hover, values) {
29961 this.switchImages(selected);
29962 this.resize();
29963 this.left = x - this.width / 2;
29964 this.top = y - this.height / 2; // draw the background circle. IMPORTANT: the stroke in this method is used by the clip method below.
29965
29966 this._drawRawCircle(ctx, x, y, values); // now we draw in the circle, we save so we can revert the clip operation after drawing.
29967
29968
29969 ctx.save(); // clip is used to use the stroke in drawRawCircle as an area that we can draw in.
29970
29971 ctx.clip(); // draw the image
29972
29973 this._drawImageAtPosition(ctx, values); // restore so we can again draw on the full canvas
29974
29975
29976 ctx.restore();
29977
29978 this._drawImageLabel(ctx, x, y, selected, hover);
29979
29980 this.updateBoundingBox(x, y);
29981 } // TODO: compare with Circle.updateBoundingBox(), consolidate? More stuff is happening here
29982
29983 /**
29984 *
29985 * @param {number} x width
29986 * @param {number} y height
29987 */
29988
29989 }, {
29990 key: "updateBoundingBox",
29991 value: function updateBoundingBox(x, y) {
29992 this.boundingBox.top = y - this.options.size;
29993 this.boundingBox.left = x - this.options.size;
29994 this.boundingBox.right = x + this.options.size;
29995 this.boundingBox.bottom = y + this.options.size; // TODO: compare with Image.updateBoundingBox(), consolidate?
29996
29997 this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left);
29998 this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width);
29999 this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelOffset);
30000 }
30001 /**
30002 *
30003 * @param {CanvasRenderingContext2D} ctx
30004 * @param {number} angle - Unused
30005 * @returns {number}
30006 */
30007
30008 }, {
30009 key: "distanceToBorder",
30010 value: function distanceToBorder(ctx, angle) {
30011 // eslint-disable-line no-unused-vars
30012 this.resize(ctx);
30013 return this.width * 0.5;
30014 }
30015 }]);
30016
30017 return CircularImage;
30018}(CircleImageBase);
30019
30020/**
30021 * A Database Node/Cluster shape.
30022 *
30023 * @extends NodeBase
30024 */
30025
30026var Database =
30027/*#__PURE__*/
30028function (_NodeBase) {
30029 _inherits(Database, _NodeBase);
30030
30031 /**
30032 * @param {Object} options
30033 * @param {Object} body
30034 * @param {Label} labelModule
30035 */
30036 function Database(options, body, labelModule) {
30037 var _this;
30038
30039 _classCallCheck(this, Database);
30040
30041 _this = _possibleConstructorReturn(this, _getPrototypeOf(Database).call(this, options, body, labelModule));
30042
30043 _this._setMargins(labelModule);
30044
30045 return _this;
30046 }
30047 /**
30048 *
30049 * @param {CanvasRenderingContext2D} ctx
30050 * @param {boolean} selected
30051 * @param {boolean} hover
30052 */
30053
30054
30055 _createClass(Database, [{
30056 key: "resize",
30057 value: function resize(ctx, selected, hover) {
30058 if (this.needsRefresh(selected, hover)) {
30059 var dimensions = this.getDimensionsFromLabel(ctx, selected, hover);
30060 var size = dimensions.width + this.margin.right + this.margin.left;
30061 this.width = size;
30062 this.height = size;
30063 this.radius = this.width / 2;
30064 }
30065 }
30066 /**
30067 *
30068 * @param {CanvasRenderingContext2D} ctx
30069 * @param {number} x width
30070 * @param {number} y height
30071 * @param {boolean} selected
30072 * @param {boolean} hover
30073 * @param {ArrowOptions} values
30074 */
30075
30076 }, {
30077 key: "draw",
30078 value: function draw(ctx, x, y, selected, hover, values) {
30079 this.resize(ctx, selected, hover);
30080 this.left = x - this.width / 2;
30081 this.top = y - this.height / 2;
30082 this.initContextForDraw(ctx, values);
30083 ctx.database(x - this.width / 2, y - this.height / 2, this.width, this.height);
30084 this.performFill(ctx, values);
30085 this.updateBoundingBox(x, y, ctx, selected, hover);
30086 this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left, this.top + this.textSize.height / 2 + this.margin.top, selected, hover);
30087 }
30088 /**
30089 *
30090 * @param {CanvasRenderingContext2D} ctx
30091 * @param {number} angle
30092 * @returns {number}
30093 */
30094
30095 }, {
30096 key: "distanceToBorder",
30097 value: function distanceToBorder(ctx, angle) {
30098 return this._distanceToBorder(ctx, angle);
30099 }
30100 }]);
30101
30102 return Database;
30103}(NodeBase);
30104
30105/**
30106 * Base class for constructing Node/Cluster Shapes.
30107 *
30108 * @extends NodeBase
30109 */
30110
30111var ShapeBase =
30112/*#__PURE__*/
30113function (_NodeBase) {
30114 _inherits(ShapeBase, _NodeBase);
30115
30116 /**
30117 * @param {Object} options
30118 * @param {Object} body
30119 * @param {Label} labelModule
30120 */
30121 function ShapeBase(options, body, labelModule) {
30122 _classCallCheck(this, ShapeBase);
30123
30124 return _possibleConstructorReturn(this, _getPrototypeOf(ShapeBase).call(this, options, body, labelModule));
30125 }
30126 /**
30127 *
30128 * @param {CanvasRenderingContext2D} ctx
30129 * @param {boolean} [selected]
30130 * @param {boolean} [hover]
30131 * @param {Object} [values={size: this.options.size}]
30132 */
30133
30134
30135 _createClass(ShapeBase, [{
30136 key: "resize",
30137 value: function resize(ctx) {
30138 var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.selected;
30139 var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hover;
30140 var values = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {
30141 size: this.options.size
30142 };
30143
30144 if (this.needsRefresh(selected, hover)) {
30145 this.labelModule.getTextSize(ctx, selected, hover);
30146 var size = 2 * values.size;
30147 this.width = size;
30148 this.height = size;
30149 this.radius = 0.5 * this.width;
30150 }
30151 }
30152 /**
30153 *
30154 * @param {CanvasRenderingContext2D} ctx
30155 * @param {string} shape
30156 * @param {number} sizeMultiplier - Unused! TODO: Remove next major release
30157 * @param {number} x
30158 * @param {number} y
30159 * @param {boolean} selected
30160 * @param {boolean} hover
30161 * @param {ArrowOptions} values
30162 * @private
30163 */
30164
30165 }, {
30166 key: "_drawShape",
30167 value: function _drawShape(ctx, shape, sizeMultiplier, x, y, selected, hover, values) {
30168 this.resize(ctx, selected, hover, values);
30169 this.left = x - this.width / 2;
30170 this.top = y - this.height / 2;
30171 this.initContextForDraw(ctx, values);
30172 ctx[shape](x, y, values.size);
30173 this.performFill(ctx, values);
30174
30175 if (this.options.icon !== undefined) {
30176 if (this.options.icon.code !== undefined) {
30177 ctx.font = (selected ? "bold " : "") + this.height / 2 + "px " + (this.options.icon.face || 'FontAwesome');
30178 ctx.fillStyle = this.options.icon.color || "black";
30179 ctx.textAlign = "center";
30180 ctx.textBaseline = "middle";
30181 ctx.fillText(this.options.icon.code, x, y);
30182 }
30183 }
30184
30185 if (this.options.label !== undefined) {
30186 // Need to call following here in order to ensure value for `this.labelModule.size.height`
30187 this.labelModule.calculateLabelSize(ctx, selected, hover, x, y, 'hanging');
30188 var yLabel = y + 0.5 * this.height + 0.5 * this.labelModule.size.height;
30189 this.labelModule.draw(ctx, x, yLabel, selected, hover, 'hanging');
30190 }
30191
30192 this.updateBoundingBox(x, y);
30193 }
30194 /**
30195 *
30196 * @param {number} x
30197 * @param {number} y
30198 */
30199
30200 }, {
30201 key: "updateBoundingBox",
30202 value: function updateBoundingBox(x, y) {
30203 this.boundingBox.top = y - this.options.size;
30204 this.boundingBox.left = x - this.options.size;
30205 this.boundingBox.right = x + this.options.size;
30206 this.boundingBox.bottom = y + this.options.size;
30207
30208 if (this.options.label !== undefined && this.labelModule.size.width > 0) {
30209 this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left);
30210 this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width);
30211 this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelModule.size.height);
30212 }
30213 }
30214 }]);
30215
30216 return ShapeBase;
30217}(NodeBase);
30218
30219/**
30220 * A Diamond Node/Cluster shape.
30221 *
30222 * @extends ShapeBase
30223 */
30224
30225var Diamond =
30226/*#__PURE__*/
30227function (_ShapeBase) {
30228 _inherits(Diamond, _ShapeBase);
30229
30230 /**
30231 * @param {Object} options
30232 * @param {Object} body
30233 * @param {Label} labelModule
30234 */
30235 function Diamond(options, body, labelModule) {
30236 _classCallCheck(this, Diamond);
30237
30238 return _possibleConstructorReturn(this, _getPrototypeOf(Diamond).call(this, options, body, labelModule));
30239 }
30240 /**
30241 *
30242 * @param {CanvasRenderingContext2D} ctx
30243 * @param {number} x width
30244 * @param {number} y height
30245 * @param {boolean} selected
30246 * @param {boolean} hover
30247 * @param {ArrowOptions} values
30248 */
30249
30250
30251 _createClass(Diamond, [{
30252 key: "draw",
30253 value: function draw(ctx, x, y, selected, hover, values) {
30254 this._drawShape(ctx, 'diamond', 4, x, y, selected, hover, values);
30255 }
30256 /**
30257 *
30258 * @param {CanvasRenderingContext2D} ctx
30259 * @param {number} angle
30260 * @returns {number}
30261 */
30262
30263 }, {
30264 key: "distanceToBorder",
30265 value: function distanceToBorder(ctx, angle) {
30266 return this._distanceToBorder(ctx, angle);
30267 }
30268 }]);
30269
30270 return Diamond;
30271}(ShapeBase);
30272
30273/**
30274 * A Dot Node/Cluster shape.
30275 *
30276 * @extends ShapeBase
30277 */
30278
30279var Dot =
30280/*#__PURE__*/
30281function (_ShapeBase) {
30282 _inherits(Dot, _ShapeBase);
30283
30284 /**
30285 * @param {Object} options
30286 * @param {Object} body
30287 * @param {Label} labelModule
30288 */
30289 function Dot(options, body, labelModule) {
30290 _classCallCheck(this, Dot);
30291
30292 return _possibleConstructorReturn(this, _getPrototypeOf(Dot).call(this, options, body, labelModule));
30293 }
30294 /**
30295 *
30296 * @param {CanvasRenderingContext2D} ctx
30297 * @param {number} x width
30298 * @param {number} y height
30299 * @param {boolean} selected
30300 * @param {boolean} hover
30301 * @param {ArrowOptions} values
30302 */
30303
30304
30305 _createClass(Dot, [{
30306 key: "draw",
30307 value: function draw(ctx, x, y, selected, hover, values) {
30308 this._drawShape(ctx, 'circle', 2, x, y, selected, hover, values);
30309 }
30310 /**
30311 *
30312 * @param {CanvasRenderingContext2D} ctx
30313 * @param {number} angle
30314 * @returns {number}
30315 */
30316
30317 }, {
30318 key: "distanceToBorder",
30319 value: function distanceToBorder(ctx, angle) {
30320 // eslint-disable-line no-unused-vars
30321 this.resize(ctx);
30322 return this.options.size;
30323 }
30324 }]);
30325
30326 return Dot;
30327}(ShapeBase);
30328
30329/**
30330 * Am Ellipse Node/Cluster shape.
30331 *
30332 * @extends NodeBase
30333 */
30334
30335var Ellipse =
30336/*#__PURE__*/
30337function (_NodeBase) {
30338 _inherits(Ellipse, _NodeBase);
30339
30340 /**
30341 * @param {Object} options
30342 * @param {Object} body
30343 * @param {Label} labelModule
30344 */
30345 function Ellipse(options, body, labelModule) {
30346 _classCallCheck(this, Ellipse);
30347
30348 return _possibleConstructorReturn(this, _getPrototypeOf(Ellipse).call(this, options, body, labelModule));
30349 }
30350 /**
30351 *
30352 * @param {CanvasRenderingContext2D} ctx
30353 * @param {boolean} [selected]
30354 * @param {boolean} [hover]
30355 */
30356
30357
30358 _createClass(Ellipse, [{
30359 key: "resize",
30360 value: function resize(ctx) {
30361 var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.selected;
30362 var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hover;
30363
30364 if (this.needsRefresh(selected, hover)) {
30365 var dimensions = this.getDimensionsFromLabel(ctx, selected, hover);
30366 this.height = dimensions.height * 2;
30367 this.width = dimensions.width + dimensions.height;
30368 this.radius = 0.5 * this.width;
30369 }
30370 }
30371 /**
30372 *
30373 * @param {CanvasRenderingContext2D} ctx
30374 * @param {number} x width
30375 * @param {number} y height
30376 * @param {boolean} selected
30377 * @param {boolean} hover
30378 * @param {ArrowOptions} values
30379 */
30380
30381 }, {
30382 key: "draw",
30383 value: function draw(ctx, x, y, selected, hover, values) {
30384 this.resize(ctx, selected, hover);
30385 this.left = x - this.width * 0.5;
30386 this.top = y - this.height * 0.5;
30387 this.initContextForDraw(ctx, values);
30388 ctx.ellipse_vis(this.left, this.top, this.width, this.height);
30389 this.performFill(ctx, values);
30390 this.updateBoundingBox(x, y, ctx, selected, hover);
30391 this.labelModule.draw(ctx, x, y, selected, hover);
30392 }
30393 /**
30394 *
30395 * @param {CanvasRenderingContext2D} ctx
30396 * @param {number} angle
30397 * @returns {number}
30398 */
30399
30400 }, {
30401 key: "distanceToBorder",
30402 value: function distanceToBorder(ctx, angle) {
30403 this.resize(ctx);
30404 var a = this.width * 0.5;
30405 var b = this.height * 0.5;
30406 var w = Math.sin(angle) * a;
30407 var h = Math.cos(angle) * b;
30408 return a * b / Math.sqrt(w * w + h * h);
30409 }
30410 }]);
30411
30412 return Ellipse;
30413}(NodeBase);
30414
30415/**
30416 * An icon replacement for the default Node shape.
30417 *
30418 * @extends NodeBase
30419 */
30420
30421var Icon =
30422/*#__PURE__*/
30423function (_NodeBase) {
30424 _inherits(Icon, _NodeBase);
30425
30426 /**
30427 * @param {Object} options
30428 * @param {Object} body
30429 * @param {Label} labelModule
30430 */
30431 function Icon(options, body, labelModule) {
30432 var _this;
30433
30434 _classCallCheck(this, Icon);
30435
30436 _this = _possibleConstructorReturn(this, _getPrototypeOf(Icon).call(this, options, body, labelModule));
30437
30438 _this._setMargins(labelModule);
30439
30440 return _this;
30441 }
30442 /**
30443 *
30444 * @param {CanvasRenderingContext2D} ctx - Unused.
30445 * @param {boolean} [selected]
30446 * @param {boolean} [hover]
30447 */
30448
30449
30450 _createClass(Icon, [{
30451 key: "resize",
30452 value: function resize(ctx, selected, hover) {
30453 if (this.needsRefresh(selected, hover)) {
30454 this.iconSize = {
30455 width: Number(this.options.icon.size),
30456 height: Number(this.options.icon.size)
30457 };
30458 this.width = this.iconSize.width + this.margin.right + this.margin.left;
30459 this.height = this.iconSize.height + this.margin.top + this.margin.bottom;
30460 this.radius = 0.5 * this.width;
30461 }
30462 }
30463 /**
30464 *
30465 * @param {CanvasRenderingContext2D} ctx
30466 * @param {number} x width
30467 * @param {number} y height
30468 * @param {boolean} selected
30469 * @param {boolean} hover
30470 * @param {ArrowOptions} values
30471 */
30472
30473 }, {
30474 key: "draw",
30475 value: function draw(ctx, x, y, selected, hover, values) {
30476 this.resize(ctx, selected, hover);
30477 this.options.icon.size = this.options.icon.size || 50;
30478 this.left = x - this.width / 2;
30479 this.top = y - this.height / 2;
30480
30481 this._icon(ctx, x, y, selected, hover, values);
30482
30483 if (this.options.label !== undefined) {
30484 var iconTextSpacing = 5;
30485 this.labelModule.draw(ctx, this.left + this.iconSize.width / 2 + this.margin.left, y + this.height / 2 + iconTextSpacing, selected);
30486 }
30487
30488 this.updateBoundingBox(x, y);
30489 }
30490 /**
30491 *
30492 * @param {number} x
30493 * @param {number} y
30494 */
30495
30496 }, {
30497 key: "updateBoundingBox",
30498 value: function updateBoundingBox(x, y) {
30499 this.boundingBox.top = y - this.options.icon.size * 0.5;
30500 this.boundingBox.left = x - this.options.icon.size * 0.5;
30501 this.boundingBox.right = x + this.options.icon.size * 0.5;
30502 this.boundingBox.bottom = y + this.options.icon.size * 0.5;
30503
30504 if (this.options.label !== undefined && this.labelModule.size.width > 0) {
30505 var iconTextSpacing = 5;
30506 this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left);
30507 this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width);
30508 this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelModule.size.height + iconTextSpacing);
30509 }
30510 }
30511 /**
30512 *
30513 * @param {CanvasRenderingContext2D} ctx
30514 * @param {number} x width
30515 * @param {number} y height
30516 * @param {boolean} selected
30517 * @param {boolean} hover - Unused
30518 * @param {ArrowOptions} values
30519 */
30520
30521 }, {
30522 key: "_icon",
30523 value: function _icon(ctx, x, y, selected, hover, values) {
30524 var iconSize = Number(this.options.icon.size);
30525
30526 if (this.options.icon.code !== undefined) {
30527 ctx.font = [this.options.icon.weight != null ? this.options.icon.weight : selected ? "bold" : "", // If the weight is forced (for example to make Font Awesome 5 work
30528 // properly) substitute slightly bigger size for bold font face.
30529 (this.options.icon.weight != null && selected ? 5 : 0) + iconSize + "px", this.options.icon.face].join(" "); // draw icon
30530
30531 ctx.fillStyle = this.options.icon.color || "black";
30532 ctx.textAlign = "center";
30533 ctx.textBaseline = "middle"; // draw shadow if enabled
30534
30535 this.enableShadow(ctx, values);
30536 ctx.fillText(this.options.icon.code, x, y); // disable shadows for other elements.
30537
30538 this.disableShadow(ctx, values);
30539 } else {
30540 console.error('When using the icon shape, you need to define the code in the icon options object. This can be done per node or globally.');
30541 }
30542 }
30543 /**
30544 *
30545 * @param {CanvasRenderingContext2D} ctx
30546 * @param {number} angle
30547 * @returns {number}
30548 */
30549
30550 }, {
30551 key: "distanceToBorder",
30552 value: function distanceToBorder(ctx, angle) {
30553 return this._distanceToBorder(ctx, angle);
30554 }
30555 }]);
30556
30557 return Icon;
30558}(NodeBase);
30559
30560/**
30561 * An image-based replacement for the default Node shape.
30562 *
30563 * @extends CircleImageBase
30564 */
30565
30566var Image$1 =
30567/*#__PURE__*/
30568function (_CircleImageBase) {
30569 _inherits(Image, _CircleImageBase);
30570
30571 /**
30572 * @param {Object} options
30573 * @param {Object} body
30574 * @param {Label} labelModule
30575 * @param {Image} imageObj
30576 * @param {Image} imageObjAlt
30577 */
30578 function Image(options, body, labelModule, imageObj, imageObjAlt) {
30579 var _this;
30580
30581 _classCallCheck(this, Image);
30582
30583 _this = _possibleConstructorReturn(this, _getPrototypeOf(Image).call(this, options, body, labelModule));
30584
30585 _this.setImages(imageObj, imageObjAlt);
30586
30587 return _this;
30588 }
30589 /**
30590 *
30591 * @param {CanvasRenderingContext2D} ctx - Unused.
30592 * @param {boolean} [selected]
30593 * @param {boolean} [hover]
30594 */
30595
30596
30597 _createClass(Image, [{
30598 key: "resize",
30599 value: function resize(ctx) {
30600 var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.selected;
30601 var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hover;
30602 var imageAbsent = this.imageObj.src === undefined || this.imageObj.width === undefined || this.imageObj.height === undefined;
30603
30604 if (imageAbsent) {
30605 var side = this.options.size * 2;
30606 this.width = side;
30607 this.height = side;
30608 return;
30609 }
30610
30611 if (this.needsRefresh(selected, hover)) {
30612 this._resizeImage();
30613 }
30614 }
30615 /**
30616 *
30617 * @param {CanvasRenderingContext2D} ctx
30618 * @param {number} x width
30619 * @param {number} y height
30620 * @param {boolean} selected
30621 * @param {boolean} hover
30622 * @param {ArrowOptions} values
30623 */
30624
30625 }, {
30626 key: "draw",
30627 value: function draw(ctx, x, y, selected, hover, values) {
30628 this.switchImages(selected);
30629 this.resize();
30630 this.left = x - this.width / 2;
30631 this.top = y - this.height / 2;
30632
30633 if (this.options.shapeProperties.useBorderWithImage === true) {
30634 var neutralborderWidth = this.options.borderWidth;
30635 var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth;
30636 var borderWidth = (selected ? selectionLineWidth : neutralborderWidth) / this.body.view.scale;
30637 ctx.lineWidth = Math.min(this.width, borderWidth);
30638 ctx.beginPath(); // setup the line properties.
30639
30640 ctx.strokeStyle = selected ? this.options.color.highlight.border : hover ? this.options.color.hover.border : this.options.color.border; // set a fillstyle
30641
30642 ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; // draw a rectangle to form the border around. This rectangle is filled so the opacity of a picture (in future vis releases?) can be used to tint the image
30643
30644 ctx.rect(this.left - 0.5 * ctx.lineWidth, this.top - 0.5 * ctx.lineWidth, this.width + ctx.lineWidth, this.height + ctx.lineWidth);
30645 ctx.fill();
30646 this.performStroke(ctx, values);
30647 ctx.closePath();
30648 }
30649
30650 this._drawImageAtPosition(ctx, values);
30651
30652 this._drawImageLabel(ctx, x, y, selected, hover);
30653
30654 this.updateBoundingBox(x, y);
30655 }
30656 /**
30657 *
30658 * @param {number} x
30659 * @param {number} y
30660 */
30661
30662 }, {
30663 key: "updateBoundingBox",
30664 value: function updateBoundingBox(x, y) {
30665 this.resize();
30666
30667 this._updateBoundingBox(x, y);
30668
30669 if (this.options.label !== undefined && this.labelModule.size.width > 0) {
30670 this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left);
30671 this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width);
30672 this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelOffset);
30673 }
30674 }
30675 /**
30676 *
30677 * @param {CanvasRenderingContext2D} ctx
30678 * @param {number} angle
30679 * @returns {number}
30680 */
30681
30682 }, {
30683 key: "distanceToBorder",
30684 value: function distanceToBorder(ctx, angle) {
30685 return this._distanceToBorder(ctx, angle);
30686 }
30687 }]);
30688
30689 return Image;
30690}(CircleImageBase);
30691
30692/**
30693 * A Square Node/Cluster shape.
30694 *
30695 * @extends ShapeBase
30696 */
30697
30698var Square =
30699/*#__PURE__*/
30700function (_ShapeBase) {
30701 _inherits(Square, _ShapeBase);
30702
30703 /**
30704 * @param {Object} options
30705 * @param {Object} body
30706 * @param {Label} labelModule
30707 */
30708 function Square(options, body, labelModule) {
30709 _classCallCheck(this, Square);
30710
30711 return _possibleConstructorReturn(this, _getPrototypeOf(Square).call(this, options, body, labelModule));
30712 }
30713 /**
30714 *
30715 * @param {CanvasRenderingContext2D} ctx
30716 * @param {number} x width
30717 * @param {number} y height
30718 * @param {boolean} selected
30719 * @param {boolean} hover
30720 * @param {ArrowOptions} values
30721 */
30722
30723
30724 _createClass(Square, [{
30725 key: "draw",
30726 value: function draw(ctx, x, y, selected, hover, values) {
30727 this._drawShape(ctx, 'square', 2, x, y, selected, hover, values);
30728 }
30729 /**
30730 *
30731 * @param {CanvasRenderingContext2D} ctx
30732 * @param {number} angle
30733 * @returns {number}
30734 */
30735
30736 }, {
30737 key: "distanceToBorder",
30738 value: function distanceToBorder(ctx, angle) {
30739 return this._distanceToBorder(ctx, angle);
30740 }
30741 }]);
30742
30743 return Square;
30744}(ShapeBase);
30745
30746/**
30747 * A Hexagon Node/Cluster shape.
30748 *
30749 * @extends ShapeBase
30750 */
30751
30752var Hexagon =
30753/*#__PURE__*/
30754function (_ShapeBase) {
30755 _inherits(Hexagon, _ShapeBase);
30756
30757 /**
30758 * @param {Object} options
30759 * @param {Object} body
30760 * @param {Label} labelModule
30761 */
30762 function Hexagon(options, body, labelModule) {
30763 _classCallCheck(this, Hexagon);
30764
30765 return _possibleConstructorReturn(this, _getPrototypeOf(Hexagon).call(this, options, body, labelModule));
30766 }
30767 /**
30768 *
30769 * @param {CanvasRenderingContext2D} ctx
30770 * @param {number} x width
30771 * @param {number} y height
30772 * @param {boolean} selected
30773 * @param {boolean} hover
30774 * @param {ArrowOptions} values
30775 */
30776
30777
30778 _createClass(Hexagon, [{
30779 key: "draw",
30780 value: function draw(ctx, x, y, selected, hover, values) {
30781 this._drawShape(ctx, 'hexagon', 4, x, y, selected, hover, values);
30782 }
30783 /**
30784 *
30785 * @param {CanvasRenderingContext2D} ctx
30786 * @param {number} angle
30787 * @returns {number}
30788 */
30789
30790 }, {
30791 key: "distanceToBorder",
30792 value: function distanceToBorder(ctx, angle) {
30793 return this._distanceToBorder(ctx, angle);
30794 }
30795 }]);
30796
30797 return Hexagon;
30798}(ShapeBase);
30799
30800/**
30801 * A Star Node/Cluster shape.
30802 *
30803 * @extends ShapeBase
30804 */
30805
30806var Star =
30807/*#__PURE__*/
30808function (_ShapeBase) {
30809 _inherits(Star, _ShapeBase);
30810
30811 /**
30812 * @param {Object} options
30813 * @param {Object} body
30814 * @param {Label} labelModule
30815 */
30816 function Star(options, body, labelModule) {
30817 _classCallCheck(this, Star);
30818
30819 return _possibleConstructorReturn(this, _getPrototypeOf(Star).call(this, options, body, labelModule));
30820 }
30821 /**
30822 *
30823 * @param {CanvasRenderingContext2D} ctx
30824 * @param {number} x width
30825 * @param {number} y height
30826 * @param {boolean} selected
30827 * @param {boolean} hover
30828 * @param {ArrowOptions} values
30829 */
30830
30831
30832 _createClass(Star, [{
30833 key: "draw",
30834 value: function draw(ctx, x, y, selected, hover, values) {
30835 this._drawShape(ctx, 'star', 4, x, y, selected, hover, values);
30836 }
30837 /**
30838 *
30839 * @param {CanvasRenderingContext2D} ctx
30840 * @param {number} angle
30841 * @returns {number}
30842 */
30843
30844 }, {
30845 key: "distanceToBorder",
30846 value: function distanceToBorder(ctx, angle) {
30847 return this._distanceToBorder(ctx, angle);
30848 }
30849 }]);
30850
30851 return Star;
30852}(ShapeBase);
30853
30854/**
30855 * A text-based replacement for the default Node shape.
30856 *
30857 * @extends NodeBase
30858 */
30859
30860var Text =
30861/*#__PURE__*/
30862function (_NodeBase) {
30863 _inherits(Text, _NodeBase);
30864
30865 /**
30866 * @param {Object} options
30867 * @param {Object} body
30868 * @param {Label} labelModule
30869 */
30870 function Text(options, body, labelModule) {
30871 var _this;
30872
30873 _classCallCheck(this, Text);
30874
30875 _this = _possibleConstructorReturn(this, _getPrototypeOf(Text).call(this, options, body, labelModule));
30876
30877 _this._setMargins(labelModule);
30878
30879 return _this;
30880 }
30881 /**
30882 *
30883 * @param {CanvasRenderingContext2D} ctx
30884 * @param {boolean} selected
30885 * @param {boolean} hover
30886 */
30887
30888
30889 _createClass(Text, [{
30890 key: "resize",
30891 value: function resize(ctx, selected, hover) {
30892 if (this.needsRefresh(selected, hover)) {
30893 this.textSize = this.labelModule.getTextSize(ctx, selected, hover);
30894 this.width = this.textSize.width + this.margin.right + this.margin.left;
30895 this.height = this.textSize.height + this.margin.top + this.margin.bottom;
30896 this.radius = 0.5 * this.width;
30897 }
30898 }
30899 /**
30900 *
30901 * @param {CanvasRenderingContext2D} ctx
30902 * @param {number} x width
30903 * @param {number} y height
30904 * @param {boolean} selected
30905 * @param {boolean} hover
30906 * @param {ArrowOptions} values
30907 */
30908
30909 }, {
30910 key: "draw",
30911 value: function draw(ctx, x, y, selected, hover, values) {
30912 this.resize(ctx, selected, hover);
30913 this.left = x - this.width / 2;
30914 this.top = y - this.height / 2; // draw shadow if enabled
30915
30916 this.enableShadow(ctx, values);
30917 this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left, this.top + this.textSize.height / 2 + this.margin.top, selected, hover); // disable shadows for other elements.
30918
30919 this.disableShadow(ctx, values);
30920 this.updateBoundingBox(x, y, ctx, selected, hover);
30921 }
30922 /**
30923 *
30924 * @param {CanvasRenderingContext2D} ctx
30925 * @param {number} angle
30926 * @returns {number}
30927 */
30928
30929 }, {
30930 key: "distanceToBorder",
30931 value: function distanceToBorder(ctx, angle) {
30932 return this._distanceToBorder(ctx, angle);
30933 }
30934 }]);
30935
30936 return Text;
30937}(NodeBase);
30938
30939/**
30940 * A Triangle Node/Cluster shape.
30941 *
30942 * @extends ShapeBase
30943 */
30944
30945var Triangle =
30946/*#__PURE__*/
30947function (_ShapeBase) {
30948 _inherits(Triangle, _ShapeBase);
30949
30950 /**
30951 * @param {Object} options
30952 * @param {Object} body
30953 * @param {Label} labelModule
30954 */
30955 function Triangle(options, body, labelModule) {
30956 _classCallCheck(this, Triangle);
30957
30958 return _possibleConstructorReturn(this, _getPrototypeOf(Triangle).call(this, options, body, labelModule));
30959 }
30960 /**
30961 *
30962 * @param {CanvasRenderingContext2D} ctx
30963 * @param {number} x
30964 * @param {number} y
30965 * @param {boolean} selected
30966 * @param {boolean} hover
30967 * @param {ArrowOptions} values
30968 */
30969
30970
30971 _createClass(Triangle, [{
30972 key: "draw",
30973 value: function draw(ctx, x, y, selected, hover, values) {
30974 this._drawShape(ctx, 'triangle', 3, x, y, selected, hover, values);
30975 }
30976 /**
30977 *
30978 * @param {CanvasRenderingContext2D} ctx
30979 * @param {number} angle
30980 * @returns {number}
30981 */
30982
30983 }, {
30984 key: "distanceToBorder",
30985 value: function distanceToBorder(ctx, angle) {
30986 return this._distanceToBorder(ctx, angle);
30987 }
30988 }]);
30989
30990 return Triangle;
30991}(ShapeBase);
30992
30993/**
30994 * A downward facing Triangle Node/Cluster shape.
30995 *
30996 * @extends ShapeBase
30997 */
30998
30999var TriangleDown =
31000/*#__PURE__*/
31001function (_ShapeBase) {
31002 _inherits(TriangleDown, _ShapeBase);
31003
31004 /**
31005 * @param {Object} options
31006 * @param {Object} body
31007 * @param {Label} labelModule
31008 */
31009 function TriangleDown(options, body, labelModule) {
31010 _classCallCheck(this, TriangleDown);
31011
31012 return _possibleConstructorReturn(this, _getPrototypeOf(TriangleDown).call(this, options, body, labelModule));
31013 }
31014 /**
31015 *
31016 * @param {CanvasRenderingContext2D} ctx
31017 * @param {number} x
31018 * @param {number} y
31019 * @param {boolean} selected
31020 * @param {boolean} hover
31021 * @param {ArrowOptions} values
31022 */
31023
31024
31025 _createClass(TriangleDown, [{
31026 key: "draw",
31027 value: function draw(ctx, x, y, selected, hover, values) {
31028 this._drawShape(ctx, 'triangleDown', 3, x, y, selected, hover, values);
31029 }
31030 /**
31031 *
31032 * @param {CanvasRenderingContext2D} ctx
31033 * @param {number} angle
31034 * @returns {number}
31035 */
31036
31037 }, {
31038 key: "distanceToBorder",
31039 value: function distanceToBorder(ctx, angle) {
31040 return this._distanceToBorder(ctx, angle);
31041 }
31042 }]);
31043
31044 return TriangleDown;
31045}(ShapeBase);
31046
31047var DatePrototype = Date.prototype;
31048var INVALID_DATE = 'Invalid Date';
31049var TO_STRING$2 = 'toString';
31050var nativeDateToString = DatePrototype[TO_STRING$2];
31051var getTime = DatePrototype.getTime; // `Date.prototype.toString` method
31052// https://tc39.github.io/ecma262/#sec-date.prototype.tostring
31053
31054if (new Date(NaN) + '' != INVALID_DATE) {
31055 redefine(DatePrototype, TO_STRING$2, function toString() {
31056 var value = getTime.call(this); // eslint-disable-next-line no-self-compare
31057
31058 return value === value ? nativeDateToString.call(this) : INVALID_DATE;
31059 });
31060}
31061
31062var FAILS_ON_PRIMITIVES$1 = fails(function () {
31063 objectKeys(1);
31064}); // `Object.keys` method
31065// https://tc39.github.io/ecma262/#sec-object.keys
31066
31067_export({
31068 target: 'Object',
31069 stat: true,
31070 forced: FAILS_ON_PRIMITIVES$1
31071}, {
31072 keys: function keys(it) {
31073 return objectKeys(toObject(it));
31074 }
31075});
31076
31077var errorFound = false;
31078var allOptions;
31079var printStyle = 'background: #FFeeee; color: #dd0000';
31080/**
31081 * Used to validate options.
31082 */
31083
31084var Validator =
31085/*#__PURE__*/
31086function () {
31087 /**
31088 * @ignore
31089 */
31090 function Validator() {
31091 _classCallCheck(this, Validator);
31092 }
31093 /**
31094 * Main function to be called
31095 * @param {Object} options
31096 * @param {Object} referenceOptions
31097 * @param {Object} subObject
31098 * @returns {boolean}
31099 * @static
31100 */
31101
31102
31103 _createClass(Validator, null, [{
31104 key: "validate",
31105 value: function validate(options, referenceOptions, subObject) {
31106 errorFound = false;
31107 allOptions = referenceOptions;
31108 var usedOptions = referenceOptions;
31109
31110 if (subObject !== undefined) {
31111 usedOptions = referenceOptions[subObject];
31112 }
31113
31114 Validator.parse(options, usedOptions, []);
31115 return errorFound;
31116 }
31117 /**
31118 * Will traverse an object recursively and check every value
31119 * @param {Object} options
31120 * @param {Object} referenceOptions
31121 * @param {array} path | where to look for the actual option
31122 * @static
31123 */
31124
31125 }, {
31126 key: "parse",
31127 value: function parse(options, referenceOptions, path) {
31128 for (var option in options) {
31129 if (options.hasOwnProperty(option)) {
31130 Validator.check(option, options, referenceOptions, path);
31131 }
31132 }
31133 }
31134 /**
31135 * Check every value. If the value is an object, call the parse function on that object.
31136 * @param {string} option
31137 * @param {Object} options
31138 * @param {Object} referenceOptions
31139 * @param {array} path | where to look for the actual option
31140 * @static
31141 */
31142
31143 }, {
31144 key: "check",
31145 value: function check(option, options, referenceOptions, path) {
31146 if (referenceOptions[option] === undefined && referenceOptions.__any__ === undefined) {
31147 Validator.getSuggestion(option, referenceOptions, path);
31148 return;
31149 }
31150
31151 var referenceOption = option;
31152 var is_object = true;
31153
31154 if (referenceOptions[option] === undefined && referenceOptions.__any__ !== undefined) {
31155 // NOTE: This only triggers if the __any__ is in the top level of the options object.
31156 // THAT'S A REALLY BAD PLACE TO ALLOW IT!!!!
31157 // TODO: Examine if needed, remove if possible
31158 // __any__ is a wildcard. Any value is accepted and will be further analysed by reference.
31159 referenceOption = '__any__'; // if the any-subgroup is not a predefined object in the configurator,
31160 // we do not look deeper into the object.
31161
31162 is_object = Validator.getType(options[option]) === 'object';
31163 }
31164
31165 var refOptionObj = referenceOptions[referenceOption];
31166
31167 if (is_object && refOptionObj.__type__ !== undefined) {
31168 refOptionObj = refOptionObj.__type__;
31169 }
31170
31171 Validator.checkFields(option, options, referenceOptions, referenceOption, refOptionObj, path);
31172 }
31173 /**
31174 *
31175 * @param {string} option | the option property
31176 * @param {Object} options | The supplied options object
31177 * @param {Object} referenceOptions | The reference options containing all options and their allowed formats
31178 * @param {string} referenceOption | Usually this is the same as option, except when handling an __any__ tag.
31179 * @param {string} refOptionObj | This is the type object from the reference options
31180 * @param {Array} path | where in the object is the option
31181 * @static
31182 */
31183
31184 }, {
31185 key: "checkFields",
31186 value: function checkFields(option, options, referenceOptions, referenceOption, refOptionObj, path) {
31187 var log = function log(message) {
31188 console.log('%c' + message + Validator.printLocation(path, option), printStyle);
31189 };
31190
31191 var optionType = Validator.getType(options[option]);
31192 var refOptionType = refOptionObj[optionType];
31193
31194 if (refOptionType !== undefined) {
31195 // if the type is correct, we check if it is supposed to be one of a few select values
31196 if (Validator.getType(refOptionType) === 'array' && refOptionType.indexOf(options[option]) === -1) {
31197 log('Invalid option detected in "' + option + '".' + ' Allowed values are:' + Validator.print(refOptionType) + ' not "' + options[option] + '". ');
31198 errorFound = true;
31199 } else if (optionType === 'object' && referenceOption !== "__any__") {
31200 path = copyAndExtendArray(path, option);
31201 Validator.parse(options[option], referenceOptions[referenceOption], path);
31202 }
31203 } else if (refOptionObj['any'] === undefined) {
31204 // type of the field is incorrect and the field cannot be any
31205 log('Invalid type received for "' + option + '". Expected: ' + Validator.print(Object.keys(refOptionObj)) + '. Received [' + optionType + '] "' + options[option] + '"');
31206 errorFound = true;
31207 }
31208 }
31209 /**
31210 *
31211 * @param {Object|boolean|number|string|Array.<number>|Date|Node|Moment|undefined|null} object
31212 * @returns {string}
31213 * @static
31214 */
31215
31216 }, {
31217 key: "getType",
31218 value: function getType(object) {
31219 var type = _typeof$1(object);
31220
31221 if (type === 'object') {
31222 if (object === null) {
31223 return 'null';
31224 }
31225
31226 if (object instanceof Boolean) {
31227 return 'boolean';
31228 }
31229
31230 if (object instanceof Number) {
31231 return 'number';
31232 }
31233
31234 if (object instanceof String) {
31235 return 'string';
31236 }
31237
31238 if (Array.isArray(object)) {
31239 return 'array';
31240 }
31241
31242 if (object instanceof Date) {
31243 return 'date';
31244 }
31245
31246 if (object.nodeType !== undefined) {
31247 return 'dom';
31248 }
31249
31250 if (object._isAMomentObject === true) {
31251 return 'moment';
31252 }
31253
31254 return 'object';
31255 } else if (type === 'number') {
31256 return 'number';
31257 } else if (type === 'boolean') {
31258 return 'boolean';
31259 } else if (type === 'string') {
31260 return 'string';
31261 } else if (type === undefined) {
31262 return 'undefined';
31263 }
31264
31265 return type;
31266 }
31267 /**
31268 * @param {string} option
31269 * @param {Object} options
31270 * @param {Array.<string>} path
31271 * @static
31272 */
31273
31274 }, {
31275 key: "getSuggestion",
31276 value: function getSuggestion(option, options, path) {
31277 var localSearch = Validator.findInOptions(option, options, path, false);
31278 var globalSearch = Validator.findInOptions(option, allOptions, [], true);
31279 var localSearchThreshold = 8;
31280 var globalSearchThreshold = 4;
31281 var msg;
31282
31283 if (localSearch.indexMatch !== undefined) {
31284 msg = ' in ' + Validator.printLocation(localSearch.path, option, '') + 'Perhaps it was incomplete? Did you mean: "' + localSearch.indexMatch + '"?\n\n';
31285 } else if (globalSearch.distance <= globalSearchThreshold && localSearch.distance > globalSearch.distance) {
31286 msg = ' in ' + Validator.printLocation(localSearch.path, option, '') + 'Perhaps it was misplaced? Matching option found at: ' + Validator.printLocation(globalSearch.path, globalSearch.closestMatch, '');
31287 } else if (localSearch.distance <= localSearchThreshold) {
31288 msg = '. Did you mean "' + localSearch.closestMatch + '"?' + Validator.printLocation(localSearch.path, option);
31289 } else {
31290 msg = '. Did you mean one of these: ' + Validator.print(Object.keys(options)) + Validator.printLocation(path, option);
31291 }
31292
31293 console.log('%cUnknown option detected: "' + option + '"' + msg, printStyle);
31294 errorFound = true;
31295 }
31296 /**
31297 * traverse the options in search for a match.
31298 * @param {string} option
31299 * @param {Object} options
31300 * @param {Array} path | where to look for the actual option
31301 * @param {boolean} [recursive=false]
31302 * @returns {{closestMatch: string, path: Array, distance: number}}
31303 * @static
31304 */
31305
31306 }, {
31307 key: "findInOptions",
31308 value: function findInOptions(option, options, path) {
31309 var recursive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
31310 var min = 1e9;
31311 var closestMatch = '';
31312 var closestMatchPath = [];
31313 var lowerCaseOption = option.toLowerCase();
31314 var indexMatch = undefined;
31315
31316 for (var op in options) {
31317 // eslint-disable-line guard-for-in
31318 var distance = void 0;
31319
31320 if (options[op].__type__ !== undefined && recursive === true) {
31321 var result = Validator.findInOptions(option, options[op], copyAndExtendArray(path, op));
31322
31323 if (min > result.distance) {
31324 closestMatch = result.closestMatch;
31325 closestMatchPath = result.path;
31326 min = result.distance;
31327 indexMatch = result.indexMatch;
31328 }
31329 } else {
31330 if (op.toLowerCase().indexOf(lowerCaseOption) !== -1) {
31331 indexMatch = op;
31332 }
31333
31334 distance = Validator.levenshteinDistance(option, op);
31335
31336 if (min > distance) {
31337 closestMatch = op;
31338 closestMatchPath = copyArray(path);
31339 min = distance;
31340 }
31341 }
31342 }
31343
31344 return {
31345 closestMatch: closestMatch,
31346 path: closestMatchPath,
31347 distance: min,
31348 indexMatch: indexMatch
31349 };
31350 }
31351 /**
31352 * @param {Array.<string>} path
31353 * @param {Object} option
31354 * @param {string} prefix
31355 * @returns {String}
31356 * @static
31357 */
31358
31359 }, {
31360 key: "printLocation",
31361 value: function printLocation(path, option) {
31362 var prefix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'Problem value found at: \n';
31363 var str = '\n\n' + prefix + 'options = {\n';
31364
31365 for (var i = 0; i < path.length; i++) {
31366 for (var j = 0; j < i + 1; j++) {
31367 str += ' ';
31368 }
31369
31370 str += path[i] + ': {\n';
31371 }
31372
31373 for (var _j = 0; _j < path.length + 1; _j++) {
31374 str += ' ';
31375 }
31376
31377 str += option + '\n';
31378
31379 for (var _i = 0; _i < path.length + 1; _i++) {
31380 for (var _j2 = 0; _j2 < path.length - _i; _j2++) {
31381 str += ' ';
31382 }
31383
31384 str += '}\n';
31385 }
31386
31387 return str + '\n\n';
31388 }
31389 /**
31390 * @param {Object} options
31391 * @returns {String}
31392 * @static
31393 */
31394
31395 }, {
31396 key: "print",
31397 value: function print(options) {
31398 return JSON.stringify(options).replace(/(\")|(\[)|(\])|(,"__type__")/g, "").replace(/(\,)/g, ', ');
31399 }
31400 /**
31401 * Compute the edit distance between the two given strings
31402 * http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript
31403 *
31404 * Copyright (c) 2011 Andrei Mackenzie
31405 *
31406 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
31407 *
31408 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
31409 *
31410 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31411 *
31412 * @param {string} a
31413 * @param {string} b
31414 * @returns {Array.<Array.<number>>}}
31415 * @static
31416 */
31417
31418 }, {
31419 key: "levenshteinDistance",
31420 value: function levenshteinDistance(a, b) {
31421 if (a.length === 0) return b.length;
31422 if (b.length === 0) return a.length;
31423 var matrix = []; // increment along the first column of each row
31424
31425 var i;
31426
31427 for (i = 0; i <= b.length; i++) {
31428 matrix[i] = [i];
31429 } // increment each column in the first row
31430
31431
31432 var j;
31433
31434 for (j = 0; j <= a.length; j++) {
31435 matrix[0][j] = j;
31436 } // Fill in the rest of the matrix
31437
31438
31439 for (i = 1; i <= b.length; i++) {
31440 for (j = 1; j <= a.length; j++) {
31441 if (b.charAt(i - 1) == a.charAt(j - 1)) {
31442 matrix[i][j] = matrix[i - 1][j - 1];
31443 } else {
31444 matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
31445 Math.min(matrix[i][j - 1] + 1, // insertion
31446 matrix[i - 1][j] + 1)); // deletion
31447 }
31448 }
31449 }
31450
31451 return matrix[b.length][a.length];
31452 }
31453 }]);
31454
31455 return Validator;
31456}();
31457
31458/**
31459 * A node. A node can be connected to other nodes via one or multiple edges.
31460 */
31461
31462var Node =
31463/*#__PURE__*/
31464function () {
31465 /**
31466 *
31467 * @param {object} options An object containing options for the node. All
31468 * options are optional, except for the id.
31469 * {number} id Id of the node. Required
31470 * {string} label Text label for the node
31471 * {number} x Horizontal position of the node
31472 * {number} y Vertical position of the node
31473 * {string} shape Node shape
31474 * {string} image An image url
31475 * {string} title A title text, can be HTML
31476 * {anytype} group A group name or number
31477 *
31478 * @param {Object} body Shared state of current network instance
31479 * @param {Network.Images} imagelist A list with images. Only needed when the node has an image
31480 * @param {Groups} grouplist A list with groups. Needed for retrieving group options
31481 * @param {Object} globalOptions Current global node options; these serve as defaults for the node instance
31482 * @param {Object} defaultOptions Global default options for nodes; note that this is also the prototype
31483 * for parameter `globalOptions`.
31484 */
31485 function Node(options, body, imagelist, grouplist, globalOptions, defaultOptions) {
31486 _classCallCheck(this, Node);
31487
31488 this.options = bridgeObject(globalOptions);
31489 this.globalOptions = globalOptions;
31490 this.defaultOptions = defaultOptions;
31491 this.body = body;
31492 this.edges = []; // all edges connected to this node
31493 // set defaults for the options
31494
31495 this.id = undefined;
31496 this.imagelist = imagelist;
31497 this.grouplist = grouplist; // state options
31498
31499 this.x = undefined;
31500 this.y = undefined;
31501 this.baseSize = this.options.size;
31502 this.baseFontSize = this.options.font.size;
31503 this.predefinedPosition = false; // used to check if initial fit should just take the range or approximate
31504
31505 this.selected = false;
31506 this.hover = false;
31507 this.labelModule = new Label(this.body, this.options, false
31508 /* Not edge label */
31509 );
31510 this.setOptions(options);
31511 }
31512 /**
31513 * Attach a edge to the node
31514 * @param {Edge} edge
31515 */
31516
31517
31518 _createClass(Node, [{
31519 key: "attachEdge",
31520 value: function attachEdge(edge) {
31521 if (this.edges.indexOf(edge) === -1) {
31522 this.edges.push(edge);
31523 }
31524 }
31525 /**
31526 * Detach a edge from the node
31527 *
31528 * @param {Edge} edge
31529 */
31530
31531 }, {
31532 key: "detachEdge",
31533 value: function detachEdge(edge) {
31534 var index = this.edges.indexOf(edge);
31535
31536 if (index != -1) {
31537 this.edges.splice(index, 1);
31538 }
31539 }
31540 /**
31541 * Set or overwrite options for the node
31542 *
31543 * @param {Object} options an object with options
31544 * @returns {null|boolean}
31545 */
31546
31547 }, {
31548 key: "setOptions",
31549 value: function setOptions(options) {
31550 var currentShape = this.options.shape;
31551
31552 if (!options) {
31553 return; // Note that the return value will be 'undefined'! This is OK.
31554 } // Save the color for later.
31555 // This is necessary in order to prevent local color from being overwritten by group color.
31556 // TODO: To prevent such workarounds the way options are handled should be rewritten from scratch.
31557 // This is not the only problem with current options handling.
31558
31559
31560 if (typeof options.color !== 'undefined') {
31561 this._localColor = options.color;
31562 } // basic options
31563
31564
31565 if (options.id !== undefined) {
31566 this.id = options.id;
31567 }
31568
31569 if (this.id === undefined) {
31570 throw new Error("Node must have an id");
31571 }
31572
31573 Node.checkMass(options, this.id); // set these options locally
31574 // clear x and y positions
31575
31576 if (options.x !== undefined) {
31577 if (options.x === null) {
31578 this.x = undefined;
31579 this.predefinedPosition = false;
31580 } else {
31581 this.x = parseInt(options.x);
31582 this.predefinedPosition = true;
31583 }
31584 }
31585
31586 if (options.y !== undefined) {
31587 if (options.y === null) {
31588 this.y = undefined;
31589 this.predefinedPosition = false;
31590 } else {
31591 this.y = parseInt(options.y);
31592 this.predefinedPosition = true;
31593 }
31594 }
31595
31596 if (options.size !== undefined) {
31597 this.baseSize = options.size;
31598 }
31599
31600 if (options.value !== undefined) {
31601 options.value = parseFloat(options.value);
31602 } // this transforms all shorthands into fully defined options
31603
31604
31605 Node.parseOptions(this.options, options, true, this.globalOptions, this.grouplist);
31606 var pile = [options, this.options, this.defaultOptions];
31607 this.chooser = ComponentUtil.choosify('node', pile);
31608
31609 this._load_images();
31610
31611 this.updateLabelModule(options);
31612 this.updateShape(currentShape);
31613 return options.hidden !== undefined || options.physics !== undefined;
31614 }
31615 /**
31616 * Load the images from the options, for the nodes that need them.
31617 *
31618 * Images are always loaded, even if they are not used in the current shape.
31619 * The user may switch to an image shape later on.
31620 *
31621 * @private
31622 */
31623
31624 }, {
31625 key: "_load_images",
31626 value: function _load_images() {
31627 if (this.options.shape === 'circularImage' || this.options.shape === 'image') {
31628 if (this.options.image === undefined) {
31629 throw new Error("Option image must be defined for node type '" + this.options.shape + "'");
31630 }
31631 }
31632
31633 if (this.options.image === undefined) {
31634 return;
31635 }
31636
31637 if (this.imagelist === undefined) {
31638 throw new Error("Internal Error: No images provided");
31639 }
31640
31641 if (typeof this.options.image === 'string') {
31642 this.imageObj = this.imagelist.load(this.options.image, this.options.brokenImage, this.id);
31643 } else {
31644 if (this.options.image.unselected === undefined) {
31645 throw new Error("No unselected image provided");
31646 }
31647
31648 this.imageObj = this.imagelist.load(this.options.image.unselected, this.options.brokenImage, this.id);
31649
31650 if (this.options.image.selected !== undefined) {
31651 this.imageObjAlt = this.imagelist.load(this.options.image.selected, this.options.brokenImage, this.id);
31652 } else {
31653 this.imageObjAlt = undefined;
31654 }
31655 }
31656 }
31657 /**
31658 * Copy group option values into the node options.
31659 *
31660 * The group options override the global node options, so the copy of group options
31661 * must happen *after* the global node options have been set.
31662 *
31663 * This method must also be called also if the global node options have changed and the group options did not.
31664 *
31665 * @param {Object} parentOptions
31666 * @param {Object} newOptions new values for the options, currently only passed in for check
31667 * @param {Object} groupList
31668 */
31669
31670 }, {
31671 key: "getFormattingValues",
31672
31673 /**
31674 *
31675 * @returns {{color: *, borderWidth: *, borderColor: *, size: *, borderDashes: (boolean|Array|allOptions.nodes.shapeProperties.borderDashes|{boolean, array}), borderRadius: (number|allOptions.nodes.shapeProperties.borderRadius|{number}|Array), shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *}}
31676 */
31677 value: function getFormattingValues() {
31678 var values = {
31679 color: this.options.color.background,
31680 borderWidth: this.options.borderWidth,
31681 borderColor: this.options.color.border,
31682 size: this.options.size,
31683 borderDashes: this.options.shapeProperties.borderDashes,
31684 borderRadius: this.options.shapeProperties.borderRadius,
31685 shadow: this.options.shadow.enabled,
31686 shadowColor: this.options.shadow.color,
31687 shadowSize: this.options.shadow.size,
31688 shadowX: this.options.shadow.x,
31689 shadowY: this.options.shadow.y
31690 };
31691
31692 if (this.selected || this.hover) {
31693 if (this.chooser === true) {
31694 if (this.selected) {
31695 values.borderWidth *= 2;
31696 values.color = this.options.color.highlight.background;
31697 values.borderColor = this.options.color.highlight.border;
31698 values.shadow = this.options.shadow.enabled;
31699 } else if (this.hover) {
31700 values.color = this.options.color.hover.background;
31701 values.borderColor = this.options.color.hover.border;
31702 values.shadow = this.options.shadow.enabled;
31703 }
31704 } else if (typeof this.chooser === 'function') {
31705 this.chooser(values, this.options.id, this.selected, this.hover);
31706
31707 if (values.shadow === false) {
31708 if (values.shadowColor !== this.options.shadow.color || values.shadowSize !== this.options.shadow.size || values.shadowX !== this.options.shadow.x || values.shadowY !== this.options.shadow.y) {
31709 values.shadow = true;
31710 }
31711 }
31712 }
31713 } else {
31714 values.shadow = this.options.shadow.enabled;
31715 }
31716
31717 return values;
31718 }
31719 /**
31720 *
31721 * @param {Object} options
31722 */
31723
31724 }, {
31725 key: "updateLabelModule",
31726 value: function updateLabelModule(options) {
31727 if (this.options.label === undefined || this.options.label === null) {
31728 this.options.label = '';
31729 }
31730
31731 Node.updateGroupOptions(this.options, _objectSpread2$1({}, options, {
31732 color: options && options.color || this._localColor || undefined
31733 }), this.grouplist); //
31734 // Note:The prototype chain for this.options is:
31735 //
31736 // this.options -> NodesHandler.options -> NodesHandler.defaultOptions
31737 // (also: this.globalOptions)
31738 //
31739 // Note that the prototypes are mentioned explicitly in the pile list below;
31740 // WE DON'T WANT THE ORDER OF THE PROTOTYPES!!!! At least, not for font handling of labels.
31741 // This is a good indication that the prototype usage of options is deficient.
31742 //
31743
31744 var currentGroup = this.grouplist.get(this.options.group, false);
31745 var pile = [options, // new options
31746 this.options, // current node options, see comment above for prototype
31747 currentGroup, // group options, if any
31748 this.globalOptions, // Currently set global node options
31749 this.defaultOptions // Default global node options
31750 ];
31751 this.labelModule.update(this.options, pile);
31752
31753 if (this.labelModule.baseSize !== undefined) {
31754 this.baseFontSize = this.labelModule.baseSize;
31755 }
31756 }
31757 /**
31758 *
31759 * @param {string} currentShape
31760 */
31761
31762 }, {
31763 key: "updateShape",
31764 value: function updateShape(currentShape) {
31765 if (currentShape === this.options.shape && this.shape) {
31766 this.shape.setOptions(this.options, this.imageObj, this.imageObjAlt);
31767 } else {
31768 // choose draw method depending on the shape
31769 switch (this.options.shape) {
31770 case 'box':
31771 this.shape = new Box(this.options, this.body, this.labelModule);
31772 break;
31773
31774 case 'circle':
31775 this.shape = new Circle(this.options, this.body, this.labelModule);
31776 break;
31777
31778 case 'circularImage':
31779 this.shape = new CircularImage(this.options, this.body, this.labelModule, this.imageObj, this.imageObjAlt);
31780 break;
31781
31782 case 'database':
31783 this.shape = new Database(this.options, this.body, this.labelModule);
31784 break;
31785
31786 case 'diamond':
31787 this.shape = new Diamond(this.options, this.body, this.labelModule);
31788 break;
31789
31790 case 'dot':
31791 this.shape = new Dot(this.options, this.body, this.labelModule);
31792 break;
31793
31794 case 'ellipse':
31795 this.shape = new Ellipse(this.options, this.body, this.labelModule);
31796 break;
31797
31798 case 'icon':
31799 this.shape = new Icon(this.options, this.body, this.labelModule);
31800 break;
31801
31802 case 'image':
31803 this.shape = new Image$1(this.options, this.body, this.labelModule, this.imageObj, this.imageObjAlt);
31804 break;
31805
31806 case 'square':
31807 this.shape = new Square(this.options, this.body, this.labelModule);
31808 break;
31809
31810 case 'hexagon':
31811 this.shape = new Hexagon(this.options, this.body, this.labelModule);
31812 break;
31813
31814 case 'star':
31815 this.shape = new Star(this.options, this.body, this.labelModule);
31816 break;
31817
31818 case 'text':
31819 this.shape = new Text(this.options, this.body, this.labelModule);
31820 break;
31821
31822 case 'triangle':
31823 this.shape = new Triangle(this.options, this.body, this.labelModule);
31824 break;
31825
31826 case 'triangleDown':
31827 this.shape = new TriangleDown(this.options, this.body, this.labelModule);
31828 break;
31829
31830 default:
31831 this.shape = new Ellipse(this.options, this.body, this.labelModule);
31832 break;
31833 }
31834 }
31835
31836 this.needsRefresh();
31837 }
31838 /**
31839 * select this node
31840 */
31841
31842 }, {
31843 key: "select",
31844 value: function select() {
31845 this.selected = true;
31846 this.needsRefresh();
31847 }
31848 /**
31849 * unselect this node
31850 */
31851
31852 }, {
31853 key: "unselect",
31854 value: function unselect() {
31855 this.selected = false;
31856 this.needsRefresh();
31857 }
31858 /**
31859 * Reset the calculated size of the node, forces it to recalculate its size
31860 */
31861
31862 }, {
31863 key: "needsRefresh",
31864 value: function needsRefresh() {
31865 this.shape.refreshNeeded = true;
31866 }
31867 /**
31868 * get the title of this node.
31869 * @return {string} title The title of the node, or undefined when no title
31870 * has been set.
31871 */
31872
31873 }, {
31874 key: "getTitle",
31875 value: function getTitle() {
31876 return this.options.title;
31877 }
31878 /**
31879 * Calculate the distance to the border of the Node
31880 * @param {CanvasRenderingContext2D} ctx
31881 * @param {number} angle Angle in radians
31882 * @returns {number} distance Distance to the border in pixels
31883 */
31884
31885 }, {
31886 key: "distanceToBorder",
31887 value: function distanceToBorder(ctx, angle) {
31888 return this.shape.distanceToBorder(ctx, angle);
31889 }
31890 /**
31891 * Check if this node has a fixed x and y position
31892 * @return {boolean} true if fixed, false if not
31893 */
31894
31895 }, {
31896 key: "isFixed",
31897 value: function isFixed() {
31898 return this.options.fixed.x && this.options.fixed.y;
31899 }
31900 /**
31901 * check if this node is selecte
31902 * @return {boolean} selected True if node is selected, else false
31903 */
31904
31905 }, {
31906 key: "isSelected",
31907 value: function isSelected() {
31908 return this.selected;
31909 }
31910 /**
31911 * Retrieve the value of the node. Can be undefined
31912 * @return {number} value
31913 */
31914
31915 }, {
31916 key: "getValue",
31917 value: function getValue() {
31918 return this.options.value;
31919 }
31920 /**
31921 * Get the current dimensions of the label
31922 *
31923 * @return {rect}
31924 */
31925
31926 }, {
31927 key: "getLabelSize",
31928 value: function getLabelSize() {
31929 return this.labelModule.size();
31930 }
31931 /**
31932 * Adjust the value range of the node. The node will adjust it's size
31933 * based on its value.
31934 * @param {number} min
31935 * @param {number} max
31936 * @param {number} total
31937 */
31938
31939 }, {
31940 key: "setValueRange",
31941 value: function setValueRange(min, max, total) {
31942 if (this.options.value !== undefined) {
31943 var scale = this.options.scaling.customScalingFunction(min, max, total, this.options.value);
31944 var sizeDiff = this.options.scaling.max - this.options.scaling.min;
31945
31946 if (this.options.scaling.label.enabled === true) {
31947 var fontDiff = this.options.scaling.label.max - this.options.scaling.label.min;
31948 this.options.font.size = this.options.scaling.label.min + scale * fontDiff;
31949 }
31950
31951 this.options.size = this.options.scaling.min + scale * sizeDiff;
31952 } else {
31953 this.options.size = this.baseSize;
31954 this.options.font.size = this.baseFontSize;
31955 }
31956
31957 this.updateLabelModule();
31958 }
31959 /**
31960 * Draw this node in the given canvas
31961 * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
31962 * @param {CanvasRenderingContext2D} ctx
31963 */
31964
31965 }, {
31966 key: "draw",
31967 value: function draw(ctx) {
31968 var values = this.getFormattingValues();
31969 this.shape.draw(ctx, this.x, this.y, this.selected, this.hover, values);
31970 }
31971 /**
31972 * Update the bounding box of the shape
31973 * @param {CanvasRenderingContext2D} ctx
31974 */
31975
31976 }, {
31977 key: "updateBoundingBox",
31978 value: function updateBoundingBox(ctx) {
31979 this.shape.updateBoundingBox(this.x, this.y, ctx);
31980 }
31981 /**
31982 * Recalculate the size of this node in the given canvas
31983 * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
31984 * @param {CanvasRenderingContext2D} ctx
31985 */
31986
31987 }, {
31988 key: "resize",
31989 value: function resize(ctx) {
31990 var values = this.getFormattingValues();
31991 this.shape.resize(ctx, this.selected, this.hover, values);
31992 }
31993 /**
31994 * Determine all visual elements of this node instance, in which the given
31995 * point falls within the bounding shape.
31996 *
31997 * @param {point} point
31998 * @returns {Array.<nodeClickItem|nodeLabelClickItem>} list with the items which are on the point
31999 */
32000
32001 }, {
32002 key: "getItemsOnPoint",
32003 value: function getItemsOnPoint(point) {
32004 var ret = [];
32005
32006 if (this.labelModule.visible()) {
32007 if (ComponentUtil.pointInRect(this.labelModule.getSize(), point)) {
32008 ret.push({
32009 nodeId: this.id,
32010 labelId: 0
32011 });
32012 }
32013 }
32014
32015 if (ComponentUtil.pointInRect(this.shape.boundingBox, point)) {
32016 ret.push({
32017 nodeId: this.id
32018 });
32019 }
32020
32021 return ret;
32022 }
32023 /**
32024 * Check if this object is overlapping with the provided object
32025 * @param {Object} obj an object with parameters left, top, right, bottom
32026 * @return {boolean} True if location is located on node
32027 */
32028
32029 }, {
32030 key: "isOverlappingWith",
32031 value: function isOverlappingWith(obj) {
32032 return this.shape.left < obj.right && this.shape.left + this.shape.width > obj.left && this.shape.top < obj.bottom && this.shape.top + this.shape.height > obj.top;
32033 }
32034 /**
32035 * Check if this object is overlapping with the provided object
32036 * @param {Object} obj an object with parameters left, top, right, bottom
32037 * @return {boolean} True if location is located on node
32038 */
32039
32040 }, {
32041 key: "isBoundingBoxOverlappingWith",
32042 value: function isBoundingBoxOverlappingWith(obj) {
32043 return this.shape.boundingBox.left < obj.right && this.shape.boundingBox.right > obj.left && this.shape.boundingBox.top < obj.bottom && this.shape.boundingBox.bottom > obj.top;
32044 }
32045 /**
32046 * Check valid values for mass
32047 *
32048 * The mass may not be negative or zero. If it is, reset to 1
32049 *
32050 * @param {object} options
32051 * @param {Node.id} id
32052 * @static
32053 */
32054
32055 }], [{
32056 key: "updateGroupOptions",
32057 value: function updateGroupOptions(parentOptions, newOptions, groupList) {
32058 if (groupList === undefined) return; // No groups, nothing to do
32059
32060 var group = parentOptions.group; // paranoia: the selected group is already merged into node options, check.
32061
32062 if (newOptions !== undefined && newOptions.group !== undefined && group !== newOptions.group) {
32063 throw new Error("updateGroupOptions: group values in options don't match.");
32064 }
32065
32066 var hasGroup = typeof group === 'number' || typeof group === 'string' && group != '';
32067 if (!hasGroup) return; // current node has no group, no need to merge
32068
32069 var groupObj = groupList.get(group); // Skip merging of group font options into parent; these are required to be distinct for labels
32070 // Also skip mergin of color IF it is already defined in the node itself. This is to avoid the color of the
32071 // group overriding the color set at the node level
32072 // TODO: It might not be a good idea either to merge the rest of the options, investigate this.
32073
32074 var skipProperties = ['font'];
32075 if (newOptions !== undefined && newOptions.color !== undefined && newOptions.color != null) skipProperties.push('color');
32076 selectiveNotDeepExtend(skipProperties, parentOptions, groupObj); // the color object needs to be completely defined.
32077 // Since groups can partially overwrite the colors, we parse it again, just in case.
32078
32079 parentOptions.color = parseColor(parentOptions.color);
32080 }
32081 /**
32082 * This process all possible shorthands in the new options and makes sure that the parentOptions are fully defined.
32083 * Static so it can also be used by the handler.
32084 *
32085 * @param {Object} parentOptions
32086 * @param {Object} newOptions
32087 * @param {boolean} [allowDeletion=false]
32088 * @param {Object} [globalOptions={}]
32089 * @param {Object} [groupList]
32090 * @static
32091 */
32092
32093 }, {
32094 key: "parseOptions",
32095 value: function parseOptions(parentOptions, newOptions) {
32096 var allowDeletion = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
32097 var globalOptions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
32098 var groupList = arguments.length > 4 ? arguments[4] : undefined;
32099 var fields = ['color', 'fixed', 'shadow'];
32100 selectiveNotDeepExtend(fields, parentOptions, newOptions, allowDeletion);
32101 Node.checkMass(newOptions); // merge the shadow options into the parent.
32102
32103 mergeOptions(parentOptions, newOptions, 'shadow', globalOptions); // individual shape newOptions
32104
32105 if (newOptions.color !== undefined && newOptions.color !== null) {
32106 var parsedColor = parseColor(newOptions.color);
32107 fillIfDefined(parentOptions.color, parsedColor);
32108 } else if (allowDeletion === true && newOptions.color === null) {
32109 parentOptions.color = bridgeObject(globalOptions.color); // set the object back to the global options
32110 } // handle the fixed options
32111
32112
32113 if (newOptions.fixed !== undefined && newOptions.fixed !== null) {
32114 if (typeof newOptions.fixed === 'boolean') {
32115 parentOptions.fixed.x = newOptions.fixed;
32116 parentOptions.fixed.y = newOptions.fixed;
32117 } else {
32118 if (newOptions.fixed.x !== undefined && typeof newOptions.fixed.x === 'boolean') {
32119 parentOptions.fixed.x = newOptions.fixed.x;
32120 }
32121
32122 if (newOptions.fixed.y !== undefined && typeof newOptions.fixed.y === 'boolean') {
32123 parentOptions.fixed.y = newOptions.fixed.y;
32124 }
32125 }
32126 }
32127
32128 if (allowDeletion === true && newOptions.font === null) {
32129 parentOptions.font = bridgeObject(globalOptions.font); // set the object back to the global options
32130 }
32131
32132 Node.updateGroupOptions(parentOptions, newOptions, groupList); // handle the scaling options, specifically the label part
32133
32134 if (newOptions.scaling !== undefined) {
32135 mergeOptions(parentOptions.scaling, newOptions.scaling, 'label', globalOptions.scaling);
32136 }
32137 }
32138 }, {
32139 key: "checkMass",
32140 value: function checkMass(options, id) {
32141 if (options.mass !== undefined && options.mass <= 0) {
32142 var strId = '';
32143
32144 if (id !== undefined) {
32145 strId = ' in node id: ' + id;
32146 }
32147
32148 console.log('%cNegative or zero mass disallowed' + strId + ', setting mass to 1.', printStyle);
32149 options.mass = 1;
32150 }
32151 }
32152 }]);
32153
32154 return Node;
32155}();
32156
32157/**
32158 * Handler for Nodes
32159 */
32160
32161var NodesHandler =
32162/*#__PURE__*/
32163function () {
32164 /**
32165 * @param {Object} body
32166 * @param {Images} images
32167 * @param {Array.<Group>} groups
32168 * @param {LayoutEngine} layoutEngine
32169 */
32170 function NodesHandler(body, images, groups, layoutEngine) {
32171 var _this = this;
32172
32173 _classCallCheck(this, NodesHandler);
32174
32175 this.body = body;
32176 this.images = images;
32177 this.groups = groups;
32178 this.layoutEngine = layoutEngine; // create the node API in the body container
32179
32180 this.body.functions.createNode = this.create.bind(this);
32181 this.nodesListeners = {
32182 add: function add(event, params) {
32183 _this.add(params.items);
32184 },
32185 update: function update(event, params) {
32186 _this.update(params.items, params.data, params.oldData);
32187 },
32188 remove: function remove(event, params) {
32189 _this.remove(params.items);
32190 }
32191 };
32192 this.defaultOptions = {
32193 borderWidth: 1,
32194 borderWidthSelected: 2,
32195 brokenImage: undefined,
32196 color: {
32197 border: '#2B7CE9',
32198 background: '#97C2FC',
32199 highlight: {
32200 border: '#2B7CE9',
32201 background: '#D2E5FF'
32202 },
32203 hover: {
32204 border: '#2B7CE9',
32205 background: '#D2E5FF'
32206 }
32207 },
32208 fixed: {
32209 x: false,
32210 y: false
32211 },
32212 font: {
32213 color: '#343434',
32214 size: 14,
32215 // px
32216 face: 'arial',
32217 background: 'none',
32218 strokeWidth: 0,
32219 // px
32220 strokeColor: '#ffffff',
32221 align: 'center',
32222 vadjust: 0,
32223 multi: false,
32224 bold: {
32225 mod: 'bold'
32226 },
32227 boldital: {
32228 mod: 'bold italic'
32229 },
32230 ital: {
32231 mod: 'italic'
32232 },
32233 mono: {
32234 mod: '',
32235 size: 15,
32236 // px
32237 face: 'monospace',
32238 vadjust: 2
32239 }
32240 },
32241 group: undefined,
32242 hidden: false,
32243 icon: {
32244 face: 'FontAwesome',
32245 //'FontAwesome',
32246 code: undefined,
32247 //'\uf007',
32248 size: 50,
32249 //50,
32250 color: '#2B7CE9' //'#aa00ff'
32251
32252 },
32253 image: undefined,
32254 // --> URL
32255 imagePadding: {
32256 // only for image shape
32257 top: 0,
32258 right: 0,
32259 bottom: 0,
32260 left: 0
32261 },
32262 label: undefined,
32263 labelHighlightBold: true,
32264 level: undefined,
32265 margin: {
32266 top: 5,
32267 right: 5,
32268 bottom: 5,
32269 left: 5
32270 },
32271 mass: 1,
32272 physics: true,
32273 scaling: {
32274 min: 10,
32275 max: 30,
32276 label: {
32277 enabled: false,
32278 min: 14,
32279 max: 30,
32280 maxVisible: 30,
32281 drawThreshold: 5
32282 },
32283 customScalingFunction: function customScalingFunction(min, max, total, value) {
32284 if (max === min) {
32285 return 0.5;
32286 } else {
32287 var scale = 1 / (max - min);
32288 return Math.max(0, (value - min) * scale);
32289 }
32290 }
32291 },
32292 shadow: {
32293 enabled: false,
32294 color: 'rgba(0,0,0,0.5)',
32295 size: 10,
32296 x: 5,
32297 y: 5
32298 },
32299 shape: 'ellipse',
32300 shapeProperties: {
32301 borderDashes: false,
32302 // only for borders
32303 borderRadius: 6,
32304 // only for box shape
32305 interpolation: true,
32306 // only for image and circularImage shapes
32307 useImageSize: false,
32308 // only for image and circularImage shapes
32309 useBorderWithImage: false // only for image shape
32310
32311 },
32312 size: 25,
32313 title: undefined,
32314 value: undefined,
32315 x: undefined,
32316 y: undefined
32317 }; // Protect from idiocy
32318
32319 if (this.defaultOptions.mass <= 0) {
32320 throw 'Internal error: mass in defaultOptions of NodesHandler may not be zero or negative';
32321 }
32322
32323 this.options = bridgeObject(this.defaultOptions);
32324 this.bindEventListeners();
32325 }
32326 /**
32327 * Binds event listeners
32328 */
32329
32330
32331 _createClass(NodesHandler, [{
32332 key: "bindEventListeners",
32333 value: function bindEventListeners() {
32334 var _this2 = this;
32335
32336 // refresh the nodes. Used when reverting from hierarchical layout
32337 this.body.emitter.on('refreshNodes', this.refresh.bind(this));
32338 this.body.emitter.on('refresh', this.refresh.bind(this));
32339 this.body.emitter.on('destroy', function () {
32340 forEach(_this2.nodesListeners, function (callback, event) {
32341 if (_this2.body.data.nodes) _this2.body.data.nodes.off(event, callback);
32342 });
32343 delete _this2.body.functions.createNode;
32344 delete _this2.nodesListeners.add;
32345 delete _this2.nodesListeners.update;
32346 delete _this2.nodesListeners.remove;
32347 delete _this2.nodesListeners;
32348 });
32349 }
32350 /**
32351 *
32352 * @param {Object} options
32353 */
32354
32355 }, {
32356 key: "setOptions",
32357 value: function setOptions(options) {
32358 if (options !== undefined) {
32359 Node.parseOptions(this.options, options); // update the shape in all nodes
32360
32361 if (options.shape !== undefined) {
32362 for (var nodeId in this.body.nodes) {
32363 if (this.body.nodes.hasOwnProperty(nodeId)) {
32364 this.body.nodes[nodeId].updateShape();
32365 }
32366 }
32367 } // update the font in all nodes
32368
32369
32370 if (options.font !== undefined) {
32371 for (var _nodeId in this.body.nodes) {
32372 if (this.body.nodes.hasOwnProperty(_nodeId)) {
32373 this.body.nodes[_nodeId].updateLabelModule();
32374
32375 this.body.nodes[_nodeId].needsRefresh();
32376 }
32377 }
32378 } // update the shape size in all nodes
32379
32380
32381 if (options.size !== undefined) {
32382 for (var _nodeId2 in this.body.nodes) {
32383 if (this.body.nodes.hasOwnProperty(_nodeId2)) {
32384 this.body.nodes[_nodeId2].needsRefresh();
32385 }
32386 }
32387 } // update the state of the variables if needed
32388
32389
32390 if (options.hidden !== undefined || options.physics !== undefined) {
32391 this.body.emitter.emit('_dataChanged');
32392 }
32393 }
32394 }
32395 /**
32396 * Set a data set with nodes for the network
32397 * @param {Array | DataSet | DataView} nodes The data containing the nodes.
32398 * @param {boolean} [doNotEmit=false]
32399 * @private
32400 */
32401
32402 }, {
32403 key: "setData",
32404 value: function setData(nodes) {
32405 var doNotEmit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
32406 var oldNodesData = this.body.data.nodes;
32407
32408 if (nodes instanceof DataSet || nodes instanceof DataView$2) {
32409 this.body.data.nodes = nodes;
32410 } else if (Array.isArray(nodes)) {
32411 this.body.data.nodes = new DataSet();
32412 this.body.data.nodes.add(nodes);
32413 } else if (!nodes) {
32414 this.body.data.nodes = new DataSet();
32415 } else {
32416 throw new TypeError('Array or DataSet expected');
32417 }
32418
32419 if (oldNodesData) {
32420 // unsubscribe from old dataset
32421 forEach(this.nodesListeners, function (callback, event) {
32422 oldNodesData.off(event, callback);
32423 });
32424 } // remove drawn nodes
32425
32426
32427 this.body.nodes = {};
32428
32429 if (this.body.data.nodes) {
32430 // subscribe to new dataset
32431 var me = this;
32432 forEach(this.nodesListeners, function (callback, event) {
32433 me.body.data.nodes.on(event, callback);
32434 }); // draw all new nodes
32435
32436 var ids = this.body.data.nodes.getIds();
32437 this.add(ids, true);
32438 }
32439
32440 if (doNotEmit === false) {
32441 this.body.emitter.emit("_dataChanged");
32442 }
32443 }
32444 /**
32445 * Add nodes
32446 * @param {number[] | string[]} ids
32447 * @param {boolean} [doNotEmit=false]
32448 * @private
32449 */
32450
32451 }, {
32452 key: "add",
32453 value: function add(ids) {
32454 var doNotEmit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
32455 var id;
32456 var newNodes = [];
32457
32458 for (var i = 0; i < ids.length; i++) {
32459 id = ids[i];
32460 var properties = this.body.data.nodes.get(id);
32461 var node = this.create(properties);
32462 newNodes.push(node);
32463 this.body.nodes[id] = node; // note: this may replace an existing node
32464 }
32465
32466 this.layoutEngine.positionInitially(newNodes);
32467
32468 if (doNotEmit === false) {
32469 this.body.emitter.emit("_dataChanged");
32470 }
32471 }
32472 /**
32473 * Update existing nodes, or create them when not yet existing
32474 * @param {number[] | string[]} ids id's of changed nodes
32475 * @param {Array} changedData array with changed data
32476 * @param {Array|undefined} oldData optional; array with previous data
32477 * @private
32478 */
32479
32480 }, {
32481 key: "update",
32482 value: function update(ids, changedData, oldData) {
32483 var nodes = this.body.nodes;
32484 var dataChanged = false;
32485
32486 for (var i = 0; i < ids.length; i++) {
32487 var id = ids[i];
32488 var node = nodes[id];
32489 var data = changedData[i];
32490
32491 if (node !== undefined) {
32492 // update node
32493 if (node.setOptions(data)) {
32494 dataChanged = true;
32495 }
32496 } else {
32497 dataChanged = true; // create node
32498
32499 node = this.create(data);
32500 nodes[id] = node;
32501 }
32502 }
32503
32504 if (!dataChanged && oldData !== undefined) {
32505 // Check for any changes which should trigger a layout recalculation
32506 // For now, this is just 'level' for hierarchical layout
32507 // Assumption: old and new data arranged in same order; at time of writing, this holds.
32508 dataChanged = changedData.some(function (newValue, index) {
32509 var oldValue = oldData[index];
32510 return oldValue && oldValue.level !== newValue.level;
32511 });
32512 }
32513
32514 if (dataChanged === true) {
32515 this.body.emitter.emit("_dataChanged");
32516 } else {
32517 this.body.emitter.emit("_dataUpdated");
32518 }
32519 }
32520 /**
32521 * Remove existing nodes. If nodes do not exist, the method will just ignore it.
32522 * @param {number[] | string[]} ids
32523 * @private
32524 */
32525
32526 }, {
32527 key: "remove",
32528 value: function remove(ids) {
32529 var nodes = this.body.nodes;
32530
32531 for (var i = 0; i < ids.length; i++) {
32532 var id = ids[i];
32533 delete nodes[id];
32534 }
32535
32536 this.body.emitter.emit("_dataChanged");
32537 }
32538 /**
32539 * create a node
32540 * @param {Object} properties
32541 * @param {class} [constructorClass=Node.default]
32542 * @returns {*}
32543 */
32544
32545 }, {
32546 key: "create",
32547 value: function create(properties) {
32548 var constructorClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Node;
32549 return new constructorClass(properties, this.body, this.images, this.groups, this.options, this.defaultOptions);
32550 }
32551 /**
32552 *
32553 * @param {boolean} [clearPositions=false]
32554 */
32555
32556 }, {
32557 key: "refresh",
32558 value: function refresh() {
32559 var _this3 = this;
32560
32561 var clearPositions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
32562 forEach(this.body.nodes, function (node, nodeId) {
32563 var data = _this3.body.data.nodes.get(nodeId);
32564
32565 if (data !== undefined) {
32566 if (clearPositions === true) {
32567 node.setOptions({
32568 x: null,
32569 y: null
32570 });
32571 }
32572
32573 node.setOptions({
32574 fixed: false
32575 });
32576 node.setOptions(data);
32577 }
32578 });
32579 }
32580 /**
32581 * Returns the positions of the nodes.
32582 * @param {Array.<Node.id>|String} [ids] --> optional, can be array of nodeIds, can be string
32583 * @returns {{}}
32584 */
32585
32586 }, {
32587 key: "getPositions",
32588 value: function getPositions(ids) {
32589 var dataArray = {};
32590
32591 if (ids !== undefined) {
32592 if (Array.isArray(ids) === true) {
32593 for (var i = 0; i < ids.length; i++) {
32594 if (this.body.nodes[ids[i]] !== undefined) {
32595 var node = this.body.nodes[ids[i]];
32596 dataArray[ids[i]] = {
32597 x: Math.round(node.x),
32598 y: Math.round(node.y)
32599 };
32600 }
32601 }
32602 } else {
32603 if (this.body.nodes[ids] !== undefined) {
32604 var _node = this.body.nodes[ids];
32605 dataArray[ids] = {
32606 x: Math.round(_node.x),
32607 y: Math.round(_node.y)
32608 };
32609 }
32610 }
32611 } else {
32612 for (var _i = 0; _i < this.body.nodeIndices.length; _i++) {
32613 var _node2 = this.body.nodes[this.body.nodeIndices[_i]];
32614 dataArray[this.body.nodeIndices[_i]] = {
32615 x: Math.round(_node2.x),
32616 y: Math.round(_node2.y)
32617 };
32618 }
32619 }
32620
32621 return dataArray;
32622 }
32623 /**
32624 * Load the XY positions of the nodes into the dataset.
32625 */
32626
32627 }, {
32628 key: "storePositions",
32629 value: function storePositions() {
32630 // todo: add support for clusters and hierarchical.
32631 var dataArray = [];
32632 var dataset = this.body.data.nodes.getDataSet();
32633
32634 for (var nodeId in dataset._data) {
32635 if (dataset._data.hasOwnProperty(nodeId)) {
32636 var node = this.body.nodes[nodeId];
32637
32638 if (dataset._data[nodeId].x != Math.round(node.x) || dataset._data[nodeId].y != Math.round(node.y)) {
32639 dataArray.push({
32640 id: node.id,
32641 x: Math.round(node.x),
32642 y: Math.round(node.y)
32643 });
32644 }
32645 }
32646 }
32647
32648 dataset.update(dataArray);
32649 }
32650 /**
32651 * get the bounding box of a node.
32652 * @param {Node.id} nodeId
32653 * @returns {j|*}
32654 */
32655
32656 }, {
32657 key: "getBoundingBox",
32658 value: function getBoundingBox(nodeId) {
32659 if (this.body.nodes[nodeId] !== undefined) {
32660 return this.body.nodes[nodeId].shape.boundingBox;
32661 }
32662 }
32663 /**
32664 * Get the Ids of nodes connected to this node.
32665 * @param {Node.id} nodeId
32666 * @param {'to'|'from'|undefined} direction values 'from' and 'to' select respectively parent and child nodes only.
32667 * Any other value returns both parent and child nodes.
32668 * @returns {Array}
32669 */
32670
32671 }, {
32672 key: "getConnectedNodes",
32673 value: function getConnectedNodes(nodeId, direction) {
32674 var nodeList = [];
32675
32676 if (this.body.nodes[nodeId] !== undefined) {
32677 var node = this.body.nodes[nodeId];
32678 var nodeObj = {}; // used to quickly check if node already exists
32679
32680 for (var i = 0; i < node.edges.length; i++) {
32681 var edge = node.edges[i];
32682
32683 if (direction !== 'to' && edge.toId == node.id) {
32684 // these are double equals since ids can be numeric or string
32685 if (nodeObj[edge.fromId] === undefined) {
32686 nodeList.push(edge.fromId);
32687 nodeObj[edge.fromId] = true;
32688 }
32689 } else if (direction !== 'from' && edge.fromId == node.id) {
32690 // these are double equals since ids can be numeric or string
32691 if (nodeObj[edge.toId] === undefined) {
32692 nodeList.push(edge.toId);
32693 nodeObj[edge.toId] = true;
32694 }
32695 }
32696 }
32697 }
32698
32699 return nodeList;
32700 }
32701 /**
32702 * Get the ids of the edges connected to this node.
32703 * @param {Node.id} nodeId
32704 * @returns {*}
32705 */
32706
32707 }, {
32708 key: "getConnectedEdges",
32709 value: function getConnectedEdges(nodeId) {
32710 var edgeList = [];
32711
32712 if (this.body.nodes[nodeId] !== undefined) {
32713 var node = this.body.nodes[nodeId];
32714
32715 for (var i = 0; i < node.edges.length; i++) {
32716 edgeList.push(node.edges[i].id);
32717 }
32718 } else {
32719 console.log("NodeId provided for getConnectedEdges does not exist. Provided: ", nodeId);
32720 }
32721
32722 return edgeList;
32723 }
32724 /**
32725 * Move a node.
32726 *
32727 * @param {Node.id} nodeId
32728 * @param {number} x
32729 * @param {number} y
32730 */
32731
32732 }, {
32733 key: "moveNode",
32734 value: function moveNode(nodeId, x, y) {
32735 var _this4 = this;
32736
32737 if (this.body.nodes[nodeId] !== undefined) {
32738 this.body.nodes[nodeId].x = Number(x);
32739 this.body.nodes[nodeId].y = Number(y);
32740 setTimeout(function () {
32741 _this4.body.emitter.emit("startSimulation");
32742 }, 0);
32743 } else {
32744 console.log("Node id supplied to moveNode does not exist. Provided: ", nodeId);
32745 }
32746 }
32747 }]);
32748
32749 return NodesHandler;
32750}();
32751
32752var $hypot = Math.hypot;
32753var abs$2 = Math.abs;
32754var sqrt = Math.sqrt; // Chrome 77 bug
32755// https://bugs.chromium.org/p/v8/issues/detail?id=9546
32756
32757var BUGGY$1 = !!$hypot && $hypot(Infinity, NaN) !== Infinity; // `Math.hypot` method
32758// https://tc39.github.io/ecma262/#sec-math.hypot
32759
32760_export({
32761 target: 'Math',
32762 stat: true,
32763 forced: BUGGY$1
32764}, {
32765 hypot: function hypot(value1, value2) {
32766 // eslint-disable-line no-unused-vars
32767 var sum = 0;
32768 var i = 0;
32769 var aLen = arguments.length;
32770 var larg = 0;
32771 var arg, div;
32772
32773 while (i < aLen) {
32774 arg = abs$2(arguments[i++]);
32775
32776 if (larg < arg) {
32777 div = larg / arg;
32778 sum = sum * div * div + 1;
32779 larg = arg;
32780 } else if (arg > 0) {
32781 div = arg / larg;
32782 sum += div * div;
32783 } else sum += arg;
32784 }
32785
32786 return larg === Infinity ? Infinity : larg * sqrt(sum);
32787 }
32788});
32789
32790/** ============================================================================
32791 * Location of all the endpoint drawing routines.
32792 *
32793 * Every endpoint has its own drawing routine, which contains an endpoint definition.
32794 *
32795 * The endpoint definitions must have the following properies:
32796 *
32797 * - (0,0) is the connection point to the node it attaches to
32798 * - The endpoints are orientated to the positive x-direction
32799 * - The length of the endpoint is at most 1
32800 *
32801 * As long as the endpoint classes remain simple and not too numerous, they will
32802 * be contained within this module.
32803 * All classes here except `EndPoints` should be considered as private to this module.
32804 *
32805 * -----------------------------------------------------------------------------
32806 * ### Further Actions
32807 *
32808 * After adding a new endpoint here, you also need to do the following things:
32809 *
32810 * - Add the new endpoint name to `network/options.js` in array `endPoints`.
32811 * - Add the new endpoint name to the documentation.
32812 * Scan for 'arrows.to.type` and add it to the description.
32813 * - Add the endpoint to the examples. At the very least, add it to example
32814 * `edgeStyles/arrowTypes`.
32815 * ============================================================================= */
32816
32817/**
32818 * Common methods for endpoints
32819 *
32820 * @class
32821 */
32822var EndPoint =
32823/*#__PURE__*/
32824function () {
32825 function EndPoint() {
32826 _classCallCheck(this, EndPoint);
32827 }
32828
32829 _createClass(EndPoint, null, [{
32830 key: "transform",
32831
32832 /**
32833 * Apply transformation on points for display.
32834 *
32835 * The following is done:
32836 * - rotate by the specified angle
32837 * - multiply the (normalized) coordinates by the passed length
32838 * - offset by the target coordinates
32839 *
32840 * @param points - The point(s) to be transformed.
32841 * @param arrowData - The data determining the result of the transformation.
32842 */
32843 value: function transform(points, arrowData) {
32844 if (!Array.isArray(points)) {
32845 points = [points];
32846 }
32847
32848 var x = arrowData.point.x;
32849 var y = arrowData.point.y;
32850 var angle = arrowData.angle;
32851 var length = arrowData.length;
32852
32853 for (var i = 0; i < points.length; ++i) {
32854 var p = points[i];
32855 var xt = p.x * Math.cos(angle) - p.y * Math.sin(angle);
32856 var yt = p.x * Math.sin(angle) + p.y * Math.cos(angle);
32857 p.x = x + length * xt;
32858 p.y = y + length * yt;
32859 }
32860 }
32861 /**
32862 * Draw a closed path using the given real coordinates.
32863 *
32864 * @param ctx - The path will be rendered into this context.
32865 * @param points - The points of the path.
32866 */
32867
32868 }, {
32869 key: "drawPath",
32870 value: function drawPath(ctx, points) {
32871 ctx.beginPath();
32872 ctx.moveTo(points[0].x, points[0].y);
32873
32874 for (var i = 1; i < points.length; ++i) {
32875 ctx.lineTo(points[i].x, points[i].y);
32876 }
32877
32878 ctx.closePath();
32879 }
32880 }]);
32881
32882 return EndPoint;
32883}();
32884/**
32885 * Drawing methods for the arrow endpoint.
32886 */
32887
32888
32889var Image$2 =
32890/*#__PURE__*/
32891function (_EndPoint) {
32892 _inherits(Image, _EndPoint);
32893
32894 function Image() {
32895 _classCallCheck(this, Image);
32896
32897 return _possibleConstructorReturn(this, _getPrototypeOf(Image).apply(this, arguments));
32898 }
32899
32900 _createClass(Image, null, [{
32901 key: "draw",
32902
32903 /**
32904 * Draw this shape at the end of a line.
32905 *
32906 * @param ctx - The shape will be rendered into this context.
32907 * @param arrowData - The data determining the shape.
32908 *
32909 * @returns False as there is no way to fill an image.
32910 */
32911 value: function draw(ctx, arrowData) {
32912 if (arrowData.image) {
32913 ctx.save();
32914 ctx.translate(arrowData.point.x, arrowData.point.y);
32915 ctx.rotate(Math.PI / 2 + arrowData.angle);
32916 var width = arrowData.imageWidth != null ? arrowData.imageWidth : arrowData.image.width;
32917 var height = arrowData.imageHeight != null ? arrowData.imageHeight : arrowData.image.height;
32918 arrowData.image.drawImageAtPosition(ctx, 1, // scale
32919 -width / 2, // x
32920 0, // y
32921 width, height);
32922 ctx.restore();
32923 }
32924
32925 return false;
32926 }
32927 }]);
32928
32929 return Image;
32930}(EndPoint);
32931/**
32932 * Drawing methods for the arrow endpoint.
32933 */
32934
32935
32936var Arrow =
32937/*#__PURE__*/
32938function (_EndPoint2) {
32939 _inherits(Arrow, _EndPoint2);
32940
32941 function Arrow() {
32942 _classCallCheck(this, Arrow);
32943
32944 return _possibleConstructorReturn(this, _getPrototypeOf(Arrow).apply(this, arguments));
32945 }
32946
32947 _createClass(Arrow, null, [{
32948 key: "draw",
32949
32950 /**
32951 * Draw this shape at the end of a line.
32952 *
32953 * @param ctx - The shape will be rendered into this context.
32954 * @param arrowData - The data determining the shape.
32955 *
32956 * @returns True because ctx.fill() can be used to fill the arrow.
32957 */
32958 value: function draw(ctx, arrowData) {
32959 // Normalized points of closed path, in the order that they should be drawn.
32960 // (0, 0) is the attachment point, and the point around which should be rotated
32961 var points = [{
32962 x: 0,
32963 y: 0
32964 }, {
32965 x: -1,
32966 y: 0.3
32967 }, {
32968 x: -0.9,
32969 y: 0
32970 }, {
32971 x: -1,
32972 y: -0.3
32973 }];
32974 EndPoint.transform(points, arrowData);
32975 EndPoint.drawPath(ctx, points);
32976 return true;
32977 }
32978 }]);
32979
32980 return Arrow;
32981}(EndPoint);
32982/**
32983 * Drawing methods for the crow endpoint.
32984 */
32985
32986
32987var Crow =
32988/*#__PURE__*/
32989function () {
32990 function Crow() {
32991 _classCallCheck(this, Crow);
32992 }
32993
32994 _createClass(Crow, null, [{
32995 key: "draw",
32996
32997 /**
32998 * Draw this shape at the end of a line.
32999 *
33000 * @param ctx - The shape will be rendered into this context.
33001 * @param arrowData - The data determining the shape.
33002 *
33003 * @returns True because ctx.fill() can be used to fill the arrow.
33004 */
33005 value: function draw(ctx, arrowData) {
33006 // Normalized points of closed path, in the order that they should be drawn.
33007 // (0, 0) is the attachment point, and the point around which should be rotated
33008 var points = [{
33009 x: -1,
33010 y: 0
33011 }, {
33012 x: 0,
33013 y: 0.3
33014 }, {
33015 x: -0.4,
33016 y: 0
33017 }, {
33018 x: 0,
33019 y: -0.3
33020 }];
33021 EndPoint.transform(points, arrowData);
33022 EndPoint.drawPath(ctx, points);
33023 return true;
33024 }
33025 }]);
33026
33027 return Crow;
33028}();
33029/**
33030 * Drawing methods for the curve endpoint.
33031 */
33032
33033
33034var Curve =
33035/*#__PURE__*/
33036function () {
33037 function Curve() {
33038 _classCallCheck(this, Curve);
33039 }
33040
33041 _createClass(Curve, null, [{
33042 key: "draw",
33043
33044 /**
33045 * Draw this shape at the end of a line.
33046 *
33047 * @param ctx - The shape will be rendered into this context.
33048 * @param arrowData - The data determining the shape.
33049 *
33050 * @returns True because ctx.fill() can be used to fill the arrow.
33051 */
33052 value: function draw(ctx, arrowData) {
33053 // Normalized points of closed path, in the order that they should be drawn.
33054 // (0, 0) is the attachment point, and the point around which should be rotated
33055 var point = {
33056 x: -0.4,
33057 y: 0
33058 };
33059 EndPoint.transform(point, arrowData); // Update endpoint style for drawing transparent arc.
33060
33061 ctx.strokeStyle = ctx.fillStyle;
33062 ctx.fillStyle = "rgba(0, 0, 0, 0)"; // Define curve endpoint as semicircle.
33063
33064 var pi = Math.PI;
33065 var startAngle = arrowData.angle - pi / 2;
33066 var endAngle = arrowData.angle + pi / 2;
33067 ctx.beginPath();
33068 ctx.arc(point.x, point.y, arrowData.length * 0.4, startAngle, endAngle, false);
33069 ctx.stroke();
33070 return true;
33071 }
33072 }]);
33073
33074 return Curve;
33075}();
33076/**
33077 * Drawing methods for the inverted curve endpoint.
33078 */
33079
33080
33081var InvertedCurve =
33082/*#__PURE__*/
33083function () {
33084 function InvertedCurve() {
33085 _classCallCheck(this, InvertedCurve);
33086 }
33087
33088 _createClass(InvertedCurve, null, [{
33089 key: "draw",
33090
33091 /**
33092 * Draw this shape at the end of a line.
33093 *
33094 * @param ctx - The shape will be rendered into this context.
33095 * @param arrowData - The data determining the shape.
33096 *
33097 * @returns True because ctx.fill() can be used to fill the arrow.
33098 */
33099 value: function draw(ctx, arrowData) {
33100 // Normalized points of closed path, in the order that they should be drawn.
33101 // (0, 0) is the attachment point, and the point around which should be rotated
33102 var point = {
33103 x: -0.3,
33104 y: 0
33105 };
33106 EndPoint.transform(point, arrowData); // Update endpoint style for drawing transparent arc.
33107
33108 ctx.strokeStyle = ctx.fillStyle;
33109 ctx.fillStyle = "rgba(0, 0, 0, 0)"; // Define inverted curve endpoint as semicircle.
33110
33111 var pi = Math.PI;
33112 var startAngle = arrowData.angle + pi / 2;
33113 var endAngle = arrowData.angle + 3 * pi / 2;
33114 ctx.beginPath();
33115 ctx.arc(point.x, point.y, arrowData.length * 0.4, startAngle, endAngle, false);
33116 ctx.stroke();
33117 return true;
33118 }
33119 }]);
33120
33121 return InvertedCurve;
33122}();
33123/**
33124 * Drawing methods for the trinagle endpoint.
33125 */
33126
33127
33128var Triangle$1 =
33129/*#__PURE__*/
33130function () {
33131 function Triangle() {
33132 _classCallCheck(this, Triangle);
33133 }
33134
33135 _createClass(Triangle, null, [{
33136 key: "draw",
33137
33138 /**
33139 * Draw this shape at the end of a line.
33140 *
33141 * @param ctx - The shape will be rendered into this context.
33142 * @param arrowData - The data determining the shape.
33143 *
33144 * @returns True because ctx.fill() can be used to fill the arrow.
33145 */
33146 value: function draw(ctx, arrowData) {
33147 // Normalized points of closed path, in the order that they should be drawn.
33148 // (0, 0) is the attachment point, and the point around which should be rotated
33149 var points = [{
33150 x: 0.02,
33151 y: 0
33152 }, {
33153 x: -1,
33154 y: 0.3
33155 }, {
33156 x: -1,
33157 y: -0.3
33158 }];
33159 EndPoint.transform(points, arrowData);
33160 EndPoint.drawPath(ctx, points);
33161 return true;
33162 }
33163 }]);
33164
33165 return Triangle;
33166}();
33167/**
33168 * Drawing methods for the inverted trinagle endpoint.
33169 */
33170
33171
33172var InvertedTriangle =
33173/*#__PURE__*/
33174function () {
33175 function InvertedTriangle() {
33176 _classCallCheck(this, InvertedTriangle);
33177 }
33178
33179 _createClass(InvertedTriangle, null, [{
33180 key: "draw",
33181
33182 /**
33183 * Draw this shape at the end of a line.
33184 *
33185 * @param ctx - The shape will be rendered into this context.
33186 * @param arrowData - The data determining the shape.
33187 *
33188 * @returns True because ctx.fill() can be used to fill the arrow.
33189 */
33190 value: function draw(ctx, arrowData) {
33191 // Normalized points of closed path, in the order that they should be drawn.
33192 // (0, 0) is the attachment point, and the point around which should be rotated
33193 var points = [{
33194 x: 0,
33195 y: 0.3
33196 }, {
33197 x: 0,
33198 y: -0.3
33199 }, {
33200 x: -1,
33201 y: 0
33202 }];
33203 EndPoint.transform(points, arrowData);
33204 EndPoint.drawPath(ctx, points);
33205 return true;
33206 }
33207 }]);
33208
33209 return InvertedTriangle;
33210}();
33211/**
33212 * Drawing methods for the circle endpoint.
33213 */
33214
33215
33216var Circle$1 =
33217/*#__PURE__*/
33218function () {
33219 function Circle() {
33220 _classCallCheck(this, Circle);
33221 }
33222
33223 _createClass(Circle, null, [{
33224 key: "draw",
33225
33226 /**
33227 * Draw this shape at the end of a line.
33228 *
33229 * @param ctx - The shape will be rendered into this context.
33230 * @param arrowData - The data determining the shape.
33231 *
33232 * @returns True because ctx.fill() can be used to fill the arrow.
33233 */
33234 value: function draw(ctx, arrowData) {
33235 var point = {
33236 x: -0.4,
33237 y: 0
33238 };
33239 EndPoint.transform(point, arrowData);
33240 ctx.circle(point.x, point.y, arrowData.length * 0.4);
33241 return true;
33242 }
33243 }]);
33244
33245 return Circle;
33246}();
33247/**
33248 * Drawing methods for the bar endpoint.
33249 */
33250
33251
33252var Bar =
33253/*#__PURE__*/
33254function () {
33255 function Bar() {
33256 _classCallCheck(this, Bar);
33257 }
33258
33259 _createClass(Bar, null, [{
33260 key: "draw",
33261
33262 /**
33263 * Draw this shape at the end of a line.
33264 *
33265 * @param ctx - The shape will be rendered into this context.
33266 * @param arrowData - The data determining the shape.
33267 *
33268 * @returns True because ctx.fill() can be used to fill the arrow.
33269 */
33270 value: function draw(ctx, arrowData) {
33271 /*
33272 var points = [
33273 {x:0, y:0.5},
33274 {x:0, y:-0.5}
33275 ];
33276 EndPoint.transform(points, arrowData);
33277 ctx.beginPath();
33278 ctx.moveTo(points[0].x, points[0].y);
33279 ctx.lineTo(points[1].x, points[1].y);
33280 ctx.stroke();
33281 */
33282 var points = [{
33283 x: 0,
33284 y: 0.5
33285 }, {
33286 x: 0,
33287 y: -0.5
33288 }, {
33289 x: -0.15,
33290 y: -0.5
33291 }, {
33292 x: -0.15,
33293 y: 0.5
33294 }];
33295 EndPoint.transform(points, arrowData);
33296 EndPoint.drawPath(ctx, points);
33297 return true;
33298 }
33299 }]);
33300
33301 return Bar;
33302}();
33303/**
33304 * Drawing methods for the box endpoint.
33305 */
33306
33307
33308var Box$1 =
33309/*#__PURE__*/
33310function () {
33311 function Box() {
33312 _classCallCheck(this, Box);
33313 }
33314
33315 _createClass(Box, null, [{
33316 key: "draw",
33317
33318 /**
33319 * Draw this shape at the end of a line.
33320 *
33321 * @param ctx - The shape will be rendered into this context.
33322 * @param arrowData - The data determining the shape.
33323 *
33324 * @returns True because ctx.fill() can be used to fill the arrow.
33325 */
33326 value: function draw(ctx, arrowData) {
33327 var points = [{
33328 x: 0,
33329 y: 0.3
33330 }, {
33331 x: 0,
33332 y: -0.3
33333 }, {
33334 x: -0.6,
33335 y: -0.3
33336 }, {
33337 x: -0.6,
33338 y: 0.3
33339 }];
33340 EndPoint.transform(points, arrowData);
33341 EndPoint.drawPath(ctx, points);
33342 return true;
33343 }
33344 }]);
33345
33346 return Box;
33347}();
33348/**
33349 * Drawing methods for the diamond endpoint.
33350 */
33351
33352
33353var Diamond$1 =
33354/*#__PURE__*/
33355function () {
33356 function Diamond() {
33357 _classCallCheck(this, Diamond);
33358 }
33359
33360 _createClass(Diamond, null, [{
33361 key: "draw",
33362
33363 /**
33364 * Draw this shape at the end of a line.
33365 *
33366 * @param ctx - The shape will be rendered into this context.
33367 * @param arrowData - The data determining the shape.
33368 *
33369 * @returns True because ctx.fill() can be used to fill the arrow.
33370 */
33371 value: function draw(ctx, arrowData) {
33372 var points = [{
33373 x: 0,
33374 y: 0
33375 }, {
33376 x: -0.5,
33377 y: -0.3
33378 }, {
33379 x: -1,
33380 y: 0
33381 }, {
33382 x: -0.5,
33383 y: 0.3
33384 }];
33385 EndPoint.transform(points, arrowData);
33386 EndPoint.drawPath(ctx, points);
33387 return true;
33388 }
33389 }]);
33390
33391 return Diamond;
33392}();
33393/**
33394 * Drawing methods for the vee endpoint.
33395 */
33396
33397
33398var Vee =
33399/*#__PURE__*/
33400function () {
33401 function Vee() {
33402 _classCallCheck(this, Vee);
33403 }
33404
33405 _createClass(Vee, null, [{
33406 key: "draw",
33407
33408 /**
33409 * Draw this shape at the end of a line.
33410 *
33411 * @param ctx - The shape will be rendered into this context.
33412 * @param arrowData - The data determining the shape.
33413 *
33414 * @returns True because ctx.fill() can be used to fill the arrow.
33415 */
33416 value: function draw(ctx, arrowData) {
33417 // Normalized points of closed path, in the order that they should be drawn.
33418 // (0, 0) is the attachment point, and the point around which should be rotated
33419 var points = [{
33420 x: -1,
33421 y: 0.3
33422 }, {
33423 x: -0.5,
33424 y: 0
33425 }, {
33426 x: -1,
33427 y: -0.3
33428 }, {
33429 x: 0,
33430 y: 0
33431 }];
33432 EndPoint.transform(points, arrowData);
33433 EndPoint.drawPath(ctx, points);
33434 return true;
33435 }
33436 }]);
33437
33438 return Vee;
33439}();
33440/**
33441 * Drawing methods for the endpoints.
33442 */
33443
33444
33445var EndPoints =
33446/*#__PURE__*/
33447function () {
33448 function EndPoints() {
33449 _classCallCheck(this, EndPoints);
33450 }
33451
33452 _createClass(EndPoints, null, [{
33453 key: "draw",
33454
33455 /**
33456 * Draw an endpoint.
33457 *
33458 * @param ctx - The shape will be rendered into this context.
33459 * @param arrowData - The data determining the shape.
33460 *
33461 * @returns True if ctx.fill() can be used to fill the arrow, false otherwise.
33462 */
33463 value: function draw(ctx, arrowData) {
33464 var type;
33465
33466 if (arrowData.type) {
33467 type = arrowData.type.toLowerCase();
33468 }
33469
33470 switch (type) {
33471 case "image":
33472 return Image$2.draw(ctx, arrowData);
33473
33474 case "circle":
33475 return Circle$1.draw(ctx, arrowData);
33476
33477 case "box":
33478 return Box$1.draw(ctx, arrowData);
33479
33480 case "crow":
33481 return Crow.draw(ctx, arrowData);
33482
33483 case "curve":
33484 return Curve.draw(ctx, arrowData);
33485
33486 case "diamond":
33487 return Diamond$1.draw(ctx, arrowData);
33488
33489 case "inv_curve":
33490 return InvertedCurve.draw(ctx, arrowData);
33491
33492 case "triangle":
33493 return Triangle$1.draw(ctx, arrowData);
33494
33495 case "inv_triangle":
33496 return InvertedTriangle.draw(ctx, arrowData);
33497
33498 case "bar":
33499 return Bar.draw(ctx, arrowData);
33500
33501 case "vee":
33502 return Vee.draw(ctx, arrowData);
33503
33504 case "arrow": // fall-through
33505
33506 default:
33507 return Arrow.draw(ctx, arrowData);
33508 }
33509 }
33510 }]);
33511
33512 return EndPoints;
33513}();
33514
33515/**
33516 * The Base Class for all edges.
33517 */
33518
33519var EdgeBase =
33520/*#__PURE__*/
33521function () {
33522 /**
33523 * Create a new instance.
33524 *
33525 * @param options - The options object of given edge.
33526 * @param _body - The body of the network.
33527 * @param _labelModule - Label module.
33528 */
33529 function EdgeBase(options, _body, _labelModule) {
33530 _classCallCheck(this, EdgeBase);
33531
33532 this._body = _body;
33533 this._labelModule = _labelModule;
33534 this.color = {};
33535 this.colorDirty = true;
33536 this.hoverWidth = 1.5;
33537 this.selectionWidth = 2;
33538 this.setOptions(options);
33539 this.fromPoint = this.from;
33540 this.toPoint = this.to;
33541 }
33542 /** @inheritdoc */
33543
33544
33545 _createClass(EdgeBase, [{
33546 key: "connect",
33547 value: function connect() {
33548 this.from = this._body.nodes[this.options.from];
33549 this.to = this._body.nodes[this.options.to];
33550 }
33551 /** @inheritdoc */
33552
33553 }, {
33554 key: "cleanup",
33555 value: function cleanup() {
33556 return false;
33557 }
33558 /**
33559 * Set new edge options.
33560 *
33561 * @param options - The new edge options object.
33562 */
33563
33564 }, {
33565 key: "setOptions",
33566 value: function setOptions(options) {
33567 this.options = options;
33568 this.from = this._body.nodes[this.options.from];
33569 this.to = this._body.nodes[this.options.to];
33570 this.id = this.options.id;
33571 }
33572 /** @inheritdoc */
33573
33574 }, {
33575 key: "drawLine",
33576 value: function drawLine(ctx, values, _selected, _hover) {
33577 var viaNode = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : this.getViaNode();
33578 // set style
33579 ctx.strokeStyle = this.getColor(ctx, values);
33580 ctx.lineWidth = values.width;
33581
33582 if (values.dashes !== false) {
33583 this._drawDashedLine(ctx, values, viaNode);
33584 } else {
33585 this._drawLine(ctx, values, viaNode);
33586 }
33587 }
33588 /**
33589 * Draw a line with given style between two nodes through supplied node(s).
33590 *
33591 * @param ctx - The context that will be used for rendering.
33592 * @param values - Formatting values like color, opacity or shadow.
33593 * @param viaNode - Additional control point(s) for the edge.
33594 * @param fromPoint - TODO: Seems ignored, remove?
33595 * @param toPoint - TODO: Seems ignored, remove?
33596 */
33597
33598 }, {
33599 key: "_drawLine",
33600 value: function _drawLine(ctx, values, viaNode, fromPoint, toPoint) {
33601 if (this.from != this.to) {
33602 // draw line
33603 this._line(ctx, values, viaNode, fromPoint, toPoint);
33604 } else {
33605 var _this$_getCircleData = this._getCircleData(ctx),
33606 _this$_getCircleData2 = _slicedToArray(_this$_getCircleData, 3),
33607 x = _this$_getCircleData2[0],
33608 y = _this$_getCircleData2[1],
33609 radius = _this$_getCircleData2[2];
33610
33611 this._circle(ctx, values, x, y, radius);
33612 }
33613 }
33614 /**
33615 * Draw a dashed line with given style between two nodes through supplied node(s).
33616 *
33617 * @param ctx - The context that will be used for rendering.
33618 * @param values - Formatting values like color, opacity or shadow.
33619 * @param viaNode - Additional control point(s) for the edge.
33620 * @param _fromPoint - Ignored (TODO: remove in the future).
33621 * @param _toPoint - Ignored (TODO: remove in the future).
33622 */
33623
33624 }, {
33625 key: "_drawDashedLine",
33626 value: function _drawDashedLine(ctx, values, viaNode, _fromPoint, _toPoint) {
33627 ctx.lineCap = "round";
33628 var pattern = Array.isArray(values.dashes) ? values.dashes : [5, 5]; // only firefox and chrome support this method, else we use the legacy one.
33629
33630 if (ctx.setLineDash !== undefined) {
33631 ctx.save(); // set dash settings for chrome or firefox
33632
33633 ctx.setLineDash(pattern);
33634 ctx.lineDashOffset = 0; // draw the line
33635
33636 if (this.from != this.to) {
33637 // draw line
33638 this._line(ctx, values, viaNode);
33639 } else {
33640 var _this$_getCircleData3 = this._getCircleData(ctx),
33641 _this$_getCircleData4 = _slicedToArray(_this$_getCircleData3, 3),
33642 x = _this$_getCircleData4[0],
33643 y = _this$_getCircleData4[1],
33644 radius = _this$_getCircleData4[2];
33645
33646 this._circle(ctx, values, x, y, radius);
33647 } // restore the dash settings.
33648
33649
33650 ctx.setLineDash([0]);
33651 ctx.lineDashOffset = 0;
33652 ctx.restore();
33653 } else {
33654 // unsupporting smooth lines
33655 if (this.from != this.to) {
33656 // draw line
33657 ctx.dashedLine(this.from.x, this.from.y, this.to.x, this.to.y, pattern);
33658 } else {
33659 var _this$_getCircleData5 = this._getCircleData(ctx),
33660 _this$_getCircleData6 = _slicedToArray(_this$_getCircleData5, 3),
33661 _x = _this$_getCircleData6[0],
33662 _y = _this$_getCircleData6[1],
33663 _radius = _this$_getCircleData6[2];
33664
33665 this._circle(ctx, values, _x, _y, _radius);
33666 } // draw shadow if enabled
33667
33668
33669 this.enableShadow(ctx, values);
33670 ctx.stroke(); // disable shadows for other elements.
33671
33672 this.disableShadow(ctx, values);
33673 }
33674 }
33675 /**
33676 * Find the intersection between the border of the node and the edge.
33677 *
33678 * @param node - The node (either from or to node of the edge).
33679 * @param ctx - The context that will be used for rendering.
33680 * @param options - Additional options.
33681 *
33682 * @returns Cartesian coordinates of the intersection between the border of the node and the edge.
33683 */
33684
33685 }, {
33686 key: "findBorderPosition",
33687 value: function findBorderPosition(node, ctx, options) {
33688 if (this.from != this.to) {
33689 return this._findBorderPosition(node, ctx, options);
33690 } else {
33691 return this._findBorderPositionCircle(node, ctx, options);
33692 }
33693 }
33694 /** @inheritdoc */
33695
33696 }, {
33697 key: "findBorderPositions",
33698 value: function findBorderPositions(ctx) {
33699 if (this.from != this.to) {
33700 return {
33701 from: this._findBorderPosition(this.from, ctx),
33702 to: this._findBorderPosition(this.to, ctx)
33703 };
33704 } else {
33705 var _this$_getCircleData$ = this._getCircleData(ctx).slice(0, 2),
33706 _this$_getCircleData$2 = _slicedToArray(_this$_getCircleData$, 2),
33707 x = _this$_getCircleData$2[0],
33708 y = _this$_getCircleData$2[1];
33709
33710 return {
33711 from: this._findBorderPositionCircle(this.from, ctx, {
33712 x: x,
33713 y: y,
33714 low: 0.25,
33715 high: 0.6,
33716 direction: -1
33717 }),
33718 to: this._findBorderPositionCircle(this.from, ctx, {
33719 x: x,
33720 y: y,
33721 low: 0.6,
33722 high: 0.8,
33723 direction: 1
33724 })
33725 };
33726 }
33727 }
33728 /**
33729 * Compute the center point and radius of an edge connected to the same node at both ends.
33730 *
33731 * @param ctx - The context that will be used for rendering.
33732 *
33733 * @returns `[x, y, radius]`
33734 */
33735
33736 }, {
33737 key: "_getCircleData",
33738 value: function _getCircleData(ctx) {
33739 var x;
33740 var y;
33741 var node = this.from;
33742 var radius = this.options.selfReferenceSize;
33743
33744 if (ctx !== undefined) {
33745 if (node.shape.width === undefined) {
33746 node.shape.resize(ctx);
33747 }
33748 } // get circle coordinates
33749
33750
33751 if (node.shape.width > node.shape.height) {
33752 x = node.x + node.shape.width * 0.5;
33753 y = node.y - radius;
33754 } else {
33755 x = node.x + radius;
33756 y = node.y - node.shape.height * 0.5;
33757 }
33758
33759 return [x, y, radius];
33760 }
33761 /**
33762 * Get a point on a circle.
33763 *
33764 * @param x - Center of the circle on the x axis.
33765 * @param y - Center of the circle on the y axis.
33766 * @param radius - Radius of the circle.
33767 * @param position - Value between 0 (line start) and 1 (line end).
33768 *
33769 * @returns Cartesian coordinates of requested point on the circle.
33770 */
33771
33772 }, {
33773 key: "_pointOnCircle",
33774 value: function _pointOnCircle(x, y, radius, position) {
33775 var angle = position * 2 * Math.PI;
33776 return {
33777 x: x + radius * Math.cos(angle),
33778 y: y - radius * Math.sin(angle)
33779 };
33780 }
33781 /**
33782 * Find the intersection between the border of the node and the edge.
33783 *
33784 * @remarks
33785 * This function uses binary search to look for the point where the circle crosses the border of the node.
33786 *
33787 * @param nearNode - The node (either from or to node of the edge).
33788 * @param ctx - The context that will be used for rendering.
33789 * @param options - Additional options.
33790 *
33791 * @returns Cartesian coordinates of the intersection between the border of the node and the edge.
33792 */
33793
33794 }, {
33795 key: "_findBorderPositionCircle",
33796 value: function _findBorderPositionCircle(nearNode, ctx, options) {
33797 var x = options.x;
33798 var y = options.y;
33799 var low = options.low;
33800 var high = options.high;
33801 var direction = options.direction;
33802 var maxIterations = 10;
33803 var radius = this.options.selfReferenceSize;
33804 var threshold = 0.05;
33805 var pos;
33806 var middle = (low + high) * 0.5;
33807 var iteration = 0;
33808
33809 do {
33810 middle = (low + high) * 0.5;
33811 pos = this._pointOnCircle(x, y, radius, middle);
33812 var angle = Math.atan2(nearNode.y - pos.y, nearNode.x - pos.x);
33813 var distanceToBorder = nearNode.distanceToBorder(ctx, angle);
33814 var distanceToPoint = Math.sqrt(Math.pow(pos.x - nearNode.x, 2) + Math.pow(pos.y - nearNode.y, 2));
33815 var difference = distanceToBorder - distanceToPoint;
33816
33817 if (Math.abs(difference) < threshold) {
33818 break; // found
33819 } else if (difference > 0) {
33820 // distance to nodes is larger than distance to border --> t needs to be bigger if we're looking at the to node.
33821 if (direction > 0) {
33822 low = middle;
33823 } else {
33824 high = middle;
33825 }
33826 } else {
33827 if (direction > 0) {
33828 high = middle;
33829 } else {
33830 low = middle;
33831 }
33832 }
33833
33834 ++iteration;
33835 } while (low <= high && iteration < maxIterations);
33836
33837 return _objectSpread2$1({}, pos, {
33838 t: middle
33839 });
33840 }
33841 /**
33842 * Get the line width of the edge. Depends on width and whether one of the connected nodes is selected.
33843 *
33844 * @param selected - Determines wheter the line is selected.
33845 * @param hover - Determines wheter the line is being hovered, only applies if selected is false.
33846 *
33847 * @returns The width of the line.
33848 */
33849
33850 }, {
33851 key: "getLineWidth",
33852 value: function getLineWidth(selected, hover) {
33853 if (selected === true) {
33854 return Math.max(this.selectionWidth, 0.3 / this._body.view.scale);
33855 } else if (hover === true) {
33856 return Math.max(this.hoverWidth, 0.3 / this._body.view.scale);
33857 } else {
33858 return Math.max(this.options.width, 0.3 / this._body.view.scale);
33859 }
33860 }
33861 /**
33862 * Compute the color or gradient for given edge.
33863 *
33864 * @param ctx - The context that will be used for rendering.
33865 * @param values - Formatting values like color, opacity or shadow.
33866 * @param _selected - Ignored (TODO: remove in the future).
33867 * @param _hover - Ignored (TODO: remove in the future).
33868 *
33869 * @returns Color string if single color is inherited or gradient if two.
33870 */
33871
33872 }, {
33873 key: "getColor",
33874 value: function getColor(ctx, values) {
33875 if (values.inheritsColor !== false) {
33876 // when this is a loop edge, just use the 'from' method
33877 if (values.inheritsColor === "both" && this.from.id !== this.to.id) {
33878 var grd = ctx.createLinearGradient(this.from.x, this.from.y, this.to.x, this.to.y);
33879 var fromColor = this.from.options.color.highlight.border;
33880 var toColor = this.to.options.color.highlight.border;
33881
33882 if (this.from.selected === false && this.to.selected === false) {
33883 fromColor = overrideOpacity(this.from.options.color.border, values.opacity);
33884 toColor = overrideOpacity(this.to.options.color.border, values.opacity);
33885 } else if (this.from.selected === true && this.to.selected === false) {
33886 toColor = this.to.options.color.border;
33887 } else if (this.from.selected === false && this.to.selected === true) {
33888 fromColor = this.from.options.color.border;
33889 }
33890
33891 grd.addColorStop(0, fromColor);
33892 grd.addColorStop(1, toColor); // -------------------- this returns -------------------- //
33893
33894 return grd;
33895 }
33896
33897 if (values.inheritsColor === "to") {
33898 return overrideOpacity(this.to.options.color.border, values.opacity);
33899 } else {
33900 // "from"
33901 return overrideOpacity(this.from.options.color.border, values.opacity);
33902 }
33903 } else {
33904 return overrideOpacity(values.color, values.opacity);
33905 }
33906 }
33907 /**
33908 * Draw a line from a node to itself, a circle.
33909 *
33910 * @param ctx - The context that will be used for rendering.
33911 * @param values - Formatting values like color, opacity or shadow.
33912 * @param x - Center of the circle on the x axis.
33913 * @param y - Center of the circle on the y axis.
33914 * @param radius - Radius of the circle.
33915 */
33916
33917 }, {
33918 key: "_circle",
33919 value: function _circle(ctx, values, x, y, radius) {
33920 // draw shadow if enabled
33921 this.enableShadow(ctx, values); // draw a circle
33922
33923 ctx.beginPath();
33924 ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
33925 ctx.stroke(); // disable shadows for other elements.
33926
33927 this.disableShadow(ctx, values);
33928 }
33929 /**
33930 * @inheritdoc
33931 *
33932 * @remarks
33933 * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment
33934 */
33935
33936 }, {
33937 key: "getDistanceToEdge",
33938 value: function getDistanceToEdge(x1, y1, x2, y2, x3, y3) {
33939 if (this.from != this.to) {
33940 return this._getDistanceToEdge(x1, y1, x2, y2, x3, y3);
33941 } else {
33942 var _this$_getCircleData7 = this._getCircleData(undefined),
33943 _this$_getCircleData8 = _slicedToArray(_this$_getCircleData7, 3),
33944 x = _this$_getCircleData8[0],
33945 y = _this$_getCircleData8[1],
33946 radius = _this$_getCircleData8[2];
33947
33948 var dx = x - x3;
33949 var dy = y - y3;
33950 return Math.abs(Math.sqrt(dx * dx + dy * dy) - radius);
33951 }
33952 }
33953 /**
33954 * Calculate the distance between a point (x3, y3) and a line segment from (x1, y1) to (x2, y2).
33955 *
33956 * @param x1 - First end of the line segment on the x axis.
33957 * @param y1 - First end of the line segment on the y axis.
33958 * @param x2 - Second end of the line segment on the x axis.
33959 * @param y2 - Second end of the line segment on the y axis.
33960 * @param x3 - Position of the point on the x axis.
33961 * @param y3 - Position of the point on the y axis.
33962 *
33963 * @returns The distance between the line segment and the point.
33964 */
33965
33966 }, {
33967 key: "_getDistanceToLine",
33968 value: function _getDistanceToLine(x1, y1, x2, y2, x3, y3) {
33969 var px = x2 - x1;
33970 var py = y2 - y1;
33971 var something = px * px + py * py;
33972 var u = ((x3 - x1) * px + (y3 - y1) * py) / something;
33973
33974 if (u > 1) {
33975 u = 1;
33976 } else if (u < 0) {
33977 u = 0;
33978 }
33979
33980 var x = x1 + u * px;
33981 var y = y1 + u * py;
33982 var dx = x - x3;
33983 var dy = y - y3; //# Note: If the actual distance does not matter,
33984 //# if you only want to compare what this function
33985 //# returns to other results of this function, you
33986 //# can just return the squared distance instead
33987 //# (i.e. remove the sqrt) to gain a little performance
33988
33989 return Math.sqrt(dx * dx + dy * dy);
33990 }
33991 /** @inheritdoc */
33992
33993 }, {
33994 key: "getArrowData",
33995 value: function getArrowData(ctx, position, viaNode, _selected, _hover, values) {
33996 // set lets
33997 var angle;
33998 var arrowPoint;
33999 var node1;
34000 var node2;
34001 var reversed;
34002 var scaleFactor;
34003 var type;
34004 var lineWidth = values.width;
34005
34006 if (position === "from") {
34007 node1 = this.from;
34008 node2 = this.to;
34009 reversed = values.fromArrowScale < 0;
34010 scaleFactor = Math.abs(values.fromArrowScale);
34011 type = values.fromArrowType;
34012 } else if (position === "to") {
34013 node1 = this.to;
34014 node2 = this.from;
34015 reversed = values.toArrowScale < 0;
34016 scaleFactor = Math.abs(values.toArrowScale);
34017 type = values.toArrowType;
34018 } else {
34019 node1 = this.to;
34020 node2 = this.from;
34021 reversed = values.middleArrowScale < 0;
34022 scaleFactor = Math.abs(values.middleArrowScale);
34023 type = values.middleArrowType;
34024 }
34025
34026 var length = 15 * scaleFactor + 3 * lineWidth; // 3* lineWidth is the width of the edge.
34027 // if not connected to itself
34028
34029 if (node1 != node2) {
34030 var approximateEdgeLength = Math.hypot(node1.x - node2.x, node1.y - node2.y);
34031 var relativeLength = length / approximateEdgeLength;
34032
34033 if (position !== "middle") {
34034 // draw arrow head
34035 if (this.options.smooth.enabled === true) {
34036 var pointT = this._findBorderPosition(node1, ctx, {
34037 via: viaNode
34038 });
34039
34040 var guidePos = this.getPoint(pointT.t + relativeLength * (position === "from" ? 1 : -1), viaNode);
34041 angle = Math.atan2(pointT.y - guidePos.y, pointT.x - guidePos.x);
34042 arrowPoint = pointT;
34043 } else {
34044 angle = Math.atan2(node1.y - node2.y, node1.x - node2.x);
34045 arrowPoint = this._findBorderPosition(node1, ctx);
34046 }
34047 } else {
34048 // Negative half length reverses arrow direction.
34049 var halfLength = (reversed ? -relativeLength : relativeLength) / 2;
34050 var guidePos1 = this.getPoint(0.5 + halfLength, viaNode);
34051 var guidePos2 = this.getPoint(0.5 - halfLength, viaNode);
34052 angle = Math.atan2(guidePos1.y - guidePos2.y, guidePos1.x - guidePos2.x);
34053 arrowPoint = this.getPoint(0.5, viaNode);
34054 }
34055 } else {
34056 // draw circle
34057 var _this$_getCircleData9 = this._getCircleData(ctx),
34058 _this$_getCircleData10 = _slicedToArray(_this$_getCircleData9, 3),
34059 x = _this$_getCircleData10[0],
34060 y = _this$_getCircleData10[1],
34061 radius = _this$_getCircleData10[2];
34062
34063 if (position === "from") {
34064 var _pointT = this._findBorderPositionCircle(this.from, ctx, {
34065 x: x,
34066 y: y,
34067 low: 0.25,
34068 high: 0.6,
34069 direction: -1
34070 });
34071
34072 angle = _pointT.t * -2 * Math.PI + 1.5 * Math.PI + 0.1 * Math.PI;
34073 arrowPoint = _pointT;
34074 } else if (position === "to") {
34075 var _pointT2 = this._findBorderPositionCircle(this.from, ctx, {
34076 x: x,
34077 y: y,
34078 low: 0.6,
34079 high: 1.0,
34080 direction: 1
34081 });
34082
34083 angle = _pointT2.t * -2 * Math.PI + 1.5 * Math.PI - 1.1 * Math.PI;
34084 arrowPoint = _pointT2;
34085 } else {
34086 arrowPoint = this._pointOnCircle(x, y, radius, 0.175);
34087 angle = 3.9269908169872414; // === 0.175 * -2 * Math.PI + 1.5 * Math.PI + 0.1 * Math.PI;
34088 }
34089 }
34090
34091 var xi = arrowPoint.x - length * 0.9 * Math.cos(angle);
34092 var yi = arrowPoint.y - length * 0.9 * Math.sin(angle);
34093 var arrowCore = {
34094 x: xi,
34095 y: yi
34096 };
34097 return {
34098 point: arrowPoint,
34099 core: arrowCore,
34100 angle: angle,
34101 length: length,
34102 type: type
34103 };
34104 }
34105 /** @inheritdoc */
34106
34107 }, {
34108 key: "drawArrowHead",
34109 value: function drawArrowHead(ctx, values, _selected, _hover, arrowData) {
34110 // set style
34111 ctx.strokeStyle = this.getColor(ctx, values);
34112 ctx.fillStyle = ctx.strokeStyle;
34113 ctx.lineWidth = values.width;
34114 var canFill = EndPoints.draw(ctx, arrowData);
34115
34116 if (canFill) {
34117 // draw shadow if enabled
34118 this.enableShadow(ctx, values);
34119 ctx.fill(); // disable shadows for other elements.
34120
34121 this.disableShadow(ctx, values);
34122 }
34123 }
34124 /**
34125 * Set the shadow formatting values in the context if enabled, do nothing otherwise.
34126 *
34127 * @param ctx - The context that will be used for rendering.
34128 * @param values - Formatting values for the shadow.
34129 */
34130
34131 }, {
34132 key: "enableShadow",
34133 value: function enableShadow(ctx, values) {
34134 if (values.shadow === true) {
34135 ctx.shadowColor = values.shadowColor;
34136 ctx.shadowBlur = values.shadowSize;
34137 ctx.shadowOffsetX = values.shadowX;
34138 ctx.shadowOffsetY = values.shadowY;
34139 }
34140 }
34141 /**
34142 * Reset the shadow formatting values in the context if enabled, do nothing otherwise.
34143 *
34144 * @param ctx - The context that will be used for rendering.
34145 * @param values - Formatting values for the shadow.
34146 */
34147
34148 }, {
34149 key: "disableShadow",
34150 value: function disableShadow(ctx, values) {
34151 if (values.shadow === true) {
34152 ctx.shadowColor = "rgba(0,0,0,0)";
34153 ctx.shadowBlur = 0;
34154 ctx.shadowOffsetX = 0;
34155 ctx.shadowOffsetY = 0;
34156 }
34157 }
34158 /**
34159 * Render the background according to the formatting values.
34160 *
34161 * @param ctx - The context that will be used for rendering.
34162 * @param values - Formatting values for the background.
34163 */
34164
34165 }, {
34166 key: "drawBackground",
34167 value: function drawBackground(ctx, values) {
34168 if (values.background !== false) {
34169 // save original line attrs
34170 var origCtxAttr = {
34171 strokeStyle: ctx.strokeStyle,
34172 lineWidth: ctx.lineWidth,
34173 dashes: ctx.dashes
34174 };
34175 ctx.strokeStyle = values.backgroundColor;
34176 ctx.lineWidth = values.backgroundSize;
34177 this.setStrokeDashed(ctx, values.backgroundDashes);
34178 ctx.stroke(); // restore original line attrs
34179
34180 ctx.strokeStyle = origCtxAttr.strokeStyle;
34181 ctx.lineWidth = origCtxAttr.lineWidth;
34182 ctx.dashes = origCtxAttr.dashes;
34183 this.setStrokeDashed(ctx, values.dashes);
34184 }
34185 }
34186 /**
34187 * Set the line dash pattern if supported. Logs a warning to the console if it isn't supported.
34188 *
34189 * @param ctx - The context that will be used for rendering.
34190 * @param dashes - The pattern [line, space, line…], true for default dashed line or false for normal line.
34191 */
34192
34193 }, {
34194 key: "setStrokeDashed",
34195 value: function setStrokeDashed(ctx, dashes) {
34196 if (dashes !== false) {
34197 if (ctx.setLineDash !== undefined) {
34198 var pattern = Array.isArray(dashes) ? dashes : [5, 5];
34199 ctx.setLineDash(pattern);
34200 } else {
34201 console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.");
34202 }
34203 } else {
34204 if (ctx.setLineDash !== undefined) {
34205 ctx.setLineDash([]);
34206 } else {
34207 console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.");
34208 }
34209 }
34210 }
34211 }]);
34212
34213 return EdgeBase;
34214}();
34215
34216/**
34217 * The Base Class for all Bezier edges.
34218 * Bezier curves are used to model smooth gradual curves in paths between nodes.
34219 */
34220
34221var BezierEdgeBase =
34222/*#__PURE__*/
34223function (_EdgeBase) {
34224 _inherits(BezierEdgeBase, _EdgeBase);
34225
34226 /**
34227 * Create a new instance.
34228 *
34229 * @param options - The options object of given edge.
34230 * @param body - The body of the network.
34231 * @param labelModule - Label module.
34232 */
34233 function BezierEdgeBase(options, body, labelModule) {
34234 _classCallCheck(this, BezierEdgeBase);
34235
34236 return _possibleConstructorReturn(this, _getPrototypeOf(BezierEdgeBase).call(this, options, body, labelModule));
34237 }
34238 /**
34239 * Find the intersection between the border of the node and the edge.
34240 *
34241 * @remarks
34242 * This function uses binary search to look for the point where the bezier curve crosses the border of the node.
34243 *
34244 * @param nearNode - The node (either from or to node of the edge).
34245 * @param ctx - The context that will be used for rendering.
34246 * @param viaNode - Additional node(s) the edge passes through.
34247 *
34248 * @returns Cartesian coordinates of the intersection between the border of the node and the edge.
34249 */
34250
34251
34252 _createClass(BezierEdgeBase, [{
34253 key: "_findBorderPositionBezier",
34254 value: function _findBorderPositionBezier(nearNode, ctx) {
34255 var viaNode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this._getViaCoordinates();
34256 var maxIterations = 10;
34257 var threshold = 0.2;
34258 var from = false;
34259 var high = 1;
34260 var low = 0;
34261 var node = this.to;
34262 var pos;
34263 var middle;
34264
34265 if (nearNode.id === this.from.id) {
34266 node = this.from;
34267 from = true;
34268 }
34269
34270 var iteration = 0;
34271
34272 do {
34273 middle = (low + high) * 0.5;
34274 pos = this.getPoint(middle, viaNode);
34275 var angle = Math.atan2(node.y - pos.y, node.x - pos.x);
34276 var distanceToBorder = node.distanceToBorder(ctx, angle);
34277 var distanceToPoint = Math.sqrt(Math.pow(pos.x - node.x, 2) + Math.pow(pos.y - node.y, 2));
34278 var difference = distanceToBorder - distanceToPoint;
34279
34280 if (Math.abs(difference) < threshold) {
34281 break; // found
34282 } else if (difference < 0) {
34283 // distance to nodes is larger than distance to border --> t needs to be bigger if we're looking at the to node.
34284 if (from === false) {
34285 low = middle;
34286 } else {
34287 high = middle;
34288 }
34289 } else {
34290 if (from === false) {
34291 high = middle;
34292 } else {
34293 low = middle;
34294 }
34295 }
34296
34297 ++iteration;
34298 } while (low <= high && iteration < maxIterations);
34299
34300 return _objectSpread2$1({}, pos, {
34301 t: middle
34302 });
34303 }
34304 /**
34305 * Calculate the distance between a point (x3,y3) and a line segment from (x1,y1) to (x2,y2).
34306 *
34307 * @remarks
34308 * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment
34309 *
34310 * @param x1 - First end of the line segment on the x axis.
34311 * @param y1 - First end of the line segment on the y axis.
34312 * @param x2 - Second end of the line segment on the x axis.
34313 * @param y2 - Second end of the line segment on the y axis.
34314 * @param x3 - Position of the point on the x axis.
34315 * @param y3 - Position of the point on the y axis.
34316 * @param via - The control point for the edge.
34317 *
34318 * @returns The distance between the line segment and the point.
34319 */
34320
34321 }, {
34322 key: "_getDistanceToBezierEdge",
34323 value: function _getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via) {
34324 // x3,y3 is the point
34325 var minDistance = 1e9;
34326 var distance;
34327 var i, t, x, y;
34328 var lastX = x1;
34329 var lastY = y1;
34330
34331 for (i = 1; i < 10; i++) {
34332 t = 0.1 * i;
34333 x = Math.pow(1 - t, 2) * x1 + 2 * t * (1 - t) * via.x + Math.pow(t, 2) * x2;
34334 y = Math.pow(1 - t, 2) * y1 + 2 * t * (1 - t) * via.y + Math.pow(t, 2) * y2;
34335
34336 if (i > 0) {
34337 distance = this._getDistanceToLine(lastX, lastY, x, y, x3, y3);
34338 minDistance = distance < minDistance ? distance : minDistance;
34339 }
34340
34341 lastX = x;
34342 lastY = y;
34343 }
34344
34345 return minDistance;
34346 }
34347 /**
34348 * Render a bezier curve between two nodes.
34349 *
34350 * @remarks
34351 * The method accepts zero, one or two control points.
34352 * Passing zero control points just draws a straight line.
34353 *
34354 * @param ctx - The context that will be used for rendering.
34355 * @param values - Style options for edge drawing.
34356 * @param viaNode1 - First control point for curve drawing.
34357 * @param viaNode2 - Second control point for curve drawing.
34358 */
34359
34360 }, {
34361 key: "_bezierCurve",
34362 value: function _bezierCurve(ctx, values, viaNode1, viaNode2) {
34363 ctx.beginPath();
34364 ctx.moveTo(this.fromPoint.x, this.fromPoint.y);
34365
34366 if (viaNode1 != null && viaNode1.x != null) {
34367 if (viaNode2 != null && viaNode2.x != null) {
34368 ctx.bezierCurveTo(viaNode1.x, viaNode1.y, viaNode2.x, viaNode2.y, this.toPoint.x, this.toPoint.y);
34369 } else {
34370 ctx.quadraticCurveTo(viaNode1.x, viaNode1.y, this.toPoint.x, this.toPoint.y);
34371 }
34372 } else {
34373 // fallback to normal straight edge
34374 ctx.lineTo(this.toPoint.x, this.toPoint.y);
34375 } // draw a background
34376
34377
34378 this.drawBackground(ctx, values); // draw shadow if enabled
34379
34380 this.enableShadow(ctx, values);
34381 ctx.stroke();
34382 this.disableShadow(ctx, values);
34383 }
34384 /** @inheritdoc */
34385
34386 }, {
34387 key: "getViaNode",
34388 value: function getViaNode() {
34389 return this._getViaCoordinates();
34390 }
34391 }]);
34392
34393 return BezierEdgeBase;
34394}(EdgeBase);
34395
34396/**
34397 * A Dynamic Bezier Edge. Bezier curves are used to model smooth gradual
34398 * curves in paths between nodes. The Dynamic piece refers to how the curve
34399 * reacts to physics changes.
34400 *
34401 * @extends BezierEdgeBase
34402 */
34403
34404var BezierEdgeDynamic =
34405/*#__PURE__*/
34406function (_BezierEdgeBase) {
34407 _inherits(BezierEdgeDynamic, _BezierEdgeBase);
34408
34409 /**
34410 * Create a new instance.
34411 *
34412 * @param options - The options object of given edge.
34413 * @param body - The body of the network.
34414 * @param labelModule - Label module.
34415 */
34416 function BezierEdgeDynamic(options, body, labelModule) {
34417 var _this;
34418
34419 _classCallCheck(this, BezierEdgeDynamic);
34420
34421 //this.via = undefined; // Here for completeness but not allowed to defined before super() is invoked.
34422 _this = _possibleConstructorReturn(this, _getPrototypeOf(BezierEdgeDynamic).call(this, options, body, labelModule)); // --> this calls the setOptions below
34423
34424 _this.via = _this.via; // constructor → super → super → setOptions → setupSupportNode
34425
34426 _this._boundFunction = function () {
34427 _this.positionBezierNode();
34428 };
34429
34430 _this._body.emitter.on("_repositionBezierNodes", _this._boundFunction);
34431
34432 return _this;
34433 }
34434 /** @inheritdoc */
34435
34436
34437 _createClass(BezierEdgeDynamic, [{
34438 key: "setOptions",
34439 value: function setOptions(options) {
34440 _get(_getPrototypeOf(BezierEdgeDynamic.prototype), "setOptions", this).call(this, options); // check if the physics has changed.
34441
34442
34443 var physicsChange = false;
34444
34445 if (this.options.physics !== options.physics) {
34446 physicsChange = true;
34447 } // set the options and the to and from nodes
34448
34449
34450 this.options = options;
34451 this.id = this.options.id;
34452 this.from = this._body.nodes[this.options.from];
34453 this.to = this._body.nodes[this.options.to]; // setup the support node and connect
34454
34455 this.setupSupportNode();
34456 this.connect(); // when we change the physics state of the edge, we reposition the support node.
34457
34458 if (physicsChange === true) {
34459 this.via.setOptions({
34460 physics: this.options.physics
34461 });
34462 this.positionBezierNode();
34463 }
34464 }
34465 /** @inheritdoc */
34466
34467 }, {
34468 key: "connect",
34469 value: function connect() {
34470 this.from = this._body.nodes[this.options.from];
34471 this.to = this._body.nodes[this.options.to];
34472
34473 if (this.from === undefined || this.to === undefined || this.options.physics === false) {
34474 this.via.setOptions({
34475 physics: false
34476 });
34477 } else {
34478 // fix weird behaviour where a self referencing node has physics enabled
34479 if (this.from.id === this.to.id) {
34480 this.via.setOptions({
34481 physics: false
34482 });
34483 } else {
34484 this.via.setOptions({
34485 physics: true
34486 });
34487 }
34488 }
34489 }
34490 /** @inheritdoc */
34491
34492 }, {
34493 key: "cleanup",
34494 value: function cleanup() {
34495 this._body.emitter.off("_repositionBezierNodes", this._boundFunction);
34496
34497 if (this.via !== undefined) {
34498 delete this._body.nodes[this.via.id];
34499 this.via = undefined;
34500 return true;
34501 }
34502
34503 return false;
34504 }
34505 /**
34506 * Create and add a support node if not already present.
34507 *
34508 * @remarks
34509 * Bezier curves require an anchor point to calculate the smooth flow.
34510 * These points are nodes.
34511 * These nodes are invisible but are used for the force calculation.
34512 *
34513 * The changed data is not called, if needed, it is returned by the main edge constructor.
34514 */
34515
34516 }, {
34517 key: "setupSupportNode",
34518 value: function setupSupportNode() {
34519 if (this.via === undefined) {
34520 var nodeId = "edgeId:" + this.id;
34521
34522 var node = this._body.functions.createNode({
34523 id: nodeId,
34524 shape: "circle",
34525 physics: true,
34526 hidden: true
34527 });
34528
34529 this._body.nodes[nodeId] = node;
34530 this.via = node;
34531 this.via.parentEdgeId = this.id;
34532 this.positionBezierNode();
34533 }
34534 }
34535 /**
34536 * Position bezier node.
34537 */
34538
34539 }, {
34540 key: "positionBezierNode",
34541 value: function positionBezierNode() {
34542 if (this.via !== undefined && this.from !== undefined && this.to !== undefined) {
34543 this.via.x = 0.5 * (this.from.x + this.to.x);
34544 this.via.y = 0.5 * (this.from.y + this.to.y);
34545 } else if (this.via !== undefined) {
34546 this.via.x = 0;
34547 this.via.y = 0;
34548 }
34549 }
34550 /** @inheritdoc */
34551
34552 }, {
34553 key: "_line",
34554 value: function _line(ctx, values, viaNode) {
34555 this._bezierCurve(ctx, values, viaNode);
34556 }
34557 /** @inheritdoc */
34558
34559 }, {
34560 key: "_getViaCoordinates",
34561 value: function _getViaCoordinates() {
34562 return this.via;
34563 }
34564 /** @inheritdoc */
34565
34566 }, {
34567 key: "getViaNode",
34568 value: function getViaNode() {
34569 return this.via;
34570 }
34571 /** @inheritdoc */
34572
34573 }, {
34574 key: "getPoint",
34575 value: function getPoint(position) {
34576 var viaNode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.via;
34577
34578 if (this.from === this.to) {
34579 var _this$_getCircleData = this._getCircleData(),
34580 _this$_getCircleData2 = _slicedToArray(_this$_getCircleData, 3),
34581 cx = _this$_getCircleData2[0],
34582 cy = _this$_getCircleData2[1],
34583 cr = _this$_getCircleData2[2];
34584
34585 var a = 2 * Math.PI * (1 - position);
34586 return {
34587 x: cx + cr * Math.sin(a),
34588 y: cy + cr - cr * (1 - Math.cos(a))
34589 };
34590 } else {
34591 return {
34592 x: Math.pow(1 - position, 2) * this.fromPoint.x + 2 * position * (1 - position) * viaNode.x + Math.pow(position, 2) * this.toPoint.x,
34593 y: Math.pow(1 - position, 2) * this.fromPoint.y + 2 * position * (1 - position) * viaNode.y + Math.pow(position, 2) * this.toPoint.y
34594 };
34595 }
34596 }
34597 /** @inheritdoc */
34598
34599 }, {
34600 key: "_findBorderPosition",
34601 value: function _findBorderPosition(nearNode, ctx) {
34602 return this._findBorderPositionBezier(nearNode, ctx, this.via);
34603 }
34604 /** @inheritdoc */
34605
34606 }, {
34607 key: "_getDistanceToEdge",
34608 value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) {
34609 // x3,y3 is the point
34610 return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, this.via);
34611 }
34612 }]);
34613
34614 return BezierEdgeDynamic;
34615}(BezierEdgeBase);
34616
34617/**
34618 * A Static Bezier Edge. Bezier curves are used to model smooth gradual curves in paths between nodes.
34619 */
34620
34621var BezierEdgeStatic =
34622/*#__PURE__*/
34623function (_BezierEdgeBase) {
34624 _inherits(BezierEdgeStatic, _BezierEdgeBase);
34625
34626 /**
34627 * Create a new instance.
34628 *
34629 * @param options - The options object of given edge.
34630 * @param body - The body of the network.
34631 * @param labelModule - Label module.
34632 */
34633 function BezierEdgeStatic(options, body, labelModule) {
34634 _classCallCheck(this, BezierEdgeStatic);
34635
34636 return _possibleConstructorReturn(this, _getPrototypeOf(BezierEdgeStatic).call(this, options, body, labelModule));
34637 }
34638 /** @inheritdoc */
34639
34640
34641 _createClass(BezierEdgeStatic, [{
34642 key: "_line",
34643 value: function _line(ctx, values, viaNode) {
34644 this._bezierCurve(ctx, values, viaNode);
34645 }
34646 /** @inheritdoc */
34647
34648 }, {
34649 key: "getViaNode",
34650 value: function getViaNode() {
34651 return this._getViaCoordinates();
34652 }
34653 /**
34654 * Compute the coordinates of the via node.
34655 *
34656 * @remarks
34657 * We do not use the to and fromPoints here to make the via nodes the same as edges without arrows.
34658 *
34659 * @returns Cartesian coordinates of the via node.
34660 */
34661
34662 }, {
34663 key: "_getViaCoordinates",
34664 value: function _getViaCoordinates() {
34665 // Assumption: x/y coordinates in from/to always defined
34666 var factor = this.options.smooth.roundness;
34667 var type = this.options.smooth.type;
34668 var dx = Math.abs(this.from.x - this.to.x);
34669 var dy = Math.abs(this.from.y - this.to.y);
34670
34671 if (type === "discrete" || type === "diagonalCross") {
34672 var stepX;
34673 var stepY;
34674
34675 if (dx <= dy) {
34676 stepX = stepY = factor * dy;
34677 } else {
34678 stepX = stepY = factor * dx;
34679 }
34680
34681 if (this.from.x > this.to.x) {
34682 stepX = -stepX;
34683 }
34684
34685 if (this.from.y >= this.to.y) {
34686 stepY = -stepY;
34687 }
34688
34689 var xVia = this.from.x + stepX;
34690 var yVia = this.from.y + stepY;
34691
34692 if (type === "discrete") {
34693 if (dx <= dy) {
34694 xVia = dx < factor * dy ? this.from.x : xVia;
34695 } else {
34696 yVia = dy < factor * dx ? this.from.y : yVia;
34697 }
34698 }
34699
34700 return {
34701 x: xVia,
34702 y: yVia
34703 };
34704 } else if (type === "straightCross") {
34705 var _stepX = (1 - factor) * dx;
34706
34707 var _stepY = (1 - factor) * dy;
34708
34709 if (dx <= dy) {
34710 // up - down
34711 _stepX = 0;
34712
34713 if (this.from.y < this.to.y) {
34714 _stepY = -_stepY;
34715 }
34716 } else {
34717 // left - right
34718 if (this.from.x < this.to.x) {
34719 _stepX = -_stepX;
34720 }
34721
34722 _stepY = 0;
34723 }
34724
34725 return {
34726 x: this.to.x + _stepX,
34727 y: this.to.y + _stepY
34728 };
34729 } else if (type === "horizontal") {
34730 var _stepX2 = (1 - factor) * dx;
34731
34732 if (this.from.x < this.to.x) {
34733 _stepX2 = -_stepX2;
34734 }
34735
34736 return {
34737 x: this.to.x + _stepX2,
34738 y: this.from.y
34739 };
34740 } else if (type === "vertical") {
34741 var _stepY2 = (1 - factor) * dy;
34742
34743 if (this.from.y < this.to.y) {
34744 _stepY2 = -_stepY2;
34745 }
34746
34747 return {
34748 x: this.from.x,
34749 y: this.to.y + _stepY2
34750 };
34751 } else if (type === "curvedCW") {
34752 dx = this.to.x - this.from.x;
34753 dy = this.from.y - this.to.y;
34754 var radius = Math.sqrt(dx * dx + dy * dy);
34755 var pi = Math.PI;
34756 var originalAngle = Math.atan2(dy, dx);
34757 var myAngle = (originalAngle + (factor * 0.5 + 0.5) * pi) % (2 * pi);
34758 return {
34759 x: this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle),
34760 y: this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle)
34761 };
34762 } else if (type === "curvedCCW") {
34763 dx = this.to.x - this.from.x;
34764 dy = this.from.y - this.to.y;
34765
34766 var _radius = Math.sqrt(dx * dx + dy * dy);
34767
34768 var _pi = Math.PI;
34769
34770 var _originalAngle = Math.atan2(dy, dx);
34771
34772 var _myAngle = (_originalAngle + (-factor * 0.5 + 0.5) * _pi) % (2 * _pi);
34773
34774 return {
34775 x: this.from.x + (factor * 0.5 + 0.5) * _radius * Math.sin(_myAngle),
34776 y: this.from.y + (factor * 0.5 + 0.5) * _radius * Math.cos(_myAngle)
34777 };
34778 } else {
34779 // continuous
34780 var _stepX3;
34781
34782 var _stepY3;
34783
34784 if (dx <= dy) {
34785 _stepX3 = _stepY3 = factor * dy;
34786 } else {
34787 _stepX3 = _stepY3 = factor * dx;
34788 }
34789
34790 if (this.from.x > this.to.x) {
34791 _stepX3 = -_stepX3;
34792 }
34793
34794 if (this.from.y >= this.to.y) {
34795 _stepY3 = -_stepY3;
34796 }
34797
34798 var _xVia = this.from.x + _stepX3;
34799
34800 var _yVia = this.from.y + _stepY3;
34801
34802 if (dx <= dy) {
34803 if (this.from.x <= this.to.x) {
34804 _xVia = this.to.x < _xVia ? this.to.x : _xVia;
34805 } else {
34806 _xVia = this.to.x > _xVia ? this.to.x : _xVia;
34807 }
34808 } else {
34809 if (this.from.y >= this.to.y) {
34810 _yVia = this.to.y > _yVia ? this.to.y : _yVia;
34811 } else {
34812 _yVia = this.to.y < _yVia ? this.to.y : _yVia;
34813 }
34814 }
34815
34816 return {
34817 x: _xVia,
34818 y: _yVia
34819 };
34820 }
34821 }
34822 /** @inheritdoc */
34823
34824 }, {
34825 key: "_findBorderPosition",
34826 value: function _findBorderPosition(nearNode, ctx) {
34827 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
34828 return this._findBorderPositionBezier(nearNode, ctx, options.via);
34829 }
34830 /** @inheritdoc */
34831
34832 }, {
34833 key: "_getDistanceToEdge",
34834 value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) {
34835 var viaNode = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : this._getViaCoordinates();
34836 // x3,y3 is the point
34837 return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, viaNode);
34838 }
34839 /** @inheritdoc */
34840
34841 }, {
34842 key: "getPoint",
34843 value: function getPoint(position) {
34844 var viaNode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this._getViaCoordinates();
34845 var t = position;
34846 var x = Math.pow(1 - t, 2) * this.fromPoint.x + 2 * t * (1 - t) * viaNode.x + Math.pow(t, 2) * this.toPoint.x;
34847 var y = Math.pow(1 - t, 2) * this.fromPoint.y + 2 * t * (1 - t) * viaNode.y + Math.pow(t, 2) * this.toPoint.y;
34848 return {
34849 x: x,
34850 y: y
34851 };
34852 }
34853 }]);
34854
34855 return BezierEdgeStatic;
34856}(BezierEdgeBase);
34857
34858/**
34859 * A Base Class for all Cubic Bezier Edges. Bezier curves are used to model
34860 * smooth gradual curves in paths between nodes.
34861 *
34862 * @extends BezierEdgeBase
34863 */
34864
34865var CubicBezierEdgeBase =
34866/*#__PURE__*/
34867function (_BezierEdgeBase) {
34868 _inherits(CubicBezierEdgeBase, _BezierEdgeBase);
34869
34870 /**
34871 * Create a new instance.
34872 *
34873 * @param options - The options object of given edge.
34874 * @param body - The body of the network.
34875 * @param labelModule - Label module.
34876 */
34877 function CubicBezierEdgeBase(options, body, labelModule) {
34878 _classCallCheck(this, CubicBezierEdgeBase);
34879
34880 return _possibleConstructorReturn(this, _getPrototypeOf(CubicBezierEdgeBase).call(this, options, body, labelModule));
34881 }
34882 /**
34883 * Calculate the distance between a point (x3,y3) and a line segment from (x1,y1) to (x2,y2).
34884 *
34885 * @remarks
34886 * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment
34887 * https://en.wikipedia.org/wiki/B%C3%A9zier_curve
34888 *
34889 * @param x1 - First end of the line segment on the x axis.
34890 * @param y1 - First end of the line segment on the y axis.
34891 * @param x2 - Second end of the line segment on the x axis.
34892 * @param y2 - Second end of the line segment on the y axis.
34893 * @param x3 - Position of the point on the x axis.
34894 * @param y3 - Position of the point on the y axis.
34895 * @param via1 - The first point this edge passes through.
34896 * @param via2 - The second point this edge passes through.
34897 *
34898 * @returns The distance between the line segment and the point.
34899 */
34900
34901
34902 _createClass(CubicBezierEdgeBase, [{
34903 key: "_getDistanceToBezierEdge2",
34904 value: function _getDistanceToBezierEdge2(x1, y1, x2, y2, x3, y3, via1, via2) {
34905 // x3,y3 is the point
34906 var minDistance = 1e9;
34907 var lastX = x1;
34908 var lastY = y1;
34909 var vec = [0, 0, 0, 0];
34910
34911 for (var i = 1; i < 10; i++) {
34912 var t = 0.1 * i;
34913 vec[0] = Math.pow(1 - t, 3);
34914 vec[1] = 3 * t * Math.pow(1 - t, 2);
34915 vec[2] = 3 * Math.pow(t, 2) * (1 - t);
34916 vec[3] = Math.pow(t, 3);
34917 var x = vec[0] * x1 + vec[1] * via1.x + vec[2] * via2.x + vec[3] * x2;
34918 var y = vec[0] * y1 + vec[1] * via1.y + vec[2] * via2.y + vec[3] * y2;
34919
34920 if (i > 0) {
34921 var distance = this._getDistanceToLine(lastX, lastY, x, y, x3, y3);
34922
34923 minDistance = distance < minDistance ? distance : minDistance;
34924 }
34925
34926 lastX = x;
34927 lastY = y;
34928 }
34929
34930 return minDistance;
34931 }
34932 }]);
34933
34934 return CubicBezierEdgeBase;
34935}(BezierEdgeBase);
34936
34937/**
34938 * A Cubic Bezier Edge. Bezier curves are used to model smooth gradual curves in paths between nodes.
34939 */
34940
34941var CubicBezierEdge =
34942/*#__PURE__*/
34943function (_CubicBezierEdgeBase) {
34944 _inherits(CubicBezierEdge, _CubicBezierEdgeBase);
34945
34946 /**
34947 * Create a new instance.
34948 *
34949 * @param options - The options object of given edge.
34950 * @param body - The body of the network.
34951 * @param labelModule - Label module.
34952 */
34953 function CubicBezierEdge(options, body, labelModule) {
34954 _classCallCheck(this, CubicBezierEdge);
34955
34956 return _possibleConstructorReturn(this, _getPrototypeOf(CubicBezierEdge).call(this, options, body, labelModule));
34957 }
34958 /** @inheritdoc */
34959
34960
34961 _createClass(CubicBezierEdge, [{
34962 key: "_line",
34963 value: function _line(ctx, values, viaNodes) {
34964 // get the coordinates of the support points.
34965 var via1 = viaNodes[0];
34966 var via2 = viaNodes[1];
34967
34968 this._bezierCurve(ctx, values, via1, via2);
34969 }
34970 /**
34971 * Compute the additional points the edge passes through.
34972 *
34973 * @returns Cartesian coordinates of the points the edge passes through.
34974 */
34975
34976 }, {
34977 key: "_getViaCoordinates",
34978 value: function _getViaCoordinates() {
34979 var dx = this.from.x - this.to.x;
34980 var dy = this.from.y - this.to.y;
34981 var x1;
34982 var y1;
34983 var x2;
34984 var y2;
34985 var roundness = this.options.smooth.roundness; // horizontal if x > y or if direction is forced or if direction is horizontal
34986
34987 if ((Math.abs(dx) > Math.abs(dy) || this.options.smooth.forceDirection === true || this.options.smooth.forceDirection === "horizontal") && this.options.smooth.forceDirection !== "vertical") {
34988 y1 = this.from.y;
34989 y2 = this.to.y;
34990 x1 = this.from.x - roundness * dx;
34991 x2 = this.to.x + roundness * dx;
34992 } else {
34993 y1 = this.from.y - roundness * dy;
34994 y2 = this.to.y + roundness * dy;
34995 x1 = this.from.x;
34996 x2 = this.to.x;
34997 }
34998
34999 return [{
35000 x: x1,
35001 y: y1
35002 }, {
35003 x: x2,
35004 y: y2
35005 }];
35006 }
35007 /** @inheritdoc */
35008
35009 }, {
35010 key: "getViaNode",
35011 value: function getViaNode() {
35012 return this._getViaCoordinates();
35013 }
35014 /** @inheritdoc */
35015
35016 }, {
35017 key: "_findBorderPosition",
35018 value: function _findBorderPosition(nearNode, ctx) {
35019 return this._findBorderPositionBezier(nearNode, ctx);
35020 }
35021 /** @inheritdoc */
35022
35023 }, {
35024 key: "_getDistanceToEdge",
35025 value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) {
35026 var _ref = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : this._getViaCoordinates(),
35027 _ref2 = _slicedToArray(_ref, 2),
35028 via1 = _ref2[0],
35029 via2 = _ref2[1];
35030
35031 // x3,y3 is the point
35032 return this._getDistanceToBezierEdge2(x1, y1, x2, y2, x3, y3, via1, via2);
35033 }
35034 /** @inheritdoc */
35035
35036 }, {
35037 key: "getPoint",
35038 value: function getPoint(position) {
35039 var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this._getViaCoordinates(),
35040 _ref4 = _slicedToArray(_ref3, 2),
35041 via1 = _ref4[0],
35042 via2 = _ref4[1];
35043
35044 var t = position;
35045 var vec = [Math.pow(1 - t, 3), 3 * t * Math.pow(1 - t, 2), 3 * Math.pow(t, 2) * (1 - t), Math.pow(t, 3)];
35046 var x = vec[0] * this.fromPoint.x + vec[1] * via1.x + vec[2] * via2.x + vec[3] * this.toPoint.x;
35047 var y = vec[0] * this.fromPoint.y + vec[1] * via1.y + vec[2] * via2.y + vec[3] * this.toPoint.y;
35048 return {
35049 x: x,
35050 y: y
35051 };
35052 }
35053 }]);
35054
35055 return CubicBezierEdge;
35056}(CubicBezierEdgeBase);
35057
35058/**
35059 * A Straight Edge.
35060 */
35061
35062var StraightEdge =
35063/*#__PURE__*/
35064function (_EdgeBase) {
35065 _inherits(StraightEdge, _EdgeBase);
35066
35067 /**
35068 * Create a new instance.
35069 *
35070 * @param options - The options object of given edge.
35071 * @param body - The body of the network.
35072 * @param labelModule - Label module.
35073 */
35074 function StraightEdge(options, body, labelModule) {
35075 _classCallCheck(this, StraightEdge);
35076
35077 return _possibleConstructorReturn(this, _getPrototypeOf(StraightEdge).call(this, options, body, labelModule));
35078 }
35079 /** @inheritdoc */
35080
35081
35082 _createClass(StraightEdge, [{
35083 key: "_line",
35084 value: function _line(ctx, values) {
35085 // draw a straight line
35086 ctx.beginPath();
35087 ctx.moveTo(this.fromPoint.x, this.fromPoint.y);
35088 ctx.lineTo(this.toPoint.x, this.toPoint.y); // draw shadow if enabled
35089
35090 this.enableShadow(ctx, values);
35091 ctx.stroke();
35092 this.disableShadow(ctx, values);
35093 }
35094 /** @inheritdoc */
35095
35096 }, {
35097 key: "getViaNode",
35098 value: function getViaNode() {
35099 return undefined;
35100 }
35101 /** @inheritdoc */
35102
35103 }, {
35104 key: "getPoint",
35105 value: function getPoint(position) {
35106 return {
35107 x: (1 - position) * this.fromPoint.x + position * this.toPoint.x,
35108 y: (1 - position) * this.fromPoint.y + position * this.toPoint.y
35109 };
35110 }
35111 /** @inheritdoc */
35112
35113 }, {
35114 key: "_findBorderPosition",
35115 value: function _findBorderPosition(nearNode, ctx) {
35116 var node1 = this.to;
35117 var node2 = this.from;
35118
35119 if (nearNode.id === this.from.id) {
35120 node1 = this.from;
35121 node2 = this.to;
35122 }
35123
35124 var angle = Math.atan2(node1.y - node2.y, node1.x - node2.x);
35125 var dx = node1.x - node2.x;
35126 var dy = node1.y - node2.y;
35127 var edgeSegmentLength = Math.sqrt(dx * dx + dy * dy);
35128 var toBorderDist = nearNode.distanceToBorder(ctx, angle);
35129 var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength;
35130 return {
35131 x: (1 - toBorderPoint) * node2.x + toBorderPoint * node1.x,
35132 y: (1 - toBorderPoint) * node2.y + toBorderPoint * node1.y,
35133 t: 0
35134 };
35135 }
35136 /** @inheritdoc */
35137
35138 }, {
35139 key: "_getDistanceToEdge",
35140 value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) {
35141 // x3,y3 is the point
35142 return this._getDistanceToLine(x1, y1, x2, y2, x3, y3);
35143 }
35144 }]);
35145
35146 return StraightEdge;
35147}(EdgeBase);
35148
35149/**
35150 * An edge connects two nodes and has a specific direction.
35151 */
35152
35153var Edge =
35154/*#__PURE__*/
35155function () {
35156 /**
35157 * @param {Object} options values specific to this edge, must contain at least 'from' and 'to'
35158 * @param {Object} body shared state from Network instance
35159 * @param {Network.Images} imagelist A list with images. Only needed when the edge has image arrows.
35160 * @param {Object} globalOptions options from the EdgesHandler instance
35161 * @param {Object} defaultOptions default options from the EdgeHandler instance. Value and reference are constant
35162 */
35163 function Edge(options, body, imagelist, globalOptions, defaultOptions) {
35164 _classCallCheck(this, Edge);
35165
35166 if (body === undefined) {
35167 throw new Error("No body provided");
35168 } // Since globalOptions is constant in values as well as reference,
35169 // Following needs to be done only once.
35170
35171
35172 this.options = bridgeObject(globalOptions);
35173 this.globalOptions = globalOptions;
35174 this.defaultOptions = defaultOptions;
35175 this.body = body;
35176 this.imagelist = imagelist; // initialize variables
35177
35178 this.id = undefined;
35179 this.fromId = undefined;
35180 this.toId = undefined;
35181 this.selected = false;
35182 this.hover = false;
35183 this.labelDirty = true;
35184 this.baseWidth = this.options.width;
35185 this.baseFontSize = this.options.font.size;
35186 this.from = undefined; // a node
35187
35188 this.to = undefined; // a node
35189
35190 this.edgeType = undefined;
35191 this.connected = false;
35192 this.labelModule = new Label(this.body, this.options, true
35193 /* It's an edge label */
35194 );
35195 this.setOptions(options);
35196 }
35197 /**
35198 * Set or overwrite options for the edge
35199 * @param {Object} options an object with options
35200 * @returns {undefined|boolean} undefined if no options, true if layout affecting data changed, false otherwise.
35201 */
35202
35203
35204 _createClass(Edge, [{
35205 key: "setOptions",
35206 value: function setOptions(options) {
35207 if (!options) {
35208 return;
35209 } // Following options if changed affect the layout.
35210
35211
35212 var affectsLayout = typeof options.physics !== "undefined" && this.options.physics !== options.physics || typeof options.hidden !== "undefined" && (this.options.hidden || false) !== (options.hidden || false) || typeof options.from !== "undefined" && this.options.from !== options.from || typeof options.to !== "undefined" && this.options.to !== options.to;
35213 Edge.parseOptions(this.options, options, true, this.globalOptions);
35214
35215 if (options.id !== undefined) {
35216 this.id = options.id;
35217 }
35218
35219 if (options.from !== undefined) {
35220 this.fromId = options.from;
35221 }
35222
35223 if (options.to !== undefined) {
35224 this.toId = options.to;
35225 }
35226
35227 if (options.title !== undefined) {
35228 this.title = options.title;
35229 }
35230
35231 if (options.value !== undefined) {
35232 options.value = parseFloat(options.value);
35233 }
35234
35235 var pile = [options, this.options, this.defaultOptions];
35236 this.chooser = ComponentUtil.choosify('edge', pile); // update label Module
35237
35238 this.updateLabelModule(options); // Update edge type, this if changed affects the layout.
35239
35240 affectsLayout = this.updateEdgeType() || affectsLayout; // if anything has been updates, reset the selection width and the hover width
35241
35242 this._setInteractionWidths(); // A node is connected when it has a from and to node that both exist in the network.body.nodes.
35243
35244
35245 this.connect();
35246 return affectsLayout;
35247 }
35248 /**
35249 *
35250 * @param {Object} parentOptions
35251 * @param {Object} newOptions
35252 * @param {boolean} [allowDeletion=false]
35253 * @param {Object} [globalOptions={}]
35254 * @param {boolean} [copyFromGlobals=false]
35255 */
35256
35257 }, {
35258 key: "getFormattingValues",
35259
35260 /**
35261 *
35262 * @returns {ArrowOptions}
35263 */
35264 value: function getFormattingValues() {
35265 var toArrow = this.options.arrows.to === true || this.options.arrows.to.enabled === true;
35266 var fromArrow = this.options.arrows.from === true || this.options.arrows.from.enabled === true;
35267 var middleArrow = this.options.arrows.middle === true || this.options.arrows.middle.enabled === true;
35268 var inheritsColor = this.options.color.inherit;
35269 var values = {
35270 toArrow: toArrow,
35271 toArrowScale: this.options.arrows.to.scaleFactor,
35272 toArrowType: this.options.arrows.to.type,
35273 toArrowSrc: this.options.arrows.to.src,
35274 toArrowImageWidth: this.options.arrows.to.imageWidth,
35275 toArrowImageHeight: this.options.arrows.to.imageHeight,
35276 middleArrow: middleArrow,
35277 middleArrowScale: this.options.arrows.middle.scaleFactor,
35278 middleArrowType: this.options.arrows.middle.type,
35279 middleArrowSrc: this.options.arrows.middle.src,
35280 middleArrowImageWidth: this.options.arrows.middle.imageWidth,
35281 middleArrowImageHeight: this.options.arrows.middle.imageHeight,
35282 fromArrow: fromArrow,
35283 fromArrowScale: this.options.arrows.from.scaleFactor,
35284 fromArrowType: this.options.arrows.from.type,
35285 fromArrowSrc: this.options.arrows.from.src,
35286 fromArrowImageWidth: this.options.arrows.from.imageWidth,
35287 fromArrowImageHeight: this.options.arrows.from.imageHeight,
35288 arrowStrikethrough: this.options.arrowStrikethrough,
35289 color: inheritsColor ? undefined : this.options.color.color,
35290 inheritsColor: inheritsColor,
35291 opacity: this.options.color.opacity,
35292 hidden: this.options.hidden,
35293 length: this.options.length,
35294 shadow: this.options.shadow.enabled,
35295 shadowColor: this.options.shadow.color,
35296 shadowSize: this.options.shadow.size,
35297 shadowX: this.options.shadow.x,
35298 shadowY: this.options.shadow.y,
35299 dashes: this.options.dashes,
35300 width: this.options.width,
35301 background: this.options.background.enabled,
35302 backgroundColor: this.options.background.color,
35303 backgroundSize: this.options.background.size,
35304 backgroundDashes: this.options.background.dashes
35305 };
35306
35307 if (this.selected || this.hover) {
35308 if (this.chooser === true) {
35309 if (this.selected) {
35310 var selectedWidth = this.options.selectionWidth;
35311
35312 if (typeof selectedWidth === 'function') {
35313 values.width = selectedWidth(values.width);
35314 } else if (typeof selectedWidth === 'number') {
35315 values.width += selectedWidth;
35316 }
35317
35318 values.width = Math.max(values.width, 0.3 / this.body.view.scale);
35319 values.color = this.options.color.highlight;
35320 values.shadow = this.options.shadow.enabled;
35321 } else if (this.hover) {
35322 var hoverWidth = this.options.hoverWidth;
35323
35324 if (typeof hoverWidth === 'function') {
35325 values.width = hoverWidth(values.width);
35326 } else if (typeof hoverWidth === 'number') {
35327 values.width += hoverWidth;
35328 }
35329
35330 values.width = Math.max(values.width, 0.3 / this.body.view.scale);
35331 values.color = this.options.color.hover;
35332 values.shadow = this.options.shadow.enabled;
35333 }
35334 } else if (typeof this.chooser === 'function') {
35335 this.chooser(values, this.options.id, this.selected, this.hover);
35336
35337 if (values.color !== undefined) {
35338 values.inheritsColor = false;
35339 }
35340
35341 if (values.shadow === false) {
35342 if (values.shadowColor !== this.options.shadow.color || values.shadowSize !== this.options.shadow.size || values.shadowX !== this.options.shadow.x || values.shadowY !== this.options.shadow.y) {
35343 values.shadow = true;
35344 }
35345 }
35346 }
35347 } else {
35348 values.shadow = this.options.shadow.enabled;
35349 values.width = Math.max(values.width, 0.3 / this.body.view.scale);
35350 }
35351
35352 return values;
35353 }
35354 /**
35355 * update the options in the label module
35356 *
35357 * @param {Object} options
35358 */
35359
35360 }, {
35361 key: "updateLabelModule",
35362 value: function updateLabelModule(options) {
35363 var pile = [options, this.options, this.globalOptions, // Currently set global edge options
35364 this.defaultOptions];
35365 this.labelModule.update(this.options, pile);
35366
35367 if (this.labelModule.baseSize !== undefined) {
35368 this.baseFontSize = this.labelModule.baseSize;
35369 }
35370 }
35371 /**
35372 * update the edge type, set the options
35373 * @returns {boolean}
35374 */
35375
35376 }, {
35377 key: "updateEdgeType",
35378 value: function updateEdgeType() {
35379 var smooth = this.options.smooth;
35380 var dataChanged = false;
35381 var changeInType = true;
35382
35383 if (this.edgeType !== undefined) {
35384 if (this.edgeType instanceof BezierEdgeDynamic && smooth.enabled === true && smooth.type === 'dynamic' || this.edgeType instanceof CubicBezierEdge && smooth.enabled === true && smooth.type === 'cubicBezier' || this.edgeType instanceof BezierEdgeStatic && smooth.enabled === true && smooth.type !== 'dynamic' && smooth.type !== 'cubicBezier' || this.edgeType instanceof StraightEdge && smooth.type.enabled === false) {
35385 changeInType = false;
35386 }
35387
35388 if (changeInType === true) {
35389 dataChanged = this.cleanup();
35390 }
35391 }
35392
35393 if (changeInType === true) {
35394 if (smooth.enabled === true) {
35395 if (smooth.type === 'dynamic') {
35396 dataChanged = true;
35397 this.edgeType = new BezierEdgeDynamic(this.options, this.body, this.labelModule);
35398 } else if (smooth.type === 'cubicBezier') {
35399 this.edgeType = new CubicBezierEdge(this.options, this.body, this.labelModule);
35400 } else {
35401 this.edgeType = new BezierEdgeStatic(this.options, this.body, this.labelModule);
35402 }
35403 } else {
35404 this.edgeType = new StraightEdge(this.options, this.body, this.labelModule);
35405 }
35406 } else {
35407 // if nothing changes, we just set the options.
35408 this.edgeType.setOptions(this.options);
35409 }
35410
35411 return dataChanged;
35412 }
35413 /**
35414 * Connect an edge to its nodes
35415 */
35416
35417 }, {
35418 key: "connect",
35419 value: function connect() {
35420 this.disconnect();
35421 this.from = this.body.nodes[this.fromId] || undefined;
35422 this.to = this.body.nodes[this.toId] || undefined;
35423 this.connected = this.from !== undefined && this.to !== undefined;
35424
35425 if (this.connected === true) {
35426 this.from.attachEdge(this);
35427 this.to.attachEdge(this);
35428 } else {
35429 if (this.from) {
35430 this.from.detachEdge(this);
35431 }
35432
35433 if (this.to) {
35434 this.to.detachEdge(this);
35435 }
35436 }
35437
35438 this.edgeType.connect();
35439 }
35440 /**
35441 * Disconnect an edge from its nodes
35442 */
35443
35444 }, {
35445 key: "disconnect",
35446 value: function disconnect() {
35447 if (this.from) {
35448 this.from.detachEdge(this);
35449 this.from = undefined;
35450 }
35451
35452 if (this.to) {
35453 this.to.detachEdge(this);
35454 this.to = undefined;
35455 }
35456
35457 this.connected = false;
35458 }
35459 /**
35460 * get the title of this edge.
35461 * @return {string} title The title of the edge, or undefined when no title
35462 * has been set.
35463 */
35464
35465 }, {
35466 key: "getTitle",
35467 value: function getTitle() {
35468 return this.title;
35469 }
35470 /**
35471 * check if this node is selecte
35472 * @return {boolean} selected True if node is selected, else false
35473 */
35474
35475 }, {
35476 key: "isSelected",
35477 value: function isSelected() {
35478 return this.selected;
35479 }
35480 /**
35481 * Retrieve the value of the edge. Can be undefined
35482 * @return {number} value
35483 */
35484
35485 }, {
35486 key: "getValue",
35487 value: function getValue() {
35488 return this.options.value;
35489 }
35490 /**
35491 * Adjust the value range of the edge. The edge will adjust it's width
35492 * based on its value.
35493 * @param {number} min
35494 * @param {number} max
35495 * @param {number} total
35496 */
35497
35498 }, {
35499 key: "setValueRange",
35500 value: function setValueRange(min, max, total) {
35501 if (this.options.value !== undefined) {
35502 var scale = this.options.scaling.customScalingFunction(min, max, total, this.options.value);
35503 var widthDiff = this.options.scaling.max - this.options.scaling.min;
35504
35505 if (this.options.scaling.label.enabled === true) {
35506 var fontDiff = this.options.scaling.label.max - this.options.scaling.label.min;
35507 this.options.font.size = this.options.scaling.label.min + scale * fontDiff;
35508 }
35509
35510 this.options.width = this.options.scaling.min + scale * widthDiff;
35511 } else {
35512 this.options.width = this.baseWidth;
35513 this.options.font.size = this.baseFontSize;
35514 }
35515
35516 this._setInteractionWidths();
35517
35518 this.updateLabelModule();
35519 }
35520 /**
35521 *
35522 * @private
35523 */
35524
35525 }, {
35526 key: "_setInteractionWidths",
35527 value: function _setInteractionWidths() {
35528 if (typeof this.options.hoverWidth === 'function') {
35529 this.edgeType.hoverWidth = this.options.hoverWidth(this.options.width);
35530 } else {
35531 this.edgeType.hoverWidth = this.options.hoverWidth + this.options.width;
35532 }
35533
35534 if (typeof this.options.selectionWidth === 'function') {
35535 this.edgeType.selectionWidth = this.options.selectionWidth(this.options.width);
35536 } else {
35537 this.edgeType.selectionWidth = this.options.selectionWidth + this.options.width;
35538 }
35539 }
35540 /**
35541 * Redraw a edge
35542 * Draw this edge in the given canvas
35543 * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
35544 * @param {CanvasRenderingContext2D} ctx
35545 */
35546
35547 }, {
35548 key: "draw",
35549 value: function draw(ctx) {
35550 var values = this.getFormattingValues();
35551
35552 if (values.hidden) {
35553 return;
35554 } // get the via node from the edge type
35555
35556
35557 var viaNode = this.edgeType.getViaNode();
35558 var arrowData = {}; // restore edge targets to defaults
35559
35560 this.edgeType.fromPoint = this.edgeType.from;
35561 this.edgeType.toPoint = this.edgeType.to; // from and to arrows give a different end point for edges. we set them here
35562
35563 if (values.fromArrow) {
35564 arrowData.from = this.edgeType.getArrowData(ctx, "from", viaNode, this.selected, this.hover, values);
35565 if (values.arrowStrikethrough === false) this.edgeType.fromPoint = arrowData.from.core;
35566
35567 if (values.fromArrowSrc) {
35568 arrowData.from.image = this.imagelist.load(values.fromArrowSrc);
35569 }
35570
35571 if (values.fromArrowImageWidth) {
35572 arrowData.from.imageWidth = values.fromArrowImageWidth;
35573 }
35574
35575 if (values.fromArrowImageHeight) {
35576 arrowData.from.imageHeight = values.fromArrowImageHeight;
35577 }
35578 }
35579
35580 if (values.toArrow) {
35581 arrowData.to = this.edgeType.getArrowData(ctx, "to", viaNode, this.selected, this.hover, values);
35582 if (values.arrowStrikethrough === false) this.edgeType.toPoint = arrowData.to.core;
35583
35584 if (values.toArrowSrc) {
35585 arrowData.to.image = this.imagelist.load(values.toArrowSrc);
35586 }
35587
35588 if (values.toArrowImageWidth) {
35589 arrowData.to.imageWidth = values.toArrowImageWidth;
35590 }
35591
35592 if (values.toArrowImageHeight) {
35593 arrowData.to.imageHeight = values.toArrowImageHeight;
35594 }
35595 } // the middle arrow depends on the line, which can depend on the to and from arrows so we do this one lastly.
35596
35597
35598 if (values.middleArrow) {
35599 arrowData.middle = this.edgeType.getArrowData(ctx, "middle", viaNode, this.selected, this.hover, values);
35600
35601 if (values.middleArrowSrc) {
35602 arrowData.middle.image = this.imagelist.load(values.middleArrowSrc);
35603 }
35604
35605 if (values.middleArrowImageWidth) {
35606 arrowData.middle.imageWidth = values.middleArrowImageWidth;
35607 }
35608
35609 if (values.middleArrowImageHeight) {
35610 arrowData.middle.imageHeight = values.middleArrowImageHeight;
35611 }
35612 } // draw everything
35613
35614
35615 this.edgeType.drawLine(ctx, values, this.selected, this.hover, viaNode);
35616 this.drawArrows(ctx, arrowData, values);
35617 this.drawLabel(ctx, viaNode);
35618 }
35619 /**
35620 *
35621 * @param {CanvasRenderingContext2D} ctx
35622 * @param {Object} arrowData
35623 * @param {ArrowOptions} values
35624 */
35625
35626 }, {
35627 key: "drawArrows",
35628 value: function drawArrows(ctx, arrowData, values) {
35629 if (values.fromArrow) {
35630 this.edgeType.drawArrowHead(ctx, values, this.selected, this.hover, arrowData.from);
35631 }
35632
35633 if (values.middleArrow) {
35634 this.edgeType.drawArrowHead(ctx, values, this.selected, this.hover, arrowData.middle);
35635 }
35636
35637 if (values.toArrow) {
35638 this.edgeType.drawArrowHead(ctx, values, this.selected, this.hover, arrowData.to);
35639 }
35640 }
35641 /**
35642 *
35643 * @param {CanvasRenderingContext2D} ctx
35644 * @param {Node} viaNode
35645 */
35646
35647 }, {
35648 key: "drawLabel",
35649 value: function drawLabel(ctx, viaNode) {
35650 if (this.options.label !== undefined) {
35651 // set style
35652 var node1 = this.from;
35653 var node2 = this.to;
35654
35655 if (this.labelModule.differentState(this.selected, this.hover)) {
35656 this.labelModule.getTextSize(ctx, this.selected, this.hover);
35657 }
35658
35659 if (node1.id != node2.id) {
35660 this.labelModule.pointToSelf = false;
35661 var point = this.edgeType.getPoint(0.5, viaNode);
35662 ctx.save();
35663
35664 var rotationPoint = this._getRotation(ctx);
35665
35666 if (rotationPoint.angle != 0) {
35667 ctx.translate(rotationPoint.x, rotationPoint.y);
35668 ctx.rotate(rotationPoint.angle);
35669 } // draw the label
35670
35671
35672 this.labelModule.draw(ctx, point.x, point.y, this.selected, this.hover);
35673 /*
35674 // Useful debug code: draw a border around the label
35675 // This should **not** be enabled in production!
35676 var size = this.labelModule.getSize();; // ;; intentional so lint catches it
35677 ctx.strokeStyle = "#ff0000";
35678 ctx.strokeRect(size.left, size.top, size.width, size.height);
35679 // End debug code
35680 */
35681
35682 ctx.restore();
35683 } else {
35684 // Ignore the orientations.
35685 this.labelModule.pointToSelf = true;
35686 var x, y;
35687 var radius = this.options.selfReferenceSize;
35688
35689 if (node1.shape.width > node1.shape.height) {
35690 x = node1.x + node1.shape.width * 0.5;
35691 y = node1.y - radius;
35692 } else {
35693 x = node1.x + radius;
35694 y = node1.y - node1.shape.height * 0.5;
35695 }
35696
35697 point = this._pointOnCircle(x, y, radius, 0.125);
35698 this.labelModule.draw(ctx, point.x, point.y, this.selected, this.hover);
35699 }
35700 }
35701 }
35702 /**
35703 * Determine all visual elements of this edge instance, in which the given
35704 * point falls within the bounding shape.
35705 *
35706 * @param {point} point
35707 * @returns {Array.<edgeClickItem|edgeLabelClickItem>} list with the items which are on the point
35708 */
35709
35710 }, {
35711 key: "getItemsOnPoint",
35712 value: function getItemsOnPoint(point) {
35713 var ret = [];
35714
35715 if (this.labelModule.visible()) {
35716 var rotationPoint = this._getRotation();
35717
35718 if (ComponentUtil.pointInRect(this.labelModule.getSize(), point, rotationPoint)) {
35719 ret.push({
35720 edgeId: this.id,
35721 labelId: 0
35722 });
35723 }
35724 }
35725
35726 var obj = {
35727 left: point.x,
35728 top: point.y
35729 };
35730
35731 if (this.isOverlappingWith(obj)) {
35732 ret.push({
35733 edgeId: this.id
35734 });
35735 }
35736
35737 return ret;
35738 }
35739 /**
35740 * Check if this object is overlapping with the provided object
35741 * @param {Object} obj an object with parameters left, top
35742 * @return {boolean} True if location is located on the edge
35743 */
35744
35745 }, {
35746 key: "isOverlappingWith",
35747 value: function isOverlappingWith(obj) {
35748 if (this.connected) {
35749 var distMax = 10;
35750 var xFrom = this.from.x;
35751 var yFrom = this.from.y;
35752 var xTo = this.to.x;
35753 var yTo = this.to.y;
35754 var xObj = obj.left;
35755 var yObj = obj.top;
35756 var dist = this.edgeType.getDistanceToEdge(xFrom, yFrom, xTo, yTo, xObj, yObj);
35757 return dist < distMax;
35758 } else {
35759 return false;
35760 }
35761 }
35762 /**
35763 * Determine the rotation point, if any.
35764 *
35765 * @param {CanvasRenderingContext2D} [ctx] if passed, do a recalculation of the label size
35766 * @returns {rotationPoint} the point to rotate around and the angle in radians to rotate
35767 * @private
35768 */
35769
35770 }, {
35771 key: "_getRotation",
35772 value: function _getRotation(ctx) {
35773 var viaNode = this.edgeType.getViaNode();
35774 var point = this.edgeType.getPoint(0.5, viaNode);
35775
35776 if (ctx !== undefined) {
35777 this.labelModule.calculateLabelSize(ctx, this.selected, this.hover, point.x, point.y);
35778 }
35779
35780 var ret = {
35781 x: point.x,
35782 y: this.labelModule.size.yLine,
35783 angle: 0
35784 };
35785
35786 if (!this.labelModule.visible()) {
35787 return ret; // Don't even bother doing the atan2, there's nothing to draw
35788 }
35789
35790 if (this.options.font.align === "horizontal") {
35791 return ret; // No need to calculate angle
35792 }
35793
35794 var dy = this.from.y - this.to.y;
35795 var dx = this.from.x - this.to.x;
35796 var angle = Math.atan2(dy, dx); // radians
35797 // rotate so that label is readable
35798
35799 if (angle < -1 && dx < 0 || angle > 0 && dx < 0) {
35800 angle += Math.PI;
35801 }
35802
35803 ret.angle = angle;
35804 return ret;
35805 }
35806 /**
35807 * Get a point on a circle
35808 * @param {number} x
35809 * @param {number} y
35810 * @param {number} radius
35811 * @param {number} percentage Value between 0 (line start) and 1 (line end)
35812 * @return {Object} point
35813 * @private
35814 */
35815
35816 }, {
35817 key: "_pointOnCircle",
35818 value: function _pointOnCircle(x, y, radius, percentage) {
35819 var angle = percentage * 2 * Math.PI;
35820 return {
35821 x: x + radius * Math.cos(angle),
35822 y: y - radius * Math.sin(angle)
35823 };
35824 }
35825 /**
35826 * Sets selected state to true
35827 */
35828
35829 }, {
35830 key: "select",
35831 value: function select() {
35832 this.selected = true;
35833 }
35834 /**
35835 * Sets selected state to false
35836 */
35837
35838 }, {
35839 key: "unselect",
35840 value: function unselect() {
35841 this.selected = false;
35842 }
35843 /**
35844 * cleans all required things on delete
35845 * @returns {*}
35846 */
35847
35848 }, {
35849 key: "cleanup",
35850 value: function cleanup() {
35851 return this.edgeType.cleanup();
35852 }
35853 /**
35854 * Remove edge from the list and perform necessary cleanup.
35855 */
35856
35857 }, {
35858 key: "remove",
35859 value: function remove() {
35860 this.cleanup();
35861 this.disconnect();
35862 delete this.body.edges[this.id];
35863 }
35864 /**
35865 * Check if both connecting nodes exist
35866 * @returns {boolean}
35867 */
35868
35869 }, {
35870 key: "endPointsValid",
35871 value: function endPointsValid() {
35872 return this.body.nodes[this.fromId] !== undefined && this.body.nodes[this.toId] !== undefined;
35873 }
35874 }], [{
35875 key: "parseOptions",
35876 value: function parseOptions(parentOptions, newOptions) {
35877 var allowDeletion = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
35878 var globalOptions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
35879 var copyFromGlobals = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
35880 var fields = ['arrowStrikethrough', 'id', 'from', 'hidden', 'hoverWidth', 'labelHighlightBold', 'length', 'line', 'opacity', 'physics', 'scaling', 'selectionWidth', 'selfReferenceSize', 'to', 'title', 'value', 'width', 'font', 'chosen', 'widthConstraint']; // only deep extend the items in the field array. These do not have shorthand.
35881
35882 selectiveDeepExtend(fields, parentOptions, newOptions, allowDeletion); // Only copy label if it's a legal value.
35883
35884 if (ComponentUtil.isValidLabel(newOptions.label)) {
35885 parentOptions.label = newOptions.label;
35886 } else if (!ComponentUtil.isValidLabel(parentOptions.label)) {
35887 parentOptions.label = undefined;
35888 }
35889
35890 mergeOptions(parentOptions, newOptions, 'smooth', globalOptions);
35891 mergeOptions(parentOptions, newOptions, 'shadow', globalOptions);
35892 mergeOptions(parentOptions, newOptions, 'background', globalOptions);
35893
35894 if (newOptions.dashes !== undefined && newOptions.dashes !== null) {
35895 parentOptions.dashes = newOptions.dashes;
35896 } else if (allowDeletion === true && newOptions.dashes === null) {
35897 parentOptions.dashes = Object.create(globalOptions.dashes); // this sets the pointer of the option back to the global option.
35898 } // set the scaling newOptions
35899
35900
35901 if (newOptions.scaling !== undefined && newOptions.scaling !== null) {
35902 if (newOptions.scaling.min !== undefined) {
35903 parentOptions.scaling.min = newOptions.scaling.min;
35904 }
35905
35906 if (newOptions.scaling.max !== undefined) {
35907 parentOptions.scaling.max = newOptions.scaling.max;
35908 }
35909
35910 mergeOptions(parentOptions.scaling, newOptions.scaling, 'label', globalOptions.scaling);
35911 } else if (allowDeletion === true && newOptions.scaling === null) {
35912 parentOptions.scaling = Object.create(globalOptions.scaling); // this sets the pointer of the option back to the global option.
35913 } // handle multiple input cases for arrows
35914
35915
35916 if (newOptions.arrows !== undefined && newOptions.arrows !== null) {
35917 if (typeof newOptions.arrows === 'string') {
35918 var arrows = newOptions.arrows.toLowerCase();
35919 parentOptions.arrows.to.enabled = arrows.indexOf("to") != -1;
35920 parentOptions.arrows.middle.enabled = arrows.indexOf("middle") != -1;
35921 parentOptions.arrows.from.enabled = arrows.indexOf("from") != -1;
35922 } else if (_typeof$1(newOptions.arrows) === 'object') {
35923 mergeOptions(parentOptions.arrows, newOptions.arrows, 'to', globalOptions.arrows);
35924 mergeOptions(parentOptions.arrows, newOptions.arrows, 'middle', globalOptions.arrows);
35925 mergeOptions(parentOptions.arrows, newOptions.arrows, 'from', globalOptions.arrows);
35926 } else {
35927 throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:" + JSON.stringify(newOptions.arrows));
35928 }
35929 } else if (allowDeletion === true && newOptions.arrows === null) {
35930 parentOptions.arrows = Object.create(globalOptions.arrows); // this sets the pointer of the option back to the global option.
35931 } // handle multiple input cases for color
35932
35933
35934 if (newOptions.color !== undefined && newOptions.color !== null) {
35935 var fromColor = isString(newOptions.color) ? {
35936 color: newOptions.color,
35937 highlight: newOptions.color,
35938 hover: newOptions.color,
35939 inherit: false,
35940 opacity: 1
35941 } : newOptions.color;
35942 var toColor = parentOptions.color; // If passed, fill in values from default options - required in the case of no prototype bridging
35943
35944 if (copyFromGlobals) {
35945 deepExtend(toColor, globalOptions.color, false, allowDeletion);
35946 } else {
35947 // Clear local properties - need to do it like this in order to retain prototype bridges
35948 for (var i in toColor) {
35949 if (toColor.hasOwnProperty(i)) {
35950 delete toColor[i];
35951 }
35952 }
35953 }
35954
35955 if (isString(toColor)) {
35956 toColor.color = toColor;
35957 toColor.highlight = toColor;
35958 toColor.hover = toColor;
35959 toColor.inherit = false;
35960
35961 if (fromColor.opacity === undefined) {
35962 toColor.opacity = 1.0; // set default
35963 }
35964 } else {
35965 var colorsDefined = false;
35966
35967 if (fromColor.color !== undefined) {
35968 toColor.color = fromColor.color;
35969 colorsDefined = true;
35970 }
35971
35972 if (fromColor.highlight !== undefined) {
35973 toColor.highlight = fromColor.highlight;
35974 colorsDefined = true;
35975 }
35976
35977 if (fromColor.hover !== undefined) {
35978 toColor.hover = fromColor.hover;
35979 colorsDefined = true;
35980 }
35981
35982 if (fromColor.inherit !== undefined) {
35983 toColor.inherit = fromColor.inherit;
35984 }
35985
35986 if (fromColor.opacity !== undefined) {
35987 toColor.opacity = Math.min(1, Math.max(0, fromColor.opacity));
35988 }
35989
35990 if (colorsDefined === true) {
35991 toColor.inherit = false;
35992 } else {
35993 if (toColor.inherit === undefined) {
35994 toColor.inherit = 'from'; // Set default
35995 }
35996 }
35997 }
35998 } else if (allowDeletion === true && newOptions.color === null) {
35999 parentOptions.color = bridgeObject(globalOptions.color); // set the object back to the global options
36000 }
36001
36002 if (allowDeletion === true && newOptions.font === null) {
36003 parentOptions.font = bridgeObject(globalOptions.font); // set the object back to the global options
36004 }
36005 }
36006 }]);
36007
36008 return Edge;
36009}();
36010
36011/**
36012 * Handler for Edges
36013 */
36014
36015var EdgesHandler =
36016/*#__PURE__*/
36017function () {
36018 /**
36019 * @param {Object} body
36020 * @param {Array.<Image>} images
36021 * @param {Array.<Group>} groups
36022 */
36023 function EdgesHandler(body, images, groups) {
36024 var _this = this;
36025
36026 _classCallCheck(this, EdgesHandler);
36027
36028 this.body = body;
36029 this.images = images;
36030 this.groups = groups; // create the edge API in the body container
36031
36032 this.body.functions.createEdge = this.create.bind(this);
36033 this.edgesListeners = {
36034 add: function add(event, params) {
36035 _this.add(params.items);
36036 },
36037 update: function update(event, params) {
36038 _this.update(params.items);
36039 },
36040 remove: function remove(event, params) {
36041 _this.remove(params.items);
36042 }
36043 };
36044 this.options = {};
36045 this.defaultOptions = {
36046 arrows: {
36047 to: {
36048 enabled: false,
36049 scaleFactor: 1,
36050 type: 'arrow'
36051 },
36052 // boolean / {arrowScaleFactor:1} / {enabled: false, arrowScaleFactor:1}
36053 middle: {
36054 enabled: false,
36055 scaleFactor: 1,
36056 type: 'arrow'
36057 },
36058 from: {
36059 enabled: false,
36060 scaleFactor: 1,
36061 type: 'arrow'
36062 }
36063 },
36064 arrowStrikethrough: true,
36065 color: {
36066 color: '#848484',
36067 highlight: '#848484',
36068 hover: '#848484',
36069 inherit: 'from',
36070 opacity: 1.0
36071 },
36072 dashes: false,
36073 font: {
36074 color: '#343434',
36075 size: 14,
36076 // px
36077 face: 'arial',
36078 background: 'none',
36079 strokeWidth: 2,
36080 // px
36081 strokeColor: '#ffffff',
36082 align: 'horizontal',
36083 multi: false,
36084 vadjust: 0,
36085 bold: {
36086 mod: 'bold'
36087 },
36088 boldital: {
36089 mod: 'bold italic'
36090 },
36091 ital: {
36092 mod: 'italic'
36093 },
36094 mono: {
36095 mod: '',
36096 size: 15,
36097 // px
36098 face: 'courier new',
36099 vadjust: 2
36100 }
36101 },
36102 hidden: false,
36103 hoverWidth: 1.5,
36104 label: undefined,
36105 labelHighlightBold: true,
36106 length: undefined,
36107 physics: true,
36108 scaling: {
36109 min: 1,
36110 max: 15,
36111 label: {
36112 enabled: true,
36113 min: 14,
36114 max: 30,
36115 maxVisible: 30,
36116 drawThreshold: 5
36117 },
36118 customScalingFunction: function customScalingFunction(min, max, total, value) {
36119 if (max === min) {
36120 return 0.5;
36121 } else {
36122 var scale = 1 / (max - min);
36123 return Math.max(0, (value - min) * scale);
36124 }
36125 }
36126 },
36127 selectionWidth: 1.5,
36128 selfReferenceSize: 20,
36129 shadow: {
36130 enabled: false,
36131 color: 'rgba(0,0,0,0.5)',
36132 size: 10,
36133 x: 5,
36134 y: 5
36135 },
36136 background: {
36137 enabled: false,
36138 color: 'rgba(111,111,111,1)',
36139 size: 10,
36140 dashes: false
36141 },
36142 smooth: {
36143 enabled: true,
36144 type: "dynamic",
36145 forceDirection: 'none',
36146 roundness: 0.5
36147 },
36148 title: undefined,
36149 width: 1,
36150 value: undefined
36151 };
36152 deepExtend(this.options, this.defaultOptions);
36153 this.bindEventListeners();
36154 }
36155 /**
36156 * Binds event listeners
36157 */
36158
36159
36160 _createClass(EdgesHandler, [{
36161 key: "bindEventListeners",
36162 value: function bindEventListeners() {
36163 var _this2 = this;
36164
36165 // this allows external modules to force all dynamic curves to turn static.
36166 this.body.emitter.on("_forceDisableDynamicCurves", function (type) {
36167 var emit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
36168
36169 if (type === 'dynamic') {
36170 type = 'continuous';
36171 }
36172
36173 var dataChanged = false;
36174
36175 for (var edgeId in _this2.body.edges) {
36176 if (_this2.body.edges.hasOwnProperty(edgeId)) {
36177 var edge = _this2.body.edges[edgeId];
36178 var edgeData = _this2.body.data.edges._data[edgeId]; // only forcibly remove the smooth curve if the data has been set of the edge has the smooth curves defined.
36179 // this is because a change in the global would not affect these curves.
36180
36181 if (edgeData !== undefined) {
36182 var smoothOptions = edgeData.smooth;
36183
36184 if (smoothOptions !== undefined) {
36185 if (smoothOptions.enabled === true && smoothOptions.type === 'dynamic') {
36186 if (type === undefined) {
36187 edge.setOptions({
36188 smooth: false
36189 });
36190 } else {
36191 edge.setOptions({
36192 smooth: {
36193 type: type
36194 }
36195 });
36196 }
36197
36198 dataChanged = true;
36199 }
36200 }
36201 }
36202 }
36203 }
36204
36205 if (emit === true && dataChanged === true) {
36206 _this2.body.emitter.emit("_dataChanged");
36207 }
36208 }); // this is called when options of EXISTING nodes or edges have changed.
36209 //
36210 // NOTE: Not true, called when options have NOT changed, for both existing as well as new nodes.
36211 // See update() for logic.
36212 // TODO: Verify and examine the consequences of this. It might still trigger when
36213 // non-option fields have changed, but then reconnecting edges is still useless.
36214 // Alternatively, it might also be called when edges are removed.
36215 //
36216
36217 this.body.emitter.on("_dataUpdated", function () {
36218 _this2.reconnectEdges();
36219 }); // refresh the edges. Used when reverting from hierarchical layout
36220
36221 this.body.emitter.on("refreshEdges", this.refresh.bind(this));
36222 this.body.emitter.on("refresh", this.refresh.bind(this));
36223 this.body.emitter.on("destroy", function () {
36224 forEach(_this2.edgesListeners, function (callback, event) {
36225 if (_this2.body.data.edges) _this2.body.data.edges.off(event, callback);
36226 });
36227 delete _this2.body.functions.createEdge;
36228 delete _this2.edgesListeners.add;
36229 delete _this2.edgesListeners.update;
36230 delete _this2.edgesListeners.remove;
36231 delete _this2.edgesListeners;
36232 });
36233 }
36234 /**
36235 *
36236 * @param {Object} options
36237 */
36238
36239 }, {
36240 key: "setOptions",
36241 value: function setOptions(options) {
36242 if (options !== undefined) {
36243 // use the parser from the Edge class to fill in all shorthand notations
36244 Edge.parseOptions(this.options, options, true, this.defaultOptions, true); // update smooth settings in all edges
36245
36246 var dataChanged = false;
36247
36248 if (options.smooth !== undefined) {
36249 for (var edgeId in this.body.edges) {
36250 if (this.body.edges.hasOwnProperty(edgeId)) {
36251 dataChanged = this.body.edges[edgeId].updateEdgeType() || dataChanged;
36252 }
36253 }
36254 } // update fonts in all edges
36255
36256
36257 if (options.font !== undefined) {
36258 for (var _edgeId in this.body.edges) {
36259 if (this.body.edges.hasOwnProperty(_edgeId)) {
36260 this.body.edges[_edgeId].updateLabelModule();
36261 }
36262 }
36263 } // update the state of the variables if needed
36264
36265
36266 if (options.hidden !== undefined || options.physics !== undefined || dataChanged === true) {
36267 this.body.emitter.emit('_dataChanged');
36268 }
36269 }
36270 }
36271 /**
36272 * Load edges by reading the data table
36273 * @param {Array | DataSet | DataView} edges The data containing the edges.
36274 * @param {boolean} [doNotEmit=false]
36275 * @private
36276 */
36277
36278 }, {
36279 key: "setData",
36280 value: function setData(edges) {
36281 var _this3 = this;
36282
36283 var doNotEmit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
36284 var oldEdgesData = this.body.data.edges;
36285
36286 if (edges instanceof DataSet || edges instanceof DataView$2) {
36287 this.body.data.edges = edges;
36288 } else if (Array.isArray(edges)) {
36289 this.body.data.edges = new DataSet();
36290 this.body.data.edges.add(edges);
36291 } else if (!edges) {
36292 this.body.data.edges = new DataSet();
36293 } else {
36294 throw new TypeError('Array or DataSet expected');
36295 } // TODO: is this null or undefined or false?
36296
36297
36298 if (oldEdgesData) {
36299 // unsubscribe from old dataset
36300 forEach(this.edgesListeners, function (callback, event) {
36301 oldEdgesData.off(event, callback);
36302 });
36303 } // remove drawn edges
36304
36305
36306 this.body.edges = {}; // TODO: is this null or undefined or false?
36307
36308 if (this.body.data.edges) {
36309 // subscribe to new dataset
36310 forEach(this.edgesListeners, function (callback, event) {
36311 _this3.body.data.edges.on(event, callback);
36312 }); // draw all new nodes
36313
36314 var ids = this.body.data.edges.getIds();
36315 this.add(ids, true);
36316 }
36317
36318 this.body.emitter.emit('_adjustEdgesForHierarchicalLayout');
36319
36320 if (doNotEmit === false) {
36321 this.body.emitter.emit("_dataChanged");
36322 }
36323 }
36324 /**
36325 * Add edges
36326 * @param {number[] | string[]} ids
36327 * @param {boolean} [doNotEmit=false]
36328 * @private
36329 */
36330
36331 }, {
36332 key: "add",
36333 value: function add(ids) {
36334 var doNotEmit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
36335 var edges = this.body.edges;
36336 var edgesData = this.body.data.edges;
36337
36338 for (var i = 0; i < ids.length; i++) {
36339 var id = ids[i];
36340 var oldEdge = edges[id];
36341
36342 if (oldEdge) {
36343 oldEdge.disconnect();
36344 }
36345
36346 var data = edgesData.get(id, {
36347 "showInternalIds": true
36348 });
36349 edges[id] = this.create(data);
36350 }
36351
36352 this.body.emitter.emit('_adjustEdgesForHierarchicalLayout');
36353
36354 if (doNotEmit === false) {
36355 this.body.emitter.emit("_dataChanged");
36356 }
36357 }
36358 /**
36359 * Update existing edges, or create them when not yet existing
36360 * @param {number[] | string[]} ids
36361 * @private
36362 */
36363
36364 }, {
36365 key: "update",
36366 value: function update(ids) {
36367 var edges = this.body.edges;
36368 var edgesData = this.body.data.edges;
36369 var dataChanged = false;
36370
36371 for (var i = 0; i < ids.length; i++) {
36372 var id = ids[i];
36373 var data = edgesData.get(id);
36374 var edge = edges[id];
36375
36376 if (edge !== undefined) {
36377 // update edge
36378 edge.disconnect();
36379 dataChanged = edge.setOptions(data) || dataChanged; // if a support node is added, data can be changed.
36380
36381 edge.connect();
36382 } else {
36383 // create edge
36384 this.body.edges[id] = this.create(data);
36385 dataChanged = true;
36386 }
36387 }
36388
36389 if (dataChanged === true) {
36390 this.body.emitter.emit('_adjustEdgesForHierarchicalLayout');
36391 this.body.emitter.emit("_dataChanged");
36392 } else {
36393 this.body.emitter.emit("_dataUpdated");
36394 }
36395 }
36396 /**
36397 * Remove existing edges. Non existing ids will be ignored
36398 * @param {number[] | string[]} ids
36399 * @param {boolean} [emit=true]
36400 * @private
36401 */
36402
36403 }, {
36404 key: "remove",
36405 value: function remove(ids) {
36406 var emit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
36407 if (ids.length === 0) return; // early out
36408
36409 var edges = this.body.edges;
36410 forEach(ids, function (id) {
36411 var edge = edges[id];
36412
36413 if (edge !== undefined) {
36414 edge.remove();
36415 }
36416 });
36417
36418 if (emit) {
36419 this.body.emitter.emit("_dataChanged");
36420 }
36421 }
36422 /**
36423 * Refreshes Edge Handler
36424 */
36425
36426 }, {
36427 key: "refresh",
36428 value: function refresh() {
36429 var _this4 = this;
36430
36431 forEach(this.body.edges, function (edge, edgeId) {
36432 var data = _this4.body.data.edges._data[edgeId];
36433
36434 if (data !== undefined) {
36435 edge.setOptions(data);
36436 }
36437 });
36438 }
36439 /**
36440 *
36441 * @param {Object} properties
36442 * @returns {Edge}
36443 */
36444
36445 }, {
36446 key: "create",
36447 value: function create(properties) {
36448 return new Edge(properties, this.body, this.images, this.options, this.defaultOptions);
36449 }
36450 /**
36451 * Reconnect all edges
36452 * @private
36453 */
36454
36455 }, {
36456 key: "reconnectEdges",
36457 value: function reconnectEdges() {
36458 var id;
36459 var nodes = this.body.nodes;
36460 var edges = this.body.edges;
36461
36462 for (id in nodes) {
36463 if (nodes.hasOwnProperty(id)) {
36464 nodes[id].edges = [];
36465 }
36466 }
36467
36468 for (id in edges) {
36469 if (edges.hasOwnProperty(id)) {
36470 var edge = edges[id];
36471 edge.from = null;
36472 edge.to = null;
36473 edge.connect();
36474 }
36475 }
36476 }
36477 /**
36478 *
36479 * @param {Edge.id} edgeId
36480 * @returns {Array}
36481 */
36482
36483 }, {
36484 key: "getConnectedNodes",
36485 value: function getConnectedNodes(edgeId) {
36486 var nodeList = [];
36487
36488 if (this.body.edges[edgeId] !== undefined) {
36489 var edge = this.body.edges[edgeId];
36490
36491 if (edge.fromId !== undefined) {
36492 nodeList.push(edge.fromId);
36493 }
36494
36495 if (edge.toId !== undefined) {
36496 nodeList.push(edge.toId);
36497 }
36498 }
36499
36500 return nodeList;
36501 }
36502 /**
36503 * There is no direct relation between the nodes and the edges DataSet,
36504 * so the right place to do call this is in the handler for event `_dataUpdated`.
36505 */
36506
36507 }, {
36508 key: "_updateState",
36509 value: function _updateState() {
36510 this._addMissingEdges();
36511
36512 this._removeInvalidEdges();
36513 }
36514 /**
36515 * Scan for missing nodes and remove corresponding edges, if any.
36516 * @private
36517 */
36518
36519 }, {
36520 key: "_removeInvalidEdges",
36521 value: function _removeInvalidEdges() {
36522 var _this5 = this;
36523
36524 var edgesToDelete = [];
36525 forEach(this.body.edges, function (edge, id) {
36526 var toNode = _this5.body.nodes[edge.toId];
36527 var fromNode = _this5.body.nodes[edge.fromId]; // Skip clustering edges here, let the Clustering module handle those
36528
36529 if (toNode !== undefined && toNode.isCluster === true || fromNode !== undefined && fromNode.isCluster === true) {
36530 return;
36531 }
36532
36533 if (toNode === undefined || fromNode === undefined) {
36534 edgesToDelete.push(id);
36535 }
36536 });
36537 this.remove(edgesToDelete, false);
36538 }
36539 /**
36540 * add all edges from dataset that are not in the cached state
36541 * @private
36542 */
36543
36544 }, {
36545 key: "_addMissingEdges",
36546 value: function _addMissingEdges() {
36547 var edgesData = this.body.data.edges;
36548
36549 if (edgesData === undefined || edgesData === null) {
36550 return; // No edges DataSet yet; can happen on startup
36551 }
36552
36553 var edges = this.body.edges;
36554 var addIds = [];
36555 edgesData.forEach(function (edgeData, edgeId) {
36556 var edge = edges[edgeId];
36557
36558 if (edge === undefined) {
36559 addIds.push(edgeId);
36560 }
36561 });
36562 this.add(addIds, true);
36563 }
36564 }]);
36565
36566 return EdgesHandler;
36567}();
36568
36569/**
36570 * Barnes Hut Solver
36571 */
36572var BarnesHutSolver =
36573/*#__PURE__*/
36574function () {
36575 /**
36576 * @param {Object} body
36577 * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
36578 * @param {Object} options
36579 */
36580 function BarnesHutSolver(body, physicsBody, options) {
36581 _classCallCheck(this, BarnesHutSolver);
36582
36583 this.body = body;
36584 this.physicsBody = physicsBody;
36585 this.barnesHutTree;
36586 this.setOptions(options);
36587 this.randomSeed = 5; // debug: show grid
36588 // this.body.emitter.on("afterDrawing", (ctx) => {this._debug(ctx,'#ff0000')})
36589 }
36590 /**
36591 *
36592 * @param {Object} options
36593 */
36594
36595
36596 _createClass(BarnesHutSolver, [{
36597 key: "setOptions",
36598 value: function setOptions(options) {
36599 this.options = options;
36600 this.thetaInversed = 1 / this.options.theta; // if 1 then min distance = 0.5, if 0.5 then min distance = 0.5 + 0.5*node.shape.radius
36601
36602 this.overlapAvoidanceFactor = 1 - Math.max(0, Math.min(1, this.options.avoidOverlap));
36603 }
36604 /**
36605 *
36606 * @returns {number} random integer
36607 */
36608
36609 }, {
36610 key: "seededRandom",
36611 value: function seededRandom() {
36612 var x = Math.sin(this.randomSeed++) * 10000;
36613 return x - Math.floor(x);
36614 }
36615 /**
36616 * This function calculates the forces the nodes apply on each other based on a gravitational model.
36617 * The Barnes Hut method is used to speed up this N-body simulation.
36618 *
36619 * @private
36620 */
36621
36622 }, {
36623 key: "solve",
36624 value: function solve() {
36625 if (this.options.gravitationalConstant !== 0 && this.physicsBody.physicsNodeIndices.length > 0) {
36626 var node;
36627 var nodes = this.body.nodes;
36628 var nodeIndices = this.physicsBody.physicsNodeIndices;
36629 var nodeCount = nodeIndices.length; // create the tree
36630
36631 var barnesHutTree = this._formBarnesHutTree(nodes, nodeIndices); // for debugging
36632
36633
36634 this.barnesHutTree = barnesHutTree; // place the nodes one by one recursively
36635
36636 for (var i = 0; i < nodeCount; i++) {
36637 node = nodes[nodeIndices[i]];
36638
36639 if (node.options.mass > 0) {
36640 // starting with root is irrelevant, it never passes the BarnesHutSolver condition
36641 this._getForceContributions(barnesHutTree.root, node);
36642 }
36643 }
36644 }
36645 }
36646 /**
36647 * @param {Object} parentBranch
36648 * @param {Node} node
36649 * @private
36650 */
36651
36652 }, {
36653 key: "_getForceContributions",
36654 value: function _getForceContributions(parentBranch, node) {
36655 this._getForceContribution(parentBranch.children.NW, node);
36656
36657 this._getForceContribution(parentBranch.children.NE, node);
36658
36659 this._getForceContribution(parentBranch.children.SW, node);
36660
36661 this._getForceContribution(parentBranch.children.SE, node);
36662 }
36663 /**
36664 * This function traverses the barnesHutTree. It checks when it can approximate distant nodes with their center of mass.
36665 * If a region contains a single node, we check if it is not itself, then we apply the force.
36666 *
36667 * @param {Object} parentBranch
36668 * @param {Node} node
36669 * @private
36670 */
36671
36672 }, {
36673 key: "_getForceContribution",
36674 value: function _getForceContribution(parentBranch, node) {
36675 // we get no force contribution from an empty region
36676 if (parentBranch.childrenCount > 0) {
36677 var dx, dy, distance; // get the distance from the center of mass to the node.
36678
36679 dx = parentBranch.centerOfMass.x - node.x;
36680 dy = parentBranch.centerOfMass.y - node.y;
36681 distance = Math.sqrt(dx * dx + dy * dy); // BarnesHutSolver condition
36682 // original condition : s/d < theta = passed === d/s > 1/theta = passed
36683 // calcSize = 1/s --> d * 1/s > 1/theta = passed
36684
36685 if (distance * parentBranch.calcSize > this.thetaInversed) {
36686 this._calculateForces(distance, dx, dy, node, parentBranch);
36687 } else {
36688 // Did not pass the condition, go into children if available
36689 if (parentBranch.childrenCount === 4) {
36690 this._getForceContributions(parentBranch, node);
36691 } else {
36692 // parentBranch must have only one node, if it was empty we wouldnt be here
36693 if (parentBranch.children.data.id != node.id) {
36694 // if it is not self
36695 this._calculateForces(distance, dx, dy, node, parentBranch);
36696 }
36697 }
36698 }
36699 }
36700 }
36701 /**
36702 * Calculate the forces based on the distance.
36703 *
36704 * @param {number} distance
36705 * @param {number} dx
36706 * @param {number} dy
36707 * @param {Node} node
36708 * @param {Object} parentBranch
36709 * @private
36710 */
36711
36712 }, {
36713 key: "_calculateForces",
36714 value: function _calculateForces(distance, dx, dy, node, parentBranch) {
36715 if (distance === 0) {
36716 distance = 0.1;
36717 dx = distance;
36718 }
36719
36720 if (this.overlapAvoidanceFactor < 1 && node.shape.radius) {
36721 distance = Math.max(0.1 + this.overlapAvoidanceFactor * node.shape.radius, distance - node.shape.radius);
36722 } // the dividing by the distance cubed instead of squared allows us to get the fx and fy components without sines and cosines
36723 // it is shorthand for gravityforce with distance squared and fx = dx/distance * gravityForce
36724
36725
36726 var gravityForce = this.options.gravitationalConstant * parentBranch.mass * node.options.mass / Math.pow(distance, 3);
36727 var fx = dx * gravityForce;
36728 var fy = dy * gravityForce;
36729 this.physicsBody.forces[node.id].x += fx;
36730 this.physicsBody.forces[node.id].y += fy;
36731 }
36732 /**
36733 * This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes.
36734 *
36735 * @param {Array.<Node>} nodes
36736 * @param {Array.<number>} nodeIndices
36737 * @returns {{root: {centerOfMass: {x: number, y: number}, mass: number, range: {minX: number, maxX: number, minY: number, maxY: number}, size: number, calcSize: number, children: {data: null}, maxWidth: number, level: number, childrenCount: number}}} BarnesHutTree
36738 * @private
36739 */
36740
36741 }, {
36742 key: "_formBarnesHutTree",
36743 value: function _formBarnesHutTree(nodes, nodeIndices) {
36744 var node;
36745 var nodeCount = nodeIndices.length;
36746 var minX = nodes[nodeIndices[0]].x;
36747 var minY = nodes[nodeIndices[0]].y;
36748 var maxX = nodes[nodeIndices[0]].x;
36749 var maxY = nodes[nodeIndices[0]].y; // get the range of the nodes
36750
36751 for (var i = 1; i < nodeCount; i++) {
36752 var _node = nodes[nodeIndices[i]];
36753 var x = _node.x;
36754 var y = _node.y;
36755
36756 if (_node.options.mass > 0) {
36757 if (x < minX) {
36758 minX = x;
36759 }
36760
36761 if (x > maxX) {
36762 maxX = x;
36763 }
36764
36765 if (y < minY) {
36766 minY = y;
36767 }
36768
36769 if (y > maxY) {
36770 maxY = y;
36771 }
36772 }
36773 } // make the range a square
36774
36775
36776 var sizeDiff = Math.abs(maxX - minX) - Math.abs(maxY - minY); // difference between X and Y
36777
36778 if (sizeDiff > 0) {
36779 minY -= 0.5 * sizeDiff;
36780 maxY += 0.5 * sizeDiff;
36781 } // xSize > ySize
36782 else {
36783 minX += 0.5 * sizeDiff;
36784 maxX -= 0.5 * sizeDiff;
36785 } // xSize < ySize
36786
36787
36788 var minimumTreeSize = 1e-5;
36789 var rootSize = Math.max(minimumTreeSize, Math.abs(maxX - minX));
36790 var halfRootSize = 0.5 * rootSize;
36791 var centerX = 0.5 * (minX + maxX),
36792 centerY = 0.5 * (minY + maxY); // construct the barnesHutTree
36793
36794 var barnesHutTree = {
36795 root: {
36796 centerOfMass: {
36797 x: 0,
36798 y: 0
36799 },
36800 mass: 0,
36801 range: {
36802 minX: centerX - halfRootSize,
36803 maxX: centerX + halfRootSize,
36804 minY: centerY - halfRootSize,
36805 maxY: centerY + halfRootSize
36806 },
36807 size: rootSize,
36808 calcSize: 1 / rootSize,
36809 children: {
36810 data: null
36811 },
36812 maxWidth: 0,
36813 level: 0,
36814 childrenCount: 4
36815 }
36816 };
36817
36818 this._splitBranch(barnesHutTree.root); // place the nodes one by one recursively
36819
36820
36821 for (var _i = 0; _i < nodeCount; _i++) {
36822 node = nodes[nodeIndices[_i]];
36823
36824 if (node.options.mass > 0) {
36825 this._placeInTree(barnesHutTree.root, node);
36826 }
36827 } // make global
36828
36829
36830 return barnesHutTree;
36831 }
36832 /**
36833 * this updates the mass of a branch. this is increased by adding a node.
36834 *
36835 * @param {Object} parentBranch
36836 * @param {Node} node
36837 * @private
36838 */
36839
36840 }, {
36841 key: "_updateBranchMass",
36842 value: function _updateBranchMass(parentBranch, node) {
36843 var centerOfMass = parentBranch.centerOfMass;
36844 var totalMass = parentBranch.mass + node.options.mass;
36845 var totalMassInv = 1 / totalMass;
36846 centerOfMass.x = centerOfMass.x * parentBranch.mass + node.x * node.options.mass;
36847 centerOfMass.x *= totalMassInv;
36848 centerOfMass.y = centerOfMass.y * parentBranch.mass + node.y * node.options.mass;
36849 centerOfMass.y *= totalMassInv;
36850 parentBranch.mass = totalMass;
36851 var biggestSize = Math.max(Math.max(node.height, node.radius), node.width);
36852 parentBranch.maxWidth = parentBranch.maxWidth < biggestSize ? biggestSize : parentBranch.maxWidth;
36853 }
36854 /**
36855 * determine in which branch the node will be placed.
36856 *
36857 * @param {Object} parentBranch
36858 * @param {Node} node
36859 * @param {boolean} skipMassUpdate
36860 * @private
36861 */
36862
36863 }, {
36864 key: "_placeInTree",
36865 value: function _placeInTree(parentBranch, node, skipMassUpdate) {
36866 if (skipMassUpdate != true || skipMassUpdate === undefined) {
36867 // update the mass of the branch.
36868 this._updateBranchMass(parentBranch, node);
36869 }
36870
36871 var range = parentBranch.children.NW.range;
36872 var region;
36873
36874 if (range.maxX > node.x) {
36875 // in NW or SW
36876 if (range.maxY > node.y) {
36877 region = "NW";
36878 } else {
36879 region = "SW";
36880 }
36881 } else {
36882 // in NE or SE
36883 if (range.maxY > node.y) {
36884 region = "NE";
36885 } else {
36886 region = "SE";
36887 }
36888 }
36889
36890 this._placeInRegion(parentBranch, node, region);
36891 }
36892 /**
36893 * actually place the node in a region (or branch)
36894 *
36895 * @param {Object} parentBranch
36896 * @param {Node} node
36897 * @param {'NW'| 'NE' | 'SW' | 'SE'} region
36898 * @private
36899 */
36900
36901 }, {
36902 key: "_placeInRegion",
36903 value: function _placeInRegion(parentBranch, node, region) {
36904 var children = parentBranch.children[region];
36905
36906 switch (children.childrenCount) {
36907 case 0:
36908 // place node here
36909 children.children.data = node;
36910 children.childrenCount = 1;
36911
36912 this._updateBranchMass(children, node);
36913
36914 break;
36915
36916 case 1:
36917 // convert into children
36918 // if there are two nodes exactly overlapping (on init, on opening of cluster etc.)
36919 // we move one node a little bit and we do not put it in the tree.
36920 if (children.children.data.x === node.x && children.children.data.y === node.y) {
36921 node.x += this.seededRandom();
36922 node.y += this.seededRandom();
36923 } else {
36924 this._splitBranch(children);
36925
36926 this._placeInTree(children, node);
36927 }
36928
36929 break;
36930
36931 case 4:
36932 // place in branch
36933 this._placeInTree(children, node);
36934
36935 break;
36936 }
36937 }
36938 /**
36939 * this function splits a branch into 4 sub branches. If the branch contained a node, we place it in the subbranch
36940 * after the split is complete.
36941 *
36942 * @param {Object} parentBranch
36943 * @private
36944 */
36945
36946 }, {
36947 key: "_splitBranch",
36948 value: function _splitBranch(parentBranch) {
36949 // if the branch is shaded with a node, replace the node in the new subset.
36950 var containedNode = null;
36951
36952 if (parentBranch.childrenCount === 1) {
36953 containedNode = parentBranch.children.data;
36954 parentBranch.mass = 0;
36955 parentBranch.centerOfMass.x = 0;
36956 parentBranch.centerOfMass.y = 0;
36957 }
36958
36959 parentBranch.childrenCount = 4;
36960 parentBranch.children.data = null;
36961
36962 this._insertRegion(parentBranch, "NW");
36963
36964 this._insertRegion(parentBranch, "NE");
36965
36966 this._insertRegion(parentBranch, "SW");
36967
36968 this._insertRegion(parentBranch, "SE");
36969
36970 if (containedNode != null) {
36971 this._placeInTree(parentBranch, containedNode);
36972 }
36973 }
36974 /**
36975 * This function subdivides the region into four new segments.
36976 * Specifically, this inserts a single new segment.
36977 * It fills the children section of the parentBranch
36978 *
36979 * @param {Object} parentBranch
36980 * @param {'NW'| 'NE' | 'SW' | 'SE'} region
36981 * @private
36982 */
36983
36984 }, {
36985 key: "_insertRegion",
36986 value: function _insertRegion(parentBranch, region) {
36987 var minX, maxX, minY, maxY;
36988 var childSize = 0.5 * parentBranch.size;
36989
36990 switch (region) {
36991 case "NW":
36992 minX = parentBranch.range.minX;
36993 maxX = parentBranch.range.minX + childSize;
36994 minY = parentBranch.range.minY;
36995 maxY = parentBranch.range.minY + childSize;
36996 break;
36997
36998 case "NE":
36999 minX = parentBranch.range.minX + childSize;
37000 maxX = parentBranch.range.maxX;
37001 minY = parentBranch.range.minY;
37002 maxY = parentBranch.range.minY + childSize;
37003 break;
37004
37005 case "SW":
37006 minX = parentBranch.range.minX;
37007 maxX = parentBranch.range.minX + childSize;
37008 minY = parentBranch.range.minY + childSize;
37009 maxY = parentBranch.range.maxY;
37010 break;
37011
37012 case "SE":
37013 minX = parentBranch.range.minX + childSize;
37014 maxX = parentBranch.range.maxX;
37015 minY = parentBranch.range.minY + childSize;
37016 maxY = parentBranch.range.maxY;
37017 break;
37018 }
37019
37020 parentBranch.children[region] = {
37021 centerOfMass: {
37022 x: 0,
37023 y: 0
37024 },
37025 mass: 0,
37026 range: {
37027 minX: minX,
37028 maxX: maxX,
37029 minY: minY,
37030 maxY: maxY
37031 },
37032 size: 0.5 * parentBranch.size,
37033 calcSize: 2 * parentBranch.calcSize,
37034 children: {
37035 data: null
37036 },
37037 maxWidth: 0,
37038 level: parentBranch.level + 1,
37039 childrenCount: 0
37040 };
37041 } //--------------------------- DEBUGGING BELOW ---------------------------//
37042
37043 /**
37044 * This function is for debugging purposed, it draws the tree.
37045 *
37046 * @param {CanvasRenderingContext2D} ctx
37047 * @param {string} color
37048 * @private
37049 */
37050
37051 }, {
37052 key: "_debug",
37053 value: function _debug(ctx, color) {
37054 if (this.barnesHutTree !== undefined) {
37055 ctx.lineWidth = 1;
37056
37057 this._drawBranch(this.barnesHutTree.root, ctx, color);
37058 }
37059 }
37060 /**
37061 * This function is for debugging purposes. It draws the branches recursively.
37062 *
37063 * @param {Object} branch
37064 * @param {CanvasRenderingContext2D} ctx
37065 * @param {string} color
37066 * @private
37067 */
37068
37069 }, {
37070 key: "_drawBranch",
37071 value: function _drawBranch(branch, ctx, color) {
37072 if (color === undefined) {
37073 color = "#FF0000";
37074 }
37075
37076 if (branch.childrenCount === 4) {
37077 this._drawBranch(branch.children.NW, ctx);
37078
37079 this._drawBranch(branch.children.NE, ctx);
37080
37081 this._drawBranch(branch.children.SE, ctx);
37082
37083 this._drawBranch(branch.children.SW, ctx);
37084 }
37085
37086 ctx.strokeStyle = color;
37087 ctx.beginPath();
37088 ctx.moveTo(branch.range.minX, branch.range.minY);
37089 ctx.lineTo(branch.range.maxX, branch.range.minY);
37090 ctx.stroke();
37091 ctx.beginPath();
37092 ctx.moveTo(branch.range.maxX, branch.range.minY);
37093 ctx.lineTo(branch.range.maxX, branch.range.maxY);
37094 ctx.stroke();
37095 ctx.beginPath();
37096 ctx.moveTo(branch.range.maxX, branch.range.maxY);
37097 ctx.lineTo(branch.range.minX, branch.range.maxY);
37098 ctx.stroke();
37099 ctx.beginPath();
37100 ctx.moveTo(branch.range.minX, branch.range.maxY);
37101 ctx.lineTo(branch.range.minX, branch.range.minY);
37102 ctx.stroke();
37103 /*
37104 if (branch.mass > 0) {
37105 ctx.circle(branch.centerOfMass.x, branch.centerOfMass.y, 3*branch.mass);
37106 ctx.stroke();
37107 }
37108 */
37109 }
37110 }]);
37111
37112 return BarnesHutSolver;
37113}();
37114
37115/**
37116 * Repulsion Solver
37117 */
37118var RepulsionSolver =
37119/*#__PURE__*/
37120function () {
37121 /**
37122 * @param {Object} body
37123 * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
37124 * @param {Object} options
37125 */
37126 function RepulsionSolver(body, physicsBody, options) {
37127 _classCallCheck(this, RepulsionSolver);
37128
37129 this.body = body;
37130 this.physicsBody = physicsBody;
37131 this.setOptions(options);
37132 }
37133 /**
37134 *
37135 * @param {Object} options
37136 */
37137
37138
37139 _createClass(RepulsionSolver, [{
37140 key: "setOptions",
37141 value: function setOptions(options) {
37142 this.options = options;
37143 }
37144 /**
37145 * Calculate the forces the nodes apply on each other based on a repulsion field.
37146 * This field is linearly approximated.
37147 *
37148 * @private
37149 */
37150
37151 }, {
37152 key: "solve",
37153 value: function solve() {
37154 var dx, dy, distance, fx, fy, repulsingForce, node1, node2;
37155 var nodes = this.body.nodes;
37156 var nodeIndices = this.physicsBody.physicsNodeIndices;
37157 var forces = this.physicsBody.forces; // repulsing forces between nodes
37158
37159 var nodeDistance = this.options.nodeDistance; // approximation constants
37160
37161 var a = -2 / 3 / nodeDistance;
37162 var b = 4 / 3; // we loop from i over all but the last entree in the array
37163 // j loops from i+1 to the last. This way we do not double count any of the indices, nor i === j
37164
37165 for (var i = 0; i < nodeIndices.length - 1; i++) {
37166 node1 = nodes[nodeIndices[i]];
37167
37168 for (var j = i + 1; j < nodeIndices.length; j++) {
37169 node2 = nodes[nodeIndices[j]];
37170 dx = node2.x - node1.x;
37171 dy = node2.y - node1.y;
37172 distance = Math.sqrt(dx * dx + dy * dy); // same condition as BarnesHutSolver, making sure nodes are never 100% overlapping.
37173
37174 if (distance === 0) {
37175 distance = 0.1 * Math.random();
37176 dx = distance;
37177 }
37178
37179 if (distance < 2 * nodeDistance) {
37180 if (distance < 0.5 * nodeDistance) {
37181 repulsingForce = 1.0;
37182 } else {
37183 repulsingForce = a * distance + b; // linear approx of 1 / (1 + Math.exp((distance / nodeDistance - 1) * steepness))
37184 }
37185
37186 repulsingForce = repulsingForce / distance;
37187 fx = dx * repulsingForce;
37188 fy = dy * repulsingForce;
37189 forces[node1.id].x -= fx;
37190 forces[node1.id].y -= fy;
37191 forces[node2.id].x += fx;
37192 forces[node2.id].y += fy;
37193 }
37194 }
37195 }
37196 }
37197 }]);
37198
37199 return RepulsionSolver;
37200}();
37201
37202/**
37203 * Hierarchical Repulsion Solver
37204 */
37205var HierarchicalRepulsionSolver =
37206/*#__PURE__*/
37207function () {
37208 /**
37209 * @param {Object} body
37210 * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
37211 * @param {Object} options
37212 */
37213 function HierarchicalRepulsionSolver(body, physicsBody, options) {
37214 _classCallCheck(this, HierarchicalRepulsionSolver);
37215
37216 this.body = body;
37217 this.physicsBody = physicsBody;
37218 this.setOptions(options);
37219 }
37220 /**
37221 *
37222 * @param {Object} options
37223 */
37224
37225
37226 _createClass(HierarchicalRepulsionSolver, [{
37227 key: "setOptions",
37228 value: function setOptions(options) {
37229 this.options = options;
37230 this.overlapAvoidanceFactor = Math.max(0, Math.min(1, this.options.avoidOverlap || 0));
37231 }
37232 /**
37233 * Calculate the forces the nodes apply on each other based on a repulsion field.
37234 * This field is linearly approximated.
37235 *
37236 * @private
37237 */
37238
37239 }, {
37240 key: "solve",
37241 value: function solve() {
37242 var nodes = this.body.nodes;
37243 var nodeIndices = this.physicsBody.physicsNodeIndices;
37244 var forces = this.physicsBody.forces; // repulsing forces between nodes
37245
37246 var nodeDistance = this.options.nodeDistance; // we loop from i over all but the last entree in the array
37247 // j loops from i+1 to the last. This way we do not double count any of the indices, nor i === j
37248
37249 for (var i = 0; i < nodeIndices.length - 1; i++) {
37250 var node1 = nodes[nodeIndices[i]];
37251
37252 for (var j = i + 1; j < nodeIndices.length; j++) {
37253 var node2 = nodes[nodeIndices[j]]; // nodes only affect nodes on their level
37254
37255 if (node1.level === node2.level) {
37256 var theseNodesDistance = nodeDistance + this.overlapAvoidanceFactor * ((node1.shape.radius || 0) / 2 + (node2.shape.radius || 0) / 2);
37257 var dx = node2.x - node1.x;
37258 var dy = node2.y - node1.y;
37259 var distance = Math.sqrt(dx * dx + dy * dy);
37260 var steepness = 0.05;
37261 var repulsingForce = void 0;
37262
37263 if (distance < theseNodesDistance) {
37264 repulsingForce = -Math.pow(steepness * distance, 2) + Math.pow(steepness * theseNodesDistance, 2);
37265 } else {
37266 repulsingForce = 0;
37267 } // normalize force with
37268
37269
37270 if (distance === 0) {
37271 distance = (_readOnlyError("distance"), 0.01);
37272 } else {
37273 repulsingForce = repulsingForce / distance;
37274 }
37275
37276 var fx = dx * repulsingForce;
37277 var fy = dy * repulsingForce;
37278 forces[node1.id].x -= fx;
37279 forces[node1.id].y -= fy;
37280 forces[node2.id].x += fx;
37281 forces[node2.id].y += fy;
37282 }
37283 }
37284 }
37285 }
37286 }]);
37287
37288 return HierarchicalRepulsionSolver;
37289}();
37290
37291/**
37292 * Spring Solver
37293 */
37294var SpringSolver =
37295/*#__PURE__*/
37296function () {
37297 /**
37298 * @param {Object} body
37299 * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
37300 * @param {Object} options
37301 */
37302 function SpringSolver(body, physicsBody, options) {
37303 _classCallCheck(this, SpringSolver);
37304
37305 this.body = body;
37306 this.physicsBody = physicsBody;
37307 this.setOptions(options);
37308 }
37309 /**
37310 *
37311 * @param {Object} options
37312 */
37313
37314
37315 _createClass(SpringSolver, [{
37316 key: "setOptions",
37317 value: function setOptions(options) {
37318 this.options = options;
37319 }
37320 /**
37321 * This function calculates the springforces on the nodes, accounting for the support nodes.
37322 *
37323 * @private
37324 */
37325
37326 }, {
37327 key: "solve",
37328 value: function solve() {
37329 var edgeLength, edge;
37330 var edgeIndices = this.physicsBody.physicsEdgeIndices;
37331 var edges = this.body.edges;
37332 var node1, node2, node3; // forces caused by the edges, modelled as springs
37333
37334 for (var i = 0; i < edgeIndices.length; i++) {
37335 edge = edges[edgeIndices[i]];
37336
37337 if (edge.connected === true && edge.toId !== edge.fromId) {
37338 // only calculate forces if nodes are in the same sector
37339 if (this.body.nodes[edge.toId] !== undefined && this.body.nodes[edge.fromId] !== undefined) {
37340 if (edge.edgeType.via !== undefined) {
37341 edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length;
37342 node1 = edge.to;
37343 node2 = edge.edgeType.via;
37344 node3 = edge.from;
37345
37346 this._calculateSpringForce(node1, node2, 0.5 * edgeLength);
37347
37348 this._calculateSpringForce(node2, node3, 0.5 * edgeLength);
37349 } else {
37350 // the * 1.5 is here so the edge looks as large as a smooth edge. It does not initially because the smooth edges use
37351 // the support nodes which exert a repulsive force on the to and from nodes, making the edge appear larger.
37352 edgeLength = edge.options.length === undefined ? this.options.springLength * 1.5 : edge.options.length;
37353
37354 this._calculateSpringForce(edge.from, edge.to, edgeLength);
37355 }
37356 }
37357 }
37358 }
37359 }
37360 /**
37361 * This is the code actually performing the calculation for the function above.
37362 *
37363 * @param {Node} node1
37364 * @param {Node} node2
37365 * @param {number} edgeLength
37366 * @private
37367 */
37368
37369 }, {
37370 key: "_calculateSpringForce",
37371 value: function _calculateSpringForce(node1, node2, edgeLength) {
37372 var dx = node1.x - node2.x;
37373 var dy = node1.y - node2.y;
37374 var distance = Math.max(Math.sqrt(dx * dx + dy * dy), 0.01); // the 1/distance is so the fx and fy can be calculated without sine or cosine.
37375
37376 var springForce = this.options.springConstant * (edgeLength - distance) / distance;
37377 var fx = dx * springForce;
37378 var fy = dy * springForce; // handle the case where one node is not part of the physcis
37379
37380 if (this.physicsBody.forces[node1.id] !== undefined) {
37381 this.physicsBody.forces[node1.id].x += fx;
37382 this.physicsBody.forces[node1.id].y += fy;
37383 }
37384
37385 if (this.physicsBody.forces[node2.id] !== undefined) {
37386 this.physicsBody.forces[node2.id].x -= fx;
37387 this.physicsBody.forces[node2.id].y -= fy;
37388 }
37389 }
37390 }]);
37391
37392 return SpringSolver;
37393}();
37394
37395/**
37396 * Hierarchical Spring Solver
37397 */
37398var HierarchicalSpringSolver =
37399/*#__PURE__*/
37400function () {
37401 /**
37402 * @param {Object} body
37403 * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
37404 * @param {Object} options
37405 */
37406 function HierarchicalSpringSolver(body, physicsBody, options) {
37407 _classCallCheck(this, HierarchicalSpringSolver);
37408
37409 this.body = body;
37410 this.physicsBody = physicsBody;
37411 this.setOptions(options);
37412 }
37413 /**
37414 *
37415 * @param {Object} options
37416 */
37417
37418
37419 _createClass(HierarchicalSpringSolver, [{
37420 key: "setOptions",
37421 value: function setOptions(options) {
37422 this.options = options;
37423 }
37424 /**
37425 * This function calculates the springforces on the nodes, accounting for the support nodes.
37426 *
37427 * @private
37428 */
37429
37430 }, {
37431 key: "solve",
37432 value: function solve() {
37433 var edgeLength, edge;
37434 var dx, dy, fx, fy, springForce, distance;
37435 var edges = this.body.edges;
37436 var factor = 0.5;
37437 var edgeIndices = this.physicsBody.physicsEdgeIndices;
37438 var nodeIndices = this.physicsBody.physicsNodeIndices;
37439 var forces = this.physicsBody.forces; // initialize the spring force counters
37440
37441 for (var i = 0; i < nodeIndices.length; i++) {
37442 var nodeId = nodeIndices[i];
37443 forces[nodeId].springFx = 0;
37444 forces[nodeId].springFy = 0;
37445 } // forces caused by the edges, modelled as springs
37446
37447
37448 for (var _i = 0; _i < edgeIndices.length; _i++) {
37449 edge = edges[edgeIndices[_i]];
37450
37451 if (edge.connected === true) {
37452 edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length;
37453 dx = edge.from.x - edge.to.x;
37454 dy = edge.from.y - edge.to.y;
37455 distance = Math.sqrt(dx * dx + dy * dy);
37456 distance = distance === 0 ? 0.01 : distance; // the 1/distance is so the fx and fy can be calculated without sine or cosine.
37457
37458 springForce = this.options.springConstant * (edgeLength - distance) / distance;
37459 fx = dx * springForce;
37460 fy = dy * springForce;
37461
37462 if (edge.to.level != edge.from.level) {
37463 if (forces[edge.toId] !== undefined) {
37464 forces[edge.toId].springFx -= fx;
37465 forces[edge.toId].springFy -= fy;
37466 }
37467
37468 if (forces[edge.fromId] !== undefined) {
37469 forces[edge.fromId].springFx += fx;
37470 forces[edge.fromId].springFy += fy;
37471 }
37472 } else {
37473 if (forces[edge.toId] !== undefined) {
37474 forces[edge.toId].x -= factor * fx;
37475 forces[edge.toId].y -= factor * fy;
37476 }
37477
37478 if (forces[edge.fromId] !== undefined) {
37479 forces[edge.fromId].x += factor * fx;
37480 forces[edge.fromId].y += factor * fy;
37481 }
37482 }
37483 }
37484 } // normalize spring forces
37485
37486
37487 springForce = 1;
37488 var springFx, springFy;
37489
37490 for (var _i2 = 0; _i2 < nodeIndices.length; _i2++) {
37491 var _nodeId = nodeIndices[_i2];
37492 springFx = Math.min(springForce, Math.max(-springForce, forces[_nodeId].springFx));
37493 springFy = Math.min(springForce, Math.max(-springForce, forces[_nodeId].springFy));
37494 forces[_nodeId].x += springFx;
37495 forces[_nodeId].y += springFy;
37496 } // retain energy balance
37497
37498
37499 var totalFx = 0;
37500 var totalFy = 0;
37501
37502 for (var _i3 = 0; _i3 < nodeIndices.length; _i3++) {
37503 var _nodeId2 = nodeIndices[_i3];
37504 totalFx += forces[_nodeId2].x;
37505 totalFy += forces[_nodeId2].y;
37506 }
37507
37508 var correctionFx = totalFx / nodeIndices.length;
37509 var correctionFy = totalFy / nodeIndices.length;
37510
37511 for (var _i4 = 0; _i4 < nodeIndices.length; _i4++) {
37512 var _nodeId3 = nodeIndices[_i4];
37513 forces[_nodeId3].x -= correctionFx;
37514 forces[_nodeId3].y -= correctionFy;
37515 }
37516 }
37517 }]);
37518
37519 return HierarchicalSpringSolver;
37520}();
37521
37522/**
37523 * Central Gravity Solver
37524 */
37525var CentralGravitySolver =
37526/*#__PURE__*/
37527function () {
37528 /**
37529 * @param {Object} body
37530 * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
37531 * @param {Object} options
37532 */
37533 function CentralGravitySolver(body, physicsBody, options) {
37534 _classCallCheck(this, CentralGravitySolver);
37535
37536 this.body = body;
37537 this.physicsBody = physicsBody;
37538 this.setOptions(options);
37539 }
37540 /**
37541 *
37542 * @param {Object} options
37543 */
37544
37545
37546 _createClass(CentralGravitySolver, [{
37547 key: "setOptions",
37548 value: function setOptions(options) {
37549 this.options = options;
37550 }
37551 /**
37552 * Calculates forces for each node
37553 */
37554
37555 }, {
37556 key: "solve",
37557 value: function solve() {
37558 var dx, dy, distance, node;
37559 var nodes = this.body.nodes;
37560 var nodeIndices = this.physicsBody.physicsNodeIndices;
37561 var forces = this.physicsBody.forces;
37562
37563 for (var i = 0; i < nodeIndices.length; i++) {
37564 var nodeId = nodeIndices[i];
37565 node = nodes[nodeId];
37566 dx = -node.x;
37567 dy = -node.y;
37568 distance = Math.sqrt(dx * dx + dy * dy);
37569
37570 this._calculateForces(distance, dx, dy, forces, node);
37571 }
37572 }
37573 /**
37574 * Calculate the forces based on the distance.
37575 * @param {number} distance
37576 * @param {number} dx
37577 * @param {number} dy
37578 * @param {Object<Node.id, vis.Node>} forces
37579 * @param {Node} node
37580 * @private
37581 */
37582
37583 }, {
37584 key: "_calculateForces",
37585 value: function _calculateForces(distance, dx, dy, forces, node) {
37586 var gravityForce = distance === 0 ? 0 : this.options.centralGravity / distance;
37587 forces[node.id].x = dx * gravityForce;
37588 forces[node.id].y = dy * gravityForce;
37589 }
37590 }]);
37591
37592 return CentralGravitySolver;
37593}();
37594
37595/**
37596 * @extends BarnesHutSolver
37597 */
37598
37599var ForceAtlas2BasedRepulsionSolver =
37600/*#__PURE__*/
37601function (_BarnesHutSolver) {
37602 _inherits(ForceAtlas2BasedRepulsionSolver, _BarnesHutSolver);
37603
37604 /**
37605 * @param {Object} body
37606 * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
37607 * @param {Object} options
37608 */
37609 function ForceAtlas2BasedRepulsionSolver(body, physicsBody, options) {
37610 _classCallCheck(this, ForceAtlas2BasedRepulsionSolver);
37611
37612 return _possibleConstructorReturn(this, _getPrototypeOf(ForceAtlas2BasedRepulsionSolver).call(this, body, physicsBody, options));
37613 }
37614 /**
37615 * Calculate the forces based on the distance.
37616 *
37617 * @param {number} distance
37618 * @param {number} dx
37619 * @param {number} dy
37620 * @param {Node} node
37621 * @param {Object} parentBranch
37622 * @private
37623 */
37624
37625
37626 _createClass(ForceAtlas2BasedRepulsionSolver, [{
37627 key: "_calculateForces",
37628 value: function _calculateForces(distance, dx, dy, node, parentBranch) {
37629 if (distance === 0) {
37630 distance = 0.1 * Math.random();
37631 dx = distance;
37632 }
37633
37634 if (this.overlapAvoidanceFactor < 1 && node.shape.radius) {
37635 distance = Math.max(0.1 + this.overlapAvoidanceFactor * node.shape.radius, distance - node.shape.radius);
37636 }
37637
37638 var degree = node.edges.length + 1; // the dividing by the distance cubed instead of squared allows us to get the fx and fy components without sines and cosines
37639 // it is shorthand for gravityforce with distance squared and fx = dx/distance * gravityForce
37640
37641 var gravityForce = this.options.gravitationalConstant * parentBranch.mass * node.options.mass * degree / Math.pow(distance, 2);
37642 var fx = dx * gravityForce;
37643 var fy = dy * gravityForce;
37644 this.physicsBody.forces[node.id].x += fx;
37645 this.physicsBody.forces[node.id].y += fy;
37646 }
37647 }]);
37648
37649 return ForceAtlas2BasedRepulsionSolver;
37650}(BarnesHutSolver);
37651
37652/**
37653 * @extends CentralGravitySolver
37654 */
37655
37656var ForceAtlas2BasedCentralGravitySolver =
37657/*#__PURE__*/
37658function (_CentralGravitySolver) {
37659 _inherits(ForceAtlas2BasedCentralGravitySolver, _CentralGravitySolver);
37660
37661 /**
37662 * @param {Object} body
37663 * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
37664 * @param {Object} options
37665 */
37666 function ForceAtlas2BasedCentralGravitySolver(body, physicsBody, options) {
37667 _classCallCheck(this, ForceAtlas2BasedCentralGravitySolver);
37668
37669 return _possibleConstructorReturn(this, _getPrototypeOf(ForceAtlas2BasedCentralGravitySolver).call(this, body, physicsBody, options));
37670 }
37671 /**
37672 * Calculate the forces based on the distance.
37673 *
37674 * @param {number} distance
37675 * @param {number} dx
37676 * @param {number} dy
37677 * @param {Object<Node.id, Node>} forces
37678 * @param {Node} node
37679 * @private
37680 */
37681
37682
37683 _createClass(ForceAtlas2BasedCentralGravitySolver, [{
37684 key: "_calculateForces",
37685 value: function _calculateForces(distance, dx, dy, forces, node) {
37686 if (distance > 0) {
37687 var degree = node.edges.length + 1;
37688 var gravityForce = this.options.centralGravity * degree * node.options.mass;
37689 forces[node.id].x = dx * gravityForce;
37690 forces[node.id].y = dy * gravityForce;
37691 }
37692 }
37693 }]);
37694
37695 return ForceAtlas2BasedCentralGravitySolver;
37696}(CentralGravitySolver);
37697
37698/**
37699 * The physics engine
37700 */
37701
37702var PhysicsEngine =
37703/*#__PURE__*/
37704function () {
37705 /**
37706 * @param {Object} body
37707 */
37708 function PhysicsEngine(body) {
37709 _classCallCheck(this, PhysicsEngine);
37710
37711 this.body = body;
37712 this.physicsBody = {
37713 physicsNodeIndices: [],
37714 physicsEdgeIndices: [],
37715 forces: {},
37716 velocities: {}
37717 };
37718 this.physicsEnabled = true;
37719 this.simulationInterval = 1000 / 60;
37720 this.requiresTimeout = true;
37721 this.previousStates = {};
37722 this.referenceState = {};
37723 this.freezeCache = {};
37724 this.renderTimer = undefined; // parameters for the adaptive timestep
37725
37726 this.adaptiveTimestep = false;
37727 this.adaptiveTimestepEnabled = false;
37728 this.adaptiveCounter = 0;
37729 this.adaptiveInterval = 3;
37730 this.stabilized = false;
37731 this.startedStabilization = false;
37732 this.stabilizationIterations = 0;
37733 this.ready = false; // will be set to true if the stabilize
37734 // default options
37735
37736 this.options = {};
37737 this.defaultOptions = {
37738 enabled: true,
37739 barnesHut: {
37740 theta: 0.5,
37741 gravitationalConstant: -2000,
37742 centralGravity: 0.3,
37743 springLength: 95,
37744 springConstant: 0.04,
37745 damping: 0.09,
37746 avoidOverlap: 0
37747 },
37748 forceAtlas2Based: {
37749 theta: 0.5,
37750 gravitationalConstant: -50,
37751 centralGravity: 0.01,
37752 springConstant: 0.08,
37753 springLength: 100,
37754 damping: 0.4,
37755 avoidOverlap: 0
37756 },
37757 repulsion: {
37758 centralGravity: 0.2,
37759 springLength: 200,
37760 springConstant: 0.05,
37761 nodeDistance: 100,
37762 damping: 0.09,
37763 avoidOverlap: 0
37764 },
37765 hierarchicalRepulsion: {
37766 centralGravity: 0.0,
37767 springLength: 100,
37768 springConstant: 0.01,
37769 nodeDistance: 120,
37770 damping: 0.09
37771 },
37772 maxVelocity: 50,
37773 minVelocity: 0.75,
37774 // px/s
37775 solver: 'barnesHut',
37776 stabilization: {
37777 enabled: true,
37778 iterations: 1000,
37779 // maximum number of iteration to stabilize
37780 updateInterval: 50,
37781 onlyDynamicEdges: false,
37782 fit: true
37783 },
37784 timestep: 0.5,
37785 adaptiveTimestep: true
37786 };
37787 extend(this.options, this.defaultOptions);
37788 this.timestep = 0.5;
37789 this.layoutFailed = false;
37790 this.bindEventListeners();
37791 }
37792 /**
37793 * Binds event listeners
37794 */
37795
37796
37797 _createClass(PhysicsEngine, [{
37798 key: "bindEventListeners",
37799 value: function bindEventListeners() {
37800 var _this = this;
37801
37802 this.body.emitter.on('initPhysics', function () {
37803 _this.initPhysics();
37804 });
37805 this.body.emitter.on('_layoutFailed', function () {
37806 _this.layoutFailed = true;
37807 });
37808 this.body.emitter.on('resetPhysics', function () {
37809 _this.stopSimulation();
37810
37811 _this.ready = false;
37812 });
37813 this.body.emitter.on('disablePhysics', function () {
37814 _this.physicsEnabled = false;
37815
37816 _this.stopSimulation();
37817 });
37818 this.body.emitter.on('restorePhysics', function () {
37819 _this.setOptions(_this.options);
37820
37821 if (_this.ready === true) {
37822 _this.startSimulation();
37823 }
37824 });
37825 this.body.emitter.on('startSimulation', function () {
37826 if (_this.ready === true) {
37827 _this.startSimulation();
37828 }
37829 });
37830 this.body.emitter.on('stopSimulation', function () {
37831 _this.stopSimulation();
37832 });
37833 this.body.emitter.on('destroy', function () {
37834 _this.stopSimulation(false);
37835
37836 _this.body.emitter.off();
37837 });
37838 this.body.emitter.on("_dataChanged", function () {
37839 // Nodes and/or edges have been added or removed, update shortcut lists.
37840 _this.updatePhysicsData();
37841 }); // debug: show forces
37842 // this.body.emitter.on("afterDrawing", (ctx) => {this._drawForces(ctx);});
37843 }
37844 /**
37845 * set the physics options
37846 * @param {Object} options
37847 */
37848
37849 }, {
37850 key: "setOptions",
37851 value: function setOptions(options) {
37852 if (options !== undefined) {
37853 if (options === false) {
37854 this.options.enabled = false;
37855 this.physicsEnabled = false;
37856 this.stopSimulation();
37857 } else if (options === true) {
37858 this.options.enabled = true;
37859 this.physicsEnabled = true;
37860 this.startSimulation();
37861 } else {
37862 this.physicsEnabled = true;
37863 selectiveNotDeepExtend(['stabilization'], this.options, options);
37864 mergeOptions(this.options, options, 'stabilization');
37865
37866 if (options.enabled === undefined) {
37867 this.options.enabled = true;
37868 }
37869
37870 if (this.options.enabled === false) {
37871 this.physicsEnabled = false;
37872 this.stopSimulation();
37873 } // set the timestep
37874
37875
37876 this.timestep = this.options.timestep;
37877 }
37878 }
37879
37880 this.init();
37881 }
37882 /**
37883 * configure the engine.
37884 */
37885
37886 }, {
37887 key: "init",
37888 value: function init() {
37889 var options;
37890
37891 if (this.options.solver === 'forceAtlas2Based') {
37892 options = this.options.forceAtlas2Based;
37893 this.nodesSolver = new ForceAtlas2BasedRepulsionSolver(this.body, this.physicsBody, options);
37894 this.edgesSolver = new SpringSolver(this.body, this.physicsBody, options);
37895 this.gravitySolver = new ForceAtlas2BasedCentralGravitySolver(this.body, this.physicsBody, options);
37896 } else if (this.options.solver === 'repulsion') {
37897 options = this.options.repulsion;
37898 this.nodesSolver = new RepulsionSolver(this.body, this.physicsBody, options);
37899 this.edgesSolver = new SpringSolver(this.body, this.physicsBody, options);
37900 this.gravitySolver = new CentralGravitySolver(this.body, this.physicsBody, options);
37901 } else if (this.options.solver === 'hierarchicalRepulsion') {
37902 options = this.options.hierarchicalRepulsion;
37903 this.nodesSolver = new HierarchicalRepulsionSolver(this.body, this.physicsBody, options);
37904 this.edgesSolver = new HierarchicalSpringSolver(this.body, this.physicsBody, options);
37905 this.gravitySolver = new CentralGravitySolver(this.body, this.physicsBody, options);
37906 } else {
37907 // barnesHut
37908 options = this.options.barnesHut;
37909 this.nodesSolver = new BarnesHutSolver(this.body, this.physicsBody, options);
37910 this.edgesSolver = new SpringSolver(this.body, this.physicsBody, options);
37911 this.gravitySolver = new CentralGravitySolver(this.body, this.physicsBody, options);
37912 }
37913
37914 this.modelOptions = options;
37915 }
37916 /**
37917 * initialize the engine
37918 */
37919
37920 }, {
37921 key: "initPhysics",
37922 value: function initPhysics() {
37923 if (this.physicsEnabled === true && this.options.enabled === true) {
37924 if (this.options.stabilization.enabled === true) {
37925 this.stabilize();
37926 } else {
37927 this.stabilized = false;
37928 this.ready = true;
37929 this.body.emitter.emit('fit', {}, this.layoutFailed); // if the layout failed, we use the approximation for the zoom
37930
37931 this.startSimulation();
37932 }
37933 } else {
37934 this.ready = true;
37935 this.body.emitter.emit('fit');
37936 }
37937 }
37938 /**
37939 * Start the simulation
37940 */
37941
37942 }, {
37943 key: "startSimulation",
37944 value: function startSimulation() {
37945 if (this.physicsEnabled === true && this.options.enabled === true) {
37946 this.stabilized = false; // when visible, adaptivity is disabled.
37947
37948 this.adaptiveTimestep = false; // this sets the width of all nodes initially which could be required for the avoidOverlap
37949
37950 this.body.emitter.emit("_resizeNodes");
37951
37952 if (this.viewFunction === undefined) {
37953 this.viewFunction = this.simulationStep.bind(this);
37954 this.body.emitter.on('initRedraw', this.viewFunction);
37955 this.body.emitter.emit('_startRendering');
37956 }
37957 } else {
37958 this.body.emitter.emit('_redraw');
37959 }
37960 }
37961 /**
37962 * Stop the simulation, force stabilization.
37963 * @param {boolean} [emit=true]
37964 */
37965
37966 }, {
37967 key: "stopSimulation",
37968 value: function stopSimulation() {
37969 var emit = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
37970 this.stabilized = true;
37971
37972 if (emit === true) {
37973 this._emitStabilized();
37974 }
37975
37976 if (this.viewFunction !== undefined) {
37977 this.body.emitter.off('initRedraw', this.viewFunction);
37978 this.viewFunction = undefined;
37979
37980 if (emit === true) {
37981 this.body.emitter.emit('_stopRendering');
37982 }
37983 }
37984 }
37985 /**
37986 * The viewFunction inserts this step into each render loop. It calls the physics tick and handles the cleanup at stabilized.
37987 *
37988 */
37989
37990 }, {
37991 key: "simulationStep",
37992 value: function simulationStep() {
37993 // check if the physics have settled
37994 var startTime = Date.now();
37995 this.physicsTick();
37996 var physicsTime = Date.now() - startTime; // run double speed if it is a little graph
37997
37998 if ((physicsTime < 0.4 * this.simulationInterval || this.runDoubleSpeed === true) && this.stabilized === false) {
37999 this.physicsTick(); // this makes sure there is no jitter. The decision is taken once to run it at double speed.
38000
38001 this.runDoubleSpeed = true;
38002 }
38003
38004 if (this.stabilized === true) {
38005 this.stopSimulation();
38006 }
38007 }
38008 /**
38009 * trigger the stabilized event.
38010 *
38011 * @param {number} [amountOfIterations=this.stabilizationIterations]
38012 * @private
38013 */
38014
38015 }, {
38016 key: "_emitStabilized",
38017 value: function _emitStabilized() {
38018 var _this2 = this;
38019
38020 var amountOfIterations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.stabilizationIterations;
38021
38022 if (this.stabilizationIterations > 1 || this.startedStabilization === true) {
38023 setTimeout(function () {
38024 _this2.body.emitter.emit('stabilized', {
38025 iterations: amountOfIterations
38026 });
38027
38028 _this2.startedStabilization = false;
38029 _this2.stabilizationIterations = 0;
38030 }, 0);
38031 }
38032 }
38033 /**
38034 * Calculate the forces for one physics iteration and move the nodes.
38035 * @private
38036 */
38037
38038 }, {
38039 key: "physicsStep",
38040 value: function physicsStep() {
38041 this.gravitySolver.solve();
38042 this.nodesSolver.solve();
38043 this.edgesSolver.solve();
38044 this.moveNodes();
38045 }
38046 /**
38047 * Make dynamic adjustments to the timestep, based on current state.
38048 *
38049 * Helper function for physicsTick().
38050 * @private
38051 */
38052
38053 }, {
38054 key: "adjustTimeStep",
38055 value: function adjustTimeStep() {
38056 var factor = 1.2; // Factor for increasing the timestep on success.
38057 // we compare the two steps. if it is acceptable we double the step.
38058
38059 if (this._evaluateStepQuality() === true) {
38060 this.timestep = factor * this.timestep;
38061 } else {
38062 // if not, we decrease the step to a minimum of the options timestep.
38063 // if the decreased timestep is smaller than the options step, we do not reset the counter
38064 // we assume that the options timestep is stable enough.
38065 if (this.timestep / factor < this.options.timestep) {
38066 this.timestep = this.options.timestep;
38067 } else {
38068 // if the timestep was larger than 2 times the option one we check the adaptivity again to ensure
38069 // that large instabilities do not form.
38070 this.adaptiveCounter = -1; // check again next iteration
38071
38072 this.timestep = Math.max(this.options.timestep, this.timestep / factor);
38073 }
38074 }
38075 }
38076 /**
38077 * A single simulation step (or 'tick') in the physics simulation
38078 *
38079 * @private
38080 */
38081
38082 }, {
38083 key: "physicsTick",
38084 value: function physicsTick() {
38085 this._startStabilizing(); // this ensures that there is no start event when the network is already stable.
38086
38087
38088 if (this.stabilized === true) return; // adaptivity means the timestep adapts to the situation, only applicable for stabilization
38089
38090 if (this.adaptiveTimestep === true && this.adaptiveTimestepEnabled === true) {
38091 // timestep remains stable for "interval" iterations.
38092 var doAdaptive = this.adaptiveCounter % this.adaptiveInterval === 0;
38093
38094 if (doAdaptive) {
38095 // first the big step and revert.
38096 this.timestep = 2 * this.timestep;
38097 this.physicsStep();
38098 this.revert(); // saves the reference state
38099 // now the normal step. Since this is the last step, it is the more stable one and we will take this.
38100
38101 this.timestep = 0.5 * this.timestep; // since it's half the step, we do it twice.
38102
38103 this.physicsStep();
38104 this.physicsStep();
38105 this.adjustTimeStep();
38106 } else {
38107 this.physicsStep(); // normal step, keeping timestep constant
38108 }
38109
38110 this.adaptiveCounter += 1;
38111 } else {
38112 // case for the static timestep, we reset it to the one in options and take a normal step.
38113 this.timestep = this.options.timestep;
38114 this.physicsStep();
38115 }
38116
38117 if (this.stabilized === true) this.revert();
38118 this.stabilizationIterations++;
38119 }
38120 /**
38121 * Nodes and edges can have the physics toggles on or off. A collection of indices is created here so we can skip the check all the time.
38122 *
38123 * @private
38124 */
38125
38126 }, {
38127 key: "updatePhysicsData",
38128 value: function updatePhysicsData() {
38129 this.physicsBody.forces = {};
38130 this.physicsBody.physicsNodeIndices = [];
38131 this.physicsBody.physicsEdgeIndices = [];
38132 var nodes = this.body.nodes;
38133 var edges = this.body.edges; // get node indices for physics
38134
38135 for (var nodeId in nodes) {
38136 if (nodes.hasOwnProperty(nodeId)) {
38137 if (nodes[nodeId].options.physics === true) {
38138 this.physicsBody.physicsNodeIndices.push(nodes[nodeId].id);
38139 }
38140 }
38141 } // get edge indices for physics
38142
38143
38144 for (var edgeId in edges) {
38145 if (edges.hasOwnProperty(edgeId)) {
38146 if (edges[edgeId].options.physics === true) {
38147 this.physicsBody.physicsEdgeIndices.push(edges[edgeId].id);
38148 }
38149 }
38150 } // get the velocity and the forces vector
38151
38152
38153 for (var i = 0; i < this.physicsBody.physicsNodeIndices.length; i++) {
38154 var _nodeId = this.physicsBody.physicsNodeIndices[i];
38155 this.physicsBody.forces[_nodeId] = {
38156 x: 0,
38157 y: 0
38158 }; // forces can be reset because they are recalculated. Velocities have to persist.
38159
38160 if (this.physicsBody.velocities[_nodeId] === undefined) {
38161 this.physicsBody.velocities[_nodeId] = {
38162 x: 0,
38163 y: 0
38164 };
38165 }
38166 } // clean deleted nodes from the velocity vector
38167
38168
38169 for (var _nodeId2 in this.physicsBody.velocities) {
38170 if (nodes[_nodeId2] === undefined) {
38171 delete this.physicsBody.velocities[_nodeId2];
38172 }
38173 }
38174 }
38175 /**
38176 * Revert the simulation one step. This is done so after stabilization, every new start of the simulation will also say stabilized.
38177 */
38178
38179 }, {
38180 key: "revert",
38181 value: function revert() {
38182 var nodeIds = Object.keys(this.previousStates);
38183 var nodes = this.body.nodes;
38184 var velocities = this.physicsBody.velocities;
38185 this.referenceState = {};
38186
38187 for (var i = 0; i < nodeIds.length; i++) {
38188 var nodeId = nodeIds[i];
38189
38190 if (nodes[nodeId] !== undefined) {
38191 if (nodes[nodeId].options.physics === true) {
38192 this.referenceState[nodeId] = {
38193 positions: {
38194 x: nodes[nodeId].x,
38195 y: nodes[nodeId].y
38196 }
38197 };
38198 velocities[nodeId].x = this.previousStates[nodeId].vx;
38199 velocities[nodeId].y = this.previousStates[nodeId].vy;
38200 nodes[nodeId].x = this.previousStates[nodeId].x;
38201 nodes[nodeId].y = this.previousStates[nodeId].y;
38202 }
38203 } else {
38204 delete this.previousStates[nodeId];
38205 }
38206 }
38207 }
38208 /**
38209 * This compares the reference state to the current state
38210 *
38211 * @returns {boolean}
38212 * @private
38213 */
38214
38215 }, {
38216 key: "_evaluateStepQuality",
38217 value: function _evaluateStepQuality() {
38218 var dx, dy, dpos;
38219 var nodes = this.body.nodes;
38220 var reference = this.referenceState;
38221 var posThreshold = 0.3;
38222
38223 for (var nodeId in this.referenceState) {
38224 if (this.referenceState.hasOwnProperty(nodeId) && nodes[nodeId] !== undefined) {
38225 dx = nodes[nodeId].x - reference[nodeId].positions.x;
38226 dy = nodes[nodeId].y - reference[nodeId].positions.y;
38227 dpos = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
38228
38229 if (dpos > posThreshold) {
38230 return false;
38231 }
38232 }
38233 }
38234
38235 return true;
38236 }
38237 /**
38238 * move the nodes one timestep and check if they are stabilized
38239 */
38240
38241 }, {
38242 key: "moveNodes",
38243 value: function moveNodes() {
38244 var nodeIndices = this.physicsBody.physicsNodeIndices;
38245 var maxNodeVelocity = 0;
38246 var averageNodeVelocity = 0; // the velocity threshold (energy in the system) for the adaptivity toggle
38247
38248 var velocityAdaptiveThreshold = 5;
38249
38250 for (var i = 0; i < nodeIndices.length; i++) {
38251 var nodeId = nodeIndices[i];
38252
38253 var nodeVelocity = this._performStep(nodeId); // stabilized is true if stabilized is true and velocity is smaller than vmin --> all nodes must be stabilized
38254
38255
38256 maxNodeVelocity = Math.max(maxNodeVelocity, nodeVelocity);
38257 averageNodeVelocity += nodeVelocity;
38258 } // evaluating the stabilized and adaptiveTimestepEnabled conditions
38259
38260
38261 this.adaptiveTimestepEnabled = averageNodeVelocity / nodeIndices.length < velocityAdaptiveThreshold;
38262 this.stabilized = maxNodeVelocity < this.options.minVelocity;
38263 }
38264 /**
38265 * Calculate new velocity for a coordinate direction
38266 *
38267 * @param {number} v velocity for current coordinate
38268 * @param {number} f regular force for current coordinate
38269 * @param {number} m mass of current node
38270 * @returns {number} new velocity for current coordinate
38271 * @private
38272 */
38273
38274 }, {
38275 key: "calculateComponentVelocity",
38276 value: function calculateComponentVelocity(v, f, m) {
38277 var df = this.modelOptions.damping * v; // damping force
38278
38279 var a = (f - df) / m; // acceleration
38280
38281 v += a * this.timestep; // Put a limit on the velocities if it is really high
38282
38283 var maxV = this.options.maxVelocity || 1e9;
38284
38285 if (Math.abs(v) > maxV) {
38286 v = v > 0 ? maxV : -maxV;
38287 }
38288
38289 return v;
38290 }
38291 /**
38292 * Perform the actual step
38293 *
38294 * @param {Node.id} nodeId
38295 * @returns {number} the new velocity of given node
38296 * @private
38297 */
38298
38299 }, {
38300 key: "_performStep",
38301 value: function _performStep(nodeId) {
38302 var node = this.body.nodes[nodeId];
38303 var force = this.physicsBody.forces[nodeId];
38304 var velocity = this.physicsBody.velocities[nodeId]; // store the state so we can revert
38305
38306 this.previousStates[nodeId] = {
38307 x: node.x,
38308 y: node.y,
38309 vx: velocity.x,
38310 vy: velocity.y
38311 };
38312
38313 if (node.options.fixed.x === false) {
38314 velocity.x = this.calculateComponentVelocity(velocity.x, force.x, node.options.mass);
38315 node.x += velocity.x * this.timestep;
38316 } else {
38317 force.x = 0;
38318 velocity.x = 0;
38319 }
38320
38321 if (node.options.fixed.y === false) {
38322 velocity.y = this.calculateComponentVelocity(velocity.y, force.y, node.options.mass);
38323 node.y += velocity.y * this.timestep;
38324 } else {
38325 force.y = 0;
38326 velocity.y = 0;
38327 }
38328
38329 var totalVelocity = Math.sqrt(Math.pow(velocity.x, 2) + Math.pow(velocity.y, 2));
38330 return totalVelocity;
38331 }
38332 /**
38333 * When initializing and stabilizing, we can freeze nodes with a predefined position.
38334 * This greatly speeds up stabilization because only the supportnodes for the smoothCurves have to settle.
38335 *
38336 * @private
38337 */
38338
38339 }, {
38340 key: "_freezeNodes",
38341 value: function _freezeNodes() {
38342 var nodes = this.body.nodes;
38343
38344 for (var id in nodes) {
38345 if (nodes.hasOwnProperty(id)) {
38346 if (nodes[id].x && nodes[id].y) {
38347 var fixed = nodes[id].options.fixed;
38348 this.freezeCache[id] = {
38349 x: fixed.x,
38350 y: fixed.y
38351 };
38352 fixed.x = true;
38353 fixed.y = true;
38354 }
38355 }
38356 }
38357 }
38358 /**
38359 * Unfreezes the nodes that have been frozen by _freezeDefinedNodes.
38360 *
38361 * @private
38362 */
38363
38364 }, {
38365 key: "_restoreFrozenNodes",
38366 value: function _restoreFrozenNodes() {
38367 var nodes = this.body.nodes;
38368
38369 for (var id in nodes) {
38370 if (nodes.hasOwnProperty(id)) {
38371 if (this.freezeCache[id] !== undefined) {
38372 nodes[id].options.fixed.x = this.freezeCache[id].x;
38373 nodes[id].options.fixed.y = this.freezeCache[id].y;
38374 }
38375 }
38376 }
38377
38378 this.freezeCache = {};
38379 }
38380 /**
38381 * Find a stable position for all nodes
38382 *
38383 * @param {number} [iterations=this.options.stabilization.iterations]
38384 */
38385
38386 }, {
38387 key: "stabilize",
38388 value: function stabilize() {
38389 var _this3 = this;
38390
38391 var iterations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.options.stabilization.iterations;
38392
38393 if (typeof iterations !== 'number') {
38394 iterations = this.options.stabilization.iterations;
38395 console.log('The stabilize method needs a numeric amount of iterations. Switching to default: ', iterations);
38396 }
38397
38398 if (this.physicsBody.physicsNodeIndices.length === 0) {
38399 this.ready = true;
38400 return;
38401 } // enable adaptive timesteps
38402
38403
38404 this.adaptiveTimestep = this.options.adaptiveTimestep; // this sets the width of all nodes initially which could be required for the avoidOverlap
38405
38406 this.body.emitter.emit("_resizeNodes");
38407 this.stopSimulation(); // stop the render loop
38408
38409 this.stabilized = false; // block redraw requests
38410
38411 this.body.emitter.emit('_blockRedraw');
38412 this.targetIterations = iterations; // start the stabilization
38413
38414 if (this.options.stabilization.onlyDynamicEdges === true) {
38415 this._freezeNodes();
38416 }
38417
38418 this.stabilizationIterations = 0;
38419 setTimeout(function () {
38420 return _this3._stabilizationBatch();
38421 }, 0);
38422 }
38423 /**
38424 * If not already stabilizing, start it and emit a start event.
38425 *
38426 * @returns {boolean} true if stabilization started with this call
38427 * @private
38428 */
38429
38430 }, {
38431 key: "_startStabilizing",
38432 value: function _startStabilizing() {
38433 if (this.startedStabilization === true) return false;
38434 this.body.emitter.emit('startStabilizing');
38435 this.startedStabilization = true;
38436 return true;
38437 }
38438 /**
38439 * One batch of stabilization
38440 * @private
38441 */
38442
38443 }, {
38444 key: "_stabilizationBatch",
38445 value: function _stabilizationBatch() {
38446 var _this4 = this;
38447
38448 var running = function running() {
38449 return _this4.stabilized === false && _this4.stabilizationIterations < _this4.targetIterations;
38450 };
38451
38452 var sendProgress = function sendProgress() {
38453 _this4.body.emitter.emit('stabilizationProgress', {
38454 iterations: _this4.stabilizationIterations,
38455 total: _this4.targetIterations
38456 });
38457 };
38458
38459 if (this._startStabilizing()) {
38460 sendProgress(); // Ensure that there is at least one start event.
38461 }
38462
38463 var count = 0;
38464
38465 while (running() && count < this.options.stabilization.updateInterval) {
38466 this.physicsTick();
38467 count++;
38468 }
38469
38470 sendProgress();
38471
38472 if (running()) {
38473 setTimeout(this._stabilizationBatch.bind(this), 0);
38474 } else {
38475 this._finalizeStabilization();
38476 }
38477 }
38478 /**
38479 * Wrap up the stabilization, fit and emit the events.
38480 * @private
38481 */
38482
38483 }, {
38484 key: "_finalizeStabilization",
38485 value: function _finalizeStabilization() {
38486 this.body.emitter.emit('_allowRedraw');
38487
38488 if (this.options.stabilization.fit === true) {
38489 this.body.emitter.emit('fit');
38490 }
38491
38492 if (this.options.stabilization.onlyDynamicEdges === true) {
38493 this._restoreFrozenNodes();
38494 }
38495
38496 this.body.emitter.emit('stabilizationIterationsDone');
38497 this.body.emitter.emit('_requestRedraw');
38498
38499 if (this.stabilized === true) {
38500 this._emitStabilized();
38501 } else {
38502 this.startSimulation();
38503 }
38504
38505 this.ready = true;
38506 } //--------------------------- DEBUGGING BELOW ---------------------------//
38507
38508 /**
38509 * Debug function that display arrows for the forces currently active in the network.
38510 *
38511 * Use this when debugging only.
38512 *
38513 * @param {CanvasRenderingContext2D} ctx
38514 * @private
38515 */
38516
38517 }, {
38518 key: "_drawForces",
38519 value: function _drawForces(ctx) {
38520 for (var i = 0; i < this.physicsBody.physicsNodeIndices.length; i++) {
38521 var index = this.physicsBody.physicsNodeIndices[i];
38522 var node = this.body.nodes[index];
38523 var force = this.physicsBody.forces[index];
38524 var factor = 20;
38525 var colorFactor = 0.03;
38526 var forceSize = Math.sqrt(Math.pow(force.x, 2) + Math.pow(force.x, 2));
38527 var size = Math.min(Math.max(5, forceSize), 15);
38528 var arrowSize = 3 * size;
38529 var color = HSVToHex((180 - Math.min(1, Math.max(0, colorFactor * forceSize)) * 180) / 360, 1, 1);
38530 var point = {
38531 x: node.x + factor * force.x,
38532 y: node.y + factor * force.y
38533 };
38534 ctx.lineWidth = size;
38535 ctx.strokeStyle = color;
38536 ctx.beginPath();
38537 ctx.moveTo(node.x, node.y);
38538 ctx.lineTo(point.x, point.y);
38539 ctx.stroke();
38540 var angle = Math.atan2(force.y, force.x);
38541 ctx.fillStyle = color;
38542 EndPoints.draw(ctx, {
38543 type: 'arrow',
38544 point: point,
38545 angle: angle,
38546 length: arrowSize
38547 });
38548 ctx.fill();
38549 }
38550 }
38551 }]);
38552
38553 return PhysicsEngine;
38554}();
38555
38556var nativeReverse = [].reverse;
38557var test$2 = [1, 2]; // `Array.prototype.reverse` method
38558// https://tc39.github.io/ecma262/#sec-array.prototype.reverse
38559// fix for Safari 12.0 bug
38560// https://bugs.webkit.org/show_bug.cgi?id=188794
38561
38562_export({
38563 target: 'Array',
38564 proto: true,
38565 forced: String(test$2) === String(test$2.reverse())
38566}, {
38567 reverse: function reverse() {
38568 if (isArray(this)) this.length = this.length;
38569 return nativeReverse.call(this);
38570 }
38571});
38572
38573/**
38574 * Utility Class
38575 */
38576
38577var NetworkUtil =
38578/*#__PURE__*/
38579function () {
38580 /**
38581 * @ignore
38582 */
38583 function NetworkUtil() {
38584 _classCallCheck(this, NetworkUtil);
38585 }
38586 /**
38587 * Find the center position of the network considering the bounding boxes
38588 *
38589 * @param {Array.<Node>} allNodes
38590 * @param {Array.<Node>} [specificNodes=[]]
38591 * @returns {{minX: number, maxX: number, minY: number, maxY: number}}
38592 * @static
38593 */
38594
38595
38596 _createClass(NetworkUtil, null, [{
38597 key: "getRange",
38598 value: function getRange(allNodes) {
38599 var specificNodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
38600 var minY = 1e9,
38601 maxY = -1e9,
38602 minX = 1e9,
38603 maxX = -1e9,
38604 node;
38605
38606 if (specificNodes.length > 0) {
38607 for (var i = 0; i < specificNodes.length; i++) {
38608 node = allNodes[specificNodes[i]];
38609
38610 if (minX > node.shape.boundingBox.left) {
38611 minX = node.shape.boundingBox.left;
38612 }
38613
38614 if (maxX < node.shape.boundingBox.right) {
38615 maxX = node.shape.boundingBox.right;
38616 }
38617
38618 if (minY > node.shape.boundingBox.top) {
38619 minY = node.shape.boundingBox.top;
38620 } // top is negative, bottom is positive
38621
38622
38623 if (maxY < node.shape.boundingBox.bottom) {
38624 maxY = node.shape.boundingBox.bottom;
38625 } // top is negative, bottom is positive
38626
38627 }
38628 }
38629
38630 if (minX === 1e9 && maxX === -1e9 && minY === 1e9 && maxY === -1e9) {
38631 minY = 0, maxY = 0, minX = 0, maxX = 0;
38632 }
38633
38634 return {
38635 minX: minX,
38636 maxX: maxX,
38637 minY: minY,
38638 maxY: maxY
38639 };
38640 }
38641 /**
38642 * Find the center position of the network
38643 *
38644 * @param {Array.<Node>} allNodes
38645 * @param {Array.<Node>} [specificNodes=[]]
38646 * @returns {{minX: number, maxX: number, minY: number, maxY: number}}
38647 * @static
38648 */
38649
38650 }, {
38651 key: "getRangeCore",
38652 value: function getRangeCore(allNodes) {
38653 var specificNodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
38654 var minY = 1e9,
38655 maxY = -1e9,
38656 minX = 1e9,
38657 maxX = -1e9,
38658 node;
38659
38660 if (specificNodes.length > 0) {
38661 for (var i = 0; i < specificNodes.length; i++) {
38662 node = allNodes[specificNodes[i]];
38663
38664 if (minX > node.x) {
38665 minX = node.x;
38666 }
38667
38668 if (maxX < node.x) {
38669 maxX = node.x;
38670 }
38671
38672 if (minY > node.y) {
38673 minY = node.y;
38674 } // top is negative, bottom is positive
38675
38676
38677 if (maxY < node.y) {
38678 maxY = node.y;
38679 } // top is negative, bottom is positive
38680
38681 }
38682 }
38683
38684 if (minX === 1e9 && maxX === -1e9 && minY === 1e9 && maxY === -1e9) {
38685 minY = 0, maxY = 0, minX = 0, maxX = 0;
38686 }
38687
38688 return {
38689 minX: minX,
38690 maxX: maxX,
38691 minY: minY,
38692 maxY: maxY
38693 };
38694 }
38695 /**
38696 * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY};
38697 * @returns {{x: number, y: number}}
38698 * @static
38699 */
38700
38701 }, {
38702 key: "findCenter",
38703 value: function findCenter(range) {
38704 return {
38705 x: 0.5 * (range.maxX + range.minX),
38706 y: 0.5 * (range.maxY + range.minY)
38707 };
38708 }
38709 /**
38710 * This returns a clone of the options or options of the edge or node to be used for construction of new edges or check functions for new nodes.
38711 * @param {vis.Item} item
38712 * @param {'node'|undefined} type
38713 * @returns {{}}
38714 * @static
38715 */
38716
38717 }, {
38718 key: "cloneOptions",
38719 value: function cloneOptions(item, type) {
38720 var clonedOptions = {};
38721
38722 if (type === undefined || type === 'node') {
38723 deepExtend(clonedOptions, item.options, true);
38724 clonedOptions.x = item.x;
38725 clonedOptions.y = item.y;
38726 clonedOptions.amountOfConnections = item.edges.length;
38727 } else {
38728 deepExtend(clonedOptions, item.options, true);
38729 }
38730
38731 return clonedOptions;
38732 }
38733 }]);
38734
38735 return NetworkUtil;
38736}();
38737
38738/**
38739 * A Cluster is a special Node that allows a group of Nodes positioned closely together
38740 * to be represented by a single Cluster Node.
38741 *
38742 * @extends Node
38743 */
38744
38745var Cluster =
38746/*#__PURE__*/
38747function (_Node) {
38748 _inherits(Cluster, _Node);
38749
38750 /**
38751 * @param {Object} options
38752 * @param {Object} body
38753 * @param {Array.<HTMLImageElement>}imagelist
38754 * @param {Array} grouplist
38755 * @param {Object} globalOptions
38756 * @param {Object} defaultOptions Global default options for nodes
38757 */
38758 function Cluster(options, body, imagelist, grouplist, globalOptions, defaultOptions) {
38759 var _this;
38760
38761 _classCallCheck(this, Cluster);
38762
38763 _this = _possibleConstructorReturn(this, _getPrototypeOf(Cluster).call(this, options, body, imagelist, grouplist, globalOptions, defaultOptions));
38764 _this.isCluster = true;
38765 _this.containedNodes = {};
38766 _this.containedEdges = {};
38767 return _this;
38768 }
38769 /**
38770 * Transfer child cluster data to current and disconnect the child cluster.
38771 *
38772 * Please consult the header comment in 'Clustering.js' for the fields set here.
38773 *
38774 * @param {string|number} childClusterId id of child cluster to open
38775 */
38776
38777
38778 _createClass(Cluster, [{
38779 key: "_openChildCluster",
38780 value: function _openChildCluster(childClusterId) {
38781 var _this2 = this;
38782
38783 var childCluster = this.body.nodes[childClusterId];
38784
38785 if (this.containedNodes[childClusterId] === undefined) {
38786 throw new Error('node with id: ' + childClusterId + ' not in current cluster');
38787 }
38788
38789 if (!childCluster.isCluster) {
38790 throw new Error('node with id: ' + childClusterId + ' is not a cluster');
38791 } // Disconnect child cluster from current cluster
38792
38793
38794 delete this.containedNodes[childClusterId];
38795 forEach(childCluster.edges, function (edge) {
38796 delete _this2.containedEdges[edge.id];
38797 }); // Transfer nodes and edges
38798
38799 forEach(childCluster.containedNodes, function (node, nodeId) {
38800 _this2.containedNodes[nodeId] = node;
38801 });
38802 childCluster.containedNodes = {};
38803 forEach(childCluster.containedEdges, function (edge, edgeId) {
38804 _this2.containedEdges[edgeId] = edge;
38805 });
38806 childCluster.containedEdges = {}; // Transfer edges within cluster edges which are clustered
38807
38808 forEach(childCluster.edges, function (clusterEdge) {
38809 forEach(_this2.edges, function (parentClusterEdge) {
38810 // Assumption: a clustered edge can only be present in a single clustering edge
38811 // Not tested here
38812 var index = parentClusterEdge.clusteringEdgeReplacingIds.indexOf(clusterEdge.id);
38813 if (index === -1) return;
38814 forEach(clusterEdge.clusteringEdgeReplacingIds, function (srcId) {
38815 parentClusterEdge.clusteringEdgeReplacingIds.push(srcId); // Maintain correct bookkeeping for transferred edge
38816
38817 _this2.body.edges[srcId].edgeReplacedById = parentClusterEdge.id;
38818 }); // Remove cluster edge from parent cluster edge
38819
38820 parentClusterEdge.clusteringEdgeReplacingIds.splice(index, 1);
38821 });
38822 });
38823 childCluster.edges = [];
38824 }
38825 }]);
38826
38827 return Cluster;
38828}(Node);
38829
38830/**
38831 * The clustering engine
38832 */
38833
38834var ClusterEngine =
38835/*#__PURE__*/
38836function () {
38837 /**
38838 * @param {Object} body
38839 */
38840 function ClusterEngine(body) {
38841 var _this = this;
38842
38843 _classCallCheck(this, ClusterEngine);
38844
38845 this.body = body;
38846 this.clusteredNodes = {}; // key: node id, value: { clusterId: <id of cluster>, node: <node instance>}
38847
38848 this.clusteredEdges = {}; // key: edge id, value: restore information for given edge
38849
38850 this.options = {};
38851 this.defaultOptions = {};
38852 extend(this.options, this.defaultOptions);
38853 this.body.emitter.on('_resetData', function () {
38854 _this.clusteredNodes = {};
38855 _this.clusteredEdges = {};
38856 });
38857 }
38858 /**
38859 *
38860 * @param {number} hubsize
38861 * @param {Object} options
38862 */
38863
38864
38865 _createClass(ClusterEngine, [{
38866 key: "clusterByHubsize",
38867 value: function clusterByHubsize(hubsize, options) {
38868 if (hubsize === undefined) {
38869 hubsize = this._getHubSize();
38870 } else if (_typeof$1(hubsize) === "object") {
38871 options = this._checkOptions(hubsize);
38872 hubsize = this._getHubSize();
38873 }
38874
38875 var nodesToCluster = [];
38876
38877 for (var i = 0; i < this.body.nodeIndices.length; i++) {
38878 var node = this.body.nodes[this.body.nodeIndices[i]];
38879
38880 if (node.edges.length >= hubsize) {
38881 nodesToCluster.push(node.id);
38882 }
38883 }
38884
38885 for (var _i = 0; _i < nodesToCluster.length; _i++) {
38886 this.clusterByConnection(nodesToCluster[_i], options, true);
38887 }
38888
38889 this.body.emitter.emit('_dataChanged');
38890 }
38891 /**
38892 * loop over all nodes, check if they adhere to the condition and cluster if needed.
38893 * @param {Object} options
38894 * @param {boolean} [refreshData=true]
38895 */
38896
38897 }, {
38898 key: "cluster",
38899 value: function cluster() {
38900 var _this2 = this;
38901
38902 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
38903 var refreshData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
38904
38905 if (options.joinCondition === undefined) {
38906 throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options.");
38907 } // check if the options object is fine, append if needed
38908
38909
38910 options = this._checkOptions(options);
38911 var childNodesObj = {};
38912 var childEdgesObj = {}; // collect the nodes that will be in the cluster
38913
38914 forEach(this.body.nodes, function (node, nodeId) {
38915 if (node.options && options.joinCondition(node.options) === true) {
38916 childNodesObj[nodeId] = node; // collect the edges that will be in the cluster
38917
38918 forEach(node.edges, function (edge) {
38919 if (_this2.clusteredEdges[edge.id] === undefined) {
38920 childEdgesObj[edge.id] = edge;
38921 }
38922 });
38923 }
38924 });
38925
38926 this._cluster(childNodesObj, childEdgesObj, options, refreshData);
38927 }
38928 /**
38929 * Cluster all nodes in the network that have only X edges
38930 * @param {number} edgeCount
38931 * @param {Object} options
38932 * @param {boolean} [refreshData=true]
38933 */
38934
38935 }, {
38936 key: "clusterByEdgeCount",
38937 value: function clusterByEdgeCount(edgeCount, options) {
38938 var _this3 = this;
38939
38940 var refreshData = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
38941 options = this._checkOptions(options);
38942 var clusters = [];
38943 var usedNodes = {};
38944 var edge, edges, relevantEdgeCount; // collect the nodes that will be in the cluster
38945
38946 var _loop = function _loop(i) {
38947 var childNodesObj = {};
38948 var childEdgesObj = {};
38949 var nodeId = _this3.body.nodeIndices[i];
38950 var node = _this3.body.nodes[nodeId]; // if this node is already used in another cluster this session, we do not have to re-evaluate it.
38951
38952 if (usedNodes[nodeId] === undefined) {
38953 relevantEdgeCount = 0;
38954 edges = [];
38955
38956 for (var j = 0; j < node.edges.length; j++) {
38957 edge = node.edges[j];
38958
38959 if (_this3.clusteredEdges[edge.id] === undefined) {
38960 if (edge.toId !== edge.fromId) {
38961 relevantEdgeCount++;
38962 }
38963
38964 edges.push(edge);
38965 }
38966 } // this node qualifies, we collect its neighbours to start the clustering process.
38967
38968
38969 if (relevantEdgeCount === edgeCount) {
38970 checkJoinCondition = function checkJoinCondition(node) {
38971 if (options.joinCondition === undefined || options.joinCondition === null) {
38972 return true;
38973 }
38974
38975 var clonedOptions = NetworkUtil.cloneOptions(node);
38976 return options.joinCondition(clonedOptions);
38977 };
38978
38979 var gatheringSuccessful = true;
38980
38981 for (var _j = 0; _j < edges.length; _j++) {
38982 edge = edges[_j];
38983
38984 var childNodeId = _this3._getConnectedId(edge, nodeId); // add the nodes to the list by the join condition.
38985
38986
38987 if (checkJoinCondition(node)) {
38988 childEdgesObj[edge.id] = edge;
38989 childNodesObj[nodeId] = node;
38990 childNodesObj[childNodeId] = _this3.body.nodes[childNodeId];
38991 usedNodes[nodeId] = true;
38992 } else {
38993 // this node does not qualify after all.
38994 gatheringSuccessful = false;
38995 break;
38996 }
38997 } // add to the cluster queue
38998
38999
39000 if (Object.keys(childNodesObj).length > 0 && Object.keys(childEdgesObj).length > 0 && gatheringSuccessful === true) {
39001 /**
39002 * Search for cluster data that contains any of the node id's
39003 * @returns {Boolean} true if no joinCondition, otherwise return value of joinCondition
39004 */
39005 findClusterData = function findClusterData() {
39006 for (var n = 0; n < clusters.length; ++n) {
39007 // Search for a cluster containing any of the node id's
39008 for (var m in childNodesObj) {
39009 if (clusters[n].nodes[m] !== undefined) {
39010 return clusters[n];
39011 }
39012 }
39013 }
39014
39015 return undefined;
39016 }; // If any of the found nodes is part of a cluster found in this method,
39017 // add the current values to that cluster
39018
39019
39020 foundCluster = findClusterData();
39021
39022 if (foundCluster !== undefined) {
39023 // Add nodes to found cluster if not present
39024 for (var m in childNodesObj) {
39025 if (foundCluster.nodes[m] === undefined) {
39026 foundCluster.nodes[m] = childNodesObj[m];
39027 }
39028 } // Add edges to found cluster, if not present
39029
39030
39031 for (var _m in childEdgesObj) {
39032 if (foundCluster.edges[_m] === undefined) {
39033 foundCluster.edges[_m] = childEdgesObj[_m];
39034 }
39035 }
39036 } else {
39037 // Create a new cluster group
39038 clusters.push({
39039 nodes: childNodesObj,
39040 edges: childEdgesObj
39041 });
39042 }
39043 }
39044 }
39045 }
39046 };
39047
39048 for (var i = 0; i < this.body.nodeIndices.length; i++) {
39049 var checkJoinCondition;
39050 var findClusterData;
39051 var foundCluster;
39052
39053 _loop(i);
39054 }
39055
39056 for (var _i2 = 0; _i2 < clusters.length; _i2++) {
39057 this._cluster(clusters[_i2].nodes, clusters[_i2].edges, options, false);
39058 }
39059
39060 if (refreshData === true) {
39061 this.body.emitter.emit('_dataChanged');
39062 }
39063 }
39064 /**
39065 * Cluster all nodes in the network that have only 1 edge
39066 * @param {Object} options
39067 * @param {boolean} [refreshData=true]
39068 */
39069
39070 }, {
39071 key: "clusterOutliers",
39072 value: function clusterOutliers(options) {
39073 var refreshData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
39074 this.clusterByEdgeCount(1, options, refreshData);
39075 }
39076 /**
39077 * Cluster all nodes in the network that have only 2 edge
39078 * @param {Object} options
39079 * @param {boolean} [refreshData=true]
39080 */
39081
39082 }, {
39083 key: "clusterBridges",
39084 value: function clusterBridges(options) {
39085 var refreshData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
39086 this.clusterByEdgeCount(2, options, refreshData);
39087 }
39088 /**
39089 * suck all connected nodes of a node into the node.
39090 * @param {Node.id} nodeId
39091 * @param {Object} options
39092 * @param {boolean} [refreshData=true]
39093 */
39094
39095 }, {
39096 key: "clusterByConnection",
39097 value: function clusterByConnection(nodeId, options) {
39098 var refreshData = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
39099
39100 // kill conditions
39101 if (nodeId === undefined) {
39102 throw new Error("No nodeId supplied to clusterByConnection!");
39103 }
39104
39105 if (this.body.nodes[nodeId] === undefined) {
39106 throw new Error("The nodeId given to clusterByConnection does not exist!");
39107 }
39108
39109 var node = this.body.nodes[nodeId];
39110 options = this._checkOptions(options, node);
39111
39112 if (options.clusterNodeProperties.x === undefined) {
39113 options.clusterNodeProperties.x = node.x;
39114 }
39115
39116 if (options.clusterNodeProperties.y === undefined) {
39117 options.clusterNodeProperties.y = node.y;
39118 }
39119
39120 if (options.clusterNodeProperties.fixed === undefined) {
39121 options.clusterNodeProperties.fixed = {};
39122 options.clusterNodeProperties.fixed.x = node.options.fixed.x;
39123 options.clusterNodeProperties.fixed.y = node.options.fixed.y;
39124 }
39125
39126 var childNodesObj = {};
39127 var childEdgesObj = {};
39128 var parentNodeId = node.id;
39129 var parentClonedOptions = NetworkUtil.cloneOptions(node);
39130 childNodesObj[parentNodeId] = node; // collect the nodes that will be in the cluster
39131
39132 for (var i = 0; i < node.edges.length; i++) {
39133 var edge = node.edges[i];
39134
39135 if (this.clusteredEdges[edge.id] === undefined) {
39136 var childNodeId = this._getConnectedId(edge, parentNodeId); // if the child node is not in a cluster
39137
39138
39139 if (this.clusteredNodes[childNodeId] === undefined) {
39140 if (childNodeId !== parentNodeId) {
39141 if (options.joinCondition === undefined) {
39142 childEdgesObj[edge.id] = edge;
39143 childNodesObj[childNodeId] = this.body.nodes[childNodeId];
39144 } else {
39145 // clone the options and insert some additional parameters that could be interesting.
39146 var childClonedOptions = NetworkUtil.cloneOptions(this.body.nodes[childNodeId]);
39147
39148 if (options.joinCondition(parentClonedOptions, childClonedOptions) === true) {
39149 childEdgesObj[edge.id] = edge;
39150 childNodesObj[childNodeId] = this.body.nodes[childNodeId];
39151 }
39152 }
39153 } else {
39154 // swallow the edge if it is self-referencing.
39155 childEdgesObj[edge.id] = edge;
39156 }
39157 }
39158 }
39159 }
39160
39161 var childNodeIDs = Object.keys(childNodesObj).map(function (childNode) {
39162 return childNodesObj[childNode].id;
39163 });
39164
39165 for (childNode in childNodesObj) {
39166 if (!childNodesObj.hasOwnProperty(childNode)) continue;
39167 var childNode = childNodesObj[childNode];
39168
39169 for (var y = 0; y < childNode.edges.length; y++) {
39170 var childEdge = childNode.edges[y];
39171
39172 if (childNodeIDs.indexOf(this._getConnectedId(childEdge, childNode.id)) > -1) {
39173 childEdgesObj[childEdge.id] = childEdge;
39174 }
39175 }
39176 }
39177
39178 this._cluster(childNodesObj, childEdgesObj, options, refreshData);
39179 }
39180 /**
39181 * This function creates the edges that will be attached to the cluster
39182 * It looks for edges that are connected to the nodes from the "outside' of the cluster.
39183 *
39184 * @param {{Node.id: vis.Node}} childNodesObj
39185 * @param {{vis.Edge.id: vis.Edge}} childEdgesObj
39186 * @param {Object} clusterNodeProperties
39187 * @param {Object} clusterEdgeProperties
39188 * @private
39189 */
39190
39191 }, {
39192 key: "_createClusterEdges",
39193 value: function _createClusterEdges(childNodesObj, childEdgesObj, clusterNodeProperties, clusterEdgeProperties) {
39194 var edge, childNodeId, childNode, toId, fromId, otherNodeId; // loop over all child nodes and their edges to find edges going out of the cluster
39195 // these edges will be replaced by clusterEdges.
39196
39197 var childKeys = Object.keys(childNodesObj);
39198 var createEdges = [];
39199
39200 for (var i = 0; i < childKeys.length; i++) {
39201 childNodeId = childKeys[i];
39202 childNode = childNodesObj[childNodeId]; // construct new edges from the cluster to others
39203
39204 for (var j = 0; j < childNode.edges.length; j++) {
39205 edge = childNode.edges[j]; // we only handle edges that are visible to the system, not the disabled ones from the clustering process.
39206
39207 if (this.clusteredEdges[edge.id] === undefined) {
39208 // self-referencing edges will be added to the "hidden" list
39209 if (edge.toId == edge.fromId) {
39210 childEdgesObj[edge.id] = edge;
39211 } else {
39212 // set up the from and to.
39213 if (edge.toId == childNodeId) {
39214 // this is a double equals because ints and strings can be interchanged here.
39215 toId = clusterNodeProperties.id;
39216 fromId = edge.fromId;
39217 otherNodeId = fromId;
39218 } else {
39219 toId = edge.toId;
39220 fromId = clusterNodeProperties.id;
39221 otherNodeId = toId;
39222 }
39223 } // Only edges from the cluster outwards are being replaced.
39224
39225
39226 if (childNodesObj[otherNodeId] === undefined) {
39227 createEdges.push({
39228 edge: edge,
39229 fromId: fromId,
39230 toId: toId
39231 });
39232 }
39233 }
39234 }
39235 } //
39236 // Here we actually create the replacement edges.
39237 //
39238 // We could not do this in the loop above as the creation process
39239 // would add an edge to the edges array we are iterating over.
39240 //
39241 // NOTE: a clustered edge can have multiple base edges!
39242 //
39243
39244
39245 var newEdges = [];
39246 /**
39247 * Find a cluster edge which matches the given created edge.
39248 * @param {vis.Edge} createdEdge
39249 * @returns {vis.Edge}
39250 */
39251
39252 var getNewEdge = function getNewEdge(createdEdge) {
39253 for (var _j2 = 0; _j2 < newEdges.length; _j2++) {
39254 var newEdge = newEdges[_j2]; // We replace both to and from edges with a single cluster edge
39255
39256 var matchToDirection = createdEdge.fromId === newEdge.fromId && createdEdge.toId === newEdge.toId;
39257 var matchFromDirection = createdEdge.fromId === newEdge.toId && createdEdge.toId === newEdge.fromId;
39258
39259 if (matchToDirection || matchFromDirection) {
39260 return newEdge;
39261 }
39262 }
39263
39264 return null;
39265 };
39266
39267 for (var _j3 = 0; _j3 < createEdges.length; _j3++) {
39268 var createdEdge = createEdges[_j3];
39269 var _edge = createdEdge.edge;
39270 var newEdge = getNewEdge(createdEdge);
39271
39272 if (newEdge === null) {
39273 // Create a clustered edge for this connection
39274 newEdge = this._createClusteredEdge(createdEdge.fromId, createdEdge.toId, _edge, clusterEdgeProperties);
39275 newEdges.push(newEdge);
39276 } else {
39277 newEdge.clusteringEdgeReplacingIds.push(_edge.id);
39278 } // also reference the new edge in the old edge
39279
39280
39281 this.body.edges[_edge.id].edgeReplacedById = newEdge.id; // hide the replaced edge
39282
39283 this._backupEdgeOptions(_edge);
39284
39285 _edge.setOptions({
39286 physics: false
39287 });
39288 }
39289 }
39290 /**
39291 * This function checks the options that can be supplied to the different cluster functions
39292 * for certain fields and inserts defaults if needed
39293 * @param {Object} options
39294 * @returns {*}
39295 * @private
39296 */
39297
39298 }, {
39299 key: "_checkOptions",
39300 value: function _checkOptions() {
39301 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
39302
39303 if (options.clusterEdgeProperties === undefined) {
39304 options.clusterEdgeProperties = {};
39305 }
39306
39307 if (options.clusterNodeProperties === undefined) {
39308 options.clusterNodeProperties = {};
39309 }
39310
39311 return options;
39312 }
39313 /**
39314 *
39315 * @param {Object} childNodesObj | object with node objects, id as keys, same as childNodes except it also contains a source node
39316 * @param {Object} childEdgesObj | object with edge objects, id as keys
39317 * @param {Array} options | object with {clusterNodeProperties, clusterEdgeProperties, processProperties}
39318 * @param {boolean} refreshData | when true, do not wrap up
39319 * @private
39320 */
39321
39322 }, {
39323 key: "_cluster",
39324 value: function _cluster(childNodesObj, childEdgesObj, options) {
39325 var refreshData = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
39326 // Remove nodes which are already clustered
39327 var tmpNodesToRemove = [];
39328
39329 for (var nodeId in childNodesObj) {
39330 if (childNodesObj.hasOwnProperty(nodeId)) {
39331 if (this.clusteredNodes[nodeId] !== undefined) {
39332 tmpNodesToRemove.push(nodeId);
39333 }
39334 }
39335 }
39336
39337 for (var n = 0; n < tmpNodesToRemove.length; ++n) {
39338 delete childNodesObj[tmpNodesToRemove[n]];
39339 } // kill condition: no nodes don't bother
39340
39341
39342 if (Object.keys(childNodesObj).length == 0) {
39343 return;
39344 } // allow clusters of 1 if options allow
39345
39346
39347 if (Object.keys(childNodesObj).length == 1 && options.clusterNodeProperties.allowSingleNodeCluster != true) {
39348 return;
39349 }
39350
39351 var clusterNodeProperties = deepExtend({}, options.clusterNodeProperties); // construct the clusterNodeProperties
39352
39353 if (options.processProperties !== undefined) {
39354 // get the childNode options
39355 var childNodesOptions = [];
39356
39357 for (var _nodeId in childNodesObj) {
39358 if (childNodesObj.hasOwnProperty(_nodeId)) {
39359 var clonedOptions = NetworkUtil.cloneOptions(childNodesObj[_nodeId]);
39360 childNodesOptions.push(clonedOptions);
39361 }
39362 } // get cluster properties based on childNodes
39363
39364
39365 var childEdgesOptions = [];
39366
39367 for (var edgeId in childEdgesObj) {
39368 if (childEdgesObj.hasOwnProperty(edgeId)) {
39369 // these cluster edges will be removed on creation of the cluster.
39370 if (edgeId.substr(0, 12) !== "clusterEdge:") {
39371 var _clonedOptions = NetworkUtil.cloneOptions(childEdgesObj[edgeId], 'edge');
39372
39373 childEdgesOptions.push(_clonedOptions);
39374 }
39375 }
39376 }
39377
39378 clusterNodeProperties = options.processProperties(clusterNodeProperties, childNodesOptions, childEdgesOptions);
39379
39380 if (!clusterNodeProperties) {
39381 throw new Error("The processProperties function does not return properties!");
39382 }
39383 } // check if we have an unique id;
39384
39385
39386 if (clusterNodeProperties.id === undefined) {
39387 clusterNodeProperties.id = 'cluster:' + uuid4();
39388 }
39389
39390 var clusterId = clusterNodeProperties.id;
39391
39392 if (clusterNodeProperties.label === undefined) {
39393 clusterNodeProperties.label = 'cluster';
39394 } // give the clusterNode a position if it does not have one.
39395
39396
39397 var pos = undefined;
39398
39399 if (clusterNodeProperties.x === undefined) {
39400 pos = this._getClusterPosition(childNodesObj);
39401 clusterNodeProperties.x = pos.x;
39402 }
39403
39404 if (clusterNodeProperties.y === undefined) {
39405 if (pos === undefined) {
39406 pos = this._getClusterPosition(childNodesObj);
39407 }
39408
39409 clusterNodeProperties.y = pos.y;
39410 } // force the ID to remain the same
39411
39412
39413 clusterNodeProperties.id = clusterId; // create the cluster Node
39414 // Note that allowSingleNodeCluster, if present, is stored in the options as well
39415
39416 var clusterNode = this.body.functions.createNode(clusterNodeProperties, Cluster);
39417 clusterNode.containedNodes = childNodesObj;
39418 clusterNode.containedEdges = childEdgesObj; // cache a copy from the cluster edge properties if we have to reconnect others later on
39419
39420 clusterNode.clusterEdgeProperties = options.clusterEdgeProperties; // finally put the cluster node into global
39421
39422 this.body.nodes[clusterNodeProperties.id] = clusterNode;
39423
39424 this._clusterEdges(childNodesObj, childEdgesObj, clusterNodeProperties, options.clusterEdgeProperties); // set ID to undefined so no duplicates arise
39425
39426
39427 clusterNodeProperties.id = undefined; // wrap up
39428
39429 if (refreshData === true) {
39430 this.body.emitter.emit('_dataChanged');
39431 }
39432 }
39433 /**
39434 *
39435 * @param {Edge} edge
39436 * @private
39437 */
39438
39439 }, {
39440 key: "_backupEdgeOptions",
39441 value: function _backupEdgeOptions(edge) {
39442 if (this.clusteredEdges[edge.id] === undefined) {
39443 this.clusteredEdges[edge.id] = {
39444 physics: edge.options.physics
39445 };
39446 }
39447 }
39448 /**
39449 *
39450 * @param {Edge} edge
39451 * @private
39452 */
39453
39454 }, {
39455 key: "_restoreEdge",
39456 value: function _restoreEdge(edge) {
39457 var originalOptions = this.clusteredEdges[edge.id];
39458
39459 if (originalOptions !== undefined) {
39460 edge.setOptions({
39461 physics: originalOptions.physics
39462 });
39463 delete this.clusteredEdges[edge.id];
39464 }
39465 }
39466 /**
39467 * Check if a node is a cluster.
39468 * @param {Node.id} nodeId
39469 * @returns {*}
39470 */
39471
39472 }, {
39473 key: "isCluster",
39474 value: function isCluster(nodeId) {
39475 if (this.body.nodes[nodeId] !== undefined) {
39476 return this.body.nodes[nodeId].isCluster === true;
39477 } else {
39478 console.log("Node does not exist.");
39479 return false;
39480 }
39481 }
39482 /**
39483 * get the position of the cluster node based on what's inside
39484 * @param {object} childNodesObj | object with node objects, id as keys
39485 * @returns {{x: number, y: number}}
39486 * @private
39487 */
39488
39489 }, {
39490 key: "_getClusterPosition",
39491 value: function _getClusterPosition(childNodesObj) {
39492 var childKeys = Object.keys(childNodesObj);
39493 var minX = childNodesObj[childKeys[0]].x;
39494 var maxX = childNodesObj[childKeys[0]].x;
39495 var minY = childNodesObj[childKeys[0]].y;
39496 var maxY = childNodesObj[childKeys[0]].y;
39497 var node;
39498
39499 for (var i = 1; i < childKeys.length; i++) {
39500 node = childNodesObj[childKeys[i]];
39501 minX = node.x < minX ? node.x : minX;
39502 maxX = node.x > maxX ? node.x : maxX;
39503 minY = node.y < minY ? node.y : minY;
39504 maxY = node.y > maxY ? node.y : maxY;
39505 }
39506
39507 return {
39508 x: 0.5 * (minX + maxX),
39509 y: 0.5 * (minY + maxY)
39510 };
39511 }
39512 /**
39513 * Open a cluster by calling this function.
39514 * @param {vis.Edge.id} clusterNodeId | the ID of the cluster node
39515 * @param {Object} options
39516 * @param {boolean} refreshData | wrap up afterwards if not true
39517 */
39518
39519 }, {
39520 key: "openCluster",
39521 value: function openCluster(clusterNodeId, options) {
39522 var refreshData = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
39523
39524 // kill conditions
39525 if (clusterNodeId === undefined) {
39526 throw new Error("No clusterNodeId supplied to openCluster.");
39527 }
39528
39529 var clusterNode = this.body.nodes[clusterNodeId];
39530
39531 if (clusterNode === undefined) {
39532 throw new Error("The clusterNodeId supplied to openCluster does not exist.");
39533 }
39534
39535 if (clusterNode.isCluster !== true || clusterNode.containedNodes === undefined || clusterNode.containedEdges === undefined) {
39536 throw new Error("The node:" + clusterNodeId + " is not a valid cluster.");
39537 } // Check if current cluster is clustered itself
39538
39539
39540 var stack = this.findNode(clusterNodeId);
39541 var parentIndex = stack.indexOf(clusterNodeId) - 1;
39542
39543 if (parentIndex >= 0) {
39544 // Current cluster is clustered; transfer contained nodes and edges to parent
39545 var parentClusterNodeId = stack[parentIndex];
39546 var parentClusterNode = this.body.nodes[parentClusterNodeId]; // clustering.clusteredNodes and clustering.clusteredEdges remain unchanged
39547
39548 parentClusterNode._openChildCluster(clusterNodeId); // All components of child cluster node have been transferred. It can die now.
39549
39550
39551 delete this.body.nodes[clusterNodeId];
39552
39553 if (refreshData === true) {
39554 this.body.emitter.emit('_dataChanged');
39555 }
39556
39557 return;
39558 } // main body
39559
39560
39561 var containedNodes = clusterNode.containedNodes;
39562 var containedEdges = clusterNode.containedEdges; // allow the user to position the nodes after release.
39563
39564 if (options !== undefined && options.releaseFunction !== undefined && typeof options.releaseFunction === 'function') {
39565 var positions = {};
39566 var clusterPosition = {
39567 x: clusterNode.x,
39568 y: clusterNode.y
39569 };
39570
39571 for (var nodeId in containedNodes) {
39572 if (containedNodes.hasOwnProperty(nodeId)) {
39573 var containedNode = this.body.nodes[nodeId];
39574 positions[nodeId] = {
39575 x: containedNode.x,
39576 y: containedNode.y
39577 };
39578 }
39579 }
39580
39581 var newPositions = options.releaseFunction(clusterPosition, positions);
39582
39583 for (var _nodeId2 in containedNodes) {
39584 if (containedNodes.hasOwnProperty(_nodeId2)) {
39585 var _containedNode = this.body.nodes[_nodeId2];
39586
39587 if (newPositions[_nodeId2] !== undefined) {
39588 _containedNode.x = newPositions[_nodeId2].x === undefined ? clusterNode.x : newPositions[_nodeId2].x;
39589 _containedNode.y = newPositions[_nodeId2].y === undefined ? clusterNode.y : newPositions[_nodeId2].y;
39590 }
39591 }
39592 }
39593 } else {
39594 // copy the position from the cluster
39595 forEach(containedNodes, function (containedNode) {
39596 // inherit position
39597 if (containedNode.options.fixed.x === false) {
39598 containedNode.x = clusterNode.x;
39599 }
39600
39601 if (containedNode.options.fixed.y === false) {
39602 containedNode.y = clusterNode.y;
39603 }
39604 });
39605 } // release nodes
39606
39607
39608 for (var _nodeId3 in containedNodes) {
39609 if (containedNodes.hasOwnProperty(_nodeId3)) {
39610 var _containedNode2 = this.body.nodes[_nodeId3]; // inherit speed
39611
39612 _containedNode2.vx = clusterNode.vx;
39613 _containedNode2.vy = clusterNode.vy;
39614
39615 _containedNode2.setOptions({
39616 physics: true
39617 });
39618
39619 delete this.clusteredNodes[_nodeId3];
39620 }
39621 } // copy the clusterNode edges because we cannot iterate over an object that we add or remove from.
39622
39623
39624 var edgesToBeDeleted = [];
39625
39626 for (var i = 0; i < clusterNode.edges.length; i++) {
39627 edgesToBeDeleted.push(clusterNode.edges[i]);
39628 } // actually handling the deleting.
39629
39630
39631 for (var _i3 = 0; _i3 < edgesToBeDeleted.length; _i3++) {
39632 var edge = edgesToBeDeleted[_i3];
39633
39634 var otherNodeId = this._getConnectedId(edge, clusterNodeId);
39635
39636 var otherNode = this.clusteredNodes[otherNodeId];
39637
39638 for (var j = 0; j < edge.clusteringEdgeReplacingIds.length; j++) {
39639 var transferId = edge.clusteringEdgeReplacingIds[j];
39640 var transferEdge = this.body.edges[transferId];
39641 if (transferEdge === undefined) continue; // if the other node is in another cluster, we transfer ownership of this edge to the other cluster
39642
39643 if (otherNode !== undefined) {
39644 // transfer ownership:
39645 var otherCluster = this.body.nodes[otherNode.clusterId];
39646 otherCluster.containedEdges[transferEdge.id] = transferEdge; // delete local reference
39647
39648 delete containedEdges[transferEdge.id]; // get to and from
39649
39650 var fromId = transferEdge.fromId;
39651 var toId = transferEdge.toId;
39652
39653 if (transferEdge.toId == otherNodeId) {
39654 toId = otherNode.clusterId;
39655 } else {
39656 fromId = otherNode.clusterId;
39657 } // create new cluster edge from the otherCluster
39658
39659
39660 this._createClusteredEdge(fromId, toId, transferEdge, otherCluster.clusterEdgeProperties, {
39661 hidden: false,
39662 physics: true
39663 });
39664 } else {
39665 this._restoreEdge(transferEdge);
39666 }
39667 }
39668
39669 edge.remove();
39670 } // handle the releasing of the edges
39671
39672
39673 for (var edgeId in containedEdges) {
39674 if (containedEdges.hasOwnProperty(edgeId)) {
39675 this._restoreEdge(containedEdges[edgeId]);
39676 }
39677 } // remove clusterNode
39678
39679
39680 delete this.body.nodes[clusterNodeId];
39681
39682 if (refreshData === true) {
39683 this.body.emitter.emit('_dataChanged');
39684 }
39685 }
39686 /**
39687 *
39688 * @param {Cluster.id} clusterId
39689 * @returns {Array.<Node.id>}
39690 */
39691
39692 }, {
39693 key: "getNodesInCluster",
39694 value: function getNodesInCluster(clusterId) {
39695 var nodesArray = [];
39696
39697 if (this.isCluster(clusterId) === true) {
39698 var containedNodes = this.body.nodes[clusterId].containedNodes;
39699
39700 for (var nodeId in containedNodes) {
39701 if (containedNodes.hasOwnProperty(nodeId)) {
39702 nodesArray.push(this.body.nodes[nodeId].id);
39703 }
39704 }
39705 }
39706
39707 return nodesArray;
39708 }
39709 /**
39710 * Get the stack clusterId's that a certain node resides in. cluster A -> cluster B -> cluster C -> node
39711 *
39712 * If a node can't be found in the chain, return an empty array.
39713 *
39714 * @param {string|number} nodeId
39715 * @returns {Array}
39716 */
39717
39718 }, {
39719 key: "findNode",
39720 value: function findNode(nodeId) {
39721 var stack = [];
39722 var max = 100;
39723 var counter = 0;
39724 var node;
39725
39726 while (this.clusteredNodes[nodeId] !== undefined && counter < max) {
39727 node = this.body.nodes[nodeId];
39728 if (node === undefined) return [];
39729 stack.push(node.id);
39730 nodeId = this.clusteredNodes[nodeId].clusterId;
39731 counter++;
39732 }
39733
39734 node = this.body.nodes[nodeId];
39735 if (node === undefined) return [];
39736 stack.push(node.id);
39737 stack.reverse();
39738 return stack;
39739 }
39740 /**
39741 * Using a clustered nodeId, update with the new options
39742 * @param {vis.Edge.id} clusteredNodeId
39743 * @param {object} newOptions
39744 */
39745
39746 }, {
39747 key: "updateClusteredNode",
39748 value: function updateClusteredNode(clusteredNodeId, newOptions) {
39749 if (clusteredNodeId === undefined) {
39750 throw new Error("No clusteredNodeId supplied to updateClusteredNode.");
39751 }
39752
39753 if (newOptions === undefined) {
39754 throw new Error("No newOptions supplied to updateClusteredNode.");
39755 }
39756
39757 if (this.body.nodes[clusteredNodeId] === undefined) {
39758 throw new Error("The clusteredNodeId supplied to updateClusteredNode does not exist.");
39759 }
39760
39761 this.body.nodes[clusteredNodeId].setOptions(newOptions);
39762 this.body.emitter.emit('_dataChanged');
39763 }
39764 /**
39765 * Using a base edgeId, update all related clustered edges with the new options
39766 * @param {vis.Edge.id} startEdgeId
39767 * @param {object} newOptions
39768 */
39769
39770 }, {
39771 key: "updateEdge",
39772 value: function updateEdge(startEdgeId, newOptions) {
39773 if (startEdgeId === undefined) {
39774 throw new Error("No startEdgeId supplied to updateEdge.");
39775 }
39776
39777 if (newOptions === undefined) {
39778 throw new Error("No newOptions supplied to updateEdge.");
39779 }
39780
39781 if (this.body.edges[startEdgeId] === undefined) {
39782 throw new Error("The startEdgeId supplied to updateEdge does not exist.");
39783 }
39784
39785 var allEdgeIds = this.getClusteredEdges(startEdgeId);
39786
39787 for (var i = 0; i < allEdgeIds.length; i++) {
39788 var edge = this.body.edges[allEdgeIds[i]];
39789 edge.setOptions(newOptions);
39790 }
39791
39792 this.body.emitter.emit('_dataChanged');
39793 }
39794 /**
39795 * Get a stack of clusterEdgeId's (+base edgeid) that a base edge is the same as. cluster edge C -> cluster edge B -> cluster edge A -> base edge(edgeId)
39796 * @param {vis.Edge.id} edgeId
39797 * @returns {Array.<vis.Edge.id>}
39798 */
39799
39800 }, {
39801 key: "getClusteredEdges",
39802 value: function getClusteredEdges(edgeId) {
39803 var stack = [];
39804 var max = 100;
39805 var counter = 0;
39806
39807 while (edgeId !== undefined && this.body.edges[edgeId] !== undefined && counter < max) {
39808 stack.push(this.body.edges[edgeId].id);
39809 edgeId = this.body.edges[edgeId].edgeReplacedById;
39810 counter++;
39811 }
39812
39813 stack.reverse();
39814 return stack;
39815 }
39816 /**
39817 * Get the base edge id of clusterEdgeId. cluster edge (clusteredEdgeId) -> cluster edge B -> cluster edge C -> base edge
39818 * @param {vis.Edge.id} clusteredEdgeId
39819 * @returns {vis.Edge.id} baseEdgeId
39820 *
39821 * TODO: deprecate in 5.0.0. Method getBaseEdges() is the correct one to use.
39822 */
39823
39824 }, {
39825 key: "getBaseEdge",
39826 value: function getBaseEdge(clusteredEdgeId) {
39827 // Just kludge this by returning the first base edge id found
39828 return this.getBaseEdges(clusteredEdgeId)[0];
39829 }
39830 /**
39831 * Get all regular edges for this clustered edge id.
39832 *
39833 * @param {vis.Edge.id} clusteredEdgeId
39834 * @returns {Array.<vis.Edge.id>} all baseEdgeId's under this clustered edge
39835 */
39836
39837 }, {
39838 key: "getBaseEdges",
39839 value: function getBaseEdges(clusteredEdgeId) {
39840 var IdsToHandle = [clusteredEdgeId];
39841 var doneIds = [];
39842 var foundIds = [];
39843 var max = 100;
39844 var counter = 0;
39845
39846 while (IdsToHandle.length > 0 && counter < max) {
39847 var nextId = IdsToHandle.pop();
39848 if (nextId === undefined) continue; // Paranoia here and onwards
39849
39850 var nextEdge = this.body.edges[nextId];
39851 if (nextEdge === undefined) continue;
39852 counter++;
39853 var replacingIds = nextEdge.clusteringEdgeReplacingIds;
39854
39855 if (replacingIds === undefined) {
39856 // nextId is a base id
39857 foundIds.push(nextId);
39858 } else {
39859 // Another cluster edge, unravel this one as well
39860 for (var i = 0; i < replacingIds.length; ++i) {
39861 var replacingId = replacingIds[i]; // Don't add if already handled
39862 // TODO: never triggers; find a test-case which does
39863
39864 if (IdsToHandle.indexOf(replacingIds) !== -1 || doneIds.indexOf(replacingIds) !== -1) {
39865 continue;
39866 }
39867
39868 IdsToHandle.push(replacingId);
39869 }
39870 }
39871
39872 doneIds.push(nextId);
39873 }
39874
39875 return foundIds;
39876 }
39877 /**
39878 * Get the Id the node is connected to
39879 * @param {vis.Edge} edge
39880 * @param {Node.id} nodeId
39881 * @returns {*}
39882 * @private
39883 */
39884
39885 }, {
39886 key: "_getConnectedId",
39887 value: function _getConnectedId(edge, nodeId) {
39888 if (edge.toId != nodeId) {
39889 return edge.toId;
39890 } else if (edge.fromId != nodeId) {
39891 return edge.fromId;
39892 } else {
39893 return edge.fromId;
39894 }
39895 }
39896 /**
39897 * We determine how many connections denote an important hub.
39898 * We take the mean + 2*std as the important hub size. (Assuming a normal distribution of data, ~2.2%)
39899 *
39900 * @returns {number}
39901 * @private
39902 */
39903
39904 }, {
39905 key: "_getHubSize",
39906 value: function _getHubSize() {
39907 var average = 0;
39908 var averageSquared = 0;
39909 var hubCounter = 0;
39910 var largestHub = 0;
39911
39912 for (var i = 0; i < this.body.nodeIndices.length; i++) {
39913 var node = this.body.nodes[this.body.nodeIndices[i]];
39914
39915 if (node.edges.length > largestHub) {
39916 largestHub = node.edges.length;
39917 }
39918
39919 average += node.edges.length;
39920 averageSquared += Math.pow(node.edges.length, 2);
39921 hubCounter += 1;
39922 }
39923
39924 average = average / hubCounter;
39925 averageSquared = averageSquared / hubCounter;
39926 var variance = averageSquared - Math.pow(average, 2);
39927 var standardDeviation = Math.sqrt(variance);
39928 var hubThreshold = Math.floor(average + 2 * standardDeviation); // always have at least one to cluster
39929
39930 if (hubThreshold > largestHub) {
39931 hubThreshold = largestHub;
39932 }
39933
39934 return hubThreshold;
39935 }
39936 /**
39937 * Create an edge for the cluster representation.
39938 *
39939 * @param {Node.id} fromId
39940 * @param {Node.id} toId
39941 * @param {vis.Edge} baseEdge
39942 * @param {Object} clusterEdgeProperties
39943 * @param {Object} extraOptions
39944 * @returns {Edge} newly created clustered edge
39945 * @private
39946 */
39947
39948 }, {
39949 key: "_createClusteredEdge",
39950 value: function _createClusteredEdge(fromId, toId, baseEdge, clusterEdgeProperties, extraOptions) {
39951 // copy the options of the edge we will replace
39952 var clonedOptions = NetworkUtil.cloneOptions(baseEdge, 'edge'); // make sure the properties of clusterEdges are superimposed on it
39953
39954 deepExtend(clonedOptions, clusterEdgeProperties); // set up the edge
39955
39956 clonedOptions.from = fromId;
39957 clonedOptions.to = toId;
39958 clonedOptions.id = 'clusterEdge:' + uuid4(); // apply the edge specific options to it if specified
39959
39960 if (extraOptions !== undefined) {
39961 deepExtend(clonedOptions, extraOptions);
39962 }
39963
39964 var newEdge = this.body.functions.createEdge(clonedOptions);
39965 newEdge.clusteringEdgeReplacingIds = [baseEdge.id];
39966 newEdge.connect(); // Register the new edge
39967
39968 this.body.edges[newEdge.id] = newEdge;
39969 return newEdge;
39970 }
39971 /**
39972 * Add the passed child nodes and edges to the given cluster node.
39973 *
39974 * @param {Object|Node} childNodes hash of nodes or single node to add in cluster
39975 * @param {Object|Edge} childEdges hash of edges or single edge to take into account when clustering
39976 * @param {Node} clusterNode cluster node to add nodes and edges to
39977 * @param {Object} [clusterEdgeProperties]
39978 * @private
39979 */
39980
39981 }, {
39982 key: "_clusterEdges",
39983 value: function _clusterEdges(childNodes, childEdges, clusterNode, clusterEdgeProperties) {
39984 if (childEdges instanceof Edge) {
39985 var edge = childEdges;
39986 var obj = {};
39987 obj[edge.id] = edge;
39988 childEdges = obj;
39989 }
39990
39991 if (childNodes instanceof Node) {
39992 var node = childNodes;
39993 var _obj = {};
39994 _obj[node.id] = node;
39995 childNodes = _obj;
39996 }
39997
39998 if (clusterNode === undefined || clusterNode === null) {
39999 throw new Error("_clusterEdges: parameter clusterNode required");
40000 }
40001
40002 if (clusterEdgeProperties === undefined) {
40003 // Take the required properties from the cluster node
40004 clusterEdgeProperties = clusterNode.clusterEdgeProperties;
40005 } // create the new edges that will connect to the cluster.
40006 // All self-referencing edges will be added to childEdges here.
40007
40008
40009 this._createClusterEdges(childNodes, childEdges, clusterNode, clusterEdgeProperties); // disable the childEdges
40010
40011
40012 for (var edgeId in childEdges) {
40013 if (childEdges.hasOwnProperty(edgeId)) {
40014 if (this.body.edges[edgeId] !== undefined) {
40015 var _edge2 = this.body.edges[edgeId]; // cache the options before changing
40016
40017 this._backupEdgeOptions(_edge2); // disable physics and hide the edge
40018
40019
40020 _edge2.setOptions({
40021 physics: false
40022 });
40023 }
40024 }
40025 } // disable the childNodes
40026
40027
40028 for (var nodeId in childNodes) {
40029 if (childNodes.hasOwnProperty(nodeId)) {
40030 this.clusteredNodes[nodeId] = {
40031 clusterId: clusterNode.id,
40032 node: this.body.nodes[nodeId]
40033 };
40034 this.body.nodes[nodeId].setOptions({
40035 physics: false
40036 });
40037 }
40038 }
40039 }
40040 /**
40041 * Determine in which cluster given nodeId resides.
40042 *
40043 * If not in cluster, return undefined.
40044 *
40045 * NOTE: If you know a cleaner way to do this, please enlighten me (wimrijnders).
40046 *
40047 * @param {Node.id} nodeId
40048 * @returns {Node|undefined} Node instance for cluster, if present
40049 * @private
40050 */
40051
40052 }, {
40053 key: "_getClusterNodeForNode",
40054 value: function _getClusterNodeForNode(nodeId) {
40055 if (nodeId === undefined) return undefined;
40056 var clusteredNode = this.clusteredNodes[nodeId]; // NOTE: If no cluster info found, it should actually be an error
40057
40058 if (clusteredNode === undefined) return undefined;
40059 var clusterId = clusteredNode.clusterId;
40060 if (clusterId === undefined) return undefined;
40061 return this.body.nodes[clusterId];
40062 }
40063 /**
40064 * Internal helper function for conditionally removing items in array
40065 *
40066 * Done like this because Array.filter() is not fully supported by all IE's.
40067 *
40068 * @param {Array} arr
40069 * @param {function} callback
40070 * @returns {Array}
40071 * @private
40072 */
40073
40074 }, {
40075 key: "_filter",
40076 value: function _filter(arr, callback) {
40077 var ret = [];
40078 forEach(arr, function (item) {
40079 if (callback(item)) {
40080 ret.push(item);
40081 }
40082 });
40083 return ret;
40084 }
40085 /**
40086 * Scan all edges for changes in clustering and adjust this if necessary.
40087 *
40088 * Call this (internally) after there has been a change in node or edge data.
40089 *
40090 * Pre: States of this.body.nodes and this.body.edges consistent
40091 * Pre: this.clusteredNodes and this.clusteredEdge consistent with containedNodes and containedEdges
40092 * of cluster nodes.
40093 */
40094
40095 }, {
40096 key: "_updateState",
40097 value: function _updateState() {
40098 var _this4 = this;
40099
40100 var nodeId;
40101 var deletedNodeIds = [];
40102 var deletedEdgeIds = {};
40103 /**
40104 * Utility function to iterate over clustering nodes only
40105 *
40106 * @param {Function} callback function to call for each cluster node
40107 */
40108
40109 var eachClusterNode = function eachClusterNode(callback) {
40110 forEach(_this4.body.nodes, function (node) {
40111 if (node.isCluster === true) {
40112 callback(node);
40113 }
40114 });
40115 }; //
40116 // Remove deleted regular nodes from clustering
40117 //
40118 // Determine the deleted nodes
40119
40120
40121 for (nodeId in this.clusteredNodes) {
40122 if (!this.clusteredNodes.hasOwnProperty(nodeId)) continue;
40123 var node = this.body.nodes[nodeId];
40124
40125 if (node === undefined) {
40126 deletedNodeIds.push(nodeId);
40127 }
40128 } // Remove nodes from cluster nodes
40129
40130
40131 eachClusterNode(function (clusterNode) {
40132 for (var n = 0; n < deletedNodeIds.length; n++) {
40133 delete clusterNode.containedNodes[deletedNodeIds[n]];
40134 }
40135 }); // Remove nodes from cluster list
40136
40137 for (var n = 0; n < deletedNodeIds.length; n++) {
40138 delete this.clusteredNodes[deletedNodeIds[n]];
40139 } //
40140 // Remove deleted edges from clustering
40141 //
40142 // Add the deleted clustered edges to the list
40143
40144
40145 forEach(this.clusteredEdges, function (edgeId) {
40146 var edge = _this4.body.edges[edgeId];
40147
40148 if (edge === undefined || !edge.endPointsValid()) {
40149 deletedEdgeIds[edgeId] = edgeId;
40150 }
40151 }); // Cluster nodes can also contain edges which are not clustered,
40152 // i.e. nodes 1-2 within cluster with an edge in between.
40153 // So the cluster nodes also need to be scanned for invalid edges
40154
40155 eachClusterNode(function (clusterNode) {
40156 forEach(clusterNode.containedEdges, function (edge, edgeId) {
40157 if (!edge.endPointsValid() && !deletedEdgeIds[edgeId]) {
40158 deletedEdgeIds[edgeId] = edgeId;
40159 }
40160 });
40161 }); // Also scan for cluster edges which need to be removed in the active list.
40162 // Regular edges have been removed beforehand, so this only picks up the cluster edges.
40163
40164 forEach(this.body.edges, function (edge, edgeId) {
40165 // Explicitly scan the contained edges for validity
40166 var isValid = true;
40167 var replacedIds = edge.clusteringEdgeReplacingIds;
40168
40169 if (replacedIds !== undefined) {
40170 var numValid = 0;
40171 forEach(replacedIds, function (containedEdgeId) {
40172 var containedEdge = _this4.body.edges[containedEdgeId];
40173
40174 if (containedEdge !== undefined && containedEdge.endPointsValid()) {
40175 numValid += 1;
40176 }
40177 });
40178 isValid = numValid > 0;
40179 }
40180
40181 if (!edge.endPointsValid() || !isValid) {
40182 deletedEdgeIds[edgeId] = edgeId;
40183 }
40184 }); // Remove edges from cluster nodes
40185
40186 eachClusterNode(function (clusterNode) {
40187 forEach(deletedEdgeIds, function (deletedEdgeId) {
40188 delete clusterNode.containedEdges[deletedEdgeId];
40189 forEach(clusterNode.edges, function (edge, m) {
40190 if (edge.id === deletedEdgeId) {
40191 clusterNode.edges[m] = null; // Don't want to directly delete here, because in the loop
40192
40193 return;
40194 }
40195
40196 edge.clusteringEdgeReplacingIds = _this4._filter(edge.clusteringEdgeReplacingIds, function (id) {
40197 return !deletedEdgeIds[id];
40198 });
40199 }); // Clean up the nulls
40200
40201 clusterNode.edges = _this4._filter(clusterNode.edges, function (item) {
40202 return item !== null;
40203 });
40204 });
40205 }); // Remove from cluster list
40206
40207 forEach(deletedEdgeIds, function (edgeId) {
40208 delete _this4.clusteredEdges[edgeId];
40209 }); // Remove cluster edges from active list (this.body.edges).
40210 // deletedEdgeIds still contains id of regular edges, but these should all
40211 // be gone when you reach here.
40212
40213 forEach(deletedEdgeIds, function (edgeId) {
40214 delete _this4.body.edges[edgeId];
40215 }); //
40216 // Check changed cluster state of edges
40217 //
40218 // Iterating over keys here, because edges may be removed in the loop
40219
40220 var ids = Object.keys(this.body.edges);
40221 forEach(ids, function (edgeId) {
40222 var edge = _this4.body.edges[edgeId];
40223
40224 var shouldBeClustered = _this4._isClusteredNode(edge.fromId) || _this4._isClusteredNode(edge.toId);
40225
40226 if (shouldBeClustered === _this4._isClusteredEdge(edge.id)) {
40227 return; // all is well
40228 }
40229
40230 if (shouldBeClustered) {
40231 // add edge to clustering
40232 var clusterFrom = _this4._getClusterNodeForNode(edge.fromId);
40233
40234 if (clusterFrom !== undefined) {
40235 _this4._clusterEdges(_this4.body.nodes[edge.fromId], edge, clusterFrom);
40236 }
40237
40238 var clusterTo = _this4._getClusterNodeForNode(edge.toId);
40239
40240 if (clusterTo !== undefined) {
40241 _this4._clusterEdges(_this4.body.nodes[edge.toId], edge, clusterTo);
40242 } // TODO: check that it works for both edges clustered
40243 // (This might be paranoia)
40244
40245 } else {
40246 delete _this4._clusterEdges[edgeId];
40247
40248 _this4._restoreEdge(edge); // This should not be happening, the state should
40249 // be properly updated at this point.
40250 //
40251 // If it *is* reached during normal operation, then we have to implement
40252 // undo clustering for this edge here.
40253 // throw new Error('remove edge from clustering not implemented!')
40254
40255 }
40256 }); // Clusters may be nested to any level. Keep on opening until nothing to open
40257
40258 var changed = false;
40259 var continueLoop = true;
40260
40261 var _loop2 = function _loop2() {
40262 var clustersToOpen = []; // Determine the id's of clusters that need opening
40263
40264 eachClusterNode(function (clusterNode) {
40265 var numNodes = Object.keys(clusterNode.containedNodes).length;
40266 var allowSingle = clusterNode.options.allowSingleNodeCluster === true;
40267
40268 if (allowSingle && numNodes < 1 || !allowSingle && numNodes < 2) {
40269 clustersToOpen.push(clusterNode.id);
40270 }
40271 }); // Open them
40272
40273 for (var _n = 0; _n < clustersToOpen.length; ++_n) {
40274 _this4.openCluster(clustersToOpen[_n], {}, false
40275 /* Don't refresh, we're in an refresh/update already */
40276 );
40277 }
40278
40279 continueLoop = clustersToOpen.length > 0;
40280 changed = changed || continueLoop;
40281 };
40282
40283 while (continueLoop) {
40284 _loop2();
40285 }
40286
40287 if (changed) {
40288 this._updateState(); // Redo this method (recursion possible! should be safe)
40289
40290 }
40291 }
40292 /**
40293 * Determine if node with given id is part of a cluster.
40294 *
40295 * @param {Node.id} nodeId
40296 * @return {boolean} true if part of a cluster.
40297 */
40298
40299 }, {
40300 key: "_isClusteredNode",
40301 value: function _isClusteredNode(nodeId) {
40302 return this.clusteredNodes[nodeId] !== undefined;
40303 }
40304 /**
40305 * Determine if edge with given id is not visible due to clustering.
40306 *
40307 * An edge is considered clustered if:
40308 * - it is directly replaced by a clustering edge
40309 * - any of its connecting nodes is in a cluster
40310 *
40311 * @param {vis.Edge.id} edgeId
40312 * @return {boolean} true if part of a cluster.
40313 */
40314
40315 }, {
40316 key: "_isClusteredEdge",
40317 value: function _isClusteredEdge(edgeId) {
40318 return this.clusteredEdges[edgeId] !== undefined;
40319 }
40320 }]);
40321
40322 return ClusterEngine;
40323}();
40324
40325/**
40326 * Initializes window.requestAnimationFrame() to a usable form.
40327 *
40328 * Specifically, set up this method for the case of running on node.js with jsdom enabled.
40329 *
40330 * NOTES:
40331 *
40332 * * On node.js, when calling this directly outside of this class, `window` is not defined.
40333 * This happens even if jsdom is used.
40334 * * For node.js + jsdom, `window` is available at the moment the constructor is called.
40335 * For this reason, the called is placed within the constructor.
40336 * * Even then, `window.requestAnimationFrame()` is not defined, so it still needs to be added.
40337 * * During unit testing, it happens that the window object is reset during execution, causing
40338 * a runtime error due to missing `requestAnimationFrame()`. This needs to be compensated for,
40339 * see `_requestNextFrame()`.
40340 * * Since this is a global object, it may affect other modules besides `Network`. With normal
40341 * usage, this does not cause any problems. During unit testing, errors may occur. These have
40342 * been compensated for, see comment block in _requestNextFrame().
40343 *
40344 * @private
40345 */
40346function _initRequestAnimationFrame() {
40347 var func;
40348
40349 if (window !== undefined) {
40350 func = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
40351 }
40352
40353 if (func === undefined) {
40354 // window or method not present, setting mock requestAnimationFrame
40355 window.requestAnimationFrame = function (callback) {
40356 //console.log("Called mock requestAnimationFrame");
40357 callback();
40358 };
40359 } else {
40360 window.requestAnimationFrame = func;
40361 }
40362}
40363/**
40364 * The canvas renderer
40365 */
40366
40367var CanvasRenderer =
40368/*#__PURE__*/
40369function () {
40370 /**
40371 * @param {Object} body
40372 * @param {Canvas} canvas
40373 */
40374 function CanvasRenderer(body, canvas) {
40375 _classCallCheck(this, CanvasRenderer);
40376
40377 _initRequestAnimationFrame();
40378
40379 this.body = body;
40380 this.canvas = canvas;
40381 this.redrawRequested = false;
40382 this.renderTimer = undefined;
40383 this.requiresTimeout = true;
40384 this.renderingActive = false;
40385 this.renderRequests = 0;
40386 this.allowRedraw = true;
40387 this.dragging = false;
40388 this.zooming = false;
40389 this.options = {};
40390 this.defaultOptions = {
40391 hideEdgesOnDrag: false,
40392 hideEdgesOnZoom: false,
40393 hideNodesOnDrag: false
40394 };
40395 extend(this.options, this.defaultOptions);
40396
40397 this._determineBrowserMethod();
40398
40399 this.bindEventListeners();
40400 }
40401 /**
40402 * Binds event listeners
40403 */
40404
40405
40406 _createClass(CanvasRenderer, [{
40407 key: "bindEventListeners",
40408 value: function bindEventListeners() {
40409 var _this = this;
40410
40411 this.body.emitter.on("dragStart", function () {
40412 _this.dragging = true;
40413 });
40414 this.body.emitter.on("dragEnd", function () {
40415 _this.dragging = false;
40416 });
40417 this.body.emitter.on("zoom", function () {
40418 _this.zooming = true;
40419 window.clearTimeout(_this.zoomTimeoutId);
40420 _this.zoomTimeoutId = window.setTimeout(function () {
40421 _this.zooming = false;
40422
40423 _this._requestRedraw.bind(_this)();
40424 }, 250);
40425 });
40426 this.body.emitter.on("_resizeNodes", function () {
40427 _this._resizeNodes();
40428 });
40429 this.body.emitter.on("_redraw", function () {
40430 if (_this.renderingActive === false) {
40431 _this._redraw();
40432 }
40433 });
40434 this.body.emitter.on("_blockRedraw", function () {
40435 _this.allowRedraw = false;
40436 });
40437 this.body.emitter.on("_allowRedraw", function () {
40438 _this.allowRedraw = true;
40439 _this.redrawRequested = false;
40440 });
40441 this.body.emitter.on("_requestRedraw", this._requestRedraw.bind(this));
40442 this.body.emitter.on("_startRendering", function () {
40443 _this.renderRequests += 1;
40444 _this.renderingActive = true;
40445
40446 _this._startRendering();
40447 });
40448 this.body.emitter.on("_stopRendering", function () {
40449 _this.renderRequests -= 1;
40450 _this.renderingActive = _this.renderRequests > 0;
40451 _this.renderTimer = undefined;
40452 });
40453 this.body.emitter.on('destroy', function () {
40454 _this.renderRequests = 0;
40455 _this.allowRedraw = false;
40456 _this.renderingActive = false;
40457
40458 if (_this.requiresTimeout === true) {
40459 clearTimeout(_this.renderTimer);
40460 } else {
40461 window.cancelAnimationFrame(_this.renderTimer);
40462 }
40463
40464 _this.body.emitter.off();
40465 });
40466 }
40467 /**
40468 *
40469 * @param {Object} options
40470 */
40471
40472 }, {
40473 key: "setOptions",
40474 value: function setOptions(options) {
40475 if (options !== undefined) {
40476 var fields = ['hideEdgesOnDrag', 'hideEdgesOnZoom', 'hideNodesOnDrag'];
40477 selectiveDeepExtend(fields, this.options, options);
40478 }
40479 }
40480 /**
40481 * Prepare the drawing of the next frame.
40482 *
40483 * Calls the callback when the next frame can or will be drawn.
40484 *
40485 * @param {function} callback
40486 * @param {number} delay - timeout case only, wait this number of milliseconds
40487 * @returns {function|undefined}
40488 * @private
40489 */
40490
40491 }, {
40492 key: "_requestNextFrame",
40493 value: function _requestNextFrame(callback, delay) {
40494 // During unit testing, it happens that the mock window object is reset while
40495 // the next frame is still pending. Then, either 'window' is not present, or
40496 // 'requestAnimationFrame()' is not present because it is not defined on the
40497 // mock window object.
40498 //
40499 // As a consequence, unrelated unit tests may appear to fail, even if the problem
40500 // described happens in the current unit test.
40501 //
40502 // This is not something that will happen in normal operation, but we still need
40503 // to take it into account.
40504 //
40505 if (typeof window === 'undefined') return; // Doing `if (window === undefined)` does not work here!
40506
40507 var timer;
40508 var myWindow = window; // Grab a reference to reduce the possibility that 'window' is reset
40509 // while running this method.
40510
40511 if (this.requiresTimeout === true) {
40512 // wait given number of milliseconds and perform the animation step function
40513 timer = myWindow.setTimeout(callback, delay);
40514 } else {
40515 if (myWindow.requestAnimationFrame) {
40516 timer = myWindow.requestAnimationFrame(callback);
40517 }
40518 }
40519
40520 return timer;
40521 }
40522 /**
40523 *
40524 * @private
40525 */
40526
40527 }, {
40528 key: "_startRendering",
40529 value: function _startRendering() {
40530 if (this.renderingActive === true) {
40531 if (this.renderTimer === undefined) {
40532 this.renderTimer = this._requestNextFrame(this._renderStep.bind(this), this.simulationInterval);
40533 }
40534 }
40535 }
40536 /**
40537 *
40538 * @private
40539 */
40540
40541 }, {
40542 key: "_renderStep",
40543 value: function _renderStep() {
40544 if (this.renderingActive === true) {
40545 // reset the renderTimer so a new scheduled animation step can be set
40546 this.renderTimer = undefined;
40547
40548 if (this.requiresTimeout === true) {
40549 // this schedules a new simulation step
40550 this._startRendering();
40551 }
40552
40553 this._redraw();
40554
40555 if (this.requiresTimeout === false) {
40556 // this schedules a new simulation step
40557 this._startRendering();
40558 }
40559 }
40560 }
40561 /**
40562 * Redraw the network with the current data
40563 * chart will be resized too.
40564 */
40565
40566 }, {
40567 key: "redraw",
40568 value: function redraw() {
40569 this.body.emitter.emit('setSize');
40570
40571 this._redraw();
40572 }
40573 /**
40574 * Redraw the network with the current data
40575 * @private
40576 */
40577
40578 }, {
40579 key: "_requestRedraw",
40580 value: function _requestRedraw() {
40581 var _this2 = this;
40582
40583 if (this.redrawRequested !== true && this.renderingActive === false && this.allowRedraw === true) {
40584 this.redrawRequested = true;
40585
40586 this._requestNextFrame(function () {
40587 _this2._redraw(false);
40588 }, 0);
40589 }
40590 }
40591 /**
40592 * Redraw the network with the current data
40593 * @param {boolean} [hidden=false] | Used to get the first estimate of the node sizes.
40594 * Only the nodes are drawn after which they are quickly drawn over.
40595 * @private
40596 */
40597
40598 }, {
40599 key: "_redraw",
40600 value: function _redraw() {
40601 var hidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
40602
40603 if (this.allowRedraw === true) {
40604 this.body.emitter.emit("initRedraw");
40605 this.redrawRequested = false; // when the container div was hidden, this fixes it back up!
40606
40607 if (this.canvas.frame.canvas.width === 0 || this.canvas.frame.canvas.height === 0) {
40608 this.canvas.setSize();
40609 }
40610
40611 this.canvas.setTransform();
40612 var ctx = this.canvas.getContext(); // clear the canvas
40613
40614 var w = this.canvas.frame.canvas.clientWidth;
40615 var h = this.canvas.frame.canvas.clientHeight;
40616 ctx.clearRect(0, 0, w, h); // if the div is hidden, we stop the redraw here for performance.
40617
40618 if (this.canvas.frame.clientWidth === 0) {
40619 return;
40620 } // set scaling and translation
40621
40622
40623 ctx.save();
40624 ctx.translate(this.body.view.translation.x, this.body.view.translation.y);
40625 ctx.scale(this.body.view.scale, this.body.view.scale);
40626 ctx.beginPath();
40627 this.body.emitter.emit("beforeDrawing", ctx);
40628 ctx.closePath();
40629
40630 if (hidden === false) {
40631 if ((this.dragging === false || this.dragging === true && this.options.hideEdgesOnDrag === false) && (this.zooming === false || this.zooming === true && this.options.hideEdgesOnZoom === false)) {
40632 this._drawEdges(ctx);
40633 }
40634 }
40635
40636 if (this.dragging === false || this.dragging === true && this.options.hideNodesOnDrag === false) {
40637 this._drawNodes(ctx, hidden);
40638 }
40639
40640 ctx.beginPath();
40641 this.body.emitter.emit("afterDrawing", ctx);
40642 ctx.closePath(); // restore original scaling and translation
40643
40644 ctx.restore();
40645
40646 if (hidden === true) {
40647 ctx.clearRect(0, 0, w, h);
40648 }
40649 }
40650 }
40651 /**
40652 * Redraw all nodes
40653 *
40654 * @param {CanvasRenderingContext2D} ctx
40655 * @param {boolean} [alwaysShow]
40656 * @private
40657 */
40658
40659 }, {
40660 key: "_resizeNodes",
40661 value: function _resizeNodes() {
40662 this.canvas.setTransform();
40663 var ctx = this.canvas.getContext();
40664 ctx.save();
40665 ctx.translate(this.body.view.translation.x, this.body.view.translation.y);
40666 ctx.scale(this.body.view.scale, this.body.view.scale);
40667 var nodes = this.body.nodes;
40668 var node; // resize all nodes
40669
40670 for (var nodeId in nodes) {
40671 if (nodes.hasOwnProperty(nodeId)) {
40672 node = nodes[nodeId];
40673 node.resize(ctx);
40674 node.updateBoundingBox(ctx, node.selected);
40675 }
40676 } // restore original scaling and translation
40677
40678
40679 ctx.restore();
40680 }
40681 /**
40682 * Redraw all nodes
40683 *
40684 * @param {CanvasRenderingContext2D} ctx 2D context of a HTML canvas
40685 * @param {boolean} [alwaysShow]
40686 * @private
40687 */
40688
40689 }, {
40690 key: "_drawNodes",
40691 value: function _drawNodes(ctx) {
40692 var alwaysShow = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
40693 var nodes = this.body.nodes;
40694 var nodeIndices = this.body.nodeIndices;
40695 var node;
40696 var selected = [];
40697 var margin = 20;
40698 var topLeft = this.canvas.DOMtoCanvas({
40699 x: -margin,
40700 y: -margin
40701 });
40702 var bottomRight = this.canvas.DOMtoCanvas({
40703 x: this.canvas.frame.canvas.clientWidth + margin,
40704 y: this.canvas.frame.canvas.clientHeight + margin
40705 });
40706 var viewableArea = {
40707 top: topLeft.y,
40708 left: topLeft.x,
40709 bottom: bottomRight.y,
40710 right: bottomRight.x
40711 }; // draw unselected nodes;
40712
40713 for (var i = 0; i < nodeIndices.length; i++) {
40714 node = nodes[nodeIndices[i]]; // set selected nodes aside
40715
40716 if (node.isSelected()) {
40717 selected.push(nodeIndices[i]);
40718 } else {
40719 if (alwaysShow === true) {
40720 node.draw(ctx);
40721 } else if (node.isBoundingBoxOverlappingWith(viewableArea) === true) {
40722 node.draw(ctx);
40723 } else {
40724 node.updateBoundingBox(ctx, node.selected);
40725 }
40726 }
40727 } // draw the selected nodes on top
40728
40729
40730 for (var _i = 0; _i < selected.length; _i++) {
40731 node = nodes[selected[_i]];
40732 node.draw(ctx);
40733 }
40734 }
40735 /**
40736 * Redraw all edges
40737 * @param {CanvasRenderingContext2D} ctx 2D context of a HTML canvas
40738 * @private
40739 */
40740
40741 }, {
40742 key: "_drawEdges",
40743 value: function _drawEdges(ctx) {
40744 var edges = this.body.edges;
40745 var edgeIndices = this.body.edgeIndices;
40746 var edge;
40747
40748 for (var i = 0; i < edgeIndices.length; i++) {
40749 edge = edges[edgeIndices[i]];
40750
40751 if (edge.connected === true) {
40752 edge.draw(ctx);
40753 }
40754 }
40755 }
40756 /**
40757 * Determine if the browser requires a setTimeout or a requestAnimationFrame. This was required because
40758 * some implementations (safari and IE9) did not support requestAnimationFrame
40759 * @private
40760 */
40761
40762 }, {
40763 key: "_determineBrowserMethod",
40764 value: function _determineBrowserMethod() {
40765 if (typeof window !== 'undefined') {
40766 var browserType = navigator.userAgent.toLowerCase();
40767 this.requiresTimeout = false;
40768
40769 if (browserType.indexOf('msie 9.0') != -1) {
40770 // IE 9
40771 this.requiresTimeout = true;
40772 } else if (browserType.indexOf('safari') != -1) {
40773 // safari
40774 if (browserType.indexOf('chrome') <= -1) {
40775 this.requiresTimeout = true;
40776 }
40777 }
40778 } else {
40779 this.requiresTimeout = true;
40780 }
40781 }
40782 }]);
40783
40784 return CanvasRenderer;
40785}();
40786
40787var hammerUtil = createCommonjsModule(function (module, exports) {
40788 /**
40789 * Register a touch event, taking place before a gesture
40790 * @param {Hammer} hammer A hammer instance
40791 * @param {function} callback Callback, called as callback(event)
40792 */
40793 exports.onTouch = function (hammer, callback) {
40794 callback.inputHandler = function (event) {
40795 if (event.isFirst) {
40796 callback(event);
40797 }
40798 };
40799
40800 hammer.on('hammer.input', callback.inputHandler);
40801 };
40802 /**
40803 * Register a release event, taking place after a gesture
40804 * @param {Hammer} hammer A hammer instance
40805 * @param {function} callback Callback, called as callback(event)
40806 * @returns {*}
40807 */
40808
40809
40810 exports.onRelease = function (hammer, callback) {
40811 callback.inputHandler = function (event) {
40812 if (event.isFinal) {
40813 callback(event);
40814 }
40815 };
40816
40817 return hammer.on('hammer.input', callback.inputHandler);
40818 };
40819 /**
40820 * Unregister a touch event, taking place before a gesture
40821 * @param {Hammer} hammer A hammer instance
40822 * @param {function} callback Callback, called as callback(event)
40823 */
40824
40825
40826 exports.offTouch = function (hammer, callback) {
40827 hammer.off('hammer.input', callback.inputHandler);
40828 };
40829 /**
40830 * Unregister a release event, taking place before a gesture
40831 * @param {Hammer} hammer A hammer instance
40832 * @param {function} callback Callback, called as callback(event)
40833 */
40834
40835
40836 exports.offRelease = exports.offTouch;
40837 /**
40838 * Hack the PinchRecognizer such that it doesn't prevent default behavior
40839 * for vertical panning.
40840 *
40841 * Yeah ... this is quite a hack ... see https://github.com/hammerjs/hammer.js/issues/932
40842 *
40843 * @param {Hammer.Pinch} pinchRecognizer
40844 * @return {Hammer.Pinch} returns the pinchRecognizer
40845 */
40846
40847 exports.disablePreventDefaultVertically = function (pinchRecognizer) {
40848 var TOUCH_ACTION_PAN_Y = 'pan-y';
40849
40850 pinchRecognizer.getTouchAction = function () {
40851 // default method returns [TOUCH_ACTION_NONE]
40852 return [TOUCH_ACTION_PAN_Y];
40853 };
40854
40855 return pinchRecognizer;
40856 };
40857});
40858var hammerUtil_1 = hammerUtil.onTouch;
40859var hammerUtil_2 = hammerUtil.onRelease;
40860var hammerUtil_3 = hammerUtil.offTouch;
40861var hammerUtil_4 = hammerUtil.offRelease;
40862var hammerUtil_5 = hammerUtil.disablePreventDefaultVertically;
40863
40864/**
40865 * Create the main frame for the Network.
40866 * This function is executed once when a Network object is created. The frame
40867 * contains a canvas, and this canvas contains all objects like the axis and
40868 * nodes.
40869 */
40870
40871var Canvas =
40872/*#__PURE__*/
40873function () {
40874 /**
40875 * @param {Object} body
40876 */
40877 function Canvas(body) {
40878 _classCallCheck(this, Canvas);
40879
40880 this.body = body;
40881 this.pixelRatio = 1;
40882 this.resizeTimer = undefined;
40883 this.resizeFunction = this._onResize.bind(this);
40884 this.cameraState = {};
40885 this.initialized = false;
40886 this.canvasViewCenter = {};
40887 this.options = {};
40888 this.defaultOptions = {
40889 autoResize: true,
40890 height: '100%',
40891 width: '100%'
40892 };
40893 extend(this.options, this.defaultOptions);
40894 this.bindEventListeners();
40895 }
40896 /**
40897 * Binds event listeners
40898 */
40899
40900
40901 _createClass(Canvas, [{
40902 key: "bindEventListeners",
40903 value: function bindEventListeners() {
40904 var _this = this;
40905
40906 // bind the events
40907 this.body.emitter.once("resize", function (obj) {
40908 if (obj.width !== 0) {
40909 _this.body.view.translation.x = obj.width * 0.5;
40910 }
40911
40912 if (obj.height !== 0) {
40913 _this.body.view.translation.y = obj.height * 0.5;
40914 }
40915 });
40916 this.body.emitter.on("setSize", this.setSize.bind(this));
40917 this.body.emitter.on("destroy", function () {
40918 _this.hammerFrame.destroy();
40919
40920 _this.hammer.destroy();
40921
40922 _this._cleanUp();
40923 });
40924 }
40925 /**
40926 * @param {Object} options
40927 */
40928
40929 }, {
40930 key: "setOptions",
40931 value: function setOptions(options) {
40932 var _this2 = this;
40933
40934 if (options !== undefined) {
40935 var fields = ['width', 'height', 'autoResize'];
40936 selectiveDeepExtend(fields, this.options, options);
40937 }
40938
40939 if (this.options.autoResize === true) {
40940 // automatically adapt to a changing size of the browser.
40941 this._cleanUp();
40942
40943 this.resizeTimer = setInterval(function () {
40944 var changed = _this2.setSize();
40945
40946 if (changed === true) {
40947 _this2.body.emitter.emit("_requestRedraw");
40948 }
40949 }, 1000);
40950 this.resizeFunction = this._onResize.bind(this);
40951 addEventListener(window, 'resize', this.resizeFunction);
40952 }
40953 }
40954 /**
40955 * @private
40956 */
40957
40958 }, {
40959 key: "_cleanUp",
40960 value: function _cleanUp() {
40961 // automatically adapt to a changing size of the browser.
40962 if (this.resizeTimer !== undefined) {
40963 clearInterval(this.resizeTimer);
40964 }
40965
40966 removeEventListener(window, 'resize', this.resizeFunction);
40967 this.resizeFunction = undefined;
40968 }
40969 /**
40970 * @private
40971 */
40972
40973 }, {
40974 key: "_onResize",
40975 value: function _onResize() {
40976 this.setSize();
40977 this.body.emitter.emit("_redraw");
40978 }
40979 /**
40980 * Get and store the cameraState
40981 *
40982 * @param {number} [pixelRatio=this.pixelRatio]
40983 * @private
40984 */
40985
40986 }, {
40987 key: "_getCameraState",
40988 value: function _getCameraState() {
40989 var pixelRatio = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.pixelRatio;
40990
40991 if (this.initialized === true) {
40992 this.cameraState.previousWidth = this.frame.canvas.width / pixelRatio;
40993 this.cameraState.previousHeight = this.frame.canvas.height / pixelRatio;
40994 this.cameraState.scale = this.body.view.scale;
40995 this.cameraState.position = this.DOMtoCanvas({
40996 x: 0.5 * this.frame.canvas.width / pixelRatio,
40997 y: 0.5 * this.frame.canvas.height / pixelRatio
40998 });
40999 }
41000 }
41001 /**
41002 * Set the cameraState
41003 * @private
41004 */
41005
41006 }, {
41007 key: "_setCameraState",
41008 value: function _setCameraState() {
41009 if (this.cameraState.scale !== undefined && this.frame.canvas.clientWidth !== 0 && this.frame.canvas.clientHeight !== 0 && this.pixelRatio !== 0 && this.cameraState.previousWidth > 0) {
41010 var widthRatio = this.frame.canvas.width / this.pixelRatio / this.cameraState.previousWidth;
41011 var heightRatio = this.frame.canvas.height / this.pixelRatio / this.cameraState.previousHeight;
41012 var newScale = this.cameraState.scale;
41013
41014 if (widthRatio != 1 && heightRatio != 1) {
41015 newScale = this.cameraState.scale * 0.5 * (widthRatio + heightRatio);
41016 } else if (widthRatio != 1) {
41017 newScale = this.cameraState.scale * widthRatio;
41018 } else if (heightRatio != 1) {
41019 newScale = this.cameraState.scale * heightRatio;
41020 }
41021
41022 this.body.view.scale = newScale; // this comes from the view module.
41023
41024 var currentViewCenter = this.DOMtoCanvas({
41025 x: 0.5 * this.frame.canvas.clientWidth,
41026 y: 0.5 * this.frame.canvas.clientHeight
41027 });
41028 var distanceFromCenter = {
41029 // offset from view, distance view has to change by these x and y to center the node
41030 x: currentViewCenter.x - this.cameraState.position.x,
41031 y: currentViewCenter.y - this.cameraState.position.y
41032 };
41033 this.body.view.translation.x += distanceFromCenter.x * this.body.view.scale;
41034 this.body.view.translation.y += distanceFromCenter.y * this.body.view.scale;
41035 }
41036 }
41037 /**
41038 *
41039 * @param {number|string} value
41040 * @returns {string}
41041 * @private
41042 */
41043
41044 }, {
41045 key: "_prepareValue",
41046 value: function _prepareValue(value) {
41047 if (typeof value === 'number') {
41048 return value + 'px';
41049 } else if (typeof value === 'string') {
41050 if (value.indexOf('%') !== -1 || value.indexOf('px') !== -1) {
41051 return value;
41052 } else if (value.indexOf('%') === -1) {
41053 return value + 'px';
41054 }
41055 }
41056
41057 throw new Error('Could not use the value supplied for width or height:' + value);
41058 }
41059 /**
41060 * Create the HTML
41061 */
41062
41063 }, {
41064 key: "_create",
41065 value: function _create() {
41066 // remove all elements from the container element.
41067 while (this.body.container.hasChildNodes()) {
41068 this.body.container.removeChild(this.body.container.firstChild);
41069 }
41070
41071 this.frame = document.createElement('div');
41072 this.frame.className = 'vis-network';
41073 this.frame.style.position = 'relative';
41074 this.frame.style.overflow = 'hidden';
41075 this.frame.tabIndex = 900; // tab index is required for keycharm to bind keystrokes to the div instead of the window
41076 //////////////////////////////////////////////////////////////////
41077
41078 this.frame.canvas = document.createElement("canvas");
41079 this.frame.canvas.style.position = 'relative';
41080 this.frame.appendChild(this.frame.canvas);
41081
41082 if (!this.frame.canvas.getContext) {
41083 var noCanvas = document.createElement('DIV');
41084 noCanvas.style.color = 'red';
41085 noCanvas.style.fontWeight = 'bold';
41086 noCanvas.style.padding = '10px';
41087 noCanvas.innerHTML = 'Error: your browser does not support HTML canvas';
41088 this.frame.canvas.appendChild(noCanvas);
41089 } else {
41090 this._setPixelRatio();
41091
41092 this.setTransform();
41093 } // add the frame to the container element
41094
41095
41096 this.body.container.appendChild(this.frame);
41097 this.body.view.scale = 1;
41098 this.body.view.translation = {
41099 x: 0.5 * this.frame.canvas.clientWidth,
41100 y: 0.5 * this.frame.canvas.clientHeight
41101 };
41102
41103 this._bindHammer();
41104 }
41105 /**
41106 * This function binds hammer, it can be repeated over and over due to the uniqueness check.
41107 * @private
41108 */
41109
41110 }, {
41111 key: "_bindHammer",
41112 value: function _bindHammer() {
41113 var _this3 = this;
41114
41115 if (this.hammer !== undefined) {
41116 this.hammer.destroy();
41117 }
41118
41119 this.drag = {};
41120 this.pinch = {}; // init hammer
41121
41122 this.hammer = new hammer(this.frame.canvas);
41123 this.hammer.get('pinch').set({
41124 enable: true
41125 }); // enable to get better response, todo: test on mobile.
41126
41127 this.hammer.get('pan').set({
41128 threshold: 5,
41129 direction: hammer.DIRECTION_ALL
41130 });
41131 hammerUtil.onTouch(this.hammer, function (event) {
41132 _this3.body.eventListeners.onTouch(event);
41133 });
41134 this.hammer.on('tap', function (event) {
41135 _this3.body.eventListeners.onTap(event);
41136 });
41137 this.hammer.on('doubletap', function (event) {
41138 _this3.body.eventListeners.onDoubleTap(event);
41139 });
41140 this.hammer.on('press', function (event) {
41141 _this3.body.eventListeners.onHold(event);
41142 });
41143 this.hammer.on('panstart', function (event) {
41144 _this3.body.eventListeners.onDragStart(event);
41145 });
41146 this.hammer.on('panmove', function (event) {
41147 _this3.body.eventListeners.onDrag(event);
41148 });
41149 this.hammer.on('panend', function (event) {
41150 _this3.body.eventListeners.onDragEnd(event);
41151 });
41152 this.hammer.on('pinch', function (event) {
41153 _this3.body.eventListeners.onPinch(event);
41154 }); // TODO: neatly cleanup these handlers when re-creating the Canvas, IF these are done with hammer, event.stopPropagation will not work?
41155
41156 this.frame.canvas.addEventListener('wheel', function (event) {
41157 _this3.body.eventListeners.onMouseWheel(event);
41158 });
41159 this.frame.canvas.addEventListener('mousemove', function (event) {
41160 _this3.body.eventListeners.onMouseMove(event);
41161 });
41162 this.frame.canvas.addEventListener('contextmenu', function (event) {
41163 _this3.body.eventListeners.onContext(event);
41164 });
41165 this.hammerFrame = new hammer(this.frame);
41166 hammerUtil.onRelease(this.hammerFrame, function (event) {
41167 _this3.body.eventListeners.onRelease(event);
41168 });
41169 }
41170 /**
41171 * Set a new size for the network
41172 * @param {string} width Width in pixels or percentage (for example '800px'
41173 * or '50%')
41174 * @param {string} height Height in pixels or percentage (for example '400px'
41175 * or '30%')
41176 * @returns {boolean}
41177 */
41178
41179 }, {
41180 key: "setSize",
41181 value: function setSize() {
41182 var width = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.options.width;
41183 var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.options.height;
41184 width = this._prepareValue(width);
41185 height = this._prepareValue(height);
41186 var emitEvent = false;
41187 var oldWidth = this.frame.canvas.width;
41188 var oldHeight = this.frame.canvas.height; // update the pixel ratio
41189 //
41190 // NOTE: Comment in following is rather inconsistent; this is the ONLY place in the code
41191 // where it is assumed that the pixel ratio could change at runtime.
41192 // The only way I can think of this happening is a rotating screen or tablet; but then
41193 // there should be a mechanism for reloading the data (TODO: check if this is present).
41194 //
41195 // If the assumption is true (i.e. pixel ratio can change at runtime), then *all* usage
41196 // of pixel ratio must be overhauled for this.
41197 //
41198 // For the time being, I will humor the assumption here, and in the rest of the code assume it is
41199 // constant.
41200
41201 var previousRatio = this.pixelRatio; // we cache this because the camera state storage needs the old value
41202
41203 this._setPixelRatio();
41204
41205 if (width != this.options.width || height != this.options.height || this.frame.style.width != width || this.frame.style.height != height) {
41206 this._getCameraState(previousRatio);
41207
41208 this.frame.style.width = width;
41209 this.frame.style.height = height;
41210 this.frame.canvas.style.width = '100%';
41211 this.frame.canvas.style.height = '100%';
41212 this.frame.canvas.width = Math.round(this.frame.canvas.clientWidth * this.pixelRatio);
41213 this.frame.canvas.height = Math.round(this.frame.canvas.clientHeight * this.pixelRatio);
41214 this.options.width = width;
41215 this.options.height = height;
41216 this.canvasViewCenter = {
41217 x: 0.5 * this.frame.clientWidth,
41218 y: 0.5 * this.frame.clientHeight
41219 };
41220 emitEvent = true;
41221 } else {
41222 // this would adapt the width of the canvas to the width from 100% if and only if
41223 // there is a change.
41224 var newWidth = Math.round(this.frame.canvas.clientWidth * this.pixelRatio);
41225 var newHeight = Math.round(this.frame.canvas.clientHeight * this.pixelRatio); // store the camera if there is a change in size.
41226
41227 if (this.frame.canvas.width !== newWidth || this.frame.canvas.height !== newHeight) {
41228 this._getCameraState(previousRatio);
41229 }
41230
41231 if (this.frame.canvas.width !== newWidth) {
41232 this.frame.canvas.width = newWidth;
41233 emitEvent = true;
41234 }
41235
41236 if (this.frame.canvas.height !== newHeight) {
41237 this.frame.canvas.height = newHeight;
41238 emitEvent = true;
41239 }
41240 }
41241
41242 if (emitEvent === true) {
41243 this.body.emitter.emit('resize', {
41244 width: Math.round(this.frame.canvas.width / this.pixelRatio),
41245 height: Math.round(this.frame.canvas.height / this.pixelRatio),
41246 oldWidth: Math.round(oldWidth / this.pixelRatio),
41247 oldHeight: Math.round(oldHeight / this.pixelRatio)
41248 }); // restore the camera on change.
41249
41250 this._setCameraState();
41251 } // set initialized so the get and set camera will work from now on.
41252
41253
41254 this.initialized = true;
41255 return emitEvent;
41256 }
41257 /**
41258 *
41259 * @returns {CanvasRenderingContext2D}
41260 */
41261
41262 }, {
41263 key: "getContext",
41264 value: function getContext() {
41265 return this.frame.canvas.getContext("2d");
41266 }
41267 /**
41268 * Determine the pixel ratio for various browsers.
41269 *
41270 * @returns {number}
41271 * @private
41272 */
41273
41274 }, {
41275 key: "_determinePixelRatio",
41276 value: function _determinePixelRatio() {
41277 var ctx = this.getContext();
41278
41279 if (ctx === undefined) {
41280 throw new Error("Could not get canvax context");
41281 }
41282
41283 var numerator = 1;
41284
41285 if (typeof window !== 'undefined') {
41286 // (window !== undefined) doesn't work here!
41287 // Protection during unit tests, where 'window' can be missing
41288 numerator = window.devicePixelRatio || 1;
41289 }
41290
41291 var denominator = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
41292 return numerator / denominator;
41293 }
41294 /**
41295 * Lazy determination of pixel ratio.
41296 *
41297 * @private
41298 */
41299
41300 }, {
41301 key: "_setPixelRatio",
41302 value: function _setPixelRatio() {
41303 this.pixelRatio = this._determinePixelRatio();
41304 }
41305 /**
41306 * Set the transform in the contained context, based on its pixelRatio
41307 */
41308
41309 }, {
41310 key: "setTransform",
41311 value: function setTransform() {
41312 var ctx = this.getContext();
41313
41314 if (ctx === undefined) {
41315 throw new Error("Could not get canvax context");
41316 }
41317
41318 ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0);
41319 }
41320 /**
41321 * Convert the X coordinate in DOM-space (coordinate point in browser relative to the container div) to
41322 * the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon)
41323 * @param {number} x
41324 * @returns {number}
41325 * @private
41326 */
41327
41328 }, {
41329 key: "_XconvertDOMtoCanvas",
41330 value: function _XconvertDOMtoCanvas(x) {
41331 return (x - this.body.view.translation.x) / this.body.view.scale;
41332 }
41333 /**
41334 * Convert the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to
41335 * the X coordinate in DOM-space (coordinate point in browser relative to the container div)
41336 * @param {number} x
41337 * @returns {number}
41338 * @private
41339 */
41340
41341 }, {
41342 key: "_XconvertCanvasToDOM",
41343 value: function _XconvertCanvasToDOM(x) {
41344 return x * this.body.view.scale + this.body.view.translation.x;
41345 }
41346 /**
41347 * Convert the Y coordinate in DOM-space (coordinate point in browser relative to the container div) to
41348 * the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon)
41349 * @param {number} y
41350 * @returns {number}
41351 * @private
41352 */
41353
41354 }, {
41355 key: "_YconvertDOMtoCanvas",
41356 value: function _YconvertDOMtoCanvas(y) {
41357 return (y - this.body.view.translation.y) / this.body.view.scale;
41358 }
41359 /**
41360 * Convert the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to
41361 * the Y coordinate in DOM-space (coordinate point in browser relative to the container div)
41362 * @param {number} y
41363 * @returns {number}
41364 * @private
41365 */
41366
41367 }, {
41368 key: "_YconvertCanvasToDOM",
41369 value: function _YconvertCanvasToDOM(y) {
41370 return y * this.body.view.scale + this.body.view.translation.y;
41371 }
41372 /**
41373 * @param {point} pos
41374 * @returns {point}
41375 */
41376
41377 }, {
41378 key: "canvasToDOM",
41379 value: function canvasToDOM(pos) {
41380 return {
41381 x: this._XconvertCanvasToDOM(pos.x),
41382 y: this._YconvertCanvasToDOM(pos.y)
41383 };
41384 }
41385 /**
41386 *
41387 * @param {point} pos
41388 * @returns {point}
41389 */
41390
41391 }, {
41392 key: "DOMtoCanvas",
41393 value: function DOMtoCanvas(pos) {
41394 return {
41395 x: this._XconvertDOMtoCanvas(pos.x),
41396 y: this._YconvertDOMtoCanvas(pos.y)
41397 };
41398 }
41399 }]);
41400
41401 return Canvas;
41402}();
41403
41404var globalIsFinite = global_1.isFinite; // `Number.isFinite` method
41405// https://tc39.github.io/ecma262/#sec-number.isfinite
41406
41407var numberIsFinite = Number.isFinite || function isFinite(it) {
41408 return typeof it == 'number' && globalIsFinite(it);
41409};
41410
41411// https://tc39.github.io/ecma262/#sec-number.isfinite
41412
41413_export({
41414 target: 'Number',
41415 stat: true
41416}, {
41417 isFinite: numberIsFinite
41418});
41419
41420/**
41421 * The view
41422 */
41423
41424var View =
41425/*#__PURE__*/
41426function () {
41427 /**
41428 * @param {Object} body
41429 * @param {Canvas} canvas
41430 */
41431 function View(body, canvas) {
41432 var _this = this;
41433
41434 _classCallCheck(this, View);
41435
41436 this.body = body;
41437 this.canvas = canvas;
41438 this.animationSpeed = 1 / this.renderRefreshRate;
41439 this.animationEasingFunction = "easeInOutQuint";
41440 this.easingTime = 0;
41441 this.sourceScale = 0;
41442 this.targetScale = 0;
41443 this.sourceTranslation = 0;
41444 this.targetTranslation = 0;
41445 this.lockedOnNodeId = undefined;
41446 this.lockedOnNodeOffset = undefined;
41447 this.touchTime = 0;
41448 this.viewFunction = undefined;
41449 this.body.emitter.on("fit", this.fit.bind(this));
41450 this.body.emitter.on("animationFinished", function () {
41451 _this.body.emitter.emit("_stopRendering");
41452 });
41453 this.body.emitter.on("unlockNode", this.releaseNode.bind(this));
41454 }
41455 /**
41456 *
41457 * @param {Object} [options={}]
41458 */
41459
41460
41461 _createClass(View, [{
41462 key: "setOptions",
41463 value: function setOptions() {
41464 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
41465 this.options = options;
41466 }
41467 /**
41468 * This function zooms out to fit all data on screen based on amount of nodes
41469 * @param {Object} [options={{nodes=Array}}]
41470 * @param {boolean} [initialZoom=false] | zoom based on fitted formula or range, true = fitted, default = false;
41471 */
41472
41473 }, {
41474 key: "fit",
41475 value: function fit() {
41476 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
41477 nodes: []
41478 };
41479 var initialZoom = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
41480 var range;
41481 var zoomLevel;
41482 options = Object.assign({}, options);
41483
41484 if (options.nodes === undefined || options.nodes.length === 0) {
41485 options.nodes = this.body.nodeIndices;
41486 }
41487
41488 if (initialZoom === true) {
41489 // check if more than half of the nodes have a predefined position. If so, we use the range, not the approximation.
41490 var positionDefined = 0;
41491
41492 for (var nodeId in this.body.nodes) {
41493 if (this.body.nodes.hasOwnProperty(nodeId)) {
41494 var node = this.body.nodes[nodeId];
41495
41496 if (node.predefinedPosition === true) {
41497 positionDefined += 1;
41498 }
41499 }
41500 }
41501
41502 if (positionDefined > 0.5 * this.body.nodeIndices.length) {
41503 this.fit(options, false);
41504 return;
41505 }
41506
41507 range = NetworkUtil.getRange(this.body.nodes, options.nodes);
41508 var numberOfNodes = this.body.nodeIndices.length;
41509 zoomLevel = 12.662 / (numberOfNodes + 7.4147) + 0.0964822; // this is obtained from fitting a dataset from 5 points with scale levels that looked good.
41510 // correct for larger canvasses.
41511
41512 var factor = Math.min(this.canvas.frame.canvas.clientWidth / 600, this.canvas.frame.canvas.clientHeight / 600);
41513 zoomLevel *= factor;
41514 } else {
41515 this.body.emitter.emit("_resizeNodes");
41516 range = NetworkUtil.getRange(this.body.nodes, options.nodes);
41517 var xDistance = Math.abs(range.maxX - range.minX) * 1.1;
41518 var yDistance = Math.abs(range.maxY - range.minY) * 1.1;
41519 var xZoomLevel = this.canvas.frame.canvas.clientWidth / xDistance;
41520 var yZoomLevel = this.canvas.frame.canvas.clientHeight / yDistance;
41521 zoomLevel = xZoomLevel <= yZoomLevel ? xZoomLevel : yZoomLevel;
41522 }
41523
41524 if (zoomLevel > 1.0) {
41525 zoomLevel = 1.0;
41526 } else if (zoomLevel === 0) {
41527 zoomLevel = 1.0;
41528 }
41529
41530 var center = NetworkUtil.findCenter(range);
41531 var animationOptions = {
41532 position: center,
41533 scale: zoomLevel,
41534 animation: options.animation
41535 };
41536 this.moveTo(animationOptions);
41537 } // animation
41538
41539 /**
41540 * Center a node in view.
41541 *
41542 * @param {number} nodeId
41543 * @param {number} [options]
41544 */
41545
41546 }, {
41547 key: "focus",
41548 value: function focus(nodeId) {
41549 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
41550
41551 if (this.body.nodes[nodeId] !== undefined) {
41552 var nodePosition = {
41553 x: this.body.nodes[nodeId].x,
41554 y: this.body.nodes[nodeId].y
41555 };
41556 options.position = nodePosition;
41557 options.lockedOnNode = nodeId;
41558 this.moveTo(options);
41559 } else {
41560 console.log("Node: " + nodeId + " cannot be found.");
41561 }
41562 }
41563 /**
41564 *
41565 * @param {Object} options | options.offset = {x:number, y:number} // offset from the center in DOM pixels
41566 * | options.scale = number // scale to move to
41567 * | options.position = {x:number, y:number} // position to move to
41568 * | options.animation = {duration:number, easingFunction:String} || Boolean // position to move to
41569 */
41570
41571 }, {
41572 key: "moveTo",
41573 value: function moveTo(options) {
41574 if (options === undefined) {
41575 options = {};
41576 return;
41577 }
41578
41579 if (options.offset != null) {
41580 if (options.offset.x != null) {
41581 // Coerce and verify that x is valid.
41582 options.offset.x = +options.offset.x;
41583
41584 if (!Number.isFinite(options.offset.x)) {
41585 throw new TypeError('The option "offset.x" has to be a finite number.');
41586 }
41587 } else {
41588 options.offset.x = 0;
41589 }
41590
41591 if (options.offset.y != null) {
41592 // Coerce and verify that y is valid.
41593 options.offset.y = +options.offset.y;
41594
41595 if (!Number.isFinite(options.offset.y)) {
41596 throw new TypeError('The option "offset.y" has to be a finite number.');
41597 }
41598 } else {
41599 options.offset.x = 0;
41600 }
41601 } else {
41602 options.offset = {
41603 x: 0,
41604 y: 0
41605 };
41606 }
41607
41608 if (options.position != null) {
41609 if (options.position.x != null) {
41610 // Coerce and verify that x is valid.
41611 options.position.x = +options.position.x;
41612
41613 if (!Number.isFinite(options.position.x)) {
41614 throw new TypeError('The option "position.x" has to be a finite number.');
41615 }
41616 } else {
41617 options.position.x = 0;
41618 }
41619
41620 if (options.position.y != null) {
41621 // Coerce and verify that y is valid.
41622 options.position.y = +options.position.y;
41623
41624 if (!Number.isFinite(options.position.y)) {
41625 throw new TypeError('The option "position.y" has to be a finite number.');
41626 }
41627 } else {
41628 options.position.x = 0;
41629 }
41630 } else {
41631 options.position = this.getViewPosition();
41632 }
41633
41634 if (options.scale != null) {
41635 // Coerce and verify that the scale is valid.
41636 options.scale = +options.scale;
41637
41638 if (!(options.scale > 0)) {
41639 throw new TypeError('The option "scale" has to be a number greater than zero.');
41640 }
41641 } else {
41642 options.scale = this.body.view.scale;
41643 }
41644
41645 if (options.animation === undefined) {
41646 options.animation = {
41647 duration: 0
41648 };
41649 }
41650
41651 if (options.animation === false) {
41652 options.animation = {
41653 duration: 0
41654 };
41655 }
41656
41657 if (options.animation === true) {
41658 options.animation = {};
41659 }
41660
41661 if (options.animation.duration === undefined) {
41662 options.animation.duration = 1000;
41663 } // default duration
41664
41665
41666 if (options.animation.easingFunction === undefined) {
41667 options.animation.easingFunction = "easeInOutQuad";
41668 } // default easing function
41669
41670
41671 this.animateView(options);
41672 }
41673 /**
41674 *
41675 * @param {Object} options | options.offset = {x:number, y:number} // offset from the center in DOM pixels
41676 * | options.time = number // animation time in milliseconds
41677 * | options.scale = number // scale to animate to
41678 * | options.position = {x:number, y:number} // position to animate to
41679 * | options.easingFunction = String // linear, easeInQuad, easeOutQuad, easeInOutQuad,
41680 * // easeInCubic, easeOutCubic, easeInOutCubic,
41681 * // easeInQuart, easeOutQuart, easeInOutQuart,
41682 * // easeInQuint, easeOutQuint, easeInOutQuint
41683 */
41684
41685 }, {
41686 key: "animateView",
41687 value: function animateView(options) {
41688 if (options === undefined) {
41689 return;
41690 }
41691
41692 this.animationEasingFunction = options.animation.easingFunction; // release if something focussed on the node
41693
41694 this.releaseNode();
41695
41696 if (options.locked === true) {
41697 this.lockedOnNodeId = options.lockedOnNode;
41698 this.lockedOnNodeOffset = options.offset;
41699 } // forcefully complete the old animation if it was still running
41700
41701
41702 if (this.easingTime != 0) {
41703 this._transitionRedraw(true); // by setting easingtime to 1, we finish the animation.
41704
41705 }
41706
41707 this.sourceScale = this.body.view.scale;
41708 this.sourceTranslation = this.body.view.translation;
41709 this.targetScale = options.scale; // set the scale so the viewCenter is based on the correct zoom level. This is overridden in the transitionRedraw
41710 // but at least then we'll have the target transition
41711
41712 this.body.view.scale = this.targetScale;
41713 var viewCenter = this.canvas.DOMtoCanvas({
41714 x: 0.5 * this.canvas.frame.canvas.clientWidth,
41715 y: 0.5 * this.canvas.frame.canvas.clientHeight
41716 });
41717 var distanceFromCenter = {
41718 // offset from view, distance view has to change by these x and y to center the node
41719 x: viewCenter.x - options.position.x,
41720 y: viewCenter.y - options.position.y
41721 };
41722 this.targetTranslation = {
41723 x: this.sourceTranslation.x + distanceFromCenter.x * this.targetScale + options.offset.x,
41724 y: this.sourceTranslation.y + distanceFromCenter.y * this.targetScale + options.offset.y
41725 }; // if the time is set to 0, don't do an animation
41726
41727 if (options.animation.duration === 0) {
41728 if (this.lockedOnNodeId != undefined) {
41729 this.viewFunction = this._lockedRedraw.bind(this);
41730 this.body.emitter.on("initRedraw", this.viewFunction);
41731 } else {
41732 this.body.view.scale = this.targetScale;
41733 this.body.view.translation = this.targetTranslation;
41734 this.body.emitter.emit("_requestRedraw");
41735 }
41736 } else {
41737 this.animationSpeed = 1 / (60 * options.animation.duration * 0.001) || 1 / 60; // 60 for 60 seconds, 0.001 for milli's
41738
41739 this.animationEasingFunction = options.animation.easingFunction;
41740 this.viewFunction = this._transitionRedraw.bind(this);
41741 this.body.emitter.on("initRedraw", this.viewFunction);
41742 this.body.emitter.emit("_startRendering");
41743 }
41744 }
41745 /**
41746 * used to animate smoothly by hijacking the redraw function.
41747 * @private
41748 */
41749
41750 }, {
41751 key: "_lockedRedraw",
41752 value: function _lockedRedraw() {
41753 var nodePosition = {
41754 x: this.body.nodes[this.lockedOnNodeId].x,
41755 y: this.body.nodes[this.lockedOnNodeId].y
41756 };
41757 var viewCenter = this.canvas.DOMtoCanvas({
41758 x: 0.5 * this.canvas.frame.canvas.clientWidth,
41759 y: 0.5 * this.canvas.frame.canvas.clientHeight
41760 });
41761 var distanceFromCenter = {
41762 // offset from view, distance view has to change by these x and y to center the node
41763 x: viewCenter.x - nodePosition.x,
41764 y: viewCenter.y - nodePosition.y
41765 };
41766 var sourceTranslation = this.body.view.translation;
41767 var targetTranslation = {
41768 x: sourceTranslation.x + distanceFromCenter.x * this.body.view.scale + this.lockedOnNodeOffset.x,
41769 y: sourceTranslation.y + distanceFromCenter.y * this.body.view.scale + this.lockedOnNodeOffset.y
41770 };
41771 this.body.view.translation = targetTranslation;
41772 }
41773 /**
41774 * Resets state of a locked on Node
41775 */
41776
41777 }, {
41778 key: "releaseNode",
41779 value: function releaseNode() {
41780 if (this.lockedOnNodeId !== undefined && this.viewFunction !== undefined) {
41781 this.body.emitter.off("initRedraw", this.viewFunction);
41782 this.lockedOnNodeId = undefined;
41783 this.lockedOnNodeOffset = undefined;
41784 }
41785 }
41786 /**
41787 * @param {boolean} [finished=false]
41788 * @private
41789 */
41790
41791 }, {
41792 key: "_transitionRedraw",
41793 value: function _transitionRedraw() {
41794 var finished = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
41795 this.easingTime += this.animationSpeed;
41796 this.easingTime = finished === true ? 1.0 : this.easingTime;
41797 var progress = easingFunctions[this.animationEasingFunction](this.easingTime);
41798 this.body.view.scale = this.sourceScale + (this.targetScale - this.sourceScale) * progress;
41799 this.body.view.translation = {
41800 x: this.sourceTranslation.x + (this.targetTranslation.x - this.sourceTranslation.x) * progress,
41801 y: this.sourceTranslation.y + (this.targetTranslation.y - this.sourceTranslation.y) * progress
41802 }; // cleanup
41803
41804 if (this.easingTime >= 1.0) {
41805 this.body.emitter.off("initRedraw", this.viewFunction);
41806 this.easingTime = 0;
41807
41808 if (this.lockedOnNodeId != undefined) {
41809 this.viewFunction = this._lockedRedraw.bind(this);
41810 this.body.emitter.on("initRedraw", this.viewFunction);
41811 }
41812
41813 this.body.emitter.emit("animationFinished");
41814 }
41815 }
41816 /**
41817 *
41818 * @returns {number}
41819 */
41820
41821 }, {
41822 key: "getScale",
41823 value: function getScale() {
41824 return this.body.view.scale;
41825 }
41826 /**
41827 *
41828 * @returns {{x: number, y: number}}
41829 */
41830
41831 }, {
41832 key: "getViewPosition",
41833 value: function getViewPosition() {
41834 return this.canvas.DOMtoCanvas({
41835 x: 0.5 * this.canvas.frame.canvas.clientWidth,
41836 y: 0.5 * this.canvas.frame.canvas.clientHeight
41837 });
41838 }
41839 }]);
41840
41841 return View;
41842}();
41843
41844/**
41845 * Navigation Handler
41846 */
41847
41848var NavigationHandler =
41849/*#__PURE__*/
41850function () {
41851 /**
41852 * @param {Object} body
41853 * @param {Canvas} canvas
41854 */
41855 function NavigationHandler(body, canvas) {
41856 var _this = this;
41857
41858 _classCallCheck(this, NavigationHandler);
41859
41860 this.body = body;
41861 this.canvas = canvas;
41862 this.iconsCreated = false;
41863 this.navigationHammers = [];
41864 this.boundFunctions = {};
41865 this.touchTime = 0;
41866 this.activated = false;
41867 this.body.emitter.on("activate", function () {
41868 _this.activated = true;
41869
41870 _this.configureKeyboardBindings();
41871 });
41872 this.body.emitter.on("deactivate", function () {
41873 _this.activated = false;
41874
41875 _this.configureKeyboardBindings();
41876 });
41877 this.body.emitter.on("destroy", function () {
41878 if (_this.keycharm !== undefined) {
41879 _this.keycharm.destroy();
41880 }
41881 });
41882 this.options = {};
41883 }
41884 /**
41885 *
41886 * @param {Object} options
41887 */
41888
41889
41890 _createClass(NavigationHandler, [{
41891 key: "setOptions",
41892 value: function setOptions(options) {
41893 if (options !== undefined) {
41894 this.options = options;
41895 this.create();
41896 }
41897 }
41898 /**
41899 * Creates or refreshes navigation and sets key bindings
41900 */
41901
41902 }, {
41903 key: "create",
41904 value: function create() {
41905 if (this.options.navigationButtons === true) {
41906 if (this.iconsCreated === false) {
41907 this.loadNavigationElements();
41908 }
41909 } else if (this.iconsCreated === true) {
41910 this.cleanNavigation();
41911 }
41912
41913 this.configureKeyboardBindings();
41914 }
41915 /**
41916 * Cleans up previous navigation items
41917 */
41918
41919 }, {
41920 key: "cleanNavigation",
41921 value: function cleanNavigation() {
41922 // clean hammer bindings
41923 if (this.navigationHammers.length != 0) {
41924 for (var i = 0; i < this.navigationHammers.length; i++) {
41925 this.navigationHammers[i].destroy();
41926 }
41927
41928 this.navigationHammers = [];
41929 } // clean up previous navigation items
41930
41931
41932 if (this.navigationDOM && this.navigationDOM['wrapper'] && this.navigationDOM['wrapper'].parentNode) {
41933 this.navigationDOM['wrapper'].parentNode.removeChild(this.navigationDOM['wrapper']);
41934 }
41935
41936 this.iconsCreated = false;
41937 }
41938 /**
41939 * Creation of the navigation controls nodes. They are drawn over the rest of the nodes and are not affected by scale and translation
41940 * they have a triggerFunction which is called on click. If the position of the navigation controls is dependent
41941 * on this.frame.canvas.clientWidth or this.frame.canvas.clientHeight, we flag horizontalAlignLeft and verticalAlignTop false.
41942 * This means that the location will be corrected by the _relocateNavigation function on a size change of the canvas.
41943 *
41944 * @private
41945 */
41946
41947 }, {
41948 key: "loadNavigationElements",
41949 value: function loadNavigationElements() {
41950 var _this2 = this;
41951
41952 this.cleanNavigation();
41953 this.navigationDOM = {};
41954 var navigationDivs = ['up', 'down', 'left', 'right', 'zoomIn', 'zoomOut', 'zoomExtends'];
41955 var navigationDivActions = ['_moveUp', '_moveDown', '_moveLeft', '_moveRight', '_zoomIn', '_zoomOut', '_fit'];
41956 this.navigationDOM['wrapper'] = document.createElement('div');
41957 this.navigationDOM['wrapper'].className = 'vis-navigation';
41958 this.canvas.frame.appendChild(this.navigationDOM['wrapper']);
41959
41960 for (var i = 0; i < navigationDivs.length; i++) {
41961 this.navigationDOM[navigationDivs[i]] = document.createElement('div');
41962 this.navigationDOM[navigationDivs[i]].className = 'vis-button vis-' + navigationDivs[i];
41963 this.navigationDOM['wrapper'].appendChild(this.navigationDOM[navigationDivs[i]]);
41964 var hammer$1 = new hammer(this.navigationDOM[navigationDivs[i]]);
41965
41966 if (navigationDivActions[i] === "_fit") {
41967 hammerUtil.onTouch(hammer$1, this._fit.bind(this));
41968 } else {
41969 hammerUtil.onTouch(hammer$1, this.bindToRedraw.bind(this, navigationDivActions[i]));
41970 }
41971
41972 this.navigationHammers.push(hammer$1);
41973 } // use a hammer for the release so we do not require the one used in the rest of the network
41974 // the one the rest uses can be overloaded by the manipulation system.
41975
41976
41977 var hammerFrame = new hammer(this.canvas.frame);
41978 hammerUtil.onRelease(hammerFrame, function () {
41979 _this2._stopMovement();
41980 });
41981 this.navigationHammers.push(hammerFrame);
41982 this.iconsCreated = true;
41983 }
41984 /**
41985 *
41986 * @param {string} action
41987 */
41988
41989 }, {
41990 key: "bindToRedraw",
41991 value: function bindToRedraw(action) {
41992 if (this.boundFunctions[action] === undefined) {
41993 this.boundFunctions[action] = this[action].bind(this);
41994 this.body.emitter.on("initRedraw", this.boundFunctions[action]);
41995 this.body.emitter.emit("_startRendering");
41996 }
41997 }
41998 /**
41999 *
42000 * @param {string} action
42001 */
42002
42003 }, {
42004 key: "unbindFromRedraw",
42005 value: function unbindFromRedraw(action) {
42006 if (this.boundFunctions[action] !== undefined) {
42007 this.body.emitter.off("initRedraw", this.boundFunctions[action]);
42008 this.body.emitter.emit("_stopRendering");
42009 delete this.boundFunctions[action];
42010 }
42011 }
42012 /**
42013 * this stops all movement induced by the navigation buttons
42014 *
42015 * @private
42016 */
42017
42018 }, {
42019 key: "_fit",
42020 value: function _fit() {
42021 if (new Date().valueOf() - this.touchTime > 700) {
42022 // TODO: fix ugly hack to avoid hammer's double fireing of event (because we use release?)
42023 this.body.emitter.emit("fit", {
42024 duration: 700
42025 });
42026 this.touchTime = new Date().valueOf();
42027 }
42028 }
42029 /**
42030 * this stops all movement induced by the navigation buttons
42031 *
42032 * @private
42033 */
42034
42035 }, {
42036 key: "_stopMovement",
42037 value: function _stopMovement() {
42038 for (var boundAction in this.boundFunctions) {
42039 if (this.boundFunctions.hasOwnProperty(boundAction)) {
42040 this.body.emitter.off("initRedraw", this.boundFunctions[boundAction]);
42041 this.body.emitter.emit("_stopRendering");
42042 }
42043 }
42044
42045 this.boundFunctions = {};
42046 }
42047 /**
42048 *
42049 * @private
42050 */
42051
42052 }, {
42053 key: "_moveUp",
42054 value: function _moveUp() {
42055 this.body.view.translation.y += this.options.keyboard.speed.y;
42056 }
42057 /**
42058 *
42059 * @private
42060 */
42061
42062 }, {
42063 key: "_moveDown",
42064 value: function _moveDown() {
42065 this.body.view.translation.y -= this.options.keyboard.speed.y;
42066 }
42067 /**
42068 *
42069 * @private
42070 */
42071
42072 }, {
42073 key: "_moveLeft",
42074 value: function _moveLeft() {
42075 this.body.view.translation.x += this.options.keyboard.speed.x;
42076 }
42077 /**
42078 *
42079 * @private
42080 */
42081
42082 }, {
42083 key: "_moveRight",
42084 value: function _moveRight() {
42085 this.body.view.translation.x -= this.options.keyboard.speed.x;
42086 }
42087 /**
42088 *
42089 * @private
42090 */
42091
42092 }, {
42093 key: "_zoomIn",
42094 value: function _zoomIn() {
42095 var scaleOld = this.body.view.scale;
42096 var scale = this.body.view.scale * (1 + this.options.keyboard.speed.zoom);
42097 var translation = this.body.view.translation;
42098 var scaleFrac = scale / scaleOld;
42099 var tx = (1 - scaleFrac) * this.canvas.canvasViewCenter.x + translation.x * scaleFrac;
42100 var ty = (1 - scaleFrac) * this.canvas.canvasViewCenter.y + translation.y * scaleFrac;
42101 this.body.view.scale = scale;
42102 this.body.view.translation = {
42103 x: tx,
42104 y: ty
42105 };
42106 this.body.emitter.emit('zoom', {
42107 direction: '+',
42108 scale: this.body.view.scale,
42109 pointer: null
42110 });
42111 }
42112 /**
42113 *
42114 * @private
42115 */
42116
42117 }, {
42118 key: "_zoomOut",
42119 value: function _zoomOut() {
42120 var scaleOld = this.body.view.scale;
42121 var scale = this.body.view.scale / (1 + this.options.keyboard.speed.zoom);
42122 var translation = this.body.view.translation;
42123 var scaleFrac = scale / scaleOld;
42124 var tx = (1 - scaleFrac) * this.canvas.canvasViewCenter.x + translation.x * scaleFrac;
42125 var ty = (1 - scaleFrac) * this.canvas.canvasViewCenter.y + translation.y * scaleFrac;
42126 this.body.view.scale = scale;
42127 this.body.view.translation = {
42128 x: tx,
42129 y: ty
42130 };
42131 this.body.emitter.emit('zoom', {
42132 direction: '-',
42133 scale: this.body.view.scale,
42134 pointer: null
42135 });
42136 }
42137 /**
42138 * bind all keys using keycharm.
42139 */
42140
42141 }, {
42142 key: "configureKeyboardBindings",
42143 value: function configureKeyboardBindings() {
42144 var _this3 = this;
42145
42146 if (this.keycharm !== undefined) {
42147 this.keycharm.destroy();
42148 }
42149
42150 if (this.options.keyboard.enabled === true) {
42151 if (this.options.keyboard.bindToWindow === true) {
42152 this.keycharm = keycharm({
42153 container: window,
42154 preventDefault: true
42155 });
42156 } else {
42157 this.keycharm = keycharm({
42158 container: this.canvas.frame,
42159 preventDefault: true
42160 });
42161 }
42162
42163 this.keycharm.reset();
42164
42165 if (this.activated === true) {
42166 this.keycharm.bind("up", function () {
42167 _this3.bindToRedraw("_moveUp");
42168 }, "keydown");
42169 this.keycharm.bind("down", function () {
42170 _this3.bindToRedraw("_moveDown");
42171 }, "keydown");
42172 this.keycharm.bind("left", function () {
42173 _this3.bindToRedraw("_moveLeft");
42174 }, "keydown");
42175 this.keycharm.bind("right", function () {
42176 _this3.bindToRedraw("_moveRight");
42177 }, "keydown");
42178 this.keycharm.bind("=", function () {
42179 _this3.bindToRedraw("_zoomIn");
42180 }, "keydown");
42181 this.keycharm.bind("num+", function () {
42182 _this3.bindToRedraw("_zoomIn");
42183 }, "keydown");
42184 this.keycharm.bind("num-", function () {
42185 _this3.bindToRedraw("_zoomOut");
42186 }, "keydown");
42187 this.keycharm.bind("-", function () {
42188 _this3.bindToRedraw("_zoomOut");
42189 }, "keydown");
42190 this.keycharm.bind("[", function () {
42191 _this3.bindToRedraw("_zoomOut");
42192 }, "keydown");
42193 this.keycharm.bind("]", function () {
42194 _this3.bindToRedraw("_zoomIn");
42195 }, "keydown");
42196 this.keycharm.bind("pageup", function () {
42197 _this3.bindToRedraw("_zoomIn");
42198 }, "keydown");
42199 this.keycharm.bind("pagedown", function () {
42200 _this3.bindToRedraw("_zoomOut");
42201 }, "keydown");
42202 this.keycharm.bind("up", function () {
42203 _this3.unbindFromRedraw("_moveUp");
42204 }, "keyup");
42205 this.keycharm.bind("down", function () {
42206 _this3.unbindFromRedraw("_moveDown");
42207 }, "keyup");
42208 this.keycharm.bind("left", function () {
42209 _this3.unbindFromRedraw("_moveLeft");
42210 }, "keyup");
42211 this.keycharm.bind("right", function () {
42212 _this3.unbindFromRedraw("_moveRight");
42213 }, "keyup");
42214 this.keycharm.bind("=", function () {
42215 _this3.unbindFromRedraw("_zoomIn");
42216 }, "keyup");
42217 this.keycharm.bind("num+", function () {
42218 _this3.unbindFromRedraw("_zoomIn");
42219 }, "keyup");
42220 this.keycharm.bind("num-", function () {
42221 _this3.unbindFromRedraw("_zoomOut");
42222 }, "keyup");
42223 this.keycharm.bind("-", function () {
42224 _this3.unbindFromRedraw("_zoomOut");
42225 }, "keyup");
42226 this.keycharm.bind("[", function () {
42227 _this3.unbindFromRedraw("_zoomOut");
42228 }, "keyup");
42229 this.keycharm.bind("]", function () {
42230 _this3.unbindFromRedraw("_zoomIn");
42231 }, "keyup");
42232 this.keycharm.bind("pageup", function () {
42233 _this3.unbindFromRedraw("_zoomIn");
42234 }, "keyup");
42235 this.keycharm.bind("pagedown", function () {
42236 _this3.unbindFromRedraw("_zoomOut");
42237 }, "keyup");
42238 }
42239 }
42240 }
42241 }]);
42242
42243 return NavigationHandler;
42244}();
42245
42246/**
42247 * Popup is a class to create a popup window with some text
42248 */
42249
42250var Popup =
42251/*#__PURE__*/
42252function () {
42253 /**
42254 * @param {Element} container The container object.
42255 * @param {string} overflowMethod How the popup should act to overflowing ('flip' or 'cap')
42256 */
42257 function Popup(container, overflowMethod) {
42258 _classCallCheck(this, Popup);
42259
42260 this.container = container;
42261 this.overflowMethod = overflowMethod || 'cap';
42262 this.x = 0;
42263 this.y = 0;
42264 this.padding = 5;
42265 this.hidden = false; // create the frame
42266
42267 this.frame = document.createElement('div');
42268 this.frame.className = 'vis-tooltip';
42269 this.container.appendChild(this.frame);
42270 }
42271 /**
42272 * @param {number} x Horizontal position of the popup window
42273 * @param {number} y Vertical position of the popup window
42274 */
42275
42276
42277 _createClass(Popup, [{
42278 key: "setPosition",
42279 value: function setPosition(x, y) {
42280 this.x = parseInt(x);
42281 this.y = parseInt(y);
42282 }
42283 /**
42284 * Set the content for the popup window. This can be HTML code or text.
42285 * @param {string | Element} content
42286 */
42287
42288 }, {
42289 key: "setText",
42290 value: function setText(content) {
42291 if (content instanceof Element) {
42292 this.frame.innerHTML = '';
42293 this.frame.appendChild(content);
42294 } else {
42295 this.frame.innerHTML = content; // string containing text or HTML
42296 }
42297 }
42298 /**
42299 * Show the popup window
42300 * @param {boolean} [doShow] Show or hide the window
42301 */
42302
42303 }, {
42304 key: "show",
42305 value: function show(doShow) {
42306 if (doShow === undefined) {
42307 doShow = true;
42308 }
42309
42310 if (doShow === true) {
42311 var height = this.frame.clientHeight;
42312 var width = this.frame.clientWidth;
42313 var maxHeight = this.frame.parentNode.clientHeight;
42314 var maxWidth = this.frame.parentNode.clientWidth;
42315 var left = 0,
42316 top = 0;
42317
42318 if (this.overflowMethod == 'flip') {
42319 var isLeft = false,
42320 isTop = true; // Where around the position it's located
42321
42322 if (this.y - height < this.padding) {
42323 isTop = false;
42324 }
42325
42326 if (this.x + width > maxWidth - this.padding) {
42327 isLeft = true;
42328 }
42329
42330 if (isLeft) {
42331 left = this.x - width;
42332 } else {
42333 left = this.x;
42334 }
42335
42336 if (isTop) {
42337 top = this.y - height;
42338 } else {
42339 top = this.y;
42340 }
42341 } else {
42342 top = this.y - height;
42343
42344 if (top + height + this.padding > maxHeight) {
42345 top = maxHeight - height - this.padding;
42346 }
42347
42348 if (top < this.padding) {
42349 top = this.padding;
42350 }
42351
42352 left = this.x;
42353
42354 if (left + width + this.padding > maxWidth) {
42355 left = maxWidth - width - this.padding;
42356 }
42357
42358 if (left < this.padding) {
42359 left = this.padding;
42360 }
42361 }
42362
42363 this.frame.style.left = left + "px";
42364 this.frame.style.top = top + "px";
42365 this.frame.style.visibility = "visible";
42366 this.hidden = false;
42367 } else {
42368 this.hide();
42369 }
42370 }
42371 /**
42372 * Hide the popup window
42373 */
42374
42375 }, {
42376 key: "hide",
42377 value: function hide() {
42378 this.hidden = true;
42379 this.frame.style.left = "0";
42380 this.frame.style.top = "0";
42381 this.frame.style.visibility = "hidden";
42382 }
42383 /**
42384 * Remove the popup window
42385 */
42386
42387 }, {
42388 key: "destroy",
42389 value: function destroy() {
42390 this.frame.parentNode.removeChild(this.frame); // Remove element from DOM
42391 }
42392 }]);
42393
42394 return Popup;
42395}();
42396
42397/**
42398 * Handler for interactions
42399 */
42400
42401var InteractionHandler =
42402/*#__PURE__*/
42403function () {
42404 /**
42405 * @param {Object} body
42406 * @param {Canvas} canvas
42407 * @param {SelectionHandler} selectionHandler
42408 */
42409 function InteractionHandler(body, canvas, selectionHandler) {
42410 _classCallCheck(this, InteractionHandler);
42411
42412 this.body = body;
42413 this.canvas = canvas;
42414 this.selectionHandler = selectionHandler;
42415 this.navigationHandler = new NavigationHandler(body, canvas); // bind the events from hammer to functions in this object
42416
42417 this.body.eventListeners.onTap = this.onTap.bind(this);
42418 this.body.eventListeners.onTouch = this.onTouch.bind(this);
42419 this.body.eventListeners.onDoubleTap = this.onDoubleTap.bind(this);
42420 this.body.eventListeners.onHold = this.onHold.bind(this);
42421 this.body.eventListeners.onDragStart = this.onDragStart.bind(this);
42422 this.body.eventListeners.onDrag = this.onDrag.bind(this);
42423 this.body.eventListeners.onDragEnd = this.onDragEnd.bind(this);
42424 this.body.eventListeners.onMouseWheel = this.onMouseWheel.bind(this);
42425 this.body.eventListeners.onPinch = this.onPinch.bind(this);
42426 this.body.eventListeners.onMouseMove = this.onMouseMove.bind(this);
42427 this.body.eventListeners.onRelease = this.onRelease.bind(this);
42428 this.body.eventListeners.onContext = this.onContext.bind(this);
42429 this.touchTime = 0;
42430 this.drag = {};
42431 this.pinch = {};
42432 this.popup = undefined;
42433 this.popupObj = undefined;
42434 this.popupTimer = undefined;
42435 this.body.functions.getPointer = this.getPointer.bind(this);
42436 this.options = {};
42437 this.defaultOptions = {
42438 dragNodes: true,
42439 dragView: true,
42440 hover: false,
42441 keyboard: {
42442 enabled: false,
42443 speed: {
42444 x: 10,
42445 y: 10,
42446 zoom: 0.02
42447 },
42448 bindToWindow: true
42449 },
42450 navigationButtons: false,
42451 tooltipDelay: 300,
42452 zoomView: true,
42453 zoomSpeed: 1
42454 };
42455 extend(this.options, this.defaultOptions);
42456 this.bindEventListeners();
42457 }
42458 /**
42459 * Binds event listeners
42460 */
42461
42462
42463 _createClass(InteractionHandler, [{
42464 key: "bindEventListeners",
42465 value: function bindEventListeners() {
42466 var _this = this;
42467
42468 this.body.emitter.on('destroy', function () {
42469 clearTimeout(_this.popupTimer);
42470 delete _this.body.functions.getPointer;
42471 });
42472 }
42473 /**
42474 *
42475 * @param {Object} options
42476 */
42477
42478 }, {
42479 key: "setOptions",
42480 value: function setOptions(options) {
42481 if (options !== undefined) {
42482 // extend all but the values in fields
42483 var fields = ['hideEdgesOnDrag', 'hideEdgesOnZoom', 'hideNodesOnDrag', 'keyboard', 'multiselect', 'selectable', 'selectConnectedEdges'];
42484 selectiveNotDeepExtend(fields, this.options, options); // merge the keyboard options in.
42485
42486 mergeOptions(this.options, options, 'keyboard');
42487
42488 if (options.tooltip) {
42489 extend(this.options.tooltip, options.tooltip);
42490
42491 if (options.tooltip.color) {
42492 this.options.tooltip.color = parseColor(options.tooltip.color);
42493 }
42494 }
42495 }
42496
42497 this.navigationHandler.setOptions(this.options);
42498 }
42499 /**
42500 * Get the pointer location from a touch location
42501 * @param {{x: number, y: number}} touch
42502 * @return {{x: number, y: number}} pointer
42503 * @private
42504 */
42505
42506 }, {
42507 key: "getPointer",
42508 value: function getPointer(touch) {
42509 return {
42510 x: touch.x - getAbsoluteLeft(this.canvas.frame.canvas),
42511 y: touch.y - getAbsoluteTop(this.canvas.frame.canvas)
42512 };
42513 }
42514 /**
42515 * On start of a touch gesture, store the pointer
42516 * @param {Event} event The event
42517 * @private
42518 */
42519
42520 }, {
42521 key: "onTouch",
42522 value: function onTouch(event) {
42523 if (new Date().valueOf() - this.touchTime > 50) {
42524 this.drag.pointer = this.getPointer(event.center);
42525 this.drag.pinched = false;
42526 this.pinch.scale = this.body.view.scale; // to avoid double fireing of this event because we have two hammer instances. (on canvas and on frame)
42527
42528 this.touchTime = new Date().valueOf();
42529 }
42530 }
42531 /**
42532 * handle tap/click event: select/unselect a node
42533 * @param {Event} event
42534 * @private
42535 */
42536
42537 }, {
42538 key: "onTap",
42539 value: function onTap(event) {
42540 var pointer = this.getPointer(event.center);
42541 var multiselect = this.selectionHandler.options.multiselect && (event.changedPointers[0].ctrlKey || event.changedPointers[0].metaKey);
42542 this.checkSelectionChanges(pointer, event, multiselect);
42543
42544 this.selectionHandler._generateClickEvent('click', event, pointer);
42545 }
42546 /**
42547 * handle doubletap event
42548 * @param {Event} event
42549 * @private
42550 */
42551
42552 }, {
42553 key: "onDoubleTap",
42554 value: function onDoubleTap(event) {
42555 var pointer = this.getPointer(event.center);
42556
42557 this.selectionHandler._generateClickEvent('doubleClick', event, pointer);
42558 }
42559 /**
42560 * handle long tap event: multi select nodes
42561 * @param {Event} event
42562 * @private
42563 */
42564
42565 }, {
42566 key: "onHold",
42567 value: function onHold(event) {
42568 var pointer = this.getPointer(event.center);
42569 var multiselect = this.selectionHandler.options.multiselect;
42570 this.checkSelectionChanges(pointer, event, multiselect);
42571
42572 this.selectionHandler._generateClickEvent('click', event, pointer);
42573
42574 this.selectionHandler._generateClickEvent('hold', event, pointer);
42575 }
42576 /**
42577 * handle the release of the screen
42578 *
42579 * @param {Event} event
42580 * @private
42581 */
42582
42583 }, {
42584 key: "onRelease",
42585 value: function onRelease(event) {
42586 if (new Date().valueOf() - this.touchTime > 10) {
42587 var pointer = this.getPointer(event.center);
42588
42589 this.selectionHandler._generateClickEvent('release', event, pointer); // to avoid double fireing of this event because we have two hammer instances. (on canvas and on frame)
42590
42591
42592 this.touchTime = new Date().valueOf();
42593 }
42594 }
42595 /**
42596 *
42597 * @param {Event} event
42598 */
42599
42600 }, {
42601 key: "onContext",
42602 value: function onContext(event) {
42603 var pointer = this.getPointer({
42604 x: event.clientX,
42605 y: event.clientY
42606 });
42607
42608 this.selectionHandler._generateClickEvent('oncontext', event, pointer);
42609 }
42610 /**
42611 * Select and deselect nodes depending current selection change.
42612 *
42613 * For changing nodes, select/deselect events are fired.
42614 *
42615 * NOTE: For a given edge, if one connecting node is deselected and with the same
42616 * click the other node is selected, no events for the edge will fire.
42617 * It was selected and it will remain selected.
42618 *
42619 * TODO: This is all SelectionHandler calls; the method should be moved to there.
42620 *
42621 * @param {{x: number, y: number}} pointer
42622 * @param {Event} event
42623 * @param {boolean} [add=false]
42624 */
42625
42626 }, {
42627 key: "checkSelectionChanges",
42628 value: function checkSelectionChanges(pointer, event) {
42629 var add = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
42630 var previousSelection = this.selectionHandler.getSelection();
42631 var selected = false;
42632
42633 if (add === true) {
42634 selected = this.selectionHandler.selectAdditionalOnPoint(pointer);
42635 } else {
42636 selected = this.selectionHandler.selectOnPoint(pointer);
42637 }
42638
42639 var currentSelection = this.selectionHandler.getSelection(); // See NOTE in method comment for the reason to do it like this
42640
42641 var deselectedItems = this._determineDifference(previousSelection, currentSelection);
42642
42643 var selectedItems = this._determineDifference(currentSelection, previousSelection);
42644
42645 if (deselectedItems.edges.length > 0) {
42646 this.selectionHandler._generateClickEvent('deselectEdge', event, pointer, previousSelection);
42647
42648 selected = true;
42649 }
42650
42651 if (deselectedItems.nodes.length > 0) {
42652 this.selectionHandler._generateClickEvent('deselectNode', event, pointer, previousSelection);
42653
42654 selected = true;
42655 }
42656
42657 if (selectedItems.nodes.length > 0) {
42658 this.selectionHandler._generateClickEvent('selectNode', event, pointer);
42659
42660 selected = true;
42661 }
42662
42663 if (selectedItems.edges.length > 0) {
42664 this.selectionHandler._generateClickEvent('selectEdge', event, pointer);
42665
42666 selected = true;
42667 } // fire the select event if anything has been selected or deselected
42668
42669
42670 if (selected === true) {
42671 // select or unselect
42672 this.selectionHandler._generateClickEvent('select', event, pointer);
42673 }
42674 }
42675 /**
42676 * Remove all node and edge id's from the first set that are present in the second one.
42677 *
42678 * @param {{nodes: Array.<Node>, edges: Array.<vis.Edge>}} firstSet
42679 * @param {{nodes: Array.<Node>, edges: Array.<vis.Edge>}} secondSet
42680 * @returns {{nodes: Array.<Node>, edges: Array.<vis.Edge>}}
42681 * @private
42682 */
42683
42684 }, {
42685 key: "_determineDifference",
42686 value: function _determineDifference(firstSet, secondSet) {
42687 var arrayDiff = function arrayDiff(firstArr, secondArr) {
42688 var result = [];
42689
42690 for (var i = 0; i < firstArr.length; i++) {
42691 var value = firstArr[i];
42692
42693 if (secondArr.indexOf(value) === -1) {
42694 result.push(value);
42695 }
42696 }
42697
42698 return result;
42699 };
42700
42701 return {
42702 nodes: arrayDiff(firstSet.nodes, secondSet.nodes),
42703 edges: arrayDiff(firstSet.edges, secondSet.edges)
42704 };
42705 }
42706 /**
42707 * This function is called by onDragStart.
42708 * It is separated out because we can then overload it for the datamanipulation system.
42709 *
42710 * @param {Event} event
42711 * @private
42712 */
42713
42714 }, {
42715 key: "onDragStart",
42716 value: function onDragStart(event) {
42717 //in case the touch event was triggered on an external div, do the initial touch now.
42718 if (this.drag.pointer === undefined) {
42719 this.onTouch(event);
42720 } // note: drag.pointer is set in onTouch to get the initial touch location
42721
42722
42723 var node = this.selectionHandler.getNodeAt(this.drag.pointer);
42724 this.drag.dragging = true;
42725 this.drag.selection = [];
42726 this.drag.translation = extend({}, this.body.view.translation); // copy the object
42727
42728 this.drag.nodeId = undefined;
42729
42730 if (node !== undefined && this.options.dragNodes === true) {
42731 this.drag.nodeId = node.id; // select the clicked node if not yet selected
42732
42733 if (node.isSelected() === false) {
42734 this.selectionHandler.unselectAll();
42735 this.selectionHandler.selectObject(node);
42736 } // after select to contain the node
42737
42738
42739 this.selectionHandler._generateClickEvent('dragStart', event, this.drag.pointer);
42740
42741 var selection = this.selectionHandler.selectionObj.nodes; // create an array with the selected nodes and their original location and status
42742
42743 for (var nodeId in selection) {
42744 if (selection.hasOwnProperty(nodeId)) {
42745 var object = selection[nodeId];
42746 var s = {
42747 id: object.id,
42748 node: object,
42749 // store original x, y, xFixed and yFixed, make the node temporarily Fixed
42750 x: object.x,
42751 y: object.y,
42752 xFixed: object.options.fixed.x,
42753 yFixed: object.options.fixed.y
42754 };
42755 object.options.fixed.x = true;
42756 object.options.fixed.y = true;
42757 this.drag.selection.push(s);
42758 }
42759 }
42760 } else {
42761 // fallback if no node is selected and thus the view is dragged.
42762 this.selectionHandler._generateClickEvent('dragStart', event, this.drag.pointer, undefined, true);
42763 }
42764 }
42765 /**
42766 * handle drag event
42767 * @param {Event} event
42768 * @private
42769 */
42770
42771 }, {
42772 key: "onDrag",
42773 value: function onDrag(event) {
42774 var _this2 = this;
42775
42776 if (this.drag.pinched === true) {
42777 return;
42778 } // remove the focus on node if it is focussed on by the focusOnNode
42779
42780
42781 this.body.emitter.emit('unlockNode');
42782 var pointer = this.getPointer(event.center);
42783 var selection = this.drag.selection;
42784
42785 if (selection && selection.length && this.options.dragNodes === true) {
42786 this.selectionHandler._generateClickEvent('dragging', event, pointer); // calculate delta's and new location
42787
42788
42789 var deltaX = pointer.x - this.drag.pointer.x;
42790 var deltaY = pointer.y - this.drag.pointer.y; // update position of all selected nodes
42791
42792 selection.forEach(function (selection) {
42793 var node = selection.node; // only move the node if it was not fixed initially
42794
42795 if (selection.xFixed === false) {
42796 node.x = _this2.canvas._XconvertDOMtoCanvas(_this2.canvas._XconvertCanvasToDOM(selection.x) + deltaX);
42797 } // only move the node if it was not fixed initially
42798
42799
42800 if (selection.yFixed === false) {
42801 node.y = _this2.canvas._YconvertDOMtoCanvas(_this2.canvas._YconvertCanvasToDOM(selection.y) + deltaY);
42802 }
42803 }); // start the simulation of the physics
42804
42805 this.body.emitter.emit('startSimulation');
42806 } else {
42807 // move the network
42808 if (this.options.dragView === true) {
42809 this.selectionHandler._generateClickEvent('dragging', event, pointer, undefined, true); // if the drag was not started properly because the click started outside the network div, start it now.
42810
42811
42812 if (this.drag.pointer === undefined) {
42813 this.onDragStart(event);
42814 return;
42815 }
42816
42817 var diffX = pointer.x - this.drag.pointer.x;
42818 var diffY = pointer.y - this.drag.pointer.y;
42819 this.body.view.translation = {
42820 x: this.drag.translation.x + diffX,
42821 y: this.drag.translation.y + diffY
42822 };
42823 this.body.emitter.emit('_requestRedraw');
42824 }
42825 }
42826 }
42827 /**
42828 * handle drag start event
42829 * @param {Event} event
42830 * @private
42831 */
42832
42833 }, {
42834 key: "onDragEnd",
42835 value: function onDragEnd(event) {
42836 this.drag.dragging = false;
42837 var selection = this.drag.selection;
42838
42839 if (selection && selection.length) {
42840 selection.forEach(function (s) {
42841 // restore original xFixed and yFixed
42842 s.node.options.fixed.x = s.xFixed;
42843 s.node.options.fixed.y = s.yFixed;
42844 });
42845
42846 this.selectionHandler._generateClickEvent('dragEnd', event, this.getPointer(event.center));
42847
42848 this.body.emitter.emit('startSimulation');
42849 } else {
42850 this.selectionHandler._generateClickEvent('dragEnd', event, this.getPointer(event.center), undefined, true);
42851
42852 this.body.emitter.emit('_requestRedraw');
42853 }
42854 }
42855 /**
42856 * Handle pinch event
42857 * @param {Event} event The event
42858 * @private
42859 */
42860
42861 }, {
42862 key: "onPinch",
42863 value: function onPinch(event) {
42864 var pointer = this.getPointer(event.center);
42865 this.drag.pinched = true;
42866
42867 if (this.pinch['scale'] === undefined) {
42868 this.pinch.scale = 1;
42869 } // TODO: enabled moving while pinching?
42870
42871
42872 var scale = this.pinch.scale * event.scale;
42873 this.zoom(scale, pointer);
42874 }
42875 /**
42876 * Zoom the network in or out
42877 * @param {number} scale a number around 1, and between 0.01 and 10
42878 * @param {{x: number, y: number}} pointer Position on screen
42879 * @private
42880 */
42881
42882 }, {
42883 key: "zoom",
42884 value: function zoom(scale, pointer) {
42885 if (this.options.zoomView === true) {
42886 var scaleOld = this.body.view.scale;
42887
42888 if (scale < 0.00001) {
42889 scale = 0.00001;
42890 }
42891
42892 if (scale > 10) {
42893 scale = 10;
42894 }
42895
42896 var preScaleDragPointer = undefined;
42897
42898 if (this.drag !== undefined) {
42899 if (this.drag.dragging === true) {
42900 preScaleDragPointer = this.canvas.DOMtoCanvas(this.drag.pointer);
42901 }
42902 } // + this.canvas.frame.canvas.clientHeight / 2
42903
42904
42905 var translation = this.body.view.translation;
42906 var scaleFrac = scale / scaleOld;
42907 var tx = (1 - scaleFrac) * pointer.x + translation.x * scaleFrac;
42908 var ty = (1 - scaleFrac) * pointer.y + translation.y * scaleFrac;
42909 this.body.view.scale = scale;
42910 this.body.view.translation = {
42911 x: tx,
42912 y: ty
42913 };
42914
42915 if (preScaleDragPointer != undefined) {
42916 var postScaleDragPointer = this.canvas.canvasToDOM(preScaleDragPointer);
42917 this.drag.pointer.x = postScaleDragPointer.x;
42918 this.drag.pointer.y = postScaleDragPointer.y;
42919 }
42920
42921 this.body.emitter.emit('_requestRedraw');
42922
42923 if (scaleOld < scale) {
42924 this.body.emitter.emit('zoom', {
42925 direction: '+',
42926 scale: this.body.view.scale,
42927 pointer: pointer
42928 });
42929 } else {
42930 this.body.emitter.emit('zoom', {
42931 direction: '-',
42932 scale: this.body.view.scale,
42933 pointer: pointer
42934 });
42935 }
42936 }
42937 }
42938 /**
42939 * Event handler for mouse wheel event, used to zoom the timeline
42940 * See http://adomas.org/javascript-mouse-wheel/
42941 * https://github.com/EightMedia/hammer.js/issues/256
42942 * @param {MouseEvent} event
42943 * @private
42944 */
42945
42946 }, {
42947 key: "onMouseWheel",
42948 value: function onMouseWheel(event) {
42949 if (this.options.zoomView === true) {
42950 // If delta is nonzero, handle it.
42951 // Basically, delta is now positive if wheel was scrolled up,
42952 // and negative, if wheel was scrolled down.
42953 if (event.deltaY !== 0) {
42954 // calculate the new scale
42955 var scale = this.body.view.scale;
42956 scale *= 1 + (event.deltaY < 0 ? 1 : -1) * (this.options.zoomSpeed * 0.1); // calculate the pointer location
42957
42958 var pointer = this.getPointer({
42959 x: event.clientX,
42960 y: event.clientY
42961 }); // apply the new scale
42962
42963 this.zoom(scale, pointer);
42964 } // Prevent default actions caused by mouse wheel.
42965
42966
42967 event.preventDefault();
42968 }
42969 }
42970 /**
42971 * Mouse move handler for checking whether the title moves over a node with a title.
42972 * @param {Event} event
42973 * @private
42974 */
42975
42976 }, {
42977 key: "onMouseMove",
42978 value: function onMouseMove(event) {
42979 var _this3 = this;
42980
42981 var pointer = this.getPointer({
42982 x: event.clientX,
42983 y: event.clientY
42984 });
42985 var popupVisible = false; // check if the previously selected node is still selected
42986
42987 if (this.popup !== undefined) {
42988 if (this.popup.hidden === false) {
42989 this._checkHidePopup(pointer);
42990 } // if the popup was not hidden above
42991
42992
42993 if (this.popup.hidden === false) {
42994 popupVisible = true;
42995 this.popup.setPosition(pointer.x + 3, pointer.y - 5);
42996 this.popup.show();
42997 }
42998 } // if we bind the keyboard to the div, we have to highlight it to use it. This highlights it on mouse over.
42999
43000
43001 if (this.options.keyboard.bindToWindow === false && this.options.keyboard.enabled === true) {
43002 this.canvas.frame.focus();
43003 } // start a timeout that will check if the mouse is positioned above an element
43004
43005
43006 if (popupVisible === false) {
43007 if (this.popupTimer !== undefined) {
43008 clearInterval(this.popupTimer); // stop any running calculationTimer
43009
43010 this.popupTimer = undefined;
43011 }
43012
43013 if (!this.drag.dragging) {
43014 this.popupTimer = setTimeout(function () {
43015 return _this3._checkShowPopup(pointer);
43016 }, this.options.tooltipDelay);
43017 }
43018 } // adding hover highlights
43019
43020
43021 if (this.options.hover === true) {
43022 this.selectionHandler.hoverObject(event, pointer);
43023 }
43024 }
43025 /**
43026 * Check if there is an element on the given position in the network
43027 * (a node or edge). If so, and if this element has a title,
43028 * show a popup window with its title.
43029 *
43030 * @param {{x:number, y:number}} pointer
43031 * @private
43032 */
43033
43034 }, {
43035 key: "_checkShowPopup",
43036 value: function _checkShowPopup(pointer) {
43037 var x = this.canvas._XconvertDOMtoCanvas(pointer.x);
43038
43039 var y = this.canvas._YconvertDOMtoCanvas(pointer.y);
43040
43041 var pointerObj = {
43042 left: x,
43043 top: y,
43044 right: x,
43045 bottom: y
43046 };
43047 var previousPopupObjId = this.popupObj === undefined ? undefined : this.popupObj.id;
43048 var nodeUnderCursor = false;
43049 var popupType = 'node'; // check if a node is under the cursor.
43050
43051 if (this.popupObj === undefined) {
43052 // search the nodes for overlap, select the top one in case of multiple nodes
43053 var nodeIndices = this.body.nodeIndices;
43054 var nodes = this.body.nodes;
43055 var node;
43056 var overlappingNodes = [];
43057
43058 for (var i = 0; i < nodeIndices.length; i++) {
43059 node = nodes[nodeIndices[i]];
43060
43061 if (node.isOverlappingWith(pointerObj) === true) {
43062 nodeUnderCursor = true;
43063
43064 if (node.getTitle() !== undefined) {
43065 overlappingNodes.push(nodeIndices[i]);
43066 }
43067 }
43068 }
43069
43070 if (overlappingNodes.length > 0) {
43071 // if there are overlapping nodes, select the last one, this is the one which is drawn on top of the others
43072 this.popupObj = nodes[overlappingNodes[overlappingNodes.length - 1]]; // if you hover over a node, the title of the edge is not supposed to be shown.
43073
43074 nodeUnderCursor = true;
43075 }
43076 }
43077
43078 if (this.popupObj === undefined && nodeUnderCursor === false) {
43079 // search the edges for overlap
43080 var edgeIndices = this.body.edgeIndices;
43081 var edges = this.body.edges;
43082 var edge;
43083 var overlappingEdges = [];
43084
43085 for (var _i = 0; _i < edgeIndices.length; _i++) {
43086 edge = edges[edgeIndices[_i]];
43087
43088 if (edge.isOverlappingWith(pointerObj) === true) {
43089 if (edge.connected === true && edge.getTitle() !== undefined) {
43090 overlappingEdges.push(edgeIndices[_i]);
43091 }
43092 }
43093 }
43094
43095 if (overlappingEdges.length > 0) {
43096 this.popupObj = edges[overlappingEdges[overlappingEdges.length - 1]];
43097 popupType = 'edge';
43098 }
43099 }
43100
43101 if (this.popupObj !== undefined) {
43102 // show popup message window
43103 if (this.popupObj.id !== previousPopupObjId) {
43104 if (this.popup === undefined) {
43105 this.popup = new Popup(this.canvas.frame);
43106 }
43107
43108 this.popup.popupTargetType = popupType;
43109 this.popup.popupTargetId = this.popupObj.id; // adjust a small offset such that the mouse cursor is located in the
43110 // bottom left location of the popup, and you can easily move over the
43111 // popup area
43112
43113 this.popup.setPosition(pointer.x + 3, pointer.y - 5);
43114 this.popup.setText(this.popupObj.getTitle());
43115 this.popup.show();
43116 this.body.emitter.emit('showPopup', this.popupObj.id);
43117 }
43118 } else {
43119 if (this.popup !== undefined) {
43120 this.popup.hide();
43121 this.body.emitter.emit('hidePopup');
43122 }
43123 }
43124 }
43125 /**
43126 * Check if the popup must be hidden, which is the case when the mouse is no
43127 * longer hovering on the object
43128 * @param {{x:number, y:number}} pointer
43129 * @private
43130 */
43131
43132 }, {
43133 key: "_checkHidePopup",
43134 value: function _checkHidePopup(pointer) {
43135 var pointerObj = this.selectionHandler._pointerToPositionObject(pointer);
43136
43137 var stillOnObj = false;
43138
43139 if (this.popup.popupTargetType === 'node') {
43140 if (this.body.nodes[this.popup.popupTargetId] !== undefined) {
43141 stillOnObj = this.body.nodes[this.popup.popupTargetId].isOverlappingWith(pointerObj); // if the mouse is still one the node, we have to check if it is not also on one that is drawn on top of it.
43142 // we initially only check stillOnObj because this is much faster.
43143
43144 if (stillOnObj === true) {
43145 var overNode = this.selectionHandler.getNodeAt(pointer);
43146 stillOnObj = overNode === undefined ? false : overNode.id === this.popup.popupTargetId;
43147 }
43148 }
43149 } else {
43150 if (this.selectionHandler.getNodeAt(pointer) === undefined) {
43151 if (this.body.edges[this.popup.popupTargetId] !== undefined) {
43152 stillOnObj = this.body.edges[this.popup.popupTargetId].isOverlappingWith(pointerObj);
43153 }
43154 }
43155 }
43156
43157 if (stillOnObj === false) {
43158 this.popupObj = undefined;
43159 this.popup.hide();
43160 this.body.emitter.emit('hidePopup');
43161 }
43162 }
43163 }]);
43164
43165 return InteractionHandler;
43166}();
43167
43168/**
43169 * The handler for selections
43170 */
43171
43172var SelectionHandler =
43173/*#__PURE__*/
43174function () {
43175 /**
43176 * @param {Object} body
43177 * @param {Canvas} canvas
43178 */
43179 function SelectionHandler(body, canvas) {
43180 var _this = this;
43181
43182 _classCallCheck(this, SelectionHandler);
43183
43184 this.body = body;
43185 this.canvas = canvas;
43186 this.selectionObj = {
43187 nodes: [],
43188 edges: []
43189 };
43190 this.hoverObj = {
43191 nodes: {},
43192 edges: {}
43193 };
43194 this.options = {};
43195 this.defaultOptions = {
43196 multiselect: false,
43197 selectable: true,
43198 selectConnectedEdges: true,
43199 hoverConnectedEdges: true
43200 };
43201 extend(this.options, this.defaultOptions);
43202 this.body.emitter.on("_dataChanged", function () {
43203 _this.updateSelection();
43204 });
43205 }
43206 /**
43207 *
43208 * @param {Object} [options]
43209 */
43210
43211
43212 _createClass(SelectionHandler, [{
43213 key: "setOptions",
43214 value: function setOptions(options) {
43215 if (options !== undefined) {
43216 var fields = ['multiselect', 'hoverConnectedEdges', 'selectable', 'selectConnectedEdges'];
43217 selectiveDeepExtend(fields, this.options, options);
43218 }
43219 }
43220 /**
43221 * handles the selection part of the tap;
43222 *
43223 * @param {{x: number, y: number}} pointer
43224 * @returns {boolean}
43225 */
43226
43227 }, {
43228 key: "selectOnPoint",
43229 value: function selectOnPoint(pointer) {
43230 var selected = false;
43231
43232 if (this.options.selectable === true) {
43233 var obj = this.getNodeAt(pointer) || this.getEdgeAt(pointer); // unselect after getting the objects in order to restore width and height.
43234
43235 this.unselectAll();
43236
43237 if (obj !== undefined) {
43238 selected = this.selectObject(obj);
43239 }
43240
43241 this.body.emitter.emit("_requestRedraw");
43242 }
43243
43244 return selected;
43245 }
43246 /**
43247 *
43248 * @param {{x: number, y: number}} pointer
43249 * @returns {boolean}
43250 */
43251
43252 }, {
43253 key: "selectAdditionalOnPoint",
43254 value: function selectAdditionalOnPoint(pointer) {
43255 var selectionChanged = false;
43256
43257 if (this.options.selectable === true) {
43258 var obj = this.getNodeAt(pointer) || this.getEdgeAt(pointer);
43259
43260 if (obj !== undefined) {
43261 selectionChanged = true;
43262
43263 if (obj.isSelected() === true) {
43264 this.deselectObject(obj);
43265 } else {
43266 this.selectObject(obj);
43267 }
43268
43269 this.body.emitter.emit("_requestRedraw");
43270 }
43271 }
43272
43273 return selectionChanged;
43274 }
43275 /**
43276 * Create an object containing the standard fields for an event.
43277 *
43278 * @param {Event} event
43279 * @param {{x: number, y: number}} pointer Object with the x and y screen coordinates of the mouse
43280 * @returns {{}}
43281 * @private
43282 */
43283
43284 }, {
43285 key: "_initBaseEvent",
43286 value: function _initBaseEvent(event, pointer) {
43287 var properties = {};
43288 properties['pointer'] = {
43289 DOM: {
43290 x: pointer.x,
43291 y: pointer.y
43292 },
43293 canvas: this.canvas.DOMtoCanvas(pointer)
43294 };
43295 properties['event'] = event;
43296 return properties;
43297 }
43298 /**
43299 * Generate an event which the user can catch.
43300 *
43301 * This adds some extra data to the event with respect to cursor position and
43302 * selected nodes and edges.
43303 *
43304 * @param {string} eventType Name of event to send
43305 * @param {Event} event
43306 * @param {{x: number, y: number}} pointer Object with the x and y screen coordinates of the mouse
43307 * @param {Object|undefined} oldSelection If present, selection state before event occured
43308 * @param {boolean|undefined} [emptySelection=false] Indicate if selection data should be passed
43309 */
43310
43311 }, {
43312 key: "_generateClickEvent",
43313 value: function _generateClickEvent(eventType, event, pointer, oldSelection) {
43314 var emptySelection = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
43315
43316 var properties = this._initBaseEvent(event, pointer);
43317
43318 if (emptySelection === true) {
43319 properties.nodes = [];
43320 properties.edges = [];
43321 } else {
43322 var tmp = this.getSelection();
43323 properties.nodes = tmp.nodes;
43324 properties.edges = tmp.edges;
43325 }
43326
43327 if (oldSelection !== undefined) {
43328 properties['previousSelection'] = oldSelection;
43329 }
43330
43331 if (eventType == 'click') {
43332 // For the time being, restrict this functionality to
43333 // just the click event.
43334 properties.items = this.getClickedItems(pointer);
43335 }
43336
43337 if (event.controlEdge !== undefined) {
43338 properties.controlEdge = event.controlEdge;
43339 }
43340
43341 this.body.emitter.emit(eventType, properties);
43342 }
43343 /**
43344 *
43345 * @param {Object} obj
43346 * @param {boolean} [highlightEdges=this.options.selectConnectedEdges]
43347 * @returns {boolean}
43348 */
43349
43350 }, {
43351 key: "selectObject",
43352 value: function selectObject(obj) {
43353 var highlightEdges = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.options.selectConnectedEdges;
43354
43355 if (obj !== undefined) {
43356 if (obj instanceof Node) {
43357 if (highlightEdges === true) {
43358 this._selectConnectedEdges(obj);
43359 }
43360 }
43361
43362 obj.select();
43363
43364 this._addToSelection(obj);
43365
43366 return true;
43367 }
43368
43369 return false;
43370 }
43371 /**
43372 *
43373 * @param {Object} obj
43374 */
43375
43376 }, {
43377 key: "deselectObject",
43378 value: function deselectObject(obj) {
43379 if (obj.isSelected() === true) {
43380 obj.selected = false;
43381
43382 this._removeFromSelection(obj);
43383 }
43384 }
43385 /**
43386 * retrieve all nodes overlapping with given object
43387 * @param {Object} object An object with parameters left, top, right, bottom
43388 * @return {number[]} An array with id's of the overlapping nodes
43389 * @private
43390 */
43391
43392 }, {
43393 key: "_getAllNodesOverlappingWith",
43394 value: function _getAllNodesOverlappingWith(object) {
43395 var overlappingNodes = [];
43396 var nodes = this.body.nodes;
43397
43398 for (var i = 0; i < this.body.nodeIndices.length; i++) {
43399 var nodeId = this.body.nodeIndices[i];
43400
43401 if (nodes[nodeId].isOverlappingWith(object)) {
43402 overlappingNodes.push(nodeId);
43403 }
43404 }
43405
43406 return overlappingNodes;
43407 }
43408 /**
43409 * Return a position object in canvasspace from a single point in screenspace
43410 *
43411 * @param {{x: number, y: number}} pointer
43412 * @returns {{left: number, top: number, right: number, bottom: number}}
43413 * @private
43414 */
43415
43416 }, {
43417 key: "_pointerToPositionObject",
43418 value: function _pointerToPositionObject(pointer) {
43419 var canvasPos = this.canvas.DOMtoCanvas(pointer);
43420 return {
43421 left: canvasPos.x - 1,
43422 top: canvasPos.y + 1,
43423 right: canvasPos.x + 1,
43424 bottom: canvasPos.y - 1
43425 };
43426 }
43427 /**
43428 * Get the top node at the passed point (like a click)
43429 *
43430 * @param {{x: number, y: number}} pointer
43431 * @param {boolean} [returnNode=true]
43432 * @return {Node | undefined} node
43433 */
43434
43435 }, {
43436 key: "getNodeAt",
43437 value: function getNodeAt(pointer) {
43438 var returnNode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
43439
43440 // we first check if this is an navigation controls element
43441 var positionObject = this._pointerToPositionObject(pointer);
43442
43443 var overlappingNodes = this._getAllNodesOverlappingWith(positionObject); // if there are overlapping nodes, select the last one, this is the
43444 // one which is drawn on top of the others
43445
43446
43447 if (overlappingNodes.length > 0) {
43448 if (returnNode === true) {
43449 return this.body.nodes[overlappingNodes[overlappingNodes.length - 1]];
43450 } else {
43451 return overlappingNodes[overlappingNodes.length - 1];
43452 }
43453 } else {
43454 return undefined;
43455 }
43456 }
43457 /**
43458 * retrieve all edges overlapping with given object, selector is around center
43459 * @param {Object} object An object with parameters left, top, right, bottom
43460 * @param {number[]} overlappingEdges An array with id's of the overlapping nodes
43461 * @private
43462 */
43463
43464 }, {
43465 key: "_getEdgesOverlappingWith",
43466 value: function _getEdgesOverlappingWith(object, overlappingEdges) {
43467 var edges = this.body.edges;
43468
43469 for (var i = 0; i < this.body.edgeIndices.length; i++) {
43470 var edgeId = this.body.edgeIndices[i];
43471
43472 if (edges[edgeId].isOverlappingWith(object)) {
43473 overlappingEdges.push(edgeId);
43474 }
43475 }
43476 }
43477 /**
43478 * retrieve all nodes overlapping with given object
43479 * @param {Object} object An object with parameters left, top, right, bottom
43480 * @return {number[]} An array with id's of the overlapping nodes
43481 * @private
43482 */
43483
43484 }, {
43485 key: "_getAllEdgesOverlappingWith",
43486 value: function _getAllEdgesOverlappingWith(object) {
43487 var overlappingEdges = [];
43488
43489 this._getEdgesOverlappingWith(object, overlappingEdges);
43490
43491 return overlappingEdges;
43492 }
43493 /**
43494 * Get the edges nearest to the passed point (like a click)
43495 *
43496 * @param {{x: number, y: number}} pointer
43497 * @param {boolean} [returnEdge=true]
43498 * @return {Edge | undefined} node
43499 */
43500
43501 }, {
43502 key: "getEdgeAt",
43503 value: function getEdgeAt(pointer) {
43504 var returnEdge = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
43505 // Iterate over edges, pick closest within 10
43506 var canvasPos = this.canvas.DOMtoCanvas(pointer);
43507 var mindist = 10;
43508 var overlappingEdge = null;
43509 var edges = this.body.edges;
43510
43511 for (var i = 0; i < this.body.edgeIndices.length; i++) {
43512 var edgeId = this.body.edgeIndices[i];
43513 var edge = edges[edgeId];
43514
43515 if (edge.connected) {
43516 var xFrom = edge.from.x;
43517 var yFrom = edge.from.y;
43518 var xTo = edge.to.x;
43519 var yTo = edge.to.y;
43520 var dist = edge.edgeType.getDistanceToEdge(xFrom, yFrom, xTo, yTo, canvasPos.x, canvasPos.y);
43521
43522 if (dist < mindist) {
43523 overlappingEdge = edgeId;
43524 mindist = dist;
43525 }
43526 }
43527 }
43528
43529 if (overlappingEdge !== null) {
43530 if (returnEdge === true) {
43531 return this.body.edges[overlappingEdge];
43532 } else {
43533 return overlappingEdge;
43534 }
43535 } else {
43536 return undefined;
43537 }
43538 }
43539 /**
43540 * Add object to the selection array.
43541 *
43542 * @param {Object} obj
43543 * @private
43544 */
43545
43546 }, {
43547 key: "_addToSelection",
43548 value: function _addToSelection(obj) {
43549 if (obj instanceof Node) {
43550 this.selectionObj.nodes[obj.id] = obj;
43551 } else {
43552 this.selectionObj.edges[obj.id] = obj;
43553 }
43554 }
43555 /**
43556 * Add object to the selection array.
43557 *
43558 * @param {Object} obj
43559 * @private
43560 */
43561
43562 }, {
43563 key: "_addToHover",
43564 value: function _addToHover(obj) {
43565 if (obj instanceof Node) {
43566 this.hoverObj.nodes[obj.id] = obj;
43567 } else {
43568 this.hoverObj.edges[obj.id] = obj;
43569 }
43570 }
43571 /**
43572 * Remove a single option from selection.
43573 *
43574 * @param {Object} obj
43575 * @private
43576 */
43577
43578 }, {
43579 key: "_removeFromSelection",
43580 value: function _removeFromSelection(obj) {
43581 if (obj instanceof Node) {
43582 delete this.selectionObj.nodes[obj.id];
43583
43584 this._unselectConnectedEdges(obj);
43585 } else {
43586 delete this.selectionObj.edges[obj.id];
43587 }
43588 }
43589 /**
43590 * Unselect all. The selectionObj is useful for this.
43591 */
43592
43593 }, {
43594 key: "unselectAll",
43595 value: function unselectAll() {
43596 for (var nodeId in this.selectionObj.nodes) {
43597 if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
43598 this.selectionObj.nodes[nodeId].unselect();
43599 }
43600 }
43601
43602 for (var edgeId in this.selectionObj.edges) {
43603 if (this.selectionObj.edges.hasOwnProperty(edgeId)) {
43604 this.selectionObj.edges[edgeId].unselect();
43605 }
43606 }
43607
43608 this.selectionObj = {
43609 nodes: {},
43610 edges: {}
43611 };
43612 }
43613 /**
43614 * return the number of selected nodes
43615 *
43616 * @returns {number}
43617 * @private
43618 */
43619
43620 }, {
43621 key: "_getSelectedNodeCount",
43622 value: function _getSelectedNodeCount() {
43623 var count = 0;
43624
43625 for (var nodeId in this.selectionObj.nodes) {
43626 if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
43627 count += 1;
43628 }
43629 }
43630
43631 return count;
43632 }
43633 /**
43634 * return the selected node
43635 *
43636 * @returns {number}
43637 * @private
43638 */
43639
43640 }, {
43641 key: "_getSelectedNode",
43642 value: function _getSelectedNode() {
43643 for (var nodeId in this.selectionObj.nodes) {
43644 if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
43645 return this.selectionObj.nodes[nodeId];
43646 }
43647 }
43648
43649 return undefined;
43650 }
43651 /**
43652 * return the selected edge
43653 *
43654 * @returns {number}
43655 * @private
43656 */
43657
43658 }, {
43659 key: "_getSelectedEdge",
43660 value: function _getSelectedEdge() {
43661 for (var edgeId in this.selectionObj.edges) {
43662 if (this.selectionObj.edges.hasOwnProperty(edgeId)) {
43663 return this.selectionObj.edges[edgeId];
43664 }
43665 }
43666
43667 return undefined;
43668 }
43669 /**
43670 * return the number of selected edges
43671 *
43672 * @returns {number}
43673 * @private
43674 */
43675
43676 }, {
43677 key: "_getSelectedEdgeCount",
43678 value: function _getSelectedEdgeCount() {
43679 var count = 0;
43680
43681 for (var edgeId in this.selectionObj.edges) {
43682 if (this.selectionObj.edges.hasOwnProperty(edgeId)) {
43683 count += 1;
43684 }
43685 }
43686
43687 return count;
43688 }
43689 /**
43690 * return the number of selected objects.
43691 *
43692 * @returns {number}
43693 * @private
43694 */
43695
43696 }, {
43697 key: "_getSelectedObjectCount",
43698 value: function _getSelectedObjectCount() {
43699 var count = 0;
43700
43701 for (var nodeId in this.selectionObj.nodes) {
43702 if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
43703 count += 1;
43704 }
43705 }
43706
43707 for (var edgeId in this.selectionObj.edges) {
43708 if (this.selectionObj.edges.hasOwnProperty(edgeId)) {
43709 count += 1;
43710 }
43711 }
43712
43713 return count;
43714 }
43715 /**
43716 * Check if anything is selected
43717 *
43718 * @returns {boolean}
43719 * @private
43720 */
43721
43722 }, {
43723 key: "_selectionIsEmpty",
43724 value: function _selectionIsEmpty() {
43725 for (var nodeId in this.selectionObj.nodes) {
43726 if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
43727 return false;
43728 }
43729 }
43730
43731 for (var edgeId in this.selectionObj.edges) {
43732 if (this.selectionObj.edges.hasOwnProperty(edgeId)) {
43733 return false;
43734 }
43735 }
43736
43737 return true;
43738 }
43739 /**
43740 * check if one of the selected nodes is a cluster.
43741 *
43742 * @returns {boolean}
43743 * @private
43744 */
43745
43746 }, {
43747 key: "_clusterInSelection",
43748 value: function _clusterInSelection() {
43749 for (var nodeId in this.selectionObj.nodes) {
43750 if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
43751 if (this.selectionObj.nodes[nodeId].clusterSize > 1) {
43752 return true;
43753 }
43754 }
43755 }
43756
43757 return false;
43758 }
43759 /**
43760 * select the edges connected to the node that is being selected
43761 *
43762 * @param {Node} node
43763 * @private
43764 */
43765
43766 }, {
43767 key: "_selectConnectedEdges",
43768 value: function _selectConnectedEdges(node) {
43769 for (var i = 0; i < node.edges.length; i++) {
43770 var edge = node.edges[i];
43771 edge.select();
43772
43773 this._addToSelection(edge);
43774 }
43775 }
43776 /**
43777 * select the edges connected to the node that is being selected
43778 *
43779 * @param {Node} node
43780 * @private
43781 */
43782
43783 }, {
43784 key: "_hoverConnectedEdges",
43785 value: function _hoverConnectedEdges(node) {
43786 for (var i = 0; i < node.edges.length; i++) {
43787 var edge = node.edges[i];
43788 edge.hover = true;
43789
43790 this._addToHover(edge);
43791 }
43792 }
43793 /**
43794 * unselect the edges connected to the node that is being selected
43795 *
43796 * @param {Node} node
43797 * @private
43798 */
43799
43800 }, {
43801 key: "_unselectConnectedEdges",
43802 value: function _unselectConnectedEdges(node) {
43803 for (var i = 0; i < node.edges.length; i++) {
43804 var edge = node.edges[i];
43805 edge.unselect();
43806
43807 this._removeFromSelection(edge);
43808 }
43809 }
43810 /**
43811 * Remove the highlight from a node or edge, in response to mouse movement
43812 *
43813 * @param {Event} event
43814 * @param {{x: number, y: number}} pointer object with the x and y screen coordinates of the mouse
43815 * @param {Node|vis.Edge} object
43816 * @private
43817 */
43818
43819 }, {
43820 key: "emitBlurEvent",
43821 value: function emitBlurEvent(event, pointer, object) {
43822 var properties = this._initBaseEvent(event, pointer);
43823
43824 if (object.hover === true) {
43825 object.hover = false;
43826
43827 if (object instanceof Node) {
43828 properties.node = object.id;
43829 this.body.emitter.emit("blurNode", properties);
43830 } else {
43831 properties.edge = object.id;
43832 this.body.emitter.emit("blurEdge", properties);
43833 }
43834 }
43835 }
43836 /**
43837 * Create the highlight for a node or edge, in response to mouse movement
43838 *
43839 * @param {Event} event
43840 * @param {{x: number, y: number}} pointer object with the x and y screen coordinates of the mouse
43841 * @param {Node|vis.Edge} object
43842 * @returns {boolean} hoverChanged
43843 * @private
43844 */
43845
43846 }, {
43847 key: "emitHoverEvent",
43848 value: function emitHoverEvent(event, pointer, object) {
43849 var properties = this._initBaseEvent(event, pointer);
43850
43851 var hoverChanged = false;
43852
43853 if (object.hover === false) {
43854 object.hover = true;
43855
43856 this._addToHover(object);
43857
43858 hoverChanged = true;
43859
43860 if (object instanceof Node) {
43861 properties.node = object.id;
43862 this.body.emitter.emit("hoverNode", properties);
43863 } else {
43864 properties.edge = object.id;
43865 this.body.emitter.emit("hoverEdge", properties);
43866 }
43867 }
43868
43869 return hoverChanged;
43870 }
43871 /**
43872 * Perform actions in response to a mouse movement.
43873 *
43874 * @param {Event} event
43875 * @param {{x: number, y: number}} pointer | object with the x and y screen coordinates of the mouse
43876 */
43877
43878 }, {
43879 key: "hoverObject",
43880 value: function hoverObject(event, pointer) {
43881 var object = this.getNodeAt(pointer);
43882
43883 if (object === undefined) {
43884 object = this.getEdgeAt(pointer);
43885 }
43886
43887 var hoverChanged = false; // remove all node hover highlights
43888
43889 for (var nodeId in this.hoverObj.nodes) {
43890 if (this.hoverObj.nodes.hasOwnProperty(nodeId)) {
43891 if (object === undefined || object instanceof Node && object.id != nodeId || object instanceof Edge) {
43892 this.emitBlurEvent(event, pointer, this.hoverObj.nodes[nodeId]);
43893 delete this.hoverObj.nodes[nodeId];
43894 hoverChanged = true;
43895 }
43896 }
43897 } // removing all edge hover highlights
43898
43899
43900 for (var edgeId in this.hoverObj.edges) {
43901 if (this.hoverObj.edges.hasOwnProperty(edgeId)) {
43902 // if the hover has been changed here it means that the node has been hovered over or off
43903 // we then do not use the emitBlurEvent method here.
43904 if (hoverChanged === true) {
43905 this.hoverObj.edges[edgeId].hover = false;
43906 delete this.hoverObj.edges[edgeId];
43907 } // if the blur remains the same and the object is undefined (mouse off) or another
43908 // edge has been hovered, or another node has been hovered we blur the edge.
43909 else if (object === undefined || object instanceof Edge && object.id != edgeId || object instanceof Node && !object.hover) {
43910 this.emitBlurEvent(event, pointer, this.hoverObj.edges[edgeId]);
43911 delete this.hoverObj.edges[edgeId];
43912 hoverChanged = true;
43913 }
43914 }
43915 }
43916
43917 if (object !== undefined) {
43918 var hoveredEdgesCount = Object.keys(this.hoverObj.edges).length;
43919 var hoveredNodesCount = Object.keys(this.hoverObj.nodes).length;
43920 var newOnlyHoveredEdge = object instanceof Edge && hoveredEdgesCount === 0 && hoveredNodesCount === 0;
43921 var newOnlyHoveredNode = object instanceof Node && hoveredEdgesCount === 0 && hoveredNodesCount === 0;
43922
43923 if (hoverChanged || newOnlyHoveredEdge || newOnlyHoveredNode) {
43924 hoverChanged = this.emitHoverEvent(event, pointer, object);
43925 }
43926
43927 if (object instanceof Node && this.options.hoverConnectedEdges === true) {
43928 this._hoverConnectedEdges(object);
43929 }
43930 }
43931
43932 if (hoverChanged === true) {
43933 this.body.emitter.emit('_requestRedraw');
43934 }
43935 }
43936 /**
43937 *
43938 * retrieve the currently selected objects
43939 * @return {{nodes: Array.<string>, edges: Array.<string>}} selection
43940 */
43941
43942 }, {
43943 key: "getSelection",
43944 value: function getSelection() {
43945 var nodeIds = this.getSelectedNodes();
43946 var edgeIds = this.getSelectedEdges();
43947 return {
43948 nodes: nodeIds,
43949 edges: edgeIds
43950 };
43951 }
43952 /**
43953 *
43954 * retrieve the currently selected nodes
43955 * @return {string[]} selection An array with the ids of the
43956 * selected nodes.
43957 */
43958
43959 }, {
43960 key: "getSelectedNodes",
43961 value: function getSelectedNodes() {
43962 var idArray = [];
43963
43964 if (this.options.selectable === true) {
43965 for (var nodeId in this.selectionObj.nodes) {
43966 if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
43967 idArray.push(this.selectionObj.nodes[nodeId].id);
43968 }
43969 }
43970 }
43971
43972 return idArray;
43973 }
43974 /**
43975 *
43976 * retrieve the currently selected edges
43977 * @return {Array} selection An array with the ids of the
43978 * selected nodes.
43979 */
43980
43981 }, {
43982 key: "getSelectedEdges",
43983 value: function getSelectedEdges() {
43984 var idArray = [];
43985
43986 if (this.options.selectable === true) {
43987 for (var edgeId in this.selectionObj.edges) {
43988 if (this.selectionObj.edges.hasOwnProperty(edgeId)) {
43989 idArray.push(this.selectionObj.edges[edgeId].id);
43990 }
43991 }
43992 }
43993
43994 return idArray;
43995 }
43996 /**
43997 * Updates the current selection
43998 * @param {{nodes: Array.<string>, edges: Array.<string>}} selection
43999 * @param {Object} options Options
44000 */
44001
44002 }, {
44003 key: "setSelection",
44004 value: function setSelection(selection) {
44005 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
44006 var i, id;
44007 if (!selection || !selection.nodes && !selection.edges) throw 'Selection must be an object with nodes and/or edges properties'; // first unselect any selected node, if option is true or undefined
44008
44009 if (options.unselectAll || options.unselectAll === undefined) {
44010 this.unselectAll();
44011 }
44012
44013 if (selection.nodes) {
44014 for (i = 0; i < selection.nodes.length; i++) {
44015 id = selection.nodes[i];
44016 var node = this.body.nodes[id];
44017
44018 if (!node) {
44019 throw new RangeError('Node with id "' + id + '" not found');
44020 } // don't select edges with it
44021
44022
44023 this.selectObject(node, options.highlightEdges);
44024 }
44025 }
44026
44027 if (selection.edges) {
44028 for (i = 0; i < selection.edges.length; i++) {
44029 id = selection.edges[i];
44030 var edge = this.body.edges[id];
44031
44032 if (!edge) {
44033 throw new RangeError('Edge with id "' + id + '" not found');
44034 }
44035
44036 this.selectObject(edge);
44037 }
44038 }
44039
44040 this.body.emitter.emit('_requestRedraw');
44041 }
44042 /**
44043 * select zero or more nodes with the option to highlight edges
44044 * @param {number[] | string[]} selection An array with the ids of the
44045 * selected nodes.
44046 * @param {boolean} [highlightEdges]
44047 */
44048
44049 }, {
44050 key: "selectNodes",
44051 value: function selectNodes(selection) {
44052 var highlightEdges = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
44053 if (!selection || selection.length === undefined) throw 'Selection must be an array with ids';
44054 this.setSelection({
44055 nodes: selection
44056 }, {
44057 highlightEdges: highlightEdges
44058 });
44059 }
44060 /**
44061 * select zero or more edges
44062 * @param {number[] | string[]} selection An array with the ids of the
44063 * selected nodes.
44064 */
44065
44066 }, {
44067 key: "selectEdges",
44068 value: function selectEdges(selection) {
44069 if (!selection || selection.length === undefined) throw 'Selection must be an array with ids';
44070 this.setSelection({
44071 edges: selection
44072 });
44073 }
44074 /**
44075 * Validate the selection: remove ids of nodes which no longer exist
44076 * @private
44077 */
44078
44079 }, {
44080 key: "updateSelection",
44081 value: function updateSelection() {
44082 for (var nodeId in this.selectionObj.nodes) {
44083 if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
44084 if (!this.body.nodes.hasOwnProperty(nodeId)) {
44085 delete this.selectionObj.nodes[nodeId];
44086 }
44087 }
44088 }
44089
44090 for (var edgeId in this.selectionObj.edges) {
44091 if (this.selectionObj.edges.hasOwnProperty(edgeId)) {
44092 if (!this.body.edges.hasOwnProperty(edgeId)) {
44093 delete this.selectionObj.edges[edgeId];
44094 }
44095 }
44096 }
44097 }
44098 /**
44099 * Determine all the visual elements clicked which are on the given point.
44100 *
44101 * All elements are returned; this includes nodes, edges and their labels.
44102 * The order returned is from highest to lowest, i.e. element 0 of the return
44103 * value is the topmost item clicked on.
44104 *
44105 * The return value consists of an array of the following possible elements:
44106 *
44107 * - `{nodeId:number}` - node with given id clicked on
44108 * - `{nodeId:number, labelId:0}` - label of node with given id clicked on
44109 * - `{edgeId:number}` - edge with given id clicked on
44110 * - `{edge:number, labelId:0}` - label of edge with given id clicked on
44111 *
44112 * ## NOTES
44113 *
44114 * - Currently, there is only one label associated with a node or an edge,
44115 * but this is expected to change somewhere in the future.
44116 * - Since there is no z-indexing yet, it is not really possible to set the nodes and
44117 * edges in the correct order. For the time being, nodes come first.
44118 *
44119 * @param {point} pointer mouse position in screen coordinates
44120 * @returns {Array.<nodeClickItem|nodeLabelClickItem|edgeClickItem|edgeLabelClickItem>}
44121 * @private
44122 */
44123
44124 }, {
44125 key: "getClickedItems",
44126 value: function getClickedItems(pointer) {
44127 var point = this.canvas.DOMtoCanvas(pointer);
44128 var items = []; // Note reverse order; we want the topmost clicked items to be first in the array
44129 // Also note that selected nodes are disregarded here; these normally display on top
44130
44131 var nodeIndices = this.body.nodeIndices;
44132 var nodes = this.body.nodes;
44133
44134 for (var i = nodeIndices.length - 1; i >= 0; i--) {
44135 var node = nodes[nodeIndices[i]];
44136 var ret = node.getItemsOnPoint(point);
44137 items.push.apply(items, ret); // Append the return value to the running list.
44138 }
44139
44140 var edgeIndices = this.body.edgeIndices;
44141 var edges = this.body.edges;
44142
44143 for (var _i = edgeIndices.length - 1; _i >= 0; _i--) {
44144 var edge = edges[edgeIndices[_i]];
44145
44146 var _ret = edge.getItemsOnPoint(point);
44147
44148 items.push.apply(items, _ret); // Append the return value to the running list.
44149 }
44150
44151 return items;
44152 }
44153 }]);
44154
44155 return SelectionHandler;
44156}();
44157
44158var nativeSort = [].sort;
44159var test$3 = [1, 2, 3]; // IE8-
44160
44161var FAILS_ON_UNDEFINED = fails(function () {
44162 test$3.sort(undefined);
44163}); // V8 bug
44164
44165var FAILS_ON_NULL = fails(function () {
44166 test$3.sort(null);
44167}); // Old WebKit
44168
44169var SLOPPY_METHOD$2 = sloppyArrayMethod('sort');
44170var FORCED$3 = FAILS_ON_UNDEFINED || !FAILS_ON_NULL || SLOPPY_METHOD$2; // `Array.prototype.sort` method
44171// https://tc39.github.io/ecma262/#sec-array.prototype.sort
44172
44173_export({
44174 target: 'Array',
44175 proto: true,
44176 forced: FORCED$3
44177}, {
44178 sort: function sort(comparefn) {
44179 return comparefn === undefined ? nativeSort.call(toObject(this)) : nativeSort.call(toObject(this), aFunction$1(comparefn));
44180 }
44181});
44182
44183var timsort = createCommonjsModule(function (module, exports) {
44184 /****
44185 * The MIT License
44186 *
44187 * Copyright (c) 2015 Marco Ziccardi
44188 *
44189 * Permission is hereby granted, free of charge, to any person obtaining a copy
44190 * of this software and associated documentation files (the "Software"), to deal
44191 * in the Software without restriction, including without limitation the rights
44192 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
44193 * copies of the Software, and to permit persons to whom the Software is
44194 * furnished to do so, subject to the following conditions:
44195 *
44196 * The above copyright notice and this permission notice shall be included in
44197 * all copies or substantial portions of the Software.
44198 *
44199 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44200 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44201 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
44202 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
44203 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44204 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44205 * THE SOFTWARE.
44206 *
44207 ****/
44208 (function (global, factory) {
44209 {
44210 factory(exports);
44211 }
44212 })(commonjsGlobal, function (exports) {
44213
44214 exports.__esModule = true;
44215 exports.sort = sort;
44216
44217 function _classCallCheck(instance, Constructor) {
44218 if (!(instance instanceof Constructor)) {
44219 throw new TypeError('Cannot call a class as a function');
44220 }
44221 }
44222
44223 var DEFAULT_MIN_MERGE = 32;
44224 var DEFAULT_MIN_GALLOPING = 7;
44225 var DEFAULT_TMP_STORAGE_LENGTH = 256;
44226 var POWERS_OF_TEN = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9];
44227
44228 function log10(x) {
44229 if (x < 1e5) {
44230 if (x < 1e2) {
44231 return x < 1e1 ? 0 : 1;
44232 }
44233
44234 if (x < 1e4) {
44235 return x < 1e3 ? 2 : 3;
44236 }
44237
44238 return 4;
44239 }
44240
44241 if (x < 1e7) {
44242 return x < 1e6 ? 5 : 6;
44243 }
44244
44245 if (x < 1e9) {
44246 return x < 1e8 ? 7 : 8;
44247 }
44248
44249 return 9;
44250 }
44251
44252 function alphabeticalCompare(a, b) {
44253 if (a === b) {
44254 return 0;
44255 }
44256
44257 if (~~a === a && ~~b === b) {
44258 if (a === 0 || b === 0) {
44259 return a < b ? -1 : 1;
44260 }
44261
44262 if (a < 0 || b < 0) {
44263 if (b >= 0) {
44264 return -1;
44265 }
44266
44267 if (a >= 0) {
44268 return 1;
44269 }
44270
44271 a = -a;
44272 b = -b;
44273 }
44274
44275 var al = log10(a);
44276 var bl = log10(b);
44277 var t = 0;
44278
44279 if (al < bl) {
44280 a *= POWERS_OF_TEN[bl - al - 1];
44281 b /= 10;
44282 t = -1;
44283 } else if (al > bl) {
44284 b *= POWERS_OF_TEN[al - bl - 1];
44285 a /= 10;
44286 t = 1;
44287 }
44288
44289 if (a === b) {
44290 return t;
44291 }
44292
44293 return a < b ? -1 : 1;
44294 }
44295
44296 var aStr = String(a);
44297 var bStr = String(b);
44298
44299 if (aStr === bStr) {
44300 return 0;
44301 }
44302
44303 return aStr < bStr ? -1 : 1;
44304 }
44305
44306 function minRunLength(n) {
44307 var r = 0;
44308
44309 while (n >= DEFAULT_MIN_MERGE) {
44310 r |= n & 1;
44311 n >>= 1;
44312 }
44313
44314 return n + r;
44315 }
44316
44317 function makeAscendingRun(array, lo, hi, compare) {
44318 var runHi = lo + 1;
44319
44320 if (runHi === hi) {
44321 return 1;
44322 }
44323
44324 if (compare(array[runHi++], array[lo]) < 0) {
44325 while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) {
44326 runHi++;
44327 }
44328
44329 reverseRun(array, lo, runHi);
44330 } else {
44331 while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) {
44332 runHi++;
44333 }
44334 }
44335
44336 return runHi - lo;
44337 }
44338
44339 function reverseRun(array, lo, hi) {
44340 hi--;
44341
44342 while (lo < hi) {
44343 var t = array[lo];
44344 array[lo++] = array[hi];
44345 array[hi--] = t;
44346 }
44347 }
44348
44349 function binaryInsertionSort(array, lo, hi, start, compare) {
44350 if (start === lo) {
44351 start++;
44352 }
44353
44354 for (; start < hi; start++) {
44355 var pivot = array[start];
44356 var left = lo;
44357 var right = start;
44358
44359 while (left < right) {
44360 var mid = left + right >>> 1;
44361
44362 if (compare(pivot, array[mid]) < 0) {
44363 right = mid;
44364 } else {
44365 left = mid + 1;
44366 }
44367 }
44368
44369 var n = start - left;
44370
44371 switch (n) {
44372 case 3:
44373 array[left + 3] = array[left + 2];
44374
44375 case 2:
44376 array[left + 2] = array[left + 1];
44377
44378 case 1:
44379 array[left + 1] = array[left];
44380 break;
44381
44382 default:
44383 while (n > 0) {
44384 array[left + n] = array[left + n - 1];
44385 n--;
44386 }
44387
44388 }
44389
44390 array[left] = pivot;
44391 }
44392 }
44393
44394 function gallopLeft(value, array, start, length, hint, compare) {
44395 var lastOffset = 0;
44396 var maxOffset = 0;
44397 var offset = 1;
44398
44399 if (compare(value, array[start + hint]) > 0) {
44400 maxOffset = length - hint;
44401
44402 while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) {
44403 lastOffset = offset;
44404 offset = (offset << 1) + 1;
44405
44406 if (offset <= 0) {
44407 offset = maxOffset;
44408 }
44409 }
44410
44411 if (offset > maxOffset) {
44412 offset = maxOffset;
44413 }
44414
44415 lastOffset += hint;
44416 offset += hint;
44417 } else {
44418 maxOffset = hint + 1;
44419
44420 while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) {
44421 lastOffset = offset;
44422 offset = (offset << 1) + 1;
44423
44424 if (offset <= 0) {
44425 offset = maxOffset;
44426 }
44427 }
44428
44429 if (offset > maxOffset) {
44430 offset = maxOffset;
44431 }
44432
44433 var tmp = lastOffset;
44434 lastOffset = hint - offset;
44435 offset = hint - tmp;
44436 }
44437
44438 lastOffset++;
44439
44440 while (lastOffset < offset) {
44441 var m = lastOffset + (offset - lastOffset >>> 1);
44442
44443 if (compare(value, array[start + m]) > 0) {
44444 lastOffset = m + 1;
44445 } else {
44446 offset = m;
44447 }
44448 }
44449
44450 return offset;
44451 }
44452
44453 function gallopRight(value, array, start, length, hint, compare) {
44454 var lastOffset = 0;
44455 var maxOffset = 0;
44456 var offset = 1;
44457
44458 if (compare(value, array[start + hint]) < 0) {
44459 maxOffset = hint + 1;
44460
44461 while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) {
44462 lastOffset = offset;
44463 offset = (offset << 1) + 1;
44464
44465 if (offset <= 0) {
44466 offset = maxOffset;
44467 }
44468 }
44469
44470 if (offset > maxOffset) {
44471 offset = maxOffset;
44472 }
44473
44474 var tmp = lastOffset;
44475 lastOffset = hint - offset;
44476 offset = hint - tmp;
44477 } else {
44478 maxOffset = length - hint;
44479
44480 while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) {
44481 lastOffset = offset;
44482 offset = (offset << 1) + 1;
44483
44484 if (offset <= 0) {
44485 offset = maxOffset;
44486 }
44487 }
44488
44489 if (offset > maxOffset) {
44490 offset = maxOffset;
44491 }
44492
44493 lastOffset += hint;
44494 offset += hint;
44495 }
44496
44497 lastOffset++;
44498
44499 while (lastOffset < offset) {
44500 var m = lastOffset + (offset - lastOffset >>> 1);
44501
44502 if (compare(value, array[start + m]) < 0) {
44503 offset = m;
44504 } else {
44505 lastOffset = m + 1;
44506 }
44507 }
44508
44509 return offset;
44510 }
44511
44512 var TimSort = function () {
44513 function TimSort(array, compare) {
44514 _classCallCheck(this, TimSort);
44515
44516 this.array = null;
44517 this.compare = null;
44518 this.minGallop = DEFAULT_MIN_GALLOPING;
44519 this.length = 0;
44520 this.tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH;
44521 this.stackLength = 0;
44522 this.runStart = null;
44523 this.runLength = null;
44524 this.stackSize = 0;
44525 this.array = array;
44526 this.compare = compare;
44527 this.length = array.length;
44528
44529 if (this.length < 2 * DEFAULT_TMP_STORAGE_LENGTH) {
44530 this.tmpStorageLength = this.length >>> 1;
44531 }
44532
44533 this.tmp = new Array(this.tmpStorageLength);
44534 this.stackLength = this.length < 120 ? 5 : this.length < 1542 ? 10 : this.length < 119151 ? 19 : 40;
44535 this.runStart = new Array(this.stackLength);
44536 this.runLength = new Array(this.stackLength);
44537 }
44538
44539 TimSort.prototype.pushRun = function pushRun(runStart, runLength) {
44540 this.runStart[this.stackSize] = runStart;
44541 this.runLength[this.stackSize] = runLength;
44542 this.stackSize += 1;
44543 };
44544
44545 TimSort.prototype.mergeRuns = function mergeRuns() {
44546 while (this.stackSize > 1) {
44547 var n = this.stackSize - 2;
44548
44549 if (n >= 1 && this.runLength[n - 1] <= this.runLength[n] + this.runLength[n + 1] || n >= 2 && this.runLength[n - 2] <= this.runLength[n] + this.runLength[n - 1]) {
44550 if (this.runLength[n - 1] < this.runLength[n + 1]) {
44551 n--;
44552 }
44553 } else if (this.runLength[n] > this.runLength[n + 1]) {
44554 break;
44555 }
44556
44557 this.mergeAt(n);
44558 }
44559 };
44560
44561 TimSort.prototype.forceMergeRuns = function forceMergeRuns() {
44562 while (this.stackSize > 1) {
44563 var n = this.stackSize - 2;
44564
44565 if (n > 0 && this.runLength[n - 1] < this.runLength[n + 1]) {
44566 n--;
44567 }
44568
44569 this.mergeAt(n);
44570 }
44571 };
44572
44573 TimSort.prototype.mergeAt = function mergeAt(i) {
44574 var compare = this.compare;
44575 var array = this.array;
44576 var start1 = this.runStart[i];
44577 var length1 = this.runLength[i];
44578 var start2 = this.runStart[i + 1];
44579 var length2 = this.runLength[i + 1];
44580 this.runLength[i] = length1 + length2;
44581
44582 if (i === this.stackSize - 3) {
44583 this.runStart[i + 1] = this.runStart[i + 2];
44584 this.runLength[i + 1] = this.runLength[i + 2];
44585 }
44586
44587 this.stackSize--;
44588 var k = gallopRight(array[start2], array, start1, length1, 0, compare);
44589 start1 += k;
44590 length1 -= k;
44591
44592 if (length1 === 0) {
44593 return;
44594 }
44595
44596 length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare);
44597
44598 if (length2 === 0) {
44599 return;
44600 }
44601
44602 if (length1 <= length2) {
44603 this.mergeLow(start1, length1, start2, length2);
44604 } else {
44605 this.mergeHigh(start1, length1, start2, length2);
44606 }
44607 };
44608
44609 TimSort.prototype.mergeLow = function mergeLow(start1, length1, start2, length2) {
44610 var compare = this.compare;
44611 var array = this.array;
44612 var tmp = this.tmp;
44613 var i = 0;
44614
44615 for (i = 0; i < length1; i++) {
44616 tmp[i] = array[start1 + i];
44617 }
44618
44619 var cursor1 = 0;
44620 var cursor2 = start2;
44621 var dest = start1;
44622 array[dest++] = array[cursor2++];
44623
44624 if (--length2 === 0) {
44625 for (i = 0; i < length1; i++) {
44626 array[dest + i] = tmp[cursor1 + i];
44627 }
44628
44629 return;
44630 }
44631
44632 if (length1 === 1) {
44633 for (i = 0; i < length2; i++) {
44634 array[dest + i] = array[cursor2 + i];
44635 }
44636
44637 array[dest + length2] = tmp[cursor1];
44638 return;
44639 }
44640
44641 var minGallop = this.minGallop;
44642
44643 while (true) {
44644 var count1 = 0;
44645 var count2 = 0;
44646 var exit = false;
44647
44648 do {
44649 if (compare(array[cursor2], tmp[cursor1]) < 0) {
44650 array[dest++] = array[cursor2++];
44651 count2++;
44652 count1 = 0;
44653
44654 if (--length2 === 0) {
44655 exit = true;
44656 break;
44657 }
44658 } else {
44659 array[dest++] = tmp[cursor1++];
44660 count1++;
44661 count2 = 0;
44662
44663 if (--length1 === 1) {
44664 exit = true;
44665 break;
44666 }
44667 }
44668 } while ((count1 | count2) < minGallop);
44669
44670 if (exit) {
44671 break;
44672 }
44673
44674 do {
44675 count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare);
44676
44677 if (count1 !== 0) {
44678 for (i = 0; i < count1; i++) {
44679 array[dest + i] = tmp[cursor1 + i];
44680 }
44681
44682 dest += count1;
44683 cursor1 += count1;
44684 length1 -= count1;
44685
44686 if (length1 <= 1) {
44687 exit = true;
44688 break;
44689 }
44690 }
44691
44692 array[dest++] = array[cursor2++];
44693
44694 if (--length2 === 0) {
44695 exit = true;
44696 break;
44697 }
44698
44699 count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare);
44700
44701 if (count2 !== 0) {
44702 for (i = 0; i < count2; i++) {
44703 array[dest + i] = array[cursor2 + i];
44704 }
44705
44706 dest += count2;
44707 cursor2 += count2;
44708 length2 -= count2;
44709
44710 if (length2 === 0) {
44711 exit = true;
44712 break;
44713 }
44714 }
44715
44716 array[dest++] = tmp[cursor1++];
44717
44718 if (--length1 === 1) {
44719 exit = true;
44720 break;
44721 }
44722
44723 minGallop--;
44724 } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
44725
44726 if (exit) {
44727 break;
44728 }
44729
44730 if (minGallop < 0) {
44731 minGallop = 0;
44732 }
44733
44734 minGallop += 2;
44735 }
44736
44737 this.minGallop = minGallop;
44738
44739 if (minGallop < 1) {
44740 this.minGallop = 1;
44741 }
44742
44743 if (length1 === 1) {
44744 for (i = 0; i < length2; i++) {
44745 array[dest + i] = array[cursor2 + i];
44746 }
44747
44748 array[dest + length2] = tmp[cursor1];
44749 } else if (length1 === 0) {
44750 throw new Error('mergeLow preconditions were not respected');
44751 } else {
44752 for (i = 0; i < length1; i++) {
44753 array[dest + i] = tmp[cursor1 + i];
44754 }
44755 }
44756 };
44757
44758 TimSort.prototype.mergeHigh = function mergeHigh(start1, length1, start2, length2) {
44759 var compare = this.compare;
44760 var array = this.array;
44761 var tmp = this.tmp;
44762 var i = 0;
44763
44764 for (i = 0; i < length2; i++) {
44765 tmp[i] = array[start2 + i];
44766 }
44767
44768 var cursor1 = start1 + length1 - 1;
44769 var cursor2 = length2 - 1;
44770 var dest = start2 + length2 - 1;
44771 var customCursor = 0;
44772 var customDest = 0;
44773 array[dest--] = array[cursor1--];
44774
44775 if (--length1 === 0) {
44776 customCursor = dest - (length2 - 1);
44777
44778 for (i = 0; i < length2; i++) {
44779 array[customCursor + i] = tmp[i];
44780 }
44781
44782 return;
44783 }
44784
44785 if (length2 === 1) {
44786 dest -= length1;
44787 cursor1 -= length1;
44788 customDest = dest + 1;
44789 customCursor = cursor1 + 1;
44790
44791 for (i = length1 - 1; i >= 0; i--) {
44792 array[customDest + i] = array[customCursor + i];
44793 }
44794
44795 array[dest] = tmp[cursor2];
44796 return;
44797 }
44798
44799 var minGallop = this.minGallop;
44800
44801 while (true) {
44802 var count1 = 0;
44803 var count2 = 0;
44804 var exit = false;
44805
44806 do {
44807 if (compare(tmp[cursor2], array[cursor1]) < 0) {
44808 array[dest--] = array[cursor1--];
44809 count1++;
44810 count2 = 0;
44811
44812 if (--length1 === 0) {
44813 exit = true;
44814 break;
44815 }
44816 } else {
44817 array[dest--] = tmp[cursor2--];
44818 count2++;
44819 count1 = 0;
44820
44821 if (--length2 === 1) {
44822 exit = true;
44823 break;
44824 }
44825 }
44826 } while ((count1 | count2) < minGallop);
44827
44828 if (exit) {
44829 break;
44830 }
44831
44832 do {
44833 count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare);
44834
44835 if (count1 !== 0) {
44836 dest -= count1;
44837 cursor1 -= count1;
44838 length1 -= count1;
44839 customDest = dest + 1;
44840 customCursor = cursor1 + 1;
44841
44842 for (i = count1 - 1; i >= 0; i--) {
44843 array[customDest + i] = array[customCursor + i];
44844 }
44845
44846 if (length1 === 0) {
44847 exit = true;
44848 break;
44849 }
44850 }
44851
44852 array[dest--] = tmp[cursor2--];
44853
44854 if (--length2 === 1) {
44855 exit = true;
44856 break;
44857 }
44858
44859 count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare);
44860
44861 if (count2 !== 0) {
44862 dest -= count2;
44863 cursor2 -= count2;
44864 length2 -= count2;
44865 customDest = dest + 1;
44866 customCursor = cursor2 + 1;
44867
44868 for (i = 0; i < count2; i++) {
44869 array[customDest + i] = tmp[customCursor + i];
44870 }
44871
44872 if (length2 <= 1) {
44873 exit = true;
44874 break;
44875 }
44876 }
44877
44878 array[dest--] = array[cursor1--];
44879
44880 if (--length1 === 0) {
44881 exit = true;
44882 break;
44883 }
44884
44885 minGallop--;
44886 } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
44887
44888 if (exit) {
44889 break;
44890 }
44891
44892 if (minGallop < 0) {
44893 minGallop = 0;
44894 }
44895
44896 minGallop += 2;
44897 }
44898
44899 this.minGallop = minGallop;
44900
44901 if (minGallop < 1) {
44902 this.minGallop = 1;
44903 }
44904
44905 if (length2 === 1) {
44906 dest -= length1;
44907 cursor1 -= length1;
44908 customDest = dest + 1;
44909 customCursor = cursor1 + 1;
44910
44911 for (i = length1 - 1; i >= 0; i--) {
44912 array[customDest + i] = array[customCursor + i];
44913 }
44914
44915 array[dest] = tmp[cursor2];
44916 } else if (length2 === 0) {
44917 throw new Error('mergeHigh preconditions were not respected');
44918 } else {
44919 customCursor = dest - (length2 - 1);
44920
44921 for (i = 0; i < length2; i++) {
44922 array[customCursor + i] = tmp[i];
44923 }
44924 }
44925 };
44926
44927 return TimSort;
44928 }();
44929
44930 function sort(array, compare, lo, hi) {
44931 if (!Array.isArray(array)) {
44932 throw new TypeError('Can only sort arrays');
44933 }
44934
44935 if (!compare) {
44936 compare = alphabeticalCompare;
44937 } else if (typeof compare !== 'function') {
44938 hi = lo;
44939 lo = compare;
44940 compare = alphabeticalCompare;
44941 }
44942
44943 if (!lo) {
44944 lo = 0;
44945 }
44946
44947 if (!hi) {
44948 hi = array.length;
44949 }
44950
44951 var remaining = hi - lo;
44952
44953 if (remaining < 2) {
44954 return;
44955 }
44956
44957 var runLength = 0;
44958
44959 if (remaining < DEFAULT_MIN_MERGE) {
44960 runLength = makeAscendingRun(array, lo, hi, compare);
44961 binaryInsertionSort(array, lo, hi, lo + runLength, compare);
44962 return;
44963 }
44964
44965 var ts = new TimSort(array, compare);
44966 var minRun = minRunLength(remaining);
44967
44968 do {
44969 runLength = makeAscendingRun(array, lo, hi, compare);
44970
44971 if (runLength < minRun) {
44972 var force = remaining;
44973
44974 if (force > minRun) {
44975 force = minRun;
44976 }
44977
44978 binaryInsertionSort(array, lo, lo + force, lo + runLength, compare);
44979 runLength = force;
44980 }
44981
44982 ts.pushRun(lo, runLength);
44983 ts.mergeRuns();
44984 remaining -= runLength;
44985 lo += runLength;
44986 } while (remaining !== 0);
44987
44988 ts.forceMergeRuns();
44989 }
44990 });
44991});
44992unwrapExports(timsort);
44993
44994var timsort$1 = timsort;
44995var timsort_1 = timsort$1.sort;
44996
44997/**
44998 * Interface definition for direction strategy classes.
44999 *
45000 * This class describes the interface for the Strategy
45001 * pattern classes used to differentiate horizontal and vertical
45002 * direction of hierarchical results.
45003 *
45004 * For a given direction, one coordinate will be 'fixed', meaning that it is
45005 * determined by level.
45006 * The other coordinate is 'unfixed', meaning that the nodes on a given level
45007 * can still move along that coordinate. So:
45008 *
45009 * - `vertical` layout: `x` unfixed, `y` fixed per level
45010 * - `horizontal` layout: `x` fixed per level, `y` unfixed
45011 *
45012 * The local methods are stubs and should be regarded as abstract.
45013 * Derived classes **must** implement all the methods themselves.
45014 *
45015 * @private
45016 */
45017
45018var DirectionInterface =
45019/*#__PURE__*/
45020function () {
45021 function DirectionInterface() {
45022 _classCallCheck(this, DirectionInterface);
45023 }
45024
45025 _createClass(DirectionInterface, [{
45026 key: "abstract",
45027
45028 /** @ignore **/
45029 value: function abstract() {
45030 throw new Error("Can't instantiate abstract class!");
45031 }
45032 /**
45033 * This is a dummy call which is used to suppress the jsdoc errors of type:
45034 *
45035 * "'param' is assigned a value but never used"
45036 *
45037 * @ignore
45038 **/
45039
45040 }, {
45041 key: "fake_use",
45042 value: function fake_use() {} // Do nothing special
45043
45044 /**
45045 * Type to use to translate dynamic curves to, in the case of hierarchical layout.
45046 * Dynamic curves do not work for these.
45047 *
45048 * The value should be perpendicular to the actual direction of the layout.
45049 *
45050 * @return {string} Direction, either 'vertical' or 'horizontal'
45051 */
45052
45053 }, {
45054 key: "curveType",
45055 value: function curveType() {
45056 return this.abstract();
45057 }
45058 /**
45059 * Return the value of the coordinate that is not fixed for this direction.
45060 *
45061 * @param {Node} node The node to read
45062 * @return {number} Value of the unfixed coordinate
45063 */
45064
45065 }, {
45066 key: "getPosition",
45067 value: function getPosition(node) {
45068 this.fake_use(node);
45069 return this.abstract();
45070 }
45071 /**
45072 * Set the value of the coordinate that is not fixed for this direction.
45073 *
45074 * @param {Node} node The node to adjust
45075 * @param {number} position
45076 * @param {number} [level] if specified, the hierarchy level that this node should be fixed to
45077 */
45078
45079 }, {
45080 key: "setPosition",
45081 value: function setPosition(node, position) {
45082 var level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
45083 this.fake_use(node, position, level);
45084 this.abstract();
45085 }
45086 /**
45087 * Get the width of a tree.
45088 *
45089 * A `tree` here is a subset of nodes within the network which are not connected to other nodes,
45090 * only among themselves. In essence, it is a sub-network.
45091 *
45092 * @param {number} index The index number of a tree
45093 * @return {number} the width of a tree in the view coordinates
45094 */
45095
45096 }, {
45097 key: "getTreeSize",
45098 value: function getTreeSize(index) {
45099 this.fake_use(index);
45100 return this.abstract();
45101 }
45102 /**
45103 * Sort array of nodes on the unfixed coordinates.
45104 *
45105 * **Note:** chrome has non-stable sorting implementation, which
45106 * has a tendency to change the order of the array items,
45107 * even if the custom sort function returns 0.
45108 *
45109 * For this reason, an external sort implementation is used,
45110 * which has the added benefit of being faster than the standard
45111 * platforms implementation. This has been verified on `node.js`,
45112 * `firefox` and `chrome` (all linux).
45113 *
45114 * @param {Array.<Node>} nodeArray array of nodes to sort
45115 */
45116
45117 }, {
45118 key: "sort",
45119 value: function sort(nodeArray) {
45120 this.fake_use(nodeArray);
45121 this.abstract();
45122 }
45123 /**
45124 * Assign the fixed coordinate of the node to the given level
45125 *
45126 * @param {Node} node The node to adjust
45127 * @param {number} level The level to fix to
45128 */
45129
45130 }, {
45131 key: "fix",
45132 value: function fix(node, level) {
45133 this.fake_use(node, level);
45134 this.abstract();
45135 }
45136 /**
45137 * Add an offset to the unfixed coordinate of the given node.
45138 *
45139 * @param {NodeId} nodeId Id of the node to adjust
45140 * @param {number} diff Offset to add to the unfixed coordinate
45141 */
45142
45143 }, {
45144 key: "shift",
45145 value: function shift(nodeId, diff) {
45146 this.fake_use(nodeId, diff);
45147 this.abstract();
45148 }
45149 }]);
45150
45151 return DirectionInterface;
45152}();
45153/**
45154 * Vertical Strategy
45155 *
45156 * Coordinate `y` is fixed on levels, coordinate `x` is unfixed.
45157 *
45158 * @extends DirectionInterface
45159 * @private
45160 */
45161
45162
45163var VerticalStrategy =
45164/*#__PURE__*/
45165function (_DirectionInterface) {
45166 _inherits(VerticalStrategy, _DirectionInterface);
45167
45168 /**
45169 * Constructor
45170 *
45171 * @param {Object} layout reference to the parent LayoutEngine instance.
45172 */
45173 function VerticalStrategy(layout) {
45174 var _this;
45175
45176 _classCallCheck(this, VerticalStrategy);
45177
45178 _this = _possibleConstructorReturn(this, _getPrototypeOf(VerticalStrategy).call(this));
45179 _this.layout = layout;
45180 return _this;
45181 }
45182 /** @inheritdoc */
45183
45184
45185 _createClass(VerticalStrategy, [{
45186 key: "curveType",
45187 value: function curveType() {
45188 return 'horizontal';
45189 }
45190 /** @inheritdoc */
45191
45192 }, {
45193 key: "getPosition",
45194 value: function getPosition(node) {
45195 return node.x;
45196 }
45197 /** @inheritdoc */
45198
45199 }, {
45200 key: "setPosition",
45201 value: function setPosition(node, position) {
45202 var level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
45203
45204 if (level !== undefined) {
45205 this.layout.hierarchical.addToOrdering(node, level);
45206 }
45207
45208 node.x = position;
45209 }
45210 /** @inheritdoc */
45211
45212 }, {
45213 key: "getTreeSize",
45214 value: function getTreeSize(index) {
45215 var res = this.layout.hierarchical.getTreeSize(this.layout.body.nodes, index);
45216 return {
45217 min: res.min_x,
45218 max: res.max_x
45219 };
45220 }
45221 /** @inheritdoc */
45222
45223 }, {
45224 key: "sort",
45225 value: function sort(nodeArray) {
45226 timsort_1(nodeArray, function (a, b) {
45227 return a.x - b.x;
45228 });
45229 }
45230 /** @inheritdoc */
45231
45232 }, {
45233 key: "fix",
45234 value: function fix(node, level) {
45235 node.y = this.layout.options.hierarchical.levelSeparation * level;
45236 node.options.fixed.y = true;
45237 }
45238 /** @inheritdoc */
45239
45240 }, {
45241 key: "shift",
45242 value: function shift(nodeId, diff) {
45243 this.layout.body.nodes[nodeId].x += diff;
45244 }
45245 }]);
45246
45247 return VerticalStrategy;
45248}(DirectionInterface);
45249/**
45250 * Horizontal Strategy
45251 *
45252 * Coordinate `x` is fixed on levels, coordinate `y` is unfixed.
45253 *
45254 * @extends DirectionInterface
45255 * @private
45256 */
45257
45258
45259var HorizontalStrategy =
45260/*#__PURE__*/
45261function (_DirectionInterface2) {
45262 _inherits(HorizontalStrategy, _DirectionInterface2);
45263
45264 /**
45265 * Constructor
45266 *
45267 * @param {Object} layout reference to the parent LayoutEngine instance.
45268 */
45269 function HorizontalStrategy(layout) {
45270 var _this2;
45271
45272 _classCallCheck(this, HorizontalStrategy);
45273
45274 _this2 = _possibleConstructorReturn(this, _getPrototypeOf(HorizontalStrategy).call(this));
45275 _this2.layout = layout;
45276 return _this2;
45277 }
45278 /** @inheritdoc */
45279
45280
45281 _createClass(HorizontalStrategy, [{
45282 key: "curveType",
45283 value: function curveType() {
45284 return 'vertical';
45285 }
45286 /** @inheritdoc */
45287
45288 }, {
45289 key: "getPosition",
45290 value: function getPosition(node) {
45291 return node.y;
45292 }
45293 /** @inheritdoc */
45294
45295 }, {
45296 key: "setPosition",
45297 value: function setPosition(node, position) {
45298 var level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
45299
45300 if (level !== undefined) {
45301 this.layout.hierarchical.addToOrdering(node, level);
45302 }
45303
45304 node.y = position;
45305 }
45306 /** @inheritdoc */
45307
45308 }, {
45309 key: "getTreeSize",
45310 value: function getTreeSize(index) {
45311 var res = this.layout.hierarchical.getTreeSize(this.layout.body.nodes, index);
45312 return {
45313 min: res.min_y,
45314 max: res.max_y
45315 };
45316 }
45317 /** @inheritdoc */
45318
45319 }, {
45320 key: "sort",
45321 value: function sort(nodeArray) {
45322 timsort_1(nodeArray, function (a, b) {
45323 return a.y - b.y;
45324 });
45325 }
45326 /** @inheritdoc */
45327
45328 }, {
45329 key: "fix",
45330 value: function fix(node, level) {
45331 node.x = this.layout.options.hierarchical.levelSeparation * level;
45332 node.options.fixed.x = true;
45333 }
45334 /** @inheritdoc */
45335
45336 }, {
45337 key: "shift",
45338 value: function shift(nodeId, diff) {
45339 this.layout.body.nodes[nodeId].y += diff;
45340 }
45341 }]);
45342
45343 return HorizontalStrategy;
45344}(DirectionInterface);
45345
45346var nativeGetOwnPropertyNames = objectGetOwnPropertyNames.f;
45347var toString$2 = {}.toString;
45348var windowNames$1 = typeof window == 'object' && window && Object.getOwnPropertyNames ? Object.getOwnPropertyNames(window) : [];
45349
45350var getWindowNames$1 = function (it) {
45351 try {
45352 return nativeGetOwnPropertyNames(it);
45353 } catch (error) {
45354 return windowNames$1.slice();
45355 }
45356}; // fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
45357
45358
45359var f$7 = function getOwnPropertyNames(it) {
45360 return windowNames$1 && toString$2.call(it) == '[object Window]' ? getWindowNames$1(it) : nativeGetOwnPropertyNames(toIndexedObject(it));
45361};
45362
45363var objectGetOwnPropertyNamesExternal = {
45364 f: f$7
45365};
45366
45367var f$8 = wellKnownSymbol;
45368var wrappedWellKnownSymbol = {
45369 f: f$8
45370};
45371
45372var defineProperty$8 = objectDefineProperty.f;
45373
45374var defineWellKnownSymbol = function (NAME) {
45375 var Symbol = path.Symbol || (path.Symbol = {});
45376 if (!has(Symbol, NAME)) defineProperty$8(Symbol, NAME, {
45377 value: wrappedWellKnownSymbol.f(NAME)
45378 });
45379};
45380
45381var $forEach$1 = arrayIteration.forEach;
45382var HIDDEN$1 = sharedKey('hidden');
45383var SYMBOL = 'Symbol';
45384var PROTOTYPE$4 = 'prototype';
45385var TO_PRIMITIVE$1 = wellKnownSymbol('toPrimitive');
45386var setInternalState$2 = internalState.set;
45387var getInternalState$2 = internalState.getterFor(SYMBOL);
45388var ObjectPrototype$3 = Object[PROTOTYPE$4];
45389var $Symbol$1 = global_1.Symbol;
45390var JSON$1 = global_1.JSON;
45391var nativeJSONStringify = JSON$1 && JSON$1.stringify;
45392var nativeGetOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f;
45393var nativeDefineProperty$1 = objectDefineProperty.f;
45394var nativeGetOwnPropertyNames$1 = objectGetOwnPropertyNamesExternal.f;
45395var nativePropertyIsEnumerable$1 = objectPropertyIsEnumerable.f;
45396var AllSymbols$1 = shared('symbols');
45397var ObjectPrototypeSymbols = shared('op-symbols');
45398var StringToSymbolRegistry = shared('string-to-symbol-registry');
45399var SymbolToStringRegistry = shared('symbol-to-string-registry');
45400var WellKnownSymbolsStore = shared('wks');
45401var QObject$1 = global_1.QObject; // Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173
45402
45403var USE_SETTER = !QObject$1 || !QObject$1[PROTOTYPE$4] || !QObject$1[PROTOTYPE$4].findChild; // fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687
45404
45405var setSymbolDescriptor = descriptors && fails(function () {
45406 return objectCreate(nativeDefineProperty$1({}, 'a', {
45407 get: function () {
45408 return nativeDefineProperty$1(this, 'a', {
45409 value: 7
45410 }).a;
45411 }
45412 })).a != 7;
45413}) ? function (O, P, Attributes) {
45414 var ObjectPrototypeDescriptor = nativeGetOwnPropertyDescriptor$1(ObjectPrototype$3, P);
45415 if (ObjectPrototypeDescriptor) delete ObjectPrototype$3[P];
45416 nativeDefineProperty$1(O, P, Attributes);
45417
45418 if (ObjectPrototypeDescriptor && O !== ObjectPrototype$3) {
45419 nativeDefineProperty$1(ObjectPrototype$3, P, ObjectPrototypeDescriptor);
45420 }
45421} : nativeDefineProperty$1;
45422
45423var wrap$1 = function (tag, description) {
45424 var symbol = AllSymbols$1[tag] = objectCreate($Symbol$1[PROTOTYPE$4]);
45425 setInternalState$2(symbol, {
45426 type: SYMBOL,
45427 tag: tag,
45428 description: description
45429 });
45430 if (!descriptors) symbol.description = description;
45431 return symbol;
45432};
45433
45434var isSymbol$1 = nativeSymbol && typeof $Symbol$1.iterator == 'symbol' ? function (it) {
45435 return typeof it == 'symbol';
45436} : function (it) {
45437 return Object(it) instanceof $Symbol$1;
45438};
45439
45440var $defineProperty$1 = function defineProperty(O, P, Attributes) {
45441 if (O === ObjectPrototype$3) $defineProperty$1(ObjectPrototypeSymbols, P, Attributes);
45442 anObject(O);
45443 var key = toPrimitive(P, true);
45444 anObject(Attributes);
45445
45446 if (has(AllSymbols$1, key)) {
45447 if (!Attributes.enumerable) {
45448 if (!has(O, HIDDEN$1)) nativeDefineProperty$1(O, HIDDEN$1, createPropertyDescriptor(1, {}));
45449 O[HIDDEN$1][key] = true;
45450 } else {
45451 if (has(O, HIDDEN$1) && O[HIDDEN$1][key]) O[HIDDEN$1][key] = false;
45452 Attributes = objectCreate(Attributes, {
45453 enumerable: createPropertyDescriptor(0, false)
45454 });
45455 }
45456
45457 return setSymbolDescriptor(O, key, Attributes);
45458 }
45459
45460 return nativeDefineProperty$1(O, key, Attributes);
45461};
45462
45463var $defineProperties$1 = function defineProperties(O, Properties) {
45464 anObject(O);
45465 var properties = toIndexedObject(Properties);
45466 var keys = objectKeys(properties).concat($getOwnPropertySymbols$1(properties));
45467 $forEach$1(keys, function (key) {
45468 if (!descriptors || $propertyIsEnumerable$1.call(properties, key)) $defineProperty$1(O, key, properties[key]);
45469 });
45470 return O;
45471};
45472
45473var $create$1 = function create(O, Properties) {
45474 return Properties === undefined ? objectCreate(O) : $defineProperties$1(objectCreate(O), Properties);
45475};
45476
45477var $propertyIsEnumerable$1 = function propertyIsEnumerable(V) {
45478 var P = toPrimitive(V, true);
45479 var enumerable = nativePropertyIsEnumerable$1.call(this, P);
45480 if (this === ObjectPrototype$3 && has(AllSymbols$1, P) && !has(ObjectPrototypeSymbols, P)) return false;
45481 return enumerable || !has(this, P) || !has(AllSymbols$1, P) || has(this, HIDDEN$1) && this[HIDDEN$1][P] ? enumerable : true;
45482};
45483
45484var $getOwnPropertyDescriptor$1 = function getOwnPropertyDescriptor(O, P) {
45485 var it = toIndexedObject(O);
45486 var key = toPrimitive(P, true);
45487 if (it === ObjectPrototype$3 && has(AllSymbols$1, key) && !has(ObjectPrototypeSymbols, key)) return;
45488 var descriptor = nativeGetOwnPropertyDescriptor$1(it, key);
45489
45490 if (descriptor && has(AllSymbols$1, key) && !(has(it, HIDDEN$1) && it[HIDDEN$1][key])) {
45491 descriptor.enumerable = true;
45492 }
45493
45494 return descriptor;
45495};
45496
45497var $getOwnPropertyNames$1 = function getOwnPropertyNames(O) {
45498 var names = nativeGetOwnPropertyNames$1(toIndexedObject(O));
45499 var result = [];
45500 $forEach$1(names, function (key) {
45501 if (!has(AllSymbols$1, key) && !has(hiddenKeys, key)) result.push(key);
45502 });
45503 return result;
45504};
45505
45506var $getOwnPropertySymbols$1 = function getOwnPropertySymbols(O) {
45507 var IS_OBJECT_PROTOTYPE = O === ObjectPrototype$3;
45508 var names = nativeGetOwnPropertyNames$1(IS_OBJECT_PROTOTYPE ? ObjectPrototypeSymbols : toIndexedObject(O));
45509 var result = [];
45510 $forEach$1(names, function (key) {
45511 if (has(AllSymbols$1, key) && (!IS_OBJECT_PROTOTYPE || has(ObjectPrototype$3, key))) {
45512 result.push(AllSymbols$1[key]);
45513 }
45514 });
45515 return result;
45516}; // `Symbol` constructor
45517// https://tc39.github.io/ecma262/#sec-symbol-constructor
45518
45519
45520if (!nativeSymbol) {
45521 $Symbol$1 = function Symbol() {
45522 if (this instanceof $Symbol$1) throw TypeError('Symbol is not a constructor');
45523 var description = !arguments.length || arguments[0] === undefined ? undefined : String(arguments[0]);
45524 var tag = uid(description);
45525
45526 var setter = function (value) {
45527 if (this === ObjectPrototype$3) setter.call(ObjectPrototypeSymbols, value);
45528 if (has(this, HIDDEN$1) && has(this[HIDDEN$1], tag)) this[HIDDEN$1][tag] = false;
45529 setSymbolDescriptor(this, tag, createPropertyDescriptor(1, value));
45530 };
45531
45532 if (descriptors && USE_SETTER) setSymbolDescriptor(ObjectPrototype$3, tag, {
45533 configurable: true,
45534 set: setter
45535 });
45536 return wrap$1(tag, description);
45537 };
45538
45539 redefine($Symbol$1[PROTOTYPE$4], 'toString', function toString() {
45540 return getInternalState$2(this).tag;
45541 });
45542 objectPropertyIsEnumerable.f = $propertyIsEnumerable$1;
45543 objectDefineProperty.f = $defineProperty$1;
45544 objectGetOwnPropertyDescriptor.f = $getOwnPropertyDescriptor$1;
45545 objectGetOwnPropertyNames.f = objectGetOwnPropertyNamesExternal.f = $getOwnPropertyNames$1;
45546 objectGetOwnPropertySymbols.f = $getOwnPropertySymbols$1;
45547
45548 if (descriptors) {
45549 // https://github.com/tc39/proposal-Symbol-description
45550 nativeDefineProperty$1($Symbol$1[PROTOTYPE$4], 'description', {
45551 configurable: true,
45552 get: function description() {
45553 return getInternalState$2(this).description;
45554 }
45555 });
45556
45557 {
45558 redefine(ObjectPrototype$3, 'propertyIsEnumerable', $propertyIsEnumerable$1, {
45559 unsafe: true
45560 });
45561 }
45562 }
45563
45564 wrappedWellKnownSymbol.f = function (name) {
45565 return wrap$1(wellKnownSymbol(name), name);
45566 };
45567}
45568
45569_export({
45570 global: true,
45571 wrap: true,
45572 forced: !nativeSymbol,
45573 sham: !nativeSymbol
45574}, {
45575 Symbol: $Symbol$1
45576});
45577$forEach$1(objectKeys(WellKnownSymbolsStore), function (name) {
45578 defineWellKnownSymbol(name);
45579});
45580_export({
45581 target: SYMBOL,
45582 stat: true,
45583 forced: !nativeSymbol
45584}, {
45585 // `Symbol.for` method
45586 // https://tc39.github.io/ecma262/#sec-symbol.for
45587 'for': function (key) {
45588 var string = String(key);
45589 if (has(StringToSymbolRegistry, string)) return StringToSymbolRegistry[string];
45590 var symbol = $Symbol$1(string);
45591 StringToSymbolRegistry[string] = symbol;
45592 SymbolToStringRegistry[symbol] = string;
45593 return symbol;
45594 },
45595 // `Symbol.keyFor` method
45596 // https://tc39.github.io/ecma262/#sec-symbol.keyfor
45597 keyFor: function keyFor(sym) {
45598 if (!isSymbol$1(sym)) throw TypeError(sym + ' is not a symbol');
45599 if (has(SymbolToStringRegistry, sym)) return SymbolToStringRegistry[sym];
45600 },
45601 useSetter: function () {
45602 USE_SETTER = true;
45603 },
45604 useSimple: function () {
45605 USE_SETTER = false;
45606 }
45607});
45608_export({
45609 target: 'Object',
45610 stat: true,
45611 forced: !nativeSymbol,
45612 sham: !descriptors
45613}, {
45614 // `Object.create` method
45615 // https://tc39.github.io/ecma262/#sec-object.create
45616 create: $create$1,
45617 // `Object.defineProperty` method
45618 // https://tc39.github.io/ecma262/#sec-object.defineproperty
45619 defineProperty: $defineProperty$1,
45620 // `Object.defineProperties` method
45621 // https://tc39.github.io/ecma262/#sec-object.defineproperties
45622 defineProperties: $defineProperties$1,
45623 // `Object.getOwnPropertyDescriptor` method
45624 // https://tc39.github.io/ecma262/#sec-object.getownpropertydescriptors
45625 getOwnPropertyDescriptor: $getOwnPropertyDescriptor$1
45626});
45627_export({
45628 target: 'Object',
45629 stat: true,
45630 forced: !nativeSymbol
45631}, {
45632 // `Object.getOwnPropertyNames` method
45633 // https://tc39.github.io/ecma262/#sec-object.getownpropertynames
45634 getOwnPropertyNames: $getOwnPropertyNames$1,
45635 // `Object.getOwnPropertySymbols` method
45636 // https://tc39.github.io/ecma262/#sec-object.getownpropertysymbols
45637 getOwnPropertySymbols: $getOwnPropertySymbols$1
45638}); // Chrome 38 and 39 `Object.getOwnPropertySymbols` fails on primitives
45639// https://bugs.chromium.org/p/v8/issues/detail?id=3443
45640
45641_export({
45642 target: 'Object',
45643 stat: true,
45644 forced: fails(function () {
45645 objectGetOwnPropertySymbols.f(1);
45646 })
45647}, {
45648 getOwnPropertySymbols: function getOwnPropertySymbols(it) {
45649 return objectGetOwnPropertySymbols.f(toObject(it));
45650 }
45651}); // `JSON.stringify` method behavior with symbols
45652// https://tc39.github.io/ecma262/#sec-json.stringify
45653
45654JSON$1 && _export({
45655 target: 'JSON',
45656 stat: true,
45657 forced: !nativeSymbol || fails(function () {
45658 var symbol = $Symbol$1(); // MS Edge converts symbol values to JSON as {}
45659
45660 return nativeJSONStringify([symbol]) != '[null]' // WebKit converts symbol values to JSON as null
45661 || nativeJSONStringify({
45662 a: symbol
45663 }) != '{}' // V8 throws on boxed symbols
45664 || nativeJSONStringify(Object(symbol)) != '{}';
45665 })
45666}, {
45667 stringify: function stringify(it) {
45668 var args = [it];
45669 var index = 1;
45670 var replacer, $replacer;
45671
45672 while (arguments.length > index) args.push(arguments[index++]);
45673
45674 $replacer = replacer = args[1];
45675 if (!isObject(replacer) && it === undefined || isSymbol$1(it)) return; // IE8 returns string on undefined
45676
45677 if (!isArray(replacer)) replacer = function (key, value) {
45678 if (typeof $replacer == 'function') value = $replacer.call(this, key, value);
45679 if (!isSymbol$1(value)) return value;
45680 };
45681 args[1] = replacer;
45682 return nativeJSONStringify.apply(JSON$1, args);
45683 }
45684}); // `Symbol.prototype[@@toPrimitive]` method
45685// https://tc39.github.io/ecma262/#sec-symbol.prototype-@@toprimitive
45686
45687if (!$Symbol$1[PROTOTYPE$4][TO_PRIMITIVE$1]) {
45688 createNonEnumerableProperty($Symbol$1[PROTOTYPE$4], TO_PRIMITIVE$1, $Symbol$1[PROTOTYPE$4].valueOf);
45689} // `Symbol.prototype[@@toStringTag]` property
45690// https://tc39.github.io/ecma262/#sec-symbol.prototype-@@tostringtag
45691
45692
45693setToStringTag($Symbol$1, SYMBOL);
45694hiddenKeys[HIDDEN$1] = true;
45695
45696var defineProperty$9 = objectDefineProperty.f;
45697var NativeSymbol = global_1.Symbol;
45698
45699if (descriptors && typeof NativeSymbol == 'function' && (!('description' in NativeSymbol.prototype) || // Safari 12 bug
45700NativeSymbol().description !== undefined)) {
45701 var EmptyStringDescriptionStore = {}; // wrap Symbol constructor for correct work with undefined description
45702
45703 var SymbolWrapper = function Symbol() {
45704 var description = arguments.length < 1 || arguments[0] === undefined ? undefined : String(arguments[0]);
45705 var result = this instanceof SymbolWrapper ? new NativeSymbol(description) // in Edge 13, String(Symbol(undefined)) === 'Symbol(undefined)'
45706 : description === undefined ? NativeSymbol() : NativeSymbol(description);
45707 if (description === '') EmptyStringDescriptionStore[result] = true;
45708 return result;
45709 };
45710
45711 copyConstructorProperties(SymbolWrapper, NativeSymbol);
45712 var symbolPrototype = SymbolWrapper.prototype = NativeSymbol.prototype;
45713 symbolPrototype.constructor = SymbolWrapper;
45714 var symbolToString = symbolPrototype.toString;
45715 var native = String(NativeSymbol('test')) == 'Symbol(test)';
45716 var regexp = /^Symbol\((.*)\)[^)]+$/;
45717 defineProperty$9(symbolPrototype, 'description', {
45718 configurable: true,
45719 get: function description() {
45720 var symbol = isObject(this) ? this.valueOf() : this;
45721 var string = symbolToString.call(symbol);
45722 if (has(EmptyStringDescriptionStore, symbol)) return '';
45723 var desc = native ? string.slice(7, -1) : string.replace(regexp, '$1');
45724 return desc === '' ? undefined : desc;
45725 }
45726 });
45727 _export({
45728 global: true,
45729 forced: true
45730 }, {
45731 Symbol: SymbolWrapper
45732 });
45733}
45734
45735// https://tc39.github.io/ecma262/#sec-symbol.iterator
45736
45737defineWellKnownSymbol('iterator');
45738
45739var $every = arrayIteration.every; // `Array.prototype.every` method
45740// https://tc39.github.io/ecma262/#sec-array.prototype.every
45741
45742_export({
45743 target: 'Array',
45744 proto: true,
45745 forced: sloppyArrayMethod('every')
45746}, {
45747 every: function every(callbackfn
45748 /* , thisArg */
45749 ) {
45750 return $every(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
45751 }
45752});
45753
45754var $filter = arrayIteration.filter; // `Array.prototype.filter` method
45755// https://tc39.github.io/ecma262/#sec-array.prototype.filter
45756// with adding support of @@species
45757
45758_export({
45759 target: 'Array',
45760 proto: true,
45761 forced: !arrayMethodHasSpeciesSupport('filter')
45762}, {
45763 filter: function filter(callbackfn
45764 /* , thisArg */
45765 ) {
45766 return $filter(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
45767 }
45768});
45769
45770var freezing = !fails(function () {
45771 return Object.isExtensible(Object.preventExtensions({}));
45772});
45773
45774var internalMetadata = createCommonjsModule(function (module) {
45775 var defineProperty = objectDefineProperty.f;
45776 var METADATA = uid('meta');
45777 var id = 0;
45778
45779 var isExtensible = Object.isExtensible || function () {
45780 return true;
45781 };
45782
45783 var setMetadata = function (it) {
45784 defineProperty(it, METADATA, {
45785 value: {
45786 objectID: 'O' + ++id,
45787 // object ID
45788 weakData: {} // weak collections IDs
45789
45790 }
45791 });
45792 };
45793
45794 var fastKey = function (it, create) {
45795 // return a primitive with prefix
45796 if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
45797
45798 if (!has(it, METADATA)) {
45799 // can't set metadata to uncaught frozen object
45800 if (!isExtensible(it)) return 'F'; // not necessary to add metadata
45801
45802 if (!create) return 'E'; // add missing metadata
45803
45804 setMetadata(it); // return object ID
45805 }
45806
45807 return it[METADATA].objectID;
45808 };
45809
45810 var getWeakData = function (it, create) {
45811 if (!has(it, METADATA)) {
45812 // can't set metadata to uncaught frozen object
45813 if (!isExtensible(it)) return true; // not necessary to add metadata
45814
45815 if (!create) return false; // add missing metadata
45816
45817 setMetadata(it); // return the store of weak collections IDs
45818 }
45819
45820 return it[METADATA].weakData;
45821 }; // add metadata on freeze-family methods calling
45822
45823
45824 var onFreeze = function (it) {
45825 if (freezing && meta.REQUIRED && isExtensible(it) && !has(it, METADATA)) setMetadata(it);
45826 return it;
45827 };
45828
45829 var meta = module.exports = {
45830 REQUIRED: false,
45831 fastKey: fastKey,
45832 getWeakData: getWeakData,
45833 onFreeze: onFreeze
45834 };
45835 hiddenKeys[METADATA] = true;
45836});
45837var internalMetadata_1 = internalMetadata.REQUIRED;
45838var internalMetadata_2 = internalMetadata.fastKey;
45839var internalMetadata_3 = internalMetadata.getWeakData;
45840var internalMetadata_4 = internalMetadata.onFreeze;
45841
45842var ITERATOR$5 = wellKnownSymbol('iterator');
45843var ArrayPrototype$1 = Array.prototype; // check on default Array iterator
45844
45845var isArrayIteratorMethod = function (it) {
45846 return it !== undefined && (iterators.Array === it || ArrayPrototype$1[ITERATOR$5] === it);
45847};
45848
45849var ITERATOR$6 = wellKnownSymbol('iterator');
45850
45851var getIteratorMethod = function (it) {
45852 if (it != undefined) return it[ITERATOR$6] || it['@@iterator'] || iterators[classof(it)];
45853};
45854
45855var callWithSafeIterationClosing = function (iterator, fn, value, ENTRIES) {
45856 try {
45857 return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value); // 7.4.6 IteratorClose(iterator, completion)
45858 } catch (error) {
45859 var returnMethod = iterator['return'];
45860 if (returnMethod !== undefined) anObject(returnMethod.call(iterator));
45861 throw error;
45862 }
45863};
45864
45865var iterate_1 = createCommonjsModule(function (module) {
45866 var Result = function (stopped, result) {
45867 this.stopped = stopped;
45868 this.result = result;
45869 };
45870
45871 var iterate = module.exports = function (iterable, fn, that, AS_ENTRIES, IS_ITERATOR) {
45872 var boundFunction = bindContext(fn, that, AS_ENTRIES ? 2 : 1);
45873 var iterator, iterFn, index, length, result, next, step;
45874
45875 if (IS_ITERATOR) {
45876 iterator = iterable;
45877 } else {
45878 iterFn = getIteratorMethod(iterable);
45879 if (typeof iterFn != 'function') throw TypeError('Target is not iterable'); // optimisation for array iterators
45880
45881 if (isArrayIteratorMethod(iterFn)) {
45882 for (index = 0, length = toLength(iterable.length); length > index; index++) {
45883 result = AS_ENTRIES ? boundFunction(anObject(step = iterable[index])[0], step[1]) : boundFunction(iterable[index]);
45884 if (result && result instanceof Result) return result;
45885 }
45886
45887 return new Result(false);
45888 }
45889
45890 iterator = iterFn.call(iterable);
45891 }
45892
45893 next = iterator.next;
45894
45895 while (!(step = next.call(iterator)).done) {
45896 result = callWithSafeIterationClosing(iterator, boundFunction, step.value, AS_ENTRIES);
45897 if (typeof result == 'object' && result && result instanceof Result) return result;
45898 }
45899
45900 return new Result(false);
45901 };
45902
45903 iterate.stop = function (result) {
45904 return new Result(true, result);
45905 };
45906});
45907
45908var ITERATOR$7 = wellKnownSymbol('iterator');
45909var SAFE_CLOSING = false;
45910
45911try {
45912 var called = 0;
45913 var iteratorWithReturn = {
45914 next: function () {
45915 return {
45916 done: !!called++
45917 };
45918 },
45919 'return': function () {
45920 SAFE_CLOSING = true;
45921 }
45922 };
45923
45924 iteratorWithReturn[ITERATOR$7] = function () {
45925 return this;
45926 }; // eslint-disable-next-line no-throw-literal
45927
45928
45929 Array.from(iteratorWithReturn, function () {
45930 throw 2;
45931 });
45932} catch (error) {
45933 /* empty */
45934}
45935
45936var checkCorrectnessOfIteration = function (exec, SKIP_CLOSING) {
45937 if (!SKIP_CLOSING && !SAFE_CLOSING) return false;
45938 var ITERATION_SUPPORT = false;
45939
45940 try {
45941 var object = {};
45942
45943 object[ITERATOR$7] = function () {
45944 return {
45945 next: function () {
45946 return {
45947 done: ITERATION_SUPPORT = true
45948 };
45949 }
45950 };
45951 };
45952
45953 exec(object);
45954 } catch (error) {
45955 /* empty */
45956 }
45957
45958 return ITERATION_SUPPORT;
45959};
45960
45961var collection = function (CONSTRUCTOR_NAME, wrapper, common, IS_MAP, IS_WEAK) {
45962 var NativeConstructor = global_1[CONSTRUCTOR_NAME];
45963 var NativePrototype = NativeConstructor && NativeConstructor.prototype;
45964 var Constructor = NativeConstructor;
45965 var ADDER = IS_MAP ? 'set' : 'add';
45966 var exported = {};
45967
45968 var fixMethod = function (KEY) {
45969 var nativeMethod = NativePrototype[KEY];
45970 redefine(NativePrototype, KEY, KEY == 'add' ? function add(value) {
45971 nativeMethod.call(this, value === 0 ? 0 : value);
45972 return this;
45973 } : KEY == 'delete' ? function (key) {
45974 return IS_WEAK && !isObject(key) ? false : nativeMethod.call(this, key === 0 ? 0 : key);
45975 } : KEY == 'get' ? function get(key) {
45976 return IS_WEAK && !isObject(key) ? undefined : nativeMethod.call(this, key === 0 ? 0 : key);
45977 } : KEY == 'has' ? function has(key) {
45978 return IS_WEAK && !isObject(key) ? false : nativeMethod.call(this, key === 0 ? 0 : key);
45979 } : function set(key, value) {
45980 nativeMethod.call(this, key === 0 ? 0 : key, value);
45981 return this;
45982 });
45983 }; // eslint-disable-next-line max-len
45984
45985
45986 if (isForced_1(CONSTRUCTOR_NAME, typeof NativeConstructor != 'function' || !(IS_WEAK || NativePrototype.forEach && !fails(function () {
45987 new NativeConstructor().entries().next();
45988 })))) {
45989 // create collection constructor
45990 Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER);
45991 internalMetadata.REQUIRED = true;
45992 } else if (isForced_1(CONSTRUCTOR_NAME, true)) {
45993 var instance = new Constructor(); // early implementations not supports chaining
45994
45995 var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance; // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false
45996
45997 var THROWS_ON_PRIMITIVES = fails(function () {
45998 instance.has(1);
45999 }); // most early implementations doesn't supports iterables, most modern - not close it correctly
46000 // eslint-disable-next-line no-new
46001
46002 var ACCEPT_ITERABLES = checkCorrectnessOfIteration(function (iterable) {
46003 new NativeConstructor(iterable);
46004 }); // for early implementations -0 and +0 not the same
46005
46006 var BUGGY_ZERO = !IS_WEAK && fails(function () {
46007 // V8 ~ Chromium 42- fails only with 5+ elements
46008 var $instance = new NativeConstructor();
46009 var index = 5;
46010
46011 while (index--) $instance[ADDER](index, index);
46012
46013 return !$instance.has(-0);
46014 });
46015
46016 if (!ACCEPT_ITERABLES) {
46017 Constructor = wrapper(function (dummy, iterable) {
46018 anInstance(dummy, Constructor, CONSTRUCTOR_NAME);
46019 var that = inheritIfRequired(new NativeConstructor(), dummy, Constructor);
46020 if (iterable != undefined) iterate_1(iterable, that[ADDER], that, IS_MAP);
46021 return that;
46022 });
46023 Constructor.prototype = NativePrototype;
46024 NativePrototype.constructor = Constructor;
46025 }
46026
46027 if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
46028 fixMethod('delete');
46029 fixMethod('has');
46030 IS_MAP && fixMethod('get');
46031 }
46032
46033 if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER); // weak collections should not contains .clear method
46034
46035 if (IS_WEAK && NativePrototype.clear) delete NativePrototype.clear;
46036 }
46037
46038 exported[CONSTRUCTOR_NAME] = Constructor;
46039 _export({
46040 global: true,
46041 forced: Constructor != NativeConstructor
46042 }, exported);
46043 setToStringTag(Constructor, CONSTRUCTOR_NAME);
46044 if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP);
46045 return Constructor;
46046};
46047
46048var defineProperty$a = objectDefineProperty.f;
46049var fastKey = internalMetadata.fastKey;
46050var setInternalState$3 = internalState.set;
46051var internalStateGetterFor = internalState.getterFor;
46052var collectionStrong = {
46053 getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
46054 var C = wrapper(function (that, iterable) {
46055 anInstance(that, C, CONSTRUCTOR_NAME);
46056 setInternalState$3(that, {
46057 type: CONSTRUCTOR_NAME,
46058 index: objectCreate(null),
46059 first: undefined,
46060 last: undefined,
46061 size: 0
46062 });
46063 if (!descriptors) that.size = 0;
46064 if (iterable != undefined) iterate_1(iterable, that[ADDER], that, IS_MAP);
46065 });
46066 var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
46067
46068 var define = function (that, key, value) {
46069 var state = getInternalState(that);
46070 var entry = getEntry(that, key);
46071 var previous, index; // change existing entry
46072
46073 if (entry) {
46074 entry.value = value; // create new entry
46075 } else {
46076 state.last = entry = {
46077 index: index = fastKey(key, true),
46078 key: key,
46079 value: value,
46080 previous: previous = state.last,
46081 next: undefined,
46082 removed: false
46083 };
46084 if (!state.first) state.first = entry;
46085 if (previous) previous.next = entry;
46086 if (descriptors) state.size++;else that.size++; // add to index
46087
46088 if (index !== 'F') state.index[index] = entry;
46089 }
46090
46091 return that;
46092 };
46093
46094 var getEntry = function (that, key) {
46095 var state = getInternalState(that); // fast case
46096
46097 var index = fastKey(key);
46098 var entry;
46099 if (index !== 'F') return state.index[index]; // frozen object case
46100
46101 for (entry = state.first; entry; entry = entry.next) {
46102 if (entry.key == key) return entry;
46103 }
46104 };
46105
46106 redefineAll(C.prototype, {
46107 // 23.1.3.1 Map.prototype.clear()
46108 // 23.2.3.2 Set.prototype.clear()
46109 clear: function clear() {
46110 var that = this;
46111 var state = getInternalState(that);
46112 var data = state.index;
46113 var entry = state.first;
46114
46115 while (entry) {
46116 entry.removed = true;
46117 if (entry.previous) entry.previous = entry.previous.next = undefined;
46118 delete data[entry.index];
46119 entry = entry.next;
46120 }
46121
46122 state.first = state.last = undefined;
46123 if (descriptors) state.size = 0;else that.size = 0;
46124 },
46125 // 23.1.3.3 Map.prototype.delete(key)
46126 // 23.2.3.4 Set.prototype.delete(value)
46127 'delete': function (key) {
46128 var that = this;
46129 var state = getInternalState(that);
46130 var entry = getEntry(that, key);
46131
46132 if (entry) {
46133 var next = entry.next;
46134 var prev = entry.previous;
46135 delete state.index[entry.index];
46136 entry.removed = true;
46137 if (prev) prev.next = next;
46138 if (next) next.previous = prev;
46139 if (state.first == entry) state.first = next;
46140 if (state.last == entry) state.last = prev;
46141 if (descriptors) state.size--;else that.size--;
46142 }
46143
46144 return !!entry;
46145 },
46146 // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)
46147 // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)
46148 forEach: function forEach(callbackfn
46149 /* , that = undefined */
46150 ) {
46151 var state = getInternalState(this);
46152 var boundFunction = bindContext(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3);
46153 var entry;
46154
46155 while (entry = entry ? entry.next : state.first) {
46156 boundFunction(entry.value, entry.key, this); // revert to the last existing entry
46157
46158 while (entry && entry.removed) entry = entry.previous;
46159 }
46160 },
46161 // 23.1.3.7 Map.prototype.has(key)
46162 // 23.2.3.7 Set.prototype.has(value)
46163 has: function has(key) {
46164 return !!getEntry(this, key);
46165 }
46166 });
46167 redefineAll(C.prototype, IS_MAP ? {
46168 // 23.1.3.6 Map.prototype.get(key)
46169 get: function get(key) {
46170 var entry = getEntry(this, key);
46171 return entry && entry.value;
46172 },
46173 // 23.1.3.9 Map.prototype.set(key, value)
46174 set: function set(key, value) {
46175 return define(this, key === 0 ? 0 : key, value);
46176 }
46177 } : {
46178 // 23.2.3.1 Set.prototype.add(value)
46179 add: function add(value) {
46180 return define(this, value = value === 0 ? 0 : value, value);
46181 }
46182 });
46183 if (descriptors) defineProperty$a(C.prototype, 'size', {
46184 get: function () {
46185 return getInternalState(this).size;
46186 }
46187 });
46188 return C;
46189 },
46190 setStrong: function (C, CONSTRUCTOR_NAME, IS_MAP) {
46191 var ITERATOR_NAME = CONSTRUCTOR_NAME + ' Iterator';
46192 var getInternalCollectionState = internalStateGetterFor(CONSTRUCTOR_NAME);
46193 var getInternalIteratorState = internalStateGetterFor(ITERATOR_NAME); // add .keys, .values, .entries, [@@iterator]
46194 // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11
46195
46196 defineIterator(C, CONSTRUCTOR_NAME, function (iterated, kind) {
46197 setInternalState$3(this, {
46198 type: ITERATOR_NAME,
46199 target: iterated,
46200 state: getInternalCollectionState(iterated),
46201 kind: kind,
46202 last: undefined
46203 });
46204 }, function () {
46205 var state = getInternalIteratorState(this);
46206 var kind = state.kind;
46207 var entry = state.last; // revert to the last existing entry
46208
46209 while (entry && entry.removed) entry = entry.previous; // get next entry
46210
46211
46212 if (!state.target || !(state.last = entry = entry ? entry.next : state.state.first)) {
46213 // or finish the iteration
46214 state.target = undefined;
46215 return {
46216 value: undefined,
46217 done: true
46218 };
46219 } // return step by kind
46220
46221
46222 if (kind == 'keys') return {
46223 value: entry.key,
46224 done: false
46225 };
46226 if (kind == 'values') return {
46227 value: entry.value,
46228 done: false
46229 };
46230 return {
46231 value: [entry.key, entry.value],
46232 done: false
46233 };
46234 }, IS_MAP ? 'entries' : 'values', !IS_MAP, true); // add [@@species], 23.1.2.2, 23.2.2.2
46235
46236 setSpecies(CONSTRUCTOR_NAME);
46237 }
46238};
46239
46240// https://tc39.github.io/ecma262/#sec-set-objects
46241
46242
46243var es_set = collection('Set', function (get) {
46244 return function Set() {
46245 return get(this, arguments.length ? arguments[0] : undefined);
46246 };
46247}, collectionStrong);
46248
46249var charAt$1 = stringMultibyte.charAt;
46250var STRING_ITERATOR = 'String Iterator';
46251var setInternalState$4 = internalState.set;
46252var getInternalState$3 = internalState.getterFor(STRING_ITERATOR); // `String.prototype[@@iterator]` method
46253// https://tc39.github.io/ecma262/#sec-string.prototype-@@iterator
46254
46255defineIterator(String, 'String', function (iterated) {
46256 setInternalState$4(this, {
46257 type: STRING_ITERATOR,
46258 string: String(iterated),
46259 index: 0
46260 }); // `%StringIteratorPrototype%.next` method
46261 // https://tc39.github.io/ecma262/#sec-%stringiteratorprototype%.next
46262}, function next() {
46263 var state = getInternalState$3(this);
46264 var string = state.string;
46265 var index = state.index;
46266 var point;
46267 if (index >= string.length) return {
46268 value: undefined,
46269 done: true
46270 };
46271 point = charAt$1(string, index);
46272 state.index += point.length;
46273 return {
46274 value: point,
46275 done: false
46276 };
46277});
46278
46279/**
46280 * Try to assign levels to nodes according to their positions in the cyclic “hierarchy”.
46281 *
46282 * @param nodes - Nodes of the graph.
46283 * @param levels - If present levels will be added to it, if not a new object will be created.
46284 *
46285 * @returns Populated node levels.
46286 */
46287function fillLevelsByDirectionCyclic(nodes, levels) {
46288 var edges = new Set();
46289 nodes.forEach(function (node) {
46290 node.edges.forEach(function (edge) {
46291 if (edge.connected) {
46292 edges.add(edge);
46293 }
46294 });
46295 });
46296 edges.forEach(function (edge) {
46297 var fromId = edge.from.id;
46298 var toId = edge.to.id;
46299
46300 if (levels[fromId] == null) {
46301 levels[fromId] = 0;
46302 }
46303
46304 if (levels[toId] == null || levels[fromId] >= levels[toId]) {
46305 levels[toId] = levels[fromId] + 1;
46306 }
46307 });
46308 return levels;
46309}
46310/**
46311 * Assign levels to nodes according to their positions in the hierarchy. Leaves will be lined up at the bottom and all other nodes as close to their children as possible.
46312 *
46313 * @param nodes - Nodes of the graph.
46314 * @param levels - If present levels will be added to it, if not a new object will be created.
46315 *
46316 * @returns Populated node levels.
46317 */
46318
46319
46320function fillLevelsByDirectionLeaves(nodes) {
46321 var levels = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Object.create(null);
46322 return fillLevelsByDirection( // Pick only leaves (nodes without children).
46323 function (node) {
46324 return !node.edges.every(function (edge) {
46325 return edge.to === node;
46326 });
46327 }, // Use the lowest level.
46328 function (newLevel, oldLevel) {
46329 return oldLevel > newLevel;
46330 }, // Go against the direction of the edges.
46331 "from", nodes, levels);
46332}
46333/**
46334 * Assign levels to nodes according to their positions in the hierarchy. Roots will be lined up at the top and all nodes as close to their parents as possible.
46335 *
46336 * @param nodes - Nodes of the graph.
46337 * @param levels - If present levels will be added to it, if not a new object will be created.
46338 *
46339 * @returns Populated node levels.
46340 */
46341
46342function fillLevelsByDirectionRoots(nodes) {
46343 var levels = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Object.create(null);
46344 return fillLevelsByDirection( // Pick only roots (nodes without parents).
46345 function (node) {
46346 return !node.edges.every(function (edge) {
46347 return edge.from === node;
46348 });
46349 }, // Use the highest level.
46350 function (newLevel, oldLevel) {
46351 return oldLevel < newLevel;
46352 }, // Go in the direction of the edges.
46353 "to", nodes, levels);
46354}
46355/**
46356 * Assign levels to nodes according to their positions in the hierarchy.
46357 *
46358 * @param isEntryNode - Checks and return true if the graph should be traversed from this node.
46359 * @param shouldLevelBeReplaced - Checks and returns true if the level of given node should be updated to the new value.
46360 * @param direction - Wheter the graph should be traversed in the direction of the edges `"to"` or in the other way `"from"`.
46361 * @param nodes - Nodes of the graph.
46362 * @param levels - If present levels will be added to it, if not a new object will be created.
46363 *
46364 * @returns Populated node levels.
46365 */
46366
46367function fillLevelsByDirection(isEntryNode, shouldLevelBeReplaced, direction, nodes, levels) {
46368 var limit = nodes.length;
46369 var edgeIdProp = direction + "Id";
46370 var newLevelDiff = direction === "to" ? 1 : -1;
46371 var _iteratorNormalCompletion = true;
46372 var _didIteratorError = false;
46373 var _iteratorError = undefined;
46374
46375 try {
46376 var _loop = function _loop() {
46377 var entryNode = _step.value;
46378
46379 if (isEntryNode(entryNode)) {
46380 return "continue";
46381 } // Line up all the entry nodes on level 0.
46382
46383
46384 levels[entryNode.id] = 0;
46385 var stack = [entryNode];
46386 var done = 0;
46387 var node = void 0;
46388
46389 var _loop2 = function _loop2() {
46390 var newLevel = levels[node.id] + newLevelDiff;
46391 node.edges.filter(function (edge) {
46392 return (// Ignore disconnected edges.
46393 edge.connected && // Ignore circular edges.
46394 edge.to !== edge.from && // Ignore edges leading to the node that's currently being processed.
46395 edge[direction] !== node
46396 );
46397 }).forEach(function (edge) {
46398 var targetNodeId = edge[edgeIdProp];
46399 var oldLevel = levels[targetNodeId];
46400
46401 if (oldLevel == null || shouldLevelBeReplaced(newLevel, oldLevel)) {
46402 levels[targetNodeId] = newLevel;
46403 stack.push(edge[direction]);
46404 }
46405 });
46406
46407 if (done > limit) {
46408 // This would run forever on a cyclic graph.
46409 return {
46410 v: {
46411 v: fillLevelsByDirectionCyclic(nodes, levels)
46412 }
46413 };
46414 } else {
46415 ++done;
46416 }
46417 };
46418
46419 while (node = stack.pop()) {
46420 var _ret2 = _loop2();
46421
46422 if (_typeof$1(_ret2) === "object") return _ret2.v;
46423 }
46424 };
46425
46426 for (var _iterator = nodes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
46427 var _ret = _loop();
46428
46429 switch (_ret) {
46430 case "continue":
46431 continue;
46432
46433 default:
46434 if (_typeof$1(_ret) === "object") return _ret.v;
46435 }
46436 }
46437 } catch (err) {
46438 _didIteratorError = true;
46439 _iteratorError = err;
46440 } finally {
46441 try {
46442 if (!_iteratorNormalCompletion && _iterator.return != null) {
46443 _iterator.return();
46444 }
46445 } finally {
46446 if (_didIteratorError) {
46447 throw _iteratorError;
46448 }
46449 }
46450 }
46451
46452 return levels;
46453}
46454
46455/**
46456 * There's a mix-up with terms in the code. Following are the formal definitions:
46457 *
46458 * tree - a strict hierarchical network, i.e. every node has at most one parent
46459 * forest - a collection of trees. These distinct trees are thus not connected.
46460 *
46461 * So:
46462 * - in a network that is not a tree, there exist nodes with multiple parents.
46463 * - a network consisting of unconnected sub-networks, of which at least one
46464 * is not a tree, is not a forest.
46465 *
46466 * In the code, the definitions are:
46467 *
46468 * tree - any disconnected sub-network, strict hierarchical or not.
46469 * forest - a bunch of these sub-networks
46470 *
46471 * The difference between tree and not-tree is important in the code, notably within
46472 * to the block-shifting algorithm. The algorithm assumes formal trees and fails
46473 * for not-trees, often in a spectacular manner (search for 'exploding network' in the issues).
46474 *
46475 * In order to distinguish the definitions in the following code, the adjective 'formal' is
46476 * used. If 'formal' is absent, you must assume the non-formal definition.
46477 *
46478 * ----------------------------------------------------------------------------------
46479 * NOTES
46480 * =====
46481 *
46482 * A hierarchical layout is a different thing from a hierarchical network.
46483 * The layout is a way to arrange the nodes in the view; this can be done
46484 * on non-hierarchical networks as well. The converse is also possible.
46485 */
46486/**
46487 * Container for derived data on current network, relating to hierarchy.
46488 *
46489 * @private
46490 */
46491
46492var HierarchicalStatus =
46493/*#__PURE__*/
46494function () {
46495 /**
46496 * @ignore
46497 */
46498 function HierarchicalStatus() {
46499 _classCallCheck(this, HierarchicalStatus);
46500
46501 this.childrenReference = {}; // child id's per node id
46502
46503 this.parentReference = {}; // parent id's per node id
46504
46505 this.trees = {}; // tree id per node id; i.e. to which tree does given node id belong
46506
46507 this.distributionOrdering = {}; // The nodes per level, in the display order
46508
46509 this.levels = {}; // hierarchy level per node id
46510
46511 this.distributionIndex = {}; // The position of the node in the level sorting order, per node id.
46512
46513 this.isTree = false; // True if current network is a formal tree
46514
46515 this.treeIndex = -1; // Highest tree id in current network.
46516 }
46517 /**
46518 * Add the relation between given nodes to the current state.
46519 *
46520 * @param {Node.id} parentNodeId
46521 * @param {Node.id} childNodeId
46522 */
46523
46524
46525 _createClass(HierarchicalStatus, [{
46526 key: "addRelation",
46527 value: function addRelation(parentNodeId, childNodeId) {
46528 if (this.childrenReference[parentNodeId] === undefined) {
46529 this.childrenReference[parentNodeId] = [];
46530 }
46531
46532 this.childrenReference[parentNodeId].push(childNodeId);
46533
46534 if (this.parentReference[childNodeId] === undefined) {
46535 this.parentReference[childNodeId] = [];
46536 }
46537
46538 this.parentReference[childNodeId].push(parentNodeId);
46539 }
46540 /**
46541 * Check if the current state is for a formal tree or formal forest.
46542 *
46543 * This is the case if every node has at most one parent.
46544 *
46545 * Pre: parentReference init'ed properly for current network
46546 */
46547
46548 }, {
46549 key: "checkIfTree",
46550 value: function checkIfTree() {
46551 for (var i in this.parentReference) {
46552 if (this.parentReference[i].length > 1) {
46553 this.isTree = false;
46554 return;
46555 }
46556 }
46557
46558 this.isTree = true;
46559 }
46560 /**
46561 * Return the number of separate trees in the current network.
46562 * @returns {number}
46563 */
46564
46565 }, {
46566 key: "numTrees",
46567 value: function numTrees() {
46568 return this.treeIndex + 1; // This assumes the indexes are assigned consecitively
46569 }
46570 /**
46571 * Assign a tree id to a node
46572 * @param {Node} node
46573 * @param {string|number} treeId
46574 */
46575
46576 }, {
46577 key: "setTreeIndex",
46578 value: function setTreeIndex(node, treeId) {
46579 if (treeId === undefined) return; // Don't bother
46580
46581 if (this.trees[node.id] === undefined) {
46582 this.trees[node.id] = treeId;
46583 this.treeIndex = Math.max(treeId, this.treeIndex);
46584 }
46585 }
46586 /**
46587 * Ensure level for given id is defined.
46588 *
46589 * Sets level to zero for given node id if not already present
46590 *
46591 * @param {Node.id} nodeId
46592 */
46593
46594 }, {
46595 key: "ensureLevel",
46596 value: function ensureLevel(nodeId) {
46597 if (this.levels[nodeId] === undefined) {
46598 this.levels[nodeId] = 0;
46599 }
46600 }
46601 /**
46602 * get the maximum level of a branch.
46603 *
46604 * TODO: Never entered; find a test case to test this!
46605 * @param {Node.id} nodeId
46606 * @returns {number}
46607 */
46608
46609 }, {
46610 key: "getMaxLevel",
46611 value: function getMaxLevel(nodeId) {
46612 var _this = this;
46613
46614 var accumulator = {};
46615
46616 var _getMaxLevel = function _getMaxLevel(nodeId) {
46617 if (accumulator[nodeId] !== undefined) {
46618 return accumulator[nodeId];
46619 }
46620
46621 var level = _this.levels[nodeId];
46622
46623 if (_this.childrenReference[nodeId]) {
46624 var children = _this.childrenReference[nodeId];
46625
46626 if (children.length > 0) {
46627 for (var i = 0; i < children.length; i++) {
46628 level = Math.max(level, _getMaxLevel(children[i]));
46629 }
46630 }
46631 }
46632
46633 accumulator[nodeId] = level;
46634 return level;
46635 };
46636
46637 return _getMaxLevel(nodeId);
46638 }
46639 /**
46640 *
46641 * @param {Node} nodeA
46642 * @param {Node} nodeB
46643 */
46644
46645 }, {
46646 key: "levelDownstream",
46647 value: function levelDownstream(nodeA, nodeB) {
46648 if (this.levels[nodeB.id] === undefined) {
46649 // set initial level
46650 if (this.levels[nodeA.id] === undefined) {
46651 this.levels[nodeA.id] = 0;
46652 } // set level
46653
46654
46655 this.levels[nodeB.id] = this.levels[nodeA.id] + 1;
46656 }
46657 }
46658 /**
46659 * Small util method to set the minimum levels of the nodes to zero.
46660 *
46661 * @param {Array.<Node>} nodes
46662 */
46663
46664 }, {
46665 key: "setMinLevelToZero",
46666 value: function setMinLevelToZero(nodes) {
46667 var minLevel = 1e9; // get the minimum level
46668
46669 for (var nodeId in nodes) {
46670 if (nodes.hasOwnProperty(nodeId)) {
46671 if (this.levels[nodeId] !== undefined) {
46672 minLevel = Math.min(this.levels[nodeId], minLevel);
46673 }
46674 }
46675 } // subtract the minimum from the set so we have a range starting from 0
46676
46677
46678 for (var _nodeId in nodes) {
46679 if (nodes.hasOwnProperty(_nodeId)) {
46680 if (this.levels[_nodeId] !== undefined) {
46681 this.levels[_nodeId] -= minLevel;
46682 }
46683 }
46684 }
46685 }
46686 /**
46687 * Get the min and max xy-coordinates of a given tree
46688 *
46689 * @param {Array.<Node>} nodes
46690 * @param {number} index
46691 * @returns {{min_x: number, max_x: number, min_y: number, max_y: number}}
46692 */
46693
46694 }, {
46695 key: "getTreeSize",
46696 value: function getTreeSize(nodes, index) {
46697 var min_x = 1e9;
46698 var max_x = -1e9;
46699 var min_y = 1e9;
46700 var max_y = -1e9;
46701
46702 for (var nodeId in this.trees) {
46703 if (this.trees.hasOwnProperty(nodeId)) {
46704 if (this.trees[nodeId] === index) {
46705 var node = nodes[nodeId];
46706 min_x = Math.min(node.x, min_x);
46707 max_x = Math.max(node.x, max_x);
46708 min_y = Math.min(node.y, min_y);
46709 max_y = Math.max(node.y, max_y);
46710 }
46711 }
46712 }
46713
46714 return {
46715 min_x: min_x,
46716 max_x: max_x,
46717 min_y: min_y,
46718 max_y: max_y
46719 };
46720 }
46721 /**
46722 * Check if two nodes have the same parent(s)
46723 *
46724 * @param {Node} node1
46725 * @param {Node} node2
46726 * @return {boolean} true if the two nodes have a same ancestor node, false otherwise
46727 */
46728
46729 }, {
46730 key: "hasSameParent",
46731 value: function hasSameParent(node1, node2) {
46732 var parents1 = this.parentReference[node1.id];
46733 var parents2 = this.parentReference[node2.id];
46734
46735 if (parents1 === undefined || parents2 === undefined) {
46736 return false;
46737 }
46738
46739 for (var i = 0; i < parents1.length; i++) {
46740 for (var j = 0; j < parents2.length; j++) {
46741 if (parents1[i] == parents2[j]) {
46742 return true;
46743 }
46744 }
46745 }
46746
46747 return false;
46748 }
46749 /**
46750 * Check if two nodes are in the same tree.
46751 *
46752 * @param {Node} node1
46753 * @param {Node} node2
46754 * @return {Boolean} true if this is so, false otherwise
46755 */
46756
46757 }, {
46758 key: "inSameSubNetwork",
46759 value: function inSameSubNetwork(node1, node2) {
46760 return this.trees[node1.id] === this.trees[node2.id];
46761 }
46762 /**
46763 * Get a list of the distinct levels in the current network
46764 *
46765 * @returns {Array}
46766 */
46767
46768 }, {
46769 key: "getLevels",
46770 value: function getLevels() {
46771 return Object.keys(this.distributionOrdering);
46772 }
46773 /**
46774 * Add a node to the ordering per level
46775 *
46776 * @param {Node} node
46777 * @param {number} level
46778 */
46779
46780 }, {
46781 key: "addToOrdering",
46782 value: function addToOrdering(node, level) {
46783 if (this.distributionOrdering[level] === undefined) {
46784 this.distributionOrdering[level] = [];
46785 }
46786
46787 var isPresent = false;
46788 var curLevel = this.distributionOrdering[level];
46789
46790 for (var n in curLevel) {
46791 //if (curLevel[n].id === node.id) {
46792 if (curLevel[n] === node) {
46793 isPresent = true;
46794 break;
46795 }
46796 }
46797
46798 if (!isPresent) {
46799 this.distributionOrdering[level].push(node);
46800 this.distributionIndex[node.id] = this.distributionOrdering[level].length - 1;
46801 }
46802 }
46803 }]);
46804
46805 return HierarchicalStatus;
46806}();
46807/**
46808 * The Layout Engine
46809 */
46810
46811
46812var LayoutEngine =
46813/*#__PURE__*/
46814function () {
46815 /**
46816 * @param {Object} body
46817 */
46818 function LayoutEngine(body) {
46819 _classCallCheck(this, LayoutEngine);
46820
46821 this.body = body;
46822 this.initialRandomSeed = Math.round(Math.random() * 1000000);
46823 this.randomSeed = this.initialRandomSeed;
46824 this.setPhysics = false;
46825 this.options = {};
46826 this.optionsBackup = {
46827 physics: {}
46828 };
46829 this.defaultOptions = {
46830 randomSeed: undefined,
46831 improvedLayout: true,
46832 clusterThreshold: 150,
46833 hierarchical: {
46834 enabled: false,
46835 levelSeparation: 150,
46836 nodeSpacing: 100,
46837 treeSpacing: 200,
46838 blockShifting: true,
46839 edgeMinimization: true,
46840 parentCentralization: true,
46841 direction: 'UD',
46842 // UD, DU, LR, RL
46843 sortMethod: 'hubsize' // hubsize, directed
46844
46845 }
46846 };
46847 extend(this.options, this.defaultOptions);
46848 this.bindEventListeners();
46849 }
46850 /**
46851 * Binds event listeners
46852 */
46853
46854
46855 _createClass(LayoutEngine, [{
46856 key: "bindEventListeners",
46857 value: function bindEventListeners() {
46858 var _this2 = this;
46859
46860 this.body.emitter.on('_dataChanged', function () {
46861 _this2.setupHierarchicalLayout();
46862 });
46863 this.body.emitter.on('_dataLoaded', function () {
46864 _this2.layoutNetwork();
46865 });
46866 this.body.emitter.on('_resetHierarchicalLayout', function () {
46867 _this2.setupHierarchicalLayout();
46868 });
46869 this.body.emitter.on('_adjustEdgesForHierarchicalLayout', function () {
46870 if (_this2.options.hierarchical.enabled !== true) {
46871 return;
46872 } // get the type of static smooth curve in case it is required
46873
46874
46875 var type = _this2.direction.curveType(); // force all edges into static smooth curves.
46876
46877
46878 _this2.body.emitter.emit('_forceDisableDynamicCurves', type, false);
46879 });
46880 }
46881 /**
46882 *
46883 * @param {Object} options
46884 * @param {Object} allOptions
46885 * @returns {Object}
46886 */
46887
46888 }, {
46889 key: "setOptions",
46890 value: function setOptions(options, allOptions) {
46891 if (options !== undefined) {
46892 var hierarchical = this.options.hierarchical;
46893 var prevHierarchicalState = hierarchical.enabled;
46894 selectiveDeepExtend(["randomSeed", "improvedLayout", "clusterThreshold"], this.options, options);
46895 mergeOptions(this.options, options, 'hierarchical');
46896
46897 if (options.randomSeed !== undefined) {
46898 this.initialRandomSeed = options.randomSeed;
46899 }
46900
46901 if (hierarchical.enabled === true) {
46902 if (prevHierarchicalState === true) {
46903 // refresh the overridden options for nodes and edges.
46904 this.body.emitter.emit('refresh', true);
46905 } // make sure the level separation is the right way up
46906
46907
46908 if (hierarchical.direction === 'RL' || hierarchical.direction === 'DU') {
46909 if (hierarchical.levelSeparation > 0) {
46910 hierarchical.levelSeparation *= -1;
46911 }
46912 } else {
46913 if (hierarchical.levelSeparation < 0) {
46914 hierarchical.levelSeparation *= -1;
46915 }
46916 }
46917
46918 this.setDirectionStrategy();
46919 this.body.emitter.emit('_resetHierarchicalLayout'); // because the hierarchical system needs it's own physics and smooth curve settings,
46920 // we adapt the other options if needed.
46921
46922 return this.adaptAllOptionsForHierarchicalLayout(allOptions);
46923 } else {
46924 if (prevHierarchicalState === true) {
46925 // refresh the overridden options for nodes and edges.
46926 this.body.emitter.emit('refresh');
46927 return deepExtend(allOptions, this.optionsBackup);
46928 }
46929 }
46930 }
46931
46932 return allOptions;
46933 }
46934 /**
46935 *
46936 * @param {Object} allOptions
46937 * @returns {Object}
46938 */
46939
46940 }, {
46941 key: "adaptAllOptionsForHierarchicalLayout",
46942 value: function adaptAllOptionsForHierarchicalLayout(allOptions) {
46943 if (this.options.hierarchical.enabled === true) {
46944 var backupPhysics = this.optionsBackup.physics; // set the physics
46945
46946 if (allOptions.physics === undefined || allOptions.physics === true) {
46947 allOptions.physics = {
46948 enabled: backupPhysics.enabled === undefined ? true : backupPhysics.enabled,
46949 solver: 'hierarchicalRepulsion'
46950 };
46951 backupPhysics.enabled = backupPhysics.enabled === undefined ? true : backupPhysics.enabled;
46952 backupPhysics.solver = backupPhysics.solver || 'barnesHut';
46953 } else if (_typeof$1(allOptions.physics) === 'object') {
46954 backupPhysics.enabled = allOptions.physics.enabled === undefined ? true : allOptions.physics.enabled;
46955 backupPhysics.solver = allOptions.physics.solver || 'barnesHut';
46956 allOptions.physics.solver = 'hierarchicalRepulsion';
46957 } else if (allOptions.physics !== false) {
46958 backupPhysics.solver = 'barnesHut';
46959 allOptions.physics = {
46960 solver: 'hierarchicalRepulsion'
46961 };
46962 } // get the type of static smooth curve in case it is required
46963
46964
46965 var type = this.direction.curveType(); // disable smooth curves if nothing is defined. If smooth curves have been turned on,
46966 // turn them into static smooth curves.
46967
46968 if (allOptions.edges === undefined) {
46969 this.optionsBackup.edges = {
46970 smooth: {
46971 enabled: true,
46972 type: 'dynamic'
46973 }
46974 };
46975 allOptions.edges = {
46976 smooth: false
46977 };
46978 } else if (allOptions.edges.smooth === undefined) {
46979 this.optionsBackup.edges = {
46980 smooth: {
46981 enabled: true,
46982 type: 'dynamic'
46983 }
46984 };
46985 allOptions.edges.smooth = false;
46986 } else {
46987 if (typeof allOptions.edges.smooth === 'boolean') {
46988 this.optionsBackup.edges = {
46989 smooth: allOptions.edges.smooth
46990 };
46991 allOptions.edges.smooth = {
46992 enabled: allOptions.edges.smooth,
46993 type: type
46994 };
46995 } else {
46996 var smooth = allOptions.edges.smooth; // allow custom types except for dynamic
46997
46998 if (smooth.type !== undefined && smooth.type !== 'dynamic') {
46999 type = smooth.type;
47000 } // TODO: this is options merging; see if the standard routines can be used here.
47001
47002
47003 this.optionsBackup.edges = {
47004 smooth: smooth.enabled === undefined ? true : smooth.enabled,
47005 type: smooth.type === undefined ? 'dynamic' : smooth.type,
47006 roundness: smooth.roundness === undefined ? 0.5 : smooth.roundness,
47007 forceDirection: smooth.forceDirection === undefined ? false : smooth.forceDirection
47008 }; // NOTE: Copying an object to self; this is basically setting defaults for undefined variables
47009
47010 allOptions.edges.smooth = {
47011 enabled: smooth.enabled === undefined ? true : smooth.enabled,
47012 type: type,
47013 roundness: smooth.roundness === undefined ? 0.5 : smooth.roundness,
47014 forceDirection: smooth.forceDirection === undefined ? false : smooth.forceDirection
47015 };
47016 }
47017 } // Force all edges into static smooth curves.
47018 // Only applies to edges that do not use the global options for smooth.
47019
47020
47021 this.body.emitter.emit('_forceDisableDynamicCurves', type);
47022 }
47023
47024 return allOptions;
47025 }
47026 /**
47027 *
47028 * @returns {number}
47029 */
47030
47031 }, {
47032 key: "seededRandom",
47033 value: function seededRandom() {
47034 var x = Math.sin(this.randomSeed++) * 10000;
47035 return x - Math.floor(x);
47036 }
47037 /**
47038 *
47039 * @param {Array.<Node>} nodesArray
47040 */
47041
47042 }, {
47043 key: "positionInitially",
47044 value: function positionInitially(nodesArray) {
47045 if (this.options.hierarchical.enabled !== true) {
47046 this.randomSeed = this.initialRandomSeed;
47047 var radius = nodesArray.length + 50;
47048
47049 for (var i = 0; i < nodesArray.length; i++) {
47050 var node = nodesArray[i];
47051 var angle = 2 * Math.PI * this.seededRandom();
47052
47053 if (node.x === undefined) {
47054 node.x = radius * Math.cos(angle);
47055 }
47056
47057 if (node.y === undefined) {
47058 node.y = radius * Math.sin(angle);
47059 }
47060 }
47061 }
47062 }
47063 /**
47064 * Use Kamada Kawai to position nodes. This is quite a heavy algorithm so if there are a lot of nodes we
47065 * cluster them first to reduce the amount.
47066 */
47067
47068 }, {
47069 key: "layoutNetwork",
47070 value: function layoutNetwork() {
47071 if (this.options.hierarchical.enabled !== true && this.options.improvedLayout === true) {
47072 var indices = this.body.nodeIndices; // first check if we should Kamada Kawai to layout. The threshold is if less than half of the visible
47073 // nodes have predefined positions we use this.
47074
47075 var positionDefined = 0;
47076
47077 for (var i = 0; i < indices.length; i++) {
47078 var node = this.body.nodes[indices[i]];
47079
47080 if (node.predefinedPosition === true) {
47081 positionDefined += 1;
47082 }
47083 } // if less than half of the nodes have a predefined position we continue
47084
47085
47086 if (positionDefined < 0.5 * indices.length) {
47087 var MAX_LEVELS = 10;
47088 var level = 0;
47089 var clusterThreshold = this.options.clusterThreshold; //
47090 // Define the options for the hidden cluster nodes
47091 // These options don't propagate outside the clustering phase.
47092 //
47093 // Some options are explicitly disabled, because they may be set in group or default node options.
47094 // The clusters are never displayed, so most explicit settings here serve as performance optimizations.
47095 //
47096 // The explicit setting of 'shape' is to avoid `shape: 'image'`; images are not passed to the hidden
47097 // cluster nodes, leading to an exception on creation.
47098 //
47099 // All settings here are performance related, except when noted otherwise.
47100 //
47101
47102 var clusterOptions = {
47103 clusterNodeProperties: {
47104 shape: 'ellipse',
47105 // Bugfix: avoid type 'image', no images supplied
47106 label: '',
47107 // avoid label handling
47108 group: '',
47109 // avoid group handling
47110 font: {
47111 multi: false
47112 } // avoid font propagation
47113
47114 },
47115 clusterEdgeProperties: {
47116 label: '',
47117 // avoid label handling
47118 font: {
47119 multi: false
47120 },
47121 // avoid font propagation
47122 smooth: {
47123 enabled: false // avoid drawing penalty for complex edges
47124
47125 }
47126 }
47127 }; // if there are a lot of nodes, we cluster before we run the algorithm.
47128 // NOTE: this part fails to find clusters for large scale-free networks, which should
47129 // be easily clusterable.
47130 // TODO: examine why this is so
47131
47132 if (indices.length > clusterThreshold) {
47133 var startLength = indices.length;
47134
47135 while (indices.length > clusterThreshold && level <= MAX_LEVELS) {
47136 //console.time("clustering")
47137 level += 1;
47138 var before = indices.length; // if there are many nodes we do a hubsize cluster
47139
47140 if (level % 3 === 0) {
47141 this.body.modules.clustering.clusterBridges(clusterOptions);
47142 } else {
47143 this.body.modules.clustering.clusterOutliers(clusterOptions);
47144 }
47145
47146 var after = indices.length;
47147
47148 if (before == after && level % 3 !== 0) {
47149 this._declusterAll();
47150
47151 this.body.emitter.emit("_layoutFailed");
47152 console.info("This network could not be positioned by this version of the improved layout algorithm." + " Please disable improvedLayout for better performance.");
47153 return;
47154 } //console.timeEnd("clustering")
47155 //console.log(before,level,after);
47156
47157 } // increase the size of the edges
47158
47159
47160 this.body.modules.kamadaKawai.setOptions({
47161 springLength: Math.max(150, 2 * startLength)
47162 });
47163 }
47164
47165 if (level > MAX_LEVELS) {
47166 console.info("The clustering didn't succeed within the amount of interations allowed," + " progressing with partial result.");
47167 } // position the system for these nodes and edges
47168
47169
47170 this.body.modules.kamadaKawai.solve(indices, this.body.edgeIndices, true); // shift to center point
47171
47172 this._shiftToCenter(); // perturb the nodes a little bit to force the physics to kick in
47173
47174
47175 var offset = 70;
47176
47177 for (var _i = 0; _i < indices.length; _i++) {
47178 // Only perturb the nodes that aren't fixed
47179 var _node = this.body.nodes[indices[_i]];
47180
47181 if (_node.predefinedPosition === false) {
47182 _node.x += (0.5 - this.seededRandom()) * offset;
47183 _node.y += (0.5 - this.seededRandom()) * offset;
47184 }
47185 } // uncluster all clusters
47186
47187
47188 this._declusterAll(); // reposition all bezier nodes.
47189
47190
47191 this.body.emitter.emit("_repositionBezierNodes");
47192 }
47193 }
47194 }
47195 /**
47196 * Move all the nodes towards to the center so gravitational pull wil not move the nodes away from view
47197 * @private
47198 */
47199
47200 }, {
47201 key: "_shiftToCenter",
47202 value: function _shiftToCenter() {
47203 var range = NetworkUtil.getRangeCore(this.body.nodes, this.body.nodeIndices);
47204 var center = NetworkUtil.findCenter(range);
47205
47206 for (var i = 0; i < this.body.nodeIndices.length; i++) {
47207 var node = this.body.nodes[this.body.nodeIndices[i]];
47208 node.x -= center.x;
47209 node.y -= center.y;
47210 }
47211 }
47212 /**
47213 * Expands all clusters
47214 * @private
47215 */
47216
47217 }, {
47218 key: "_declusterAll",
47219 value: function _declusterAll() {
47220 var clustersPresent = true;
47221
47222 while (clustersPresent === true) {
47223 clustersPresent = false;
47224
47225 for (var i = 0; i < this.body.nodeIndices.length; i++) {
47226 if (this.body.nodes[this.body.nodeIndices[i]].isCluster === true) {
47227 clustersPresent = true;
47228 this.body.modules.clustering.openCluster(this.body.nodeIndices[i], {}, false);
47229 }
47230 }
47231
47232 if (clustersPresent === true) {
47233 this.body.emitter.emit('_dataChanged');
47234 }
47235 }
47236 }
47237 /**
47238 *
47239 * @returns {number|*}
47240 */
47241
47242 }, {
47243 key: "getSeed",
47244 value: function getSeed() {
47245 return this.initialRandomSeed;
47246 }
47247 /**
47248 * This is the main function to layout the nodes in a hierarchical way.
47249 * It checks if the node details are supplied correctly
47250 *
47251 * @private
47252 */
47253
47254 }, {
47255 key: "setupHierarchicalLayout",
47256 value: function setupHierarchicalLayout() {
47257 if (this.options.hierarchical.enabled === true && this.body.nodeIndices.length > 0) {
47258 // get the size of the largest hubs and check if the user has defined a level for a node.
47259 var node, nodeId;
47260 var definedLevel = false;
47261 var undefinedLevel = false;
47262 this.lastNodeOnLevel = {};
47263 this.hierarchical = new HierarchicalStatus();
47264
47265 for (nodeId in this.body.nodes) {
47266 if (this.body.nodes.hasOwnProperty(nodeId)) {
47267 node = this.body.nodes[nodeId];
47268
47269 if (node.options.level !== undefined) {
47270 definedLevel = true;
47271 this.hierarchical.levels[nodeId] = node.options.level;
47272 } else {
47273 undefinedLevel = true;
47274 }
47275 }
47276 } // if the user defined some levels but not all, alert and run without hierarchical layout
47277
47278
47279 if (undefinedLevel === true && definedLevel === true) {
47280 throw new Error('To use the hierarchical layout, nodes require either no predefined levels' + ' or levels have to be defined for all nodes.');
47281 } else {
47282 // define levels if undefined by the users. Based on hubsize.
47283 if (undefinedLevel === true) {
47284 var sortMethod = this.options.hierarchical.sortMethod;
47285
47286 if (sortMethod === 'hubsize') {
47287 this._determineLevelsByHubsize();
47288 } else if (sortMethod === 'directed') {
47289 this._determineLevelsDirected();
47290 } else if (sortMethod === 'custom') {
47291 this._determineLevelsCustomCallback();
47292 }
47293 } // fallback for cases where there are nodes but no edges
47294
47295
47296 for (var _nodeId2 in this.body.nodes) {
47297 if (this.body.nodes.hasOwnProperty(_nodeId2)) {
47298 this.hierarchical.ensureLevel(_nodeId2);
47299 }
47300 } // check the distribution of the nodes per level.
47301
47302
47303 var distribution = this._getDistribution(); // get the parent children relations.
47304
47305
47306 this._generateMap(); // place the nodes on the canvas.
47307
47308
47309 this._placeNodesByHierarchy(distribution); // condense the whitespace.
47310
47311
47312 this._condenseHierarchy(); // shift to center so gravity does not have to do much
47313
47314
47315 this._shiftToCenter();
47316 }
47317 }
47318 }
47319 /**
47320 * @private
47321 */
47322
47323 }, {
47324 key: "_condenseHierarchy",
47325 value: function _condenseHierarchy() {
47326 var _this3 = this;
47327
47328 // Global var in this scope to define when the movement has stopped.
47329 var stillShifting = false;
47330 var branches = {}; // first we have some methods to help shifting trees around.
47331 // the main method to shift the trees
47332
47333 var shiftTrees = function shiftTrees() {
47334 var treeSizes = getTreeSizes();
47335 var shiftBy = 0;
47336
47337 for (var i = 0; i < treeSizes.length - 1; i++) {
47338 var diff = treeSizes[i].max - treeSizes[i + 1].min;
47339 shiftBy += diff + _this3.options.hierarchical.treeSpacing;
47340 shiftTree(i + 1, shiftBy);
47341 }
47342 }; // shift a single tree by an offset
47343
47344
47345 var shiftTree = function shiftTree(index, offset) {
47346 var trees = _this3.hierarchical.trees;
47347
47348 for (var nodeId in trees) {
47349 if (trees.hasOwnProperty(nodeId)) {
47350 if (trees[nodeId] === index) {
47351 _this3.direction.shift(nodeId, offset);
47352 }
47353 }
47354 }
47355 }; // get the width of all trees
47356
47357
47358 var getTreeSizes = function getTreeSizes() {
47359 var treeWidths = [];
47360
47361 for (var i = 0; i < _this3.hierarchical.numTrees(); i++) {
47362 treeWidths.push(_this3.direction.getTreeSize(i));
47363 }
47364
47365 return treeWidths;
47366 }; // get a map of all nodes in this branch
47367
47368
47369 var getBranchNodes = function getBranchNodes(source, map) {
47370 if (map[source.id]) {
47371 return;
47372 }
47373
47374 map[source.id] = true;
47375
47376 if (_this3.hierarchical.childrenReference[source.id]) {
47377 var children = _this3.hierarchical.childrenReference[source.id];
47378
47379 if (children.length > 0) {
47380 for (var i = 0; i < children.length; i++) {
47381 getBranchNodes(_this3.body.nodes[children[i]], map);
47382 }
47383 }
47384 }
47385 }; // get a min max width as well as the maximum movement space it has on either sides
47386 // we use min max terminology because width and height can interchange depending on the direction of the layout
47387
47388
47389 var getBranchBoundary = function getBranchBoundary(branchMap) {
47390 var maxLevel = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e9;
47391 var minSpace = 1e9;
47392 var maxSpace = 1e9;
47393 var min = 1e9;
47394 var max = -1e9;
47395
47396 for (var branchNode in branchMap) {
47397 if (branchMap.hasOwnProperty(branchNode)) {
47398 var node = _this3.body.nodes[branchNode];
47399 var level = _this3.hierarchical.levels[node.id];
47400
47401 var position = _this3.direction.getPosition(node); // get the space around the node.
47402
47403
47404 var _this3$_getSpaceAroun = _this3._getSpaceAroundNode(node, branchMap),
47405 _this3$_getSpaceAroun2 = _slicedToArray(_this3$_getSpaceAroun, 2),
47406 minSpaceNode = _this3$_getSpaceAroun2[0],
47407 maxSpaceNode = _this3$_getSpaceAroun2[1];
47408
47409 minSpace = Math.min(minSpaceNode, minSpace);
47410 maxSpace = Math.min(maxSpaceNode, maxSpace); // the width is only relevant for the levels two nodes have in common. This is why we filter on this.
47411
47412 if (level <= maxLevel) {
47413 min = Math.min(position, min);
47414 max = Math.max(position, max);
47415 }
47416 }
47417 }
47418
47419 return [min, max, minSpace, maxSpace];
47420 }; // check what the maximum level is these nodes have in common.
47421
47422
47423 var getCollisionLevel = function getCollisionLevel(node1, node2) {
47424 var maxLevel1 = _this3.hierarchical.getMaxLevel(node1.id);
47425
47426 var maxLevel2 = _this3.hierarchical.getMaxLevel(node2.id);
47427
47428 return Math.min(maxLevel1, maxLevel2);
47429 };
47430 /**
47431 * Condense elements. These can be nodes or branches depending on the callback.
47432 *
47433 * @param {function} callback
47434 * @param {Array.<number>} levels
47435 * @param {*} centerParents
47436 */
47437
47438
47439 var shiftElementsCloser = function shiftElementsCloser(callback, levels, centerParents) {
47440 var hier = _this3.hierarchical;
47441
47442 for (var i = 0; i < levels.length; i++) {
47443 var level = levels[i];
47444 var levelNodes = hier.distributionOrdering[level];
47445
47446 if (levelNodes.length > 1) {
47447 for (var j = 0; j < levelNodes.length - 1; j++) {
47448 var node1 = levelNodes[j];
47449 var node2 = levelNodes[j + 1]; // NOTE: logic maintained as it was; if nodes have same ancestor,
47450 // then of course they are in the same sub-network.
47451
47452 if (hier.hasSameParent(node1, node2) && hier.inSameSubNetwork(node1, node2)) {
47453 callback(node1, node2, centerParents);
47454 }
47455 }
47456 }
47457 }
47458 }; // callback for shifting branches
47459
47460
47461 var branchShiftCallback = function branchShiftCallback(node1, node2) {
47462 var centerParent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
47463
47464 //window.CALLBACKS.push(() => {
47465 var pos1 = _this3.direction.getPosition(node1);
47466
47467 var pos2 = _this3.direction.getPosition(node2);
47468
47469 var diffAbs = Math.abs(pos2 - pos1);
47470 var nodeSpacing = _this3.options.hierarchical.nodeSpacing; //console.log("NOW CHECKING:", node1.id, node2.id, diffAbs);
47471
47472 if (diffAbs > nodeSpacing) {
47473 var branchNodes1 = {};
47474 var branchNodes2 = {};
47475 getBranchNodes(node1, branchNodes1);
47476 getBranchNodes(node2, branchNodes2); // check the largest distance between the branches
47477
47478 var maxLevel = getCollisionLevel(node1, node2);
47479 var branchNodeBoundary1 = getBranchBoundary(branchNodes1, maxLevel);
47480 var branchNodeBoundary2 = getBranchBoundary(branchNodes2, maxLevel);
47481 var max1 = branchNodeBoundary1[1];
47482 var min2 = branchNodeBoundary2[0];
47483 var minSpace2 = branchNodeBoundary2[2]; //console.log(node1.id, getBranchBoundary(branchNodes1, maxLevel), node2.id,
47484 // getBranchBoundary(branchNodes2, maxLevel), maxLevel);
47485
47486 var diffBranch = Math.abs(max1 - min2);
47487
47488 if (diffBranch > nodeSpacing) {
47489 var offset = max1 - min2 + nodeSpacing;
47490
47491 if (offset < -minSpace2 + nodeSpacing) {
47492 offset = -minSpace2 + nodeSpacing; //console.log("RESETTING OFFSET", max1 - min2 + this.options.hierarchical.nodeSpacing, -minSpace2, offset);
47493 }
47494
47495 if (offset < 0) {
47496 //console.log("SHIFTING", node2.id, offset);
47497 _this3._shiftBlock(node2.id, offset);
47498
47499 stillShifting = true;
47500 if (centerParent === true) _this3._centerParent(node2);
47501 }
47502 }
47503 } //this.body.emitter.emit("_redraw");})
47504
47505 };
47506
47507 var minimizeEdgeLength = function minimizeEdgeLength(iterations, node) {
47508 //window.CALLBACKS.push(() => {
47509 // console.log("ts",node.id);
47510 var nodeId = node.id;
47511 var allEdges = node.edges;
47512 var nodeLevel = _this3.hierarchical.levels[node.id]; // gather constants
47513
47514 var C2 = _this3.options.hierarchical.levelSeparation * _this3.options.hierarchical.levelSeparation;
47515 var referenceNodes = {};
47516 var aboveEdges = [];
47517
47518 for (var i = 0; i < allEdges.length; i++) {
47519 var edge = allEdges[i];
47520
47521 if (edge.toId != edge.fromId) {
47522 var otherNode = edge.toId == nodeId ? edge.from : edge.to;
47523 referenceNodes[allEdges[i].id] = otherNode;
47524
47525 if (_this3.hierarchical.levels[otherNode.id] < nodeLevel) {
47526 aboveEdges.push(edge);
47527 }
47528 }
47529 } // differentiated sum of lengths based on only moving one node over one axis
47530
47531
47532 var getFx = function getFx(point, edges) {
47533 var sum = 0;
47534
47535 for (var _i2 = 0; _i2 < edges.length; _i2++) {
47536 if (referenceNodes[edges[_i2].id] !== undefined) {
47537 var a = _this3.direction.getPosition(referenceNodes[edges[_i2].id]) - point;
47538 sum += a / Math.sqrt(a * a + C2);
47539 }
47540 }
47541
47542 return sum;
47543 }; // doubly differentiated sum of lengths based on only moving one node over one axis
47544
47545
47546 var getDFx = function getDFx(point, edges) {
47547 var sum = 0;
47548
47549 for (var _i3 = 0; _i3 < edges.length; _i3++) {
47550 if (referenceNodes[edges[_i3].id] !== undefined) {
47551 var a = _this3.direction.getPosition(referenceNodes[edges[_i3].id]) - point;
47552 sum -= C2 * Math.pow(a * a + C2, -1.5);
47553 }
47554 }
47555
47556 return sum;
47557 };
47558
47559 var getGuess = function getGuess(iterations, edges) {
47560 var guess = _this3.direction.getPosition(node); // Newton's method for optimization
47561
47562
47563 var guessMap = {};
47564
47565 for (var _i4 = 0; _i4 < iterations; _i4++) {
47566 var fx = getFx(guess, edges);
47567 var dfx = getDFx(guess, edges); // we limit the movement to avoid instability.
47568
47569 var limit = 40;
47570 var ratio = Math.max(-limit, Math.min(limit, Math.round(fx / dfx)));
47571 guess = guess - ratio; // reduce duplicates
47572
47573 if (guessMap[guess] !== undefined) {
47574 break;
47575 }
47576
47577 guessMap[guess] = _i4;
47578 }
47579
47580 return guess;
47581 };
47582
47583 var moveBranch = function moveBranch(guess) {
47584 // position node if there is space
47585 var nodePosition = _this3.direction.getPosition(node); // check movable area of the branch
47586
47587
47588 if (branches[node.id] === undefined) {
47589 var branchNodes = {};
47590 getBranchNodes(node, branchNodes);
47591 branches[node.id] = branchNodes;
47592 }
47593
47594 var branchBoundary = getBranchBoundary(branches[node.id]);
47595 var minSpaceBranch = branchBoundary[2];
47596 var maxSpaceBranch = branchBoundary[3];
47597 var diff = guess - nodePosition; // check if we are allowed to move the node:
47598
47599 var branchOffset = 0;
47600
47601 if (diff > 0) {
47602 branchOffset = Math.min(diff, maxSpaceBranch - _this3.options.hierarchical.nodeSpacing);
47603 } else if (diff < 0) {
47604 branchOffset = -Math.min(-diff, minSpaceBranch - _this3.options.hierarchical.nodeSpacing);
47605 }
47606
47607 if (branchOffset != 0) {
47608 //console.log("moving branch:",branchOffset, maxSpaceBranch, minSpaceBranch)
47609 _this3._shiftBlock(node.id, branchOffset); //this.body.emitter.emit("_redraw");
47610
47611
47612 stillShifting = true;
47613 }
47614 };
47615
47616 var moveNode = function moveNode(guess) {
47617 var nodePosition = _this3.direction.getPosition(node); // position node if there is space
47618
47619
47620 var _this3$_getSpaceAroun3 = _this3._getSpaceAroundNode(node),
47621 _this3$_getSpaceAroun4 = _slicedToArray(_this3$_getSpaceAroun3, 2),
47622 minSpace = _this3$_getSpaceAroun4[0],
47623 maxSpace = _this3$_getSpaceAroun4[1];
47624
47625 var diff = guess - nodePosition; // check if we are allowed to move the node:
47626
47627 var newPosition = nodePosition;
47628
47629 if (diff > 0) {
47630 newPosition = Math.min(nodePosition + (maxSpace - _this3.options.hierarchical.nodeSpacing), guess);
47631 } else if (diff < 0) {
47632 newPosition = Math.max(nodePosition - (minSpace - _this3.options.hierarchical.nodeSpacing), guess);
47633 }
47634
47635 if (newPosition !== nodePosition) {
47636 //console.log("moving Node:",diff, minSpace, maxSpace);
47637 _this3.direction.setPosition(node, newPosition); //this.body.emitter.emit("_redraw");
47638
47639
47640 stillShifting = true;
47641 }
47642 };
47643
47644 var guess = getGuess(iterations, aboveEdges);
47645 moveBranch(guess);
47646 guess = getGuess(iterations, allEdges);
47647 moveNode(guess); //})
47648 }; // method to remove whitespace between branches. Because we do bottom up, we can center the parents.
47649
47650
47651 var minimizeEdgeLengthBottomUp = function minimizeEdgeLengthBottomUp(iterations) {
47652 var levels = _this3.hierarchical.getLevels();
47653
47654 levels = levels.reverse();
47655
47656 for (var i = 0; i < iterations; i++) {
47657 stillShifting = false;
47658
47659 for (var j = 0; j < levels.length; j++) {
47660 var level = levels[j];
47661 var levelNodes = _this3.hierarchical.distributionOrdering[level];
47662
47663 for (var k = 0; k < levelNodes.length; k++) {
47664 minimizeEdgeLength(1000, levelNodes[k]);
47665 }
47666 }
47667
47668 if (stillShifting !== true) {
47669 //console.log("FINISHED minimizeEdgeLengthBottomUp IN " + i);
47670 break;
47671 }
47672 }
47673 }; // method to remove whitespace between branches. Because we do bottom up, we can center the parents.
47674
47675
47676 var shiftBranchesCloserBottomUp = function shiftBranchesCloserBottomUp(iterations) {
47677 var levels = _this3.hierarchical.getLevels();
47678
47679 levels = levels.reverse();
47680
47681 for (var i = 0; i < iterations; i++) {
47682 stillShifting = false;
47683 shiftElementsCloser(branchShiftCallback, levels, true);
47684
47685 if (stillShifting !== true) {
47686 //console.log("FINISHED shiftBranchesCloserBottomUp IN " + (i+1));
47687 break;
47688 }
47689 }
47690 }; // center all parents
47691
47692
47693 var centerAllParents = function centerAllParents() {
47694 for (var nodeId in _this3.body.nodes) {
47695 if (_this3.body.nodes.hasOwnProperty(nodeId)) _this3._centerParent(_this3.body.nodes[nodeId]);
47696 }
47697 }; // center all parents
47698
47699
47700 var centerAllParentsBottomUp = function centerAllParentsBottomUp() {
47701 var levels = _this3.hierarchical.getLevels();
47702
47703 levels = levels.reverse();
47704
47705 for (var i = 0; i < levels.length; i++) {
47706 var level = levels[i];
47707 var levelNodes = _this3.hierarchical.distributionOrdering[level];
47708
47709 for (var j = 0; j < levelNodes.length; j++) {
47710 _this3._centerParent(levelNodes[j]);
47711 }
47712 }
47713 }; // the actual work is done here.
47714
47715
47716 if (this.options.hierarchical.blockShifting === true) {
47717 shiftBranchesCloserBottomUp(5);
47718 centerAllParents();
47719 } // minimize edge length
47720
47721
47722 if (this.options.hierarchical.edgeMinimization === true) {
47723 minimizeEdgeLengthBottomUp(20);
47724 }
47725
47726 if (this.options.hierarchical.parentCentralization === true) {
47727 centerAllParentsBottomUp();
47728 }
47729
47730 shiftTrees();
47731 }
47732 /**
47733 * This gives the space around the node. IF a map is supplied, it will only check against nodes NOT in the map.
47734 * This is used to only get the distances to nodes outside of a branch.
47735 * @param {Node} node
47736 * @param {{Node.id: vis.Node}} map
47737 * @returns {number[]}
47738 * @private
47739 */
47740
47741 }, {
47742 key: "_getSpaceAroundNode",
47743 value: function _getSpaceAroundNode(node, map) {
47744 var useMap = true;
47745
47746 if (map === undefined) {
47747 useMap = false;
47748 }
47749
47750 var level = this.hierarchical.levels[node.id];
47751
47752 if (level !== undefined) {
47753 var index = this.hierarchical.distributionIndex[node.id];
47754 var position = this.direction.getPosition(node);
47755 var ordering = this.hierarchical.distributionOrdering[level];
47756 var minSpace = 1e9;
47757 var maxSpace = 1e9;
47758
47759 if (index !== 0) {
47760 var prevNode = ordering[index - 1];
47761
47762 if (useMap === true && map[prevNode.id] === undefined || useMap === false) {
47763 var prevPos = this.direction.getPosition(prevNode);
47764 minSpace = position - prevPos;
47765 }
47766 }
47767
47768 if (index != ordering.length - 1) {
47769 var nextNode = ordering[index + 1];
47770
47771 if (useMap === true && map[nextNode.id] === undefined || useMap === false) {
47772 var nextPos = this.direction.getPosition(nextNode);
47773 maxSpace = Math.min(maxSpace, nextPos - position);
47774 }
47775 }
47776
47777 return [minSpace, maxSpace];
47778 } else {
47779 return [0, 0];
47780 }
47781 }
47782 /**
47783 * We use this method to center a parent node and check if it does not cross other nodes when it does.
47784 * @param {Node} node
47785 * @private
47786 */
47787
47788 }, {
47789 key: "_centerParent",
47790 value: function _centerParent(node) {
47791 if (this.hierarchical.parentReference[node.id]) {
47792 var parents = this.hierarchical.parentReference[node.id];
47793
47794 for (var i = 0; i < parents.length; i++) {
47795 var parentId = parents[i];
47796 var parentNode = this.body.nodes[parentId];
47797 var children = this.hierarchical.childrenReference[parentId];
47798
47799 if (children !== undefined) {
47800 // get the range of the children
47801 var newPosition = this._getCenterPosition(children);
47802
47803 var position = this.direction.getPosition(parentNode);
47804
47805 var _this$_getSpaceAround = this._getSpaceAroundNode(parentNode),
47806 _this$_getSpaceAround2 = _slicedToArray(_this$_getSpaceAround, 2),
47807 minSpace = _this$_getSpaceAround2[0],
47808 maxSpace = _this$_getSpaceAround2[1];
47809
47810 var diff = position - newPosition;
47811
47812 if (diff < 0 && Math.abs(diff) < maxSpace - this.options.hierarchical.nodeSpacing || diff > 0 && Math.abs(diff) < minSpace - this.options.hierarchical.nodeSpacing) {
47813 this.direction.setPosition(parentNode, newPosition);
47814 }
47815 }
47816 }
47817 }
47818 }
47819 /**
47820 * This function places the nodes on the canvas based on the hierarchial distribution.
47821 *
47822 * @param {Object} distribution | obtained by the function this._getDistribution()
47823 * @private
47824 */
47825
47826 }, {
47827 key: "_placeNodesByHierarchy",
47828 value: function _placeNodesByHierarchy(distribution) {
47829 this.positionedNodes = {}; // start placing all the level 0 nodes first. Then recursively position their branches.
47830
47831 for (var level in distribution) {
47832 if (distribution.hasOwnProperty(level)) {
47833 // sort nodes in level by position:
47834 var nodeArray = Object.keys(distribution[level]);
47835 nodeArray = this._indexArrayToNodes(nodeArray);
47836 this.direction.sort(nodeArray);
47837 var handledNodeCount = 0;
47838
47839 for (var i = 0; i < nodeArray.length; i++) {
47840 var node = nodeArray[i];
47841
47842 if (this.positionedNodes[node.id] === undefined) {
47843 var spacing = this.options.hierarchical.nodeSpacing;
47844 var pos = spacing * handledNodeCount; // We get the X or Y values we need and store them in pos and previousPos.
47845 // The get and set make sure we get X or Y
47846
47847 if (handledNodeCount > 0) {
47848 pos = this.direction.getPosition(nodeArray[i - 1]) + spacing;
47849 }
47850
47851 this.direction.setPosition(node, pos, level);
47852
47853 this._validatePositionAndContinue(node, level, pos);
47854
47855 handledNodeCount++;
47856 }
47857 }
47858 }
47859 }
47860 }
47861 /**
47862 * This is a recursively called function to enumerate the branches from the largest hubs and place the nodes
47863 * on a X position that ensures there will be no overlap.
47864 *
47865 * @param {Node.id} parentId
47866 * @param {number} parentLevel
47867 * @private
47868 */
47869
47870 }, {
47871 key: "_placeBranchNodes",
47872 value: function _placeBranchNodes(parentId, parentLevel) {
47873 var childRef = this.hierarchical.childrenReference[parentId]; // if this is not a parent, cancel the placing. This can happen with multiple parents to one child.
47874
47875 if (childRef === undefined) {
47876 return;
47877 } // get a list of childNodes
47878
47879
47880 var childNodes = [];
47881
47882 for (var i = 0; i < childRef.length; i++) {
47883 childNodes.push(this.body.nodes[childRef[i]]);
47884 } // use the positions to order the nodes.
47885
47886
47887 this.direction.sort(childNodes); // position the childNodes
47888
47889 for (var _i5 = 0; _i5 < childNodes.length; _i5++) {
47890 var childNode = childNodes[_i5];
47891 var childNodeLevel = this.hierarchical.levels[childNode.id]; // check if the child node is below the parent node and if it has already been positioned.
47892
47893 if (childNodeLevel > parentLevel && this.positionedNodes[childNode.id] === undefined) {
47894 // get the amount of space required for this node. If parent the width is based on the amount of children.
47895 var spacing = this.options.hierarchical.nodeSpacing;
47896 var pos = void 0; // we get the X or Y values we need and store them in pos and previousPos.
47897 // The get and set make sure we get X or Y
47898
47899 if (_i5 === 0) {
47900 pos = this.direction.getPosition(this.body.nodes[parentId]);
47901 } else {
47902 pos = this.direction.getPosition(childNodes[_i5 - 1]) + spacing;
47903 }
47904
47905 this.direction.setPosition(childNode, pos, childNodeLevel);
47906
47907 this._validatePositionAndContinue(childNode, childNodeLevel, pos);
47908 } else {
47909 return;
47910 }
47911 } // center the parent nodes.
47912
47913
47914 var center = this._getCenterPosition(childNodes);
47915
47916 this.direction.setPosition(this.body.nodes[parentId], center, parentLevel);
47917 }
47918 /**
47919 * This method checks for overlap and if required shifts the branch. It also keeps records of positioned nodes.
47920 * Finally it will call _placeBranchNodes to place the branch nodes.
47921 * @param {Node} node
47922 * @param {number} level
47923 * @param {number} pos
47924 * @private
47925 */
47926
47927 }, {
47928 key: "_validatePositionAndContinue",
47929 value: function _validatePositionAndContinue(node, level, pos) {
47930 // This method only works for formal trees and formal forests
47931 // Early exit if this is not the case
47932 if (!this.hierarchical.isTree) return; // if overlap has been detected, we shift the branch
47933
47934 if (this.lastNodeOnLevel[level] !== undefined) {
47935 var previousPos = this.direction.getPosition(this.body.nodes[this.lastNodeOnLevel[level]]);
47936
47937 if (pos - previousPos < this.options.hierarchical.nodeSpacing) {
47938 var diff = previousPos + this.options.hierarchical.nodeSpacing - pos;
47939
47940 var sharedParent = this._findCommonParent(this.lastNodeOnLevel[level], node.id);
47941
47942 this._shiftBlock(sharedParent.withChild, diff);
47943 }
47944 }
47945
47946 this.lastNodeOnLevel[level] = node.id; // store change in position.
47947
47948 this.positionedNodes[node.id] = true;
47949
47950 this._placeBranchNodes(node.id, level);
47951 }
47952 /**
47953 * Receives an array with node indices and returns an array with the actual node references.
47954 * Used for sorting based on node properties.
47955 * @param {Array.<Node.id>} idArray
47956 * @returns {Array.<Node>}
47957 */
47958
47959 }, {
47960 key: "_indexArrayToNodes",
47961 value: function _indexArrayToNodes(idArray) {
47962 var array = [];
47963
47964 for (var i = 0; i < idArray.length; i++) {
47965 array.push(this.body.nodes[idArray[i]]);
47966 }
47967
47968 return array;
47969 }
47970 /**
47971 * This function get the distribution of levels based on hubsize
47972 *
47973 * @returns {Object}
47974 * @private
47975 */
47976
47977 }, {
47978 key: "_getDistribution",
47979 value: function _getDistribution() {
47980 var distribution = {};
47981 var nodeId, node; // we fix Y because the hierarchy is vertical,
47982 // we fix X so we do not give a node an x position for a second time.
47983 // the fix of X is removed after the x value has been set.
47984
47985 for (nodeId in this.body.nodes) {
47986 if (this.body.nodes.hasOwnProperty(nodeId)) {
47987 node = this.body.nodes[nodeId];
47988 var level = this.hierarchical.levels[nodeId] === undefined ? 0 : this.hierarchical.levels[nodeId];
47989 this.direction.fix(node, level);
47990
47991 if (distribution[level] === undefined) {
47992 distribution[level] = {};
47993 }
47994
47995 distribution[level][nodeId] = node;
47996 }
47997 }
47998
47999 return distribution;
48000 }
48001 /**
48002 * Return the active (i.e. visible) edges for this node
48003 *
48004 * @param {Node} node
48005 * @returns {Array.<vis.Edge>} Array of edge instances
48006 * @private
48007 */
48008
48009 }, {
48010 key: "_getActiveEdges",
48011 value: function _getActiveEdges(node) {
48012 var _this4 = this;
48013
48014 var result = [];
48015 forEach(node.edges, function (edge) {
48016 if (_this4.body.edgeIndices.indexOf(edge.id) !== -1) {
48017 result.push(edge);
48018 }
48019 });
48020 return result;
48021 }
48022 /**
48023 * Get the hubsizes for all active nodes.
48024 *
48025 * @returns {number}
48026 * @private
48027 */
48028
48029 }, {
48030 key: "_getHubSizes",
48031 value: function _getHubSizes() {
48032 var _this5 = this;
48033
48034 var hubSizes = {};
48035 var nodeIds = this.body.nodeIndices;
48036 forEach(nodeIds, function (nodeId) {
48037 var node = _this5.body.nodes[nodeId];
48038
48039 var hubSize = _this5._getActiveEdges(node).length;
48040
48041 hubSizes[hubSize] = true;
48042 }); // Make an array of the size sorted descending
48043
48044 var result = [];
48045 forEach(hubSizes, function (size) {
48046 result.push(Number(size));
48047 });
48048 timsort$1.sort(result, function (a, b) {
48049 return b - a;
48050 });
48051 return result;
48052 }
48053 /**
48054 * this function allocates nodes in levels based on the recursive branching from the largest hubs.
48055 *
48056 * @private
48057 */
48058
48059 }, {
48060 key: "_determineLevelsByHubsize",
48061 value: function _determineLevelsByHubsize() {
48062 var _this6 = this;
48063
48064 var levelDownstream = function levelDownstream(nodeA, nodeB) {
48065 _this6.hierarchical.levelDownstream(nodeA, nodeB);
48066 };
48067
48068 var hubSizes = this._getHubSizes();
48069
48070 var _loop = function _loop(i) {
48071 var hubSize = hubSizes[i];
48072 if (hubSize === 0) return "break";
48073 forEach(_this6.body.nodeIndices, function (nodeId) {
48074 var node = _this6.body.nodes[nodeId];
48075
48076 if (hubSize === _this6._getActiveEdges(node).length) {
48077 _this6._crawlNetwork(levelDownstream, nodeId);
48078 }
48079 });
48080 };
48081
48082 for (var i = 0; i < hubSizes.length; ++i) {
48083 var _ret = _loop(i);
48084
48085 if (_ret === "break") break;
48086 }
48087 }
48088 /**
48089 * TODO: release feature
48090 * TODO: Determine if this feature is needed at all
48091 *
48092 * @private
48093 */
48094
48095 }, {
48096 key: "_determineLevelsCustomCallback",
48097 value: function _determineLevelsCustomCallback() {
48098 var _this7 = this;
48099
48100 var minLevel = 100000; // TODO: this should come from options.
48101
48102 var customCallback = function customCallback(nodeA, nodeB, edge) {// eslint-disable-line no-unused-vars
48103 }; // TODO: perhaps move to HierarchicalStatus.
48104 // But I currently don't see the point, this method is not used.
48105
48106
48107 var levelByDirection = function levelByDirection(nodeA, nodeB, edge) {
48108 var levelA = _this7.hierarchical.levels[nodeA.id]; // set initial level
48109
48110 if (levelA === undefined) {
48111 levelA = _this7.hierarchical.levels[nodeA.id] = minLevel;
48112 }
48113
48114 var diff = customCallback(NetworkUtil.cloneOptions(nodeA, 'node'), NetworkUtil.cloneOptions(nodeB, 'node'), NetworkUtil.cloneOptions(edge, 'edge'));
48115 _this7.hierarchical.levels[nodeB.id] = levelA + diff;
48116 };
48117
48118 this._crawlNetwork(levelByDirection);
48119
48120 this.hierarchical.setMinLevelToZero(this.body.nodes);
48121 }
48122 /**
48123 * Allocate nodes in levels based on the direction of the edges.
48124 *
48125 * @private
48126 */
48127
48128 }, {
48129 key: "_determineLevelsDirected",
48130 value: function _determineLevelsDirected() {
48131 var _this8 = this;
48132
48133 var nodes = this.body.nodeIndices.map(function (id) {
48134 return _this8.body.nodes[id];
48135 });
48136 var levels = this.hierarchical.levels;
48137
48138 if (this.options.hierarchical.shakeTowards === "roots") {
48139 this.hierarchical.levels = fillLevelsByDirectionRoots(nodes, this.hierarchical.levels);
48140 } else {
48141 this.hierarchical.levels = fillLevelsByDirectionLeaves(nodes, this.hierarchical.levels);
48142 }
48143
48144 this.hierarchical.setMinLevelToZero(this.body.nodes);
48145 }
48146 /**
48147 * Update the bookkeeping of parent and child.
48148 * @private
48149 */
48150
48151 }, {
48152 key: "_generateMap",
48153 value: function _generateMap() {
48154 var _this9 = this;
48155
48156 var fillInRelations = function fillInRelations(parentNode, childNode) {
48157 if (_this9.hierarchical.levels[childNode.id] > _this9.hierarchical.levels[parentNode.id]) {
48158 _this9.hierarchical.addRelation(parentNode.id, childNode.id);
48159 }
48160 };
48161
48162 this._crawlNetwork(fillInRelations);
48163
48164 this.hierarchical.checkIfTree();
48165 }
48166 /**
48167 * Crawl over the entire network and use a callback on each node couple that is connected to each other.
48168 * @param {function} [callback=function(){}] | will receive nodeA, nodeB and the connecting edge. A and B are distinct.
48169 * @param {Node.id} startingNodeId
48170 * @private
48171 */
48172
48173 }, {
48174 key: "_crawlNetwork",
48175 value: function _crawlNetwork() {
48176 var _this10 = this;
48177
48178 var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
48179 var startingNodeId = arguments.length > 1 ? arguments[1] : undefined;
48180 var progress = {};
48181
48182 var crawler = function crawler(node, tree) {
48183 if (progress[node.id] === undefined) {
48184 _this10.hierarchical.setTreeIndex(node, tree);
48185
48186 progress[node.id] = true;
48187 var childNode;
48188
48189 var edges = _this10._getActiveEdges(node);
48190
48191 for (var i = 0; i < edges.length; i++) {
48192 var edge = edges[i];
48193
48194 if (edge.connected === true) {
48195 if (edge.toId == node.id) {
48196 // Not '===' because id's can be string and numeric
48197 childNode = edge.from;
48198 } else {
48199 childNode = edge.to;
48200 }
48201
48202 if (node.id != childNode.id) {
48203 // Not '!==' because id's can be string and numeric
48204 callback(node, childNode, edge);
48205 crawler(childNode, tree);
48206 }
48207 }
48208 }
48209 }
48210 };
48211
48212 if (startingNodeId === undefined) {
48213 // Crawl over all nodes
48214 var treeIndex = 0; // Serves to pass a unique id for the current distinct tree
48215
48216 for (var i = 0; i < this.body.nodeIndices.length; i++) {
48217 var nodeId = this.body.nodeIndices[i];
48218
48219 if (progress[nodeId] === undefined) {
48220 var node = this.body.nodes[nodeId];
48221 crawler(node, treeIndex);
48222 treeIndex += 1;
48223 }
48224 }
48225 } else {
48226 // Crawl from the given starting node
48227 var _node2 = this.body.nodes[startingNodeId];
48228
48229 if (_node2 === undefined) {
48230 console.error("Node not found:", startingNodeId);
48231 return;
48232 }
48233
48234 crawler(_node2);
48235 }
48236 }
48237 /**
48238 * Shift a branch a certain distance
48239 * @param {Node.id} parentId
48240 * @param {number} diff
48241 * @private
48242 */
48243
48244 }, {
48245 key: "_shiftBlock",
48246 value: function _shiftBlock(parentId, diff) {
48247 var _this11 = this;
48248
48249 var progress = {};
48250
48251 var shifter = function shifter(parentId) {
48252 if (progress[parentId]) {
48253 return;
48254 }
48255
48256 progress[parentId] = true;
48257
48258 _this11.direction.shift(parentId, diff);
48259
48260 var childRef = _this11.hierarchical.childrenReference[parentId];
48261
48262 if (childRef !== undefined) {
48263 for (var i = 0; i < childRef.length; i++) {
48264 shifter(childRef[i]);
48265 }
48266 }
48267 };
48268
48269 shifter(parentId);
48270 }
48271 /**
48272 * Find a common parent between branches.
48273 * @param {Node.id} childA
48274 * @param {Node.id} childB
48275 * @returns {{foundParent, withChild}}
48276 * @private
48277 */
48278
48279 }, {
48280 key: "_findCommonParent",
48281 value: function _findCommonParent(childA, childB) {
48282 var _this12 = this;
48283
48284 var parents = {};
48285
48286 var iterateParents = function iterateParents(parents, child) {
48287 var parentRef = _this12.hierarchical.parentReference[child];
48288
48289 if (parentRef !== undefined) {
48290 for (var i = 0; i < parentRef.length; i++) {
48291 var parent = parentRef[i];
48292 parents[parent] = true;
48293 iterateParents(parents, parent);
48294 }
48295 }
48296 };
48297
48298 var findParent = function findParent(parents, child) {
48299 var parentRef = _this12.hierarchical.parentReference[child];
48300
48301 if (parentRef !== undefined) {
48302 for (var i = 0; i < parentRef.length; i++) {
48303 var parent = parentRef[i];
48304
48305 if (parents[parent] !== undefined) {
48306 return {
48307 foundParent: parent,
48308 withChild: child
48309 };
48310 }
48311
48312 var branch = findParent(parents, parent);
48313
48314 if (branch.foundParent !== null) {
48315 return branch;
48316 }
48317 }
48318 }
48319
48320 return {
48321 foundParent: null,
48322 withChild: child
48323 };
48324 };
48325
48326 iterateParents(parents, childA);
48327 return findParent(parents, childB);
48328 }
48329 /**
48330 * Set the strategy pattern for handling the coordinates given the current direction.
48331 *
48332 * The individual instances contain all the operations and data specific to a layout direction.
48333 *
48334 * @param {Node} node
48335 * @param {{x: number, y: number}} position
48336 * @param {number} level
48337 * @param {boolean} [doNotUpdate=false]
48338 * @private
48339 */
48340
48341 }, {
48342 key: "setDirectionStrategy",
48343 value: function setDirectionStrategy() {
48344 var isVertical = this.options.hierarchical.direction === 'UD' || this.options.hierarchical.direction === 'DU';
48345
48346 if (isVertical) {
48347 this.direction = new VerticalStrategy(this);
48348 } else {
48349 this.direction = new HorizontalStrategy(this);
48350 }
48351 }
48352 /**
48353 * Determine the center position of a branch from the passed list of child nodes
48354 *
48355 * This takes into account the positions of all the child nodes.
48356 * @param {Array.<Node|vis.Node.id>} childNodes Array of either child nodes or node id's
48357 * @return {number}
48358 * @private
48359 */
48360
48361 }, {
48362 key: "_getCenterPosition",
48363 value: function _getCenterPosition(childNodes) {
48364 var minPos = 1e9;
48365 var maxPos = -1e9;
48366
48367 for (var i = 0; i < childNodes.length; i++) {
48368 var childNode = void 0;
48369
48370 if (childNodes[i].id !== undefined) {
48371 childNode = childNodes[i];
48372 } else {
48373 var childNodeId = childNodes[i];
48374 childNode = this.body.nodes[childNodeId];
48375 }
48376
48377 var position = this.direction.getPosition(childNode);
48378 minPos = Math.min(minPos, position);
48379 maxPos = Math.max(maxPos, position);
48380 }
48381
48382 return 0.5 * (minPos + maxPos);
48383 }
48384 }]);
48385
48386 return LayoutEngine;
48387}();
48388
48389/**
48390 * Clears the toolbar div element of children
48391 *
48392 * @private
48393 */
48394
48395var ManipulationSystem =
48396/*#__PURE__*/
48397function () {
48398 /**
48399 * @param {Object} body
48400 * @param {Canvas} canvas
48401 * @param {SelectionHandler} selectionHandler
48402 */
48403 function ManipulationSystem(body, canvas, selectionHandler, interactionHandler) {
48404 var _this = this;
48405
48406 _classCallCheck(this, ManipulationSystem);
48407
48408 this.body = body;
48409 this.canvas = canvas;
48410 this.selectionHandler = selectionHandler;
48411 this.interactionHandler = interactionHandler;
48412 this.editMode = false;
48413 this.manipulationDiv = undefined;
48414 this.editModeDiv = undefined;
48415 this.closeDiv = undefined;
48416 this.manipulationHammers = [];
48417 this.temporaryUIFunctions = {};
48418 this.temporaryEventFunctions = [];
48419 this.touchTime = 0;
48420 this.temporaryIds = {
48421 nodes: [],
48422 edges: []
48423 };
48424 this.guiEnabled = false;
48425 this.inMode = false;
48426 this.selectedControlNode = undefined;
48427 this.options = {};
48428 this.defaultOptions = {
48429 enabled: false,
48430 initiallyActive: false,
48431 addNode: true,
48432 addEdge: true,
48433 editNode: undefined,
48434 editEdge: true,
48435 deleteNode: true,
48436 deleteEdge: true,
48437 controlNodeStyle: {
48438 shape: 'dot',
48439 size: 6,
48440 color: {
48441 background: '#ff0000',
48442 border: '#3c3c3c',
48443 highlight: {
48444 background: '#07f968',
48445 border: '#3c3c3c'
48446 }
48447 },
48448 borderWidth: 2,
48449 borderWidthSelected: 2
48450 }
48451 };
48452 extend(this.options, this.defaultOptions);
48453 this.body.emitter.on('destroy', function () {
48454 _this._clean();
48455 });
48456 this.body.emitter.on('_dataChanged', this._restore.bind(this));
48457 this.body.emitter.on('_resetData', this._restore.bind(this));
48458 }
48459 /**
48460 * If something changes in the data during editing, switch back to the initial datamanipulation state and close all edit modes.
48461 * @private
48462 */
48463
48464
48465 _createClass(ManipulationSystem, [{
48466 key: "_restore",
48467 value: function _restore() {
48468 if (this.inMode !== false) {
48469 if (this.options.initiallyActive === true) {
48470 this.enableEditMode();
48471 } else {
48472 this.disableEditMode();
48473 }
48474 }
48475 }
48476 /**
48477 * Set the Options
48478 *
48479 * @param {Object} options
48480 * @param {Object} allOptions
48481 * @param {Object} globalOptions
48482 */
48483
48484 }, {
48485 key: "setOptions",
48486 value: function setOptions(options, allOptions, globalOptions) {
48487 if (allOptions !== undefined) {
48488 if (allOptions.locale !== undefined) {
48489 this.options.locale = allOptions.locale;
48490 } else {
48491 this.options.locale = globalOptions.locale;
48492 }
48493
48494 if (allOptions.locales !== undefined) {
48495 this.options.locales = allOptions.locales;
48496 } else {
48497 this.options.locales = globalOptions.locales;
48498 }
48499 }
48500
48501 if (options !== undefined) {
48502 if (typeof options === 'boolean') {
48503 this.options.enabled = options;
48504 } else {
48505 this.options.enabled = true;
48506 deepExtend(this.options, options);
48507 }
48508
48509 if (this.options.initiallyActive === true) {
48510 this.editMode = true;
48511 }
48512
48513 this._setup();
48514 }
48515 }
48516 /**
48517 * Enable or disable edit-mode. Draws the DOM required and cleans up after itself.
48518 *
48519 * @private
48520 */
48521
48522 }, {
48523 key: "toggleEditMode",
48524 value: function toggleEditMode() {
48525 if (this.editMode === true) {
48526 this.disableEditMode();
48527 } else {
48528 this.enableEditMode();
48529 }
48530 }
48531 /**
48532 * Enables Edit Mode
48533 */
48534
48535 }, {
48536 key: "enableEditMode",
48537 value: function enableEditMode() {
48538 this.editMode = true;
48539
48540 this._clean();
48541
48542 if (this.guiEnabled === true) {
48543 this.manipulationDiv.style.display = 'block';
48544 this.closeDiv.style.display = 'block';
48545 this.editModeDiv.style.display = 'none';
48546 this.showManipulatorToolbar();
48547 }
48548 }
48549 /**
48550 * Disables Edit Mode
48551 */
48552
48553 }, {
48554 key: "disableEditMode",
48555 value: function disableEditMode() {
48556 this.editMode = false;
48557
48558 this._clean();
48559
48560 if (this.guiEnabled === true) {
48561 this.manipulationDiv.style.display = 'none';
48562 this.closeDiv.style.display = 'none';
48563 this.editModeDiv.style.display = 'block';
48564
48565 this._createEditButton();
48566 }
48567 }
48568 /**
48569 * Creates the main toolbar. Removes functions bound to the select event. Binds all the buttons of the toolbar.
48570 *
48571 * @private
48572 */
48573
48574 }, {
48575 key: "showManipulatorToolbar",
48576 value: function showManipulatorToolbar() {
48577 // restore the state of any bound functions or events, remove control nodes, restore physics
48578 this._clean(); // reset global variables
48579
48580
48581 this.manipulationDOM = {}; // if the gui is enabled, draw all elements.
48582
48583 if (this.guiEnabled === true) {
48584 // a _restore will hide these menus
48585 this.editMode = true;
48586 this.manipulationDiv.style.display = 'block';
48587 this.closeDiv.style.display = 'block';
48588
48589 var selectedNodeCount = this.selectionHandler._getSelectedNodeCount();
48590
48591 var selectedEdgeCount = this.selectionHandler._getSelectedEdgeCount();
48592
48593 var selectedTotalCount = selectedNodeCount + selectedEdgeCount;
48594 var locale = this.options.locales[this.options.locale];
48595 var needSeperator = false;
48596
48597 if (this.options.addNode !== false) {
48598 this._createAddNodeButton(locale);
48599
48600 needSeperator = true;
48601 }
48602
48603 if (this.options.addEdge !== false) {
48604 if (needSeperator === true) {
48605 this._createSeperator(1);
48606 } else {
48607 needSeperator = true;
48608 }
48609
48610 this._createAddEdgeButton(locale);
48611 }
48612
48613 if (selectedNodeCount === 1 && typeof this.options.editNode === 'function') {
48614 if (needSeperator === true) {
48615 this._createSeperator(2);
48616 } else {
48617 needSeperator = true;
48618 }
48619
48620 this._createEditNodeButton(locale);
48621 } else if (selectedEdgeCount === 1 && selectedNodeCount === 0 && this.options.editEdge !== false) {
48622 if (needSeperator === true) {
48623 this._createSeperator(3);
48624 } else {
48625 needSeperator = true;
48626 }
48627
48628 this._createEditEdgeButton(locale);
48629 } // remove buttons
48630
48631
48632 if (selectedTotalCount !== 0) {
48633 if (selectedNodeCount > 0 && this.options.deleteNode !== false) {
48634 if (needSeperator === true) {
48635 this._createSeperator(4);
48636 }
48637
48638 this._createDeleteButton(locale);
48639 } else if (selectedNodeCount === 0 && this.options.deleteEdge !== false) {
48640 if (needSeperator === true) {
48641 this._createSeperator(4);
48642 }
48643
48644 this._createDeleteButton(locale);
48645 }
48646 } // bind the close button
48647
48648
48649 this._bindHammerToDiv(this.closeDiv, this.toggleEditMode.bind(this)); // refresh this bar based on what has been selected
48650
48651
48652 this._temporaryBindEvent('select', this.showManipulatorToolbar.bind(this));
48653 } // redraw to show any possible changes
48654
48655
48656 this.body.emitter.emit('_redraw');
48657 }
48658 /**
48659 * Create the toolbar for adding Nodes
48660 */
48661
48662 }, {
48663 key: "addNodeMode",
48664 value: function addNodeMode() {
48665 // when using the gui, enable edit mode if it wasnt already.
48666 if (this.editMode !== true) {
48667 this.enableEditMode();
48668 } // restore the state of any bound functions or events, remove control nodes, restore physics
48669
48670
48671 this._clean();
48672
48673 this.inMode = 'addNode';
48674
48675 if (this.guiEnabled === true) {
48676 var locale = this.options.locales[this.options.locale];
48677 this.manipulationDOM = {};
48678
48679 this._createBackButton(locale);
48680
48681 this._createSeperator();
48682
48683 this._createDescription(locale['addDescription'] || this.options.locales['en']['addDescription']); // bind the close button
48684
48685
48686 this._bindHammerToDiv(this.closeDiv, this.toggleEditMode.bind(this));
48687 }
48688
48689 this._temporaryBindEvent('click', this._performAddNode.bind(this));
48690 }
48691 /**
48692 * call the bound function to handle the editing of the node. The node has to be selected.
48693 */
48694
48695 }, {
48696 key: "editNode",
48697 value: function editNode() {
48698 var _this2 = this;
48699
48700 // when using the gui, enable edit mode if it wasnt already.
48701 if (this.editMode !== true) {
48702 this.enableEditMode();
48703 } // restore the state of any bound functions or events, remove control nodes, restore physics
48704
48705
48706 this._clean();
48707
48708 var node = this.selectionHandler._getSelectedNode();
48709
48710 if (node !== undefined) {
48711 this.inMode = 'editNode';
48712
48713 if (typeof this.options.editNode === 'function') {
48714 if (node.isCluster !== true) {
48715 var data = deepExtend({}, node.options, false);
48716 data.x = node.x;
48717 data.y = node.y;
48718
48719 if (this.options.editNode.length === 2) {
48720 this.options.editNode(data, function (finalizedData) {
48721 if (finalizedData !== null && finalizedData !== undefined && _this2.inMode === 'editNode') {
48722 // if for whatever reason the mode has changes (due to dataset change) disregard the callback) {
48723 _this2.body.data.nodes.getDataSet().update(finalizedData);
48724 }
48725
48726 _this2.showManipulatorToolbar();
48727 });
48728 } else {
48729 throw new Error('The function for edit does not support two arguments (data, callback)');
48730 }
48731 } else {
48732 alert(this.options.locales[this.options.locale]['editClusterError'] || this.options.locales['en']['editClusterError']);
48733 }
48734 } else {
48735 throw new Error('No function has been configured to handle the editing of nodes.');
48736 }
48737 } else {
48738 this.showManipulatorToolbar();
48739 }
48740 }
48741 /**
48742 * create the toolbar to connect nodes
48743 */
48744
48745 }, {
48746 key: "addEdgeMode",
48747 value: function addEdgeMode() {
48748 // when using the gui, enable edit mode if it wasnt already.
48749 if (this.editMode !== true) {
48750 this.enableEditMode();
48751 } // restore the state of any bound functions or events, remove control nodes, restore physics
48752
48753
48754 this._clean();
48755
48756 this.inMode = 'addEdge';
48757
48758 if (this.guiEnabled === true) {
48759 var locale = this.options.locales[this.options.locale];
48760 this.manipulationDOM = {};
48761
48762 this._createBackButton(locale);
48763
48764 this._createSeperator();
48765
48766 this._createDescription(locale['edgeDescription'] || this.options.locales['en']['edgeDescription']); // bind the close button
48767
48768
48769 this._bindHammerToDiv(this.closeDiv, this.toggleEditMode.bind(this));
48770 } // temporarily overload functions
48771
48772
48773 this._temporaryBindUI('onTouch', this._handleConnect.bind(this));
48774
48775 this._temporaryBindUI('onDragEnd', this._finishConnect.bind(this));
48776
48777 this._temporaryBindUI('onDrag', this._dragControlNode.bind(this));
48778
48779 this._temporaryBindUI('onRelease', this._finishConnect.bind(this));
48780
48781 this._temporaryBindUI('onDragStart', this._dragStartEdge.bind(this));
48782
48783 this._temporaryBindUI('onHold', function () {});
48784 }
48785 /**
48786 * create the toolbar to edit edges
48787 */
48788
48789 }, {
48790 key: "editEdgeMode",
48791 value: function editEdgeMode() {
48792 // when using the gui, enable edit mode if it wasn't already.
48793 if (this.editMode !== true) {
48794 this.enableEditMode();
48795 } // restore the state of any bound functions or events, remove control nodes, restore physics
48796
48797
48798 this._clean();
48799
48800 this.inMode = 'editEdge';
48801
48802 if (_typeof$1(this.options.editEdge) === 'object' && typeof this.options.editEdge.editWithoutDrag === "function") {
48803 this.edgeBeingEditedId = this.selectionHandler.getSelectedEdges()[0];
48804
48805 if (this.edgeBeingEditedId !== undefined) {
48806 var edge = this.body.edges[this.edgeBeingEditedId];
48807
48808 this._performEditEdge(edge.from.id, edge.to.id);
48809
48810 return;
48811 }
48812 }
48813
48814 if (this.guiEnabled === true) {
48815 var locale = this.options.locales[this.options.locale];
48816 this.manipulationDOM = {};
48817
48818 this._createBackButton(locale);
48819
48820 this._createSeperator();
48821
48822 this._createDescription(locale['editEdgeDescription'] || this.options.locales['en']['editEdgeDescription']); // bind the close button
48823
48824
48825 this._bindHammerToDiv(this.closeDiv, this.toggleEditMode.bind(this));
48826 }
48827
48828 this.edgeBeingEditedId = this.selectionHandler.getSelectedEdges()[0];
48829
48830 if (this.edgeBeingEditedId !== undefined) {
48831 var _edge = this.body.edges[this.edgeBeingEditedId]; // create control nodes
48832
48833 var controlNodeFrom = this._getNewTargetNode(_edge.from.x, _edge.from.y);
48834
48835 var controlNodeTo = this._getNewTargetNode(_edge.to.x, _edge.to.y);
48836
48837 this.temporaryIds.nodes.push(controlNodeFrom.id);
48838 this.temporaryIds.nodes.push(controlNodeTo.id);
48839 this.body.nodes[controlNodeFrom.id] = controlNodeFrom;
48840 this.body.nodeIndices.push(controlNodeFrom.id);
48841 this.body.nodes[controlNodeTo.id] = controlNodeTo;
48842 this.body.nodeIndices.push(controlNodeTo.id); // temporarily overload UI functions, cleaned up automatically because of _temporaryBindUI
48843
48844 this._temporaryBindUI('onTouch', this._controlNodeTouch.bind(this)); // used to get the position
48845
48846
48847 this._temporaryBindUI('onTap', function () {}); // disabled
48848
48849
48850 this._temporaryBindUI('onHold', function () {}); // disabled
48851
48852
48853 this._temporaryBindUI('onDragStart', this._controlNodeDragStart.bind(this)); // used to select control node
48854
48855
48856 this._temporaryBindUI('onDrag', this._controlNodeDrag.bind(this)); // used to drag control node
48857
48858
48859 this._temporaryBindUI('onDragEnd', this._controlNodeDragEnd.bind(this)); // used to connect or revert control nodes
48860
48861
48862 this._temporaryBindUI('onMouseMove', function () {}); // disabled
48863 // create function to position control nodes correctly on movement
48864 // automatically cleaned up because we use the temporary bind
48865
48866
48867 this._temporaryBindEvent('beforeDrawing', function (ctx) {
48868 var positions = _edge.edgeType.findBorderPositions(ctx);
48869
48870 if (controlNodeFrom.selected === false) {
48871 controlNodeFrom.x = positions.from.x;
48872 controlNodeFrom.y = positions.from.y;
48873 }
48874
48875 if (controlNodeTo.selected === false) {
48876 controlNodeTo.x = positions.to.x;
48877 controlNodeTo.y = positions.to.y;
48878 }
48879 });
48880
48881 this.body.emitter.emit('_redraw');
48882 } else {
48883 this.showManipulatorToolbar();
48884 }
48885 }
48886 /**
48887 * delete everything in the selection
48888 */
48889
48890 }, {
48891 key: "deleteSelected",
48892 value: function deleteSelected() {
48893 var _this3 = this;
48894
48895 // when using the gui, enable edit mode if it wasnt already.
48896 if (this.editMode !== true) {
48897 this.enableEditMode();
48898 } // restore the state of any bound functions or events, remove control nodes, restore physics
48899
48900
48901 this._clean();
48902
48903 this.inMode = 'delete';
48904 var selectedNodes = this.selectionHandler.getSelectedNodes();
48905 var selectedEdges = this.selectionHandler.getSelectedEdges();
48906 var deleteFunction = undefined;
48907
48908 if (selectedNodes.length > 0) {
48909 for (var i = 0; i < selectedNodes.length; i++) {
48910 if (this.body.nodes[selectedNodes[i]].isCluster === true) {
48911 alert(this.options.locales[this.options.locale]['deleteClusterError'] || this.options.locales['en']['deleteClusterError']);
48912 return;
48913 }
48914 }
48915
48916 if (typeof this.options.deleteNode === 'function') {
48917 deleteFunction = this.options.deleteNode;
48918 }
48919 } else if (selectedEdges.length > 0) {
48920 if (typeof this.options.deleteEdge === 'function') {
48921 deleteFunction = this.options.deleteEdge;
48922 }
48923 }
48924
48925 if (typeof deleteFunction === 'function') {
48926 var data = {
48927 nodes: selectedNodes,
48928 edges: selectedEdges
48929 };
48930
48931 if (deleteFunction.length === 2) {
48932 deleteFunction(data, function (finalizedData) {
48933 if (finalizedData !== null && finalizedData !== undefined && _this3.inMode === 'delete') {
48934 // if for whatever reason the mode has changes (due to dataset change) disregard the callback) {
48935 _this3.body.data.edges.getDataSet().remove(finalizedData.edges);
48936
48937 _this3.body.data.nodes.getDataSet().remove(finalizedData.nodes);
48938
48939 _this3.body.emitter.emit('startSimulation');
48940
48941 _this3.showManipulatorToolbar();
48942 } else {
48943 _this3.body.emitter.emit('startSimulation');
48944
48945 _this3.showManipulatorToolbar();
48946 }
48947 });
48948 } else {
48949 throw new Error('The function for delete does not support two arguments (data, callback)');
48950 }
48951 } else {
48952 this.body.data.edges.getDataSet().remove(selectedEdges);
48953 this.body.data.nodes.getDataSet().remove(selectedNodes);
48954 this.body.emitter.emit('startSimulation');
48955 this.showManipulatorToolbar();
48956 }
48957 } //********************************************** PRIVATE ***************************************//
48958
48959 /**
48960 * draw or remove the DOM
48961 * @private
48962 */
48963
48964 }, {
48965 key: "_setup",
48966 value: function _setup() {
48967 if (this.options.enabled === true) {
48968 // Enable the GUI
48969 this.guiEnabled = true;
48970
48971 this._createWrappers();
48972
48973 if (this.editMode === false) {
48974 this._createEditButton();
48975 } else {
48976 this.showManipulatorToolbar();
48977 }
48978 } else {
48979 this._removeManipulationDOM(); // disable the gui
48980
48981
48982 this.guiEnabled = false;
48983 }
48984 }
48985 /**
48986 * create the div overlays that contain the DOM
48987 * @private
48988 */
48989
48990 }, {
48991 key: "_createWrappers",
48992 value: function _createWrappers() {
48993 // load the manipulator HTML elements. All styling done in css.
48994 if (this.manipulationDiv === undefined) {
48995 this.manipulationDiv = document.createElement('div');
48996 this.manipulationDiv.className = 'vis-manipulation';
48997
48998 if (this.editMode === true) {
48999 this.manipulationDiv.style.display = 'block';
49000 } else {
49001 this.manipulationDiv.style.display = 'none';
49002 }
49003
49004 this.canvas.frame.appendChild(this.manipulationDiv);
49005 } // container for the edit button.
49006
49007
49008 if (this.editModeDiv === undefined) {
49009 this.editModeDiv = document.createElement('div');
49010 this.editModeDiv.className = 'vis-edit-mode';
49011
49012 if (this.editMode === true) {
49013 this.editModeDiv.style.display = 'none';
49014 } else {
49015 this.editModeDiv.style.display = 'block';
49016 }
49017
49018 this.canvas.frame.appendChild(this.editModeDiv);
49019 } // container for the close div button
49020
49021
49022 if (this.closeDiv === undefined) {
49023 this.closeDiv = document.createElement('div');
49024 this.closeDiv.className = 'vis-close';
49025 this.closeDiv.style.display = this.manipulationDiv.style.display;
49026 this.canvas.frame.appendChild(this.closeDiv);
49027 }
49028 }
49029 /**
49030 * generate a new target node. Used for creating new edges and editing edges
49031 *
49032 * @param {number} x
49033 * @param {number} y
49034 * @returns {Node}
49035 * @private
49036 */
49037
49038 }, {
49039 key: "_getNewTargetNode",
49040 value: function _getNewTargetNode(x, y) {
49041 var controlNodeStyle = deepExtend({}, this.options.controlNodeStyle);
49042 controlNodeStyle.id = 'targetNode' + uuid4();
49043 controlNodeStyle.hidden = false;
49044 controlNodeStyle.physics = false;
49045 controlNodeStyle.x = x;
49046 controlNodeStyle.y = y; // we have to define the bounding box in order for the nodes to be drawn immediately
49047
49048 var node = this.body.functions.createNode(controlNodeStyle);
49049 node.shape.boundingBox = {
49050 left: x,
49051 right: x,
49052 top: y,
49053 bottom: y
49054 };
49055 return node;
49056 }
49057 /**
49058 * Create the edit button
49059 */
49060
49061 }, {
49062 key: "_createEditButton",
49063 value: function _createEditButton() {
49064 // restore everything to it's original state (if applicable)
49065 this._clean(); // reset the manipulationDOM
49066
49067
49068 this.manipulationDOM = {}; // empty the editModeDiv
49069
49070 recursiveDOMDelete(this.editModeDiv); // create the contents for the editMode button
49071
49072 var locale = this.options.locales[this.options.locale];
49073
49074 var button = this._createButton('editMode', 'vis-button vis-edit vis-edit-mode', locale['edit'] || this.options.locales['en']['edit']);
49075
49076 this.editModeDiv.appendChild(button); // bind a hammer listener to the button, calling the function toggleEditMode.
49077
49078 this._bindHammerToDiv(button, this.toggleEditMode.bind(this));
49079 }
49080 /**
49081 * this function cleans up after everything this module does. Temporary elements, functions and events are removed, physics restored, hammers removed.
49082 * @private
49083 */
49084
49085 }, {
49086 key: "_clean",
49087 value: function _clean() {
49088 // not in mode
49089 this.inMode = false; // _clean the divs
49090
49091 if (this.guiEnabled === true) {
49092 recursiveDOMDelete(this.editModeDiv);
49093 recursiveDOMDelete(this.manipulationDiv); // removes all the bindings and overloads
49094
49095 this._cleanManipulatorHammers();
49096 } // remove temporary nodes and edges
49097
49098
49099 this._cleanupTemporaryNodesAndEdges(); // restore overloaded UI functions
49100
49101
49102 this._unbindTemporaryUIs(); // remove the temporaryEventFunctions
49103
49104
49105 this._unbindTemporaryEvents(); // restore the physics if required
49106
49107
49108 this.body.emitter.emit('restorePhysics');
49109 }
49110 /**
49111 * Each dom element has it's own hammer. They are stored in this.manipulationHammers. This cleans them up.
49112 * @private
49113 */
49114
49115 }, {
49116 key: "_cleanManipulatorHammers",
49117 value: function _cleanManipulatorHammers() {
49118 // _clean hammer bindings
49119 if (this.manipulationHammers.length != 0) {
49120 for (var i = 0; i < this.manipulationHammers.length; i++) {
49121 this.manipulationHammers[i].destroy();
49122 }
49123
49124 this.manipulationHammers = [];
49125 }
49126 }
49127 /**
49128 * Remove all DOM elements created by this module.
49129 * @private
49130 */
49131
49132 }, {
49133 key: "_removeManipulationDOM",
49134 value: function _removeManipulationDOM() {
49135 // removes all the bindings and overloads
49136 this._clean(); // empty the manipulation divs
49137
49138
49139 recursiveDOMDelete(this.manipulationDiv);
49140 recursiveDOMDelete(this.editModeDiv);
49141 recursiveDOMDelete(this.closeDiv); // remove the manipulation divs
49142
49143 if (this.manipulationDiv) {
49144 this.canvas.frame.removeChild(this.manipulationDiv);
49145 }
49146
49147 if (this.editModeDiv) {
49148 this.canvas.frame.removeChild(this.editModeDiv);
49149 }
49150
49151 if (this.closeDiv) {
49152 this.canvas.frame.removeChild(this.closeDiv);
49153 } // set the references to undefined
49154
49155
49156 this.manipulationDiv = undefined;
49157 this.editModeDiv = undefined;
49158 this.closeDiv = undefined;
49159 }
49160 /**
49161 * create a seperator line. the index is to differentiate in the manipulation dom
49162 * @param {number} [index=1]
49163 * @private
49164 */
49165
49166 }, {
49167 key: "_createSeperator",
49168 value: function _createSeperator() {
49169 var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
49170 this.manipulationDOM['seperatorLineDiv' + index] = document.createElement('div');
49171 this.manipulationDOM['seperatorLineDiv' + index].className = 'vis-separator-line';
49172 this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv' + index]);
49173 } // ---------------------- DOM functions for buttons --------------------------//
49174
49175 /**
49176 *
49177 * @param {Locale} locale
49178 * @private
49179 */
49180
49181 }, {
49182 key: "_createAddNodeButton",
49183 value: function _createAddNodeButton(locale) {
49184 var button = this._createButton('addNode', 'vis-button vis-add', locale['addNode'] || this.options.locales['en']['addNode']);
49185
49186 this.manipulationDiv.appendChild(button);
49187
49188 this._bindHammerToDiv(button, this.addNodeMode.bind(this));
49189 }
49190 /**
49191 *
49192 * @param {Locale} locale
49193 * @private
49194 */
49195
49196 }, {
49197 key: "_createAddEdgeButton",
49198 value: function _createAddEdgeButton(locale) {
49199 var button = this._createButton('addEdge', 'vis-button vis-connect', locale['addEdge'] || this.options.locales['en']['addEdge']);
49200
49201 this.manipulationDiv.appendChild(button);
49202
49203 this._bindHammerToDiv(button, this.addEdgeMode.bind(this));
49204 }
49205 /**
49206 *
49207 * @param {Locale} locale
49208 * @private
49209 */
49210
49211 }, {
49212 key: "_createEditNodeButton",
49213 value: function _createEditNodeButton(locale) {
49214 var button = this._createButton('editNode', 'vis-button vis-edit', locale['editNode'] || this.options.locales['en']['editNode']);
49215
49216 this.manipulationDiv.appendChild(button);
49217
49218 this._bindHammerToDiv(button, this.editNode.bind(this));
49219 }
49220 /**
49221 *
49222 * @param {Locale} locale
49223 * @private
49224 */
49225
49226 }, {
49227 key: "_createEditEdgeButton",
49228 value: function _createEditEdgeButton(locale) {
49229 var button = this._createButton('editEdge', 'vis-button vis-edit', locale['editEdge'] || this.options.locales['en']['editEdge']);
49230
49231 this.manipulationDiv.appendChild(button);
49232
49233 this._bindHammerToDiv(button, this.editEdgeMode.bind(this));
49234 }
49235 /**
49236 *
49237 * @param {Locale} locale
49238 * @private
49239 */
49240
49241 }, {
49242 key: "_createDeleteButton",
49243 value: function _createDeleteButton(locale) {
49244 var deleteBtnClass;
49245
49246 if (this.options.rtl) {
49247 deleteBtnClass = 'vis-button vis-delete-rtl';
49248 } else {
49249 deleteBtnClass = 'vis-button vis-delete';
49250 }
49251
49252 var button = this._createButton('delete', deleteBtnClass, locale['del'] || this.options.locales['en']['del']);
49253
49254 this.manipulationDiv.appendChild(button);
49255
49256 this._bindHammerToDiv(button, this.deleteSelected.bind(this));
49257 }
49258 /**
49259 *
49260 * @param {Locale} locale
49261 * @private
49262 */
49263
49264 }, {
49265 key: "_createBackButton",
49266 value: function _createBackButton(locale) {
49267 var button = this._createButton('back', 'vis-button vis-back', locale['back'] || this.options.locales['en']['back']);
49268
49269 this.manipulationDiv.appendChild(button);
49270
49271 this._bindHammerToDiv(button, this.showManipulatorToolbar.bind(this));
49272 }
49273 /**
49274 *
49275 * @param {number|string} id
49276 * @param {string} className
49277 * @param {label} label
49278 * @param {string} labelClassName
49279 * @returns {HTMLElement}
49280 * @private
49281 */
49282
49283 }, {
49284 key: "_createButton",
49285 value: function _createButton(id, className, label) {
49286 var labelClassName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'vis-label';
49287 this.manipulationDOM[id + 'Div'] = document.createElement('div');
49288 this.manipulationDOM[id + 'Div'].className = className;
49289 this.manipulationDOM[id + 'Label'] = document.createElement('div');
49290 this.manipulationDOM[id + 'Label'].className = labelClassName;
49291 this.manipulationDOM[id + 'Label'].innerHTML = label;
49292 this.manipulationDOM[id + 'Div'].appendChild(this.manipulationDOM[id + 'Label']);
49293 return this.manipulationDOM[id + 'Div'];
49294 }
49295 /**
49296 *
49297 * @param {Label} label
49298 * @private
49299 */
49300
49301 }, {
49302 key: "_createDescription",
49303 value: function _createDescription(label) {
49304 this.manipulationDiv.appendChild(this._createButton('description', 'vis-button vis-none', label));
49305 } // -------------------------- End of DOM functions for buttons ------------------------------//
49306
49307 /**
49308 * this binds an event until cleanup by the clean functions.
49309 * @param {Event} event The event
49310 * @param {function} newFunction
49311 * @private
49312 */
49313
49314 }, {
49315 key: "_temporaryBindEvent",
49316 value: function _temporaryBindEvent(event, newFunction) {
49317 this.temporaryEventFunctions.push({
49318 event: event,
49319 boundFunction: newFunction
49320 });
49321 this.body.emitter.on(event, newFunction);
49322 }
49323 /**
49324 * this overrides an UI function until cleanup by the clean function
49325 * @param {string} UIfunctionName
49326 * @param {function} newFunction
49327 * @private
49328 */
49329
49330 }, {
49331 key: "_temporaryBindUI",
49332 value: function _temporaryBindUI(UIfunctionName, newFunction) {
49333 if (this.body.eventListeners[UIfunctionName] !== undefined) {
49334 this.temporaryUIFunctions[UIfunctionName] = this.body.eventListeners[UIfunctionName];
49335 this.body.eventListeners[UIfunctionName] = newFunction;
49336 } else {
49337 throw new Error('This UI function does not exist. Typo? You tried: ' + UIfunctionName + ' possible are: ' + JSON.stringify(Object.keys(this.body.eventListeners)));
49338 }
49339 }
49340 /**
49341 * Restore the overridden UI functions to their original state.
49342 *
49343 * @private
49344 */
49345
49346 }, {
49347 key: "_unbindTemporaryUIs",
49348 value: function _unbindTemporaryUIs() {
49349 for (var functionName in this.temporaryUIFunctions) {
49350 if (this.temporaryUIFunctions.hasOwnProperty(functionName)) {
49351 this.body.eventListeners[functionName] = this.temporaryUIFunctions[functionName];
49352 delete this.temporaryUIFunctions[functionName];
49353 }
49354 }
49355
49356 this.temporaryUIFunctions = {};
49357 }
49358 /**
49359 * Unbind the events created by _temporaryBindEvent
49360 * @private
49361 */
49362
49363 }, {
49364 key: "_unbindTemporaryEvents",
49365 value: function _unbindTemporaryEvents() {
49366 for (var i = 0; i < this.temporaryEventFunctions.length; i++) {
49367 var eventName = this.temporaryEventFunctions[i].event;
49368 var boundFunction = this.temporaryEventFunctions[i].boundFunction;
49369 this.body.emitter.off(eventName, boundFunction);
49370 }
49371
49372 this.temporaryEventFunctions = [];
49373 }
49374 /**
49375 * Bind an hammer instance to a DOM element.
49376 *
49377 * @param {Element} domElement
49378 * @param {function} boundFunction
49379 */
49380
49381 }, {
49382 key: "_bindHammerToDiv",
49383 value: function _bindHammerToDiv(domElement, boundFunction) {
49384 var hammer$1 = new hammer(domElement, {});
49385 hammerUtil.onTouch(hammer$1, boundFunction);
49386 this.manipulationHammers.push(hammer$1);
49387 }
49388 /**
49389 * Neatly clean up temporary edges and nodes
49390 * @private
49391 */
49392
49393 }, {
49394 key: "_cleanupTemporaryNodesAndEdges",
49395 value: function _cleanupTemporaryNodesAndEdges() {
49396 // _clean temporary edges
49397 for (var i = 0; i < this.temporaryIds.edges.length; i++) {
49398 this.body.edges[this.temporaryIds.edges[i]].disconnect();
49399 delete this.body.edges[this.temporaryIds.edges[i]];
49400 var indexTempEdge = this.body.edgeIndices.indexOf(this.temporaryIds.edges[i]);
49401
49402 if (indexTempEdge !== -1) {
49403 this.body.edgeIndices.splice(indexTempEdge, 1);
49404 }
49405 } // _clean temporary nodes
49406
49407
49408 for (var _i = 0; _i < this.temporaryIds.nodes.length; _i++) {
49409 delete this.body.nodes[this.temporaryIds.nodes[_i]];
49410 var indexTempNode = this.body.nodeIndices.indexOf(this.temporaryIds.nodes[_i]);
49411
49412 if (indexTempNode !== -1) {
49413 this.body.nodeIndices.splice(indexTempNode, 1);
49414 }
49415 }
49416
49417 this.temporaryIds = {
49418 nodes: [],
49419 edges: []
49420 };
49421 } // ------------------------------------------ EDIT EDGE FUNCTIONS -----------------------------------------//
49422
49423 /**
49424 * the touch is used to get the position of the initial click
49425 * @param {Event} event The event
49426 * @private
49427 */
49428
49429 }, {
49430 key: "_controlNodeTouch",
49431 value: function _controlNodeTouch(event) {
49432 this.selectionHandler.unselectAll();
49433 this.lastTouch = this.body.functions.getPointer(event.center);
49434 this.lastTouch.translation = extend({}, this.body.view.translation); // copy the object
49435 }
49436 /**
49437 * the drag start is used to mark one of the control nodes as selected.
49438 * @param {Event} event The event
49439 * @private
49440 */
49441
49442 }, {
49443 key: "_controlNodeDragStart",
49444 value: function _controlNodeDragStart(event) {
49445 // eslint-disable-line no-unused-vars
49446 var pointer = this.lastTouch;
49447
49448 var pointerObj = this.selectionHandler._pointerToPositionObject(pointer);
49449
49450 var from = this.body.nodes[this.temporaryIds.nodes[0]];
49451 var to = this.body.nodes[this.temporaryIds.nodes[1]];
49452 var edge = this.body.edges[this.edgeBeingEditedId];
49453 this.selectedControlNode = undefined;
49454 var fromSelect = from.isOverlappingWith(pointerObj);
49455 var toSelect = to.isOverlappingWith(pointerObj);
49456
49457 if (fromSelect === true) {
49458 this.selectedControlNode = from;
49459 edge.edgeType.from = from;
49460 } else if (toSelect === true) {
49461 this.selectedControlNode = to;
49462 edge.edgeType.to = to;
49463 } // we use the selection to find the node that is being dragged. We explicitly select it here.
49464
49465
49466 if (this.selectedControlNode !== undefined) {
49467 this.selectionHandler.selectObject(this.selectedControlNode);
49468 }
49469
49470 this.body.emitter.emit('_redraw');
49471 }
49472 /**
49473 * dragging the control nodes or the canvas
49474 * @param {Event} event The event
49475 * @private
49476 */
49477
49478 }, {
49479 key: "_controlNodeDrag",
49480 value: function _controlNodeDrag(event) {
49481 this.body.emitter.emit('disablePhysics');
49482 var pointer = this.body.functions.getPointer(event.center);
49483 var pos = this.canvas.DOMtoCanvas(pointer);
49484
49485 if (this.selectedControlNode !== undefined) {
49486 this.selectedControlNode.x = pos.x;
49487 this.selectedControlNode.y = pos.y;
49488 } else {
49489 this.interactionHandler.onDrag(event);
49490 }
49491
49492 this.body.emitter.emit('_redraw');
49493 }
49494 /**
49495 * connecting or restoring the control nodes.
49496 * @param {Event} event The event
49497 * @private
49498 */
49499
49500 }, {
49501 key: "_controlNodeDragEnd",
49502 value: function _controlNodeDragEnd(event) {
49503 var pointer = this.body.functions.getPointer(event.center);
49504
49505 var pointerObj = this.selectionHandler._pointerToPositionObject(pointer);
49506
49507 var edge = this.body.edges[this.edgeBeingEditedId]; // if the node that was dragged is not a control node, return
49508
49509 if (this.selectedControlNode === undefined) {
49510 return;
49511 } // we use the selection to find the node that is being dragged. We explicitly DEselect the control node here.
49512
49513
49514 this.selectionHandler.unselectAll();
49515
49516 var overlappingNodeIds = this.selectionHandler._getAllNodesOverlappingWith(pointerObj);
49517
49518 var node = undefined;
49519
49520 for (var i = overlappingNodeIds.length - 1; i >= 0; i--) {
49521 if (overlappingNodeIds[i] !== this.selectedControlNode.id) {
49522 node = this.body.nodes[overlappingNodeIds[i]];
49523 break;
49524 }
49525 } // perform the connection
49526
49527
49528 if (node !== undefined && this.selectedControlNode !== undefined) {
49529 if (node.isCluster === true) {
49530 alert(this.options.locales[this.options.locale]['createEdgeError'] || this.options.locales['en']['createEdgeError']);
49531 } else {
49532 var from = this.body.nodes[this.temporaryIds.nodes[0]];
49533
49534 if (this.selectedControlNode.id === from.id) {
49535 this._performEditEdge(node.id, edge.to.id);
49536 } else {
49537 this._performEditEdge(edge.from.id, node.id);
49538 }
49539 }
49540 } else {
49541 edge.updateEdgeType();
49542 this.body.emitter.emit('restorePhysics');
49543 }
49544
49545 this.body.emitter.emit('_redraw');
49546 } // ------------------------------------ END OF EDIT EDGE FUNCTIONS -----------------------------------------//
49547 // ------------------------------------------- ADD EDGE FUNCTIONS -----------------------------------------//
49548
49549 /**
49550 * the function bound to the selection event. It checks if you want to connect a cluster and changes the description
49551 * to walk the user through the process.
49552 *
49553 * @param {Event} event
49554 * @private
49555 */
49556
49557 }, {
49558 key: "_handleConnect",
49559 value: function _handleConnect(event) {
49560 // check to avoid double fireing of this function.
49561 if (new Date().valueOf() - this.touchTime > 100) {
49562 this.lastTouch = this.body.functions.getPointer(event.center);
49563 this.lastTouch.translation = extend({}, this.body.view.translation); // copy the object
49564
49565 var pointer = this.lastTouch;
49566 var node = this.selectionHandler.getNodeAt(pointer);
49567
49568 if (node !== undefined) {
49569 if (node.isCluster === true) {
49570 alert(this.options.locales[this.options.locale]['createEdgeError'] || this.options.locales['en']['createEdgeError']);
49571 } else {
49572 // create a node the temporary line can look at
49573 var targetNode = this._getNewTargetNode(node.x, node.y);
49574
49575 this.body.nodes[targetNode.id] = targetNode;
49576 this.body.nodeIndices.push(targetNode.id); // create a temporary edge
49577
49578 var connectionEdge = this.body.functions.createEdge({
49579 id: 'connectionEdge' + uuid4(),
49580 from: node.id,
49581 to: targetNode.id,
49582 physics: false,
49583 smooth: {
49584 enabled: true,
49585 type: 'continuous',
49586 roundness: 0.5
49587 }
49588 });
49589 this.body.edges[connectionEdge.id] = connectionEdge;
49590 this.body.edgeIndices.push(connectionEdge.id);
49591 this.temporaryIds.nodes.push(targetNode.id);
49592 this.temporaryIds.edges.push(connectionEdge.id);
49593 }
49594 }
49595
49596 this.touchTime = new Date().valueOf();
49597 }
49598 }
49599 /**
49600 *
49601 * @param {Event} event
49602 * @private
49603 */
49604
49605 }, {
49606 key: "_dragControlNode",
49607 value: function _dragControlNode(event) {
49608 var pointer = this.body.functions.getPointer(event.center);
49609
49610 var pointerObj = this.selectionHandler._pointerToPositionObject(pointer); // remember the edge id
49611
49612
49613 var connectFromId = undefined;
49614
49615 if (this.temporaryIds.edges[0] !== undefined) {
49616 connectFromId = this.body.edges[this.temporaryIds.edges[0]].fromId;
49617 } // get the overlapping node but NOT the temporary node;
49618
49619
49620 var overlappingNodeIds = this.selectionHandler._getAllNodesOverlappingWith(pointerObj);
49621
49622 var node = undefined;
49623
49624 for (var i = overlappingNodeIds.length - 1; i >= 0; i--) {
49625 // if the node id is NOT a temporary node, accept the node.
49626 if (this.temporaryIds.nodes.indexOf(overlappingNodeIds[i]) === -1) {
49627 node = this.body.nodes[overlappingNodeIds[i]];
49628 break;
49629 }
49630 }
49631
49632 event.controlEdge = {
49633 from: connectFromId,
49634 to: node ? node.id : undefined
49635 };
49636
49637 this.selectionHandler._generateClickEvent('controlNodeDragging', event, pointer);
49638
49639 if (this.temporaryIds.nodes[0] !== undefined) {
49640 var targetNode = this.body.nodes[this.temporaryIds.nodes[0]]; // there is only one temp node in the add edge mode.
49641
49642 targetNode.x = this.canvas._XconvertDOMtoCanvas(pointer.x);
49643 targetNode.y = this.canvas._YconvertDOMtoCanvas(pointer.y);
49644 this.body.emitter.emit('_redraw');
49645 } else {
49646 this.interactionHandler.onDrag(event);
49647 }
49648 }
49649 /**
49650 * Connect the new edge to the target if one exists, otherwise remove temp line
49651 * @param {Event} event The event
49652 * @private
49653 */
49654
49655 }, {
49656 key: "_finishConnect",
49657 value: function _finishConnect(event) {
49658 var pointer = this.body.functions.getPointer(event.center);
49659
49660 var pointerObj = this.selectionHandler._pointerToPositionObject(pointer); // remember the edge id
49661
49662
49663 var connectFromId = undefined;
49664
49665 if (this.temporaryIds.edges[0] !== undefined) {
49666 connectFromId = this.body.edges[this.temporaryIds.edges[0]].fromId;
49667 } // get the overlapping node but NOT the temporary node;
49668
49669
49670 var overlappingNodeIds = this.selectionHandler._getAllNodesOverlappingWith(pointerObj);
49671
49672 var node = undefined;
49673
49674 for (var i = overlappingNodeIds.length - 1; i >= 0; i--) {
49675 // if the node id is NOT a temporary node, accept the node.
49676 if (this.temporaryIds.nodes.indexOf(overlappingNodeIds[i]) === -1) {
49677 node = this.body.nodes[overlappingNodeIds[i]];
49678 break;
49679 }
49680 } // clean temporary nodes and edges.
49681
49682
49683 this._cleanupTemporaryNodesAndEdges(); // perform the connection
49684
49685
49686 if (node !== undefined) {
49687 if (node.isCluster === true) {
49688 alert(this.options.locales[this.options.locale]['createEdgeError'] || this.options.locales['en']['createEdgeError']);
49689 } else {
49690 if (this.body.nodes[connectFromId] !== undefined && this.body.nodes[node.id] !== undefined) {
49691 this._performAddEdge(connectFromId, node.id);
49692 }
49693 }
49694 }
49695
49696 event.controlEdge = {
49697 from: connectFromId,
49698 to: node ? node.id : undefined
49699 };
49700
49701 this.selectionHandler._generateClickEvent('controlNodeDragEnd', event, pointer); // No need to do _generateclickevent('dragEnd') here, the regular dragEnd event fires.
49702
49703
49704 this.body.emitter.emit('_redraw');
49705 }
49706 /**
49707 *
49708 * @param {Event} event
49709 * @private
49710 */
49711
49712 }, {
49713 key: "_dragStartEdge",
49714 value: function _dragStartEdge(event) {
49715 var pointer = this.lastTouch;
49716
49717 this.selectionHandler._generateClickEvent('dragStart', event, pointer, undefined, true);
49718 } // --------------------------------------- END OF ADD EDGE FUNCTIONS -------------------------------------//
49719 // ------------------------------ Performing all the actual data manipulation ------------------------//
49720
49721 /**
49722 * Adds a node on the specified location
49723 *
49724 * @param {Object} clickData
49725 * @private
49726 */
49727
49728 }, {
49729 key: "_performAddNode",
49730 value: function _performAddNode(clickData) {
49731 var _this4 = this;
49732
49733 var defaultData = {
49734 id: uuid4(),
49735 x: clickData.pointer.canvas.x,
49736 y: clickData.pointer.canvas.y,
49737 label: 'new'
49738 };
49739
49740 if (typeof this.options.addNode === 'function') {
49741 if (this.options.addNode.length === 2) {
49742 this.options.addNode(defaultData, function (finalizedData) {
49743 if (finalizedData !== null && finalizedData !== undefined && _this4.inMode === 'addNode') {
49744 // if for whatever reason the mode has changes (due to dataset change) disregard the callback
49745 _this4.body.data.nodes.getDataSet().add(finalizedData);
49746 }
49747
49748 _this4.showManipulatorToolbar();
49749 });
49750 } else {
49751 this.showManipulatorToolbar();
49752 throw new Error('The function for add does not support two arguments (data,callback)');
49753 }
49754 } else {
49755 this.body.data.nodes.getDataSet().add(defaultData);
49756 this.showManipulatorToolbar();
49757 }
49758 }
49759 /**
49760 * connect two nodes with a new edge.
49761 *
49762 * @param {Node.id} sourceNodeId
49763 * @param {Node.id} targetNodeId
49764 * @private
49765 */
49766
49767 }, {
49768 key: "_performAddEdge",
49769 value: function _performAddEdge(sourceNodeId, targetNodeId) {
49770 var _this5 = this;
49771
49772 var defaultData = {
49773 from: sourceNodeId,
49774 to: targetNodeId
49775 };
49776
49777 if (typeof this.options.addEdge === 'function') {
49778 if (this.options.addEdge.length === 2) {
49779 this.options.addEdge(defaultData, function (finalizedData) {
49780 if (finalizedData !== null && finalizedData !== undefined && _this5.inMode === 'addEdge') {
49781 // if for whatever reason the mode has changes (due to dataset change) disregard the callback
49782 _this5.body.data.edges.getDataSet().add(finalizedData);
49783
49784 _this5.selectionHandler.unselectAll();
49785
49786 _this5.showManipulatorToolbar();
49787 }
49788 });
49789 } else {
49790 throw new Error('The function for connect does not support two arguments (data,callback)');
49791 }
49792 } else {
49793 this.body.data.edges.getDataSet().add(defaultData);
49794 this.selectionHandler.unselectAll();
49795 this.showManipulatorToolbar();
49796 }
49797 }
49798 /**
49799 * connect two nodes with a new edge.
49800 *
49801 * @param {Node.id} sourceNodeId
49802 * @param {Node.id} targetNodeId
49803 * @private
49804 */
49805
49806 }, {
49807 key: "_performEditEdge",
49808 value: function _performEditEdge(sourceNodeId, targetNodeId) {
49809 var _this6 = this;
49810
49811 var defaultData = {
49812 id: this.edgeBeingEditedId,
49813 from: sourceNodeId,
49814 to: targetNodeId,
49815 label: this.body.data.edges._data[this.edgeBeingEditedId].label
49816 };
49817 var eeFunct = this.options.editEdge;
49818
49819 if (_typeof$1(eeFunct) === 'object') {
49820 eeFunct = eeFunct.editWithoutDrag;
49821 }
49822
49823 if (typeof eeFunct === 'function') {
49824 if (eeFunct.length === 2) {
49825 eeFunct(defaultData, function (finalizedData) {
49826 if (finalizedData === null || finalizedData === undefined || _this6.inMode !== 'editEdge') {
49827 // if for whatever reason the mode has changes (due to dataset change) disregard the callback) {
49828 _this6.body.edges[defaultData.id].updateEdgeType();
49829
49830 _this6.body.emitter.emit('_redraw');
49831
49832 _this6.showManipulatorToolbar();
49833 } else {
49834 _this6.body.data.edges.getDataSet().update(finalizedData);
49835
49836 _this6.selectionHandler.unselectAll();
49837
49838 _this6.showManipulatorToolbar();
49839 }
49840 });
49841 } else {
49842 throw new Error('The function for edit does not support two arguments (data, callback)');
49843 }
49844 } else {
49845 this.body.data.edges.getDataSet().update(defaultData);
49846 this.selectionHandler.unselectAll();
49847 this.showManipulatorToolbar();
49848 }
49849 }
49850 }]);
49851
49852 return ManipulationSystem;
49853}();
49854
49855var htmlColors = {
49856 black: '#000000',
49857 navy: '#000080',
49858 darkblue: '#00008B',
49859 mediumblue: '#0000CD',
49860 blue: '#0000FF',
49861 darkgreen: '#006400',
49862 green: '#008000',
49863 teal: '#008080',
49864 darkcyan: '#008B8B',
49865 deepskyblue: '#00BFFF',
49866 darkturquoise: '#00CED1',
49867 mediumspringgreen: '#00FA9A',
49868 lime: '#00FF00',
49869 springgreen: '#00FF7F',
49870 aqua: '#00FFFF',
49871 cyan: '#00FFFF',
49872 midnightblue: '#191970',
49873 dodgerblue: '#1E90FF',
49874 lightseagreen: '#20B2AA',
49875 forestgreen: '#228B22',
49876 seagreen: '#2E8B57',
49877 darkslategray: '#2F4F4F',
49878 limegreen: '#32CD32',
49879 mediumseagreen: '#3CB371',
49880 turquoise: '#40E0D0',
49881 royalblue: '#4169E1',
49882 steelblue: '#4682B4',
49883 darkslateblue: '#483D8B',
49884 mediumturquoise: '#48D1CC',
49885 indigo: '#4B0082',
49886 darkolivegreen: '#556B2F',
49887 cadetblue: '#5F9EA0',
49888 cornflowerblue: '#6495ED',
49889 mediumaquamarine: '#66CDAA',
49890 dimgray: '#696969',
49891 slateblue: '#6A5ACD',
49892 olivedrab: '#6B8E23',
49893 slategray: '#708090',
49894 lightslategray: '#778899',
49895 mediumslateblue: '#7B68EE',
49896 lawngreen: '#7CFC00',
49897 chartreuse: '#7FFF00',
49898 aquamarine: '#7FFFD4',
49899 maroon: '#800000',
49900 purple: '#800080',
49901 olive: '#808000',
49902 gray: '#808080',
49903 skyblue: '#87CEEB',
49904 lightskyblue: '#87CEFA',
49905 blueviolet: '#8A2BE2',
49906 darkred: '#8B0000',
49907 darkmagenta: '#8B008B',
49908 saddlebrown: '#8B4513',
49909 darkseagreen: '#8FBC8F',
49910 lightgreen: '#90EE90',
49911 mediumpurple: '#9370D8',
49912 darkviolet: '#9400D3',
49913 palegreen: '#98FB98',
49914 darkorchid: '#9932CC',
49915 yellowgreen: '#9ACD32',
49916 sienna: '#A0522D',
49917 brown: '#A52A2A',
49918 darkgray: '#A9A9A9',
49919 lightblue: '#ADD8E6',
49920 greenyellow: '#ADFF2F',
49921 paleturquoise: '#AFEEEE',
49922 lightsteelblue: '#B0C4DE',
49923 powderblue: '#B0E0E6',
49924 firebrick: '#B22222',
49925 darkgoldenrod: '#B8860B',
49926 mediumorchid: '#BA55D3',
49927 rosybrown: '#BC8F8F',
49928 darkkhaki: '#BDB76B',
49929 silver: '#C0C0C0',
49930 mediumvioletred: '#C71585',
49931 indianred: '#CD5C5C',
49932 peru: '#CD853F',
49933 chocolate: '#D2691E',
49934 tan: '#D2B48C',
49935 lightgrey: '#D3D3D3',
49936 palevioletred: '#D87093',
49937 thistle: '#D8BFD8',
49938 orchid: '#DA70D6',
49939 goldenrod: '#DAA520',
49940 crimson: '#DC143C',
49941 gainsboro: '#DCDCDC',
49942 plum: '#DDA0DD',
49943 burlywood: '#DEB887',
49944 lightcyan: '#E0FFFF',
49945 lavender: '#E6E6FA',
49946 darksalmon: '#E9967A',
49947 violet: '#EE82EE',
49948 palegoldenrod: '#EEE8AA',
49949 lightcoral: '#F08080',
49950 khaki: '#F0E68C',
49951 aliceblue: '#F0F8FF',
49952 honeydew: '#F0FFF0',
49953 azure: '#F0FFFF',
49954 sandybrown: '#F4A460',
49955 wheat: '#F5DEB3',
49956 beige: '#F5F5DC',
49957 whitesmoke: '#F5F5F5',
49958 mintcream: '#F5FFFA',
49959 ghostwhite: '#F8F8FF',
49960 salmon: '#FA8072',
49961 antiquewhite: '#FAEBD7',
49962 linen: '#FAF0E6',
49963 lightgoldenrodyellow: '#FAFAD2',
49964 oldlace: '#FDF5E6',
49965 red: '#FF0000',
49966 fuchsia: '#FF00FF',
49967 magenta: '#FF00FF',
49968 deeppink: '#FF1493',
49969 orangered: '#FF4500',
49970 tomato: '#FF6347',
49971 hotpink: '#FF69B4',
49972 coral: '#FF7F50',
49973 darkorange: '#FF8C00',
49974 lightsalmon: '#FFA07A',
49975 orange: '#FFA500',
49976 lightpink: '#FFB6C1',
49977 pink: '#FFC0CB',
49978 gold: '#FFD700',
49979 peachpuff: '#FFDAB9',
49980 navajowhite: '#FFDEAD',
49981 moccasin: '#FFE4B5',
49982 bisque: '#FFE4C4',
49983 mistyrose: '#FFE4E1',
49984 blanchedalmond: '#FFEBCD',
49985 papayawhip: '#FFEFD5',
49986 lavenderblush: '#FFF0F5',
49987 seashell: '#FFF5EE',
49988 cornsilk: '#FFF8DC',
49989 lemonchiffon: '#FFFACD',
49990 floralwhite: '#FFFAF0',
49991 snow: '#FFFAFA',
49992 yellow: '#FFFF00',
49993 lightyellow: '#FFFFE0',
49994 ivory: '#FFFFF0',
49995 white: '#FFFFFF'
49996};
49997/**
49998 * @param {number} [pixelRatio=1]
49999 */
50000
50001var ColorPicker =
50002/*#__PURE__*/
50003function () {
50004 /**
50005 * @param {number} [pixelRatio=1]
50006 */
50007 function ColorPicker() {
50008 var pixelRatio = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
50009
50010 _classCallCheck(this, ColorPicker);
50011
50012 this.pixelRatio = pixelRatio;
50013 this.generated = false;
50014 this.centerCoordinates = {
50015 x: 289 / 2,
50016 y: 289 / 2
50017 };
50018 this.r = 289 * 0.49;
50019 this.color = {
50020 r: 255,
50021 g: 255,
50022 b: 255,
50023 a: 1.0
50024 };
50025 this.hueCircle = undefined;
50026 this.initialColor = {
50027 r: 255,
50028 g: 255,
50029 b: 255,
50030 a: 1.0
50031 };
50032 this.previousColor = undefined;
50033 this.applied = false; // bound by
50034
50035 this.updateCallback = function () {};
50036
50037 this.closeCallback = function () {}; // create all DOM elements
50038
50039
50040 this._create();
50041 }
50042 /**
50043 * this inserts the colorPicker into a div from the DOM
50044 * @param {Element} container
50045 */
50046
50047
50048 _createClass(ColorPicker, [{
50049 key: "insertTo",
50050 value: function insertTo(container) {
50051 if (this.hammer !== undefined) {
50052 this.hammer.destroy();
50053 this.hammer = undefined;
50054 }
50055
50056 this.container = container;
50057 this.container.appendChild(this.frame);
50058
50059 this._bindHammer();
50060
50061 this._setSize();
50062 }
50063 /**
50064 * the callback is executed on apply and save. Bind it to the application
50065 * @param {function} callback
50066 */
50067
50068 }, {
50069 key: "setUpdateCallback",
50070 value: function setUpdateCallback(callback) {
50071 if (typeof callback === 'function') {
50072 this.updateCallback = callback;
50073 } else {
50074 throw new Error("Function attempted to set as colorPicker update callback is not a function.");
50075 }
50076 }
50077 /**
50078 * the callback is executed on apply and save. Bind it to the application
50079 * @param {function} callback
50080 */
50081
50082 }, {
50083 key: "setCloseCallback",
50084 value: function setCloseCallback(callback) {
50085 if (typeof callback === 'function') {
50086 this.closeCallback = callback;
50087 } else {
50088 throw new Error("Function attempted to set as colorPicker closing callback is not a function.");
50089 }
50090 }
50091 /**
50092 *
50093 * @param {string} color
50094 * @returns {String}
50095 * @private
50096 */
50097
50098 }, {
50099 key: "_isColorString",
50100 value: function _isColorString(color) {
50101 if (typeof color === 'string') {
50102 return htmlColors[color];
50103 }
50104 }
50105 /**
50106 * Set the color of the colorPicker
50107 * Supported formats:
50108 * 'red' --> HTML color string
50109 * '#ffffff' --> hex string
50110 * 'rgb(255,255,255)' --> rgb string
50111 * 'rgba(255,255,255,1.0)' --> rgba string
50112 * {r:255,g:255,b:255} --> rgb object
50113 * {r:255,g:255,b:255,a:1.0} --> rgba object
50114 * @param {string|Object} color
50115 * @param {boolean} [setInitial=true]
50116 */
50117
50118 }, {
50119 key: "setColor",
50120 value: function setColor(color) {
50121 var setInitial = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
50122
50123 if (color === 'none') {
50124 return;
50125 }
50126
50127 var rgba; // if a html color shorthand is used, convert to hex
50128
50129 var htmlColor = this._isColorString(color);
50130
50131 if (htmlColor !== undefined) {
50132 color = htmlColor;
50133 } // check format
50134
50135
50136 if (isString(color) === true) {
50137 if (isValidRGB(color) === true) {
50138 var rgbaArray = color.substr(4).substr(0, color.length - 5).split(',');
50139 rgba = {
50140 r: rgbaArray[0],
50141 g: rgbaArray[1],
50142 b: rgbaArray[2],
50143 a: 1.0
50144 };
50145 } else if (isValidRGBA(color) === true) {
50146 var _rgbaArray = color.substr(5).substr(0, color.length - 6).split(',');
50147
50148 rgba = {
50149 r: _rgbaArray[0],
50150 g: _rgbaArray[1],
50151 b: _rgbaArray[2],
50152 a: _rgbaArray[3]
50153 };
50154 } else if (isValidHex(color) === true) {
50155 var rgbObj = hexToRGB(color);
50156 rgba = {
50157 r: rgbObj.r,
50158 g: rgbObj.g,
50159 b: rgbObj.b,
50160 a: 1.0
50161 };
50162 }
50163 } else {
50164 if (color instanceof Object) {
50165 if (color.r !== undefined && color.g !== undefined && color.b !== undefined) {
50166 var alpha = color.a !== undefined ? color.a : '1.0';
50167 rgba = {
50168 r: color.r,
50169 g: color.g,
50170 b: color.b,
50171 a: alpha
50172 };
50173 }
50174 }
50175 } // set color
50176
50177
50178 if (rgba === undefined) {
50179 throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: " + JSON.stringify(color));
50180 } else {
50181 this._setColor(rgba, setInitial);
50182 }
50183 }
50184 /**
50185 * this shows the color picker.
50186 * The hue circle is constructed once and stored.
50187 */
50188
50189 }, {
50190 key: "show",
50191 value: function show() {
50192 if (this.closeCallback !== undefined) {
50193 this.closeCallback();
50194 this.closeCallback = undefined;
50195 }
50196
50197 this.applied = false;
50198 this.frame.style.display = 'block';
50199
50200 this._generateHueCircle();
50201 } // ------------------------------------------ PRIVATE ----------------------------- //
50202
50203 /**
50204 * Hide the picker. Is called by the cancel button.
50205 * Optional boolean to store the previous color for easy access later on.
50206 * @param {boolean} [storePrevious=true]
50207 * @private
50208 */
50209
50210 }, {
50211 key: "_hide",
50212 value: function _hide() {
50213 var _this = this;
50214
50215 var storePrevious = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
50216
50217 // store the previous color for next time;
50218 if (storePrevious === true) {
50219 this.previousColor = extend({}, this.color);
50220 }
50221
50222 if (this.applied === true) {
50223 this.updateCallback(this.initialColor);
50224 }
50225
50226 this.frame.style.display = 'none'; // call the closing callback, restoring the onclick method.
50227 // this is in a setTimeout because it will trigger the show again before the click is done.
50228
50229 setTimeout(function () {
50230 if (_this.closeCallback !== undefined) {
50231 _this.closeCallback();
50232
50233 _this.closeCallback = undefined;
50234 }
50235 }, 0);
50236 }
50237 /**
50238 * bound to the save button. Saves and hides.
50239 * @private
50240 */
50241
50242 }, {
50243 key: "_save",
50244 value: function _save() {
50245 this.updateCallback(this.color);
50246 this.applied = false;
50247
50248 this._hide();
50249 }
50250 /**
50251 * Bound to apply button. Saves but does not close. Is undone by the cancel button.
50252 * @private
50253 */
50254
50255 }, {
50256 key: "_apply",
50257 value: function _apply() {
50258 this.applied = true;
50259 this.updateCallback(this.color);
50260
50261 this._updatePicker(this.color);
50262 }
50263 /**
50264 * load the color from the previous session.
50265 * @private
50266 */
50267
50268 }, {
50269 key: "_loadLast",
50270 value: function _loadLast() {
50271 if (this.previousColor !== undefined) {
50272 this.setColor(this.previousColor, false);
50273 } else {
50274 alert("There is no last color to load...");
50275 }
50276 }
50277 /**
50278 * set the color, place the picker
50279 * @param {Object} rgba
50280 * @param {boolean} [setInitial=true]
50281 * @private
50282 */
50283
50284 }, {
50285 key: "_setColor",
50286 value: function _setColor(rgba) {
50287 var setInitial = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
50288
50289 // store the initial color
50290 if (setInitial === true) {
50291 this.initialColor = extend({}, rgba);
50292 }
50293
50294 this.color = rgba;
50295 var hsv = RGBToHSV(rgba.r, rgba.g, rgba.b);
50296 var angleConvert = 2 * Math.PI;
50297 var radius = this.r * hsv.s;
50298 var x = this.centerCoordinates.x + radius * Math.sin(angleConvert * hsv.h);
50299 var y = this.centerCoordinates.y + radius * Math.cos(angleConvert * hsv.h);
50300 this.colorPickerSelector.style.left = x - 0.5 * this.colorPickerSelector.clientWidth + 'px';
50301 this.colorPickerSelector.style.top = y - 0.5 * this.colorPickerSelector.clientHeight + 'px';
50302
50303 this._updatePicker(rgba);
50304 }
50305 /**
50306 * bound to opacity control
50307 * @param {number} value
50308 * @private
50309 */
50310
50311 }, {
50312 key: "_setOpacity",
50313 value: function _setOpacity(value) {
50314 this.color.a = value / 100;
50315
50316 this._updatePicker(this.color);
50317 }
50318 /**
50319 * bound to brightness control
50320 * @param {number} value
50321 * @private
50322 */
50323
50324 }, {
50325 key: "_setBrightness",
50326 value: function _setBrightness(value) {
50327 var hsv = RGBToHSV(this.color.r, this.color.g, this.color.b);
50328 hsv.v = value / 100;
50329 var rgba = HSVToRGB(hsv.h, hsv.s, hsv.v);
50330 rgba['a'] = this.color.a;
50331 this.color = rgba;
50332
50333 this._updatePicker();
50334 }
50335 /**
50336 * update the color picker. A black circle overlays the hue circle to mimic the brightness decreasing.
50337 * @param {Object} rgba
50338 * @private
50339 */
50340
50341 }, {
50342 key: "_updatePicker",
50343 value: function _updatePicker() {
50344 var rgba = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.color;
50345 var hsv = RGBToHSV(rgba.r, rgba.g, rgba.b);
50346 var ctx = this.colorPickerCanvas.getContext('2d');
50347
50348 if (this.pixelRation === undefined) {
50349 this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1);
50350 }
50351
50352 ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); // clear the canvas
50353
50354 var w = this.colorPickerCanvas.clientWidth;
50355 var h = this.colorPickerCanvas.clientHeight;
50356 ctx.clearRect(0, 0, w, h);
50357 ctx.putImageData(this.hueCircle, 0, 0);
50358 ctx.fillStyle = 'rgba(0,0,0,' + (1 - hsv.v) + ')';
50359 ctx.circle(this.centerCoordinates.x, this.centerCoordinates.y, this.r);
50360 ctx.fill();
50361 this.brightnessRange.value = 100 * hsv.v;
50362 this.opacityRange.value = 100 * rgba.a;
50363 this.initialColorDiv.style.backgroundColor = 'rgba(' + this.initialColor.r + ',' + this.initialColor.g + ',' + this.initialColor.b + ',' + this.initialColor.a + ')';
50364 this.newColorDiv.style.backgroundColor = 'rgba(' + this.color.r + ',' + this.color.g + ',' + this.color.b + ',' + this.color.a + ')';
50365 }
50366 /**
50367 * used by create to set the size of the canvas.
50368 * @private
50369 */
50370
50371 }, {
50372 key: "_setSize",
50373 value: function _setSize() {
50374 this.colorPickerCanvas.style.width = '100%';
50375 this.colorPickerCanvas.style.height = '100%';
50376 this.colorPickerCanvas.width = 289 * this.pixelRatio;
50377 this.colorPickerCanvas.height = 289 * this.pixelRatio;
50378 }
50379 /**
50380 * create all dom elements
50381 * TODO: cleanup, lots of similar dom elements
50382 * @private
50383 */
50384
50385 }, {
50386 key: "_create",
50387 value: function _create() {
50388 this.frame = document.createElement('div');
50389 this.frame.className = 'vis-color-picker';
50390 this.colorPickerDiv = document.createElement('div');
50391 this.colorPickerSelector = document.createElement('div');
50392 this.colorPickerSelector.className = 'vis-selector';
50393 this.colorPickerDiv.appendChild(this.colorPickerSelector);
50394 this.colorPickerCanvas = document.createElement('canvas');
50395 this.colorPickerDiv.appendChild(this.colorPickerCanvas);
50396
50397 if (!this.colorPickerCanvas.getContext) {
50398 var noCanvas = document.createElement('DIV');
50399 noCanvas.style.color = 'red';
50400 noCanvas.style.fontWeight = 'bold';
50401 noCanvas.style.padding = '10px';
50402 noCanvas.innerHTML = 'Error: your browser does not support HTML canvas';
50403 this.colorPickerCanvas.appendChild(noCanvas);
50404 } else {
50405 var ctx = this.colorPickerCanvas.getContext("2d");
50406 this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1);
50407 this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0);
50408 }
50409
50410 this.colorPickerDiv.className = 'vis-color';
50411 this.opacityDiv = document.createElement('div');
50412 this.opacityDiv.className = 'vis-opacity';
50413 this.brightnessDiv = document.createElement('div');
50414 this.brightnessDiv.className = 'vis-brightness';
50415 this.arrowDiv = document.createElement('div');
50416 this.arrowDiv.className = 'vis-arrow';
50417 this.opacityRange = document.createElement('input');
50418
50419 try {
50420 this.opacityRange.type = 'range'; // Not supported on IE9
50421
50422 this.opacityRange.min = '0';
50423 this.opacityRange.max = '100';
50424 } // TODO: Add some error handling and remove this lint exception
50425 catch (err) {} // eslint-disable-line no-empty
50426
50427
50428 this.opacityRange.value = '100';
50429 this.opacityRange.className = 'vis-range';
50430 this.brightnessRange = document.createElement('input');
50431
50432 try {
50433 this.brightnessRange.type = 'range'; // Not supported on IE9
50434
50435 this.brightnessRange.min = '0';
50436 this.brightnessRange.max = '100';
50437 } // TODO: Add some error handling and remove this lint exception
50438 catch (err) {} // eslint-disable-line no-empty
50439
50440
50441 this.brightnessRange.value = '100';
50442 this.brightnessRange.className = 'vis-range';
50443 this.opacityDiv.appendChild(this.opacityRange);
50444 this.brightnessDiv.appendChild(this.brightnessRange);
50445 var me = this;
50446
50447 this.opacityRange.onchange = function () {
50448 me._setOpacity(this.value);
50449 };
50450
50451 this.opacityRange.oninput = function () {
50452 me._setOpacity(this.value);
50453 };
50454
50455 this.brightnessRange.onchange = function () {
50456 me._setBrightness(this.value);
50457 };
50458
50459 this.brightnessRange.oninput = function () {
50460 me._setBrightness(this.value);
50461 };
50462
50463 this.brightnessLabel = document.createElement("div");
50464 this.brightnessLabel.className = "vis-label vis-brightness";
50465 this.brightnessLabel.innerHTML = 'brightness:';
50466 this.opacityLabel = document.createElement("div");
50467 this.opacityLabel.className = "vis-label vis-opacity";
50468 this.opacityLabel.innerHTML = 'opacity:';
50469 this.newColorDiv = document.createElement("div");
50470 this.newColorDiv.className = "vis-new-color";
50471 this.newColorDiv.innerHTML = 'new';
50472 this.initialColorDiv = document.createElement("div");
50473 this.initialColorDiv.className = "vis-initial-color";
50474 this.initialColorDiv.innerHTML = 'initial';
50475 this.cancelButton = document.createElement("div");
50476 this.cancelButton.className = "vis-button vis-cancel";
50477 this.cancelButton.innerHTML = 'cancel';
50478 this.cancelButton.onclick = this._hide.bind(this, false);
50479 this.applyButton = document.createElement("div");
50480 this.applyButton.className = "vis-button vis-apply";
50481 this.applyButton.innerHTML = 'apply';
50482 this.applyButton.onclick = this._apply.bind(this);
50483 this.saveButton = document.createElement("div");
50484 this.saveButton.className = "vis-button vis-save";
50485 this.saveButton.innerHTML = 'save';
50486 this.saveButton.onclick = this._save.bind(this);
50487 this.loadButton = document.createElement("div");
50488 this.loadButton.className = "vis-button vis-load";
50489 this.loadButton.innerHTML = 'load last';
50490 this.loadButton.onclick = this._loadLast.bind(this);
50491 this.frame.appendChild(this.colorPickerDiv);
50492 this.frame.appendChild(this.arrowDiv);
50493 this.frame.appendChild(this.brightnessLabel);
50494 this.frame.appendChild(this.brightnessDiv);
50495 this.frame.appendChild(this.opacityLabel);
50496 this.frame.appendChild(this.opacityDiv);
50497 this.frame.appendChild(this.newColorDiv);
50498 this.frame.appendChild(this.initialColorDiv);
50499 this.frame.appendChild(this.cancelButton);
50500 this.frame.appendChild(this.applyButton);
50501 this.frame.appendChild(this.saveButton);
50502 this.frame.appendChild(this.loadButton);
50503 }
50504 /**
50505 * bind hammer to the color picker
50506 * @private
50507 */
50508
50509 }, {
50510 key: "_bindHammer",
50511 value: function _bindHammer() {
50512 var _this2 = this;
50513
50514 this.drag = {};
50515 this.pinch = {};
50516 this.hammer = new hammer(this.colorPickerCanvas);
50517 this.hammer.get('pinch').set({
50518 enable: true
50519 });
50520 hammerUtil.onTouch(this.hammer, function (event) {
50521 _this2._moveSelector(event);
50522 });
50523 this.hammer.on('tap', function (event) {
50524 _this2._moveSelector(event);
50525 });
50526 this.hammer.on('panstart', function (event) {
50527 _this2._moveSelector(event);
50528 });
50529 this.hammer.on('panmove', function (event) {
50530 _this2._moveSelector(event);
50531 });
50532 this.hammer.on('panend', function (event) {
50533 _this2._moveSelector(event);
50534 });
50535 }
50536 /**
50537 * generate the hue circle. This is relatively heavy (200ms) and is done only once on the first time it is shown.
50538 * @private
50539 */
50540
50541 }, {
50542 key: "_generateHueCircle",
50543 value: function _generateHueCircle() {
50544 if (this.generated === false) {
50545 var ctx = this.colorPickerCanvas.getContext('2d');
50546
50547 if (this.pixelRation === undefined) {
50548 this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1);
50549 }
50550
50551 ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); // clear the canvas
50552
50553 var w = this.colorPickerCanvas.clientWidth;
50554 var h = this.colorPickerCanvas.clientHeight;
50555 ctx.clearRect(0, 0, w, h); // draw hue circle
50556
50557 var x, y, hue, sat;
50558 this.centerCoordinates = {
50559 x: w * 0.5,
50560 y: h * 0.5
50561 };
50562 this.r = 0.49 * w;
50563 var angleConvert = 2 * Math.PI / 360;
50564 var hfac = 1 / 360;
50565 var sfac = 1 / this.r;
50566 var rgb;
50567
50568 for (hue = 0; hue < 360; hue++) {
50569 for (sat = 0; sat < this.r; sat++) {
50570 x = this.centerCoordinates.x + sat * Math.sin(angleConvert * hue);
50571 y = this.centerCoordinates.y + sat * Math.cos(angleConvert * hue);
50572 rgb = HSVToRGB(hue * hfac, sat * sfac, 1);
50573 ctx.fillStyle = 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')';
50574 ctx.fillRect(x - 0.5, y - 0.5, 2, 2);
50575 }
50576 }
50577
50578 ctx.strokeStyle = 'rgba(0,0,0,1)';
50579 ctx.circle(this.centerCoordinates.x, this.centerCoordinates.y, this.r);
50580 ctx.stroke();
50581 this.hueCircle = ctx.getImageData(0, 0, w, h);
50582 }
50583
50584 this.generated = true;
50585 }
50586 /**
50587 * move the selector. This is called by hammer functions.
50588 *
50589 * @param {Event} event The event
50590 * @private
50591 */
50592
50593 }, {
50594 key: "_moveSelector",
50595 value: function _moveSelector(event) {
50596 var rect = this.colorPickerDiv.getBoundingClientRect();
50597 var left = event.center.x - rect.left;
50598 var top = event.center.y - rect.top;
50599 var centerY = 0.5 * this.colorPickerDiv.clientHeight;
50600 var centerX = 0.5 * this.colorPickerDiv.clientWidth;
50601 var x = left - centerX;
50602 var y = top - centerY;
50603 var angle = Math.atan2(x, y);
50604 var radius = 0.98 * Math.min(Math.sqrt(x * x + y * y), centerX);
50605 var newTop = Math.cos(angle) * radius + centerY;
50606 var newLeft = Math.sin(angle) * radius + centerX;
50607 this.colorPickerSelector.style.top = newTop - 0.5 * this.colorPickerSelector.clientHeight + 'px';
50608 this.colorPickerSelector.style.left = newLeft - 0.5 * this.colorPickerSelector.clientWidth + 'px'; // set color
50609
50610 var h = angle / (2 * Math.PI);
50611 h = h < 0 ? h + 1 : h;
50612 var s = radius / this.r;
50613 var hsv = RGBToHSV(this.color.r, this.color.g, this.color.b);
50614 hsv.h = h;
50615 hsv.s = s;
50616 var rgba = HSVToRGB(hsv.h, hsv.s, hsv.v);
50617 rgba['a'] = this.color.a;
50618 this.color = rgba; // update previews
50619
50620 this.initialColorDiv.style.backgroundColor = 'rgba(' + this.initialColor.r + ',' + this.initialColor.g + ',' + this.initialColor.b + ',' + this.initialColor.a + ')';
50621 this.newColorDiv.style.backgroundColor = 'rgba(' + this.color.r + ',' + this.color.g + ',' + this.color.b + ',' + this.color.a + ')';
50622 }
50623 }]);
50624
50625 return ColorPicker;
50626}();
50627
50628/**
50629 * The way this works is for all properties of this.possible options, you can supply the property name in any form to list the options.
50630 * Boolean options are recognised as Boolean
50631 * Number options should be written as array: [default value, min value, max value, stepsize]
50632 * Colors should be written as array: ['color', '#ffffff']
50633 * Strings with should be written as array: [option1, option2, option3, ..]
50634 *
50635 * The options are matched with their counterparts in each of the modules and the values used in the configuration are
50636 */
50637
50638var Configurator =
50639/*#__PURE__*/
50640function () {
50641 /**
50642 * @param {Object} parentModule | the location where parentModule.setOptions() can be called
50643 * @param {Object} defaultContainer | the default container of the module
50644 * @param {Object} configureOptions | the fully configured and predefined options set found in allOptions.js
50645 * @param {number} pixelRatio | canvas pixel ratio
50646 */
50647 function Configurator(parentModule, defaultContainer, configureOptions) {
50648 var pixelRatio = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
50649
50650 _classCallCheck(this, Configurator);
50651
50652 this.parent = parentModule;
50653 this.changedOptions = [];
50654 this.container = defaultContainer;
50655 this.allowCreation = false;
50656 this.options = {};
50657 this.initialized = false;
50658 this.popupCounter = 0;
50659 this.defaultOptions = {
50660 enabled: false,
50661 filter: true,
50662 container: undefined,
50663 showButton: true
50664 };
50665 extend(this.options, this.defaultOptions);
50666 this.configureOptions = configureOptions;
50667 this.moduleOptions = {};
50668 this.domElements = [];
50669 this.popupDiv = {};
50670 this.popupLimit = 5;
50671 this.popupHistory = {};
50672 this.colorPicker = new ColorPicker(pixelRatio);
50673 this.wrapper = undefined;
50674 }
50675 /**
50676 * refresh all options.
50677 * Because all modules parse their options by themselves, we just use their options. We copy them here.
50678 *
50679 * @param {Object} options
50680 */
50681
50682
50683 _createClass(Configurator, [{
50684 key: "setOptions",
50685 value: function setOptions(options) {
50686 if (options !== undefined) {
50687 // reset the popup history because the indices may have been changed.
50688 this.popupHistory = {};
50689
50690 this._removePopup();
50691
50692 var enabled = true;
50693
50694 if (typeof options === 'string') {
50695 this.options.filter = options;
50696 } else if (options instanceof Array) {
50697 this.options.filter = options.join();
50698 } else if (_typeof$1(options) === 'object') {
50699 if (options == null) {
50700 throw new TypeError('options cannot be null');
50701 }
50702
50703 if (options.container !== undefined) {
50704 this.options.container = options.container;
50705 }
50706
50707 if (options.filter !== undefined) {
50708 this.options.filter = options.filter;
50709 }
50710
50711 if (options.showButton !== undefined) {
50712 this.options.showButton = options.showButton;
50713 }
50714
50715 if (options.enabled !== undefined) {
50716 enabled = options.enabled;
50717 }
50718 } else if (typeof options === 'boolean') {
50719 this.options.filter = true;
50720 enabled = options;
50721 } else if (typeof options === 'function') {
50722 this.options.filter = options;
50723 enabled = true;
50724 }
50725
50726 if (this.options.filter === false) {
50727 enabled = false;
50728 }
50729
50730 this.options.enabled = enabled;
50731 }
50732
50733 this._clean();
50734 }
50735 /**
50736 *
50737 * @param {Object} moduleOptions
50738 */
50739
50740 }, {
50741 key: "setModuleOptions",
50742 value: function setModuleOptions(moduleOptions) {
50743 this.moduleOptions = moduleOptions;
50744
50745 if (this.options.enabled === true) {
50746 this._clean();
50747
50748 if (this.options.container !== undefined) {
50749 this.container = this.options.container;
50750 }
50751
50752 this._create();
50753 }
50754 }
50755 /**
50756 * Create all DOM elements
50757 * @private
50758 */
50759
50760 }, {
50761 key: "_create",
50762 value: function _create() {
50763 this._clean();
50764
50765 this.changedOptions = [];
50766 var filter = this.options.filter;
50767 var counter = 0;
50768 var show = false;
50769
50770 for (var option in this.configureOptions) {
50771 if (this.configureOptions.hasOwnProperty(option)) {
50772 this.allowCreation = false;
50773 show = false;
50774
50775 if (typeof filter === 'function') {
50776 show = filter(option, []);
50777 show = show || this._handleObject(this.configureOptions[option], [option], true);
50778 } else if (filter === true || filter.indexOf(option) !== -1) {
50779 show = true;
50780 }
50781
50782 if (show !== false) {
50783 this.allowCreation = true; // linebreak between categories
50784
50785 if (counter > 0) {
50786 this._makeItem([]);
50787 } // a header for the category
50788
50789
50790 this._makeHeader(option); // get the sub options
50791
50792
50793 this._handleObject(this.configureOptions[option], [option]);
50794 }
50795
50796 counter++;
50797 }
50798 }
50799
50800 this._makeButton();
50801
50802 this._push(); //~ this.colorPicker.insertTo(this.container);
50803
50804 }
50805 /**
50806 * draw all DOM elements on the screen
50807 * @private
50808 */
50809
50810 }, {
50811 key: "_push",
50812 value: function _push() {
50813 this.wrapper = document.createElement('div');
50814 this.wrapper.className = 'vis-configuration-wrapper';
50815 this.container.appendChild(this.wrapper);
50816
50817 for (var i = 0; i < this.domElements.length; i++) {
50818 this.wrapper.appendChild(this.domElements[i]);
50819 }
50820
50821 this._showPopupIfNeeded();
50822 }
50823 /**
50824 * delete all DOM elements
50825 * @private
50826 */
50827
50828 }, {
50829 key: "_clean",
50830 value: function _clean() {
50831 for (var i = 0; i < this.domElements.length; i++) {
50832 this.wrapper.removeChild(this.domElements[i]);
50833 }
50834
50835 if (this.wrapper !== undefined) {
50836 this.container.removeChild(this.wrapper);
50837 this.wrapper = undefined;
50838 }
50839
50840 this.domElements = [];
50841
50842 this._removePopup();
50843 }
50844 /**
50845 * get the value from the actualOptions if it exists
50846 * @param {array} path | where to look for the actual option
50847 * @returns {*}
50848 * @private
50849 */
50850
50851 }, {
50852 key: "_getValue",
50853 value: function _getValue(path) {
50854 var base = this.moduleOptions;
50855
50856 for (var i = 0; i < path.length; i++) {
50857 if (base[path[i]] !== undefined) {
50858 base = base[path[i]];
50859 } else {
50860 base = undefined;
50861 break;
50862 }
50863 }
50864
50865 return base;
50866 }
50867 /**
50868 * all option elements are wrapped in an item
50869 * @param {Array} path | where to look for the actual option
50870 * @param {Array.<Element>} domElements
50871 * @returns {number}
50872 * @private
50873 */
50874
50875 }, {
50876 key: "_makeItem",
50877 value: function _makeItem(path) {
50878 if (this.allowCreation === true) {
50879 var item = document.createElement('div');
50880 item.className = 'vis-configuration vis-config-item vis-config-s' + path.length;
50881
50882 for (var _len = arguments.length, domElements = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
50883 domElements[_key - 1] = arguments[_key];
50884 }
50885
50886 domElements.forEach(function (element) {
50887 item.appendChild(element);
50888 });
50889 this.domElements.push(item);
50890 return this.domElements.length;
50891 }
50892
50893 return 0;
50894 }
50895 /**
50896 * header for major subjects
50897 * @param {string} name
50898 * @private
50899 */
50900
50901 }, {
50902 key: "_makeHeader",
50903 value: function _makeHeader(name) {
50904 var div = document.createElement('div');
50905 div.className = 'vis-configuration vis-config-header';
50906 div.innerHTML = name;
50907
50908 this._makeItem([], div);
50909 }
50910 /**
50911 * make a label, if it is an object label, it gets different styling.
50912 * @param {string} name
50913 * @param {array} path | where to look for the actual option
50914 * @param {string} objectLabel
50915 * @returns {HTMLElement}
50916 * @private
50917 */
50918
50919 }, {
50920 key: "_makeLabel",
50921 value: function _makeLabel(name, path) {
50922 var objectLabel = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
50923 var div = document.createElement('div');
50924 div.className = 'vis-configuration vis-config-label vis-config-s' + path.length;
50925
50926 if (objectLabel === true) {
50927 div.innerHTML = '<i><b>' + name + ':</b></i>';
50928 } else {
50929 div.innerHTML = name + ':';
50930 }
50931
50932 return div;
50933 }
50934 /**
50935 * make a dropdown list for multiple possible string optoins
50936 * @param {Array.<number>} arr
50937 * @param {number} value
50938 * @param {array} path | where to look for the actual option
50939 * @private
50940 */
50941
50942 }, {
50943 key: "_makeDropdown",
50944 value: function _makeDropdown(arr, value, path) {
50945 var select = document.createElement('select');
50946 select.className = 'vis-configuration vis-config-select';
50947 var selectedValue = 0;
50948
50949 if (value !== undefined) {
50950 if (arr.indexOf(value) !== -1) {
50951 selectedValue = arr.indexOf(value);
50952 }
50953 }
50954
50955 for (var i = 0; i < arr.length; i++) {
50956 var option = document.createElement('option');
50957 option.value = arr[i];
50958
50959 if (i === selectedValue) {
50960 option.selected = 'selected';
50961 }
50962
50963 option.innerHTML = arr[i];
50964 select.appendChild(option);
50965 }
50966
50967 var me = this;
50968
50969 select.onchange = function () {
50970 me._update(this.value, path);
50971 };
50972
50973 var label = this._makeLabel(path[path.length - 1], path);
50974
50975 this._makeItem(path, label, select);
50976 }
50977 /**
50978 * make a range object for numeric options
50979 * @param {Array.<number>} arr
50980 * @param {number} value
50981 * @param {array} path | where to look for the actual option
50982 * @private
50983 */
50984
50985 }, {
50986 key: "_makeRange",
50987 value: function _makeRange(arr, value, path) {
50988 var defaultValue = arr[0];
50989 var min = arr[1];
50990 var max = arr[2];
50991 var step = arr[3];
50992 var range = document.createElement('input');
50993 range.className = 'vis-configuration vis-config-range';
50994
50995 try {
50996 range.type = 'range'; // not supported on IE9
50997
50998 range.min = min;
50999 range.max = max;
51000 } // TODO: Add some error handling and remove this lint exception
51001 catch (err) {} // eslint-disable-line no-empty
51002
51003
51004 range.step = step; // set up the popup settings in case they are needed.
51005
51006 var popupString = '';
51007 var popupValue = 0;
51008
51009 if (value !== undefined) {
51010 var factor = 1.20;
51011
51012 if (value < 0 && value * factor < min) {
51013 range.min = Math.ceil(value * factor);
51014 popupValue = range.min;
51015 popupString = 'range increased';
51016 } else if (value / factor < min) {
51017 range.min = Math.ceil(value / factor);
51018 popupValue = range.min;
51019 popupString = 'range increased';
51020 }
51021
51022 if (value * factor > max && max !== 1) {
51023 range.max = Math.ceil(value * factor);
51024 popupValue = range.max;
51025 popupString = 'range increased';
51026 }
51027
51028 range.value = value;
51029 } else {
51030 range.value = defaultValue;
51031 }
51032
51033 var input = document.createElement('input');
51034 input.className = 'vis-configuration vis-config-rangeinput';
51035 input.value = range.value;
51036 var me = this;
51037
51038 range.onchange = function () {
51039 input.value = this.value;
51040
51041 me._update(Number(this.value), path);
51042 };
51043
51044 range.oninput = function () {
51045 input.value = this.value;
51046 };
51047
51048 var label = this._makeLabel(path[path.length - 1], path);
51049
51050 var itemIndex = this._makeItem(path, label, range, input); // if a popup is needed AND it has not been shown for this value, show it.
51051
51052
51053 if (popupString !== '' && this.popupHistory[itemIndex] !== popupValue) {
51054 this.popupHistory[itemIndex] = popupValue;
51055
51056 this._setupPopup(popupString, itemIndex);
51057 }
51058 }
51059 /**
51060 * make a button object
51061 * @private
51062 */
51063
51064 }, {
51065 key: "_makeButton",
51066 value: function _makeButton() {
51067 var _this = this;
51068
51069 if (this.options.showButton === true) {
51070 var generateButton = document.createElement('div');
51071 generateButton.className = 'vis-configuration vis-config-button';
51072 generateButton.innerHTML = 'generate options';
51073
51074 generateButton.onclick = function () {
51075 _this._printOptions();
51076 };
51077
51078 generateButton.onmouseover = function () {
51079 generateButton.className = 'vis-configuration vis-config-button hover';
51080 };
51081
51082 generateButton.onmouseout = function () {
51083 generateButton.className = 'vis-configuration vis-config-button';
51084 };
51085
51086 this.optionsContainer = document.createElement('div');
51087 this.optionsContainer.className = 'vis-configuration vis-config-option-container';
51088 this.domElements.push(this.optionsContainer);
51089 this.domElements.push(generateButton);
51090 }
51091 }
51092 /**
51093 * prepare the popup
51094 * @param {string} string
51095 * @param {number} index
51096 * @private
51097 */
51098
51099 }, {
51100 key: "_setupPopup",
51101 value: function _setupPopup(string, index) {
51102 var _this2 = this;
51103
51104 if (this.initialized === true && this.allowCreation === true && this.popupCounter < this.popupLimit) {
51105 var div = document.createElement("div");
51106 div.id = "vis-configuration-popup";
51107 div.className = "vis-configuration-popup";
51108 div.innerHTML = string;
51109
51110 div.onclick = function () {
51111 _this2._removePopup();
51112 };
51113
51114 this.popupCounter += 1;
51115 this.popupDiv = {
51116 html: div,
51117 index: index
51118 };
51119 }
51120 }
51121 /**
51122 * remove the popup from the dom
51123 * @private
51124 */
51125
51126 }, {
51127 key: "_removePopup",
51128 value: function _removePopup() {
51129 if (this.popupDiv.html !== undefined) {
51130 this.popupDiv.html.parentNode.removeChild(this.popupDiv.html);
51131 clearTimeout(this.popupDiv.hideTimeout);
51132 clearTimeout(this.popupDiv.deleteTimeout);
51133 this.popupDiv = {};
51134 }
51135 }
51136 /**
51137 * Show the popup if it is needed.
51138 * @private
51139 */
51140
51141 }, {
51142 key: "_showPopupIfNeeded",
51143 value: function _showPopupIfNeeded() {
51144 var _this3 = this;
51145
51146 if (this.popupDiv.html !== undefined) {
51147 var correspondingElement = this.domElements[this.popupDiv.index];
51148 var rect = correspondingElement.getBoundingClientRect();
51149 this.popupDiv.html.style.left = rect.left + "px";
51150 this.popupDiv.html.style.top = rect.top - 30 + "px"; // 30 is the height;
51151
51152 document.body.appendChild(this.popupDiv.html);
51153 this.popupDiv.hideTimeout = setTimeout(function () {
51154 _this3.popupDiv.html.style.opacity = 0;
51155 }, 1500);
51156 this.popupDiv.deleteTimeout = setTimeout(function () {
51157 _this3._removePopup();
51158 }, 1800);
51159 }
51160 }
51161 /**
51162 * make a checkbox for boolean options.
51163 * @param {number} defaultValue
51164 * @param {number} value
51165 * @param {array} path | where to look for the actual option
51166 * @private
51167 */
51168
51169 }, {
51170 key: "_makeCheckbox",
51171 value: function _makeCheckbox(defaultValue, value, path) {
51172 var checkbox = document.createElement('input');
51173 checkbox.type = 'checkbox';
51174 checkbox.className = 'vis-configuration vis-config-checkbox';
51175 checkbox.checked = defaultValue;
51176
51177 if (value !== undefined) {
51178 checkbox.checked = value;
51179
51180 if (value !== defaultValue) {
51181 if (_typeof$1(defaultValue) === 'object') {
51182 if (value !== defaultValue.enabled) {
51183 this.changedOptions.push({
51184 path: path,
51185 value: value
51186 });
51187 }
51188 } else {
51189 this.changedOptions.push({
51190 path: path,
51191 value: value
51192 });
51193 }
51194 }
51195 }
51196
51197 var me = this;
51198
51199 checkbox.onchange = function () {
51200 me._update(this.checked, path);
51201 };
51202
51203 var label = this._makeLabel(path[path.length - 1], path);
51204
51205 this._makeItem(path, label, checkbox);
51206 }
51207 /**
51208 * make a text input field for string options.
51209 * @param {number} defaultValue
51210 * @param {number} value
51211 * @param {array} path | where to look for the actual option
51212 * @private
51213 */
51214
51215 }, {
51216 key: "_makeTextInput",
51217 value: function _makeTextInput(defaultValue, value, path) {
51218 var checkbox = document.createElement('input');
51219 checkbox.type = 'text';
51220 checkbox.className = 'vis-configuration vis-config-text';
51221 checkbox.value = value;
51222
51223 if (value !== defaultValue) {
51224 this.changedOptions.push({
51225 path: path,
51226 value: value
51227 });
51228 }
51229
51230 var me = this;
51231
51232 checkbox.onchange = function () {
51233 me._update(this.value, path);
51234 };
51235
51236 var label = this._makeLabel(path[path.length - 1], path);
51237
51238 this._makeItem(path, label, checkbox);
51239 }
51240 /**
51241 * make a color field with a color picker for color fields
51242 * @param {Array.<number>} arr
51243 * @param {number} value
51244 * @param {array} path | where to look for the actual option
51245 * @private
51246 */
51247
51248 }, {
51249 key: "_makeColorField",
51250 value: function _makeColorField(arr, value, path) {
51251 var _this4 = this;
51252
51253 var defaultColor = arr[1];
51254 var div = document.createElement('div');
51255 value = value === undefined ? defaultColor : value;
51256
51257 if (value !== 'none') {
51258 div.className = 'vis-configuration vis-config-colorBlock';
51259 div.style.backgroundColor = value;
51260 } else {
51261 div.className = 'vis-configuration vis-config-colorBlock none';
51262 }
51263
51264 value = value === undefined ? defaultColor : value;
51265
51266 div.onclick = function () {
51267 _this4._showColorPicker(value, div, path);
51268 };
51269
51270 var label = this._makeLabel(path[path.length - 1], path);
51271
51272 this._makeItem(path, label, div);
51273 }
51274 /**
51275 * used by the color buttons to call the color picker.
51276 * @param {number} value
51277 * @param {HTMLElement} div
51278 * @param {array} path | where to look for the actual option
51279 * @private
51280 */
51281
51282 }, {
51283 key: "_showColorPicker",
51284 value: function _showColorPicker(value, div, path) {
51285 var _this5 = this;
51286
51287 // clear the callback from this div
51288 div.onclick = function () {};
51289
51290 this.colorPicker.insertTo(div);
51291 this.colorPicker.show();
51292 this.colorPicker.setColor(value);
51293 this.colorPicker.setUpdateCallback(function (color) {
51294 var colorString = 'rgba(' + color.r + ',' + color.g + ',' + color.b + ',' + color.a + ')';
51295 div.style.backgroundColor = colorString;
51296
51297 _this5._update(colorString, path);
51298 }); // on close of the colorpicker, restore the callback.
51299
51300 this.colorPicker.setCloseCallback(function () {
51301 div.onclick = function () {
51302 _this5._showColorPicker(value, div, path);
51303 };
51304 });
51305 }
51306 /**
51307 * parse an object and draw the correct items
51308 * @param {Object} obj
51309 * @param {array} [path=[]] | where to look for the actual option
51310 * @param {boolean} [checkOnly=false]
51311 * @returns {boolean}
51312 * @private
51313 */
51314
51315 }, {
51316 key: "_handleObject",
51317 value: function _handleObject(obj) {
51318 var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
51319 var checkOnly = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
51320 var show = false;
51321 var filter = this.options.filter;
51322 var visibleInSet = false;
51323
51324 for (var subObj in obj) {
51325 if (obj.hasOwnProperty(subObj)) {
51326 show = true;
51327 var item = obj[subObj];
51328 var newPath = copyAndExtendArray(path, subObj);
51329
51330 if (typeof filter === 'function') {
51331 show = filter(subObj, path); // if needed we must go deeper into the object.
51332
51333 if (show === false) {
51334 if (!(item instanceof Array) && typeof item !== 'string' && typeof item !== 'boolean' && item instanceof Object) {
51335 this.allowCreation = false;
51336 show = this._handleObject(item, newPath, true);
51337 this.allowCreation = checkOnly === false;
51338 }
51339 }
51340 }
51341
51342 if (show !== false) {
51343 visibleInSet = true;
51344
51345 var value = this._getValue(newPath);
51346
51347 if (item instanceof Array) {
51348 this._handleArray(item, value, newPath);
51349 } else if (typeof item === 'string') {
51350 this._makeTextInput(item, value, newPath);
51351 } else if (typeof item === 'boolean') {
51352 this._makeCheckbox(item, value, newPath);
51353 } else if (item instanceof Object) {
51354 // collapse the physics options that are not enabled
51355 var draw = true;
51356
51357 if (path.indexOf('physics') !== -1) {
51358 if (this.moduleOptions.physics.solver !== subObj) {
51359 draw = false;
51360 }
51361 }
51362
51363 if (draw === true) {
51364 // initially collapse options with an disabled enabled option.
51365 if (item.enabled !== undefined) {
51366 var enabledPath = copyAndExtendArray(newPath, 'enabled');
51367
51368 var enabledValue = this._getValue(enabledPath);
51369
51370 if (enabledValue === true) {
51371 var label = this._makeLabel(subObj, newPath, true);
51372
51373 this._makeItem(newPath, label);
51374
51375 visibleInSet = this._handleObject(item, newPath) || visibleInSet;
51376 } else {
51377 this._makeCheckbox(item, enabledValue, newPath);
51378 }
51379 } else {
51380 var _label = this._makeLabel(subObj, newPath, true);
51381
51382 this._makeItem(newPath, _label);
51383
51384 visibleInSet = this._handleObject(item, newPath) || visibleInSet;
51385 }
51386 }
51387 } else {
51388 console.error('dont know how to handle', item, subObj, newPath);
51389 }
51390 }
51391 }
51392 }
51393
51394 return visibleInSet;
51395 }
51396 /**
51397 * handle the array type of option
51398 * @param {Array.<number>} arr
51399 * @param {number} value
51400 * @param {array} path | where to look for the actual option
51401 * @private
51402 */
51403
51404 }, {
51405 key: "_handleArray",
51406 value: function _handleArray(arr, value, path) {
51407 if (typeof arr[0] === 'string' && arr[0] === 'color') {
51408 this._makeColorField(arr, value, path);
51409
51410 if (arr[1] !== value) {
51411 this.changedOptions.push({
51412 path: path,
51413 value: value
51414 });
51415 }
51416 } else if (typeof arr[0] === 'string') {
51417 this._makeDropdown(arr, value, path);
51418
51419 if (arr[0] !== value) {
51420 this.changedOptions.push({
51421 path: path,
51422 value: value
51423 });
51424 }
51425 } else if (typeof arr[0] === 'number') {
51426 this._makeRange(arr, value, path);
51427
51428 if (arr[0] !== value) {
51429 this.changedOptions.push({
51430 path: path,
51431 value: Number(value)
51432 });
51433 }
51434 }
51435 }
51436 /**
51437 * called to update the network with the new settings.
51438 * @param {number} value
51439 * @param {array} path | where to look for the actual option
51440 * @private
51441 */
51442
51443 }, {
51444 key: "_update",
51445 value: function _update(value, path) {
51446 var options = this._constructOptions(value, path);
51447
51448 if (this.parent.body && this.parent.body.emitter && this.parent.body.emitter.emit) {
51449 this.parent.body.emitter.emit("configChange", options);
51450 }
51451
51452 this.initialized = true;
51453 this.parent.setOptions(options);
51454 }
51455 /**
51456 *
51457 * @param {string|Boolean} value
51458 * @param {Array.<string>} path
51459 * @param {{}} optionsObj
51460 * @returns {{}}
51461 * @private
51462 */
51463
51464 }, {
51465 key: "_constructOptions",
51466 value: function _constructOptions(value, path) {
51467 var optionsObj = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
51468 var pointer = optionsObj; // when dropdown boxes can be string or boolean, we typecast it into correct types
51469
51470 value = value === 'true' ? true : value;
51471 value = value === 'false' ? false : value;
51472
51473 for (var i = 0; i < path.length; i++) {
51474 if (path[i] !== 'global') {
51475 if (pointer[path[i]] === undefined) {
51476 pointer[path[i]] = {};
51477 }
51478
51479 if (i !== path.length - 1) {
51480 pointer = pointer[path[i]];
51481 } else {
51482 pointer[path[i]] = value;
51483 }
51484 }
51485 }
51486
51487 return optionsObj;
51488 }
51489 /**
51490 * @private
51491 */
51492
51493 }, {
51494 key: "_printOptions",
51495 value: function _printOptions() {
51496 var options = this.getOptions();
51497 this.optionsContainer.innerHTML = '<pre>var options = ' + JSON.stringify(options, null, 2) + '</pre>';
51498 }
51499 /**
51500 *
51501 * @returns {{}} options
51502 */
51503
51504 }, {
51505 key: "getOptions",
51506 value: function getOptions() {
51507 var options = {};
51508
51509 for (var i = 0; i < this.changedOptions.length; i++) {
51510 this._constructOptions(this.changedOptions[i].value, this.changedOptions[i].path, options);
51511 }
51512
51513 return options;
51514 }
51515 }]);
51516
51517 return Configurator;
51518}();
51519
51520/**
51521 * This object contains all possible options. It will check if the types are correct, if required if the option is one
51522 * of the allowed values.
51523 *
51524 * __any__ means that the name of the property does not matter.
51525 * __type__ is a required field for all objects and contains the allowed types of all objects
51526 */
51527var string = 'string';
51528var bool = 'boolean';
51529var number = 'number';
51530var array = 'array';
51531var object = 'object'; // should only be in a __type__ property
51532
51533var dom = 'dom';
51534var any = 'any'; // List of endpoints
51535
51536var endPoints = ["arrow", "bar", "box", "circle", "crow", "curve", "diamond", "image", "inv_curve", "inv_triangle", "triangle", "vee"];
51537var allOptions$1 = {
51538 configure: {
51539 enabled: {
51540 boolean: bool
51541 },
51542 filter: {
51543 boolean: bool,
51544 string: string,
51545 array: array,
51546 'function': 'function'
51547 },
51548 container: {
51549 dom: dom
51550 },
51551 showButton: {
51552 boolean: bool
51553 },
51554 __type__: {
51555 object: object,
51556 boolean: bool,
51557 string: string,
51558 array: array,
51559 'function': 'function'
51560 }
51561 },
51562 edges: {
51563 arrows: {
51564 to: {
51565 enabled: {
51566 boolean: bool
51567 },
51568 scaleFactor: {
51569 number: number
51570 },
51571 type: {
51572 string: endPoints
51573 },
51574 imageHeight: {
51575 number: number
51576 },
51577 imageWidth: {
51578 number: number
51579 },
51580 src: {
51581 string: string
51582 },
51583 __type__: {
51584 object: object,
51585 boolean: bool
51586 }
51587 },
51588 middle: {
51589 enabled: {
51590 boolean: bool
51591 },
51592 scaleFactor: {
51593 number: number
51594 },
51595 type: {
51596 string: endPoints
51597 },
51598 imageWidth: {
51599 number: number
51600 },
51601 imageHeight: {
51602 number: number
51603 },
51604 src: {
51605 string: string
51606 },
51607 __type__: {
51608 object: object,
51609 boolean: bool
51610 }
51611 },
51612 from: {
51613 enabled: {
51614 boolean: bool
51615 },
51616 scaleFactor: {
51617 number: number
51618 },
51619 type: {
51620 string: endPoints
51621 },
51622 imageWidth: {
51623 number: number
51624 },
51625 imageHeight: {
51626 number: number
51627 },
51628 src: {
51629 string: string
51630 },
51631 __type__: {
51632 object: object,
51633 boolean: bool
51634 }
51635 },
51636 __type__: {
51637 string: ["from", "to", "middle"],
51638 object: object
51639 }
51640 },
51641 arrowStrikethrough: {
51642 boolean: bool
51643 },
51644 background: {
51645 enabled: {
51646 boolean: bool
51647 },
51648 color: {
51649 string: string
51650 },
51651 size: {
51652 number: number
51653 },
51654 dashes: {
51655 boolean: bool,
51656 array: array
51657 },
51658 __type__: {
51659 object: object,
51660 boolean: bool
51661 }
51662 },
51663 chosen: {
51664 label: {
51665 boolean: bool,
51666 'function': 'function'
51667 },
51668 edge: {
51669 boolean: bool,
51670 'function': 'function'
51671 },
51672 __type__: {
51673 object: object,
51674 boolean: bool
51675 }
51676 },
51677 color: {
51678 color: {
51679 string: string
51680 },
51681 highlight: {
51682 string: string
51683 },
51684 hover: {
51685 string: string
51686 },
51687 inherit: {
51688 string: ['from', 'to', 'both'],
51689 boolean: bool
51690 },
51691 opacity: {
51692 number: number
51693 },
51694 __type__: {
51695 object: object,
51696 string: string
51697 }
51698 },
51699 dashes: {
51700 boolean: bool,
51701 array: array
51702 },
51703 font: {
51704 color: {
51705 string: string
51706 },
51707 size: {
51708 number: number
51709 },
51710 // px
51711 face: {
51712 string: string
51713 },
51714 background: {
51715 string: string
51716 },
51717 strokeWidth: {
51718 number: number
51719 },
51720 // px
51721 strokeColor: {
51722 string: string
51723 },
51724 align: {
51725 string: ['horizontal', 'top', 'middle', 'bottom']
51726 },
51727 vadjust: {
51728 number: number
51729 },
51730 multi: {
51731 boolean: bool,
51732 string: string
51733 },
51734 bold: {
51735 color: {
51736 string: string
51737 },
51738 size: {
51739 number: number
51740 },
51741 // px
51742 face: {
51743 string: string
51744 },
51745 mod: {
51746 string: string
51747 },
51748 vadjust: {
51749 number: number
51750 },
51751 __type__: {
51752 object: object,
51753 string: string
51754 }
51755 },
51756 boldital: {
51757 color: {
51758 string: string
51759 },
51760 size: {
51761 number: number
51762 },
51763 // px
51764 face: {
51765 string: string
51766 },
51767 mod: {
51768 string: string
51769 },
51770 vadjust: {
51771 number: number
51772 },
51773 __type__: {
51774 object: object,
51775 string: string
51776 }
51777 },
51778 ital: {
51779 color: {
51780 string: string
51781 },
51782 size: {
51783 number: number
51784 },
51785 // px
51786 face: {
51787 string: string
51788 },
51789 mod: {
51790 string: string
51791 },
51792 vadjust: {
51793 number: number
51794 },
51795 __type__: {
51796 object: object,
51797 string: string
51798 }
51799 },
51800 mono: {
51801 color: {
51802 string: string
51803 },
51804 size: {
51805 number: number
51806 },
51807 // px
51808 face: {
51809 string: string
51810 },
51811 mod: {
51812 string: string
51813 },
51814 vadjust: {
51815 number: number
51816 },
51817 __type__: {
51818 object: object,
51819 string: string
51820 }
51821 },
51822 __type__: {
51823 object: object,
51824 string: string
51825 }
51826 },
51827 hidden: {
51828 boolean: bool
51829 },
51830 hoverWidth: {
51831 'function': 'function',
51832 number: number
51833 },
51834 label: {
51835 string: string,
51836 'undefined': 'undefined'
51837 },
51838 labelHighlightBold: {
51839 boolean: bool
51840 },
51841 length: {
51842 number: number,
51843 'undefined': 'undefined'
51844 },
51845 physics: {
51846 boolean: bool
51847 },
51848 scaling: {
51849 min: {
51850 number: number
51851 },
51852 max: {
51853 number: number
51854 },
51855 label: {
51856 enabled: {
51857 boolean: bool
51858 },
51859 min: {
51860 number: number
51861 },
51862 max: {
51863 number: number
51864 },
51865 maxVisible: {
51866 number: number
51867 },
51868 drawThreshold: {
51869 number: number
51870 },
51871 __type__: {
51872 object: object,
51873 boolean: bool
51874 }
51875 },
51876 customScalingFunction: {
51877 'function': 'function'
51878 },
51879 __type__: {
51880 object: object
51881 }
51882 },
51883 selectionWidth: {
51884 'function': 'function',
51885 number: number
51886 },
51887 selfReferenceSize: {
51888 number: number
51889 },
51890 shadow: {
51891 enabled: {
51892 boolean: bool
51893 },
51894 color: {
51895 string: string
51896 },
51897 size: {
51898 number: number
51899 },
51900 x: {
51901 number: number
51902 },
51903 y: {
51904 number: number
51905 },
51906 __type__: {
51907 object: object,
51908 boolean: bool
51909 }
51910 },
51911 smooth: {
51912 enabled: {
51913 boolean: bool
51914 },
51915 type: {
51916 string: ['dynamic', 'continuous', 'discrete', 'diagonalCross', 'straightCross', 'horizontal', 'vertical', 'curvedCW', 'curvedCCW', 'cubicBezier']
51917 },
51918 roundness: {
51919 number: number
51920 },
51921 forceDirection: {
51922 string: ['horizontal', 'vertical', 'none'],
51923 boolean: bool
51924 },
51925 __type__: {
51926 object: object,
51927 boolean: bool
51928 }
51929 },
51930 title: {
51931 string: string,
51932 'undefined': 'undefined'
51933 },
51934 width: {
51935 number: number
51936 },
51937 widthConstraint: {
51938 maximum: {
51939 number: number
51940 },
51941 __type__: {
51942 object: object,
51943 boolean: bool,
51944 number: number
51945 }
51946 },
51947 value: {
51948 number: number,
51949 'undefined': 'undefined'
51950 },
51951 __type__: {
51952 object: object
51953 }
51954 },
51955 groups: {
51956 useDefaultGroups: {
51957 boolean: bool
51958 },
51959 __any__: 'get from nodes, will be overwritten below',
51960 __type__: {
51961 object: object
51962 }
51963 },
51964 interaction: {
51965 dragNodes: {
51966 boolean: bool
51967 },
51968 dragView: {
51969 boolean: bool
51970 },
51971 hideEdgesOnDrag: {
51972 boolean: bool
51973 },
51974 hideEdgesOnZoom: {
51975 boolean: bool
51976 },
51977 hideNodesOnDrag: {
51978 boolean: bool
51979 },
51980 hover: {
51981 boolean: bool
51982 },
51983 keyboard: {
51984 enabled: {
51985 boolean: bool
51986 },
51987 speed: {
51988 x: {
51989 number: number
51990 },
51991 y: {
51992 number: number
51993 },
51994 zoom: {
51995 number: number
51996 },
51997 __type__: {
51998 object: object
51999 }
52000 },
52001 bindToWindow: {
52002 boolean: bool
52003 },
52004 __type__: {
52005 object: object,
52006 boolean: bool
52007 }
52008 },
52009 multiselect: {
52010 boolean: bool
52011 },
52012 navigationButtons: {
52013 boolean: bool
52014 },
52015 selectable: {
52016 boolean: bool
52017 },
52018 selectConnectedEdges: {
52019 boolean: bool
52020 },
52021 hoverConnectedEdges: {
52022 boolean: bool
52023 },
52024 tooltipDelay: {
52025 number: number
52026 },
52027 zoomView: {
52028 boolean: bool
52029 },
52030 zoomSpeed: {
52031 number: number
52032 },
52033 __type__: {
52034 object: object
52035 }
52036 },
52037 layout: {
52038 randomSeed: {
52039 'undefined': 'undefined',
52040 number: number
52041 },
52042 improvedLayout: {
52043 boolean: bool
52044 },
52045 clusterThreshold: {
52046 number: number
52047 },
52048 hierarchical: {
52049 enabled: {
52050 boolean: bool
52051 },
52052 levelSeparation: {
52053 number: number
52054 },
52055 nodeSpacing: {
52056 number: number
52057 },
52058 treeSpacing: {
52059 number: number
52060 },
52061 blockShifting: {
52062 boolean: bool
52063 },
52064 edgeMinimization: {
52065 boolean: bool
52066 },
52067 parentCentralization: {
52068 boolean: bool
52069 },
52070 direction: {
52071 string: ['UD', 'DU', 'LR', 'RL']
52072 },
52073 // UD, DU, LR, RL
52074 sortMethod: {
52075 string: ['hubsize', 'directed']
52076 },
52077 // hubsize, directed
52078 shakeTowards: {
52079 string: ['leaves', 'roots']
52080 },
52081 // leaves, roots
52082 __type__: {
52083 object: object,
52084 boolean: bool
52085 }
52086 },
52087 __type__: {
52088 object: object
52089 }
52090 },
52091 manipulation: {
52092 enabled: {
52093 boolean: bool
52094 },
52095 initiallyActive: {
52096 boolean: bool
52097 },
52098 addNode: {
52099 boolean: bool,
52100 'function': 'function'
52101 },
52102 addEdge: {
52103 boolean: bool,
52104 'function': 'function'
52105 },
52106 editNode: {
52107 'function': 'function'
52108 },
52109 editEdge: {
52110 editWithoutDrag: {
52111 'function': 'function'
52112 },
52113 __type__: {
52114 object: object,
52115 boolean: bool,
52116 'function': 'function'
52117 }
52118 },
52119 deleteNode: {
52120 boolean: bool,
52121 'function': 'function'
52122 },
52123 deleteEdge: {
52124 boolean: bool,
52125 'function': 'function'
52126 },
52127 controlNodeStyle: 'get from nodes, will be overwritten below',
52128 __type__: {
52129 object: object,
52130 boolean: bool
52131 }
52132 },
52133 nodes: {
52134 borderWidth: {
52135 number: number
52136 },
52137 borderWidthSelected: {
52138 number: number,
52139 'undefined': 'undefined'
52140 },
52141 brokenImage: {
52142 string: string,
52143 'undefined': 'undefined'
52144 },
52145 chosen: {
52146 label: {
52147 boolean: bool,
52148 'function': 'function'
52149 },
52150 node: {
52151 boolean: bool,
52152 'function': 'function'
52153 },
52154 __type__: {
52155 object: object,
52156 boolean: bool
52157 }
52158 },
52159 color: {
52160 border: {
52161 string: string
52162 },
52163 background: {
52164 string: string
52165 },
52166 highlight: {
52167 border: {
52168 string: string
52169 },
52170 background: {
52171 string: string
52172 },
52173 __type__: {
52174 object: object,
52175 string: string
52176 }
52177 },
52178 hover: {
52179 border: {
52180 string: string
52181 },
52182 background: {
52183 string: string
52184 },
52185 __type__: {
52186 object: object,
52187 string: string
52188 }
52189 },
52190 __type__: {
52191 object: object,
52192 string: string
52193 }
52194 },
52195 fixed: {
52196 x: {
52197 boolean: bool
52198 },
52199 y: {
52200 boolean: bool
52201 },
52202 __type__: {
52203 object: object,
52204 boolean: bool
52205 }
52206 },
52207 font: {
52208 align: {
52209 string: string
52210 },
52211 color: {
52212 string: string
52213 },
52214 size: {
52215 number: number
52216 },
52217 // px
52218 face: {
52219 string: string
52220 },
52221 background: {
52222 string: string
52223 },
52224 strokeWidth: {
52225 number: number
52226 },
52227 // px
52228 strokeColor: {
52229 string: string
52230 },
52231 vadjust: {
52232 number: number
52233 },
52234 multi: {
52235 boolean: bool,
52236 string: string
52237 },
52238 bold: {
52239 color: {
52240 string: string
52241 },
52242 size: {
52243 number: number
52244 },
52245 // px
52246 face: {
52247 string: string
52248 },
52249 mod: {
52250 string: string
52251 },
52252 vadjust: {
52253 number: number
52254 },
52255 __type__: {
52256 object: object,
52257 string: string
52258 }
52259 },
52260 boldital: {
52261 color: {
52262 string: string
52263 },
52264 size: {
52265 number: number
52266 },
52267 // px
52268 face: {
52269 string: string
52270 },
52271 mod: {
52272 string: string
52273 },
52274 vadjust: {
52275 number: number
52276 },
52277 __type__: {
52278 object: object,
52279 string: string
52280 }
52281 },
52282 ital: {
52283 color: {
52284 string: string
52285 },
52286 size: {
52287 number: number
52288 },
52289 // px
52290 face: {
52291 string: string
52292 },
52293 mod: {
52294 string: string
52295 },
52296 vadjust: {
52297 number: number
52298 },
52299 __type__: {
52300 object: object,
52301 string: string
52302 }
52303 },
52304 mono: {
52305 color: {
52306 string: string
52307 },
52308 size: {
52309 number: number
52310 },
52311 // px
52312 face: {
52313 string: string
52314 },
52315 mod: {
52316 string: string
52317 },
52318 vadjust: {
52319 number: number
52320 },
52321 __type__: {
52322 object: object,
52323 string: string
52324 }
52325 },
52326 __type__: {
52327 object: object,
52328 string: string
52329 }
52330 },
52331 group: {
52332 string: string,
52333 number: number,
52334 'undefined': 'undefined'
52335 },
52336 heightConstraint: {
52337 minimum: {
52338 number: number
52339 },
52340 valign: {
52341 string: string
52342 },
52343 __type__: {
52344 object: object,
52345 boolean: bool,
52346 number: number
52347 }
52348 },
52349 hidden: {
52350 boolean: bool
52351 },
52352 icon: {
52353 face: {
52354 string: string
52355 },
52356 code: {
52357 string: string
52358 },
52359 //'\uf007',
52360 size: {
52361 number: number
52362 },
52363 //50,
52364 color: {
52365 string: string
52366 },
52367 weight: {
52368 string: string,
52369 number: number
52370 },
52371 __type__: {
52372 object: object
52373 }
52374 },
52375 id: {
52376 string: string,
52377 number: number
52378 },
52379 image: {
52380 selected: {
52381 string: string,
52382 'undefined': 'undefined'
52383 },
52384 // --> URL
52385 unselected: {
52386 string: string,
52387 'undefined': 'undefined'
52388 },
52389 // --> URL
52390 __type__: {
52391 object: object,
52392 string: string
52393 }
52394 },
52395 imagePadding: {
52396 top: {
52397 number: number
52398 },
52399 right: {
52400 number: number
52401 },
52402 bottom: {
52403 number: number
52404 },
52405 left: {
52406 number: number
52407 },
52408 __type__: {
52409 object: object,
52410 number: number
52411 }
52412 },
52413 label: {
52414 string: string,
52415 'undefined': 'undefined'
52416 },
52417 labelHighlightBold: {
52418 boolean: bool
52419 },
52420 level: {
52421 number: number,
52422 'undefined': 'undefined'
52423 },
52424 margin: {
52425 top: {
52426 number: number
52427 },
52428 right: {
52429 number: number
52430 },
52431 bottom: {
52432 number: number
52433 },
52434 left: {
52435 number: number
52436 },
52437 __type__: {
52438 object: object,
52439 number: number
52440 }
52441 },
52442 mass: {
52443 number: number
52444 },
52445 physics: {
52446 boolean: bool
52447 },
52448 scaling: {
52449 min: {
52450 number: number
52451 },
52452 max: {
52453 number: number
52454 },
52455 label: {
52456 enabled: {
52457 boolean: bool
52458 },
52459 min: {
52460 number: number
52461 },
52462 max: {
52463 number: number
52464 },
52465 maxVisible: {
52466 number: number
52467 },
52468 drawThreshold: {
52469 number: number
52470 },
52471 __type__: {
52472 object: object,
52473 boolean: bool
52474 }
52475 },
52476 customScalingFunction: {
52477 'function': 'function'
52478 },
52479 __type__: {
52480 object: object
52481 }
52482 },
52483 shadow: {
52484 enabled: {
52485 boolean: bool
52486 },
52487 color: {
52488 string: string
52489 },
52490 size: {
52491 number: number
52492 },
52493 x: {
52494 number: number
52495 },
52496 y: {
52497 number: number
52498 },
52499 __type__: {
52500 object: object,
52501 boolean: bool
52502 }
52503 },
52504 shape: {
52505 string: ['ellipse', 'circle', 'database', 'box', 'text', 'image', 'circularImage', 'diamond', 'dot', 'star', 'triangle', 'triangleDown', 'square', 'icon', 'hexagon']
52506 },
52507 shapeProperties: {
52508 borderDashes: {
52509 boolean: bool,
52510 array: array
52511 },
52512 borderRadius: {
52513 number: number
52514 },
52515 interpolation: {
52516 boolean: bool
52517 },
52518 useImageSize: {
52519 boolean: bool
52520 },
52521 useBorderWithImage: {
52522 boolean: bool
52523 },
52524 __type__: {
52525 object: object
52526 }
52527 },
52528 size: {
52529 number: number
52530 },
52531 title: {
52532 string: string,
52533 dom: dom,
52534 'undefined': 'undefined'
52535 },
52536 value: {
52537 number: number,
52538 'undefined': 'undefined'
52539 },
52540 widthConstraint: {
52541 minimum: {
52542 number: number
52543 },
52544 maximum: {
52545 number: number
52546 },
52547 __type__: {
52548 object: object,
52549 boolean: bool,
52550 number: number
52551 }
52552 },
52553 x: {
52554 number: number
52555 },
52556 y: {
52557 number: number
52558 },
52559 __type__: {
52560 object: object
52561 }
52562 },
52563 physics: {
52564 enabled: {
52565 boolean: bool
52566 },
52567 barnesHut: {
52568 gravitationalConstant: {
52569 number: number
52570 },
52571 centralGravity: {
52572 number: number
52573 },
52574 springLength: {
52575 number: number
52576 },
52577 springConstant: {
52578 number: number
52579 },
52580 damping: {
52581 number: number
52582 },
52583 avoidOverlap: {
52584 number: number
52585 },
52586 __type__: {
52587 object: object
52588 }
52589 },
52590 forceAtlas2Based: {
52591 gravitationalConstant: {
52592 number: number
52593 },
52594 centralGravity: {
52595 number: number
52596 },
52597 springLength: {
52598 number: number
52599 },
52600 springConstant: {
52601 number: number
52602 },
52603 damping: {
52604 number: number
52605 },
52606 avoidOverlap: {
52607 number: number
52608 },
52609 __type__: {
52610 object: object
52611 }
52612 },
52613 repulsion: {
52614 centralGravity: {
52615 number: number
52616 },
52617 springLength: {
52618 number: number
52619 },
52620 springConstant: {
52621 number: number
52622 },
52623 nodeDistance: {
52624 number: number
52625 },
52626 damping: {
52627 number: number
52628 },
52629 __type__: {
52630 object: object
52631 }
52632 },
52633 hierarchicalRepulsion: {
52634 centralGravity: {
52635 number: number
52636 },
52637 springLength: {
52638 number: number
52639 },
52640 springConstant: {
52641 number: number
52642 },
52643 nodeDistance: {
52644 number: number
52645 },
52646 damping: {
52647 number: number
52648 },
52649 avoidOverlap: {
52650 number: number
52651 },
52652 __type__: {
52653 object: object
52654 }
52655 },
52656 maxVelocity: {
52657 number: number
52658 },
52659 minVelocity: {
52660 number: number
52661 },
52662 // px/s
52663 solver: {
52664 string: ['barnesHut', 'repulsion', 'hierarchicalRepulsion', 'forceAtlas2Based']
52665 },
52666 stabilization: {
52667 enabled: {
52668 boolean: bool
52669 },
52670 iterations: {
52671 number: number
52672 },
52673 // maximum number of iteration to stabilize
52674 updateInterval: {
52675 number: number
52676 },
52677 onlyDynamicEdges: {
52678 boolean: bool
52679 },
52680 fit: {
52681 boolean: bool
52682 },
52683 __type__: {
52684 object: object,
52685 boolean: bool
52686 }
52687 },
52688 timestep: {
52689 number: number
52690 },
52691 adaptiveTimestep: {
52692 boolean: bool
52693 },
52694 __type__: {
52695 object: object,
52696 boolean: bool
52697 }
52698 },
52699 //globals :
52700 autoResize: {
52701 boolean: bool
52702 },
52703 clickToUse: {
52704 boolean: bool
52705 },
52706 locale: {
52707 string: string
52708 },
52709 locales: {
52710 __any__: {
52711 any: any
52712 },
52713 __type__: {
52714 object: object
52715 }
52716 },
52717 height: {
52718 string: string
52719 },
52720 width: {
52721 string: string
52722 },
52723 __type__: {
52724 object: object
52725 }
52726};
52727allOptions$1.groups.__any__ = allOptions$1.nodes;
52728allOptions$1.manipulation.controlNodeStyle = allOptions$1.nodes;
52729var configureOptions = {
52730 nodes: {
52731 borderWidth: [1, 0, 10, 1],
52732 borderWidthSelected: [2, 0, 10, 1],
52733 color: {
52734 border: ['color', '#2B7CE9'],
52735 background: ['color', '#97C2FC'],
52736 highlight: {
52737 border: ['color', '#2B7CE9'],
52738 background: ['color', '#D2E5FF']
52739 },
52740 hover: {
52741 border: ['color', '#2B7CE9'],
52742 background: ['color', '#D2E5FF']
52743 }
52744 },
52745 fixed: {
52746 x: false,
52747 y: false
52748 },
52749 font: {
52750 color: ['color', '#343434'],
52751 size: [14, 0, 100, 1],
52752 // px
52753 face: ['arial', 'verdana', 'tahoma'],
52754 background: ['color', 'none'],
52755 strokeWidth: [0, 0, 50, 1],
52756 // px
52757 strokeColor: ['color', '#ffffff']
52758 },
52759 //group: 'string',
52760 hidden: false,
52761 labelHighlightBold: true,
52762 //icon: {
52763 // face: 'string', //'FontAwesome',
52764 // code: 'string', //'\uf007',
52765 // size: [50, 0, 200, 1], //50,
52766 // color: ['color','#2B7CE9'] //'#aa00ff'
52767 //},
52768 //image: 'string', // --> URL
52769 physics: true,
52770 scaling: {
52771 min: [10, 0, 200, 1],
52772 max: [30, 0, 200, 1],
52773 label: {
52774 enabled: false,
52775 min: [14, 0, 200, 1],
52776 max: [30, 0, 200, 1],
52777 maxVisible: [30, 0, 200, 1],
52778 drawThreshold: [5, 0, 20, 1]
52779 }
52780 },
52781 shadow: {
52782 enabled: false,
52783 color: 'rgba(0,0,0,0.5)',
52784 size: [10, 0, 20, 1],
52785 x: [5, -30, 30, 1],
52786 y: [5, -30, 30, 1]
52787 },
52788 shape: ['ellipse', 'box', 'circle', 'database', 'diamond', 'dot', 'square', 'star', 'text', 'triangle', 'triangleDown', 'hexagon'],
52789 shapeProperties: {
52790 borderDashes: false,
52791 borderRadius: [6, 0, 20, 1],
52792 interpolation: true,
52793 useImageSize: false
52794 },
52795 size: [25, 0, 200, 1]
52796 },
52797 edges: {
52798 arrows: {
52799 to: {
52800 enabled: false,
52801 scaleFactor: [1, 0, 3, 0.05],
52802 type: 'arrow'
52803 },
52804 middle: {
52805 enabled: false,
52806 scaleFactor: [1, 0, 3, 0.05],
52807 type: 'arrow'
52808 },
52809 from: {
52810 enabled: false,
52811 scaleFactor: [1, 0, 3, 0.05],
52812 type: 'arrow'
52813 }
52814 },
52815 arrowStrikethrough: true,
52816 color: {
52817 color: ['color', '#848484'],
52818 highlight: ['color', '#848484'],
52819 hover: ['color', '#848484'],
52820 inherit: ['from', 'to', 'both', true, false],
52821 opacity: [1, 0, 1, 0.05]
52822 },
52823 dashes: false,
52824 font: {
52825 color: ['color', '#343434'],
52826 size: [14, 0, 100, 1],
52827 // px
52828 face: ['arial', 'verdana', 'tahoma'],
52829 background: ['color', 'none'],
52830 strokeWidth: [2, 0, 50, 1],
52831 // px
52832 strokeColor: ['color', '#ffffff'],
52833 align: ['horizontal', 'top', 'middle', 'bottom']
52834 },
52835 hidden: false,
52836 hoverWidth: [1.5, 0, 5, 0.1],
52837 labelHighlightBold: true,
52838 physics: true,
52839 scaling: {
52840 min: [1, 0, 100, 1],
52841 max: [15, 0, 100, 1],
52842 label: {
52843 enabled: true,
52844 min: [14, 0, 200, 1],
52845 max: [30, 0, 200, 1],
52846 maxVisible: [30, 0, 200, 1],
52847 drawThreshold: [5, 0, 20, 1]
52848 }
52849 },
52850 selectionWidth: [1.5, 0, 5, 0.1],
52851 selfReferenceSize: [20, 0, 200, 1],
52852 shadow: {
52853 enabled: false,
52854 color: 'rgba(0,0,0,0.5)',
52855 size: [10, 0, 20, 1],
52856 x: [5, -30, 30, 1],
52857 y: [5, -30, 30, 1]
52858 },
52859 smooth: {
52860 enabled: true,
52861 type: ['dynamic', 'continuous', 'discrete', 'diagonalCross', 'straightCross', 'horizontal', 'vertical', 'curvedCW', 'curvedCCW', 'cubicBezier'],
52862 forceDirection: ['horizontal', 'vertical', 'none'],
52863 roundness: [0.5, 0, 1, 0.05]
52864 },
52865 width: [1, 0, 30, 1]
52866 },
52867 layout: {
52868 //randomSeed: [0, 0, 500, 1],
52869 //improvedLayout: true,
52870 hierarchical: {
52871 enabled: false,
52872 levelSeparation: [150, 20, 500, 5],
52873 nodeSpacing: [100, 20, 500, 5],
52874 treeSpacing: [200, 20, 500, 5],
52875 blockShifting: true,
52876 edgeMinimization: true,
52877 parentCentralization: true,
52878 direction: ['UD', 'DU', 'LR', 'RL'],
52879 // UD, DU, LR, RL
52880 sortMethod: ['hubsize', 'directed'],
52881 // hubsize, directed
52882 shakeTowards: ['leaves', 'roots'] // leaves, roots
52883
52884 }
52885 },
52886 interaction: {
52887 dragNodes: true,
52888 dragView: true,
52889 hideEdgesOnDrag: false,
52890 hideEdgesOnZoom: false,
52891 hideNodesOnDrag: false,
52892 hover: false,
52893 keyboard: {
52894 enabled: false,
52895 speed: {
52896 x: [10, 0, 40, 1],
52897 y: [10, 0, 40, 1],
52898 zoom: [0.02, 0, 0.1, 0.005]
52899 },
52900 bindToWindow: true
52901 },
52902 multiselect: false,
52903 navigationButtons: false,
52904 selectable: true,
52905 selectConnectedEdges: true,
52906 hoverConnectedEdges: true,
52907 tooltipDelay: [300, 0, 1000, 25],
52908 zoomView: true,
52909 zoomSpeed: [1, 1, 1, 1]
52910 },
52911 manipulation: {
52912 enabled: false,
52913 initiallyActive: false
52914 },
52915 physics: {
52916 enabled: true,
52917 barnesHut: {
52918 //theta: [0.5, 0.1, 1, 0.05],
52919 gravitationalConstant: [-2000, -30000, 0, 50],
52920 centralGravity: [0.3, 0, 10, 0.05],
52921 springLength: [95, 0, 500, 5],
52922 springConstant: [0.04, 0, 1.2, 0.005],
52923 damping: [0.09, 0, 1, 0.01],
52924 avoidOverlap: [0, 0, 1, 0.01]
52925 },
52926 forceAtlas2Based: {
52927 //theta: [0.5, 0.1, 1, 0.05],
52928 gravitationalConstant: [-50, -500, 0, 1],
52929 centralGravity: [0.01, 0, 1, 0.005],
52930 springLength: [95, 0, 500, 5],
52931 springConstant: [0.08, 0, 1.2, 0.005],
52932 damping: [0.4, 0, 1, 0.01],
52933 avoidOverlap: [0, 0, 1, 0.01]
52934 },
52935 repulsion: {
52936 centralGravity: [0.2, 0, 10, 0.05],
52937 springLength: [200, 0, 500, 5],
52938 springConstant: [0.05, 0, 1.2, 0.005],
52939 nodeDistance: [100, 0, 500, 5],
52940 damping: [0.09, 0, 1, 0.01]
52941 },
52942 hierarchicalRepulsion: {
52943 centralGravity: [0.2, 0, 10, 0.05],
52944 springLength: [100, 0, 500, 5],
52945 springConstant: [0.01, 0, 1.2, 0.005],
52946 nodeDistance: [120, 0, 500, 5],
52947 damping: [0.09, 0, 1, 0.01],
52948 avoidOverlap: [0, 0, 1, 0.01]
52949 },
52950 maxVelocity: [50, 0, 150, 1],
52951 minVelocity: [0.1, 0.01, 0.5, 0.01],
52952 solver: ['barnesHut', 'forceAtlas2Based', 'repulsion', 'hierarchicalRepulsion'],
52953 timestep: [0.5, 0.01, 1, 0.01] //adaptiveTimestep: true
52954
52955 }
52956};
52957
52958var allOptions$2 = /*#__PURE__*/Object.freeze({
52959 __proto__: null,
52960 allOptions: allOptions$1,
52961 configureOptions: configureOptions
52962});
52963
52964/**
52965 * The Floyd–Warshall algorithm is an algorithm for finding shortest paths in
52966 * a weighted graph with positive or negative edge weights (but with no negative
52967 * cycles). - https://en.wikipedia.org/wiki/Floyd–Warshall_algorithm
52968 */
52969var FloydWarshall =
52970/*#__PURE__*/
52971function () {
52972 /**
52973 * @ignore
52974 */
52975 function FloydWarshall() {
52976 _classCallCheck(this, FloydWarshall);
52977 }
52978 /**
52979 *
52980 * @param {Object} body
52981 * @param {Array.<Node>} nodesArray
52982 * @param {Array.<Edge>} edgesArray
52983 * @returns {{}}
52984 */
52985
52986
52987 _createClass(FloydWarshall, [{
52988 key: "getDistances",
52989 value: function getDistances(body, nodesArray, edgesArray) {
52990 var D_matrix = {};
52991 var edges = body.edges; // prepare matrix with large numbers
52992
52993 for (var i = 0; i < nodesArray.length; i++) {
52994 var node = nodesArray[i];
52995 var cell = {};
52996 D_matrix[node] = cell;
52997
52998 for (var j = 0; j < nodesArray.length; j++) {
52999 cell[nodesArray[j]] = i == j ? 0 : 1e9;
53000 }
53001 } // put the weights for the edges in. This assumes unidirectionality.
53002
53003
53004 for (var _i = 0; _i < edgesArray.length; _i++) {
53005 var edge = edges[edgesArray[_i]]; // edge has to be connected if it counts to the distances. If it is connected to inner clusters it will crash so we also check if it is in the D_matrix
53006
53007 if (edge.connected === true && D_matrix[edge.fromId] !== undefined && D_matrix[edge.toId] !== undefined) {
53008 D_matrix[edge.fromId][edge.toId] = 1;
53009 D_matrix[edge.toId][edge.fromId] = 1;
53010 }
53011 }
53012
53013 var nodeCount = nodesArray.length; // Adapted FloydWarshall based on unidirectionality to greatly reduce complexity.
53014
53015 for (var k = 0; k < nodeCount; k++) {
53016 var knode = nodesArray[k];
53017 var kcolm = D_matrix[knode];
53018
53019 for (var _i2 = 0; _i2 < nodeCount - 1; _i2++) {
53020 var inode = nodesArray[_i2];
53021 var icolm = D_matrix[inode];
53022
53023 for (var _j = _i2 + 1; _j < nodeCount; _j++) {
53024 var jnode = nodesArray[_j];
53025 var jcolm = D_matrix[jnode];
53026 var val = Math.min(icolm[jnode], icolm[knode] + kcolm[jnode]);
53027 icolm[jnode] = val;
53028 jcolm[inode] = val;
53029 }
53030 }
53031 }
53032
53033 return D_matrix;
53034 }
53035 }]);
53036
53037 return FloydWarshall;
53038}();
53039
53040/**
53041 * KamadaKawai positions the nodes initially based on
53042 *
53043 * "AN ALGORITHM FOR DRAWING GENERAL UNDIRECTED GRAPHS"
53044 * -- Tomihisa KAMADA and Satoru KAWAI in 1989
53045 *
53046 * Possible optimizations in the distance calculation can be implemented.
53047 */
53048
53049var KamadaKawai =
53050/*#__PURE__*/
53051function () {
53052 /**
53053 * @param {Object} body
53054 * @param {number} edgeLength
53055 * @param {number} edgeStrength
53056 */
53057 function KamadaKawai(body, edgeLength, edgeStrength) {
53058 _classCallCheck(this, KamadaKawai);
53059
53060 this.body = body;
53061 this.springLength = edgeLength;
53062 this.springConstant = edgeStrength;
53063 this.distanceSolver = new FloydWarshall();
53064 }
53065 /**
53066 * Not sure if needed but can be used to update the spring length and spring constant
53067 * @param {Object} options
53068 */
53069
53070
53071 _createClass(KamadaKawai, [{
53072 key: "setOptions",
53073 value: function setOptions(options) {
53074 if (options) {
53075 if (options.springLength) {
53076 this.springLength = options.springLength;
53077 }
53078
53079 if (options.springConstant) {
53080 this.springConstant = options.springConstant;
53081 }
53082 }
53083 }
53084 /**
53085 * Position the system
53086 * @param {Array.<Node>} nodesArray
53087 * @param {Array.<vis.Edge>} edgesArray
53088 * @param {boolean} [ignoreClusters=false]
53089 */
53090
53091 }, {
53092 key: "solve",
53093 value: function solve(nodesArray, edgesArray) {
53094 var ignoreClusters = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
53095 // get distance matrix
53096 var D_matrix = this.distanceSolver.getDistances(this.body, nodesArray, edgesArray); // distance matrix
53097 // get the L Matrix
53098
53099 this._createL_matrix(D_matrix); // get the K Matrix
53100
53101
53102 this._createK_matrix(D_matrix); // initial E Matrix
53103
53104
53105 this._createE_matrix(); // calculate positions
53106
53107
53108 var threshold = 0.01;
53109 var innerThreshold = 1;
53110 var iterations = 0;
53111 var maxIterations = Math.max(1000, Math.min(10 * this.body.nodeIndices.length, 6000));
53112 var maxInnerIterations = 5;
53113 var maxEnergy = 1e9;
53114 var highE_nodeId = 0,
53115 dE_dx = 0,
53116 dE_dy = 0,
53117 delta_m = 0,
53118 subIterations = 0;
53119
53120 while (maxEnergy > threshold && iterations < maxIterations) {
53121 iterations += 1;
53122
53123 var _this$_getHighestEner = this._getHighestEnergyNode(ignoreClusters);
53124
53125 var _this$_getHighestEner2 = _slicedToArray(_this$_getHighestEner, 4);
53126
53127 highE_nodeId = _this$_getHighestEner2[0];
53128 maxEnergy = _this$_getHighestEner2[1];
53129 dE_dx = _this$_getHighestEner2[2];
53130 dE_dy = _this$_getHighestEner2[3];
53131 delta_m = maxEnergy;
53132 subIterations = 0;
53133
53134 while (delta_m > innerThreshold && subIterations < maxInnerIterations) {
53135 subIterations += 1;
53136
53137 this._moveNode(highE_nodeId, dE_dx, dE_dy);
53138
53139 var _this$_getEnergy = this._getEnergy(highE_nodeId);
53140
53141 var _this$_getEnergy2 = _slicedToArray(_this$_getEnergy, 3);
53142
53143 delta_m = _this$_getEnergy2[0];
53144 dE_dx = _this$_getEnergy2[1];
53145 dE_dy = _this$_getEnergy2[2];
53146 }
53147 }
53148 }
53149 /**
53150 * get the node with the highest energy
53151 * @param {boolean} ignoreClusters
53152 * @returns {number[]}
53153 * @private
53154 */
53155
53156 }, {
53157 key: "_getHighestEnergyNode",
53158 value: function _getHighestEnergyNode(ignoreClusters) {
53159 var nodesArray = this.body.nodeIndices;
53160 var nodes = this.body.nodes;
53161 var maxEnergy = 0;
53162 var maxEnergyNodeId = nodesArray[0];
53163 var dE_dx_max = 0,
53164 dE_dy_max = 0;
53165
53166 for (var nodeIdx = 0; nodeIdx < nodesArray.length; nodeIdx++) {
53167 var m = nodesArray[nodeIdx]; // by not evaluating nodes with predefined positions we should only move nodes that have no positions.
53168
53169 if (nodes[m].predefinedPosition === false || nodes[m].isCluster === true && ignoreClusters === true || nodes[m].options.fixed.x === true || nodes[m].options.fixed.y === true) {
53170 var _this$_getEnergy3 = this._getEnergy(m),
53171 _this$_getEnergy4 = _slicedToArray(_this$_getEnergy3, 3),
53172 delta_m = _this$_getEnergy4[0],
53173 dE_dx = _this$_getEnergy4[1],
53174 dE_dy = _this$_getEnergy4[2];
53175
53176 if (maxEnergy < delta_m) {
53177 maxEnergy = delta_m;
53178 maxEnergyNodeId = m;
53179 dE_dx_max = dE_dx;
53180 dE_dy_max = dE_dy;
53181 }
53182 }
53183 }
53184
53185 return [maxEnergyNodeId, maxEnergy, dE_dx_max, dE_dy_max];
53186 }
53187 /**
53188 * calculate the energy of a single node
53189 * @param {Node.id} m
53190 * @returns {number[]}
53191 * @private
53192 */
53193
53194 }, {
53195 key: "_getEnergy",
53196 value: function _getEnergy(m) {
53197 var _this$E_sums$m = _slicedToArray(this.E_sums[m], 2),
53198 dE_dx = _this$E_sums$m[0],
53199 dE_dy = _this$E_sums$m[1];
53200
53201 var delta_m = Math.sqrt(Math.pow(dE_dx, 2) + Math.pow(dE_dy, 2));
53202 return [delta_m, dE_dx, dE_dy];
53203 }
53204 /**
53205 * move the node based on it's energy
53206 * the dx and dy are calculated from the linear system proposed by Kamada and Kawai
53207 * @param {number} m
53208 * @param {number} dE_dx
53209 * @param {number} dE_dy
53210 * @private
53211 */
53212
53213 }, {
53214 key: "_moveNode",
53215 value: function _moveNode(m, dE_dx, dE_dy) {
53216 var nodesArray = this.body.nodeIndices;
53217 var nodes = this.body.nodes;
53218 var d2E_dx2 = 0;
53219 var d2E_dxdy = 0;
53220 var d2E_dy2 = 0;
53221 var x_m = nodes[m].x;
53222 var y_m = nodes[m].y;
53223 var km = this.K_matrix[m];
53224 var lm = this.L_matrix[m];
53225
53226 for (var iIdx = 0; iIdx < nodesArray.length; iIdx++) {
53227 var i = nodesArray[iIdx];
53228
53229 if (i !== m) {
53230 var x_i = nodes[i].x;
53231 var y_i = nodes[i].y;
53232 var kmat = km[i];
53233 var lmat = lm[i];
53234 var denominator = 1.0 / Math.pow(Math.pow(x_m - x_i, 2) + Math.pow(y_m - y_i, 2), 1.5);
53235 d2E_dx2 += kmat * (1 - lmat * Math.pow(y_m - y_i, 2) * denominator);
53236 d2E_dxdy += kmat * (lmat * (x_m - x_i) * (y_m - y_i) * denominator);
53237 d2E_dy2 += kmat * (1 - lmat * Math.pow(x_m - x_i, 2) * denominator);
53238 }
53239 } // make the variable names easier to make the solving of the linear system easier to read
53240
53241
53242 var A = d2E_dx2,
53243 B = d2E_dxdy,
53244 C = dE_dx,
53245 D = d2E_dy2,
53246 E = dE_dy; // solve the linear system for dx and dy
53247
53248 var dy = (C / A + E / B) / (B / A - D / B);
53249 var dx = -(B * dy + C) / A; // move the node
53250
53251 nodes[m].x += dx;
53252 nodes[m].y += dy; // Recalculate E_matrix (should be incremental)
53253
53254 this._updateE_matrix(m);
53255 }
53256 /**
53257 * Create the L matrix: edge length times shortest path
53258 * @param {Object} D_matrix
53259 * @private
53260 */
53261
53262 }, {
53263 key: "_createL_matrix",
53264 value: function _createL_matrix(D_matrix) {
53265 var nodesArray = this.body.nodeIndices;
53266 var edgeLength = this.springLength;
53267 this.L_matrix = [];
53268
53269 for (var i = 0; i < nodesArray.length; i++) {
53270 this.L_matrix[nodesArray[i]] = {};
53271
53272 for (var j = 0; j < nodesArray.length; j++) {
53273 this.L_matrix[nodesArray[i]][nodesArray[j]] = edgeLength * D_matrix[nodesArray[i]][nodesArray[j]];
53274 }
53275 }
53276 }
53277 /**
53278 * Create the K matrix: spring constants times shortest path
53279 * @param {Object} D_matrix
53280 * @private
53281 */
53282
53283 }, {
53284 key: "_createK_matrix",
53285 value: function _createK_matrix(D_matrix) {
53286 var nodesArray = this.body.nodeIndices;
53287 var edgeStrength = this.springConstant;
53288 this.K_matrix = [];
53289
53290 for (var i = 0; i < nodesArray.length; i++) {
53291 this.K_matrix[nodesArray[i]] = {};
53292
53293 for (var j = 0; j < nodesArray.length; j++) {
53294 this.K_matrix[nodesArray[i]][nodesArray[j]] = edgeStrength * Math.pow(D_matrix[nodesArray[i]][nodesArray[j]], -2);
53295 }
53296 }
53297 }
53298 /**
53299 * Create matrix with all energies between nodes
53300 * @private
53301 */
53302
53303 }, {
53304 key: "_createE_matrix",
53305 value: function _createE_matrix() {
53306 var nodesArray = this.body.nodeIndices;
53307 var nodes = this.body.nodes;
53308 this.E_matrix = {};
53309 this.E_sums = {};
53310
53311 for (var mIdx = 0; mIdx < nodesArray.length; mIdx++) {
53312 this.E_matrix[nodesArray[mIdx]] = [];
53313 }
53314
53315 for (var _mIdx = 0; _mIdx < nodesArray.length; _mIdx++) {
53316 var m = nodesArray[_mIdx];
53317 var x_m = nodes[m].x;
53318 var y_m = nodes[m].y;
53319 var dE_dx = 0;
53320 var dE_dy = 0;
53321
53322 for (var iIdx = _mIdx; iIdx < nodesArray.length; iIdx++) {
53323 var i = nodesArray[iIdx];
53324
53325 if (i !== m) {
53326 var x_i = nodes[i].x;
53327 var y_i = nodes[i].y;
53328 var denominator = 1.0 / Math.sqrt(Math.pow(x_m - x_i, 2) + Math.pow(y_m - y_i, 2));
53329 this.E_matrix[m][iIdx] = [this.K_matrix[m][i] * (x_m - x_i - this.L_matrix[m][i] * (x_m - x_i) * denominator), this.K_matrix[m][i] * (y_m - y_i - this.L_matrix[m][i] * (y_m - y_i) * denominator)];
53330 this.E_matrix[i][_mIdx] = this.E_matrix[m][iIdx];
53331 dE_dx += this.E_matrix[m][iIdx][0];
53332 dE_dy += this.E_matrix[m][iIdx][1];
53333 }
53334 } //Store sum
53335
53336
53337 this.E_sums[m] = [dE_dx, dE_dy];
53338 }
53339 }
53340 /**
53341 * Update method, just doing single column (rows are auto-updated) (update all sums)
53342 *
53343 * @param {number} m
53344 * @private
53345 */
53346
53347 }, {
53348 key: "_updateE_matrix",
53349 value: function _updateE_matrix(m) {
53350 var nodesArray = this.body.nodeIndices;
53351 var nodes = this.body.nodes;
53352 var colm = this.E_matrix[m];
53353 var kcolm = this.K_matrix[m];
53354 var lcolm = this.L_matrix[m];
53355 var x_m = nodes[m].x;
53356 var y_m = nodes[m].y;
53357 var dE_dx = 0;
53358 var dE_dy = 0;
53359
53360 for (var iIdx = 0; iIdx < nodesArray.length; iIdx++) {
53361 var i = nodesArray[iIdx];
53362
53363 if (i !== m) {
53364 //Keep old energy value for sum modification below
53365 var cell = colm[iIdx];
53366 var oldDx = cell[0];
53367 var oldDy = cell[1]; //Calc new energy:
53368
53369 var x_i = nodes[i].x;
53370 var y_i = nodes[i].y;
53371 var denominator = 1.0 / Math.sqrt(Math.pow(x_m - x_i, 2) + Math.pow(y_m - y_i, 2));
53372 var dx = kcolm[i] * (x_m - x_i - lcolm[i] * (x_m - x_i) * denominator);
53373 var dy = kcolm[i] * (y_m - y_i - lcolm[i] * (y_m - y_i) * denominator);
53374 colm[iIdx] = [dx, dy];
53375 dE_dx += dx;
53376 dE_dy += dy; //add new energy to sum of each column
53377
53378 var sum = this.E_sums[i];
53379 sum[0] += dx - oldDx;
53380 sum[1] += dy - oldDy;
53381 }
53382 } //Store sum at -1 index
53383
53384
53385 this.E_sums[m] = [dE_dx, dE_dy];
53386 }
53387 }]);
53388
53389 return KamadaKawai;
53390}();
53391
53392// Load custom shapes into CanvasRenderingContext2D
53393/**
53394 * Create a network visualization, displaying nodes and edges.
53395 *
53396 * @param {Element} container The DOM element in which the Network will
53397 * be created. Normally a div element.
53398 * @param {Object} data An object containing parameters
53399 * {Array} nodes
53400 * {Array} edges
53401 * @param {Object} options Options
53402 * @constructor Network
53403 */
53404
53405function Network(container, data, options) {
53406 var _this = this;
53407
53408 if (!(this instanceof Network)) {
53409 throw new SyntaxError('Constructor must be called with the new operator');
53410 } // set constant values
53411
53412
53413 this.options = {};
53414 this.defaultOptions = {
53415 locale: 'en',
53416 locales: locales,
53417 clickToUse: false
53418 };
53419 extend(this.options, this.defaultOptions);
53420 /**
53421 * Containers for nodes and edges.
53422 *
53423 * 'edges' and 'nodes' contain the full definitions of all the network elements.
53424 * 'nodeIndices' and 'edgeIndices' contain the id's of the active elements.
53425 *
53426 * The distinction is important, because a defined node need not be active, i.e.
53427 * visible on the canvas. This happens in particular when clusters are defined, in
53428 * that case there will be nodes and edges not displayed.
53429 * The bottom line is that all code with actions related to visibility, *must* use
53430 * 'nodeIndices' and 'edgeIndices', not 'nodes' and 'edges' directly.
53431 */
53432
53433 this.body = {
53434 container: container,
53435 // See comment above for following fields
53436 nodes: {},
53437 nodeIndices: [],
53438 edges: {},
53439 edgeIndices: [],
53440 emitter: {
53441 on: this.on.bind(this),
53442 off: this.off.bind(this),
53443 emit: this.emit.bind(this),
53444 once: this.once.bind(this)
53445 },
53446 eventListeners: {
53447 onTap: function onTap() {},
53448 onTouch: function onTouch() {},
53449 onDoubleTap: function onDoubleTap() {},
53450 onHold: function onHold() {},
53451 onDragStart: function onDragStart() {},
53452 onDrag: function onDrag() {},
53453 onDragEnd: function onDragEnd() {},
53454 onMouseWheel: function onMouseWheel() {},
53455 onPinch: function onPinch() {},
53456 onMouseMove: function onMouseMove() {},
53457 onRelease: function onRelease() {},
53458 onContext: function onContext() {}
53459 },
53460 data: {
53461 nodes: null,
53462 // A DataSet or DataView
53463 edges: null // A DataSet or DataView
53464
53465 },
53466 functions: {
53467 createNode: function createNode() {},
53468 createEdge: function createEdge() {},
53469 getPointer: function getPointer() {}
53470 },
53471 modules: {},
53472 view: {
53473 scale: 1,
53474 translation: {
53475 x: 0,
53476 y: 0
53477 }
53478 }
53479 }; // bind the event listeners
53480
53481 this.bindEventListeners(); // setting up all modules
53482
53483 this.images = new Images(function () {
53484 return _this.body.emitter.emit("_requestRedraw");
53485 }); // object with images
53486
53487 this.groups = new Groups(); // object with groups
53488
53489 this.canvas = new Canvas(this.body); // DOM handler
53490
53491 this.selectionHandler = new SelectionHandler(this.body, this.canvas); // Selection handler
53492
53493 this.interactionHandler = new InteractionHandler(this.body, this.canvas, this.selectionHandler); // Interaction handler handles all the hammer bindings (that are bound by canvas), key
53494
53495 this.view = new View(this.body, this.canvas); // camera handler, does animations and zooms
53496
53497 this.renderer = new CanvasRenderer(this.body, this.canvas); // renderer, starts renderloop, has events that modules can hook into
53498
53499 this.physics = new PhysicsEngine(this.body); // physics engine, does all the simulations
53500
53501 this.layoutEngine = new LayoutEngine(this.body); // layout engine for inital layout and hierarchical layout
53502
53503 this.clustering = new ClusterEngine(this.body); // clustering api
53504
53505 this.manipulation = new ManipulationSystem(this.body, this.canvas, this.selectionHandler, this.interactionHandler); // data manipulation system
53506
53507 this.nodesHandler = new NodesHandler(this.body, this.images, this.groups, this.layoutEngine); // Handle adding, deleting and updating of nodes as well as global options
53508
53509 this.edgesHandler = new EdgesHandler(this.body, this.images, this.groups); // Handle adding, deleting and updating of edges as well as global options
53510
53511 this.body.modules["kamadaKawai"] = new KamadaKawai(this.body, 150, 0.05); // Layouting algorithm.
53512
53513 this.body.modules["clustering"] = this.clustering; // create the DOM elements
53514
53515 this.canvas._create(); // apply options
53516
53517
53518 this.setOptions(options); // load data (the disable start variable will be the same as the enabled clustering)
53519
53520 this.setData(data);
53521} // Extend Network with an Emitter mixin
53522
53523componentEmitter(Network.prototype);
53524/**
53525 * Set options
53526 * @param {Object} options
53527 */
53528
53529Network.prototype.setOptions = function (options) {
53530 var _this2 = this;
53531
53532 if (options === null) {
53533 options = undefined; // This ensures that options handling doesn't crash in the handling
53534 }
53535
53536 if (options !== undefined) {
53537 var errorFound = Validator.validate(options, allOptions$1);
53538
53539 if (errorFound === true) {
53540 console.log('%cErrors have been found in the supplied options object.', printStyle);
53541 } // copy the global fields over
53542
53543
53544 var fields = ['locale', 'locales', 'clickToUse'];
53545 selectiveDeepExtend(fields, this.options, options); // the hierarchical system can adapt the edges and the physics to it's own options because not all combinations work with the hierarichical system.
53546
53547 options = this.layoutEngine.setOptions(options.layout, options);
53548 this.canvas.setOptions(options); // options for canvas are in globals
53549 // pass the options to the modules
53550
53551 this.groups.setOptions(options.groups);
53552 this.nodesHandler.setOptions(options.nodes);
53553 this.edgesHandler.setOptions(options.edges);
53554 this.physics.setOptions(options.physics);
53555 this.manipulation.setOptions(options.manipulation, options, this.options); // manipulation uses the locales in the globals
53556
53557 this.interactionHandler.setOptions(options.interaction);
53558 this.renderer.setOptions(options.interaction); // options for rendering are in interaction
53559
53560 this.selectionHandler.setOptions(options.interaction); // options for selection are in interaction
53561 // reload the settings of the nodes to apply changes in groups that are not referenced by pointer.
53562
53563 if (options.groups !== undefined) {
53564 this.body.emitter.emit("refreshNodes");
53565 } // these two do not have options at the moment, here for completeness
53566 //this.view.setOptions(options.view);
53567 //this.clustering.setOptions(options.clustering);
53568
53569
53570 if ('configure' in options) {
53571 if (!this.configurator) {
53572 this.configurator = new Configurator(this, this.body.container, configureOptions, this.canvas.pixelRatio);
53573 }
53574
53575 this.configurator.setOptions(options.configure);
53576 } // if the configuration system is enabled, copy all options and put them into the config system
53577
53578
53579 if (this.configurator && this.configurator.options.enabled === true) {
53580 var networkOptions = {
53581 nodes: {},
53582 edges: {},
53583 layout: {},
53584 interaction: {},
53585 manipulation: {},
53586 physics: {},
53587 global: {}
53588 };
53589 deepExtend(networkOptions.nodes, this.nodesHandler.options);
53590 deepExtend(networkOptions.edges, this.edgesHandler.options);
53591 deepExtend(networkOptions.layout, this.layoutEngine.options); // load the selectionHandler and render default options in to the interaction group
53592
53593 deepExtend(networkOptions.interaction, this.selectionHandler.options);
53594 deepExtend(networkOptions.interaction, this.renderer.options);
53595 deepExtend(networkOptions.interaction, this.interactionHandler.options);
53596 deepExtend(networkOptions.manipulation, this.manipulation.options);
53597 deepExtend(networkOptions.physics, this.physics.options); // load globals into the global object
53598
53599 deepExtend(networkOptions.global, this.canvas.options);
53600 deepExtend(networkOptions.global, this.options);
53601 this.configurator.setModuleOptions(networkOptions);
53602 } // handle network global options
53603
53604
53605 if (options.clickToUse !== undefined) {
53606 if (options.clickToUse === true) {
53607 if (this.activator === undefined) {
53608 this.activator = new Activator_1(this.canvas.frame);
53609 this.activator.on('change', function () {
53610 _this2.body.emitter.emit("activate");
53611 });
53612 }
53613 } else {
53614 if (this.activator !== undefined) {
53615 this.activator.destroy();
53616 delete this.activator;
53617 }
53618
53619 this.body.emitter.emit("activate");
53620 }
53621 } else {
53622 this.body.emitter.emit("activate");
53623 }
53624
53625 this.canvas.setSize(); // start the physics simulation. Can be safely called multiple times.
53626
53627 this.body.emitter.emit("startSimulation");
53628 }
53629};
53630/**
53631 * Update the visible nodes and edges list with the most recent node state.
53632 *
53633 * Visible nodes are stored in this.body.nodeIndices.
53634 * Visible edges are stored in this.body.edgeIndices.
53635 * A node or edges is visible if it is not hidden or clustered.
53636 *
53637 * @private
53638 */
53639
53640
53641Network.prototype._updateVisibleIndices = function () {
53642 var nodes = this.body.nodes;
53643 var edges = this.body.edges;
53644 this.body.nodeIndices = [];
53645 this.body.edgeIndices = [];
53646
53647 for (var nodeId in nodes) {
53648 if (nodes.hasOwnProperty(nodeId)) {
53649 if (!this.clustering._isClusteredNode(nodeId) && nodes[nodeId].options.hidden === false) {
53650 this.body.nodeIndices.push(nodes[nodeId].id);
53651 }
53652 }
53653 }
53654
53655 for (var edgeId in edges) {
53656 if (edges.hasOwnProperty(edgeId)) {
53657 var edge = edges[edgeId]; // It can happen that this is executed *after* a node edge has been removed,
53658 // but *before* the edge itself has been removed. Taking this into account.
53659
53660 var fromNode = nodes[edge.fromId];
53661 var toNode = nodes[edge.toId];
53662 var edgeNodesPresent = fromNode !== undefined && toNode !== undefined;
53663 var isVisible = !this.clustering._isClusteredEdge(edgeId) && edge.options.hidden === false && edgeNodesPresent && fromNode.options.hidden === false // Also hidden if any of its connecting nodes are hidden
53664 && toNode.options.hidden === false; // idem
53665
53666 if (isVisible) {
53667 this.body.edgeIndices.push(edge.id);
53668 }
53669 }
53670 }
53671};
53672/**
53673 * Bind all events
53674 */
53675
53676
53677Network.prototype.bindEventListeners = function () {
53678 var _this3 = this;
53679
53680 // This event will trigger a rebuilding of the cache everything.
53681 // Used when nodes or edges have been added or removed.
53682 this.body.emitter.on("_dataChanged", function () {
53683 _this3.edgesHandler._updateState();
53684
53685 _this3.body.emitter.emit("_dataUpdated");
53686 }); // this is called when options of EXISTING nodes or edges have changed.
53687
53688 this.body.emitter.on("_dataUpdated", function () {
53689 // Order important in following block
53690 _this3.clustering._updateState();
53691
53692 _this3._updateVisibleIndices();
53693
53694 _this3._updateValueRange(_this3.body.nodes);
53695
53696 _this3._updateValueRange(_this3.body.edges); // start simulation (can be called safely, even if already running)
53697
53698
53699 _this3.body.emitter.emit("startSimulation");
53700
53701 _this3.body.emitter.emit("_requestRedraw");
53702 });
53703};
53704/**
53705 * Set nodes and edges, and optionally options as well.
53706 *
53707 * @param {Object} data Object containing parameters:
53708 * {Array | DataSet | DataView} [nodes] Array with nodes
53709 * {Array | DataSet | DataView} [edges] Array with edges
53710 * {String} [dot] String containing data in DOT format
53711 * {String} [gephi] String containing data in gephi JSON format
53712 * {Options} [options] Object with options
53713 */
53714
53715
53716Network.prototype.setData = function (data) {
53717 // reset the physics engine.
53718 this.body.emitter.emit("resetPhysics");
53719 this.body.emitter.emit("_resetData"); // unselect all to ensure no selections from old data are carried over.
53720
53721 this.selectionHandler.unselectAll();
53722
53723 if (data && data.dot && (data.nodes || data.edges)) {
53724 throw new SyntaxError('Data must contain either parameter "dot" or ' + ' parameter pair "nodes" and "edges", but not both.');
53725 } // set options
53726
53727
53728 this.setOptions(data && data.options); // set all data
53729
53730 if (data && data.dot) {
53731 console.log('The dot property has been deprecated. Please use the static convertDot method to convert DOT into vis.network format and use the normal data format with nodes and edges. This converter is used like this: var data = vis.network.convertDot(dotString);'); // parse DOT file
53732
53733 var dotData = dotparser.DOTToGraph(data.dot);
53734 this.setData(dotData);
53735 return;
53736 } else if (data && data.gephi) {
53737 // parse DOT file
53738 console.log('The gephi property has been deprecated. Please use the static convertGephi method to convert gephi into vis.network format and use the normal data format with nodes and edges. This converter is used like this: var data = vis.network.convertGephi(gephiJson);');
53739 var gephiData = parseGephi(data.gephi);
53740 this.setData(gephiData);
53741 return;
53742 } else {
53743 this.nodesHandler.setData(data && data.nodes, true);
53744 this.edgesHandler.setData(data && data.edges, true);
53745 } // emit change in data
53746
53747
53748 this.body.emitter.emit("_dataChanged"); // emit data loaded
53749
53750 this.body.emitter.emit("_dataLoaded"); // find a stable position or start animating to a stable position
53751
53752 this.body.emitter.emit("initPhysics");
53753};
53754/**
53755 * Cleans up all bindings of the network, removing it fully from the memory IF the variable is set to null after calling this function.
53756 * var network = new vis.Network(..);
53757 * network.destroy();
53758 * network = null;
53759 */
53760
53761
53762Network.prototype.destroy = function () {
53763 this.body.emitter.emit("destroy"); // clear events
53764
53765 this.body.emitter.off();
53766 this.off(); // delete modules
53767
53768 delete this.groups;
53769 delete this.canvas;
53770 delete this.selectionHandler;
53771 delete this.interactionHandler;
53772 delete this.view;
53773 delete this.renderer;
53774 delete this.physics;
53775 delete this.layoutEngine;
53776 delete this.clustering;
53777 delete this.manipulation;
53778 delete this.nodesHandler;
53779 delete this.edgesHandler;
53780 delete this.configurator;
53781 delete this.images;
53782
53783 for (var nodeId in this.body.nodes) {
53784 if (!this.body.nodes.hasOwnProperty(nodeId)) continue;
53785 delete this.body.nodes[nodeId];
53786 }
53787
53788 for (var edgeId in this.body.edges) {
53789 if (!this.body.edges.hasOwnProperty(edgeId)) continue;
53790 delete this.body.edges[edgeId];
53791 } // remove the container and everything inside it recursively
53792
53793
53794 recursiveDOMDelete(this.body.container);
53795};
53796/**
53797 * Update the values of all object in the given array according to the current
53798 * value range of the objects in the array.
53799 * @param {Object} obj An object containing a set of Edges or Nodes
53800 * The objects must have a method getValue() and
53801 * setValueRange(min, max).
53802 * @private
53803 */
53804
53805
53806Network.prototype._updateValueRange = function (obj) {
53807 var id; // determine the range of the objects
53808
53809 var valueMin = undefined;
53810 var valueMax = undefined;
53811 var valueTotal = 0;
53812
53813 for (id in obj) {
53814 if (obj.hasOwnProperty(id)) {
53815 var value = obj[id].getValue();
53816
53817 if (value !== undefined) {
53818 valueMin = valueMin === undefined ? value : Math.min(value, valueMin);
53819 valueMax = valueMax === undefined ? value : Math.max(value, valueMax);
53820 valueTotal += value;
53821 }
53822 }
53823 } // adjust the range of all objects
53824
53825
53826 if (valueMin !== undefined && valueMax !== undefined) {
53827 for (id in obj) {
53828 if (obj.hasOwnProperty(id)) {
53829 obj[id].setValueRange(valueMin, valueMax, valueTotal);
53830 }
53831 }
53832 }
53833};
53834/**
53835 * Returns true when the Network is active.
53836 * @returns {boolean}
53837 */
53838
53839
53840Network.prototype.isActive = function () {
53841 return !this.activator || this.activator.active;
53842};
53843
53844Network.prototype.setSize = function () {
53845 return this.canvas.setSize.apply(this.canvas, arguments);
53846};
53847
53848Network.prototype.canvasToDOM = function () {
53849 return this.canvas.canvasToDOM.apply(this.canvas, arguments);
53850};
53851
53852Network.prototype.DOMtoCanvas = function () {
53853 return this.canvas.DOMtoCanvas.apply(this.canvas, arguments);
53854};
53855/**
53856 * Nodes can be in clusters. Clusters can also be in clusters. This function returns and array of
53857 * nodeIds showing where the node is.
53858 *
53859 * If any nodeId in the chain, especially the first passed in as a parameter, is not present in
53860 * the current nodes list, an empty array is returned.
53861 *
53862 * Example:
53863 * cluster 'A' contains cluster 'B',
53864 * cluster 'B' contains cluster 'C',
53865 * cluster 'C' contains node 'fred'.
53866 * `jsnetwork.clustering.findNode('fred')` will return `['A','B','C','fred']`.
53867 *
53868 * @param {string|number} nodeId
53869 * @returns {Array}
53870 */
53871
53872
53873Network.prototype.findNode = function () {
53874 return this.clustering.findNode.apply(this.clustering, arguments);
53875};
53876
53877Network.prototype.isCluster = function () {
53878 return this.clustering.isCluster.apply(this.clustering, arguments);
53879};
53880
53881Network.prototype.openCluster = function () {
53882 return this.clustering.openCluster.apply(this.clustering, arguments);
53883};
53884
53885Network.prototype.cluster = function () {
53886 return this.clustering.cluster.apply(this.clustering, arguments);
53887};
53888
53889Network.prototype.getNodesInCluster = function () {
53890 return this.clustering.getNodesInCluster.apply(this.clustering, arguments);
53891};
53892
53893Network.prototype.clusterByConnection = function () {
53894 return this.clustering.clusterByConnection.apply(this.clustering, arguments);
53895};
53896
53897Network.prototype.clusterByHubsize = function () {
53898 return this.clustering.clusterByHubsize.apply(this.clustering, arguments);
53899};
53900/**
53901 * This method will cluster all nodes with 1 edge with their respective connected node.
53902 * The options object is explained in full <a data-scroll="" data-options="{ &quot;easing&quot;: &quot;easeInCubic&quot; }" href="#optionsObject">below</a>.
53903 *
53904 * @param {object} [options]
53905 * @returns {undefined}
53906 */
53907
53908
53909Network.prototype.clusterOutliers = function () {
53910 return this.clustering.clusterOutliers.apply(this.clustering, arguments);
53911};
53912
53913Network.prototype.getSeed = function () {
53914 return this.layoutEngine.getSeed.apply(this.layoutEngine, arguments);
53915};
53916
53917Network.prototype.enableEditMode = function () {
53918 return this.manipulation.enableEditMode.apply(this.manipulation, arguments);
53919};
53920
53921Network.prototype.disableEditMode = function () {
53922 return this.manipulation.disableEditMode.apply(this.manipulation, arguments);
53923};
53924
53925Network.prototype.addNodeMode = function () {
53926 return this.manipulation.addNodeMode.apply(this.manipulation, arguments);
53927};
53928
53929Network.prototype.editNode = function () {
53930 return this.manipulation.editNode.apply(this.manipulation, arguments);
53931};
53932
53933Network.prototype.editNodeMode = function () {
53934 console.log("Deprecated: Please use editNode instead of editNodeMode.");
53935 return this.manipulation.editNode.apply(this.manipulation, arguments);
53936};
53937
53938Network.prototype.addEdgeMode = function () {
53939 return this.manipulation.addEdgeMode.apply(this.manipulation, arguments);
53940};
53941
53942Network.prototype.editEdgeMode = function () {
53943 return this.manipulation.editEdgeMode.apply(this.manipulation, arguments);
53944};
53945
53946Network.prototype.deleteSelected = function () {
53947 return this.manipulation.deleteSelected.apply(this.manipulation, arguments);
53948};
53949
53950Network.prototype.getPositions = function () {
53951 return this.nodesHandler.getPositions.apply(this.nodesHandler, arguments);
53952};
53953
53954Network.prototype.storePositions = function () {
53955 return this.nodesHandler.storePositions.apply(this.nodesHandler, arguments);
53956};
53957
53958Network.prototype.moveNode = function () {
53959 return this.nodesHandler.moveNode.apply(this.nodesHandler, arguments);
53960};
53961
53962Network.prototype.getBoundingBox = function () {
53963 return this.nodesHandler.getBoundingBox.apply(this.nodesHandler, arguments);
53964};
53965
53966Network.prototype.getConnectedNodes = function (objectId) {
53967 if (this.body.nodes[objectId] !== undefined) {
53968 return this.nodesHandler.getConnectedNodes.apply(this.nodesHandler, arguments);
53969 } else {
53970 return this.edgesHandler.getConnectedNodes.apply(this.edgesHandler, arguments);
53971 }
53972};
53973
53974Network.prototype.getConnectedEdges = function () {
53975 return this.nodesHandler.getConnectedEdges.apply(this.nodesHandler, arguments);
53976};
53977
53978Network.prototype.startSimulation = function () {
53979 return this.physics.startSimulation.apply(this.physics, arguments);
53980};
53981
53982Network.prototype.stopSimulation = function () {
53983 return this.physics.stopSimulation.apply(this.physics, arguments);
53984};
53985
53986Network.prototype.stabilize = function () {
53987 return this.physics.stabilize.apply(this.physics, arguments);
53988};
53989
53990Network.prototype.getSelection = function () {
53991 return this.selectionHandler.getSelection.apply(this.selectionHandler, arguments);
53992};
53993
53994Network.prototype.setSelection = function () {
53995 return this.selectionHandler.setSelection.apply(this.selectionHandler, arguments);
53996};
53997
53998Network.prototype.getSelectedNodes = function () {
53999 return this.selectionHandler.getSelectedNodes.apply(this.selectionHandler, arguments);
54000};
54001
54002Network.prototype.getSelectedEdges = function () {
54003 return this.selectionHandler.getSelectedEdges.apply(this.selectionHandler, arguments);
54004};
54005
54006Network.prototype.getNodeAt = function () {
54007 var node = this.selectionHandler.getNodeAt.apply(this.selectionHandler, arguments);
54008
54009 if (node !== undefined && node.id !== undefined) {
54010 return node.id;
54011 }
54012
54013 return node;
54014};
54015
54016Network.prototype.getEdgeAt = function () {
54017 var edge = this.selectionHandler.getEdgeAt.apply(this.selectionHandler, arguments);
54018
54019 if (edge !== undefined && edge.id !== undefined) {
54020 return edge.id;
54021 }
54022
54023 return edge;
54024};
54025
54026Network.prototype.selectNodes = function () {
54027 return this.selectionHandler.selectNodes.apply(this.selectionHandler, arguments);
54028};
54029
54030Network.prototype.selectEdges = function () {
54031 return this.selectionHandler.selectEdges.apply(this.selectionHandler, arguments);
54032};
54033
54034Network.prototype.unselectAll = function () {
54035 this.selectionHandler.unselectAll.apply(this.selectionHandler, arguments);
54036 this.redraw();
54037};
54038
54039Network.prototype.redraw = function () {
54040 return this.renderer.redraw.apply(this.renderer, arguments);
54041};
54042
54043Network.prototype.getScale = function () {
54044 return this.view.getScale.apply(this.view, arguments);
54045};
54046
54047Network.prototype.getViewPosition = function () {
54048 return this.view.getViewPosition.apply(this.view, arguments);
54049};
54050
54051Network.prototype.fit = function () {
54052 return this.view.fit.apply(this.view, arguments);
54053};
54054
54055Network.prototype.moveTo = function () {
54056 return this.view.moveTo.apply(this.view, arguments);
54057};
54058
54059Network.prototype.focus = function () {
54060 return this.view.focus.apply(this.view, arguments);
54061};
54062
54063Network.prototype.releaseNode = function () {
54064 return this.view.releaseNode.apply(this.view, arguments);
54065};
54066
54067Network.prototype.getOptionsFromConfigurator = function () {
54068 var options = {};
54069
54070 if (this.configurator) {
54071 options = this.configurator.getOptions.apply(this.configurator);
54072 }
54073
54074 return options;
54075};
54076
54077var DOMutil = createCommonjsModule(function (module, exports) {
54078 // DOM utility methods
54079
54080 /**
54081 * this prepares the JSON container for allocating SVG elements
54082 * @param {Object} JSONcontainer
54083 * @private
54084 */
54085 exports.prepareElements = function (JSONcontainer) {
54086 // cleanup the redundant svgElements;
54087 for (var elementType in JSONcontainer) {
54088 if (JSONcontainer.hasOwnProperty(elementType)) {
54089 JSONcontainer[elementType].redundant = JSONcontainer[elementType].used;
54090 JSONcontainer[elementType].used = [];
54091 }
54092 }
54093 };
54094 /**
54095 * this cleans up all the unused SVG elements. By asking for the parentNode, we only need to supply the JSON container from
54096 * which to remove the redundant elements.
54097 *
54098 * @param {Object} JSONcontainer
54099 * @private
54100 */
54101
54102
54103 exports.cleanupElements = function (JSONcontainer) {
54104 // cleanup the redundant svgElements;
54105 for (var elementType in JSONcontainer) {
54106 if (JSONcontainer.hasOwnProperty(elementType)) {
54107 if (JSONcontainer[elementType].redundant) {
54108 for (var i = 0; i < JSONcontainer[elementType].redundant.length; i++) {
54109 JSONcontainer[elementType].redundant[i].parentNode.removeChild(JSONcontainer[elementType].redundant[i]);
54110 }
54111
54112 JSONcontainer[elementType].redundant = [];
54113 }
54114 }
54115 }
54116 };
54117 /**
54118 * Ensures that all elements are removed first up so they can be recreated cleanly
54119 * @param {Object} JSONcontainer
54120 */
54121
54122
54123 exports.resetElements = function (JSONcontainer) {
54124 exports.prepareElements(JSONcontainer);
54125 exports.cleanupElements(JSONcontainer);
54126 exports.prepareElements(JSONcontainer);
54127 };
54128 /**
54129 * Allocate or generate an SVG element if needed. Store a reference to it in the JSON container and draw it in the svgContainer
54130 * the JSON container and the SVG container have to be supplied so other svg containers (like the legend) can use this.
54131 *
54132 * @param {string} elementType
54133 * @param {Object} JSONcontainer
54134 * @param {Object} svgContainer
54135 * @returns {Element}
54136 * @private
54137 */
54138
54139
54140 exports.getSVGElement = function (elementType, JSONcontainer, svgContainer) {
54141 var element; // allocate SVG element, if it doesnt yet exist, create one.
54142
54143 if (JSONcontainer.hasOwnProperty(elementType)) {
54144 // this element has been created before
54145 // check if there is an redundant element
54146 if (JSONcontainer[elementType].redundant.length > 0) {
54147 element = JSONcontainer[elementType].redundant[0];
54148 JSONcontainer[elementType].redundant.shift();
54149 } else {
54150 // create a new element and add it to the SVG
54151 element = document.createElementNS('http://www.w3.org/2000/svg', elementType);
54152 svgContainer.appendChild(element);
54153 }
54154 } else {
54155 // create a new element and add it to the SVG, also create a new object in the svgElements to keep track of it.
54156 element = document.createElementNS('http://www.w3.org/2000/svg', elementType);
54157 JSONcontainer[elementType] = {
54158 used: [],
54159 redundant: []
54160 };
54161 svgContainer.appendChild(element);
54162 }
54163
54164 JSONcontainer[elementType].used.push(element);
54165 return element;
54166 };
54167 /**
54168 * Allocate or generate an SVG element if needed. Store a reference to it in the JSON container and draw it in the svgContainer
54169 * the JSON container and the SVG container have to be supplied so other svg containers (like the legend) can use this.
54170 *
54171 * @param {string} elementType
54172 * @param {Object} JSONcontainer
54173 * @param {Element} DOMContainer
54174 * @param {Element} insertBefore
54175 * @returns {*}
54176 */
54177
54178
54179 exports.getDOMElement = function (elementType, JSONcontainer, DOMContainer, insertBefore) {
54180 var element; // allocate DOM element, if it doesnt yet exist, create one.
54181
54182 if (JSONcontainer.hasOwnProperty(elementType)) {
54183 // this element has been created before
54184 // check if there is an redundant element
54185 if (JSONcontainer[elementType].redundant.length > 0) {
54186 element = JSONcontainer[elementType].redundant[0];
54187 JSONcontainer[elementType].redundant.shift();
54188 } else {
54189 // create a new element and add it to the SVG
54190 element = document.createElement(elementType);
54191
54192 if (insertBefore !== undefined) {
54193 DOMContainer.insertBefore(element, insertBefore);
54194 } else {
54195 DOMContainer.appendChild(element);
54196 }
54197 }
54198 } else {
54199 // create a new element and add it to the SVG, also create a new object in the svgElements to keep track of it.
54200 element = document.createElement(elementType);
54201 JSONcontainer[elementType] = {
54202 used: [],
54203 redundant: []
54204 };
54205
54206 if (insertBefore !== undefined) {
54207 DOMContainer.insertBefore(element, insertBefore);
54208 } else {
54209 DOMContainer.appendChild(element);
54210 }
54211 }
54212
54213 JSONcontainer[elementType].used.push(element);
54214 return element;
54215 };
54216 /**
54217 * Draw a point object. This is a separate function because it can also be called by the legend.
54218 * The reason the JSONcontainer and the target SVG svgContainer have to be supplied is so the legend can use these functions
54219 * as well.
54220 *
54221 * @param {number} x
54222 * @param {number} y
54223 * @param {Object} groupTemplate: A template containing the necessary information to draw the datapoint e.g., {style: 'circle', size: 5, className: 'className' }
54224 * @param {Object} JSONcontainer
54225 * @param {Object} svgContainer
54226 * @param {Object} labelObj
54227 * @returns {vis.PointItem}
54228 */
54229
54230
54231 exports.drawPoint = function (x, y, groupTemplate, JSONcontainer, svgContainer, labelObj) {
54232 var point;
54233
54234 if (groupTemplate.style == 'circle') {
54235 point = exports.getSVGElement('circle', JSONcontainer, svgContainer);
54236 point.setAttributeNS(null, "cx", x);
54237 point.setAttributeNS(null, "cy", y);
54238 point.setAttributeNS(null, "r", 0.5 * groupTemplate.size);
54239 } else {
54240 point = exports.getSVGElement('rect', JSONcontainer, svgContainer);
54241 point.setAttributeNS(null, "x", x - 0.5 * groupTemplate.size);
54242 point.setAttributeNS(null, "y", y - 0.5 * groupTemplate.size);
54243 point.setAttributeNS(null, "width", groupTemplate.size);
54244 point.setAttributeNS(null, "height", groupTemplate.size);
54245 }
54246
54247 if (groupTemplate.styles !== undefined) {
54248 point.setAttributeNS(null, "style", groupTemplate.styles);
54249 }
54250
54251 point.setAttributeNS(null, "class", groupTemplate.className + " vis-point"); //handle label
54252
54253 if (labelObj) {
54254 var label = exports.getSVGElement('text', JSONcontainer, svgContainer);
54255
54256 if (labelObj.xOffset) {
54257 x = x + labelObj.xOffset;
54258 }
54259
54260 if (labelObj.yOffset) {
54261 y = y + labelObj.yOffset;
54262 }
54263
54264 if (labelObj.content) {
54265 label.textContent = labelObj.content;
54266 }
54267
54268 if (labelObj.className) {
54269 label.setAttributeNS(null, "class", labelObj.className + " vis-label");
54270 }
54271
54272 label.setAttributeNS(null, "x", x);
54273 label.setAttributeNS(null, "y", y);
54274 }
54275
54276 return point;
54277 };
54278 /**
54279 * draw a bar SVG element centered on the X coordinate
54280 *
54281 * @param {number} x
54282 * @param {number} y
54283 * @param {number} width
54284 * @param {number} height
54285 * @param {string} className
54286 * @param {Object} JSONcontainer
54287 * @param {Object} svgContainer
54288 * @param {string} style
54289 */
54290
54291
54292 exports.drawBar = function (x, y, width, height, className, JSONcontainer, svgContainer, style) {
54293 if (height != 0) {
54294 if (height < 0) {
54295 height *= -1;
54296 y -= height;
54297 }
54298
54299 var rect = exports.getSVGElement('rect', JSONcontainer, svgContainer);
54300 rect.setAttributeNS(null, "x", x - 0.5 * width);
54301 rect.setAttributeNS(null, "y", y);
54302 rect.setAttributeNS(null, "width", width);
54303 rect.setAttributeNS(null, "height", height);
54304 rect.setAttributeNS(null, "class", className);
54305
54306 if (style) {
54307 rect.setAttributeNS(null, "style", style);
54308 }
54309 }
54310 };
54311});
54312var DOMutil_1 = DOMutil.prepareElements;
54313var DOMutil_2 = DOMutil.cleanupElements;
54314var DOMutil_3 = DOMutil.resetElements;
54315var DOMutil_4 = DOMutil.getSVGElement;
54316var DOMutil_5 = DOMutil.getDOMElement;
54317var DOMutil_6 = DOMutil.drawPoint;
54318var DOMutil_7 = DOMutil.drawBar;
54319
54320var DOMutil$1 = /*#__PURE__*/Object.freeze({
54321 __proto__: null,
54322 'default': DOMutil,
54323 __moduleExports: DOMutil,
54324 prepareElements: DOMutil_1,
54325 cleanupElements: DOMutil_2,
54326 resetElements: DOMutil_3,
54327 getSVGElement: DOMutil_4,
54328 getDOMElement: DOMutil_5,
54329 drawPoint: DOMutil_6,
54330 drawBar: DOMutil_7
54331});
54332
54333var moment$2 = createCommonjsModule(function (module, exports) {
54334
54335 (function (global, factory) {
54336 module.exports = factory() ;
54337 })(commonjsGlobal, function () {
54338
54339 var hookCallback;
54340
54341 function hooks() {
54342 return hookCallback.apply(null, arguments);
54343 } // This is done to register the method called with moment()
54344 // without creating circular dependencies.
54345
54346
54347 function setHookCallback(callback) {
54348 hookCallback = callback;
54349 }
54350
54351 function isArray(input) {
54352 return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
54353 }
54354
54355 function isObject(input) {
54356 // IE8 will treat undefined and null as object if it wasn't for
54357 // input != null
54358 return input != null && Object.prototype.toString.call(input) === '[object Object]';
54359 }
54360
54361 function isObjectEmpty(obj) {
54362 if (Object.getOwnPropertyNames) {
54363 return Object.getOwnPropertyNames(obj).length === 0;
54364 } else {
54365 var k;
54366
54367 for (k in obj) {
54368 if (obj.hasOwnProperty(k)) {
54369 return false;
54370 }
54371 }
54372
54373 return true;
54374 }
54375 }
54376
54377 function isUndefined(input) {
54378 return input === void 0;
54379 }
54380
54381 function isNumber(input) {
54382 return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
54383 }
54384
54385 function isDate(input) {
54386 return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
54387 }
54388
54389 function map(arr, fn) {
54390 var res = [],
54391 i;
54392
54393 for (i = 0; i < arr.length; ++i) {
54394 res.push(fn(arr[i], i));
54395 }
54396
54397 return res;
54398 }
54399
54400 function hasOwnProp(a, b) {
54401 return Object.prototype.hasOwnProperty.call(a, b);
54402 }
54403
54404 function extend(a, b) {
54405 for (var i in b) {
54406 if (hasOwnProp(b, i)) {
54407 a[i] = b[i];
54408 }
54409 }
54410
54411 if (hasOwnProp(b, 'toString')) {
54412 a.toString = b.toString;
54413 }
54414
54415 if (hasOwnProp(b, 'valueOf')) {
54416 a.valueOf = b.valueOf;
54417 }
54418
54419 return a;
54420 }
54421
54422 function createUTC(input, format, locale, strict) {
54423 return createLocalOrUTC(input, format, locale, strict, true).utc();
54424 }
54425
54426 function defaultParsingFlags() {
54427 // We need to deep clone this object.
54428 return {
54429 empty: false,
54430 unusedTokens: [],
54431 unusedInput: [],
54432 overflow: -2,
54433 charsLeftOver: 0,
54434 nullInput: false,
54435 invalidMonth: null,
54436 invalidFormat: false,
54437 userInvalidated: false,
54438 iso: false,
54439 parsedDateParts: [],
54440 meridiem: null,
54441 rfc2822: false,
54442 weekdayMismatch: false
54443 };
54444 }
54445
54446 function getParsingFlags(m) {
54447 if (m._pf == null) {
54448 m._pf = defaultParsingFlags();
54449 }
54450
54451 return m._pf;
54452 }
54453
54454 var some;
54455
54456 if (Array.prototype.some) {
54457 some = Array.prototype.some;
54458 } else {
54459 some = function (fun) {
54460 var t = Object(this);
54461 var len = t.length >>> 0;
54462
54463 for (var i = 0; i < len; i++) {
54464 if (i in t && fun.call(this, t[i], i, t)) {
54465 return true;
54466 }
54467 }
54468
54469 return false;
54470 };
54471 }
54472
54473 function isValid(m) {
54474 if (m._isValid == null) {
54475 var flags = getParsingFlags(m);
54476 var parsedParts = some.call(flags.parsedDateParts, function (i) {
54477 return i != null;
54478 });
54479 var isNowValid = !isNaN(m._d.getTime()) && flags.overflow < 0 && !flags.empty && !flags.invalidMonth && !flags.invalidWeekday && !flags.weekdayMismatch && !flags.nullInput && !flags.invalidFormat && !flags.userInvalidated && (!flags.meridiem || flags.meridiem && parsedParts);
54480
54481 if (m._strict) {
54482 isNowValid = isNowValid && flags.charsLeftOver === 0 && flags.unusedTokens.length === 0 && flags.bigHour === undefined;
54483 }
54484
54485 if (Object.isFrozen == null || !Object.isFrozen(m)) {
54486 m._isValid = isNowValid;
54487 } else {
54488 return isNowValid;
54489 }
54490 }
54491
54492 return m._isValid;
54493 }
54494
54495 function createInvalid(flags) {
54496 var m = createUTC(NaN);
54497
54498 if (flags != null) {
54499 extend(getParsingFlags(m), flags);
54500 } else {
54501 getParsingFlags(m).userInvalidated = true;
54502 }
54503
54504 return m;
54505 } // Plugins that add properties should also add the key here (null value),
54506 // so we can properly clone ourselves.
54507
54508
54509 var momentProperties = hooks.momentProperties = [];
54510
54511 function copyConfig(to, from) {
54512 var i, prop, val;
54513
54514 if (!isUndefined(from._isAMomentObject)) {
54515 to._isAMomentObject = from._isAMomentObject;
54516 }
54517
54518 if (!isUndefined(from._i)) {
54519 to._i = from._i;
54520 }
54521
54522 if (!isUndefined(from._f)) {
54523 to._f = from._f;
54524 }
54525
54526 if (!isUndefined(from._l)) {
54527 to._l = from._l;
54528 }
54529
54530 if (!isUndefined(from._strict)) {
54531 to._strict = from._strict;
54532 }
54533
54534 if (!isUndefined(from._tzm)) {
54535 to._tzm = from._tzm;
54536 }
54537
54538 if (!isUndefined(from._isUTC)) {
54539 to._isUTC = from._isUTC;
54540 }
54541
54542 if (!isUndefined(from._offset)) {
54543 to._offset = from._offset;
54544 }
54545
54546 if (!isUndefined(from._pf)) {
54547 to._pf = getParsingFlags(from);
54548 }
54549
54550 if (!isUndefined(from._locale)) {
54551 to._locale = from._locale;
54552 }
54553
54554 if (momentProperties.length > 0) {
54555 for (i = 0; i < momentProperties.length; i++) {
54556 prop = momentProperties[i];
54557 val = from[prop];
54558
54559 if (!isUndefined(val)) {
54560 to[prop] = val;
54561 }
54562 }
54563 }
54564
54565 return to;
54566 }
54567
54568 var updateInProgress = false; // Moment prototype object
54569
54570 function Moment(config) {
54571 copyConfig(this, config);
54572 this._d = new Date(config._d != null ? config._d.getTime() : NaN);
54573
54574 if (!this.isValid()) {
54575 this._d = new Date(NaN);
54576 } // Prevent infinite loop in case updateOffset creates new moment
54577 // objects.
54578
54579
54580 if (updateInProgress === false) {
54581 updateInProgress = true;
54582 hooks.updateOffset(this);
54583 updateInProgress = false;
54584 }
54585 }
54586
54587 function isMoment(obj) {
54588 return obj instanceof Moment || obj != null && obj._isAMomentObject != null;
54589 }
54590
54591 function absFloor(number) {
54592 if (number < 0) {
54593 // -0 -> 0
54594 return Math.ceil(number) || 0;
54595 } else {
54596 return Math.floor(number);
54597 }
54598 }
54599
54600 function toInt(argumentForCoercion) {
54601 var coercedNumber = +argumentForCoercion,
54602 value = 0;
54603
54604 if (coercedNumber !== 0 && isFinite(coercedNumber)) {
54605 value = absFloor(coercedNumber);
54606 }
54607
54608 return value;
54609 } // compare two arrays, return the number of differences
54610
54611
54612 function compareArrays(array1, array2, dontConvert) {
54613 var len = Math.min(array1.length, array2.length),
54614 lengthDiff = Math.abs(array1.length - array2.length),
54615 diffs = 0,
54616 i;
54617
54618 for (i = 0; i < len; i++) {
54619 if (dontConvert && array1[i] !== array2[i] || !dontConvert && toInt(array1[i]) !== toInt(array2[i])) {
54620 diffs++;
54621 }
54622 }
54623
54624 return diffs + lengthDiff;
54625 }
54626
54627 function warn(msg) {
54628 if (hooks.suppressDeprecationWarnings === false && typeof console !== 'undefined' && console.warn) {
54629 console.warn('Deprecation warning: ' + msg);
54630 }
54631 }
54632
54633 function deprecate(msg, fn) {
54634 var firstTime = true;
54635 return extend(function () {
54636 if (hooks.deprecationHandler != null) {
54637 hooks.deprecationHandler(null, msg);
54638 }
54639
54640 if (firstTime) {
54641 var args = [];
54642 var arg;
54643
54644 for (var i = 0; i < arguments.length; i++) {
54645 arg = '';
54646
54647 if (typeof arguments[i] === 'object') {
54648 arg += '\n[' + i + '] ';
54649
54650 for (var key in arguments[0]) {
54651 arg += key + ': ' + arguments[0][key] + ', ';
54652 }
54653
54654 arg = arg.slice(0, -2); // Remove trailing comma and space
54655 } else {
54656 arg = arguments[i];
54657 }
54658
54659 args.push(arg);
54660 }
54661
54662 warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + new Error().stack);
54663 firstTime = false;
54664 }
54665
54666 return fn.apply(this, arguments);
54667 }, fn);
54668 }
54669
54670 var deprecations = {};
54671
54672 function deprecateSimple(name, msg) {
54673 if (hooks.deprecationHandler != null) {
54674 hooks.deprecationHandler(name, msg);
54675 }
54676
54677 if (!deprecations[name]) {
54678 warn(msg);
54679 deprecations[name] = true;
54680 }
54681 }
54682
54683 hooks.suppressDeprecationWarnings = false;
54684 hooks.deprecationHandler = null;
54685
54686 function isFunction(input) {
54687 return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
54688 }
54689
54690 function set(config) {
54691 var prop, i;
54692
54693 for (i in config) {
54694 prop = config[i];
54695
54696 if (isFunction(prop)) {
54697 this[i] = prop;
54698 } else {
54699 this['_' + i] = prop;
54700 }
54701 }
54702
54703 this._config = config; // Lenient ordinal parsing accepts just a number in addition to
54704 // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
54705 // TODO: Remove "ordinalParse" fallback in next major release.
54706
54707 this._dayOfMonthOrdinalParseLenient = new RegExp((this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) + '|' + /\d{1,2}/.source);
54708 }
54709
54710 function mergeConfigs(parentConfig, childConfig) {
54711 var res = extend({}, parentConfig),
54712 prop;
54713
54714 for (prop in childConfig) {
54715 if (hasOwnProp(childConfig, prop)) {
54716 if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
54717 res[prop] = {};
54718 extend(res[prop], parentConfig[prop]);
54719 extend(res[prop], childConfig[prop]);
54720 } else if (childConfig[prop] != null) {
54721 res[prop] = childConfig[prop];
54722 } else {
54723 delete res[prop];
54724 }
54725 }
54726 }
54727
54728 for (prop in parentConfig) {
54729 if (hasOwnProp(parentConfig, prop) && !hasOwnProp(childConfig, prop) && isObject(parentConfig[prop])) {
54730 // make sure changes to properties don't modify parent config
54731 res[prop] = extend({}, res[prop]);
54732 }
54733 }
54734
54735 return res;
54736 }
54737
54738 function Locale(config) {
54739 if (config != null) {
54740 this.set(config);
54741 }
54742 }
54743
54744 var keys;
54745
54746 if (Object.keys) {
54747 keys = Object.keys;
54748 } else {
54749 keys = function (obj) {
54750 var i,
54751 res = [];
54752
54753 for (i in obj) {
54754 if (hasOwnProp(obj, i)) {
54755 res.push(i);
54756 }
54757 }
54758
54759 return res;
54760 };
54761 }
54762
54763 var defaultCalendar = {
54764 sameDay: '[Today at] LT',
54765 nextDay: '[Tomorrow at] LT',
54766 nextWeek: 'dddd [at] LT',
54767 lastDay: '[Yesterday at] LT',
54768 lastWeek: '[Last] dddd [at] LT',
54769 sameElse: 'L'
54770 };
54771
54772 function calendar(key, mom, now) {
54773 var output = this._calendar[key] || this._calendar['sameElse'];
54774 return isFunction(output) ? output.call(mom, now) : output;
54775 }
54776
54777 var defaultLongDateFormat = {
54778 LTS: 'h:mm:ss A',
54779 LT: 'h:mm A',
54780 L: 'MM/DD/YYYY',
54781 LL: 'MMMM D, YYYY',
54782 LLL: 'MMMM D, YYYY h:mm A',
54783 LLLL: 'dddd, MMMM D, YYYY h:mm A'
54784 };
54785
54786 function longDateFormat(key) {
54787 var format = this._longDateFormat[key],
54788 formatUpper = this._longDateFormat[key.toUpperCase()];
54789
54790 if (format || !formatUpper) {
54791 return format;
54792 }
54793
54794 this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
54795 return val.slice(1);
54796 });
54797 return this._longDateFormat[key];
54798 }
54799
54800 var defaultInvalidDate = 'Invalid date';
54801
54802 function invalidDate() {
54803 return this._invalidDate;
54804 }
54805
54806 var defaultOrdinal = '%d';
54807 var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
54808
54809 function ordinal(number) {
54810 return this._ordinal.replace('%d', number);
54811 }
54812
54813 var defaultRelativeTime = {
54814 future: 'in %s',
54815 past: '%s ago',
54816 s: 'a few seconds',
54817 ss: '%d seconds',
54818 m: 'a minute',
54819 mm: '%d minutes',
54820 h: 'an hour',
54821 hh: '%d hours',
54822 d: 'a day',
54823 dd: '%d days',
54824 M: 'a month',
54825 MM: '%d months',
54826 y: 'a year',
54827 yy: '%d years'
54828 };
54829
54830 function relativeTime(number, withoutSuffix, string, isFuture) {
54831 var output = this._relativeTime[string];
54832 return isFunction(output) ? output(number, withoutSuffix, string, isFuture) : output.replace(/%d/i, number);
54833 }
54834
54835 function pastFuture(diff, output) {
54836 var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
54837 return isFunction(format) ? format(output) : format.replace(/%s/i, output);
54838 }
54839
54840 var aliases = {};
54841
54842 function addUnitAlias(unit, shorthand) {
54843 var lowerCase = unit.toLowerCase();
54844 aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
54845 }
54846
54847 function normalizeUnits(units) {
54848 return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
54849 }
54850
54851 function normalizeObjectUnits(inputObject) {
54852 var normalizedInput = {},
54853 normalizedProp,
54854 prop;
54855
54856 for (prop in inputObject) {
54857 if (hasOwnProp(inputObject, prop)) {
54858 normalizedProp = normalizeUnits(prop);
54859
54860 if (normalizedProp) {
54861 normalizedInput[normalizedProp] = inputObject[prop];
54862 }
54863 }
54864 }
54865
54866 return normalizedInput;
54867 }
54868
54869 var priorities = {};
54870
54871 function addUnitPriority(unit, priority) {
54872 priorities[unit] = priority;
54873 }
54874
54875 function getPrioritizedUnits(unitsObj) {
54876 var units = [];
54877
54878 for (var u in unitsObj) {
54879 units.push({
54880 unit: u,
54881 priority: priorities[u]
54882 });
54883 }
54884
54885 units.sort(function (a, b) {
54886 return a.priority - b.priority;
54887 });
54888 return units;
54889 }
54890
54891 function zeroFill(number, targetLength, forceSign) {
54892 var absNumber = '' + Math.abs(number),
54893 zerosToFill = targetLength - absNumber.length,
54894 sign = number >= 0;
54895 return (sign ? forceSign ? '+' : '' : '-') + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
54896 }
54897
54898 var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
54899 var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
54900 var formatFunctions = {};
54901 var formatTokenFunctions = {}; // token: 'M'
54902 // padded: ['MM', 2]
54903 // ordinal: 'Mo'
54904 // callback: function () { this.month() + 1 }
54905
54906 function addFormatToken(token, padded, ordinal, callback) {
54907 var func = callback;
54908
54909 if (typeof callback === 'string') {
54910 func = function () {
54911 return this[callback]();
54912 };
54913 }
54914
54915 if (token) {
54916 formatTokenFunctions[token] = func;
54917 }
54918
54919 if (padded) {
54920 formatTokenFunctions[padded[0]] = function () {
54921 return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
54922 };
54923 }
54924
54925 if (ordinal) {
54926 formatTokenFunctions[ordinal] = function () {
54927 return this.localeData().ordinal(func.apply(this, arguments), token);
54928 };
54929 }
54930 }
54931
54932 function removeFormattingTokens(input) {
54933 if (input.match(/\[[\s\S]/)) {
54934 return input.replace(/^\[|\]$/g, '');
54935 }
54936
54937 return input.replace(/\\/g, '');
54938 }
54939
54940 function makeFormatFunction(format) {
54941 var array = format.match(formattingTokens),
54942 i,
54943 length;
54944
54945 for (i = 0, length = array.length; i < length; i++) {
54946 if (formatTokenFunctions[array[i]]) {
54947 array[i] = formatTokenFunctions[array[i]];
54948 } else {
54949 array[i] = removeFormattingTokens(array[i]);
54950 }
54951 }
54952
54953 return function (mom) {
54954 var output = '',
54955 i;
54956
54957 for (i = 0; i < length; i++) {
54958 output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
54959 }
54960
54961 return output;
54962 };
54963 } // format date using native date object
54964
54965
54966 function formatMoment(m, format) {
54967 if (!m.isValid()) {
54968 return m.localeData().invalidDate();
54969 }
54970
54971 format = expandFormat(format, m.localeData());
54972 formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
54973 return formatFunctions[format](m);
54974 }
54975
54976 function expandFormat(format, locale) {
54977 var i = 5;
54978
54979 function replaceLongDateFormatTokens(input) {
54980 return locale.longDateFormat(input) || input;
54981 }
54982
54983 localFormattingTokens.lastIndex = 0;
54984
54985 while (i >= 0 && localFormattingTokens.test(format)) {
54986 format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
54987 localFormattingTokens.lastIndex = 0;
54988 i -= 1;
54989 }
54990
54991 return format;
54992 }
54993
54994 var match1 = /\d/; // 0 - 9
54995
54996 var match2 = /\d\d/; // 00 - 99
54997
54998 var match3 = /\d{3}/; // 000 - 999
54999
55000 var match4 = /\d{4}/; // 0000 - 9999
55001
55002 var match6 = /[+-]?\d{6}/; // -999999 - 999999
55003
55004 var match1to2 = /\d\d?/; // 0 - 99
55005
55006 var match3to4 = /\d\d\d\d?/; // 999 - 9999
55007
55008 var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999
55009
55010 var match1to3 = /\d{1,3}/; // 0 - 999
55011
55012 var match1to4 = /\d{1,4}/; // 0 - 9999
55013
55014 var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
55015
55016 var matchUnsigned = /\d+/; // 0 - inf
55017
55018 var matchSigned = /[+-]?\d+/; // -inf - inf
55019
55020 var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
55021
55022 var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
55023
55024 var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
55025 // any word (or two) characters or numbers including two/three word month in arabic.
55026 // includes scottish gaelic two word and hyphenated months
55027
55028 var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
55029 var regexes = {};
55030
55031 function addRegexToken(token, regex, strictRegex) {
55032 regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
55033 return isStrict && strictRegex ? strictRegex : regex;
55034 };
55035 }
55036
55037 function getParseRegexForToken(token, config) {
55038 if (!hasOwnProp(regexes, token)) {
55039 return new RegExp(unescapeFormat(token));
55040 }
55041
55042 return regexes[token](config._strict, config._locale);
55043 } // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
55044
55045
55046 function unescapeFormat(s) {
55047 return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
55048 return p1 || p2 || p3 || p4;
55049 }));
55050 }
55051
55052 function regexEscape(s) {
55053 return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
55054 }
55055
55056 var tokens = {};
55057
55058 function addParseToken(token, callback) {
55059 var i,
55060 func = callback;
55061
55062 if (typeof token === 'string') {
55063 token = [token];
55064 }
55065
55066 if (isNumber(callback)) {
55067 func = function (input, array) {
55068 array[callback] = toInt(input);
55069 };
55070 }
55071
55072 for (i = 0; i < token.length; i++) {
55073 tokens[token[i]] = func;
55074 }
55075 }
55076
55077 function addWeekParseToken(token, callback) {
55078 addParseToken(token, function (input, array, config, token) {
55079 config._w = config._w || {};
55080 callback(input, config._w, config, token);
55081 });
55082 }
55083
55084 function addTimeToArrayFromToken(token, input, config) {
55085 if (input != null && hasOwnProp(tokens, token)) {
55086 tokens[token](input, config._a, config, token);
55087 }
55088 }
55089
55090 var YEAR = 0;
55091 var MONTH = 1;
55092 var DATE = 2;
55093 var HOUR = 3;
55094 var MINUTE = 4;
55095 var SECOND = 5;
55096 var MILLISECOND = 6;
55097 var WEEK = 7;
55098 var WEEKDAY = 8; // FORMATTING
55099
55100 addFormatToken('Y', 0, 0, function () {
55101 var y = this.year();
55102 return y <= 9999 ? '' + y : '+' + y;
55103 });
55104 addFormatToken(0, ['YY', 2], 0, function () {
55105 return this.year() % 100;
55106 });
55107 addFormatToken(0, ['YYYY', 4], 0, 'year');
55108 addFormatToken(0, ['YYYYY', 5], 0, 'year');
55109 addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); // ALIASES
55110
55111 addUnitAlias('year', 'y'); // PRIORITIES
55112
55113 addUnitPriority('year', 1); // PARSING
55114
55115 addRegexToken('Y', matchSigned);
55116 addRegexToken('YY', match1to2, match2);
55117 addRegexToken('YYYY', match1to4, match4);
55118 addRegexToken('YYYYY', match1to6, match6);
55119 addRegexToken('YYYYYY', match1to6, match6);
55120 addParseToken(['YYYYY', 'YYYYYY'], YEAR);
55121 addParseToken('YYYY', function (input, array) {
55122 array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
55123 });
55124 addParseToken('YY', function (input, array) {
55125 array[YEAR] = hooks.parseTwoDigitYear(input);
55126 });
55127 addParseToken('Y', function (input, array) {
55128 array[YEAR] = parseInt(input, 10);
55129 }); // HELPERS
55130
55131 function daysInYear(year) {
55132 return isLeapYear(year) ? 366 : 365;
55133 }
55134
55135 function isLeapYear(year) {
55136 return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
55137 } // HOOKS
55138
55139
55140 hooks.parseTwoDigitYear = function (input) {
55141 return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
55142 }; // MOMENTS
55143
55144
55145 var getSetYear = makeGetSet('FullYear', true);
55146
55147 function getIsLeapYear() {
55148 return isLeapYear(this.year());
55149 }
55150
55151 function makeGetSet(unit, keepTime) {
55152 return function (value) {
55153 if (value != null) {
55154 set$1(this, unit, value);
55155 hooks.updateOffset(this, keepTime);
55156 return this;
55157 } else {
55158 return get(this, unit);
55159 }
55160 };
55161 }
55162
55163 function get(mom, unit) {
55164 return mom.isValid() ? mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
55165 }
55166
55167 function set$1(mom, unit, value) {
55168 if (mom.isValid() && !isNaN(value)) {
55169 if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
55170 mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
55171 } else {
55172 mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
55173 }
55174 }
55175 } // MOMENTS
55176
55177
55178 function stringGet(units) {
55179 units = normalizeUnits(units);
55180
55181 if (isFunction(this[units])) {
55182 return this[units]();
55183 }
55184
55185 return this;
55186 }
55187
55188 function stringSet(units, value) {
55189 if (typeof units === 'object') {
55190 units = normalizeObjectUnits(units);
55191 var prioritized = getPrioritizedUnits(units);
55192
55193 for (var i = 0; i < prioritized.length; i++) {
55194 this[prioritized[i].unit](units[prioritized[i].unit]);
55195 }
55196 } else {
55197 units = normalizeUnits(units);
55198
55199 if (isFunction(this[units])) {
55200 return this[units](value);
55201 }
55202 }
55203
55204 return this;
55205 }
55206
55207 function mod(n, x) {
55208 return (n % x + x) % x;
55209 }
55210
55211 var indexOf;
55212
55213 if (Array.prototype.indexOf) {
55214 indexOf = Array.prototype.indexOf;
55215 } else {
55216 indexOf = function (o) {
55217 // I know
55218 var i;
55219
55220 for (i = 0; i < this.length; ++i) {
55221 if (this[i] === o) {
55222 return i;
55223 }
55224 }
55225
55226 return -1;
55227 };
55228 }
55229
55230 function daysInMonth(year, month) {
55231 if (isNaN(year) || isNaN(month)) {
55232 return NaN;
55233 }
55234
55235 var modMonth = mod(month, 12);
55236 year += (month - modMonth) / 12;
55237 return modMonth === 1 ? isLeapYear(year) ? 29 : 28 : 31 - modMonth % 7 % 2;
55238 } // FORMATTING
55239
55240
55241 addFormatToken('M', ['MM', 2], 'Mo', function () {
55242 return this.month() + 1;
55243 });
55244 addFormatToken('MMM', 0, 0, function (format) {
55245 return this.localeData().monthsShort(this, format);
55246 });
55247 addFormatToken('MMMM', 0, 0, function (format) {
55248 return this.localeData().months(this, format);
55249 }); // ALIASES
55250
55251 addUnitAlias('month', 'M'); // PRIORITY
55252
55253 addUnitPriority('month', 8); // PARSING
55254
55255 addRegexToken('M', match1to2);
55256 addRegexToken('MM', match1to2, match2);
55257 addRegexToken('MMM', function (isStrict, locale) {
55258 return locale.monthsShortRegex(isStrict);
55259 });
55260 addRegexToken('MMMM', function (isStrict, locale) {
55261 return locale.monthsRegex(isStrict);
55262 });
55263 addParseToken(['M', 'MM'], function (input, array) {
55264 array[MONTH] = toInt(input) - 1;
55265 });
55266 addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
55267 var month = config._locale.monthsParse(input, token, config._strict); // if we didn't find a month name, mark the date as invalid.
55268
55269
55270 if (month != null) {
55271 array[MONTH] = month;
55272 } else {
55273 getParsingFlags(config).invalidMonth = input;
55274 }
55275 }); // LOCALES
55276
55277 var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
55278 var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
55279
55280 function localeMonths(m, format) {
55281 if (!m) {
55282 return isArray(this._months) ? this._months : this._months['standalone'];
55283 }
55284
55285 return isArray(this._months) ? this._months[m.month()] : this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
55286 }
55287
55288 var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
55289
55290 function localeMonthsShort(m, format) {
55291 if (!m) {
55292 return isArray(this._monthsShort) ? this._monthsShort : this._monthsShort['standalone'];
55293 }
55294
55295 return isArray(this._monthsShort) ? this._monthsShort[m.month()] : this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
55296 }
55297
55298 function handleStrictParse(monthName, format, strict) {
55299 var i,
55300 ii,
55301 mom,
55302 llc = monthName.toLocaleLowerCase();
55303
55304 if (!this._monthsParse) {
55305 // this is not used
55306 this._monthsParse = [];
55307 this._longMonthsParse = [];
55308 this._shortMonthsParse = [];
55309
55310 for (i = 0; i < 12; ++i) {
55311 mom = createUTC([2000, i]);
55312 this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
55313 this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
55314 }
55315 }
55316
55317 if (strict) {
55318 if (format === 'MMM') {
55319 ii = indexOf.call(this._shortMonthsParse, llc);
55320 return ii !== -1 ? ii : null;
55321 } else {
55322 ii = indexOf.call(this._longMonthsParse, llc);
55323 return ii !== -1 ? ii : null;
55324 }
55325 } else {
55326 if (format === 'MMM') {
55327 ii = indexOf.call(this._shortMonthsParse, llc);
55328
55329 if (ii !== -1) {
55330 return ii;
55331 }
55332
55333 ii = indexOf.call(this._longMonthsParse, llc);
55334 return ii !== -1 ? ii : null;
55335 } else {
55336 ii = indexOf.call(this._longMonthsParse, llc);
55337
55338 if (ii !== -1) {
55339 return ii;
55340 }
55341
55342 ii = indexOf.call(this._shortMonthsParse, llc);
55343 return ii !== -1 ? ii : null;
55344 }
55345 }
55346 }
55347
55348 function localeMonthsParse(monthName, format, strict) {
55349 var i, mom, regex;
55350
55351 if (this._monthsParseExact) {
55352 return handleStrictParse.call(this, monthName, format, strict);
55353 }
55354
55355 if (!this._monthsParse) {
55356 this._monthsParse = [];
55357 this._longMonthsParse = [];
55358 this._shortMonthsParse = [];
55359 } // TODO: add sorting
55360 // Sorting makes sure if one month (or abbr) is a prefix of another
55361 // see sorting in computeMonthsParse
55362
55363
55364 for (i = 0; i < 12; i++) {
55365 // make the regex if we don't have it already
55366 mom = createUTC([2000, i]);
55367
55368 if (strict && !this._longMonthsParse[i]) {
55369 this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
55370 this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
55371 }
55372
55373 if (!strict && !this._monthsParse[i]) {
55374 regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
55375 this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
55376 } // test the regex
55377
55378
55379 if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
55380 return i;
55381 } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
55382 return i;
55383 } else if (!strict && this._monthsParse[i].test(monthName)) {
55384 return i;
55385 }
55386 }
55387 } // MOMENTS
55388
55389
55390 function setMonth(mom, value) {
55391 var dayOfMonth;
55392
55393 if (!mom.isValid()) {
55394 // No op
55395 return mom;
55396 }
55397
55398 if (typeof value === 'string') {
55399 if (/^\d+$/.test(value)) {
55400 value = toInt(value);
55401 } else {
55402 value = mom.localeData().monthsParse(value); // TODO: Another silent failure?
55403
55404 if (!isNumber(value)) {
55405 return mom;
55406 }
55407 }
55408 }
55409
55410 dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
55411
55412 mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
55413
55414 return mom;
55415 }
55416
55417 function getSetMonth(value) {
55418 if (value != null) {
55419 setMonth(this, value);
55420 hooks.updateOffset(this, true);
55421 return this;
55422 } else {
55423 return get(this, 'Month');
55424 }
55425 }
55426
55427 function getDaysInMonth() {
55428 return daysInMonth(this.year(), this.month());
55429 }
55430
55431 var defaultMonthsShortRegex = matchWord;
55432
55433 function monthsShortRegex(isStrict) {
55434 if (this._monthsParseExact) {
55435 if (!hasOwnProp(this, '_monthsRegex')) {
55436 computeMonthsParse.call(this);
55437 }
55438
55439 if (isStrict) {
55440 return this._monthsShortStrictRegex;
55441 } else {
55442 return this._monthsShortRegex;
55443 }
55444 } else {
55445 if (!hasOwnProp(this, '_monthsShortRegex')) {
55446 this._monthsShortRegex = defaultMonthsShortRegex;
55447 }
55448
55449 return this._monthsShortStrictRegex && isStrict ? this._monthsShortStrictRegex : this._monthsShortRegex;
55450 }
55451 }
55452
55453 var defaultMonthsRegex = matchWord;
55454
55455 function monthsRegex(isStrict) {
55456 if (this._monthsParseExact) {
55457 if (!hasOwnProp(this, '_monthsRegex')) {
55458 computeMonthsParse.call(this);
55459 }
55460
55461 if (isStrict) {
55462 return this._monthsStrictRegex;
55463 } else {
55464 return this._monthsRegex;
55465 }
55466 } else {
55467 if (!hasOwnProp(this, '_monthsRegex')) {
55468 this._monthsRegex = defaultMonthsRegex;
55469 }
55470
55471 return this._monthsStrictRegex && isStrict ? this._monthsStrictRegex : this._monthsRegex;
55472 }
55473 }
55474
55475 function computeMonthsParse() {
55476 function cmpLenRev(a, b) {
55477 return b.length - a.length;
55478 }
55479
55480 var shortPieces = [],
55481 longPieces = [],
55482 mixedPieces = [],
55483 i,
55484 mom;
55485
55486 for (i = 0; i < 12; i++) {
55487 // make the regex if we don't have it already
55488 mom = createUTC([2000, i]);
55489 shortPieces.push(this.monthsShort(mom, ''));
55490 longPieces.push(this.months(mom, ''));
55491 mixedPieces.push(this.months(mom, ''));
55492 mixedPieces.push(this.monthsShort(mom, ''));
55493 } // Sorting makes sure if one month (or abbr) is a prefix of another it
55494 // will match the longer piece.
55495
55496
55497 shortPieces.sort(cmpLenRev);
55498 longPieces.sort(cmpLenRev);
55499 mixedPieces.sort(cmpLenRev);
55500
55501 for (i = 0; i < 12; i++) {
55502 shortPieces[i] = regexEscape(shortPieces[i]);
55503 longPieces[i] = regexEscape(longPieces[i]);
55504 }
55505
55506 for (i = 0; i < 24; i++) {
55507 mixedPieces[i] = regexEscape(mixedPieces[i]);
55508 }
55509
55510 this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
55511 this._monthsShortRegex = this._monthsRegex;
55512 this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
55513 this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
55514 }
55515
55516 function createDate(y, m, d, h, M, s, ms) {
55517 // can't just apply() to create a date:
55518 // https://stackoverflow.com/q/181348
55519 var date; // the date constructor remaps years 0-99 to 1900-1999
55520
55521 if (y < 100 && y >= 0) {
55522 // preserve leap years using a full 400 year cycle, then reset
55523 date = new Date(y + 400, m, d, h, M, s, ms);
55524
55525 if (isFinite(date.getFullYear())) {
55526 date.setFullYear(y);
55527 }
55528 } else {
55529 date = new Date(y, m, d, h, M, s, ms);
55530 }
55531
55532 return date;
55533 }
55534
55535 function createUTCDate(y) {
55536 var date; // the Date.UTC function remaps years 0-99 to 1900-1999
55537
55538 if (y < 100 && y >= 0) {
55539 var args = Array.prototype.slice.call(arguments); // preserve leap years using a full 400 year cycle, then reset
55540
55541 args[0] = y + 400;
55542 date = new Date(Date.UTC.apply(null, args));
55543
55544 if (isFinite(date.getUTCFullYear())) {
55545 date.setUTCFullYear(y);
55546 }
55547 } else {
55548 date = new Date(Date.UTC.apply(null, arguments));
55549 }
55550
55551 return date;
55552 } // start-of-first-week - start-of-year
55553
55554
55555 function firstWeekOffset(year, dow, doy) {
55556 var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
55557 fwd = 7 + dow - doy,
55558 // first-week day local weekday -- which local weekday is fwd
55559 fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
55560 return -fwdlw + fwd - 1;
55561 } // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
55562
55563
55564 function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
55565 var localWeekday = (7 + weekday - dow) % 7,
55566 weekOffset = firstWeekOffset(year, dow, doy),
55567 dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
55568 resYear,
55569 resDayOfYear;
55570
55571 if (dayOfYear <= 0) {
55572 resYear = year - 1;
55573 resDayOfYear = daysInYear(resYear) + dayOfYear;
55574 } else if (dayOfYear > daysInYear(year)) {
55575 resYear = year + 1;
55576 resDayOfYear = dayOfYear - daysInYear(year);
55577 } else {
55578 resYear = year;
55579 resDayOfYear = dayOfYear;
55580 }
55581
55582 return {
55583 year: resYear,
55584 dayOfYear: resDayOfYear
55585 };
55586 }
55587
55588 function weekOfYear(mom, dow, doy) {
55589 var weekOffset = firstWeekOffset(mom.year(), dow, doy),
55590 week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
55591 resWeek,
55592 resYear;
55593
55594 if (week < 1) {
55595 resYear = mom.year() - 1;
55596 resWeek = week + weeksInYear(resYear, dow, doy);
55597 } else if (week > weeksInYear(mom.year(), dow, doy)) {
55598 resWeek = week - weeksInYear(mom.year(), dow, doy);
55599 resYear = mom.year() + 1;
55600 } else {
55601 resYear = mom.year();
55602 resWeek = week;
55603 }
55604
55605 return {
55606 week: resWeek,
55607 year: resYear
55608 };
55609 }
55610
55611 function weeksInYear(year, dow, doy) {
55612 var weekOffset = firstWeekOffset(year, dow, doy),
55613 weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
55614 return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
55615 } // FORMATTING
55616
55617
55618 addFormatToken('w', ['ww', 2], 'wo', 'week');
55619 addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); // ALIASES
55620
55621 addUnitAlias('week', 'w');
55622 addUnitAlias('isoWeek', 'W'); // PRIORITIES
55623
55624 addUnitPriority('week', 5);
55625 addUnitPriority('isoWeek', 5); // PARSING
55626
55627 addRegexToken('w', match1to2);
55628 addRegexToken('ww', match1to2, match2);
55629 addRegexToken('W', match1to2);
55630 addRegexToken('WW', match1to2, match2);
55631 addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
55632 week[token.substr(0, 1)] = toInt(input);
55633 }); // HELPERS
55634 // LOCALES
55635
55636 function localeWeek(mom) {
55637 return weekOfYear(mom, this._week.dow, this._week.doy).week;
55638 }
55639
55640 var defaultLocaleWeek = {
55641 dow: 0,
55642 // Sunday is the first day of the week.
55643 doy: 6 // The week that contains Jan 6th is the first week of the year.
55644
55645 };
55646
55647 function localeFirstDayOfWeek() {
55648 return this._week.dow;
55649 }
55650
55651 function localeFirstDayOfYear() {
55652 return this._week.doy;
55653 } // MOMENTS
55654
55655
55656 function getSetWeek(input) {
55657 var week = this.localeData().week(this);
55658 return input == null ? week : this.add((input - week) * 7, 'd');
55659 }
55660
55661 function getSetISOWeek(input) {
55662 var week = weekOfYear(this, 1, 4).week;
55663 return input == null ? week : this.add((input - week) * 7, 'd');
55664 } // FORMATTING
55665
55666
55667 addFormatToken('d', 0, 'do', 'day');
55668 addFormatToken('dd', 0, 0, function (format) {
55669 return this.localeData().weekdaysMin(this, format);
55670 });
55671 addFormatToken('ddd', 0, 0, function (format) {
55672 return this.localeData().weekdaysShort(this, format);
55673 });
55674 addFormatToken('dddd', 0, 0, function (format) {
55675 return this.localeData().weekdays(this, format);
55676 });
55677 addFormatToken('e', 0, 0, 'weekday');
55678 addFormatToken('E', 0, 0, 'isoWeekday'); // ALIASES
55679
55680 addUnitAlias('day', 'd');
55681 addUnitAlias('weekday', 'e');
55682 addUnitAlias('isoWeekday', 'E'); // PRIORITY
55683
55684 addUnitPriority('day', 11);
55685 addUnitPriority('weekday', 11);
55686 addUnitPriority('isoWeekday', 11); // PARSING
55687
55688 addRegexToken('d', match1to2);
55689 addRegexToken('e', match1to2);
55690 addRegexToken('E', match1to2);
55691 addRegexToken('dd', function (isStrict, locale) {
55692 return locale.weekdaysMinRegex(isStrict);
55693 });
55694 addRegexToken('ddd', function (isStrict, locale) {
55695 return locale.weekdaysShortRegex(isStrict);
55696 });
55697 addRegexToken('dddd', function (isStrict, locale) {
55698 return locale.weekdaysRegex(isStrict);
55699 });
55700 addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
55701 var weekday = config._locale.weekdaysParse(input, token, config._strict); // if we didn't get a weekday name, mark the date as invalid
55702
55703
55704 if (weekday != null) {
55705 week.d = weekday;
55706 } else {
55707 getParsingFlags(config).invalidWeekday = input;
55708 }
55709 });
55710 addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
55711 week[token] = toInt(input);
55712 }); // HELPERS
55713
55714 function parseWeekday(input, locale) {
55715 if (typeof input !== 'string') {
55716 return input;
55717 }
55718
55719 if (!isNaN(input)) {
55720 return parseInt(input, 10);
55721 }
55722
55723 input = locale.weekdaysParse(input);
55724
55725 if (typeof input === 'number') {
55726 return input;
55727 }
55728
55729 return null;
55730 }
55731
55732 function parseIsoWeekday(input, locale) {
55733 if (typeof input === 'string') {
55734 return locale.weekdaysParse(input) % 7 || 7;
55735 }
55736
55737 return isNaN(input) ? null : input;
55738 } // LOCALES
55739
55740
55741 function shiftWeekdays(ws, n) {
55742 return ws.slice(n, 7).concat(ws.slice(0, n));
55743 }
55744
55745 var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
55746
55747 function localeWeekdays(m, format) {
55748 var weekdays = isArray(this._weekdays) ? this._weekdays : this._weekdays[m && m !== true && this._weekdays.isFormat.test(format) ? 'format' : 'standalone'];
55749 return m === true ? shiftWeekdays(weekdays, this._week.dow) : m ? weekdays[m.day()] : weekdays;
55750 }
55751
55752 var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
55753
55754 function localeWeekdaysShort(m) {
55755 return m === true ? shiftWeekdays(this._weekdaysShort, this._week.dow) : m ? this._weekdaysShort[m.day()] : this._weekdaysShort;
55756 }
55757
55758 var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
55759
55760 function localeWeekdaysMin(m) {
55761 return m === true ? shiftWeekdays(this._weekdaysMin, this._week.dow) : m ? this._weekdaysMin[m.day()] : this._weekdaysMin;
55762 }
55763
55764 function handleStrictParse$1(weekdayName, format, strict) {
55765 var i,
55766 ii,
55767 mom,
55768 llc = weekdayName.toLocaleLowerCase();
55769
55770 if (!this._weekdaysParse) {
55771 this._weekdaysParse = [];
55772 this._shortWeekdaysParse = [];
55773 this._minWeekdaysParse = [];
55774
55775 for (i = 0; i < 7; ++i) {
55776 mom = createUTC([2000, 1]).day(i);
55777 this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
55778 this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
55779 this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
55780 }
55781 }
55782
55783 if (strict) {
55784 if (format === 'dddd') {
55785 ii = indexOf.call(this._weekdaysParse, llc);
55786 return ii !== -1 ? ii : null;
55787 } else if (format === 'ddd') {
55788 ii = indexOf.call(this._shortWeekdaysParse, llc);
55789 return ii !== -1 ? ii : null;
55790 } else {
55791 ii = indexOf.call(this._minWeekdaysParse, llc);
55792 return ii !== -1 ? ii : null;
55793 }
55794 } else {
55795 if (format === 'dddd') {
55796 ii = indexOf.call(this._weekdaysParse, llc);
55797
55798 if (ii !== -1) {
55799 return ii;
55800 }
55801
55802 ii = indexOf.call(this._shortWeekdaysParse, llc);
55803
55804 if (ii !== -1) {
55805 return ii;
55806 }
55807
55808 ii = indexOf.call(this._minWeekdaysParse, llc);
55809 return ii !== -1 ? ii : null;
55810 } else if (format === 'ddd') {
55811 ii = indexOf.call(this._shortWeekdaysParse, llc);
55812
55813 if (ii !== -1) {
55814 return ii;
55815 }
55816
55817 ii = indexOf.call(this._weekdaysParse, llc);
55818
55819 if (ii !== -1) {
55820 return ii;
55821 }
55822
55823 ii = indexOf.call(this._minWeekdaysParse, llc);
55824 return ii !== -1 ? ii : null;
55825 } else {
55826 ii = indexOf.call(this._minWeekdaysParse, llc);
55827
55828 if (ii !== -1) {
55829 return ii;
55830 }
55831
55832 ii = indexOf.call(this._weekdaysParse, llc);
55833
55834 if (ii !== -1) {
55835 return ii;
55836 }
55837
55838 ii = indexOf.call(this._shortWeekdaysParse, llc);
55839 return ii !== -1 ? ii : null;
55840 }
55841 }
55842 }
55843
55844 function localeWeekdaysParse(weekdayName, format, strict) {
55845 var i, mom, regex;
55846
55847 if (this._weekdaysParseExact) {
55848 return handleStrictParse$1.call(this, weekdayName, format, strict);
55849 }
55850
55851 if (!this._weekdaysParse) {
55852 this._weekdaysParse = [];
55853 this._minWeekdaysParse = [];
55854 this._shortWeekdaysParse = [];
55855 this._fullWeekdaysParse = [];
55856 }
55857
55858 for (i = 0; i < 7; i++) {
55859 // make the regex if we don't have it already
55860 mom = createUTC([2000, 1]).day(i);
55861
55862 if (strict && !this._fullWeekdaysParse[i]) {
55863 this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i');
55864 this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i');
55865 this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i');
55866 }
55867
55868 if (!this._weekdaysParse[i]) {
55869 regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
55870 this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
55871 } // test the regex
55872
55873
55874 if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
55875 return i;
55876 } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
55877 return i;
55878 } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
55879 return i;
55880 } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
55881 return i;
55882 }
55883 }
55884 } // MOMENTS
55885
55886
55887 function getSetDayOfWeek(input) {
55888 if (!this.isValid()) {
55889 return input != null ? this : NaN;
55890 }
55891
55892 var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
55893
55894 if (input != null) {
55895 input = parseWeekday(input, this.localeData());
55896 return this.add(input - day, 'd');
55897 } else {
55898 return day;
55899 }
55900 }
55901
55902 function getSetLocaleDayOfWeek(input) {
55903 if (!this.isValid()) {
55904 return input != null ? this : NaN;
55905 }
55906
55907 var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
55908 return input == null ? weekday : this.add(input - weekday, 'd');
55909 }
55910
55911 function getSetISODayOfWeek(input) {
55912 if (!this.isValid()) {
55913 return input != null ? this : NaN;
55914 } // behaves the same as moment#day except
55915 // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
55916 // as a setter, sunday should belong to the previous week.
55917
55918
55919 if (input != null) {
55920 var weekday = parseIsoWeekday(input, this.localeData());
55921 return this.day(this.day() % 7 ? weekday : weekday - 7);
55922 } else {
55923 return this.day() || 7;
55924 }
55925 }
55926
55927 var defaultWeekdaysRegex = matchWord;
55928
55929 function weekdaysRegex(isStrict) {
55930 if (this._weekdaysParseExact) {
55931 if (!hasOwnProp(this, '_weekdaysRegex')) {
55932 computeWeekdaysParse.call(this);
55933 }
55934
55935 if (isStrict) {
55936 return this._weekdaysStrictRegex;
55937 } else {
55938 return this._weekdaysRegex;
55939 }
55940 } else {
55941 if (!hasOwnProp(this, '_weekdaysRegex')) {
55942 this._weekdaysRegex = defaultWeekdaysRegex;
55943 }
55944
55945 return this._weekdaysStrictRegex && isStrict ? this._weekdaysStrictRegex : this._weekdaysRegex;
55946 }
55947 }
55948
55949 var defaultWeekdaysShortRegex = matchWord;
55950
55951 function weekdaysShortRegex(isStrict) {
55952 if (this._weekdaysParseExact) {
55953 if (!hasOwnProp(this, '_weekdaysRegex')) {
55954 computeWeekdaysParse.call(this);
55955 }
55956
55957 if (isStrict) {
55958 return this._weekdaysShortStrictRegex;
55959 } else {
55960 return this._weekdaysShortRegex;
55961 }
55962 } else {
55963 if (!hasOwnProp(this, '_weekdaysShortRegex')) {
55964 this._weekdaysShortRegex = defaultWeekdaysShortRegex;
55965 }
55966
55967 return this._weekdaysShortStrictRegex && isStrict ? this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
55968 }
55969 }
55970
55971 var defaultWeekdaysMinRegex = matchWord;
55972
55973 function weekdaysMinRegex(isStrict) {
55974 if (this._weekdaysParseExact) {
55975 if (!hasOwnProp(this, '_weekdaysRegex')) {
55976 computeWeekdaysParse.call(this);
55977 }
55978
55979 if (isStrict) {
55980 return this._weekdaysMinStrictRegex;
55981 } else {
55982 return this._weekdaysMinRegex;
55983 }
55984 } else {
55985 if (!hasOwnProp(this, '_weekdaysMinRegex')) {
55986 this._weekdaysMinRegex = defaultWeekdaysMinRegex;
55987 }
55988
55989 return this._weekdaysMinStrictRegex && isStrict ? this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
55990 }
55991 }
55992
55993 function computeWeekdaysParse() {
55994 function cmpLenRev(a, b) {
55995 return b.length - a.length;
55996 }
55997
55998 var minPieces = [],
55999 shortPieces = [],
56000 longPieces = [],
56001 mixedPieces = [],
56002 i,
56003 mom,
56004 minp,
56005 shortp,
56006 longp;
56007
56008 for (i = 0; i < 7; i++) {
56009 // make the regex if we don't have it already
56010 mom = createUTC([2000, 1]).day(i);
56011 minp = this.weekdaysMin(mom, '');
56012 shortp = this.weekdaysShort(mom, '');
56013 longp = this.weekdays(mom, '');
56014 minPieces.push(minp);
56015 shortPieces.push(shortp);
56016 longPieces.push(longp);
56017 mixedPieces.push(minp);
56018 mixedPieces.push(shortp);
56019 mixedPieces.push(longp);
56020 } // Sorting makes sure if one weekday (or abbr) is a prefix of another it
56021 // will match the longer piece.
56022
56023
56024 minPieces.sort(cmpLenRev);
56025 shortPieces.sort(cmpLenRev);
56026 longPieces.sort(cmpLenRev);
56027 mixedPieces.sort(cmpLenRev);
56028
56029 for (i = 0; i < 7; i++) {
56030 shortPieces[i] = regexEscape(shortPieces[i]);
56031 longPieces[i] = regexEscape(longPieces[i]);
56032 mixedPieces[i] = regexEscape(mixedPieces[i]);
56033 }
56034
56035 this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
56036 this._weekdaysShortRegex = this._weekdaysRegex;
56037 this._weekdaysMinRegex = this._weekdaysRegex;
56038 this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
56039 this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
56040 this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
56041 } // FORMATTING
56042
56043
56044 function hFormat() {
56045 return this.hours() % 12 || 12;
56046 }
56047
56048 function kFormat() {
56049 return this.hours() || 24;
56050 }
56051
56052 addFormatToken('H', ['HH', 2], 0, 'hour');
56053 addFormatToken('h', ['hh', 2], 0, hFormat);
56054 addFormatToken('k', ['kk', 2], 0, kFormat);
56055 addFormatToken('hmm', 0, 0, function () {
56056 return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
56057 });
56058 addFormatToken('hmmss', 0, 0, function () {
56059 return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + zeroFill(this.seconds(), 2);
56060 });
56061 addFormatToken('Hmm', 0, 0, function () {
56062 return '' + this.hours() + zeroFill(this.minutes(), 2);
56063 });
56064 addFormatToken('Hmmss', 0, 0, function () {
56065 return '' + this.hours() + zeroFill(this.minutes(), 2) + zeroFill(this.seconds(), 2);
56066 });
56067
56068 function meridiem(token, lowercase) {
56069 addFormatToken(token, 0, 0, function () {
56070 return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
56071 });
56072 }
56073
56074 meridiem('a', true);
56075 meridiem('A', false); // ALIASES
56076
56077 addUnitAlias('hour', 'h'); // PRIORITY
56078
56079 addUnitPriority('hour', 13); // PARSING
56080
56081 function matchMeridiem(isStrict, locale) {
56082 return locale._meridiemParse;
56083 }
56084
56085 addRegexToken('a', matchMeridiem);
56086 addRegexToken('A', matchMeridiem);
56087 addRegexToken('H', match1to2);
56088 addRegexToken('h', match1to2);
56089 addRegexToken('k', match1to2);
56090 addRegexToken('HH', match1to2, match2);
56091 addRegexToken('hh', match1to2, match2);
56092 addRegexToken('kk', match1to2, match2);
56093 addRegexToken('hmm', match3to4);
56094 addRegexToken('hmmss', match5to6);
56095 addRegexToken('Hmm', match3to4);
56096 addRegexToken('Hmmss', match5to6);
56097 addParseToken(['H', 'HH'], HOUR);
56098 addParseToken(['k', 'kk'], function (input, array, config) {
56099 var kInput = toInt(input);
56100 array[HOUR] = kInput === 24 ? 0 : kInput;
56101 });
56102 addParseToken(['a', 'A'], function (input, array, config) {
56103 config._isPm = config._locale.isPM(input);
56104 config._meridiem = input;
56105 });
56106 addParseToken(['h', 'hh'], function (input, array, config) {
56107 array[HOUR] = toInt(input);
56108 getParsingFlags(config).bigHour = true;
56109 });
56110 addParseToken('hmm', function (input, array, config) {
56111 var pos = input.length - 2;
56112 array[HOUR] = toInt(input.substr(0, pos));
56113 array[MINUTE] = toInt(input.substr(pos));
56114 getParsingFlags(config).bigHour = true;
56115 });
56116 addParseToken('hmmss', function (input, array, config) {
56117 var pos1 = input.length - 4;
56118 var pos2 = input.length - 2;
56119 array[HOUR] = toInt(input.substr(0, pos1));
56120 array[MINUTE] = toInt(input.substr(pos1, 2));
56121 array[SECOND] = toInt(input.substr(pos2));
56122 getParsingFlags(config).bigHour = true;
56123 });
56124 addParseToken('Hmm', function (input, array, config) {
56125 var pos = input.length - 2;
56126 array[HOUR] = toInt(input.substr(0, pos));
56127 array[MINUTE] = toInt(input.substr(pos));
56128 });
56129 addParseToken('Hmmss', function (input, array, config) {
56130 var pos1 = input.length - 4;
56131 var pos2 = input.length - 2;
56132 array[HOUR] = toInt(input.substr(0, pos1));
56133 array[MINUTE] = toInt(input.substr(pos1, 2));
56134 array[SECOND] = toInt(input.substr(pos2));
56135 }); // LOCALES
56136
56137 function localeIsPM(input) {
56138 // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
56139 // Using charAt should be more compatible.
56140 return (input + '').toLowerCase().charAt(0) === 'p';
56141 }
56142
56143 var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
56144
56145 function localeMeridiem(hours, minutes, isLower) {
56146 if (hours > 11) {
56147 return isLower ? 'pm' : 'PM';
56148 } else {
56149 return isLower ? 'am' : 'AM';
56150 }
56151 } // MOMENTS
56152 // Setting the hour should keep the time, because the user explicitly
56153 // specified which hour they want. So trying to maintain the same hour (in
56154 // a new timezone) makes sense. Adding/subtracting hours does not follow
56155 // this rule.
56156
56157
56158 var getSetHour = makeGetSet('Hours', true);
56159 var baseConfig = {
56160 calendar: defaultCalendar,
56161 longDateFormat: defaultLongDateFormat,
56162 invalidDate: defaultInvalidDate,
56163 ordinal: defaultOrdinal,
56164 dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
56165 relativeTime: defaultRelativeTime,
56166 months: defaultLocaleMonths,
56167 monthsShort: defaultLocaleMonthsShort,
56168 week: defaultLocaleWeek,
56169 weekdays: defaultLocaleWeekdays,
56170 weekdaysMin: defaultLocaleWeekdaysMin,
56171 weekdaysShort: defaultLocaleWeekdaysShort,
56172 meridiemParse: defaultLocaleMeridiemParse
56173 }; // internal storage for locale config files
56174
56175 var locales = {};
56176 var localeFamilies = {};
56177 var globalLocale;
56178
56179 function normalizeLocale(key) {
56180 return key ? key.toLowerCase().replace('_', '-') : key;
56181 } // pick the locale from the array
56182 // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
56183 // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
56184
56185
56186 function chooseLocale(names) {
56187 var i = 0,
56188 j,
56189 next,
56190 locale,
56191 split;
56192
56193 while (i < names.length) {
56194 split = normalizeLocale(names[i]).split('-');
56195 j = split.length;
56196 next = normalizeLocale(names[i + 1]);
56197 next = next ? next.split('-') : null;
56198
56199 while (j > 0) {
56200 locale = loadLocale(split.slice(0, j).join('-'));
56201
56202 if (locale) {
56203 return locale;
56204 }
56205
56206 if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
56207 //the next array item is better than a shallower substring of this one
56208 break;
56209 }
56210
56211 j--;
56212 }
56213
56214 i++;
56215 }
56216
56217 return globalLocale;
56218 }
56219
56220 function loadLocale(name) {
56221 var oldLocale = null; // TODO: Find a better way to register and load all the locales in Node
56222
56223 if (!locales[name] && 'object' !== 'undefined' && module && module.exports) {
56224 try {
56225 oldLocale = globalLocale._abbr;
56226 var aliasedRequire = commonjsRequire;
56227 aliasedRequire('./locale/' + name);
56228 getSetGlobalLocale(oldLocale);
56229 } catch (e) {}
56230 }
56231
56232 return locales[name];
56233 } // This function will load locale and then set the global locale. If
56234 // no arguments are passed in, it will simply return the current global
56235 // locale key.
56236
56237
56238 function getSetGlobalLocale(key, values) {
56239 var data;
56240
56241 if (key) {
56242 if (isUndefined(values)) {
56243 data = getLocale(key);
56244 } else {
56245 data = defineLocale(key, values);
56246 }
56247
56248 if (data) {
56249 // moment.duration._locale = moment._locale = data;
56250 globalLocale = data;
56251 } else {
56252 if (typeof console !== 'undefined' && console.warn) {
56253 //warn user if arguments are passed but the locale could not be set
56254 console.warn('Locale ' + key + ' not found. Did you forget to load it?');
56255 }
56256 }
56257 }
56258
56259 return globalLocale._abbr;
56260 }
56261
56262 function defineLocale(name, config) {
56263 if (config !== null) {
56264 var locale,
56265 parentConfig = baseConfig;
56266 config.abbr = name;
56267
56268 if (locales[name] != null) {
56269 deprecateSimple('defineLocaleOverride', 'use moment.updateLocale(localeName, config) to change ' + 'an existing locale. moment.defineLocale(localeName, ' + 'config) should only be used for creating a new locale ' + 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
56270 parentConfig = locales[name]._config;
56271 } else if (config.parentLocale != null) {
56272 if (locales[config.parentLocale] != null) {
56273 parentConfig = locales[config.parentLocale]._config;
56274 } else {
56275 locale = loadLocale(config.parentLocale);
56276
56277 if (locale != null) {
56278 parentConfig = locale._config;
56279 } else {
56280 if (!localeFamilies[config.parentLocale]) {
56281 localeFamilies[config.parentLocale] = [];
56282 }
56283
56284 localeFamilies[config.parentLocale].push({
56285 name: name,
56286 config: config
56287 });
56288 return null;
56289 }
56290 }
56291 }
56292
56293 locales[name] = new Locale(mergeConfigs(parentConfig, config));
56294
56295 if (localeFamilies[name]) {
56296 localeFamilies[name].forEach(function (x) {
56297 defineLocale(x.name, x.config);
56298 });
56299 } // backwards compat for now: also set the locale
56300 // make sure we set the locale AFTER all child locales have been
56301 // created, so we won't end up with the child locale set.
56302
56303
56304 getSetGlobalLocale(name);
56305 return locales[name];
56306 } else {
56307 // useful for testing
56308 delete locales[name];
56309 return null;
56310 }
56311 }
56312
56313 function updateLocale(name, config) {
56314 if (config != null) {
56315 var locale,
56316 tmpLocale,
56317 parentConfig = baseConfig; // MERGE
56318
56319 tmpLocale = loadLocale(name);
56320
56321 if (tmpLocale != null) {
56322 parentConfig = tmpLocale._config;
56323 }
56324
56325 config = mergeConfigs(parentConfig, config);
56326 locale = new Locale(config);
56327 locale.parentLocale = locales[name];
56328 locales[name] = locale; // backwards compat for now: also set the locale
56329
56330 getSetGlobalLocale(name);
56331 } else {
56332 // pass null for config to unupdate, useful for tests
56333 if (locales[name] != null) {
56334 if (locales[name].parentLocale != null) {
56335 locales[name] = locales[name].parentLocale;
56336 } else if (locales[name] != null) {
56337 delete locales[name];
56338 }
56339 }
56340 }
56341
56342 return locales[name];
56343 } // returns locale data
56344
56345
56346 function getLocale(key) {
56347 var locale;
56348
56349 if (key && key._locale && key._locale._abbr) {
56350 key = key._locale._abbr;
56351 }
56352
56353 if (!key) {
56354 return globalLocale;
56355 }
56356
56357 if (!isArray(key)) {
56358 //short-circuit everything else
56359 locale = loadLocale(key);
56360
56361 if (locale) {
56362 return locale;
56363 }
56364
56365 key = [key];
56366 }
56367
56368 return chooseLocale(key);
56369 }
56370
56371 function listLocales() {
56372 return keys(locales);
56373 }
56374
56375 function checkOverflow(m) {
56376 var overflow;
56377 var a = m._a;
56378
56379 if (a && getParsingFlags(m).overflow === -2) {
56380 overflow = a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : a[HOUR] < 0 || a[HOUR] > 24 || a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0) ? HOUR : a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : -1;
56381
56382 if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
56383 overflow = DATE;
56384 }
56385
56386 if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
56387 overflow = WEEK;
56388 }
56389
56390 if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
56391 overflow = WEEKDAY;
56392 }
56393
56394 getParsingFlags(m).overflow = overflow;
56395 }
56396
56397 return m;
56398 } // Pick the first defined of two or three arguments.
56399
56400
56401 function defaults(a, b, c) {
56402 if (a != null) {
56403 return a;
56404 }
56405
56406 if (b != null) {
56407 return b;
56408 }
56409
56410 return c;
56411 }
56412
56413 function currentDateArray(config) {
56414 // hooks is actually the exported moment object
56415 var nowValue = new Date(hooks.now());
56416
56417 if (config._useUTC) {
56418 return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
56419 }
56420
56421 return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
56422 } // convert an array to a date.
56423 // the array should mirror the parameters below
56424 // note: all values past the year are optional and will default to the lowest possible value.
56425 // [year, month, day , hour, minute, second, millisecond]
56426
56427
56428 function configFromArray(config) {
56429 var i,
56430 date,
56431 input = [],
56432 currentDate,
56433 expectedWeekday,
56434 yearToUse;
56435
56436 if (config._d) {
56437 return;
56438 }
56439
56440 currentDate = currentDateArray(config); //compute day of the year from weeks and weekdays
56441
56442 if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
56443 dayOfYearFromWeekInfo(config);
56444 } //if the day of the year is set, figure out what it is
56445
56446
56447 if (config._dayOfYear != null) {
56448 yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
56449
56450 if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
56451 getParsingFlags(config)._overflowDayOfYear = true;
56452 }
56453
56454 date = createUTCDate(yearToUse, 0, config._dayOfYear);
56455 config._a[MONTH] = date.getUTCMonth();
56456 config._a[DATE] = date.getUTCDate();
56457 } // Default to current date.
56458 // * if no year, month, day of month are given, default to today
56459 // * if day of month is given, default month and year
56460 // * if month is given, default only year
56461 // * if year is given, don't default anything
56462
56463
56464 for (i = 0; i < 3 && config._a[i] == null; ++i) {
56465 config._a[i] = input[i] = currentDate[i];
56466 } // Zero out whatever was not defaulted, including time
56467
56468
56469 for (; i < 7; i++) {
56470 config._a[i] = input[i] = config._a[i] == null ? i === 2 ? 1 : 0 : config._a[i];
56471 } // Check for 24:00:00.000
56472
56473
56474 if (config._a[HOUR] === 24 && config._a[MINUTE] === 0 && config._a[SECOND] === 0 && config._a[MILLISECOND] === 0) {
56475 config._nextDay = true;
56476 config._a[HOUR] = 0;
56477 }
56478
56479 config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
56480 expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay(); // Apply timezone offset from input. The actual utcOffset can be changed
56481 // with parseZone.
56482
56483 if (config._tzm != null) {
56484 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
56485 }
56486
56487 if (config._nextDay) {
56488 config._a[HOUR] = 24;
56489 } // check for mismatching day of week
56490
56491
56492 if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) {
56493 getParsingFlags(config).weekdayMismatch = true;
56494 }
56495 }
56496
56497 function dayOfYearFromWeekInfo(config) {
56498 var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
56499 w = config._w;
56500
56501 if (w.GG != null || w.W != null || w.E != null) {
56502 dow = 1;
56503 doy = 4; // TODO: We need to take the current isoWeekYear, but that depends on
56504 // how we interpret now (local, utc, fixed offset). So create
56505 // a now version of current config (take local/utc/offset flags, and
56506 // create now).
56507
56508 weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
56509 week = defaults(w.W, 1);
56510 weekday = defaults(w.E, 1);
56511
56512 if (weekday < 1 || weekday > 7) {
56513 weekdayOverflow = true;
56514 }
56515 } else {
56516 dow = config._locale._week.dow;
56517 doy = config._locale._week.doy;
56518 var curWeek = weekOfYear(createLocal(), dow, doy);
56519 weekYear = defaults(w.gg, config._a[YEAR], curWeek.year); // Default to current week.
56520
56521 week = defaults(w.w, curWeek.week);
56522
56523 if (w.d != null) {
56524 // weekday -- low day numbers are considered next week
56525 weekday = w.d;
56526
56527 if (weekday < 0 || weekday > 6) {
56528 weekdayOverflow = true;
56529 }
56530 } else if (w.e != null) {
56531 // local weekday -- counting starts from beginning of week
56532 weekday = w.e + dow;
56533
56534 if (w.e < 0 || w.e > 6) {
56535 weekdayOverflow = true;
56536 }
56537 } else {
56538 // default to beginning of week
56539 weekday = dow;
56540 }
56541 }
56542
56543 if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
56544 getParsingFlags(config)._overflowWeeks = true;
56545 } else if (weekdayOverflow != null) {
56546 getParsingFlags(config)._overflowWeekday = true;
56547 } else {
56548 temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
56549 config._a[YEAR] = temp.year;
56550 config._dayOfYear = temp.dayOfYear;
56551 }
56552 } // iso 8601 regex
56553 // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
56554
56555
56556 var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
56557 var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
56558 var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
56559 var isoDates = [['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], ['GGGG-[W]WW', /\d{4}-W\d\d/, false], ['YYYY-DDD', /\d{4}-\d{3}/], ['YYYY-MM', /\d{4}-\d\d/, false], ['YYYYYYMMDD', /[+-]\d{10}/], ['YYYYMMDD', /\d{8}/], // YYYYMM is NOT allowed by the standard
56560 ['GGGG[W]WWE', /\d{4}W\d{3}/], ['GGGG[W]WW', /\d{4}W\d{2}/, false], ['YYYYDDD', /\d{7}/]]; // iso time formats and regexes
56561
56562 var isoTimes = [['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], ['HH:mm:ss', /\d\d:\d\d:\d\d/], ['HH:mm', /\d\d:\d\d/], ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], ['HHmmss', /\d\d\d\d\d\d/], ['HHmm', /\d\d\d\d/], ['HH', /\d\d/]];
56563 var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; // date from iso format
56564
56565 function configFromISO(config) {
56566 var i,
56567 l,
56568 string = config._i,
56569 match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
56570 allowTime,
56571 dateFormat,
56572 timeFormat,
56573 tzFormat;
56574
56575 if (match) {
56576 getParsingFlags(config).iso = true;
56577
56578 for (i = 0, l = isoDates.length; i < l; i++) {
56579 if (isoDates[i][1].exec(match[1])) {
56580 dateFormat = isoDates[i][0];
56581 allowTime = isoDates[i][2] !== false;
56582 break;
56583 }
56584 }
56585
56586 if (dateFormat == null) {
56587 config._isValid = false;
56588 return;
56589 }
56590
56591 if (match[3]) {
56592 for (i = 0, l = isoTimes.length; i < l; i++) {
56593 if (isoTimes[i][1].exec(match[3])) {
56594 // match[2] should be 'T' or space
56595 timeFormat = (match[2] || ' ') + isoTimes[i][0];
56596 break;
56597 }
56598 }
56599
56600 if (timeFormat == null) {
56601 config._isValid = false;
56602 return;
56603 }
56604 }
56605
56606 if (!allowTime && timeFormat != null) {
56607 config._isValid = false;
56608 return;
56609 }
56610
56611 if (match[4]) {
56612 if (tzRegex.exec(match[4])) {
56613 tzFormat = 'Z';
56614 } else {
56615 config._isValid = false;
56616 return;
56617 }
56618 }
56619
56620 config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
56621 configFromStringAndFormat(config);
56622 } else {
56623 config._isValid = false;
56624 }
56625 } // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
56626
56627
56628 var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
56629
56630 function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
56631 var result = [untruncateYear(yearStr), defaultLocaleMonthsShort.indexOf(monthStr), parseInt(dayStr, 10), parseInt(hourStr, 10), parseInt(minuteStr, 10)];
56632
56633 if (secondStr) {
56634 result.push(parseInt(secondStr, 10));
56635 }
56636
56637 return result;
56638 }
56639
56640 function untruncateYear(yearStr) {
56641 var year = parseInt(yearStr, 10);
56642
56643 if (year <= 49) {
56644 return 2000 + year;
56645 } else if (year <= 999) {
56646 return 1900 + year;
56647 }
56648
56649 return year;
56650 }
56651
56652 function preprocessRFC2822(s) {
56653 // Remove comments and folding whitespace and replace multiple-spaces with a single space
56654 return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
56655 }
56656
56657 function checkWeekday(weekdayStr, parsedInput, config) {
56658 if (weekdayStr) {
56659 // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
56660 var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
56661 weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
56662
56663 if (weekdayProvided !== weekdayActual) {
56664 getParsingFlags(config).weekdayMismatch = true;
56665 config._isValid = false;
56666 return false;
56667 }
56668 }
56669
56670 return true;
56671 }
56672
56673 var obsOffsets = {
56674 UT: 0,
56675 GMT: 0,
56676 EDT: -4 * 60,
56677 EST: -5 * 60,
56678 CDT: -5 * 60,
56679 CST: -6 * 60,
56680 MDT: -6 * 60,
56681 MST: -7 * 60,
56682 PDT: -7 * 60,
56683 PST: -8 * 60
56684 };
56685
56686 function calculateOffset(obsOffset, militaryOffset, numOffset) {
56687 if (obsOffset) {
56688 return obsOffsets[obsOffset];
56689 } else if (militaryOffset) {
56690 // the only allowed military tz is Z
56691 return 0;
56692 } else {
56693 var hm = parseInt(numOffset, 10);
56694 var m = hm % 100,
56695 h = (hm - m) / 100;
56696 return h * 60 + m;
56697 }
56698 } // date and time from ref 2822 format
56699
56700
56701 function configFromRFC2822(config) {
56702 var match = rfc2822.exec(preprocessRFC2822(config._i));
56703
56704 if (match) {
56705 var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
56706
56707 if (!checkWeekday(match[1], parsedArray, config)) {
56708 return;
56709 }
56710
56711 config._a = parsedArray;
56712 config._tzm = calculateOffset(match[8], match[9], match[10]);
56713 config._d = createUTCDate.apply(null, config._a);
56714
56715 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
56716
56717 getParsingFlags(config).rfc2822 = true;
56718 } else {
56719 config._isValid = false;
56720 }
56721 } // date from iso format or fallback
56722
56723
56724 function configFromString(config) {
56725 var matched = aspNetJsonRegex.exec(config._i);
56726
56727 if (matched !== null) {
56728 config._d = new Date(+matched[1]);
56729 return;
56730 }
56731
56732 configFromISO(config);
56733
56734 if (config._isValid === false) {
56735 delete config._isValid;
56736 } else {
56737 return;
56738 }
56739
56740 configFromRFC2822(config);
56741
56742 if (config._isValid === false) {
56743 delete config._isValid;
56744 } else {
56745 return;
56746 } // Final attempt, use Input Fallback
56747
56748
56749 hooks.createFromInputFallback(config);
56750 }
56751
56752 hooks.createFromInputFallback = deprecate('value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' + 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' + 'discouraged and will be removed in an upcoming major release. Please refer to ' + 'http://momentjs.com/guides/#/warnings/js-date/ for more info.', function (config) {
56753 config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
56754 }); // constant that refers to the ISO standard
56755
56756 hooks.ISO_8601 = function () {}; // constant that refers to the RFC 2822 form
56757
56758
56759 hooks.RFC_2822 = function () {}; // date from string and format string
56760
56761
56762 function configFromStringAndFormat(config) {
56763 // TODO: Move this to another part of the creation flow to prevent circular deps
56764 if (config._f === hooks.ISO_8601) {
56765 configFromISO(config);
56766 return;
56767 }
56768
56769 if (config._f === hooks.RFC_2822) {
56770 configFromRFC2822(config);
56771 return;
56772 }
56773
56774 config._a = [];
56775 getParsingFlags(config).empty = true; // This array is used to make a Date, either with `new Date` or `Date.UTC`
56776
56777 var string = '' + config._i,
56778 i,
56779 parsedInput,
56780 tokens,
56781 token,
56782 skipped,
56783 stringLength = string.length,
56784 totalParsedInputLength = 0;
56785 tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
56786
56787 for (i = 0; i < tokens.length; i++) {
56788 token = tokens[i];
56789 parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; // console.log('token', token, 'parsedInput', parsedInput,
56790 // 'regex', getParseRegexForToken(token, config));
56791
56792 if (parsedInput) {
56793 skipped = string.substr(0, string.indexOf(parsedInput));
56794
56795 if (skipped.length > 0) {
56796 getParsingFlags(config).unusedInput.push(skipped);
56797 }
56798
56799 string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
56800 totalParsedInputLength += parsedInput.length;
56801 } // don't parse if it's not a known token
56802
56803
56804 if (formatTokenFunctions[token]) {
56805 if (parsedInput) {
56806 getParsingFlags(config).empty = false;
56807 } else {
56808 getParsingFlags(config).unusedTokens.push(token);
56809 }
56810
56811 addTimeToArrayFromToken(token, parsedInput, config);
56812 } else if (config._strict && !parsedInput) {
56813 getParsingFlags(config).unusedTokens.push(token);
56814 }
56815 } // add remaining unparsed input length to the string
56816
56817
56818 getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
56819
56820 if (string.length > 0) {
56821 getParsingFlags(config).unusedInput.push(string);
56822 } // clear _12h flag if hour is <= 12
56823
56824
56825 if (config._a[HOUR] <= 12 && getParsingFlags(config).bigHour === true && config._a[HOUR] > 0) {
56826 getParsingFlags(config).bigHour = undefined;
56827 }
56828
56829 getParsingFlags(config).parsedDateParts = config._a.slice(0);
56830 getParsingFlags(config).meridiem = config._meridiem; // handle meridiem
56831
56832 config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
56833 configFromArray(config);
56834 checkOverflow(config);
56835 }
56836
56837 function meridiemFixWrap(locale, hour, meridiem) {
56838 var isPm;
56839
56840 if (meridiem == null) {
56841 // nothing to do
56842 return hour;
56843 }
56844
56845 if (locale.meridiemHour != null) {
56846 return locale.meridiemHour(hour, meridiem);
56847 } else if (locale.isPM != null) {
56848 // Fallback
56849 isPm = locale.isPM(meridiem);
56850
56851 if (isPm && hour < 12) {
56852 hour += 12;
56853 }
56854
56855 if (!isPm && hour === 12) {
56856 hour = 0;
56857 }
56858
56859 return hour;
56860 } else {
56861 // this is not supposed to happen
56862 return hour;
56863 }
56864 } // date from string and array of format strings
56865
56866
56867 function configFromStringAndArray(config) {
56868 var tempConfig, bestMoment, scoreToBeat, i, currentScore;
56869
56870 if (config._f.length === 0) {
56871 getParsingFlags(config).invalidFormat = true;
56872 config._d = new Date(NaN);
56873 return;
56874 }
56875
56876 for (i = 0; i < config._f.length; i++) {
56877 currentScore = 0;
56878 tempConfig = copyConfig({}, config);
56879
56880 if (config._useUTC != null) {
56881 tempConfig._useUTC = config._useUTC;
56882 }
56883
56884 tempConfig._f = config._f[i];
56885 configFromStringAndFormat(tempConfig);
56886
56887 if (!isValid(tempConfig)) {
56888 continue;
56889 } // if there is any input that was not parsed add a penalty for that format
56890
56891
56892 currentScore += getParsingFlags(tempConfig).charsLeftOver; //or tokens
56893
56894 currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
56895 getParsingFlags(tempConfig).score = currentScore;
56896
56897 if (scoreToBeat == null || currentScore < scoreToBeat) {
56898 scoreToBeat = currentScore;
56899 bestMoment = tempConfig;
56900 }
56901 }
56902
56903 extend(config, bestMoment || tempConfig);
56904 }
56905
56906 function configFromObject(config) {
56907 if (config._d) {
56908 return;
56909 }
56910
56911 var i = normalizeObjectUnits(config._i);
56912 config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
56913 return obj && parseInt(obj, 10);
56914 });
56915 configFromArray(config);
56916 }
56917
56918 function createFromConfig(config) {
56919 var res = new Moment(checkOverflow(prepareConfig(config)));
56920
56921 if (res._nextDay) {
56922 // Adding is smart enough around DST
56923 res.add(1, 'd');
56924 res._nextDay = undefined;
56925 }
56926
56927 return res;
56928 }
56929
56930 function prepareConfig(config) {
56931 var input = config._i,
56932 format = config._f;
56933 config._locale = config._locale || getLocale(config._l);
56934
56935 if (input === null || format === undefined && input === '') {
56936 return createInvalid({
56937 nullInput: true
56938 });
56939 }
56940
56941 if (typeof input === 'string') {
56942 config._i = input = config._locale.preparse(input);
56943 }
56944
56945 if (isMoment(input)) {
56946 return new Moment(checkOverflow(input));
56947 } else if (isDate(input)) {
56948 config._d = input;
56949 } else if (isArray(format)) {
56950 configFromStringAndArray(config);
56951 } else if (format) {
56952 configFromStringAndFormat(config);
56953 } else {
56954 configFromInput(config);
56955 }
56956
56957 if (!isValid(config)) {
56958 config._d = null;
56959 }
56960
56961 return config;
56962 }
56963
56964 function configFromInput(config) {
56965 var input = config._i;
56966
56967 if (isUndefined(input)) {
56968 config._d = new Date(hooks.now());
56969 } else if (isDate(input)) {
56970 config._d = new Date(input.valueOf());
56971 } else if (typeof input === 'string') {
56972 configFromString(config);
56973 } else if (isArray(input)) {
56974 config._a = map(input.slice(0), function (obj) {
56975 return parseInt(obj, 10);
56976 });
56977 configFromArray(config);
56978 } else if (isObject(input)) {
56979 configFromObject(config);
56980 } else if (isNumber(input)) {
56981 // from milliseconds
56982 config._d = new Date(input);
56983 } else {
56984 hooks.createFromInputFallback(config);
56985 }
56986 }
56987
56988 function createLocalOrUTC(input, format, locale, strict, isUTC) {
56989 var c = {};
56990
56991 if (locale === true || locale === false) {
56992 strict = locale;
56993 locale = undefined;
56994 }
56995
56996 if (isObject(input) && isObjectEmpty(input) || isArray(input) && input.length === 0) {
56997 input = undefined;
56998 } // object construction must be done this way.
56999 // https://github.com/moment/moment/issues/1423
57000
57001
57002 c._isAMomentObject = true;
57003 c._useUTC = c._isUTC = isUTC;
57004 c._l = locale;
57005 c._i = input;
57006 c._f = format;
57007 c._strict = strict;
57008 return createFromConfig(c);
57009 }
57010
57011 function createLocal(input, format, locale, strict) {
57012 return createLocalOrUTC(input, format, locale, strict, false);
57013 }
57014
57015 var prototypeMin = deprecate('moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', function () {
57016 var other = createLocal.apply(null, arguments);
57017
57018 if (this.isValid() && other.isValid()) {
57019 return other < this ? this : other;
57020 } else {
57021 return createInvalid();
57022 }
57023 });
57024 var prototypeMax = deprecate('moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', function () {
57025 var other = createLocal.apply(null, arguments);
57026
57027 if (this.isValid() && other.isValid()) {
57028 return other > this ? this : other;
57029 } else {
57030 return createInvalid();
57031 }
57032 }); // Pick a moment m from moments so that m[fn](other) is true for all
57033 // other. This relies on the function fn to be transitive.
57034 //
57035 // moments should either be an array of moment objects or an array, whose
57036 // first element is an array of moment objects.
57037
57038 function pickBy(fn, moments) {
57039 var res, i;
57040
57041 if (moments.length === 1 && isArray(moments[0])) {
57042 moments = moments[0];
57043 }
57044
57045 if (!moments.length) {
57046 return createLocal();
57047 }
57048
57049 res = moments[0];
57050
57051 for (i = 1; i < moments.length; ++i) {
57052 if (!moments[i].isValid() || moments[i][fn](res)) {
57053 res = moments[i];
57054 }
57055 }
57056
57057 return res;
57058 } // TODO: Use [].sort instead?
57059
57060
57061 function min() {
57062 var args = [].slice.call(arguments, 0);
57063 return pickBy('isBefore', args);
57064 }
57065
57066 function max() {
57067 var args = [].slice.call(arguments, 0);
57068 return pickBy('isAfter', args);
57069 }
57070
57071 var now = function () {
57072 return Date.now ? Date.now() : +new Date();
57073 };
57074
57075 var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
57076
57077 function isDurationValid(m) {
57078 for (var key in m) {
57079 if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
57080 return false;
57081 }
57082 }
57083
57084 var unitHasDecimal = false;
57085
57086 for (var i = 0; i < ordering.length; ++i) {
57087 if (m[ordering[i]]) {
57088 if (unitHasDecimal) {
57089 return false; // only allow non-integers for smallest unit
57090 }
57091
57092 if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
57093 unitHasDecimal = true;
57094 }
57095 }
57096 }
57097
57098 return true;
57099 }
57100
57101 function isValid$1() {
57102 return this._isValid;
57103 }
57104
57105 function createInvalid$1() {
57106 return createDuration(NaN);
57107 }
57108
57109 function Duration(duration) {
57110 var normalizedInput = normalizeObjectUnits(duration),
57111 years = normalizedInput.year || 0,
57112 quarters = normalizedInput.quarter || 0,
57113 months = normalizedInput.month || 0,
57114 weeks = normalizedInput.week || normalizedInput.isoWeek || 0,
57115 days = normalizedInput.day || 0,
57116 hours = normalizedInput.hour || 0,
57117 minutes = normalizedInput.minute || 0,
57118 seconds = normalizedInput.second || 0,
57119 milliseconds = normalizedInput.millisecond || 0;
57120 this._isValid = isDurationValid(normalizedInput); // representation for dateAddRemove
57121
57122 this._milliseconds = +milliseconds + seconds * 1e3 + // 1000
57123 minutes * 6e4 + // 1000 * 60
57124 hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
57125 // Because of dateAddRemove treats 24 hours as different from a
57126 // day when working around DST, we need to store them separately
57127
57128 this._days = +days + weeks * 7; // It is impossible to translate months into days without knowing
57129 // which months you are are talking about, so we have to store
57130 // it separately.
57131
57132 this._months = +months + quarters * 3 + years * 12;
57133 this._data = {};
57134 this._locale = getLocale();
57135
57136 this._bubble();
57137 }
57138
57139 function isDuration(obj) {
57140 return obj instanceof Duration;
57141 }
57142
57143 function absRound(number) {
57144 if (number < 0) {
57145 return Math.round(-1 * number) * -1;
57146 } else {
57147 return Math.round(number);
57148 }
57149 } // FORMATTING
57150
57151
57152 function offset(token, separator) {
57153 addFormatToken(token, 0, 0, function () {
57154 var offset = this.utcOffset();
57155 var sign = '+';
57156
57157 if (offset < 0) {
57158 offset = -offset;
57159 sign = '-';
57160 }
57161
57162 return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~offset % 60, 2);
57163 });
57164 }
57165
57166 offset('Z', ':');
57167 offset('ZZ', ''); // PARSING
57168
57169 addRegexToken('Z', matchShortOffset);
57170 addRegexToken('ZZ', matchShortOffset);
57171 addParseToken(['Z', 'ZZ'], function (input, array, config) {
57172 config._useUTC = true;
57173 config._tzm = offsetFromString(matchShortOffset, input);
57174 }); // HELPERS
57175 // timezone chunker
57176 // '+10:00' > ['10', '00']
57177 // '-1530' > ['-15', '30']
57178
57179 var chunkOffset = /([\+\-]|\d\d)/gi;
57180
57181 function offsetFromString(matcher, string) {
57182 var matches = (string || '').match(matcher);
57183
57184 if (matches === null) {
57185 return null;
57186 }
57187
57188 var chunk = matches[matches.length - 1] || [];
57189 var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
57190 var minutes = +(parts[1] * 60) + toInt(parts[2]);
57191 return minutes === 0 ? 0 : parts[0] === '+' ? minutes : -minutes;
57192 } // Return a moment from input, that is local/utc/zone equivalent to model.
57193
57194
57195 function cloneWithOffset(input, model) {
57196 var res, diff;
57197
57198 if (model._isUTC) {
57199 res = model.clone();
57200 diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf(); // Use low-level api, because this fn is low-level api.
57201
57202 res._d.setTime(res._d.valueOf() + diff);
57203
57204 hooks.updateOffset(res, false);
57205 return res;
57206 } else {
57207 return createLocal(input).local();
57208 }
57209 }
57210
57211 function getDateOffset(m) {
57212 // On Firefox.24 Date#getTimezoneOffset returns a floating point.
57213 // https://github.com/moment/moment/pull/1871
57214 return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
57215 } // HOOKS
57216 // This function will be called whenever a moment is mutated.
57217 // It is intended to keep the offset in sync with the timezone.
57218
57219
57220 hooks.updateOffset = function () {}; // MOMENTS
57221 // keepLocalTime = true means only change the timezone, without
57222 // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
57223 // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
57224 // +0200, so we adjust the time as needed, to be valid.
57225 //
57226 // Keeping the time actually adds/subtracts (one hour)
57227 // from the actual represented time. That is why we call updateOffset
57228 // a second time. In case it wants us to change the offset again
57229 // _changeInProgress == true case, then we have to adjust, because
57230 // there is no such time in the given timezone.
57231
57232
57233 function getSetOffset(input, keepLocalTime, keepMinutes) {
57234 var offset = this._offset || 0,
57235 localAdjust;
57236
57237 if (!this.isValid()) {
57238 return input != null ? this : NaN;
57239 }
57240
57241 if (input != null) {
57242 if (typeof input === 'string') {
57243 input = offsetFromString(matchShortOffset, input);
57244
57245 if (input === null) {
57246 return this;
57247 }
57248 } else if (Math.abs(input) < 16 && !keepMinutes) {
57249 input = input * 60;
57250 }
57251
57252 if (!this._isUTC && keepLocalTime) {
57253 localAdjust = getDateOffset(this);
57254 }
57255
57256 this._offset = input;
57257 this._isUTC = true;
57258
57259 if (localAdjust != null) {
57260 this.add(localAdjust, 'm');
57261 }
57262
57263 if (offset !== input) {
57264 if (!keepLocalTime || this._changeInProgress) {
57265 addSubtract(this, createDuration(input - offset, 'm'), 1, false);
57266 } else if (!this._changeInProgress) {
57267 this._changeInProgress = true;
57268 hooks.updateOffset(this, true);
57269 this._changeInProgress = null;
57270 }
57271 }
57272
57273 return this;
57274 } else {
57275 return this._isUTC ? offset : getDateOffset(this);
57276 }
57277 }
57278
57279 function getSetZone(input, keepLocalTime) {
57280 if (input != null) {
57281 if (typeof input !== 'string') {
57282 input = -input;
57283 }
57284
57285 this.utcOffset(input, keepLocalTime);
57286 return this;
57287 } else {
57288 return -this.utcOffset();
57289 }
57290 }
57291
57292 function setOffsetToUTC(keepLocalTime) {
57293 return this.utcOffset(0, keepLocalTime);
57294 }
57295
57296 function setOffsetToLocal(keepLocalTime) {
57297 if (this._isUTC) {
57298 this.utcOffset(0, keepLocalTime);
57299 this._isUTC = false;
57300
57301 if (keepLocalTime) {
57302 this.subtract(getDateOffset(this), 'm');
57303 }
57304 }
57305
57306 return this;
57307 }
57308
57309 function setOffsetToParsedOffset() {
57310 if (this._tzm != null) {
57311 this.utcOffset(this._tzm, false, true);
57312 } else if (typeof this._i === 'string') {
57313 var tZone = offsetFromString(matchOffset, this._i);
57314
57315 if (tZone != null) {
57316 this.utcOffset(tZone);
57317 } else {
57318 this.utcOffset(0, true);
57319 }
57320 }
57321
57322 return this;
57323 }
57324
57325 function hasAlignedHourOffset(input) {
57326 if (!this.isValid()) {
57327 return false;
57328 }
57329
57330 input = input ? createLocal(input).utcOffset() : 0;
57331 return (this.utcOffset() - input) % 60 === 0;
57332 }
57333
57334 function isDaylightSavingTime() {
57335 return this.utcOffset() > this.clone().month(0).utcOffset() || this.utcOffset() > this.clone().month(5).utcOffset();
57336 }
57337
57338 function isDaylightSavingTimeShifted() {
57339 if (!isUndefined(this._isDSTShifted)) {
57340 return this._isDSTShifted;
57341 }
57342
57343 var c = {};
57344 copyConfig(c, this);
57345 c = prepareConfig(c);
57346
57347 if (c._a) {
57348 var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
57349 this._isDSTShifted = this.isValid() && compareArrays(c._a, other.toArray()) > 0;
57350 } else {
57351 this._isDSTShifted = false;
57352 }
57353
57354 return this._isDSTShifted;
57355 }
57356
57357 function isLocal() {
57358 return this.isValid() ? !this._isUTC : false;
57359 }
57360
57361 function isUtcOffset() {
57362 return this.isValid() ? this._isUTC : false;
57363 }
57364
57365 function isUtc() {
57366 return this.isValid() ? this._isUTC && this._offset === 0 : false;
57367 } // ASP.NET json date format regex
57368
57369
57370 var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/; // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
57371 // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
57372 // and further modified to allow for strings containing both week and day
57373
57374 var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
57375
57376 function createDuration(input, key) {
57377 var duration = input,
57378 // matching against regexp is expensive, do it on demand
57379 match = null,
57380 sign,
57381 ret,
57382 diffRes;
57383
57384 if (isDuration(input)) {
57385 duration = {
57386 ms: input._milliseconds,
57387 d: input._days,
57388 M: input._months
57389 };
57390 } else if (isNumber(input)) {
57391 duration = {};
57392
57393 if (key) {
57394 duration[key] = input;
57395 } else {
57396 duration.milliseconds = input;
57397 }
57398 } else if (!!(match = aspNetRegex.exec(input))) {
57399 sign = match[1] === '-' ? -1 : 1;
57400 duration = {
57401 y: 0,
57402 d: toInt(match[DATE]) * sign,
57403 h: toInt(match[HOUR]) * sign,
57404 m: toInt(match[MINUTE]) * sign,
57405 s: toInt(match[SECOND]) * sign,
57406 ms: toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
57407
57408 };
57409 } else if (!!(match = isoRegex.exec(input))) {
57410 sign = match[1] === '-' ? -1 : 1;
57411 duration = {
57412 y: parseIso(match[2], sign),
57413 M: parseIso(match[3], sign),
57414 w: parseIso(match[4], sign),
57415 d: parseIso(match[5], sign),
57416 h: parseIso(match[6], sign),
57417 m: parseIso(match[7], sign),
57418 s: parseIso(match[8], sign)
57419 };
57420 } else if (duration == null) {
57421 // checks for null or undefined
57422 duration = {};
57423 } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
57424 diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
57425 duration = {};
57426 duration.ms = diffRes.milliseconds;
57427 duration.M = diffRes.months;
57428 }
57429
57430 ret = new Duration(duration);
57431
57432 if (isDuration(input) && hasOwnProp(input, '_locale')) {
57433 ret._locale = input._locale;
57434 }
57435
57436 return ret;
57437 }
57438
57439 createDuration.fn = Duration.prototype;
57440 createDuration.invalid = createInvalid$1;
57441
57442 function parseIso(inp, sign) {
57443 // We'd normally use ~~inp for this, but unfortunately it also
57444 // converts floats to ints.
57445 // inp may be undefined, so careful calling replace on it.
57446 var res = inp && parseFloat(inp.replace(',', '.')); // apply sign while we're at it
57447
57448 return (isNaN(res) ? 0 : res) * sign;
57449 }
57450
57451 function positiveMomentsDifference(base, other) {
57452 var res = {};
57453 res.months = other.month() - base.month() + (other.year() - base.year()) * 12;
57454
57455 if (base.clone().add(res.months, 'M').isAfter(other)) {
57456 --res.months;
57457 }
57458
57459 res.milliseconds = +other - +base.clone().add(res.months, 'M');
57460 return res;
57461 }
57462
57463 function momentsDifference(base, other) {
57464 var res;
57465
57466 if (!(base.isValid() && other.isValid())) {
57467 return {
57468 milliseconds: 0,
57469 months: 0
57470 };
57471 }
57472
57473 other = cloneWithOffset(other, base);
57474
57475 if (base.isBefore(other)) {
57476 res = positiveMomentsDifference(base, other);
57477 } else {
57478 res = positiveMomentsDifference(other, base);
57479 res.milliseconds = -res.milliseconds;
57480 res.months = -res.months;
57481 }
57482
57483 return res;
57484 } // TODO: remove 'name' arg after deprecation is removed
57485
57486
57487 function createAdder(direction, name) {
57488 return function (val, period) {
57489 var dur, tmp; //invert the arguments, but complain about it
57490
57491 if (period !== null && !isNaN(+period)) {
57492 deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' + 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
57493 tmp = val;
57494 val = period;
57495 period = tmp;
57496 }
57497
57498 val = typeof val === 'string' ? +val : val;
57499 dur = createDuration(val, period);
57500 addSubtract(this, dur, direction);
57501 return this;
57502 };
57503 }
57504
57505 function addSubtract(mom, duration, isAdding, updateOffset) {
57506 var milliseconds = duration._milliseconds,
57507 days = absRound(duration._days),
57508 months = absRound(duration._months);
57509
57510 if (!mom.isValid()) {
57511 // No op
57512 return;
57513 }
57514
57515 updateOffset = updateOffset == null ? true : updateOffset;
57516
57517 if (months) {
57518 setMonth(mom, get(mom, 'Month') + months * isAdding);
57519 }
57520
57521 if (days) {
57522 set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
57523 }
57524
57525 if (milliseconds) {
57526 mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
57527 }
57528
57529 if (updateOffset) {
57530 hooks.updateOffset(mom, days || months);
57531 }
57532 }
57533
57534 var add = createAdder(1, 'add');
57535 var subtract = createAdder(-1, 'subtract');
57536
57537 function getCalendarFormat(myMoment, now) {
57538 var diff = myMoment.diff(now, 'days', true);
57539 return diff < -6 ? 'sameElse' : diff < -1 ? 'lastWeek' : diff < 0 ? 'lastDay' : diff < 1 ? 'sameDay' : diff < 2 ? 'nextDay' : diff < 7 ? 'nextWeek' : 'sameElse';
57540 }
57541
57542 function calendar$1(time, formats) {
57543 // We want to compare the start of today, vs this.
57544 // Getting start-of-today depends on whether we're local/utc/offset or not.
57545 var now = time || createLocal(),
57546 sod = cloneWithOffset(now, this).startOf('day'),
57547 format = hooks.calendarFormat(this, sod) || 'sameElse';
57548 var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
57549 return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
57550 }
57551
57552 function clone() {
57553 return new Moment(this);
57554 }
57555
57556 function isAfter(input, units) {
57557 var localInput = isMoment(input) ? input : createLocal(input);
57558
57559 if (!(this.isValid() && localInput.isValid())) {
57560 return false;
57561 }
57562
57563 units = normalizeUnits(units) || 'millisecond';
57564
57565 if (units === 'millisecond') {
57566 return this.valueOf() > localInput.valueOf();
57567 } else {
57568 return localInput.valueOf() < this.clone().startOf(units).valueOf();
57569 }
57570 }
57571
57572 function isBefore(input, units) {
57573 var localInput = isMoment(input) ? input : createLocal(input);
57574
57575 if (!(this.isValid() && localInput.isValid())) {
57576 return false;
57577 }
57578
57579 units = normalizeUnits(units) || 'millisecond';
57580
57581 if (units === 'millisecond') {
57582 return this.valueOf() < localInput.valueOf();
57583 } else {
57584 return this.clone().endOf(units).valueOf() < localInput.valueOf();
57585 }
57586 }
57587
57588 function isBetween(from, to, units, inclusivity) {
57589 var localFrom = isMoment(from) ? from : createLocal(from),
57590 localTo = isMoment(to) ? to : createLocal(to);
57591
57592 if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
57593 return false;
57594 }
57595
57596 inclusivity = inclusivity || '()';
57597 return (inclusivity[0] === '(' ? this.isAfter(localFrom, units) : !this.isBefore(localFrom, units)) && (inclusivity[1] === ')' ? this.isBefore(localTo, units) : !this.isAfter(localTo, units));
57598 }
57599
57600 function isSame(input, units) {
57601 var localInput = isMoment(input) ? input : createLocal(input),
57602 inputMs;
57603
57604 if (!(this.isValid() && localInput.isValid())) {
57605 return false;
57606 }
57607
57608 units = normalizeUnits(units) || 'millisecond';
57609
57610 if (units === 'millisecond') {
57611 return this.valueOf() === localInput.valueOf();
57612 } else {
57613 inputMs = localInput.valueOf();
57614 return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
57615 }
57616 }
57617
57618 function isSameOrAfter(input, units) {
57619 return this.isSame(input, units) || this.isAfter(input, units);
57620 }
57621
57622 function isSameOrBefore(input, units) {
57623 return this.isSame(input, units) || this.isBefore(input, units);
57624 }
57625
57626 function diff(input, units, asFloat) {
57627 var that, zoneDelta, output;
57628
57629 if (!this.isValid()) {
57630 return NaN;
57631 }
57632
57633 that = cloneWithOffset(input, this);
57634
57635 if (!that.isValid()) {
57636 return NaN;
57637 }
57638
57639 zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
57640 units = normalizeUnits(units);
57641
57642 switch (units) {
57643 case 'year':
57644 output = monthDiff(this, that) / 12;
57645 break;
57646
57647 case 'month':
57648 output = monthDiff(this, that);
57649 break;
57650
57651 case 'quarter':
57652 output = monthDiff(this, that) / 3;
57653 break;
57654
57655 case 'second':
57656 output = (this - that) / 1e3;
57657 break;
57658 // 1000
57659
57660 case 'minute':
57661 output = (this - that) / 6e4;
57662 break;
57663 // 1000 * 60
57664
57665 case 'hour':
57666 output = (this - that) / 36e5;
57667 break;
57668 // 1000 * 60 * 60
57669
57670 case 'day':
57671 output = (this - that - zoneDelta) / 864e5;
57672 break;
57673 // 1000 * 60 * 60 * 24, negate dst
57674
57675 case 'week':
57676 output = (this - that - zoneDelta) / 6048e5;
57677 break;
57678 // 1000 * 60 * 60 * 24 * 7, negate dst
57679
57680 default:
57681 output = this - that;
57682 }
57683
57684 return asFloat ? output : absFloor(output);
57685 }
57686
57687 function monthDiff(a, b) {
57688 // difference in months
57689 var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()),
57690 // b is in (anchor - 1 month, anchor + 1 month)
57691 anchor = a.clone().add(wholeMonthDiff, 'months'),
57692 anchor2,
57693 adjust;
57694
57695 if (b - anchor < 0) {
57696 anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); // linear across the month
57697
57698 adjust = (b - anchor) / (anchor - anchor2);
57699 } else {
57700 anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); // linear across the month
57701
57702 adjust = (b - anchor) / (anchor2 - anchor);
57703 } //check for negative zero, return zero if negative zero
57704
57705
57706 return -(wholeMonthDiff + adjust) || 0;
57707 }
57708
57709 hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
57710 hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
57711
57712 function toString() {
57713 return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
57714 }
57715
57716 function toISOString(keepOffset) {
57717 if (!this.isValid()) {
57718 return null;
57719 }
57720
57721 var utc = keepOffset !== true;
57722 var m = utc ? this.clone().utc() : this;
57723
57724 if (m.year() < 0 || m.year() > 9999) {
57725 return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ');
57726 }
57727
57728 if (isFunction(Date.prototype.toISOString)) {
57729 // native implementation is ~50x faster, use it when we can
57730 if (utc) {
57731 return this.toDate().toISOString();
57732 } else {
57733 return new Date(this.valueOf() + this.utcOffset() * 60 * 1000).toISOString().replace('Z', formatMoment(m, 'Z'));
57734 }
57735 }
57736
57737 return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
57738 }
57739 /**
57740 * Return a human readable representation of a moment that can
57741 * also be evaluated to get a new moment which is the same
57742 *
57743 * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
57744 */
57745
57746
57747 function inspect() {
57748 if (!this.isValid()) {
57749 return 'moment.invalid(/* ' + this._i + ' */)';
57750 }
57751
57752 var func = 'moment';
57753 var zone = '';
57754
57755 if (!this.isLocal()) {
57756 func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
57757 zone = 'Z';
57758 }
57759
57760 var prefix = '[' + func + '("]';
57761 var year = 0 <= this.year() && this.year() <= 9999 ? 'YYYY' : 'YYYYYY';
57762 var datetime = '-MM-DD[T]HH:mm:ss.SSS';
57763 var suffix = zone + '[")]';
57764 return this.format(prefix + year + datetime + suffix);
57765 }
57766
57767 function format(inputString) {
57768 if (!inputString) {
57769 inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
57770 }
57771
57772 var output = formatMoment(this, inputString);
57773 return this.localeData().postformat(output);
57774 }
57775
57776 function from(time, withoutSuffix) {
57777 if (this.isValid() && (isMoment(time) && time.isValid() || createLocal(time).isValid())) {
57778 return createDuration({
57779 to: this,
57780 from: time
57781 }).locale(this.locale()).humanize(!withoutSuffix);
57782 } else {
57783 return this.localeData().invalidDate();
57784 }
57785 }
57786
57787 function fromNow(withoutSuffix) {
57788 return this.from(createLocal(), withoutSuffix);
57789 }
57790
57791 function to(time, withoutSuffix) {
57792 if (this.isValid() && (isMoment(time) && time.isValid() || createLocal(time).isValid())) {
57793 return createDuration({
57794 from: this,
57795 to: time
57796 }).locale(this.locale()).humanize(!withoutSuffix);
57797 } else {
57798 return this.localeData().invalidDate();
57799 }
57800 }
57801
57802 function toNow(withoutSuffix) {
57803 return this.to(createLocal(), withoutSuffix);
57804 } // If passed a locale key, it will set the locale for this
57805 // instance. Otherwise, it will return the locale configuration
57806 // variables for this instance.
57807
57808
57809 function locale(key) {
57810 var newLocaleData;
57811
57812 if (key === undefined) {
57813 return this._locale._abbr;
57814 } else {
57815 newLocaleData = getLocale(key);
57816
57817 if (newLocaleData != null) {
57818 this._locale = newLocaleData;
57819 }
57820
57821 return this;
57822 }
57823 }
57824
57825 var lang = deprecate('moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', function (key) {
57826 if (key === undefined) {
57827 return this.localeData();
57828 } else {
57829 return this.locale(key);
57830 }
57831 });
57832
57833 function localeData() {
57834 return this._locale;
57835 }
57836
57837 var MS_PER_SECOND = 1000;
57838 var MS_PER_MINUTE = 60 * MS_PER_SECOND;
57839 var MS_PER_HOUR = 60 * MS_PER_MINUTE;
57840 var MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR; // actual modulo - handles negative numbers (for dates before 1970):
57841
57842 function mod$1(dividend, divisor) {
57843 return (dividend % divisor + divisor) % divisor;
57844 }
57845
57846 function localStartOfDate(y, m, d) {
57847 // the date constructor remaps years 0-99 to 1900-1999
57848 if (y < 100 && y >= 0) {
57849 // preserve leap years using a full 400 year cycle, then reset
57850 return new Date(y + 400, m, d) - MS_PER_400_YEARS;
57851 } else {
57852 return new Date(y, m, d).valueOf();
57853 }
57854 }
57855
57856 function utcStartOfDate(y, m, d) {
57857 // Date.UTC remaps years 0-99 to 1900-1999
57858 if (y < 100 && y >= 0) {
57859 // preserve leap years using a full 400 year cycle, then reset
57860 return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
57861 } else {
57862 return Date.UTC(y, m, d);
57863 }
57864 }
57865
57866 function startOf(units) {
57867 var time;
57868 units = normalizeUnits(units);
57869
57870 if (units === undefined || units === 'millisecond' || !this.isValid()) {
57871 return this;
57872 }
57873
57874 var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
57875
57876 switch (units) {
57877 case 'year':
57878 time = startOfDate(this.year(), 0, 1);
57879 break;
57880
57881 case 'quarter':
57882 time = startOfDate(this.year(), this.month() - this.month() % 3, 1);
57883 break;
57884
57885 case 'month':
57886 time = startOfDate(this.year(), this.month(), 1);
57887 break;
57888
57889 case 'week':
57890 time = startOfDate(this.year(), this.month(), this.date() - this.weekday());
57891 break;
57892
57893 case 'isoWeek':
57894 time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1));
57895 break;
57896
57897 case 'day':
57898 case 'date':
57899 time = startOfDate(this.year(), this.month(), this.date());
57900 break;
57901
57902 case 'hour':
57903 time = this._d.valueOf();
57904 time -= mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR);
57905 break;
57906
57907 case 'minute':
57908 time = this._d.valueOf();
57909 time -= mod$1(time, MS_PER_MINUTE);
57910 break;
57911
57912 case 'second':
57913 time = this._d.valueOf();
57914 time -= mod$1(time, MS_PER_SECOND);
57915 break;
57916 }
57917
57918 this._d.setTime(time);
57919
57920 hooks.updateOffset(this, true);
57921 return this;
57922 }
57923
57924 function endOf(units) {
57925 var time;
57926 units = normalizeUnits(units);
57927
57928 if (units === undefined || units === 'millisecond' || !this.isValid()) {
57929 return this;
57930 }
57931
57932 var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
57933
57934 switch (units) {
57935 case 'year':
57936 time = startOfDate(this.year() + 1, 0, 1) - 1;
57937 break;
57938
57939 case 'quarter':
57940 time = startOfDate(this.year(), this.month() - this.month() % 3 + 3, 1) - 1;
57941 break;
57942
57943 case 'month':
57944 time = startOfDate(this.year(), this.month() + 1, 1) - 1;
57945 break;
57946
57947 case 'week':
57948 time = startOfDate(this.year(), this.month(), this.date() - this.weekday() + 7) - 1;
57949 break;
57950
57951 case 'isoWeek':
57952 time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1) + 7) - 1;
57953 break;
57954
57955 case 'day':
57956 case 'date':
57957 time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
57958 break;
57959
57960 case 'hour':
57961 time = this._d.valueOf();
57962 time += MS_PER_HOUR - mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR) - 1;
57963 break;
57964
57965 case 'minute':
57966 time = this._d.valueOf();
57967 time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
57968 break;
57969
57970 case 'second':
57971 time = this._d.valueOf();
57972 time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
57973 break;
57974 }
57975
57976 this._d.setTime(time);
57977
57978 hooks.updateOffset(this, true);
57979 return this;
57980 }
57981
57982 function valueOf() {
57983 return this._d.valueOf() - (this._offset || 0) * 60000;
57984 }
57985
57986 function unix() {
57987 return Math.floor(this.valueOf() / 1000);
57988 }
57989
57990 function toDate() {
57991 return new Date(this.valueOf());
57992 }
57993
57994 function toArray() {
57995 var m = this;
57996 return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
57997 }
57998
57999 function toObject() {
58000 var m = this;
58001 return {
58002 years: m.year(),
58003 months: m.month(),
58004 date: m.date(),
58005 hours: m.hours(),
58006 minutes: m.minutes(),
58007 seconds: m.seconds(),
58008 milliseconds: m.milliseconds()
58009 };
58010 }
58011
58012 function toJSON() {
58013 // new Date(NaN).toJSON() === null
58014 return this.isValid() ? this.toISOString() : null;
58015 }
58016
58017 function isValid$2() {
58018 return isValid(this);
58019 }
58020
58021 function parsingFlags() {
58022 return extend({}, getParsingFlags(this));
58023 }
58024
58025 function invalidAt() {
58026 return getParsingFlags(this).overflow;
58027 }
58028
58029 function creationData() {
58030 return {
58031 input: this._i,
58032 format: this._f,
58033 locale: this._locale,
58034 isUTC: this._isUTC,
58035 strict: this._strict
58036 };
58037 } // FORMATTING
58038
58039
58040 addFormatToken(0, ['gg', 2], 0, function () {
58041 return this.weekYear() % 100;
58042 });
58043 addFormatToken(0, ['GG', 2], 0, function () {
58044 return this.isoWeekYear() % 100;
58045 });
58046
58047 function addWeekYearFormatToken(token, getter) {
58048 addFormatToken(0, [token, token.length], 0, getter);
58049 }
58050
58051 addWeekYearFormatToken('gggg', 'weekYear');
58052 addWeekYearFormatToken('ggggg', 'weekYear');
58053 addWeekYearFormatToken('GGGG', 'isoWeekYear');
58054 addWeekYearFormatToken('GGGGG', 'isoWeekYear'); // ALIASES
58055
58056 addUnitAlias('weekYear', 'gg');
58057 addUnitAlias('isoWeekYear', 'GG'); // PRIORITY
58058
58059 addUnitPriority('weekYear', 1);
58060 addUnitPriority('isoWeekYear', 1); // PARSING
58061
58062 addRegexToken('G', matchSigned);
58063 addRegexToken('g', matchSigned);
58064 addRegexToken('GG', match1to2, match2);
58065 addRegexToken('gg', match1to2, match2);
58066 addRegexToken('GGGG', match1to4, match4);
58067 addRegexToken('gggg', match1to4, match4);
58068 addRegexToken('GGGGG', match1to6, match6);
58069 addRegexToken('ggggg', match1to6, match6);
58070 addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
58071 week[token.substr(0, 2)] = toInt(input);
58072 });
58073 addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
58074 week[token] = hooks.parseTwoDigitYear(input);
58075 }); // MOMENTS
58076
58077 function getSetWeekYear(input) {
58078 return getSetWeekYearHelper.call(this, input, this.week(), this.weekday(), this.localeData()._week.dow, this.localeData()._week.doy);
58079 }
58080
58081 function getSetISOWeekYear(input) {
58082 return getSetWeekYearHelper.call(this, input, this.isoWeek(), this.isoWeekday(), 1, 4);
58083 }
58084
58085 function getISOWeeksInYear() {
58086 return weeksInYear(this.year(), 1, 4);
58087 }
58088
58089 function getWeeksInYear() {
58090 var weekInfo = this.localeData()._week;
58091
58092 return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
58093 }
58094
58095 function getSetWeekYearHelper(input, week, weekday, dow, doy) {
58096 var weeksTarget;
58097
58098 if (input == null) {
58099 return weekOfYear(this, dow, doy).year;
58100 } else {
58101 weeksTarget = weeksInYear(input, dow, doy);
58102
58103 if (week > weeksTarget) {
58104 week = weeksTarget;
58105 }
58106
58107 return setWeekAll.call(this, input, week, weekday, dow, doy);
58108 }
58109 }
58110
58111 function setWeekAll(weekYear, week, weekday, dow, doy) {
58112 var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
58113 date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
58114 this.year(date.getUTCFullYear());
58115 this.month(date.getUTCMonth());
58116 this.date(date.getUTCDate());
58117 return this;
58118 } // FORMATTING
58119
58120
58121 addFormatToken('Q', 0, 'Qo', 'quarter'); // ALIASES
58122
58123 addUnitAlias('quarter', 'Q'); // PRIORITY
58124
58125 addUnitPriority('quarter', 7); // PARSING
58126
58127 addRegexToken('Q', match1);
58128 addParseToken('Q', function (input, array) {
58129 array[MONTH] = (toInt(input) - 1) * 3;
58130 }); // MOMENTS
58131
58132 function getSetQuarter(input) {
58133 return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
58134 } // FORMATTING
58135
58136
58137 addFormatToken('D', ['DD', 2], 'Do', 'date'); // ALIASES
58138
58139 addUnitAlias('date', 'D'); // PRIORITY
58140
58141 addUnitPriority('date', 9); // PARSING
58142
58143 addRegexToken('D', match1to2);
58144 addRegexToken('DD', match1to2, match2);
58145 addRegexToken('Do', function (isStrict, locale) {
58146 // TODO: Remove "ordinalParse" fallback in next major release.
58147 return isStrict ? locale._dayOfMonthOrdinalParse || locale._ordinalParse : locale._dayOfMonthOrdinalParseLenient;
58148 });
58149 addParseToken(['D', 'DD'], DATE);
58150 addParseToken('Do', function (input, array) {
58151 array[DATE] = toInt(input.match(match1to2)[0]);
58152 }); // MOMENTS
58153
58154 var getSetDayOfMonth = makeGetSet('Date', true); // FORMATTING
58155
58156 addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); // ALIASES
58157
58158 addUnitAlias('dayOfYear', 'DDD'); // PRIORITY
58159
58160 addUnitPriority('dayOfYear', 4); // PARSING
58161
58162 addRegexToken('DDD', match1to3);
58163 addRegexToken('DDDD', match3);
58164 addParseToken(['DDD', 'DDDD'], function (input, array, config) {
58165 config._dayOfYear = toInt(input);
58166 }); // HELPERS
58167 // MOMENTS
58168
58169 function getSetDayOfYear(input) {
58170 var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
58171 return input == null ? dayOfYear : this.add(input - dayOfYear, 'd');
58172 } // FORMATTING
58173
58174
58175 addFormatToken('m', ['mm', 2], 0, 'minute'); // ALIASES
58176
58177 addUnitAlias('minute', 'm'); // PRIORITY
58178
58179 addUnitPriority('minute', 14); // PARSING
58180
58181 addRegexToken('m', match1to2);
58182 addRegexToken('mm', match1to2, match2);
58183 addParseToken(['m', 'mm'], MINUTE); // MOMENTS
58184
58185 var getSetMinute = makeGetSet('Minutes', false); // FORMATTING
58186
58187 addFormatToken('s', ['ss', 2], 0, 'second'); // ALIASES
58188
58189 addUnitAlias('second', 's'); // PRIORITY
58190
58191 addUnitPriority('second', 15); // PARSING
58192
58193 addRegexToken('s', match1to2);
58194 addRegexToken('ss', match1to2, match2);
58195 addParseToken(['s', 'ss'], SECOND); // MOMENTS
58196
58197 var getSetSecond = makeGetSet('Seconds', false); // FORMATTING
58198
58199 addFormatToken('S', 0, 0, function () {
58200 return ~~(this.millisecond() / 100);
58201 });
58202 addFormatToken(0, ['SS', 2], 0, function () {
58203 return ~~(this.millisecond() / 10);
58204 });
58205 addFormatToken(0, ['SSS', 3], 0, 'millisecond');
58206 addFormatToken(0, ['SSSS', 4], 0, function () {
58207 return this.millisecond() * 10;
58208 });
58209 addFormatToken(0, ['SSSSS', 5], 0, function () {
58210 return this.millisecond() * 100;
58211 });
58212 addFormatToken(0, ['SSSSSS', 6], 0, function () {
58213 return this.millisecond() * 1000;
58214 });
58215 addFormatToken(0, ['SSSSSSS', 7], 0, function () {
58216 return this.millisecond() * 10000;
58217 });
58218 addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
58219 return this.millisecond() * 100000;
58220 });
58221 addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
58222 return this.millisecond() * 1000000;
58223 }); // ALIASES
58224
58225 addUnitAlias('millisecond', 'ms'); // PRIORITY
58226
58227 addUnitPriority('millisecond', 16); // PARSING
58228
58229 addRegexToken('S', match1to3, match1);
58230 addRegexToken('SS', match1to3, match2);
58231 addRegexToken('SSS', match1to3, match3);
58232 var token;
58233
58234 for (token = 'SSSS'; token.length <= 9; token += 'S') {
58235 addRegexToken(token, matchUnsigned);
58236 }
58237
58238 function parseMs(input, array) {
58239 array[MILLISECOND] = toInt(('0.' + input) * 1000);
58240 }
58241
58242 for (token = 'S'; token.length <= 9; token += 'S') {
58243 addParseToken(token, parseMs);
58244 } // MOMENTS
58245
58246
58247 var getSetMillisecond = makeGetSet('Milliseconds', false); // FORMATTING
58248
58249 addFormatToken('z', 0, 0, 'zoneAbbr');
58250 addFormatToken('zz', 0, 0, 'zoneName'); // MOMENTS
58251
58252 function getZoneAbbr() {
58253 return this._isUTC ? 'UTC' : '';
58254 }
58255
58256 function getZoneName() {
58257 return this._isUTC ? 'Coordinated Universal Time' : '';
58258 }
58259
58260 var proto = Moment.prototype;
58261 proto.add = add;
58262 proto.calendar = calendar$1;
58263 proto.clone = clone;
58264 proto.diff = diff;
58265 proto.endOf = endOf;
58266 proto.format = format;
58267 proto.from = from;
58268 proto.fromNow = fromNow;
58269 proto.to = to;
58270 proto.toNow = toNow;
58271 proto.get = stringGet;
58272 proto.invalidAt = invalidAt;
58273 proto.isAfter = isAfter;
58274 proto.isBefore = isBefore;
58275 proto.isBetween = isBetween;
58276 proto.isSame = isSame;
58277 proto.isSameOrAfter = isSameOrAfter;
58278 proto.isSameOrBefore = isSameOrBefore;
58279 proto.isValid = isValid$2;
58280 proto.lang = lang;
58281 proto.locale = locale;
58282 proto.localeData = localeData;
58283 proto.max = prototypeMax;
58284 proto.min = prototypeMin;
58285 proto.parsingFlags = parsingFlags;
58286 proto.set = stringSet;
58287 proto.startOf = startOf;
58288 proto.subtract = subtract;
58289 proto.toArray = toArray;
58290 proto.toObject = toObject;
58291 proto.toDate = toDate;
58292 proto.toISOString = toISOString;
58293 proto.inspect = inspect;
58294 proto.toJSON = toJSON;
58295 proto.toString = toString;
58296 proto.unix = unix;
58297 proto.valueOf = valueOf;
58298 proto.creationData = creationData;
58299 proto.year = getSetYear;
58300 proto.isLeapYear = getIsLeapYear;
58301 proto.weekYear = getSetWeekYear;
58302 proto.isoWeekYear = getSetISOWeekYear;
58303 proto.quarter = proto.quarters = getSetQuarter;
58304 proto.month = getSetMonth;
58305 proto.daysInMonth = getDaysInMonth;
58306 proto.week = proto.weeks = getSetWeek;
58307 proto.isoWeek = proto.isoWeeks = getSetISOWeek;
58308 proto.weeksInYear = getWeeksInYear;
58309 proto.isoWeeksInYear = getISOWeeksInYear;
58310 proto.date = getSetDayOfMonth;
58311 proto.day = proto.days = getSetDayOfWeek;
58312 proto.weekday = getSetLocaleDayOfWeek;
58313 proto.isoWeekday = getSetISODayOfWeek;
58314 proto.dayOfYear = getSetDayOfYear;
58315 proto.hour = proto.hours = getSetHour;
58316 proto.minute = proto.minutes = getSetMinute;
58317 proto.second = proto.seconds = getSetSecond;
58318 proto.millisecond = proto.milliseconds = getSetMillisecond;
58319 proto.utcOffset = getSetOffset;
58320 proto.utc = setOffsetToUTC;
58321 proto.local = setOffsetToLocal;
58322 proto.parseZone = setOffsetToParsedOffset;
58323 proto.hasAlignedHourOffset = hasAlignedHourOffset;
58324 proto.isDST = isDaylightSavingTime;
58325 proto.isLocal = isLocal;
58326 proto.isUtcOffset = isUtcOffset;
58327 proto.isUtc = isUtc;
58328 proto.isUTC = isUtc;
58329 proto.zoneAbbr = getZoneAbbr;
58330 proto.zoneName = getZoneName;
58331 proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
58332 proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
58333 proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);
58334 proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
58335 proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
58336
58337 function createUnix(input) {
58338 return createLocal(input * 1000);
58339 }
58340
58341 function createInZone() {
58342 return createLocal.apply(null, arguments).parseZone();
58343 }
58344
58345 function preParsePostFormat(string) {
58346 return string;
58347 }
58348
58349 var proto$1 = Locale.prototype;
58350 proto$1.calendar = calendar;
58351 proto$1.longDateFormat = longDateFormat;
58352 proto$1.invalidDate = invalidDate;
58353 proto$1.ordinal = ordinal;
58354 proto$1.preparse = preParsePostFormat;
58355 proto$1.postformat = preParsePostFormat;
58356 proto$1.relativeTime = relativeTime;
58357 proto$1.pastFuture = pastFuture;
58358 proto$1.set = set;
58359 proto$1.months = localeMonths;
58360 proto$1.monthsShort = localeMonthsShort;
58361 proto$1.monthsParse = localeMonthsParse;
58362 proto$1.monthsRegex = monthsRegex;
58363 proto$1.monthsShortRegex = monthsShortRegex;
58364 proto$1.week = localeWeek;
58365 proto$1.firstDayOfYear = localeFirstDayOfYear;
58366 proto$1.firstDayOfWeek = localeFirstDayOfWeek;
58367 proto$1.weekdays = localeWeekdays;
58368 proto$1.weekdaysMin = localeWeekdaysMin;
58369 proto$1.weekdaysShort = localeWeekdaysShort;
58370 proto$1.weekdaysParse = localeWeekdaysParse;
58371 proto$1.weekdaysRegex = weekdaysRegex;
58372 proto$1.weekdaysShortRegex = weekdaysShortRegex;
58373 proto$1.weekdaysMinRegex = weekdaysMinRegex;
58374 proto$1.isPM = localeIsPM;
58375 proto$1.meridiem = localeMeridiem;
58376
58377 function get$1(format, index, field, setter) {
58378 var locale = getLocale();
58379 var utc = createUTC().set(setter, index);
58380 return locale[field](utc, format);
58381 }
58382
58383 function listMonthsImpl(format, index, field) {
58384 if (isNumber(format)) {
58385 index = format;
58386 format = undefined;
58387 }
58388
58389 format = format || '';
58390
58391 if (index != null) {
58392 return get$1(format, index, field, 'month');
58393 }
58394
58395 var i;
58396 var out = [];
58397
58398 for (i = 0; i < 12; i++) {
58399 out[i] = get$1(format, i, field, 'month');
58400 }
58401
58402 return out;
58403 } // ()
58404 // (5)
58405 // (fmt, 5)
58406 // (fmt)
58407 // (true)
58408 // (true, 5)
58409 // (true, fmt, 5)
58410 // (true, fmt)
58411
58412
58413 function listWeekdaysImpl(localeSorted, format, index, field) {
58414 if (typeof localeSorted === 'boolean') {
58415 if (isNumber(format)) {
58416 index = format;
58417 format = undefined;
58418 }
58419
58420 format = format || '';
58421 } else {
58422 format = localeSorted;
58423 index = format;
58424 localeSorted = false;
58425
58426 if (isNumber(format)) {
58427 index = format;
58428 format = undefined;
58429 }
58430
58431 format = format || '';
58432 }
58433
58434 var locale = getLocale(),
58435 shift = localeSorted ? locale._week.dow : 0;
58436
58437 if (index != null) {
58438 return get$1(format, (index + shift) % 7, field, 'day');
58439 }
58440
58441 var i;
58442 var out = [];
58443
58444 for (i = 0; i < 7; i++) {
58445 out[i] = get$1(format, (i + shift) % 7, field, 'day');
58446 }
58447
58448 return out;
58449 }
58450
58451 function listMonths(format, index) {
58452 return listMonthsImpl(format, index, 'months');
58453 }
58454
58455 function listMonthsShort(format, index) {
58456 return listMonthsImpl(format, index, 'monthsShort');
58457 }
58458
58459 function listWeekdays(localeSorted, format, index) {
58460 return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
58461 }
58462
58463 function listWeekdaysShort(localeSorted, format, index) {
58464 return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
58465 }
58466
58467 function listWeekdaysMin(localeSorted, format, index) {
58468 return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
58469 }
58470
58471 getSetGlobalLocale('en', {
58472 dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
58473 ordinal: function (number) {
58474 var b = number % 10,
58475 output = toInt(number % 100 / 10) === 1 ? 'th' : b === 1 ? 'st' : b === 2 ? 'nd' : b === 3 ? 'rd' : 'th';
58476 return number + output;
58477 }
58478 }); // Side effect imports
58479
58480 hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
58481 hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
58482 var mathAbs = Math.abs;
58483
58484 function abs() {
58485 var data = this._data;
58486 this._milliseconds = mathAbs(this._milliseconds);
58487 this._days = mathAbs(this._days);
58488 this._months = mathAbs(this._months);
58489 data.milliseconds = mathAbs(data.milliseconds);
58490 data.seconds = mathAbs(data.seconds);
58491 data.minutes = mathAbs(data.minutes);
58492 data.hours = mathAbs(data.hours);
58493 data.months = mathAbs(data.months);
58494 data.years = mathAbs(data.years);
58495 return this;
58496 }
58497
58498 function addSubtract$1(duration, input, value, direction) {
58499 var other = createDuration(input, value);
58500 duration._milliseconds += direction * other._milliseconds;
58501 duration._days += direction * other._days;
58502 duration._months += direction * other._months;
58503 return duration._bubble();
58504 } // supports only 2.0-style add(1, 's') or add(duration)
58505
58506
58507 function add$1(input, value) {
58508 return addSubtract$1(this, input, value, 1);
58509 } // supports only 2.0-style subtract(1, 's') or subtract(duration)
58510
58511
58512 function subtract$1(input, value) {
58513 return addSubtract$1(this, input, value, -1);
58514 }
58515
58516 function absCeil(number) {
58517 if (number < 0) {
58518 return Math.floor(number);
58519 } else {
58520 return Math.ceil(number);
58521 }
58522 }
58523
58524 function bubble() {
58525 var milliseconds = this._milliseconds;
58526 var days = this._days;
58527 var months = this._months;
58528 var data = this._data;
58529 var seconds, minutes, hours, years, monthsFromDays; // if we have a mix of positive and negative values, bubble down first
58530 // check: https://github.com/moment/moment/issues/2166
58531
58532 if (!(milliseconds >= 0 && days >= 0 && months >= 0 || milliseconds <= 0 && days <= 0 && months <= 0)) {
58533 milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
58534 days = 0;
58535 months = 0;
58536 } // The following code bubbles up values, see the tests for
58537 // examples of what that means.
58538
58539
58540 data.milliseconds = milliseconds % 1000;
58541 seconds = absFloor(milliseconds / 1000);
58542 data.seconds = seconds % 60;
58543 minutes = absFloor(seconds / 60);
58544 data.minutes = minutes % 60;
58545 hours = absFloor(minutes / 60);
58546 data.hours = hours % 24;
58547 days += absFloor(hours / 24); // convert days to months
58548
58549 monthsFromDays = absFloor(daysToMonths(days));
58550 months += monthsFromDays;
58551 days -= absCeil(monthsToDays(monthsFromDays)); // 12 months -> 1 year
58552
58553 years = absFloor(months / 12);
58554 months %= 12;
58555 data.days = days;
58556 data.months = months;
58557 data.years = years;
58558 return this;
58559 }
58560
58561 function daysToMonths(days) {
58562 // 400 years have 146097 days (taking into account leap year rules)
58563 // 400 years have 12 months === 4800
58564 return days * 4800 / 146097;
58565 }
58566
58567 function monthsToDays(months) {
58568 // the reverse of daysToMonths
58569 return months * 146097 / 4800;
58570 }
58571
58572 function as(units) {
58573 if (!this.isValid()) {
58574 return NaN;
58575 }
58576
58577 var days;
58578 var months;
58579 var milliseconds = this._milliseconds;
58580 units = normalizeUnits(units);
58581
58582 if (units === 'month' || units === 'quarter' || units === 'year') {
58583 days = this._days + milliseconds / 864e5;
58584 months = this._months + daysToMonths(days);
58585
58586 switch (units) {
58587 case 'month':
58588 return months;
58589
58590 case 'quarter':
58591 return months / 3;
58592
58593 case 'year':
58594 return months / 12;
58595 }
58596 } else {
58597 // handle milliseconds separately because of floating point math errors (issue #1867)
58598 days = this._days + Math.round(monthsToDays(this._months));
58599
58600 switch (units) {
58601 case 'week':
58602 return days / 7 + milliseconds / 6048e5;
58603
58604 case 'day':
58605 return days + milliseconds / 864e5;
58606
58607 case 'hour':
58608 return days * 24 + milliseconds / 36e5;
58609
58610 case 'minute':
58611 return days * 1440 + milliseconds / 6e4;
58612
58613 case 'second':
58614 return days * 86400 + milliseconds / 1000;
58615 // Math.floor prevents floating point math errors here
58616
58617 case 'millisecond':
58618 return Math.floor(days * 864e5) + milliseconds;
58619
58620 default:
58621 throw new Error('Unknown unit ' + units);
58622 }
58623 }
58624 } // TODO: Use this.as('ms')?
58625
58626
58627 function valueOf$1() {
58628 if (!this.isValid()) {
58629 return NaN;
58630 }
58631
58632 return this._milliseconds + this._days * 864e5 + this._months % 12 * 2592e6 + toInt(this._months / 12) * 31536e6;
58633 }
58634
58635 function makeAs(alias) {
58636 return function () {
58637 return this.as(alias);
58638 };
58639 }
58640
58641 var asMilliseconds = makeAs('ms');
58642 var asSeconds = makeAs('s');
58643 var asMinutes = makeAs('m');
58644 var asHours = makeAs('h');
58645 var asDays = makeAs('d');
58646 var asWeeks = makeAs('w');
58647 var asMonths = makeAs('M');
58648 var asQuarters = makeAs('Q');
58649 var asYears = makeAs('y');
58650
58651 function clone$1() {
58652 return createDuration(this);
58653 }
58654
58655 function get$2(units) {
58656 units = normalizeUnits(units);
58657 return this.isValid() ? this[units + 's']() : NaN;
58658 }
58659
58660 function makeGetter(name) {
58661 return function () {
58662 return this.isValid() ? this._data[name] : NaN;
58663 };
58664 }
58665
58666 var milliseconds = makeGetter('milliseconds');
58667 var seconds = makeGetter('seconds');
58668 var minutes = makeGetter('minutes');
58669 var hours = makeGetter('hours');
58670 var days = makeGetter('days');
58671 var months = makeGetter('months');
58672 var years = makeGetter('years');
58673
58674 function weeks() {
58675 return absFloor(this.days() / 7);
58676 }
58677
58678 var round = Math.round;
58679 var thresholds = {
58680 ss: 44,
58681 // a few seconds to seconds
58682 s: 45,
58683 // seconds to minute
58684 m: 45,
58685 // minutes to hour
58686 h: 22,
58687 // hours to day
58688 d: 26,
58689 // days to month
58690 M: 11 // months to year
58691
58692 }; // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
58693
58694 function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
58695 return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
58696 }
58697
58698 function relativeTime$1(posNegDuration, withoutSuffix, locale) {
58699 var duration = createDuration(posNegDuration).abs();
58700 var seconds = round(duration.as('s'));
58701 var minutes = round(duration.as('m'));
58702 var hours = round(duration.as('h'));
58703 var days = round(duration.as('d'));
58704 var months = round(duration.as('M'));
58705 var years = round(duration.as('y'));
58706 var a = seconds <= thresholds.ss && ['s', seconds] || seconds < thresholds.s && ['ss', seconds] || minutes <= 1 && ['m'] || minutes < thresholds.m && ['mm', minutes] || hours <= 1 && ['h'] || hours < thresholds.h && ['hh', hours] || days <= 1 && ['d'] || days < thresholds.d && ['dd', days] || months <= 1 && ['M'] || months < thresholds.M && ['MM', months] || years <= 1 && ['y'] || ['yy', years];
58707 a[2] = withoutSuffix;
58708 a[3] = +posNegDuration > 0;
58709 a[4] = locale;
58710 return substituteTimeAgo.apply(null, a);
58711 } // This function allows you to set the rounding function for relative time strings
58712
58713
58714 function getSetRelativeTimeRounding(roundingFunction) {
58715 if (roundingFunction === undefined) {
58716 return round;
58717 }
58718
58719 if (typeof roundingFunction === 'function') {
58720 round = roundingFunction;
58721 return true;
58722 }
58723
58724 return false;
58725 } // This function allows you to set a threshold for relative time strings
58726
58727
58728 function getSetRelativeTimeThreshold(threshold, limit) {
58729 if (thresholds[threshold] === undefined) {
58730 return false;
58731 }
58732
58733 if (limit === undefined) {
58734 return thresholds[threshold];
58735 }
58736
58737 thresholds[threshold] = limit;
58738
58739 if (threshold === 's') {
58740 thresholds.ss = limit - 1;
58741 }
58742
58743 return true;
58744 }
58745
58746 function humanize(withSuffix) {
58747 if (!this.isValid()) {
58748 return this.localeData().invalidDate();
58749 }
58750
58751 var locale = this.localeData();
58752 var output = relativeTime$1(this, !withSuffix, locale);
58753
58754 if (withSuffix) {
58755 output = locale.pastFuture(+this, output);
58756 }
58757
58758 return locale.postformat(output);
58759 }
58760
58761 var abs$1 = Math.abs;
58762
58763 function sign(x) {
58764 return (x > 0) - (x < 0) || +x;
58765 }
58766
58767 function toISOString$1() {
58768 // for ISO strings we do not use the normal bubbling rules:
58769 // * milliseconds bubble up until they become hours
58770 // * days do not bubble at all
58771 // * months bubble up until they become years
58772 // This is because there is no context-free conversion between hours and days
58773 // (think of clock changes)
58774 // and also not between days and months (28-31 days per month)
58775 if (!this.isValid()) {
58776 return this.localeData().invalidDate();
58777 }
58778
58779 var seconds = abs$1(this._milliseconds) / 1000;
58780 var days = abs$1(this._days);
58781 var months = abs$1(this._months);
58782 var minutes, hours, years; // 3600 seconds -> 60 minutes -> 1 hour
58783
58784 minutes = absFloor(seconds / 60);
58785 hours = absFloor(minutes / 60);
58786 seconds %= 60;
58787 minutes %= 60; // 12 months -> 1 year
58788
58789 years = absFloor(months / 12);
58790 months %= 12; // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
58791
58792 var Y = years;
58793 var M = months;
58794 var D = days;
58795 var h = hours;
58796 var m = minutes;
58797 var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
58798 var total = this.asSeconds();
58799
58800 if (!total) {
58801 // this is the same as C#'s (Noda) and python (isodate)...
58802 // but not other JS (goog.date)
58803 return 'P0D';
58804 }
58805
58806 var totalSign = total < 0 ? '-' : '';
58807 var ymSign = sign(this._months) !== sign(total) ? '-' : '';
58808 var daysSign = sign(this._days) !== sign(total) ? '-' : '';
58809 var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
58810 return totalSign + 'P' + (Y ? ymSign + Y + 'Y' : '') + (M ? ymSign + M + 'M' : '') + (D ? daysSign + D + 'D' : '') + (h || m || s ? 'T' : '') + (h ? hmsSign + h + 'H' : '') + (m ? hmsSign + m + 'M' : '') + (s ? hmsSign + s + 'S' : '');
58811 }
58812
58813 var proto$2 = Duration.prototype;
58814 proto$2.isValid = isValid$1;
58815 proto$2.abs = abs;
58816 proto$2.add = add$1;
58817 proto$2.subtract = subtract$1;
58818 proto$2.as = as;
58819 proto$2.asMilliseconds = asMilliseconds;
58820 proto$2.asSeconds = asSeconds;
58821 proto$2.asMinutes = asMinutes;
58822 proto$2.asHours = asHours;
58823 proto$2.asDays = asDays;
58824 proto$2.asWeeks = asWeeks;
58825 proto$2.asMonths = asMonths;
58826 proto$2.asQuarters = asQuarters;
58827 proto$2.asYears = asYears;
58828 proto$2.valueOf = valueOf$1;
58829 proto$2._bubble = bubble;
58830 proto$2.clone = clone$1;
58831 proto$2.get = get$2;
58832 proto$2.milliseconds = milliseconds;
58833 proto$2.seconds = seconds;
58834 proto$2.minutes = minutes;
58835 proto$2.hours = hours;
58836 proto$2.days = days;
58837 proto$2.weeks = weeks;
58838 proto$2.months = months;
58839 proto$2.years = years;
58840 proto$2.humanize = humanize;
58841 proto$2.toISOString = toISOString$1;
58842 proto$2.toString = toISOString$1;
58843 proto$2.toJSON = toISOString$1;
58844 proto$2.locale = locale;
58845 proto$2.localeData = localeData;
58846 proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
58847 proto$2.lang = lang; // Side effect imports
58848 // FORMATTING
58849
58850 addFormatToken('X', 0, 0, 'unix');
58851 addFormatToken('x', 0, 0, 'valueOf'); // PARSING
58852
58853 addRegexToken('x', matchSigned);
58854 addRegexToken('X', matchTimestamp);
58855 addParseToken('X', function (input, array, config) {
58856 config._d = new Date(parseFloat(input, 10) * 1000);
58857 });
58858 addParseToken('x', function (input, array, config) {
58859 config._d = new Date(toInt(input));
58860 }); // Side effect imports
58861
58862 hooks.version = '2.24.0';
58863 setHookCallback(createLocal);
58864 hooks.fn = proto;
58865 hooks.min = min;
58866 hooks.max = max;
58867 hooks.now = now;
58868 hooks.utc = createUTC;
58869 hooks.unix = createUnix;
58870 hooks.months = listMonths;
58871 hooks.isDate = isDate;
58872 hooks.locale = getSetGlobalLocale;
58873 hooks.invalid = createInvalid;
58874 hooks.duration = createDuration;
58875 hooks.isMoment = isMoment;
58876 hooks.weekdays = listWeekdays;
58877 hooks.parseZone = createInZone;
58878 hooks.localeData = getLocale;
58879 hooks.isDuration = isDuration;
58880 hooks.monthsShort = listMonthsShort;
58881 hooks.weekdaysMin = listWeekdaysMin;
58882 hooks.defineLocale = defineLocale;
58883 hooks.updateLocale = updateLocale;
58884 hooks.locales = listLocales;
58885 hooks.weekdaysShort = listWeekdaysShort;
58886 hooks.normalizeUnits = normalizeUnits;
58887 hooks.relativeTimeRounding = getSetRelativeTimeRounding;
58888 hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
58889 hooks.calendarFormat = getCalendarFormat;
58890 hooks.prototype = proto; // currently HTML5 input type only supports 24-hour formats
58891
58892 hooks.HTML5_FMT = {
58893 DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm',
58894 // <input type="datetime-local" />
58895 DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss',
58896 // <input type="datetime-local" step="1" />
58897 DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS',
58898 // <input type="datetime-local" step="0.001" />
58899 DATE: 'YYYY-MM-DD',
58900 // <input type="date" />
58901 TIME: 'HH:mm',
58902 // <input type="time" />
58903 TIME_SECONDS: 'HH:mm:ss',
58904 // <input type="time" step="1" />
58905 TIME_MS: 'HH:mm:ss.SSS',
58906 // <input type="time" step="0.001" />
58907 WEEK: 'GGGG-[W]WW',
58908 // <input type="week" />
58909 MONTH: 'YYYY-MM' // <input type="month" />
58910
58911 };
58912 return hooks;
58913 });
58914});
58915
58916// use this instance. Else, load via commonjs.
58917
58918var moment$3 = typeof window !== 'undefined' && window['moment'] || moment$2;
58919
58920var moment$4 = /*#__PURE__*/Object.freeze({
58921 __proto__: null,
58922 'default': moment$3,
58923 __moduleExports: moment$3
58924});
58925
58926var network = {
58927 Images: Images,
58928 dotparser: dotparser$1,
58929 gephiParser: gephiParser,
58930 allOptions: allOptions$2,
58931 convertDot: DOTToGraph_1,
58932 convertGephi: parseGephi
58933}; // utils
58934
58935var indexLegacy = /*#__PURE__*/Object.freeze({
58936 __proto__: null,
58937 network: network,
58938 DOMutil: DOMutil$1,
58939 util: esm,
58940 data: esm$1,
58941 moment: moment$4,
58942 Hammer: hammer$1,
58943 keycharm: keycharm$1,
58944 DataSet: DataSet,
58945 DataView: DataView$2,
58946 Queue: Queue,
58947 Network: Network
58948});
58949
58950export default indexLegacy;
58951export { DOMutil$1 as DOMutil, DataSet, DataView$2 as DataView, hammer$1 as Hammer, Network, Queue, esm$1 as data, keycharm$1 as keycharm, moment$4 as moment, network, esm as util };
58952//# sourceMappingURL=vis-network.esm.js.map