UNPKG

@progress/kendo-angular-grid

Version:

Kendo UI Grid for Angular - high performance data grid with paging, filtering, virtualization, CRUD, and more.

229 lines (228 loc) 6.72 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { iterator } from '../utils'; import { isPresent } from '../utils'; const isGroupItem = (source) => { return source.items !== undefined && source.field !== undefined; }; const isVirtualGroupItem = (source) => { return source.offset !== undefined && source.skipHeader !== undefined; }; const flattenGroups = (groups) => (groups.reduce((acc, curr) => { if (isGroupItem(curr)) { return acc.concat(flattenGroups(curr.items)); } return acc.concat([curr]); }, [])); /** * @hidden */ export const itemAt = (data, index) => { const first = data[0]; if (isPresent(first) && isGroupItem(first)) { return flattenGroups(data)[index]; } return data[index]; }; /** * @hidden */ export const getIterator = (data, { footers, level, dataIndex, parentGroupIndex, groupIndex, parentGroup }) => { const first = data[0]; if (isPresent(first) && isGroupItem(first)) { if (isVirtualGroupItem(first)) { groupIndex = isPresent(first.offset) ? first.offset : groupIndex; } return new GroupIterator(data, footers, level, dataIndex, parentGroupIndex, groupIndex, parentGroup); } return new ItemIterator(data, dataIndex, parentGroupIndex, parentGroup); }; class ArrayIterator { arr; idx; constructor(arr, idx = 0) { this.arr = arr; this.idx = idx; this.arr = arr || []; } [iterator]() { return this; } next() { return this.idx < this.arr.length ? { done: false, value: this.arr[this.idx++] } : { done: true, value: undefined }; } } /** * @hidden */ export class Iterator { dataIndex; resultMap; _innerIterator; constructor(arr, dataIndex = 0, resultMap = (x) => x) { this.dataIndex = dataIndex; this.resultMap = resultMap; const iter = arr[iterator]; this._innerIterator = iter ? arr[iterator]() : new ArrayIterator(arr); } [iterator]() { return this; } next() { return this.resultMap(this._innerIterator.next(), this.dataIndex++); } } /** * @hidden */ export class ItemIterator extends Iterator { constructor(arr, dataIndex, groupIndex, group) { super(arr, dataIndex, (x, idx) => ({ done: x.done, value: { data: x.value, groupIndex: groupIndex, index: idx, type: 'data', group } })); } /** * The index of the next record. * @readonly * @type {number} */ get index() { return this.dataIndex; } } const prefix = (s, n) => { const p = s ? s + "_" : s; return `${p}${n}`; }; /** * @hidden */ export class GroupIterator { arr; outputFooters; level; dataIndex; parentIndex; groupIndex; parentGroup; current; _innerIterator; _iterator; currentGroupIndex = ""; constructor(arr, outputFooters = false, level = 0, dataIndex = 0, parentIndex = '', groupIndex = 0, parentGroup = undefined) { this.arr = arr; this.outputFooters = outputFooters; this.level = level; this.dataIndex = dataIndex; this.parentIndex = parentIndex; this.groupIndex = groupIndex; this.parentGroup = parentGroup; this.arr = arr || []; this._iterator = new Iterator(this.arr, this.dataIndex); } [iterator]() { return this; } nextGroupItem() { this.current = this._iterator.next().value; this._innerIterator = null; if (this.current) { this.currentGroupIndex = prefix(this.parentIndex, this.groupIndex++); return { done: false, value: { data: this.current, index: this.currentGroupIndex, level: this.level, type: 'group', parentGroup: this.parentGroup } }; } else { this.current = null; return { done: true, value: undefined }; } } footerItem() { if (this.current) { const group = this.current; this.current = null; return { done: false, value: { data: group, groupIndex: this.currentGroupIndex, level: this.level, type: 'footer', group: { data: group, index: this.currentGroupIndex, level: this.level, type: 'group', parentGroup: this.parentGroup } } }; } else { this.current = null; return { done: true, value: undefined }; } } innerIterator(group) { if (!this._innerIterator) { this._innerIterator = getIterator(group.items, { dataIndex: this.dataIndex, footers: this.outputFooters, level: this.level + 1, parentGroupIndex: this.currentGroupIndex, parentGroup: { data: this.current, index: this.currentGroupIndex, level: this.level, type: 'group', parentGroup: this.parentGroup } }); } return this._innerIterator; } nextDataItem(group) { const iterator = this.innerIterator(group); const result = iterator.next(); if (isPresent(result.value) && !result.done && result.value.type === "data") { this.dataIndex = result.value.index + 1; } return !result.done ? result : undefined; } next() { if (!isPresent(this.current)) { return this.nextGroupItem(); } const item = this.nextDataItem(this.current); return item ? item : (this.outputFooters ? this.footerItem() : this.nextGroupItem()); } /** * The index of the last iterated data record. * @readonly * @type {number} */ get index() { return this.dataIndex + 1; } }