UNPKG

@progress/kendo-angular-listbox

Version:
167 lines (166 loc) 7.67 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { EventEmitter, Injectable } from "@angular/core"; import * as i0 from "@angular/core"; /** * @hidden */ export class ListBoxSelectionService { selectedIndices = []; selectionMode = 'single'; lastSelectedOrUnselectedIndex = null; rangeSelectionTargetIndex = null; rangeSelectionAnchorIndex = null; isItemDisabled = () => false; onSelect = new EventEmitter(); select(index, ctrlKey = false, shiftKey = false) { if (this.isItemDisabled(index)) { return; } const previousSelection = [...this.selectedIndices]; let selectedIndices = []; let deselectedIndices = null; const previousTargetIndex = this.rangeSelectionTargetIndex; if (this.selectionMode === 'single') { if (ctrlKey) { const isSelected = this.isSelected(index); if (isSelected) { this.selectedIndices = []; deselectedIndices = [index]; } else { this.selectedIndices = [index]; selectedIndices = [index]; if (previousSelection.length > 0) { deselectedIndices = previousSelection; } } this.lastSelectedOrUnselectedIndex = index; } else { this.selectedIndices = [index]; selectedIndices = [index]; this.lastSelectedOrUnselectedIndex = index; this.rangeSelectionAnchorIndex = index; if (previousSelection.length > 0 && previousSelection[0] !== index) { deselectedIndices = previousSelection; } } } else if (this.selectionMode === 'multiple') { if (shiftKey) { let anchorIndex = this.rangeSelectionAnchorIndex ?? this.lastSelectedOrUnselectedIndex ?? 0; if (index === anchorIndex) { this.selectedIndices = [anchorIndex]; this.rangeSelectionTargetIndex = index; selectedIndices = this.selectedIndices.filter(i => !previousSelection.includes(i)); const nowDeselected = previousSelection.filter(i => !this.selectedIndices.includes(i)); deselectedIndices = nowDeselected.length > 0 ? nowDeselected : null; } else { if (previousTargetIndex !== null && previousTargetIndex !== anchorIndex) { const previousDirection = previousTargetIndex > anchorIndex ? 'down' : 'up'; const currentDirection = index > anchorIndex ? 'down' : 'up'; if (previousDirection !== currentDirection) { this.rangeSelectionAnchorIndex = previousTargetIndex; anchorIndex = previousTargetIndex; } } const startIndex = Math.min(anchorIndex, index); const endIndex = Math.max(anchorIndex, index); this.selectedIndices = []; for (let i = startIndex; i <= endIndex; i++) { if (!this.isItemDisabled(i)) { this.selectedIndices.push(i); } } this.rangeSelectionTargetIndex = index; selectedIndices = this.selectedIndices.filter(i => !previousSelection.includes(i)); const nowDeselected = previousSelection.filter(i => !this.selectedIndices.includes(i)); deselectedIndices = nowDeselected.length > 0 ? nowDeselected : null; } } else if (ctrlKey) { const indexInSelection = this.selectedIndices.indexOf(index); if (indexInSelection === -1) { this.selectedIndices.push(index); selectedIndices = [index]; } else { this.selectedIndices.splice(indexInSelection, 1); deselectedIndices = [index]; } this.lastSelectedOrUnselectedIndex = index; this.rangeSelectionAnchorIndex = index; this.rangeSelectionTargetIndex = index; } else { this.selectedIndices = [index]; selectedIndices = [index]; this.lastSelectedOrUnselectedIndex = index; this.rangeSelectionAnchorIndex = index; this.rangeSelectionTargetIndex = index; const nowDeselected = previousSelection.filter(i => i !== index); deselectedIndices = nowDeselected.length > 0 ? nowDeselected : null; } } this.onSelect.next({ selectedIndices: selectedIndices.length > 0 ? selectedIndices : null, deselectedIndices }); } selectRange(targetIndex) { const anchorIndex = this.lastSelectedOrUnselectedIndex ?? 0; const startIndex = Math.min(anchorIndex, targetIndex); const endIndex = Math.max(anchorIndex, targetIndex); this.selectedIndices = []; for (let i = startIndex; i <= endIndex; i++) { if (!this.isItemDisabled(i)) { this.selectedIndices.push(i); } } } setSelectedIndices(indices) { this.selectedIndices = indices.filter(i => !this.isItemDisabled(i)); } addToSelectedIndices(index) { if (this.isItemDisabled(index)) { return; } if (this.selectionMode === 'single') { this.selectedIndices = [index]; } else if (this.selectedIndices.indexOf(index) === -1) { this.selectedIndices = [...this.selectedIndices, index]; } } selectAll(totalItems) { if (this.selectionMode === 'multiple') { this.selectedIndices = []; for (let i = 0; i < totalItems; i++) { if (!this.isItemDisabled(i)) { this.selectedIndices.push(i); } } } } areAllSelected(totalItems) { const allSelectableItems = Array.from({ length: totalItems }, (_, i) => i).filter(i => !this.isItemDisabled(i)); return this.selectedIndices.length === allSelectableItems.length && allSelectableItems.length > 0; } isSelected(index) { return this.selectedIndices.indexOf(index) !== -1; } clearSelection() { this.selectedIndices = []; this.lastSelectedOrUnselectedIndex = null; this.rangeSelectionAnchorIndex = null; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ListBoxSelectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ListBoxSelectionService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ListBoxSelectionService, decorators: [{ type: Injectable }] });