@progress/kendo-angular-listbox
Version:
Kendo UI for Angular ListBox
167 lines (166 loc) • 7.67 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* 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
}] });