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.
@@ -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...
@@ -406,6 +408,7 @@ export default function (self) {
406
408
  * @param {number} y The row index of the cell to set active.
407
409
  */
408
410
  self.setActiveCell = function (x, y) {
411
+ if (typeof x === 'undefined') return;
409
412
  if (x < 0) {
410
413
  x = 0;
411
414
  }
@@ -426,6 +429,8 @@ export default function (self) {
426
429
  */
427
430
  self.selectNone = function (dontDraw) {
428
431
  self.selections = [];
432
+ self.selectedRows = [];
433
+ self.selectedColumns = [];
429
434
  self.dispatchEvent('selectionchanged', {
430
435
  selectedData: self.getSelectedData(),
431
436
  selections: self.selections,
@@ -457,55 +462,47 @@ export default function (self) {
457
462
  self.draw();
458
463
  };
459
464
  /**
460
- * Returns true if indices of columns next to the selected columnIndex is selected on every row.
465
+ * Returns true if the selected columnIndex is selected on every row.
461
466
  * @memberof canvasDatagrid
462
- * @name isMultiColumnsSelected
467
+ * @name isColumnSelected
463
468
  * @method
464
469
  * @param {number} columnIndex The column index to check.
465
470
  */
466
- self.isMultiColumnsSelected = function (columnIndex) {
467
- var multiColIsSelected = true;
471
+ self.isColumnSelected = function (columnIndex) {
472
+ var colIsSelected = true;
468
473
  self.viewData.forEach(function (row, rowIndex) {
469
- var columnIndices = self.selections[rowIndex];
470
474
  if (
471
- !columnIndices ||
472
- columnIndices.length <= 1 ||
473
- columnIndices.indexOf(columnIndex) === -1
475
+ !self.selections[rowIndex] ||
476
+ self.selections[rowIndex].indexOf(columnIndex) === -1
474
477
  ) {
475
- multiColIsSelected = false;
476
- } else if (columnIndices.length > 1) {
477
- if (columnIndices[0] != columnIndex) multiColIsSelected = false;
478
- else {
479
- for (var i = 0; i < columnIndices.length - 1; i++) {
480
- if (columnIndices[i] + 1 != columnIndices[i + 1]) {
481
- multiColIsSelected = false;
482
- break;
483
- }
484
- }
485
- }
478
+ colIsSelected = false;
486
479
  }
487
480
  });
488
- return multiColIsSelected;
481
+ return colIsSelected;
489
482
  };
490
483
  /**
491
- * Returns true if the selected columnIndex is selected on every row.
484
+ * Returns true if the selected rowIndex is selected on every column.
492
485
  * @memberof canvasDatagrid
493
- * @name isColumnSelected
486
+ * @name isRowSelected
494
487
  * @method
495
- * @param {number} columnIndex The column index to check.
488
+ * @param {number} rowIndex The row index to check.
496
489
  */
497
- self.isColumnSelected = function (columnIndex) {
498
- var colIsSelected = true;
499
- self.viewData.forEach(function (row, rowIndex) {
490
+
491
+ self.isRowSelected = function (rowIndex) {
492
+ if (!self.selections[rowIndex]) return false;
493
+ var rowIsSelected = true;
494
+ var schema = self.getVisibleSchema();
495
+ schema.forEach(function (col, index) {
500
496
  if (
501
497
  !self.selections[rowIndex] ||
502
- self.selections[rowIndex].indexOf(columnIndex) === -1
498
+ self.selections[rowIndex].indexOf(index) === -1
503
499
  ) {
504
- colIsSelected = false;
500
+ rowIsSelected = false;
505
501
  }
506
502
  });
507
- return colIsSelected;
503
+ return rowIsSelected;
508
504
  };
505
+
509
506
  /**
510
507
  * Runs the defined method on each selected cell.
511
508
  * @memberof canvasDatagrid
@@ -547,6 +544,8 @@ export default function (self) {
547
544
  */
548
545
  self.selectColumn = function (columnIndex, ctrl, shift, supressEvent) {
549
546
  var s, e, x;
547
+ self.isMultiRowsSelected = false;
548
+ self.isMultiColumnsSelected = false;
550
549
  function addCol(i) {
551
550
  self.viewData.forEach(function (row, rowIndex) {
552
551
  self.selections[rowIndex] = self.selections[rowIndex] || [];
@@ -574,17 +573,23 @@ export default function (self) {
574
573
  e = Math.max(self.activeCell.columnIndex, columnIndex);
575
574
  for (x = s; e > x; x += 1) {
576
575
  addCol(x);
576
+ if (self.selectedColumns.indexOf(x) === -1)
577
+ self.selectedColumns.push(x);
577
578
  }
579
+ if (s != e) self.isMultiColumnsSelected = true;
578
580
  }
579
581
  if (!ctrl && !shift) {
580
582
  self.selections = [];
583
+ self.selectedColumns = [];
581
584
  self.activeCell.columnIndex = columnIndex;
582
585
  self.activeCell.rowIndex = self.scrollIndexTop;
583
586
  }
584
587
  if (ctrl && self.isColumnSelected(columnIndex)) {
585
588
  removeCol(columnIndex);
589
+ self.selectedColumns.splice(columnIndex, 1);
586
590
  } else {
587
591
  addCol(columnIndex);
592
+ self.selectedColumns.push(columnIndex);
588
593
  }
589
594
  if (supressEvent) {
590
595
  return;
@@ -628,6 +633,13 @@ export default function (self) {
628
633
  self.selections[ri].push(-1);
629
634
  s.forEach(function (col, index) {
630
635
  self.selections[ri].push(self.orders.columns.indexOf(col.index));
636
+ if (
637
+ col.index !== -1 &&
638
+ self.selectedColumns.indexOf(
639
+ self.orders.columns.indexOf(col.index),
640
+ ) === -1
641
+ )
642
+ self.selectedColumns.push(self.orders.columns.indexOf(col.index));
631
643
  });
632
644
  }
633
645
  if (self.dragAddToSelection === false || self.dragObject === undefined) {
@@ -651,9 +663,12 @@ export default function (self) {
651
663
  en = Math.max(self.activeCell.rowIndex, rowIndex);
652
664
  for (x = st; en >= x; x += 1) {
653
665
  addRow(x);
666
+ self.selectedRows.push(x);
654
667
  }
655
668
  } else {
656
669
  addRow(rowIndex);
670
+ self.selectedRows = [];
671
+ self.selectedRows.push(rowIndex);
657
672
  }
658
673
  }
659
674
  de();
@@ -762,6 +777,101 @@ export default function (self) {
762
777
  }
763
778
  }
764
779
  };
780
+ /**
781
+ * Hide column/columns
782
+ * @memberof canvasDatagrid
783
+ * @name hideColumns
784
+ * @method
785
+ * @param {number} beginColumnOrderIndex
786
+ * @param {number} [endColumnOrderIndex]
787
+ */
788
+ self.hideColumns = function (beginColumnOrderIndex, endColumnOrderIndex) {
789
+ const schema = self.getSchema();
790
+ const orders = self.orders.columns;
791
+ const hiddenColumns = [];
792
+ if (typeof endColumnOrderIndex !== 'number')
793
+ endColumnOrderIndex = beginColumnOrderIndex;
794
+ for (
795
+ let orderIndex = beginColumnOrderIndex;
796
+ orderIndex <= endColumnOrderIndex;
797
+ orderIndex++
798
+ ) {
799
+ const columnIndex = orders[orderIndex];
800
+ if (columnIndex >= 0 && !schema[columnIndex].hidden) {
801
+ hiddenColumns.push(columnIndex);
802
+ schema[columnIndex].hidden = true;
803
+
804
+ self.dispatchEvent('columnhide', {
805
+ columnIndex,
806
+ });
807
+ }
808
+ }
809
+
810
+ if (hiddenColumns.length > 0) {
811
+ self.setStorageData();
812
+ setTimeout(function () {
813
+ self.resize(true);
814
+ }, 10);
815
+ }
816
+
817
+ self.dispatchEvent('hidecolumns', {
818
+ hiddenColumns,
819
+ });
820
+ };
821
+ /**
822
+ * Unihde column/columns
823
+ * @memberof canvasDatagrid
824
+ * @name unhideColumns
825
+ * @method
826
+ * @param {number} beginColumnOrderIndex
827
+ * @param {number} [endColumnOrderIndex]
828
+ */
829
+ self.unhideColumns = function (beginColumnOrderIndex, endColumnOrderIndex) {
830
+ const orders = self.orders.columns;
831
+ const schema = self.getSchema();
832
+
833
+ for (let i = beginColumnOrderIndex; i <= endColumnOrderIndex; i++) {
834
+ const columnIndex = orders[i];
835
+ const s = schema[columnIndex];
836
+
837
+ if (s && s.hidden) {
838
+ s.hidden = false;
839
+
840
+ self.dispatchEvent('columnunhide', {
841
+ columnIndex,
842
+ });
843
+ }
844
+ }
845
+ self.refresh();
846
+ };
847
+ /**
848
+ * Hide rows
849
+ * @memberof canvasDatagrid
850
+ * @name hideRows
851
+ * @method
852
+ * @param {number} beginRowIndex
853
+ * @param {number} endRowIndex
854
+ */
855
+ self.hideRows = function (beginRowIndex, endRowIndex) {
856
+ if (
857
+ mergeHiddenRowRanges(self.hiddenRowRanges, [beginRowIndex, endRowIndex])
858
+ )
859
+ self.refresh();
860
+ };
861
+ /**
862
+ * Unhide rows
863
+ * @memberof canvasDatagrid
864
+ * @name unhideRows
865
+ * @method
866
+ * @param {number} beginRowIndex
867
+ * @param {number} endRowIndex
868
+ */
869
+ self.unhideRows = function (beginRowIndex, endRowIndex) {
870
+ self.hiddenRowRanges = self.hiddenRowRanges.filter(
871
+ (range) => range[0] !== beginRowIndex || range[1] !== endRowIndex,
872
+ );
873
+ self.refresh();
874
+ };
765
875
  /**
766
876
  * Resizes a column to fit the longest value in the column. Call without a value to resize all columns.
767
877
  * Warning, can be slow on very large record sets (1m records ~3-5 seconds on an i7).
@@ -890,6 +1000,7 @@ export default function (self) {
890
1000
  /**
891
1001
  * Add grouping
892
1002
  * @param {'columns'|'rows'} groupFor
1003
+ * @method
893
1004
  * @param {number} from
894
1005
  * @param {number} to
895
1006
  */
@@ -945,6 +1056,7 @@ export default function (self) {
945
1056
  /**
946
1057
  * Remove grouping
947
1058
  * @param {Array<Array<{from:number,to:number,collapsed:boolean}>>} allGroups
1059
+ * @method
948
1060
  * @param {number} from
949
1061
  * @param {number} to
950
1062
  */
@@ -1140,10 +1252,15 @@ export default function (self) {
1140
1252
  */
1141
1253
  self.moveSelection = function (offsetX, offsetY) {
1142
1254
  var sel = [];
1255
+ self.selectedRows = [];
1256
+ self.selectedColumns = [];
1143
1257
  self.selections.forEach(function (row, rowIndex) {
1144
1258
  sel[rowIndex + offsetY] = [];
1259
+ self.selectedRows.push(rowIndex + offsetY);
1145
1260
  row.forEach(function (colIndex) {
1146
1261
  sel[rowIndex + offsetY].push(colIndex + offsetX);
1262
+ if (self.selectedColumns.indexOf(colIndex + offsetX) === -1)
1263
+ self.selectedColumns.push(colIndex + offsetX);
1147
1264
  });
1148
1265
  });
1149
1266
  self.selections = sel;
@@ -1336,6 +1453,28 @@ export default function (self) {
1336
1453
  return c.columnIndex === x && c.rowIndex === y;
1337
1454
  })[0];
1338
1455
  };
1456
+ /**
1457
+ * Get an unhide indicator at grid pixel coordinate x and y.
1458
+ * @memberof canvasDatagrid
1459
+ * @name getUnhideIndicator
1460
+ * @method
1461
+ * @param {number} x Number of pixels from the left.
1462
+ * @param {number} y Number of pixels from the top.
1463
+ */
1464
+ self.getUnhideIndicator = function (x, y) {
1465
+ const indicators = self.visibleUnhideIndicators;
1466
+ if (indicators.length <= 0) return;
1467
+ for (let i = 0; i < indicators.length; i++) {
1468
+ const indicator = indicators[i];
1469
+ if (
1470
+ x >= indicator.x &&
1471
+ y >= indicator.y &&
1472
+ x <= indicator.x2 &&
1473
+ y <= indicator.y2
1474
+ )
1475
+ return indicator;
1476
+ }
1477
+ };
1339
1478
  /**
1340
1479
  * Get a column group at grid pixel coordinate x and y.
1341
1480
  * @memberof canvasDatagrid
@@ -1417,6 +1556,14 @@ export default function (self) {
1417
1556
  }
1418
1557
  x -= self.getRowGroupAreaWidth();
1419
1558
  y -= self.getColumnGroupAreaHeight();
1559
+
1560
+ if (self.dragStartObject !== undefined) {
1561
+ if (x <= 0) x = 1;
1562
+ if (x >= self.width) x = self.width - 1;
1563
+ if (y <= 0) y = 1;
1564
+ if (y >= self.height) y = self.height - 1;
1565
+ }
1566
+
1420
1567
  var border,
1421
1568
  tsz = useTouchScrollZones ? self.attributes.touchScrollZone : 0,
1422
1569
  moveMode = self.attributes.borderDragBehavior === 'move',
@@ -1463,13 +1610,15 @@ export default function (self) {
1463
1610
  entitiy.y + entitiy.height + self.style.cellBorderWidth > y
1464
1611
  ) {
1465
1612
  if (/frozen-row-marker/.test(cell.style)) {
1613
+ if (self.dragMode === 'frozen-column-marker') continue;
1466
1614
  cell.dragContext = cell.style;
1467
- cell.context = 'row-resize';
1615
+ cell.context = 'grab';
1468
1616
  return cell;
1469
1617
  }
1470
1618
  if (/frozen-column-marker/.test(cell.style)) {
1619
+ if (self.dragMode === 'frozen-row-marker') continue;
1471
1620
  cell.dragContext = cell.style;
1472
- cell.context = 'col-resize';
1621
+ cell.context = 'grab';
1473
1622
  return cell;
1474
1623
  }
1475
1624
  if (/selection-handle-/.test(cell.style)) {
@@ -1566,11 +1715,12 @@ export default function (self) {
1566
1715
  }
1567
1716
  if (cell.style === 'columnHeaderCell') {
1568
1717
  if (
1569
- cell.x +
1570
- cell.width -
1571
- self.attributes.columnGrabZoneSize -
1572
- self.style.cellBorderWidth >
1573
- x ||
1718
+ (!self.isColumnSelected(cell.columnIndex) &&
1719
+ cell.x +
1720
+ cell.width -
1721
+ self.attributes.columnGrabZoneSize -
1722
+ self.style.cellBorderWidth >
1723
+ x) ||
1574
1724
  !self.attributes.allowRowReordering
1575
1725
  ) {
1576
1726
  cell.dragContext = 'cell';
@@ -1583,9 +1733,10 @@ export default function (self) {
1583
1733
  }
1584
1734
  if (cell.style === 'rowHeaderCell') {
1585
1735
  if (
1586
- self.attributes.rowGrabZoneSize +
1587
- (cell.y - self.style.cellBorderWidth) <
1588
- y ||
1736
+ (!self.isRowSelected(cell.rowIndex) &&
1737
+ self.attributes.rowGrabZoneSize +
1738
+ (cell.y - self.style.cellBorderWidth) <
1739
+ y) ||
1589
1740
  !self.attributes.allowRowReordering
1590
1741
  ) {
1591
1742
  cell.dragContext = 'cell';
@@ -1709,6 +1860,8 @@ export default function (self) {
1709
1860
  s = self.getSchema();
1710
1861
  if (!ctrl) {
1711
1862
  self.selections = [];
1863
+ self.selectedRows = [];
1864
+ self.selectedColumns = [];
1712
1865
  }
1713
1866
  if (
1714
1867
  self.selectionBounds.top < -1 ||
@@ -1724,6 +1877,7 @@ export default function (self) {
1724
1877
  x += 1
1725
1878
  ) {
1726
1879
  self.selections[x] = [];
1880
+ self.selectedRows.push(x);
1727
1881
  for (
1728
1882
  y = self.selectionBounds.left;
1729
1883
  y <= self.selectionBounds.right;
@@ -1732,6 +1886,9 @@ export default function (self) {
1732
1886
  if (self.selections[x].indexOf(y) === -1) {
1733
1887
  self.selections[x].push(y);
1734
1888
  }
1889
+ if (y !== -1 && self.selectedColumns.indexOf(y) === -1) {
1890
+ self.selectedColumns.push(y);
1891
+ }
1735
1892
  }
1736
1893
  }
1737
1894
  ev = {
@@ -1783,8 +1940,9 @@ export default function (self) {
1783
1940
  self.ctx.font = self.style.columnHeaderCellFont;
1784
1941
  var t =
1785
1942
  self.ctx.measureText(col.title || col.name).width +
1786
- self.style.headerCellPaddingRight +
1787
- self.style.headerCellPaddingLeft;
1943
+ self.style.columnHeaderCellPaddingRight +
1944
+ self.style.columnHeaderCellPaddingLeft +
1945
+ self.style.cellAutoResizePadding;
1788
1946
  m = t > m ? t : m;
1789
1947
  formatter = self.formatters[col.type];
1790
1948
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canvas-datagrid",
3
- "version": "0.4.1",
3
+ "version": "0.4.4",
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",