canvas-datagrid 0.3.24 → 0.4.2

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/dist/types.d.ts CHANGED
@@ -74,6 +74,8 @@
74
74
  * @param [args.blanksText = (Blanks)] - The text that appears on the context menu for filtering blank values (i.e. `undefined`, `null`, `''`).
75
75
  * @param [args.ellipsisText = ...] - The text used as ellipsis text on truncated values.
76
76
  * @param [args.allowSorting = true] - Allow user to sort rows by clicking on column headers.
77
+ * @param [args.allowGroupingColumns = true] - Allow user to group columns by clicking on column headers.
78
+ * @param [args.allowGroupingRows = true] - Allow user to group rows by clicking on rows headers.
77
79
  * @param [args.showFilter = true] - When true, filter will be an option in the context menu.
78
80
  * @param [args.pageUpDownOverlap = 1] - Amount of rows to overlap when pageup/pagedown is used.
79
81
  * @param [args.persistantSelectionMode = false] - When true, selections will behave as if the command/control key is held down at all times. Conflicts with singleSelectionMode.
@@ -101,6 +103,18 @@
101
103
  * @param [args.clearSettingsOptionText = 'Clear saved settings'] - Text that appears on the clear settings option.
102
104
  * @param [args.showOrderByOptionTextDesc = 'Order by %s ascending'] - Text that appears on the order by descending option.
103
105
  * @param [args.showOrderByOptionTextAsc = 'Order by %s desc'] - Text that appears on the order by ascending option.
106
+ * @param [args.showGroupColumns = 'Group columns %s'] - Text that appears on the group columns option.
107
+ * @param [args.showGroupRows = 'Group row %s'] - Text that appears on the group rows option.
108
+ * @param [args.showRemoveGroupColumns = 'Remove group %s'] - Text that appears on the remove columns group option.
109
+ * @param [args.showRemoveGroupRows = 'Remove group %s'] - Text that appears on the remove rows group option.
110
+ * @param [args.showRemoveAllGroupColumns = 'Remove all column groups'] - Text that appears on the remove all column groups option.
111
+ * @param [args.showRemoveAllGroupRows = 'Remove all row groups'] - Text that appears on the remove all row groups option.
112
+ * @param [args.showExpandAllGroupColumns = 'Expand all column groups'] - Text that appears on the expand all column groups option.
113
+ * @param [args.showExpandAllGroupRows = 'Expand all row groups'] - Text that appears on the expand all row groups option.
114
+ * @param [args.showCollapseAllGroupColumns = 'Collapse all column groups'] - Text that appears on the collapsed all column groups option.
115
+ * @param [args.showCollapseAllGroupRows = 'Collapse all row groups'] - Text that appears on the collapsed all row groups option.
116
+ * @param [args.columnGroupIndicatorPosition = 'right'] - The position of the column group inidcator(icon), available values: 'left' and 'right'.
117
+ * @param [args.rowGroupIndicatorPosition = 'bottom'] - Ths position of the row group indicator(icon), available values: 'top' and 'bottom'.
104
118
  * @param [args.showOrderByOption = true] - Show an option on the context menu sort rows.
105
119
  * @param [args.showPaste = false] - Show the paste option in the context menu when applicable.
106
120
  * @param [args.schema = []] - Sets the schema. See {@link canvasDatagrid.schema}.
