@progress/kendo-angular-grid
Version:
Kendo UI Grid for Angular - high performance data grid with paging, filtering, virtualization, CRUD, and more.
159 lines (158 loc) • 5.31 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
/**
* @hidden
*
* Quick look-up structure for combinations of keys or single keys.
* Similar to the native JS Set, however, working with single keys or a couple of keys.
* Supports both primitive keys and object keys (compared by reference).
*/
export class PairSet {
/**
* Symbol used internally to represent "no Y key" when storing single X keys.
*/
static SINGLE_KEY_SYMBOL = Symbol('SINGLE_KEY');
/**
* Gets the total number of key entries (both single keys and key pairs).
*/
get size() {
return this.totalKeysCount;
}
/**
* Holds a set of Y keys for each defined X key.
* Each X key creates a map which holds a set of Y keys.
* For single keys, the Y value is the SINGLE_KEY_SYMBOL.
*
* Map { 'foo' => Set { Symbol(SINGLE_KEY) } } // single key: {x: 'foo'}
* Map { 'foo2' => Set { 'bar', 'baz' } } // pairs: {x: 'foo2', y: 'bar'}, {x: 'foo2', y: 'baz'}
*/
keysX = new Map();
/**
* Count each added or deleted key manually to avoid iterating over all items when calling `this.size`.
*/
totalKeysCount = 0;
constructor(items, keyXField, keyYField) {
if (items && keyXField) {
items.forEach(item => {
if (keyYField && item[keyYField] !== undefined) {
this.add(item[keyXField], item[keyYField]);
}
else {
this.addSingle(item[keyXField]);
}
});
}
}
/**
* Adds a single key entry.
*/
addSingle(keyX) {
if (!this.keysX.has(keyX)) {
this.keysX.set(keyX, new Set());
}
if (!this.hasSingle(keyX)) {
this.keysX.get(keyX).add(PairSet.SINGLE_KEY_SYMBOL);
this.totalKeysCount += 1;
}
}
/**
* Adds a couple of items identified as a combination.
*/
add(keyX, keyY) {
if (!this.keysX.has(keyX)) {
this.keysX.set(keyX, new Set());
}
if (!this.has(keyX, keyY)) {
this.keysX.get(keyX).add(keyY);
this.totalKeysCount += 1;
}
}
/**
* Deletes a single key entry.
*/
deleteSingle(keyX) {
if (this.hasSingle(keyX)) {
this.keysX.get(keyX).delete(PairSet.SINGLE_KEY_SYMBOL);
this.totalKeysCount -= 1;
if (this.keysX.get(keyX).size === 0) {
this.keysX.delete(keyX);
}
}
}
/**
* Deletes a combination of a couple of items identified together.
*/
delete(keyX, keyY) {
if (this.has(keyX, keyY)) {
this.keysX.get(keyX).delete(keyY);
this.totalKeysCount -= 1;
if (this.keysX.get(keyX).size === 0) {
this.keysX.delete(keyX);
}
}
}
/**
* Checks whether a single key is stored.
*/
hasSingle(keyX) {
return this.keysX.has(keyX) && this.keysX.get(keyX).has(PairSet.SINGLE_KEY_SYMBOL);
}
/**
* Checks whether the defined combination is stored.
*/
has(keyX, keyY) {
return this.keysX.has(keyX) && this.keysX.get(keyX).has(keyY);
}
/**
* Checks whether any entry exists for the given X key (single or paired).
*/
hasX(keyX) {
return this.keysX.has(keyX) && this.keysX.get(keyX).size > 0;
}
/**
* Gets all Y keys for a given X key, excluding single key entries.
*/
getYKeys(keyX) {
if (!this.keysX.has(keyX)) {
return [];
}
const yKeys = Array.from(this.keysX.get(keyX));
return yKeys.filter(yKey => yKey !== PairSet.SINGLE_KEY_SYMBOL);
}
/**
* Clears all key combinations and single keys.
*/
clear() {
this.keysX.clear();
this.totalKeysCount = 0;
}
/**
* Converts the persisted data structure to an array of objects,
* using the provided field names for the object props.
* Single keys will only have the keyXField property.
* Pair keys will have both keyXField and keyYField properties.
*/
toArray(keyXField, keyYField) {
return Array.from(this.keysX).reduce((pairs, pair) => {
// Array.from(mapInstance) returns an array of arrays [[itemKey1, columnKeysSet1], [itemKey2, columnKeysSet2]]
const [keyX, keysY] = pair;
Array.from(keysY).forEach(keyY => {
if (keyY === PairSet.SINGLE_KEY_SYMBOL) {
// Single key entry
pairs.push({ [keyXField]: keyX });
}
else {
// Pair key entry
const entry = { [keyXField]: keyX };
if (keyYField) {
entry[keyYField] = keyY;
}
pairs.push(entry);
}
});
return pairs;
}, []);
}
}