canvas-datagrid 0.3.18 → 0.3.22

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.
@@ -254,7 +254,13 @@ export default function (self) {
254
254
  setScrollBoxSize();
255
255
  self.scrollBox.scrollWidth = dataWidth - self.scrollBox.width;
256
256
  self.scrollBox.scrollHeight = dataHeight - self.scrollBox.height;
257
- self.scrollBox.widthBoxRatio = self.scrollBox.width / dataWidth;
257
+ if (self.frozenColumn > 0) {
258
+ self.scrollBox.widthBoxRatio =
259
+ (self.scrollBox.width - self.scrollCache.x[self.frozenColumn - 1]) /
260
+ dataWidth;
261
+ } else {
262
+ self.scrollBox.widthBoxRatio = self.scrollBox.width / dataWidth;
263
+ }
258
264
  self.scrollBox.scrollBoxWidth =
259
265
  self.scrollBox.width * self.scrollBox.widthBoxRatio -
260
266
  self.style.scrollBarWidth -
@@ -266,7 +272,10 @@ export default function (self) {
266
272
  // the dragged mouse.
267
273
  // https://github.com/TonyGermaneri/canvas-datagrid/issues/97
268
274
  self.scrollBox.heightBoxRatio =
269
- (self.scrollBox.height - columnHeaderCellHeight) / dataHeight;
275
+ (self.scrollBox.height -
276
+ columnHeaderCellHeight -
277
+ self.scrollCache.y[self.frozenRow]) /
278
+ dataHeight;
270
279
  self.scrollBox.scrollBoxHeight =
271
280
  self.scrollBox.height * self.scrollBox.heightBoxRatio -
272
281
  self.style.scrollBarWidth -
@@ -296,12 +305,13 @@ export default function (self) {
296
305
  self.style.scrollBarWidth -
297
306
  self.style.scrollBarBorderWidth -
298
307
  d;
299
- v.y += columnHeaderCellHeight;
308
+ v.y += columnHeaderCellHeight + self.scrollCache.y[self.frozenRow];
300
309
  v.width = self.style.scrollBarWidth + self.style.scrollBarBorderWidth + d;
301
310
  v.height =
302
311
  self.height - columnHeaderCellHeight - self.style.scrollBarWidth - d - m;
303
312
  // vertical box
304
313
  vb.x = v.x + self.style.scrollBarBoxMargin;
314
+ vb.y += self.scrollCache.y[self.frozenRow];
305
315
  vb.width = self.style.scrollBarBoxWidth;
306
316
  vb.height = self.scrollBox.scrollBoxHeight;
307
317
  // corner
@@ -458,7 +468,26 @@ export default function (self) {
458
468
  self.hovers = {
459
469
  rowIndex: cell.rowIndex,
460
470
  columnIndex: cell.columnIndex,
471
+ onFilterButton: false,
461
472
  };
473
+ if (
474
+ cell.isFilterable &&
475
+ x >
476
+ cell.x +
477
+ cell.width +
478
+ self.canvasOffsetLeft -
479
+ self.style.filterButtonWidth &&
480
+ x < cell.x + cell.width + self.canvasOffsetLeft &&
481
+ y >
482
+ cell.y +
483
+ cell.height +
484
+ self.canvasOffsetTop -
485
+ self.style.filterButtonHeight &&
486
+ y < cell.y + cell.height + self.canvasOffsetTop
487
+ ) {
488
+ self.hovers.onFilterButton = true;
489
+ self.draw();
490
+ }
462
491
  }
463
492
  if (self.selecting || self.reorderObject) {
464
493
  delta = {
@@ -502,30 +531,57 @@ export default function (self) {
502
531
  ) {
503
532
  self.selectRow(cell.rowIndex, ctrl, null, true);
504
533
  } else if (self.attributes.selectionMode !== 'row') {
505
- if (!self.dragAddToSelection && cell.rowIndex !== undefined) {
506
- if (
507
- self.selections[cell.rowIndex] &&
508
- self.selections[cell.rowIndex].indexOf(cell.columnIndex) !== -1
509
- ) {
510
- self.selections[cell.rowIndex].splice(
511
- self.selections[cell.rowIndex].indexOf(cell.columnIndex),
512
- 1,
513
- );
534
+ if (cell.hovered && self.hovers.onFilterButton) {
535
+ if (cell.openedFilter) {
536
+ cell.openedFilter = false;
537
+ self.selectedFilterButton = {
538
+ columnIndex: -1,
539
+ rowIndex: -1,
540
+ };
541
+ } else {
542
+ self.selectedFilterButton.rowIndex = cell.rowIndex;
543
+ self.selectedFilterButton.columnIndex = cell.columnIndex;
544
+ self.contextmenuEvent(e, {
545
+ x: cell.x + cell.width - self.style.filterButtonWidth,
546
+ y: cell.y + cell.height,
547
+ rect: { left: 0, top: 0 },
548
+ });
514
549
  }
550
+ self.draw();
551
+ return;
515
552
  } else {
516
- self.selections[cell.rowIndex] =
517
- self.selections[cell.rowIndex] || [];
518
- if (
519
- self.selections[cell.rowIndex].indexOf(cell.columnIndex) === -1
520
- ) {
521
- self.selections[cell.rowIndex].push(cell.columnIndex);
522
- const event = {
523
- selections: self.selections,
524
- selectedData: self.getSelectedData(),
525
- selectedCells: self.getSelectedCells(),
526
- selectionBounds: self.getSelectionBounds(),
527
- };
528
- self.dispatchEvent('selectionchanged', event);
553
+ self.selectedFilterButton = {
554
+ columnIndex: -1,
555
+ rowIndex: -1,
556
+ };
557
+ if (self.hovers.onFilterButton) return;
558
+ if (!self.dragAddToSelection && cell.rowIndex !== undefined) {
559
+ if (
560
+ self.selections[cell.rowIndex] &&
561
+ self.selections[cell.rowIndex].indexOf(cell.columnIndex) !==
562
+ -1
563
+ ) {
564
+ self.selections[cell.rowIndex].splice(
565
+ self.selections[cell.rowIndex].indexOf(cell.columnIndex),
566
+ 1,
567
+ );
568
+ }
569
+ } else {
570
+ self.selections[cell.rowIndex] =
571
+ self.selections[cell.rowIndex] || [];
572
+ if (
573
+ self.selections[cell.rowIndex].indexOf(cell.columnIndex) ===
574
+ -1
575
+ ) {
576
+ self.selections[cell.rowIndex].push(cell.columnIndex);
577
+ var event = {
578
+ selections: self.selections,
579
+ selectedData: self.getSelectedData(),
580
+ selectedCells: self.getSelectedCells(),
581
+ selectionBounds: self.getSelectionBounds(),
582
+ };
583
+ self.dispatchEvent('selectionchanged', event);
584
+ }
529
585
  }
530
586
  }
531
587
  }
@@ -538,14 +594,21 @@ export default function (self) {
538
594
  dragBounds.right !== self.selectionBounds.right) &&
539
595
  !ctrl
540
596
  ) {
541
- self.selections = [];
597
+ if (!(cell.hovered && self.hovers.onFilterButton)) {
598
+ self.selections = [];
599
+ }
600
+ if (dragBounds.top === -1) {
601
+ dragBounds.top = 0;
602
+ }
542
603
  sBounds = dragBounds;
543
604
  if (self.attributes.selectionMode === 'row') {
544
605
  for (i = sBounds.top; i <= sBounds.bottom; i += 1) {
545
606
  self.selectRow(i, true, null, true);
546
607
  }
547
- } else if (dragBounds.top !== -1) {
608
+ } else {
548
609
  self.selectArea(sBounds, true);
610
+ if (sBounds.left == -1 && sBounds.top !== sBounds.bottom)
611
+ self.isMultiRowsSelected = true;
549
612
  }
550
613
  }
551
614
 
@@ -620,7 +683,9 @@ export default function (self) {
620
683
  -1 &&
621
684
  !ctrl
622
685
  ) {
623
- self.setActiveCell(i.columnIndex, i.rowIndex);
686
+ if (!self.hovers.onFilterButton) {
687
+ self.setActiveCell(i.columnIndex, i.rowIndex);
688
+ }
624
689
  }
625
690
  if (self.currentCell.context === 'cell') {
626
691
  if (self.currentCell.style === 'cornerCell') {
@@ -641,11 +706,6 @@ export default function (self) {
641
706
  checkSelectionChange();
642
707
  return;
643
708
  }
644
- if (self.attributes.columnHeaderClickBehavior === 'select') {
645
- self.selectColumn(i.header.index, ctrl, e.shiftKey);
646
- self.draw();
647
- return;
648
- }
649
709
  }
650
710
  self.selections[i.rowIndex] = self.selections[i.rowIndex] || [];
651
711
  if (
@@ -737,7 +797,32 @@ export default function (self) {
737
797
  }
738
798
  self.ellipsisCache = {};
739
799
  };
740
- self.stopDragResize = function () {
800
+ self.stopDragResize = function (e) {
801
+ const pos = self.getLayerPos(e);
802
+ const hasMoved = !!(pos.x - self.dragStart.x);
803
+ const width = self.resizingStartingWidth + pos.x - self.dragStart.x;
804
+
805
+ if (self.dragMode === 'ew-resize') {
806
+ const selectedColumns = self.selections[0];
807
+ const dragItemIsSelected = self.isColumnSelected(
808
+ self.dragItem.columnIndex,
809
+ );
810
+
811
+ if (dragItemIsSelected)
812
+ for (const selectedColumnIndex of selectedColumns) {
813
+ const boundColumnIndex = self.getBoundColumnIndexFromViewColumnIndex(
814
+ selectedColumnIndex,
815
+ );
816
+
817
+ if (
818
+ hasMoved &&
819
+ dragItemIsSelected &&
820
+ self.isColumnSelected(selectedColumnIndex)
821
+ )
822
+ self.sizes.columns[boundColumnIndex] = width;
823
+ }
824
+ }
825
+
741
826
  self.resize();
742
827
  document.body.removeEventListener(
743
828
  'mousemove',
@@ -868,6 +953,14 @@ export default function (self) {
868
953
  if (!self.attributes.allowRowReordering && rowReorder) {
869
954
  return;
870
955
  }
956
+ if ((e.ctrlKey || e.metaKey || e.shiftKey) && self.reorderObject) {
957
+ if (
958
+ self.dragMode === 'column-reorder' &&
959
+ !self.isMultiColumnsSelected(self.draggingItem.header.index)
960
+ ) {
961
+ self.selectColumn(self.draggingItem.header.index, false, false);
962
+ }
963
+ }
871
964
  if (
872
965
  self.dispatchEvent('reordering', {
873
966
  NativeEvent: e,
@@ -883,6 +976,11 @@ export default function (self) {
883
976
  Math.abs(y) > self.attributes.reorderDeadZone
884
977
  ) {
885
978
  self.reorderObject = self.draggingItem;
979
+ if (self.isMultiRowsSelected)
980
+ self.reorderObject = self.getVisibleCellByIndex(
981
+ -1,
982
+ self.activeCell.rowIndex,
983
+ );
886
984
  self.reorderTarget = self.currentCell;
887
985
  self.reorderObject.dragOffset = {
888
986
  x: x,
@@ -899,7 +997,7 @@ export default function (self) {
899
997
  self.stopDragReorder = function (e) {
900
998
  var oIndex,
901
999
  tIndex,
902
- odata,
1000
+ odata = [],
903
1001
  cr = {
904
1002
  'row-reorder': self.orders.rows,
905
1003
  'column-reorder': self.orders.columns,
@@ -931,14 +1029,40 @@ export default function (self) {
931
1029
  oIndex = cr[self.dragMode].indexOf(self.reorderObject[i]);
932
1030
  tIndex = cr[self.dragMode].indexOf(self.reorderTarget[i]);
933
1031
  if (self.dragMode === 'column-reorder') {
934
- cr[self.dragMode].splice(oIndex, 1);
935
- cr[self.dragMode].splice(tIndex, 0, self.reorderObject[i]);
1032
+ var sortColumnIndices = [];
1033
+ var seletedColumnIndices = [];
1034
+ if (self.selections[0]) {
1035
+ self.selections[0].forEach(function (value) {
1036
+ sortColumnIndices.push(self.orders.columns[value]);
1037
+ });
1038
+ }
1039
+ var deleteCount = sortColumnIndices.length;
1040
+ cr[self.dragMode].splice(oIndex, deleteCount);
1041
+ if (tIndex > oIndex) tIndex = tIndex - (deleteCount - 1);
1042
+ for (var i = 0; i < sortColumnIndices.length; i++) {
1043
+ seletedColumnIndices.push(tIndex + i);
1044
+ cr[self.dragMode].splice(tIndex + i, 0, sortColumnIndices[i]);
1045
+ }
936
1046
  self.orders.columns = cr[self.dragMode];
1047
+ self.viewData.forEach(function (row, rowIndex) {
1048
+ self.selections[rowIndex] = seletedColumnIndices;
1049
+ });
937
1050
  } else {
938
- // self.orders.rows = cr[self.dragMode];
939
- odata = self.viewData[oIndex];
940
- self.viewData[oIndex] = self.viewData[tIndex];
941
- self.viewData[tIndex] = odata;
1051
+ var selectedRows = [];
1052
+ self.selections.forEach(function (row, rowIndex) {
1053
+ if (row) {
1054
+ selectedRows.push(row);
1055
+ odata.push(self.viewData[rowIndex]);
1056
+ }
1057
+ });
1058
+ self.viewData.splice(oIndex, odata.length);
1059
+ self.selections = [];
1060
+ if (tIndex > oIndex) tIndex = tIndex - (odata.length - 1);
1061
+ self.activeCell.rowIndex = tIndex;
1062
+ for (var i = 0; i < odata.length; i++) {
1063
+ self.viewData.splice(tIndex + i, 0, odata[i]);
1064
+ self.selections[tIndex + i] = selectedRows[i];
1065
+ }
942
1066
  }
943
1067
  self.resize();
944
1068
  self.setStorageData();
@@ -1000,7 +1124,12 @@ export default function (self) {
1000
1124
  ) {
1001
1125
  return;
1002
1126
  }
1003
- var pos = self.getLayerPos(e);
1127
+ var pos = self.getLayerPos(e),
1128
+ bm = self.style.gridBorderCollapse === 'collapse' ? 1 : 2,
1129
+ columnHeaderCellBorder = self.style.columnHeaderCellBorderWidth * bm,
1130
+ columnHeaderCellHeight = self.getColumnHeaderCellHeight(),
1131
+ rowHeaderCellWidth = self.getRowHeaderCellWidth();
1132
+
1004
1133
  self.ignoreNextClick = true;
1005
1134
  self.freezeMarkerPosition = pos;
1006
1135
  if (
@@ -1010,6 +1139,28 @@ export default function (self) {
1010
1139
  ) {
1011
1140
  self.scrollBox.scrollTop = 0;
1012
1141
  self.frozenRow = self.currentCell.rowIndex + 1;
1142
+ self.scrollBox.bar.v.y =
1143
+ columnHeaderCellHeight +
1144
+ columnHeaderCellBorder +
1145
+ self.scrollCache.y[self.frozenRow];
1146
+ self.scrollBox.box.v.y =
1147
+ columnHeaderCellHeight +
1148
+ columnHeaderCellBorder +
1149
+ self.scrollCache.y[self.frozenRow];
1150
+ var dataHeight = self.scrollCache.y[self.scrollCache.y.length - 1];
1151
+ self.scrollBox.heightBoxRatio =
1152
+ (self.scrollBox.height -
1153
+ columnHeaderCellHeight -
1154
+ self.scrollCache.y[self.frozenRow]) /
1155
+ dataHeight;
1156
+ self.scrollBox.scrollBoxHeight =
1157
+ self.scrollBox.height * self.scrollBox.heightBoxRatio -
1158
+ self.style.scrollBarWidth;
1159
+ self.scrollBox.scrollBoxHeight = Math.max(
1160
+ self.scrollBox.scrollBoxHeight,
1161
+ self.style.scrollBarBoxMinSize,
1162
+ );
1163
+ self.scrollBox.box.v.height = self.scrollBox.scrollBoxHeight;
1013
1164
  }
1014
1165
  if (
1015
1166
  self.currentCell &&
@@ -1018,6 +1169,22 @@ export default function (self) {
1018
1169
  ) {
1019
1170
  self.scrollBox.scrollLeft = 0;
1020
1171
  self.frozenColumn = self.currentCell.columnIndex + 1;
1172
+ self.scrollBox.bar.h.x =
1173
+ rowHeaderCellWidth + self.scrollCache.x[self.frozenColumn - 1];
1174
+ self.scrollBox.box.h.x =
1175
+ rowHeaderCellWidth + self.scrollCache.x[self.frozenColumn - 1];
1176
+ var dataWidth = self.scrollCache.x[self.scrollCache.x.length - 1];
1177
+ self.scrollBox.widthBoxRatio =
1178
+ (self.scrollBox.width - self.scrollCache.x[self.frozenColumn - 1]) /
1179
+ dataWidth;
1180
+ self.scrollBox.scrollBoxWidth =
1181
+ self.scrollBox.width * self.scrollBox.widthBoxRatio -
1182
+ self.style.scrollBarWidth;
1183
+ self.scrollBox.scrollBoxWidth = Math.max(
1184
+ self.scrollBox.scrollBoxWidth,
1185
+ self.style.scrollBarBoxMinSize,
1186
+ );
1187
+ self.scrollBox.box.h.width = self.scrollBox.scrollBoxWidth;
1021
1188
  }
1022
1189
  if (
1023
1190
  Math.abs(pos.x) > self.attributes.reorderDeadZone ||
@@ -1084,7 +1251,12 @@ export default function (self) {
1084
1251
  !freeze &&
1085
1252
  !resize
1086
1253
  ) {
1087
- self.selections = [];
1254
+ if (
1255
+ !(self.dragMode == 'row-reorder' && self.isMultiRowsSelected) &&
1256
+ !(self.currentCell.hovered && self.hovers.onFilterButton)
1257
+ ) {
1258
+ self.selections = [];
1259
+ }
1088
1260
  }
1089
1261
  if (self.dragStartObject.isGrid) {
1090
1262
  return;
@@ -1175,10 +1347,11 @@ export default function (self) {
1175
1347
  self.draggingItem = self.dragStartObject;
1176
1348
  if (
1177
1349
  self.dragMode === 'column-reorder' &&
1178
- self.attributes.columnHeaderClickBehavior === 'select'
1350
+ !self.isMultiColumnsSelected(self.currentCell.header.index)
1179
1351
  ) {
1180
1352
  self.selectColumn(self.currentCell.header.index, ctrl, e.shiftKey);
1181
- self.draw();
1353
+ } else if (self.dragMode === 'row-reorder' && !self.isMultiRowsSelected) {
1354
+ self.selectRow(self.dragStartObject.rowIndex, ctrl, null);
1182
1355
  }
1183
1356
  document.body.addEventListener('mousemove', self.dragReorder, false);
1184
1357
  document.body.addEventListener('mouseup', self.stopDragReorder, false);
@@ -1187,14 +1360,9 @@ export default function (self) {
1187
1360
  };
1188
1361
  self.mouseup = function (e) {
1189
1362
  clearTimeout(self.scrollTimer);
1190
- var ctrl = e.ctrlKey || e.metaKey;
1191
1363
  self.cellBoundaryCrossed = true;
1192
1364
  self.rowBoundaryCrossed = true;
1193
1365
  self.columnBoundaryCrossed = true;
1194
- if (self.draggingItem) {
1195
- self.selectColumn(self.currentCell.header.index, ctrl, e.shiftKey);
1196
- self.draw();
1197
- }
1198
1366
  self.selecting = undefined;
1199
1367
  self.draggingItem = undefined;
1200
1368
  self.dragStartObject = undefined;
@@ -1285,6 +1453,8 @@ export default function (self) {
1285
1453
  self.selectNone();
1286
1454
  } else if (ctrl && e.key === 'a') {
1287
1455
  self.selectAll();
1456
+ } else if (['Backspace', 'Delete'].includes(e.key)) {
1457
+ self.deleteSelectedData();
1288
1458
  } else if (e.key === 'ArrowDown') {
1289
1459
  y += 1;
1290
1460
  } else if (e.key === 'ArrowUp') {
@@ -1464,13 +1634,26 @@ export default function (self) {
1464
1634
  self.currentCell.context === 'ew-resize' &&
1465
1635
  self.currentCell.style === 'columnHeaderCell'
1466
1636
  ) {
1467
- self.fitColumnToValues(self.currentCell.header.name);
1637
+ // Check that double-clicked cell is selected or part of selection.
1638
+ const currentCellIsSelected = self.isColumnSelected(
1639
+ self.currentCell.columnIndex,
1640
+ );
1641
+
1642
+ if (currentCellIsSelected) {
1643
+ // There might be more
1644
+ self.fitSelectedColumns();
1645
+ } else {
1646
+ self.fitColumnToValues(self.currentCell.header.name);
1647
+ }
1468
1648
  } else if (
1469
1649
  self.currentCell.context === 'ew-resize' &&
1470
1650
  self.currentCell.style === 'cornerCell'
1471
1651
  ) {
1472
1652
  self.autosize();
1473
- } else if (['cell', 'activeCell'].indexOf(self.currentCell.style) !== -1) {
1653
+ } else if (
1654
+ ['cell', 'activeCell'].includes(self.currentCell.style) &&
1655
+ !self.hovers.onFilterButton
1656
+ ) {
1474
1657
  self.beginEditAt(self.currentCell.columnIndex, self.currentCell.rowIndex);
1475
1658
  }
1476
1659
  };
@@ -1694,103 +1877,38 @@ export default function (self) {
1694
1877
  });
1695
1878
  };
1696
1879
  self.cut = function (e) {
1697
- self.copy(e);
1698
- const schema = self.getSchema();
1699
-
1700
- var affectedCells = [];
1701
- for (const [rowIndex, row] of self.selections.entries()) {
1702
- if (!row) continue;
1880
+ if (self.dispatchEvent('cut', { NativeEvent: e })) {
1881
+ return;
1882
+ }
1703
1883
 
1704
- const boundRowIndex = self.getBoundRowIndexFromViewRowIndex(rowIndex);
1884
+ // Expecting instance of `ClipboardEvent` with `clipboardData` attribute
1885
+ if (!self.hasFocus || !e.clipboardData) {
1886
+ return;
1887
+ }
1705
1888
 
1706
- for (const columnIndex of row) {
1707
- const boundColumnIndex = self.getBoundColumnIndexFromViewColumnIndex(
1708
- columnIndex,
1709
- );
1710
- const colName = schema[boundColumnIndex].name;
1889
+ self.copySelectedCellsToClipboard(e.clipboardData);
1711
1890
 
1712
- self.viewData[rowIndex][colName] = '';
1891
+ const affectedCells = self.clearSelectedCells();
1713
1892
 
1714
- affectedCells.push([
1715
- rowIndex,
1716
- columnIndex,
1717
- boundRowIndex,
1718
- boundColumnIndex,
1719
- ]);
1720
- }
1721
- }
1893
+ self.dispatchEvent('aftercut', {
1894
+ cells: affectedCells,
1895
+ });
1722
1896
 
1723
- if (self.dispatchEvent('cut', { NativeEvent: e, cells: affectedCells })) {
1724
- return;
1725
- }
1897
+ requestAnimationFrame(() => self.draw());
1726
1898
  };
1727
1899
  self.copy = function (e) {
1728
1900
  if (self.dispatchEvent('copy', { NativeEvent: e })) {
1729
1901
  return;
1730
1902
  }
1903
+
1904
+ // Expecting instance of `ClipboardEvent` with `clipboardData` attribute
1731
1905
  if (!self.hasFocus || !e.clipboardData) {
1732
1906
  return;
1733
1907
  }
1734
- var t = '',
1735
- d = '',
1736
- textRows = [],
1737
- sData = self.getSelectedData(),
1738
- s = self.getSchema(),
1739
- sSorted = [],
1740
- firstRowKeys,
1741
- isNeat = true; // Selected like [[0, 1], [0, 1]] of [[0, 3]] is neat; Selected like [[0, 1], [1, 2]] is untidy
1742
- function htmlSafe(v) {
1743
- return v.replace(/</g, '&lt;').replace(/>/g, '&gt;');
1744
- }
1745
- s.forEach(function (column, columnIndex) {
1746
- sSorted.push(s[self.orders.columns[columnIndex]]);
1747
- });
1748
- if (sData.length > 0) {
1749
- sData.forEach((row) => {
1750
- if (!row) return;
1751
- var rowKeys = Object.keys(row);
1752
- var textRow = [];
1753
- if (!firstRowKeys) firstRowKeys = Object.keys(row);
1754
- if (isNeat && rowKeys.length !== firstRowKeys.length) isNeat = false;
1755
- sSorted.forEach(function (column, columnIndex) {
1756
- if (rowKeys.indexOf(column.name) < 0) {
1757
- if (firstRowKeys.indexOf(column.name) < 0) {
1758
- return;
1759
- } else if (isNeat) {
1760
- isNeat = false;
1761
- }
1762
- }
1763
- textRow.push(row[column.name] || '');
1764
- });
1765
- textRows.push(textRow);
1766
- });
1767
- if (isNeat) {
1768
- t = textRows.map((row) => row.join('\t')).join('\n');
1769
- /**
1770
- * The html content copied by Excel has not header
1771
- */
1772
- d += '<table>';
1773
- d += textRows
1774
- .map(
1775
- (row) =>
1776
- '<tr>' +
1777
- row.map((value) => '<td>' + htmlSafe(value) + '</td>').join('') +
1778
- '</tr>',
1779
- )
1780
- .join('');
1781
- d += '</table>';
1782
- } else {
1783
- t = textRows.map((row) => row.join('')).join('');
1784
- d = t;
1785
- }
1786
- if (t) {
1787
- e.clipboardData.setData('text/html', d);
1788
- e.clipboardData.setData('text/plain', t);
1789
- e.clipboardData.setData('text/csv', t);
1790
- e.clipboardData.setData('application/json', JSON.stringify(sData));
1791
- }
1792
- e.preventDefault();
1793
- }
1908
+
1909
+ self.copySelectedCellsToClipboard(e.clipboardData);
1910
+
1911
+ e.preventDefault();
1794
1912
  };
1795
1913
  return;
1796
1914
  }
@@ -86,11 +86,49 @@ const parseData = function (data, mimeType) {
86
86
  return parseText(data);
87
87
  };
88
88
 
89
+ const htmlSafe = (value) => {
90
+ if (typeof value === 'number') return value;
91
+ return value.replace(/</g, '&lt;').replace(/>/g, '&gt;');
92
+ };
93
+
94
+ const createTextString = (selectedData, isNeat) => {
95
+ // Selected like [[0, 1], [0, 1]] of [[0, 3]] is neat; Selected like [[0, 1], [1, 2]] is untidy.
96
+ // If not isNeat we just return a simple string of concatenated values.
97
+ if (!isNeat)
98
+ return selectedData.map((row) => Object.values(row).join('')).join('');
99
+
100
+ // If isNeat, we can create tab separated mutti-line text.
101
+ return selectedData.map((row) => Object.values(row).join('\t')).join('\n');
102
+ };
103
+
104
+ const createHTMLString = (selectedData, isNeat) => {
105
+ if (!isNeat) return createTextString(selectedData, isNeat);
106
+
107
+ // If isNeat, we can create a HTML table with the selected data.
108
+ let htmlString = '<table>';
109
+ htmlString += selectedData
110
+ .map(
111
+ (row) =>
112
+ '<tr>' +
113
+ Object.values(row)
114
+ .map((value) => '<td>' + htmlSafe(value) + '</td>')
115
+ .join('') +
116
+ '</tr>',
117
+ )
118
+ .join('');
119
+ htmlString += '</table>';
120
+
121
+ return htmlString;
122
+ };
123
+
89
124
  export {
125
+ createTextString,
126
+ createHTMLString,
90
127
  isSupportedHtml,
91
- sanitizeElementData,
128
+ htmlSafe,
92
129
  parseData,
93
130
  parseHtmlTable,
94
131
  parseHtmlText,
95
132
  parseText,
133
+ sanitizeElementData,
96
134
  };