@@ -163,6 +177,8 @@ declare class canvasDatagrid {
163
177
  blanksText?: string;
164
178
  ellipsisText?: string;
165
179
  allowSorting?: boolean;
180
+ allowGroupingColumns?: boolean;
181
+ allowGroupingRows?: boolean;
166
182
  showFilter?: boolean;
167
183
  pageUpDownOverlap?: number;
168
184
  persistantSelectionMode?: boolean;
@@ -190,6 +206,18 @@ declare class canvasDatagrid {
190
206
  clearSettingsOptionText?: string;
191
207
  showOrderByOptionTextDesc?: string;
192
208
  showOrderByOptionTextAsc?: string;
209
+ showGroupColumns?: string;
210
+ showGroupRows?: string;
211
+ showRemoveGroupColumns?: string;
212
+ showRemoveGroupRows?: string;
213
+ showRemoveAllGroupColumns?: string;
214
+ showRemoveAllGroupRows?: string;
215
+ showExpandAllGroupColumns?: string;
216
+ showExpandAllGroupRows?: string;
217
+ showCollapseAllGroupColumns?: string;
218
+ showCollapseAllGroupRows?: string;
219
+ columnGroupIndicatorPosition?: string;
220
+ rowGroupIndicatorPosition?: string;
193
221
  showOrderByOption?: boolean;
194
222
  showPaste?: boolean;
195
223
  schema?: any[];
@@ -401,6 +429,16 @@ declare class canvasDatagrid {
401
429
  * @param imgSrc - icon path to add into button.
402
430
  */
403
431
  static addButton(columnIndex: number, rowIndex: number, offset: any, items: any, imgSrc: string): void;
432
+ /**
433
+ * Expand/Collapse CellTree.
434
+ * @param treeData - The array of cellTree to expand or collapse.
435
+ */
436
+ static toggleCellCollapseTree(treeData: any[]): void;
437
+ /**
438
+ * Expand/Collapse CellTree.
439
+ * @param treeData - The array of cellTree to expand or collapse.
440
+ */
441
+ static expandCollapseCellTree(treeData: any[]): void;
404
442
  /**
405
443
  * Scrolls the cell at cell x, row y into view if it is not already.
406
444
  * @param x - The column index of the cell to scroll into view.
@@ -499,6 +537,42 @@ declare class canvasDatagrid {
499
537
  * @param [dontSetStorageData] - Don't store this setting for future use.
500
538
  */
501
539
  static order(columnName: number, direction: string, sortFunction?: (...params: any[]) => any, dontSetStorageData?: boolean): void;
540
+ /**
541
+ * Grouping columns
542
+ * @param firstColumnName - Name of the first column to be grouped.
543
+ * @param lastColumnName - Name of the last column to be grouped.
544
+ */
545
+ static groupColumns(firstColumnName: number | string, lastColumnName: number | string): void;
546
+ /**
547
+ * Grouping columns
548
+ * @param rowIndexFrom - The row index which is the beginning of the group
549
+ * @param rowIndexTo - The row index which is the end of the group
550
+ */
551
+ static groupRows(rowIndexFrom: number, rowIndexTo: number): void;
552
+ /**
553
+ * Remove grouping columns
554
+ * @param firstColumnName - Name of the first column to be grouped.
555
+ * @param lastColumnName - Name of the last column to be grouped.
556
+ */
557
+ static removeGroupColumns(firstColumnName: number | string, lastColumnName: number | string): void;
558
+ /**
559
+ * Remove grouping columns
560
+ * @param rowIndexFrom - The row index which is the beginning of the group
561
+ * @param rowIndexTo - The row index which is the end of the group
562
+ */
563
+ static removeGroupRows(rowIndexFrom: number, rowIndexTo: number): void;
564
+ /**
565
+ * Toggle(expand/collapsed) grouping columns
566
+ * @param firstColumnName - Name of the first column to be grouped.
567
+ * @param lastColumnName - Name of the last column to be grouped.
568
+ */
569
+ static toggleGroupColumns(firstColumnName: number | string, lastColumnName: number | string): void;
570
+ /**
571
+ * Toggle(expand/collapsed) grouping rows
572
+ * @param rowIndexFrom - The row index which is the beginning of the group
573
+ * @param rowIndexTo - The row index which is the end of the group
574
+ */
575
+ static toggleGroupRows(rowIndexFrom: number, rowIndexTo: number): void;
502
576
  /**
503
577
  * Moves the current selection relative to the its current position. Note: this method does not move the selected data, just the selection itself.
504
578
  * @param offsetX - The number of columns to offset the selection.
@@ -517,6 +591,16 @@ declare class canvasDatagrid {
517
591
  * @param y - The row index to start inserting the selection at.
518
592
  */
519
593
  static moveTo(sel: any[], x: number, y: number): void;
594
+ /**
595
+ * Get the column group info given column belongs to
596
+ * @param columnIndex - Column index.
597
+ */
598
+ static getGroupsColumnBelongsTo(columnIndex: number): { from: number; to: number; collapsed: boolean; }[];
599
+ /**
600
+ * Get the row group info given row belongs to
601
+ * @param rowIndex - Row index.
602
+ */
603
+ static getGroupsRowBelongsTo(rowIndex: number): { from: number; to: number; collapsed: boolean; }[];
520
604
  /**
521
605
  * Checks if a given column is visible.
522
606
  * @param columnIndex - Column index.
@@ -536,6 +620,18 @@ declare class canvasDatagrid {
536
620
  * @returns cell at the selected location.
537
621
  */
538
622
  static getVisibleCellByIndex(x: number, y: number): cell;
623
+ /**
624
+ * Get a column group at grid pixel coordinate x and y.
625
+ * @param x - Number of pixels from the left.
626
+ * @param y - Number of pixels from the top.
627
+ */
628
+ static getColumnGroupAt(x: number, y: number): void;
629
+ /**
630
+ * Get a row group at grid pixel coordinate x and y.
631
+ * @param x - Number of pixels from the left.
632
+ * @param y - Number of pixels from the top.
633
+ */
634
+ static getRowGroupAt(x: number, y: number): void;
539
635
  /**
540
636
  * 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.
541
637
  * @param x - Number of pixels from the left.
@@ -1108,6 +1204,7 @@ declare namespace canvasDatagrid {
1108
1204
  * @property [childContextMenuMarginTop = 0] - Style of childContextMenuMarginTop.
1109
1205
  * @property [childContextMenuArrowHTML = ►] - Style of childContextMenuArrowHTML.
1110
1206
  * @property [childContextMenuArrowColor = rgba(43, 48, 43, 1)] - Style of childContextMenuArrowColor.
1207
+ * @property [columnGroupRowHeight = 25] - Style of columnGroupRowHeight.
1111
1208
  * @property [contextMenuChildArrowFontSize = 12px] - Style of contextMenuChildArrowFontSize.
1112
1209
  * @property [cellWidth = 250] - Style of cellWidth.
1113
1210
  * @property [contextMenuBackground = rgba(240, 240, 240, 1)] - Style of contextMenuBackground.
@@ -1162,6 +1259,8 @@ declare namespace canvasDatagrid {
1162
1259
  * @property [gridBackgroundColor = rgba(240, 240, 240, 1)] - Style of gridBackgroundColor.
1163
1260
  * @property [gridBorderColor = rgba(202, 202, 202, 1)] - Style of gridBorderColor.
1164
1261
  * @property [gridBorderWidth = 1] - Style of gridBorderWidth.
1262
+ * @property [groupIndicatorColor = rgba(155, 155, 155, 1)'] - Foreground color of the group indicator(icon).
1263
+ * @property [groupIndicatorBackgroundColor = rgba(255, 255, 255, 1)'] - Background color of the group indicator(icon).
1165
1264
  * @property [columnHeaderCellCapBackgroundColor = rgba(240, 240, 240, 1)] - Style of columnHeaderCellBackgroundColor.
1166
1265
  * @property [columnHeaderCellCapBorderColor = rgba(172, 172, 172, 1)] - Style of columnHeaderCellBackgroundColor.
1167
1266
  * @property [columnHeaderCellCapBorderWidth = 1] - Style of columnHeaderCellBackgroundColor.
@@ -1196,6 +1295,7 @@ declare namespace canvasDatagrid {
1196
1295
  * @property [reorderMarkerBorderWidth = 1.25] - Style of reorderMarkerBorderWidth.
1197
1296
  * @property [reorderMarkerIndexBorderColor = rgba(66, 133, 244, 1)] - Style of reorderMarkerIndexBorderColor.
1198
1297
  * @property [reorderMarkerIndexBorderWidth = 2.75] - Style of reorderMarkerIndexBorderWidth.
1298
+ * @property [rowGroupColumnWidth = 25] - Style of rowGroupColumnWidth.
1199
1299
  * @property [rowHeaderCellBackgroundColor = rgba(240, 240, 240, 1)] - Style of rowHeaderCellBackgroundColor.
1200
1300
  * @property [rowHeaderCellBorderColor = rgba(152, 152, 152, 1)] - Style of rowHeaderCellBorderColor.
1201
1301
  * @property [rowHeaderCellBorderWidth = 0.25] - Style of rowHeaderCellBorderWidth.
@@ -1466,6 +1566,10 @@ declare namespace canvasDatagrid {
1466
1566
  * Style of childContextMenuArrowColor.
1467
1567
  */
1468
1568
  childContextMenuArrowColor?: string;
1569
+ /**
1570
+ * Style of columnGroupRowHeight.
1571
+ */
1572
+ columnGroupRowHeight?: number;
1469
1573
  /**
1470
1574
  * Style of contextMenuChildArrowFontSize.
1471
1575
  */
@@ -1682,6 +1786,14 @@ declare namespace canvasDatagrid {
1682
1786
  * Style of gridBorderWidth.
1683
1787
  */
1684
1788
  gridBorderWidth?: number;
1789
+ /**
1790
+ * Foreground color of the group indicator(icon).
1791
+ */
1792
+ groupIndicatorColor?: string;
1793
+ /**
1794
+ * Background color of the group indicator(icon).
1795
+ */
1796
+ groupIndicatorBackgroundColor?: string;
1685
1797
  /**
1686
1798
  * Style of columnHeaderCellBackgroundColor.
1687
1799
  */
@@ -1818,6 +1930,10 @@ declare namespace canvasDatagrid {
1818
1930
  * Style of reorderMarkerIndexBorderWidth.
1819
1931
  */
1820
1932
  reorderMarkerIndexBorderWidth?: number;
1933
+ /**
1934
+ * Style of rowGroupColumnWidth.
1935
+ */
1936
+ rowGroupColumnWidth?: number;
1821
1937
  /**
1822
1938
  * Style of rowHeaderCellBackgroundColor.
1823
1939
  */
@@ -609,13 +609,18 @@ export default function (self) {
609
609
  },
610
610
  });
611
611
  if (e.cell && e.cell.header && e.cell.columnIndex > -1) {
612
+ // This variable represents the order index because of the following codes from `draw.js`:
613
+ // columnIndex: columnOrderIndex,
614
+ const columnOrderIndex = e.cell.columnIndex;
615
+ const columnIndex = self.orders.columns[columnOrderIndex];
616
+
612
617
  e.items.push({
613
618
  title: self.attributes.hideColumnText.replace(
614
619
  /%s/gi,
615
620
  e.cell.header.title || e.cell.header.name,
616
621
  ),
617
622
  click: function (ev) {
618
- self.getSchema()[e.cell.columnIndex].hidden = true;
623
+ self.getSchema()[columnIndex].hidden = true;
619
624
  ev.preventDefault();
620
625
  self.stopPropagation(ev);
621
626
  self.disposeContextMenu();
@@ -684,6 +689,241 @@ export default function (self) {
684
689
  },
685
690
  });
686
691
  }
692
+ //#region group/ungroup columns
693
+ const groupAreaHeight = self.getColumnGroupAreaHeight();
694
+ const groupAreaWidth = self.getRowGroupAreaWidth();
695
+ const setCollapseStateForAllGroups = (allGroups, collapsed) => {
696
+ if (allGroups.length === 0) return;
697
+ for (let i = 0; i < allGroups.length; i++) {
698
+ const groups = allGroups[i];
699
+ for (let j = 0; j < groups.length; j++) {
700
+ const group = groups[j];
701
+ group.collapsed = collapsed;
702
+ }
703
+ }
704
+ self.refresh();
705
+ };
706
+ if (e.pos && e.pos.y < groupAreaHeight) {
707
+ e.items.push({
708
+ title: self.attributes.showRemoveAllGroupColumns,
709
+ click: function (ev) {
710
+ ev.preventDefault();
711
+ self.groupedColumns = [];
712
+ self.refresh();
713
+ },
714
+ });
715
+ e.items.push({
716
+ title: self.attributes.showExpandAllGroupColumns,
717
+ click: function (ev) {
718
+ ev.preventDefault();
719
+ setCollapseStateForAllGroups(self.groupedColumns, false);
720
+ },
721
+ });
722
+ e.items.push({
723
+ title: self.attributes.showCollapseAllGroupColumns,
724
+ click: function (ev) {
725
+ ev.preventDefault();
726
+ setCollapseStateForAllGroups(self.groupedColumns, true);
727
+ },
728
+ });
729
+ }
730
+ if (e.pos && e.pos.x < groupAreaWidth) {
731
+ e.items.push({
732
+ title: self.attributes.showRemoveAllGroupRows,
733
+ click: function (ev) {
734
+ ev.preventDefault();
735
+ self.groupedRows = [];
736
+ self.refresh();
737
+ },
738
+ });
739
+ e.items.push({
740
+ title: self.attributes.showExpandAllGroupRows,
741
+ click: function (ev) {
742
+ ev.preventDefault();
743
+ setCollapseStateForAllGroups(self.groupedRows, false);
744
+ },
745
+ });
746
+ e.items.push({
747
+ title: self.attributes.showCollapseAllGroupRows,
748
+ click: function (ev) {
749
+ ev.preventDefault();
750
+ setCollapseStateForAllGroups(self.groupedRows, true);
751
+ },
752
+ });
753
+ }
754
+
755
+ const canGroupByColumns =
756
+ self.attributes.allowGroupingColumns &&
757
+ e.cell.isColumnHeader &&
758
+ e.cell.header &&
759
+ e.cell.header.index > 0;
760
+ const canUngroupColumns =
761
+ self.attributes.allowGroupingColumns && e.cell.isColumnHeader;
762
+ const canGroupByRows =
763
+ self.attributes.allowGroupingRows && e.cell.isRowHeader && e.cell.header;
764
+ const canUngroupRows =
765
+ self.attributes.allowGroupingRows && e.cell.isRowHeader;
766
+
767
+ /**
768
+ * The value for storing the return value from `self.getSchema()`
769
+ * @type {any[]}
770
+ */
771
+ let schema;
772
+ /**
773
+ * A map between columnIndex and column data
774
+ * @type {Map<string,any>}
775
+ */
776
+ let columns;
777
+ const getColumnsMap = () => {
778
+ if (!columns) {
779
+ if (!schema) schema = self.getSchema();
780
+ columns = new Map(schema.map((_col) => [_col.columnIndex, _col]));
781
+ }
782
+ return columns;
783
+ };
784
+
785
+ if (canGroupByColumns) {
786
+ /** @type {number[]} */
787
+ const groupIndexes = [];
788
+ /** @type {number} */
789
+ const headerIndex = e.cell.header.index;
790
+ let col = headerIndex;
791
+ for (; col >= 0; col--) {
792
+ if (!self.isColumnSelected(col)) break;
793
+ groupIndexes[0] = col;
794
+ }
795
+ for (col = headerIndex; ; col++) {
796
+ if (!self.isColumnSelected(col)) break;
797
+ groupIndexes[1] = col;
798
+ }
799
+ if (
800
+ col !== headerIndex &&
801
+ groupIndexes.length === 2 &&
802
+ groupIndexes[1] > groupIndexes[0] &&
803
+ self.isNewGroupRangeValid(
804
+ self.groupedColumns,
805
+ groupIndexes[0],
806
+ groupIndexes[1],
807
+ )
808
+ ) {
809
+ const columns = getColumnsMap();
810
+ const groupTitles = [];
811
+ const groupNames = [];
812
+ for (let i = 0; i < groupIndexes.length; i++) {
813
+ const columnIndex = groupIndexes[i];
814
+ const column = columns.get(columnIndex);
815
+ if (column) {
816
+ groupNames.push(column.name);
817
+ groupTitles.push(column.title || column.name || column.index);
818
+ }
819
+ }
820
+ if (groupNames[0] && groupNames[1]) {
821
+ // show group options
822
+ e.items.push({
823
+ title: self.attributes.showGroupColumns.replace(
824
+ '%s',
825
+ groupTitles[0] + '-' + groupTitles[1],
826
+ ),
827
+ click: function (ev) {
828
+ ev.preventDefault();
829
+ self.groupColumns(groupNames[0], groupNames[1]);
830
+ self.controlInput.focus();
831
+ },
832
+ });
833
+ }
834
+ }
835
+ }
836
+ if (canUngroupColumns) {
837
+ const columnIndex = e.cell.columnIndex;
838
+ const groups = self.getGroupsColumnBelongsTo(columnIndex);
839
+ const columns = getColumnsMap();
840
+ for (let i = 0; i < groups.length; i++) {
841
+ const { from, to } = groups[i];
842
+ const cell0 = columns.get(from);
843
+ const cell1 = columns.get(to);
844
+ if (cell0 && cell1) {
845
+ const formatArgs =
846
+ (cell0.title || cell0.name || cell0.index) +
847
+ '-' +
848
+ (cell1.title || cell1.name || cell1.index);
849
+ e.items.push({
850
+ title: self.attributes.showRemoveGroupColumns.replace(
851
+ '%s',
852
+ formatArgs,
853
+ ),
854
+ click: function (ev) {
855
+ ev.preventDefault();
856
+ self.removeGroupColumns(cell0.name, cell1.name);
857
+ self.controlInput.focus();
858
+ },
859
+ });
860
+ } else {
861
+ console.warn(`Cannot find column ${from} or column ${to}`);
862
+ }
863
+ }
864
+ }
865
+ if (canGroupByRows) {
866
+ let range = [];
867
+ let prev = -2;
868
+ let ok = true;
869
+ self.selections.forEach(function (row, index) {
870
+ if (!ok) return;
871
+ if (prev < -1) {
872
+ prev = index;
873
+ range[0] = index;
874
+ return;
875
+ }
876
+ if (index !== prev + 1 || !row || row.length === 0) {
877
+ ok = false;
878
+ return;
879
+ }
880
+ prev = index;
881
+ range[1] = index;
882
+ });
883
+ const rangeTitle = range
884
+ .map((rowIndex) => {
885
+ const index = self.getBoundRowIndexFromViewRowIndex(rowIndex);
886
+ if (typeof index === 'number') return index + 1;
887
+ return rowIndex + 1;
888
+ })
889
+ .join('-');
890
+ if (
891
+ ok &&
892
+ range.length === 2 &&
893
+ self.isNewGroupRangeValid(self.groupedRows, range[0], range[1])
894
+ ) {
895
+ e.items.push({
896
+ title: self.attributes.showGroupRows.replace('%s', rangeTitle),
897
+ click: function (ev) {
898
+ ev.preventDefault();
899
+ self.groupRows(range[0], range[1]);
900
+ },
901
+ });
902
+ }
903
+ }
904
+ if (canUngroupRows) {
905
+ const rowIndex = e.cell.rowIndex;
906
+ const groups = self.getGroupsRowBelongsTo(rowIndex);
907
+ for (let i = 0; i < groups.length; i++) {
908
+ const { from, to } = groups[i];
909
+ const rangeTitle = [from, to]
910
+ .map((rowIndex) => {
911
+ const index = self.getBoundRowIndexFromViewRowIndex(rowIndex);
912
+ if (typeof index === 'number') return index + 1;
913
+ return rowIndex + 1;
914
+ })
915
+ .join('-');
916
+ e.items.push({
917
+ title: self.attributes.showRemoveGroupRows.replace('%s', rangeTitle),
918
+ click: function (ev) {
919
+ ev.preventDefault();
920
+ self.removeGroupRows(from, to);
921
+ self.controlInput.focus();
922
+ },
923
+ });
924
+ }
925
+ }
926
+ //#endregion group/ungroup columns
687
927
  }
688
928
  self.disposeAutocomplete = function () {
689
929
  if (autoCompleteContext) {
@@ -709,6 +949,53 @@ export default function (self) {
709
949
  if (!self.hasFocus && e.target !== self.canvas) {
710
950
  return;
711
951
  }
952
+ // don't create context menu for parents if current position is located in child grid
953
+ const children = Object.keys(self.childGrids);
954
+ for (let i = 0; i < children.length; i++) {
955
+ const childGrid = self.childGrids[children[i]];
956
+ const parentNode = childGrid && childGrid.parentNode;
957
+ if (!parentNode) continue;
958
+ const { offsetLeft, offsetWidth, offsetTop, offsetHeight } = parentNode;
959
+ if ((e.x >= offsetLeft && e.x <= offsetLeft + offsetWidth) === false)
960
+ continue;
961
+ if ((e.y >= offsetTop && e.y <= offsetTop + offsetHeight) === false)
962
+ continue;
963
+ return; // in child grid
964
+ }
965
+ // don't create context menu for child if current position is located in parent grid
966
+ if (self.isChildGrid && self.parentNode) {
967
+ //#region check is current child grid closed
968
+ const childGridsOfParent = self.parentGrid && self.parentGrid.childGrids;
969
+ if (!childGridsOfParent || !Array.isArray(childGridsOfParent)) return;
970
+ const matchedMe = childGridsOfParent.find((grid) => {
971
+ const nodeA = grid.parentNode;
972
+ const nodeB = self.parentNode;
973
+ return (
974
+ nodeA.offsetTop == nodeB.offsetTop &&
975
+ nodeA.offsetLeft === nodeB.offsetLeft
976
+ );
977
+ });
978
+ if (!matchedMe) return;
979
+ //#endregion
980
+
981
+ let x0 = self.parentNode.offsetLeft;
982
+ let x1 = self.parentNode.offsetLeft + self.parentNode.offsetWidth;
983
+ let y0 = self.parentNode.offsetTop;
984
+ let y1 = self.parentNode.offsetTop + self.parentNode.offsetHeight;
985
+ let node = self.parentNode.parentNode;
986
+ while (node) {
987
+ const { offsetLeft, offsetWidth, offsetTop, offsetHeight } = node;
988
+ if (offsetLeft > x0) x0 = offsetLeft;
989
+ if (offsetTop > y0) y0 = offsetTop;
990
+ const newX1 = offsetLeft + offsetWidth;
991
+ const newY1 = offsetTop + offsetHeight;
992
+ if (newX1 < x1) x1 = newX1;
993
+ if (newY1 < y1) y1 = newY1;
994
+ if (node.nodeType !== 'canvas-datagrid-tree') break;
995
+ node = node.parentNode;
996
+ }
997
+ if ((e.x >= x0 && e.x <= x1 && e.y >= y0 && e.y <= y1) === false) return;
998
+ }
712
999
  function createDisposeEvent() {
713
1000
  requestAnimationFrame(function () {
714
1001
  document.addEventListener('click', self.disposeContextMenu);
@@ -721,6 +1008,7 @@ export default function (self) {
721
1008
  ev = {
722
1009
  NativeEvent: e,
723
1010
  cell: self.getCellAt(pos.x, pos.y),
1011
+ pos,
724
1012
  items: items,
725
1013
  };
726
1014
  if (!ev.cell.isGrid) {
package/lib/defaults.js CHANGED
@@ -16,6 +16,8 @@ export default function (self) {
16
16
  ['allowRowResize', true],
17
17
  ['allowRowResizeFromCell', false],
18
18
  ['allowSorting', true],
19
+ ['allowGroupingRows', true],
20
+ ['allowGroupingColumns', true],
19
21
  ['animationDurationShowContextMenu', 50],
20
22
  ['animationDurationHideContextMenu', 50],
21
23
  ['autoGenerateSchema', false],
@@ -55,6 +57,7 @@ export default function (self) {
55
57
  ['reorderDeadZone', 3],
56
58
  ['resizeScrollZone', 20],
57
59
  ['rowGrabZoneSize', 5],
60
+ ['columnGrabZoneSize', 30],
58
61
  ['saveAppearance', true],
59
62
  ['scrollAnimationPPSThreshold', 0.75],
60
63
  ['scrollPointerLock', false],
@@ -74,6 +77,20 @@ export default function (self) {
74
77
  ['showOrderByOption', true],
75
78
  ['showOrderByOptionTextAsc', 'Order by %s ascending'],
76
79
  ['showOrderByOptionTextDesc', 'Order by %s descending'],
80
+ //#region grouping
81
+ ['showGroupColumns', 'Group columns %s'],
82
+ ['showGroupRows', 'Group rows %s'],
83
+ ['showRemoveGroupColumns', 'Remove group %s'],
84
+ ['showRemoveGroupRows', 'Remove group %s'],
85
+ ['showRemoveAllGroupColumns', 'Remove all column groups'],
86
+ ['showRemoveAllGroupRows', 'Remove all row groups'],
87
+ ['showExpandAllGroupColumns', 'Expand all column groups'],
88
+ ['showExpandAllGroupRows', 'Expand all row groups'],
89
+ ['showCollapseAllGroupColumns', 'Collapse all column groups'],
90
+ ['showCollapseAllGroupRows', 'Collapse all row groups'],
91
+ ['columnGroupIndicatorPosition', 'right'],
92
+ ['rowGroupIndicatorPosition', 'bottom'],
93
+ //#endregion grouping
77
94
  ['showPaste', false],
78
95
  ['showPerformance', false],
79
96
  ['showRowHeaders', true],
@@ -95,6 +112,11 @@ export default function (self) {
95
112
  ['maxPixelRatio', 2],
96
113
  ['tree', false],
97
114
  ['treeHorizontalScroll', false],
115
+ ['rowTree', []],
116
+ ['rowTreeColIndex', 0],
117
+ ['columnTree', []],
118
+ ['columnTreeRowStartIndex', 0],
119
+ ['columnTreeRowEndIndex', 0],
98
120
  ],
99
121
  styles: [
100
122
  ['activeCellBackgroundColor', 'rgba(255, 255, 255, 1)'],
@@ -149,6 +171,15 @@ export default function (self) {
149
171
  ['cellPaddingTop', 5],
150
172
  ['cellSelectedBackgroundColor', 'rgba(236, 243, 255, 1)'],
151
173
  ['cellSelectedColor', 'rgba(0, 0, 0, 1)'],
174
+ ['cellTreeIconBorderColor', 'rgba(162, 174, 207, 1)'],
175
+ ['cellTreeIconFillColor', 'rgba(240, 240, 240, 1)'],
176
+ ['cellTreeIconHoverFillColor', 'rgba(198, 217, 233, 1)'],
177
+ ['cellTreeIconLineColor', 'rgba(43, 53, 81, 1)'],
178
+ ['cellTreeIconLineWidth', 1.5],
179
+ ['cellTreeIconMarginLeft', 0],
180
+ ['cellTreeIconMarginRight', 5],
181
+ ['cellTreeIconMarginTop', 6],
182
+ ['cellTreeIconWidth', 13],
152
183
  ['cellVerticalAlignment', 'center'],
153
184
  ['cellWidth', 250],
154
185
  ['cellWidthWithChildGrid', 250],
@@ -159,6 +190,7 @@ export default function (self) {
159
190
  ['childContextMenuArrowHTML', '&#x25BA;'],
160
191
  ['childContextMenuMarginLeft', -11],
161
192
  ['childContextMenuMarginTop', -6],
193
+ ['columnGroupRowHeight', 25],
162
194
  ['columnHeaderCellBackgroundColor', 'rgba(240, 240, 240, 1)'],
163
195
  ['columnHeaderCellBorderColor', 'rgba(172, 172, 172, 1)'],
164
196
  ['columnHeaderCellBorderWidth', 1],
@@ -267,10 +299,13 @@ export default function (self) {
267
299
  ['frozenMarkerBorderColor', 'rgba(168, 168, 168, 1)'],
268
300
  ['frozenMarkerBorderWidth', 1],
269
301
  ['frozenMarkerWidth', 2],
302
+ ['groupingAreaBackgroundColor', 'rgba(240, 240, 240, 1)'],
270
303
  ['gridBackgroundColor', 'rgba(240, 240, 240, 1)'],
271
304
  ['gridBorderCollapse', 'collapse'],
272
305
  ['gridBorderColor', 'rgba(202, 202, 202, 1)'],
273
306
  ['gridBorderWidth', 1],
307
+ ['groupIndicatorColor', 'rgba(155, 155, 155, 1)'],
308
+ ['groupIndicatorBackgroundColor', 'rgba(255, 255, 255, 1)'],
274
309
  ['height', 'auto'],
275
310
  ['maxHeight', 'inherit'],
276
311
  ['maxWidth', 'inherit'],
@@ -293,6 +328,7 @@ export default function (self) {
293
328
  ['reorderMarkerBorderWidth', 1.25],
294
329
  ['reorderMarkerIndexBorderColor', 'rgba(66, 133, 244, 1)'],
295
330
  ['reorderMarkerIndexBorderWidth', 2.75],
331
+ ['rowGroupColumnWidth', 25],
296
332
  ['rowHeaderCellBackgroundColor', 'rgba(240, 240, 240, 1)'],
297
333
  ['rowHeaderCellBorderColor', 'rgba(200, 200, 200, 1)'],
298
334
  ['rowHeaderCellBorderWidth', 1],
package/lib/docs.js CHANGED
@@ -37,6 +37,8 @@
37
37
  * @param {string} [args.blanksText=(Blanks)] - The text that appears on the context menu for filtering blank values (i.e. `undefined`, `null`, `''`).
38
38
  * @param {string} [args.ellipsisText=...] - The text used as ellipsis text on truncated values.
39
39
  * @param {boolean} [args.allowSorting=true] - Allow user to sort rows by clicking on column headers.
40
+ * @param {boolean} [args.allowGroupingColumns=true] - Allow user to group columns by clicking on column headers.
41
+ * @param {boolean} [args.allowGroupingRows=true] - Allow user to group rows by clicking on rows headers.
40
42
  * @param {boolean} [args.showFilter=true] - When true, filter will be an option in the context menu.
41
43
  * @param {number} [args.pageUpDownOverlap=1] - Amount of rows to overlap when pageup/pagedown is used.
42
44
  * @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.
@@ -64,6 +66,18 @@
64
66
  * @param {string} [args.clearSettingsOptionText='Clear saved settings'] - Text that appears on the clear settings option.
65
67
  * @param {string} [args.showOrderByOptionTextDesc='Order by %s ascending'] - Text that appears on the order by descending option.
66
68
  * @param {string} [args.showOrderByOptionTextAsc='Order by %s desc'] - Text that appears on the order by ascending option.
69
+ * @param {string} [args.showGroupColumns='Group columns %s'] - Text that appears on the group columns option.
70
+ * @param {string} [args.showGroupRows='Group row %s'] - Text that appears on the group rows option.
71
+ * @param {string} [args.showRemoveGroupColumns='Remove group %s'] - Text that appears on the remove columns group option.
72
+ * @param {string} [args.showRemoveGroupRows='Remove group %s'] - Text that appears on the remove rows group option.
73
+ * @param {string} [args.showRemoveAllGroupColumns='Remove all column groups'] - Text that appears on the remove all column groups option.
74
+ * @param {string} [args.showRemoveAllGroupRows='Remove all row groups'] - Text that appears on the remove all row groups option.
75
+ * @param {string} [args.showExpandAllGroupColumns='Expand all column groups'] - Text that appears on the expand all column groups option.
76
+ * @param {string} [args.showExpandAllGroupRows='Expand all row groups'] - Text that appears on the expand all row groups option.
77
+ * @param {string} [args.showCollapseAllGroupColumns='Collapse all column groups'] - Text that appears on the collapsed all column groups option.
78
+ * @param {string} [args.showCollapseAllGroupRows='Collapse all row groups'] - Text that appears on the collapsed all row groups option.
79
+ * @param {string} [args.columnGroupIndicatorPosition='right'] - The position of the column group inidcator(icon), available values: 'left' and 'right'.
80
+ * @param {string} [args.rowGroupIndicatorPosition='bottom'] - Ths position of the row group indicator(icon), available values: 'top' and 'bottom'.
67
81
  * @param {boolean} [args.showOrderByOption=true] - Show an option on the context menu sort rows.
68
82
  * @param {boolean} [args.showPaste=false] - Show the paste option in the context menu when applicable.
69
83
  * @param {array} [args.schema=[]] - Sets the schema. See {@link canvasDatagrid.schema}.
@@ -298,6 +312,7 @@
298
312
  * @property {number} [childContextMenuMarginTop=0] - Style of childContextMenuMarginTop.
299
313
  * @property {string} [childContextMenuArrowHTML=&#x25BA;] - Style of childContextMenuArrowHTML.
300
314
  * @property {string} [childContextMenuArrowColor=rgba(43, 48, 43, 1)] - Style of childContextMenuArrowColor.
315
+ * @property {number} [columnGroupRowHeight=25] - Style of columnGroupRowHeight.
301
316
  * @property {string} [contextMenuChildArrowFontSize=12px] - Style of contextMenuChildArrowFontSize.
302
317
  * @property {number} [cellWidth=250] - Style of cellWidth.
303
318
  * @property {string} [contextMenuBackground=rgba(240, 240, 240, 1)] - Style of contextMenuBackground.
@@ -352,6 +367,8 @@
352
367
  * @property {string} [gridBackgroundColor=rgba(240, 240, 240, 1)] - Style of gridBackgroundColor.
353
368
  * @property {string} [gridBorderColor=rgba(202, 202, 202, 1)] - Style of gridBorderColor.
354
369
  * @property {number} [gridBorderWidth=1] - Style of gridBorderWidth.
370
+ * @property {string} [groupIndicatorColor=rgba(155, 155, 155, 1)'] - Foreground color of the group indicator(icon).
371
+ * @property {string} [groupIndicatorBackgroundColor=rgba(255, 255, 255, 1)'] - Background color of the group indicator(icon).
355
372
  * @property {string} [columnHeaderCellCapBackgroundColor=rgba(240, 240, 240, 1)] - Style of columnHeaderCellBackgroundColor.
356
373
  * @property {string} [columnHeaderCellCapBorderColor=rgba(172, 172, 172, 1)] - Style of columnHeaderCellBackgroundColor.
357
374
  * @property {number} [columnHeaderCellCapBorderWidth=1] - Style of columnHeaderCellBackgroundColor.
@@ -386,6 +403,7 @@
386
403
  * @property {number} [reorderMarkerBorderWidth=1.25] - Style of reorderMarkerBorderWidth.
387
404
  * @property {string} [reorderMarkerIndexBorderColor=rgba(66, 133, 244, 1)] - Style of reorderMarkerIndexBorderColor.
388
405
  * @property {number} [reorderMarkerIndexBorderWidth=2.75] - Style of reorderMarkerIndexBorderWidth.
406
+ * @property {number} [rowGroupColumnWidth=25] - Style of rowGroupColumnWidth.
389
407
  * @property {string} [rowHeaderCellBackgroundColor=rgba(240, 240, 240, 1)] - Style of rowHeaderCellBackgroundColor.
390
408
  * @property {string} [rowHeaderCellBorderColor=rgba(152, 152, 152, 1)] - Style of rowHeaderCellBorderColor.
391
409
  * @property {number} [rowHeaderCellBorderWidth=0.25] - Style of rowHeaderCellBorderWidth.