canvas-datagrid 0.4.1 → 0.4.4

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.
@@ -74,6 +74,43 @@ export default function (self) {
74
74
  1),
75
75
  );
76
76
  };
77
+ /**
78
+ * @returns {number} dataWidth
79
+ */
80
+ self.refreshScrollCacheX = function () {
81
+ const s = self.getSchema();
82
+ self.scrollCache.x = [];
83
+
84
+ /** @type {number} it will be used in `reduceSchema` only */
85
+ let frozenWidth = 0;
86
+
87
+ const collapsedColumnGroups = self.getCollapsedColumnGroups();
88
+ const isColumnCollapsed = (columnIndex) =>
89
+ collapsedColumnGroups.findIndex(
90
+ (group) => columnIndex >= group.from && columnIndex <= group.to,
91
+ ) >= 0;
92
+
93
+ const dataWidth =
94
+ s.reduce(function reduceSchema(accumulator, column, columnIndex) {
95
+ // intentional redefintion of column. This causes scrollCache to be in the correct order
96
+ const schemaIndex = self.orders.columns[columnIndex];
97
+ const columnWidth = self.getColumnWidth(schemaIndex);
98
+ column = s[schemaIndex];
99
+ if (!column.hidden && !isColumnCollapsed(columnIndex))
100
+ accumulator += columnWidth;
101
+ if (columnIndex < self.frozenColumn) {
102
+ self.scrollCache.x[columnIndex] = accumulator;
103
+ frozenWidth = accumulator;
104
+ } else {
105
+ self.scrollCache.x[columnIndex] = Math.max(
106
+ frozenWidth + columnWidth,
107
+ accumulator,
108
+ );
109
+ }
110
+ return accumulator;
111
+ }, 0) || 0;
112
+ return dataWidth;
113
+ };
77
114
  self.resize = function (drawAfterResize) {
78
115
  if (!self.canvas) {
79
116
  return;
@@ -132,8 +169,7 @@ export default function (self) {
132
169
  rowHeaderCellWidth = self.getRowHeaderCellWidth(),
133
170
  topGroupAreaHeight = self.getColumnGroupAreaHeight(),
134
171
  leftGroupAreaWidth = self.getRowGroupAreaWidth(),
135
- ch = self.style.cellHeight,
136
- s = self.getSchema();
172
+ ch = self.style.cellHeight;
137
173
  // sets actual DOM canvas element
138
174
  function checkScrollBoxVisibility() {
139
175
  self.scrollBox.horizontalBarVisible =
@@ -187,7 +223,7 @@ export default function (self) {
187
223
  }
188
224
  });
189
225
  }
190
- self.scrollCache.x = [];
226
+ dataWidth = self.refreshScrollCacheX();
191
227
  self.scrollCache.y = [];
192
228
  for (x = 0; x < l; x += 1) {
193
229
  self.scrollCache.y[x] = dataHeight;
@@ -199,32 +235,6 @@ export default function (self) {
199
235
  if (l > 1) {
200
236
  self.scrollCache.y[x] = dataHeight;
201
237
  }
202
- const collapsedColumnGroups = self.getCollapsedColumnGroups();
203
- const isColumnCollapsed = (columnIndex) =>
204
- collapsedColumnGroups.findIndex(
205
- (group) => columnIndex >= group.from && columnIndex <= group.to,
206
- ) >= 0;
207
- /** @type {number} it will be used in `reduceSchema` only */
208
- let frozenWidth = 0;
209
- dataWidth =
210
- s.reduce(function reduceSchema(accumulator, column, columnIndex) {
211
- // intentional redefintion of column. This causes scrollCache to be in the correct order
212
- const schemaIndex = self.orders.columns[columnIndex];
213
- const columnWidth = self.getColumnWidth(schemaIndex);
214
- column = s[schemaIndex];
215
- if (!column.hidden && !isColumnCollapsed(columnIndex))
216
- accumulator += columnWidth;
217
- if (columnIndex < self.frozenColumn) {
218
- self.scrollCache.x[columnIndex] = accumulator;
219
- frozenWidth = accumulator;
220
- } else {
221
- self.scrollCache.x[columnIndex] = Math.max(
222
- frozenWidth + columnWidth,
223
- accumulator,
224
- );
225
- }
226
- return accumulator;
227
- }, 0) || 0;
228
238
  if (self.attributes.showNewRow) {
229
239
  dataHeight += ch;
230
240
  }
@@ -376,9 +386,17 @@ export default function (self) {
376
386
  );
377
387
  // set canvas drawing related items
378
388
  if (!self.isChildGrid) {
379
- self.canvas.width = self.width * ratio;
380
- self.canvas.height = self.height * ratio;
381
- self.ctx.scale(ratio, ratio);
389
+ const newWidth = self.width * ratio;
390
+ const newHeight = self.height * ratio;
391
+ // We need to check is settings size to canvas necessary,
392
+ // because settings the canvas'size will cause the canvas and its state be cleared
393
+ // even if the size is the same.
394
+ // Notes: Please don't call `self.resize()` without a subsequent call to `self.draw()`
395
+ if (self.canvas.width !== newWidth || self.canvas.height !== newHeight) {
396
+ self.canvas.width = newWidth;
397
+ self.canvas.height = newHeight;
398
+ self.ctx.scale(ratio, ratio);
399
+ }
382
400
  }
383
401
  // resize any open dom elements (input/textarea)
384
402
  self.resizeEditInput();
@@ -455,6 +473,14 @@ export default function (self) {
455
473
  if (self.contextMenu || self.input) {
456
474
  return;
457
475
  }
476
+
477
+ // Cancel dragging action if user ventures outside grid
478
+ if (self.draggingItem && e.which === 0) {
479
+ self.stopFreezeMove(e);
480
+ self.mouseup(e);
481
+ return;
482
+ }
483
+
458
484
  self.mouse = overridePos || self.getLayerPos(e);
459
485
  var ctrl =
460
486
  (e.ctrlKey || e.metaKey || self.attributes.persistantSelectionMode) &&
@@ -493,6 +519,20 @@ export default function (self) {
493
519
  }
494
520
  self.currentCell = cell;
495
521
 
522
+ if (
523
+ !self.draggingItem && // It is not in dragging mode (avoid changing hovers frequent)
524
+ cell &&
525
+ (cell.context === 'cell' || cell.context === self.cursorGrab)
526
+ ) {
527
+ const indicator = self.getUnhideIndicator(self.mouse.x, self.mouse.y);
528
+ if (indicator) {
529
+ self.cursor = 'pointer';
530
+ self.hovers = { unhideIndicator: indicator };
531
+ self.draw();
532
+ return;
533
+ }
534
+ }
535
+
496
536
  self.hovers = {};
497
537
  if (!self.draggingItem && cell) {
498
538
  self.dragItem = cell;
@@ -584,6 +624,9 @@ export default function (self) {
584
624
  dragBounds.top = -1;
585
625
  dragBounds.bottom = self.viewData.length - 1;
586
626
  if (dragBounds.left < 0) dragBounds.left = 0;
627
+ if (dragBounds.left != dragBounds.right)
628
+ self.isMultiColumnsSelected = true;
629
+ else self.isMultiRowsSelected = false;
587
630
  }
588
631
 
589
632
  if (
@@ -697,6 +740,8 @@ export default function (self) {
697
740
  ) {
698
741
  if (!(cell.hovered && self.hovers.onFilterButton)) {
699
742
  self.selections = [];
743
+ self.selectedRows = [];
744
+ self.selectedColumns = [];
700
745
  }
701
746
  if (dragBounds.top === -1) {
702
747
  dragBounds.top = 0;
@@ -708,8 +753,13 @@ export default function (self) {
708
753
  }
709
754
  } else {
710
755
  self.selectArea(sBounds, true);
711
- if (sBounds.left == -1 && sBounds.top !== sBounds.bottom)
756
+ self.activeCell.rowIndex = sBounds.top;
757
+ self.activeCell.columnIndex = sBounds.left;
758
+ if (sBounds.left == -1 && sBounds.top !== sBounds.bottom) {
759
+ self.activeCell.columnIndex = 0;
712
760
  self.isMultiRowsSelected = true;
761
+ self.isMultiColumnsSelected = false;
762
+ }
713
763
  }
714
764
  }
715
765
 
@@ -783,6 +833,15 @@ export default function (self) {
783
833
  return;
784
834
  }
785
835
 
836
+ const unhideIndicator = self.getUnhideIndicator(pos.x, pos.y);
837
+ if (unhideIndicator) {
838
+ const { dir, orderIndex0, orderIndex1 } = unhideIndicator;
839
+ if (dir === 'l' || dir === 'r')
840
+ self.unhideColumns(orderIndex0, orderIndex1);
841
+ else self.unhideRows(orderIndex0, orderIndex1);
842
+ return;
843
+ }
844
+
786
845
  let group = self.getColumnGroupAt(pos.x, pos.y);
787
846
  if (!group) group = self.getRowGroupAt(pos.x, pos.y);
788
847
  if (group) {
@@ -940,12 +999,8 @@ export default function (self) {
940
999
  }
941
1000
 
942
1001
  self.resize();
943
- document.body.removeEventListener(
944
- 'mousemove',
945
- self.dragResizeColumn,
946
- false,
947
- );
948
- document.body.removeEventListener('mouseup', self.stopDragResize, false);
1002
+ window.removeEventListener('mousemove', self.dragResizeColumn, false);
1003
+ window.removeEventListener('mouseup', self.stopDragResize, false);
949
1004
  self.setStorageData();
950
1005
  self.draw(true);
951
1006
  self.ignoreNextClick = true;
@@ -1052,7 +1107,7 @@ export default function (self) {
1052
1107
  if (document.exitPointerLock) {
1053
1108
  document.exitPointerLock();
1054
1109
  }
1055
- document.removeEventListener('mousemove', self.scrollGrid, false);
1110
+ window.removeEventListener('mousemove', self.scrollGrid, false);
1056
1111
  };
1057
1112
  self.dragReorder = function (e) {
1058
1113
  var pos,
@@ -1070,10 +1125,7 @@ export default function (self) {
1070
1125
  return;
1071
1126
  }
1072
1127
  if ((e.ctrlKey || e.metaKey || e.shiftKey) && self.reorderObject) {
1073
- if (
1074
- self.dragMode === 'column-reorder' &&
1075
- !self.isMultiColumnsSelected(self.draggingItem.header.index)
1076
- ) {
1128
+ if (self.dragMode === 'column-reorder' && !self.isMultiColumnsSelected) {
1077
1129
  self.selectColumn(self.draggingItem.header.index, false, false);
1078
1130
  }
1079
1131
  }
@@ -1097,6 +1149,11 @@ export default function (self) {
1097
1149
  -1,
1098
1150
  self.activeCell.rowIndex,
1099
1151
  );
1152
+ if (self.isMultiColumnsSelected)
1153
+ self.reorderObject = self.getVisibleCellByIndex(
1154
+ self.activeCell.columnIndex,
1155
+ -1,
1156
+ );
1100
1157
  if (!self.reorderObject) return;
1101
1158
  self.reorderTarget = self.currentCell;
1102
1159
  self.reorderObject.dragOffset = {
@@ -1123,8 +1180,8 @@ export default function (self) {
1123
1180
  'row-reorder': 'rowIndex',
1124
1181
  'column-reorder': 'sortColumnIndex',
1125
1182
  }[self.dragMode];
1126
- document.body.removeEventListener('mousemove', self.dragReorder, false);
1127
- document.body.removeEventListener('mouseup', self.stopDragReorder, false);
1183
+ window.removeEventListener('mousemove', self.dragReorder, false);
1184
+ window.removeEventListener('mouseup', self.stopDragReorder, false);
1128
1185
  if (
1129
1186
  self.reorderObject &&
1130
1187
  self.reorderTarget &&
@@ -1147,23 +1204,34 @@ export default function (self) {
1147
1204
  tIndex = cr[self.dragMode].indexOf(self.reorderTarget[i]);
1148
1205
  if (self.dragMode === 'column-reorder') {
1149
1206
  var sortColumnIndices = [];
1150
- var seletedColumnIndices = [];
1207
+ var selectedColumnIndices = [];
1151
1208
  if (self.selections[0]) {
1209
+ oIndex = self.selections[0][0];
1152
1210
  self.selections[0].forEach(function (value) {
1153
1211
  sortColumnIndices.push(self.orders.columns[value]);
1154
1212
  });
1155
1213
  }
1156
1214
  var deleteCount = sortColumnIndices.length;
1157
- cr[self.dragMode].splice(oIndex, deleteCount);
1158
- if (tIndex > oIndex) tIndex = tIndex - (deleteCount - 1);
1159
- for (var i = 0; i < sortColumnIndices.length; i++) {
1160
- seletedColumnIndices.push(tIndex + i);
1161
- cr[self.dragMode].splice(tIndex + i, 0, sortColumnIndices[i]);
1215
+ if (
1216
+ tIndex < oIndex ||
1217
+ (tIndex > oIndex && Math.abs(tIndex - oIndex) >= deleteCount)
1218
+ ) {
1219
+ cr[self.dragMode].splice(oIndex, deleteCount);
1220
+ if (tIndex > oIndex) tIndex = tIndex - (deleteCount - 1);
1221
+
1222
+ self.selectedColumns = [];
1223
+ for (var i = 0; i < sortColumnIndices.length; i++) {
1224
+ if (i === 0) self.activeCell.columnIndex = tIndex;
1225
+ selectedColumnIndices.push(tIndex + i);
1226
+ self.selectedColumns.push(sortColumnIndices[i]);
1227
+ cr[self.dragMode].splice(tIndex + i, 0, sortColumnIndices[i]);
1228
+ }
1229
+
1230
+ self.orders.columns = cr[self.dragMode];
1231
+ self.viewData.forEach(function (row, rowIndex) {
1232
+ self.selections[rowIndex] = selectedColumnIndices;
1233
+ });
1162
1234
  }
1163
- self.orders.columns = cr[self.dragMode];
1164
- self.viewData.forEach(function (row, rowIndex) {
1165
- self.selections[rowIndex] = seletedColumnIndices;
1166
- });
1167
1235
  } else {
1168
1236
  var selectedRows = [];
1169
1237
  self.selections.forEach(function (row, rowIndex) {
@@ -1172,13 +1240,21 @@ export default function (self) {
1172
1240
  odata.push(self.viewData[rowIndex]);
1173
1241
  }
1174
1242
  });
1175
- self.viewData.splice(oIndex, odata.length);
1176
- self.selections = [];
1177
- if (tIndex > oIndex) tIndex = tIndex - (odata.length - 1);
1178
- self.activeCell.rowIndex = tIndex;
1179
- for (var i = 0; i < odata.length; i++) {
1180
- self.viewData.splice(tIndex + i, 0, odata[i]);
1181
- self.selections[tIndex + i] = selectedRows[i];
1243
+ if (
1244
+ tIndex < oIndex ||
1245
+ (tIndex > oIndex && Math.abs(tIndex - oIndex) >= odata.length)
1246
+ ) {
1247
+ self.viewData.splice(oIndex, odata.length);
1248
+ self.selections = [];
1249
+ self.selectedRows = [];
1250
+ if (tIndex > oIndex) tIndex = tIndex - (odata.length - 1);
1251
+ self.activeCell.rowIndex = tIndex;
1252
+
1253
+ for (var i = 0; i < odata.length; i++) {
1254
+ self.viewData.splice(tIndex + i, 0, odata[i]);
1255
+ self.selections[tIndex + i] = selectedRows[i];
1256
+ self.selectedRows.push(tIndex + i);
1257
+ }
1182
1258
  }
1183
1259
  }
1184
1260
  self.resize();
@@ -1209,8 +1285,8 @@ export default function (self) {
1209
1285
  }
1210
1286
  };
1211
1287
  self.stopDragMove = function (e) {
1212
- document.body.removeEventListener('mousemove', self.dragMove, false);
1213
- document.body.removeEventListener('mouseup', self.stopDragMove, false);
1288
+ window.removeEventListener('mousemove', self.dragMove, false);
1289
+ window.removeEventListener('mouseup', self.stopDragMove, false);
1214
1290
  var b = self.getSelectionBounds();
1215
1291
  if (
1216
1292
  self.dispatchEvent('endmove', { NativeEvent: e, cell: self.currentCell })
@@ -1241,16 +1317,30 @@ export default function (self) {
1241
1317
  ) {
1242
1318
  return;
1243
1319
  }
1244
- var pos = self.getLayerPos(e),
1320
+ var pos = self.getLayerPos(e);
1321
+
1322
+ self.ignoreNextClick = true;
1323
+ self.freezeMarkerPosition = pos;
1324
+ pos.x -= self.getRowGroupAreaWidth();
1325
+ pos.y -= self.getColumnGroupAreaHeight();
1326
+ if (
1327
+ Math.abs(pos.x) > self.attributes.reorderDeadZone ||
1328
+ Math.abs(pos.y) > self.attributes.reorderDeadZone
1329
+ ) {
1330
+ setTimeout(function () {
1331
+ self.autoScrollZone(e, pos.x, pos.y, false);
1332
+ }, 1);
1333
+ }
1334
+ };
1335
+ self.stopFreezeMove = function (e) {
1336
+ let pos = self.getLayerPos(e),
1245
1337
  bm = self.style.gridBorderCollapse === 'collapse' ? 1 : 2,
1246
1338
  columnHeaderCellBorder = self.style.columnHeaderCellBorderWidth * bm,
1247
1339
  columnHeaderCellHeight = self.getColumnHeaderCellHeight(),
1248
1340
  rowHeaderCellWidth = self.getRowHeaderCellWidth();
1249
-
1250
- self.ignoreNextClick = true;
1251
- self.freezeMarkerPosition = pos;
1252
1341
  pos.x -= self.getRowGroupAreaWidth();
1253
1342
  pos.y -= self.getColumnGroupAreaHeight();
1343
+
1254
1344
  if (
1255
1345
  self.currentCell &&
1256
1346
  self.currentCell.rowIndex !== undefined &&
@@ -1286,15 +1376,20 @@ export default function (self) {
1286
1376
  self.currentCell.columnIndex !== undefined &&
1287
1377
  self.dragMode === 'frozen-column-marker'
1288
1378
  ) {
1379
+ const dataWidth = self.refreshScrollCacheX();
1289
1380
  self.scrollBox.scrollLeft = 0;
1290
- self.frozenColumn = self.currentCell.columnIndex + 1;
1381
+ let x =
1382
+ self.currentCell.x -
1383
+ self.style.frozenMarkerWidth -
1384
+ self.style.frozenMarkerBorderWidth;
1385
+ if (pos.x > x + self.currentCell.width / 2)
1386
+ self.frozenColumn = self.currentCell.columnIndex + 1;
1387
+ else if (self.currentCell.columnIndex >= 0)
1388
+ self.frozenColumn = self.currentCell.columnIndex;
1291
1389
  self.scrollBox.bar.h.x =
1292
- rowHeaderCellWidth + self.scrollCache.x[self.frozenColumn - 1];
1293
- self.scrollBox.box.h.x =
1294
- rowHeaderCellWidth + self.scrollCache.x[self.frozenColumn - 1];
1295
- var dataWidth = self.scrollCache.x[self.scrollCache.x.length - 1];
1390
+ rowHeaderCellWidth + self.scrollCache.x[self.frozenColumn];
1296
1391
  self.scrollBox.widthBoxRatio =
1297
- (self.scrollBox.width - self.scrollCache.x[self.frozenColumn - 1]) /
1392
+ (self.scrollBox.width - self.scrollCache.x[self.frozenColumn]) /
1298
1393
  dataWidth;
1299
1394
  self.scrollBox.scrollBoxWidth =
1300
1395
  self.scrollBox.width * self.scrollBox.widthBoxRatio -
@@ -1313,10 +1408,9 @@ export default function (self) {
1313
1408
  self.autoScrollZone(e, pos.x, pos.y, false);
1314
1409
  }, 1);
1315
1410
  }
1316
- };
1317
- self.stopFreezeMove = function (e) {
1318
- document.body.removeEventListener('mousemove', self.freezeMove, false);
1319
- document.body.removeEventListener('mouseup', self.stopFreezeMove, false);
1411
+
1412
+ window.removeEventListener('mousemove', self.freezeMove, false);
1413
+ window.removeEventListener('mouseup', self.stopFreezeMove, false);
1320
1414
  self.freezeMarkerPosition = undefined;
1321
1415
  if (
1322
1416
  self.dispatchEvent('endfreezemove', {
@@ -1330,6 +1424,7 @@ export default function (self) {
1330
1424
  return;
1331
1425
  }
1332
1426
  self.draw(true);
1427
+ self.resize();
1333
1428
  };
1334
1429
  self.mousedown = function (e, overridePos) {
1335
1430
  self.lastMouseDownTarget = e.target;
@@ -1351,6 +1446,7 @@ export default function (self) {
1351
1446
  move = /-move/.test(self.dragMode),
1352
1447
  freeze = /frozen-row-marker|frozen-column-marker/.test(self.dragMode),
1353
1448
  resize = /-resize/.test(self.dragMode);
1449
+ const onUnhideIndicator = self.hovers && self.hovers.unhideIndicator;
1354
1450
  self.dragStart = overridePos || self.getLayerPos(e);
1355
1451
  self.scrollStart = {
1356
1452
  left: self.scrollBox.scrollLeft,
@@ -1375,12 +1471,17 @@ export default function (self) {
1375
1471
  !(self.currentCell.hovered && self.hovers.onFilterButton)
1376
1472
  ) {
1377
1473
  self.selections = [];
1474
+ self.selectedRows = [];
1475
+ self.selectedColumns = [];
1378
1476
  }
1379
1477
  }
1380
1478
  if (self.dragStartObject.isGrid) {
1381
1479
  return;
1382
1480
  }
1383
- if (self.scrollModes.indexOf(self.dragStartObject.context) !== -1) {
1481
+ if (
1482
+ self.scrollModes.indexOf(self.dragStartObject.context) !== -1 &&
1483
+ !onUnhideIndicator
1484
+ ) {
1384
1485
  self.scrollMode = self.dragStartObject.context;
1385
1486
  self.scrollStartMode = self.dragStartObject.context;
1386
1487
  self.scrollGrid(e);
@@ -1396,8 +1497,8 @@ export default function (self) {
1396
1497
  };
1397
1498
  self.canvas.requestPointerLock();
1398
1499
  }
1399
- document.addEventListener('mousemove', self.scrollGrid, false);
1400
- document.addEventListener('mouseup', self.stopScrollGrid, false);
1500
+ window.addEventListener('mousemove', self.scrollGrid, false);
1501
+ window.addEventListener('mouseup', self.stopScrollGrid, false);
1401
1502
  self.ignoreNextClick = true;
1402
1503
  return;
1403
1504
  }
@@ -1415,7 +1516,9 @@ export default function (self) {
1415
1516
  self.dragStartObject.columnIndex > -1
1416
1517
  ) {
1417
1518
  self.selectColumn(self.currentCell.header.index, ctrl, e.shiftKey);
1418
- } else if (self.attributes.selectionMode !== 'row') {
1519
+ return;
1520
+ }
1521
+ if (self.attributes.selectionMode !== 'row') {
1419
1522
  self.mousemove(e);
1420
1523
  }
1421
1524
  return;
@@ -1432,8 +1535,8 @@ export default function (self) {
1432
1535
  ) {
1433
1536
  return;
1434
1537
  }
1435
- document.body.addEventListener('mousemove', self.dragMove, false);
1436
- document.body.addEventListener('mouseup', self.stopDragMove, false);
1538
+ window.addEventListener('mousemove', self.dragMove, false);
1539
+ window.addEventListener('mouseup', self.stopDragMove, false);
1437
1540
  return self.mousemove(e);
1438
1541
  }
1439
1542
  if (freeze) {
@@ -1445,11 +1548,15 @@ export default function (self) {
1445
1548
  if (self.dispatchEvent('beginfreezemove', { NativeEvent: e })) {
1446
1549
  return;
1447
1550
  }
1448
- document.body.addEventListener('mousemove', self.freezeMove, false);
1449
- document.body.addEventListener('mouseup', self.stopFreezeMove, false);
1551
+
1552
+ self.freezeMarkerPosition = self.getLayerPos(e);
1553
+ self.freezeMarkerPosition.isGrab = true;
1554
+
1555
+ window.addEventListener('mousemove', self.freezeMove, false);
1556
+ window.addEventListener('mouseup', self.stopFreezeMove, false);
1450
1557
  return self.mousemove(e);
1451
1558
  }
1452
- if (resize) {
1559
+ if (resize && !onUnhideIndicator) {
1453
1560
  self.draggingItem = self.dragItem;
1454
1561
  if (self.draggingItem.rowOpen) {
1455
1562
  self.resizingStartingHeight =
@@ -1464,22 +1571,19 @@ export default function (self) {
1464
1571
  ? 'cornerCell'
1465
1572
  : self.draggingItem.sortColumnIndex
1466
1573
  ] || self.draggingItem.width;
1467
- document.body.addEventListener('mousemove', self.dragResizeColumn, false);
1468
- document.body.addEventListener('mouseup', self.stopDragResize, false);
1574
+ window.addEventListener('mousemove', self.dragResizeColumn, false);
1575
+ window.addEventListener('mouseup', self.stopDragResize, false);
1469
1576
  return;
1470
1577
  }
1471
1578
  if (['row-reorder', 'column-reorder'].indexOf(self.dragMode) !== -1) {
1472
1579
  self.draggingItem = self.dragStartObject;
1473
- if (
1474
- self.dragMode === 'column-reorder' &&
1475
- !self.isMultiColumnsSelected(self.currentCell.header.index)
1476
- ) {
1580
+ if (self.dragMode === 'column-reorder' && !self.isMultiColumnsSelected) {
1477
1581
  self.selectColumn(self.currentCell.header.index, ctrl, e.shiftKey);
1478
1582
  } else if (self.dragMode === 'row-reorder' && !self.isMultiRowsSelected) {
1479
1583
  self.selectRow(self.dragStartObject.rowIndex, ctrl, null);
1480
1584
  }
1481
- document.body.addEventListener('mousemove', self.dragReorder, false);
1482
- document.body.addEventListener('mouseup', self.stopDragReorder, false);
1585
+ window.addEventListener('mousemove', self.dragReorder, false);
1586
+ window.addEventListener('mouseup', self.stopDragReorder, false);
1483
1587
  return;
1484
1588
  }
1485
1589
  };
@@ -1707,6 +1811,8 @@ export default function (self) {
1707
1811
  if (!e.shiftKey && self.attributes.selectionFollowsActiveCell) {
1708
1812
  if (!ctrl) {
1709
1813
  self.selections = [];
1814
+ self.selectedRows = [];
1815
+ self.selectedColumns = [];
1710
1816
  }
1711
1817
  self.selections[y] = self.selections[y] || [];
1712
1818
  self.selections[y].push(x);
@@ -1865,6 +1971,8 @@ export default function (self) {
1865
1971
  });
1866
1972
  } else {
1867
1973
  var selections = [];
1974
+ self.selectedRows = [];
1975
+ self.selectedColumns = [];
1868
1976
  for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) {
1869
1977
  // Rows may have been moved by user, so get the actual row index
1870
1978
  // (instead of the row index at which the row is rendered):
@@ -1875,6 +1983,7 @@ export default function (self) {
1875
1983
  var newRowData = Object.assign({}, existingRowData);
1876
1984
 
1877
1985
  selections[realRowIndex] = [];
1986
+ self.selectedRows.push(realRowIndex);
1878
1987
 
1879
1988
  for (var colIndex = 0; colIndex < cells.length; colIndex++) {
1880
1989
  var column = schema[startColIndex + colIndex];
@@ -1897,6 +2006,8 @@ export default function (self) {
1897
2006
  selections[realRowIndex].push(startColIndex + colIndex);
1898
2007
 
1899
2008
  newRowData[columnName] = cellData;
2009
+ if (self.selectedColumns.indexOf(startColIndex + colIndex) === -1)
2010
+ self.selectedColumns.push(startColIndex + colIndex);
1900
2011
  }
1901
2012
 
1902
2013
  self.originalData[self.boundRowIndexMap.get(realRowIndex)] = newRowData;
@@ -0,0 +1,42 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Merge a new hidden row range into existed ranges array
5
+ * @param {any[]} hiddenRowRanges tuples: Array<[bgeinRowIndex, endRowIndex]>
6
+ * @param {number[]} newRange tuple: [beginRowIndex, endRowIndex]
7
+ * @returns {boolean}
8
+ */
9
+ const mergeHiddenRowRanges = function (hiddenRowRanges, newRange) {
10
+ const [beginRowIndex, endRowIndex] = newRange;
11
+ if (endRowIndex < beginRowIndex) return false;
12
+ let inserted = false;
13
+ for (let i = 0; i < hiddenRowRanges.length; i++) {
14
+ const range = hiddenRowRanges[i];
15
+ if (beginRowIndex > range[1] + 1) continue;
16
+ if (beginRowIndex <= range[0] && endRowIndex >= range[0]) {
17
+ hiddenRowRanges[i] = [beginRowIndex, Math.max(endRowIndex, range[1])];
18
+ inserted = true;
19
+ break;
20
+ }
21
+ if (beginRowIndex >= range[0]) {
22
+ hiddenRowRanges[i] = [range[0], Math.max(endRowIndex, range[1])];
23
+ inserted = true;
24
+ break;
25
+ }
26
+ }
27
+ if (!inserted) hiddenRowRanges.push([beginRowIndex, endRowIndex]);
28
+ // merge intersections after sorting ranges
29
+ hiddenRowRanges.sort((a, b) => a[0] - b[0]);
30
+ for (let i = 0; i < hiddenRowRanges.length - 1; i++) {
31
+ const range = hiddenRowRanges[i];
32
+ const nextRange = hiddenRowRanges[i + 1];
33
+ if (nextRange[0] <= range[1] + 1) {
34
+ hiddenRowRanges[i] = [range[0], Math.max(range[1], nextRange[1])];
35
+ hiddenRowRanges.splice(i + 1, 1);
36
+ i--;
37
+ }
38
+ }
39
+ return true;
40
+ };
41
+
42
+ export { mergeHiddenRowRanges };
package/lib/intf.js CHANGED
@@ -57,6 +57,19 @@ export default function (self, ctor) {
57
57
  self.scrollBox = {};
58
58
  self.visibleRows = [];
59
59
  self.visibleCells = [];
60
+ /**
61
+ * Each item of this array contains these properties:
62
+ * - `x`, `y`, `x2`, `y2`
63
+ * - `orderIndex0`, `orderIndex1`: The closed interval of the hiding rows/columns.
64
+ * - `dir`: The directon of the unhide indicator. 'l' and 'r' for columns, 't' and 'b' for rows
65
+ */
66
+ self.visibleUnhideIndicators = [];
67
+ /**
68
+ * Each item is a tuple conatins two numbers:
69
+ * its type difination: Array<[beginRowIndex, endRowIndex]>
70
+ * Each tuple represents a closed Interval
71
+ */
72
+ self.hiddenRowRanges = [];
60
73
  /**
61
74
  * This array stored all groups information with context for drawing,
62
75
  * it is generated by drawing functions,
@@ -77,6 +90,8 @@ export default function (self, ctor) {
77
90
  trees: {},
78
91
  };
79
92
  self.selections = [];
93
+ self.selectedRows = [];
94
+ self.selectedColumns = [];
80
95
  self.filterable = {
81
96
  rows: [],
82
97
  columns: [],
@@ -162,6 +177,8 @@ export default function (self, ctor) {
162
177
  'cellmouseover',
163
178
  'click',
164
179
  'collapsetree',
180
+ 'columnhide',
181
+ 'columnunhide',
165
182
  'contextmenu',
166
183
  'copy',
167
184
  'datachanged',
@@ -654,6 +671,16 @@ export default function (self, ctor) {
654
671
  originalRowIndex,
655
672
  ]);
656
673
 
674
+ // Remove hidden rows here. So we can keep the bound indexes correct
675
+ if (self.hiddenRowRanges.length > 0) {
676
+ const ranges = self.hiddenRowRanges.sort((a, b) => b[1] - a[1]);
677
+ for (let i = 0; i < ranges.length; i++) {
678
+ const [beginRowIndex, endRowIndex] = ranges[i];
679
+ const countOfRows = endRowIndex - beginRowIndex + 1;
680
+ newViewData.splice(beginRowIndex, countOfRows);
681
+ }
682
+ }
683
+
657
684
  // Apply filtering
658
685
  for (const [headerName, filterText] of Object.entries(self.columnFilters)) {
659
686
  const header = self.getHeaderByName(headerName);
@@ -880,7 +907,6 @@ export default function (self, ctor) {
880
907
  if (!self.isChildGrid) {
881
908
  document.body.removeChild(self.controlInput);
882
909
  }
883
- self.eventParent.removeEventListener('mouseup', self.mouseup, false);
884
910
  self.eventParent.removeEventListener('mousedown', self.mousedown, false);
885
911
  self.eventParent.removeEventListener('dblclick', self.dblclick, false);
886
912
  self.eventParent.removeEventListener('click', self.click, false);
@@ -894,7 +920,8 @@ export default function (self, ctor) {
894
920
  self.controlInput.removeEventListener('keypress', self.keypress, false);
895
921
  self.controlInput.removeEventListener('keyup', self.keyup, false);
896
922
  self.controlInput.removeEventListener('keydown', self.keydown, false);
897
- document.body.removeEventListener('mousemove', self.mousemove);
923
+ window.removeEventListener('mouseup', self.mouseup, false);
924
+ window.removeEventListener('mousemove', self.mousemove);
898
925
  window.removeEventListener('resize', self.resize);
899
926
  if (self.observer && self.observer.disconnect) {
900
927
  self.observer.disconnect();
@@ -1487,6 +1514,10 @@ export default function (self, ctor) {
1487
1514
  self.intf.cut = self.cut;
1488
1515
  self.intf.paste = self.paste;
1489
1516
  self.intf.setStyleProperty = self.setStyleProperty;
1517
+ self.intf.hideColumns = self.hideColumns;
1518
+ self.intf.unhideColumns = self.unhideColumns;
1519
+ self.intf.hideRows = self.hideRows;
1520
+ self.intf.unhideRows = self.unhideRows;
1490
1521
  Object.defineProperty(self.intf, 'defaults', {
1491
1522
  get: function () {
1492
1523
  return {