@danielgindi/dgtable.js 2.0.6 → 2.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +547 -282
- package/dist/SelectionHelper.d.ts +24 -0
- package/dist/SelectionHelper.d.ts.map +1 -0
- package/dist/by_column_filter.d.ts +14 -0
- package/dist/by_column_filter.d.ts.map +1 -0
- package/dist/cell_preview.d.ts +28 -0
- package/dist/cell_preview.d.ts.map +1 -0
- package/dist/column_collection.d.ts +41 -0
- package/dist/column_collection.d.ts.map +1 -0
- package/dist/column_resize.d.ts +25 -0
- package/dist/column_resize.d.ts.map +1 -0
- package/dist/constants.d.ts +19 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/header_events.d.ts +63 -0
- package/dist/header_events.d.ts.map +1 -0
- package/dist/helpers.d.ts +50 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/index.d.ts +166 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/internal.d.ts +56 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/lib.cjs.js +6906 -3933
- package/dist/lib.cjs.js.map +1 -1
- package/dist/lib.cjs.min.js +2 -2
- package/dist/lib.cjs.min.js.map +1 -1
- package/dist/lib.es6.js +6908 -3935
- package/dist/lib.es6.js.map +1 -1
- package/dist/lib.es6.min.js +2 -2
- package/dist/lib.es6.min.js.map +1 -1
- package/dist/lib.umd.js +9251 -4353
- package/dist/lib.umd.js.map +1 -1
- package/dist/lib.umd.min.js +2 -2
- package/dist/lib.umd.min.js.map +1 -1
- package/dist/private_types.d.ts +145 -0
- package/dist/private_types.d.ts.map +1 -0
- package/dist/rendering.d.ts +57 -0
- package/dist/rendering.d.ts.map +1 -0
- package/dist/row_collection.d.ts +38 -0
- package/dist/row_collection.d.ts.map +1 -0
- package/dist/types.d.ts +221 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/util.d.ts +9 -0
- package/dist/util.d.ts.map +1 -0
- package/eslint.config.mjs +1 -0
- package/package.json +17 -12
- package/src/SelectionHelper.ts +90 -0
- package/src/by_column_filter.ts +36 -0
- package/src/cell_preview.ts +325 -0
- package/src/column_collection.ts +131 -0
- package/src/column_resize.ts +363 -0
- package/src/constants.ts +22 -0
- package/src/header_events.ts +369 -0
- package/src/helpers.ts +291 -0
- package/src/index.ts +1628 -0
- package/src/internal.ts +263 -0
- package/src/private_types.ts +156 -0
- package/src/rendering.ts +771 -0
- package/src/row_collection.ts +197 -0
- package/src/types.ts +265 -0
- package/src/util.ts +27 -0
- package/tsconfig.json +38 -0
- package/src/SelectionHelper.js +0 -65
- package/src/by_column_filter.js +0 -25
- package/src/column_collection.js +0 -153
- package/src/index.js +0 -3999
- package/src/row_collection.js +0 -183
- package/src/util.js +0 -17
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arguments for the by-column filter
|
|
3
|
+
*/
|
|
4
|
+
export interface ByColumnFilterArgs {
|
|
5
|
+
column: string;
|
|
6
|
+
keyword?: string | null;
|
|
7
|
+
caseSensitive?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Default filter function that filters rows by a column value containing a keyword
|
|
12
|
+
*/
|
|
13
|
+
function ByColumnFilter(row: Record<string, unknown>, args: ByColumnFilterArgs): boolean {
|
|
14
|
+
const column = args.column;
|
|
15
|
+
const keyword = args.keyword == null ? '' : args.keyword.toString();
|
|
16
|
+
|
|
17
|
+
if (!keyword || !column) return true;
|
|
18
|
+
|
|
19
|
+
let actualVal = row[column];
|
|
20
|
+
if (actualVal == null) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let actualValStr = actualVal.toString();
|
|
25
|
+
let keywordStr = keyword;
|
|
26
|
+
|
|
27
|
+
if (!args.caseSensitive) {
|
|
28
|
+
actualValStr = actualValStr.toLowerCase();
|
|
29
|
+
keywordStr = keywordStr.toLowerCase();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return actualValStr.indexOf(keywordStr) !== -1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default ByColumnFilter;
|
|
36
|
+
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cell preview functionality for DGTable
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
6
|
+
// @ts-ignore - No type declarations available for this module
|
|
7
|
+
import { getElementWidth, getElementHeight, getElementOffset, setCssProps } from '@danielgindi/dom-utils/lib/Css.js';
|
|
8
|
+
import SelectionHelper from './SelectionHelper';
|
|
9
|
+
import { disableCssSelect } from './helpers';
|
|
10
|
+
import type { RowData } from './types';
|
|
11
|
+
import type { DGTableInterface } from './private_types';
|
|
12
|
+
import {
|
|
13
|
+
OriginalCellSymbol,
|
|
14
|
+
PreviewCellSymbol,
|
|
15
|
+
} from './private_types';
|
|
16
|
+
import { bindHeaderColumnEvents } from "./internal";
|
|
17
|
+
|
|
18
|
+
const nativeIndexOf = Array.prototype.indexOf;
|
|
19
|
+
const createElement = document.createElement.bind(document);
|
|
20
|
+
|
|
21
|
+
// Extended element types for cell preview
|
|
22
|
+
interface PreviewCellElement extends HTMLDivElement {
|
|
23
|
+
rowVIndex?: number;
|
|
24
|
+
rowIndex?: number;
|
|
25
|
+
columnName?: string;
|
|
26
|
+
[OriginalCellSymbol]?: HTMLElement;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface CellElement extends HTMLElement {
|
|
30
|
+
[PreviewCellSymbol]?: PreviewCellElement;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface RowElement extends HTMLElement {
|
|
34
|
+
vIndex?: number;
|
|
35
|
+
index?: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface ElementOffset {
|
|
39
|
+
left: number;
|
|
40
|
+
top: number;
|
|
41
|
+
right?: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Handle cell mouse over event - show preview if content overflows
|
|
46
|
+
*/
|
|
47
|
+
export function cellMouseOverEvent(table: DGTableInterface, el: CellElement): void {
|
|
48
|
+
const o = table._o, p = table._p;
|
|
49
|
+
|
|
50
|
+
const elInner = el.firstElementChild as HTMLElement;
|
|
51
|
+
if (!elInner) return;
|
|
52
|
+
|
|
53
|
+
if (!((elInner.scrollWidth - elInner.clientWidth > 1) ||
|
|
54
|
+
(elInner.scrollHeight - elInner.clientHeight > 1)))
|
|
55
|
+
return;
|
|
56
|
+
|
|
57
|
+
hideCellPreview(table);
|
|
58
|
+
p.abortCellPreview = false;
|
|
59
|
+
|
|
60
|
+
const rowEl = el.parentElement as RowElement;
|
|
61
|
+
if (!rowEl) return;
|
|
62
|
+
|
|
63
|
+
const previewCell = createElement('div') as PreviewCellElement;
|
|
64
|
+
previewCell.innerHTML = el.innerHTML;
|
|
65
|
+
previewCell.className = o.cellPreviewClassName;
|
|
66
|
+
|
|
67
|
+
const isHeaderCell = el.classList.contains(`${o.tableClassName}-header-cell`);
|
|
68
|
+
if (isHeaderCell) {
|
|
69
|
+
previewCell.classList.add('header');
|
|
70
|
+
if (el.classList.contains('sortable')) {
|
|
71
|
+
previewCell.classList.add('sortable');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
previewCell.draggable = true;
|
|
75
|
+
|
|
76
|
+
bindHeaderColumnEvents(table, previewCell);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const elStyle = getComputedStyle(el);
|
|
80
|
+
const elInnerStyle = getComputedStyle(elInner);
|
|
81
|
+
|
|
82
|
+
const rtl = elStyle.float === 'right';
|
|
83
|
+
const prop = rtl ? 'right' : 'left';
|
|
84
|
+
|
|
85
|
+
const paddingL = parseFloat(elStyle.paddingLeft) || 0;
|
|
86
|
+
const paddingR = parseFloat(elStyle.paddingRight) || 0;
|
|
87
|
+
const paddingT = parseFloat(elStyle.paddingTop) || 0;
|
|
88
|
+
const paddingB = parseFloat(elStyle.paddingBottom) || 0;
|
|
89
|
+
|
|
90
|
+
let requiredWidth = elInner.scrollWidth + (el.clientWidth - elInner.offsetWidth);
|
|
91
|
+
|
|
92
|
+
const borderBox = elStyle.boxSizing === 'border-box';
|
|
93
|
+
if (borderBox) {
|
|
94
|
+
previewCell.style.boxSizing = 'border-box';
|
|
95
|
+
} else {
|
|
96
|
+
requiredWidth -= paddingL + paddingR;
|
|
97
|
+
previewCell.style.marginTop = (parseFloat(elStyle.borderTopWidth) || 0) + 'px';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!p.transparentBgColor1) {
|
|
101
|
+
// Detect browser's transparent spec
|
|
102
|
+
const tempDiv = document.createElement('div');
|
|
103
|
+
document.body.appendChild(tempDiv);
|
|
104
|
+
tempDiv.style.backgroundColor = 'transparent';
|
|
105
|
+
p.transparentBgColor1 = getComputedStyle(tempDiv).backgroundColor;
|
|
106
|
+
tempDiv.style.backgroundColor = 'rgba(0,0,0,0)';
|
|
107
|
+
p.transparentBgColor2 = getComputedStyle(tempDiv).backgroundColor;
|
|
108
|
+
tempDiv.remove();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const css: Record<string, string | number> = {
|
|
112
|
+
'box-sizing': borderBox ? 'border-box' : 'content-box',
|
|
113
|
+
'width': requiredWidth,
|
|
114
|
+
'min-height': Math.max(getElementHeight(el), /%/.test(elStyle.minHeight) ? 0 : (parseFloat(elStyle.minHeight) || 0)) + 'px',
|
|
115
|
+
'padding-left': paddingL,
|
|
116
|
+
'padding-right': paddingR,
|
|
117
|
+
'padding-top': paddingT,
|
|
118
|
+
'padding-bottom': paddingB,
|
|
119
|
+
'overflow': 'hidden',
|
|
120
|
+
'position': 'absolute',
|
|
121
|
+
'z-index': '-1',
|
|
122
|
+
[prop]: '0',
|
|
123
|
+
'top': '0',
|
|
124
|
+
'cursor': elStyle.cursor,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
let bgColor = elStyle.backgroundColor;
|
|
128
|
+
if (bgColor === p.transparentBgColor1 || bgColor === p.transparentBgColor2) {
|
|
129
|
+
bgColor = getComputedStyle(rowEl).backgroundColor;
|
|
130
|
+
}
|
|
131
|
+
if (bgColor === p.transparentBgColor1 || bgColor === p.transparentBgColor2) {
|
|
132
|
+
bgColor = '#fff';
|
|
133
|
+
}
|
|
134
|
+
css['background-color'] = bgColor;
|
|
135
|
+
|
|
136
|
+
setCssProps(previewCell, css);
|
|
137
|
+
if (previewCell.firstChild) {
|
|
138
|
+
setCssProps(previewCell.firstChild as HTMLElement, {
|
|
139
|
+
'direction': elInnerStyle.direction,
|
|
140
|
+
'white-space': elInnerStyle.whiteSpace,
|
|
141
|
+
'min-height': elInnerStyle.minHeight,
|
|
142
|
+
'line-height': elInnerStyle.lineHeight,
|
|
143
|
+
'font': elInnerStyle.font,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
table.el.appendChild(previewCell);
|
|
148
|
+
|
|
149
|
+
if (isHeaderCell) {
|
|
150
|
+
disableCssSelect(previewCell);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
previewCell.rowVIndex = rowEl.vIndex;
|
|
154
|
+
const rowIndex = previewCell.rowIndex = rowEl.index;
|
|
155
|
+
previewCell.columnName = p.visibleColumns[nativeIndexOf.call(rowEl.childNodes, el)]?.name;
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
const selection = SelectionHelper.saveSelection(el);
|
|
159
|
+
if (selection)
|
|
160
|
+
SelectionHelper.restoreSelection(previewCell, selection);
|
|
161
|
+
} catch {
|
|
162
|
+
/* we're ok with this */
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
table.emit('cellpreview', {
|
|
166
|
+
el: previewCell.firstElementChild,
|
|
167
|
+
name: previewCell.columnName,
|
|
168
|
+
rowIndex: rowIndex ?? null,
|
|
169
|
+
rowData: rowIndex == null ? null : p.rows[rowIndex] as RowData,
|
|
170
|
+
cell: el,
|
|
171
|
+
cellEl: elInner,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
if (p.abortCellPreview) {
|
|
175
|
+
previewCell.remove();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (rowIndex != null) {
|
|
180
|
+
previewCell.addEventListener('click', (event: MouseEvent) => {
|
|
181
|
+
table.emit('rowclick', {
|
|
182
|
+
event: event,
|
|
183
|
+
filteredRowIndex: rowEl.vIndex,
|
|
184
|
+
rowIndex: rowIndex,
|
|
185
|
+
rowEl: rowEl,
|
|
186
|
+
rowData: p.rows[rowIndex] as RowData,
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const parent = table.el;
|
|
192
|
+
const scrollParent = parent === (window as unknown as HTMLElement) ? document : parent;
|
|
193
|
+
|
|
194
|
+
const parentStyle = getComputedStyle(parent);
|
|
195
|
+
|
|
196
|
+
const offset = getElementOffset(el) as ElementOffset;
|
|
197
|
+
const parentOffset = getElementOffset(parent) as ElementOffset;
|
|
198
|
+
|
|
199
|
+
// Handle RTL, go from the other side
|
|
200
|
+
if (rtl) {
|
|
201
|
+
const windowWidth = window.innerWidth;
|
|
202
|
+
offset.right = windowWidth - (offset.left + getElementWidth(el, true, true, true));
|
|
203
|
+
parentOffset.right = windowWidth - (parentOffset.left + getElementWidth(parent, true, true, true));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// If the parent has borders, then it would offset the offset...
|
|
207
|
+
offset.left -= parseFloat(parentStyle.borderLeftWidth) || 0;
|
|
208
|
+
if (prop === 'right' && offset.right !== undefined && parentOffset.right !== undefined)
|
|
209
|
+
offset.right -= parseFloat(parentStyle.borderRightWidth) || 0;
|
|
210
|
+
offset.top -= parseFloat(parentStyle.borderTopWidth) || 0;
|
|
211
|
+
|
|
212
|
+
// Handle border widths of the element being offset
|
|
213
|
+
const borderPropWidth = prop === 'left' ? 'borderLeftWidth' : 'borderRightWidth';
|
|
214
|
+
if (prop === 'left') {
|
|
215
|
+
offset.left += parseFloat(elStyle.borderLeftWidth) || 0;
|
|
216
|
+
} else if (offset.right !== undefined) {
|
|
217
|
+
offset.right += parseFloat(elStyle.borderRightWidth) || 0;
|
|
218
|
+
}
|
|
219
|
+
offset.top += parseFloat(elStyle.borderTopWidth) || parseFloat(elStyle.borderBottomWidth) || 0;
|
|
220
|
+
|
|
221
|
+
// Subtract offsets to get offset relative to parent
|
|
222
|
+
offset.left -= parentOffset.left;
|
|
223
|
+
if (prop === 'right' && offset.right !== undefined && parentOffset.right !== undefined)
|
|
224
|
+
offset.right -= parentOffset.right;
|
|
225
|
+
offset.top -= parentOffset.top;
|
|
226
|
+
|
|
227
|
+
// Constrain horizontally
|
|
228
|
+
const minHorz = 0;
|
|
229
|
+
const maxHorz = getElementWidth(parent, false, false, false) - getElementWidth(previewCell, true, true, true);
|
|
230
|
+
const horzOffset = prop === 'left' ? offset.left : (offset.right ?? 0);
|
|
231
|
+
const constrainedHorz = horzOffset < minHorz ? minHorz : (horzOffset > maxHorz ? maxHorz : horzOffset);
|
|
232
|
+
if (prop === 'left') {
|
|
233
|
+
offset.left = constrainedHorz;
|
|
234
|
+
} else {
|
|
235
|
+
offset.right = constrainedHorz;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Constrain vertically
|
|
239
|
+
const totalHeight = getElementHeight(el, true, true, true);
|
|
240
|
+
const scrollTop = 'scrollTop' in scrollParent ? scrollParent.scrollTop : 0;
|
|
241
|
+
const maxTop = scrollTop + getElementHeight(parent, true) - totalHeight;
|
|
242
|
+
if (offset.top > maxTop) {
|
|
243
|
+
offset.top = Math.max(0, maxTop);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Apply css to preview cell
|
|
247
|
+
const previewCss: Record<string, string | number> = {
|
|
248
|
+
'top': offset.top + 'px',
|
|
249
|
+
'z-index': 9999,
|
|
250
|
+
};
|
|
251
|
+
previewCss[prop] = (prop === 'left' ? offset.left : offset.right) + 'px';
|
|
252
|
+
setCssProps(previewCell, previewCss);
|
|
253
|
+
|
|
254
|
+
previewCell[OriginalCellSymbol] = el;
|
|
255
|
+
p.cellPreviewCell = previewCell;
|
|
256
|
+
el[PreviewCellSymbol] = previewCell;
|
|
257
|
+
|
|
258
|
+
p._bindCellHoverOut(el);
|
|
259
|
+
p._bindCellHoverOut(previewCell);
|
|
260
|
+
|
|
261
|
+
// Avoid interfering with wheel scrolling the table
|
|
262
|
+
previewCell.addEventListener('wheel', () => {
|
|
263
|
+
// Let the table naturally scroll with the wheel
|
|
264
|
+
hideCellPreview(table);
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Handle cell mouse out event
|
|
270
|
+
*/
|
|
271
|
+
export function cellMouseOutEvent(table: DGTableInterface, _el: HTMLElement): void {
|
|
272
|
+
hideCellPreview(table);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Hide the current cell preview
|
|
277
|
+
*/
|
|
278
|
+
export function hideCellPreview(table: DGTableInterface): DGTableInterface {
|
|
279
|
+
const p = table._p;
|
|
280
|
+
|
|
281
|
+
if (p.cellPreviewCell) {
|
|
282
|
+
const previewCell = p.cellPreviewCell as PreviewCellElement;
|
|
283
|
+
const origCell = previewCell[OriginalCellSymbol] as CellElement;
|
|
284
|
+
let selection;
|
|
285
|
+
|
|
286
|
+
try {
|
|
287
|
+
selection = SelectionHelper.saveSelection(previewCell);
|
|
288
|
+
} catch {
|
|
289
|
+
/* we're ok with this */
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
p.cellPreviewCell.remove();
|
|
293
|
+
if (origCell) p._unbindCellHoverOut(origCell);
|
|
294
|
+
p._unbindCellHoverOut(previewCell);
|
|
295
|
+
|
|
296
|
+
try {
|
|
297
|
+
if (selection && origCell)
|
|
298
|
+
SelectionHelper.restoreSelection(origCell, selection);
|
|
299
|
+
} catch {
|
|
300
|
+
/* we're ok with this */
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
table.emit('cellpreviewdestroy', {
|
|
304
|
+
el: previewCell.firstChild,
|
|
305
|
+
name: previewCell.columnName,
|
|
306
|
+
rowIndex: previewCell.rowIndex ?? null,
|
|
307
|
+
rowData: previewCell.rowIndex == null ? null : p.rows[previewCell.rowIndex] as RowData,
|
|
308
|
+
cell: origCell,
|
|
309
|
+
cellEl: origCell?.firstChild,
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
if (origCell) {
|
|
313
|
+
delete origCell[PreviewCellSymbol];
|
|
314
|
+
}
|
|
315
|
+
delete previewCell[OriginalCellSymbol];
|
|
316
|
+
|
|
317
|
+
p.cellPreviewCell = null;
|
|
318
|
+
p.abortCellPreview = false;
|
|
319
|
+
} else {
|
|
320
|
+
p.abortCellPreview = true;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return table;
|
|
324
|
+
}
|
|
325
|
+
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InternalColumn,
|
|
3
|
+
} from './private_types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A collection of columns that extends Array functionality
|
|
7
|
+
*/
|
|
8
|
+
class ColumnCollection extends Array<InternalColumn> {
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get the column by this name
|
|
15
|
+
*/
|
|
16
|
+
get(column: string): InternalColumn | null {
|
|
17
|
+
for (let i = 0, len = this.length; i < len; i++) {
|
|
18
|
+
if (this[i].name === column) {
|
|
19
|
+
return this[i];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get the index of the column by this name
|
|
27
|
+
*/
|
|
28
|
+
indexOf(column: string | InternalColumn): number {
|
|
29
|
+
const columnName = typeof column === 'string' ? column : column.name;
|
|
30
|
+
for (let i = 0, len = this.length; i < len; i++) {
|
|
31
|
+
if (this[i].name === columnName) {
|
|
32
|
+
return i;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return -1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get the column by the specified order
|
|
40
|
+
*/
|
|
41
|
+
getByOrder(order: number): InternalColumn | null {
|
|
42
|
+
for (let i = 0, len = this.length; i < len; i++) {
|
|
43
|
+
if (this[i].order === order) {
|
|
44
|
+
return this[i];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Normalize order to be sequential starting from 0
|
|
52
|
+
*/
|
|
53
|
+
normalizeOrder(): this {
|
|
54
|
+
const ordered: InternalColumn[] = [];
|
|
55
|
+
for (let i = 0; i < this.length; i++) {
|
|
56
|
+
ordered.push(this[i]);
|
|
57
|
+
}
|
|
58
|
+
ordered.sort((col1, col2) => col1.order < col2.order ? -1 : (col1.order > col2.order ? 1 : 0));
|
|
59
|
+
for (let i = 0; i < ordered.length; i++) {
|
|
60
|
+
ordered[i].order = i;
|
|
61
|
+
}
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get the array of columns, ordered by the order property
|
|
67
|
+
*/
|
|
68
|
+
getColumns(): InternalColumn[] {
|
|
69
|
+
const cols: InternalColumn[] = [];
|
|
70
|
+
for (let i = 0; i < this.length; i++) {
|
|
71
|
+
cols.push(this[i]);
|
|
72
|
+
}
|
|
73
|
+
cols.sort((col1, col2) => col1.order < col2.order ? -1 : (col1.order > col2.order ? 1 : 0));
|
|
74
|
+
return cols;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get the array of visible columns, ordered by the order property
|
|
79
|
+
*/
|
|
80
|
+
getVisibleColumns(): InternalColumn[] {
|
|
81
|
+
const cols: InternalColumn[] = [];
|
|
82
|
+
for (let i = 0; i < this.length; i++) {
|
|
83
|
+
const column = this[i];
|
|
84
|
+
if (column.visible) {
|
|
85
|
+
cols.push(column);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
cols.sort((col1, col2) => col1.order < col2.order ? -1 : (col1.order > col2.order ? 1 : 0));
|
|
89
|
+
return cols;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get the maximum order currently in the array
|
|
94
|
+
*/
|
|
95
|
+
getMaxOrder(): number {
|
|
96
|
+
let order = 0;
|
|
97
|
+
for (let i = 0; i < this.length; i++) {
|
|
98
|
+
const column = this[i];
|
|
99
|
+
if (column.order > order) {
|
|
100
|
+
order = column.order;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return order;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Move a column to a new spot in the collection
|
|
108
|
+
*/
|
|
109
|
+
moveColumn(src: InternalColumn, dest: InternalColumn): this {
|
|
110
|
+
if (src && dest) {
|
|
111
|
+
const srcOrder = src.order;
|
|
112
|
+
const destOrder = dest.order;
|
|
113
|
+
if (srcOrder < destOrder) {
|
|
114
|
+
for (let i = srcOrder + 1; i <= destOrder; i++) {
|
|
115
|
+
const col = this.getByOrder(i);
|
|
116
|
+
if (col) col.order--;
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
for (let i = srcOrder - 1; i >= destOrder; i--) {
|
|
120
|
+
const col = this.getByOrder(i);
|
|
121
|
+
if (col) col.order++;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
src.order = destOrder;
|
|
125
|
+
}
|
|
126
|
+
return this;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export default ColumnCollection;
|
|
131
|
+
|