vis-util 5.0.7 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/declarations/deep-object-assign.d.ts +0 -2
- package/declarations/deep-object-assign.d.ts.map +1 -1
- package/declarations/entry-esnext.d.ts +4 -4
- package/declarations/entry-esnext.d.ts.map +1 -1
- package/declarations/index.d.ts +2 -2
- package/declarations/index.d.ts.map +1 -1
- package/declarations/random/alea.d.ts +0 -2
- package/declarations/random/alea.d.ts.map +1 -1
- package/declarations/random/index.d.ts +1 -1
- package/declarations/random/index.d.ts.map +1 -1
- package/declarations/shared/configurator-types.d.ts +0 -1
- package/declarations/shared/configurator-types.d.ts.map +1 -1
- package/declarations/shared/index.d.ts +1 -2
- package/declarations/shared/index.d.ts.map +1 -1
- package/declarations/util.d.ts +2 -63
- package/declarations/util.d.ts.map +1 -1
- package/esnext/esm/vis-util.js +1629 -1757
- package/esnext/esm/vis-util.js.map +1 -1
- package/esnext/esm/vis-util.min.js +3 -3
- package/esnext/esm/vis-util.min.js.map +1 -1
- package/esnext/esm/vis-util.min.mjs +27 -0
- package/esnext/esm/vis-util.min.mjs.map +1 -0
- package/esnext/esm/vis-util.mjs +3924 -0
- package/esnext/esm/vis-util.mjs.map +1 -0
- package/esnext/umd/vis-util.cjs +3924 -0
- package/esnext/umd/vis-util.cjs.map +1 -0
- package/esnext/umd/vis-util.js +3610 -3802
- package/esnext/umd/vis-util.js.map +1 -1
- package/esnext/umd/vis-util.min.cjs +27 -0
- package/esnext/umd/vis-util.min.cjs.map +1 -0
- package/esnext/umd/vis-util.min.js +3 -3
- package/esnext/umd/vis-util.min.js.map +1 -1
- package/package.json +161 -30
- package/peer/esm/vis-util.js +7463 -6156
- package/peer/esm/vis-util.js.map +1 -1
- package/peer/esm/vis-util.min.js +4 -4
- package/peer/esm/vis-util.min.js.map +1 -1
- package/peer/esm/vis-util.min.mjs +34 -0
- package/peer/esm/vis-util.min.mjs.map +1 -0
- package/peer/esm/vis-util.mjs +12696 -0
- package/peer/esm/vis-util.mjs.map +1 -0
- package/peer/umd/vis-util.cjs +12763 -0
- package/peer/umd/vis-util.cjs.map +1 -0
- package/peer/umd/vis-util.js +7463 -6156
- package/peer/umd/vis-util.js.map +1 -1
- package/peer/umd/vis-util.min.cjs +34 -0
- package/peer/umd/vis-util.min.cjs.map +1 -0
- package/peer/umd/vis-util.min.js +4 -4
- package/peer/umd/vis-util.min.js.map +1 -1
- package/standalone/esm/vis-util.js +7463 -6156
- package/standalone/esm/vis-util.js.map +1 -1
- package/standalone/esm/vis-util.min.js +4 -4
- package/standalone/esm/vis-util.min.js.map +1 -1
- package/standalone/esm/vis-util.min.mjs +34 -0
- package/standalone/esm/vis-util.min.mjs.map +1 -0
- package/standalone/esm/vis-util.mjs +12696 -0
- package/standalone/esm/vis-util.mjs.map +1 -0
- package/standalone/umd/vis-util.cjs +12763 -0
- package/standalone/umd/vis-util.cjs.map +1 -0
- package/standalone/umd/vis-util.js +7463 -6156
- package/standalone/umd/vis-util.js.map +1 -1
- package/standalone/umd/vis-util.min.cjs +34 -0
- package/standalone/umd/vis-util.min.cjs.map +1 -0
- package/standalone/umd/vis-util.min.js +4 -4
- package/standalone/umd/vis-util.min.js.map +1 -1
package/esnext/esm/vis-util.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*
|
|
5
5
|
* utilitie collection for visjs
|
|
6
6
|
*
|
|
7
|
-
* @version
|
|
8
|
-
* @date
|
|
7
|
+
* @version 6.0.0
|
|
8
|
+
* @date 2025-07-12T18:02:43.836Z
|
|
9
9
|
*
|
|
10
10
|
* @copyright (c) 2011-2017 Almende B.V, http://almende.com
|
|
11
11
|
* @copyright (c) 2017-2019 visjs contributors, https://github.com/visjs
|
|
@@ -27,204 +27,193 @@
|
|
|
27
27
|
import Emitter from 'component-emitter';
|
|
28
28
|
import RealHammer from '@egjs/hammerjs';
|
|
29
29
|
|
|
30
|
-
/**
|
|
31
|
-
* Use this symbol to delete properies in deepObjectAssign.
|
|
32
|
-
*/
|
|
33
|
-
const DELETE = Symbol("DELETE");
|
|
34
|
-
/**
|
|
35
|
-
* Pure version of deepObjectAssign, it doesn't modify any of it's arguments.
|
|
36
|
-
*
|
|
37
|
-
* @param
|
|
38
|
-
* @
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* @
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (values.length
|
|
65
|
-
return values[0];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
else if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
a[prop] =
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
else if (typeof a[prop] === "object" && a[prop] !== null) {
|
|
126
|
-
stripDelete(a[prop]);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
30
|
+
/**
|
|
31
|
+
* Use this symbol to delete properies in deepObjectAssign.
|
|
32
|
+
*/
|
|
33
|
+
const DELETE = Symbol("DELETE");
|
|
34
|
+
/**
|
|
35
|
+
* Pure version of deepObjectAssign, it doesn't modify any of it's arguments.
|
|
36
|
+
* @param base - The base object that fullfils the whole interface T.
|
|
37
|
+
* @param updates - Updates that may change or delete props.
|
|
38
|
+
* @returns A brand new instance with all the supplied objects deeply merged.
|
|
39
|
+
*/
|
|
40
|
+
function pureDeepObjectAssign(base, ...updates) {
|
|
41
|
+
return deepObjectAssign({}, base, ...updates);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Deep version of object assign with additional deleting by the DELETE symbol.
|
|
45
|
+
* @param values - Objects to be deeply merged.
|
|
46
|
+
* @returns The first object from values.
|
|
47
|
+
*/
|
|
48
|
+
function deepObjectAssign(...values) {
|
|
49
|
+
const merged = deepObjectAssignNonentry(...values);
|
|
50
|
+
stripDelete(merged);
|
|
51
|
+
return merged;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Deep version of object assign with additional deleting by the DELETE symbol.
|
|
55
|
+
* @remarks
|
|
56
|
+
* This doesn't strip the DELETE symbols so they may end up in the final object.
|
|
57
|
+
* @param values - Objects to be deeply merged.
|
|
58
|
+
* @returns The first object from values.
|
|
59
|
+
*/
|
|
60
|
+
function deepObjectAssignNonentry(...values) {
|
|
61
|
+
if (values.length < 2) {
|
|
62
|
+
return values[0];
|
|
63
|
+
}
|
|
64
|
+
else if (values.length > 2) {
|
|
65
|
+
return deepObjectAssignNonentry(deepObjectAssign(values[0], values[1]), ...values.slice(2));
|
|
66
|
+
}
|
|
67
|
+
const a = values[0];
|
|
68
|
+
const b = values[1];
|
|
69
|
+
if (a instanceof Date && b instanceof Date) {
|
|
70
|
+
a.setTime(b.getTime());
|
|
71
|
+
return a;
|
|
72
|
+
}
|
|
73
|
+
for (const prop of Reflect.ownKeys(b)) {
|
|
74
|
+
if (!Object.prototype.propertyIsEnumerable.call(b, prop)) ;
|
|
75
|
+
else if (b[prop] === DELETE) {
|
|
76
|
+
delete a[prop];
|
|
77
|
+
}
|
|
78
|
+
else if (a[prop] !== null &&
|
|
79
|
+
b[prop] !== null &&
|
|
80
|
+
typeof a[prop] === "object" &&
|
|
81
|
+
typeof b[prop] === "object" &&
|
|
82
|
+
!Array.isArray(a[prop]) &&
|
|
83
|
+
!Array.isArray(b[prop])) {
|
|
84
|
+
a[prop] = deepObjectAssignNonentry(a[prop], b[prop]);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
a[prop] = clone(b[prop]);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return a;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Deep clone given object or array. In case of primitive simply return.
|
|
94
|
+
* @param a - Anything.
|
|
95
|
+
* @returns Deep cloned object/array or unchanged a.
|
|
96
|
+
*/
|
|
97
|
+
function clone(a) {
|
|
98
|
+
if (Array.isArray(a)) {
|
|
99
|
+
return a.map((value) => clone(value));
|
|
100
|
+
}
|
|
101
|
+
else if (typeof a === "object" && a !== null) {
|
|
102
|
+
if (a instanceof Date) {
|
|
103
|
+
return new Date(a.getTime());
|
|
104
|
+
}
|
|
105
|
+
return deepObjectAssignNonentry({}, a);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
return a;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Strip DELETE from given object.
|
|
113
|
+
* @param a - Object which may contain DELETE but won't after this is executed.
|
|
114
|
+
*/
|
|
115
|
+
function stripDelete(a) {
|
|
116
|
+
for (const prop of Object.keys(a)) {
|
|
117
|
+
if (a[prop] === DELETE) {
|
|
118
|
+
delete a[prop];
|
|
119
|
+
}
|
|
120
|
+
else if (typeof a[prop] === "object" && a[prop] !== null) {
|
|
121
|
+
stripDelete(a[prop]);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
129
124
|
}
|
|
130
125
|
|
|
131
|
-
/**
|
|
132
|
-
* Seedable, fast and reasonably good (not crypto but more than okay for our
|
|
133
|
-
* needs) random number generator.
|
|
134
|
-
*
|
|
135
|
-
* @
|
|
136
|
-
*
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* @
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
*
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
random.
|
|
165
|
-
random.
|
|
166
|
-
random
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
*
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
n
|
|
211
|
-
|
|
212
|
-
n
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
h -= n;
|
|
217
|
-
n += h * 0x100000000; // 2^32
|
|
218
|
-
}
|
|
219
|
-
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
|
|
220
|
-
};
|
|
126
|
+
/**
|
|
127
|
+
* Seedable, fast and reasonably good (not crypto but more than okay for our
|
|
128
|
+
* needs) random number generator.
|
|
129
|
+
* @remarks
|
|
130
|
+
* Adapted from {@link https://web.archive.org/web/20110429100736/http://baagoe.com:80/en/RandomMusings/javascript}.
|
|
131
|
+
* Original algorithm created by Johannes Baagøe \<baagoe\@baagoe.com\> in 2010.
|
|
132
|
+
*/
|
|
133
|
+
/**
|
|
134
|
+
* Create a seeded pseudo random generator based on Alea by Johannes Baagøe.
|
|
135
|
+
* @param seed - All supplied arguments will be used as a seed. In case nothing
|
|
136
|
+
* is supplied the current time will be used to seed the generator.
|
|
137
|
+
* @returns A ready to use seeded generator.
|
|
138
|
+
*/
|
|
139
|
+
function Alea(...seed) {
|
|
140
|
+
return AleaImplementation(seed.length ? seed : [Date.now()]);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* An implementation of [[Alea]] without user input validation.
|
|
144
|
+
* @param seed - The data that will be used to seed the generator.
|
|
145
|
+
* @returns A ready to use seeded generator.
|
|
146
|
+
*/
|
|
147
|
+
function AleaImplementation(seed) {
|
|
148
|
+
let [s0, s1, s2] = mashSeed(seed);
|
|
149
|
+
let c = 1;
|
|
150
|
+
const random = () => {
|
|
151
|
+
const t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
|
|
152
|
+
s0 = s1;
|
|
153
|
+
s1 = s2;
|
|
154
|
+
return (s2 = t - (c = t | 0));
|
|
155
|
+
};
|
|
156
|
+
random.uint32 = () => random() * 0x100000000; // 2^32
|
|
157
|
+
random.fract53 = () => random() + ((random() * 0x200000) | 0) * 1.1102230246251565e-16; // 2^-53
|
|
158
|
+
random.algorithm = "Alea";
|
|
159
|
+
random.seed = seed;
|
|
160
|
+
random.version = "0.9";
|
|
161
|
+
return random;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Turn arbitrary data into values [[AleaImplementation]] can use to generate
|
|
165
|
+
* random numbers.
|
|
166
|
+
* @param seed - Arbitrary data that will be used as the seed.
|
|
167
|
+
* @returns Three numbers to use as initial values for [[AleaImplementation]].
|
|
168
|
+
*/
|
|
169
|
+
function mashSeed(...seed) {
|
|
170
|
+
const mash = Mash();
|
|
171
|
+
let s0 = mash(" ");
|
|
172
|
+
let s1 = mash(" ");
|
|
173
|
+
let s2 = mash(" ");
|
|
174
|
+
for (let i = 0; i < seed.length; i++) {
|
|
175
|
+
s0 -= mash(seed[i]);
|
|
176
|
+
if (s0 < 0) {
|
|
177
|
+
s0 += 1;
|
|
178
|
+
}
|
|
179
|
+
s1 -= mash(seed[i]);
|
|
180
|
+
if (s1 < 0) {
|
|
181
|
+
s1 += 1;
|
|
182
|
+
}
|
|
183
|
+
s2 -= mash(seed[i]);
|
|
184
|
+
if (s2 < 0) {
|
|
185
|
+
s2 += 1;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return [s0, s1, s2];
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Create a new mash function.
|
|
192
|
+
* @returns A nonpure function that takes arbitrary [[Mashable]] data and turns
|
|
193
|
+
* them into numbers.
|
|
194
|
+
*/
|
|
195
|
+
function Mash() {
|
|
196
|
+
let n = 0xefc8249d;
|
|
197
|
+
return function (data) {
|
|
198
|
+
const string = data.toString();
|
|
199
|
+
for (let i = 0; i < string.length; i++) {
|
|
200
|
+
n += string.charCodeAt(i);
|
|
201
|
+
let h = 0.02519603282416938 * n;
|
|
202
|
+
n = h >>> 0;
|
|
203
|
+
h -= n;
|
|
204
|
+
h *= n;
|
|
205
|
+
n = h >>> 0;
|
|
206
|
+
h -= n;
|
|
207
|
+
n += h * 0x100000000; // 2^32
|
|
208
|
+
}
|
|
209
|
+
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
|
|
210
|
+
};
|
|
221
211
|
}
|
|
222
212
|
|
|
223
213
|
/**
|
|
224
214
|
* Setup a mock hammer.js object, for unit testing.
|
|
225
215
|
*
|
|
226
216
|
* Inspiration: https://github.com/uber/deck.gl/pull/658
|
|
227
|
-
*
|
|
228
217
|
* @returns {{on: noop, off: noop, destroy: noop, emit: noop, get: get}}
|
|
229
218
|
*/
|
|
230
219
|
function hammerMock() {
|
|
@@ -259,7 +248,6 @@ const Hammer$1 =
|
|
|
259
248
|
* When active, the element is displayed with a blue border around it, and
|
|
260
249
|
* the interactive contents of the element can be used. When clicked outside
|
|
261
250
|
* the element, the elements mode is changed to inactive.
|
|
262
|
-
*
|
|
263
251
|
* @param {Element} container
|
|
264
252
|
* @class Activator
|
|
265
253
|
*/
|
|
@@ -386,7 +374,6 @@ Activator$1.prototype.deactivate = function () {
|
|
|
386
374
|
|
|
387
375
|
/**
|
|
388
376
|
* Handle a tap event: activate the container
|
|
389
|
-
*
|
|
390
377
|
* @param {Event} event The event
|
|
391
378
|
* @private
|
|
392
379
|
*/
|
|
@@ -399,7 +386,6 @@ Activator$1.prototype._onTapOverlay = function (event) {
|
|
|
399
386
|
/**
|
|
400
387
|
* Test whether the element has the requested parent element somewhere in
|
|
401
388
|
* its chain of parent nodes.
|
|
402
|
-
*
|
|
403
389
|
* @param {HTMLElement} element
|
|
404
390
|
* @param {HTMLElement} parent
|
|
405
391
|
* @returns {boolean} Returns true when the parent is found somewhere in the
|
|
@@ -416,1487 +402,1419 @@ function _hasParent(element, parent) {
|
|
|
416
402
|
return false;
|
|
417
403
|
}
|
|
418
404
|
|
|
419
|
-
// utility functions
|
|
420
|
-
// parse ASP.Net Date pattern,
|
|
421
|
-
// for example '/Date(1198908717056)/' or '/Date(1198908717056-0700)/'
|
|
422
|
-
// code from http://momentjs.com/
|
|
423
|
-
const ASPDateRegex = /^\/?Date\((-?\d+)/i;
|
|
424
|
-
// Color REs
|
|
425
|
-
const fullHexRE = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
|
|
426
|
-
const shortHexRE = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
|
427
|
-
const 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;
|
|
428
|
-
const 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;
|
|
429
|
-
/**
|
|
430
|
-
* Test whether given object is a number.
|
|
431
|
-
*
|
|
432
|
-
* @
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
*
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
*
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
*
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
*
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
* @param
|
|
552
|
-
* @
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
*
|
|
581
|
-
*
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
*
|
|
624
|
-
*
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
}
|
|
650
|
-
if (b[prop]
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
*
|
|
778
|
-
* @
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
*
|
|
786
|
-
* @param
|
|
787
|
-
* @returns
|
|
788
|
-
*/
|
|
789
|
-
function
|
|
790
|
-
return
|
|
791
|
-
}
|
|
792
|
-
/**
|
|
793
|
-
* Retrieve the absolute
|
|
794
|
-
*
|
|
795
|
-
* @
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
*
|
|
803
|
-
*
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
*
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
*
|
|
852
|
-
* @param
|
|
853
|
-
* @
|
|
854
|
-
*/
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
/**
|
|
873
|
-
*
|
|
874
|
-
*
|
|
875
|
-
* @
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
*
|
|
936
|
-
* @
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
let
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
*
|
|
988
|
-
* @param
|
|
989
|
-
* @
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
*
|
|
1003
|
-
* @param value - Value to be converted
|
|
1004
|
-
* @param defaultValue - If the value or the return value of the function == null then this will be returned.
|
|
1005
|
-
* @returns Corresponding
|
|
1006
|
-
*/
|
|
1007
|
-
|
|
1008
|
-
if (typeof value == "function") {
|
|
1009
|
-
value = value();
|
|
1010
|
-
}
|
|
1011
|
-
if (value
|
|
1012
|
-
return
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
return
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
*
|
|
1070
|
-
* @
|
|
1071
|
-
*
|
|
1072
|
-
* @
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
return
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
*
|
|
1107
|
-
* @
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
*
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
const
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
hover:
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
background:
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
*
|
|
1268
|
-
* @param
|
|
1269
|
-
* @param
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
const
|
|
1284
|
-
const
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
*
|
|
1292
|
-
*
|
|
1293
|
-
* @param
|
|
1294
|
-
* @
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
*
|
|
1334
|
-
* @param h - Hue.
|
|
1335
|
-
* @param s - Saturation.
|
|
1336
|
-
* @param v - Value.
|
|
1337
|
-
* @returns
|
|
1338
|
-
*/
|
|
1339
|
-
function
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
*
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
}
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
* This
|
|
1430
|
-
*
|
|
1431
|
-
* @param
|
|
1432
|
-
* @
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
*
|
|
1454
|
-
*
|
|
1455
|
-
*
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
function
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
}
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
//
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
if (
|
|
1544
|
-
|
|
1545
|
-
}
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
}
|
|
1577
|
-
else {
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
//
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
*
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
*
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
*
|
|
1725
|
-
* @
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
*
|
|
1733
|
-
* @param t - Time.
|
|
1734
|
-
* @returns Value at time t.
|
|
1735
|
-
*/
|
|
1736
|
-
|
|
1737
|
-
return t *
|
|
1738
|
-
},
|
|
1739
|
-
/**
|
|
1740
|
-
* Accelerate
|
|
1741
|
-
*
|
|
1742
|
-
* @
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
*
|
|
1750
|
-
*
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
*
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
*
|
|
1833
|
-
* @returns The width in pixels.
|
|
1834
|
-
*/
|
|
1835
|
-
function getScrollBarWidth() {
|
|
1836
|
-
const inner = document.createElement("p");
|
|
1837
|
-
inner.style.width = "100%";
|
|
1838
|
-
inner.style.height = "200px";
|
|
1839
|
-
const outer = document.createElement("div");
|
|
1840
|
-
outer.style.position = "absolute";
|
|
1841
|
-
outer.style.top = "0px";
|
|
1842
|
-
outer.style.left = "0px";
|
|
1843
|
-
outer.style.visibility = "hidden";
|
|
1844
|
-
outer.style.width = "200px";
|
|
1845
|
-
outer.style.height = "150px";
|
|
1846
|
-
outer.style.overflow = "hidden";
|
|
1847
|
-
outer.appendChild(inner);
|
|
1848
|
-
document.body.appendChild(outer);
|
|
1849
|
-
const w1 = inner.offsetWidth;
|
|
1850
|
-
outer.style.overflow = "scroll";
|
|
1851
|
-
let w2 = inner.offsetWidth;
|
|
1852
|
-
if (w1 == w2) {
|
|
1853
|
-
w2 = outer.clientWidth;
|
|
1854
|
-
}
|
|
1855
|
-
document.body.removeChild(outer);
|
|
1856
|
-
return w1 - w2;
|
|
1857
|
-
}
|
|
1858
|
-
// @TODO: This doesn't work properly.
|
|
1859
|
-
// It works only for single property objects,
|
|
1860
|
-
// otherwise it combines all of the types in a union.
|
|
1861
|
-
// export function topMost<K1 extends string, V1> (
|
|
1862
|
-
// pile: Record<K1, undefined | V1>[],
|
|
1863
|
-
// accessors: K1 | [K1]
|
|
1864
|
-
// ): undefined | V1
|
|
1865
|
-
// export function topMost<K1 extends string, K2 extends string, V1, V2> (
|
|
1866
|
-
// pile: Record<K1, undefined | V1 | Record<K2, undefined | V2>>[],
|
|
1867
|
-
// accessors: [K1, K2]
|
|
1868
|
-
// ): undefined | V1 | V2
|
|
1869
|
-
// export function topMost<K1 extends string, K2 extends string, K3 extends string, V1, V2, V3> (
|
|
1870
|
-
// pile: Record<K1, undefined | V1 | Record<K2, undefined | V2 | Record<K3, undefined | V3>>>[],
|
|
1871
|
-
// accessors: [K1, K2, K3]
|
|
1872
|
-
// ): undefined | V1 | V2 | V3
|
|
1873
|
-
/**
|
|
1874
|
-
* Get the top most property value from a pile of objects.
|
|
1875
|
-
*
|
|
1876
|
-
* @param pile - Array of objects, no required format.
|
|
1877
|
-
* @param accessors - Array of property names.
|
|
1878
|
-
* For example `object['foo']['bar']` → `['foo', 'bar']`.
|
|
1879
|
-
* @returns Value of the property with given accessors path from the first pile item where it's not undefined.
|
|
1880
|
-
*/
|
|
1881
|
-
function topMost(pile, accessors) {
|
|
1882
|
-
let candidate;
|
|
1883
|
-
if (!Array.isArray(accessors)) {
|
|
1884
|
-
accessors = [accessors];
|
|
1885
|
-
}
|
|
1886
|
-
for (const member of pile) {
|
|
1887
|
-
if (member) {
|
|
1888
|
-
candidate = member[accessors[0]];
|
|
1889
|
-
for (let i = 1; i < accessors.length; i++) {
|
|
1890
|
-
if (candidate) {
|
|
1891
|
-
candidate = candidate[accessors[i]];
|
|
1892
|
-
}
|
|
1893
|
-
}
|
|
1894
|
-
if (typeof candidate !== "undefined") {
|
|
1895
|
-
break;
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
}
|
|
1899
|
-
return candidate;
|
|
405
|
+
// utility functions
|
|
406
|
+
// parse ASP.Net Date pattern,
|
|
407
|
+
// for example '/Date(1198908717056)/' or '/Date(1198908717056-0700)/'
|
|
408
|
+
// code from http://momentjs.com/
|
|
409
|
+
const ASPDateRegex = /^\/?Date\((-?\d+)/i;
|
|
410
|
+
// Color REs
|
|
411
|
+
const fullHexRE = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
|
|
412
|
+
const shortHexRE = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
|
413
|
+
const 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;
|
|
414
|
+
const 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;
|
|
415
|
+
/**
|
|
416
|
+
* Test whether given object is a number.
|
|
417
|
+
* @param value - Input value of unknown type.
|
|
418
|
+
* @returns True if number, false otherwise.
|
|
419
|
+
*/
|
|
420
|
+
function isNumber(value) {
|
|
421
|
+
return value instanceof Number || typeof value === "number";
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Remove everything in the DOM object.
|
|
425
|
+
* @param DOMobject - Node whose child nodes will be recursively deleted.
|
|
426
|
+
*/
|
|
427
|
+
function recursiveDOMDelete(DOMobject) {
|
|
428
|
+
if (DOMobject) {
|
|
429
|
+
while (DOMobject.hasChildNodes() === true) {
|
|
430
|
+
const child = DOMobject.firstChild;
|
|
431
|
+
if (child) {
|
|
432
|
+
recursiveDOMDelete(child);
|
|
433
|
+
DOMobject.removeChild(child);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Test whether given object is a string.
|
|
440
|
+
* @param value - Input value of unknown type.
|
|
441
|
+
* @returns True if string, false otherwise.
|
|
442
|
+
*/
|
|
443
|
+
function isString(value) {
|
|
444
|
+
return value instanceof String || typeof value === "string";
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Test whether given object is a object (not primitive or null).
|
|
448
|
+
* @param value - Input value of unknown type.
|
|
449
|
+
* @returns True if not null object, false otherwise.
|
|
450
|
+
*/
|
|
451
|
+
function isObject(value) {
|
|
452
|
+
return typeof value === "object" && value !== null;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Test whether given object is a Date, or a String containing a Date.
|
|
456
|
+
* @param value - Input value of unknown type.
|
|
457
|
+
* @returns True if Date instance or string date representation, false otherwise.
|
|
458
|
+
*/
|
|
459
|
+
function isDate(value) {
|
|
460
|
+
if (value instanceof Date) {
|
|
461
|
+
return true;
|
|
462
|
+
}
|
|
463
|
+
else if (isString(value)) {
|
|
464
|
+
// test whether this string contains a date
|
|
465
|
+
const match = ASPDateRegex.exec(value);
|
|
466
|
+
if (match) {
|
|
467
|
+
return true;
|
|
468
|
+
}
|
|
469
|
+
else if (!isNaN(Date.parse(value))) {
|
|
470
|
+
return true;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Copy property from b to a if property present in a.
|
|
477
|
+
* If property in b explicitly set to null, delete it if `allowDeletion` set.
|
|
478
|
+
*
|
|
479
|
+
* Internal helper routine, should not be exported. Not added to `exports` for that reason.
|
|
480
|
+
* @param a - Target object.
|
|
481
|
+
* @param b - Source object.
|
|
482
|
+
* @param prop - Name of property to copy from b to a.
|
|
483
|
+
* @param allowDeletion - If true, delete property in a if explicitly set to null in b.
|
|
484
|
+
*/
|
|
485
|
+
function copyOrDelete(a, b, prop, allowDeletion) {
|
|
486
|
+
let doDeletion = false;
|
|
487
|
+
if (allowDeletion === true) {
|
|
488
|
+
doDeletion = b[prop] === null && a[prop] !== undefined;
|
|
489
|
+
}
|
|
490
|
+
if (doDeletion) {
|
|
491
|
+
delete a[prop];
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
a[prop] = b[prop]; // Remember, this is a reference copy!
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Fill an object with a possibly partially defined other object.
|
|
499
|
+
*
|
|
500
|
+
* Only copies values for the properties already present in a.
|
|
501
|
+
* That means an object is not created on a property if only the b object has it.
|
|
502
|
+
* @param a - The object that will have it's properties updated.
|
|
503
|
+
* @param b - The object with property updates.
|
|
504
|
+
* @param allowDeletion - If true, delete properties in a that are explicitly set to null in b.
|
|
505
|
+
*/
|
|
506
|
+
function fillIfDefined(a, b, allowDeletion = false) {
|
|
507
|
+
// NOTE: iteration of properties of a
|
|
508
|
+
// NOTE: prototype properties iterated over as well
|
|
509
|
+
for (const prop in a) {
|
|
510
|
+
if (b[prop] !== undefined) {
|
|
511
|
+
if (b[prop] === null || typeof b[prop] !== "object") {
|
|
512
|
+
// Note: typeof null === 'object'
|
|
513
|
+
copyOrDelete(a, b, prop, allowDeletion);
|
|
514
|
+
}
|
|
515
|
+
else {
|
|
516
|
+
const aProp = a[prop];
|
|
517
|
+
const bProp = b[prop];
|
|
518
|
+
if (isObject(aProp) && isObject(bProp)) {
|
|
519
|
+
fillIfDefined(aProp, bProp, allowDeletion);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Copy the values of all of the enumerable own properties from one or more source objects to a
|
|
527
|
+
* target object. Returns the target object.
|
|
528
|
+
* @param target - The target object to copy to.
|
|
529
|
+
* @param source - The source object from which to copy properties.
|
|
530
|
+
* @returns The target object.
|
|
531
|
+
*/
|
|
532
|
+
const extend = Object.assign;
|
|
533
|
+
/**
|
|
534
|
+
* Extend object a with selected properties of object b or a series of objects.
|
|
535
|
+
* @remarks
|
|
536
|
+
* Only properties with defined values are copied.
|
|
537
|
+
* @param props - Properties to be copied to a.
|
|
538
|
+
* @param a - The target.
|
|
539
|
+
* @param others - The sources.
|
|
540
|
+
* @returns Argument a.
|
|
541
|
+
*/
|
|
542
|
+
function selectiveExtend(props, a, ...others) {
|
|
543
|
+
if (!Array.isArray(props)) {
|
|
544
|
+
throw new Error("Array with property names expected as first argument");
|
|
545
|
+
}
|
|
546
|
+
for (const other of others) {
|
|
547
|
+
for (let p = 0; p < props.length; p++) {
|
|
548
|
+
const prop = props[p];
|
|
549
|
+
if (other && Object.prototype.hasOwnProperty.call(other, prop)) {
|
|
550
|
+
a[prop] = other[prop];
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return a;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Extend object a with selected properties of object b.
|
|
558
|
+
* Only properties with defined values are copied.
|
|
559
|
+
* @remarks
|
|
560
|
+
* Previous version of this routine implied that multiple source objects could
|
|
561
|
+
* be used; however, the implementation was **wrong**. Since multiple (\>1)
|
|
562
|
+
* sources weren't used anywhere in the `vis.js` code, this has been removed
|
|
563
|
+
* @param props - Names of first-level properties to copy over.
|
|
564
|
+
* @param a - Target object.
|
|
565
|
+
* @param b - Source object.
|
|
566
|
+
* @param allowDeletion - If true, delete property in a if explicitly set to null in b.
|
|
567
|
+
* @returns Argument a.
|
|
568
|
+
*/
|
|
569
|
+
function selectiveDeepExtend(props, a, b, allowDeletion = false) {
|
|
570
|
+
// TODO: add support for Arrays to deepExtend
|
|
571
|
+
if (Array.isArray(b)) {
|
|
572
|
+
throw new TypeError("Arrays are not supported by deepExtend");
|
|
573
|
+
}
|
|
574
|
+
for (let p = 0; p < props.length; p++) {
|
|
575
|
+
const prop = props[p];
|
|
576
|
+
if (Object.prototype.hasOwnProperty.call(b, prop)) {
|
|
577
|
+
if (b[prop] && b[prop].constructor === Object) {
|
|
578
|
+
if (a[prop] === undefined) {
|
|
579
|
+
a[prop] = {};
|
|
580
|
+
}
|
|
581
|
+
if (a[prop].constructor === Object) {
|
|
582
|
+
deepExtend(a[prop], b[prop], false, allowDeletion);
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
copyOrDelete(a, b, prop, allowDeletion);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
else if (Array.isArray(b[prop])) {
|
|
589
|
+
throw new TypeError("Arrays are not supported by deepExtend");
|
|
590
|
+
}
|
|
591
|
+
else {
|
|
592
|
+
copyOrDelete(a, b, prop, allowDeletion);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return a;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Extend object `a` with properties of object `b`, ignoring properties which
|
|
600
|
+
* are explicitly specified to be excluded.
|
|
601
|
+
* @remarks
|
|
602
|
+
* The properties of `b` are considered for copying. Properties which are
|
|
603
|
+
* themselves objects are are also extended. Only properties with defined
|
|
604
|
+
* values are copied.
|
|
605
|
+
* @param propsToExclude - Names of properties which should *not* be copied.
|
|
606
|
+
* @param a - Object to extend.
|
|
607
|
+
* @param b - Object to take properties from for extension.
|
|
608
|
+
* @param allowDeletion - If true, delete properties in a that are explicitly
|
|
609
|
+
* set to null in b.
|
|
610
|
+
* @returns Argument a.
|
|
611
|
+
*/
|
|
612
|
+
function selectiveNotDeepExtend(propsToExclude, a, b, allowDeletion = false) {
|
|
613
|
+
// TODO: add support for Arrays to deepExtend
|
|
614
|
+
// NOTE: array properties have an else-below; apparently, there is a problem here.
|
|
615
|
+
if (Array.isArray(b)) {
|
|
616
|
+
throw new TypeError("Arrays are not supported by deepExtend");
|
|
617
|
+
}
|
|
618
|
+
for (const prop in b) {
|
|
619
|
+
if (!Object.prototype.hasOwnProperty.call(b, prop)) {
|
|
620
|
+
continue;
|
|
621
|
+
} // Handle local properties only
|
|
622
|
+
if (propsToExclude.includes(prop)) {
|
|
623
|
+
continue;
|
|
624
|
+
} // In exclusion list, skip
|
|
625
|
+
if (b[prop] && b[prop].constructor === Object) {
|
|
626
|
+
if (a[prop] === undefined) {
|
|
627
|
+
a[prop] = {};
|
|
628
|
+
}
|
|
629
|
+
if (a[prop].constructor === Object) {
|
|
630
|
+
deepExtend(a[prop], b[prop]); // NOTE: allowDeletion not propagated!
|
|
631
|
+
}
|
|
632
|
+
else {
|
|
633
|
+
copyOrDelete(a, b, prop, allowDeletion);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
else if (Array.isArray(b[prop])) {
|
|
637
|
+
a[prop] = [];
|
|
638
|
+
for (let i = 0; i < b[prop].length; i++) {
|
|
639
|
+
a[prop].push(b[prop][i]);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
copyOrDelete(a, b, prop, allowDeletion);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
return a;
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Deep extend an object a with the properties of object b.
|
|
650
|
+
* @param a - Target object.
|
|
651
|
+
* @param b - Source object.
|
|
652
|
+
* @param protoExtend - If true, the prototype values will also be extended.
|
|
653
|
+
* (That is the options objects that inherit from others will also get the
|
|
654
|
+
* inherited options).
|
|
655
|
+
* @param allowDeletion - If true, the values of fields that are null will be deleted.
|
|
656
|
+
* @returns Argument a.
|
|
657
|
+
*/
|
|
658
|
+
function deepExtend(a, b, protoExtend = false, allowDeletion = false) {
|
|
659
|
+
for (const prop in b) {
|
|
660
|
+
if (Object.prototype.hasOwnProperty.call(b, prop) || protoExtend === true) {
|
|
661
|
+
if (typeof b[prop] === "object" &&
|
|
662
|
+
b[prop] !== null &&
|
|
663
|
+
Object.getPrototypeOf(b[prop]) === Object.prototype) {
|
|
664
|
+
if (a[prop] === undefined) {
|
|
665
|
+
a[prop] = deepExtend({}, b[prop], protoExtend); // NOTE: allowDeletion not propagated!
|
|
666
|
+
}
|
|
667
|
+
else if (typeof a[prop] === "object" &&
|
|
668
|
+
a[prop] !== null &&
|
|
669
|
+
Object.getPrototypeOf(a[prop]) === Object.prototype) {
|
|
670
|
+
deepExtend(a[prop], b[prop], protoExtend); // NOTE: allowDeletion not propagated!
|
|
671
|
+
}
|
|
672
|
+
else {
|
|
673
|
+
copyOrDelete(a, b, prop, allowDeletion);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
else if (Array.isArray(b[prop])) {
|
|
677
|
+
a[prop] = b[prop].slice();
|
|
678
|
+
}
|
|
679
|
+
else {
|
|
680
|
+
copyOrDelete(a, b, prop, allowDeletion);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
return a;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Test whether all elements in two arrays are equal.
|
|
688
|
+
* @param a - First array.
|
|
689
|
+
* @param b - Second array.
|
|
690
|
+
* @returns True if both arrays have the same length and same elements (1 = '1').
|
|
691
|
+
*/
|
|
692
|
+
function equalArray(a, b) {
|
|
693
|
+
if (a.length !== b.length) {
|
|
694
|
+
return false;
|
|
695
|
+
}
|
|
696
|
+
for (let i = 0, len = a.length; i < len; i++) {
|
|
697
|
+
if (a[i] != b[i]) {
|
|
698
|
+
return false;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
return true;
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Get the type of an object, for example exports.getType([]) returns 'Array'.
|
|
705
|
+
* @param object - Input value of unknown type.
|
|
706
|
+
* @returns Detected type.
|
|
707
|
+
*/
|
|
708
|
+
function getType(object) {
|
|
709
|
+
const type = typeof object;
|
|
710
|
+
if (type === "object") {
|
|
711
|
+
if (object === null) {
|
|
712
|
+
return "null";
|
|
713
|
+
}
|
|
714
|
+
if (object instanceof Boolean) {
|
|
715
|
+
return "Boolean";
|
|
716
|
+
}
|
|
717
|
+
if (object instanceof Number) {
|
|
718
|
+
return "Number";
|
|
719
|
+
}
|
|
720
|
+
if (object instanceof String) {
|
|
721
|
+
return "String";
|
|
722
|
+
}
|
|
723
|
+
if (Array.isArray(object)) {
|
|
724
|
+
return "Array";
|
|
725
|
+
}
|
|
726
|
+
if (object instanceof Date) {
|
|
727
|
+
return "Date";
|
|
728
|
+
}
|
|
729
|
+
return "Object";
|
|
730
|
+
}
|
|
731
|
+
if (type === "number") {
|
|
732
|
+
return "Number";
|
|
733
|
+
}
|
|
734
|
+
if (type === "boolean") {
|
|
735
|
+
return "Boolean";
|
|
736
|
+
}
|
|
737
|
+
if (type === "string") {
|
|
738
|
+
return "String";
|
|
739
|
+
}
|
|
740
|
+
if (type === undefined) {
|
|
741
|
+
return "undefined";
|
|
742
|
+
}
|
|
743
|
+
return type;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Used to extend an array and copy it. This is used to propagate paths recursively.
|
|
747
|
+
* @param arr - First part.
|
|
748
|
+
* @param newValue - The value to be aadded into the array.
|
|
749
|
+
* @returns A new array with all items from arr and newValue (which is last).
|
|
750
|
+
*/
|
|
751
|
+
function copyAndExtendArray(arr, newValue) {
|
|
752
|
+
return [...arr, newValue];
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Used to extend an array and copy it. This is used to propagate paths recursively.
|
|
756
|
+
* @param arr - The array to be copied.
|
|
757
|
+
* @returns Shallow copy of arr.
|
|
758
|
+
*/
|
|
759
|
+
function copyArray(arr) {
|
|
760
|
+
return arr.slice();
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Retrieve the absolute left value of a DOM element.
|
|
764
|
+
* @param elem - A dom element, for example a div.
|
|
765
|
+
* @returns The absolute left position of this element in the browser page.
|
|
766
|
+
*/
|
|
767
|
+
function getAbsoluteLeft(elem) {
|
|
768
|
+
return elem.getBoundingClientRect().left;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Retrieve the absolute right value of a DOM element.
|
|
772
|
+
* @param elem - A dom element, for example a div.
|
|
773
|
+
* @returns The absolute right position of this element in the browser page.
|
|
774
|
+
*/
|
|
775
|
+
function getAbsoluteRight(elem) {
|
|
776
|
+
return elem.getBoundingClientRect().right;
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Retrieve the absolute top value of a DOM element.
|
|
780
|
+
* @param elem - A dom element, for example a div.
|
|
781
|
+
* @returns The absolute top position of this element in the browser page.
|
|
782
|
+
*/
|
|
783
|
+
function getAbsoluteTop(elem) {
|
|
784
|
+
return elem.getBoundingClientRect().top;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Add a className to the given elements style.
|
|
788
|
+
* @param elem - The element to which the classes will be added.
|
|
789
|
+
* @param classNames - Space separated list of classes.
|
|
790
|
+
*/
|
|
791
|
+
function addClassName(elem, classNames) {
|
|
792
|
+
let classes = elem.className.split(" ");
|
|
793
|
+
const newClasses = classNames.split(" ");
|
|
794
|
+
classes = classes.concat(newClasses.filter(function (className) {
|
|
795
|
+
return !classes.includes(className);
|
|
796
|
+
}));
|
|
797
|
+
elem.className = classes.join(" ");
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Remove a className from the given elements style.
|
|
801
|
+
* @param elem - The element from which the classes will be removed.
|
|
802
|
+
* @param classNames - Space separated list of classes.
|
|
803
|
+
*/
|
|
804
|
+
function removeClassName(elem, classNames) {
|
|
805
|
+
let classes = elem.className.split(" ");
|
|
806
|
+
const oldClasses = classNames.split(" ");
|
|
807
|
+
classes = classes.filter(function (className) {
|
|
808
|
+
return !oldClasses.includes(className);
|
|
809
|
+
});
|
|
810
|
+
elem.className = classes.join(" ");
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* For each method for both arrays and objects.
|
|
814
|
+
* In case of an array, the built-in Array.forEach() is applied (**No, it's not!**).
|
|
815
|
+
* In case of an Object, the method loops over all properties of the object.
|
|
816
|
+
* @param object - An Object or Array to be iterated over.
|
|
817
|
+
* @param callback - Array.forEach-like callback.
|
|
818
|
+
*/
|
|
819
|
+
function forEach(object, callback) {
|
|
820
|
+
if (Array.isArray(object)) {
|
|
821
|
+
// array
|
|
822
|
+
const len = object.length;
|
|
823
|
+
for (let i = 0; i < len; i++) {
|
|
824
|
+
callback(object[i], i, object);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
else {
|
|
828
|
+
// object
|
|
829
|
+
for (const key in object) {
|
|
830
|
+
if (Object.prototype.hasOwnProperty.call(object, key)) {
|
|
831
|
+
callback(object[key], key, object);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Convert an object into an array: all objects properties are put into the array. The resulting array is unordered.
|
|
838
|
+
* @param o - Object that contains the properties and methods.
|
|
839
|
+
* @returns An array of unordered values.
|
|
840
|
+
*/
|
|
841
|
+
const toArray = Object.values;
|
|
842
|
+
/**
|
|
843
|
+
* Update a property in an object.
|
|
844
|
+
* @param object - The object whose property will be updated.
|
|
845
|
+
* @param key - Name of the property to be updated.
|
|
846
|
+
* @param value - The new value to be assigned.
|
|
847
|
+
* @returns Whether the value was updated (true) or already strictly the same in the original object (false).
|
|
848
|
+
*/
|
|
849
|
+
function updateProperty(object, key, value) {
|
|
850
|
+
if (object[key] !== value) {
|
|
851
|
+
object[key] = value;
|
|
852
|
+
return true;
|
|
853
|
+
}
|
|
854
|
+
else {
|
|
855
|
+
return false;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Throttle the given function to be only executed once per animation frame.
|
|
860
|
+
* @param fn - The original function.
|
|
861
|
+
* @returns The throttled function.
|
|
862
|
+
*/
|
|
863
|
+
function throttle(fn) {
|
|
864
|
+
let scheduled = false;
|
|
865
|
+
return () => {
|
|
866
|
+
if (!scheduled) {
|
|
867
|
+
scheduled = true;
|
|
868
|
+
requestAnimationFrame(() => {
|
|
869
|
+
scheduled = false;
|
|
870
|
+
fn();
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Cancels the event's default action if it is cancelable, without stopping further propagation of the event.
|
|
877
|
+
* @param event - The event whose default action should be prevented.
|
|
878
|
+
*/
|
|
879
|
+
function preventDefault(event) {
|
|
880
|
+
if (!event) {
|
|
881
|
+
event = window.event;
|
|
882
|
+
}
|
|
883
|
+
if (!event) ;
|
|
884
|
+
else if (event.preventDefault) {
|
|
885
|
+
event.preventDefault(); // non-IE browsers
|
|
886
|
+
}
|
|
887
|
+
else {
|
|
888
|
+
// @TODO: IE types? Does anyone care?
|
|
889
|
+
event.returnValue = false; // IE browsers
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Get HTML element which is the target of the event.
|
|
894
|
+
* @param event - The event.
|
|
895
|
+
* @returns The element or null if not obtainable.
|
|
896
|
+
*/
|
|
897
|
+
function getTarget(event = window.event) {
|
|
898
|
+
// code from http://www.quirksmode.org/js/events_properties.html
|
|
899
|
+
// @TODO: EventTarget can be almost anything, is it okay to return only Elements?
|
|
900
|
+
let target = null;
|
|
901
|
+
if (!event) ;
|
|
902
|
+
else if (event.target) {
|
|
903
|
+
target = event.target;
|
|
904
|
+
}
|
|
905
|
+
else if (event.srcElement) {
|
|
906
|
+
target = event.srcElement;
|
|
907
|
+
}
|
|
908
|
+
if (!(target instanceof Element)) {
|
|
909
|
+
return null;
|
|
910
|
+
}
|
|
911
|
+
if (target.nodeType != null && target.nodeType == 3) {
|
|
912
|
+
// defeat Safari bug
|
|
913
|
+
target = target.parentNode;
|
|
914
|
+
if (!(target instanceof Element)) {
|
|
915
|
+
return null;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
return target;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Check if given element contains given parent somewhere in the DOM tree.
|
|
922
|
+
* @param element - The element to be tested.
|
|
923
|
+
* @param parent - The ancestor (not necessarily parent) of the element.
|
|
924
|
+
* @returns True if parent is an ancestor of the element, false otherwise.
|
|
925
|
+
*/
|
|
926
|
+
function hasParent(element, parent) {
|
|
927
|
+
let elem = element;
|
|
928
|
+
while (elem) {
|
|
929
|
+
if (elem === parent) {
|
|
930
|
+
return true;
|
|
931
|
+
}
|
|
932
|
+
else if (elem.parentNode) {
|
|
933
|
+
elem = elem.parentNode;
|
|
934
|
+
}
|
|
935
|
+
else {
|
|
936
|
+
return false;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
return false;
|
|
940
|
+
}
|
|
941
|
+
const option = {
|
|
942
|
+
/**
|
|
943
|
+
* Convert a value into a boolean.
|
|
944
|
+
* @param value - Value to be converted intoboolean, a function will be executed as `(() => unknown)`.
|
|
945
|
+
* @param defaultValue - If the value or the return value of the function == null then this will be returned.
|
|
946
|
+
* @returns Corresponding boolean value, if none then the default value, if none then null.
|
|
947
|
+
*/
|
|
948
|
+
asBoolean(value, defaultValue) {
|
|
949
|
+
if (typeof value == "function") {
|
|
950
|
+
value = value();
|
|
951
|
+
}
|
|
952
|
+
if (value != null) {
|
|
953
|
+
return value != false;
|
|
954
|
+
}
|
|
955
|
+
return defaultValue || null;
|
|
956
|
+
},
|
|
957
|
+
/**
|
|
958
|
+
* Convert a value into a number.
|
|
959
|
+
* @param value - Value to be converted intonumber, a function will be executed as `(() => unknown)`.
|
|
960
|
+
* @param defaultValue - If the value or the return value of the function == null then this will be returned.
|
|
961
|
+
* @returns Corresponding **boxed** number value, if none then the default value, if none then null.
|
|
962
|
+
*/
|
|
963
|
+
asNumber(value, defaultValue) {
|
|
964
|
+
if (typeof value == "function") {
|
|
965
|
+
value = value();
|
|
966
|
+
}
|
|
967
|
+
if (value != null) {
|
|
968
|
+
return Number(value) || defaultValue || null;
|
|
969
|
+
}
|
|
970
|
+
return defaultValue || null;
|
|
971
|
+
},
|
|
972
|
+
/**
|
|
973
|
+
* Convert a value into a string.
|
|
974
|
+
* @param value - Value to be converted intostring, a function will be executed as `(() => unknown)`.
|
|
975
|
+
* @param defaultValue - If the value or the return value of the function == null then this will be returned.
|
|
976
|
+
* @returns Corresponding **boxed** string value, if none then the default value, if none then null.
|
|
977
|
+
*/
|
|
978
|
+
asString(value, defaultValue) {
|
|
979
|
+
if (typeof value == "function") {
|
|
980
|
+
value = value();
|
|
981
|
+
}
|
|
982
|
+
if (value != null) {
|
|
983
|
+
return String(value);
|
|
984
|
+
}
|
|
985
|
+
return defaultValue || null;
|
|
986
|
+
},
|
|
987
|
+
/**
|
|
988
|
+
* Convert a value into a size.
|
|
989
|
+
* @param value - Value to be converted intosize, a function will be executed as `(() => unknown)`.
|
|
990
|
+
* @param defaultValue - If the value or the return value of the function == null then this will be returned.
|
|
991
|
+
* @returns Corresponding string value (number + 'px'), if none then the default value, if none then null.
|
|
992
|
+
*/
|
|
993
|
+
asSize(value, defaultValue) {
|
|
994
|
+
if (typeof value == "function") {
|
|
995
|
+
value = value();
|
|
996
|
+
}
|
|
997
|
+
if (isString(value)) {
|
|
998
|
+
return value;
|
|
999
|
+
}
|
|
1000
|
+
else if (isNumber(value)) {
|
|
1001
|
+
return value + "px";
|
|
1002
|
+
}
|
|
1003
|
+
else {
|
|
1004
|
+
return defaultValue || null;
|
|
1005
|
+
}
|
|
1006
|
+
},
|
|
1007
|
+
/**
|
|
1008
|
+
* Convert a value into a DOM Element.
|
|
1009
|
+
* @param value - Value to be converted into DOM Element, a function will be executed as `(() => unknown)`.
|
|
1010
|
+
* @param defaultValue - If the value or the return value of the function == null then this will be returned.
|
|
1011
|
+
* @returns The DOM Element, if none then the default value, if none then null.
|
|
1012
|
+
*/
|
|
1013
|
+
asElement(value, defaultValue) {
|
|
1014
|
+
if (typeof value == "function") {
|
|
1015
|
+
value = value();
|
|
1016
|
+
}
|
|
1017
|
+
return value || defaultValue || null;
|
|
1018
|
+
},
|
|
1019
|
+
};
|
|
1020
|
+
/**
|
|
1021
|
+
* Convert hex color string into RGB color object.
|
|
1022
|
+
* @remarks
|
|
1023
|
+
* {@link http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb}
|
|
1024
|
+
* @param hex - Hex color string (3 or 6 digits, with or without #).
|
|
1025
|
+
* @returns RGB color object.
|
|
1026
|
+
*/
|
|
1027
|
+
function hexToRGB(hex) {
|
|
1028
|
+
let result;
|
|
1029
|
+
switch (hex.length) {
|
|
1030
|
+
case 3:
|
|
1031
|
+
case 4:
|
|
1032
|
+
result = shortHexRE.exec(hex);
|
|
1033
|
+
return result
|
|
1034
|
+
? {
|
|
1035
|
+
r: parseInt(result[1] + result[1], 16),
|
|
1036
|
+
g: parseInt(result[2] + result[2], 16),
|
|
1037
|
+
b: parseInt(result[3] + result[3], 16),
|
|
1038
|
+
}
|
|
1039
|
+
: null;
|
|
1040
|
+
case 6:
|
|
1041
|
+
case 7:
|
|
1042
|
+
result = fullHexRE.exec(hex);
|
|
1043
|
+
return result
|
|
1044
|
+
? {
|
|
1045
|
+
r: parseInt(result[1], 16),
|
|
1046
|
+
g: parseInt(result[2], 16),
|
|
1047
|
+
b: parseInt(result[3], 16),
|
|
1048
|
+
}
|
|
1049
|
+
: null;
|
|
1050
|
+
default:
|
|
1051
|
+
return null;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
/**
|
|
1055
|
+
* This function takes string color in hex or RGB format and adds the opacity, RGBA is passed through unchanged.
|
|
1056
|
+
* @param color - The color string (hex, RGB, RGBA).
|
|
1057
|
+
* @param opacity - The new opacity.
|
|
1058
|
+
* @returns RGBA string, for example 'rgba(255, 0, 127, 0.3)'.
|
|
1059
|
+
*/
|
|
1060
|
+
function overrideOpacity(color, opacity) {
|
|
1061
|
+
if (color.includes("rgba")) {
|
|
1062
|
+
return color;
|
|
1063
|
+
}
|
|
1064
|
+
else if (color.includes("rgb")) {
|
|
1065
|
+
const rgb = color
|
|
1066
|
+
.substr(color.indexOf("(") + 1)
|
|
1067
|
+
.replace(")", "")
|
|
1068
|
+
.split(",");
|
|
1069
|
+
return "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + opacity + ")";
|
|
1070
|
+
}
|
|
1071
|
+
else {
|
|
1072
|
+
const rgb = hexToRGB(color);
|
|
1073
|
+
if (rgb == null) {
|
|
1074
|
+
return color;
|
|
1075
|
+
}
|
|
1076
|
+
else {
|
|
1077
|
+
return "rgba(" + rgb.r + "," + rgb.g + "," + rgb.b + "," + opacity + ")";
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Convert RGB \<0, 255\> into hex color string.
|
|
1083
|
+
* @param red - Red channel.
|
|
1084
|
+
* @param green - Green channel.
|
|
1085
|
+
* @param blue - Blue channel.
|
|
1086
|
+
* @returns Hex color string (for example: '#0acdc0').
|
|
1087
|
+
*/
|
|
1088
|
+
function RGBToHex(red, green, blue) {
|
|
1089
|
+
return ("#" + ((1 << 24) + (red << 16) + (green << 8) + blue).toString(16).slice(1));
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Parse a color property into an object with border, background, and highlight colors.
|
|
1093
|
+
* @param inputColor - Shorthand color string or input color object.
|
|
1094
|
+
* @param defaultColor - Full color object to fill in missing values in inputColor.
|
|
1095
|
+
* @returns Color object.
|
|
1096
|
+
*/
|
|
1097
|
+
function parseColor(inputColor, defaultColor) {
|
|
1098
|
+
if (isString(inputColor)) {
|
|
1099
|
+
let colorStr = inputColor;
|
|
1100
|
+
if (isValidRGB(colorStr)) {
|
|
1101
|
+
const rgb = colorStr
|
|
1102
|
+
.substr(4)
|
|
1103
|
+
.substr(0, colorStr.length - 5)
|
|
1104
|
+
.split(",")
|
|
1105
|
+
.map(function (value) {
|
|
1106
|
+
return parseInt(value);
|
|
1107
|
+
});
|
|
1108
|
+
colorStr = RGBToHex(rgb[0], rgb[1], rgb[2]);
|
|
1109
|
+
}
|
|
1110
|
+
if (isValidHex(colorStr) === true) {
|
|
1111
|
+
const hsv = hexToHSV(colorStr);
|
|
1112
|
+
const lighterColorHSV = {
|
|
1113
|
+
h: hsv.h,
|
|
1114
|
+
s: hsv.s * 0.8,
|
|
1115
|
+
v: Math.min(1, hsv.v * 1.02),
|
|
1116
|
+
};
|
|
1117
|
+
const darkerColorHSV = {
|
|
1118
|
+
h: hsv.h,
|
|
1119
|
+
s: Math.min(1, hsv.s * 1.25),
|
|
1120
|
+
v: hsv.v * 0.8,
|
|
1121
|
+
};
|
|
1122
|
+
const darkerColorHex = HSVToHex(darkerColorHSV.h, darkerColorHSV.s, darkerColorHSV.v);
|
|
1123
|
+
const lighterColorHex = HSVToHex(lighterColorHSV.h, lighterColorHSV.s, lighterColorHSV.v);
|
|
1124
|
+
return {
|
|
1125
|
+
background: colorStr,
|
|
1126
|
+
border: darkerColorHex,
|
|
1127
|
+
highlight: {
|
|
1128
|
+
background: lighterColorHex,
|
|
1129
|
+
border: darkerColorHex,
|
|
1130
|
+
},
|
|
1131
|
+
hover: {
|
|
1132
|
+
background: lighterColorHex,
|
|
1133
|
+
border: darkerColorHex,
|
|
1134
|
+
},
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
else {
|
|
1138
|
+
return {
|
|
1139
|
+
background: colorStr,
|
|
1140
|
+
border: colorStr,
|
|
1141
|
+
highlight: {
|
|
1142
|
+
background: colorStr,
|
|
1143
|
+
border: colorStr,
|
|
1144
|
+
},
|
|
1145
|
+
hover: {
|
|
1146
|
+
background: colorStr,
|
|
1147
|
+
border: colorStr,
|
|
1148
|
+
},
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
else {
|
|
1153
|
+
if (defaultColor) {
|
|
1154
|
+
const color = {
|
|
1155
|
+
background: inputColor.background || defaultColor.background,
|
|
1156
|
+
border: inputColor.border || defaultColor.border,
|
|
1157
|
+
highlight: isString(inputColor.highlight)
|
|
1158
|
+
? {
|
|
1159
|
+
border: inputColor.highlight,
|
|
1160
|
+
background: inputColor.highlight,
|
|
1161
|
+
}
|
|
1162
|
+
: {
|
|
1163
|
+
background: (inputColor.highlight && inputColor.highlight.background) ||
|
|
1164
|
+
defaultColor.highlight.background,
|
|
1165
|
+
border: (inputColor.highlight && inputColor.highlight.border) ||
|
|
1166
|
+
defaultColor.highlight.border,
|
|
1167
|
+
},
|
|
1168
|
+
hover: isString(inputColor.hover)
|
|
1169
|
+
? {
|
|
1170
|
+
border: inputColor.hover,
|
|
1171
|
+
background: inputColor.hover,
|
|
1172
|
+
}
|
|
1173
|
+
: {
|
|
1174
|
+
border: (inputColor.hover && inputColor.hover.border) ||
|
|
1175
|
+
defaultColor.hover.border,
|
|
1176
|
+
background: (inputColor.hover && inputColor.hover.background) ||
|
|
1177
|
+
defaultColor.hover.background,
|
|
1178
|
+
},
|
|
1179
|
+
};
|
|
1180
|
+
return color;
|
|
1181
|
+
}
|
|
1182
|
+
else {
|
|
1183
|
+
const color = {
|
|
1184
|
+
background: inputColor.background || undefined,
|
|
1185
|
+
border: inputColor.border || undefined,
|
|
1186
|
+
highlight: isString(inputColor.highlight)
|
|
1187
|
+
? {
|
|
1188
|
+
border: inputColor.highlight,
|
|
1189
|
+
background: inputColor.highlight,
|
|
1190
|
+
}
|
|
1191
|
+
: {
|
|
1192
|
+
background: (inputColor.highlight && inputColor.highlight.background) ||
|
|
1193
|
+
undefined,
|
|
1194
|
+
border: (inputColor.highlight && inputColor.highlight.border) ||
|
|
1195
|
+
undefined,
|
|
1196
|
+
},
|
|
1197
|
+
hover: isString(inputColor.hover)
|
|
1198
|
+
? {
|
|
1199
|
+
border: inputColor.hover,
|
|
1200
|
+
background: inputColor.hover,
|
|
1201
|
+
}
|
|
1202
|
+
: {
|
|
1203
|
+
border: (inputColor.hover && inputColor.hover.border) || undefined,
|
|
1204
|
+
background: (inputColor.hover && inputColor.hover.background) || undefined,
|
|
1205
|
+
},
|
|
1206
|
+
};
|
|
1207
|
+
return color;
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
/**
|
|
1212
|
+
* Convert RGB \<0, 255\> into HSV object.
|
|
1213
|
+
* @remarks
|
|
1214
|
+
* {@link http://www.javascripter.net/faq/rgb2hsv.htm}
|
|
1215
|
+
* @param red - Red channel.
|
|
1216
|
+
* @param green - Green channel.
|
|
1217
|
+
* @param blue - Blue channel.
|
|
1218
|
+
* @returns HSV color object.
|
|
1219
|
+
*/
|
|
1220
|
+
function RGBToHSV(red, green, blue) {
|
|
1221
|
+
red = red / 255;
|
|
1222
|
+
green = green / 255;
|
|
1223
|
+
blue = blue / 255;
|
|
1224
|
+
const minRGB = Math.min(red, Math.min(green, blue));
|
|
1225
|
+
const maxRGB = Math.max(red, Math.max(green, blue));
|
|
1226
|
+
// Black-gray-white
|
|
1227
|
+
if (minRGB === maxRGB) {
|
|
1228
|
+
return { h: 0, s: 0, v: minRGB };
|
|
1229
|
+
}
|
|
1230
|
+
// Colors other than black-gray-white:
|
|
1231
|
+
const d = red === minRGB ? green - blue : blue === minRGB ? red - green : blue - red;
|
|
1232
|
+
const h = red === minRGB ? 3 : blue === minRGB ? 1 : 5;
|
|
1233
|
+
const hue = (60 * (h - d / (maxRGB - minRGB))) / 360;
|
|
1234
|
+
const saturation = (maxRGB - minRGB) / maxRGB;
|
|
1235
|
+
const value = maxRGB;
|
|
1236
|
+
return { h: hue, s: saturation, v: value };
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* Split a string with css styles into an object with key/values.
|
|
1240
|
+
* @param cssText - CSS source code to split into key/value object.
|
|
1241
|
+
* @returns Key/value object corresponding to {@link cssText}.
|
|
1242
|
+
*/
|
|
1243
|
+
function splitCSSText(cssText) {
|
|
1244
|
+
const tmpEllement = document.createElement("div");
|
|
1245
|
+
const styles = {};
|
|
1246
|
+
tmpEllement.style.cssText = cssText;
|
|
1247
|
+
for (let i = 0; i < tmpEllement.style.length; ++i) {
|
|
1248
|
+
styles[tmpEllement.style[i]] = tmpEllement.style.getPropertyValue(tmpEllement.style[i]);
|
|
1249
|
+
}
|
|
1250
|
+
return styles;
|
|
1251
|
+
}
|
|
1252
|
+
/**
|
|
1253
|
+
* Append a string with css styles to an element.
|
|
1254
|
+
* @param element - The element that will receive new styles.
|
|
1255
|
+
* @param cssText - The styles to be appended.
|
|
1256
|
+
*/
|
|
1257
|
+
function addCssText(element, cssText) {
|
|
1258
|
+
const cssStyle = splitCSSText(cssText);
|
|
1259
|
+
for (const [key, value] of Object.entries(cssStyle)) {
|
|
1260
|
+
element.style.setProperty(key, value);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* Remove a string with css styles from an element.
|
|
1265
|
+
* @param element - The element from which styles should be removed.
|
|
1266
|
+
* @param cssText - The styles to be removed.
|
|
1267
|
+
*/
|
|
1268
|
+
function removeCssText(element, cssText) {
|
|
1269
|
+
const cssStyle = splitCSSText(cssText);
|
|
1270
|
+
for (const key of Object.keys(cssStyle)) {
|
|
1271
|
+
element.style.removeProperty(key);
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Convert HSV \<0, 1\> into RGB color object.
|
|
1276
|
+
* @remarks
|
|
1277
|
+
* {@link https://gist.github.com/mjijackson/5311256}
|
|
1278
|
+
* @param h - Hue.
|
|
1279
|
+
* @param s - Saturation.
|
|
1280
|
+
* @param v - Value.
|
|
1281
|
+
* @returns RGB color object.
|
|
1282
|
+
*/
|
|
1283
|
+
function HSVToRGB(h, s, v) {
|
|
1284
|
+
let r;
|
|
1285
|
+
let g;
|
|
1286
|
+
let b;
|
|
1287
|
+
const i = Math.floor(h * 6);
|
|
1288
|
+
const f = h * 6 - i;
|
|
1289
|
+
const p = v * (1 - s);
|
|
1290
|
+
const q = v * (1 - f * s);
|
|
1291
|
+
const t = v * (1 - (1 - f) * s);
|
|
1292
|
+
switch (i % 6) {
|
|
1293
|
+
case 0:
|
|
1294
|
+
((r = v), (g = t), (b = p));
|
|
1295
|
+
break;
|
|
1296
|
+
case 1:
|
|
1297
|
+
((r = q), (g = v), (b = p));
|
|
1298
|
+
break;
|
|
1299
|
+
case 2:
|
|
1300
|
+
((r = p), (g = v), (b = t));
|
|
1301
|
+
break;
|
|
1302
|
+
case 3:
|
|
1303
|
+
((r = p), (g = q), (b = v));
|
|
1304
|
+
break;
|
|
1305
|
+
case 4:
|
|
1306
|
+
((r = t), (g = p), (b = v));
|
|
1307
|
+
break;
|
|
1308
|
+
case 5:
|
|
1309
|
+
((r = v), (g = p), (b = q));
|
|
1310
|
+
break;
|
|
1311
|
+
}
|
|
1312
|
+
return {
|
|
1313
|
+
r: Math.floor(r * 255),
|
|
1314
|
+
g: Math.floor(g * 255),
|
|
1315
|
+
b: Math.floor(b * 255),
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
/**
|
|
1319
|
+
* Convert HSV \<0, 1\> into hex color string.
|
|
1320
|
+
* @param h - Hue.
|
|
1321
|
+
* @param s - Saturation.
|
|
1322
|
+
* @param v - Value.
|
|
1323
|
+
* @returns Hex color string.
|
|
1324
|
+
*/
|
|
1325
|
+
function HSVToHex(h, s, v) {
|
|
1326
|
+
const rgb = HSVToRGB(h, s, v);
|
|
1327
|
+
return RGBToHex(rgb.r, rgb.g, rgb.b);
|
|
1328
|
+
}
|
|
1329
|
+
/**
|
|
1330
|
+
* Convert hex color string into HSV \<0, 1\>.
|
|
1331
|
+
* @param hex - Hex color string.
|
|
1332
|
+
* @returns HSV color object.
|
|
1333
|
+
*/
|
|
1334
|
+
function hexToHSV(hex) {
|
|
1335
|
+
const rgb = hexToRGB(hex);
|
|
1336
|
+
if (!rgb) {
|
|
1337
|
+
throw new TypeError(`'${hex}' is not a valid color.`);
|
|
1338
|
+
}
|
|
1339
|
+
return RGBToHSV(rgb.r, rgb.g, rgb.b);
|
|
1340
|
+
}
|
|
1341
|
+
/**
|
|
1342
|
+
* Validate hex color string.
|
|
1343
|
+
* @param hex - Unknown string that may contain a color.
|
|
1344
|
+
* @returns True if the string is valid, false otherwise.
|
|
1345
|
+
*/
|
|
1346
|
+
function isValidHex(hex) {
|
|
1347
|
+
const isOk = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(hex);
|
|
1348
|
+
return isOk;
|
|
1349
|
+
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Validate RGB color string.
|
|
1352
|
+
* @param rgb - Unknown string that may contain a color.
|
|
1353
|
+
* @returns True if the string is valid, false otherwise.
|
|
1354
|
+
*/
|
|
1355
|
+
function isValidRGB(rgb) {
|
|
1356
|
+
return rgbRE.test(rgb);
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* Validate RGBA color string.
|
|
1360
|
+
* @param rgba - Unknown string that may contain a color.
|
|
1361
|
+
* @returns True if the string is valid, false otherwise.
|
|
1362
|
+
*/
|
|
1363
|
+
function isValidRGBA(rgba) {
|
|
1364
|
+
return rgbaRE.test(rgba);
|
|
1365
|
+
}
|
|
1366
|
+
/**
|
|
1367
|
+
* This recursively redirects the prototype of JSON objects to the referenceObject.
|
|
1368
|
+
* This is used for default options.
|
|
1369
|
+
* @param fields - Names of properties to be bridged.
|
|
1370
|
+
* @param referenceObject - The original object.
|
|
1371
|
+
* @returns A new object inheriting from the referenceObject.
|
|
1372
|
+
*/
|
|
1373
|
+
function selectiveBridgeObject(fields, referenceObject) {
|
|
1374
|
+
if (referenceObject !== null && typeof referenceObject === "object") {
|
|
1375
|
+
// !!! typeof null === 'object'
|
|
1376
|
+
const objectTo = Object.create(referenceObject);
|
|
1377
|
+
for (let i = 0; i < fields.length; i++) {
|
|
1378
|
+
if (Object.prototype.hasOwnProperty.call(referenceObject, fields[i])) {
|
|
1379
|
+
if (typeof referenceObject[fields[i]] == "object") {
|
|
1380
|
+
objectTo[fields[i]] = bridgeObject(referenceObject[fields[i]]);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
return objectTo;
|
|
1385
|
+
}
|
|
1386
|
+
else {
|
|
1387
|
+
return null;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
/**
|
|
1391
|
+
* This recursively redirects the prototype of JSON objects to the referenceObject.
|
|
1392
|
+
* This is used for default options.
|
|
1393
|
+
* @param referenceObject - The original object.
|
|
1394
|
+
* @returns The Element if the referenceObject is an Element, or a new object inheriting from the referenceObject.
|
|
1395
|
+
*/
|
|
1396
|
+
function bridgeObject(referenceObject) {
|
|
1397
|
+
if (referenceObject === null || typeof referenceObject !== "object") {
|
|
1398
|
+
return null;
|
|
1399
|
+
}
|
|
1400
|
+
if (referenceObject instanceof Element) {
|
|
1401
|
+
// Avoid bridging DOM objects
|
|
1402
|
+
return referenceObject;
|
|
1403
|
+
}
|
|
1404
|
+
const objectTo = Object.create(referenceObject);
|
|
1405
|
+
for (const i in referenceObject) {
|
|
1406
|
+
if (Object.prototype.hasOwnProperty.call(referenceObject, i)) {
|
|
1407
|
+
if (typeof referenceObject[i] == "object") {
|
|
1408
|
+
objectTo[i] = bridgeObject(referenceObject[i]);
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
return objectTo;
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* This method provides a stable sort implementation, very fast for presorted data.
|
|
1416
|
+
* @param a - The array to be sorted (in-place).
|
|
1417
|
+
* @param compare - An order comparator.
|
|
1418
|
+
* @returns The argument a.
|
|
1419
|
+
*/
|
|
1420
|
+
function insertSort(a, compare) {
|
|
1421
|
+
for (let i = 0; i < a.length; i++) {
|
|
1422
|
+
const k = a[i];
|
|
1423
|
+
let j;
|
|
1424
|
+
for (j = i; j > 0 && compare(k, a[j - 1]) < 0; j--) {
|
|
1425
|
+
a[j] = a[j - 1];
|
|
1426
|
+
}
|
|
1427
|
+
a[j] = k;
|
|
1428
|
+
}
|
|
1429
|
+
return a;
|
|
1430
|
+
}
|
|
1431
|
+
/**
|
|
1432
|
+
* This is used to set the options of subobjects in the options object.
|
|
1433
|
+
*
|
|
1434
|
+
* A requirement of these subobjects is that they have an 'enabled' element
|
|
1435
|
+
* which is optional for the user but mandatory for the program.
|
|
1436
|
+
*
|
|
1437
|
+
* The added value here of the merge is that option 'enabled' is set as required.
|
|
1438
|
+
* @param mergeTarget - Either this.options or the options used for the groups.
|
|
1439
|
+
* @param options - Options.
|
|
1440
|
+
* @param option - Option key in the options argument.
|
|
1441
|
+
* @param globalOptions - Global options, passed in to determine value of option 'enabled'.
|
|
1442
|
+
*/
|
|
1443
|
+
function mergeOptions(mergeTarget, options, option, globalOptions = {}) {
|
|
1444
|
+
// Local helpers
|
|
1445
|
+
const isPresent = function (obj) {
|
|
1446
|
+
return obj !== null && obj !== undefined;
|
|
1447
|
+
};
|
|
1448
|
+
const isObject = function (obj) {
|
|
1449
|
+
return obj !== null && typeof obj === "object";
|
|
1450
|
+
};
|
|
1451
|
+
// https://stackoverflow.com/a/34491287/1223531
|
|
1452
|
+
const isEmpty = function (obj) {
|
|
1453
|
+
for (const x in obj) {
|
|
1454
|
+
if (Object.prototype.hasOwnProperty.call(obj, x)) {
|
|
1455
|
+
return false;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
return true;
|
|
1459
|
+
};
|
|
1460
|
+
// Guards
|
|
1461
|
+
if (!isObject(mergeTarget)) {
|
|
1462
|
+
throw new Error("Parameter mergeTarget must be an object");
|
|
1463
|
+
}
|
|
1464
|
+
if (!isObject(options)) {
|
|
1465
|
+
throw new Error("Parameter options must be an object");
|
|
1466
|
+
}
|
|
1467
|
+
if (!isPresent(option)) {
|
|
1468
|
+
throw new Error("Parameter option must have a value");
|
|
1469
|
+
}
|
|
1470
|
+
if (!isObject(globalOptions)) {
|
|
1471
|
+
throw new Error("Parameter globalOptions must be an object");
|
|
1472
|
+
}
|
|
1473
|
+
//
|
|
1474
|
+
// Actual merge routine, separated from main logic
|
|
1475
|
+
// Only a single level of options is merged. Deeper levels are ref'd. This may actually be an issue.
|
|
1476
|
+
//
|
|
1477
|
+
const doMerge = function (target, options, option) {
|
|
1478
|
+
if (!isObject(target[option])) {
|
|
1479
|
+
target[option] = {};
|
|
1480
|
+
}
|
|
1481
|
+
const src = options[option];
|
|
1482
|
+
const dst = target[option];
|
|
1483
|
+
for (const prop in src) {
|
|
1484
|
+
if (Object.prototype.hasOwnProperty.call(src, prop)) {
|
|
1485
|
+
dst[prop] = src[prop];
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
};
|
|
1489
|
+
// Local initialization
|
|
1490
|
+
const srcOption = options[option];
|
|
1491
|
+
const globalPassed = isObject(globalOptions) && !isEmpty(globalOptions);
|
|
1492
|
+
const globalOption = globalPassed ? globalOptions[option] : undefined;
|
|
1493
|
+
const globalEnabled = globalOption ? globalOption.enabled : undefined;
|
|
1494
|
+
/////////////////////////////////////////
|
|
1495
|
+
// Main routine
|
|
1496
|
+
/////////////////////////////////////////
|
|
1497
|
+
if (srcOption === undefined) {
|
|
1498
|
+
return; // Nothing to do
|
|
1499
|
+
}
|
|
1500
|
+
if (typeof srcOption === "boolean") {
|
|
1501
|
+
if (!isObject(mergeTarget[option])) {
|
|
1502
|
+
mergeTarget[option] = {};
|
|
1503
|
+
}
|
|
1504
|
+
mergeTarget[option].enabled = srcOption;
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
if (srcOption === null && !isObject(mergeTarget[option])) {
|
|
1508
|
+
// If possible, explicit copy from globals
|
|
1509
|
+
if (isPresent(globalOption)) {
|
|
1510
|
+
mergeTarget[option] = Object.create(globalOption);
|
|
1511
|
+
}
|
|
1512
|
+
else {
|
|
1513
|
+
return; // Nothing to do
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
if (!isObject(srcOption)) {
|
|
1517
|
+
return;
|
|
1518
|
+
}
|
|
1519
|
+
//
|
|
1520
|
+
// Ensure that 'enabled' is properly set. It is required internally
|
|
1521
|
+
// Note that the value from options will always overwrite the existing value
|
|
1522
|
+
//
|
|
1523
|
+
let enabled = true; // default value
|
|
1524
|
+
if (srcOption.enabled !== undefined) {
|
|
1525
|
+
enabled = srcOption.enabled;
|
|
1526
|
+
}
|
|
1527
|
+
else {
|
|
1528
|
+
// Take from globals, if present
|
|
1529
|
+
if (globalEnabled !== undefined) {
|
|
1530
|
+
enabled = globalOption.enabled;
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
doMerge(mergeTarget, options, option);
|
|
1534
|
+
mergeTarget[option].enabled = enabled;
|
|
1535
|
+
}
|
|
1536
|
+
/**
|
|
1537
|
+
* This function does a binary search for a visible item in a sorted list. If we find a visible item, the code that uses
|
|
1538
|
+
* this function will then iterate in both directions over this sorted list to find all visible items.
|
|
1539
|
+
* @param orderedItems - Items ordered by start.
|
|
1540
|
+
* @param comparator - -1 is lower, 0 is equal, 1 is higher.
|
|
1541
|
+
* @param field - Property name on an item (That is item[field]).
|
|
1542
|
+
* @param field2 - Second property name on an item (That is item[field][field2]).
|
|
1543
|
+
* @returns Index of the found item or -1 if nothing was found.
|
|
1544
|
+
*/
|
|
1545
|
+
function binarySearchCustom(orderedItems, comparator, field, field2) {
|
|
1546
|
+
const maxIterations = 10000;
|
|
1547
|
+
let iteration = 0;
|
|
1548
|
+
let low = 0;
|
|
1549
|
+
let high = orderedItems.length - 1;
|
|
1550
|
+
while (low <= high && iteration < maxIterations) {
|
|
1551
|
+
const middle = Math.floor((low + high) / 2);
|
|
1552
|
+
const item = orderedItems[middle];
|
|
1553
|
+
const value = field2 === undefined ? item[field] : item[field][field2];
|
|
1554
|
+
const searchResult = comparator(value);
|
|
1555
|
+
if (searchResult == 0) {
|
|
1556
|
+
// jihaa, found a visible item!
|
|
1557
|
+
return middle;
|
|
1558
|
+
}
|
|
1559
|
+
else if (searchResult == -1) {
|
|
1560
|
+
// it is too small --> increase low
|
|
1561
|
+
low = middle + 1;
|
|
1562
|
+
}
|
|
1563
|
+
else {
|
|
1564
|
+
// it is too big --> decrease high
|
|
1565
|
+
high = middle - 1;
|
|
1566
|
+
}
|
|
1567
|
+
iteration++;
|
|
1568
|
+
}
|
|
1569
|
+
return -1;
|
|
1570
|
+
}
|
|
1571
|
+
/**
|
|
1572
|
+
* This function does a binary search for a specific value in a sorted array.
|
|
1573
|
+
* If it does not exist but is in between of two values, we return either the
|
|
1574
|
+
* one before or the one after, depending on user input If it is found, we
|
|
1575
|
+
* return the index, else -1.
|
|
1576
|
+
* @param orderedItems - Sorted array.
|
|
1577
|
+
* @param target - The searched value.
|
|
1578
|
+
* @param field - Name of the property in items to be searched.
|
|
1579
|
+
* @param sidePreference - If the target is between two values, should the index of the before or the after be returned?
|
|
1580
|
+
* @param comparator - An optional comparator, returning -1, 0, 1 for \<, ===, \>.
|
|
1581
|
+
* @returns The index of found value or -1 if nothing was found.
|
|
1582
|
+
*/
|
|
1583
|
+
function binarySearchValue(orderedItems, target, field, sidePreference, comparator) {
|
|
1584
|
+
const maxIterations = 10000;
|
|
1585
|
+
let iteration = 0;
|
|
1586
|
+
let low = 0;
|
|
1587
|
+
let high = orderedItems.length - 1;
|
|
1588
|
+
let prevValue;
|
|
1589
|
+
let value;
|
|
1590
|
+
let nextValue;
|
|
1591
|
+
let middle;
|
|
1592
|
+
comparator =
|
|
1593
|
+
comparator != undefined
|
|
1594
|
+
? comparator
|
|
1595
|
+
: function (a, b) {
|
|
1596
|
+
return a == b ? 0 : a < b ? -1 : 1;
|
|
1597
|
+
};
|
|
1598
|
+
while (low <= high && iteration < maxIterations) {
|
|
1599
|
+
// get a new guess
|
|
1600
|
+
middle = Math.floor(0.5 * (high + low));
|
|
1601
|
+
prevValue = orderedItems[Math.max(0, middle - 1)][field];
|
|
1602
|
+
value = orderedItems[middle][field];
|
|
1603
|
+
nextValue =
|
|
1604
|
+
orderedItems[Math.min(orderedItems.length - 1, middle + 1)][field];
|
|
1605
|
+
if (comparator(value, target) == 0) {
|
|
1606
|
+
// we found the target
|
|
1607
|
+
return middle;
|
|
1608
|
+
}
|
|
1609
|
+
else if (comparator(prevValue, target) < 0 &&
|
|
1610
|
+
comparator(value, target) > 0) {
|
|
1611
|
+
// target is in between of the previous and the current
|
|
1612
|
+
return sidePreference == "before" ? Math.max(0, middle - 1) : middle;
|
|
1613
|
+
}
|
|
1614
|
+
else if (comparator(value, target) < 0 &&
|
|
1615
|
+
comparator(nextValue, target) > 0) {
|
|
1616
|
+
// target is in between of the current and the next
|
|
1617
|
+
return sidePreference == "before"
|
|
1618
|
+
? middle
|
|
1619
|
+
: Math.min(orderedItems.length - 1, middle + 1);
|
|
1620
|
+
}
|
|
1621
|
+
else {
|
|
1622
|
+
// didnt find the target, we need to change our boundaries.
|
|
1623
|
+
if (comparator(value, target) < 0) {
|
|
1624
|
+
// it is too small --> increase low
|
|
1625
|
+
low = middle + 1;
|
|
1626
|
+
}
|
|
1627
|
+
else {
|
|
1628
|
+
// it is too big --> decrease high
|
|
1629
|
+
high = middle - 1;
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
iteration++;
|
|
1633
|
+
}
|
|
1634
|
+
// didnt find anything. Return -1.
|
|
1635
|
+
return -1;
|
|
1636
|
+
}
|
|
1637
|
+
/*
|
|
1638
|
+
* Easing Functions.
|
|
1639
|
+
* Only considering the t value for the range [0, 1] => [0, 1].
|
|
1640
|
+
*
|
|
1641
|
+
* Inspiration: from http://gizma.com/easing/
|
|
1642
|
+
* https://gist.github.com/gre/1650294
|
|
1643
|
+
*/
|
|
1644
|
+
const easingFunctions = {
|
|
1645
|
+
/**
|
|
1646
|
+
* Provides no easing and no acceleration.
|
|
1647
|
+
* @param t - Time.
|
|
1648
|
+
* @returns Value at time t.
|
|
1649
|
+
*/
|
|
1650
|
+
linear(t) {
|
|
1651
|
+
return t;
|
|
1652
|
+
},
|
|
1653
|
+
/**
|
|
1654
|
+
* Accelerate from zero velocity.
|
|
1655
|
+
* @param t - Time.
|
|
1656
|
+
* @returns Value at time t.
|
|
1657
|
+
*/
|
|
1658
|
+
easeInQuad(t) {
|
|
1659
|
+
return t * t;
|
|
1660
|
+
},
|
|
1661
|
+
/**
|
|
1662
|
+
* Decelerate to zero velocity.
|
|
1663
|
+
* @param t - Time.
|
|
1664
|
+
* @returns Value at time t.
|
|
1665
|
+
*/
|
|
1666
|
+
easeOutQuad(t) {
|
|
1667
|
+
return t * (2 - t);
|
|
1668
|
+
},
|
|
1669
|
+
/**
|
|
1670
|
+
* Accelerate until halfway, then decelerate.
|
|
1671
|
+
* @param t - Time.
|
|
1672
|
+
* @returns Value at time t.
|
|
1673
|
+
*/
|
|
1674
|
+
easeInOutQuad(t) {
|
|
1675
|
+
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
|
1676
|
+
},
|
|
1677
|
+
/**
|
|
1678
|
+
* Accelerate from zero velocity.
|
|
1679
|
+
* @param t - Time.
|
|
1680
|
+
* @returns Value at time t.
|
|
1681
|
+
*/
|
|
1682
|
+
easeInCubic(t) {
|
|
1683
|
+
return t * t * t;
|
|
1684
|
+
},
|
|
1685
|
+
/**
|
|
1686
|
+
* Decelerate to zero velocity.
|
|
1687
|
+
* @param t - Time.
|
|
1688
|
+
* @returns Value at time t.
|
|
1689
|
+
*/
|
|
1690
|
+
easeOutCubic(t) {
|
|
1691
|
+
return --t * t * t + 1;
|
|
1692
|
+
},
|
|
1693
|
+
/**
|
|
1694
|
+
* Accelerate until halfway, then decelerate.
|
|
1695
|
+
* @param t - Time.
|
|
1696
|
+
* @returns Value at time t.
|
|
1697
|
+
*/
|
|
1698
|
+
easeInOutCubic(t) {
|
|
1699
|
+
return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
|
|
1700
|
+
},
|
|
1701
|
+
/**
|
|
1702
|
+
* Accelerate from zero velocity.
|
|
1703
|
+
* @param t - Time.
|
|
1704
|
+
* @returns Value at time t.
|
|
1705
|
+
*/
|
|
1706
|
+
easeInQuart(t) {
|
|
1707
|
+
return t * t * t * t;
|
|
1708
|
+
},
|
|
1709
|
+
/**
|
|
1710
|
+
* Decelerate to zero velocity.
|
|
1711
|
+
* @param t - Time.
|
|
1712
|
+
* @returns Value at time t.
|
|
1713
|
+
*/
|
|
1714
|
+
easeOutQuart(t) {
|
|
1715
|
+
return 1 - --t * t * t * t;
|
|
1716
|
+
},
|
|
1717
|
+
/**
|
|
1718
|
+
* Accelerate until halfway, then decelerate.
|
|
1719
|
+
* @param t - Time.
|
|
1720
|
+
* @returns Value at time t.
|
|
1721
|
+
*/
|
|
1722
|
+
easeInOutQuart(t) {
|
|
1723
|
+
return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
|
|
1724
|
+
},
|
|
1725
|
+
/**
|
|
1726
|
+
* Accelerate from zero velocity.
|
|
1727
|
+
* @param t - Time.
|
|
1728
|
+
* @returns Value at time t.
|
|
1729
|
+
*/
|
|
1730
|
+
easeInQuint(t) {
|
|
1731
|
+
return t * t * t * t * t;
|
|
1732
|
+
},
|
|
1733
|
+
/**
|
|
1734
|
+
* Decelerate to zero velocity.
|
|
1735
|
+
* @param t - Time.
|
|
1736
|
+
* @returns Value at time t.
|
|
1737
|
+
*/
|
|
1738
|
+
easeOutQuint(t) {
|
|
1739
|
+
return 1 + --t * t * t * t * t;
|
|
1740
|
+
},
|
|
1741
|
+
/**
|
|
1742
|
+
* Accelerate until halfway, then decelerate.
|
|
1743
|
+
* @param t - Time.
|
|
1744
|
+
* @returns Value at time t.
|
|
1745
|
+
*/
|
|
1746
|
+
easeInOutQuint(t) {
|
|
1747
|
+
return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
|
|
1748
|
+
},
|
|
1749
|
+
};
|
|
1750
|
+
/**
|
|
1751
|
+
* Experimentaly compute the width of the scrollbar for this browser.
|
|
1752
|
+
* @returns The width in pixels.
|
|
1753
|
+
*/
|
|
1754
|
+
function getScrollBarWidth() {
|
|
1755
|
+
const inner = document.createElement("p");
|
|
1756
|
+
inner.style.width = "100%";
|
|
1757
|
+
inner.style.height = "200px";
|
|
1758
|
+
const outer = document.createElement("div");
|
|
1759
|
+
outer.style.position = "absolute";
|
|
1760
|
+
outer.style.top = "0px";
|
|
1761
|
+
outer.style.left = "0px";
|
|
1762
|
+
outer.style.visibility = "hidden";
|
|
1763
|
+
outer.style.width = "200px";
|
|
1764
|
+
outer.style.height = "150px";
|
|
1765
|
+
outer.style.overflow = "hidden";
|
|
1766
|
+
outer.appendChild(inner);
|
|
1767
|
+
document.body.appendChild(outer);
|
|
1768
|
+
const w1 = inner.offsetWidth;
|
|
1769
|
+
outer.style.overflow = "scroll";
|
|
1770
|
+
let w2 = inner.offsetWidth;
|
|
1771
|
+
if (w1 == w2) {
|
|
1772
|
+
w2 = outer.clientWidth;
|
|
1773
|
+
}
|
|
1774
|
+
document.body.removeChild(outer);
|
|
1775
|
+
return w1 - w2;
|
|
1776
|
+
}
|
|
1777
|
+
// @TODO: This doesn't work properly.
|
|
1778
|
+
// It works only for single property objects,
|
|
1779
|
+
// otherwise it combines all of the types in a union.
|
|
1780
|
+
// export function topMost<K1 extends string, V1> (
|
|
1781
|
+
// pile: Record<K1, undefined | V1>[],
|
|
1782
|
+
// accessors: K1 | [K1]
|
|
1783
|
+
// ): undefined | V1
|
|
1784
|
+
// export function topMost<K1 extends string, K2 extends string, V1, V2> (
|
|
1785
|
+
// pile: Record<K1, undefined | V1 | Record<K2, undefined | V2>>[],
|
|
1786
|
+
// accessors: [K1, K2]
|
|
1787
|
+
// ): undefined | V1 | V2
|
|
1788
|
+
// export function topMost<K1 extends string, K2 extends string, K3 extends string, V1, V2, V3> (
|
|
1789
|
+
// pile: Record<K1, undefined | V1 | Record<K2, undefined | V2 | Record<K3, undefined | V3>>>[],
|
|
1790
|
+
// accessors: [K1, K2, K3]
|
|
1791
|
+
// ): undefined | V1 | V2 | V3
|
|
1792
|
+
/**
|
|
1793
|
+
* Get the top most property value from a pile of objects.
|
|
1794
|
+
* @param pile - Array of objects, no required format.
|
|
1795
|
+
* @param accessors - Array of property names.
|
|
1796
|
+
* For example `object['foo']['bar']` → `['foo', 'bar']`.
|
|
1797
|
+
* @returns Value of the property with given accessors path from the first pile item where it's not undefined.
|
|
1798
|
+
*/
|
|
1799
|
+
function topMost(pile, accessors) {
|
|
1800
|
+
let candidate;
|
|
1801
|
+
if (!Array.isArray(accessors)) {
|
|
1802
|
+
accessors = [accessors];
|
|
1803
|
+
}
|
|
1804
|
+
for (const member of pile) {
|
|
1805
|
+
if (member) {
|
|
1806
|
+
candidate = member[accessors[0]];
|
|
1807
|
+
for (let i = 1; i < accessors.length; i++) {
|
|
1808
|
+
if (candidate) {
|
|
1809
|
+
candidate = candidate[accessors[i]];
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
if (typeof candidate !== "undefined") {
|
|
1813
|
+
break;
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
return candidate;
|
|
1900
1818
|
}
|
|
1901
1819
|
|
|
1902
1820
|
const htmlColors = {
|
|
@@ -2047,7 +1965,7 @@ const htmlColors = {
|
|
|
2047
1965
|
*/
|
|
2048
1966
|
let ColorPicker$1 = class ColorPicker {
|
|
2049
1967
|
/**
|
|
2050
|
-
* @param {number} [pixelRatio
|
|
1968
|
+
* @param {number} [pixelRatio]
|
|
2051
1969
|
*/
|
|
2052
1970
|
constructor(pixelRatio = 1) {
|
|
2053
1971
|
this.pixelRatio = pixelRatio;
|
|
@@ -2070,7 +1988,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2070
1988
|
|
|
2071
1989
|
/**
|
|
2072
1990
|
* this inserts the colorPicker into a div from the DOM
|
|
2073
|
-
*
|
|
2074
1991
|
* @param {Element} container
|
|
2075
1992
|
*/
|
|
2076
1993
|
insertTo(container) {
|
|
@@ -2087,7 +2004,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2087
2004
|
|
|
2088
2005
|
/**
|
|
2089
2006
|
* the callback is executed on apply and save. Bind it to the application
|
|
2090
|
-
*
|
|
2091
2007
|
* @param {Function} callback
|
|
2092
2008
|
*/
|
|
2093
2009
|
setUpdateCallback(callback) {
|
|
@@ -2095,14 +2011,13 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2095
2011
|
this.updateCallback = callback;
|
|
2096
2012
|
} else {
|
|
2097
2013
|
throw new Error(
|
|
2098
|
-
"Function attempted to set as colorPicker update callback is not a function."
|
|
2014
|
+
"Function attempted to set as colorPicker update callback is not a function.",
|
|
2099
2015
|
);
|
|
2100
2016
|
}
|
|
2101
2017
|
}
|
|
2102
2018
|
|
|
2103
2019
|
/**
|
|
2104
2020
|
* the callback is executed on apply and save. Bind it to the application
|
|
2105
|
-
*
|
|
2106
2021
|
* @param {Function} callback
|
|
2107
2022
|
*/
|
|
2108
2023
|
setCloseCallback(callback) {
|
|
@@ -2110,7 +2025,7 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2110
2025
|
this.closeCallback = callback;
|
|
2111
2026
|
} else {
|
|
2112
2027
|
throw new Error(
|
|
2113
|
-
"Function attempted to set as colorPicker closing callback is not a function."
|
|
2028
|
+
"Function attempted to set as colorPicker closing callback is not a function.",
|
|
2114
2029
|
);
|
|
2115
2030
|
}
|
|
2116
2031
|
}
|
|
@@ -2136,9 +2051,8 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2136
2051
|
* 'rgba(255,255,255,1.0)' --> rgba string
|
|
2137
2052
|
* {r:255,g:255,b:255} --> rgb object
|
|
2138
2053
|
* {r:255,g:255,b:255,a:1.0} --> rgba object
|
|
2139
|
-
*
|
|
2140
2054
|
* @param {string | object} color
|
|
2141
|
-
* @param {boolean} [setInitial
|
|
2055
|
+
* @param {boolean} [setInitial]
|
|
2142
2056
|
*/
|
|
2143
2057
|
setColor(color, setInitial = true) {
|
|
2144
2058
|
if (color === "none") {
|
|
@@ -2193,7 +2107,7 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2193
2107
|
if (rgba === undefined) {
|
|
2194
2108
|
throw new Error(
|
|
2195
2109
|
"Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: " +
|
|
2196
|
-
JSON.stringify(color)
|
|
2110
|
+
JSON.stringify(color),
|
|
2197
2111
|
);
|
|
2198
2112
|
} else {
|
|
2199
2113
|
this._setColor(rgba, setInitial);
|
|
@@ -2220,8 +2134,7 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2220
2134
|
/**
|
|
2221
2135
|
* Hide the picker. Is called by the cancel button.
|
|
2222
2136
|
* Optional boolean to store the previous color for easy access later on.
|
|
2223
|
-
*
|
|
2224
|
-
* @param {boolean} [storePrevious=true]
|
|
2137
|
+
* @param {boolean} [storePrevious]
|
|
2225
2138
|
* @private
|
|
2226
2139
|
*/
|
|
2227
2140
|
_hide(storePrevious = true) {
|
|
@@ -2248,7 +2161,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2248
2161
|
|
|
2249
2162
|
/**
|
|
2250
2163
|
* bound to the save button. Saves and hides.
|
|
2251
|
-
*
|
|
2252
2164
|
* @private
|
|
2253
2165
|
*/
|
|
2254
2166
|
_save() {
|
|
@@ -2259,7 +2171,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2259
2171
|
|
|
2260
2172
|
/**
|
|
2261
2173
|
* Bound to apply button. Saves but does not close. Is undone by the cancel button.
|
|
2262
|
-
*
|
|
2263
2174
|
* @private
|
|
2264
2175
|
*/
|
|
2265
2176
|
_apply() {
|
|
@@ -2270,7 +2181,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2270
2181
|
|
|
2271
2182
|
/**
|
|
2272
2183
|
* load the color from the previous session.
|
|
2273
|
-
*
|
|
2274
2184
|
* @private
|
|
2275
2185
|
*/
|
|
2276
2186
|
_loadLast() {
|
|
@@ -2283,9 +2193,8 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2283
2193
|
|
|
2284
2194
|
/**
|
|
2285
2195
|
* set the color, place the picker
|
|
2286
|
-
*
|
|
2287
2196
|
* @param {object} rgba
|
|
2288
|
-
* @param {boolean} [setInitial
|
|
2197
|
+
* @param {boolean} [setInitial]
|
|
2289
2198
|
* @private
|
|
2290
2199
|
*/
|
|
2291
2200
|
_setColor(rgba, setInitial = true) {
|
|
@@ -2314,7 +2223,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2314
2223
|
|
|
2315
2224
|
/**
|
|
2316
2225
|
* bound to opacity control
|
|
2317
|
-
*
|
|
2318
2226
|
* @param {number} value
|
|
2319
2227
|
* @private
|
|
2320
2228
|
*/
|
|
@@ -2325,7 +2233,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2325
2233
|
|
|
2326
2234
|
/**
|
|
2327
2235
|
* bound to brightness control
|
|
2328
|
-
*
|
|
2329
2236
|
* @param {number} value
|
|
2330
2237
|
* @private
|
|
2331
2238
|
*/
|
|
@@ -2340,7 +2247,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2340
2247
|
|
|
2341
2248
|
/**
|
|
2342
2249
|
* update the color picker. A black circle overlays the hue circle to mimic the brightness decreasing.
|
|
2343
|
-
*
|
|
2344
2250
|
* @param {object} rgba
|
|
2345
2251
|
* @private
|
|
2346
2252
|
*/
|
|
@@ -2396,7 +2302,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2396
2302
|
|
|
2397
2303
|
/**
|
|
2398
2304
|
* used by create to set the size of the canvas.
|
|
2399
|
-
*
|
|
2400
2305
|
* @private
|
|
2401
2306
|
*/
|
|
2402
2307
|
_setSize() {
|
|
@@ -2410,7 +2315,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2410
2315
|
/**
|
|
2411
2316
|
* create all dom elements
|
|
2412
2317
|
* TODO: cleanup, lots of similar dom elements
|
|
2413
|
-
*
|
|
2414
2318
|
* @private
|
|
2415
2319
|
*/
|
|
2416
2320
|
_create() {
|
|
@@ -2550,7 +2454,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2550
2454
|
|
|
2551
2455
|
/**
|
|
2552
2456
|
* bind hammer to the color picker
|
|
2553
|
-
*
|
|
2554
2457
|
* @private
|
|
2555
2458
|
*/
|
|
2556
2459
|
_bindHammer() {
|
|
@@ -2580,7 +2483,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2580
2483
|
|
|
2581
2484
|
/**
|
|
2582
2485
|
* generate the hue circle. This is relatively heavy (200ms) and is done only once on the first time it is shown.
|
|
2583
|
-
*
|
|
2584
2486
|
* @private
|
|
2585
2487
|
*/
|
|
2586
2488
|
_generateHueCircle() {
|
|
@@ -2631,7 +2533,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2631
2533
|
|
|
2632
2534
|
/**
|
|
2633
2535
|
* move the selector. This is called by hammer functions.
|
|
2634
|
-
*
|
|
2635
2536
|
* @param {Event} event The event
|
|
2636
2537
|
* @private
|
|
2637
2538
|
*/
|
|
@@ -2694,7 +2595,6 @@ let ColorPicker$1 = class ColorPicker {
|
|
|
2694
2595
|
|
|
2695
2596
|
/**
|
|
2696
2597
|
* Wrap given text (last argument) in HTML elements (all preceding arguments).
|
|
2697
|
-
*
|
|
2698
2598
|
* @param {...any} rest - List of tag names followed by inner text.
|
|
2699
2599
|
* @returns An element or a text node.
|
|
2700
2600
|
*/
|
|
@@ -2732,7 +2632,7 @@ let Configurator$1 = class Configurator {
|
|
|
2732
2632
|
defaultContainer,
|
|
2733
2633
|
configureOptions,
|
|
2734
2634
|
pixelRatio = 1,
|
|
2735
|
-
hideOption = () => false
|
|
2635
|
+
hideOption = () => false,
|
|
2736
2636
|
) {
|
|
2737
2637
|
this.parent = parentModule;
|
|
2738
2638
|
this.changedOptions = [];
|
|
@@ -2764,7 +2664,6 @@ let Configurator$1 = class Configurator {
|
|
|
2764
2664
|
/**
|
|
2765
2665
|
* refresh all options.
|
|
2766
2666
|
* Because all modules parse their options by themselves, we just use their options. We copy them here.
|
|
2767
|
-
*
|
|
2768
2667
|
* @param {object} options
|
|
2769
2668
|
*/
|
|
2770
2669
|
setOptions(options) {
|
|
@@ -2827,7 +2726,6 @@ let Configurator$1 = class Configurator {
|
|
|
2827
2726
|
|
|
2828
2727
|
/**
|
|
2829
2728
|
* Create all DOM elements
|
|
2830
|
-
*
|
|
2831
2729
|
* @private
|
|
2832
2730
|
*/
|
|
2833
2731
|
_create() {
|
|
@@ -2873,7 +2771,6 @@ let Configurator$1 = class Configurator {
|
|
|
2873
2771
|
|
|
2874
2772
|
/**
|
|
2875
2773
|
* draw all DOM elements on the screen
|
|
2876
|
-
*
|
|
2877
2774
|
* @private
|
|
2878
2775
|
*/
|
|
2879
2776
|
_push() {
|
|
@@ -2889,7 +2786,6 @@ let Configurator$1 = class Configurator {
|
|
|
2889
2786
|
|
|
2890
2787
|
/**
|
|
2891
2788
|
* delete all DOM elements
|
|
2892
|
-
*
|
|
2893
2789
|
* @private
|
|
2894
2790
|
*/
|
|
2895
2791
|
_clean() {
|
|
@@ -2908,7 +2804,6 @@ let Configurator$1 = class Configurator {
|
|
|
2908
2804
|
|
|
2909
2805
|
/**
|
|
2910
2806
|
* get the value from the actualOptions if it exists
|
|
2911
|
-
*
|
|
2912
2807
|
* @param {Array} path | where to look for the actual option
|
|
2913
2808
|
* @returns {*}
|
|
2914
2809
|
* @private
|
|
@@ -2928,7 +2823,6 @@ let Configurator$1 = class Configurator {
|
|
|
2928
2823
|
|
|
2929
2824
|
/**
|
|
2930
2825
|
* all option elements are wrapped in an item
|
|
2931
|
-
*
|
|
2932
2826
|
* @param {Array} path | where to look for the actual option
|
|
2933
2827
|
* @param {Array.<Element>} domElements
|
|
2934
2828
|
* @returns {number}
|
|
@@ -2950,7 +2844,6 @@ let Configurator$1 = class Configurator {
|
|
|
2950
2844
|
|
|
2951
2845
|
/**
|
|
2952
2846
|
* header for major subjects
|
|
2953
|
-
*
|
|
2954
2847
|
* @param {string} name
|
|
2955
2848
|
* @private
|
|
2956
2849
|
*/
|
|
@@ -2963,7 +2856,6 @@ let Configurator$1 = class Configurator {
|
|
|
2963
2856
|
|
|
2964
2857
|
/**
|
|
2965
2858
|
* make a label, if it is an object label, it gets different styling.
|
|
2966
|
-
*
|
|
2967
2859
|
* @param {string} name
|
|
2968
2860
|
* @param {Array} path | where to look for the actual option
|
|
2969
2861
|
* @param {string} objectLabel
|
|
@@ -2987,7 +2879,6 @@ let Configurator$1 = class Configurator {
|
|
|
2987
2879
|
|
|
2988
2880
|
/**
|
|
2989
2881
|
* make a dropdown list for multiple possible string optoins
|
|
2990
|
-
*
|
|
2991
2882
|
* @param {Array.<number>} arr
|
|
2992
2883
|
* @param {number} value
|
|
2993
2884
|
* @param {Array} path | where to look for the actual option
|
|
@@ -3024,7 +2915,6 @@ let Configurator$1 = class Configurator {
|
|
|
3024
2915
|
|
|
3025
2916
|
/**
|
|
3026
2917
|
* make a range object for numeric options
|
|
3027
|
-
*
|
|
3028
2918
|
* @param {Array.<number>} arr
|
|
3029
2919
|
* @param {number} value
|
|
3030
2920
|
* @param {Array} path | where to look for the actual option
|
|
@@ -3096,7 +2986,6 @@ let Configurator$1 = class Configurator {
|
|
|
3096
2986
|
|
|
3097
2987
|
/**
|
|
3098
2988
|
* make a button object
|
|
3099
|
-
*
|
|
3100
2989
|
* @private
|
|
3101
2990
|
*/
|
|
3102
2991
|
_makeButton() {
|
|
@@ -3125,7 +3014,6 @@ let Configurator$1 = class Configurator {
|
|
|
3125
3014
|
|
|
3126
3015
|
/**
|
|
3127
3016
|
* prepare the popup
|
|
3128
|
-
*
|
|
3129
3017
|
* @param {string} string
|
|
3130
3018
|
* @param {number} index
|
|
3131
3019
|
* @private
|
|
@@ -3150,7 +3038,6 @@ let Configurator$1 = class Configurator {
|
|
|
3150
3038
|
|
|
3151
3039
|
/**
|
|
3152
3040
|
* remove the popup from the dom
|
|
3153
|
-
*
|
|
3154
3041
|
* @private
|
|
3155
3042
|
*/
|
|
3156
3043
|
_removePopup() {
|
|
@@ -3164,7 +3051,6 @@ let Configurator$1 = class Configurator {
|
|
|
3164
3051
|
|
|
3165
3052
|
/**
|
|
3166
3053
|
* Show the popup if it is needed.
|
|
3167
|
-
*
|
|
3168
3054
|
* @private
|
|
3169
3055
|
*/
|
|
3170
3056
|
_showPopupIfNeeded() {
|
|
@@ -3185,7 +3071,6 @@ let Configurator$1 = class Configurator {
|
|
|
3185
3071
|
|
|
3186
3072
|
/**
|
|
3187
3073
|
* make a checkbox for boolean options.
|
|
3188
|
-
*
|
|
3189
3074
|
* @param {number} defaultValue
|
|
3190
3075
|
* @param {number} value
|
|
3191
3076
|
* @param {Array} path | where to look for the actual option
|
|
@@ -3220,7 +3105,6 @@ let Configurator$1 = class Configurator {
|
|
|
3220
3105
|
|
|
3221
3106
|
/**
|
|
3222
3107
|
* make a text input field for string options.
|
|
3223
|
-
*
|
|
3224
3108
|
* @param {number} defaultValue
|
|
3225
3109
|
* @param {number} value
|
|
3226
3110
|
* @param {Array} path | where to look for the actual option
|
|
@@ -3246,7 +3130,6 @@ let Configurator$1 = class Configurator {
|
|
|
3246
3130
|
|
|
3247
3131
|
/**
|
|
3248
3132
|
* make a color field with a color picker for color fields
|
|
3249
|
-
*
|
|
3250
3133
|
* @param {Array.<number>} arr
|
|
3251
3134
|
* @param {number} value
|
|
3252
3135
|
* @param {Array} path | where to look for the actual option
|
|
@@ -3275,7 +3158,6 @@ let Configurator$1 = class Configurator {
|
|
|
3275
3158
|
|
|
3276
3159
|
/**
|
|
3277
3160
|
* used by the color buttons to call the color picker.
|
|
3278
|
-
*
|
|
3279
3161
|
* @param {number} value
|
|
3280
3162
|
* @param {HTMLElement} div
|
|
3281
3163
|
* @param {Array} path | where to look for the actual option
|
|
@@ -3306,10 +3188,9 @@ let Configurator$1 = class Configurator {
|
|
|
3306
3188
|
|
|
3307
3189
|
/**
|
|
3308
3190
|
* parse an object and draw the correct items
|
|
3309
|
-
*
|
|
3310
3191
|
* @param {object} obj
|
|
3311
|
-
* @param {Array} [path
|
|
3312
|
-
* @param {boolean} [checkOnly
|
|
3192
|
+
* @param {Array} [path] | where to look for the actual option
|
|
3193
|
+
* @param {boolean} [checkOnly]
|
|
3313
3194
|
* @returns {boolean}
|
|
3314
3195
|
* @private
|
|
3315
3196
|
*/
|
|
@@ -3383,7 +3264,6 @@ let Configurator$1 = class Configurator {
|
|
|
3383
3264
|
|
|
3384
3265
|
/**
|
|
3385
3266
|
* handle the array type of option
|
|
3386
|
-
*
|
|
3387
3267
|
* @param {Array.<number>} arr
|
|
3388
3268
|
* @param {number} value
|
|
3389
3269
|
* @param {Array} path | where to look for the actual option
|
|
@@ -3410,7 +3290,6 @@ let Configurator$1 = class Configurator {
|
|
|
3410
3290
|
|
|
3411
3291
|
/**
|
|
3412
3292
|
* called to update the network with the new settings.
|
|
3413
|
-
*
|
|
3414
3293
|
* @param {number} value
|
|
3415
3294
|
* @param {Array} path | where to look for the actual option
|
|
3416
3295
|
* @private
|
|
@@ -3469,7 +3348,7 @@ let Configurator$1 = class Configurator {
|
|
|
3469
3348
|
this.optionsContainer.removeChild(this.optionsContainer.firstChild);
|
|
3470
3349
|
}
|
|
3471
3350
|
this.optionsContainer.appendChild(
|
|
3472
|
-
wrapInTag("pre", "const options = " + JSON.stringify(options, null, 2))
|
|
3351
|
+
wrapInTag("pre", "const options = " + JSON.stringify(options, null, 2)),
|
|
3473
3352
|
);
|
|
3474
3353
|
}
|
|
3475
3354
|
|
|
@@ -3483,7 +3362,7 @@ let Configurator$1 = class Configurator {
|
|
|
3483
3362
|
this._constructOptions(
|
|
3484
3363
|
this.changedOptions[i].value,
|
|
3485
3364
|
this.changedOptions[i].path,
|
|
3486
|
-
options
|
|
3365
|
+
options,
|
|
3487
3366
|
);
|
|
3488
3367
|
}
|
|
3489
3368
|
return options;
|
|
@@ -3524,7 +3403,6 @@ let Popup$1 = class Popup {
|
|
|
3524
3403
|
|
|
3525
3404
|
/**
|
|
3526
3405
|
* Set the content for the popup window. This can be HTML code or text.
|
|
3527
|
-
*
|
|
3528
3406
|
* @param {string | Element} content
|
|
3529
3407
|
*/
|
|
3530
3408
|
setText(content) {
|
|
@@ -3542,7 +3420,6 @@ let Popup$1 = class Popup {
|
|
|
3542
3420
|
|
|
3543
3421
|
/**
|
|
3544
3422
|
* Show the popup window
|
|
3545
|
-
*
|
|
3546
3423
|
* @param {boolean} [doShow] Show or hide the window
|
|
3547
3424
|
*/
|
|
3548
3425
|
show(doShow) {
|
|
@@ -3638,7 +3515,6 @@ const VALIDATOR_PRINT_STYLE$1 = "background: #FFeeee; color: #dd0000";
|
|
|
3638
3515
|
let Validator$1 = class Validator {
|
|
3639
3516
|
/**
|
|
3640
3517
|
* Main function to be called
|
|
3641
|
-
*
|
|
3642
3518
|
* @param {object} options
|
|
3643
3519
|
* @param {object} referenceOptions
|
|
3644
3520
|
* @param {object} subObject
|
|
@@ -3658,7 +3534,6 @@ let Validator$1 = class Validator {
|
|
|
3658
3534
|
|
|
3659
3535
|
/**
|
|
3660
3536
|
* Will traverse an object recursively and check every value
|
|
3661
|
-
*
|
|
3662
3537
|
* @param {object} options
|
|
3663
3538
|
* @param {object} referenceOptions
|
|
3664
3539
|
* @param {Array} path | where to look for the actual option
|
|
@@ -3674,7 +3549,6 @@ let Validator$1 = class Validator {
|
|
|
3674
3549
|
|
|
3675
3550
|
/**
|
|
3676
3551
|
* Check every value. If the value is an object, call the parse function on that object.
|
|
3677
|
-
*
|
|
3678
3552
|
* @param {string} option
|
|
3679
3553
|
* @param {object} options
|
|
3680
3554
|
* @param {object} referenceOptions
|
|
@@ -3720,7 +3594,7 @@ let Validator$1 = class Validator {
|
|
|
3720
3594
|
referenceOptions,
|
|
3721
3595
|
referenceOption,
|
|
3722
3596
|
refOptionObj,
|
|
3723
|
-
path
|
|
3597
|
+
path,
|
|
3724
3598
|
);
|
|
3725
3599
|
}
|
|
3726
3600
|
|
|
@@ -3740,12 +3614,12 @@ let Validator$1 = class Validator {
|
|
|
3740
3614
|
referenceOptions,
|
|
3741
3615
|
referenceOption,
|
|
3742
3616
|
refOptionObj,
|
|
3743
|
-
path
|
|
3617
|
+
path,
|
|
3744
3618
|
) {
|
|
3745
3619
|
const log = function (message) {
|
|
3746
3620
|
console.error(
|
|
3747
3621
|
"%c" + message + Validator.printLocation(path, option),
|
|
3748
|
-
VALIDATOR_PRINT_STYLE$1
|
|
3622
|
+
VALIDATOR_PRINT_STYLE$1,
|
|
3749
3623
|
);
|
|
3750
3624
|
};
|
|
3751
3625
|
|
|
@@ -3766,7 +3640,7 @@ let Validator$1 = class Validator {
|
|
|
3766
3640
|
Validator.print(refOptionType) +
|
|
3767
3641
|
' not "' +
|
|
3768
3642
|
options[option] +
|
|
3769
|
-
'". '
|
|
3643
|
+
'". ',
|
|
3770
3644
|
);
|
|
3771
3645
|
errorFound = true;
|
|
3772
3646
|
} else if (optionType === "object" && referenceOption !== "__any__") {
|
|
@@ -3774,7 +3648,7 @@ let Validator$1 = class Validator {
|
|
|
3774
3648
|
Validator.parse(
|
|
3775
3649
|
options[option],
|
|
3776
3650
|
referenceOptions[referenceOption],
|
|
3777
|
-
path
|
|
3651
|
+
path,
|
|
3778
3652
|
);
|
|
3779
3653
|
}
|
|
3780
3654
|
} else if (refOptionObj["any"] === undefined) {
|
|
@@ -3788,7 +3662,7 @@ let Validator$1 = class Validator {
|
|
|
3788
3662
|
optionType +
|
|
3789
3663
|
'] "' +
|
|
3790
3664
|
options[option] +
|
|
3791
|
-
'"'
|
|
3665
|
+
'"',
|
|
3792
3666
|
);
|
|
3793
3667
|
errorFound = true;
|
|
3794
3668
|
}
|
|
@@ -3873,7 +3747,7 @@ let Validator$1 = class Validator {
|
|
|
3873
3747
|
Validator.printLocation(
|
|
3874
3748
|
globalSearch.path,
|
|
3875
3749
|
globalSearch.closestMatch,
|
|
3876
|
-
""
|
|
3750
|
+
"",
|
|
3877
3751
|
);
|
|
3878
3752
|
} else if (localSearch.distance <= localSearchThreshold) {
|
|
3879
3753
|
msg =
|
|
@@ -3890,18 +3764,17 @@ let Validator$1 = class Validator {
|
|
|
3890
3764
|
|
|
3891
3765
|
console.error(
|
|
3892
3766
|
'%cUnknown option detected: "' + option + '"' + msg,
|
|
3893
|
-
VALIDATOR_PRINT_STYLE$1
|
|
3767
|
+
VALIDATOR_PRINT_STYLE$1,
|
|
3894
3768
|
);
|
|
3895
3769
|
errorFound = true;
|
|
3896
3770
|
}
|
|
3897
3771
|
|
|
3898
3772
|
/**
|
|
3899
3773
|
* traverse the options in search for a match.
|
|
3900
|
-
*
|
|
3901
3774
|
* @param {string} option
|
|
3902
3775
|
* @param {object} options
|
|
3903
3776
|
* @param {Array} path | where to look for the actual option
|
|
3904
|
-
* @param {boolean} [recursive
|
|
3777
|
+
* @param {boolean} [recursive]
|
|
3905
3778
|
* @returns {{closestMatch: string, path: Array, distance: number}}
|
|
3906
3779
|
* @static
|
|
3907
3780
|
*/
|
|
@@ -3917,7 +3790,7 @@ let Validator$1 = class Validator {
|
|
|
3917
3790
|
const result = Validator.findInOptions(
|
|
3918
3791
|
option,
|
|
3919
3792
|
options[op],
|
|
3920
|
-
copyAndExtendArray(path, op)
|
|
3793
|
+
copyAndExtendArray(path, op),
|
|
3921
3794
|
);
|
|
3922
3795
|
if (min > result.distance) {
|
|
3923
3796
|
closestMatch = result.closestMatch;
|
|
@@ -3986,16 +3859,15 @@ let Validator$1 = class Validator {
|
|
|
3986
3859
|
|
|
3987
3860
|
/**
|
|
3988
3861
|
* Compute the edit distance between the two given strings
|
|
3989
|
-
*
|
|
3990
|
-
*
|
|
3991
|
-
* Copyright (c) 2011 Andrei Mackenzie
|
|
3862
|
+
* http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript
|
|
3992
3863
|
*
|
|
3993
|
-
*
|
|
3864
|
+
* Copyright (c) 2011 Andrei Mackenzie
|
|
3994
3865
|
*
|
|
3995
|
-
*
|
|
3866
|
+
* 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:
|
|
3996
3867
|
*
|
|
3997
|
-
*
|
|
3868
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
3998
3869
|
*
|
|
3870
|
+
* 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.
|
|
3999
3871
|
* @param {string} a
|
|
4000
3872
|
* @param {string} b
|
|
4001
3873
|
* @returns {Array.<Array.<number>>}}
|
|
@@ -4029,8 +3901,8 @@ let Validator$1 = class Validator {
|
|
|
4029
3901
|
matrix[i - 1][j - 1] + 1, // substitution
|
|
4030
3902
|
Math.min(
|
|
4031
3903
|
matrix[i][j - 1] + 1, // insertion
|
|
4032
|
-
matrix[i - 1][j] + 1
|
|
4033
|
-
)
|
|
3904
|
+
matrix[i - 1][j] + 1,
|
|
3905
|
+
),
|
|
4034
3906
|
); // deletion
|
|
4035
3907
|
}
|
|
4036
3908
|
}
|
|
@@ -4040,12 +3912,12 @@ let Validator$1 = class Validator {
|
|
|
4040
3912
|
}
|
|
4041
3913
|
};
|
|
4042
3914
|
|
|
4043
|
-
const Activator = Activator$1;
|
|
4044
|
-
const ColorPicker = ColorPicker$1;
|
|
4045
|
-
const Configurator = Configurator$1;
|
|
4046
|
-
const Hammer = Hammer$1;
|
|
4047
|
-
const Popup = Popup$1;
|
|
4048
|
-
const VALIDATOR_PRINT_STYLE = VALIDATOR_PRINT_STYLE$1;
|
|
3915
|
+
const Activator = Activator$1;
|
|
3916
|
+
const ColorPicker = ColorPicker$1;
|
|
3917
|
+
const Configurator = Configurator$1;
|
|
3918
|
+
const Hammer = Hammer$1;
|
|
3919
|
+
const Popup = Popup$1;
|
|
3920
|
+
const VALIDATOR_PRINT_STYLE = VALIDATOR_PRINT_STYLE$1;
|
|
4049
3921
|
const Validator = Validator$1;
|
|
4050
3922
|
|
|
4051
3923
|
export { Activator, Alea, ColorPicker, Configurator, DELETE, HSVToHex, HSVToRGB, Hammer, Popup, RGBToHSV, RGBToHex, VALIDATOR_PRINT_STYLE, Validator, addClassName, addCssText, binarySearchCustom, binarySearchValue, bridgeObject, copyAndExtendArray, copyArray, deepExtend, deepObjectAssign, easingFunctions, equalArray, extend, fillIfDefined, forEach, getAbsoluteLeft, getAbsoluteRight, getAbsoluteTop, getScrollBarWidth, getTarget, getType, hasParent, hexToHSV, hexToRGB, insertSort, isDate, isNumber, isObject, isString, isValidHex, isValidRGB, isValidRGBA, mergeOptions, option, overrideOpacity, parseColor, preventDefault, pureDeepObjectAssign, recursiveDOMDelete, removeClassName, removeCssText, selectiveBridgeObject, selectiveDeepExtend, selectiveExtend, selectiveNotDeepExtend, throttle, toArray, topMost, updateProperty };
|