igniteui-webcomponents
Version:
Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.
266 lines • 10.1 kB
JavaScript
import { isEmpty } from '../common/util.js';
export class IgcTreeSelectionService {
constructor(tree) {
this.itemSelection = new Set();
this.indeterminateItems = new Set();
this.tree = tree;
}
selectMultipleItems(item) {
if (!this.itemSelection.size) {
this.selectItem(item);
return;
}
const lastSelectedItemIndex = this.tree.items.indexOf(this.getSelectedItems()[this.itemSelection.size - 1]);
const currentItemIndex = this.tree.items.indexOf(item);
const items = this.tree.items.slice(Math.min(currentItemIndex, lastSelectedItemIndex), Math.max(currentItemIndex, lastSelectedItemIndex) + 1);
const added = items.filter((_item) => !this.isItemSelected(_item));
const newSelection = this.getSelectedItems().concat(added);
this.emitItemSelectionEvent(newSelection, added, []);
}
selectItem(item) {
if (this.tree.selection === 'none') {
return;
}
this.emitItemSelectionEvent([...this.getSelectedItems(), item], [item], []);
}
deselectItem(item) {
const newSelection = this.getSelectedItems().filter((_item) => _item !== item);
this.emitItemSelectionEvent(newSelection, [], [item]);
}
clearItemsSelection() {
const oldSelection = this.getSelectedItems();
const oldIndeterminate = this.getIndeterminateItems();
this.itemSelection.clear();
this.indeterminateItems.clear();
oldSelection.forEach((i) => {
i.selected = false;
});
oldIndeterminate.forEach((i) => {
i.indeterminate = false;
});
}
isItemSelected(item) {
return this.itemSelection.has(item);
}
isItemIndeterminate(item) {
return this.indeterminateItems.has(item);
}
ensureStateOnItemDelete(item) {
this.deselectItemsWithNoEvent([item, ...item.getChildren({ flatten: true })], true);
}
retriggerItemState(item) {
if (item.selected) {
this.itemSelection.delete(item);
this.selectItemsWithNoEvent([item]);
}
else {
this.itemSelection.add(item);
this.deselectItemsWithNoEvent([item]);
}
}
emitItemSelectionEvent(newSelection, added, removed) {
const currSelection = this.getSelectedItems();
if (this.areEqualCollections(currSelection, newSelection)) {
return;
}
if (this.tree.selection === 'cascade') {
this.emitCascadeItemSelectionEvent(currSelection, added, removed);
return;
}
const args = {
detail: {
newSelection,
},
cancelable: true,
};
const allowed = this.tree.emitEvent('igcSelection', args);
if (!allowed) {
return;
}
if (this.areEqualCollections(newSelection, args.detail.newSelection)) {
this.itemSelection = new Set(newSelection);
this.updateItemsState(currSelection);
}
}
selectItemsWithNoEvent(items) {
const oldSelection = this.getSelectedItems();
if (this.tree && this.tree.selection === 'cascade') {
this.cascadeSelectItemsWithNoEvent(items, oldSelection);
return;
}
items.forEach((item) => this.itemSelection.add(item));
this.updateItemsState(oldSelection);
}
deselectItemsWithNoEvent(items, onDelete = false) {
if (this.tree && this.tree.selection === 'cascade') {
this.cascadeDeselectItemsWithNoEvent(items, onDelete);
return;
}
const itemSet = new Set(items);
const oldSelection = onDelete
? this.getSelectedItems().filter((i) => !itemSet.has(i))
: this.getSelectedItems();
if (!items) {
this.itemSelection.clear();
}
else {
items.forEach((item) => this.itemSelection.delete(item));
}
this.updateItemsState(oldSelection);
}
emitCascadeItemSelectionEvent(currSelection, added, removed) {
const oldIndeterminate = this.getIndeterminateItems();
this.calculateItemsNewSelectionState(currSelection, added, removed);
const args = {
detail: {
newSelection: Array.from(this.itemsToBeSelected),
},
cancelable: true,
};
const allowed = this.tree.emitEvent('igcSelection', args);
if (!allowed) {
return;
}
if (this.areEqualCollections(Array.from(this.itemsToBeSelected), args.detail.newSelection)) {
this.itemSelection = new Set(this.itemsToBeSelected);
this.indeterminateItems = new Set(this.itemsToBeIndeterminate);
this.updateItemsState(currSelection, oldIndeterminate);
}
}
cascadeSelectItemsWithNoEvent(items, oldSelection) {
const oldIndeterminate = this.getIndeterminateItems();
const newSelection = [...oldSelection, ...items];
const newSelectionSet = new Set(newSelection);
const removed = oldSelection.filter((x) => !newSelectionSet.has(x));
const added = newSelection.filter((x) => !this.itemSelection.has(x));
this.calculateItemsNewSelectionState(oldSelection, added, removed);
this.itemSelection = new Set(this.itemsToBeSelected);
this.indeterminateItems = new Set(this.itemsToBeIndeterminate);
this.updateItemsState(oldSelection, oldIndeterminate);
}
cascadeDeselectItemsWithNoEvent(items, onDelete = false) {
const itemSet = new Set(items);
const oldSelection = onDelete
? this.getSelectedItems().filter((i) => !itemSet.has(i))
: this.getSelectedItems();
const oldIndeterminate = onDelete
? this.getIndeterminateItems().filter((i) => !itemSet.has(i))
: this.getIndeterminateItems();
if (!items) {
this.itemSelection.clear();
this.indeterminateItems.clear();
}
else {
this.calculateItemsNewSelectionState(oldSelection, [], items);
this.itemSelection = new Set(this.itemsToBeSelected);
this.indeterminateItems = new Set(this.itemsToBeIndeterminate);
}
this.updateItemsState(oldSelection, oldIndeterminate);
}
calculateItemsNewSelectionState(oldSelection, added, removed) {
this.itemsToBeSelected = new Set(oldSelection);
this.itemsToBeIndeterminate = new Set(this.getIndeterminateItems());
this.cascadeSelectionState(removed, false);
this.cascadeSelectionState(added, true);
}
cascadeSelectionState(items, selected) {
if (!items || isEmpty(items)) {
return;
}
const parents = new Set();
items.forEach((item) => {
this.selectDeselectItem(item, selected);
const itemAndAllChildren = item.getChildren({ flatten: true }) || [];
itemAndAllChildren.forEach((i) => {
this.selectDeselectItem(i, selected);
});
if (item?.parent) {
parents.add(item.parent);
}
});
for (const parent of parents) {
this.handleParentSelectionState(parent);
}
}
handleParentSelectionState(item) {
if (!item) {
return;
}
this.handleItemSelectionState(item);
if (item.parent) {
this.handleParentSelectionState(item.parent);
}
}
handleItemSelectionState(item) {
const itemsArray = item?.getChildren() ? item.getChildren() : [];
if (itemsArray.length) {
if (itemsArray.every((i) => this.itemsToBeSelected.has(i))) {
this.selectDeselectItem(item, true);
}
else if (itemsArray.some((i) => this.itemsToBeSelected.has(i) || this.itemsToBeIndeterminate.has(i))) {
this.selectDeselectItem(item, false, true);
}
else {
this.selectDeselectItem(item, false);
}
}
else if (this.isItemSelected(item)) {
this.selectDeselectItem(item, true);
}
else {
this.selectDeselectItem(item, false);
}
}
updateItemsState(oldSelection, oldIndeterminate = []) {
const selected = new Set(oldSelection);
const indeterminated = new Set(oldIndeterminate);
this.getSelectedItems().forEach((i) => {
if (!selected.has(i)) {
i.selected = true;
}
});
oldSelection.forEach((i) => {
if (!this.itemSelection.has(i)) {
i.selected = false;
}
});
if (this.tree.selection === 'cascade') {
this.indeterminateItems.forEach((i) => {
if (!indeterminated.has(i)) {
i.indeterminate = true;
}
});
oldIndeterminate.forEach((i) => {
if (!this.indeterminateItems.has(i)) {
i.indeterminate = false;
}
});
}
}
getSelectedItems() {
return Array.from(this.itemSelection);
}
getIndeterminateItems() {
return Array.from(this.indeterminateItems);
}
areEqualCollections(first, second) {
return (first.length === second.length &&
new Set(first.concat(second)).size === first.length);
}
selectDeselectItem(item, select, indeterminate = false) {
if (indeterminate) {
this.itemsToBeIndeterminate.add(item);
this.itemsToBeSelected.delete(item);
return;
}
if (select) {
this.itemsToBeSelected.add(item);
this.itemsToBeIndeterminate.delete(item);
}
else {
this.itemsToBeSelected.delete(item);
this.itemsToBeIndeterminate.delete(item);
}
}
}
//# sourceMappingURL=tree.selection.js.map