canvas-datagrid 0.25.3 → 0.26.0
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/CHANGELOG.md +328 -1
- package/README.md +85 -67
- package/dist/canvas-datagrid.debug.js +7606 -3099
- package/dist/canvas-datagrid.debug.map +1 -1
- package/dist/canvas-datagrid.js +1 -1
- package/dist/canvas-datagrid.module.js +1 -1
- package/dist/canvas-datagrid.module.js.map +1 -1
- package/dist/types.d.ts +2508 -0
- package/lib/button.js +326 -0
- package/lib/component.js +51 -13
- package/lib/contextMenu.js +408 -30
- package/lib/defaults.js +100 -7
- package/lib/docs.js +121 -11
- package/lib/dom.js +239 -18
- package/lib/draw.js +1446 -206
- package/lib/events/index.js +2640 -0
- package/lib/events/util.js +165 -0
- package/lib/groups/util.js +42 -0
- package/lib/intf.js +908 -87
- package/lib/main.js +8 -1
- package/lib/publicMethods.js +773 -377
- package/lib/selections/index.js +989 -0
- package/lib/selections/type.d.ts +38 -0
- package/lib/selections/util.js +1320 -0
- package/lib/touch.js +20 -47
- package/package.json +32 -21
- package/lib/events.js +0 -1741
package/lib/publicMethods.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
/*globals define: true, MutationObserver: false, requestAnimationFrame: false, performance: false, btoa: false*/
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
+
import { mergeHiddenRowRanges } from './groups/util';
|
|
6
|
+
|
|
5
7
|
export default function (self) {
|
|
6
8
|
/**
|
|
7
9
|
* Converts a integer into a letter A - ZZZZZ...
|
|
@@ -37,10 +39,14 @@ export default function (self) {
|
|
|
37
39
|
}
|
|
38
40
|
self.validateColumn(c, s);
|
|
39
41
|
s.splice(index, 0, c);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
|
|
43
|
+
self.originalData.forEach(function (row, rowIndex) {
|
|
44
|
+
self.applyDefaultValue(row, c, rowIndex);
|
|
42
45
|
});
|
|
43
46
|
self.intf.schema = s;
|
|
47
|
+
|
|
48
|
+
self.refresh();
|
|
49
|
+
self.dispatchDataChanged('insertcolumn', { column: c, index: index });
|
|
44
50
|
};
|
|
45
51
|
/**
|
|
46
52
|
* Deletes a column from the schema at the specified index.
|
|
@@ -51,13 +57,18 @@ export default function (self) {
|
|
|
51
57
|
* @param {number} index The index of the column to delete.
|
|
52
58
|
*/
|
|
53
59
|
self.deleteColumn = function (index) {
|
|
54
|
-
var
|
|
60
|
+
var schema = self.getSchema();
|
|
61
|
+
|
|
55
62
|
// remove data matching this column name from data
|
|
56
|
-
self.
|
|
57
|
-
delete row[
|
|
63
|
+
self.originalData.forEach(function (row) {
|
|
64
|
+
delete row[schema[index].name];
|
|
58
65
|
});
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
|
|
67
|
+
schema.splice(index, 1);
|
|
68
|
+
self.intf.schema = schema;
|
|
69
|
+
|
|
70
|
+
self.refresh();
|
|
71
|
+
self.dispatchDataChanged('deletecolumn', { index: index });
|
|
61
72
|
};
|
|
62
73
|
/**
|
|
63
74
|
* Adds a new column into the schema.
|
|
@@ -71,10 +82,13 @@ export default function (self) {
|
|
|
71
82
|
var s = self.getSchema();
|
|
72
83
|
self.validateColumn(c, s);
|
|
73
84
|
s.push(c);
|
|
74
|
-
self.
|
|
75
|
-
self.applyDefaultValue(row, c);
|
|
85
|
+
self.originalData.forEach(function (row, rowIndex) {
|
|
86
|
+
self.applyDefaultValue(row, c, rowIndex);
|
|
76
87
|
});
|
|
77
88
|
self.intf.schema = s;
|
|
89
|
+
|
|
90
|
+
self.refresh();
|
|
91
|
+
self.dispatchDataChanged('addcolumn', { column: c });
|
|
78
92
|
};
|
|
79
93
|
/**
|
|
80
94
|
* Deletes a row from the dataset at the specified index.
|
|
@@ -87,6 +101,7 @@ export default function (self) {
|
|
|
87
101
|
self.originalData.splice(index, 1);
|
|
88
102
|
self.setFilter();
|
|
89
103
|
self.resize(true);
|
|
104
|
+
self.dispatchDataChanged('deleterow', { index: index });
|
|
90
105
|
};
|
|
91
106
|
/**
|
|
92
107
|
* Inserts a new row into the dataset before the specified index.
|
|
@@ -103,11 +118,15 @@ export default function (self) {
|
|
|
103
118
|
self.originalData.splice(index, 0, d);
|
|
104
119
|
self.getSchema().forEach(function (c) {
|
|
105
120
|
if (d[c.name] === undefined) {
|
|
106
|
-
self.applyDefaultValue(self.originalData[index], c);
|
|
121
|
+
self.applyDefaultValue(self.originalData[index], c, index);
|
|
107
122
|
}
|
|
108
123
|
});
|
|
124
|
+
|
|
125
|
+
// setFilter calls .refresh(), so we need not call it again:
|
|
109
126
|
self.setFilter();
|
|
127
|
+
|
|
110
128
|
self.resize(true);
|
|
129
|
+
self.dispatchDataChanged('insertrow', { row: d, index: index });
|
|
111
130
|
};
|
|
112
131
|
/**
|
|
113
132
|
* Adds a new row into the dataset.
|
|
@@ -123,11 +142,16 @@ export default function (self) {
|
|
|
123
142
|
self.applyDefaultValue(
|
|
124
143
|
self.originalData[self.originalData.length - 1],
|
|
125
144
|
c,
|
|
145
|
+
self.originalData.length - 1,
|
|
126
146
|
);
|
|
127
147
|
}
|
|
128
148
|
});
|
|
149
|
+
|
|
150
|
+
// setFilter calls .refresh(), so we need not call it again:
|
|
129
151
|
self.setFilter();
|
|
152
|
+
|
|
130
153
|
self.resize(true);
|
|
154
|
+
self.dispatchDataChanged('addrow', { row: d });
|
|
131
155
|
};
|
|
132
156
|
/**
|
|
133
157
|
* Sets the height of a given row by index number.
|
|
@@ -190,8 +214,20 @@ export default function (self) {
|
|
|
190
214
|
delete self.columnFilters[column];
|
|
191
215
|
} else {
|
|
192
216
|
self.columnFilters[column] = value;
|
|
217
|
+
if (self.attributes.showFilterInCell) {
|
|
218
|
+
self.filterable.rows.push(0);
|
|
219
|
+
self.orders.columns.forEach(function (value, index) {
|
|
220
|
+
self.filterable.columns.push(index);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (!Object.keys(self.columnFilters).length) {
|
|
225
|
+
self.filterable = {
|
|
226
|
+
rows: [],
|
|
227
|
+
columns: [],
|
|
228
|
+
};
|
|
193
229
|
}
|
|
194
|
-
self.
|
|
230
|
+
self.refresh();
|
|
195
231
|
};
|
|
196
232
|
/**
|
|
197
233
|
* Returns the number of pixels to scroll down to line up with row rowIndex.
|
|
@@ -202,7 +238,9 @@ export default function (self) {
|
|
|
202
238
|
*/
|
|
203
239
|
self.findRowScrollTop = function (rowIndex) {
|
|
204
240
|
if (self.scrollCache.y[rowIndex] === undefined) {
|
|
205
|
-
throw new RangeError(
|
|
241
|
+
throw new RangeError(
|
|
242
|
+
`Row index ${rowIndex} out of range: ${self.scrollCache.y.length}.`,
|
|
243
|
+
);
|
|
206
244
|
}
|
|
207
245
|
return self.scrollCache.y[rowIndex];
|
|
208
246
|
};
|
|
@@ -220,7 +258,7 @@ export default function (self) {
|
|
|
220
258
|
}
|
|
221
259
|
return (
|
|
222
260
|
self.scrollCache.x[i] -
|
|
223
|
-
self.
|
|
261
|
+
self.getColumnWidth(self.orders.columns[columnIndex])
|
|
224
262
|
);
|
|
225
263
|
};
|
|
226
264
|
/**
|
|
@@ -249,6 +287,11 @@ export default function (self) {
|
|
|
249
287
|
targetY -= sbh * offsetY;
|
|
250
288
|
if (x !== undefined && y !== undefined) {
|
|
251
289
|
self.scrollBox.scrollTo(targetX, targetY);
|
|
290
|
+
if (!offsetX && !offsetY) {
|
|
291
|
+
// nothing to correct; a deferred re-scroll would only undo a scroll
|
|
292
|
+
// the user made in the meantime (#313)
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
252
295
|
requestAnimationFrame(function () {
|
|
253
296
|
cell = self.getVisibleCellByIndex(x, y);
|
|
254
297
|
// HACK: just don't offset if the target cell cannot be seen
|
|
@@ -276,6 +319,64 @@ export default function (self) {
|
|
|
276
319
|
self.gotoRow = function (y) {
|
|
277
320
|
self.gotoCell(0, y);
|
|
278
321
|
};
|
|
322
|
+
/**
|
|
323
|
+
* Add a button into the cell.
|
|
324
|
+
* @memberof canvasDatagrid
|
|
325
|
+
* @name addButton
|
|
326
|
+
* @method
|
|
327
|
+
* @param {number} columnIndex The column index of the cell to to add a button.
|
|
328
|
+
* @param {number} rowIndex The row index of the cell to to add a button.
|
|
329
|
+
* @param {object} offset Offset how far go away from cell.
|
|
330
|
+
* @param {object} items a list of items to add into button menu.
|
|
331
|
+
* @param {string} imgSrc icon path to add into button.
|
|
332
|
+
*/
|
|
333
|
+
self.addButton = function (columnIndex, rowIndex, offset, items, imgSrc) {
|
|
334
|
+
var cells = self.visibleCells.filter(function (c) {
|
|
335
|
+
return c.sortColumnIndex === columnIndex && c.sortRowIndex === rowIndex;
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
self.attachButton(
|
|
339
|
+
{
|
|
340
|
+
top: cells[0].y + cells[0].height + offset.y,
|
|
341
|
+
left: cells[0].x + cells[0].width + offset.x,
|
|
342
|
+
},
|
|
343
|
+
items,
|
|
344
|
+
imgSrc,
|
|
345
|
+
);
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Expand/Collapse CellTree.
|
|
350
|
+
* @memberof canvasDatagrid
|
|
351
|
+
* @name toggleCellCollapseTree
|
|
352
|
+
* @method
|
|
353
|
+
* @param {array} treeData The array of cellTree to expand or collapse.
|
|
354
|
+
*/
|
|
355
|
+
|
|
356
|
+
self.toggleCellCollapseTree = function (treeData) {
|
|
357
|
+
for (let type in treeData) {
|
|
358
|
+
for (let t of treeData[type])
|
|
359
|
+
if (t.length > 0) self.toggleCollapseTree(t[0], t[1], type);
|
|
360
|
+
}
|
|
361
|
+
self.draw();
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Expand/Collapse CellTree.
|
|
366
|
+
* @memberof canvasDatagrid
|
|
367
|
+
* @name expandCollapseCellTree
|
|
368
|
+
* @method
|
|
369
|
+
* @param {array} treeData The array of cellTree to expand or collapse.
|
|
370
|
+
*/
|
|
371
|
+
|
|
372
|
+
self.expandCollapseCellTree = function (treeData) {
|
|
373
|
+
for (let type in treeData) {
|
|
374
|
+
for (let t of treeData[type])
|
|
375
|
+
if (t.length > 0) self.cellTreeExpandCollapse(t[0], t[1], type);
|
|
376
|
+
}
|
|
377
|
+
self.draw();
|
|
378
|
+
};
|
|
379
|
+
|
|
279
380
|
/**
|
|
280
381
|
* Scrolls the cell at cell x, row y into view if it is not already.
|
|
281
382
|
* @memberof canvasDatagrid
|
|
@@ -287,18 +388,25 @@ export default function (self) {
|
|
|
287
388
|
* @param {number} [offsetY=0] Percentage offset the cell should be from the top edge (not including headers). The default is 0, meaning the cell will appear at the top edge. Valid values are 0 through 1. 1 = Bottom, 0 = Top, 0.5 = Center.
|
|
288
389
|
*/
|
|
289
390
|
self.scrollIntoView = function (x, y, offsetX, offsetY) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
391
|
+
const matched = self.visibleCells.filter(function (cell) {
|
|
392
|
+
return (
|
|
393
|
+
(cell.rowIndex === y || y === undefined) &&
|
|
394
|
+
(cell.columnIndex === x || x === undefined) &&
|
|
395
|
+
cell.x > 0 &&
|
|
396
|
+
cell.y > 0 &&
|
|
397
|
+
cell.x + cell.width < self.width &&
|
|
398
|
+
cell.y + cell.height < self.height
|
|
399
|
+
);
|
|
400
|
+
});
|
|
401
|
+
if (matched.length === 1 && x !== undefined && y !== undefined) {
|
|
402
|
+
// goto specific cell and its part be hidden by header
|
|
403
|
+
if (
|
|
404
|
+
matched[0].x < self.getRowHeaderCellWidth() ||
|
|
405
|
+
matched[0].y < self.getColumnHeaderCellHeight()
|
|
406
|
+
)
|
|
407
|
+
matched.length = 0;
|
|
408
|
+
}
|
|
409
|
+
if (matched.length === 0) {
|
|
302
410
|
self.gotoCell(x, y, offsetX, offsetY);
|
|
303
411
|
}
|
|
304
412
|
};
|
|
@@ -311,6 +419,7 @@ export default function (self) {
|
|
|
311
419
|
* @param {number} y The row index of the cell to set active.
|
|
312
420
|
*/
|
|
313
421
|
self.setActiveCell = function (x, y) {
|
|
422
|
+
if (typeof x === 'undefined') return;
|
|
314
423
|
if (x < 0) {
|
|
315
424
|
x = 0;
|
|
316
425
|
}
|
|
@@ -321,213 +430,40 @@ export default function (self) {
|
|
|
321
430
|
rowIndex: y,
|
|
322
431
|
columnIndex: x,
|
|
323
432
|
};
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
* Removes the selection.
|
|
327
|
-
* @memberof canvasDatagrid
|
|
328
|
-
* @name selectNone
|
|
329
|
-
* @param {boolean} dontDraw Suppress the draw method after the selection change.
|
|
330
|
-
* @method
|
|
331
|
-
*/
|
|
332
|
-
self.selectNone = function (dontDraw) {
|
|
333
|
-
self.selections = [];
|
|
334
|
-
self.dispatchEvent('selectionchanged', {
|
|
335
|
-
selectedData: self.getSelectedData(),
|
|
336
|
-
selections: self.selections,
|
|
337
|
-
selectionBounds: self.selectionBounds,
|
|
338
|
-
});
|
|
339
|
-
if (dontDraw) {
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
self.draw();
|
|
343
|
-
};
|
|
344
|
-
/**
|
|
345
|
-
* Selects every visible cell.
|
|
346
|
-
* @memberof canvasDatagrid
|
|
347
|
-
* @name selectAll
|
|
348
|
-
* @param {boolean} dontDraw Suppress the draw method after the selection change.
|
|
349
|
-
* @method
|
|
350
|
-
*/
|
|
351
|
-
self.selectAll = function (dontDraw) {
|
|
352
|
-
self.selectArea({
|
|
353
|
-
top: 0,
|
|
354
|
-
left: -1,
|
|
355
|
-
right: self.getSchema().length - 1,
|
|
356
|
-
bottom: self.data.length - 1,
|
|
357
|
-
});
|
|
358
|
-
if (dontDraw) {
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
self.draw();
|
|
362
|
-
};
|
|
363
|
-
/**
|
|
364
|
-
* Returns true if the selected columnIndex is selected on every row.
|
|
365
|
-
* @memberof canvasDatagrid
|
|
366
|
-
* @name isColumnSelected
|
|
367
|
-
* @method
|
|
368
|
-
* @param {number} columnIndex The column index to check.
|
|
369
|
-
*/
|
|
370
|
-
self.isColumnSelected = function (columnIndex) {
|
|
371
|
-
var colIsSelected = true;
|
|
372
|
-
self.data.forEach(function (row, rowIndex) {
|
|
373
|
-
if (
|
|
374
|
-
!self.selections[rowIndex] ||
|
|
375
|
-
self.selections[rowIndex].indexOf(self.orders.columns[columnIndex]) ===
|
|
376
|
-
-1
|
|
377
|
-
) {
|
|
378
|
-
colIsSelected = false;
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
return colIsSelected;
|
|
382
|
-
};
|
|
383
|
-
/**
|
|
384
|
-
* Runs the defined method on each selected cell.
|
|
385
|
-
* @memberof canvasDatagrid
|
|
386
|
-
* @name forEachSelectedCell
|
|
387
|
-
* @method
|
|
388
|
-
* @param {number} fn The function to execute. The signature of the function is: (data, rowIndex, columnName).
|
|
389
|
-
* @param {number} expandToRow When true the data in the array is expanded to the entire row.
|
|
390
|
-
*/
|
|
391
|
-
self.forEachSelectedCell = function (fn, expandToRow) {
|
|
392
|
-
var d = [],
|
|
393
|
-
s = expandToRow ? self.getSchema() : self.getVisibleSchema(),
|
|
394
|
-
l = self.data.length;
|
|
395
|
-
self.selections.forEach(function (row, index) {
|
|
396
|
-
if (index === l) {
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
if (row.length === 0) {
|
|
400
|
-
d[index] = null;
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
d[index] = {};
|
|
404
|
-
row.forEach(function (col) {
|
|
405
|
-
if (col === -1 || !s[col]) {
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
fn(self.data, index, s[col].name);
|
|
409
|
-
});
|
|
433
|
+
self.dispatchEvent('activecellchanged', {
|
|
434
|
+
cell: self.activeCell,
|
|
410
435
|
});
|
|
411
436
|
};
|
|
437
|
+
|
|
412
438
|
/**
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
* @
|
|
417
|
-
* @param {
|
|
418
|
-
* @param {boolean} toggleSelectMode When true, behaves as if you were holding control/command when you clicked the column.
|
|
419
|
-
* @param {boolean} shift When true, behaves as if you were holding shift when you clicked the column.
|
|
420
|
-
* @param {boolean} supressSelectionchangedEvent When true, prevents the selectionchanged event from firing.
|
|
439
|
+
* Dispatches `datachanged` with the source of the change so listeners can
|
|
440
|
+
* react to edits, pastes, deletions and row/column changes, not only to the
|
|
441
|
+
* data setter (#250, #512).
|
|
442
|
+
* @param {string} source One of data, edit, paste, cut, delete, fill, addrow, insertrow, deleterow, addcolumn, insertcolumn, deletecolumn.
|
|
443
|
+
* @param {object} [details] Extra event details.
|
|
421
444
|
*/
|
|
422
|
-
self.
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
if (self.selections[rowIndex].indexOf(i) === -1) {
|
|
428
|
-
self.selections[rowIndex].push(i);
|
|
429
|
-
}
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
function removeCol(i) {
|
|
433
|
-
self.data.forEach(function (row, rowIndex) {
|
|
434
|
-
self.selections[rowIndex] = self.selections[rowIndex] || [];
|
|
435
|
-
if (self.selections[rowIndex].indexOf(i) !== -1) {
|
|
436
|
-
self.selections[rowIndex].splice(
|
|
437
|
-
self.selections[rowIndex].indexOf(i),
|
|
438
|
-
1,
|
|
439
|
-
);
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
if (shift) {
|
|
444
|
-
if (!self.activeCell) {
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
s = Math.min(self.activeCell.columnIndex, columnIndex);
|
|
448
|
-
e = Math.max(self.activeCell.columnIndex, columnIndex);
|
|
449
|
-
for (x = s; e > x; x += 1) {
|
|
450
|
-
addCol(x);
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
if (!ctrl && !shift) {
|
|
454
|
-
self.selections = [];
|
|
455
|
-
self.activeCell.columnIndex = columnIndex;
|
|
456
|
-
self.activeCell.rowIndex = self.scrollIndexTop;
|
|
457
|
-
}
|
|
458
|
-
if (ctrl && self.isColumnSelected(columnIndex)) {
|
|
459
|
-
removeCol(columnIndex);
|
|
460
|
-
} else {
|
|
461
|
-
addCol(columnIndex);
|
|
462
|
-
}
|
|
463
|
-
if (supressEvent) {
|
|
464
|
-
return;
|
|
465
|
-
}
|
|
466
|
-
self.dispatchEvent('selectionchanged', {
|
|
467
|
-
selectedData: self.getSelectedData(),
|
|
468
|
-
selections: self.selections,
|
|
469
|
-
selectionBounds: self.getSelectionBounds(),
|
|
470
|
-
});
|
|
445
|
+
self.dispatchDataChanged = function (source, details) {
|
|
446
|
+
self.dispatchEvent(
|
|
447
|
+
'datachanged',
|
|
448
|
+
Object.assign({ data: self.originalData, source: source }, details || {}),
|
|
449
|
+
);
|
|
471
450
|
};
|
|
472
451
|
/**
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
* @param {
|
|
478
|
-
* @
|
|
479
|
-
* @param {boolean} shift When true, behaves as if you were holding shift when you clicked the row.
|
|
480
|
-
* @param {boolean} supressSelectionchangedEvent When true, prevents the selectionchanged event from firing.
|
|
452
|
+
* Dispatches the `resizerow` event with one consistent payload (#503).
|
|
453
|
+
* Canonical keys: `rowIndex`, `height`, `width`, `x`, `y`, `draggingItem`,
|
|
454
|
+
* `NativeEvent`. `cellHeight` and `row` are kept as deprecated aliases of
|
|
455
|
+
* `height` for listeners written against older versions.
|
|
456
|
+
* @param {object} details Event details; `height` is required.
|
|
457
|
+
* @returns {boolean} true when a listener called preventDefault.
|
|
481
458
|
*/
|
|
482
|
-
self.
|
|
483
|
-
var
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
s = self.getVisibleSchema();
|
|
487
|
-
function de() {
|
|
488
|
-
if (supressEvent) {
|
|
489
|
-
return;
|
|
490
|
-
}
|
|
491
|
-
self.dispatchEvent('selectionchanged', {
|
|
492
|
-
selectedData: self.getSelectedData(),
|
|
493
|
-
selections: self.selections,
|
|
494
|
-
selectionBounds: self.selectionBounds,
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
function addRow(ri) {
|
|
498
|
-
self.selections[ri] = [];
|
|
499
|
-
self.selections[ri].push(-1);
|
|
500
|
-
s.forEach(function (col, index) {
|
|
501
|
-
self.selections[ri].push(self.orders.columns.indexOf(col.index));
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
if (self.dragAddToSelection === false || self.dragObject === undefined) {
|
|
505
|
-
if (
|
|
506
|
-
self.selections[rowIndex] &&
|
|
507
|
-
self.selections[rowIndex].length - 1 === s.length
|
|
508
|
-
) {
|
|
509
|
-
if (ctrl) {
|
|
510
|
-
self.selections[rowIndex] = [];
|
|
511
|
-
de();
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
}
|
|
459
|
+
self.dispatchResizeRow = function (details) {
|
|
460
|
+
var ev = Object.assign({}, details);
|
|
461
|
+
if (ev.y === undefined) {
|
|
462
|
+
ev.y = ev.height;
|
|
515
463
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
st = Math.min(self.activeCell.rowIndex, rowIndex);
|
|
522
|
-
en = Math.max(self.activeCell.rowIndex, rowIndex);
|
|
523
|
-
for (x = st; en >= x; x += 1) {
|
|
524
|
-
addRow(x);
|
|
525
|
-
}
|
|
526
|
-
} else {
|
|
527
|
-
addRow(rowIndex);
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
de();
|
|
464
|
+
ev.cellHeight = ev.height;
|
|
465
|
+
ev.row = ev.height;
|
|
466
|
+
return self.dispatchEvent('resizerow', ev);
|
|
531
467
|
};
|
|
532
468
|
/**
|
|
533
469
|
* Collapse a tree grid by row index.
|
|
@@ -539,7 +475,7 @@ export default function (self) {
|
|
|
539
475
|
self.collapseTree = function (rowIndex) {
|
|
540
476
|
self.dispatchEvent('collapsetree', {
|
|
541
477
|
childGrid: self.childGrids[rowIndex],
|
|
542
|
-
data: self.
|
|
478
|
+
data: self.viewData[rowIndex],
|
|
543
479
|
rowIndex: rowIndex,
|
|
544
480
|
});
|
|
545
481
|
self.openChildren[rowIndex].blur();
|
|
@@ -547,8 +483,9 @@ export default function (self) {
|
|
|
547
483
|
delete self.openChildren[rowIndex];
|
|
548
484
|
delete self.sizes.trees[rowIndex];
|
|
549
485
|
delete self.childGrids[rowIndex];
|
|
550
|
-
self.
|
|
551
|
-
|
|
486
|
+
self.dispatchResizeRow({
|
|
487
|
+
height: self.style.cellHeight,
|
|
488
|
+
rowIndex: rowIndex,
|
|
552
489
|
});
|
|
553
490
|
self.resize(true);
|
|
554
491
|
self.draw(true);
|
|
@@ -561,7 +498,9 @@ export default function (self) {
|
|
|
561
498
|
* @param {number} index The index of the row to expand.
|
|
562
499
|
*/
|
|
563
500
|
self.expandTree = function (rowIndex) {
|
|
564
|
-
|
|
501
|
+
// copy so the caller's object is not mutated; `self.args` is empty in
|
|
502
|
+
// web-component mode, the value lives on the instance (#444)
|
|
503
|
+
var trArgs = Object.assign({}, self.treeGridAttributes || {}),
|
|
565
504
|
columnHeaderCellHeight = self.getColumnHeaderCellHeight(),
|
|
566
505
|
rowHeaderCellWidth =
|
|
567
506
|
self.sizes.columns.cornerCell || self.style.rowHeaderCellWidth,
|
|
@@ -584,7 +523,7 @@ export default function (self) {
|
|
|
584
523
|
offsetParent: self.intf.parentNode,
|
|
585
524
|
parentNode: self.intf.parentNode,
|
|
586
525
|
style: 'tree',
|
|
587
|
-
data: self.
|
|
526
|
+
data: self.viewData[rowIndex],
|
|
588
527
|
};
|
|
589
528
|
treeGrid = self.createGrid(trArgs);
|
|
590
529
|
self.childGrids[rowIndex] = treeGrid;
|
|
@@ -593,12 +532,15 @@ export default function (self) {
|
|
|
593
532
|
treeGrid.visible = true;
|
|
594
533
|
self.dispatchEvent('expandtree', {
|
|
595
534
|
treeGrid: treeGrid,
|
|
596
|
-
data: self.
|
|
535
|
+
data: self.viewData[rowIndex],
|
|
597
536
|
rowIndex: rowIndex,
|
|
598
537
|
});
|
|
599
538
|
self.openChildren[rowIndex] = treeGrid;
|
|
600
539
|
self.sizes.trees[rowIndex] = h;
|
|
601
|
-
self.
|
|
540
|
+
self.dispatchResizeRow({
|
|
541
|
+
height: self.style.cellHeight,
|
|
542
|
+
rowIndex: rowIndex,
|
|
543
|
+
});
|
|
602
544
|
self.resize(true);
|
|
603
545
|
};
|
|
604
546
|
/**
|
|
@@ -633,6 +575,101 @@ export default function (self) {
|
|
|
633
575
|
}
|
|
634
576
|
}
|
|
635
577
|
};
|
|
578
|
+
/**
|
|
579
|
+
* Hide column/columns
|
|
580
|
+
* @memberof canvasDatagrid
|
|
581
|
+
* @name hideColumns
|
|
582
|
+
* @method
|
|
583
|
+
* @param {number} beginColumnOrderIndex The begin column order index
|
|
584
|
+
* @param {number} [endColumnOrderIndex] The end column order index
|
|
585
|
+
*/
|
|
586
|
+
self.hideColumns = function (beginColumnOrderIndex, endColumnOrderIndex) {
|
|
587
|
+
const schema = self.getSchema();
|
|
588
|
+
const orders = self.orders.columns;
|
|
589
|
+
const hiddenColumns = [];
|
|
590
|
+
if (typeof endColumnOrderIndex !== 'number')
|
|
591
|
+
endColumnOrderIndex = beginColumnOrderIndex;
|
|
592
|
+
for (
|
|
593
|
+
let orderIndex = beginColumnOrderIndex;
|
|
594
|
+
orderIndex <= endColumnOrderIndex;
|
|
595
|
+
orderIndex++
|
|
596
|
+
) {
|
|
597
|
+
const columnIndex = orders[orderIndex];
|
|
598
|
+
if (columnIndex >= 0 && !schema[columnIndex].hidden) {
|
|
599
|
+
hiddenColumns.push(columnIndex);
|
|
600
|
+
schema[columnIndex].hidden = true;
|
|
601
|
+
|
|
602
|
+
self.dispatchEvent('columnhide', {
|
|
603
|
+
columnIndex,
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
if (hiddenColumns.length > 0) {
|
|
609
|
+
self.setStorageData();
|
|
610
|
+
setTimeout(function () {
|
|
611
|
+
self.resize(true);
|
|
612
|
+
}, 10);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
self.dispatchEvent('hidecolumns', {
|
|
616
|
+
hiddenColumns,
|
|
617
|
+
});
|
|
618
|
+
};
|
|
619
|
+
/**
|
|
620
|
+
* Unihde column/columns
|
|
621
|
+
* @memberof canvasDatagrid
|
|
622
|
+
* @name unhideColumns
|
|
623
|
+
* @method
|
|
624
|
+
* @param {number} beginColumnOrderIndex The begin column order index
|
|
625
|
+
* @param {number} [endColumnOrderIndex] The end column order index
|
|
626
|
+
*/
|
|
627
|
+
self.unhideColumns = function (beginColumnOrderIndex, endColumnOrderIndex) {
|
|
628
|
+
const orders = self.orders.columns;
|
|
629
|
+
const schema = self.getSchema();
|
|
630
|
+
|
|
631
|
+
for (let i = beginColumnOrderIndex; i <= endColumnOrderIndex; i++) {
|
|
632
|
+
const columnIndex = orders[i];
|
|
633
|
+
const s = schema[columnIndex];
|
|
634
|
+
|
|
635
|
+
if (s && s.hidden) {
|
|
636
|
+
s.hidden = false;
|
|
637
|
+
|
|
638
|
+
self.dispatchEvent('columnunhide', {
|
|
639
|
+
columnIndex,
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
self.refresh();
|
|
644
|
+
};
|
|
645
|
+
/**
|
|
646
|
+
* Hide rows
|
|
647
|
+
* @memberof canvasDatagrid
|
|
648
|
+
* @name hideRows
|
|
649
|
+
* @method
|
|
650
|
+
* @param {number} beginRowIndex The begin row index
|
|
651
|
+
* @param {number} endRowIndex The end row index
|
|
652
|
+
*/
|
|
653
|
+
self.hideRows = function (beginRowIndex, endRowIndex) {
|
|
654
|
+
if (
|
|
655
|
+
mergeHiddenRowRanges(self.hiddenRowRanges, [beginRowIndex, endRowIndex])
|
|
656
|
+
)
|
|
657
|
+
self.refresh();
|
|
658
|
+
};
|
|
659
|
+
/**
|
|
660
|
+
* Unhide rows
|
|
661
|
+
* @memberof canvasDatagrid
|
|
662
|
+
* @name unhideRows
|
|
663
|
+
* @method
|
|
664
|
+
* @param {number} beginRowIndex The begin row index
|
|
665
|
+
* @param {number} endRowIndex The end row index
|
|
666
|
+
*/
|
|
667
|
+
self.unhideRows = function (beginRowIndex, endRowIndex) {
|
|
668
|
+
self.hiddenRowRanges = self.hiddenRowRanges.filter(
|
|
669
|
+
(range) => range[0] !== beginRowIndex || range[1] !== endRowIndex,
|
|
670
|
+
);
|
|
671
|
+
self.refresh();
|
|
672
|
+
};
|
|
636
673
|
/**
|
|
637
674
|
* Resizes a column to fit the longest value in the column. Call without a value to resize all columns.
|
|
638
675
|
* Warning, can be slow on very large record sets (1m records ~3-5 seconds on an i7).
|
|
@@ -645,9 +682,39 @@ export default function (self) {
|
|
|
645
682
|
if (!self.canvas) {
|
|
646
683
|
return;
|
|
647
684
|
}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
685
|
+
|
|
686
|
+
if (name === undefined) {
|
|
687
|
+
// fit every column, as documented (#193)
|
|
688
|
+
self.getSchema().forEach(function (column) {
|
|
689
|
+
self.fitColumnToValues(column.name, true);
|
|
690
|
+
});
|
|
691
|
+
if (!internal) {
|
|
692
|
+
self.resize();
|
|
693
|
+
self.draw(true);
|
|
694
|
+
}
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
const header = name === 'cornerCell' ? null : self.getHeaderByName(name);
|
|
699
|
+
if (name !== 'cornerCell' && !header) {
|
|
700
|
+
console.warn('fitColumnToValues: no column named %s', name);
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
const columnIndex = name === 'cornerCell' ? -1 : header.index;
|
|
704
|
+
|
|
705
|
+
const newSize = Math.max(
|
|
706
|
+
self.findColumnMaxTextLength(name),
|
|
707
|
+
self.style.minColumnWidth,
|
|
708
|
+
);
|
|
709
|
+
|
|
710
|
+
self.sizes.columns[columnIndex] = newSize;
|
|
711
|
+
|
|
712
|
+
self.dispatchEvent('resizecolumn', {
|
|
713
|
+
x: newSize,
|
|
714
|
+
y: self.resizingStartingHeight,
|
|
715
|
+
draggingItem: self.currentCell,
|
|
716
|
+
});
|
|
717
|
+
|
|
651
718
|
if (!internal) {
|
|
652
719
|
self.resize();
|
|
653
720
|
self.draw(true);
|
|
@@ -700,6 +767,10 @@ export default function (self) {
|
|
|
700
767
|
sortFunction,
|
|
701
768
|
dontSetStorageData,
|
|
702
769
|
) {
|
|
770
|
+
if (!self.attributes.allowSorting) {
|
|
771
|
+
self.refresh();
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
703
774
|
var f,
|
|
704
775
|
c = self.getSchema().filter(function (col) {
|
|
705
776
|
return col.name === columnName;
|
|
@@ -714,7 +785,7 @@ export default function (self) {
|
|
|
714
785
|
}
|
|
715
786
|
self.orderBy = columnName;
|
|
716
787
|
self.orderDirection = direction;
|
|
717
|
-
if (!self.
|
|
788
|
+
if (!self.viewData || self.viewData.length === 0) {
|
|
718
789
|
return;
|
|
719
790
|
}
|
|
720
791
|
if (c.length === 0) {
|
|
@@ -732,41 +803,264 @@ export default function (self) {
|
|
|
732
803
|
direction,
|
|
733
804
|
typeof f === 'function' ? f : self.sorters.string,
|
|
734
805
|
);
|
|
735
|
-
self.
|
|
806
|
+
self.refresh();
|
|
736
807
|
self.dispatchEvent('sortcolumn', {
|
|
737
808
|
name: columnName,
|
|
738
809
|
direction: direction,
|
|
739
810
|
});
|
|
740
|
-
|
|
811
|
+
|
|
741
812
|
if (dontSetStorageData) {
|
|
742
813
|
return;
|
|
743
814
|
}
|
|
744
815
|
self.setStorageData();
|
|
745
816
|
};
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* Add grouping
|
|
820
|
+
* @param {'columns'|'rows'} groupFor
|
|
821
|
+
* @method
|
|
822
|
+
* @param {number} from
|
|
823
|
+
* @param {number} to
|
|
824
|
+
*/
|
|
825
|
+
function addGroup(groupFor, from, to) {
|
|
826
|
+
let newRow = false;
|
|
827
|
+
const allGroups =
|
|
828
|
+
groupFor === 'rows' ? self.groupedRows : self.groupedColumns;
|
|
829
|
+
for (let i = allGroups.length - 1; i >= 0; i--) {
|
|
830
|
+
const groups = allGroups[i];
|
|
831
|
+
const min = groups[0].from,
|
|
832
|
+
max = groups[groups.length - 1].to;
|
|
833
|
+
if (from <= min && to >= max) {
|
|
834
|
+
if (from === min && to === max && groups.length === 1) return; // nothings happened
|
|
835
|
+
// new group wrap this row
|
|
836
|
+
continue;
|
|
837
|
+
}
|
|
838
|
+
for (let gi = 0; gi < groups.length; gi++) {
|
|
839
|
+
const g = groups[gi];
|
|
840
|
+
if (from > g.to) continue;
|
|
841
|
+
if (from >= g.from) {
|
|
842
|
+
if (to > g.to) {
|
|
843
|
+
if (from === g.from) {
|
|
844
|
+
allGroups.splice(i, 0, [{ from, to, collapsed: false }]);
|
|
845
|
+
self.refresh();
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
throw new Error(`Can't group these ${groupFor}`);
|
|
849
|
+
}
|
|
850
|
+
if (to === g.to) {
|
|
851
|
+
if (from === g.from) return; // nothings happened
|
|
852
|
+
}
|
|
853
|
+
newRow = true;
|
|
854
|
+
break;
|
|
855
|
+
}
|
|
856
|
+
if (to >= g.from) {
|
|
857
|
+
if (to < g.to) throw new Error(`Can't group these ${groupFor}`);
|
|
858
|
+
allGroups.splice(i, 0, [{ from, to, collapsed: false }]);
|
|
859
|
+
} else {
|
|
860
|
+
groups.splice(gi, 0, { from, to, collapsed: false });
|
|
861
|
+
}
|
|
862
|
+
self.refresh();
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
865
|
+
if (newRow) continue;
|
|
866
|
+
groups.push({ from, to, collapsed: false });
|
|
867
|
+
self.refresh();
|
|
868
|
+
return;
|
|
749
869
|
}
|
|
750
|
-
|
|
870
|
+
if (newRow) allGroups.push([{ from, to, collapsed: false }]);
|
|
871
|
+
else allGroups.unshift([{ from, to, collapsed: false }]);
|
|
872
|
+
self.refresh();
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Remove grouping
|
|
876
|
+
* @param {Array<Array<{from:number,to:number,collapsed:boolean}>>} allGroups
|
|
877
|
+
* @method
|
|
878
|
+
* @param {number} from
|
|
879
|
+
* @param {number} to
|
|
880
|
+
*/
|
|
881
|
+
function removeGroup(allGroups, from, to) {
|
|
882
|
+
for (let i = 0; i < allGroups.length; i++) {
|
|
883
|
+
const groups = allGroups[i];
|
|
884
|
+
for (let gi = 0; gi < groups.length; gi++) {
|
|
885
|
+
const group = groups[gi];
|
|
886
|
+
if (group.from === from && group.to === to) {
|
|
887
|
+
if (groups.length <= 1) allGroups.splice(i, 1);
|
|
888
|
+
else groups.splice(gi, 1);
|
|
889
|
+
self.refresh();
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Grouping columns
|
|
897
|
+
* @memberof canvasDatagrid
|
|
898
|
+
* @name groupColumns
|
|
899
|
+
* @method
|
|
900
|
+
* @param {number|string} firstColumnName Name of the first column to be grouped.
|
|
901
|
+
* @param {number|string} lastColumnName Name of the last column to be grouped.
|
|
902
|
+
*/
|
|
903
|
+
self.groupColumns = function (firstColumnName, lastColumnName) {
|
|
904
|
+
/** @type {Array<{name: string,columnIndex:number}>} */
|
|
905
|
+
const schema = self.getSchema();
|
|
906
|
+
let firstOne, lastOne;
|
|
907
|
+
for (let i = 0; i < schema.length; i++) {
|
|
908
|
+
const it = schema[i];
|
|
909
|
+
if (firstOne && lastOne) break;
|
|
910
|
+
if (it.name === firstColumnName) {
|
|
911
|
+
firstOne = it;
|
|
912
|
+
continue;
|
|
913
|
+
}
|
|
914
|
+
if (it.name === lastColumnName) {
|
|
915
|
+
lastOne = it;
|
|
916
|
+
continue;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
if (!firstOne) throw new Error(`No such column name for first column`);
|
|
920
|
+
if (!lastOne) throw new Error(`No such column name for last column`);
|
|
921
|
+
if (lastOne.columnIndex > firstOne.columnIndex !== true)
|
|
922
|
+
throw new Error(`Can't group these columns`);
|
|
923
|
+
|
|
924
|
+
const from = firstOne.columnIndex;
|
|
925
|
+
const to = lastOne.columnIndex;
|
|
926
|
+
const ev = { group: { type: 'columns', from, to } };
|
|
927
|
+
try {
|
|
928
|
+
addGroup('columns', from, to);
|
|
929
|
+
} catch (error) {
|
|
930
|
+
ev.error = error;
|
|
931
|
+
}
|
|
932
|
+
self.dispatchEvent('aftercreategroup', ev);
|
|
751
933
|
};
|
|
752
934
|
/**
|
|
753
|
-
*
|
|
935
|
+
* Grouping columns
|
|
754
936
|
* @memberof canvasDatagrid
|
|
755
|
-
* @name
|
|
937
|
+
* @name groupRows
|
|
756
938
|
* @method
|
|
757
|
-
* @param {number}
|
|
758
|
-
* @param {number}
|
|
939
|
+
* @param {number} rowIndexFrom The row index which is the beginning of the group
|
|
940
|
+
* @param {number} rowIndexTo The row index which is the end of the group
|
|
759
941
|
*/
|
|
760
|
-
self.
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
942
|
+
self.groupRows = function (rowIndexFrom, rowIndexTo) {
|
|
943
|
+
if (!Number.isInteger(rowIndexFrom) || rowIndexFrom < 0)
|
|
944
|
+
throw new Error(`No such row for the beginning of the group`);
|
|
945
|
+
|
|
946
|
+
const dataLength = self.viewData.length;
|
|
947
|
+
if (
|
|
948
|
+
!Number.isInteger(rowIndexFrom) ||
|
|
949
|
+
rowIndexTo <= rowIndexFrom ||
|
|
950
|
+
rowIndexTo >= dataLength
|
|
951
|
+
)
|
|
952
|
+
throw new Error(`No such row for the end of the group`);
|
|
953
|
+
const ev = {
|
|
954
|
+
group: {
|
|
955
|
+
type: 'rows',
|
|
956
|
+
from: rowIndexFrom,
|
|
957
|
+
to: rowIndexTo,
|
|
958
|
+
},
|
|
959
|
+
};
|
|
960
|
+
try {
|
|
961
|
+
addGroup('rows', rowIndexFrom, rowIndexTo);
|
|
962
|
+
} catch (error) {
|
|
963
|
+
ev.error = error;
|
|
964
|
+
}
|
|
965
|
+
self.dispatchEvent('aftercreategroup', ev);
|
|
966
|
+
};
|
|
967
|
+
/**
|
|
968
|
+
* Remove grouping columns
|
|
969
|
+
* @memberof canvasDatagrid
|
|
970
|
+
* @name removeGroupColumns
|
|
971
|
+
* @method
|
|
972
|
+
* @param {number|string} firstColumnName Name of the first column to be grouped.
|
|
973
|
+
* @param {number|string} lastColumnName Name of the last column to be grouped.
|
|
974
|
+
*/
|
|
975
|
+
self.removeGroupColumns = function (firstColumnName, lastColumnName) {
|
|
976
|
+
/** @type {Array<{name:string,columnIndex:number}>} */
|
|
977
|
+
const schema = self.getSchema();
|
|
978
|
+
let firstOne, lastOne;
|
|
979
|
+
for (let i = 0; i < schema.length; i++) {
|
|
980
|
+
const it = schema[i];
|
|
981
|
+
if (firstOne && lastOne) break;
|
|
982
|
+
if (it.name === firstColumnName) {
|
|
983
|
+
firstOne = it;
|
|
984
|
+
continue;
|
|
985
|
+
}
|
|
986
|
+
if (it.name === lastColumnName) {
|
|
987
|
+
lastOne = it;
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
if (!firstOne) throw new Error(`No such column name for first column`);
|
|
992
|
+
if (!lastOne) throw new Error(`No such column name for last column`);
|
|
993
|
+
const from = firstOne.columnIndex;
|
|
994
|
+
const to = lastOne.columnIndex;
|
|
995
|
+
removeGroup(self.groupedColumns, from, to);
|
|
996
|
+
};
|
|
997
|
+
/**
|
|
998
|
+
* Remove grouping columns
|
|
999
|
+
* @memberof canvasDatagrid
|
|
1000
|
+
* @name removeGroupRows
|
|
1001
|
+
* @method
|
|
1002
|
+
* @param {number} rowIndexFrom The row index which is the beginning of the group
|
|
1003
|
+
* @param {number} rowIndexTo The row index which is the end of the group
|
|
1004
|
+
*/
|
|
1005
|
+
self.removeGroupRows = function (rowIndexFrom, rowIndexTo) {
|
|
1006
|
+
removeGroup(self.groupedRows, rowIndexFrom, rowIndexTo);
|
|
1007
|
+
};
|
|
1008
|
+
/**
|
|
1009
|
+
* Toggle(expand/collapsed) grouping columns
|
|
1010
|
+
* @memberof canvasDatagrid
|
|
1011
|
+
* @name toggleGroupColumns
|
|
1012
|
+
* @method
|
|
1013
|
+
* @param {number|string} firstColumnName Name of the first column to be grouped.
|
|
1014
|
+
* @param {number|string} lastColumnName Name of the last column to be grouped.
|
|
1015
|
+
*/
|
|
1016
|
+
self.toggleGroupColumns = function (firstColumnName, lastColumnName) {
|
|
1017
|
+
/** @type {Array<{name:string,columnIndex:number}>} */
|
|
1018
|
+
const schema = self.getSchema();
|
|
1019
|
+
let firstOne, lastOne;
|
|
1020
|
+
for (let i = 0; i < schema.length; i++) {
|
|
1021
|
+
const it = schema[i];
|
|
1022
|
+
if (firstOne && lastOne) break;
|
|
1023
|
+
if (it.name === firstColumnName) {
|
|
1024
|
+
firstOne = it;
|
|
1025
|
+
continue;
|
|
1026
|
+
}
|
|
1027
|
+
if (it.name === lastColumnName) {
|
|
1028
|
+
lastOne = it;
|
|
1029
|
+
continue;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
if (!firstOne || !lastOne) return;
|
|
1033
|
+
const from = firstOne.columnIndex;
|
|
1034
|
+
const to = lastOne.columnIndex;
|
|
1035
|
+
if (self.toggleGroup({ type: 'c', from, to })) {
|
|
1036
|
+
self.disposeContextMenu();
|
|
1037
|
+
self.setStorageData();
|
|
1038
|
+
self.refresh();
|
|
1039
|
+
}
|
|
769
1040
|
};
|
|
1041
|
+
/**
|
|
1042
|
+
* Toggle(expand/collapsed) grouping rows
|
|
1043
|
+
* @memberof canvasDatagrid
|
|
1044
|
+
* @name toggleGroupRows
|
|
1045
|
+
* @method
|
|
1046
|
+
* @param {number} rowIndexFrom The row index which is the beginning of the group
|
|
1047
|
+
* @param {number} rowIndexTo The row index which is the end of the group
|
|
1048
|
+
*/
|
|
1049
|
+
self.toggleGroupRows = function (rowIndexFrom, rowIndexTo) {
|
|
1050
|
+
if (self.toggleGroup({ type: 'r', from: rowIndexFrom, to: rowIndexTo })) {
|
|
1051
|
+
self.disposeContextMenu();
|
|
1052
|
+
self.setStorageData();
|
|
1053
|
+
self.refresh();
|
|
1054
|
+
}
|
|
1055
|
+
};
|
|
1056
|
+
|
|
1057
|
+
self.isInGrid = function (e) {
|
|
1058
|
+
if (e.x < 0 || e.x > self.width || e.y < 0 || e.y > self.height) {
|
|
1059
|
+
return false;
|
|
1060
|
+
}
|
|
1061
|
+
return true;
|
|
1062
|
+
};
|
|
1063
|
+
|
|
770
1064
|
/**
|
|
771
1065
|
* Moves data in the provided selection to another position in the grid. Moving data off the edge of the schema (columns/x) will truncate data.
|
|
772
1066
|
* @memberof canvasDatagrid
|
|
@@ -777,15 +1071,21 @@ export default function (self) {
|
|
|
777
1071
|
* @param {number} y The row index to start inserting the selection at.
|
|
778
1072
|
*/
|
|
779
1073
|
self.moveTo = function (sel, x, y) {
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
1074
|
+
// TODO: optimize this function,
|
|
1075
|
+
// we just transform the `sel` to obselete selection matrix
|
|
1076
|
+
sel = self.getObsoleteSelectionMatrix(sel);
|
|
1077
|
+
|
|
1078
|
+
// TODO: this function is not migrated done
|
|
1079
|
+
var selectedData = self.getSelectedData(),
|
|
1080
|
+
visibleSchema = self.getVisibleSchema(),
|
|
1081
|
+
selectionLength = sel.length,
|
|
783
1082
|
xi,
|
|
784
1083
|
maxRowLength = -Infinity,
|
|
785
1084
|
minXi = Infinity,
|
|
786
1085
|
yi = y - 1;
|
|
787
|
-
|
|
788
|
-
|
|
1086
|
+
|
|
1087
|
+
sel.forEach(function (row, rowIndex) {
|
|
1088
|
+
if (rowIndex === selectionLength) {
|
|
789
1089
|
return;
|
|
790
1090
|
}
|
|
791
1091
|
if (row.length === 0) {
|
|
@@ -796,15 +1096,21 @@ export default function (self) {
|
|
|
796
1096
|
row.forEach(function (colIndex) {
|
|
797
1097
|
// intentional redef of colIndex
|
|
798
1098
|
colIndex = self.getVisibleColumnIndexOf(colIndex);
|
|
799
|
-
if (!
|
|
1099
|
+
if (!visibleSchema[colIndex]) {
|
|
800
1100
|
return;
|
|
801
1101
|
}
|
|
802
|
-
|
|
803
|
-
|
|
1102
|
+
// TODO:
|
|
1103
|
+
if (!self.data) {
|
|
1104
|
+
self.data = {};
|
|
1105
|
+
}
|
|
1106
|
+
if (!self.data[rowIndex]) {
|
|
1107
|
+
self.data[rowIndex] = {};
|
|
804
1108
|
}
|
|
805
|
-
|
|
1109
|
+
// TODO:
|
|
1110
|
+
self.data[rowIndex][visibleSchema[colIndex].name] = null;
|
|
806
1111
|
});
|
|
807
1112
|
});
|
|
1113
|
+
|
|
808
1114
|
sel.forEach(function (row, index) {
|
|
809
1115
|
var lastSourceIndex;
|
|
810
1116
|
yi += 1;
|
|
@@ -819,20 +1125,71 @@ export default function (self) {
|
|
|
819
1125
|
lastSourceIndex = colIndex;
|
|
820
1126
|
if (
|
|
821
1127
|
colIndex === -1 ||
|
|
822
|
-
!
|
|
823
|
-
!
|
|
1128
|
+
!visibleSchema[xi] ||
|
|
1129
|
+
!visibleSchema[colIndex] ||
|
|
1130
|
+
// TODO:
|
|
824
1131
|
self.data.length - 1 < yi ||
|
|
825
1132
|
yi < 0
|
|
826
1133
|
) {
|
|
827
1134
|
return;
|
|
828
1135
|
}
|
|
1136
|
+
// TODO:
|
|
829
1137
|
if (!self.data[yi]) {
|
|
830
1138
|
self.data[yi] = {};
|
|
831
1139
|
}
|
|
832
|
-
|
|
1140
|
+
// TODO:
|
|
1141
|
+
self.data[yi][visibleSchema[xi].name] =
|
|
1142
|
+
selectedData[index][visibleSchema[colIndex].name];
|
|
833
1143
|
});
|
|
834
1144
|
});
|
|
835
1145
|
};
|
|
1146
|
+
/**
|
|
1147
|
+
* Get the column group info given column belongs to
|
|
1148
|
+
* @memberof canvasDatagrid
|
|
1149
|
+
* @name getGroupsColumnBelongsTo
|
|
1150
|
+
* @method
|
|
1151
|
+
* @param {number} columnIndex Column index.
|
|
1152
|
+
* @returns {Array<{from:number,to:number,collapsed:boolean}>}
|
|
1153
|
+
*/
|
|
1154
|
+
self.getGroupsColumnBelongsTo = function (columnIndex) {
|
|
1155
|
+
if (!self.attributes.allowGroupingColumns) return [];
|
|
1156
|
+
const result = [];
|
|
1157
|
+
for (let i = 0; i < self.groupedColumns.length; i++) {
|
|
1158
|
+
const groups = self.groupedColumns[i];
|
|
1159
|
+
for (let j = 0; j < groups.length; j++) {
|
|
1160
|
+
const group = groups[j];
|
|
1161
|
+
if (columnIndex >= group.from && columnIndex <= group.to) {
|
|
1162
|
+
result.push(group);
|
|
1163
|
+
break;
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
return result;
|
|
1168
|
+
};
|
|
1169
|
+
/**
|
|
1170
|
+
* Get the row group info given row belongs to
|
|
1171
|
+
* @memberof canvasDatagrid
|
|
1172
|
+
* @name getGroupsRowBelongsTo
|
|
1173
|
+
* @method
|
|
1174
|
+
* @param {number} rowIndex Row index.
|
|
1175
|
+
* @returns {Array<{from:number,to:number,collapsed:boolean}>}
|
|
1176
|
+
*/
|
|
1177
|
+
self.getGroupsRowBelongsTo = function (rowIndex) {
|
|
1178
|
+
if (!self.attributes.allowGroupingRows) return [];
|
|
1179
|
+
const result = [];
|
|
1180
|
+
for (let i = 0; i < self.groupedRows.length; i++) {
|
|
1181
|
+
const groups = self.groupedRows[i];
|
|
1182
|
+
for (let j = 0; j < groups.length; j++) {
|
|
1183
|
+
const group = groups[j];
|
|
1184
|
+
if (rowIndex >= group.from && rowIndex <= group.to) {
|
|
1185
|
+
result.push(group);
|
|
1186
|
+
break;
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
return result;
|
|
1191
|
+
};
|
|
1192
|
+
|
|
836
1193
|
/**
|
|
837
1194
|
* Checks if a given column is visible.
|
|
838
1195
|
* @memberof canvasDatagrid
|
|
@@ -877,6 +1234,66 @@ export default function (self) {
|
|
|
877
1234
|
return c.columnIndex === x && c.rowIndex === y;
|
|
878
1235
|
})[0];
|
|
879
1236
|
};
|
|
1237
|
+
/**
|
|
1238
|
+
* Get an unhide indicator at grid pixel coordinate x and y.
|
|
1239
|
+
* @memberof canvasDatagrid
|
|
1240
|
+
* @name getUnhideIndicator
|
|
1241
|
+
* @method
|
|
1242
|
+
* @param {number} x Number of pixels from the left.
|
|
1243
|
+
* @param {number} y Number of pixels from the top.
|
|
1244
|
+
*/
|
|
1245
|
+
self.getUnhideIndicator = function (x, y) {
|
|
1246
|
+
const indicators = self.visibleUnhideIndicators;
|
|
1247
|
+
if (indicators.length <= 0) return;
|
|
1248
|
+
for (let i = 0; i < indicators.length; i++) {
|
|
1249
|
+
const indicator = indicators[i];
|
|
1250
|
+
if (
|
|
1251
|
+
x >= indicator.x &&
|
|
1252
|
+
y >= indicator.y &&
|
|
1253
|
+
x <= indicator.x2 &&
|
|
1254
|
+
y <= indicator.y2
|
|
1255
|
+
)
|
|
1256
|
+
return indicator;
|
|
1257
|
+
}
|
|
1258
|
+
};
|
|
1259
|
+
/**
|
|
1260
|
+
* Get a column group at grid pixel coordinate x and y.
|
|
1261
|
+
* @memberof canvasDatagrid
|
|
1262
|
+
* @name getColumnGroupAt
|
|
1263
|
+
* @method
|
|
1264
|
+
* @param {number} x Number of pixels from the left.
|
|
1265
|
+
* @param {number} y Number of pixels from the top.
|
|
1266
|
+
*/
|
|
1267
|
+
self.getColumnGroupAt = function (x, y) {
|
|
1268
|
+
const groups = self.groupedColumns.length;
|
|
1269
|
+
if (groups <= 0) return;
|
|
1270
|
+
const yZero = self.getColumnGroupAreaHeight();
|
|
1271
|
+
if (y >= yZero) return;
|
|
1272
|
+
for (let i = 0; i < self.visibleGroups.length; i++) {
|
|
1273
|
+
const g = self.visibleGroups[i];
|
|
1274
|
+
if (g.type !== 'c') continue;
|
|
1275
|
+
if (x >= g.x && y >= g.y && x <= g.x2 && y <= g.y2) return g;
|
|
1276
|
+
}
|
|
1277
|
+
};
|
|
1278
|
+
/**
|
|
1279
|
+
* Get a row group at grid pixel coordinate x and y.
|
|
1280
|
+
* @memberof canvasDatagrid
|
|
1281
|
+
* @name getRowGroupAt
|
|
1282
|
+
* @method
|
|
1283
|
+
* @param {number} x Number of pixels from the left.
|
|
1284
|
+
* @param {number} y Number of pixels from the top.
|
|
1285
|
+
*/
|
|
1286
|
+
self.getRowGroupAt = function (x, y) {
|
|
1287
|
+
const groups = self.groupedRows.length;
|
|
1288
|
+
if (groups <= 0) return;
|
|
1289
|
+
const xZero = self.getRowGroupAreaWidth();
|
|
1290
|
+
if (x >= xZero) return;
|
|
1291
|
+
for (let i = 0; i < self.visibleGroups.length; i++) {
|
|
1292
|
+
const g = self.visibleGroups[i];
|
|
1293
|
+
if (g.type !== 'r') continue;
|
|
1294
|
+
if (x >= g.x && y >= g.y && x <= g.x2 && y <= g.y2) return g;
|
|
1295
|
+
}
|
|
1296
|
+
};
|
|
880
1297
|
/**
|
|
881
1298
|
* Gets the cell at grid pixel coordinate x and y. Author's note. This function ties drawing and events together. This is a very complex function and is core to the component.
|
|
882
1299
|
* @memberof canvasDatagrid
|
|
@@ -918,6 +1335,16 @@ export default function (self) {
|
|
|
918
1335
|
if (!self.visibleCells) {
|
|
919
1336
|
return;
|
|
920
1337
|
}
|
|
1338
|
+
x -= self.getRowGroupAreaWidth();
|
|
1339
|
+
y -= self.getColumnGroupAreaHeight();
|
|
1340
|
+
|
|
1341
|
+
if (self.dragStartObject !== undefined) {
|
|
1342
|
+
if (x <= 0) x = 1;
|
|
1343
|
+
if (x >= self.width) x = self.width - 1;
|
|
1344
|
+
if (y <= 0) y = 1;
|
|
1345
|
+
if (y >= self.height) y = self.height - 1;
|
|
1346
|
+
}
|
|
1347
|
+
|
|
921
1348
|
var border,
|
|
922
1349
|
tsz = useTouchScrollZones ? self.attributes.touchScrollZone : 0,
|
|
923
1350
|
moveMode = self.attributes.borderDragBehavior === 'move',
|
|
@@ -964,13 +1391,15 @@ export default function (self) {
|
|
|
964
1391
|
entitiy.y + entitiy.height + self.style.cellBorderWidth > y
|
|
965
1392
|
) {
|
|
966
1393
|
if (/frozen-row-marker/.test(cell.style)) {
|
|
1394
|
+
if (self.dragMode === 'frozen-column-marker') continue;
|
|
967
1395
|
cell.dragContext = cell.style;
|
|
968
|
-
cell.context = '
|
|
1396
|
+
cell.context = 'grab';
|
|
969
1397
|
return cell;
|
|
970
1398
|
}
|
|
971
1399
|
if (/frozen-column-marker/.test(cell.style)) {
|
|
1400
|
+
if (self.dragMode === 'frozen-row-marker') continue;
|
|
972
1401
|
cell.dragContext = cell.style;
|
|
973
|
-
cell.context = '
|
|
1402
|
+
cell.context = 'grab';
|
|
974
1403
|
return cell;
|
|
975
1404
|
}
|
|
976
1405
|
if (/selection-handle-/.test(cell.style)) {
|
|
@@ -1017,6 +1446,11 @@ export default function (self) {
|
|
|
1017
1446
|
if (
|
|
1018
1447
|
['l', 'r'].indexOf(border) !== -1 &&
|
|
1019
1448
|
(self.attributes.allowColumnResize || moveBorder) &&
|
|
1449
|
+
!(
|
|
1450
|
+
self.attributes.fillLastColumn &&
|
|
1451
|
+
border === 'r' &&
|
|
1452
|
+
cell.sortColumnIndex === self.getLastVisibleColumnIndex()
|
|
1453
|
+
) &&
|
|
1020
1454
|
((self.attributes.allowColumnResizeFromCell && cell.isNormal) ||
|
|
1021
1455
|
!cell.isNormal ||
|
|
1022
1456
|
moveBorder) &&
|
|
@@ -1066,15 +1500,29 @@ export default function (self) {
|
|
|
1066
1500
|
}
|
|
1067
1501
|
}
|
|
1068
1502
|
if (cell.style === 'columnHeaderCell') {
|
|
1069
|
-
|
|
1070
|
-
|
|
1503
|
+
if (
|
|
1504
|
+
(!self.isColumnSelected(cell.columnIndex) &&
|
|
1505
|
+
cell.x +
|
|
1506
|
+
cell.width -
|
|
1507
|
+
self.attributes.columnGrabZoneSize -
|
|
1508
|
+
self.style.cellBorderWidth >
|
|
1509
|
+
x) ||
|
|
1510
|
+
!self.attributes.allowColumnReordering
|
|
1511
|
+
) {
|
|
1512
|
+
cell.dragContext = 'cell';
|
|
1513
|
+
cell.context = 'cell';
|
|
1514
|
+
} else {
|
|
1515
|
+
cell.context = self.cursorGrab;
|
|
1516
|
+
cell.dragContext = 'column-reorder';
|
|
1517
|
+
}
|
|
1071
1518
|
return cell;
|
|
1072
1519
|
}
|
|
1073
1520
|
if (cell.style === 'rowHeaderCell') {
|
|
1074
1521
|
if (
|
|
1075
|
-
self.
|
|
1076
|
-
|
|
1077
|
-
|
|
1522
|
+
(!self.isRowSelected(cell.rowIndex) &&
|
|
1523
|
+
self.attributes.rowGrabZoneSize +
|
|
1524
|
+
(cell.y - self.style.cellBorderWidth) <
|
|
1525
|
+
y) ||
|
|
1078
1526
|
!self.attributes.allowRowReordering
|
|
1079
1527
|
) {
|
|
1080
1528
|
cell.dragContext = 'cell';
|
|
@@ -1111,32 +1559,6 @@ export default function (self) {
|
|
|
1111
1559
|
isBackground: true,
|
|
1112
1560
|
};
|
|
1113
1561
|
};
|
|
1114
|
-
/**
|
|
1115
|
-
* Gets the bounds of current selection.
|
|
1116
|
-
* @returns {rect} selection.
|
|
1117
|
-
* @memberof canvasDatagrid
|
|
1118
|
-
* @name getSelectionBounds
|
|
1119
|
-
* @method
|
|
1120
|
-
*/
|
|
1121
|
-
self.getSelectionBounds = function () {
|
|
1122
|
-
var low = { x: Infinity, y: Infinity },
|
|
1123
|
-
high = { x: -Infinity, y: -Infinity };
|
|
1124
|
-
self.selections.forEach(function (row, rowIndex) {
|
|
1125
|
-
var maxCol, minCol;
|
|
1126
|
-
low.y = rowIndex < low.y ? rowIndex : low.y;
|
|
1127
|
-
high.y = rowIndex > high.y ? rowIndex : high.y;
|
|
1128
|
-
maxCol = Math.max.apply(null, row);
|
|
1129
|
-
minCol = Math.min.apply(null, row);
|
|
1130
|
-
low.x = minCol < low.x ? minCol : low.x;
|
|
1131
|
-
high.x = maxCol > high.x ? maxCol : high.x;
|
|
1132
|
-
});
|
|
1133
|
-
return {
|
|
1134
|
-
top: low.y,
|
|
1135
|
-
left: low.x,
|
|
1136
|
-
bottom: high.y,
|
|
1137
|
-
right: high.x,
|
|
1138
|
-
};
|
|
1139
|
-
};
|
|
1140
1562
|
/**
|
|
1141
1563
|
* Returns an auto generated schema based on data structure.
|
|
1142
1564
|
* @memberof canvasDatagrid
|
|
@@ -1146,7 +1568,7 @@ export default function (self) {
|
|
|
1146
1568
|
* @returns {schema} schema A schema based on the first item in the data array.
|
|
1147
1569
|
*/
|
|
1148
1570
|
self.getSchemaFromData = function (d) {
|
|
1149
|
-
d = d || self.
|
|
1571
|
+
d = d || self.originalData;
|
|
1150
1572
|
return Object.keys(d[0] || { ' ': '' }).map(function mapEachSchemaColumn(
|
|
1151
1573
|
key,
|
|
1152
1574
|
index,
|
|
@@ -1183,57 +1605,6 @@ export default function (self) {
|
|
|
1183
1605
|
self.clearChangeLog = function () {
|
|
1184
1606
|
self.changes = [];
|
|
1185
1607
|
};
|
|
1186
|
-
/**
|
|
1187
|
-
* Selects an area of the grid.
|
|
1188
|
-
* @memberof canvasDatagrid
|
|
1189
|
-
* @name selectArea
|
|
1190
|
-
* @method
|
|
1191
|
-
* @param {rect} bounds A rect object representing the selected values.
|
|
1192
|
-
*/
|
|
1193
|
-
self.selectArea = function (bounds, ctrl) {
|
|
1194
|
-
self.selectionBounds = bounds || self.selectionBounds;
|
|
1195
|
-
var ev,
|
|
1196
|
-
x,
|
|
1197
|
-
y,
|
|
1198
|
-
s = self.getSchema();
|
|
1199
|
-
if (!ctrl) {
|
|
1200
|
-
self.selections = [];
|
|
1201
|
-
}
|
|
1202
|
-
if (
|
|
1203
|
-
self.selectionBounds.top < -1 ||
|
|
1204
|
-
self.selectionBounds.bottom > self.data.length ||
|
|
1205
|
-
self.selectionBounds.left < -1 ||
|
|
1206
|
-
self.selectionBounds.right > s.length
|
|
1207
|
-
) {
|
|
1208
|
-
throw new Error('Impossible selection area');
|
|
1209
|
-
}
|
|
1210
|
-
for (
|
|
1211
|
-
x = self.selectionBounds.top;
|
|
1212
|
-
x <= self.selectionBounds.bottom;
|
|
1213
|
-
x += 1
|
|
1214
|
-
) {
|
|
1215
|
-
self.selections[x] = [];
|
|
1216
|
-
for (
|
|
1217
|
-
y = self.selectionBounds.left;
|
|
1218
|
-
y <= self.selectionBounds.right;
|
|
1219
|
-
y += 1
|
|
1220
|
-
) {
|
|
1221
|
-
if (self.selections[x].indexOf(y) === -1) {
|
|
1222
|
-
self.selections[x].push(y);
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
ev = {
|
|
1227
|
-
selections: self.selections,
|
|
1228
|
-
selectionBounds: self.selectionBounds,
|
|
1229
|
-
};
|
|
1230
|
-
Object.defineProperty(ev, 'selectedData', {
|
|
1231
|
-
get: function () {
|
|
1232
|
-
return self.getSelectedData();
|
|
1233
|
-
},
|
|
1234
|
-
});
|
|
1235
|
-
self.dispatchEvent('selectionchanged', ev);
|
|
1236
|
-
};
|
|
1237
1608
|
/**
|
|
1238
1609
|
* Returns the maximum text width for a given column by column name.
|
|
1239
1610
|
* @memberof canvasDatagrid
|
|
@@ -1248,7 +1619,9 @@ export default function (self) {
|
|
|
1248
1619
|
self.ctx.font = self.style.rowHeaderCellFont;
|
|
1249
1620
|
return (
|
|
1250
1621
|
self.ctx.measureText(
|
|
1251
|
-
(
|
|
1622
|
+
(
|
|
1623
|
+
self.viewData.length + (self.attributes.showNewRow ? 1 : 0)
|
|
1624
|
+
).toString(),
|
|
1252
1625
|
).width +
|
|
1253
1626
|
self.style.autosizePadding +
|
|
1254
1627
|
self.style.autosizeHeaderCellPadding +
|
|
@@ -1269,12 +1642,13 @@ export default function (self) {
|
|
|
1269
1642
|
self.ctx.font = self.style.columnHeaderCellFont;
|
|
1270
1643
|
var t =
|
|
1271
1644
|
self.ctx.measureText(col.title || col.name).width +
|
|
1272
|
-
self.style.
|
|
1273
|
-
self.style.
|
|
1645
|
+
self.style.columnHeaderCellPaddingRight +
|
|
1646
|
+
self.style.columnHeaderCellPaddingLeft +
|
|
1647
|
+
self.style.cellAutoResizePadding;
|
|
1274
1648
|
m = t > m ? t : m;
|
|
1275
1649
|
formatter = self.formatters[col.type];
|
|
1276
1650
|
});
|
|
1277
|
-
self.
|
|
1651
|
+
self.viewData.forEach(function (row) {
|
|
1278
1652
|
var text = row[name];
|
|
1279
1653
|
if (formatter) {
|
|
1280
1654
|
text = formatter({ cell: { value: text } });
|
|
@@ -1313,16 +1687,46 @@ export default function (self) {
|
|
|
1313
1687
|
/**
|
|
1314
1688
|
* Gets the width of a column by index.
|
|
1315
1689
|
* @memberof canvasDatagrid
|
|
1316
|
-
* @name
|
|
1690
|
+
* @name getColumnWidth
|
|
1317
1691
|
* @method
|
|
1318
1692
|
* @param {number} columnIndex The column index to lookup.
|
|
1319
1693
|
*/
|
|
1320
|
-
self.
|
|
1321
|
-
|
|
1694
|
+
self.getColumnWidth = function (columnIndex) {
|
|
1695
|
+
const column = self.getSchema()[columnIndex] || {};
|
|
1696
|
+
const configuredWidth =
|
|
1322
1697
|
(self.sizes.columns[columnIndex] ||
|
|
1323
|
-
|
|
1324
|
-
self.style.cellWidth) * self.scale
|
|
1325
|
-
|
|
1698
|
+
column.width ||
|
|
1699
|
+
self.style.cellWidth) * self.scale;
|
|
1700
|
+
if (
|
|
1701
|
+
self.autoLastColumnWidth &&
|
|
1702
|
+
self.autoLastColumnWidth.index === columnIndex
|
|
1703
|
+
) {
|
|
1704
|
+
return Math.max(configuredWidth, self.autoLastColumnWidth.width);
|
|
1705
|
+
}
|
|
1706
|
+
return configuredWidth;
|
|
1707
|
+
};
|
|
1708
|
+
self.getLastVisibleColumnIndex = function () {
|
|
1709
|
+
const schema = self.getSchema();
|
|
1710
|
+
const collapsedColumnGroups = self.getCollapsedColumnGroups();
|
|
1711
|
+
const isColumnCollapsed = (columnIndex) =>
|
|
1712
|
+
collapsedColumnGroups.some(
|
|
1713
|
+
(group) => columnIndex >= group.from && columnIndex <= group.to,
|
|
1714
|
+
);
|
|
1715
|
+
for (
|
|
1716
|
+
let viewIndex = self.orders.columns.length - 1;
|
|
1717
|
+
viewIndex >= 0;
|
|
1718
|
+
viewIndex -= 1
|
|
1719
|
+
) {
|
|
1720
|
+
const schemaIndex = self.orders.columns[viewIndex];
|
|
1721
|
+
if (
|
|
1722
|
+
schema[schemaIndex] &&
|
|
1723
|
+
!schema[schemaIndex].hidden &&
|
|
1724
|
+
!isColumnCollapsed(viewIndex)
|
|
1725
|
+
) {
|
|
1726
|
+
return schemaIndex;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
return -1;
|
|
1326
1730
|
};
|
|
1327
1731
|
self.formatters.string = function cellFormatterString(e) {
|
|
1328
1732
|
return e.cell.value !== undefined ? e.cell.value : '';
|
|
@@ -1334,23 +1738,15 @@ export default function (self) {
|
|
|
1334
1738
|
self.formatters.html = self.formatters.string;
|
|
1335
1739
|
self.sorters.string = function (columnName, direction) {
|
|
1336
1740
|
var asc = direction === 'asc';
|
|
1741
|
+
// Coerce every value to a string so numbers, booleans and blanks sort
|
|
1742
|
+
// consistently (blanks first ascending, last descending) (#256, #548).
|
|
1743
|
+
function toComparable(value) {
|
|
1744
|
+
return value === undefined || value === null ? '' : String(value);
|
|
1745
|
+
}
|
|
1337
1746
|
return function (a, b) {
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
if (b[columnName] === undefined || b[columnName] === null) {
|
|
1342
|
-
return 0;
|
|
1343
|
-
}
|
|
1344
|
-
if (asc) {
|
|
1345
|
-
if (!a[columnName].localeCompare) {
|
|
1346
|
-
return 1;
|
|
1347
|
-
}
|
|
1348
|
-
return a[columnName].localeCompare(b[columnName]);
|
|
1349
|
-
}
|
|
1350
|
-
if (!b[columnName].localeCompare) {
|
|
1351
|
-
return 1;
|
|
1352
|
-
}
|
|
1353
|
-
return b[columnName].localeCompare(a[columnName]);
|
|
1747
|
+
const aValue = toComparable(a[columnName]);
|
|
1748
|
+
const bValue = toComparable(b[columnName]);
|
|
1749
|
+
return asc ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
|
|
1354
1750
|
};
|
|
1355
1751
|
};
|
|
1356
1752
|
self.sorters.number = function (columnName, direction) {
|