@oscarpalmer/tabela 0.8.0 → 0.9.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/dist/managers/column.manager.js +6 -1
- package/dist/managers/data.manager.js +5 -3
- package/dist/managers/event.manager.js +1 -1
- package/dist/managers/filter.manager.js +92 -0
- package/dist/managers/row.manager.js +9 -2
- package/dist/managers/sort.manager.js +17 -6
- package/dist/managers/virtualization.manager.js +2 -0
- package/dist/models/filter.model.js +0 -0
- package/dist/tabela.full.js +623 -13
- package/dist/tabela.js +8 -0
- package/package.json +1 -1
- package/src/managers/column.manager.ts +8 -0
- package/src/managers/data.manager.ts +8 -4
- package/src/managers/event.manager.ts +2 -2
- package/src/managers/filter.manager.ts +154 -0
- package/src/managers/row.manager.ts +16 -2
- package/src/managers/sort.manager.ts +35 -16
- package/src/managers/virtualization.manager.ts +4 -1
- package/src/models/filter.model.ts +17 -0
- package/src/models/sort.model.ts +1 -1
- package/src/models/tabela.model.ts +11 -0
- package/src/tabela.ts +16 -1
- package/types/managers/data.manager.d.ts +1 -1
- package/types/managers/filter.manager.d.ts +19 -0
- package/types/managers/sort.manager.d.ts +5 -2
- package/types/managers/virtualization.manager.d.ts +1 -1
- package/types/models/filter.model.d.ts +6 -0
- package/types/models/sort.model.d.ts +1 -1
- package/types/models/tabela.model.d.ts +10 -0
- package/types/tabela.d.ts +2 -1
package/dist/tabela.full.js
CHANGED
|
@@ -383,6 +383,8 @@ var ColumnManager = class {
|
|
|
383
383
|
this.set(columns);
|
|
384
384
|
}
|
|
385
385
|
destroy() {
|
|
386
|
+
const { length } = this.items;
|
|
387
|
+
for (let index = 0; index < length; index += 1) this.items[index].destroy();
|
|
386
388
|
this.items.length = 0;
|
|
387
389
|
}
|
|
388
390
|
remove(value) {
|
|
@@ -392,7 +394,10 @@ var ColumnManager = class {
|
|
|
392
394
|
if (length === 0) return;
|
|
393
395
|
for (let fieldIndex = 0; fieldIndex < length; fieldIndex += 1) {
|
|
394
396
|
const itemIndex = items.findIndex((component) => component.options.field === fields[fieldIndex]);
|
|
395
|
-
if (itemIndex > -1)
|
|
397
|
+
if (itemIndex > -1) {
|
|
398
|
+
items[itemIndex].destroy();
|
|
399
|
+
items.splice(itemIndex, 1);
|
|
400
|
+
}
|
|
396
401
|
}
|
|
397
402
|
components.header.update(items);
|
|
398
403
|
components.footer.update(items);
|
|
@@ -498,6 +503,90 @@ function isPlainObject(value) {
|
|
|
498
503
|
const prototype = Object.getPrototypeOf(value);
|
|
499
504
|
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
500
505
|
}
|
|
506
|
+
/**
|
|
507
|
+
* Is the value a typed array?
|
|
508
|
+
* @param value Value to check
|
|
509
|
+
* @returns `true` if the value is a typed array, otherwise `false`
|
|
510
|
+
*/
|
|
511
|
+
function isTypedArray(value) {
|
|
512
|
+
TYPED_ARRAYS ??= new Set([
|
|
513
|
+
Int8Array,
|
|
514
|
+
Uint8Array,
|
|
515
|
+
Uint8ClampedArray,
|
|
516
|
+
Int16Array,
|
|
517
|
+
Uint16Array,
|
|
518
|
+
Int32Array,
|
|
519
|
+
Uint32Array,
|
|
520
|
+
Float32Array,
|
|
521
|
+
Float64Array,
|
|
522
|
+
BigInt64Array,
|
|
523
|
+
BigUint64Array
|
|
524
|
+
]);
|
|
525
|
+
return TYPED_ARRAYS.has(value?.constructor);
|
|
526
|
+
}
|
|
527
|
+
var TYPED_ARRAYS;
|
|
528
|
+
/**
|
|
529
|
+
* Chunk an array into smaller arrays
|
|
530
|
+
* @param array Array to chunk
|
|
531
|
+
* @param size Size of each chunk _(minimum is `1`, maximum is `5000`; defaults to `5000`)_
|
|
532
|
+
* @returns Array of arrays
|
|
533
|
+
*/
|
|
534
|
+
function chunk(array, size) {
|
|
535
|
+
if (!Array.isArray(array)) return [];
|
|
536
|
+
if (array.length === 0) return [];
|
|
537
|
+
const { length } = array;
|
|
538
|
+
const actualSize = typeof size === "number" && size > 0 && size <= MAX_SIZE ? size : MAX_SIZE;
|
|
539
|
+
if (length <= actualSize) return [array];
|
|
540
|
+
const chunks = [];
|
|
541
|
+
let index = 0;
|
|
542
|
+
while (index < length) {
|
|
543
|
+
chunks.push(array.slice(index, index + actualSize));
|
|
544
|
+
index += actualSize;
|
|
545
|
+
}
|
|
546
|
+
return chunks;
|
|
547
|
+
}
|
|
548
|
+
var MAX_SIZE = 5e3;
|
|
549
|
+
function compact(array, strict) {
|
|
550
|
+
if (!Array.isArray(array)) return [];
|
|
551
|
+
if (strict === true) return array.filter(Boolean);
|
|
552
|
+
const { length } = array;
|
|
553
|
+
const compacted = [];
|
|
554
|
+
for (let index = 0; index < length; index += 1) {
|
|
555
|
+
const item = array[index];
|
|
556
|
+
if (item != null) compacted.push(item);
|
|
557
|
+
}
|
|
558
|
+
return compacted;
|
|
559
|
+
}
|
|
560
|
+
function insertChunkedValues(type, array, items, start, deleteCount) {
|
|
561
|
+
const actualDeleteCount = deleteCount < 0 ? 0 : deleteCount;
|
|
562
|
+
const actualStart = Math.min(Math.max(0, start), array.length);
|
|
563
|
+
const chunked = chunk(items);
|
|
564
|
+
const lastIndex = chunked.length - 1;
|
|
565
|
+
let index = Number(chunked.length);
|
|
566
|
+
let returned;
|
|
567
|
+
while (index > 0) {
|
|
568
|
+
index -= 1;
|
|
569
|
+
const spliced = array.splice(actualStart, index === lastIndex ? actualDeleteCount : 0, ...chunked[index]);
|
|
570
|
+
if (returned == null) returned = spliced;
|
|
571
|
+
else returned.push(...spliced);
|
|
572
|
+
}
|
|
573
|
+
if (type === "insert") return array;
|
|
574
|
+
return type === "splice" ? returned : array.length;
|
|
575
|
+
}
|
|
576
|
+
function insertValues(type, array, items, start, deleteCount) {
|
|
577
|
+
const spliceArray = type === "insert" || type === "splice";
|
|
578
|
+
if (!Array.isArray(array) || typeof start !== "number" || !Array.isArray(items) || items.length === 0) return spliceArray ? [] : 0;
|
|
579
|
+
return insertChunkedValues(type, array, items, start, spliceArray ? deleteCount : 0);
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Push items into an array _(at the end)_
|
|
583
|
+
* @param array Original array
|
|
584
|
+
* @param pushed Pushed items
|
|
585
|
+
* @returns New length of the array
|
|
586
|
+
*/
|
|
587
|
+
function push(array, pushed) {
|
|
588
|
+
return insertValues("push", array, pushed, array.length, 0);
|
|
589
|
+
}
|
|
501
590
|
function aggregate(type, array, key) {
|
|
502
591
|
const length = Array.isArray(array) ? array.length : 0;
|
|
503
592
|
if (length === 0) return {
|
|
@@ -556,6 +645,15 @@ function getString(value) {
|
|
|
556
645
|
return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
|
|
557
646
|
}
|
|
558
647
|
/**
|
|
648
|
+
* Join an array of values into a string
|
|
649
|
+
* @param value Array of values
|
|
650
|
+
* @param delimiter Delimiter to use between values
|
|
651
|
+
* @returns Joined string
|
|
652
|
+
*/
|
|
653
|
+
function join(value, delimiter) {
|
|
654
|
+
return compact(value).map(getString).join(typeof delimiter === "string" ? delimiter : "");
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
559
657
|
* Split a string into words _(and other readable parts)_
|
|
560
658
|
* @param value Original string
|
|
561
659
|
* @returns Array of words found in the string
|
|
@@ -659,7 +757,7 @@ function compareSymbols(first, second) {
|
|
|
659
757
|
}
|
|
660
758
|
function compareValue(first, second, compareStrings) {
|
|
661
759
|
const firstType = typeof first;
|
|
662
|
-
if (firstType === typeof second && firstType in comparators) return comparators[firstType](first, second);
|
|
760
|
+
if (firstType === typeof second && firstType in comparators$1) return comparators$1[firstType](first, second);
|
|
663
761
|
if (first instanceof Date && second instanceof Date) return compareNumbers(first.getTime(), second.getTime());
|
|
664
762
|
return compare.handlers.handle(first, second, compareStrings);
|
|
665
763
|
}
|
|
@@ -667,7 +765,7 @@ function getComparisonParts(value) {
|
|
|
667
765
|
if (Array.isArray(value)) return value;
|
|
668
766
|
return typeof value === "object" ? [value] : words(getString(value));
|
|
669
767
|
}
|
|
670
|
-
var comparators = {
|
|
768
|
+
var comparators$1 = {
|
|
671
769
|
bigint: compareNumbers,
|
|
672
770
|
boolean: compareNumbers,
|
|
673
771
|
number: compareNumbers,
|
|
@@ -780,7 +878,7 @@ var DataManager = class {
|
|
|
780
878
|
}
|
|
781
879
|
async add(data, render) {
|
|
782
880
|
const { field, values } = this;
|
|
783
|
-
values.objects.array
|
|
881
|
+
push(values.objects.array, data);
|
|
784
882
|
values.objects.mapped = toMap(values.objects.array, field);
|
|
785
883
|
if (render) this.render();
|
|
786
884
|
}
|
|
@@ -793,6 +891,7 @@ var DataManager = class {
|
|
|
793
891
|
values.keys.active = void 0;
|
|
794
892
|
values.keys.original.length = 0;
|
|
795
893
|
values.objects.array.length = 0;
|
|
894
|
+
this.handlers = void 0;
|
|
796
895
|
}
|
|
797
896
|
get(active) {
|
|
798
897
|
const { values } = this;
|
|
@@ -816,7 +915,8 @@ var DataManager = class {
|
|
|
816
915
|
render() {
|
|
817
916
|
const { field, managers, values } = this;
|
|
818
917
|
values.keys.original = sort(values.objects.array.map((item) => item[field]));
|
|
819
|
-
if (managers.
|
|
918
|
+
if (Object.keys(managers.filter.items).length > 0) managers.filter.filter();
|
|
919
|
+
else if (managers.sort.items.length > 0) managers.sort.sort();
|
|
820
920
|
else managers.virtualization.update(true);
|
|
821
921
|
}
|
|
822
922
|
set(data) {
|
|
@@ -1158,7 +1258,7 @@ var EventManager = class {
|
|
|
1158
1258
|
listener;
|
|
1159
1259
|
constructor(managers, element) {
|
|
1160
1260
|
this.managers = managers;
|
|
1161
|
-
on(element, "click", (event) => {
|
|
1261
|
+
this.listener = on(element, "click", (event) => {
|
|
1162
1262
|
this.onClick(event);
|
|
1163
1263
|
}, { passive: false });
|
|
1164
1264
|
}
|
|
@@ -1181,6 +1281,489 @@ var EventManager = class {
|
|
|
1181
1281
|
if (field != null) managers.sort.toggle(event, field, direction);
|
|
1182
1282
|
}
|
|
1183
1283
|
};
|
|
1284
|
+
/**
|
|
1285
|
+
* Clamp a number between a minimum and maximum value
|
|
1286
|
+
* @param value Value to clamp
|
|
1287
|
+
* @param minimum Minimum value
|
|
1288
|
+
* @param maximum Maximum value
|
|
1289
|
+
* @param loop If `true`, the value will loop around when smaller than the minimum or larger than the maximum _(defaults to `false`)_
|
|
1290
|
+
* @returns Clamped value
|
|
1291
|
+
*/
|
|
1292
|
+
function clamp(value, minimum, maximum, loop) {
|
|
1293
|
+
if (![
|
|
1294
|
+
value,
|
|
1295
|
+
minimum,
|
|
1296
|
+
maximum
|
|
1297
|
+
].every(isNumber)) return NaN;
|
|
1298
|
+
if (value < minimum) return loop === true ? maximum : minimum;
|
|
1299
|
+
return value > maximum ? loop === true ? minimum : maximum : value;
|
|
1300
|
+
}
|
|
1301
|
+
/**
|
|
1302
|
+
* Get the number value from an unknown value _(based on Lodash)_
|
|
1303
|
+
* @param value Original value
|
|
1304
|
+
* @returns Original value as a number, or `NaN` if the value is unable to be parsed
|
|
1305
|
+
*/
|
|
1306
|
+
function getNumber(value) {
|
|
1307
|
+
if (typeof value === "number") return value;
|
|
1308
|
+
if (typeof value === "bigint" || typeof value === "boolean") return Number(value);
|
|
1309
|
+
if (value == null || typeof value === "symbol") return NaN;
|
|
1310
|
+
if (typeof value === "function") return getNumber(value());
|
|
1311
|
+
let parsed = value.valueOf();
|
|
1312
|
+
if (typeof parsed === "object") parsed = parsed.toString();
|
|
1313
|
+
if (typeof parsed !== "string") return getNumber(parsed);
|
|
1314
|
+
const trimmed = parsed.trim();
|
|
1315
|
+
if (trimmed.length === 0) return NaN;
|
|
1316
|
+
if (EXPRESSION_ZEROISH.test(parsed)) return 0;
|
|
1317
|
+
const isBinary = EXPRESSION_BINARY.test(trimmed);
|
|
1318
|
+
if (isBinary || EXPRESSION_OCTAL.test(trimmed)) return Number.parseInt(trimmed.slice(2), isBinary ? 2 : OCTAL_VALUE);
|
|
1319
|
+
return Number(EXPRESSION_HEX.test(trimmed) ? trimmed : trimmed.replace(EXPRESSION_UNDERSCORE, ""));
|
|
1320
|
+
}
|
|
1321
|
+
var EXPRESSION_BINARY = /^0b[01]+$/i;
|
|
1322
|
+
var EXPRESSION_HEX = /^0x[0-9a-f]+$/i;
|
|
1323
|
+
var EXPRESSION_OCTAL = /^0o[0-7]+$/i;
|
|
1324
|
+
var EXPRESSION_UNDERSCORE = /_/g;
|
|
1325
|
+
var EXPRESSION_ZEROISH = /^\s*0+\s*$/;
|
|
1326
|
+
var OCTAL_VALUE = 8;
|
|
1327
|
+
function getSizedMaximum(first, second) {
|
|
1328
|
+
let actual;
|
|
1329
|
+
if (typeof first === "number") actual = first;
|
|
1330
|
+
else actual = typeof second === "number" ? second : MAXIMUM_DEFAULT;
|
|
1331
|
+
return clamp(actual, 1, MAXIMUM_ABSOLUTE);
|
|
1332
|
+
}
|
|
1333
|
+
var MAXIMUM_ABSOLUTE = 16777216;
|
|
1334
|
+
var MAXIMUM_DEFAULT = 1048576;
|
|
1335
|
+
/**
|
|
1336
|
+
* A Map with a maximum size
|
|
1337
|
+
*
|
|
1338
|
+
* Behavior is similar to a _LRU_-cache, where the least recently used entries are removed
|
|
1339
|
+
*/
|
|
1340
|
+
var SizedMap = class extends Map {
|
|
1341
|
+
/**
|
|
1342
|
+
* The maximum size of the Map
|
|
1343
|
+
*/
|
|
1344
|
+
#maximumSize;
|
|
1345
|
+
/**
|
|
1346
|
+
* Is the Map full?
|
|
1347
|
+
*/
|
|
1348
|
+
get full() {
|
|
1349
|
+
return this.size >= this.#maximumSize;
|
|
1350
|
+
}
|
|
1351
|
+
get maximum() {
|
|
1352
|
+
return this.#maximumSize;
|
|
1353
|
+
}
|
|
1354
|
+
constructor(first, second) {
|
|
1355
|
+
const maximum = getSizedMaximum(first, second);
|
|
1356
|
+
super();
|
|
1357
|
+
this.#maximumSize = maximum;
|
|
1358
|
+
if (Array.isArray(first)) {
|
|
1359
|
+
const { length } = first;
|
|
1360
|
+
if (length <= maximum) for (let index = 0; index < length; index += 1) this.set(...first[index]);
|
|
1361
|
+
else for (let index = 0; index < maximum; index += 1) this.set(...first[length - maximum + index]);
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
/**
|
|
1365
|
+
* @inheritdoc
|
|
1366
|
+
*/
|
|
1367
|
+
get(key) {
|
|
1368
|
+
const value = super.get(key);
|
|
1369
|
+
if (value !== void 0 || this.has(key)) this.set(key, value);
|
|
1370
|
+
return value;
|
|
1371
|
+
}
|
|
1372
|
+
/**
|
|
1373
|
+
* @inheritdoc
|
|
1374
|
+
*/
|
|
1375
|
+
set(key, value) {
|
|
1376
|
+
if (this.has(key)) this.delete(key);
|
|
1377
|
+
else if (this.size >= this.#maximumSize) this.delete(this.keys().next().value);
|
|
1378
|
+
return super.set(key, value);
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
var Memoized = class {
|
|
1382
|
+
#state;
|
|
1383
|
+
/**
|
|
1384
|
+
* Maximum cache size
|
|
1385
|
+
*/
|
|
1386
|
+
get maximum() {
|
|
1387
|
+
return this.#state.cache?.maximum ?? NaN;
|
|
1388
|
+
}
|
|
1389
|
+
/**
|
|
1390
|
+
* Current cache size
|
|
1391
|
+
*/
|
|
1392
|
+
get size() {
|
|
1393
|
+
return this.#state.cache?.size ?? NaN;
|
|
1394
|
+
}
|
|
1395
|
+
constructor(callback, options) {
|
|
1396
|
+
const cache = new SizedMap(options.cacheSize);
|
|
1397
|
+
const getter = (...parameters) => {
|
|
1398
|
+
const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join(parameters.map(getString), "_"));
|
|
1399
|
+
if (cache.has(key)) return cache.get(key);
|
|
1400
|
+
const value = callback(...parameters);
|
|
1401
|
+
cache.set(key, value);
|
|
1402
|
+
return value;
|
|
1403
|
+
};
|
|
1404
|
+
this.#state = {
|
|
1405
|
+
cache,
|
|
1406
|
+
getter
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
/**
|
|
1410
|
+
* Clear the cache
|
|
1411
|
+
*/
|
|
1412
|
+
clear() {
|
|
1413
|
+
this.#state.cache?.clear();
|
|
1414
|
+
}
|
|
1415
|
+
/**
|
|
1416
|
+
* Delete a result from the cache
|
|
1417
|
+
* @param key Key to delete
|
|
1418
|
+
* @returns `true` if the key existed and was removed, otherwise `false`
|
|
1419
|
+
*/
|
|
1420
|
+
delete(key) {
|
|
1421
|
+
return this.#state.cache?.delete(key) ?? false;
|
|
1422
|
+
}
|
|
1423
|
+
/**
|
|
1424
|
+
* Destroy the instance _(clearing its cache and removing its callback)_
|
|
1425
|
+
*/
|
|
1426
|
+
destroy() {
|
|
1427
|
+
this.#state.cache?.clear();
|
|
1428
|
+
this.#state.cache = void 0;
|
|
1429
|
+
this.#state.getter = void 0;
|
|
1430
|
+
}
|
|
1431
|
+
/**
|
|
1432
|
+
* Get a result from the cache
|
|
1433
|
+
* @param key Key to get
|
|
1434
|
+
* @returns Cached result or `undefined` if it does not exist
|
|
1435
|
+
*/
|
|
1436
|
+
get(key) {
|
|
1437
|
+
return this.#state.cache?.get(key);
|
|
1438
|
+
}
|
|
1439
|
+
/**
|
|
1440
|
+
* Does the result exist?
|
|
1441
|
+
* @param key Key to check
|
|
1442
|
+
* @returns `true` if the result exists, otherwise `false`
|
|
1443
|
+
*/
|
|
1444
|
+
has(key) {
|
|
1445
|
+
return this.#state.cache?.has(key) ?? false;
|
|
1446
|
+
}
|
|
1447
|
+
/**
|
|
1448
|
+
* Run the callback with the provided parameters
|
|
1449
|
+
* @param parameters Parameters to pass to the callback
|
|
1450
|
+
* @returns Cached or computed _(then cached)_ result
|
|
1451
|
+
*/
|
|
1452
|
+
run(...parameters) {
|
|
1453
|
+
if (this.#state.cache == null || this.#state.getter == null) throw new Error("The Memoized instance has been destroyed");
|
|
1454
|
+
return this.#state.getter(...parameters);
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
function getMemoizationOptions(input) {
|
|
1458
|
+
const { cacheKey, cacheSize } = isPlainObject(input) ? input : {};
|
|
1459
|
+
return {
|
|
1460
|
+
cacheKey: typeof cacheKey === "function" ? cacheKey : void 0,
|
|
1461
|
+
cacheSize: typeof cacheSize === "number" && cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE
|
|
1462
|
+
};
|
|
1463
|
+
}
|
|
1464
|
+
/**
|
|
1465
|
+
* Memoize a function, caching and retrieving results based on the first parameter
|
|
1466
|
+
* @param callback Callback to memoize
|
|
1467
|
+
* @param options Memoization options
|
|
1468
|
+
* @returns Memoized instance
|
|
1469
|
+
*/
|
|
1470
|
+
function memoize(callback, options) {
|
|
1471
|
+
return new Memoized(callback, getMemoizationOptions(options));
|
|
1472
|
+
}
|
|
1473
|
+
var DEFAULT_CACHE_SIZE = 1024;
|
|
1474
|
+
/**
|
|
1475
|
+
* Check if a string ends with a specified substring
|
|
1476
|
+
* @param haystack String to look in
|
|
1477
|
+
* @param needle String to look for
|
|
1478
|
+
* @param ignoreCase Ignore case when matching? _(defaults to `false`)_
|
|
1479
|
+
* @returns `true` if the string ends with the given substring, otherwise `false`
|
|
1480
|
+
*/
|
|
1481
|
+
function endsWith(haystack, needle, ignoreCase) {
|
|
1482
|
+
return match("endsWith", haystack, needle, ignoreCase === true);
|
|
1483
|
+
}
|
|
1484
|
+
/**
|
|
1485
|
+
* Check if a string includes a specified substring
|
|
1486
|
+
* @param haystack String to look in
|
|
1487
|
+
* @param needle String to look for
|
|
1488
|
+
* @param ignoreCase Ignore case when matching? _(defaults to `false`)_
|
|
1489
|
+
* @returns `true` if the string includes the given substring, otherwise `false`
|
|
1490
|
+
*/
|
|
1491
|
+
function includes(haystack, needle, ignoreCase) {
|
|
1492
|
+
return match("includes", haystack, needle, ignoreCase === true);
|
|
1493
|
+
}
|
|
1494
|
+
function match(type, haystack, needle, ignoreCase) {
|
|
1495
|
+
if (typeof haystack !== "string" || typeof needle !== "string") return false;
|
|
1496
|
+
matchMemoizers[type] ??= memoize(matchCallback.bind(type));
|
|
1497
|
+
return matchMemoizers[type].run(haystack, needle, ignoreCase);
|
|
1498
|
+
}
|
|
1499
|
+
function matchCallback(haystack, needle, ignoreCase) {
|
|
1500
|
+
return (ignoreCase ? haystack.toLocaleLowerCase() : haystack)[this](ignoreCase ? needle.toLocaleLowerCase() : needle);
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
* Check if a string starts with a specified substring
|
|
1504
|
+
* @param haystack String to look in
|
|
1505
|
+
* @param needle String to look for
|
|
1506
|
+
* @param ignoreCase Ignore case when matching? _(defaults to `false`)_
|
|
1507
|
+
* @returns `true` if the string starts with the given substring, otherwise `false`
|
|
1508
|
+
*/
|
|
1509
|
+
function startsWith(haystack, needle, ignoreCase) {
|
|
1510
|
+
return match("startsWith", haystack, needle, ignoreCase === true);
|
|
1511
|
+
}
|
|
1512
|
+
var matchMemoizers = {};
|
|
1513
|
+
function equal(first, second, options) {
|
|
1514
|
+
return equalValue(first, second, getEqualOptions(options));
|
|
1515
|
+
}
|
|
1516
|
+
equal.handlers = getCompareHandlers(equal, { callback: Object.is });
|
|
1517
|
+
equal.initialize = initializeEqualizer;
|
|
1518
|
+
equal.register = registerEqualizer;
|
|
1519
|
+
equal.unregister = unregisterEqualizer;
|
|
1520
|
+
function equalArray(first, second, options) {
|
|
1521
|
+
const { length } = first;
|
|
1522
|
+
if (length !== second.length) return false;
|
|
1523
|
+
let offset = 0;
|
|
1524
|
+
if (length >= ARRAY_THRESHOLD) {
|
|
1525
|
+
offset = Math.round(length / ARRAY_PEEK_PERCENTAGE);
|
|
1526
|
+
offset = offset > ARRAY_THRESHOLD ? ARRAY_THRESHOLD : offset;
|
|
1527
|
+
for (let index = 0; index < offset; index += 1) if (!(equalValue(first[index], second[index], options) && equalValue(first[length - index - 1], second[length - index - 1], options))) return false;
|
|
1528
|
+
}
|
|
1529
|
+
const firstChunks = chunk(first.slice(offset, length - offset), ARRAY_THRESHOLD);
|
|
1530
|
+
const secondChunks = chunk(second.slice(offset, length - offset), ARRAY_THRESHOLD);
|
|
1531
|
+
const chunksLength = firstChunks.length;
|
|
1532
|
+
for (let chunkIndex = 0; chunkIndex < chunksLength; chunkIndex += 1) {
|
|
1533
|
+
const firstChunk = firstChunks[chunkIndex];
|
|
1534
|
+
const secondChunk = secondChunks[chunkIndex];
|
|
1535
|
+
const chunkLength = firstChunk.length;
|
|
1536
|
+
for (let index = 0; index < chunkLength; index += 1) if (!equalValue(firstChunk[index], secondChunk[index], options)) return false;
|
|
1537
|
+
}
|
|
1538
|
+
return true;
|
|
1539
|
+
}
|
|
1540
|
+
function equalArrayBuffer(first, second, options) {
|
|
1541
|
+
return first.byteLength === second.byteLength ? equalArray(new Uint8Array(first), new Uint8Array(second), options) : false;
|
|
1542
|
+
}
|
|
1543
|
+
function equalDataView(first, second, options) {
|
|
1544
|
+
return first.byteOffset === second.byteOffset ? equalArrayBuffer(first.buffer, second.buffer, options) : false;
|
|
1545
|
+
}
|
|
1546
|
+
function equalMap(first, second, options) {
|
|
1547
|
+
const { size } = first;
|
|
1548
|
+
if (size !== second.size) return false;
|
|
1549
|
+
const firstKeys = [...first.keys()];
|
|
1550
|
+
const secondKeys = [...second.keys()];
|
|
1551
|
+
if (firstKeys.some((key) => !secondKeys.includes(key))) return false;
|
|
1552
|
+
for (let index = 0; index < size; index += 1) {
|
|
1553
|
+
const key = firstKeys[index];
|
|
1554
|
+
if (!equalValue(first.get(key), second.get(key), options)) return false;
|
|
1555
|
+
}
|
|
1556
|
+
return true;
|
|
1557
|
+
}
|
|
1558
|
+
function equalPlainObject(first, second, options) {
|
|
1559
|
+
let firstKeys = [...Object.keys(first), ...Object.getOwnPropertySymbols(first)];
|
|
1560
|
+
let secondKeys = [...Object.keys(second), ...Object.getOwnPropertySymbols(second)];
|
|
1561
|
+
if (options.ignoreKeys.enabled || options.ignoreExpressions.enabled) {
|
|
1562
|
+
firstKeys = firstKeys.filter((key) => filterKey(key, options));
|
|
1563
|
+
secondKeys = secondKeys.filter((key) => filterKey(key, options));
|
|
1564
|
+
}
|
|
1565
|
+
const { length } = firstKeys;
|
|
1566
|
+
if (length !== secondKeys.length || firstKeys.some((key) => !secondKeys.includes(key))) return false;
|
|
1567
|
+
for (let index = 0; index < length; index += 1) {
|
|
1568
|
+
const key = firstKeys[index];
|
|
1569
|
+
if (!equalValue(first[key], second[key], options)) return false;
|
|
1570
|
+
}
|
|
1571
|
+
return true;
|
|
1572
|
+
}
|
|
1573
|
+
function equalProperties(first, second, properties, options) {
|
|
1574
|
+
const { length } = properties;
|
|
1575
|
+
for (let index = 0; index < length; index += 1) {
|
|
1576
|
+
const property = properties[index];
|
|
1577
|
+
if (!equalValue(first[property], second[property], options)) return false;
|
|
1578
|
+
}
|
|
1579
|
+
return true;
|
|
1580
|
+
}
|
|
1581
|
+
function equalSet(first, second, options) {
|
|
1582
|
+
const { size } = first;
|
|
1583
|
+
if (size !== second.size) return false;
|
|
1584
|
+
const firstValues = [...first];
|
|
1585
|
+
const secondValues = [...second];
|
|
1586
|
+
for (let index = 0; index < size; index += 1) {
|
|
1587
|
+
const firstValue = firstValues[index];
|
|
1588
|
+
if (!secondValues.some((secondValue) => equalValue(firstValue, secondValue, options))) return false;
|
|
1589
|
+
}
|
|
1590
|
+
return true;
|
|
1591
|
+
}
|
|
1592
|
+
function equalTypedArray(first, second) {
|
|
1593
|
+
if (first.constructor !== second.constructor) return false;
|
|
1594
|
+
if (first.byteLength !== second.byteLength) return false;
|
|
1595
|
+
const { length } = first;
|
|
1596
|
+
for (let index = 0; index < length; index += 1) if (first[index] !== second[index]) return false;
|
|
1597
|
+
return true;
|
|
1598
|
+
}
|
|
1599
|
+
function equalValue(first, second, options) {
|
|
1600
|
+
if (options.relaxedNullish && first == null && second == null) return true;
|
|
1601
|
+
switch (true) {
|
|
1602
|
+
case Object.is(first, second): return true;
|
|
1603
|
+
case first == null || second == null: return first === second;
|
|
1604
|
+
case typeof first !== typeof second: return false;
|
|
1605
|
+
case typeof first === "string" && options.ignoreCase === true: return Object.is(first.toLocaleLowerCase(), second.toLocaleLowerCase());
|
|
1606
|
+
case first instanceof ArrayBuffer && second instanceof ArrayBuffer: return equalArrayBuffer(first, second, options);
|
|
1607
|
+
case first instanceof Date && second instanceof Date: return Object.is(Number(first), Number(second));
|
|
1608
|
+
case first instanceof DataView && second instanceof DataView: return equalDataView(first, second, options);
|
|
1609
|
+
case first instanceof Error && second instanceof Error: return equalProperties(first, second, ["name", "message"], options);
|
|
1610
|
+
case first instanceof Map && second instanceof Map: return equalMap(first, second, options);
|
|
1611
|
+
case first instanceof RegExp && second instanceof RegExp: return equalProperties(first, second, ["source", "flags"], options);
|
|
1612
|
+
case first instanceof Set && second instanceof Set: return equalSet(first, second, options);
|
|
1613
|
+
case Array.isArray(first) && Array.isArray(second): return equalArray(first, second, options);
|
|
1614
|
+
case isPlainObject(first) && isPlainObject(second): return equalPlainObject(first, second, options);
|
|
1615
|
+
case isTypedArray(first) && isTypedArray(second): return equalTypedArray(first, second);
|
|
1616
|
+
default: return equal.handlers.handle(first, second, options);
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
/**
|
|
1620
|
+
* Create an equalizer with predefined options
|
|
1621
|
+
* @param options Comparison options
|
|
1622
|
+
* @returns Equalizer function
|
|
1623
|
+
*/
|
|
1624
|
+
function initializeEqualizer(options) {
|
|
1625
|
+
const actual = getEqualOptions(options);
|
|
1626
|
+
const equalizer = (first, second) => equalValue(first, second, actual);
|
|
1627
|
+
equalizer.register = registerEqualizer;
|
|
1628
|
+
equalizer.unregister = unregisterEqualizer;
|
|
1629
|
+
return equalizer;
|
|
1630
|
+
}
|
|
1631
|
+
/**
|
|
1632
|
+
* Register a equality comparison function for a specific class
|
|
1633
|
+
* @param constructor Class constructor
|
|
1634
|
+
* @param fn Comparison function
|
|
1635
|
+
*/
|
|
1636
|
+
function registerEqualizer(constructor, handler) {
|
|
1637
|
+
equal.handlers.register(constructor, handler);
|
|
1638
|
+
}
|
|
1639
|
+
/**
|
|
1640
|
+
* Unregister a equality comparison handler for a specific class
|
|
1641
|
+
* @param constructor Class constructor
|
|
1642
|
+
*/
|
|
1643
|
+
function unregisterEqualizer(constructor) {
|
|
1644
|
+
equal.handlers.unregister(constructor);
|
|
1645
|
+
}
|
|
1646
|
+
function filterKey(key, options) {
|
|
1647
|
+
if (typeof key !== "string") return true;
|
|
1648
|
+
if (options.ignoreExpressions.enabled && options.ignoreExpressions.values.some((expression) => expression.test(key))) return false;
|
|
1649
|
+
if (options.ignoreKeys.enabled && options.ignoreKeys.values.has(key)) return false;
|
|
1650
|
+
return true;
|
|
1651
|
+
}
|
|
1652
|
+
function getEqualOptions(input) {
|
|
1653
|
+
const options = {
|
|
1654
|
+
ignoreCase: false,
|
|
1655
|
+
ignoreExpressions: {
|
|
1656
|
+
enabled: false,
|
|
1657
|
+
values: []
|
|
1658
|
+
},
|
|
1659
|
+
ignoreKeys: {
|
|
1660
|
+
enabled: false,
|
|
1661
|
+
values: /* @__PURE__ */ new Set()
|
|
1662
|
+
},
|
|
1663
|
+
relaxedNullish: false
|
|
1664
|
+
};
|
|
1665
|
+
if (typeof input === "boolean") {
|
|
1666
|
+
options.ignoreCase = input;
|
|
1667
|
+
return options;
|
|
1668
|
+
}
|
|
1669
|
+
if (!isPlainObject(input)) return options;
|
|
1670
|
+
options.ignoreCase = typeof input.ignoreCase === "boolean" ? input.ignoreCase : false;
|
|
1671
|
+
options.ignoreExpressions.values = (Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => key instanceof RegExp);
|
|
1672
|
+
options.ignoreKeys.values = new Set((Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => typeof key === "string"));
|
|
1673
|
+
options.ignoreExpressions.enabled = options.ignoreExpressions.values.length > 0;
|
|
1674
|
+
options.ignoreKeys.enabled = options.ignoreKeys.values.size > 0;
|
|
1675
|
+
options.relaxedNullish = input.relaxedNullish === true;
|
|
1676
|
+
return options;
|
|
1677
|
+
}
|
|
1678
|
+
var ARRAY_PEEK_PERCENTAGE = 10;
|
|
1679
|
+
var ARRAY_THRESHOLD = 100;
|
|
1680
|
+
var FilterManager = class {
|
|
1681
|
+
handlers = Object.freeze({
|
|
1682
|
+
add: (item) => this.add(item),
|
|
1683
|
+
clear: () => this.clear(),
|
|
1684
|
+
remove: (value) => this.remove(value),
|
|
1685
|
+
set: (items) => this.set(items)
|
|
1686
|
+
});
|
|
1687
|
+
items = {};
|
|
1688
|
+
constructor(managers) {
|
|
1689
|
+
this.managers = managers;
|
|
1690
|
+
}
|
|
1691
|
+
add(item) {
|
|
1692
|
+
if (this.items[item.field] == null) this.items[item.field] = [];
|
|
1693
|
+
else if (this.items[item.field].findIndex((existing) => equal(existing, item)) !== -1) return;
|
|
1694
|
+
this.items[item.field].push(item);
|
|
1695
|
+
this.filter();
|
|
1696
|
+
}
|
|
1697
|
+
clear() {
|
|
1698
|
+
if (Object.keys(this.items).length > 0) {
|
|
1699
|
+
this.items = {};
|
|
1700
|
+
this.filter();
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
destroy() {
|
|
1704
|
+
this.handlers = void 0;
|
|
1705
|
+
this.items = {};
|
|
1706
|
+
}
|
|
1707
|
+
filter() {
|
|
1708
|
+
const { managers } = this;
|
|
1709
|
+
const filtered = [];
|
|
1710
|
+
const filters = Object.entries(this.items);
|
|
1711
|
+
const keysLength = managers.data.values.keys.original.length;
|
|
1712
|
+
rowLoop: for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
|
|
1713
|
+
const key = managers.data.values.keys.original[keyIndex];
|
|
1714
|
+
const row = managers.data.values.objects.mapped.get(key);
|
|
1715
|
+
if (row == null) continue;
|
|
1716
|
+
filterLoop: for (let filterIndex = 0; filterIndex < filters.length; filterIndex += 1) {
|
|
1717
|
+
const [field, items] = filters[filterIndex];
|
|
1718
|
+
const value = row[field];
|
|
1719
|
+
for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) {
|
|
1720
|
+
const filter = items[itemIndex];
|
|
1721
|
+
if (comparators[filter.comparison](value, filter.value)) continue filterLoop;
|
|
1722
|
+
}
|
|
1723
|
+
continue rowLoop;
|
|
1724
|
+
}
|
|
1725
|
+
filtered.push(key);
|
|
1726
|
+
}
|
|
1727
|
+
managers.data.values.keys.active = filtered;
|
|
1728
|
+
if (managers.sort.items.length > 0) managers.sort.sort();
|
|
1729
|
+
else managers.virtualization.update(true, true);
|
|
1730
|
+
}
|
|
1731
|
+
remove(value) {
|
|
1732
|
+
if (typeof value === "string") {
|
|
1733
|
+
if (this.items[value] == null) return;
|
|
1734
|
+
this.items = {};
|
|
1735
|
+
} else {
|
|
1736
|
+
const { field } = value;
|
|
1737
|
+
if (this.items[field] == null) return;
|
|
1738
|
+
if (this.items[field].findIndex((item) => equal(item, value)) === -1) return;
|
|
1739
|
+
}
|
|
1740
|
+
this.filter();
|
|
1741
|
+
}
|
|
1742
|
+
set(items) {
|
|
1743
|
+
const keyed = {};
|
|
1744
|
+
const { length } = items;
|
|
1745
|
+
for (let index = 0; index < length; index += 1) {
|
|
1746
|
+
const item = items[index];
|
|
1747
|
+
keyed[item.field] ??= [];
|
|
1748
|
+
keyed[item.field].push(item);
|
|
1749
|
+
}
|
|
1750
|
+
this.items = keyed;
|
|
1751
|
+
this.filter();
|
|
1752
|
+
}
|
|
1753
|
+
};
|
|
1754
|
+
const comparators = {
|
|
1755
|
+
contains: (row, filter) => includes(getString(row), getString(filter), true),
|
|
1756
|
+
"ends-with": (row, filter) => endsWith(getString(row), getString(filter), true),
|
|
1757
|
+
equals: (row, filter) => equalizer(row, filter),
|
|
1758
|
+
"greater-than": (row, filter) => getNumber(row) > getNumber(filter),
|
|
1759
|
+
"greater-than-or-equal": (row, filter) => getNumber(row) >= getNumber(filter),
|
|
1760
|
+
"less-than": (row, filter) => getNumber(row) < getNumber(filter),
|
|
1761
|
+
"less-than-or-equal": (row, filter) => getNumber(row) <= getNumber(filter),
|
|
1762
|
+
"not-contains": (row, filter) => !includes(getString(row), getString(filter), true),
|
|
1763
|
+
"not-equals": (row, filter) => !equalizer(row, filter),
|
|
1764
|
+
"starts-with": (row, filter) => startsWith(getString(row), getString(filter), true)
|
|
1765
|
+
};
|
|
1766
|
+
const equalizer = equal.initialize({ ignoreCase: true });
|
|
1184
1767
|
function removeRow(pool, row) {
|
|
1185
1768
|
if (row.element != null) {
|
|
1186
1769
|
row.element.innerHTML = "";
|
|
@@ -1223,6 +1806,9 @@ var RowManager = class {
|
|
|
1223
1806
|
this.height = rowHeight;
|
|
1224
1807
|
}
|
|
1225
1808
|
destroy() {
|
|
1809
|
+
const components = [...this.components.values()];
|
|
1810
|
+
const { length } = components;
|
|
1811
|
+
for (let index = 0; index < length; index += 1) removeRow(this.managers.virtualization.pool, components[index]);
|
|
1226
1812
|
this.components.clear();
|
|
1227
1813
|
}
|
|
1228
1814
|
get(key) {
|
|
@@ -1237,7 +1823,11 @@ var RowManager = class {
|
|
|
1237
1823
|
return this.components.has(key);
|
|
1238
1824
|
}
|
|
1239
1825
|
remove(key) {
|
|
1240
|
-
this.components.
|
|
1826
|
+
const row = this.components.get(key);
|
|
1827
|
+
if (row != null) {
|
|
1828
|
+
removeRow(this.managers.virtualization.pool, row);
|
|
1829
|
+
this.components.delete(key);
|
|
1830
|
+
}
|
|
1241
1831
|
}
|
|
1242
1832
|
update(key) {
|
|
1243
1833
|
const row = this.components.get(key);
|
|
@@ -1267,13 +1857,19 @@ var SortManager = class {
|
|
|
1267
1857
|
addOrSet(event, field) {
|
|
1268
1858
|
if (event.ctrlKey || event.metaKey) this.add(field);
|
|
1269
1859
|
else this.set([{
|
|
1270
|
-
|
|
1860
|
+
field,
|
|
1271
1861
|
direction: "ascending"
|
|
1272
1862
|
}]);
|
|
1273
1863
|
}
|
|
1274
1864
|
clear() {
|
|
1865
|
+
if (this.items.length > 0) {
|
|
1866
|
+
this.items.length = 0;
|
|
1867
|
+
this.sort();
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
destroy() {
|
|
1871
|
+
this.handlers = void 0;
|
|
1275
1872
|
this.items.length = 0;
|
|
1276
|
-
this.sort();
|
|
1277
1873
|
}
|
|
1278
1874
|
flip(field) {
|
|
1279
1875
|
const item = this.items.find((item) => item.key === field);
|
|
@@ -1293,14 +1889,17 @@ var SortManager = class {
|
|
|
1293
1889
|
else this.clear();
|
|
1294
1890
|
}
|
|
1295
1891
|
set(items) {
|
|
1296
|
-
this.items.splice(0, this.items.length, ...items)
|
|
1892
|
+
this.items.splice(0, this.items.length, ...items.map((item) => ({
|
|
1893
|
+
key: item.field,
|
|
1894
|
+
direction: item.direction
|
|
1895
|
+
})));
|
|
1297
1896
|
this.sort();
|
|
1298
1897
|
}
|
|
1299
1898
|
sort() {
|
|
1300
1899
|
const { items, managers } = this;
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1900
|
+
const { length } = managers.column.items;
|
|
1901
|
+
for (let index = 0; index < length; index += 1) {
|
|
1902
|
+
const column = managers.column.items[index];
|
|
1304
1903
|
const sorterIndex = items.findIndex((item) => item.key === column.options.field);
|
|
1305
1904
|
const sorterItem = items[sorterIndex];
|
|
1306
1905
|
setAttributes(column.elements.wrapper, {
|
|
@@ -1309,6 +1908,8 @@ var SortManager = class {
|
|
|
1309
1908
|
});
|
|
1310
1909
|
setAttribute(column.elements.sorter, "data-sort-position", sorterIndex > -1 && items.length > 1 ? sorterIndex + 1 : void 0);
|
|
1311
1910
|
}
|
|
1911
|
+
managers.data.values.keys.active = items.length === 0 ? void 0 : sort(managers.data.values.keys.active?.map((key) => managers.data.values.objects.mapped.get(key)) ?? managers.data.values.objects.array, items).map((row) => row[managers.data.field]);
|
|
1912
|
+
managers.virtualization.update(true, true);
|
|
1312
1913
|
}
|
|
1313
1914
|
toggle(event, field, direction) {
|
|
1314
1915
|
switch (direction) {
|
|
@@ -1373,6 +1974,8 @@ var VirtualizationManager = class {
|
|
|
1373
1974
|
}
|
|
1374
1975
|
this.pool.cells = {};
|
|
1375
1976
|
this.pool.rows = [];
|
|
1977
|
+
this.listener = void 0;
|
|
1978
|
+
this.visible = void 0;
|
|
1376
1979
|
}
|
|
1377
1980
|
removeCells(fields) {
|
|
1378
1981
|
const { length } = fields;
|
|
@@ -1432,11 +2035,13 @@ var Tabela = class {
|
|
|
1432
2035
|
column: void 0,
|
|
1433
2036
|
data: void 0,
|
|
1434
2037
|
event: void 0,
|
|
2038
|
+
filter: void 0,
|
|
1435
2039
|
row: void 0,
|
|
1436
2040
|
sort: void 0,
|
|
1437
2041
|
virtualization: void 0
|
|
1438
2042
|
};
|
|
1439
2043
|
data;
|
|
2044
|
+
filter;
|
|
1440
2045
|
sort;
|
|
1441
2046
|
get key() {
|
|
1442
2047
|
return this.#key;
|
|
@@ -1454,12 +2059,14 @@ var Tabela = class {
|
|
|
1454
2059
|
this.#managers.column = new ColumnManager(this.#managers, this.#components, options.columns);
|
|
1455
2060
|
this.#managers.data = new DataManager(this.#managers, this.#components, options.key);
|
|
1456
2061
|
this.#managers.event = new EventManager(this.#managers, this.#element);
|
|
2062
|
+
this.#managers.filter = new FilterManager(this.#managers);
|
|
1457
2063
|
this.#managers.row = new RowManager(this.#managers, options.rowHeight);
|
|
1458
2064
|
this.#managers.sort = new SortManager(this.#managers);
|
|
1459
2065
|
this.#managers.virtualization = new VirtualizationManager(this.#managers, this.#components);
|
|
1460
2066
|
element.append(this.#components.header.elements.group, this.#components.body.elements.group, this.#components.footer.elements.group);
|
|
1461
2067
|
this.#managers.data.set(options.data);
|
|
1462
2068
|
this.data = this.#managers.data.handlers;
|
|
2069
|
+
this.filter = this.#managers.filter.handlers;
|
|
1463
2070
|
this.sort = this.#managers.sort.handlers;
|
|
1464
2071
|
}
|
|
1465
2072
|
destroy() {
|
|
@@ -1471,7 +2078,10 @@ var Tabela = class {
|
|
|
1471
2078
|
components.header.destroy();
|
|
1472
2079
|
managers.column.destroy();
|
|
1473
2080
|
managers.data.destroy();
|
|
2081
|
+
managers.event.destroy();
|
|
2082
|
+
managers.filter.destroy();
|
|
1474
2083
|
managers.row.destroy();
|
|
2084
|
+
managers.sort.destroy();
|
|
1475
2085
|
managers.virtualization.destroy();
|
|
1476
2086
|
element.innerHTML = "";
|
|
1477
2087
|
element.role = "";
|