canvas-datagrid 0.3.12 → 0.3.16
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 +29 -0
- package/dist/canvas-datagrid.debug.js +349 -103
- 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 +2 -0
- package/lib/defaults.js +1 -0
- package/lib/docs.js +3 -0
- package/lib/draw.js +8 -6
- package/lib/{events.js → events/index.js} +58 -60
- package/lib/events/util.js +96 -0
- package/lib/intf.js +52 -0
- package/lib/publicMethods.js +10 -10
- package/package.json +1 -1
package/dist/types.d.ts
CHANGED
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
* @param [args.pageUpDownOverlap = 1] - Amount of rows to overlap when pageup/pagedown is used.
|
|
79
79
|
* @param [args.persistantSelectionMode = false] - When true, selections will behave as if the command/control key is held down at all times. Conflicts with singleSelectionMode.
|
|
80
80
|
* @param [args.singleSelectionMode = false] - When true, selections will ignore the command/control key. Conflicts with persistantSelectionMode.
|
|
81
|
+
* @param [args.keepFocusOnMouseOut = false] - When true, grid will continue to handle keydown events when mouse is outside of the grid.
|
|
81
82
|
* @param [args.selectionMode = 'cell'] - Can be 'cell', or 'row'. This setting dictates what will be selected when the user clicks a cell. The cell, or the entire row respectively.
|
|
82
83
|
* @param [args.hoverMode = 'cell'] - Can be 'cell', or 'row'. This setting dictates whether to highlight either the individual cell, or the entire row when hovering over a cell.
|
|
83
84
|
* @param [args.autoResizeColumns = false] - When true, all columns will be automatically resized to fit the data in them. Warning! Expensive for large (>100k ~2 seconds) datasets.
|
|
@@ -166,6 +167,7 @@ declare class canvasDatagrid {
|
|
|
166
167
|
pageUpDownOverlap?: number;
|
|
167
168
|
persistantSelectionMode?: boolean;
|
|
168
169
|
singleSelectionMode?: boolean;
|
|
170
|
+
keepFocusOnMouseOut?: boolean;
|
|
169
171
|
selectionMode?: string;
|
|
170
172
|
hoverMode?: string;
|
|
171
173
|
autoResizeColumns?: boolean;
|
package/lib/defaults.js
CHANGED
package/lib/docs.js
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
* @param {number} [args.pageUpDownOverlap=1] - Amount of rows to overlap when pageup/pagedown is used.
|
|
42
42
|
* @param {boolean} [args.persistantSelectionMode=false] - When true, selections will behave as if the command/control key is held down at all times. Conflicts with singleSelectionMode.
|
|
43
43
|
* @param {boolean} [args.singleSelectionMode=false] - When true, selections will ignore the command/control key. Conflicts with persistantSelectionMode.
|
|
44
|
+
* @param {boolean} [args.keepFocusOnMouseOut=false] - When true, grid will continue to handle keydown events when mouse is outside of the grid.
|
|
44
45
|
* @param {string} [args.selectionMode='cell'] - Can be 'cell', or 'row'. This setting dictates what will be selected when the user clicks a cell. The cell, or the entire row respectively.
|
|
45
46
|
* @param {string} [args.hoverMode='cell'] - Can be 'cell', or 'row'. This setting dictates whether to highlight either the individual cell, or the entire row when hovering over a cell.
|
|
46
47
|
* @param {boolean} [args.autoResizeColumns=false] - When true, all columns will be automatically resized to fit the data in them. Warning! Expensive for large (>100k ~2 seconds) datasets.
|
|
@@ -456,6 +457,8 @@
|
|
|
456
457
|
* @param {object} e.selectedData Selected data.
|
|
457
458
|
* @param {array} e.selections Selections object. 2D matrix of selections.
|
|
458
459
|
* @param {rectangle} e.selectionBounds rectangle object describing the selection bounds.
|
|
460
|
+
* @param {object} e.boundRowIndexMap Mapping of view data row to bound data row index.
|
|
461
|
+
* @param {object} e.boundColumnIndexMap Mapping of view column order to bound column order.
|
|
459
462
|
*/
|
|
460
463
|
/**
|
|
461
464
|
* Fires when the user clicks on the "drill in" arrow. When the arrow is clicked a new
|
package/lib/draw.js
CHANGED
|
@@ -122,15 +122,15 @@ export default function (self) {
|
|
|
122
122
|
x = x + ml;
|
|
123
123
|
y = y + mt;
|
|
124
124
|
if (self.orderDirection === 'asc') {
|
|
125
|
-
self.ctx.moveTo(x, y);
|
|
126
|
-
self.ctx.lineTo(x + aw, y);
|
|
127
|
-
self.ctx.lineTo(x + aw * 0.5, y + ah);
|
|
128
|
-
self.ctx.moveTo(x, y);
|
|
129
|
-
} else {
|
|
130
125
|
self.ctx.lineTo(x, y + ah);
|
|
131
126
|
self.ctx.lineTo(x + aw, y + ah);
|
|
132
127
|
self.ctx.lineTo(x + aw * 0.5, y);
|
|
133
128
|
self.ctx.lineTo(x, y + ah);
|
|
129
|
+
} else {
|
|
130
|
+
self.ctx.moveTo(x, y);
|
|
131
|
+
self.ctx.lineTo(x + aw, y);
|
|
132
|
+
self.ctx.lineTo(x + aw * 0.5, y + ah);
|
|
133
|
+
self.ctx.moveTo(x, y);
|
|
134
134
|
}
|
|
135
135
|
self.ctx.stroke();
|
|
136
136
|
self.ctx.fill();
|
|
@@ -911,7 +911,9 @@ export default function (self) {
|
|
|
911
911
|
viewColumnIndex: columnOrderIndex,
|
|
912
912
|
|
|
913
913
|
boundRowIndex: self.getBoundRowIndexFromViewRowIndex(rowOrderIndex),
|
|
914
|
-
boundColumnIndex:
|
|
914
|
+
boundColumnIndex: self.getBoundColumnIndexFromViewColumnIndex(
|
|
915
|
+
columnOrderIndex,
|
|
916
|
+
),
|
|
915
917
|
|
|
916
918
|
sortColumnIndex: headerIndex,
|
|
917
919
|
sortRowIndex: rowIndex,
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
5
|
import isPrintableKeyEvent from 'is-printable-key-event';
|
|
6
|
+
import { isSupportedHtml, parseData } from './util';
|
|
6
7
|
|
|
7
8
|
export default function (self) {
|
|
8
9
|
var wheeling;
|
|
@@ -518,13 +519,12 @@ export default function (self) {
|
|
|
518
519
|
self.selections[cell.rowIndex].indexOf(cell.columnIndex) === -1
|
|
519
520
|
) {
|
|
520
521
|
self.selections[cell.rowIndex].push(cell.columnIndex);
|
|
521
|
-
|
|
522
522
|
const event = {
|
|
523
523
|
selections: self.selections,
|
|
524
524
|
selectedData: self.getSelectedData(),
|
|
525
|
+
selectedCells: self.getSelectedCells(),
|
|
525
526
|
selectionBounds: self.getSelectionBounds(),
|
|
526
527
|
};
|
|
527
|
-
|
|
528
528
|
self.dispatchEvent('selectionchanged', event);
|
|
529
529
|
}
|
|
530
530
|
}
|
|
@@ -583,12 +583,14 @@ export default function (self) {
|
|
|
583
583
|
function checkSelectionChange() {
|
|
584
584
|
var ev,
|
|
585
585
|
sb = self.getSelectionBounds();
|
|
586
|
+
|
|
586
587
|
if (startingBounds === JSON.stringify(sb)) {
|
|
587
588
|
return;
|
|
588
589
|
}
|
|
589
590
|
ev = {
|
|
590
591
|
selections: self.selections,
|
|
591
592
|
selectionBounds: self.getSelectionBounds(),
|
|
593
|
+
selectedCells: self.getSelectedCells(),
|
|
592
594
|
};
|
|
593
595
|
Object.defineProperty(ev, 'selectedData', {
|
|
594
596
|
get: function () {
|
|
@@ -897,6 +899,7 @@ export default function (self) {
|
|
|
897
899
|
self.stopDragReorder = function (e) {
|
|
898
900
|
var oIndex,
|
|
899
901
|
tIndex,
|
|
902
|
+
odata,
|
|
900
903
|
cr = {
|
|
901
904
|
'row-reorder': self.orders.rows,
|
|
902
905
|
'column-reorder': self.orders.columns,
|
|
@@ -927,12 +930,15 @@ export default function (self) {
|
|
|
927
930
|
self.ignoreNextClick = true;
|
|
928
931
|
oIndex = cr[self.dragMode].indexOf(self.reorderObject[i]);
|
|
929
932
|
tIndex = cr[self.dragMode].indexOf(self.reorderTarget[i]);
|
|
930
|
-
cr[self.dragMode].splice(oIndex, 1);
|
|
931
|
-
cr[self.dragMode].splice(tIndex, 0, self.reorderObject[i]);
|
|
932
933
|
if (self.dragMode === 'column-reorder') {
|
|
934
|
+
cr[self.dragMode].splice(oIndex, 1);
|
|
935
|
+
cr[self.dragMode].splice(tIndex, 0, self.reorderObject[i]);
|
|
933
936
|
self.orders.columns = cr[self.dragMode];
|
|
934
937
|
} else {
|
|
935
|
-
self.orders.rows = cr[self.dragMode];
|
|
938
|
+
// self.orders.rows = cr[self.dragMode];
|
|
939
|
+
odata = self.viewData[oIndex];
|
|
940
|
+
self.viewData[oIndex] = self.viewData[tIndex];
|
|
941
|
+
self.viewData[tIndex] = odata;
|
|
936
942
|
}
|
|
937
943
|
self.resize();
|
|
938
944
|
self.setStorageData();
|
|
@@ -1167,6 +1173,13 @@ export default function (self) {
|
|
|
1167
1173
|
}
|
|
1168
1174
|
if (['row-reorder', 'column-reorder'].indexOf(self.dragMode) !== -1) {
|
|
1169
1175
|
self.draggingItem = self.dragStartObject;
|
|
1176
|
+
if (
|
|
1177
|
+
self.dragMode === 'column-reorder' &&
|
|
1178
|
+
self.attributes.columnHeaderClickBehavior === 'select'
|
|
1179
|
+
) {
|
|
1180
|
+
self.selectColumn(self.currentCell.header.index, ctrl, e.shiftKey);
|
|
1181
|
+
self.draw();
|
|
1182
|
+
}
|
|
1170
1183
|
document.body.addEventListener('mousemove', self.dragReorder, false);
|
|
1171
1184
|
document.body.addEventListener('mouseup', self.stopDragReorder, false);
|
|
1172
1185
|
return;
|
|
@@ -1174,9 +1187,14 @@ export default function (self) {
|
|
|
1174
1187
|
};
|
|
1175
1188
|
self.mouseup = function (e) {
|
|
1176
1189
|
clearTimeout(self.scrollTimer);
|
|
1190
|
+
var ctrl = e.ctrlKey || e.metaKey;
|
|
1177
1191
|
self.cellBoundaryCrossed = true;
|
|
1178
1192
|
self.rowBoundaryCrossed = true;
|
|
1179
1193
|
self.columnBoundaryCrossed = true;
|
|
1194
|
+
if (self.draggingItem) {
|
|
1195
|
+
self.selectColumn(self.currentCell.header.index, ctrl, e.shiftKey);
|
|
1196
|
+
self.draw();
|
|
1197
|
+
}
|
|
1180
1198
|
self.selecting = undefined;
|
|
1181
1199
|
self.draggingItem = undefined;
|
|
1182
1200
|
self.dragStartObject = undefined;
|
|
@@ -1246,7 +1264,7 @@ export default function (self) {
|
|
|
1246
1264
|
return;
|
|
1247
1265
|
}
|
|
1248
1266
|
|
|
1249
|
-
if (!self.hasFocus) {
|
|
1267
|
+
if (!self.attributes.keepFocusOnMouseOut && !self.hasFocus) {
|
|
1250
1268
|
return;
|
|
1251
1269
|
}
|
|
1252
1270
|
|
|
@@ -1401,6 +1419,7 @@ export default function (self) {
|
|
|
1401
1419
|
selectedData: self.getSelectedData(),
|
|
1402
1420
|
selections: self.selections,
|
|
1403
1421
|
selectionBounds: self.getSelectionBounds(),
|
|
1422
|
+
selectedCells: self.getSelectedCells(),
|
|
1404
1423
|
};
|
|
1405
1424
|
Object.defineProperty(ev, 'selectedData', {
|
|
1406
1425
|
get: function () {
|
|
@@ -1497,24 +1516,13 @@ export default function (self) {
|
|
|
1497
1516
|
}, 1);
|
|
1498
1517
|
}
|
|
1499
1518
|
};
|
|
1500
|
-
|
|
1501
1519
|
self.pasteData = function (
|
|
1502
1520
|
pasteValue,
|
|
1503
1521
|
mimeType,
|
|
1504
1522
|
startRowIndex,
|
|
1505
1523
|
startColIndex,
|
|
1506
1524
|
) {
|
|
1507
|
-
|
|
1508
|
-
const isSupportedHtmlTable = (htmlString) =>
|
|
1509
|
-
/(?:^(<meta[^>]+>)?<table.*?>)|(?:<!--StartFragment-->\s*<table.*?>)/.test(
|
|
1510
|
-
htmlString,
|
|
1511
|
-
);
|
|
1512
|
-
|
|
1513
|
-
// TODO: support pasting tables from Excel
|
|
1514
|
-
if (
|
|
1515
|
-
mimeType === 'text/html' &&
|
|
1516
|
-
isSupportedHtmlTable(pasteValue) === false
|
|
1517
|
-
) {
|
|
1525
|
+
if (mimeType === 'text/html' && !isSupportedHtml(pasteValue)) {
|
|
1518
1526
|
console.warn(
|
|
1519
1527
|
'Unrecognized HTML format. HTML must be a simple table, e.g.: <table><tr><td>data</td></tr></table>.',
|
|
1520
1528
|
);
|
|
@@ -1524,48 +1532,12 @@ export default function (self) {
|
|
|
1524
1532
|
|
|
1525
1533
|
return;
|
|
1526
1534
|
}
|
|
1527
|
-
|
|
1528
|
-
function parseData(data, mimeType) {
|
|
1529
|
-
// TODO: use DOMParser
|
|
1530
|
-
if (mimeType === 'text/html') {
|
|
1531
|
-
const doc = new DOMParser().parseFromString(data, 'text/html');
|
|
1532
|
-
const trs = doc.querySelectorAll('table tr');
|
|
1533
|
-
const rows = [];
|
|
1534
|
-
trs.forEach((tr) => {
|
|
1535
|
-
const row = [];
|
|
1536
|
-
tr.childNodes.forEach((td) => {
|
|
1537
|
-
if (td.nodeName === '#text') return;
|
|
1538
|
-
const col = {
|
|
1539
|
-
// style: {}, // keep style if need
|
|
1540
|
-
value: [],
|
|
1541
|
-
};
|
|
1542
|
-
td.childNodes.forEach((ele) => {
|
|
1543
|
-
col.value.push({
|
|
1544
|
-
// style: {}, // keep style if need
|
|
1545
|
-
value: ele.nodeType === 1 ? ele.innerText : ele.data,
|
|
1546
|
-
});
|
|
1547
|
-
});
|
|
1548
|
-
row.push(col);
|
|
1549
|
-
});
|
|
1550
|
-
rows.push(row);
|
|
1551
|
-
});
|
|
1552
|
-
return rows;
|
|
1553
|
-
}
|
|
1554
|
-
|
|
1555
|
-
// Default data format is string, so split on new line,
|
|
1556
|
-
// and then enclose in an array (a row with one cell):
|
|
1557
|
-
return data
|
|
1558
|
-
.split('\n')
|
|
1559
|
-
.map((item) =>
|
|
1560
|
-
item.split('\t').map((value) => ({ value: [{ value }] })),
|
|
1561
|
-
);
|
|
1562
|
-
}
|
|
1563
|
-
|
|
1535
|
+
var schema = self.getSchema();
|
|
1564
1536
|
var rows = parseData(pasteValue, mimeType);
|
|
1565
1537
|
|
|
1566
1538
|
// selected cell. This mimics Excel's paste functionality, and works
|
|
1567
1539
|
// as a poor-man's fill-down.
|
|
1568
|
-
if (rows.length === 1) {
|
|
1540
|
+
if (rows.length === 1 && rows[0].length === 1) {
|
|
1569
1541
|
var cellData = rows[0][0].value.map((item) => item.value).join();
|
|
1570
1542
|
|
|
1571
1543
|
self.forEachSelectedCell(function (data, rowIndex, colName) {
|
|
@@ -1627,7 +1599,8 @@ export default function (self) {
|
|
|
1627
1599
|
affectedCells.push([
|
|
1628
1600
|
rowIndex,
|
|
1629
1601
|
columnIndex,
|
|
1630
|
-
self.
|
|
1602
|
+
self.getBoundRowIndexFromViewRowIndex(rowIndex),
|
|
1603
|
+
self.getBoundColumnIndexFromViewColumnIndex(columnIndex),
|
|
1631
1604
|
]);
|
|
1632
1605
|
});
|
|
1633
1606
|
});
|
|
@@ -1722,9 +1695,34 @@ export default function (self) {
|
|
|
1722
1695
|
};
|
|
1723
1696
|
self.cut = function (e) {
|
|
1724
1697
|
self.copy(e);
|
|
1725
|
-
self.
|
|
1726
|
-
|
|
1727
|
-
|
|
1698
|
+
const schema = self.getSchema();
|
|
1699
|
+
|
|
1700
|
+
var affectedCells = [];
|
|
1701
|
+
for (const [rowIndex, row] of self.selections.entries()) {
|
|
1702
|
+
if (!row) continue;
|
|
1703
|
+
|
|
1704
|
+
const boundRowIndex = self.getBoundRowIndexFromViewRowIndex(rowIndex);
|
|
1705
|
+
|
|
1706
|
+
for (const columnIndex of row) {
|
|
1707
|
+
const boundColumnIndex = self.getBoundColumnIndexFromViewColumnIndex(
|
|
1708
|
+
columnIndex,
|
|
1709
|
+
);
|
|
1710
|
+
const colName = schema[boundColumnIndex].name;
|
|
1711
|
+
|
|
1712
|
+
self.viewData[rowIndex][colName] = '';
|
|
1713
|
+
|
|
1714
|
+
affectedCells.push([
|
|
1715
|
+
rowIndex,
|
|
1716
|
+
columnIndex,
|
|
1717
|
+
boundRowIndex,
|
|
1718
|
+
boundColumnIndex,
|
|
1719
|
+
]);
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
if (self.dispatchEvent('cut', { NativeEvent: e, cells: affectedCells })) {
|
|
1724
|
+
return;
|
|
1725
|
+
}
|
|
1728
1726
|
};
|
|
1729
1727
|
self.copy = function (e) {
|
|
1730
1728
|
if (self.dispatchEvent('copy', { NativeEvent: e })) {
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const isSupportedHtml = function (pasteValue) {
|
|
4
|
+
// We need to match new lines in the HTML, .* won't match new line characters.
|
|
5
|
+
// `s` regex modifier can't be used with `ecmaVersion === 2017`.
|
|
6
|
+
// As a workaround using [\s\S]*. Fix when we upgrade `ecmaVersion`.
|
|
7
|
+
const genericDiv = /(?:^(<meta[^>]*>)?[\s\S]*<div[^>]*>)/;
|
|
8
|
+
const genericSpan = /(?:^(<meta[^>]*>)?[\s\S]*<span[^>]*>)/;
|
|
9
|
+
const genericTable = /(?:^(<meta[^>]*>)?[\s\S]*<table[^>]*>)/; // Matches Google Sheets format clipboard data format too.
|
|
10
|
+
const excelTable = /(?:<!--StartFragment-->[\s\S]*<tr[^>]*>)/;
|
|
11
|
+
const excelTableRow = /(?:<!--StartFragment-->[\s\S]*<td[^>]*>)/;
|
|
12
|
+
|
|
13
|
+
return [
|
|
14
|
+
genericDiv,
|
|
15
|
+
genericTable,
|
|
16
|
+
genericSpan,
|
|
17
|
+
excelTable,
|
|
18
|
+
excelTableRow,
|
|
19
|
+
].some((expression) => expression.test(pasteValue));
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// Explanation of nodeType here: https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
|
|
23
|
+
const IGNORE_NODETYPES = [8, 3]; // '#text' and '#comment'
|
|
24
|
+
|
|
25
|
+
const isHtmlTable = function (pasteValue) {
|
|
26
|
+
return /(?:<table[^>]*>)|(?:<tr[^]*>)/.test(pasteValue);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const sanitizeElementData = function (element) {
|
|
30
|
+
// It is not entirely clear if this check on nodeType is required.
|
|
31
|
+
let elementData = element.nodeType === 1 ? element.innerText : element.data;
|
|
32
|
+
|
|
33
|
+
return String(elementData).replace(/\s+/g, ' ').trim();
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const parseHtmlText = function (data) {
|
|
37
|
+
const doc = new DOMParser().parseFromString(data, 'text/html');
|
|
38
|
+
const element = doc.querySelector('div') || doc.querySelector('span');
|
|
39
|
+
const elementData = sanitizeElementData(element);
|
|
40
|
+
|
|
41
|
+
return elementData
|
|
42
|
+
.split('\n')
|
|
43
|
+
.map((item) => item.split('\t').map((value) => ({ value: [{ value }] })));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const parseHtmlTable = function (data) {
|
|
47
|
+
const doc = new DOMParser().parseFromString(data, 'text/html');
|
|
48
|
+
const trs = doc.querySelectorAll('table tr');
|
|
49
|
+
const rows = [];
|
|
50
|
+
|
|
51
|
+
for (const tr of trs) {
|
|
52
|
+
const row = [];
|
|
53
|
+
|
|
54
|
+
for (const childNode of tr.childNodes) {
|
|
55
|
+
if (IGNORE_NODETYPES.includes(childNode.nodeType)) continue;
|
|
56
|
+
|
|
57
|
+
const col = { value: [] };
|
|
58
|
+
const value = sanitizeElementData(childNode);
|
|
59
|
+
|
|
60
|
+
if (value) col.value.push({ value });
|
|
61
|
+
|
|
62
|
+
row.push(col);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
rows.push(row);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return rows;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const parseText = function (data) {
|
|
72
|
+
return data
|
|
73
|
+
.split('\n')
|
|
74
|
+
.map((item) => item.split('\t').map((value) => ({ value: [{ value }] })));
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const parseData = function (data, mimeType) {
|
|
78
|
+
if (mimeType === 'text/html' && isHtmlTable(data)) {
|
|
79
|
+
return parseHtmlTable(data);
|
|
80
|
+
} else if (mimeType === 'text/html') {
|
|
81
|
+
return parseHtmlText(data);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Default data format is string, so split on new line,
|
|
85
|
+
// and then enclose in an array (a row with one cell):
|
|
86
|
+
return parseText(data);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
isSupportedHtml,
|
|
91
|
+
sanitizeElementData,
|
|
92
|
+
parseData,
|
|
93
|
+
parseHtmlTable,
|
|
94
|
+
parseHtmlText,
|
|
95
|
+
parseText,
|
|
96
|
+
};
|
package/lib/intf.js
CHANGED
|
@@ -184,6 +184,54 @@ export default function (self, ctor) {
|
|
|
184
184
|
|
|
185
185
|
return selectedData;
|
|
186
186
|
};
|
|
187
|
+
self.getSelectedCells = function (expandToRow) {
|
|
188
|
+
const selectedCells = [];
|
|
189
|
+
const schema = self.getSchema();
|
|
190
|
+
const viewDataLength = self.viewData.length;
|
|
191
|
+
|
|
192
|
+
if (viewDataLength === 0) {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
for (const [viewRowIndex, row] of self.selections.entries()) {
|
|
197
|
+
if (!row || row.length === 0) continue;
|
|
198
|
+
|
|
199
|
+
for (const [, viewColumnIndex] of row.entries()) {
|
|
200
|
+
if (viewColumnIndex === -1 || !schema[viewColumnIndex]) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const boundColumnIndex = self.getBoundColumnIndexFromViewColumnIndex(
|
|
205
|
+
viewColumnIndex,
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
if (!expandToRow && schema[boundColumnIndex].hidden) {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (self.viewData[viewRowIndex]) {
|
|
213
|
+
const header = schema[boundColumnIndex];
|
|
214
|
+
const value = self.viewData[viewRowIndex][header.name];
|
|
215
|
+
const boundRowIndex = self.getBoundRowIndexFromViewRowIndex(
|
|
216
|
+
viewRowIndex,
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
const cell = {
|
|
220
|
+
value,
|
|
221
|
+
header,
|
|
222
|
+
boundRowIndex,
|
|
223
|
+
boundColumnIndex,
|
|
224
|
+
viewRowIndex,
|
|
225
|
+
viewColumnIndex,
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
selectedCells.push(cell);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return selectedCells;
|
|
234
|
+
};
|
|
187
235
|
self.getBoundRowIndexFromViewRowIndex = function (viewRowIndex) {
|
|
188
236
|
if (self.boundRowIndexMap && self.boundRowIndexMap.has(viewRowIndex)) {
|
|
189
237
|
return self.boundRowIndexMap.get(viewRowIndex);
|
|
@@ -191,6 +239,9 @@ export default function (self, ctor) {
|
|
|
191
239
|
|
|
192
240
|
return undefined;
|
|
193
241
|
};
|
|
242
|
+
self.getBoundColumnIndexFromViewColumnIndex = function (viewColumnIndex) {
|
|
243
|
+
return self.orders.columns[viewColumnIndex];
|
|
244
|
+
};
|
|
194
245
|
self.getColumnHeaderCellHeight = function () {
|
|
195
246
|
if (!self.attributes.showColumnHeaders) {
|
|
196
247
|
return 0;
|
|
@@ -750,6 +801,7 @@ export default function (self, ctor) {
|
|
|
750
801
|
self.intf.clearPxColorAssertions = self.clearPxColorAssertions;
|
|
751
802
|
self.intf.integerToAlpha = self.integerToAlpha;
|
|
752
803
|
self.intf.copy = self.copy;
|
|
804
|
+
self.intf.cut = self.cut;
|
|
753
805
|
self.intf.paste = self.paste;
|
|
754
806
|
self.intf.setStyleProperty = self.setStyleProperty;
|
|
755
807
|
Object.defineProperty(self.intf, 'defaults', {
|
package/lib/publicMethods.js
CHANGED
|
@@ -353,6 +353,7 @@ export default function (self) {
|
|
|
353
353
|
selectedData: self.getSelectedData(),
|
|
354
354
|
selections: self.selections,
|
|
355
355
|
selectionBounds: self.selectionBounds,
|
|
356
|
+
selectedCells: self.getSelectedCells(),
|
|
356
357
|
});
|
|
357
358
|
if (dontDraw) {
|
|
358
359
|
return;
|
|
@@ -485,6 +486,7 @@ export default function (self) {
|
|
|
485
486
|
selectedData: self.getSelectedData(),
|
|
486
487
|
selections: self.selections,
|
|
487
488
|
selectionBounds: self.getSelectionBounds(),
|
|
489
|
+
selectedCells: self.getSelectedCells(),
|
|
488
490
|
});
|
|
489
491
|
};
|
|
490
492
|
/**
|
|
@@ -510,6 +512,7 @@ export default function (self) {
|
|
|
510
512
|
selectedData: self.getSelectedData(),
|
|
511
513
|
selections: self.selections,
|
|
512
514
|
selectionBounds: self.selectionBounds,
|
|
515
|
+
selectedCells: self.getSelectedCells(),
|
|
513
516
|
});
|
|
514
517
|
}
|
|
515
518
|
function addRow(ri) {
|
|
@@ -1252,6 +1255,7 @@ export default function (self) {
|
|
|
1252
1255
|
ev = {
|
|
1253
1256
|
selections: self.selections,
|
|
1254
1257
|
selectionBounds: self.selectionBounds,
|
|
1258
|
+
selectedCells: self.getSelectedCells(),
|
|
1255
1259
|
};
|
|
1256
1260
|
Object.defineProperty(ev, 'selectedData', {
|
|
1257
1261
|
get: function () {
|
|
@@ -1363,22 +1367,18 @@ export default function (self) {
|
|
|
1363
1367
|
self.sorters.string = function (columnName, direction) {
|
|
1364
1368
|
var asc = direction === 'asc';
|
|
1365
1369
|
return function (a, b) {
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
}
|
|
1369
|
-
if (b[columnName] === undefined || b[columnName] === null) {
|
|
1370
|
-
return 0;
|
|
1371
|
-
}
|
|
1370
|
+
const aValue = a[columnName] || '';
|
|
1371
|
+
const bValue = b[columnName] || '';
|
|
1372
1372
|
if (asc) {
|
|
1373
|
-
if (!
|
|
1373
|
+
if (!aValue.localeCompare) {
|
|
1374
1374
|
return 1;
|
|
1375
1375
|
}
|
|
1376
|
-
return
|
|
1376
|
+
return aValue.localeCompare(bValue);
|
|
1377
1377
|
}
|
|
1378
|
-
if (!
|
|
1378
|
+
if (!bValue.localeCompare) {
|
|
1379
1379
|
return 1;
|
|
1380
1380
|
}
|
|
1381
|
-
return
|
|
1381
|
+
return bValue.localeCompare(aValue);
|
|
1382
1382
|
};
|
|
1383
1383
|
};
|
|
1384
1384
|
self.sorters.number = function (columnName, direction) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "canvas-datagrid",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.16",
|
|
4
4
|
"description": "Canvas based data grid web component. Capable of displaying millions of contiguous hierarchical rows and columns without paging or loading, on a single canvas element.",
|
|
5
5
|
"main": "./dist/canvas-datagrid.js",
|
|
6
6
|
"module": "./dist/canvas-datagrid.module.js",
|